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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.4  
changed lines
  Added in v.30

  ViewVC Help
Powered by ViewVC 1.1.26