/[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 63 - (hide annotations)
Sat Oct 13 15:05:59 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 38558 byte(s)
create OpenPIC
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 dpavlin 61 * Sandpoint host bridge based on uninorth
920 dpavlin 56 */
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 61 PCIINIT(mpc10x)
927 dpavlin 56 {
928 dpavlin 62 uint64_t port, memaddr;
929    
930 dpavlin 56 debug("sandpoint mpx10x host bridge\n");
931    
932     PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_MOT,
933 dpavlin 62 PCI_DEVICE_ID_MOTOROLA_MPC107)); /* FIXME MPC106 ?? */
934 dpavlin 56
935     PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
936     PCI_SUBCLASS_BRIDGE_HOST, 0) + 0x00); /* Revision? */
937    
938     PCI_SET_DATA(PCI_BHLC_REG,
939     PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
940 dpavlin 61
941 dpavlin 63 allocate_device_space(pd, 0x10000, 0x10000, &port, &memaddr);
942 dpavlin 61
943 dpavlin 56 }
944    
945    
946    
947 dpavlin 20 /*
948     * VIATECH VT82C586 devices:
949     *
950     * vt82c586_isa PCI->ISA bridge
951     * vt82c586_ide IDE controller
952     *
953     * TODO: This more or less just a dummy device, so far.
954     */
955    
956     #define PCI_VENDOR_VIATECH 0x1106 /* VIA Technologies */
957     #define PCI_PRODUCT_VIATECH_VT82C586_IDE 0x1571 /* VT82C586 (Apollo VP)
958     IDE Controller */
959     #define PCI_PRODUCT_VIATECH_VT82C586_ISA 0x0586 /* VT82C586 (Apollo VP)
960     PCI-ISA Bridge */
961    
962     PCIINIT(vt82c586_isa)
963     {
964     PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_VIATECH,
965     PCI_PRODUCT_VIATECH_VT82C586_ISA));
966    
967     PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
968     PCI_SUBCLASS_BRIDGE_ISA, 0) + 0x39); /* Revision 37 or 39 */
969    
970     PCI_SET_DATA(PCI_BHLC_REG,
971     PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
972     }
973    
974 dpavlin 30 struct vt82c586_ide_extra {
975     void *wdc0;
976     void *wdc1;
977     };
978    
979     int vt82c586_ide_cfg_reg_write(struct pci_device *pd, int reg, uint32_t value)
980     {
981     void *wdc0 = ((struct vt82c586_ide_extra *)pd->extra)->wdc0;
982     void *wdc1 = ((struct vt82c586_ide_extra *)pd->extra)->wdc1;
983     int enabled = 0;
984    
985     switch (reg) {
986     case PCI_COMMAND_STATUS_REG:
987     if (value & PCI_COMMAND_IO_ENABLE)
988     enabled = 1;
989     if (wdc0 != NULL)
990     wdc_set_io_enabled(wdc0, enabled);
991     if (wdc1 != NULL)
992     wdc_set_io_enabled(wdc1, enabled);
993     return 1;
994     }
995    
996     return 0;
997     }
998    
999 dpavlin 20 PCIINIT(vt82c586_ide)
1000     {
1001     char tmpstr[100];
1002    
1003     PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_VIATECH,
1004     PCI_PRODUCT_VIATECH_VT82C586_IDE));
1005    
1006     /* Possibly not correct: */
1007     PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_MASS_STORAGE,
1008     PCI_SUBCLASS_MASS_STORAGE_IDE, 0x00) + 0x01);
1009    
1010     /* APO_IDECONF */
1011     /* channel 0 and 1 enabled */
1012     PCI_SET_DATA(0x40, 0x00000003);
1013    
1014 dpavlin 42 CHECK_ALLOCATION(pd->extra = malloc(sizeof(struct vt82c586_ide_extra)));
1015 dpavlin 30 ((struct vt82c586_ide_extra *)pd->extra)->wdc0 = NULL;
1016     ((struct vt82c586_ide_extra *)pd->extra)->wdc1 = NULL;
1017    
1018 dpavlin 20 if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||
1019     diskimage_exist(machine, 1, DISKIMAGE_IDE)) {
1020 dpavlin 34 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%s."
1021     "isa.%i", (long long)(pd->pcibus->isa_portbase + 0x1f0),
1022     pd->pcibus->irq_path_isa, 14);
1023 dpavlin 30 ((struct vt82c586_ide_extra *)pd->extra)->wdc0 =
1024     device_add(machine, tmpstr);
1025 dpavlin 20 }
1026    
1027     if (diskimage_exist(machine, 2, DISKIMAGE_IDE) ||
1028     diskimage_exist(machine, 3, DISKIMAGE_IDE)) {
1029 dpavlin 34 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%s."
1030     "isa.%i", (long long)(pd->pcibus->isa_portbase + 0x170),
1031     pd->pcibus->irq_path_isa, 15);
1032 dpavlin 30 ((struct vt82c586_ide_extra *)pd->extra)->wdc1 =
1033     device_add(machine, tmpstr);
1034 dpavlin 20 }
1035 dpavlin 30
1036     pd->cfg_reg_write = vt82c586_ide_cfg_reg_write;
1037 dpavlin 20 }
1038    
1039    
1040    
1041     /*
1042     * Symphony Labs 83C553 PCI->ISA bridge.
1043     * Symphony Labs 82C105 PCIIDE controller.
1044     */
1045    
1046     #define PCI_VENDOR_SYMPHONY 0x10ad
1047     #define PCI_PRODUCT_SYMPHONY_83C553 0x0565
1048     #define PCI_PRODUCT_SYMPHONY_82C105 0x0105
1049    
1050     PCIINIT(symphony_83c553)
1051     {
1052     PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_SYMPHONY,
1053     PCI_PRODUCT_SYMPHONY_83C553));
1054    
1055     PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
1056     PCI_SUBCLASS_BRIDGE_ISA, 0) + 0x10);
1057    
1058     PCI_SET_DATA(PCI_BHLC_REG,
1059     PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
1060 dpavlin 34
1061     switch (machine->machine_type) {
1062     case MACHINE_NETWINDER:
1063     bus_isa_init(machine, pd->pcibus->irq_path_isa,
1064     0, 0x7c000000, 0x80000000);
1065     break;
1066     default:fatal("symphony_83c553 init: unimplemented machine type\n");
1067     exit(1);
1068     }
1069 dpavlin 20 }
1070    
1071 dpavlin 32 struct symphony_82c105_extra {
1072     void *wdc0;
1073     void *wdc1;
1074     };
1075    
1076     int symphony_82c105_cfg_reg_write(struct pci_device *pd, int reg,
1077     uint32_t value)
1078     {
1079     void *wdc0 = ((struct symphony_82c105_extra *)pd->extra)->wdc0;
1080     void *wdc1 = ((struct symphony_82c105_extra *)pd->extra)->wdc1;
1081     int enabled = 0;
1082    
1083     printf("reg = 0x%x\n", reg);
1084     switch (reg) {
1085     case PCI_COMMAND_STATUS_REG:
1086     if (value & PCI_COMMAND_IO_ENABLE)
1087     enabled = 1;
1088     printf(" value = 0x%"PRIx32"\n", value);
1089     if (wdc0 != NULL)
1090     wdc_set_io_enabled(wdc0, enabled);
1091     if (wdc1 != NULL)
1092     wdc_set_io_enabled(wdc1, enabled);
1093     /* Set all bits: */
1094     PCI_SET_DATA(reg, value);
1095     return 1;
1096     case PCI_MAPREG_START:
1097     case PCI_MAPREG_START + 4:
1098     case PCI_MAPREG_START + 8:
1099     case PCI_MAPREG_START + 12:
1100     case PCI_MAPREG_START + 16:
1101     case PCI_MAPREG_START + 20:
1102     PCI_SET_DATA(reg, value);
1103     return 1;
1104     }
1105    
1106     return 0;
1107     }
1108    
1109 dpavlin 20 PCIINIT(symphony_82c105)
1110     {
1111     char tmpstr[100];
1112    
1113     PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_SYMPHONY,
1114     PCI_PRODUCT_SYMPHONY_82C105));
1115    
1116     /* Possibly not correct: */
1117     PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_MASS_STORAGE,
1118     PCI_SUBCLASS_MASS_STORAGE_IDE, 0x00) + 0x05);
1119    
1120 dpavlin 32 /* TODO: Interrupt line: */
1121     /* PCI_SET_DATA(PCI_INTERRUPT_REG, 0x28140000); */
1122    
1123 dpavlin 20 /* APO_IDECONF */
1124     /* channel 0 and 1 enabled */
1125     PCI_SET_DATA(0x40, 0x00000003);
1126    
1127 dpavlin 44 CHECK_ALLOCATION(pd->extra =
1128     malloc(sizeof(struct symphony_82c105_extra)));
1129 dpavlin 32 ((struct symphony_82c105_extra *)pd->extra)->wdc0 = NULL;
1130     ((struct symphony_82c105_extra *)pd->extra)->wdc1 = NULL;
1131    
1132 dpavlin 20 if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||
1133     diskimage_exist(machine, 1, DISKIMAGE_IDE)) {
1134 dpavlin 34 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%s."
1135     "isa.%i", (long long)(pd->pcibus->isa_portbase + 0x1f0),
1136     pd->pcibus->irq_path_isa, 14);
1137 dpavlin 32 ((struct symphony_82c105_extra *)pd->extra)->wdc0 =
1138     device_add(machine, tmpstr);
1139 dpavlin 20 }
1140    
1141     if (diskimage_exist(machine, 2, DISKIMAGE_IDE) ||
1142     diskimage_exist(machine, 3, DISKIMAGE_IDE)) {
1143 dpavlin 34 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%s."
1144     "isa.%i", (long long)(pd->pcibus->isa_portbase + 0x170),
1145     pd->pcibus->irq_path_isa, 15);
1146 dpavlin 32 ((struct symphony_82c105_extra *)pd->extra)->wdc1 =
1147     device_add(machine, tmpstr);
1148 dpavlin 20 }
1149 dpavlin 32
1150     pd->cfg_reg_write = symphony_82c105_cfg_reg_write;
1151 dpavlin 20 }
1152    
1153    
1154    
1155     /*
1156 dpavlin 40 * Realtek 8139C+ PCI ethernet.
1157     */
1158    
1159     #define PCI_VENDOR_REALTEK 0x10ec
1160     #define PCI_PRODUCT_REALTEK_RT8139 0x8139
1161    
1162     PCIINIT(rtl8139c)
1163     {
1164     uint64_t port, memaddr;
1165     int pci_int_line = 0x101, irq = 0;
1166     char irqstr[200];
1167     char tmpstr[200];
1168    
1169     PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_REALTEK,
1170     PCI_PRODUCT_REALTEK_RT8139));
1171    
1172     PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_NETWORK,
1173     PCI_SUBCLASS_NETWORK_ETHERNET, 0x00) + 0x20);
1174    
1175     switch (machine->machine_type) {
1176     case MACHINE_LANDISK:
1177     irq = 5;
1178     pci_int_line = 0x105;
1179     break;
1180     default:fatal("rtl8139c for this machine has not been "
1181     "implemented yet\n");
1182     exit(1);
1183     }
1184    
1185     PCI_SET_DATA(PCI_INTERRUPT_REG, 0x28140000 | pci_int_line);
1186    
1187     allocate_device_space(pd, 0x100, 0, &port, &memaddr);
1188    
1189     snprintf(irqstr, sizeof(irqstr), "%s.%i",
1190     pd->pcibus->irq_path_pci, irq);
1191    
1192     snprintf(tmpstr, sizeof(tmpstr), "rtl8139c addr=0x%llx "
1193     "irq=%s pci_little_endian=1", (long long)port, irqstr);
1194    
1195     device_add(machine, tmpstr);
1196     }
1197    
1198    
1199    
1200     /*
1201 dpavlin 20 * DEC 21143 ("Tulip") PCI ethernet.
1202     */
1203    
1204     #define PCI_VENDOR_DEC 0x1011 /* Digital Equipment */
1205     #define PCI_PRODUCT_DEC_21142 0x0019 /* DECchip 21142/21143 10/100 Ethernet */
1206    
1207     PCIINIT(dec21143)
1208     {
1209     uint64_t port, memaddr;
1210 dpavlin 34 int pci_int_line = 0x101, irq = 0, isa = 0;
1211     char irqstr[200];
1212 dpavlin 20 char tmpstr[200];
1213    
1214     PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_DEC,
1215     PCI_PRODUCT_DEC_21142));
1216    
1217     PCI_SET_DATA(PCI_COMMAND_STATUS_REG, 0x02000017);
1218    
1219     PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_NETWORK,
1220     PCI_SUBCLASS_NETWORK_ETHERNET, 0x00) + 0x41);
1221    
1222     PCI_SET_DATA(PCI_BHLC_REG, PCI_BHLC_CODE(0,0,0, 0x40,0));
1223    
1224     switch (machine->machine_type) {
1225     case MACHINE_CATS:
1226 dpavlin 22 /* CATS int 18 = PCI. */
1227 dpavlin 20 irq = 18;
1228 dpavlin 22 pci_int_line = 0x101;
1229 dpavlin 20 break;
1230 dpavlin 22 case MACHINE_COBALT:
1231     /* On Cobalt, IRQ 7 = PCI. */
1232     irq = 8 + 7;
1233     pci_int_line = 0x407;
1234     break;
1235 dpavlin 20 case MACHINE_PREP:
1236 dpavlin 34 irq = 10;
1237     isa = 1;
1238 dpavlin 22 pci_int_line = 0x20a;
1239 dpavlin 20 break;
1240 dpavlin 22 case MACHINE_MVMEPPC:
1241     /* TODO */
1242 dpavlin 34 irq = 10;
1243 dpavlin 22 pci_int_line = 0x40a;
1244     break;
1245 dpavlin 20 case MACHINE_PMPPC:
1246 dpavlin 22 /* TODO, not working yet */
1247 dpavlin 42 irq = 31 - CPC_IB_EXT1;
1248     pci_int_line = 0x101;
1249 dpavlin 20 break;
1250 dpavlin 22 case MACHINE_MACPPC:
1251     /* TODO, not working yet */
1252     irq = 25;
1253     pci_int_line = 0x101;
1254     break;
1255 dpavlin 20 }
1256    
1257 dpavlin 22 PCI_SET_DATA(PCI_INTERRUPT_REG, 0x28140000 | pci_int_line);
1258 dpavlin 20
1259     allocate_device_space(pd, 0x100, 0x100, &port, &memaddr);
1260    
1261 dpavlin 34 if (isa)
1262     snprintf(irqstr, sizeof(irqstr), "%s.isa.%i",
1263     pd->pcibus->irq_path_isa, irq);
1264     else
1265     snprintf(irqstr, sizeof(irqstr), "%s.%i",
1266     pd->pcibus->irq_path_pci, irq);
1267    
1268 dpavlin 20 snprintf(tmpstr, sizeof(tmpstr), "dec21143 addr=0x%llx addr2=0x%llx "
1269 dpavlin 34 "irq=%s pci_little_endian=1", (long long)port,
1270     (long long)memaddr, irqstr);
1271    
1272 dpavlin 20 device_add(machine, tmpstr);
1273     }
1274    
1275    
1276    
1277     /*
1278     * DEC 21030 "tga" graphics.
1279     */
1280    
1281     #define PCI_PRODUCT_DEC_21030 0x0004 /* DECchip 21030 ("TGA") */
1282    
1283     PCIINIT(dec21030)
1284     {
1285     uint64_t base = 0;
1286     char tmpstr[200];
1287    
1288     PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_DEC,
1289     PCI_PRODUCT_DEC_21030));
1290    
1291     PCI_SET_DATA(PCI_COMMAND_STATUS_REG, 0x02800087); /* TODO */
1292    
1293     PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_DISPLAY,
1294     PCI_SUBCLASS_DISPLAY_VGA, 0x00) + 0x03);
1295    
1296     /*
1297     * See http://mail-index.netbsd.org/port-arc/2001/08/13/0000.html
1298     * for more info.
1299     */
1300    
1301     PCI_SET_DATA(PCI_BHLC_REG, 0x0000ff00);
1302    
1303     /* 8 = prefetchable */
1304     PCI_SET_DATA(0x10, 0x00000008);
1305     PCI_SET_DATA(0x30, 0x08000001);
1306     PCI_SET_DATA(PCI_INTERRUPT_REG, 0x00000100); /* interrupt pin A? */
1307    
1308     /*
1309     * Experimental:
1310     *
1311     * TODO: Base address, pci_little_endian, ...
1312     */
1313    
1314     switch (machine->machine_type) {
1315     case MACHINE_ARC:
1316     base = 0x100000000ULL;
1317     break;
1318     default:fatal("dec21030 in non-implemented machine type %i\n",
1319     machine->machine_type);
1320     exit(1);
1321     }
1322    
1323     snprintf(tmpstr, sizeof(tmpstr), "dec21030 addr=0x%llx",
1324     (long long)(base));
1325     device_add(machine, tmpstr);
1326     }
1327    
1328    
1329 dpavlin 22
1330 dpavlin 20 /*
1331     * Motorola MPC105 "Eagle" Host Bridge
1332     *
1333     * Used in at least PReP and BeBox.
1334     */
1335    
1336     #define PCI_VENDOR_MOT 0x1057
1337     #define PCI_PRODUCT_MOT_MPC105 0x0001
1338    
1339     PCIINIT(eagle)
1340     {
1341     PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_MOT,
1342     PCI_PRODUCT_MOT_MPC105));
1343    
1344     PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
1345     PCI_SUBCLASS_BRIDGE_HOST, 0) + 0x24);
1346    
1347     PCI_SET_DATA(PCI_BHLC_REG,
1348     PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
1349     }
1350    
1351 dpavlin 22
1352    
1353     /*
1354     * Apple (MacPPC) stuff:
1355     *
1356     * Grand Central (I/O controller)
1357     * Uni-North (PCI controller)
1358     */
1359    
1360     #define PCI_VENDOR_APPLE 0x106b
1361     #define PCI_PRODUCT_APPLE_GC 0x0002
1362     #define PCI_PRODUCT_APPLE_UNINORTH1 0x001e
1363    
1364     PCIINIT(gc_obio)
1365     {
1366     uint64_t port, memaddr;
1367    
1368     PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_APPLE,
1369     PCI_PRODUCT_APPLE_GC));
1370    
1371     /* TODO: */
1372     PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_SYSTEM,
1373     PCI_SUBCLASS_SYSTEM_PIC, 0) + 0x00);
1374    
1375     PCI_SET_DATA(PCI_BHLC_REG,
1376     PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
1377    
1378     /* TODO */
1379     allocate_device_space(pd, 0x10000, 0x10000, &port, &memaddr);
1380     }
1381    
1382     PCIINIT(uninorth)
1383     {
1384     uint64_t port, memaddr;
1385    
1386     PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_APPLE,
1387     PCI_PRODUCT_APPLE_UNINORTH1));
1388    
1389     PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
1390     PCI_SUBCLASS_BRIDGE_HOST, 0) + 0xff);
1391    
1392     PCI_SET_DATA(PCI_BHLC_REG,
1393     PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
1394    
1395     /* TODO */
1396     allocate_device_space(pd, 0x10000, 0x10000, &port, &memaddr);
1397     }
1398    
1399    
1400    
1401     /*
1402     * ATI graphics cards
1403     */
1404    
1405     #define PCI_VENDOR_ATI 0x1002
1406     #define PCI_PRODUCT_ATI_RADEON_9200_2 0x5962
1407    
1408     PCIINIT(ati_radeon_9200_2)
1409     {
1410     uint64_t port, memaddr;
1411    
1412     PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_ATI,
1413     PCI_PRODUCT_ATI_RADEON_9200_2));
1414    
1415     /* TODO: other subclass? */
1416     PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_DISPLAY,
1417     PCI_SUBCLASS_DISPLAY_VGA, 0) + 0x03);
1418    
1419     /* TODO */
1420     allocate_device_space(pd, 0x1000, 0x400000, &port, &memaddr);
1421     }
1422    

  ViewVC Help
Powered by ViewVC 1.1.26