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

Contents of /trunk/src/devices/bus_pci.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 20 - (show annotations)
Mon Oct 8 16:19:23 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 26635 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1055 2005/11/25 22:48:36 debug Exp $
20051031	Adding disassembly support for more ARM instructions (clz,
		smul* etc), and adding a hack to support "new tiny" pages
		for StrongARM.
20051101	Minor documentation updates (NetBSD 2.0.2 -> 2.1, and OpenBSD
		3.7 -> 3.8, and lots of testing).
		Changing from 1-sector PIO mode 0 transfers to 128-sector PIO
		mode 3 (in dev_wdc).
		Various minor ARM dyntrans updates (pc-relative loads from
		within the same page as the instruction are now treated as
		constant "mov").
20051102	Re-enabling instruction combinations (they were accidentally
		disabled).
		Dyntrans TLB entries are now overwritten using a round-robin
		scheme instead of randomly. This increases performance.
		Fixing a typo in file.c (thanks to Chuan-Hua Chang for
		noticing it).
		Experimenting with adding ATAPI support to dev_wdc (to make
		emulated *BSD detect cdroms as cdroms, not harddisks).
20051104	Various minor updates.
20051105	Continuing on the ATAPI emulation. Seems to work well enough
		for a NetBSD/cats installation, but not OpenBSD/cats.
		Various other updates.
20051106	Modifying the -Y command line option to allow scaleup with
		certain graphic controllers (only dev_vga so far), not just
		scaledown.
		Some minor dyntrans cleanups.
20051107	Beginning a cleanup up the PCI subsystem (removing the
		read_register hack, etc).
20051108	Continuing the cleanup; splitting up some pci devices into a
		normal autodev device and some separate pci glue code.
20051109	Continuing on the PCI bus stuff; all old pci_*.c have been
		incorporated into normal devices and/or rewritten as glue code
		only, adding a dummy Intel 82371AB PIIX4 for Malta (not really
		tested yet).
		Minor pckbc fix so that Linux doesn't complain.
		Working on the DEC 21143 NIC (ethernet mac rom stuff mostly).
		Various other minor fixes.
20051110	Some more ARM dyntrans fine-tuning (e.g. some instruction
		combinations (cmps followed by conditional branch within the
		same page) and special cases for DPIs with regform when the
		shifter isn't used).
20051111	ARM dyntrans updates: O(n)->O(1) for just-mark-as-non-
		writable in the generic pc_to_pointers function, and some other
		minor hacks.
		Merging Cobalt and evbmips (Malta) ISA interrupt handling,
		and some minor fixes to allow Linux to accept harddisk irqs.
20051112	Minor device updates (pckbc, dec21143, lpt, ...), most
		importantly fixing the ALI M1543/M5229 so that harddisk irqs
		work with Linux/CATS.
20051113	Some more generalizations of the PCI subsystem.
		Finally took the time to add a hack for SCSI CDROM TOCs; this
		enables OpenBSD to use partition 'a' (as needed by the OpenBSD
		installer), and Windows NT's installer to get a bit further.
		Also fixing dev_wdc to allow Linux to detect ATAPI CDROMs.
		Continuing on the DEC 21143.
20051114	Minor ARM dyntrans tweaks; ARM cmps+branch optimization when
		comparing with 0, and generalizing the xchg instr. comb.
		Adding disassembly of ARM mrrc/mcrr and q{,d}{add,sub}.
20051115	Continuing on various PPC things (BATs, other address trans-
		lation things, various loads/stores, BeBox emulation, etc.).
		Beginning to work on PPC interrupt/exception support.
20051116	Factoring out some code which initializes legacy ISA devices
		from those machines that use them (bus_isa).
		Continuing on PPC interrupt/exception support.
20051117	Minor Malta fixes: RTC year offset = 80, disabling a speed hack
		which caused NetBSD to detect a too fast cpu, and adding a new
		hack to make Linux detect a faster cpu.
		Continuing on the Artesyn PM/PPC emulation mode.
		Adding an Algor emulation skeleton (P4032 and P5064);
		implementing some of the basics.
		Continuing on PPC emulation in general; usage of unimplemented
		SPRs is now easier to track, continuing on memory/exception
		related issues, etc.
20051118	More work on PPC emulation (tgpr0..3, exception handling,
		memory stuff, syscalls, etc.).
20051119	Changing the ARM dyntrans code to mostly use cpu->pc, and not
		necessarily use arm reg 15. Seems to work.
		Various PPC updates; continuing on the PReP emulation mode.
20051120	Adding a workaround/hack to dev_mc146818 to allow NetBSD/prep
		to detect the clock.
20051121	More cleanup of the PCI bus (memory and I/O bases, etc).
		Continuing on various PPC things (decrementer and timebase,
		WDCs on obio (on PReP) use irq 13, not 14/15).
20051122	Continuing on the CPC700 controller (interrupts etc) for PMPPC,
		and on PPC stuff in general.
		Finally! After some bug fixes to the virtual to physical addr
		translation, NetBSD/{prep,pmppc} 2.1 reach userland and are
		stable enough to be interacted with.
		More PCI updates; reverse-endian device access for PowerPC etc.
20051123	Generalizing the IEEE floating point subsystem (moving it out
		from src/cpus/cpu_mips_coproc.c into a new src/float_emul.c).
		Input via slave xterms was sometimes not really working; fixing
		this for ns16550, and a warning message is now displayed if
		multiple non-xterm consoles are active.
		Adding some PPC floating point support, etc.
		Various interrupt related updates (dev_wdc, _ns16550, _8259,
		and the isa32 common code in machine.c).
		NetBSD/prep can now be installed! :-) (Well, with some manual
		commands necessary before running sysinst.) Updating the
		documentation and various other things to reflect this.
20051124	Various minor documentation updates.
		Continuing the work on the DEC 21143 NIC.
20051125	LOTS of work on the 21143. Both OpenBSD and NetBSD work fine
		with it now, except that OpenBSD sometimes gives a time-out
		warning.
		Minor documentation updates.

==============  RELEASE 0.3.7  ==============


1 /*
2 * Copyright (C) 2004-2005 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 * $Id: bus_pci.c,v 1.40 2005/11/25 03:59:58 debug Exp $
29 *
30 * Generic PCI bus framework. This is not a normal "device", but is used by
31 * individual PCI controllers and devices.
32 *
33 * See NetBSD's pcidevs.h for more PCI vendor and device identifiers.
34 *
35 * TODO:
36 *
37 * x) Allow guest OSes to do runtime address fixups (i.e. actually
38 * move a device from one address to another).
39 *
40 * x) Generalize the PCI and legacy ISA interrupt routing stuff.
41 *
42 * x) Make sure that pci_little_endian is used correctly everywhere.
43 */
44
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48
49 #define BUS_PCI_C
50
51 #include "bus_pci.h"
52 #include "cpu.h"
53 #include "device.h"
54 #include "devices.h"
55 #include "diskimage.h"
56 #include "machine.h"
57 #include "memory.h"
58 #include "misc.h"
59
60 extern int verbose;
61
62
63 /* #define debug fatal */
64
65
66 static void reverse(uint64_t *p, int len)
67 {
68 uint64_t x = *p, y = 0;
69 int i;
70 for (i=0; i<len; i++) {
71 y <<= 8;
72 y |= ((x >> (8*i)) & 0xff);
73 }
74 *p = y;
75 }
76
77
78 /*
79 * bus_pci_data_access():
80 *
81 * Reads from and writes to the PCI configuration registers of a device.
82 */
83 void bus_pci_data_access(struct cpu *cpu, struct memory *mem,
84 uint64_t *data, int len, int writeflag, struct pci_data *pci_data)
85 {
86 struct pci_device *dev;
87 int bus, device, function, registernr;
88 unsigned char *cfg_base;
89 uint64_t x, idata = *data;
90
91 if (cpu->byte_order == EMUL_BIG_ENDIAN)
92 reverse(&idata, len);
93
94 /* Get the bus, device, and function numbers from the address: */
95 bus = (pci_data->pci_addr >> 16) & 0xff;
96 device = (pci_data->pci_addr >> 11) & 0x1f;
97 function = (pci_data->pci_addr >> 8) & 0x7;
98 registernr = (pci_data->pci_addr) & 0xff;
99
100 /* Scan through the list of pci_device entries. */
101 dev = pci_data->first_device;
102 while (dev != NULL) {
103 if (dev->bus == bus && dev->function == function &&
104 dev->device == device)
105 break;
106 dev = dev->next;
107 }
108
109 /* No device? Then return emptiness. */
110 if (dev == NULL) {
111 if ((pci_data->pci_addr & 0xff) == 0)
112 *data = 0xffffffff;
113 else
114 *data = 0;
115 return;
116 }
117
118 /* Return normal config data, or length data? */
119 if (pci_data->last_was_write_ffffffff &&
120 registernr >= PCI_MAPREG_START && registernr <= PCI_MAPREG_END - 4)
121 cfg_base = dev->cfg_mem_size;
122 else
123 cfg_base = dev->cfg_mem;
124
125 /* Read data as little-endian: */
126 x = 0;
127 if (registernr + len - 1 < PCI_CFG_MEM_SIZE) {
128 x = cfg_base[registernr];
129 if (len > 1)
130 x |= (cfg_base[registernr+1] << 8);
131 if (len > 2)
132 x |= (cfg_base[registernr+2] << 16);
133 if (len > 3)
134 x |= ((uint64_t)cfg_base[registernr+3] << 24);
135 if (len > 4)
136 fatal("TODO: more than 32-bit PCI access?\n");
137 }
138
139 /* Register write: */
140 if (writeflag == MEM_WRITE) {
141 debug("[ bus_pci: write to PCI DATA: data = 0x%016llx ]\n",
142 (long long)idata);
143 if (idata == 0xffffffffULL && registernr >= PCI_MAPREG_START
144 && registernr <= PCI_MAPREG_END - 4) {
145 pci_data->last_was_write_ffffffff = 1;
146 return;
147 }
148 /* Writes are not really supported yet: */
149 if (idata != x) {
150 debug("[ bus_pci: write to PCI DATA: data = 0x%08llx"
151 " differs from current value 0x%08llx; NOT YET"
152 " SUPPORTED. bus %i, device %i, function %i (%s)"
153 " register 0x%02x ]\n", (long long)idata,
154 (long long)x, bus, device, function, dev->name,
155 registernr);
156 }
157 return;
158 }
159
160 /* Register read: */
161 if (cpu->byte_order == EMUL_BIG_ENDIAN)
162 reverse(&x, len);
163 *data = x;
164
165 pci_data->last_was_write_ffffffff = 0;
166
167 debug("[ bus_pci: read from PCI DATA, addr = 0x%08lx (bus %i, device "
168 "%i, function %i (%s) register 0x%02x): 0x%08lx ]\n", (long)
169 pci_data->pci_addr, bus, device, function, dev->name,
170 registernr, (long)*data);
171 }
172
173
174 /*
175 * bus_pci_access():
176 *
177 * relative_addr should be either BUS_PCI_ADDR or BUS_PCI_DATA. The uint64_t
178 * pointed to by data should contain the word to be written to the pci bus,
179 * or a placeholder for information read from the bus.
180 *
181 * Returns 1 if ok, 0 on error.
182 */
183 int bus_pci_access(struct cpu *cpu, struct memory *mem, uint64_t relative_addr,
184 uint64_t *data, int len, int writeflag, struct pci_data *pci_data)
185 {
186 if (writeflag == MEM_READ)
187 *data = 0;
188
189 switch (relative_addr) {
190
191 case BUS_PCI_ADDR:
192 if (writeflag == MEM_WRITE) {
193 debug("[ bus_pci: write to PCI ADDR: data = 0x%016llx"
194 " ]\n", (long long)*data);
195 pci_data->pci_addr = *data;
196
197 /*
198 * Big-endian systems (e.g. PowerPC) seem to access
199 * PCI config data using little-endian accesses.
200 */
201 if (cpu->byte_order == EMUL_BIG_ENDIAN) {
202 uint32_t t = pci_data->pci_addr;
203 pci_data->pci_addr = ((t >> 24) & 255)
204 | ((t >> 8) & 0xff00)
205 | ((t << 8) & 0xff0000)
206 | ((t << 24) & 0xff000000);
207 }
208
209 /* Linux seems to use type 0 even when it does
210 type 1 detection. Hm. This is commented for now. */
211 /* if (pci_data->pci_addr & 1)
212 fatal("[ bus_pci: WARNING! pci type 0 not"
213 " yet implemented! ]\n"); */
214 } else {
215 debug("[ bus_pci: read from PCI ADDR (data = "
216 "0x%016llx) ]\n", (long long)pci_data->pci_addr);
217 *data = pci_data->pci_addr;
218 }
219 break;
220
221 case BUS_PCI_DATA:
222 bus_pci_data_access(cpu, mem, data, len, writeflag, pci_data);
223 break;
224
225 default:if (writeflag == MEM_READ) {
226 debug("[ bus_pci: read from unimplemented addr "
227 "0x%x ]\n", (int)relative_addr);
228 *data = 0;
229 } else {
230 debug("[ bus_pci: write to unimplemented addr "
231 "0x%x: 0x%llx ]\n", (int)relative_addr,
232 (long long)*data);
233 }
234 }
235
236 return 1;
237 }
238
239
240 /*
241 * bus_pci_add():
242 *
243 * Add a PCI device to a bus_pci device.
244 */
245 void bus_pci_add(struct machine *machine, struct pci_data *pci_data,
246 struct memory *mem, int bus, int device, int function,
247 char *name)
248 {
249 struct pci_device *pd;
250 int ofs;
251 void (*init)(struct machine *, struct memory *, struct pci_device *);
252
253 if (pci_data == NULL) {
254 fatal("bus_pci_add(): pci_data == NULL!\n");
255 exit(1);
256 }
257
258 /* Find the PCI device: */
259 init = pci_lookup_initf(name);
260
261 /* Make sure this bus/device/function number isn't already in use: */
262 pd = pci_data->first_device;
263 while (pd != NULL) {
264 if (pd->bus == bus && pd->device == device &&
265 pd->function == function) {
266 fatal("bus_pci_add(): (bus %i, device %i, function"
267 " %i) already in use\n", bus, device, function);
268 exit(1);
269 }
270 pd = pd->next;
271 }
272
273 pd = malloc(sizeof(struct pci_device));
274 if (pd == NULL) {
275 fprintf(stderr, "out of memory\n");
276 exit(1);
277 }
278
279 memset(pd, 0, sizeof(struct pci_device));
280
281 /* Add the new device first in the PCI bus' chain: */
282 pd->next = pci_data->first_device;
283 pci_data->first_device = pd;
284
285 pd->pcibus = pci_data;
286 pd->name = strdup(name);
287 pd->bus = bus;
288 pd->device = device;
289 pd->function = function;
290
291 /*
292 * Initialize with some default values:
293 *
294 * TODO: The command status register is best to set up per device,
295 * just enabling all bits like this is not really good.
296 * The size registers should also be set up on a per-device
297 * basis.
298 */
299 PCI_SET_DATA(PCI_COMMAND_STATUS_REG, 0x00ffffffULL);
300 for (ofs = PCI_MAPREG_START; ofs < PCI_MAPREG_END; ofs += 4)
301 PCI_SET_DATA_SIZE(ofs, 0x00400000 - 1);
302
303 if (init == NULL) {
304 fatal("No init function for PCI device \"%s\"?\n", name);
305 exit(1);
306 }
307
308 /* Call the PCI device' init function: */
309 init(machine, mem, pd);
310 }
311
312
313 /*
314 * allocate_device_space():
315 *
316 * Used by glue code (see below) to allocate space for a PCI device.
317 *
318 * The returned values in portp and memp are the actual (emulated) addresses
319 * that the device should use. (Normally only one of these is actually used.)
320 *
321 * TODO: PCI irqs?
322 */
323 static void allocate_device_space(struct pci_device *pd,
324 uint64_t portsize, uint64_t memsize,
325 uint64_t *portp, uint64_t *memp)
326 {
327 uint64_t port, mem;
328
329 /* Calculate an aligned starting port: */
330 port = pd->pcibus->cur_pci_portbase;
331 if (portsize != 0) {
332 port = ((port - 1) | (portsize - 1)) + 1;
333 pd->pcibus->cur_pci_portbase = port;
334 PCI_SET_DATA(PCI_MAPREG_START, port | PCI_MAPREG_TYPE_IO);
335 PCI_SET_DATA_SIZE(PCI_MAPREG_START, portsize - 1);
336 }
337
338 /* Calculate an aligned starting memory location: */
339 mem = pd->pcibus->cur_pci_membase;
340 if (memsize != 0) {
341 mem = ((mem - 1) | (memsize - 1)) + 1;
342 pd->pcibus->cur_pci_membase = mem;
343 PCI_SET_DATA(PCI_MAPREG_START + 0x04, mem);
344 PCI_SET_DATA_SIZE(PCI_MAPREG_START + 0x04, memsize - 1);
345 }
346
347 *portp = port + pd->pcibus->pci_actual_io_offset;
348 *memp = mem + pd->pcibus->pci_actual_mem_offset;
349
350 if (verbose >= 2) {
351 debug("pci device '%s' at", pd->name);
352 if (portsize != 0)
353 debug(" port 0x%llx-0x%llx", (long long)pd->pcibus->
354 cur_pci_portbase, (long long)(pd->pcibus->
355 cur_pci_portbase + portsize - 1));
356 if (memsize != 0)
357 debug(" mem 0x%llx-0x%llx", (long long)pd->pcibus->
358 cur_pci_membase, (long long)(pd->pcibus->
359 cur_pci_membase + memsize - 1));
360 debug("\n");
361 }
362
363 pd->pcibus->cur_pci_portbase += portsize;
364 pd->pcibus->cur_pci_membase += memsize;
365 }
366
367
368 /*
369 * bus_pci_init():
370 *
371 * This doesn't register a device, but instead returns a pointer to a struct
372 * which should be passed to bus_pci_access() when accessing the PCI bus.
373 *
374 * irq_nr is the (optional) IRQ nr that this PCI bus interrupts at.
375 *
376 * pci_portbase, pci_membase, and pci_irqbase are the port, memory, and
377 * interrupt bases for PCI devices (as found in the configuration registers).
378 *
379 * pci_actual_io_offset and pci_actual_mem_offset are the offset from
380 * the values in the configuration registers to the actual (emulated) device.
381 *
382 * isa_portbase, isa_membase, and isa_irqbase are the port, memory, and
383 * interrupt bases for legacy ISA devices.
384 */
385 struct pci_data *bus_pci_init(int irq_nr,
386 uint64_t pci_actual_io_offset, uint64_t pci_actual_mem_offset,
387 uint64_t pci_portbase, uint64_t pci_membase, int pci_irqbase,
388 uint64_t isa_portbase, uint64_t isa_membase, int isa_irqbase)
389 {
390 struct pci_data *d;
391
392 d = malloc(sizeof(struct pci_data));
393 if (d == NULL) {
394 fprintf(stderr, "out of memory\n");
395 exit(1);
396 }
397 memset(d, 0, sizeof(struct pci_data));
398 d->irq_nr = irq_nr;
399 d->pci_actual_io_offset = pci_actual_io_offset;
400 d->pci_actual_mem_offset = pci_actual_mem_offset;
401 d->pci_portbase = pci_portbase;
402 d->pci_membase = pci_membase;
403 d->pci_irqbase = pci_irqbase;
404 d->isa_portbase = isa_portbase;
405 d->isa_membase = isa_membase;
406 d->isa_irqbase = isa_irqbase;
407
408 /* Assume that the first 64KB could be used by legacy ISA devices: */
409 d->cur_pci_portbase = d->pci_portbase + 0x10000;
410 d->cur_pci_membase = d->pci_membase + 0x10000;
411
412 return d;
413 }
414
415
416
417 /******************************************************************************
418 *
419 * The following is glue code for PCI controllers and devices. The glue code
420 * does the minimal stuff necessary to get an emulated OS to detect the
421 * device (i.e. set up PCI configuration registers), and then if necessary
422 * add a "normal" device.
423 *
424 ******************************************************************************/
425
426
427
428 /*
429 * Integraphics Systems "igsfb" Framebuffer (graphics) card.
430 *
431 * TODO
432 */
433
434 #define PCI_VENDOR_INTEGRAPHICS 0x10ea
435
436 PCIINIT(igsfb)
437 {
438 PCI_SET_DATA(PCI_ID_REG,
439 PCI_ID_CODE(PCI_VENDOR_INTEGRAPHICS, 0x2010));
440
441 PCI_SET_DATA(PCI_CLASS_REG,
442 PCI_CLASS_CODE(PCI_CLASS_DISPLAY,
443 PCI_SUBCLASS_DISPLAY_VGA, 0) + 0x01);
444
445 /* TODO */
446 PCI_SET_DATA(0x10, 0xb0000000);
447
448 /* TODO: This is just a dummy so far. */
449 }
450
451
452
453 /*
454 * S3 ViRGE graphics.
455 *
456 * TODO: Only emulates a standard VGA card, so far.
457 */
458
459 #define PCI_VENDOR_S3 0x5333
460 #define PCI_PRODUCT_S3_VIRGE 0x5631
461 #define PCI_PRODUCT_S3_VIRGE_DX 0x8a01
462
463 PCIINIT(s3_virge)
464 {
465 PCI_SET_DATA(PCI_ID_REG,
466 PCI_ID_CODE(PCI_VENDOR_S3, PCI_PRODUCT_S3_VIRGE_DX));
467
468 PCI_SET_DATA(PCI_CLASS_REG,
469 PCI_CLASS_CODE(PCI_CLASS_DISPLAY,
470 PCI_SUBCLASS_DISPLAY_VGA, 0) + 0x01);
471
472 dev_vga_init(machine, mem, pd->pcibus->isa_membase + 0xa0000,
473 pd->pcibus->isa_portbase + 0x3c0, machine->machine_name);
474 }
475
476
477
478 /*
479 * Acer Labs M5229 PCI-IDE (UDMA) controller.
480 * Acer Labs M1543 PCI->ISA bridge.
481 */
482
483 #define PCI_VENDOR_ALI 0x10b9
484 #define PCI_PRODUCT_ALI_M1543 0x1533 /* NOTE: not 1543 */
485 #define PCI_PRODUCT_ALI_M5229 0x5229
486
487 PCIINIT(ali_m1543)
488 {
489 PCI_SET_DATA(PCI_ID_REG,
490 PCI_ID_CODE(PCI_VENDOR_ALI, PCI_PRODUCT_ALI_M1543));
491
492 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
493 PCI_SUBCLASS_BRIDGE_ISA, 0) + 0xc3);
494
495 PCI_SET_DATA(PCI_BHLC_REG,
496 PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
497
498 /* Linux uses these to detect which IRQ the IDE controller uses: */
499 PCI_SET_DATA(0x44, 0x0000000e);
500 PCI_SET_DATA(0x58, 0x00000003);
501 }
502
503 PCIINIT(ali_m5229)
504 {
505 char tmpstr[300];
506
507 PCI_SET_DATA(PCI_ID_REG,
508 PCI_ID_CODE(PCI_VENDOR_ALI, PCI_PRODUCT_ALI_M5229));
509
510 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_MASS_STORAGE,
511 PCI_SUBCLASS_MASS_STORAGE_IDE, 0x60) + 0xc1);
512
513 if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||
514 diskimage_exist(machine, 1, DISKIMAGE_IDE)) {
515 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i",
516 (long long)(pd->pcibus->isa_portbase + 0x1f0),
517 pd->pcibus->isa_irqbase + 14);
518 device_add(machine, tmpstr);
519 }
520
521 /* The secondary channel is disabled. TODO: fix this. */
522 }
523
524
525
526 /*
527 * Adaptec AHC SCSI controller.
528 */
529
530 #define PCI_VENDOR_ADP 0x9004 /* Adaptec */
531 #define PCI_VENDOR_ADP2 0x9005 /* Adaptec (2nd PCI Vendor ID) */
532 #define PCI_PRODUCT_ADP_2940U 0x8178 /* AHA-2940 Ultra */
533 #define PCI_PRODUCT_ADP_2940UP 0x8778 /* AHA-2940 Ultra Pro */
534
535 PCIINIT(ahc)
536 {
537 /* Numbers taken from a Adaptec 2940U: */
538 /* http://mail-index.netbsd.org/netbsd-bugs/2000/04/29/0000.html */
539
540 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_ADP,
541 PCI_PRODUCT_ADP_2940U));
542
543 PCI_SET_DATA(PCI_COMMAND_STATUS_REG, 0x02900007);
544
545 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_MASS_STORAGE,
546 PCI_SUBCLASS_MASS_STORAGE_SCSI, 0) + 0x01);
547
548 PCI_SET_DATA(PCI_BHLC_REG, 0x00004008);
549
550 /* 1 = type i/o. 0x0000e801; address? */
551 /* second address reg = 0xf1002000? */
552 PCI_SET_DATA(PCI_MAPREG_START + 0x00, 0x00000001);
553 PCI_SET_DATA(PCI_MAPREG_START + 0x04, 0x00000000);
554
555 PCI_SET_DATA(PCI_MAPREG_START + 0x08, 0x00000000);
556 PCI_SET_DATA(PCI_MAPREG_START + 0x0c, 0x00000000);
557 PCI_SET_DATA(PCI_MAPREG_START + 0x10, 0x00000000);
558 PCI_SET_DATA(PCI_MAPREG_START + 0x14, 0x00000000);
559 PCI_SET_DATA(PCI_MAPREG_START + 0x18, 0x00000000);
560
561 /* Subsystem vendor ID? 0x78819004? */
562 PCI_SET_DATA(PCI_MAPREG_START + 0x1c, 0x00000000);
563
564 PCI_SET_DATA(0x30, 0xef000000);
565 PCI_SET_DATA(PCI_CAPLISTPTR_REG, 0x000000dc);
566 PCI_SET_DATA(0x38, 0x00000000);
567 PCI_SET_DATA(PCI_INTERRUPT_REG, 0x08080109); /* interrupt pin A */
568
569 /*
570 * TODO: this address is based on what NetBSD/sgimips uses
571 * on SGI IP32 (O2). Fix this!
572 */
573
574 device_add(machine, "ahc addr=0x18000000");
575
576 /* OpenBSD/sgi snapshots sometime between 2005-03-11 and
577 2005-04-04 changed to using 0x1a000000: */
578 dev_ram_init(machine, 0x1a000000, 0x2000000, DEV_RAM_MIRROR,
579 0x18000000);
580 }
581
582
583
584 /*
585 * Galileo Technology GT-64xxx PCI controller.
586 *
587 * GT-64011 Used in Cobalt machines.
588 * GT-64120 Used in evbmips machines (Malta).
589 *
590 * NOTE: This works in the opposite way compared to other devices; the PCI
591 * device is added from the normal device instead of the other way around.
592 */
593
594 #define PCI_VENDOR_GALILEO 0x11ab /* Galileo Technology */
595 #define PCI_PRODUCT_GALILEO_GT64011 0x4146 /* GT-64011 System Controller */
596 #define PCI_PRODUCT_GALILEO_GT64120 0x4620 /* GT-64120 */
597
598 PCIINIT(gt64011)
599 {
600 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_GALILEO,
601 PCI_PRODUCT_GALILEO_GT64011));
602
603 PCI_SET_DATA(PCI_CLASS_REG,
604 PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
605 PCI_SUBCLASS_BRIDGE_HOST, 0) + 0x01); /* Revision 1 */
606 }
607
608 PCIINIT(gt64120)
609 {
610 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_GALILEO,
611 PCI_PRODUCT_GALILEO_GT64120));
612
613 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
614 PCI_SUBCLASS_BRIDGE_HOST, 0) + 0x02); /* Revision 2? */
615
616 switch (machine->machine_type) {
617 case MACHINE_EVBMIPS:
618 PCI_SET_DATA(PCI_MAPREG_START + 0x10, 0x1be00000);
619 break;
620 }
621 }
622
623
624
625 /*
626 * Intel 82371AB PIIX4 PCI-ISA bridge and IDE controller
627 * and 82378ZB System I/O controller.
628 */
629
630 #define PCI_VENDOR_INTEL 0x8086
631 #define PCI_PRODUCT_INTEL_82371AB_ISA 0x7110
632 #define PCI_PRODUCT_INTEL_82371AB_IDE 0x7111
633 #define PCI_PRODUCT_INTEL_SIO 0x0484
634
635 PCIINIT(i82371ab_isa)
636 {
637 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_INTEL,
638 PCI_PRODUCT_INTEL_82371AB_ISA));
639
640 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
641 PCI_SUBCLASS_BRIDGE_ISA, 0) + 0x01); /* Rev 1 */
642
643 PCI_SET_DATA(PCI_BHLC_REG,
644 PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
645 }
646
647 PCIINIT(i82378zb)
648 {
649 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_INTEL,
650 PCI_PRODUCT_INTEL_SIO));
651
652 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
653 PCI_SUBCLASS_BRIDGE_ISA, 0) + 0x43);
654
655 PCI_SET_DATA(PCI_BHLC_REG,
656 PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
657 }
658
659 PCIINIT(i82371ab_ide)
660 {
661 char tmpstr[100];
662
663 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_INTEL,
664 PCI_PRODUCT_INTEL_82371AB_IDE));
665
666 /* Possibly not correct: */
667 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_MASS_STORAGE,
668 PCI_SUBCLASS_MASS_STORAGE_IDE, 0x00) + 0x01);
669
670 /* PIIX_IDETIM (see NetBSD's pciide_piix_reg.h) */
671 /* channel 0 and 1 enabled as IDE */
672 PCI_SET_DATA(0x40, 0x80008000);
673
674 if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||
675 diskimage_exist(machine, 1, DISKIMAGE_IDE)) {
676 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i",
677 (long long)(pd->pcibus->isa_portbase + 0x1f0),
678 pd->pcibus->isa_irqbase + 14);
679 device_add(machine, tmpstr);
680 }
681
682 if (diskimage_exist(machine, 2, DISKIMAGE_IDE) ||
683 diskimage_exist(machine, 3, DISKIMAGE_IDE)) {
684 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i",
685 (long long)(pd->pcibus->isa_portbase + 0x170),
686 pd->pcibus->isa_irqbase + 15);
687 device_add(machine, tmpstr);
688 }
689 }
690
691
692
693 /*
694 * IBM ISA bridge (used by at least one PReP machine).
695 */
696
697 #define PCI_VENDOR_IBM 0x1014
698 #define PCI_PRODUCT_IBM_ISABRIDGE 0x000a
699
700 PCIINIT(ibm_isa)
701 {
702 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_IBM,
703 PCI_PRODUCT_IBM_ISABRIDGE));
704
705 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
706 PCI_SUBCLASS_BRIDGE_ISA, 0) + 0x02);
707
708 PCI_SET_DATA(PCI_BHLC_REG,
709 PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
710 }
711
712
713
714 /*
715 * Heuricon PCI host bridge for PM/PPC.
716 */
717
718 #define PCI_VENDOR_HEURICON 0x1223
719 #define PCI_PRODUCT_HEURICON_PMPPC 0x000e
720
721 PCIINIT(heuricon_pmppc)
722 {
723 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_HEURICON,
724 PCI_PRODUCT_HEURICON_PMPPC));
725
726 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
727 PCI_SUBCLASS_BRIDGE_HOST, 0) + 0x00); /* Revision? */
728
729 PCI_SET_DATA(PCI_BHLC_REG,
730 PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
731 }
732
733
734
735 /*
736 * VIATECH VT82C586 devices:
737 *
738 * vt82c586_isa PCI->ISA bridge
739 * vt82c586_ide IDE controller
740 *
741 * TODO: This more or less just a dummy device, so far.
742 */
743
744 #define PCI_VENDOR_VIATECH 0x1106 /* VIA Technologies */
745 #define PCI_PRODUCT_VIATECH_VT82C586_IDE 0x1571 /* VT82C586 (Apollo VP)
746 IDE Controller */
747 #define PCI_PRODUCT_VIATECH_VT82C586_ISA 0x0586 /* VT82C586 (Apollo VP)
748 PCI-ISA Bridge */
749
750 PCIINIT(vt82c586_isa)
751 {
752 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_VIATECH,
753 PCI_PRODUCT_VIATECH_VT82C586_ISA));
754
755 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
756 PCI_SUBCLASS_BRIDGE_ISA, 0) + 0x39); /* Revision 37 or 39 */
757
758 PCI_SET_DATA(PCI_BHLC_REG,
759 PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
760 }
761
762 PCIINIT(vt82c586_ide)
763 {
764 char tmpstr[100];
765
766 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_VIATECH,
767 PCI_PRODUCT_VIATECH_VT82C586_IDE));
768
769 /* Possibly not correct: */
770 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_MASS_STORAGE,
771 PCI_SUBCLASS_MASS_STORAGE_IDE, 0x00) + 0x01);
772
773 /* APO_IDECONF */
774 /* channel 0 and 1 enabled */
775 PCI_SET_DATA(0x40, 0x00000003);
776
777 if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||
778 diskimage_exist(machine, 1, DISKIMAGE_IDE)) {
779 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i",
780 (long long)(pd->pcibus->isa_portbase + 0x1f0),
781 pd->pcibus->isa_irqbase + 14);
782 device_add(machine, tmpstr);
783 }
784
785 if (diskimage_exist(machine, 2, DISKIMAGE_IDE) ||
786 diskimage_exist(machine, 3, DISKIMAGE_IDE)) {
787 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i",
788 (long long)(pd->pcibus->isa_portbase + 0x170),
789 pd->pcibus->isa_irqbase + 15);
790 device_add(machine, tmpstr);
791 }
792 }
793
794
795
796 /*
797 * Symphony Labs 83C553 PCI->ISA bridge.
798 * Symphony Labs 82C105 PCIIDE controller.
799 */
800
801 #define PCI_VENDOR_SYMPHONY 0x10ad
802 #define PCI_PRODUCT_SYMPHONY_83C553 0x0565
803 #define PCI_PRODUCT_SYMPHONY_82C105 0x0105
804
805 PCIINIT(symphony_83c553)
806 {
807 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_SYMPHONY,
808 PCI_PRODUCT_SYMPHONY_83C553));
809
810 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
811 PCI_SUBCLASS_BRIDGE_ISA, 0) + 0x10);
812
813 PCI_SET_DATA(PCI_BHLC_REG,
814 PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
815 }
816
817 PCIINIT(symphony_82c105)
818 {
819 char tmpstr[100];
820
821 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_SYMPHONY,
822 PCI_PRODUCT_SYMPHONY_82C105));
823
824 /* Possibly not correct: */
825 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_MASS_STORAGE,
826 PCI_SUBCLASS_MASS_STORAGE_IDE, 0x00) + 0x05);
827
828 /* APO_IDECONF */
829 /* channel 0 and 1 enabled */
830 PCI_SET_DATA(0x40, 0x00000003);
831
832 if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||
833 diskimage_exist(machine, 1, DISKIMAGE_IDE)) {
834 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i",
835 (long long)(pd->pcibus->isa_portbase + 0x1f0),
836 pd->pcibus->isa_irqbase + 14);
837 device_add(machine, tmpstr);
838 }
839
840 if (diskimage_exist(machine, 2, DISKIMAGE_IDE) ||
841 diskimage_exist(machine, 3, DISKIMAGE_IDE)) {
842 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i",
843 (long long)(pd->pcibus->isa_portbase + 0x170),
844 pd->pcibus->isa_irqbase + 15);
845 device_add(machine, tmpstr);
846 }
847 }
848
849
850
851 /*
852 * DEC 21143 ("Tulip") PCI ethernet.
853 */
854
855 #define PCI_VENDOR_DEC 0x1011 /* Digital Equipment */
856 #define PCI_PRODUCT_DEC_21142 0x0019 /* DECchip 21142/21143 10/100 Ethernet */
857
858 PCIINIT(dec21143)
859 {
860 uint64_t port, memaddr;
861 int irq = 0; /* TODO */
862 int int_line = 1; /* TODO */
863 char tmpstr[200];
864
865 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_DEC,
866 PCI_PRODUCT_DEC_21142));
867
868 PCI_SET_DATA(PCI_COMMAND_STATUS_REG, 0x02000017);
869
870 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_NETWORK,
871 PCI_SUBCLASS_NETWORK_ETHERNET, 0x00) + 0x41);
872
873 PCI_SET_DATA(PCI_BHLC_REG, PCI_BHLC_CODE(0,0,0, 0x40,0));
874
875 switch (machine->machine_type) {
876 case MACHINE_CATS:
877 irq = 18;
878 int_line = 1;
879 break;
880 case MACHINE_PREP:
881 int_line = 0xa;
882 irq = 31 - int_line;
883 break;
884 case MACHINE_PMPPC:
885 irq = 31 - 21;
886 break;
887 }
888
889 PCI_SET_DATA(PCI_INTERRUPT_REG, 0x28140100 | int_line);
890
891 allocate_device_space(pd, 0x100, 0x100, &port, &memaddr);
892
893 snprintf(tmpstr, sizeof(tmpstr), "dec21143 addr=0x%llx addr2=0x%llx "
894 "irq=%i pci_little_endian=1", (long long)port, (long long)memaddr,
895 irq);
896 device_add(machine, tmpstr);
897 }
898
899
900
901 /*
902 * DEC 21030 "tga" graphics.
903 */
904
905 #define PCI_PRODUCT_DEC_21030 0x0004 /* DECchip 21030 ("TGA") */
906
907 PCIINIT(dec21030)
908 {
909 uint64_t base = 0;
910 char tmpstr[200];
911
912 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_DEC,
913 PCI_PRODUCT_DEC_21030));
914
915 PCI_SET_DATA(PCI_COMMAND_STATUS_REG, 0x02800087); /* TODO */
916
917 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_DISPLAY,
918 PCI_SUBCLASS_DISPLAY_VGA, 0x00) + 0x03);
919
920 /*
921 * See http://mail-index.netbsd.org/port-arc/2001/08/13/0000.html
922 * for more info.
923 */
924
925 PCI_SET_DATA(PCI_BHLC_REG, 0x0000ff00);
926
927 /* 8 = prefetchable */
928 PCI_SET_DATA(0x10, 0x00000008);
929 PCI_SET_DATA(0x30, 0x08000001);
930 PCI_SET_DATA(PCI_INTERRUPT_REG, 0x00000100); /* interrupt pin A? */
931
932 /*
933 * Experimental:
934 *
935 * TODO: Base address, pci_little_endian, ...
936 */
937
938 switch (machine->machine_type) {
939 case MACHINE_ARC:
940 base = 0x100000000ULL;
941 break;
942 default:fatal("dec21030 in non-implemented machine type %i\n",
943 machine->machine_type);
944 exit(1);
945 }
946
947 snprintf(tmpstr, sizeof(tmpstr), "dec21030 addr=0x%llx",
948 (long long)(base));
949 device_add(machine, tmpstr);
950 }
951
952
953 /*
954 * Motorola MPC105 "Eagle" Host Bridge
955 *
956 * Used in at least PReP and BeBox.
957 */
958
959 #define PCI_VENDOR_MOT 0x1057
960 #define PCI_PRODUCT_MOT_MPC105 0x0001
961
962 PCIINIT(eagle)
963 {
964 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_MOT,
965 PCI_PRODUCT_MOT_MPC105));
966
967 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
968 PCI_SUBCLASS_BRIDGE_HOST, 0) + 0x24);
969
970 PCI_SET_DATA(PCI_BHLC_REG,
971 PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
972 }
973

  ViewVC Help
Powered by ViewVC 1.1.26