/[gxemul]/trunk/src/devices/bus_isa.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/bus_isa.c

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

revision 22 by dpavlin, Mon Oct 8 16:19:37 2007 UTC revision 34 by dpavlin, Mon Oct 8 16:21:17 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   *  Copyright (C) 2005-2006  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: bus_isa.c,v 1.9 2006/01/16 01:45:27 debug Exp $   *  $Id: bus_isa.c,v 1.16 2007/02/17 06:32:06 debug Exp $
29   *     *  
30   *  Generic ISA bus. This is not a normal device, but it can be used as a quick   *  Generic ISA bus. This is not a normal device, but it can be used as a quick
31   *  way of adding most of the common legacy ISA devices to a machine.   *  way of adding most of the common legacy ISA devices to a machine.
# Line 41  Line 41 
41  #include "device.h"  #include "device.h"
42  #include "devices.h"  #include "devices.h"
43  #include "diskimage.h"  #include "diskimage.h"
44    #include "interrupt.h"
45  #include "machine.h"  #include "machine.h"
46  #include "misc.h"  #include "misc.h"
47    
48    
49  /*  /*
50   *  bus_isa_debug_dump():   *  isa_interrupt_common():
51   */   */
52  void bus_isa_debug_dump(void *extra)  void isa_interrupt_common(struct bus_isa_data *d, int old_isa_assert)
53  {  {
54          struct bus_isa_data *d = (struct bus_isa_data *) extra;          int new_isa_assert, x;
55    
56          debug("isa:\n");          /*  Any interrupt assertions on PIC2 go to irq 2 on PIC1  */
57          debug_indentation(DEBUG_INDENTATION);          /*  (TODO: don't hardcode this here)  */
58          debug("portbase:     0x%llx\n", (long long)d->isa_portbase);          if (d->pic2->irr & ~d->pic2->ier)
59          debug("membase:      0x%llx\n", (long long)d->isa_membase);                  d->pic1->irr |= 0x04;
60          debug("irqbase:      %i\n", (int)d->isa_irqbase);          else
61          debug("reassert_irq: %i\n", (int)d->reassert_irq);                  d->pic1->irr &= ~0x04;
62          debug_indentation(-DEBUG_INDENTATION);  
63            /*  printf("ISA: irr=%02x%02x ier=%02x%02x\n",
64                d->pic2->irr, d->pic1->irr, d->pic2->ier, d->pic1->ier);  */
65    
66            new_isa_assert = d->pic1->irr & ~d->pic1->ier;
67    
68            if (old_isa_assert == new_isa_assert)
69                    return;
70    
71            if (!new_isa_assert) {
72                    INTERRUPT_DEASSERT(d->irq);
73                    return;
74            }
75    
76            for (x=0; x<16; x++) {
77                    if (x == 2)
78                            continue;
79    
80                    if (x < 8 && (d->pic1->irr & ~d->pic1->ier & (1 << x)))
81                            break;
82    
83                    if (x >= 8 && (d->pic2->irr & ~d->pic2->ier & (1 << (x&7))))
84                            break;
85            }
86    
87            *d->ptr_to_last_int = x;
88    
89            INTERRUPT_ASSERT(d->irq);
90    }
91    
92    
93    /*
94     *  isa_interrupt_assert():
95     *
96     *  Called whenever an ISA device asserts an interrupt (0..15).
97     */
98    void isa_interrupt_assert(struct interrupt *interrupt)
99    {
100            struct bus_isa_data *d = interrupt->extra;
101            int old_isa_assert, line = interrupt->line;
102            int mask = 1 << (line & 7);
103    
104            old_isa_assert = d->pic1->irr & ~d->pic1->ier;
105    
106            if (line < 8)
107                    d->pic1->irr |= mask;
108            else if (d->pic2 != NULL)
109                    d->pic2->irr |= mask;
110    
111            isa_interrupt_common(d, old_isa_assert);
112    }
113    
114    
115    /*
116     *  isa_interrupt_deassert():
117     *
118     *  Called whenever an ISA device deasserts an interrupt (0..15).
119     */
120    void isa_interrupt_deassert(struct interrupt *interrupt)
121    {
122            struct bus_isa_data *d = interrupt->extra;
123            int line = interrupt->line, mask = 1 << (line & 7);
124            int old_irr1 = d->pic1->irr, old_isa_assert;
125    
126            old_isa_assert = old_irr1 & ~d->pic1->ier;
127    
128            if (line < 8)
129                    d->pic1->irr &= ~mask;
130            else if (d->pic2 != NULL)
131                    d->pic2->irr &= ~mask;
132    
133            /*  If IRQ 0 has been cleared, then this is a timer interrupt.
134                Let's ack it here:  */
135            if (old_irr1 & 1 && !(d->pic1->irr & 1) &&
136                d->ptr_to_pending_timer_interrupts != NULL &&
137                (*d->ptr_to_pending_timer_interrupts) > 0)
138                    (*d->ptr_to_pending_timer_interrupts) --;
139    
140            isa_interrupt_common(d, old_isa_assert);
141  }  }
142    
143    
# Line 67  void bus_isa_debug_dump(void *extra) Line 146  void bus_isa_debug_dump(void *extra)
146   *   *
147   *  Flags are zero or more of the following, ORed together:   *  Flags are zero or more of the following, ORed together:
148   *   *
149     *  BUS_ISA_EXTERNAL_PIC        Don't register/use isa_interrupt_*().
150   *  BUS_ISA_IDE0                Include wdc0.   *  BUS_ISA_IDE0                Include wdc0.
151   *  BUS_ISA_IDE1                Include wdc1.   *  BUS_ISA_IDE1                Include wdc1.
152   *  BUS_ISA_FDC                 Include a floppy controller. (Dummy.)   *  BUS_ISA_FDC                 Include a floppy controller. (Dummy.)
# Line 86  void bus_isa_debug_dump(void *extra) Line 166  void bus_isa_debug_dump(void *extra)
166   *   *
167   *  (*3) Similar to *2 above; machines that always boot up with VGA console   *  (*3) Similar to *2 above; machines that always boot up with VGA console
168   *       should have this flag set, so that the keyboard is always used.   *       should have this flag set, so that the keyboard is always used.
169     *
170     *  The interrupt_base_path is the name of the bus, CPU, or controller onto
171     *  which this ISA bus will be attached, e.g. "emul[0].machine[0].lca" or
172     *  "emul[0].machine[0].cpu[0].pic1".
173   */   */
174  struct bus_isa_data *bus_isa_init(struct machine *machine,  struct bus_isa_data *bus_isa_init(struct machine *machine,
175          uint32_t bus_isa_flags, uint64_t isa_portbase, uint64_t isa_membase,          char *interrupt_base_path, uint32_t bus_isa_flags,
176          int isa_irqbase, int reassert_irq)          uint64_t isa_portbase, uint64_t isa_membase)
177  {  {
178          struct bus_isa_data *d = malloc(sizeof(struct bus_isa_data));          struct bus_isa_data *d = malloc(sizeof(struct bus_isa_data));
179          char tmpstr[300];          char tmpstr[300], tmpstr2[300];
180          int wdc0_irq = 14, wdc1_irq = 15;          int wdc0_irq = 14, wdc1_irq = 15;
181          int tmp_handle, kbd_in_use;          int i, tmp_handle, kbd_in_use;
182          int lptbase = 0x378;          int lptbase = 0x378;
183    
184          memset(d, 0, sizeof(struct bus_isa_data));          memset(d, 0, sizeof(struct bus_isa_data));
185    
186          d->isa_portbase = isa_portbase;          d->isa_portbase = isa_portbase;
187          d->isa_membase  = isa_membase;          d->isa_membase  = isa_membase;
188          d->isa_irqbase  = isa_irqbase;  
189          d->reassert_irq = reassert_irq;          if (!(bus_isa_flags & BUS_ISA_EXTERNAL_PIC)) {
190          machine_bus_register(machine, "isa", bus_isa_debug_dump, d);                  /*  Connect to the interrupt which we're interrupting
191                        at (usually a CPU):  */
192                    INTERRUPT_CONNECT(interrupt_base_path, d->irq);
193    
194                    /*  Register the 16 possible ISA interrupts:  */
195                    for (i=0; i<16; i++) {
196                            struct interrupt template;
197                            char name[300];
198                            snprintf(name, sizeof(name),
199                                "%s.isa.%i", interrupt_base_path, i);
200                            memset(&template, 0, sizeof(template));
201                            template.line = i;
202                            template.name = name;
203                            template.extra = d;
204                            template.interrupt_assert = isa_interrupt_assert;
205                            template.interrupt_deassert = isa_interrupt_deassert;
206                            interrupt_handler_register(&template);
207                    }
208            }
209    
210          kbd_in_use = ((bus_isa_flags & BUS_ISA_PCKBC_FORCE_USE) ||          kbd_in_use = ((bus_isa_flags & BUS_ISA_PCKBC_FORCE_USE) ||
211              (machine->use_x11))? 1 : 0;              (machine->use_x11))? 1 : 0;
# Line 112  struct bus_isa_data *bus_isa_init(struct Line 215  struct bus_isa_data *bus_isa_init(struct
215                  wdc0_irq = wdc1_irq = 13;                  wdc0_irq = wdc1_irq = 13;
216          }          }
217    
218          snprintf(tmpstr, sizeof(tmpstr), "8259 irq=%i addr=0x%llx",          if (!(bus_isa_flags & BUS_ISA_EXTERNAL_PIC)) {
219              reassert_irq, (long long)(isa_portbase + 0x20));                  snprintf(tmpstr, sizeof(tmpstr), "8259 irq=%s addr=0x%llx",
220          machine->isa_pic_data.pic1 = device_add(machine, tmpstr);                      interrupt_base_path, (long long)(isa_portbase + 0x20));
221                    d->pic1 = machine->isa_pic_data.pic1 =
222          if (bus_isa_flags & BUS_ISA_NO_SECOND_PIC)                      device_add(machine, tmpstr);
223                  bus_isa_flags &= ~BUS_ISA_NO_SECOND_PIC;                  d->ptr_to_pending_timer_interrupts =
224          else {                      machine->isa_pic_data.pending_timer_interrupts;
225                  snprintf(tmpstr, sizeof(tmpstr), "8259 irq=%i addr=0x%llx",                  d->ptr_to_last_int = &machine->isa_pic_data.last_int;
226                      reassert_irq, (long long)(isa_portbase + 0xa0));  
227                  machine->isa_pic_data.pic2 = device_add(machine, tmpstr);                  if (bus_isa_flags & BUS_ISA_NO_SECOND_PIC)
228                            bus_isa_flags &= ~BUS_ISA_NO_SECOND_PIC;
229                    else {
230                            snprintf(tmpstr, sizeof(tmpstr),
231                                "8259 irq=%s.isa.2 addr=0x%llx",
232                                interrupt_base_path,(long long)(isa_portbase+0xa0));
233                            d->pic2 = machine->isa_pic_data.pic2 =
234                                device_add(machine, tmpstr);
235                    }
236            } else {
237                    bus_isa_flags &= ~BUS_ISA_EXTERNAL_PIC;
238          }          }
239    
240          snprintf(tmpstr, sizeof(tmpstr), "8253 irq=%i addr=0x%llx in_use=0",          snprintf(tmpstr, sizeof(tmpstr), "8253 irq=%s.isa.%i addr=0x%llx "
241              isa_irqbase + 0, (long long)(isa_portbase + 0x40));              "in_use=0", interrupt_base_path, 0,
242                (long long)(isa_portbase + 0x40));
243          device_add(machine, tmpstr);          device_add(machine, tmpstr);
244    
245          snprintf(tmpstr, sizeof(tmpstr), "pccmos addr=0x%llx",          snprintf(tmpstr, sizeof(tmpstr), "pccmos irq=%s.isa.%i addr=0x%llx",
246              (long long)(isa_portbase + 0x70));              interrupt_base_path, 8, (long long)(isa_portbase + 0x70));
247          device_add(machine, tmpstr);          device_add(machine, tmpstr);
248    
249          snprintf(tmpstr, sizeof(tmpstr), "ns16550 irq=%i addr=0x%llx name2="          snprintf(tmpstr, sizeof(tmpstr), "ns16550 irq=%s.isa.%i addr=0x%llx "
250              "tty0 in_use=%i", isa_irqbase+4, (long long)(isa_portbase + 0x3f8),              "name2=tty0 in_use=%i", interrupt_base_path, 4,
251              1 - kbd_in_use);              (long long)(isa_portbase + 0x3f8), 1 - kbd_in_use);
252          machine->main_console_handle = (size_t)device_add(machine, tmpstr);          machine->main_console_handle = (size_t)device_add(machine, tmpstr);
253    
254          snprintf(tmpstr, sizeof(tmpstr), "ns16550 irq=%i addr=0x%llx name2=tty1"          snprintf(tmpstr, sizeof(tmpstr), "ns16550 irq=%s.isa.%i addr=0x%llx "
255              " in_use=0", isa_irqbase +3, (long long)(isa_portbase + 0x2f8));              "name2=tty1 in_use=0", interrupt_base_path, 3,
256                (long long)(isa_portbase + 0x2f8));
257          device_add(machine, tmpstr);          device_add(machine, tmpstr);
258    
259          if (bus_isa_flags & BUS_ISA_LPTBASE_3BC) {          if (bus_isa_flags & BUS_ISA_LPTBASE_3BC) {
# Line 146  struct bus_isa_data *bus_isa_init(struct Line 261  struct bus_isa_data *bus_isa_init(struct
261                  lptbase = 0x3bc;                  lptbase = 0x3bc;
262          }          }
263    
264          snprintf(tmpstr, sizeof(tmpstr), "lpt irq=%i addr=0x%llx name2=lpt"          snprintf(tmpstr, sizeof(tmpstr), "lpt irq=%s.isa.%i addr=0x%llx "
265              " in_use=0", isa_irqbase + 7, (long long)(isa_portbase + lptbase));              "name2=lpt in_use=0", interrupt_base_path, 7,
266                (long long)(isa_portbase + lptbase));
267          device_add(machine, tmpstr);          device_add(machine, tmpstr);
268    
269          if (bus_isa_flags & BUS_ISA_IDE0) {          if (bus_isa_flags & BUS_ISA_IDE0) {
270                  bus_isa_flags &= ~BUS_ISA_IDE0;                  bus_isa_flags &= ~BUS_ISA_IDE0;
271                  snprintf(tmpstr, sizeof(tmpstr), "wdc irq=%i addr=0x%llx",                  snprintf(tmpstr, sizeof(tmpstr), "wdc irq=%s.isa.%i "
272                      isa_irqbase + wdc0_irq, (long long)(isa_portbase + 0x1f0));                      "addr=0x%llx", interrupt_base_path, wdc0_irq,
273                        (long long)(isa_portbase + 0x1f0));
274                  if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||                  if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||
275                      diskimage_exist(machine, 1, DISKIMAGE_IDE))                      diskimage_exist(machine, 1, DISKIMAGE_IDE))
276                          device_add(machine, tmpstr);                          device_add(machine, tmpstr);
# Line 161  struct bus_isa_data *bus_isa_init(struct Line 278  struct bus_isa_data *bus_isa_init(struct
278    
279          if (bus_isa_flags & BUS_ISA_IDE1) {          if (bus_isa_flags & BUS_ISA_IDE1) {
280                  bus_isa_flags &= ~BUS_ISA_IDE1;                  bus_isa_flags &= ~BUS_ISA_IDE1;
281                  snprintf(tmpstr, sizeof(tmpstr), "wdc irq=%i addr=0x%llx",                  snprintf(tmpstr, sizeof(tmpstr), "wdc irq=%s.isa.%i "
282                      isa_irqbase + wdc1_irq, (long long)(isa_portbase + 0x170));                      "addr=0x%llx", interrupt_base_path, wdc1_irq,
283                        (long long)(isa_portbase + 0x170));
284                  if (diskimage_exist(machine, 2, DISKIMAGE_IDE) ||                  if (diskimage_exist(machine, 2, DISKIMAGE_IDE) ||
285                      diskimage_exist(machine, 3, DISKIMAGE_IDE))                      diskimage_exist(machine, 3, DISKIMAGE_IDE))
286                          device_add(machine, tmpstr);                          device_add(machine, tmpstr);
# Line 170  struct bus_isa_data *bus_isa_init(struct Line 288  struct bus_isa_data *bus_isa_init(struct
288    
289          if (bus_isa_flags & BUS_ISA_FDC) {          if (bus_isa_flags & BUS_ISA_FDC) {
290                  bus_isa_flags &= ~BUS_ISA_FDC;                  bus_isa_flags &= ~BUS_ISA_FDC;
291                  snprintf(tmpstr, sizeof(tmpstr), "fdc irq=%i addr=0x%llx",                  snprintf(tmpstr, sizeof(tmpstr), "fdc irq=%s.isa.%i "
292                      isa_irqbase + 6, (long long)(isa_portbase + 0x3f0));                      "addr=0x%llx", interrupt_base_path, 6,
293                        (long long)(isa_portbase + 0x3f0));
294                  device_add(machine, tmpstr);                  device_add(machine, tmpstr);
295          }          }
296    
# Line 183  struct bus_isa_data *bus_isa_init(struct Line 302  struct bus_isa_data *bus_isa_init(struct
302                  bus_isa_flags &= ~(BUS_ISA_VGA | BUS_ISA_VGA_FORCE);                  bus_isa_flags &= ~(BUS_ISA_VGA | BUS_ISA_VGA_FORCE);
303          }          }
304    
305            snprintf(tmpstr, sizeof(tmpstr), "%s.isa.1", interrupt_base_path);
306            snprintf(tmpstr2, sizeof(tmpstr2), "%s.isa.12", interrupt_base_path);
307          tmp_handle = dev_pckbc_init(machine, machine->memory,          tmp_handle = dev_pckbc_init(machine, machine->memory,
308              isa_portbase + 0x60, PCKBC_8042, isa_irqbase + 1, isa_irqbase + 12,              isa_portbase + 0x60, PCKBC_8042, tmpstr, tmpstr2,
309              kbd_in_use, bus_isa_flags & BUS_ISA_PCKBC_NONPCSTYLE? 0 : 1);              kbd_in_use, bus_isa_flags & BUS_ISA_PCKBC_NONPCSTYLE? 0 : 1);
310    
311          if (kbd_in_use)          if (kbd_in_use)

Legend:
Removed from v.22  
changed lines
  Added in v.34

  ViewVC Help
Powered by ViewVC 1.1.26