/[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 44 - (hide annotations)
Mon Oct 8 16:22:56 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 37552 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1632 2007/09/11 21:46:35 debug Exp $
20070616	Implementing the MIPS32/64 revision 2 "ror" instruction.
20070617	Adding a struct for each physpage which keeps track of which
		ranges within that page (base offset, length) that are
		continuously translatable. When running with native code
		generation enabled (-b), a range is added after each read-
		ahead loop.
		Experimenting with using the physical program counter sample
		data (implemented 20070608) together with the "translatable
		range" information, to figure out which physical address ranges
		would be worth translating to native code (if the number of
		samples falling within a range is above a certain threshold).
20070618	Adding automagic building of .index comment files for
		src/file/, src/promemul/, src src/useremul/ as well.
		Adding a "has been translated" bit to the ranges, so that only
		not-yet-translated ranges will be sampled.
20070619	Moving src/cpu.c and src/memory_rw.c into src/cpus/,
		src/device.c into src/devices/, and src/machine.c into
		src/machines/.
		Creating a skeleton cc/ld native backend module; beginning on
		the function which will detect cc command line, etc.
20070620	Continuing on the native code generation infrastructure.
20070621	Moving src/x11.c and src/console.c into a new src/console/
		subdir (for everything that is console or framebuffer related).
		Moving src/symbol*.c into a new src/symbol/, which should
		contain anything that is symbol handling related.
20070624	Making the program counter sampling threshold a "settings
		variable" (sampling_threshold), i.e. it can now be changed
		during runtime.
		Switching the RELEASE notes format from plain text to HTML.
		If the TMPDIR environment variable is set, it is used instead
		of "/tmp" for temporary files.
		Continuing on the cc/ld backend: simple .c code is generated,
		the compiler and linker are called, etc.
		Adding detection of host architecture to the configure script
		(again), and adding icache invalidation support (only
		implemented for Alpha hosts so far).
20070625	Simplifying the program counter sampling mechanism.
20070626	Removing the cc/ld native code generation stuff, program
		counter sampling, etc; it would not have worked well in the
		general case.
20070627	Removing everything related to native code generation.
20070629	Removing the (practically unusable) support for multiple
		emulations. (The single emulation allowed now still supports
		multiple simultaneous machines, as before.)
		Beginning on PCCTWO and M88K interrupts.
20070723	Adding a dummy skeleton for emulation of M32R processors.
20070901	Fixing a warning found by "gcc version 4.3.0 20070817
		(experimental)" on amd64.
20070905	Removing some more traces of the old "multiple emulations"
		code.
		Also looking in /usr/local/include and /usr/local/lib for
		X11 libs, when running configure.
20070909	Minor updates to the guest OS install instructions, in
		preparation for the NetBSD 4.0 release.
20070918	More testing of NetBSD 4.0 RC1.

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

  ViewVC Help
Powered by ViewVC 1.1.26