Subversion Repositories HelenOS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4438 trochtova 1
#include <ddi.h>
2
#include <libarch/ddi.h>
3
#include <futex.h>
4
 
5
#include "pci.h"
6
#include "pci_bus.h"
7
#include "pci_conf.h"
8
 
9
#define CONF_ADDR_PORT 0xCF8
10
#define CONF_DATA_PORT 0xCFC
11
#define CONF_PORT_SIZE 4
12
 
13
static void *conf_addr_port = NULL;
14
static void *conf_data_port = NULL;
15
 
16
static atomic_t pci_conf_futex = FUTEX_INITIALIZER;
17
 
18
static void method1_conf_read(pci_dev_t *d, int reg, uint8_t *buf, int len);
19
 
20
#define CONF_ADDR(bus, dev, fn, reg)   ((1 << 31) | (bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3))
21
 
22
uint8_t pci_conf_read_8(pci_dev_t *dev, int reg)
23
{
24
    uint8_t res;
25
    method1_conf_read(dev, reg, &res, 1);
26
    return res;
27
}
28
 
29
uint16_t pci_conf_read_16(pci_dev_t *dev, int reg)
30
{
31
    uint16_t res;
32
    method1_conf_read(dev, reg, (uint8_t *)&res, 2);
33
    return res;
34
}
35
 
36
uint32_t pci_conf_read_32(pci_dev_t *dev, int reg)
37
{
38
    uint32_t res;
39
    method1_conf_read(dev, reg, (uint8_t *)&res, 4);
40
    return res;
41
}
42
 
43
static void method1_conf_read(pci_dev_t *dev, int reg, uint8_t *buf, int len)
44
{
45
    futex_down(&pci_conf_futex);
46
    uint32_t conf_addr =  CONF_ADDR(dev->bus->num, dev->dev, dev->fn, reg);
47
    void *addr = conf_data_port + (reg & 3);
48
 
49
    pio_write_32(conf_addr_port, conf_addr);
50
 
51
    switch (len) {
52
        case 1:
53
            buf[0] = pio_read_8(addr);
54
            break;
55
        case 2:
56
            ((uint16_t *)buf)[0] = pio_read_16(addr);
57
            break;
58
        case 4:
59
            ((uint32_t *)buf)[0] = pio_read_32(addr);
60
            break;
61
    }
62
 
63
    futex_up(&pci_conf_futex);
64
}
65
 
66
int pci_bus_init()
67
{  
68
    int error;
69
    if (error = pio_enable((void *)CONF_ADDR_PORT, CONF_PORT_SIZE, &conf_addr_port)) {
70
        printf("PCI: failed to enable configuration address port (error %d)\n", error);
71
        return 0;
72
    }
73
 
74
    if (error = pio_enable((void *)CONF_DATA_PORT, CONF_PORT_SIZE, &conf_data_port)) {
75
        printf("PCI: failed to enable configuration data port (error %d)\n", error);
76
        return 0;
77
    }
78
 
79
    pci_bus_t *bus = pci_alloc_bus();
80
    bus->data = NULL;
81
    bus->num = 0;
82
    pci_bus_register(bus);
83
    pci_bus_scan(bus);
84
    return 1;
85
}
86
 
87
void pci_bus_clean()
88
{
89
}
90
 
91
/* pci bus structure initialization */
92
void pci_init_bus_data(pci_bus_t *bus, pci_bus_t *parent)
93
{
94
    bus->data = NULL;
95
}