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

Legend:
Removed from v.14  
changed lines
  Added in v.40

  ViewVC Help
Powered by ViewVC 1.1.26