/[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 19 by dpavlin, Mon Oct 8 16:18:51 2007 UTC revision 20 by dpavlin, Mon Oct 8 16:19:23 2007 UTC
# 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.40 2005/11/25 03:59:58 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"  extern int verbose;
61    
62    
63  /*  #define debug fatal  */  /*  #define debug fatal  */
64    
65    
66    static void reverse(uint64_t *p, int len)
67    {
68            uint64_t x = *p, y = 0;
69            int i;
70            for (i=0; i<len; i++) {
71                    y <<= 8;
72                    y |= ((x >> (8*i)) & 0xff);
73            }
74            *p = y;
75    }
76    
77    
78    /*
79     *  bus_pci_data_access():
80     *
81     *  Reads from and writes to the PCI configuration registers of a device.
82     */
83    void bus_pci_data_access(struct cpu *cpu, struct memory *mem,
84            uint64_t *data, int len, int writeflag, struct pci_data *pci_data)
85    {
86            struct pci_device *dev;
87            int bus, device, function, registernr;
88            unsigned char *cfg_base;
89            uint64_t x, idata = *data;
90    
91            if (cpu->byte_order == EMUL_BIG_ENDIAN)
92                    reverse(&idata, len);
93    
94            /*  Get the bus, device, and function numbers from the address:  */
95            bus        = (pci_data->pci_addr >> 16) & 0xff;
96            device     = (pci_data->pci_addr >> 11) & 0x1f;
97            function   = (pci_data->pci_addr >> 8)  & 0x7;
98            registernr = (pci_data->pci_addr)       & 0xff;
99    
100            /*  Scan through the list of pci_device entries.  */
101            dev = pci_data->first_device;
102            while (dev != NULL) {
103                    if (dev->bus == bus && dev->function == function &&
104                        dev->device == device)
105                            break;
106                    dev = dev->next;
107            }
108    
109            /*  No device? Then return emptiness.  */
110            if (dev == NULL) {
111                    if ((pci_data->pci_addr & 0xff) == 0)
112                            *data = 0xffffffff;
113                    else
114                            *data = 0;
115                    return;
116            }
117    
118            /*  Return normal config data, or length data?  */
119            if (pci_data->last_was_write_ffffffff &&
120                registernr >= PCI_MAPREG_START && registernr <= PCI_MAPREG_END - 4)
121                    cfg_base = dev->cfg_mem_size;
122            else
123                    cfg_base = dev->cfg_mem;
124    
125            /*  Read data as little-endian:  */
126            x = 0;
127            if (registernr + len - 1 < PCI_CFG_MEM_SIZE) {
128                    x = cfg_base[registernr];
129                    if (len > 1)
130                            x |= (cfg_base[registernr+1] << 8);
131                    if (len > 2)
132                            x |= (cfg_base[registernr+2] << 16);
133                    if (len > 3)
134                            x |= ((uint64_t)cfg_base[registernr+3] << 24);
135                    if (len > 4)
136                            fatal("TODO: more than 32-bit PCI access?\n");
137            }
138    
139            /*  Register write:  */
140            if (writeflag == MEM_WRITE) {
141                    debug("[ bus_pci: write to PCI DATA: data = 0x%016llx ]\n",
142                        (long long)idata);
143                    if (idata == 0xffffffffULL && registernr >= PCI_MAPREG_START
144                        && registernr <= PCI_MAPREG_END - 4) {
145                            pci_data->last_was_write_ffffffff = 1;
146                            return;
147                    }
148                    /*  Writes are not really supported yet:  */
149                    if (idata != x) {
150                            debug("[ bus_pci: write to PCI DATA: data = 0x%08llx"
151                                " differs from current value 0x%08llx; NOT YET"
152                                " SUPPORTED. bus %i, device %i, function %i (%s)"
153                                " register 0x%02x ]\n", (long long)idata,
154                                (long long)x, bus, device, function, dev->name,
155                                registernr);
156                    }
157                    return;
158            }
159    
160            /*  Register read:  */
161            if (cpu->byte_order == EMUL_BIG_ENDIAN)
162                    reverse(&x, len);
163            *data = x;
164    
165            pci_data->last_was_write_ffffffff = 0;
166    
167            debug("[ bus_pci: read from PCI DATA, addr = 0x%08lx (bus %i, device "
168                "%i, function %i (%s) register 0x%02x): 0x%08lx ]\n", (long)
169                pci_data->pci_addr, bus, device, function, dev->name,
170                registernr, (long)*data);
171    }
172    
173    
174  /*  /*
175   *  bus_pci_access():   *  bus_pci_access():
176   *   *
# Line 56  Line 181 
181   *  Returns 1 if ok, 0 on error.   *  Returns 1 if ok, 0 on error.
182   */   */
183  int bus_pci_access(struct cpu *cpu, struct memory *mem, uint64_t relative_addr,  int bus_pci_access(struct cpu *cpu, struct memory *mem, uint64_t relative_addr,
184          uint64_t *data, int writeflag, struct pci_data *pci_data)          uint64_t *data, int len, int writeflag, struct pci_data *pci_data)
185  {  {
         struct pci_device *dev, *found;  
         int bus, device, function, registernr;  
   
186          if (writeflag == MEM_READ)          if (writeflag == MEM_READ)
187                  *data = 0;                  *data = 0;
188    
189          switch (relative_addr) {          switch (relative_addr) {
190    
191          case BUS_PCI_ADDR:          case BUS_PCI_ADDR:
192                  if (writeflag == MEM_WRITE) {                  if (writeflag == MEM_WRITE) {
193                          debug("[ bus_pci: write to  PCI ADDR: data = 0x%016llx"                          debug("[ bus_pci: write to PCI ADDR: data = 0x%016llx"
194                              " ]\n", (long long)*data);                              " ]\n", (long long)*data);
195                          pci_data->pci_addr = *data;                          pci_data->pci_addr = *data;
196    
197                            /*
198                             *  Big-endian systems (e.g. PowerPC) seem to access
199                             *  PCI config data using little-endian accesses.
200                             */
201                            if (cpu->byte_order == EMUL_BIG_ENDIAN) {
202                                    uint32_t t = pci_data->pci_addr;
203                                    pci_data->pci_addr = ((t >> 24) & 255)
204                                        | ((t >> 8) & 0xff00)
205                                        | ((t << 8) & 0xff0000)
206                                        | ((t << 24) & 0xff000000);
207                            }
208    
209                            /*  Linux seems to use type 0 even when it does
210                                type 1 detection. Hm. This is commented for now.  */
211                            /*  if (pci_data->pci_addr & 1)
212                                    fatal("[ bus_pci: WARNING! pci type 0 not"
213                                        " yet implemented! ]\n");  */
214                  } else {                  } else {
215                          debug("[ bus_pci: read from PCI ADDR (data = "                          debug("[ bus_pci: read from PCI ADDR (data = "
216                              "0x%016llx) ]\n", (long long)pci_data->pci_addr);                              "0x%016llx) ]\n", (long long)pci_data->pci_addr);
217                          *data = pci_data->pci_addr;                          *data = pci_data->pci_addr;
218                  }                  }
219                  break;                  break;
         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;  
                         }  
   
                         *data = 0;  
   
                         if (pci_data->last_was_write_ffffffff &&  
                             registernr >= 0x10 && registernr <= 0x24) {  
                                 /*  TODO:  real length!!!  */  
                                 *data = 0x00400000 - 1;  
                         } else if (found->read_register != NULL)  
                                 *data = found->read_register(registernr);  
   
                         pci_data->last_was_write_ffffffff = 0;  
   
                         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);  
                 }  
220    
221            case BUS_PCI_DATA:
222                    bus_pci_data_access(cpu, mem, data, len, writeflag, pci_data);
223                  break;                  break;
224          default:  
225                  if (writeflag==MEM_READ) {          default:if (writeflag == MEM_READ) {
226                          debug("[ bus_pci: read from unimplemented addr "                          debug("[ bus_pci: read from unimplemented addr "
227                              "0x%x ]\n", (int)relative_addr);                              "0x%x ]\n", (int)relative_addr);
228                          *data = 0;                          *data = 0;
229                  } else {                  } else {
230                          debug("[ bus_pci: write to unimplemented addr "                          debug("[ bus_pci: write to unimplemented addr "
231                              "0x%x:", (int)relative_addr);                              "0x%x: 0x%llx ]\n", (int)relative_addr,
232                                (long long)*data);
233                  }                  }
234          }          }
235    
# Line 150  int bus_pci_access(struct cpu *cpu, stru Line 244  int bus_pci_access(struct cpu *cpu, stru
244   */   */
245  void bus_pci_add(struct machine *machine, struct pci_data *pci_data,  void bus_pci_add(struct machine *machine, struct pci_data *pci_data,
246          struct memory *mem, int bus, int device, int function,          struct memory *mem, int bus, int device, int function,
247          void (*init)(struct machine *, struct memory *),          char *name)
         uint32_t (*read_register)(int reg))  
248  {  {
249          struct pci_device *new_device;          struct pci_device *pd;
250            int ofs;
251            void (*init)(struct machine *, struct memory *, struct pci_device *);
252    
253          if (pci_data == NULL) {          if (pci_data == NULL) {
254                  fatal("bus_pci_add(): pci_data == NULL!\n");                  fatal("bus_pci_add(): pci_data == NULL!\n");
255                  exit(1);                  exit(1);
256          }          }
257    
258            /*  Find the PCI device:  */
259            init = pci_lookup_initf(name);
260    
261          /*  Make sure this bus/device/function number isn't already in use:  */          /*  Make sure this bus/device/function number isn't already in use:  */
262          new_device = pci_data->first_device;          pd = pci_data->first_device;
263          while (new_device != NULL) {          while (pd != NULL) {
264                  if (new_device->bus == bus &&                  if (pd->bus == bus && pd->device == device &&
265                      new_device->device == device &&                      pd->function == function) {
                     new_device->function == function) {  
266                          fatal("bus_pci_add(): (bus %i, device %i, function"                          fatal("bus_pci_add(): (bus %i, device %i, function"
267                              " %i) already in use\n", bus, device, function);                              " %i) already in use\n", bus, device, function);
268                          return;                          exit(1);
269                  }                  }
270                  new_device = new_device->next;                  pd = pd->next;
271          }          }
272    
273          new_device = malloc(sizeof(struct pci_device));          pd = malloc(sizeof(struct pci_device));
274          if (new_device == NULL) {          if (pd == NULL) {
275                  fprintf(stderr, "out of memory\n");                  fprintf(stderr, "out of memory\n");
276                  exit(1);                  exit(1);
277          }          }
278    
279          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;  
280    
281          /*  Add the new device first in the PCI bus' chain:  */          /*  Add the new device first in the PCI bus' chain:  */
282          new_device->next = pci_data->first_device;          pd->next = pci_data->first_device;
283          pci_data->first_device = new_device;          pci_data->first_device = pd;
284    
285            pd->pcibus   = pci_data;
286            pd->name     = strdup(name);
287            pd->bus      = bus;
288            pd->device   = device;
289            pd->function = function;
290    
291            /*
292             *  Initialize with some default values:
293             *
294             *  TODO:  The command status register is best to set up per device,
295             *         just enabling all bits like this is not really good.
296             *         The size registers should also be set up on a per-device
297             *         basis.
298             */
299            PCI_SET_DATA(PCI_COMMAND_STATUS_REG, 0x00ffffffULL);
300            for (ofs = PCI_MAPREG_START; ofs < PCI_MAPREG_END; ofs += 4)
301                    PCI_SET_DATA_SIZE(ofs, 0x00400000 - 1);
302    
303            if (init == NULL) {
304                    fatal("No init function for PCI device \"%s\"?\n", name);
305                    exit(1);
306            }
307    
308          /*  Call the PCI device' init function:  */          /*  Call the PCI device' init function:  */
309          if (init != NULL)          init(machine, mem, pd);
310                  init(machine, mem);  }
311    
312    
313    /*
314     *  allocate_device_space():
315     *
316     *  Used by glue code (see below) to allocate space for a PCI device.
317     *
318     *  The returned values in portp and memp are the actual (emulated) addresses
319     *  that the device should use. (Normally only one of these is actually used.)
320     *
321     *  TODO: PCI irqs?
322     */
323    static void allocate_device_space(struct pci_device *pd,
324            uint64_t portsize, uint64_t memsize,
325            uint64_t *portp, uint64_t *memp)
326    {
327            uint64_t port, mem;
328    
329            /*  Calculate an aligned starting port:  */
330            port = pd->pcibus->cur_pci_portbase;
331            if (portsize != 0) {
332                    port = ((port - 1) | (portsize - 1)) + 1;
333                    pd->pcibus->cur_pci_portbase = port;
334                    PCI_SET_DATA(PCI_MAPREG_START, port | PCI_MAPREG_TYPE_IO);
335                    PCI_SET_DATA_SIZE(PCI_MAPREG_START, portsize - 1);
336            }
337    
338            /*  Calculate an aligned starting memory location:  */
339            mem = pd->pcibus->cur_pci_membase;
340            if (memsize != 0) {
341                    mem = ((mem - 1) | (memsize - 1)) + 1;
342                    pd->pcibus->cur_pci_membase = mem;
343                    PCI_SET_DATA(PCI_MAPREG_START + 0x04, mem);
344                    PCI_SET_DATA_SIZE(PCI_MAPREG_START + 0x04, memsize - 1);
345            }
346    
347            *portp = port + pd->pcibus->pci_actual_io_offset;
348            *memp  = mem  + pd->pcibus->pci_actual_mem_offset;
349    
350            if (verbose >= 2) {
351                    debug("pci device '%s' at", pd->name);
352                    if (portsize != 0)
353                            debug(" port 0x%llx-0x%llx", (long long)pd->pcibus->
354                                cur_pci_portbase, (long long)(pd->pcibus->
355                                cur_pci_portbase + portsize - 1));
356                    if (memsize != 0)
357                            debug(" mem 0x%llx-0x%llx", (long long)pd->pcibus->
358                                cur_pci_membase, (long long)(pd->pcibus->
359                                cur_pci_membase + memsize - 1));
360                    debug("\n");
361            }
362    
363            pd->pcibus->cur_pci_portbase += portsize;
364            pd->pcibus->cur_pci_membase += memsize;
365  }  }
366    
367    
# Line 201  void bus_pci_add(struct machine *machine Line 370  void bus_pci_add(struct machine *machine
370   *   *
371   *  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
372   *  which should be passed to bus_pci_access() when accessing the PCI bus.   *  which should be passed to bus_pci_access() when accessing the PCI bus.
373     *
374     *  irq_nr is the (optional) IRQ nr that this PCI bus interrupts at.
375     *
376     *  pci_portbase, pci_membase, and pci_irqbase are the port, memory, and
377     *  interrupt bases for PCI devices (as found in the configuration registers).
378     *
379     *  pci_actual_io_offset and pci_actual_mem_offset are the offset from
380     *  the values in the configuration registers to the actual (emulated) device.
381     *
382     *  isa_portbase, isa_membase, and isa_irqbase are the port, memory, and
383     *  interrupt bases for legacy ISA devices.
384   */   */
385  struct pci_data *bus_pci_init(int irq_nr)  struct pci_data *bus_pci_init(int irq_nr,
386            uint64_t pci_actual_io_offset, uint64_t pci_actual_mem_offset,
387            uint64_t pci_portbase, uint64_t pci_membase, int pci_irqbase,
388            uint64_t isa_portbase, uint64_t isa_membase, int isa_irqbase)
389  {  {
390          struct pci_data *d;          struct pci_data *d;
391    
# Line 212  struct pci_data *bus_pci_init(int irq_nr Line 395  struct pci_data *bus_pci_init(int irq_nr
395                  exit(1);                  exit(1);
396          }          }
397          memset(d, 0, sizeof(struct pci_data));          memset(d, 0, sizeof(struct pci_data));
398          d->irq_nr = irq_nr;          d->irq_nr                = irq_nr;
399            d->pci_actual_io_offset  = pci_actual_io_offset;
400            d->pci_actual_mem_offset = pci_actual_mem_offset;
401            d->pci_portbase          = pci_portbase;
402            d->pci_membase           = pci_membase;
403            d->pci_irqbase           = pci_irqbase;
404            d->isa_portbase          = isa_portbase;
405            d->isa_membase           = isa_membase;
406            d->isa_irqbase           = isa_irqbase;
407    
408            /*  Assume that the first 64KB could be used by legacy ISA devices:  */
409            d->cur_pci_portbase = d->pci_portbase + 0x10000;
410            d->cur_pci_membase  = d->pci_membase + 0x10000;
411    
412          return d;          return d;
413  }  }
414    
415    
416    
417    /******************************************************************************
418     *
419     *  The following is glue code for PCI controllers and devices. The glue code
420     *  does the minimal stuff necessary to get an emulated OS to detect the
421     *  device (i.e. set up PCI configuration registers), and then if necessary
422     *  add a "normal" device.
423     *
424     ******************************************************************************/
425    
426    
427    
428    /*
429     *  Integraphics Systems "igsfb" Framebuffer (graphics) card.
430     *
431     *  TODO
432     */
433    
434    #define PCI_VENDOR_INTEGRAPHICS         0x10ea
435    
436    PCIINIT(igsfb)
437    {
438            PCI_SET_DATA(PCI_ID_REG,
439                PCI_ID_CODE(PCI_VENDOR_INTEGRAPHICS, 0x2010));
440    
441            PCI_SET_DATA(PCI_CLASS_REG,
442                PCI_CLASS_CODE(PCI_CLASS_DISPLAY,
443                PCI_SUBCLASS_DISPLAY_VGA, 0) + 0x01);
444    
445            /*  TODO  */
446            PCI_SET_DATA(0x10, 0xb0000000);
447    
448            /*  TODO: This is just a dummy so far.  */
449    }
450    
451    
452    
453    /*
454     *  S3 ViRGE graphics.
455     *
456     *  TODO: Only emulates a standard VGA card, so far.
457     */
458    
459    #define PCI_VENDOR_S3                   0x5333
460    #define PCI_PRODUCT_S3_VIRGE            0x5631
461    #define PCI_PRODUCT_S3_VIRGE_DX         0x8a01
462    
463    PCIINIT(s3_virge)
464    {
465            PCI_SET_DATA(PCI_ID_REG,
466                PCI_ID_CODE(PCI_VENDOR_S3, PCI_PRODUCT_S3_VIRGE_DX));
467    
468            PCI_SET_DATA(PCI_CLASS_REG,
469                PCI_CLASS_CODE(PCI_CLASS_DISPLAY,
470                PCI_SUBCLASS_DISPLAY_VGA, 0) + 0x01);
471    
472            dev_vga_init(machine, mem, pd->pcibus->isa_membase + 0xa0000,
473                pd->pcibus->isa_portbase + 0x3c0, machine->machine_name);
474    }
475    
476    
477    
478    /*
479     *  Acer Labs M5229 PCI-IDE (UDMA) controller.
480     *  Acer Labs M1543 PCI->ISA bridge.
481     */
482    
483    #define PCI_VENDOR_ALI                  0x10b9
484    #define PCI_PRODUCT_ALI_M1543           0x1533  /*  NOTE: not 1543  */
485    #define PCI_PRODUCT_ALI_M5229           0x5229
486    
487    PCIINIT(ali_m1543)
488    {
489            PCI_SET_DATA(PCI_ID_REG,
490                PCI_ID_CODE(PCI_VENDOR_ALI, PCI_PRODUCT_ALI_M1543));
491    
492            PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
493                PCI_SUBCLASS_BRIDGE_ISA, 0) + 0xc3);
494    
495            PCI_SET_DATA(PCI_BHLC_REG,
496                PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
497    
498            /*  Linux uses these to detect which IRQ the IDE controller uses:  */
499            PCI_SET_DATA(0x44, 0x0000000e);
500            PCI_SET_DATA(0x58, 0x00000003);
501    }
502    
503    PCIINIT(ali_m5229)
504    {
505            char tmpstr[300];
506    
507            PCI_SET_DATA(PCI_ID_REG,
508                PCI_ID_CODE(PCI_VENDOR_ALI, PCI_PRODUCT_ALI_M5229));
509    
510            PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_MASS_STORAGE,
511                PCI_SUBCLASS_MASS_STORAGE_IDE, 0x60) + 0xc1);
512    
513            if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||
514                diskimage_exist(machine, 1, DISKIMAGE_IDE)) {
515                    snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i",
516                        (long long)(pd->pcibus->isa_portbase + 0x1f0),
517                        pd->pcibus->isa_irqbase + 14);
518                    device_add(machine, tmpstr);
519            }
520    
521            /*  The secondary channel is disabled. TODO: fix this.  */
522    }
523    
524    
525    
526    /*
527     *  Adaptec AHC SCSI controller.
528     */
529    
530    #define PCI_VENDOR_ADP  0x9004          /* Adaptec */
531    #define PCI_VENDOR_ADP2 0x9005          /* Adaptec (2nd PCI Vendor ID) */
532    #define PCI_PRODUCT_ADP_2940U   0x8178          /* AHA-2940 Ultra */
533    #define PCI_PRODUCT_ADP_2940UP  0x8778          /* AHA-2940 Ultra Pro */
534    
535    PCIINIT(ahc)
536    {
537            /*  Numbers taken from a Adaptec 2940U:  */
538            /*  http://mail-index.netbsd.org/netbsd-bugs/2000/04/29/0000.html  */
539    
540            PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_ADP,
541                PCI_PRODUCT_ADP_2940U));
542    
543            PCI_SET_DATA(PCI_COMMAND_STATUS_REG, 0x02900007);
544    
545            PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_MASS_STORAGE,
546                PCI_SUBCLASS_MASS_STORAGE_SCSI, 0) + 0x01);
547    
548            PCI_SET_DATA(PCI_BHLC_REG, 0x00004008);
549    
550            /*  1 = type i/o. 0x0000e801;  address?  */
551            /*  second address reg = 0xf1002000?  */
552            PCI_SET_DATA(PCI_MAPREG_START + 0x00, 0x00000001);
553            PCI_SET_DATA(PCI_MAPREG_START + 0x04, 0x00000000);
554    
555            PCI_SET_DATA(PCI_MAPREG_START + 0x08, 0x00000000);
556            PCI_SET_DATA(PCI_MAPREG_START + 0x0c, 0x00000000);
557            PCI_SET_DATA(PCI_MAPREG_START + 0x10, 0x00000000);
558            PCI_SET_DATA(PCI_MAPREG_START + 0x14, 0x00000000);
559            PCI_SET_DATA(PCI_MAPREG_START + 0x18, 0x00000000);
560    
561            /*  Subsystem vendor ID? 0x78819004?  */
562            PCI_SET_DATA(PCI_MAPREG_START + 0x1c, 0x00000000);
563    
564            PCI_SET_DATA(0x30, 0xef000000);
565            PCI_SET_DATA(PCI_CAPLISTPTR_REG, 0x000000dc);
566            PCI_SET_DATA(0x38, 0x00000000);
567            PCI_SET_DATA(PCI_INTERRUPT_REG, 0x08080109);    /*  interrupt pin A  */
568    
569            /*
570             *  TODO:  this address is based on what NetBSD/sgimips uses
571             *  on SGI IP32 (O2). Fix this!
572             */
573    
574            device_add(machine, "ahc addr=0x18000000");
575    
576            /*  OpenBSD/sgi snapshots sometime between 2005-03-11 and
577                2005-04-04 changed to using 0x1a000000:  */
578            dev_ram_init(machine, 0x1a000000, 0x2000000, DEV_RAM_MIRROR,
579                0x18000000);
580    }
581    
582    
583    
584    /*
585     *  Galileo Technology GT-64xxx PCI controller.
586     *
587     *      GT-64011        Used in Cobalt machines.
588     *      GT-64120        Used in evbmips machines (Malta).
589     *
590     *  NOTE: This works in the opposite way compared to other devices; the PCI
591     *  device is added from the normal device instead of the other way around.
592     */
593    
594    #define PCI_VENDOR_GALILEO           0x11ab    /* Galileo Technology */
595    #define PCI_PRODUCT_GALILEO_GT64011  0x4146    /* GT-64011 System Controller */
596    #define PCI_PRODUCT_GALILEO_GT64120  0x4620    /* GT-64120 */
597    
598    PCIINIT(gt64011)
599    {
600            PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_GALILEO,
601                PCI_PRODUCT_GALILEO_GT64011));
602    
603            PCI_SET_DATA(PCI_CLASS_REG,
604                PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
605                PCI_SUBCLASS_BRIDGE_HOST, 0) + 0x01);       /*  Revision 1  */
606    }
607    
608    PCIINIT(gt64120)
609    {
610            PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_GALILEO,
611                PCI_PRODUCT_GALILEO_GT64120));
612    
613            PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
614                PCI_SUBCLASS_BRIDGE_HOST, 0) + 0x02);       /*  Revision 2?  */
615    
616            switch (machine->machine_type) {
617            case MACHINE_EVBMIPS:
618                    PCI_SET_DATA(PCI_MAPREG_START + 0x10, 0x1be00000);
619                    break;
620            }
621    }
622    
623    
624    
625    /*
626     *  Intel 82371AB PIIX4 PCI-ISA bridge and IDE controller
627     *  and 82378ZB System I/O controller.
628     */
629    
630    #define PCI_VENDOR_INTEL                0x8086
631    #define PCI_PRODUCT_INTEL_82371AB_ISA   0x7110
632    #define PCI_PRODUCT_INTEL_82371AB_IDE   0x7111
633    #define PCI_PRODUCT_INTEL_SIO           0x0484
634    
635    PCIINIT(i82371ab_isa)
636    {
637            PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_INTEL,
638                PCI_PRODUCT_INTEL_82371AB_ISA));
639    
640            PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
641                PCI_SUBCLASS_BRIDGE_ISA, 0) + 0x01);        /*  Rev 1  */
642    
643            PCI_SET_DATA(PCI_BHLC_REG,
644                PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
645    }
646    
647    PCIINIT(i82378zb)
648    {
649            PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_INTEL,
650                PCI_PRODUCT_INTEL_SIO));
651    
652            PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
653                PCI_SUBCLASS_BRIDGE_ISA, 0) + 0x43);
654    
655            PCI_SET_DATA(PCI_BHLC_REG,
656                PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
657    }
658    
659    PCIINIT(i82371ab_ide)
660    {
661            char tmpstr[100];
662    
663            PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_INTEL,
664                PCI_PRODUCT_INTEL_82371AB_IDE));
665    
666            /*  Possibly not correct:  */
667            PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_MASS_STORAGE,
668                PCI_SUBCLASS_MASS_STORAGE_IDE, 0x00) + 0x01);
669    
670            /*  PIIX_IDETIM (see NetBSD's pciide_piix_reg.h)  */
671            /*  channel 0 and 1 enabled as IDE  */
672            PCI_SET_DATA(0x40, 0x80008000);
673    
674            if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||
675                diskimage_exist(machine, 1, DISKIMAGE_IDE)) {
676                    snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i",
677                        (long long)(pd->pcibus->isa_portbase + 0x1f0),
678                        pd->pcibus->isa_irqbase + 14);
679                    device_add(machine, tmpstr);
680            }
681    
682            if (diskimage_exist(machine, 2, DISKIMAGE_IDE) ||
683                diskimage_exist(machine, 3, DISKIMAGE_IDE)) {
684                    snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i",
685                        (long long)(pd->pcibus->isa_portbase + 0x170),
686                        pd->pcibus->isa_irqbase + 15);
687                    device_add(machine, tmpstr);
688            }
689    }
690    
691    
692    
693    /*
694     *  IBM ISA bridge (used by at least one PReP machine).
695     */
696    
697    #define PCI_VENDOR_IBM                  0x1014
698    #define PCI_PRODUCT_IBM_ISABRIDGE       0x000a
699    
700    PCIINIT(ibm_isa)
701    {
702            PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_IBM,
703                PCI_PRODUCT_IBM_ISABRIDGE));
704    
705            PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
706                PCI_SUBCLASS_BRIDGE_ISA, 0) + 0x02);
707    
708            PCI_SET_DATA(PCI_BHLC_REG,
709                PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
710    }
711    
712    
713    
714    /*
715     *  Heuricon PCI host bridge for PM/PPC.
716     */
717    
718    #define PCI_VENDOR_HEURICON             0x1223
719    #define PCI_PRODUCT_HEURICON_PMPPC      0x000e
720    
721    PCIINIT(heuricon_pmppc)
722    {
723            PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_HEURICON,
724                PCI_PRODUCT_HEURICON_PMPPC));
725    
726            PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
727                PCI_SUBCLASS_BRIDGE_HOST, 0) + 0x00);   /*  Revision?  */
728    
729            PCI_SET_DATA(PCI_BHLC_REG,
730                PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
731    }
732    
733    
734    
735    /*
736     *  VIATECH VT82C586 devices:
737     *
738     *      vt82c586_isa    PCI->ISA bridge
739     *      vt82c586_ide    IDE controller
740     *
741     *  TODO:  This more or less just a dummy device, so far.
742     */
743    
744    #define PCI_VENDOR_VIATECH                0x1106  /* VIA Technologies */
745    #define PCI_PRODUCT_VIATECH_VT82C586_IDE  0x1571  /* VT82C586 (Apollo VP)
746                                                         IDE Controller */
747    #define PCI_PRODUCT_VIATECH_VT82C586_ISA  0x0586  /* VT82C586 (Apollo VP)
748                                                         PCI-ISA Bridge */
749    
750    PCIINIT(vt82c586_isa)
751    {
752            PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_VIATECH,
753                PCI_PRODUCT_VIATECH_VT82C586_ISA));
754    
755            PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
756                PCI_SUBCLASS_BRIDGE_ISA, 0) + 0x39);   /*  Revision 37 or 39  */
757    
758            PCI_SET_DATA(PCI_BHLC_REG,
759                PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
760    }
761    
762    PCIINIT(vt82c586_ide)
763    {
764            char tmpstr[100];
765    
766            PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_VIATECH,
767                PCI_PRODUCT_VIATECH_VT82C586_IDE));
768    
769            /*  Possibly not correct:  */
770            PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_MASS_STORAGE,
771                PCI_SUBCLASS_MASS_STORAGE_IDE, 0x00) + 0x01);
772    
773            /*  APO_IDECONF  */
774            /*  channel 0 and 1 enabled  */
775            PCI_SET_DATA(0x40, 0x00000003);
776    
777            if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||
778                diskimage_exist(machine, 1, DISKIMAGE_IDE)) {
779                    snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i",
780                        (long long)(pd->pcibus->isa_portbase + 0x1f0),
781                        pd->pcibus->isa_irqbase + 14);
782                    device_add(machine, tmpstr);
783            }
784    
785            if (diskimage_exist(machine, 2, DISKIMAGE_IDE) ||
786                diskimage_exist(machine, 3, DISKIMAGE_IDE)) {
787                    snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i",
788                        (long long)(pd->pcibus->isa_portbase + 0x170),
789                        pd->pcibus->isa_irqbase + 15);
790                    device_add(machine, tmpstr);
791            }
792    }
793    
794    
795    
796    /*
797     *  Symphony Labs 83C553 PCI->ISA bridge.
798     *  Symphony Labs 82C105 PCIIDE controller.
799     */
800    
801    #define PCI_VENDOR_SYMPHONY             0x10ad
802    #define PCI_PRODUCT_SYMPHONY_83C553     0x0565
803    #define PCI_PRODUCT_SYMPHONY_82C105     0x0105
804    
805    PCIINIT(symphony_83c553)
806    {
807            PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_SYMPHONY,
808                PCI_PRODUCT_SYMPHONY_83C553));
809    
810            PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
811                PCI_SUBCLASS_BRIDGE_ISA, 0) + 0x10);
812    
813            PCI_SET_DATA(PCI_BHLC_REG,
814                PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
815    }
816    
817    PCIINIT(symphony_82c105)
818    {
819            char tmpstr[100];
820    
821            PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_SYMPHONY,
822                PCI_PRODUCT_SYMPHONY_82C105));
823    
824            /*  Possibly not correct:  */
825            PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_MASS_STORAGE,
826                PCI_SUBCLASS_MASS_STORAGE_IDE, 0x00) + 0x05);
827    
828            /*  APO_IDECONF  */
829            /*  channel 0 and 1 enabled  */
830            PCI_SET_DATA(0x40, 0x00000003);
831    
832            if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||
833                diskimage_exist(machine, 1, DISKIMAGE_IDE)) {
834                    snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i",
835                        (long long)(pd->pcibus->isa_portbase + 0x1f0),
836                        pd->pcibus->isa_irqbase + 14);
837                    device_add(machine, tmpstr);
838            }
839    
840            if (diskimage_exist(machine, 2, DISKIMAGE_IDE) ||
841                diskimage_exist(machine, 3, DISKIMAGE_IDE)) {
842                    snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i",
843                        (long long)(pd->pcibus->isa_portbase + 0x170),
844                        pd->pcibus->isa_irqbase + 15);
845                    device_add(machine, tmpstr);
846            }
847    }
848    
849    
850    
851    /*
852     *  DEC 21143 ("Tulip") PCI ethernet.
853     */
854    
855    #define PCI_VENDOR_DEC          0x1011 /* Digital Equipment */
856    #define PCI_PRODUCT_DEC_21142   0x0019 /* DECchip 21142/21143 10/100 Ethernet */
857    
858    PCIINIT(dec21143)
859    {
860            uint64_t port, memaddr;
861            int irq = 0;            /*  TODO  */
862            int int_line = 1;       /*  TODO  */
863            char tmpstr[200];
864    
865            PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_DEC,
866                PCI_PRODUCT_DEC_21142));
867    
868            PCI_SET_DATA(PCI_COMMAND_STATUS_REG, 0x02000017);
869    
870            PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_NETWORK,
871                PCI_SUBCLASS_NETWORK_ETHERNET, 0x00) + 0x41);
872    
873            PCI_SET_DATA(PCI_BHLC_REG, PCI_BHLC_CODE(0,0,0, 0x40,0));
874    
875            switch (machine->machine_type) {
876            case MACHINE_CATS:
877                    irq = 18;
878                    int_line = 1;
879                    break;
880            case MACHINE_PREP:
881                    int_line = 0xa;
882                    irq = 31 - int_line;
883                    break;
884            case MACHINE_PMPPC:
885                    irq = 31 - 21;
886                    break;
887            }
888    
889            PCI_SET_DATA(PCI_INTERRUPT_REG, 0x28140100 | int_line);
890    
891            allocate_device_space(pd, 0x100, 0x100, &port, &memaddr);
892    
893            snprintf(tmpstr, sizeof(tmpstr), "dec21143 addr=0x%llx addr2=0x%llx "
894                "irq=%i pci_little_endian=1", (long long)port, (long long)memaddr,
895                irq);
896            device_add(machine, tmpstr);
897    }
898    
899    
900    
901    /*
902     *  DEC 21030 "tga" graphics.
903     */
904    
905    #define PCI_PRODUCT_DEC_21030  0x0004          /*  DECchip 21030 ("TGA")  */
906    
907    PCIINIT(dec21030)
908    {
909            uint64_t base = 0;
910            char tmpstr[200];
911    
912            PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_DEC,
913                PCI_PRODUCT_DEC_21030));
914    
915            PCI_SET_DATA(PCI_COMMAND_STATUS_REG, 0x02800087);  /*  TODO  */
916    
917            PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_DISPLAY,
918                PCI_SUBCLASS_DISPLAY_VGA, 0x00) + 0x03);
919    
920            /*
921             *  See http://mail-index.netbsd.org/port-arc/2001/08/13/0000.html
922             *  for more info.
923             */
924    
925            PCI_SET_DATA(PCI_BHLC_REG, 0x0000ff00);
926    
927            /*  8 = prefetchable  */
928            PCI_SET_DATA(0x10, 0x00000008);
929            PCI_SET_DATA(0x30, 0x08000001);
930            PCI_SET_DATA(PCI_INTERRUPT_REG, 0x00000100);    /*  interrupt pin A?  */
931    
932            /*
933             *  Experimental:
934             *
935             *  TODO: Base address, pci_little_endian, ...
936             */
937    
938            switch (machine->machine_type) {
939            case MACHINE_ARC:
940                    base = 0x100000000ULL;
941                    break;
942            default:fatal("dec21030 in non-implemented machine type %i\n",
943                        machine->machine_type);
944                    exit(1);
945            }
946    
947            snprintf(tmpstr, sizeof(tmpstr), "dec21030 addr=0x%llx",
948                (long long)(base));
949            device_add(machine, tmpstr);
950    }
951    
952    
953    /*
954     *  Motorola MPC105 "Eagle" Host Bridge
955     *
956     *  Used in at least PReP and BeBox.
957     */
958    
959    #define PCI_VENDOR_MOT                  0x1057
960    #define PCI_PRODUCT_MOT_MPC105          0x0001
961    
962    PCIINIT(eagle)
963    {
964            PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_MOT,
965                PCI_PRODUCT_MOT_MPC105));
966    
967            PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
968                PCI_SUBCLASS_BRIDGE_HOST, 0) + 0x24);
969    
970            PCI_SET_DATA(PCI_BHLC_REG,
971                PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
972    }
973    

Legend:
Removed from v.19  
changed lines
  Added in v.20

  ViewVC Help
Powered by ViewVC 1.1.26