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

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

  ViewVC Help
Powered by ViewVC 1.1.26