Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 5e598e0 in mainline


Ignore:
Timestamp:
2010-04-07T20:55:50Z (12 years ago)
Author:
Lenka Trochtova <trochtova.lenka@…>
Branches:
lfn, master
Children:
89ce401a
Parents:
8c06905
Message:

parts of pci enumeration

Location:
uspace
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/libdrv/include/driver.h

    r8c06905 r5e598e0  
    7979        /** Globally unique device identifier (assigned to the device by the device manager). */
    8080        device_handle_t handle;
    81         /** The phone to the parent device driver.*/
     81        /** The phone to the parent device driver (if it is different from this driver).*/
    8282        int parent_phone;
     83        /** Parent device if handled by this driver, NULL otherwise. */
     84        device_t *parent;
    8385        /** The device's name.*/
    8486        const char *name;
  • uspace/srv/drivers/pciintel/pci.c

    r8c06905 r5e598e0  
    4141#include <bool.h>
    4242#include <fibril_synch.h>
    43 #include <stdlib.h>
    4443#include <string.h>
    4544#include <ctype.h>
     
    5352#include <device/hw_res.h>
    5453#include <ddi.h>
     54#include <libarch/ddi.h>
     55
     56#include "pci.h"
     57#include "pci_regs.h"
    5558
    5659#define NAME "pciintel"
     60
     61
     62#define CONF_ADDR(bus, dev, fn, reg)   ((1 << 31) | (bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3))
     63
    5764
    5865static bool pci_add_device(device_t *dev);
     
    7582        void *conf_data_port;
    7683        void *conf_addr_port;   
     84        fibril_mutex_t conf_mutex;
    7785} pci_bus_data_t;
    7886
     87static 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
     97static inline void delete_pci_bus_data(pci_bus_data_t *bus_data)
     98{
     99        free(bus_data);
     100}
     101
     102static 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
     131uint8_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
     138uint16_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
     145uint32_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
     152void 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}
    79207
    80208static bool pci_add_device(device_t *dev)
     
    82210        printf(NAME ": pci_add_device\n");
    83211       
    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();
    85213        if (NULL == bus_data) {
    86214                printf(NAME ": pci_add_device allocation failed.\n");
     
    125253       
    126254        // TODO scan the bus   
     255        pci_bus_scan(dev, 0);
    127256       
    128257        clean_hw_resource_list(&hw_resources);
  • uspace/srv/drivers/pciintel/pci.h

    r8c06905 r5e598e0  
    3636#define PCI_H
    3737
     38
     39#include <stdlib.h>
    3840#include <driver.h>
     41#include <malloc.h>
    3942
    4043typedef struct pci_dev_data {
     
    4245        int dev;
    4346        int fn;
    44         hw_resource_list hw_resources;
     47        int vendor_id;
     48        int device_id;
     49        hw_resource_list_t hw_resources;
    4550} pci_dev_data_t;
    4651
     52static inline pci_dev_data_t *create_pci_dev_data()
     53{
     54        pci_dev_data_t *res = (pci_dev_data_t *)malloc(sizeof(pci_dev_data_t));
     55        if (NULL != res) {
     56                memset(res, 0, sizeof(pci_dev_data_t));
     57        }
     58        return res;     
     59}
    4760
     61static inline void init_pci_dev_data(pci_dev_data_t *d, int bus, int dev, int fn)
     62{
     63        d->bus = bus;
     64        d->dev = dev;
     65        d->fn = fn;     
     66}
     67
     68static inline void delete_pci_dev_data(pci_dev_data_t *d)
     69{
     70        if (NULL != d) {
     71                clean_hw_resource_list(&d->hw_resources);
     72                free(d);       
     73        }
     74}
     75
     76uint8_t pci_conf_read_8(device_t *dev, int reg);
     77uint16_t pci_conf_read_16(device_t *dev, int reg);
     78uint32_t pci_conf_read_32(device_t *dev, int reg);
     79
     80void pci_bus_scan(device_t *parent, int bus_num);
    4881
    4982#endif
Note: See TracChangeset for help on using the changeset viewer.