/[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 40 - (hide annotations)
Mon Oct 8 16:22:11 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 37769 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1539 2007/05/01 04:03:51 debug Exp $
20070415	Landisk PCLOCK should be 33.33 MHz, not 50 MHz. (This makes
		the clock run at correct speed.)
		FINALLY found and fixed the bug which caused OpenBSD/landisk
		to randomly bug out: an &-sign was missing in the special case
		handling of FPSCR in the 'LDS.L @Rm+,FPSCR' instruction.
		Adding similar special case handling for 'LDC.L @Rm+,SR'
		(calling sh_update_sr() instead of just loading).
		Implementing the 'FCNVSD FPUL,DRn' and 'FCNVDS DRm,FPUL'
		SuperH instructions.
		The 'LDC Rm,SR' instruction now immediately breaks out of the
		dyntrans loop if an interrupt is to be triggered.
20070416	In memory_rw.c, if mapping a page as writable, make sure to
		invalidate code translations even if the data access was a
		read.
		Minor SuperH updates.
20070418	Removing the dummy M68K emulation mode.
		Minor SH update (turning unnecessary sts_mach_rn, sts_macl_rn,
		and sts_pr_rn instruction handlers into mov_rm_rn).
20070419	Beginning to add a skeleton for an M88K mode: Adding a hack to
		allow OpenBSD/m88k a.out binaries to be loaded, and disassembly
		of a few simple 88K instructions.
		Commenting out the 'LDC Rm,SR' fix from a few days ago, because
		it made Linux/dreamcast bug out.
		Adding a hack to dev_sh4.c (an extra translation cache
		invalidation), which allows OpenBSD/landisk to boot ok after
		an install. Upgrading the Landisk machine mode to stable,
		updating documentation, etc.
20070420	Experimenting with adding a PCI controller (pcic) to dev_sh4.
		Adding a dummy Realtek 8139C+ skeleton device (dev_rtl8139c).
		Implementing the first M88K instructions (br, or[.u] imm), and
		adding disassembly of some more instructions.
20070421	Continuing a little on dev_rtl8139c.
20070422	Implementing the 9346 EEPROM "read" command for dev_rtl8139c.
		Finally found and fixed an old bug in the log n symbol search
		(it sometimes missed symbols). Debug trace (-i, -t etc) should
		now show more symbols. :-)
20070423	Continuing a little on M88K disassembly.
20070428	Fixing a memset arg order bug in src/net/net.c (thanks to
		Nigel Horne for noticing the bug).
		Applying parts of a patch from Carl van Schaik to clear out
		bottom bits of MIPS addresses more correctly, when using large
		page sizes, and doing some other minor cleanup/refactoring.
		Fixing a couple of warnings given by gcc with the -W option (a
		few more warnings than just plain -Wall).
		Reducing SuperH dyntrans physical address space from 64-bit to
		32-bit (since SH5/SH64 isn't imlemented yet anyway).
		Adding address-to-symbol annotation to a few more instructions
		in the SuperH instruction trace output.
		Beginning regression testing for the next release.
		Reverting the value of SCIF_DELAYED_TX_VALUE from 1 to 2,
		because OpenBSD/landisk may otherwise hang randomly.
20070429	The ugly hack/workaround to get OpenBSD/landisk booting without
		crashing does NOT work anymore (with the April 21 snapshot
		of OpenBSD/landisk). Strangely enough, removing the hack
		completely causes OpenBSD/landisk to work (!).
		More regression testing (re-testing everything SuperH-related,
		and some other things).
		Cobalt interrupts were actually broken; fixing by commenting
		out the DEC21143s in the Cobalt machine.
20070430	More regression testing.
20070501	Updating the OpenBSD/landisk install instructions to use
		4.1 instead of the current snapshot.
		GAAAH! OpenBSD/landisk 4.1 _needs_ the ugly hack/workaround;
		reintroducing it again. (The 4.1 kernel is actually from
		2007-03-11.)
		Simplifying the NetBSD/evbarm install instructions a bit.
		More regression testing.

==============  RELEASE 0.4.5.1  ==============


1 dpavlin 4 /*
2 dpavlin 34 * Copyright (C) 2004-2007 Anders Gavare. All rights reserved.
3 dpavlin 4 *
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 40 * $Id: bus_pci.c,v 1.82 2007/04/21 02:36:23 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 dpavlin 34 #include "bus_isa.h"
52 dpavlin 20 #include "bus_pci.h"
53     #include "cpu.h"
54     #include "device.h"
55     #include "devices.h"
56     #include "diskimage.h"
57     #include "machine.h"
58 dpavlin 4 #include "memory.h"
59     #include "misc.h"
60    
61 dpavlin 30 #include "wdc.h"
62    
63 dpavlin 20 extern int verbose;
64 dpavlin 4
65 dpavlin 20
66 dpavlin 24 #ifdef UNSTABLE_DEVEL
67     #define debug fatal
68     #endif
69 dpavlin 4
70 dpavlin 14
71 dpavlin 22 /*
72     * bus_pci_decompose_1():
73     *
74     * Helper function for decomposing Mechanism 1 tags.
75     */
76     void bus_pci_decompose_1(uint32_t t, int *bus, int *dev, int *func, int *reg)
77 dpavlin 20 {
78 dpavlin 22 *bus = (t >> 16) & 0xff;
79     *dev = (t >> 11) & 0x1f;
80     *func = (t >> 8) & 0x7;
81     *reg = t & 0xff;
82    
83     /* Warn about unaligned register access: */
84     if (t & 3)
85     fatal("[ bus_pci_decompose_1: WARNING: reg = 0x%02x ]\n",
86     t & 0xff);
87 dpavlin 20 }
88    
89    
90 dpavlin 4 /*
91 dpavlin 20 * bus_pci_data_access():
92     *
93 dpavlin 22 * Reads from or writes to the PCI configuration registers of a device.
94 dpavlin 20 */
95 dpavlin 22 void bus_pci_data_access(struct cpu *cpu, struct pci_data *pci_data,
96     uint64_t *data, int len, int writeflag)
97 dpavlin 20 {
98     struct pci_device *dev;
99     unsigned char *cfg_base;
100     uint64_t x, idata = *data;
101 dpavlin 22 int i;
102 dpavlin 20
103     /* Scan through the list of pci_device entries. */
104     dev = pci_data->first_device;
105     while (dev != NULL) {
106 dpavlin 22 if (dev->bus == pci_data->cur_bus &&
107     dev->function == pci_data->cur_func &&
108     dev->device == pci_data->cur_device)
109 dpavlin 20 break;
110     dev = dev->next;
111     }
112    
113     /* No device? Then return emptiness. */
114     if (dev == NULL) {
115 dpavlin 22 if (writeflag == MEM_READ) {
116     if (pci_data->cur_reg == 0)
117     *data = -1;
118     else
119     *data = 0;
120     } else {
121     fatal("[ bus_pci_data_access(): write to non-existant"
122     " device? ]\n");
123     }
124 dpavlin 20 return;
125     }
126    
127     /* Return normal config data, or length data? */
128     if (pci_data->last_was_write_ffffffff &&
129 dpavlin 22 pci_data->cur_reg >= PCI_MAPREG_START &&
130     pci_data->cur_reg <= PCI_MAPREG_END - 4)
131 dpavlin 20 cfg_base = dev->cfg_mem_size;
132     else
133     cfg_base = dev->cfg_mem;
134    
135     /* Read data as little-endian: */
136     x = 0;
137 dpavlin 22 for (i=len-1; i>=0; i--) {
138     int ofs = pci_data->cur_reg + i;
139     x <<= 8;
140     x |= cfg_base[ofs & (PCI_CFG_MEM_SIZE - 1)];
141 dpavlin 20 }
142    
143     /* Register write: */
144     if (writeflag == MEM_WRITE) {
145 dpavlin 22 debug("[ bus_pci: write to PCI DATA: data = 0x%08llx ]\n",
146 dpavlin 20 (long long)idata);
147 dpavlin 22 if (idata == 0xffffffffULL &&
148     pci_data->cur_reg >= PCI_MAPREG_START &&
149     pci_data->cur_reg <= PCI_MAPREG_END - 4) {
150 dpavlin 20 pci_data->last_was_write_ffffffff = 1;
151     return;
152     }
153 dpavlin 30
154     if (dev->cfg_reg_write != NULL) {
155     dev->cfg_reg_write(dev, pci_data->cur_reg, *data);
156     } else {
157     /* Print a warning for unhandled writes: */
158 dpavlin 20 debug("[ bus_pci: write to PCI DATA: data = 0x%08llx"
159 dpavlin 30 " (current value = 0x%08llx); NOT YET"
160 dpavlin 20 " SUPPORTED. bus %i, device %i, function %i (%s)"
161     " register 0x%02x ]\n", (long long)idata,
162 dpavlin 22 (long long)x, pci_data->cur_bus,
163     pci_data->cur_device, pci_data->cur_func,
164     dev->name, pci_data->cur_reg);
165 dpavlin 30
166     /* Special warning, to detect if NetBSD's special
167     detection of PCI devices fails: */
168     if (pci_data->cur_reg == PCI_COMMAND_STATUS_REG
169     && !((*data) & PCI_COMMAND_IO_ENABLE)) {
170     fatal("\n[ NetBSD PCI detection stuff not"
171     " yet implemented for device '%s' ]\n",
172     dev->name);
173     }
174 dpavlin 20 }
175     return;
176     }
177    
178     /* Register read: */
179     *data = x;
180    
181     pci_data->last_was_write_ffffffff = 0;
182    
183 dpavlin 22 debug("[ bus_pci: read from PCI DATA, bus %i, device "
184 dpavlin 24 "%i, function %i (%s) register 0x%02x: (len=%i) 0x%08lx ]\n",
185     pci_data->cur_bus, pci_data->cur_device, pci_data->cur_func,
186     dev->name, pci_data->cur_reg, len, (long)*data);
187 dpavlin 20 }
188    
189    
190     /*
191 dpavlin 22 * bus_pci_setaddr():
192 dpavlin 4 *
193 dpavlin 22 * Sets the address in preparation for a PCI register transfer.
194 dpavlin 4 */
195 dpavlin 22 void bus_pci_setaddr(struct cpu *cpu, struct pci_data *pci_data,
196     int bus, int device, int function, int reg)
197 dpavlin 4 {
198 dpavlin 22 if (cpu == NULL || pci_data == NULL) {
199     fatal("bus_pci_setaddr(): NULL ptr\n");
200     exit(1);
201 dpavlin 4 }
202    
203 dpavlin 22 pci_data->cur_bus = bus;
204     pci_data->cur_device = device;
205     pci_data->cur_func = function;
206     pci_data->cur_reg = reg;
207 dpavlin 4 }
208    
209    
210     /*
211     * bus_pci_add():
212     *
213     * Add a PCI device to a bus_pci device.
214     */
215     void bus_pci_add(struct machine *machine, struct pci_data *pci_data,
216     struct memory *mem, int bus, int device, int function,
217 dpavlin 22 const char *name)
218 dpavlin 4 {
219 dpavlin 20 struct pci_device *pd;
220     int ofs;
221     void (*init)(struct machine *, struct memory *, struct pci_device *);
222 dpavlin 4
223 dpavlin 14 if (pci_data == NULL) {
224     fatal("bus_pci_add(): pci_data == NULL!\n");
225 dpavlin 34 abort();
226 dpavlin 14 }
227    
228 dpavlin 20 /* Find the PCI device: */
229     init = pci_lookup_initf(name);
230    
231 dpavlin 4 /* Make sure this bus/device/function number isn't already in use: */
232 dpavlin 20 pd = pci_data->first_device;
233     while (pd != NULL) {
234     if (pd->bus == bus && pd->device == device &&
235     pd->function == function) {
236 dpavlin 4 fatal("bus_pci_add(): (bus %i, device %i, function"
237     " %i) already in use\n", bus, device, function);
238 dpavlin 20 exit(1);
239 dpavlin 4 }
240 dpavlin 20 pd = pd->next;
241 dpavlin 4 }
242    
243 dpavlin 20 pd = malloc(sizeof(struct pci_device));
244     if (pd == NULL) {
245 dpavlin 4 fprintf(stderr, "out of memory\n");
246     exit(1);
247     }
248    
249 dpavlin 20 memset(pd, 0, sizeof(struct pci_device));
250 dpavlin 4
251     /* Add the new device first in the PCI bus' chain: */
252 dpavlin 20 pd->next = pci_data->first_device;
253     pci_data->first_device = pd;
254 dpavlin 4
255 dpavlin 20 pd->pcibus = pci_data;
256     pd->name = strdup(name);
257     pd->bus = bus;
258     pd->device = device;
259     pd->function = function;
260    
261     /*
262     * Initialize with some default values:
263     *
264 dpavlin 22 * TODO: The command status register is best to set up per device.
265     * The size registers should also be set up on a per-device basis.
266 dpavlin 20 */
267 dpavlin 22 PCI_SET_DATA(PCI_COMMAND_STATUS_REG,
268     PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE);
269 dpavlin 20 for (ofs = PCI_MAPREG_START; ofs < PCI_MAPREG_END; ofs += 4)
270 dpavlin 22 PCI_SET_DATA_SIZE(ofs, 0x00100000 - 1);
271 dpavlin 20
272     if (init == NULL) {
273     fatal("No init function for PCI device \"%s\"?\n", name);
274     exit(1);
275     }
276    
277 dpavlin 4 /* Call the PCI device' init function: */
278 dpavlin 20 init(machine, mem, pd);
279 dpavlin 4 }
280    
281    
282     /*
283 dpavlin 20 * allocate_device_space():
284     *
285     * Used by glue code (see below) to allocate space for a PCI device.
286     *
287     * The returned values in portp and memp are the actual (emulated) addresses
288     * that the device should use. (Normally only one of these is actually used.)
289     *
290     * TODO: PCI irqs?
291     */
292     static void allocate_device_space(struct pci_device *pd,
293     uint64_t portsize, uint64_t memsize,
294     uint64_t *portp, uint64_t *memp)
295     {
296     uint64_t port, mem;
297    
298     /* Calculate an aligned starting port: */
299     port = pd->pcibus->cur_pci_portbase;
300     if (portsize != 0) {
301     port = ((port - 1) | (portsize - 1)) + 1;
302     pd->pcibus->cur_pci_portbase = port;
303 dpavlin 22 PCI_SET_DATA(PCI_MAPREG_START + pd->cur_mapreg_offset,
304     port | PCI_MAPREG_TYPE_IO);
305     PCI_SET_DATA_SIZE(PCI_MAPREG_START + pd->cur_mapreg_offset,
306 dpavlin 24 ((portsize - 1) & ~0xf) | 0xd);
307 dpavlin 22 pd->cur_mapreg_offset += sizeof(uint32_t);
308 dpavlin 20 }
309    
310     /* Calculate an aligned starting memory location: */
311     mem = pd->pcibus->cur_pci_membase;
312     if (memsize != 0) {
313     mem = ((mem - 1) | (memsize - 1)) + 1;
314     pd->pcibus->cur_pci_membase = mem;
315 dpavlin 22 PCI_SET_DATA(PCI_MAPREG_START + pd->cur_mapreg_offset, mem);
316     PCI_SET_DATA_SIZE(PCI_MAPREG_START + pd->cur_mapreg_offset,
317 dpavlin 24 ((memsize - 1) & ~0xf) | 0x0);
318 dpavlin 22 pd->cur_mapreg_offset += sizeof(uint32_t);
319 dpavlin 20 }
320    
321     *portp = port + pd->pcibus->pci_actual_io_offset;
322     *memp = mem + pd->pcibus->pci_actual_mem_offset;
323    
324     if (verbose >= 2) {
325     debug("pci device '%s' at", pd->name);
326     if (portsize != 0)
327     debug(" port 0x%llx-0x%llx", (long long)pd->pcibus->
328     cur_pci_portbase, (long long)(pd->pcibus->
329     cur_pci_portbase + portsize - 1));
330     if (memsize != 0)
331     debug(" mem 0x%llx-0x%llx", (long long)pd->pcibus->
332     cur_pci_membase, (long long)(pd->pcibus->
333     cur_pci_membase + memsize - 1));
334     debug("\n");
335     }
336    
337     pd->pcibus->cur_pci_portbase += portsize;
338     pd->pcibus->cur_pci_membase += memsize;
339     }
340    
341    
342     /*
343 dpavlin 4 * bus_pci_init():
344     *
345     * This doesn't register a device, but instead returns a pointer to a struct
346 dpavlin 22 * which should be passed to other bus_pci functions when accessing the bus.
347 dpavlin 20 *
348 dpavlin 34 * irq_path is the interrupt path to the PCI controller.
349 dpavlin 20 *
350     * pci_portbase, pci_membase, and pci_irqbase are the port, memory, and
351     * interrupt bases for PCI devices (as found in the configuration registers).
352     *
353     * pci_actual_io_offset and pci_actual_mem_offset are the offset from
354     * the values in the configuration registers to the actual (emulated) device.
355     *
356     * isa_portbase, isa_membase, and isa_irqbase are the port, memory, and
357     * interrupt bases for legacy ISA devices.
358 dpavlin 4 */
359 dpavlin 34 struct pci_data *bus_pci_init(struct machine *machine, char *irq_path,
360 dpavlin 20 uint64_t pci_actual_io_offset, uint64_t pci_actual_mem_offset,
361 dpavlin 34 uint64_t pci_portbase, uint64_t pci_membase, char *pci_irqbase,
362     uint64_t isa_portbase, uint64_t isa_membase, char *isa_irqbase)
363 dpavlin 4 {
364     struct pci_data *d;
365    
366     d = malloc(sizeof(struct pci_data));
367     if (d == NULL) {
368     fprintf(stderr, "out of memory\n");
369     exit(1);
370     }
371     memset(d, 0, sizeof(struct pci_data));
372 dpavlin 34
373     d->irq_path = strdup(irq_path);
374     d->irq_path_isa = strdup(isa_irqbase);
375     d->irq_path_pci = strdup(pci_irqbase);
376    
377 dpavlin 20 d->pci_actual_io_offset = pci_actual_io_offset;
378     d->pci_actual_mem_offset = pci_actual_mem_offset;
379     d->pci_portbase = pci_portbase;
380     d->pci_membase = pci_membase;
381     d->isa_portbase = isa_portbase;
382     d->isa_membase = isa_membase;
383 dpavlin 4
384 dpavlin 40 d->cur_pci_portbase = d->pci_portbase;
385     d->cur_pci_membase = d->pci_membase;
386    
387 dpavlin 20 /* Assume that the first 64KB could be used by legacy ISA devices: */
388 dpavlin 40 if (d->isa_portbase != 0 || d->isa_membase != 0) {
389     d->cur_pci_portbase += 0x10000;
390     d->cur_pci_membase += 0x10000;
391     }
392 dpavlin 20
393 dpavlin 4 return d;
394     }
395    
396 dpavlin 20
397    
398     /******************************************************************************
399 dpavlin 22 * *
400     * The following is glue code for PCI controllers and devices. The glue *
401     * code does the minimal stuff necessary to get an emulated OS to detect *
402     * the device (i.e. set up PCI configuration registers), and then if *
403     * necessary adds a "normal" device. *
404     * *
405 dpavlin 20 ******************************************************************************/
406    
407    
408    
409     /*
410 dpavlin 30 * Integraphics Systems "igsfb" Framebuffer (graphics) card, used in at
411     * least the NetWinder.
412 dpavlin 20 */
413    
414     #define PCI_VENDOR_INTEGRAPHICS 0x10ea
415    
416     PCIINIT(igsfb)
417     {
418 dpavlin 30 char tmpstr[200];
419    
420 dpavlin 20 PCI_SET_DATA(PCI_ID_REG,
421     PCI_ID_CODE(PCI_VENDOR_INTEGRAPHICS, 0x2010));
422    
423     PCI_SET_DATA(PCI_CLASS_REG,
424     PCI_CLASS_CODE(PCI_CLASS_DISPLAY,
425     PCI_SUBCLASS_DISPLAY_VGA, 0) + 0x01);
426    
427     /* TODO */
428 dpavlin 22 PCI_SET_DATA(0x10, 0x08000000);
429 dpavlin 20
430 dpavlin 30 snprintf(tmpstr, sizeof(tmpstr), "igsfb addr=0x%llx",
431     (long long)(pd->pcibus->isa_membase + 0x08000000));
432     device_add(machine, tmpstr);
433 dpavlin 20 }
434    
435    
436    
437     /*
438     * S3 ViRGE graphics.
439     *
440     * TODO: Only emulates a standard VGA card, so far.
441     */
442    
443     #define PCI_VENDOR_S3 0x5333
444     #define PCI_PRODUCT_S3_VIRGE 0x5631
445     #define PCI_PRODUCT_S3_VIRGE_DX 0x8a01
446    
447     PCIINIT(s3_virge)
448     {
449     PCI_SET_DATA(PCI_ID_REG,
450     PCI_ID_CODE(PCI_VENDOR_S3, PCI_PRODUCT_S3_VIRGE_DX));
451    
452     PCI_SET_DATA(PCI_CLASS_REG,
453     PCI_CLASS_CODE(PCI_CLASS_DISPLAY,
454     PCI_SUBCLASS_DISPLAY_VGA, 0) + 0x01);
455    
456     dev_vga_init(machine, mem, pd->pcibus->isa_membase + 0xa0000,
457     pd->pcibus->isa_portbase + 0x3c0, machine->machine_name);
458     }
459    
460    
461    
462     /*
463     * Acer Labs M5229 PCI-IDE (UDMA) controller.
464     * Acer Labs M1543 PCI->ISA bridge.
465     */
466    
467     #define PCI_VENDOR_ALI 0x10b9
468     #define PCI_PRODUCT_ALI_M1543 0x1533 /* NOTE: not 1543 */
469     #define PCI_PRODUCT_ALI_M5229 0x5229
470    
471     PCIINIT(ali_m1543)
472     {
473     PCI_SET_DATA(PCI_ID_REG,
474     PCI_ID_CODE(PCI_VENDOR_ALI, PCI_PRODUCT_ALI_M1543));
475    
476     PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
477     PCI_SUBCLASS_BRIDGE_ISA, 0) + 0xc3);
478    
479     PCI_SET_DATA(PCI_BHLC_REG,
480     PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
481    
482     /* Linux uses these to detect which IRQ the IDE controller uses: */
483     PCI_SET_DATA(0x44, 0x0000000e);
484     PCI_SET_DATA(0x58, 0x00000003);
485 dpavlin 34
486     switch (machine->machine_type) {
487     case MACHINE_CATS:
488     bus_isa_init(machine, pd->pcibus->irq_path_isa,
489     BUS_ISA_PCKBC_FORCE_USE | BUS_ISA_PCKBC_NONPCSTYLE,
490     0x7c000000, 0x80000000);
491     break;
492     default:fatal("ali_m1543 init: unimplemented machine type\n");
493     exit(1);
494     }
495 dpavlin 20 }
496    
497     PCIINIT(ali_m5229)
498     {
499 dpavlin 34 char tmpstr[300], irqstr[300];
500 dpavlin 20
501     PCI_SET_DATA(PCI_ID_REG,
502     PCI_ID_CODE(PCI_VENDOR_ALI, PCI_PRODUCT_ALI_M5229));
503    
504     PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_MASS_STORAGE,
505     PCI_SUBCLASS_MASS_STORAGE_IDE, 0x60) + 0xc1);
506    
507 dpavlin 34 switch (machine->machine_type) {
508     case MACHINE_CATS:
509     /* CATS ISA interrupts are at footbridge irq 10: */
510     snprintf(irqstr, sizeof(irqstr), "%s.10.isa",
511     pd->pcibus->irq_path);
512     break;
513     default:fatal("ali_m5229 init: unimplemented machine type\n");
514     exit(1);
515     }
516    
517 dpavlin 20 if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||
518     diskimage_exist(machine, 1, DISKIMAGE_IDE)) {
519 dpavlin 34 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%s.%i",
520 dpavlin 20 (long long)(pd->pcibus->isa_portbase + 0x1f0),
521 dpavlin 34 irqstr, 14);
522 dpavlin 20 device_add(machine, tmpstr);
523     }
524    
525     /* The secondary channel is disabled. TODO: fix this. */
526     }
527    
528    
529    
530     /*
531     * Adaptec AHC SCSI controller.
532     */
533    
534     #define PCI_VENDOR_ADP 0x9004 /* Adaptec */
535     #define PCI_VENDOR_ADP2 0x9005 /* Adaptec (2nd PCI Vendor ID) */
536     #define PCI_PRODUCT_ADP_2940U 0x8178 /* AHA-2940 Ultra */
537     #define PCI_PRODUCT_ADP_2940UP 0x8778 /* AHA-2940 Ultra Pro */
538    
539     PCIINIT(ahc)
540     {
541     /* Numbers taken from a Adaptec 2940U: */
542     /* http://mail-index.netbsd.org/netbsd-bugs/2000/04/29/0000.html */
543    
544     PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_ADP,
545     PCI_PRODUCT_ADP_2940U));
546    
547     PCI_SET_DATA(PCI_COMMAND_STATUS_REG, 0x02900007);
548    
549     PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_MASS_STORAGE,
550     PCI_SUBCLASS_MASS_STORAGE_SCSI, 0) + 0x01);
551    
552     PCI_SET_DATA(PCI_BHLC_REG, 0x00004008);
553    
554     /* 1 = type i/o. 0x0000e801; address? */
555     /* second address reg = 0xf1002000? */
556     PCI_SET_DATA(PCI_MAPREG_START + 0x00, 0x00000001);
557     PCI_SET_DATA(PCI_MAPREG_START + 0x04, 0x00000000);
558    
559     PCI_SET_DATA(PCI_MAPREG_START + 0x08, 0x00000000);
560     PCI_SET_DATA(PCI_MAPREG_START + 0x0c, 0x00000000);
561     PCI_SET_DATA(PCI_MAPREG_START + 0x10, 0x00000000);
562     PCI_SET_DATA(PCI_MAPREG_START + 0x14, 0x00000000);
563     PCI_SET_DATA(PCI_MAPREG_START + 0x18, 0x00000000);
564    
565     /* Subsystem vendor ID? 0x78819004? */
566     PCI_SET_DATA(PCI_MAPREG_START + 0x1c, 0x00000000);
567    
568     PCI_SET_DATA(0x30, 0xef000000);
569     PCI_SET_DATA(PCI_CAPLISTPTR_REG, 0x000000dc);
570     PCI_SET_DATA(0x38, 0x00000000);
571     PCI_SET_DATA(PCI_INTERRUPT_REG, 0x08080109); /* interrupt pin A */
572    
573     /*
574     * TODO: this address is based on what NetBSD/sgimips uses
575     * on SGI IP32 (O2). Fix this!
576     */
577    
578     device_add(machine, "ahc addr=0x18000000");
579    
580     /* OpenBSD/sgi snapshots sometime between 2005-03-11 and
581     2005-04-04 changed to using 0x1a000000: */
582     dev_ram_init(machine, 0x1a000000, 0x2000000, DEV_RAM_MIRROR,
583     0x18000000);
584     }
585    
586    
587    
588     /*
589     * Galileo Technology GT-64xxx PCI controller.
590     *
591     * GT-64011 Used in Cobalt machines.
592     * GT-64120 Used in evbmips machines (Malta).
593     *
594     * NOTE: This works in the opposite way compared to other devices; the PCI
595     * device is added from the normal device instead of the other way around.
596     */
597    
598     #define PCI_VENDOR_GALILEO 0x11ab /* Galileo Technology */
599     #define PCI_PRODUCT_GALILEO_GT64011 0x4146 /* GT-64011 System Controller */
600     #define PCI_PRODUCT_GALILEO_GT64120 0x4620 /* GT-64120 */
601 dpavlin 22 #define PCI_PRODUCT_GALILEO_GT64260 0x6430 /* GT-64260 */
602 dpavlin 20
603     PCIINIT(gt64011)
604     {
605     PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_GALILEO,
606     PCI_PRODUCT_GALILEO_GT64011));
607    
608 dpavlin 22 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
609 dpavlin 20 PCI_SUBCLASS_BRIDGE_HOST, 0) + 0x01); /* Revision 1 */
610     }
611    
612     PCIINIT(gt64120)
613     {
614     PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_GALILEO,
615     PCI_PRODUCT_GALILEO_GT64120));
616    
617     PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
618     PCI_SUBCLASS_BRIDGE_HOST, 0) + 0x02); /* Revision 2? */
619    
620     switch (machine->machine_type) {
621     case MACHINE_EVBMIPS:
622     PCI_SET_DATA(PCI_MAPREG_START + 0x10, 0x1be00000);
623     break;
624     }
625     }
626    
627 dpavlin 22 PCIINIT(gt64260)
628     {
629     PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_GALILEO,
630     PCI_PRODUCT_GALILEO_GT64260));
631 dpavlin 20
632 dpavlin 22 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
633     PCI_SUBCLASS_BRIDGE_HOST, 0) + 0x01); /* Revision 1? */
634     }
635 dpavlin 20
636 dpavlin 22
637    
638 dpavlin 20 /*
639 dpavlin 30 * AMD PCnet Ethernet card.
640     *
641     * "Am79c970A PCnet-PCI II rev 0" or similar.
642     */
643    
644     #define PCI_VENDOR_AMD 0x1022 /* Advanced Micro Devices */
645     #define PCI_PRODUCT_AMD_PCNET_PCI 0x2000 /* PCnet-PCI Ethernet */
646    
647     PCIINIT(pcn)
648     {
649     int irq;
650    
651     PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_AMD,
652     PCI_PRODUCT_AMD_PCNET_PCI));
653    
654     PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_NETWORK,
655     PCI_SUBCLASS_NETWORK_ETHERNET, 0) + 0x00); /* Revision 0 */
656    
657     switch (machine->machine_type) {
658    
659     case MACHINE_EVBMIPS:
660     irq = (1 << 8) + 10; /* TODO */
661     break;
662    
663     default:fatal("pcn in non-implemented machine type %i\n",
664     machine->machine_type);
665     exit(1);
666     }
667    
668     PCI_SET_DATA(PCI_INTERRUPT_REG, 0x01100000 | irq);
669    
670     /*
671     * TODO: Add the pcn device here. The pcn device will need to work as
672     * a wrapper for dev_le + all the DMA magic and whatever is required.
673     * It's too much to implement right now.
674     */
675     }
676    
677    
678    
679     /*
680 dpavlin 22 * Intel 31244 Serial ATA Controller
681     * Intel 82371SB PIIX3 PCI-ISA bridge
682     * Intel 82371AB PIIX4 PCI-ISA bridge
683     * Intel 82371SB IDE controller
684     * Intel 82371AB IDE controller
685     * Intel 82378ZB System I/O controller.
686 dpavlin 20 */
687    
688     #define PCI_VENDOR_INTEL 0x8086
689 dpavlin 22 #define PCI_PRODUCT_INTEL_31244 0x3200
690     #define PCI_PRODUCT_INTEL_82371SB_ISA 0x7000
691     #define PCI_PRODUCT_INTEL_82371SB_IDE 0x7010
692 dpavlin 20 #define PCI_PRODUCT_INTEL_82371AB_ISA 0x7110
693     #define PCI_PRODUCT_INTEL_82371AB_IDE 0x7111
694     #define PCI_PRODUCT_INTEL_SIO 0x0484
695    
696 dpavlin 22 PCIINIT(i31244)
697 dpavlin 20 {
698 dpavlin 22 uint64_t port, memaddr;
699 dpavlin 24 int irq = 0;
700 dpavlin 22
701 dpavlin 20 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_INTEL,
702 dpavlin 22 PCI_PRODUCT_INTEL_31244));
703    
704     PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_MASS_STORAGE,
705     PCI_SUBCLASS_MASS_STORAGE_IDE, 0x33) + 0x00);
706    
707     switch (machine->machine_type) {
708     case MACHINE_IQ80321:
709 dpavlin 24 /* S-PCI-X slot uses PCI IRQ A, int 29 */
710     irq = (1 << 8) + 29;
711 dpavlin 22 break;
712     default:fatal("i31244 in non-implemented machine type %i\n",
713     machine->machine_type);
714     exit(1);
715     }
716    
717 dpavlin 24 PCI_SET_DATA(PCI_INTERRUPT_REG, 0x01100000 | irq);
718 dpavlin 22
719 dpavlin 24 allocate_device_space(pd, 0x1000, 0, &port, &memaddr);
720     allocate_device_space(pd, 0x1000, 0, &port, &memaddr);
721 dpavlin 22
722     /* PCI IDE using dev_wdc: */
723     if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||
724     diskimage_exist(machine, 1, DISKIMAGE_IDE)) {
725     char tmpstr[150];
726 dpavlin 34 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%s.%i",
727 dpavlin 22 (long long)(pd->pcibus->pci_actual_io_offset + 0),
728 dpavlin 34 pd->pcibus->irq_path_pci, irq & 255);
729 dpavlin 22 device_add(machine, tmpstr);
730     }
731     }
732    
733     PCIINIT(piix3_isa)
734     {
735     PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_INTEL,
736     PCI_PRODUCT_INTEL_82371SB_ISA));
737    
738     PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
739     PCI_SUBCLASS_BRIDGE_ISA, 0) + 0x01); /* Rev 1 */
740    
741     PCI_SET_DATA(PCI_BHLC_REG,
742     PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
743     }
744    
745     PCIINIT(piix4_isa)
746     {
747     PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_INTEL,
748 dpavlin 20 PCI_PRODUCT_INTEL_82371AB_ISA));
749    
750     PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
751     PCI_SUBCLASS_BRIDGE_ISA, 0) + 0x01); /* Rev 1 */
752    
753     PCI_SET_DATA(PCI_BHLC_REG,
754     PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
755     }
756    
757     PCIINIT(i82378zb)
758     {
759     PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_INTEL,
760     PCI_PRODUCT_INTEL_SIO));
761    
762     PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
763     PCI_SUBCLASS_BRIDGE_ISA, 0) + 0x43);
764    
765     PCI_SET_DATA(PCI_BHLC_REG,
766     PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
767 dpavlin 22
768     PCI_SET_DATA(0x40, 0x20);
769    
770     /* PIRQ[0]=10 PIRQ[1]=11 PIRQ[2]=14 PIRQ[3]=15 */
771     PCI_SET_DATA(0x60, 0x0f0e0b0a);
772 dpavlin 20 }
773    
774 dpavlin 30 struct piix_ide_extra {
775     void *wdc0;
776     void *wdc1;
777     };
778    
779     int piix_ide_cfg_reg_write(struct pci_device *pd, int reg, uint32_t value)
780     {
781     void *wdc0 = ((struct piix_ide_extra *)pd->extra)->wdc0;
782     void *wdc1 = ((struct piix_ide_extra *)pd->extra)->wdc1;
783     int enabled = 0;
784    
785     switch (reg) {
786     case PCI_COMMAND_STATUS_REG:
787     if (value & PCI_COMMAND_IO_ENABLE)
788     enabled = 1;
789     if (wdc0 != NULL)
790     wdc_set_io_enabled(wdc0, enabled);
791     if (wdc1 != NULL)
792     wdc_set_io_enabled(wdc1, enabled);
793     return 1;
794     }
795    
796     return 0;
797     }
798    
799 dpavlin 22 PCIINIT(piix3_ide)
800 dpavlin 20 {
801     char tmpstr[100];
802    
803     PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_INTEL,
804 dpavlin 22 PCI_PRODUCT_INTEL_82371SB_IDE));
805    
806     /* Possibly not correct: */
807     PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_MASS_STORAGE,
808     PCI_SUBCLASS_MASS_STORAGE_IDE, 0x00) + 0x00);
809    
810     /* PIIX_IDETIM (see NetBSD's pciide_piix_reg.h) */
811     /* channel 0 and 1 enabled as IDE */
812     PCI_SET_DATA(0x40, 0x80008000);
813    
814 dpavlin 30 pd->extra = malloc(sizeof(struct piix_ide_extra));
815     if (pd->extra == NULL) {
816     fatal("Out of memory.\n");
817     exit(1);
818     }
819     ((struct piix_ide_extra *)pd->extra)->wdc0 = NULL;
820     ((struct piix_ide_extra *)pd->extra)->wdc1 = NULL;
821    
822 dpavlin 22 if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||
823     diskimage_exist(machine, 1, DISKIMAGE_IDE)) {
824 dpavlin 34 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx "
825     "irq=%s.isa.%i", (long long)(pd->pcibus->isa_portbase +
826     0x1f0), pd->pcibus->irq_path_isa, 14);
827 dpavlin 30 ((struct piix_ide_extra *)pd->extra)->wdc0 =
828     device_add(machine, tmpstr);
829 dpavlin 22 }
830    
831     if (diskimage_exist(machine, 2, DISKIMAGE_IDE) ||
832     diskimage_exist(machine, 3, DISKIMAGE_IDE)) {
833 dpavlin 34 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx "
834     "irq=%s.isa.%i", (long long)(pd->pcibus->isa_portbase +
835     0x170), pd->pcibus->irq_path_isa, 15);
836 dpavlin 30 ((struct piix_ide_extra *)pd->extra)->wdc1 =
837     device_add(machine, tmpstr);
838 dpavlin 22 }
839 dpavlin 30
840     pd->cfg_reg_write = piix_ide_cfg_reg_write;
841 dpavlin 22 }
842    
843     PCIINIT(piix4_ide)
844     {
845     char tmpstr[100];
846    
847     PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_INTEL,
848 dpavlin 20 PCI_PRODUCT_INTEL_82371AB_IDE));
849    
850     /* Possibly not correct: */
851     PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_MASS_STORAGE,
852     PCI_SUBCLASS_MASS_STORAGE_IDE, 0x00) + 0x01);
853    
854     /* PIIX_IDETIM (see NetBSD's pciide_piix_reg.h) */
855     /* channel 0 and 1 enabled as IDE */
856     PCI_SET_DATA(0x40, 0x80008000);
857    
858 dpavlin 30 pd->extra = malloc(sizeof(struct piix_ide_extra));
859     if (pd->extra == NULL) {
860     fatal("Out of memory.\n");
861     exit(1);
862     }
863     ((struct piix_ide_extra *)pd->extra)->wdc0 = NULL;
864     ((struct piix_ide_extra *)pd->extra)->wdc1 = NULL;
865    
866 dpavlin 20 if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||
867     diskimage_exist(machine, 1, DISKIMAGE_IDE)) {
868 dpavlin 34 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%s."
869     "isa.%i", (long long)(pd->pcibus->isa_portbase + 0x1f0),
870     pd->pcibus->irq_path_isa, 14);
871 dpavlin 30 ((struct piix_ide_extra *)pd->extra)->wdc0 =
872     device_add(machine, tmpstr);
873 dpavlin 20 }
874    
875     if (diskimage_exist(machine, 2, DISKIMAGE_IDE) ||
876     diskimage_exist(machine, 3, DISKIMAGE_IDE)) {
877 dpavlin 34 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%s."
878     "isa.%i", (long long)(pd->pcibus->isa_portbase + 0x170),
879     pd->pcibus->irq_path_isa, 15);
880 dpavlin 30 ((struct piix_ide_extra *)pd->extra)->wdc1 =
881     device_add(machine, tmpstr);
882 dpavlin 20 }
883 dpavlin 30
884     pd->cfg_reg_write = piix_ide_cfg_reg_write;
885 dpavlin 20 }
886    
887    
888    
889     /*
890     * IBM ISA bridge (used by at least one PReP machine).
891     */
892    
893     #define PCI_VENDOR_IBM 0x1014
894     #define PCI_PRODUCT_IBM_ISABRIDGE 0x000a
895    
896     PCIINIT(ibm_isa)
897     {
898     PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_IBM,
899     PCI_PRODUCT_IBM_ISABRIDGE));
900    
901     PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
902     PCI_SUBCLASS_BRIDGE_ISA, 0) + 0x02);
903    
904     PCI_SET_DATA(PCI_BHLC_REG,
905     PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
906     }
907    
908    
909    
910     /*
911     * Heuricon PCI host bridge for PM/PPC.
912     */
913    
914     #define PCI_VENDOR_HEURICON 0x1223
915     #define PCI_PRODUCT_HEURICON_PMPPC 0x000e
916    
917     PCIINIT(heuricon_pmppc)
918     {
919     PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_HEURICON,
920     PCI_PRODUCT_HEURICON_PMPPC));
921    
922     PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
923     PCI_SUBCLASS_BRIDGE_HOST, 0) + 0x00); /* Revision? */
924    
925     PCI_SET_DATA(PCI_BHLC_REG,
926     PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
927     }
928    
929    
930    
931     /*
932     * VIATECH VT82C586 devices:
933     *
934     * vt82c586_isa PCI->ISA bridge
935     * vt82c586_ide IDE controller
936     *
937     * TODO: This more or less just a dummy device, so far.
938     */
939    
940     #define PCI_VENDOR_VIATECH 0x1106 /* VIA Technologies */
941     #define PCI_PRODUCT_VIATECH_VT82C586_IDE 0x1571 /* VT82C586 (Apollo VP)
942     IDE Controller */
943     #define PCI_PRODUCT_VIATECH_VT82C586_ISA 0x0586 /* VT82C586 (Apollo VP)
944     PCI-ISA Bridge */
945    
946     PCIINIT(vt82c586_isa)
947     {
948     PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_VIATECH,
949     PCI_PRODUCT_VIATECH_VT82C586_ISA));
950    
951     PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
952     PCI_SUBCLASS_BRIDGE_ISA, 0) + 0x39); /* Revision 37 or 39 */
953    
954     PCI_SET_DATA(PCI_BHLC_REG,
955     PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
956     }
957    
958 dpavlin 30 struct vt82c586_ide_extra {
959     void *wdc0;
960     void *wdc1;
961     };
962    
963     int vt82c586_ide_cfg_reg_write(struct pci_device *pd, int reg, uint32_t value)
964     {
965     void *wdc0 = ((struct vt82c586_ide_extra *)pd->extra)->wdc0;
966     void *wdc1 = ((struct vt82c586_ide_extra *)pd->extra)->wdc1;
967     int enabled = 0;
968    
969     switch (reg) {
970     case PCI_COMMAND_STATUS_REG:
971     if (value & PCI_COMMAND_IO_ENABLE)
972     enabled = 1;
973     if (wdc0 != NULL)
974     wdc_set_io_enabled(wdc0, enabled);
975     if (wdc1 != NULL)
976     wdc_set_io_enabled(wdc1, enabled);
977     return 1;
978     }
979    
980     return 0;
981     }
982    
983 dpavlin 20 PCIINIT(vt82c586_ide)
984     {
985     char tmpstr[100];
986    
987     PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_VIATECH,
988     PCI_PRODUCT_VIATECH_VT82C586_IDE));
989    
990     /* Possibly not correct: */
991     PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_MASS_STORAGE,
992     PCI_SUBCLASS_MASS_STORAGE_IDE, 0x00) + 0x01);
993    
994     /* APO_IDECONF */
995     /* channel 0 and 1 enabled */
996     PCI_SET_DATA(0x40, 0x00000003);
997    
998 dpavlin 30 pd->extra = malloc(sizeof(struct vt82c586_ide_extra));
999     if (pd->extra == NULL) {
1000     fatal("Out of memory.\n");
1001     exit(1);
1002     }
1003     ((struct vt82c586_ide_extra *)pd->extra)->wdc0 = NULL;
1004     ((struct vt82c586_ide_extra *)pd->extra)->wdc1 = NULL;
1005    
1006 dpavlin 20 if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||
1007     diskimage_exist(machine, 1, DISKIMAGE_IDE)) {
1008 dpavlin 34 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%s."
1009     "isa.%i", (long long)(pd->pcibus->isa_portbase + 0x1f0),
1010     pd->pcibus->irq_path_isa, 14);
1011 dpavlin 30 ((struct vt82c586_ide_extra *)pd->extra)->wdc0 =
1012     device_add(machine, tmpstr);
1013 dpavlin 20 }
1014    
1015     if (diskimage_exist(machine, 2, DISKIMAGE_IDE) ||
1016     diskimage_exist(machine, 3, DISKIMAGE_IDE)) {
1017 dpavlin 34 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%s."
1018     "isa.%i", (long long)(pd->pcibus->isa_portbase + 0x170),
1019     pd->pcibus->irq_path_isa, 15);
1020 dpavlin 30 ((struct vt82c586_ide_extra *)pd->extra)->wdc1 =
1021     device_add(machine, tmpstr);
1022 dpavlin 20 }
1023 dpavlin 30
1024     pd->cfg_reg_write = vt82c586_ide_cfg_reg_write;
1025 dpavlin 20 }
1026    
1027    
1028    
1029     /*
1030     * Symphony Labs 83C553 PCI->ISA bridge.
1031     * Symphony Labs 82C105 PCIIDE controller.
1032     */
1033    
1034     #define PCI_VENDOR_SYMPHONY 0x10ad
1035     #define PCI_PRODUCT_SYMPHONY_83C553 0x0565
1036     #define PCI_PRODUCT_SYMPHONY_82C105 0x0105
1037    
1038     PCIINIT(symphony_83c553)
1039     {
1040     PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_SYMPHONY,
1041     PCI_PRODUCT_SYMPHONY_83C553));
1042    
1043     PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
1044     PCI_SUBCLASS_BRIDGE_ISA, 0) + 0x10);
1045    
1046     PCI_SET_DATA(PCI_BHLC_REG,
1047     PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
1048 dpavlin 34
1049     switch (machine->machine_type) {
1050     case MACHINE_NETWINDER:
1051     bus_isa_init(machine, pd->pcibus->irq_path_isa,
1052     0, 0x7c000000, 0x80000000);
1053     break;
1054     default:fatal("symphony_83c553 init: unimplemented machine type\n");
1055     exit(1);
1056     }
1057 dpavlin 20 }
1058    
1059 dpavlin 32 struct symphony_82c105_extra {
1060     void *wdc0;
1061     void *wdc1;
1062     };
1063    
1064     int symphony_82c105_cfg_reg_write(struct pci_device *pd, int reg,
1065     uint32_t value)
1066     {
1067     void *wdc0 = ((struct symphony_82c105_extra *)pd->extra)->wdc0;
1068     void *wdc1 = ((struct symphony_82c105_extra *)pd->extra)->wdc1;
1069     int enabled = 0;
1070    
1071     printf("reg = 0x%x\n", reg);
1072     switch (reg) {
1073     case PCI_COMMAND_STATUS_REG:
1074     if (value & PCI_COMMAND_IO_ENABLE)
1075     enabled = 1;
1076     printf(" value = 0x%"PRIx32"\n", value);
1077     if (wdc0 != NULL)
1078     wdc_set_io_enabled(wdc0, enabled);
1079     if (wdc1 != NULL)
1080     wdc_set_io_enabled(wdc1, enabled);
1081     /* Set all bits: */
1082     PCI_SET_DATA(reg, value);
1083     return 1;
1084     case PCI_MAPREG_START:
1085     case PCI_MAPREG_START + 4:
1086     case PCI_MAPREG_START + 8:
1087     case PCI_MAPREG_START + 12:
1088     case PCI_MAPREG_START + 16:
1089     case PCI_MAPREG_START + 20:
1090     PCI_SET_DATA(reg, value);
1091     return 1;
1092     }
1093    
1094     return 0;
1095     }
1096    
1097 dpavlin 20 PCIINIT(symphony_82c105)
1098     {
1099     char tmpstr[100];
1100    
1101     PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_SYMPHONY,
1102     PCI_PRODUCT_SYMPHONY_82C105));
1103    
1104     /* Possibly not correct: */
1105     PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_MASS_STORAGE,
1106     PCI_SUBCLASS_MASS_STORAGE_IDE, 0x00) + 0x05);
1107    
1108 dpavlin 32 /* TODO: Interrupt line: */
1109     /* PCI_SET_DATA(PCI_INTERRUPT_REG, 0x28140000); */
1110    
1111 dpavlin 20 /* APO_IDECONF */
1112     /* channel 0 and 1 enabled */
1113     PCI_SET_DATA(0x40, 0x00000003);
1114    
1115 dpavlin 32 pd->extra = malloc(sizeof(struct symphony_82c105_extra));
1116     if (pd->extra == NULL) {
1117     fatal("Out of memory.\n");
1118     exit(1);
1119     }
1120     ((struct symphony_82c105_extra *)pd->extra)->wdc0 = NULL;
1121     ((struct symphony_82c105_extra *)pd->extra)->wdc1 = NULL;
1122    
1123 dpavlin 20 if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||
1124     diskimage_exist(machine, 1, DISKIMAGE_IDE)) {
1125 dpavlin 34 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%s."
1126     "isa.%i", (long long)(pd->pcibus->isa_portbase + 0x1f0),
1127     pd->pcibus->irq_path_isa, 14);
1128 dpavlin 32 ((struct symphony_82c105_extra *)pd->extra)->wdc0 =
1129     device_add(machine, tmpstr);
1130 dpavlin 20 }
1131    
1132     if (diskimage_exist(machine, 2, DISKIMAGE_IDE) ||
1133     diskimage_exist(machine, 3, DISKIMAGE_IDE)) {
1134 dpavlin 34 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%s."
1135     "isa.%i", (long long)(pd->pcibus->isa_portbase + 0x170),
1136     pd->pcibus->irq_path_isa, 15);
1137 dpavlin 32 ((struct symphony_82c105_extra *)pd->extra)->wdc1 =
1138     device_add(machine, tmpstr);
1139 dpavlin 20 }
1140 dpavlin 32
1141     pd->cfg_reg_write = symphony_82c105_cfg_reg_write;
1142 dpavlin 20 }
1143    
1144    
1145    
1146     /*
1147 dpavlin 40 * Realtek 8139C+ PCI ethernet.
1148     */
1149    
1150     #define PCI_VENDOR_REALTEK 0x10ec
1151     #define PCI_PRODUCT_REALTEK_RT8139 0x8139
1152    
1153     PCIINIT(rtl8139c)
1154     {
1155     uint64_t port, memaddr;
1156     int pci_int_line = 0x101, irq = 0;
1157     char irqstr[200];
1158     char tmpstr[200];
1159    
1160     PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_REALTEK,
1161     PCI_PRODUCT_REALTEK_RT8139));
1162    
1163     PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_NETWORK,
1164     PCI_SUBCLASS_NETWORK_ETHERNET, 0x00) + 0x20);
1165    
1166     switch (machine->machine_type) {
1167     case MACHINE_LANDISK:
1168     irq = 5;
1169     pci_int_line = 0x105;
1170     break;
1171     default:fatal("rtl8139c for this machine has not been "
1172     "implemented yet\n");
1173     exit(1);
1174     }
1175    
1176     PCI_SET_DATA(PCI_INTERRUPT_REG, 0x28140000 | pci_int_line);
1177    
1178     allocate_device_space(pd, 0x100, 0, &port, &memaddr);
1179    
1180     snprintf(irqstr, sizeof(irqstr), "%s.%i",
1181     pd->pcibus->irq_path_pci, irq);
1182    
1183     snprintf(tmpstr, sizeof(tmpstr), "rtl8139c addr=0x%llx "
1184     "irq=%s pci_little_endian=1", (long long)port, irqstr);
1185    
1186     device_add(machine, tmpstr);
1187     }
1188    
1189    
1190    
1191     /*
1192 dpavlin 20 * DEC 21143 ("Tulip") PCI ethernet.
1193     */
1194    
1195     #define PCI_VENDOR_DEC 0x1011 /* Digital Equipment */
1196     #define PCI_PRODUCT_DEC_21142 0x0019 /* DECchip 21142/21143 10/100 Ethernet */
1197    
1198     PCIINIT(dec21143)
1199     {
1200     uint64_t port, memaddr;
1201 dpavlin 34 int pci_int_line = 0x101, irq = 0, isa = 0;
1202     char irqstr[200];
1203 dpavlin 20 char tmpstr[200];
1204    
1205     PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_DEC,
1206     PCI_PRODUCT_DEC_21142));
1207    
1208     PCI_SET_DATA(PCI_COMMAND_STATUS_REG, 0x02000017);
1209    
1210     PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_NETWORK,
1211     PCI_SUBCLASS_NETWORK_ETHERNET, 0x00) + 0x41);
1212    
1213     PCI_SET_DATA(PCI_BHLC_REG, PCI_BHLC_CODE(0,0,0, 0x40,0));
1214    
1215     switch (machine->machine_type) {
1216     case MACHINE_CATS:
1217 dpavlin 22 /* CATS int 18 = PCI. */
1218 dpavlin 20 irq = 18;
1219 dpavlin 22 pci_int_line = 0x101;
1220 dpavlin 20 break;
1221 dpavlin 22 case MACHINE_COBALT:
1222     /* On Cobalt, IRQ 7 = PCI. */
1223     irq = 8 + 7;
1224     pci_int_line = 0x407;
1225     break;
1226 dpavlin 20 case MACHINE_PREP:
1227 dpavlin 34 irq = 10;
1228     isa = 1;
1229 dpavlin 22 pci_int_line = 0x20a;
1230 dpavlin 20 break;
1231 dpavlin 22 case MACHINE_MVMEPPC:
1232     /* TODO */
1233 dpavlin 34 irq = 10;
1234 dpavlin 22 pci_int_line = 0x40a;
1235     break;
1236 dpavlin 20 case MACHINE_PMPPC:
1237 dpavlin 22 /* TODO, not working yet */
1238 dpavlin 20 irq = 31 - 21;
1239 dpavlin 22 pci_int_line = 0x201;
1240 dpavlin 20 break;
1241 dpavlin 22 case MACHINE_MACPPC:
1242     /* TODO, not working yet */
1243     irq = 25;
1244     pci_int_line = 0x101;
1245     break;
1246 dpavlin 20 }
1247    
1248 dpavlin 22 PCI_SET_DATA(PCI_INTERRUPT_REG, 0x28140000 | pci_int_line);
1249 dpavlin 20
1250     allocate_device_space(pd, 0x100, 0x100, &port, &memaddr);
1251    
1252 dpavlin 34 if (isa)
1253     snprintf(irqstr, sizeof(irqstr), "%s.isa.%i",
1254     pd->pcibus->irq_path_isa, irq);
1255     else
1256     snprintf(irqstr, sizeof(irqstr), "%s.%i",
1257     pd->pcibus->irq_path_pci, irq);
1258    
1259 dpavlin 20 snprintf(tmpstr, sizeof(tmpstr), "dec21143 addr=0x%llx addr2=0x%llx "
1260 dpavlin 34 "irq=%s pci_little_endian=1", (long long)port,
1261     (long long)memaddr, irqstr);
1262    
1263 dpavlin 20 device_add(machine, tmpstr);
1264     }
1265    
1266    
1267    
1268     /*
1269     * DEC 21030 "tga" graphics.
1270     */
1271    
1272     #define PCI_PRODUCT_DEC_21030 0x0004 /* DECchip 21030 ("TGA") */
1273    
1274     PCIINIT(dec21030)
1275     {
1276     uint64_t base = 0;
1277     char tmpstr[200];
1278    
1279     PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_DEC,
1280     PCI_PRODUCT_DEC_21030));
1281    
1282     PCI_SET_DATA(PCI_COMMAND_STATUS_REG, 0x02800087); /* TODO */
1283    
1284     PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_DISPLAY,
1285     PCI_SUBCLASS_DISPLAY_VGA, 0x00) + 0x03);
1286    
1287     /*
1288     * See http://mail-index.netbsd.org/port-arc/2001/08/13/0000.html
1289     * for more info.
1290     */
1291    
1292     PCI_SET_DATA(PCI_BHLC_REG, 0x0000ff00);
1293    
1294     /* 8 = prefetchable */
1295     PCI_SET_DATA(0x10, 0x00000008);
1296     PCI_SET_DATA(0x30, 0x08000001);
1297     PCI_SET_DATA(PCI_INTERRUPT_REG, 0x00000100); /* interrupt pin A? */
1298    
1299     /*
1300     * Experimental:
1301     *
1302     * TODO: Base address, pci_little_endian, ...
1303     */
1304    
1305     switch (machine->machine_type) {
1306     case MACHINE_ARC:
1307     base = 0x100000000ULL;
1308     break;
1309     default:fatal("dec21030 in non-implemented machine type %i\n",
1310     machine->machine_type);
1311     exit(1);
1312     }
1313    
1314     snprintf(tmpstr, sizeof(tmpstr), "dec21030 addr=0x%llx",
1315     (long long)(base));
1316     device_add(machine, tmpstr);
1317     }
1318    
1319    
1320 dpavlin 22
1321 dpavlin 20 /*
1322     * Motorola MPC105 "Eagle" Host Bridge
1323     *
1324     * Used in at least PReP and BeBox.
1325     */
1326    
1327     #define PCI_VENDOR_MOT 0x1057
1328     #define PCI_PRODUCT_MOT_MPC105 0x0001
1329    
1330     PCIINIT(eagle)
1331     {
1332     PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_MOT,
1333     PCI_PRODUCT_MOT_MPC105));
1334    
1335     PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
1336     PCI_SUBCLASS_BRIDGE_HOST, 0) + 0x24);
1337    
1338     PCI_SET_DATA(PCI_BHLC_REG,
1339     PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
1340     }
1341    
1342 dpavlin 22
1343    
1344     /*
1345     * Apple (MacPPC) stuff:
1346     *
1347     * Grand Central (I/O controller)
1348     * Uni-North (PCI controller)
1349     */
1350    
1351     #define PCI_VENDOR_APPLE 0x106b
1352     #define PCI_PRODUCT_APPLE_GC 0x0002
1353     #define PCI_PRODUCT_APPLE_UNINORTH1 0x001e
1354    
1355     PCIINIT(gc_obio)
1356     {
1357     uint64_t port, memaddr;
1358    
1359     PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_APPLE,
1360     PCI_PRODUCT_APPLE_GC));
1361    
1362     /* TODO: */
1363     PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_SYSTEM,
1364     PCI_SUBCLASS_SYSTEM_PIC, 0) + 0x00);
1365    
1366     PCI_SET_DATA(PCI_BHLC_REG,
1367     PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
1368    
1369     /* TODO */
1370     allocate_device_space(pd, 0x10000, 0x10000, &port, &memaddr);
1371     }
1372    
1373     PCIINIT(uninorth)
1374     {
1375     uint64_t port, memaddr;
1376    
1377     PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_APPLE,
1378     PCI_PRODUCT_APPLE_UNINORTH1));
1379    
1380     PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
1381     PCI_SUBCLASS_BRIDGE_HOST, 0) + 0xff);
1382    
1383     PCI_SET_DATA(PCI_BHLC_REG,
1384     PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
1385    
1386     /* TODO */
1387     allocate_device_space(pd, 0x10000, 0x10000, &port, &memaddr);
1388     }
1389    
1390    
1391    
1392     /*
1393     * ATI graphics cards
1394     */
1395    
1396     #define PCI_VENDOR_ATI 0x1002
1397     #define PCI_PRODUCT_ATI_RADEON_9200_2 0x5962
1398    
1399     PCIINIT(ati_radeon_9200_2)
1400     {
1401     uint64_t port, memaddr;
1402    
1403     PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_ATI,
1404     PCI_PRODUCT_ATI_RADEON_9200_2));
1405    
1406     /* TODO: other subclass? */
1407     PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_DISPLAY,
1408     PCI_SUBCLASS_DISPLAY_VGA, 0) + 0x03);
1409    
1410     /* TODO */
1411     allocate_device_space(pd, 0x1000, 0x400000, &port, &memaddr);
1412     }
1413    

  ViewVC Help
Powered by ViewVC 1.1.26