source: mainline/uspace/srv/dd/psycho.c@ fcbd1be

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since fcbd1be was fcbd1be, checked in by Lenka Trochtova <trochtova.lenka@…>, 16 years ago

the name of the hierarchical driver was changed II

  • Property mode set to 100644
File size: 4.1 KB
Line 
1#include <malloc.h>
2#include <assert.h>
3#include <unistd.h>
4#include <ddi.h>
5#include <libarch/ddi.h>
6#include <stdio.h>
7#include <futex.h>
8
9#include "pci.h"
10#include "pci_bus.h"
11
12#define PCI_CONF_OFFSET 0x001000000
13#define PCI_CONF_SIZE 0x001000000
14
15/*
16 * virtual address of specified PCI configuration register:
17 * conf_base ... base address of configuration address space
18 * bus ... bus number
19 * dev ... device number (0 - 31)
20 * fn ... function number (0 - 7)
21 * reg ... register number (register's position within PCI configuration header)
22 **/
23#define CONF_ADDR(conf_base, bus, dev, fn, reg) ((void *)(conf_base + ((bus << 16) | (dev << 11) | (fn << 8) | reg)))
24
25static atomic_t pci_conf_futex = FUTEX_INITIALIZER;
26
27static long u2p_space_cnt = 0;
28static long *u2p_bases;
29/* virtual addresses of PCI configuration spaces */
30static void **conf_bases;
31
32static int psycho_init();
33static void u2p_bases_init();
34static void psycho_scan();
35static void * psycho_conf_addr(pci_dev_t *dev, int reg);
36static void psycho_conf_read(pci_dev_t *d, int reg, uint8_t *buf, int len);
37static void psycho_conf_write(pci_dev_t *d, int reg, uint8_t *buf, int len);
38
39
40static void * psycho_conf_addr(pci_dev_t *dev, int reg)
41{
42 return CONF_ADDR(dev->bus->data, dev->bus->num, dev->dev, dev->fn, reg);
43}
44
45static void psycho_scan()
46{
47 printf("PCI: psycho_scan\n");
48 int i, num;
49 for (i = 0; i < u2p_space_cnt; i++) {
50 for (num = 0; num <= 0x80; num += 0x80) {
51 pci_bus_t *bus = pci_alloc_bus();
52 bus->num = num;
53 bus->data = conf_bases[i];
54 pci_bus_register(bus);
55 pci_bus_scan(bus);
56 }
57 }
58}
59
60static int psycho_init()
61{
62 printf("PCI: starting psycho initialization.\n");
63 u2p_bases_init();
64 conf_bases = (void **)malloc(u2p_space_cnt * sizeof(void *));
65 int i, error;
66 for (i = 0; i < u2p_space_cnt; i++) {
67 if (error = pio_enable((void *)(u2p_bases[i] + PCI_CONF_OFFSET), PCI_CONF_SIZE, &(conf_bases[i]))) {
68 printf("PCI: failed to enable psycho conf. adr. space num. %d. (error %d)\n", i, error);
69 return 0;
70 }
71 }
72 return 1;
73}
74
75static void u2p_bases_init()
76{
77 // TODO: write this more generally - get this information from firmware (using kernel + sysinfo)
78 u2p_space_cnt = 2;
79 //u2p_space_cnt = 1;
80 u2p_bases = (void **)malloc(u2p_space_cnt * sizeof(void *));
81 u2p_bases[0] = 0x1c800000000;
82 u2p_bases[1] = 0x1ca00000000;
83}
84
85uint8_t pci_conf_read_8(pci_dev_t *dev, int reg)
86{
87 uint8_t res;
88 psycho_conf_read(dev, reg, &res, sizeof(uint8_t));
89 return res;
90}
91
92uint16_t pci_conf_read_16(pci_dev_t *dev, int reg)
93{
94 uint16_t res;
95 psycho_conf_read(dev, reg, (uint8_t *)(&res), sizeof(uint16_t));
96 return res;
97}
98
99uint32_t pci_conf_read_32(pci_dev_t *dev, int reg)
100{
101 uint32_t res;
102 psycho_conf_read(dev, reg, (uint8_t *)(&res), sizeof(uint32_t));
103 return res;
104}
105
106static inline uint16_t invert_endianness_16(uint16_t x)
107{
108 return (x & 0xFF) << 8 | (x >> 8);
109}
110
111static inline uint32_t invert_endianness_32(uint32_t x)
112{
113 return ((x & 0xFF) << 24) | ((x & 0xFF00) << 8) | ((x & 0xFF0000) >> 8) | (x >> 24);
114}
115
116static void psycho_conf_read(pci_dev_t *d, int reg, uint8_t *buf, int len)
117{
118 futex_down(&pci_conf_futex);
119 switch (len) {
120 case 1:
121 buf[0] = pio_read_8(psycho_conf_addr(d, reg));
122 break;
123 case 2:
124 *((uint16_t *)buf) = invert_endianness_16(pio_read_16(psycho_conf_addr(d, reg)));
125 break;
126 case 4:
127 *((uint32_t *)buf) = invert_endianness_32(pio_read_32(psycho_conf_addr(d, reg)));
128 break;
129 }
130 futex_up(&pci_conf_futex);
131}
132
133static void psycho_conf_write(pci_dev_t *d, int reg, uint8_t *buf, int len)
134{
135 futex_down(&pci_conf_futex);
136 switch (len) {
137 case 1:
138 pio_write_8(psycho_conf_addr(d, reg), buf[0]);
139 break;
140 case 2:
141 pio_write_16(psycho_conf_addr(d, reg), invert_endianness_16(*((uint16_t *)buf)));
142 break;
143 case 4:
144 pio_write_32(psycho_conf_addr(d, reg), invert_endianness_32(*((uint32_t *)buf)));
145 break;
146 }
147 futex_up(&pci_conf_futex);
148}
149
150/* pci bus structure initialization */
151void pci_init_bus_data(pci_bus_t *bus, pci_bus_t *parent)
152{
153 if (parent != NULL) {
154 bus->data = parent->data;
155 }
156}
157
158int pci_bus_init()
159{
160 if(!psycho_init()) {
161 return 0;
162 }
163 psycho_scan();
164 return 1;
165}
166
167void pci_bus_clean()
168{
169 free(u2p_bases);
170 free(conf_bases);
171}
Note: See TracBrowser for help on using the repository browser.