/[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 12 by dpavlin, Mon Oct 8 16:18:38 2007 UTC revision 42 by dpavlin, Mon Oct 8 16:22:32 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   *  Copyright (C) 2005  Anders Gavare.  All rights reserved.   *  Copyright (C) 2005-2007  Anders Gavare.  All rights reserved.
3   *   *
4   *  Redistribution and use in source and binary forms, with or without   *  Redistribution and use in source and binary forms, with or without
5   *  modification, are permitted provided that the following conditions are met:   *  modification, are permitted provided that the following conditions are met:
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *     *  
27   *   *
28   *  $Id: dev_8259.c,v 1.14 2005/08/05 09:08:20 debug Exp $   *  $Id: dev_8259.c,v 1.30 2007/06/15 18:13:04 debug Exp $
29   *     *  
30   *  8259 Programmable Interrupt Controller.   *  COMMENT: Intel 8259 Programmable Interrupt Controller
31   *   *
32   *  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
# Line 51  Line 51 
51  /*  #define DEV_8259_DEBUG  */  /*  #define DEV_8259_DEBUG  */
52    
53    
54  /*  DEVICE_ACCESS(8259)
  *  dev_8259_access():  
  */  
 int dev_8259_access(struct cpu *cpu, struct memory *mem,  
         uint64_t relative_addr, unsigned char *data, size_t len,  
         int writeflag, void *extra)  
55  {  {
56          struct pic8259_data *d = (struct pic8259_data *) extra;          struct pic8259_data *d = extra;
57          uint64_t idata = 0, odata = 0;          uint64_t idata = 0, odata = 0;
58          int i;          int i;
59    
60          idata = memory_readmax64(cpu, data, len);          if (writeflag == MEM_WRITE)
61                    idata = memory_readmax64(cpu, data, len);
62    
63  #ifdef DEV_8259_DEBUG  #ifdef DEV_8259_DEBUG
64          if (writeflag == MEM_READ)          if (writeflag == MEM_READ)
# Line 99  int dev_8259_access(struct cpu *cpu, str Line 95  int dev_8259_access(struct cpu *cpu, str
95                                      " it was aborted? ]\n");                                      " it was aborted? ]\n");
96                          d->init_state = 0;                          d->init_state = 0;
97    
98                          switch (idata) {                          if (idata == 0x0a) {
                         case 0x0a:  
99                                  d->current_command = 0x0a;                                  d->current_command = 0x0a;
100                                  break;                          } else if (idata == 0x0b) {
                         case 0x0b:  
101                                  d->current_command = 0x0b;                                  d->current_command = 0x0b;
102                                  break;                          } else if (idata == 0x0c) {
                         case 0x0c:  
103                                  /*  Put Master in Buffered Mode  */                                  /*  Put Master in Buffered Mode  */
104                                  d->current_command = 0x0c;                                  d->current_command = 0x0c;
105                                  break;                          } else if (idata == 0x20) {
106                          case 0x20:      /*  End Of Interrupt  */                                  int old_irr = d->irr;
107                                  /*                                  /*  End Of Interrupt  */
108                                   *  TODO: in buffered mode, is this an EOI 0?                                  /*  TODO: in buffered mode, is this an EOI 0? */
                                  */  
109                                  d->irr &= ~d->isr;                                  d->irr &= ~d->isr;
110                                  d->isr = 0;                                  d->isr = 0;
111                                  /*  Recalculate interrupt assertions:  */                                  /*  Recalculate interrupt assertions,
112                                  cpu_interrupt(cpu, d->irq_nr);                                      if necessary:  */
113                                  break;                                  if ((old_irr & ~d->ier) != (d->irr & ~d->ier)) {
114                          case 0x21:      /*  Specific EOI  */                                          if (d->irr & ~d->ier)
115                          case 0x22:                                                  INTERRUPT_ASSERT(d->irq);
116                          case 0x23:                                          else
117                          case 0x24:                                                  INTERRUPT_DEASSERT(d->irq);
118                          case 0x25:                                  }
119                          case 0x26:                          } else if ((idata >= 0x21 && idata <= 0x27) ||
120                          case 0x27:                              (idata >= 0x60 && idata <= 0x67) ||
121                          case 0x60:                              (idata >= 0xe0 && idata <= 0xe7)) {
122                          case 0x61:                                  /*  Specific EOI  */
123                          case 0x62:                                  int old_irr = d->irr;
                         case 0x63:  
                         case 0x64:  
                         case 0x65:  
                         case 0x66:  
                         case 0x67:      /*  Specific EOI  */  
124                                  d->irr &= ~(1 << (idata & 7));                                  d->irr &= ~(1 << (idata & 7));
125                                  d->isr &= ~(1 << (idata & 7));                                  d->isr &= ~(1 << (idata & 7));
126                                  /*  Recalculate interrupt assertions:  */                                  /*  Recalc. int assertions, if necessary:  */
127                                  cpu_interrupt(cpu, d->irq_nr);                                  if ((old_irr & ~d->ier) != (d->irr & ~d->ier)) {
128                                  break;                                          if (d->irr & ~d->ier)
129                          case 0x68:      /*  Set Special Mask Mode  */                                                  INTERRUPT_ASSERT(d->irq);
130                                            else
131                                                    INTERRUPT_DEASSERT(d->irq);
132                                    }
133                            } else if (idata == 0x68) {
134                                    /*  Set Special Mask Mode  */
135                                  /*  TODO  */                                  /*  TODO  */
136                                  break;                          } else if (idata >= 0xc0 && idata <= 0xc7) {
137                          case 0xc0:                                  /*  Set IRQ Priority Order  */
                         case 0xc1:  
                         case 0xc2:  
                         case 0xc3:  
                         case 0xc4:  
                         case 0xc5:  
                         case 0xc6:  
                         case 0xc7:      /*  Set IRQ Priority Order  */  
138                                  /*  TODO  */                                  /*  TODO  */
139                                  break;                          } else {
                         default:  
140                                  fatal("[ 8259: unimplemented command 0x%02x"                                  fatal("[ 8259: unimplemented command 0x%02x"
141                                      " ]\n", idata);                                      " ]\n", (int)idata);
142                                  cpu->running = 0;                                  cpu->running = 0;
143                          }                          }
144                  } else {                  } else {
# Line 167  int dev_8259_access(struct cpu *cpu, str Line 151  int dev_8259_access(struct cpu *cpu, str
151                                  break;                                  break;
152                          case 0x0c:                          case 0x0c:
153                                  /*  Buffered mode.  */                                  /*  Buffered mode.  */
154                                    odata = 0x00;
155                                    for (i=0; i<8; i++)
156                                            if ((d->irr >> i) & 1) {
157                                                    odata = 0x80 | i;
158                                                    break;
159                                            }
160                                    break;
161                          default:                          default:
162                                  odata = 0x00;                                  odata = 0x00;
163                                  for (i=0; i<8; i++)                                  for (i=0; i<8; i++)
# Line 204  int dev_8259_access(struct cpu *cpu, str Line 195  int dev_8259_access(struct cpu *cpu, str
195                                  /*  Slave attachment. TODO  */                                  /*  Slave attachment. TODO  */
196                                  d->init_state = 3;                                  d->init_state = 3;
197                          } else if (d->init_state == 3) {                          } else if (d->init_state == 3) {
198                                  if (idata & 0x02)                                  if (idata & 0x02) {
199                                          fatal("[ 8259: WARNING! Bit 1 i"                                          /*  Should not be set in PCs, but
200                                                on CATS, for example, it is set.  */
201                                            debug("[ 8259: WARNING! Bit 1 i"
202                                              "n Init Cmd 4 is set! ]\n");                                              "n Init Cmd 4 is set! ]\n");
203                                    }
204                                  if (!(idata & 0x01))                                  if (!(idata & 0x01))
205                                          fatal("[ 8259: WARNING! Bit 0 "                                          fatal("[ 8259: WARNING! Bit 0 "
206                                              "in Init Cmd 4 is not"                                              "in Init Cmd 4 is not"
# Line 217  int dev_8259_access(struct cpu *cpu, str Line 211  int dev_8259_access(struct cpu *cpu, str
211                  }                  }
212    
213                  if (writeflag == MEM_WRITE) {                  if (writeflag == MEM_WRITE) {
214                            int old_ier = d->ier;
215                          d->ier = idata;                          d->ier = idata;
216                          /*  Recalculate interrupt assertions:  */  
217                          cpu_interrupt(cpu, d->irq_nr);                          /*  Recalculate interrupt assertions,
218                                if necessary:  */
219                            if ((d->irr & ~old_ier) != (d->irr & ~d->ier)) {
220                                    if (d->irr & ~d->ier)
221                                            INTERRUPT_ASSERT(d->irq);
222                                    else
223                                            INTERRUPT_DEASSERT(d->irq);
224                            }
225                  } else {                  } else {
226                          odata = d->ier;                          odata = d->ier;
227                  }                  }
# Line 256  int dev_8259_access(struct cpu *cpu, str Line 258  int dev_8259_access(struct cpu *cpu, str
258   *          which the PIC is connected. (That is left to machine specific   *          which the PIC is connected. (That is left to machine specific
259   *          code in src/machine.c.)   *          code in src/machine.c.)
260   */   */
261  int devinit_8259(struct devinit *devinit)  DEVINIT(8259)
262  {  {
263          struct pic8259_data *d = malloc(sizeof(struct pic8259_data));          struct pic8259_data *d;
264          char *name2;          char *name2;
265          size_t nlen = strlen(devinit->name) + 20;          size_t nlen = strlen(devinit->name) + 20;
266    
267          if (d == NULL) {          CHECK_ALLOCATION(d = malloc(sizeof(struct pic8259_data)));
                 fprintf(stderr, "out of memory\n");  
                 exit(1);  
         }  
268          memset(d, 0, sizeof(struct pic8259_data));          memset(d, 0, sizeof(struct pic8259_data));
         d->irq_nr = devinit->irq_nr;  
269    
270          name2 = malloc(nlen);          INTERRUPT_CONNECT(devinit->interrupt_path, d->irq);
271    
272            CHECK_ALLOCATION(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);
# Line 278  int devinit_8259(struct devinit *devinit Line 278  int devinit_8259(struct devinit *devinit
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, d,              devinit->addr, DEV_8259_LENGTH, dev_8259_access, d,
281              MEM_DEFAULT, NULL);              DM_DEFAULT, NULL);
282    
283          devinit->return_ptr = d;          devinit->return_ptr = d;
284          return 1;          return 1;

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

  ViewVC Help
Powered by ViewVC 1.1.26