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

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

  ViewVC Help
Powered by ViewVC 1.1.26