Changeset 5e598e0 in mainline for uspace/srv/drivers/pciintel/pci.c
- Timestamp:
- 2010-04-07T20:55:50Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 89ce401a
- Parents:
- 8c06905
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/drivers/pciintel/pci.c
r8c06905 r5e598e0 41 41 #include <bool.h> 42 42 #include <fibril_synch.h> 43 #include <stdlib.h>44 43 #include <string.h> 45 44 #include <ctype.h> … … 53 52 #include <device/hw_res.h> 54 53 #include <ddi.h> 54 #include <libarch/ddi.h> 55 56 #include "pci.h" 57 #include "pci_regs.h" 55 58 56 59 #define NAME "pciintel" 60 61 62 #define CONF_ADDR(bus, dev, fn, reg) ((1 << 31) | (bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3)) 63 57 64 58 65 static bool pci_add_device(device_t *dev); … … 75 82 void *conf_data_port; 76 83 void *conf_addr_port; 84 fibril_mutex_t conf_mutex; 77 85 } pci_bus_data_t; 78 86 87 static inline pci_bus_data_t *create_pci_bus_data() 88 { 89 pci_bus_data_t *bus_data = (pci_bus_data_t *)malloc(sizeof(pci_bus_data_t)); 90 if(NULL != bus_data) { 91 memset(bus_data, 0, sizeof(pci_bus_data_t)); 92 fibril_mutex_initialize(&bus_data->conf_mutex); 93 } 94 return bus_data; 95 } 96 97 static inline void delete_pci_bus_data(pci_bus_data_t *bus_data) 98 { 99 free(bus_data); 100 } 101 102 static void pci_conf_read(device_t *dev, int reg, uint8_t *buf, size_t len) 103 { 104 assert(NULL != dev->parent); 105 106 pci_dev_data_t *dev_data = (pci_dev_data_t *)dev->driver_data; 107 pci_bus_data_t *bus_data = (pci_bus_data_t *)dev->parent->driver_data; 108 109 fibril_mutex_lock(&bus_data->conf_mutex); 110 111 uint32_t conf_addr = CONF_ADDR(dev_data->bus, dev_data->dev, dev_data->fn, reg); 112 void *addr = bus_data->conf_data_port + (reg & 3); 113 114 pio_write_32(bus_data->conf_addr_port, conf_addr); 115 116 switch (len) { 117 case 1: 118 buf[0] = pio_read_8(addr); 119 break; 120 case 2: 121 ((uint16_t *)buf)[0] = pio_read_16(addr); 122 break; 123 case 4: 124 ((uint32_t *)buf)[0] = pio_read_32(addr); 125 break; 126 } 127 128 fibril_mutex_unlock(&bus_data->conf_mutex); 129 } 130 131 uint8_t pci_conf_read_8(device_t *dev, int reg) 132 { 133 uint8_t res; 134 pci_conf_read(dev, reg, &res, 1); 135 return res; 136 } 137 138 uint16_t pci_conf_read_16(device_t *dev, int reg) 139 { 140 uint16_t res; 141 pci_conf_read(dev, reg, (uint8_t *)&res, 2); 142 return res; 143 } 144 145 uint32_t pci_conf_read_32(device_t *dev, int reg) 146 { 147 uint32_t res; 148 pci_conf_read(dev, reg, (uint8_t *)&res, 4); 149 return res; 150 } 151 152 void pci_bus_scan(device_t *parent, int bus_num) 153 { 154 device_t *dev = create_device(); 155 pci_dev_data_t *dev_data = create_pci_dev_data(); 156 dev->driver_data = dev_data; 157 dev->parent = parent; 158 159 int child_bus = 0; 160 int dnum, fnum; 161 bool multi; 162 uint8_t header_type; 163 164 for (dnum = 0; dnum < 32; dnum++) { 165 multi = true; 166 for (fnum = 0; multi && fnum < 8; fnum++) { 167 init_pci_dev_data(dev_data, bus_num, dnum, fnum); 168 dev_data->vendor_id = pci_conf_read_16(dev, PCI_VENDOR_ID); 169 dev_data->device_id = pci_conf_read_16(dev, PCI_DEVICE_ID); 170 if (dev_data->vendor_id == 0xFFFF) { // device is not present, go on scanning the bus 171 if (fnum == 0) { 172 break; 173 } else { 174 continue; 175 } 176 } 177 header_type = pci_conf_read_8(dev, PCI_HEADER_TYPE); 178 if (fnum == 0) { 179 multi = header_type >> 7; // is the device multifunction? 180 } 181 header_type = header_type & 0x7F; // clear the multifunction bit 182 183 // TODO initialize device - name, match ids, interfaces 184 // TODO register device 185 186 if (header_type == PCI_HEADER_TYPE_BRIDGE || header_type == PCI_HEADER_TYPE_CARDBUS ) { 187 child_bus = pci_conf_read_8(dev, PCI_BRIDGE_SEC_BUS_NUM); 188 printf(NAME ": device is pci-to-pci bridge, secondary bus number = %d.\n", bus_num); 189 if(child_bus > bus_num) { 190 pci_bus_scan(parent, child_bus); 191 } 192 } 193 194 dev = create_device(); // alloc new aux. dev. structure 195 dev_data = create_pci_dev_data(); 196 dev->driver_data = dev_data; 197 dev->parent = parent; 198 } 199 } 200 201 if (dev_data->vendor_id == 0xFFFF) { 202 delete_device(dev); 203 delete_pci_dev_data(dev_data); // free the auxiliary device structure 204 } 205 206 } 79 207 80 208 static bool pci_add_device(device_t *dev) … … 82 210 printf(NAME ": pci_add_device\n"); 83 211 84 pci_bus_data_t *bus_data = (pci_bus_data_t *)malloc(sizeof(pci_bus_data_t));212 pci_bus_data_t *bus_data = create_pci_bus_data(); 85 213 if (NULL == bus_data) { 86 214 printf(NAME ": pci_add_device allocation failed.\n"); … … 125 253 126 254 // TODO scan the bus 255 pci_bus_scan(dev, 0); 127 256 128 257 clean_hw_resource_list(&hw_resources);
Note:
See TracChangeset
for help on using the changeset viewer.