/[gxemul]/trunk/src/devices/dev_8259.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /trunk/src/devices/dev_8259.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 11 by dpavlin, Mon Oct 8 16:18:27 2007 UTC revision 12 by dpavlin, Mon Oct 8 16:18:38 2007 UTC
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *     *  
27   *   *
28   *  $Id: dev_8259.c,v 1.10 2005/06/20 05:52:48 debug Exp $   *  $Id: dev_8259.c,v 1.14 2005/08/05 09:08:20 debug Exp $
29   *     *  
30   *  8259 Programmable Interrupt Controller.   *  8259 Programmable Interrupt Controller.
31   *   *
32   *  This is mostly bogus. TODO. See the following URL for more details:   *  See the following URL for more details:
33   *      http://www.nondot.org/sabre/os/files/MiscHW/8259pic.txt   *      http://www.nondot.org/sabre/os/files/MiscHW/8259pic.txt
34   */   */
35    
# Line 48  Line 48 
48    
49  #define DEV_8259_LENGTH         2  #define DEV_8259_LENGTH         2
50    
51    /*  #define DEV_8259_DEBUG  */
52    
53    
54  /*  /*
55   *  dev_8259_access():   *  dev_8259_access():
# Line 58  int dev_8259_access(struct cpu *cpu, str Line 60  int dev_8259_access(struct cpu *cpu, str
60  {  {
61          struct pic8259_data *d = (struct pic8259_data *) extra;          struct pic8259_data *d = (struct pic8259_data *) extra;
62          uint64_t idata = 0, odata = 0;          uint64_t idata = 0, odata = 0;
63            int i;
64    
65          idata = memory_readmax64(cpu, data, len);          idata = memory_readmax64(cpu, data, len);
66    
67    #ifdef DEV_8259_DEBUG
68            if (writeflag == MEM_READ)
69                    fatal("[ 8259: read from 0x%x ]\n", (int)relative_addr);
70            else
71                    fatal("[ 8259: write to 0x%x: 0x%x ]\n",
72                        (int)relative_addr, (int)idata);
73    #endif
74    
75          switch (relative_addr) {          switch (relative_addr) {
76          case 0x00:          case 0x00:
77                  if (writeflag == MEM_WRITE) {                  if (writeflag == MEM_WRITE) {
# Line 73  int dev_8259_access(struct cpu *cpu, str Line 84  int dev_8259_access(struct cpu *cpu, str
84                                          fatal("[ 8259: WARNING: Bit 2 set ]\n");                                          fatal("[ 8259: WARNING: Bit 2 set ]\n");
85                                  /*  Bit 1: 0=cascade, 1=single  */                                  /*  Bit 1: 0=cascade, 1=single  */
86                                  /*  Bit 0: 1=4th init byte  */                                  /*  Bit 0: 1=4th init byte  */
87                                  if (!(idata & 0x01))                                  /*  This happens on non-x86 systems:
88                                        if (!(idata & 0x01))
89                                          fatal("[ 8259: WARNING: Bit 0 NOT set!"                                          fatal("[ 8259: WARNING: Bit 0 NOT set!"
90                                              "!! ]\n");                                              "!! ]\n");  */
91                                  d->init_state = 1;                                  d->init_state = 1;
92                                  break;                                  break;
93                          }                          }
# Line 94  int dev_8259_access(struct cpu *cpu, str Line 106  int dev_8259_access(struct cpu *cpu, str
106                          case 0x0b:                          case 0x0b:
107                                  d->current_command = 0x0b;                                  d->current_command = 0x0b;
108                                  break;                                  break;
109                            case 0x0c:
110                                    /*  Put Master in Buffered Mode  */
111                                    d->current_command = 0x0c;
112                                    break;
113                          case 0x20:      /*  End Of Interrupt  */                          case 0x20:      /*  End Of Interrupt  */
114                                    /*
115                                     *  TODO: in buffered mode, is this an EOI 0?
116                                     */
117                                  d->irr &= ~d->isr;                                  d->irr &= ~d->isr;
118                                  d->isr = 0;                                  d->isr = 0;
119                                  /*  Recalculate interrupt assertions:  */                                  /*  Recalculate interrupt assertions:  */
120                                  cpu_interrupt(cpu, 16);                                  cpu_interrupt(cpu, d->irq_nr);
121                                  break;                                  break;
122                            case 0x21:      /*  Specific EOI  */
123                            case 0x22:
124                            case 0x23:
125                            case 0x24:
126                            case 0x25:
127                            case 0x26:
128                            case 0x27:
129                          case 0x60:                          case 0x60:
130                          case 0x61:                          case 0x61:
131                          case 0x62:                          case 0x62:
# Line 111  int dev_8259_access(struct cpu *cpu, str Line 137  int dev_8259_access(struct cpu *cpu, str
137                                  d->irr &= ~(1 << (idata & 7));                                  d->irr &= ~(1 << (idata & 7));
138                                  d->isr &= ~(1 << (idata & 7));                                  d->isr &= ~(1 << (idata & 7));
139                                  /*  Recalculate interrupt assertions:  */                                  /*  Recalculate interrupt assertions:  */
140                                  cpu_interrupt(cpu, 16);                                  cpu_interrupt(cpu, d->irq_nr);
141                                  break;                                  break;
142                          case 0x68:      /*  Set Special Mask Mode  */                          case 0x68:      /*  Set Special Mask Mode  */
143                                  /*  TODO  */                                  /*  TODO  */
# Line 139  int dev_8259_access(struct cpu *cpu, str Line 165  int dev_8259_access(struct cpu *cpu, str
165                          case 0x0b:                          case 0x0b:
166                                  odata = d->isr;                                  odata = d->isr;
167                                  break;                                  break;
168                            case 0x0c:
169                                    /*  Buffered mode.  */
170                          default:                          default:
171                                  fatal("[ 8259: unimplemented command 0x%02x"                                  odata = 0x00;
172                                      " while reading ]\n", d->current_command);                                  for (i=0; i<8; i++)
173                                  cpu->running = 0;                                          if ((d->irr >> i) & 1) {
174                                                    odata = 0x80 | i;
175                                                    break;
176                                            }
177                                    break;
178                            /*
179                             *  TODO: The "default" label should really do
180                             *  something like this:
181                             *
182                             *      fatal("[ 8259: unimplemented command 0x%02x"
183                             *          " while reading ]\n", d->current_command);
184                             *      cpu->running = 0;
185                             *
186                             *  but Linux seems to read from the secondary PIC
187                             *  in a manner which works better the way things
188                             *  are coded right now.
189                             */
190                          }                          }
191                  }                  }
192                  break;                  break;
# Line 150  int dev_8259_access(struct cpu *cpu, str Line 194  int dev_8259_access(struct cpu *cpu, str
194                  if (d->init_state > 0) {                  if (d->init_state > 0) {
195                          if (d->init_state == 1) {                          if (d->init_state == 1) {
196                                  d->irq_base = idata & 0xf8;                                  d->irq_base = idata & 0xf8;
197                                  if (idata & 7)                                  /*  This happens on non-x86 machines:
198                                        if (idata & 7)
199                                          fatal("[ 8259: WARNING! Lowest"                                          fatal("[ 8259: WARNING! Lowest"
200                                              " bits in Init Cmd 1 are"                                              " bits in Init Cmd 1 are"
201                                              " non-zero! ]\n");                                              " non-zero! ]\n");  */
202                                  d->init_state = 2;                                  d->init_state = 2;
203                          } else if (d->init_state == 2) {                          } else if (d->init_state == 2) {
204                                  /*  Slave attachment. TODO  */                                  /*  Slave attachment. TODO  */
# Line 174  int dev_8259_access(struct cpu *cpu, str Line 219  int dev_8259_access(struct cpu *cpu, str
219                  if (writeflag == MEM_WRITE) {                  if (writeflag == MEM_WRITE) {
220                          d->ier = idata;                          d->ier = idata;
221                          /*  Recalculate interrupt assertions:  */                          /*  Recalculate interrupt assertions:  */
222                          cpu_interrupt(cpu, 16);                          cpu_interrupt(cpu, d->irq_nr);
223                  } else {                  } else {
224                          odata = d->ier;                          odata = d->ier;
225                  }                  }
# Line 200  int dev_8259_access(struct cpu *cpu, str Line 245  int dev_8259_access(struct cpu *cpu, str
245    
246  /*  /*
247   *  devinit_8259():   *  devinit_8259():
248     *
249     *  Initialize an 8259 PIC. Important notes:
250     *
251     *      x)  Most systems use _TWO_ 8259 PICs. These should be registered
252     *          as separate devices.
253     *
254     *      x)  The irq number specified is the number used to re-calculate
255     *          CPU interrupt assertions.  It is _not_ the irq number at
256     *          which the PIC is connected. (That is left to machine specific
257     *          code in src/machine.c.)
258   */   */
259  int devinit_8259(struct devinit *devinit)  int devinit_8259(struct devinit *devinit)
260  {  {
261          struct pic8259_data *d = malloc(sizeof(struct pic8259_data));          struct pic8259_data *d = malloc(sizeof(struct pic8259_data));
262          char *name2;          char *name2;
263          int nlen = 40;          size_t nlen = strlen(devinit->name) + 20;
264    
265          if (d == NULL) {          if (d == NULL) {
266                  fprintf(stderr, "out of memory\n");                  fprintf(stderr, "out of memory\n");
# Line 216  int devinit_8259(struct devinit *devinit Line 271  int devinit_8259(struct devinit *devinit
271    
272          name2 = malloc(nlen);          name2 = malloc(nlen);
273          snprintf(name2, nlen, "%s", devinit->name);          snprintf(name2, nlen, "%s", devinit->name);
274          if ((devinit->addr & 0xfff) == 0xa0)          if ((devinit->addr & 0xfff) == 0xa0) {
275                  strlcat(name2, " [secondary]", nlen);                  strlcat(name2, " [secondary]", nlen);
276                    d->irq_base = 8;
277            }
278    
279          memory_device_register(devinit->machine->memory, name2,          memory_device_register(devinit->machine->memory, name2,
280              devinit->addr, DEV_8259_LENGTH, dev_8259_access, (void *)d,              devinit->addr, DEV_8259_LENGTH, dev_8259_access, d,
281              MEM_DEFAULT, NULL);              MEM_DEFAULT, NULL);
282    
283          devinit->return_ptr = d;          devinit->return_ptr = d;

Legend:
Removed from v.11  
changed lines
  Added in v.12

  ViewVC Help
Powered by ViewVC 1.1.26