Back to home page

Quest Cross Reference

 
 

    


Warning, cross-references for /kernel/include/drivers/pci/pci.h need to be fixed.

0001 /*                    The Quest Operating System
0002  *  Copyright (C) 2005-2010  Richard West, Boston University
0003  *
0004  *  This program is free software: you can redistribute it and/or modify
0005  *  it under the terms of the GNU General Public License as published by
0006  *  the Free Software Foundation, either version 3 of the License, or
0007  *  (at your option) any later version.
0008  *
0009  *  This program is distributed in the hope that it will be useful,
0010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
0011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0012  *  GNU General Public License for more details.
0013  *
0014  *  You should have received a copy of the GNU General Public License
0015  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
0016  */
0017 
0018 #ifndef _PCI_H_
0019 #define _PCI_H_
0020 
0021 #include "arch/i386.h"
0022 #include "smp/apic.h"
0023 #include "types.h"
0024 
0025 /* ************************************************** */
0026 
0027 /* PCI DEVICE definition */
0028 
0029 #define PCI_MAX_DEVICES 64      /* arbitrary limit */
0030 
0031 typedef struct {
0032   union {
0033     uint32 raw;
0034     struct {
0035       uint32 setBit:1;
0036       uint32 reserved:1;
0037       uint32 ioPort:30;
0038     } ioBAR;
0039     struct {
0040       uint32 clrBit:1;
0041       uint32 memType:2;
0042       uint32 prefetch:1;
0043       uint32 baseAddr:28;
0044     } memBAR;
0045   };
0046   uint32 mask;
0047 } pci_bar;
0048 
0049 typedef struct pci_dev {
0050   uint32 bus, slot, func;
0051   uint16 vendor;
0052   uint16 device;
0053   uint8 classcode;
0054   uint8 subclass;
0055   uint8 progIF;
0056   uint8 headerType;
0057   pci_bar bar[6];
0058   uint32 data[0x10];
0059   uint index;
0060   void *drvdata;
0061 } pci_device;
0062 
0063 #define PCI_ANY_ID (~0)
0064 
0065 /* ************************************************** */
0066 
0067 /* PCI interface */
0068 
0069 /* Initialize and probe for devices */
0070 bool pci_init (void);
0071 
0072 /* Search for device by vendor, device, classcode, or subclass.  The
0073  * value (~0) is treated as a wildcard.  'start_index' allows you to
0074  * skip over devices, for example, if you are looking for multiple
0075  * matches. */
0076 bool pci_find_device (uint16 vendor, uint16 device,
0077                       uint8 classcode, uint8 subclass,
0078                       uint start_index,
0079                       uint* index);
0080 
0081 /* Decode a Base Address Register for the given device.  The value
0082  * will be written into either the mem_addr or the io_addr
0083  * parameters. */
0084 bool pci_decode_bar (uint index, uint bar_index,
0085                      uint* mem_addr, uint* io_addr, uint* mask);
0086 
0087 /* Get the interrupt line and pin from the PCI configuration info, for
0088  * the given device. */
0089 bool pci_get_interrupt (uint index, uint* line, uint* pin);
0090 
0091 /* Fill a pci_device struct given a valid device index. */
0092 bool pci_get_device (uint index, pci_device* dev);
0093 
0094 /* ************************************************** */
0095 
0096 /* PCI IRQ routing interface */
0097 
0098 /* IRQ polarity */
0099 enum {
0100   POLARITY_DEFAULT=0,
0101   POLARITY_HIGH,
0102   POLARITY_LOW
0103 };
0104 
0105 /* IRQ trigger mode */
0106 enum {
0107   TRIGGER_DEFAULT=0,
0108   TRIGGER_EDGE,
0109   TRIGGER_LEVEL
0110 };
0111 
0112 /* Enumerate pins from 1, as PCI config does. */
0113 enum {
0114   PCI_PIN_A=1,
0115   PCI_PIN_B,
0116   PCI_PIN_C,
0117   PCI_PIN_D
0118 };
0119 
0120 #define PCI_DEFAULT_POLARITY POLARITY_LOW
0121 #define PCI_DEFAULT_TRIGGER  TRIGGER_LEVEL
0122 
0123 /* PCI IRQ table entry */
0124 typedef struct {
0125   uint8 bus;
0126   uint8 dev:5;
0127   uint8 pin:3;
0128   uint8 gsi;
0129   uint8 trigger:4;
0130   uint8 polarity:4;
0131 } pci_irq_t;
0132 
0133 extern void pci_irq_register (pci_irq_t *irq);
0134 extern bool pci_irq_find (uint8 bus, uint8 dev, uint8 pin, pci_irq_t *irq_out);
0135 extern bool pci_irq_map (pci_irq_t *irq, uint8 vector,
0136                          uint8 destmask,
0137                          IOAPIC_destination_mode_t destmode,
0138                          IOAPIC_delivery_mode_t delivmode);
0139 extern bool pci_irq_map_handler (pci_irq_t *irq, vector_handler handler,
0140                                  uint8 destmask,
0141                                  IOAPIC_destination_mode_t destmode,
0142                                  IOAPIC_delivery_mode_t delivmode);
0143 
0144 /* ************************************************** */
0145 
0146 #define PCI_CONFIG_ADDRESS 0xCF8
0147 #define PCI_CONFIG_DATA    0xCFC
0148 
0149 #define PCI_MAX_BUS_NUM  ((1<<8)-1)
0150 #define PCI_MAX_DEV_NUM  ((1<<5)-1)
0151 #define PCI_MAX_FUNC_NUM ((1<<3)-1)
0152 
0153 /* ************************************************** */
0154 
0155 /* PCI configuration space access */
0156 
0157 typedef struct _pci_config_addr
0158 {
0159   uint32 regNum:8;
0160   uint32 funcNum:3;
0161   uint32 devNum:5;
0162   uint32 busNum:8;
0163   uint32 reserved:7;
0164   uint32 enable:1;
0165 } pci_config_addr;
0166 
0167 static inline void
0168 pci_config_addr_init (pci_config_addr * a,
0169                       uint8 bus, uint8 dev, uint8 func, uint8 reg)
0170 {
0171   a->regNum = reg;
0172   a->funcNum = func;
0173   a->devNum = dev;
0174   a->busNum = bus;
0175   a->reserved = 0;
0176   a->enable = 1;
0177 }
0178 
0179 static inline pci_config_addr
0180 pci_addr (uint8 bus, uint8 dev, uint8 func, uint8 reg)
0181 {
0182   pci_config_addr a;
0183   pci_config_addr_init (&a, bus, dev, func, reg);
0184   return a;
0185 }
0186 
0187 static inline uint8
0188 pci_read_byte (pci_config_addr a)
0189 {
0190   uint16 offs = a.regNum & 0x3;
0191   uint32 a32, i32;
0192   a32 = *((uint32 *) &a) & (~0x3);       /* zero out lowest 2 bits */
0193   outl (a32, PCI_CONFIG_ADDRESS);
0194   i32 = inl (PCI_CONFIG_DATA);
0195   /* offs selects the first, second, third, or fourth byte in i32. */
0196   return (i32 >> (offs << 3)) & 0xFF;
0197 }
0198 
0199 static inline uint16
0200 pci_read_word (pci_config_addr a)
0201 {
0202   uint16 offs = a.regNum & 0x2;
0203   uint32 a32, i32;
0204   a32 = *((uint32 *) &a) & (~0x3);       /* zero out lowest 2 bits */
0205   outl (a32, PCI_CONFIG_ADDRESS);
0206   i32 = inl (PCI_CONFIG_DATA);
0207   /* offs selects the first or second word in i32. */
0208   return (i32 >> (offs << 3)) & 0xFFFF;
0209 }
0210 
0211 static inline uint32
0212 pci_read_dword (pci_config_addr a)
0213 {
0214   uint32 a32, i32;
0215   a32 = *((uint32 *) &a) & (~0x3);       /* zero out lowest 2 bits */
0216   outl (a32, PCI_CONFIG_ADDRESS);
0217   i32 = inl (PCI_CONFIG_DATA);
0218   return i32;
0219 }
0220 
0221 static inline void
0222 pci_write_byte (pci_config_addr a, uint8 v)
0223 {
0224   uint16 offs = a.regNum & 0x3;
0225   uint32 a32;
0226   a32 = *((uint32 *) &a) & (~0x3);       /* zero out lowest 2 bits */
0227   outl (a32, PCI_CONFIG_ADDRESS);
0228   /* offs selects the first, second, third, or fourth byte in i32. */
0229   outb (v, PCI_CONFIG_DATA + offs);
0230 
0231 }
0232 
0233 static inline void
0234 pci_write_word (pci_config_addr a, uint16 v)
0235 {
0236   uint16 offs = a.regNum & 0x2;
0237   uint32 a32;
0238   a32 = *((uint32 *) &a) & (~0x3);       /* zero out lowest 2 bits */
0239   outl (a32, PCI_CONFIG_ADDRESS);
0240   /* offs selects the first or second word in i32. */
0241   outw (v, PCI_CONFIG_DATA + offs);
0242 }
0243 
0244 static inline void
0245 pci_write_dword (pci_config_addr a, uint32 v)
0246 {
0247   uint32 a32;
0248   a32 = *((uint32 *) &a) & (~0x3);       /* zero out lowest 2 bits */
0249   outl (a32, PCI_CONFIG_ADDRESS);
0250   outl (v, PCI_CONFIG_DATA);
0251 }
0252 
0253 #endif
0254 
0255 /*
0256  * Local Variables:
0257  * indent-tabs-mode: nil
0258  * mode: C
0259  * c-file-style: "gnu"
0260  * c-basic-offset: 2
0261  * End:
0262  */
0263 
0264 /* vi: set et sw=2 sts=2: */