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

  ViewVC Help
Powered by ViewVC 1.1.26