Changes in uspace/srv/pci/pci.c [cb0ea39:38c706cc] in mainline


Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/pci/pci.c

    rcb0ea39 r38c706cc  
    1 #include <futex.h>
    2 #include <assert.h>
     1/*
     2 * HelenOS PCI driver.
     3 *
     4 * (Based on public domain libpci example.c written by Martin Mares.)
     5 * Copyright (c) 2006 Jakub Jermar
     6 *
     7 * Can be freely distributed and used under the terms of the GNU GPL.
     8 */
    39
    4 #include "pci.h"
    5 #include "pci_bus.h"
    6 #include "pci_regs.h"
    7 #include "pci_conf.h"
     10/**
     11 * @addtogroup pci
     12 * @{
     13 */
    814
    9 #define NAME "PCI"
     15#include <stdio.h>
     16#include <ddi.h>
     17#include <task.h>
     18#include <stdlib.h>
     19#include <ipc/ipc.h>
     20#include <ipc/services.h>
     21#include <errno.h>
    1022
    11 LIST_INITIALIZE(devices_list);
    12 LIST_INITIALIZE(buses_list);
    13 LIST_INITIALIZE(drivers_list);
     23#include "libpci/pci.h"
    1424
    15 static atomic_t pci_bus_futex = FUTEX_INITIALIZER;
     25#define PCI_CONF1       0xcf8
     26#define PCI_CONF1_SIZE  8
    1627
    17 static int pci_match(pci_drv_t *drv, pci_dev_t *dev);
    18 static int pci_pass_dev(pci_drv_t *drv, pci_dev_t *dev);
    19 static void pci_lookup_driver(pci_dev_t *dev);
    20 static void pci_lookup_devices(pci_drv_t *drv);
     28#define NAME            "PCI"
    2129
     30static struct pci_access *pacc;
    2231
    23 void pci_bus_scan(pci_bus_t *bus)
     32int main(int argc, char *argv[])
    2433{
    25         pci_dev_t *dev = pci_alloc_dev();
    26         pci_bus_t *child_bus = NULL;
    27         int dnum, fnum, bus_num;
    28         bool multi;
    29         uint8_t header_type;
    30        
    31         for (dnum = 0; dnum < 32; dnum++) {
    32                 multi = true;
    33                 for (fnum = 0; multi && fnum < 8; fnum++) {
    34                         pci_init_dev(dev, bus, dnum, fnum);
    35                         dev->vendor_id = pci_conf_read_16(dev, PCI_VENDOR_ID);
    36                         dev->device_id = pci_conf_read_16(dev, PCI_DEVICE_ID);
    37                         if (dev->vendor_id == 0xFFFF) { // device is not present, go on scanning the bus
    38                                 if (fnum == 0) {
    39                                         break;
    40                                 } else {
    41                                         continue; 
    42                                 }
    43                         }
    44                         header_type = pci_conf_read_8(dev, PCI_HEADER_TYPE);
    45                         if (fnum == 0) {
    46                                  multi = header_type >> 7;  // is the device multifunction?
    47                         }
    48                         header_type = header_type & 0x7F; // clear the multifunction bit
    49                        
    50                         printf(NAME ": adding new device %3d : %2d : %2d", dev->bus->num, dnum, fnum);
    51                         printf(" - vendor = 0x%04X, device = 0x%04X.\n", dev->vendor_id, dev->device_id);
    52                         pci_device_register(dev);                       
    53                        
    54                         if (header_type == PCI_HEADER_TYPE_BRIDGE || header_type == PCI_HEADER_TYPE_CARDBUS ) {
    55                                 bus_num = pci_conf_read_8(dev, PCI_BRIDGE_SEC_BUS_NUM);
    56                                 printf(NAME ": device is pci-to-pci bridge, secondary bus number = %d.\n", bus_num);
    57                                 if(bus_num > bus->num) {                                       
    58                                         child_bus = pci_alloc_bus();
    59                                         pci_init_bus(child_bus, bus, bus_num);
    60                                         pci_bus_register(child_bus);
    61                                         pci_bus_scan(child_bus);       
    62                                 }                                       
    63                         }
    64                        
    65                         dev = pci_alloc_dev();  // alloc new aux. dev. structure
     34        struct pci_dev *dev;
     35        unsigned int c;
     36        char buf[80];
     37        ipcarg_t ns_in_phone_hash;
     38
     39        printf("%s: HelenOS PCI driver\n", NAME);
     40
     41        /*
     42         * Gain control over PCI configuration ports.
     43         */
     44        iospace_enable(task_get_id(), (void *) PCI_CONF1, PCI_CONF1_SIZE);
     45
     46        pacc = pci_alloc();           /* Get the pci_access structure */
     47        pci_init(pacc);               /* Initialize the PCI library */
     48        pci_scan_bus(pacc);           /* We want to get the list of devices */
     49        for(dev=pacc->devices; dev; dev=dev->next) {   /* Iterate over all devices */
     50                pci_fill_info(dev, PCI_FILL_IDENT | PCI_FILL_BASES | PCI_FILL_IRQ);
     51                c = pci_read_word(dev, PCI_CLASS_DEVICE); /* Read config register directly */
     52                printf("%02x:%02x.%d vendor=%04x device=%04x class=%04x irq=%d base0=%lx\n",
     53                        dev->bus, dev->dev, dev->func, dev->vendor_id, dev->device_id,
     54                        c, dev->irq, dev->base_addr[0]);
     55                printf("\t%s\n", pci_lookup_name(pacc, buf, sizeof(buf), PCI_LOOKUP_VENDOR | PCI_LOOKUP_DEVICE,
     56                        dev->vendor_id, dev->device_id));
     57        }
     58
     59        printf("%s: registering at naming service.\n", NAME);
     60        if (ipc_connect_to_me(PHONE_NS, SERVICE_PCI, 0, 0, &ns_in_phone_hash) != 0) {
     61                printf("Failed to register %s at naming service.\n", NAME);
     62                return -1;
     63        }
     64
     65        printf("%s: accepting connections\n", NAME);
     66        while (1) {             
     67                ipc_call_t call;
     68                ipc_callid_t callid;
     69                ipcarg_t retval = ENOTSUP;
     70
     71                callid = ipc_wait_for_call(&call);
     72                switch(IPC_GET_METHOD(call)) {
     73                case IPC_M_CONNECT_ME_TO:
     74                        retval = EOK;
     75                        break;
    6676                }
     77                ipc_answer_0(callid, retval);
     78                printf("%s: received call from %lX\n", NAME,
     79                    call.in_phone_hash);
    6780        }
    68        
    69         if (dev->vendor_id == 0xFFFF) {
    70                 pci_free_dev(dev);  // free the auxiliary device structure
    71         }       
    72 }
    7381
    74 /*
    75  * Usage: pci_bus_futex must be down.
    76  */
    77 static int pci_pass_dev(pci_drv_t *drv, pci_dev_t *dev)
    78 {
    79         assert(dev->driver == NULL);
    80         assert(drv->name != NULL);
    81        
    82         printf(NAME ": passing device to driver '%s'.\n", drv->name);
    83         if (drv->ops->add_device != NULL && drv->ops->add_device(dev)) {
    84                 dev->driver = drv;
    85                 return 1;
    86         }
    87        
     82        pci_cleanup(pacc);
    8883        return 0;
    8984}
    9085
    91 /*
    92  * Usage: pci_bus_futex must be down.
    93  */
    94 static void pci_lookup_driver(pci_dev_t *dev)
    95 {
    96         link_t *item = drivers_list.next;
    97         pci_drv_t *drv = NULL;
    98        
    99         while (item != &drivers_list) {
    100                 drv = list_get_instance(item, pci_drv_t, link);
    101                 if (pci_match(drv, dev) && pci_pass_dev(drv, dev)) {
    102                         return;
    103                 }
    104                 item = item->next;
    105         }
    106 }
    107 
    108 /*
    109  * Usage: pci_bus_futex must be down.
    110  */
    111 static void pci_lookup_devices(pci_drv_t *drv)
    112 {
    113         link_t *item = devices_list.next;
    114         pci_dev_t *dev = NULL;
    115        
    116         printf(NAME ": looking up devices for a newly added driver '%s'.\n", drv->name);
    117        
    118         while (item != &devices_list) {
    119                 dev = list_get_instance(item, pci_dev_t, link);
    120                 if (dev->driver == NULL && pci_match(drv, dev)) {
    121                         pci_pass_dev(drv, dev);
    122                 }
    123                 item = item->next;
    124         }
    125 }
    126 
    127 static int pci_match(pci_drv_t *drv, pci_dev_t *dev)
    128 {
    129         return drv->vendor_id == dev->vendor_id && drv->device_id == dev->device_id;
    130 }
    131 
    132 void pci_bus_register(pci_bus_t *bus)
    133 {
    134         futex_down(&pci_bus_futex);
    135        
    136         // add the device to the list of pci devices
    137         list_append(&(bus->link), &buses_list);
    138        
    139         futex_up(&pci_bus_futex);
    140 }
    141 
    142 void pci_device_register(pci_dev_t *dev)
    143 {
    144         futex_down(&pci_bus_futex);
    145        
    146         // add the device to the list of pci devices
    147         list_append(&(dev->link), &devices_list);
    148        
    149         // try to find suitable driver for the device and pass the device to it
    150         pci_lookup_driver(dev);
    151        
    152         futex_up(&pci_bus_futex);       
    153 }
    154 
    155 void pci_driver_register(pci_drv_t *drv)
    156 {       
    157         assert(drv->name != NULL);
    158        
    159         futex_down(&pci_bus_futex);
    160         printf(NAME ": registering new driver '%s'.\n", drv->name);
    161         list_append(&(drv->link), &drivers_list);
    162        
    163         // try to find compatible devices
    164         pci_lookup_devices(drv);
    165        
    166         futex_up(&pci_bus_futex);
    167 }
    168 
     86/**
     87 * @}
     88 */
Note: See TracChangeset for help on using the changeset viewer.