/[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 20 by dpavlin, Mon Oct 8 16:19:23 2007 UTC revision 30 by dpavlin, Mon Oct 8 16:20:40 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   *  Copyright (C) 2004-2005  Anders Gavare.  All rights reserved.   *  Copyright (C) 2004-2006  Anders Gavare.  All rights reserved.
3   *   *
4   *  Redistribution and use in source and binary forms, with or without   *  Redistribution and use in source and binary forms, with or without
5   *  modification, are permitted provided that the following conditions are met:   *  modification, are permitted provided that the following conditions are met:
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *     *  
27   *   *
28   *  $Id: bus_pci.c,v 1.40 2005/11/25 03:59:58 debug Exp $   *  $Id: bus_pci.c,v 1.70 2006/08/12 19:38:24 debug Exp $
29   *     *  
30   *  Generic PCI bus framework. This is not a normal "device", but is used by   *  Generic PCI bus framework. This is not a normal "device", but is used by
31   *  individual PCI controllers and devices.   *  individual PCI controllers and devices.
# Line 57  Line 57 
57  #include "memory.h"  #include "memory.h"
58  #include "misc.h"  #include "misc.h"
59    
60    #include "wdc.h"
61    
62  extern int verbose;  extern int verbose;
63    
64    
65  /*  #define debug fatal  */  #ifdef UNSTABLE_DEVEL
66    #define debug fatal
67    #endif
68    
69    
70  static void reverse(uint64_t *p, int len)  /*
71     *  bus_pci_decompose_1():
72     *
73     *  Helper function for decomposing Mechanism 1 tags.
74     */
75    void bus_pci_decompose_1(uint32_t t, int *bus, int *dev, int *func, int *reg)
76  {  {
77          uint64_t x = *p, y = 0;          *bus  = (t >> 16) & 0xff;
78          int i;          *dev  = (t >> 11) & 0x1f;
79          for (i=0; i<len; i++) {          *func = (t >>  8) &  0x7;
80                  y <<= 8;          *reg  =  t        & 0xff;
81                  y |= ((x >> (8*i)) & 0xff);  
82          }          /*  Warn about unaligned register access:  */
83          *p = y;          if (t & 3)
84                    fatal("[ bus_pci_decompose_1: WARNING: reg = 0x%02x ]\n",
85                        t & 0xff);
86  }  }
87    
88    
89  /*  /*
90   *  bus_pci_data_access():   *  bus_pci_data_access():
91   *   *
92   *  Reads from and writes to the PCI configuration registers of a device.   *  Reads from or writes to the PCI configuration registers of a device.
93   */   */
94  void bus_pci_data_access(struct cpu *cpu, struct memory *mem,  void bus_pci_data_access(struct cpu *cpu, struct pci_data *pci_data,
95          uint64_t *data, int len, int writeflag, struct pci_data *pci_data)          uint64_t *data, int len, int writeflag)
96  {  {
97          struct pci_device *dev;          struct pci_device *dev;
         int bus, device, function, registernr;  
98          unsigned char *cfg_base;          unsigned char *cfg_base;
99          uint64_t x, idata = *data;          uint64_t x, idata = *data;
100            int i;
         if (cpu->byte_order == EMUL_BIG_ENDIAN)  
                 reverse(&idata, len);  
   
         /*  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;  
101    
102          /*  Scan through the list of pci_device entries.  */          /*  Scan through the list of pci_device entries.  */
103          dev = pci_data->first_device;          dev = pci_data->first_device;
104          while (dev != NULL) {          while (dev != NULL) {
105                  if (dev->bus == bus && dev->function == function &&                  if (dev->bus      == pci_data->cur_bus &&
106                      dev->device == device)                      dev->function == pci_data->cur_func &&
107                        dev->device   == pci_data->cur_device)
108                          break;                          break;
109                  dev = dev->next;                  dev = dev->next;
110          }          }
111    
112          /*  No device? Then return emptiness.  */          /*  No device? Then return emptiness.  */
113          if (dev == NULL) {          if (dev == NULL) {
114                  if ((pci_data->pci_addr & 0xff) == 0)                  if (writeflag == MEM_READ) {
115                          *data = 0xffffffff;                          if (pci_data->cur_reg == 0)
116                  else                                  *data = -1;
117                          *data = 0;                          else
118                                    *data = 0;
119                    } else {
120                            fatal("[ bus_pci_data_access(): write to non-existant"
121                                " device? ]\n");
122                    }
123                  return;                  return;
124          }          }
125    
126          /*  Return normal config data, or length data?  */          /*  Return normal config data, or length data?  */
127          if (pci_data->last_was_write_ffffffff &&          if (pci_data->last_was_write_ffffffff &&
128              registernr >= PCI_MAPREG_START && registernr <= PCI_MAPREG_END - 4)              pci_data->cur_reg >= PCI_MAPREG_START &&
129                pci_data->cur_reg <= PCI_MAPREG_END - 4)
130                  cfg_base = dev->cfg_mem_size;                  cfg_base = dev->cfg_mem_size;
131          else          else
132                  cfg_base = dev->cfg_mem;                  cfg_base = dev->cfg_mem;
133    
134          /*  Read data as little-endian:  */          /*  Read data as little-endian:  */
135          x = 0;          x = 0;
136          if (registernr + len - 1 < PCI_CFG_MEM_SIZE) {          for (i=len-1; i>=0; i--) {
137                  x = cfg_base[registernr];                  int ofs = pci_data->cur_reg + i;
138                  if (len > 1)                  x <<= 8;
139                          x |= (cfg_base[registernr+1] << 8);                  x |= cfg_base[ofs & (PCI_CFG_MEM_SIZE - 1)];
                 if (len > 2)  
                         x |= (cfg_base[registernr+2] << 16);  
                 if (len > 3)  
                         x |= ((uint64_t)cfg_base[registernr+3] << 24);  
                 if (len > 4)  
                         fatal("TODO: more than 32-bit PCI access?\n");  
140          }          }
141    
142          /*  Register write:  */          /*  Register write:  */
143          if (writeflag == MEM_WRITE) {          if (writeflag == MEM_WRITE) {
144                  debug("[ bus_pci: write to PCI DATA: data = 0x%016llx ]\n",                  debug("[ bus_pci: write to PCI DATA: data = 0x%08llx ]\n",
145                      (long long)idata);                      (long long)idata);
146                  if (idata == 0xffffffffULL && registernr >= PCI_MAPREG_START                  if (idata == 0xffffffffULL &&
147                      && registernr <= PCI_MAPREG_END - 4) {                      pci_data->cur_reg >= PCI_MAPREG_START &&
148                        pci_data->cur_reg <= PCI_MAPREG_END - 4) {
149                          pci_data->last_was_write_ffffffff = 1;                          pci_data->last_was_write_ffffffff = 1;
150                          return;                          return;
151                  }                  }
152                  /*  Writes are not really supported yet:  */  
153                  if (idata != x) {                  if (dev->cfg_reg_write != NULL) {
154                            dev->cfg_reg_write(dev, pci_data->cur_reg, *data);
155                    } else {
156                            /*  Print a warning for unhandled writes:  */
157                          debug("[ bus_pci: write to PCI DATA: data = 0x%08llx"                          debug("[ bus_pci: write to PCI DATA: data = 0x%08llx"
158                              " differs from current value 0x%08llx; NOT YET"                              " (current value = 0x%08llx); NOT YET"
159                              " SUPPORTED. bus %i, device %i, function %i (%s)"                              " SUPPORTED. bus %i, device %i, function %i (%s)"
160                              " register 0x%02x ]\n", (long long)idata,                              " register 0x%02x ]\n", (long long)idata,
161                              (long long)x, bus, device, function, dev->name,                              (long long)x, pci_data->cur_bus,
162                              registernr);                              pci_data->cur_device, pci_data->cur_func,
163                                dev->name, pci_data->cur_reg);
164    
165                            /*  Special warning, to detect if NetBSD's special
166                                detection of PCI devices fails:  */
167                            if (pci_data->cur_reg == PCI_COMMAND_STATUS_REG
168                                && !((*data) & PCI_COMMAND_IO_ENABLE)) {
169                                    fatal("\n[ NetBSD PCI detection stuff not"
170                                        " yet implemented for device '%s' ]\n",
171                                        dev->name);
172                            }
173                  }                  }
174                  return;                  return;
175          }          }
176    
177          /*  Register read:  */          /*  Register read:  */
         if (cpu->byte_order == EMUL_BIG_ENDIAN)  
                 reverse(&x, len);  
178          *data = x;          *data = x;
179    
180          pci_data->last_was_write_ffffffff = 0;          pci_data->last_was_write_ffffffff = 0;
181    
182          debug("[ bus_pci: read from PCI DATA, addr = 0x%08lx (bus %i, device "          debug("[ bus_pci: read from PCI DATA, bus %i, device "
183              "%i, function %i (%s) register 0x%02x): 0x%08lx ]\n", (long)              "%i, function %i (%s) register 0x%02x: (len=%i) 0x%08lx ]\n",
184              pci_data->pci_addr, bus, device, function, dev->name,              pci_data->cur_bus, pci_data->cur_device, pci_data->cur_func,
185              registernr, (long)*data);              dev->name, pci_data->cur_reg, len, (long)*data);
186  }  }
187    
188    
189  /*  /*
190   *  bus_pci_access():   *  bus_pci_setaddr():
191   *   *
192   *  relative_addr should be either BUS_PCI_ADDR or BUS_PCI_DATA. The uint64_t   *  Sets the address in preparation for a PCI register transfer.
  *  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.  
193   */   */
194  int bus_pci_access(struct cpu *cpu, struct memory *mem, uint64_t relative_addr,  void bus_pci_setaddr(struct cpu *cpu, struct pci_data *pci_data,
195          uint64_t *data, int len, int writeflag, struct pci_data *pci_data)          int bus, int device, int function, int reg)
196  {  {
197          if (writeflag == MEM_READ)          if (cpu == NULL || pci_data == NULL) {
198                  *data = 0;                  fatal("bus_pci_setaddr(): NULL ptr\n");
199                    exit(1);
         switch (relative_addr) {  
   
         case BUS_PCI_ADDR:  
                 if (writeflag == MEM_WRITE) {  
                         debug("[ bus_pci: write to PCI ADDR: data = 0x%016llx"  
                             " ]\n", (long long)*data);  
                         pci_data->pci_addr = *data;  
   
                         /*  
                          *  Big-endian systems (e.g. PowerPC) seem to access  
                          *  PCI config data using little-endian accesses.  
                          */  
                         if (cpu->byte_order == EMUL_BIG_ENDIAN) {  
                                 uint32_t t = pci_data->pci_addr;  
                                 pci_data->pci_addr = ((t >> 24) & 255)  
                                     | ((t >> 8) & 0xff00)  
                                     | ((t << 8) & 0xff0000)  
                                     | ((t << 24) & 0xff000000);  
                         }  
   
                         /*  Linux seems to use type 0 even when it does  
                             type 1 detection. Hm. This is commented for now.  */  
                         /*  if (pci_data->pci_addr & 1)  
                                 fatal("[ bus_pci: WARNING! pci type 0 not"  
                                     " yet implemented! ]\n");  */  
                 } else {  
                         debug("[ bus_pci: read from PCI ADDR (data = "  
                             "0x%016llx) ]\n", (long long)pci_data->pci_addr);  
                         *data = pci_data->pci_addr;  
                 }  
                 break;  
   
         case BUS_PCI_DATA:  
                 bus_pci_data_access(cpu, mem, data, len, writeflag, pci_data);  
                 break;  
   
         default:if (writeflag == MEM_READ) {  
                         debug("[ bus_pci: read from unimplemented addr "  
                             "0x%x ]\n", (int)relative_addr);  
                         *data = 0;  
                 } else {  
                         debug("[ bus_pci: write to unimplemented addr "  
                             "0x%x: 0x%llx ]\n", (int)relative_addr,  
                             (long long)*data);  
                 }  
200          }          }
201    
202          return 1;          pci_data->cur_bus = bus;
203            pci_data->cur_device = device;
204            pci_data->cur_func = function;
205            pci_data->cur_reg = reg;
206  }  }
207    
208    
# Line 244  int bus_pci_access(struct cpu *cpu, stru Line 213  int bus_pci_access(struct cpu *cpu, stru
213   */   */
214  void bus_pci_add(struct machine *machine, struct pci_data *pci_data,  void bus_pci_add(struct machine *machine, struct pci_data *pci_data,
215          struct memory *mem, int bus, int device, int function,          struct memory *mem, int bus, int device, int function,
216          char *name)          const char *name)
217  {  {
218          struct pci_device *pd;          struct pci_device *pd;
219          int ofs;          int ofs;
# Line 291  void bus_pci_add(struct machine *machine Line 260  void bus_pci_add(struct machine *machine
260          /*          /*
261           *  Initialize with some default values:           *  Initialize with some default values:
262           *           *
263           *  TODO:  The command status register is best to set up per device,           *  TODO:  The command status register is best to set up per device.
264           *         just enabling all bits like this is not really good.           *  The size registers should also be set up on a per-device basis.
          *         The size registers should also be set up on a per-device  
          *         basis.  
265           */           */
266          PCI_SET_DATA(PCI_COMMAND_STATUS_REG, 0x00ffffffULL);          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)          for (ofs = PCI_MAPREG_START; ofs < PCI_MAPREG_END; ofs += 4)
269                  PCI_SET_DATA_SIZE(ofs, 0x00400000 - 1);                  PCI_SET_DATA_SIZE(ofs, 0x00100000 - 1);
270    
271          if (init == NULL) {          if (init == NULL) {
272                  fatal("No init function for PCI device \"%s\"?\n", name);                  fatal("No init function for PCI device \"%s\"?\n", name);
# Line 331  static void allocate_device_space(struct Line 299  static void allocate_device_space(struct
299          if (portsize != 0) {          if (portsize != 0) {
300                  port = ((port - 1) | (portsize - 1)) + 1;                  port = ((port - 1) | (portsize - 1)) + 1;
301                  pd->pcibus->cur_pci_portbase = port;                  pd->pcibus->cur_pci_portbase = port;
302                  PCI_SET_DATA(PCI_MAPREG_START, port | PCI_MAPREG_TYPE_IO);                  PCI_SET_DATA(PCI_MAPREG_START + pd->cur_mapreg_offset,
303                  PCI_SET_DATA_SIZE(PCI_MAPREG_START, portsize - 1);                      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:  */          /*  Calculate an aligned starting memory location:  */
# Line 340  static void allocate_device_space(struct Line 311  static void allocate_device_space(struct
311          if (memsize != 0) {          if (memsize != 0) {
312                  mem = ((mem - 1) | (memsize - 1)) + 1;                  mem = ((mem - 1) | (memsize - 1)) + 1;
313                  pd->pcibus->cur_pci_membase = mem;                  pd->pcibus->cur_pci_membase = mem;
314                  PCI_SET_DATA(PCI_MAPREG_START + 0x04, mem);                  PCI_SET_DATA(PCI_MAPREG_START + pd->cur_mapreg_offset, mem);
315                  PCI_SET_DATA_SIZE(PCI_MAPREG_START + 0x04, memsize - 1);                  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;          *portp = port + pd->pcibus->pci_actual_io_offset;
# Line 365  static void allocate_device_space(struct Line 338  static void allocate_device_space(struct
338  }  }
339    
340    
341    static void bus_pci_debug_dump__2(struct pci_device *pd)
342    {
343            if (pd == NULL)
344                    return;
345            bus_pci_debug_dump__2(pd->next);
346            debug("bus %3i, dev %2i, func %i: %s\n",
347                pd->bus, pd->device, pd->function, pd->name);
348    }
349    
350    
351    /*
352     *  bus_pci_debug_dump():
353     *
354     *  Lists the attached PCI devices (in reverse).
355     */
356    void bus_pci_debug_dump(void *extra)
357    {
358            struct pci_data *d = (struct pci_data *) extra;
359            int iadd = DEBUG_INDENTATION;
360    
361            debug("pci:\n");
362            debug_indentation(iadd);
363    
364            if (d->first_device == NULL)
365                    debug("no devices!\n");
366            else
367                    bus_pci_debug_dump__2(d->first_device);
368    
369            debug_indentation(-iadd);
370    }
371    
372    
373  /*  /*
374   *  bus_pci_init():   *  bus_pci_init():
375   *   *
376   *  This doesn't register a device, but instead returns a pointer to a struct   *  This doesn't register a device, but instead returns a pointer to a struct
377   *  which should be passed to bus_pci_access() when accessing the PCI bus.   *  which should be passed to other bus_pci functions when accessing the bus.
378   *   *
379   *  irq_nr is the (optional) IRQ nr that this PCI bus interrupts at.   *  irq_nr is the (optional) IRQ nr that this PCI bus interrupts at.
380   *   *
# Line 382  static void allocate_device_space(struct Line 387  static void allocate_device_space(struct
387   *  isa_portbase, isa_membase, and isa_irqbase are the port, memory, and   *  isa_portbase, isa_membase, and isa_irqbase are the port, memory, and
388   *  interrupt bases for legacy ISA devices.   *  interrupt bases for legacy ISA devices.
389   */   */
390  struct pci_data *bus_pci_init(int irq_nr,  struct pci_data *bus_pci_init(struct machine *machine, int irq_nr,
391          uint64_t pci_actual_io_offset, uint64_t pci_actual_mem_offset,          uint64_t pci_actual_io_offset, uint64_t pci_actual_mem_offset,
392          uint64_t pci_portbase, uint64_t pci_membase, int pci_irqbase,          uint64_t pci_portbase, uint64_t pci_membase, int pci_irqbase,
393          uint64_t isa_portbase, uint64_t isa_membase, int isa_irqbase)          uint64_t isa_portbase, uint64_t isa_membase, int isa_irqbase)
# Line 405  struct pci_data *bus_pci_init(int irq_nr Line 410  struct pci_data *bus_pci_init(int irq_nr
410          d->isa_membase           = isa_membase;          d->isa_membase           = isa_membase;
411          d->isa_irqbase           = isa_irqbase;          d->isa_irqbase           = isa_irqbase;
412    
413            /*  Register the bus:  */
414            machine_bus_register(machine, "pci", bus_pci_debug_dump, d);
415    
416          /*  Assume that the first 64KB could be used by legacy ISA devices:  */          /*  Assume that the first 64KB could be used by legacy ISA devices:  */
417          d->cur_pci_portbase = d->pci_portbase + 0x10000;          d->cur_pci_portbase = d->pci_portbase + 0x10000;
418          d->cur_pci_membase  = d->pci_membase + 0x10000;          d->cur_pci_membase  = d->pci_membase + 0x10000;
# Line 415  struct pci_data *bus_pci_init(int irq_nr Line 423  struct pci_data *bus_pci_init(int irq_nr
423    
424    
425  /******************************************************************************  /******************************************************************************
426   *   *                                                                            *
427   *  The following is glue code for PCI controllers and devices. The glue code   *  The following is glue code for PCI controllers and devices. The glue      *
428   *  does the minimal stuff necessary to get an emulated OS to detect the   *  code does the minimal stuff necessary to get an emulated OS to detect     *
429   *  device (i.e. set up PCI configuration registers), and then if necessary   *  the device (i.e. set up PCI configuration registers), and then if         *
430   *  add a "normal" device.   *  necessary adds a "normal" device.                                         *
431   *   *                                                                            *
432   ******************************************************************************/   ******************************************************************************/
433    
434    
435    
436  /*  /*
437   *  Integraphics Systems "igsfb" Framebuffer (graphics) card.   *  Integraphics Systems "igsfb" Framebuffer (graphics) card, used in at
438   *   *  least the NetWinder.
  *  TODO  
439   */   */
440    
441  #define PCI_VENDOR_INTEGRAPHICS         0x10ea  #define PCI_VENDOR_INTEGRAPHICS         0x10ea
442    
443  PCIINIT(igsfb)  PCIINIT(igsfb)
444  {  {
445            char tmpstr[200];
446    
447          PCI_SET_DATA(PCI_ID_REG,          PCI_SET_DATA(PCI_ID_REG,
448              PCI_ID_CODE(PCI_VENDOR_INTEGRAPHICS, 0x2010));              PCI_ID_CODE(PCI_VENDOR_INTEGRAPHICS, 0x2010));
449    
# Line 443  PCIINIT(igsfb) Line 452  PCIINIT(igsfb)
452              PCI_SUBCLASS_DISPLAY_VGA, 0) + 0x01);              PCI_SUBCLASS_DISPLAY_VGA, 0) + 0x01);
453    
454          /*  TODO  */          /*  TODO  */
455          PCI_SET_DATA(0x10, 0xb0000000);          PCI_SET_DATA(0x10, 0x08000000);
456    
457          /*  TODO: This is just a dummy so far.  */          snprintf(tmpstr, sizeof(tmpstr), "igsfb addr=0x%llx",
458                (long long)(pd->pcibus->isa_membase + 0x08000000));
459            device_add(machine, tmpstr);
460  }  }
461    
462    
# Line 594  PCIINIT(ahc) Line 605  PCIINIT(ahc)
605  #define PCI_VENDOR_GALILEO           0x11ab    /* Galileo Technology */  #define PCI_VENDOR_GALILEO           0x11ab    /* Galileo Technology */
606  #define PCI_PRODUCT_GALILEO_GT64011  0x4146    /* GT-64011 System Controller */  #define PCI_PRODUCT_GALILEO_GT64011  0x4146    /* GT-64011 System Controller */
607  #define PCI_PRODUCT_GALILEO_GT64120  0x4620    /* GT-64120 */  #define PCI_PRODUCT_GALILEO_GT64120  0x4620    /* GT-64120 */
608    #define PCI_PRODUCT_GALILEO_GT64260  0x6430    /* GT-64260 */
609    
610  PCIINIT(gt64011)  PCIINIT(gt64011)
611  {  {
612          PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_GALILEO,          PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_GALILEO,
613              PCI_PRODUCT_GALILEO_GT64011));              PCI_PRODUCT_GALILEO_GT64011));
614    
615          PCI_SET_DATA(PCI_CLASS_REG,          PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
             PCI_CLASS_CODE(PCI_CLASS_BRIDGE,  
616              PCI_SUBCLASS_BRIDGE_HOST, 0) + 0x01);       /*  Revision 1  */              PCI_SUBCLASS_BRIDGE_HOST, 0) + 0x01);       /*  Revision 1  */
617  }  }
618    
# Line 620  PCIINIT(gt64120) Line 631  PCIINIT(gt64120)
631          }          }
632  }  }
633    
634    PCIINIT(gt64260)
635    {
636            PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_GALILEO,
637                PCI_PRODUCT_GALILEO_GT64260));
638    
639            PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
640                PCI_SUBCLASS_BRIDGE_HOST, 0) + 0x01);       /*  Revision 1?  */
641    }
642    
643    
644    
645    /*
646     *  AMD PCnet Ethernet card.
647     *
648     *  "Am79c970A PCnet-PCI II rev 0" or similar.
649     */
650    
651    #define PCI_VENDOR_AMD                  0x1022  /* Advanced Micro Devices */
652    #define PCI_PRODUCT_AMD_PCNET_PCI       0x2000  /* PCnet-PCI Ethernet */
653    
654    PCIINIT(pcn)
655    {
656            int irq;
657    
658            PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_AMD,
659                PCI_PRODUCT_AMD_PCNET_PCI));
660    
661            PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_NETWORK,
662                PCI_SUBCLASS_NETWORK_ETHERNET, 0) + 0x00);  /*  Revision 0  */
663    
664            switch (machine->machine_type) {
665    
666            case MACHINE_EVBMIPS:
667                    irq = (1 << 8) + 10;    /*  TODO  */
668                    break;
669    
670            default:fatal("pcn in non-implemented machine type %i\n",
671                        machine->machine_type);
672                    exit(1);
673            }
674    
675            PCI_SET_DATA(PCI_INTERRUPT_REG, 0x01100000 | irq);
676    
677            /*
678             *  TODO: Add the pcn device here. The pcn device will need to work as
679             *  a wrapper for dev_le + all the DMA magic and whatever is required.
680             *  It's too much to implement right now.
681             */
682    }
683    
684    
685    
686  /*  /*
687   *  Intel 82371AB PIIX4 PCI-ISA bridge and IDE controller   *  Intel 31244   Serial ATA Controller
688   *  and 82378ZB System I/O controller.   *  Intel 82371SB PIIX3 PCI-ISA bridge
689     *  Intel 82371AB PIIX4 PCI-ISA bridge
690     *  Intel 82371SB IDE controller
691     *  Intel 82371AB IDE controller
692     *  Intel 82378ZB System I/O controller.
693   */   */
694    
695  #define PCI_VENDOR_INTEL                0x8086  #define PCI_VENDOR_INTEL                0x8086
696    #define PCI_PRODUCT_INTEL_31244         0x3200
697    #define PCI_PRODUCT_INTEL_82371SB_ISA   0x7000
698    #define PCI_PRODUCT_INTEL_82371SB_IDE   0x7010
699  #define PCI_PRODUCT_INTEL_82371AB_ISA   0x7110  #define PCI_PRODUCT_INTEL_82371AB_ISA   0x7110
700  #define PCI_PRODUCT_INTEL_82371AB_IDE   0x7111  #define PCI_PRODUCT_INTEL_82371AB_IDE   0x7111
701  #define PCI_PRODUCT_INTEL_SIO           0x0484  #define PCI_PRODUCT_INTEL_SIO           0x0484
702    
703  PCIINIT(i82371ab_isa)  PCIINIT(i31244)
704    {
705            uint64_t port, memaddr;
706            int irq = 0;
707    
708            PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_INTEL,
709                PCI_PRODUCT_INTEL_31244));
710    
711            PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_MASS_STORAGE,
712                PCI_SUBCLASS_MASS_STORAGE_IDE, 0x33) + 0x00);
713    
714            switch (machine->machine_type) {
715            case MACHINE_IQ80321:
716                    /*  S-PCI-X slot uses PCI IRQ A, int 29  */
717                    irq = (1 << 8) + 29;
718                    break;
719            default:fatal("i31244 in non-implemented machine type %i\n",
720                        machine->machine_type);
721                    exit(1);
722            }
723    
724            PCI_SET_DATA(PCI_INTERRUPT_REG, 0x01100000 | irq);
725    
726            allocate_device_space(pd, 0x1000, 0, &port, &memaddr);
727            allocate_device_space(pd, 0x1000, 0, &port, &memaddr);
728    
729            /*  PCI IDE using dev_wdc:  */
730            if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||
731                diskimage_exist(machine, 1, DISKIMAGE_IDE)) {
732                    char tmpstr[150];
733                    snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i",
734                        (long long)(pd->pcibus->pci_actual_io_offset + 0),
735                        pd->pcibus->pci_irqbase + 0);
736                    device_add(machine, tmpstr);
737            }
738    }
739    
740    PCIINIT(piix3_isa)
741    {
742            PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_INTEL,
743                PCI_PRODUCT_INTEL_82371SB_ISA));
744    
745            PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
746                PCI_SUBCLASS_BRIDGE_ISA, 0) + 0x01);        /*  Rev 1  */
747    
748            PCI_SET_DATA(PCI_BHLC_REG,
749                PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
750    }
751    
752    PCIINIT(piix4_isa)
753  {  {
754          PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_INTEL,          PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_INTEL,
755              PCI_PRODUCT_INTEL_82371AB_ISA));              PCI_PRODUCT_INTEL_82371AB_ISA));
# Line 654  PCIINIT(i82378zb) Line 771  PCIINIT(i82378zb)
771    
772          PCI_SET_DATA(PCI_BHLC_REG,          PCI_SET_DATA(PCI_BHLC_REG,
773              PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));              PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
774    
775            PCI_SET_DATA(0x40, 0x20);
776    
777            /*  PIRQ[0]=10 PIRQ[1]=11 PIRQ[2]=14 PIRQ[3]=15  */
778            PCI_SET_DATA(0x60, 0x0f0e0b0a);
779    }
780    
781    struct piix_ide_extra {
782            void    *wdc0;
783            void    *wdc1;
784    };
785    
786    int piix_ide_cfg_reg_write(struct pci_device *pd, int reg, uint32_t value)
787    {
788            void *wdc0 = ((struct piix_ide_extra *)pd->extra)->wdc0;
789            void *wdc1 = ((struct piix_ide_extra *)pd->extra)->wdc1;
790            int enabled = 0;
791    
792            switch (reg) {
793            case PCI_COMMAND_STATUS_REG:
794                    if (value & PCI_COMMAND_IO_ENABLE)
795                            enabled = 1;
796                    if (wdc0 != NULL)
797                            wdc_set_io_enabled(wdc0, enabled);
798                    if (wdc1 != NULL)
799                            wdc_set_io_enabled(wdc1, enabled);
800                    return 1;
801            }
802    
803            return 0;
804    }
805    
806    PCIINIT(piix3_ide)
807    {
808            char tmpstr[100];
809    
810            PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_INTEL,
811                PCI_PRODUCT_INTEL_82371SB_IDE));
812    
813            /*  Possibly not correct:  */
814            PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_MASS_STORAGE,
815                PCI_SUBCLASS_MASS_STORAGE_IDE, 0x00) + 0x00);
816    
817            /*  PIIX_IDETIM (see NetBSD's pciide_piix_reg.h)  */
818            /*  channel 0 and 1 enabled as IDE  */
819            PCI_SET_DATA(0x40, 0x80008000);
820    
821            pd->extra = malloc(sizeof(struct piix_ide_extra));
822            if (pd->extra == NULL) {
823                    fatal("Out of memory.\n");
824                    exit(1);
825            }
826            ((struct piix_ide_extra *)pd->extra)->wdc0 = NULL;
827            ((struct piix_ide_extra *)pd->extra)->wdc1 = NULL;
828    
829            if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||
830                diskimage_exist(machine, 1, DISKIMAGE_IDE)) {
831                    snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i",
832                        (long long)(pd->pcibus->isa_portbase + 0x1f0),
833                        pd->pcibus->isa_irqbase + 14);
834                    ((struct piix_ide_extra *)pd->extra)->wdc0 =
835                        device_add(machine, tmpstr);
836            }
837    
838            if (diskimage_exist(machine, 2, DISKIMAGE_IDE) ||
839                diskimage_exist(machine, 3, DISKIMAGE_IDE)) {
840                    snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i",
841                        (long long)(pd->pcibus->isa_portbase + 0x170),
842                        pd->pcibus->isa_irqbase + 15);
843                    ((struct piix_ide_extra *)pd->extra)->wdc1 =
844                        device_add(machine, tmpstr);
845            }
846    
847            pd->cfg_reg_write = piix_ide_cfg_reg_write;
848  }  }
849    
850  PCIINIT(i82371ab_ide)  PCIINIT(piix4_ide)
851  {  {
852          char tmpstr[100];          char tmpstr[100];
853    
# Line 671  PCIINIT(i82371ab_ide) Line 862  PCIINIT(i82371ab_ide)
862          /*  channel 0 and 1 enabled as IDE  */          /*  channel 0 and 1 enabled as IDE  */
863          PCI_SET_DATA(0x40, 0x80008000);          PCI_SET_DATA(0x40, 0x80008000);
864    
865            pd->extra = malloc(sizeof(struct piix_ide_extra));
866            if (pd->extra == NULL) {
867                    fatal("Out of memory.\n");
868                    exit(1);
869            }
870            ((struct piix_ide_extra *)pd->extra)->wdc0 = NULL;
871            ((struct piix_ide_extra *)pd->extra)->wdc1 = NULL;
872    
873          if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||          if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||
874              diskimage_exist(machine, 1, DISKIMAGE_IDE)) {              diskimage_exist(machine, 1, DISKIMAGE_IDE)) {
875                  snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i",                  snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i",
876                      (long long)(pd->pcibus->isa_portbase + 0x1f0),                      (long long)(pd->pcibus->isa_portbase + 0x1f0),
877                      pd->pcibus->isa_irqbase + 14);                      pd->pcibus->isa_irqbase + 14);
878                  device_add(machine, tmpstr);                  ((struct piix_ide_extra *)pd->extra)->wdc0 =
879                        device_add(machine, tmpstr);
880          }          }
881    
882          if (diskimage_exist(machine, 2, DISKIMAGE_IDE) ||          if (diskimage_exist(machine, 2, DISKIMAGE_IDE) ||
# Line 684  PCIINIT(i82371ab_ide) Line 884  PCIINIT(i82371ab_ide)
884                  snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i",                  snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i",
885                      (long long)(pd->pcibus->isa_portbase + 0x170),                      (long long)(pd->pcibus->isa_portbase + 0x170),
886                      pd->pcibus->isa_irqbase + 15);                      pd->pcibus->isa_irqbase + 15);
887                  device_add(machine, tmpstr);                  ((struct piix_ide_extra *)pd->extra)->wdc1 =
888                        device_add(machine, tmpstr);
889          }          }
890    
891            pd->cfg_reg_write = piix_ide_cfg_reg_write;
892  }  }
893    
894    
# Line 759  PCIINIT(vt82c586_isa) Line 962  PCIINIT(vt82c586_isa)
962              PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));              PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
963  }  }
964    
965    struct vt82c586_ide_extra {
966            void    *wdc0;
967            void    *wdc1;
968    };
969    
970    int vt82c586_ide_cfg_reg_write(struct pci_device *pd, int reg, uint32_t value)
971    {
972            void *wdc0 = ((struct vt82c586_ide_extra *)pd->extra)->wdc0;
973            void *wdc1 = ((struct vt82c586_ide_extra *)pd->extra)->wdc1;
974            int enabled = 0;
975    
976            switch (reg) {
977            case PCI_COMMAND_STATUS_REG:
978                    if (value & PCI_COMMAND_IO_ENABLE)
979                            enabled = 1;
980                    if (wdc0 != NULL)
981                            wdc_set_io_enabled(wdc0, enabled);
982                    if (wdc1 != NULL)
983                            wdc_set_io_enabled(wdc1, enabled);
984                    return 1;
985            }
986    
987            return 0;
988    }
989    
990  PCIINIT(vt82c586_ide)  PCIINIT(vt82c586_ide)
991  {  {
992          char tmpstr[100];          char tmpstr[100];
# Line 774  PCIINIT(vt82c586_ide) Line 1002  PCIINIT(vt82c586_ide)
1002          /*  channel 0 and 1 enabled  */          /*  channel 0 and 1 enabled  */
1003          PCI_SET_DATA(0x40, 0x00000003);          PCI_SET_DATA(0x40, 0x00000003);
1004    
1005            pd->extra = malloc(sizeof(struct vt82c586_ide_extra));
1006            if (pd->extra == NULL) {
1007                    fatal("Out of memory.\n");
1008                    exit(1);
1009            }
1010            ((struct vt82c586_ide_extra *)pd->extra)->wdc0 = NULL;
1011            ((struct vt82c586_ide_extra *)pd->extra)->wdc1 = NULL;
1012    
1013          if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||          if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||
1014              diskimage_exist(machine, 1, DISKIMAGE_IDE)) {              diskimage_exist(machine, 1, DISKIMAGE_IDE)) {
1015                  snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i",                  snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i",
1016                      (long long)(pd->pcibus->isa_portbase + 0x1f0),                      (long long)(pd->pcibus->isa_portbase + 0x1f0),
1017                      pd->pcibus->isa_irqbase + 14);                      pd->pcibus->isa_irqbase + 14);
1018                  device_add(machine, tmpstr);                  ((struct vt82c586_ide_extra *)pd->extra)->wdc0 =
1019                        device_add(machine, tmpstr);
1020          }          }
1021    
1022          if (diskimage_exist(machine, 2, DISKIMAGE_IDE) ||          if (diskimage_exist(machine, 2, DISKIMAGE_IDE) ||
# Line 787  PCIINIT(vt82c586_ide) Line 1024  PCIINIT(vt82c586_ide)
1024                  snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i",                  snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i",
1025                      (long long)(pd->pcibus->isa_portbase + 0x170),                      (long long)(pd->pcibus->isa_portbase + 0x170),
1026                      pd->pcibus->isa_irqbase + 15);                      pd->pcibus->isa_irqbase + 15);
1027                  device_add(machine, tmpstr);                  ((struct vt82c586_ide_extra *)pd->extra)->wdc1 =
1028                        device_add(machine, tmpstr);
1029          }          }
1030    
1031            pd->cfg_reg_write = vt82c586_ide_cfg_reg_write;
1032  }  }
1033    
1034    
# Line 859  PCIINIT(dec21143) Line 1099  PCIINIT(dec21143)
1099  {  {
1100          uint64_t port, memaddr;          uint64_t port, memaddr;
1101          int irq = 0;            /*  TODO  */          int irq = 0;            /*  TODO  */
1102          int int_line = 1;       /*  TODO  */          int pci_int_line = 0x101;
1103          char tmpstr[200];          char tmpstr[200];
1104    
1105          PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_DEC,          PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_DEC,
# Line 874  PCIINIT(dec21143) Line 1114  PCIINIT(dec21143)
1114    
1115          switch (machine->machine_type) {          switch (machine->machine_type) {
1116          case MACHINE_CATS:          case MACHINE_CATS:
1117                    /*  CATS int 18 = PCI.  */
1118                  irq = 18;                  irq = 18;
1119                  int_line = 1;                  pci_int_line = 0x101;
1120                    break;
1121            case MACHINE_COBALT:
1122                    /*  On Cobalt, IRQ 7 = PCI.  */
1123                    irq = 8 + 7;
1124                    pci_int_line = 0x407;
1125                    break;
1126            case MACHINE_ALGOR:
1127                    /*  TODO  */
1128                    irq = 8 + 7;
1129                    pci_int_line = 0x407;
1130                  break;                  break;
1131          case MACHINE_PREP:          case MACHINE_PREP:
1132                  int_line = 0xa;                  irq = 32 + 10;
1133                  irq = 31 - int_line;                  pci_int_line = 0x20a;
1134                    break;
1135            case MACHINE_MVMEPPC:
1136                    /*  TODO  */
1137                    irq = 32 + 10;
1138                    pci_int_line = 0x40a;
1139                  break;                  break;
1140          case MACHINE_PMPPC:          case MACHINE_PMPPC:
1141                    /*  TODO, not working yet  */
1142                  irq = 31 - 21;                  irq = 31 - 21;
1143                    pci_int_line = 0x201;
1144                    break;
1145            case MACHINE_MACPPC:
1146                    /*  TODO, not working yet  */
1147                    irq = 25;
1148                    pci_int_line = 0x101;
1149                  break;                  break;
1150          }          }
1151    
1152          PCI_SET_DATA(PCI_INTERRUPT_REG, 0x28140100 | int_line);          PCI_SET_DATA(PCI_INTERRUPT_REG, 0x28140000 | pci_int_line);
1153    
1154          allocate_device_space(pd, 0x100, 0x100, &port, &memaddr);          allocate_device_space(pd, 0x100, 0x100, &port, &memaddr);
1155    
# Line 950  PCIINIT(dec21030) Line 1213  PCIINIT(dec21030)
1213  }  }
1214    
1215    
1216    
1217  /*  /*
1218   *  Motorola MPC105 "Eagle" Host Bridge   *  Motorola MPC105 "Eagle" Host Bridge
1219   *   *
# Line 971  PCIINIT(eagle) Line 1235  PCIINIT(eagle)
1235              PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));              PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
1236  }  }
1237    
1238    
1239    
1240    /*
1241     *  Apple (MacPPC) stuff:
1242     *
1243     *  Grand Central (I/O controller)
1244     *  Uni-North (PCI controller)
1245     */
1246    
1247    #define PCI_VENDOR_APPLE                0x106b
1248    #define PCI_PRODUCT_APPLE_GC            0x0002
1249    #define PCI_PRODUCT_APPLE_UNINORTH1     0x001e
1250    
1251    PCIINIT(gc_obio)
1252    {
1253            uint64_t port, memaddr;
1254    
1255            PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_APPLE,
1256                PCI_PRODUCT_APPLE_GC));
1257    
1258            /*  TODO:  */
1259            PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_SYSTEM,
1260                PCI_SUBCLASS_SYSTEM_PIC, 0) + 0x00);
1261    
1262            PCI_SET_DATA(PCI_BHLC_REG,
1263                PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
1264    
1265            /*  TODO  */
1266            allocate_device_space(pd, 0x10000, 0x10000, &port, &memaddr);
1267    }
1268    
1269    PCIINIT(uninorth)
1270    {
1271            uint64_t port, memaddr;
1272    
1273            PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_APPLE,
1274                PCI_PRODUCT_APPLE_UNINORTH1));
1275    
1276            PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
1277                PCI_SUBCLASS_BRIDGE_HOST, 0) + 0xff);
1278    
1279            PCI_SET_DATA(PCI_BHLC_REG,
1280                PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
1281    
1282            /*  TODO  */
1283            allocate_device_space(pd, 0x10000, 0x10000, &port, &memaddr);
1284    }
1285    
1286    
1287    
1288    /*
1289     *  ATI graphics cards
1290     */
1291    
1292    #define PCI_VENDOR_ATI                  0x1002
1293    #define PCI_PRODUCT_ATI_RADEON_9200_2   0x5962
1294    
1295    PCIINIT(ati_radeon_9200_2)
1296    {
1297            uint64_t port, memaddr;
1298    
1299            PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_ATI,
1300                PCI_PRODUCT_ATI_RADEON_9200_2));
1301    
1302            /*  TODO: other subclass?  */
1303            PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_DISPLAY,
1304                PCI_SUBCLASS_DISPLAY_VGA, 0) + 0x03);
1305    
1306            /*  TODO  */
1307            allocate_device_space(pd, 0x1000, 0x400000, &port, &memaddr);
1308    }
1309    

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

  ViewVC Help
Powered by ViewVC 1.1.26