/[gxemul]/trunk/src/devices/bus_pci.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

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

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

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

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

  ViewVC Help
Powered by ViewVC 1.1.26