Changeset 5e598e0 in mainline for uspace/srv/drivers/pciintel/pci.c


Ignore:
Timestamp:
2010-04-07T20:55:50Z (14 years ago)
Author:
Lenka Trochtova <trochtova.lenka@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
89ce401a
Parents:
8c06905
Message:

parts of pci enumeration

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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);
Note: See TracChangeset for help on using the changeset viewer.