/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 20 - (hide annotations)
Mon Oct 8 16:19:23 2007 UTC (16 years, 6 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 dpavlin 4 /*
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 dpavlin 20 * $Id: bus_pci.c,v 1.40 2005/11/25 03:59:58 debug Exp $
29 dpavlin 4 *
30 dpavlin 20 * Generic PCI bus framework. This is not a normal "device", but is used by
31     * individual PCI controllers and devices.
32 dpavlin 4 *
33 dpavlin 20 * 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 dpavlin 4 */
44    
45     #include <stdio.h>
46     #include <stdlib.h>
47     #include <string.h>
48    
49 dpavlin 20 #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 dpavlin 4 #include "memory.h"
58     #include "misc.h"
59    
60 dpavlin 20 extern int verbose;
61 dpavlin 4
62 dpavlin 20
63 dpavlin 14 /* #define debug fatal */
64 dpavlin 4
65 dpavlin 14
66 dpavlin 20 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 dpavlin 4 /*
79 dpavlin 20 * 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 dpavlin 4 * 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 dpavlin 20 uint64_t *data, int len, int writeflag, struct pci_data *pci_data)
185 dpavlin 4 {
186     if (writeflag == MEM_READ)
187     *data = 0;
188    
189     switch (relative_addr) {
190 dpavlin 20
191 dpavlin 4 case BUS_PCI_ADDR:
192     if (writeflag == MEM_WRITE) {
193 dpavlin 20 debug("[ bus_pci: write to PCI ADDR: data = 0x%016llx"
194 dpavlin 4 " ]\n", (long long)*data);
195     pci_data->pci_addr = *data;
196 dpavlin 20
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 dpavlin 4 } 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 dpavlin 20
221 dpavlin 4 case BUS_PCI_DATA:
222 dpavlin 20 bus_pci_data_access(cpu, mem, data, len, writeflag, pci_data);
223     break;
224 dpavlin 4
225 dpavlin 20 default:if (writeflag == MEM_READ) {
226 dpavlin 4 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 dpavlin 20 "0x%x: 0x%llx ]\n", (int)relative_addr,
232     (long long)*data);
233 dpavlin 4 }
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 dpavlin 20 char *name)
248 dpavlin 4 {
249 dpavlin 20 struct pci_device *pd;
250     int ofs;
251     void (*init)(struct machine *, struct memory *, struct pci_device *);
252 dpavlin 4
253 dpavlin 14 if (pci_data == NULL) {
254     fatal("bus_pci_add(): pci_data == NULL!\n");
255     exit(1);
256     }
257    
258 dpavlin 20 /* Find the PCI device: */
259     init = pci_lookup_initf(name);
260    
261 dpavlin 4 /* Make sure this bus/device/function number isn't already in use: */
262 dpavlin 20 pd = pci_data->first_device;
263     while (pd != NULL) {
264     if (pd->bus == bus && pd->device == device &&
265     pd->function == function) {
266 dpavlin 4 fatal("bus_pci_add(): (bus %i, device %i, function"
267     " %i) already in use\n", bus, device, function);
268 dpavlin 20 exit(1);
269 dpavlin 4 }
270 dpavlin 20 pd = pd->next;
271 dpavlin 4 }
272    
273 dpavlin 20 pd = malloc(sizeof(struct pci_device));
274     if (pd == NULL) {
275 dpavlin 4 fprintf(stderr, "out of memory\n");
276     exit(1);
277     }
278    
279 dpavlin 20 memset(pd, 0, sizeof(struct pci_device));
280 dpavlin 4
281     /* Add the new device first in the PCI bus' chain: */
282 dpavlin 20 pd->next = pci_data->first_device;
283     pci_data->first_device = pd;
284 dpavlin 4
285 dpavlin 20 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 dpavlin 4 /* Call the PCI device' init function: */
309 dpavlin 20 init(machine, mem, pd);
310 dpavlin 4 }
311    
312    
313     /*
314 dpavlin 20 * 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 dpavlin 4 * 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 dpavlin 20 *
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 dpavlin 4 */
385 dpavlin 20 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 dpavlin 4 {
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 dpavlin 20 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 dpavlin 4
408 dpavlin 20 /* 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 dpavlin 4 return d;
413     }
414    
415 dpavlin 20
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