2 meinOS - A unix-like x86 microkernel operating system
3 Copyright (C) 2008 Janosch Gräf <janosch.graef@gmx.net>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include <cdi/lists.h>
37 uint8_t cache_line_size
;
38 uint8_t latency_timer
;
42 uint32_t cardbus_cis_ptr
;
43 uint16_t subsystem_vendor_id
;
44 uint16_t subsystem_id
;
47 uint8_t interrupt_line
;
48 uint8_t interrupt_pin
;
53 static cdi_list_t pci_devices
= NULL
;
55 static int cdi_pci_read_config(struct cdi_pci_device
*pci
) {
58 asprintf(&filename
,"dev/pci%d.%d.%d",pci
->bus
,pci
->dev
,pci
->function
);
59 int fh
= open(filename
,O_RDWR
);
63 struct pci_config conf
;
64 read(fh
,&conf
,sizeof(conf
));
66 if (conf
.header_type
==0 || conf
.header_type
==1) {
67 pci
->vendor_id
= conf
.vendor_id
;
68 pci
->device_id
= conf
.device_id
;
69 pci
->class_id
= (conf
.class<<8)|conf
.subclass
;
70 pci
->irq
= conf
.interrupt_line
; /// @todo Is that right?
71 pci
->resources
= cdi_list_create();
76 struct cdi_pci_resource
*res
= malloc(sizeof(struct cdi_pci_resource
));
77 res
->start
= conf
.bar
[i
]&0xFFFFFFF0;
78 res
->type
= (conf
.bar
[i
]&1)?CDI_PCI_IOPORTS
:CDI_PCI_MEMORY
;
80 lseek(fh
,offsetof(struct pci_config
,bar
[i
]),SEEK_SET
);
81 uint32_t bar_tmp
= 0xFFFFFFF0|(conf
.bar
[i
]&1);
83 lseek(fh
,offsetof(struct pci_config
,bar
[i
]),SEEK_SET
);
84 read(fh
,&(res
->length
),4);
85 res
->length
= (~res
->length
|0xF)+1;
86 lseek(fh
,offsetof(struct pci_config
,bar
[i
]),SEEK_SET
);
87 write(fh
,conf
.bar
+i
,4);
88 cdi_list_push(pci
->resources
,res
);
101 void cdi_pci_get_all_devices(cdi_list_t list
) {
102 if (pci_devices
==NULL
) {
103 DIR *dir
= opendir("/dev");
109 if (strncmp(ent
->d_name
,"pci",3)==0) {
110 struct cdi_pci_device
*new = malloc(sizeof(struct cdi_pci_device
));
111 if (sscanf(ent
->d_name
,"pci%d.%d.%d",&(new->bus
),&(new->dev
),&(new->function
))==3) {
112 if (cdi_pci_read_config(new)!=-1) cdi_list_push(list
,new);
123 void cdi_pci_device_destroy(struct cdi_pci_device
* device
) {
124 struct cdi_pci_resource
*res
;
126 cdi_pci_free_ioports(device
);
127 cdi_pci_free_memory(device
);
128 while ((res
= cdi_list_pop(device
->resources
))) free(res
);
129 cdi_list_destroy(device
->resources
);
133 void cdi_pci_alloc_ioports(struct cdi_pci_device
* device
) {
134 struct cdi_pci_resource
*res
;
137 for (i
=0;(res
= cdi_list_get(device
->resources
,i
));i
++) {
138 if (res
->type
==CDI_PCI_IOPORTS
) cdi_ioports_alloc(res
->start
,res
->length
);
142 void cdi_pci_free_ioports(struct cdi_pci_device
* device
) {
143 struct cdi_pci_resource
*res
;
146 for (i
=0;(res
= cdi_list_get(device
->resources
,i
));i
++) {
147 if (res
->type
==CDI_PCI_IOPORTS
) cdi_ioports_free(res
->start
,res
->length
);
151 void cdi_pci_alloc_memory(struct cdi_pci_device
*device
) {
152 struct cdi_pci_resource
*res
;
155 for (i
=0;(res
= cdi_list_get(device
->resources
,i
));i
++) {
156 if (res
->type
==CDI_PCI_MEMORY
) res
->address
= cdi_alloc_phys_addr(res
->length
,res
->start
);
160 void cdi_pci_free_memory(struct cdi_pci_device
*device
) {
161 struct cdi_pci_resource
*res
;
164 for (i
=0;(res
= cdi_list_get(device
->resources
,i
));i
++) {
165 if (res
->type
==CDI_PCI_MEMORY
) cdi_free_phys_addr(res
->length
,res
->start
);