bus_isa.cc Source File

Back to the index.

bus_isa.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005-2009 Anders Gavare. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * 3. The name of the author may not be used to endorse or promote products
13  * derived from this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  *
28  * COMMENT: Generic ISA bus framework
29  *
30  * This is not a normal device, but it can be used as a quick way of adding
31  * most of the common legacy ISA devices to a machine.
32  */
33 
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 
38 #define BUS_ISA_C
39 
40 #include "bus_isa.h"
41 #include "device.h"
42 #include "devices.h"
43 #include "diskimage.h"
44 #include "interrupt.h"
45 #include "machine.h"
46 #include "misc.h"
47 
48 
49 /*
50  * isa_interrupt_common():
51  */
52 void isa_interrupt_common(struct bus_isa_data *d, int old_isa_assert)
53 {
54  int new_isa_assert, x;
55 
56  /* Any interrupt assertions on PIC2 go to irq 2 on PIC1 */
57  /* (TODO: don't hardcode this here) */
58  if (d->pic2->irr & ~d->pic2->ier)
59  d->pic1->irr |= 0x04;
60  else
61  d->pic1->irr &= ~0x04;
62 
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  */
99 {
100  struct bus_isa_data *d = (struct bus_isa_data *) 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  */
121 {
122  struct bus_isa_data *d = (struct bus_isa_data *) 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 
144 /*
145  * bus_isa_init():
146  *
147  * 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.
151  * BUS_ISA_IDE1 Include wdc1.
152  * BUS_ISA_FDC Include a floppy controller. (Dummy.)
153  * BUS_ISA_VGA Include old-style (non-PCI) VGA. (*1)
154  * BUS_ISA_VGA_FORCE Include VGA even when running without X11. (*2)
155  * BUS_ISA_PCKBC_FORCE_USE Always assume keyboard console, not serial. (*3)
156  * BUS_ISA_PCKBC_NONPCSTYLE Don't set the pc-style flag for the keyboard.
157  * BUS_ISA_NO_SECOND_PIC Only useful for 8086 XT (pre-AT) emulation. :-)
158  * BUS_ISA_LPTBASE_3BC Set lptbase to 0x3bc instead of 0x378.
159  *
160  * (*1) For machines with a PCI bus, this flag should not be used. Instead, a
161  * PCI VGA card should be added to the PCI bus.
162  *
163  * (*2) For machines where it is easy to select VGA vs serial console during
164  * boot, this flag should not be used. Machines that "always" boot up
165  * in VGA console mode should have it set.
166  *
167  * (*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.
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. "machine[0].lca" or
172  * "machine[0].cpu[0].pic1".
173  */
174 struct bus_isa_data *bus_isa_init(struct machine *machine,
175  char *interrupt_base_path, uint32_t bus_isa_flags,
176  uint64_t isa_portbase, uint64_t isa_membase)
177 {
178  struct bus_isa_data *d;
179  char tmpstr[300], tmpstr2[300];
180  int wdc0_irq = 14, wdc1_irq = 15;
181  int i, tmp_handle, kbd_in_use;
182  int lptbase = 0x378;
183 
184  CHECK_ALLOCATION(d = (struct bus_isa_data *) malloc(sizeof(struct bus_isa_data)));
185  memset(d, 0, sizeof(struct bus_isa_data));
186 
187  d->isa_portbase = isa_portbase;
188  d->isa_membase = isa_membase;
189 
190  if (!(bus_isa_flags & BUS_ISA_EXTERNAL_PIC)) {
191  /* Connect to the interrupt which we're interrupting
192  at (usually a CPU): */
193  INTERRUPT_CONNECT(interrupt_base_path, d->irq);
194 
195  /* Register the 16 possible ISA interrupts: */
196  for (i=0; i<16; i++) {
197  struct interrupt templ;
198  char name[300];
199  snprintf(name, sizeof(name),
200  "%s.isa.%i", interrupt_base_path, i);
201  memset(&templ, 0, sizeof(templ));
202  templ.line = i;
203  templ.name = name;
204  templ.extra = d;
208  }
209  }
210 
211  kbd_in_use = ((bus_isa_flags & BUS_ISA_PCKBC_FORCE_USE) ||
212  (machine->x11_md.in_use))? 1 : 0;
213 
215  /* PReP with obio controller has both WDCs on irq 13! */
216  wdc0_irq = wdc1_irq = 13;
217  }
218 
219  if (!(bus_isa_flags & BUS_ISA_EXTERNAL_PIC)) {
220  snprintf(tmpstr, sizeof(tmpstr), "8259 irq=%s addr=0x%llx",
221  interrupt_base_path, (long long)(isa_portbase + 0x20));
222  d->pic1 = machine->isa_pic_data.pic1 = (struct pic8259_data *)
223  device_add(machine, tmpstr);
224  d->ptr_to_pending_timer_interrupts =
226  d->ptr_to_last_int = &machine->isa_pic_data.last_int;
227 
228  if (bus_isa_flags & BUS_ISA_NO_SECOND_PIC)
229  bus_isa_flags &= ~BUS_ISA_NO_SECOND_PIC;
230  else {
231  snprintf(tmpstr, sizeof(tmpstr),
232  "8259 irq=%s.isa.2 addr=0x%llx",
233  interrupt_base_path,(long long)(isa_portbase+0xa0));
234  d->pic2 = machine->isa_pic_data.pic2 = (struct pic8259_data *)
235  device_add(machine, tmpstr);
236  }
237  } else {
238  bus_isa_flags &= ~BUS_ISA_EXTERNAL_PIC;
239  }
240 
241  snprintf(tmpstr, sizeof(tmpstr), "8253 irq=%s.isa.%i addr=0x%llx "
242  "in_use=0", interrupt_base_path, 0,
243  (long long)(isa_portbase + 0x40));
244  device_add(machine, tmpstr);
245 
246  snprintf(tmpstr, sizeof(tmpstr), "pccmos irq=%s.isa.%i addr=0x%llx",
247  interrupt_base_path, 8, (long long)(isa_portbase + 0x70));
248  device_add(machine, tmpstr);
249 
250  snprintf(tmpstr, sizeof(tmpstr), "ns16550 irq=%s.isa.%i addr=0x%llx "
251  "name2=tty0 in_use=%i", interrupt_base_path, 4,
252  (long long)(isa_portbase + 0x3f8), 1 - kbd_in_use);
253  machine->main_console_handle = (size_t)device_add(machine, tmpstr);
254 
255  snprintf(tmpstr, sizeof(tmpstr), "ns16550 irq=%s.isa.%i addr=0x%llx "
256  "name2=tty1 in_use=0", interrupt_base_path, 3,
257  (long long)(isa_portbase + 0x2f8));
258  device_add(machine, tmpstr);
259 
260  if (bus_isa_flags & BUS_ISA_LPTBASE_3BC) {
261  bus_isa_flags &= ~BUS_ISA_LPTBASE_3BC;
262  lptbase = 0x3bc;
263  }
264 
265  snprintf(tmpstr, sizeof(tmpstr), "lpt irq=%s.isa.%i addr=0x%llx "
266  "name2=lpt in_use=0", interrupt_base_path, 7,
267  (long long)(isa_portbase + lptbase));
268  device_add(machine, tmpstr);
269 
270  if (bus_isa_flags & BUS_ISA_IDE0) {
271  bus_isa_flags &= ~BUS_ISA_IDE0;
272  snprintf(tmpstr, sizeof(tmpstr), "wdc irq=%s.isa.%i "
273  "addr=0x%llx", interrupt_base_path, wdc0_irq,
274  (long long)(isa_portbase + 0x1f0));
277  device_add(machine, tmpstr);
278  }
279 
280  if (bus_isa_flags & BUS_ISA_IDE1) {
281  bus_isa_flags &= ~BUS_ISA_IDE1;
282  snprintf(tmpstr, sizeof(tmpstr), "wdc irq=%s.isa.%i "
283  "addr=0x%llx", interrupt_base_path, wdc1_irq,
284  (long long)(isa_portbase + 0x170));
287  device_add(machine, tmpstr);
288  }
289 
290  if (bus_isa_flags & BUS_ISA_FDC) {
291  bus_isa_flags &= ~BUS_ISA_FDC;
292  snprintf(tmpstr, sizeof(tmpstr), "fdc irq=%s.isa.%i "
293  "addr=0x%llx", interrupt_base_path, 6,
294  (long long)(isa_portbase + 0x3f0));
295  device_add(machine, tmpstr);
296  }
297 
298  if (bus_isa_flags & BUS_ISA_VGA) {
299  if (machine->x11_md.in_use || bus_isa_flags & BUS_ISA_VGA_FORCE)
301  isa_membase + 0xa0000, isa_portbase + 0x3c0,
303  bus_isa_flags &= ~(BUS_ISA_VGA | BUS_ISA_VGA_FORCE);
304  }
305 
306  snprintf(tmpstr, sizeof(tmpstr), "%s.isa.1", interrupt_base_path);
307  snprintf(tmpstr2, sizeof(tmpstr2), "%s.isa.12", interrupt_base_path);
308  tmp_handle = dev_pckbc_init(machine, machine->memory,
309  isa_portbase + 0x60, PCKBC_8042, tmpstr, tmpstr2,
310  kbd_in_use, bus_isa_flags & BUS_ISA_PCKBC_NONPCSTYLE? 0 : 1);
311 
312  if (kbd_in_use)
313  machine->main_console_handle = tmp_handle;
314 
316 
317  if (bus_isa_flags != 0)
318  fatal("WARNING! bus_isa(): unimplemented bus_isa_flags 0x%x\n",
319  bus_isa_flags);
320 
321  return d;
322 }
323 
isa_pic_data::pending_timer_interrupts
int * pending_timer_interrupts
Definition: machine.h:51
INTERRUPT_CONNECT
#define INTERRUPT_CONNECT(name, istruct)
Definition: interrupt.h:77
BUS_ISA_PCKBC_FORCE_USE
#define BUS_ISA_PCKBC_FORCE_USE
Definition: bus_isa.h:63
INTERRUPT_ASSERT
#define INTERRUPT_ASSERT(istruct)
Definition: interrupt.h:74
BUS_ISA_EXTERNAL_PIC
#define BUS_ISA_EXTERNAL_PIC
Definition: bus_isa.h:67
interrupt::interrupt_deassert
void(* interrupt_deassert)(struct interrupt *)
Definition: interrupt.h:39
diskimage.h
PCKBC_8042
#define PCKBC_8042
Definition: devices.h:320
isa_pic_data::pic2
struct pic8259_data * pic2
Definition: machine.h:49
bus_isa.h
dev_vga_init
void dev_vga_init(struct machine *machine, struct memory *mem, uint64_t videomem_base, uint64_t control_base, const char *name)
Definition: dev_vga.cc:1187
interrupt::extra
void * extra
Definition: interrupt.h:59
isa_pic_data::pic1
struct pic8259_data * pic1
Definition: machine.h:48
isa_pic_data::last_int
int last_int
Definition: machine.h:52
isa_interrupt_assert
void isa_interrupt_assert(struct interrupt *interrupt)
Definition: bus_isa.cc:98
BUS_ISA_FDC
#define BUS_ISA_FDC
Definition: bus_isa.h:60
MACHINE_PREP
#define MACHINE_PREP
Definition: machine.h:227
device.h
BUS_ISA_IDE0
#define BUS_ISA_IDE0
Definition: bus_isa.h:58
BUS_ISA_IDE1
#define BUS_ISA_IDE1
Definition: bus_isa.h:59
interrupt.h
fatal
void fatal(const char *fmt,...)
Definition: main.cc:152
machine::isa_pic_data
struct isa_pic_data isa_pic_data
Definition: machine.h:190
x11_md::in_use
int in_use
Definition: machine.h:82
misc.h
BUS_ISA_LPTBASE_3BC
#define BUS_ISA_LPTBASE_3BC
Definition: bus_isa.h:66
device_add
void * device_add(struct machine *machine, const char *name_and_params)
Definition: device.cc:252
machine.h
machine
Definition: machine.h:97
machine::main_console_handle
int main_console_handle
Definition: machine.h:128
isa_interrupt_deassert
void isa_interrupt_deassert(struct interrupt *interrupt)
Definition: bus_isa.cc:120
BUS_ISA_PCKBC_NONPCSTYLE
#define BUS_ISA_PCKBC_NONPCSTYLE
Definition: bus_isa.h:64
pic8259_data
Definition: devices.h:63
machine::x11_md
struct x11_md x11_md
Definition: machine.h:179
machine::memory
struct memory * memory
Definition: machine.h:126
bus_isa_init
struct bus_isa_data * bus_isa_init(struct machine *machine, char *interrupt_base_path, uint32_t bus_isa_flags, uint64_t isa_portbase, uint64_t isa_membase)
Definition: bus_isa.cc:174
dev_pckbc_init
int dev_pckbc_init(struct machine *machine, struct memory *mem, uint64_t baseaddr, int type, char *keyboard_irqpath, char *mouse_irqpath, int in_use, int pc_style_flag)
Definition: dev_pckbc.cc:1157
INTERRUPT_DEASSERT
#define INTERRUPT_DEASSERT(istruct)
Definition: interrupt.h:75
machine::machine_type
int machine_type
Definition: machine.h:111
interrupt::line
uint32_t line
Definition: interrupt.h:51
DISKIMAGE_IDE
#define DISKIMAGE_IDE
Definition: diskimage.h:41
interrupt::interrupt_assert
void(* interrupt_assert)(struct interrupt *)
Definition: interrupt.h:38
interrupt_handler_register
void interrupt_handler_register(struct interrupt *templ)
Definition: interrupt.cc:81
interrupt::name
char * name
Definition: interrupt.h:66
interrupt
Definition: interrupt.h:36
devices.h
machine::machine_name
const char * machine_name
Definition: machine.h:115
BUS_ISA_VGA
#define BUS_ISA_VGA
Definition: bus_isa.h:61
BUS_ISA_NO_SECOND_PIC
#define BUS_ISA_NO_SECOND_PIC
Definition: bus_isa.h:65
isa_interrupt_common
void isa_interrupt_common(struct bus_isa_data *d, int old_isa_assert)
Definition: bus_isa.cc:52
diskimage_exist
int diskimage_exist(struct machine *machine, int id, int type)
Definition: diskimage.cc:106
BUS_ISA_VGA_FORCE
#define BUS_ISA_VGA_FORCE
Definition: bus_isa.h:62
CHECK_ALLOCATION
#define CHECK_ALLOCATION(ptr)
Definition: misc.h:239

Generated on Tue Aug 25 2020 19:25:06 for GXemul by doxygen 1.8.18