source: mainline/uspace/drv/pciintel/pci.c@ 423e8c81

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 423e8c81 was fb78ae72, checked in by Jan Vesely <jano.vesely@…>, 14 years ago

Move interrupt enabling code to pciintel driver

  • Property mode set to 100644
File size: 15.7 KB
RevLine 
[8c06905]1/*
2 * Copyright (c) 2010 Lenka Trochtova
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/**
30 * @defgroup pciintel pci bus driver for intel method 1.
31 * @brief HelenOS root pci bus driver for intel method 1.
32 * @{
33 */
34
35/** @file
36 */
37
38#include <assert.h>
39#include <stdio.h>
40#include <errno.h>
41#include <bool.h>
42#include <fibril_synch.h>
[c47e1a8]43#include <str.h>
[8c06905]44#include <ctype.h>
45#include <macros.h>
46
47#include <driver.h>
48#include <devman.h>
49#include <ipc/devman.h>
50#include <ipc/dev_iface.h>
[fb78ae72]51#include <ipc/irc.h>
52#include <ipc/ns.h>
53#include <ipc/services.h>
54#include <sysinfo.h>
[41b56084]55#include <ops/hw_res.h>
[8c06905]56#include <device/hw_res.h>
57#include <ddi.h>
[5e598e0]58#include <libarch/ddi.h>
59
60#include "pci.h"
[8c06905]61
62#define NAME "pciintel"
63
[663f41c4]64#define CONF_ADDR(bus, dev, fn, reg) \
65 ((1 << 31) | (bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3))
[5e598e0]66
[663f41c4]67static hw_resource_list_t *pciintel_get_child_resources(device_t *dev)
[3843ecb]68{
[663f41c4]69 pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data;
70
[8304889]71 if (dev_data == NULL)
[3843ecb]72 return NULL;
73 return &dev_data->hw_resources;
74}
75
[663f41c4]76static bool pciintel_enable_child_interrupt(device_t *dev)
[3843ecb]77{
[fb78ae72]78 /* This is an old ugly way, copied from ne2000 driver */
79 assert(dev);
80 pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data;
81
82 sysarg_t apic;
83 sysarg_t i8259;
84 int irc_phone = -1;
85 int irc_service = 0;
86
87 if ((sysinfo_get_value("apic", &apic) == EOK) && (apic)) {
88 irc_service = SERVICE_APIC;
89 } else if ((sysinfo_get_value("i8259", &i8259) == EOK) && (i8259)) {
90 irc_service = SERVICE_I8259;
91 }
92
93 if (irc_service) {
94 while (irc_phone < 0)
95 irc_phone = service_connect_blocking(irc_service, 0, 0);
96 } else {
97 return false;
98 }
99
100 size_t i;
101 for (i = 0; i < dev_data->hw_resources.count; i++) {
102 if (dev_data->hw_resources.resources[i].type == INTERRUPT) {
103 int irq = dev_data->hw_resources.resources[i].res.interrupt.irq;
104 async_msg_1(irc_phone, IRC_ENABLE_INTERRUPT, irq);
105 }
106 }
107
108 async_hangup(irc_phone);
109 return true;
[3843ecb]110}
111
[50c57df]112static hw_res_ops_t pciintel_child_hw_res_ops = {
[3843ecb]113 &pciintel_get_child_resources,
[663f41c4]114 &pciintel_enable_child_interrupt
[3843ecb]115};
116
[5159ae9]117static device_ops_t pci_child_ops;
[3843ecb]118
[663f41c4]119static int pci_add_device(device_t *);
[3843ecb]120
[663f41c4]121/** The pci bus driver's standard operations. */
[8c06905]122static driver_ops_t pci_ops = {
123 .add_device = &pci_add_device
124};
125
[663f41c4]126/** The pci bus driver structure. */
[8c06905]127static driver_t pci_driver = {
128 .name = NAME,
129 .driver_ops = &pci_ops
130};
131
132typedef struct pciintel_bus_data {
[d1fc8f0]133 uint32_t conf_io_addr;
[8c06905]134 void *conf_data_port;
[663f41c4]135 void *conf_addr_port;
[5e598e0]136 fibril_mutex_t conf_mutex;
[8c06905]137} pci_bus_data_t;
138
[663f41c4]139static pci_bus_data_t *create_pci_bus_data(void)
[5e598e0]140{
[663f41c4]141 pci_bus_data_t *bus_data;
142
143 bus_data = (pci_bus_data_t *) malloc(sizeof(pci_bus_data_t));
[8304889]144 if (bus_data != NULL) {
[5e598e0]145 memset(bus_data, 0, sizeof(pci_bus_data_t));
146 fibril_mutex_initialize(&bus_data->conf_mutex);
147 }
[8304889]148
[663f41c4]149 return bus_data;
[5e598e0]150}
151
[663f41c4]152static void delete_pci_bus_data(pci_bus_data_t *bus_data)
[5e598e0]153{
[663f41c4]154 free(bus_data);
[5e598e0]155}
156
157static void pci_conf_read(device_t *dev, int reg, uint8_t *buf, size_t len)
158{
[8304889]159 assert(dev->parent != NULL);
[5e598e0]160
[663f41c4]161 pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data;
162 pci_bus_data_t *bus_data = (pci_bus_data_t *) dev->parent->driver_data;
[5e598e0]163
164 fibril_mutex_lock(&bus_data->conf_mutex);
165
[663f41c4]166 uint32_t conf_addr;
167 conf_addr = CONF_ADDR(dev_data->bus, dev_data->dev, dev_data->fn, reg);
[5e598e0]168 void *addr = bus_data->conf_data_port + (reg & 3);
169
170 pio_write_32(bus_data->conf_addr_port, conf_addr);
171
172 switch (len) {
[663f41c4]173 case 1:
174 buf[0] = pio_read_8(addr);
175 break;
176 case 2:
177 ((uint16_t *) buf)[0] = pio_read_16(addr);
178 break;
179 case 4:
180 ((uint32_t *) buf)[0] = pio_read_32(addr);
181 break;
[5e598e0]182 }
183
[663f41c4]184 fibril_mutex_unlock(&bus_data->conf_mutex);
[5e598e0]185}
186
[d1fc8f0]187static void pci_conf_write(device_t *dev, int reg, uint8_t *buf, size_t len)
188{
[8304889]189 assert(dev->parent != NULL);
[d1fc8f0]190
[663f41c4]191 pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data;
192 pci_bus_data_t *bus_data = (pci_bus_data_t *) dev->parent->driver_data;
[d1fc8f0]193
194 fibril_mutex_lock(&bus_data->conf_mutex);
195
[663f41c4]196 uint32_t conf_addr;
197 conf_addr = CONF_ADDR(dev_data->bus, dev_data->dev, dev_data->fn, reg);
[d1fc8f0]198 void *addr = bus_data->conf_data_port + (reg & 3);
199
200 pio_write_32(bus_data->conf_addr_port, conf_addr);
201
202 switch (len) {
[663f41c4]203 case 1:
204 pio_write_8(addr, buf[0]);
205 break;
206 case 2:
207 pio_write_16(addr, ((uint16_t *) buf)[0]);
208 break;
209 case 4:
210 pio_write_32(addr, ((uint32_t *) buf)[0]);
211 break;
[d1fc8f0]212 }
213
[663f41c4]214 fibril_mutex_unlock(&bus_data->conf_mutex);
[d1fc8f0]215}
216
[5e598e0]217uint8_t pci_conf_read_8(device_t *dev, int reg)
218{
219 uint8_t res;
220 pci_conf_read(dev, reg, &res, 1);
221 return res;
222}
223
224uint16_t pci_conf_read_16(device_t *dev, int reg)
225{
226 uint16_t res;
[663f41c4]227 pci_conf_read(dev, reg, (uint8_t *) &res, 2);
[5e598e0]228 return res;
229}
230
231uint32_t pci_conf_read_32(device_t *dev, int reg)
232{
233 uint32_t res;
[663f41c4]234 pci_conf_read(dev, reg, (uint8_t *) &res, 4);
235 return res;
[5e598e0]236}
237
[663f41c4]238void pci_conf_write_8(device_t *dev, int reg, uint8_t val)
[d1fc8f0]239{
[663f41c4]240 pci_conf_write(dev, reg, (uint8_t *) &val, 1);
[d1fc8f0]241}
242
[663f41c4]243void pci_conf_write_16(device_t *dev, int reg, uint16_t val)
[d1fc8f0]244{
[663f41c4]245 pci_conf_write(dev, reg, (uint8_t *) &val, 2);
[d1fc8f0]246}
247
[663f41c4]248void pci_conf_write_32(device_t *dev, int reg, uint32_t val)
[d1fc8f0]249{
[663f41c4]250 pci_conf_write(dev, reg, (uint8_t *) &val, 4);
[d1fc8f0]251}
252
[89ce401a]253void create_pci_match_ids(device_t *dev)
254{
[663f41c4]255 pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data;
256 match_id_t *match_id = NULL;
257 char *match_id_str;
258
[89ce401a]259 match_id = create_match_id();
[8304889]260 if (match_id != NULL) {
[663f41c4]261 asprintf(&match_id_str, "pci/ven=%04x&dev=%04x",
262 dev_data->vendor_id, dev_data->device_id);
[c47e1a8]263 match_id->id = match_id_str;
[89ce401a]264 match_id->score = 90;
265 add_match_id(&dev->match_ids, match_id);
[8304889]266 }
267
[663f41c4]268 /* TODO add more ids (with subsys ids, using class id etc.) */
[89ce401a]269}
270
[663f41c4]271void
272pci_add_range(device_t *dev, uint64_t range_addr, size_t range_size, bool io)
[d1fc8f0]273{
[663f41c4]274 pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data;
[3a5909f]275 hw_resource_list_t *hw_res_list = &dev_data->hw_resources;
276 hw_resource_t *hw_resources = hw_res_list->resources;
[663f41c4]277 size_t count = hw_res_list->count;
[3a5909f]278
[8304889]279 assert(hw_resources != NULL);
[3a5909f]280 assert(count < PCI_MAX_HW_RES);
281
282 if (io) {
283 hw_resources[count].type = IO_RANGE;
284 hw_resources[count].res.io_range.address = range_addr;
[663f41c4]285 hw_resources[count].res.io_range.size = range_size;
286 hw_resources[count].res.io_range.endianness = LITTLE_ENDIAN;
[3a5909f]287 } else {
288 hw_resources[count].type = MEM_RANGE;
289 hw_resources[count].res.mem_range.address = range_addr;
[663f41c4]290 hw_resources[count].res.mem_range.size = range_size;
[3a5909f]291 hw_resources[count].res.mem_range.endianness = LITTLE_ENDIAN;
292 }
293
[663f41c4]294 hw_res_list->count++;
[d1fc8f0]295}
296
[663f41c4]297/** Read the base address register (BAR) of the device and if it contains valid
298 * address add it to the devices hw resource list.
299 *
300 * @param dev The pci device.
301 * @param addr The address of the BAR in the PCI configuration address space of
302 * the device.
303 * @return The addr the address of the BAR which should be read next.
[d1fc8f0]304 */
[663f41c4]305int pci_read_bar(device_t *dev, int addr)
[d1fc8f0]306{
[663f41c4]307 /* Value of the BAR */
[d1fc8f0]308 uint32_t val, mask;
[663f41c4]309 /* IO space address */
[d1fc8f0]310 bool io;
[663f41c4]311 /* 64-bit wide address */
[d93aafed]312 bool addrw64;
[d1fc8f0]313
[663f41c4]314 /* Size of the io or memory range specified by the BAR */
[d1fc8f0]315 size_t range_size;
[663f41c4]316 /* Beginning of the io or memory range specified by the BAR */
[d1fc8f0]317 uint64_t range_addr;
318
[663f41c4]319 /* Get the value of the BAR. */
[d1fc8f0]320 val = pci_conf_read_32(dev, addr);
321
[663f41c4]322 io = (bool) (val & 1);
[d1fc8f0]323 if (io) {
[d93aafed]324 addrw64 = false;
[d1fc8f0]325 } else {
326 switch ((val >> 1) & 3) {
327 case 0:
[d93aafed]328 addrw64 = false;
[d1fc8f0]329 break;
330 case 2:
[d93aafed]331 addrw64 = true;
[d1fc8f0]332 break;
333 default:
[663f41c4]334 /* reserved, go to the next BAR */
335 return addr + 4;
[d1fc8f0]336 }
337 }
338
[663f41c4]339 /* Get the address mask. */
[d1fc8f0]340 pci_conf_write_32(dev, addr, 0xffffffff);
[663f41c4]341 mask = pci_conf_read_32(dev, addr);
[d1fc8f0]342
[663f41c4]343 /* Restore the original value. */
[d1fc8f0]344 pci_conf_write_32(dev, addr, val);
[663f41c4]345 val = pci_conf_read_32(dev, addr);
[d1fc8f0]346
[3a5909f]347 range_size = pci_bar_mask_to_size(mask);
[d1fc8f0]348
[d93aafed]349 if (addrw64) {
[663f41c4]350 range_addr = ((uint64_t)pci_conf_read_32(dev, addr + 4) << 32) |
351 (val & 0xfffffff0);
[d1fc8f0]352 } else {
353 range_addr = (val & 0xfffffff0);
[663f41c4]354 }
355
[d93aafed]356 if (range_addr != 0) {
[3a5909f]357 printf(NAME ": device %s : ", dev->name);
[7e752b2]358 printf("address = %" PRIx64, range_addr);
[ab3a851]359 printf(", size = %x\n", (unsigned int) range_size);
[d1fc8f0]360 }
361
[3a5909f]362 pci_add_range(dev, range_addr, range_size, io);
[d1fc8f0]363
[d93aafed]364 if (addrw64)
[d1fc8f0]365 return addr + 8;
[663f41c4]366
367 return addr + 4;
[d1fc8f0]368}
369
[3a5909f]370void pci_add_interrupt(device_t *dev, int irq)
[d1fc8f0]371{
[663f41c4]372 pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data;
[3a5909f]373 hw_resource_list_t *hw_res_list = &dev_data->hw_resources;
[663f41c4]374 hw_resource_t *hw_resources = hw_res_list->resources;
375 size_t count = hw_res_list->count;
[d1fc8f0]376
[3a5909f]377 assert(NULL != hw_resources);
378 assert(count < PCI_MAX_HW_RES);
379
380 hw_resources[count].type = INTERRUPT;
381 hw_resources[count].res.interrupt.irq = irq;
382
[663f41c4]383 hw_res_list->count++;
[3a5909f]384
385 printf(NAME ": device %s uses irq %x.\n", dev->name, irq);
386}
387
388void pci_read_interrupt(device_t *dev)
389{
390 uint8_t irq = pci_conf_read_8(dev, PCI_BRIDGE_INT_LINE);
[8304889]391 if (irq != 0xff)
[3a5909f]392 pci_add_interrupt(dev, irq);
[d1fc8f0]393}
394
395/** Enumerate (recursively) and register the devices connected to a pci bus.
[663f41c4]396 *
397 * @param parent The host-to-pci bridge device.
398 * @param bus_num The bus number.
[d1fc8f0]399 */
[5e598e0]400void pci_bus_scan(device_t *parent, int bus_num)
401{
402 device_t *dev = create_device();
403 pci_dev_data_t *dev_data = create_pci_dev_data();
404 dev->driver_data = dev_data;
405 dev->parent = parent;
406
407 int child_bus = 0;
408 int dnum, fnum;
409 bool multi;
[d1fc8f0]410 uint8_t header_type;
[5e598e0]411
412 for (dnum = 0; dnum < 32; dnum++) {
413 multi = true;
414 for (fnum = 0; multi && fnum < 8; fnum++) {
415 init_pci_dev_data(dev_data, bus_num, dnum, fnum);
[663f41c4]416 dev_data->vendor_id = pci_conf_read_16(dev,
417 PCI_VENDOR_ID);
418 dev_data->device_id = pci_conf_read_16(dev,
419 PCI_DEVICE_ID);
420 if (dev_data->vendor_id == 0xffff) {
421 /*
422 * The device is not present, go on scanning the
423 * bus.
424 */
425 if (fnum == 0)
[5e598e0]426 break;
[663f41c4]427 else
428 continue;
[5e598e0]429 }
[663f41c4]430
[5e598e0]431 header_type = pci_conf_read_8(dev, PCI_HEADER_TYPE);
432 if (fnum == 0) {
[663f41c4]433 /* Is the device multifunction? */
434 multi = header_type >> 7;
[5e598e0]435 }
[663f41c4]436 /* Clear the multifunction bit. */
437 header_type = header_type & 0x7F;
[5e598e0]438
[3a5909f]439 create_pci_dev_name(dev);
440
441 pci_alloc_resource_list(dev);
[d1fc8f0]442 pci_read_bars(dev);
[3a5909f]443 pci_read_interrupt(dev);
444
[663f41c4]445 dev->ops = &pci_child_ops;
[89ce401a]446
[663f41c4]447 printf(NAME ": adding new child device %s.\n",
448 dev->name);
[89ce401a]449
450 create_pci_match_ids(dev);
451
[8304889]452 if (child_device_register(dev, parent) != EOK) {
[663f41c4]453 pci_clean_resource_list(dev);
[89ce401a]454 clean_match_ids(&dev->match_ids);
[663f41c4]455 free((char *) dev->name);
[89ce401a]456 dev->name = NULL;
457 continue;
458 }
[5e598e0]459
[663f41c4]460 if (header_type == PCI_HEADER_TYPE_BRIDGE ||
[8304889]461 header_type == PCI_HEADER_TYPE_CARDBUS) {
[663f41c4]462 child_bus = pci_conf_read_8(dev,
463 PCI_BRIDGE_SEC_BUS_NUM);
464 printf(NAME ": device is pci-to-pci bridge, "
465 "secondary bus number = %d.\n", bus_num);
[8304889]466 if (child_bus > bus_num)
[663f41c4]467 pci_bus_scan(parent, child_bus);
[5e598e0]468 }
469
[663f41c4]470 /* Alloc new aux. dev. structure. */
471 dev = create_device();
[5e598e0]472 dev_data = create_pci_dev_data();
473 dev->driver_data = dev_data;
474 dev->parent = parent;
475 }
476 }
477
[3a5909f]478 if (dev_data->vendor_id == 0xffff) {
[5e598e0]479 delete_device(dev);
[663f41c4]480 /* Free the auxiliary device structure. */
481 delete_pci_dev_data(dev_data);
482 }
[5e598e0]483}
[8c06905]484
[df747b9c]485static int pci_add_device(device_t *dev)
[8c06905]486{
[be942bc]487 int rc;
488
[8c06905]489 printf(NAME ": pci_add_device\n");
490
[5e598e0]491 pci_bus_data_t *bus_data = create_pci_bus_data();
[8304889]492 if (bus_data == NULL) {
[8c06905]493 printf(NAME ": pci_add_device allocation failed.\n");
[df747b9c]494 return ENOMEM;
[663f41c4]495 }
[8c06905]496
[663f41c4]497 dev->parent_phone = devman_parent_device_connect(dev->handle,
498 IPC_FLAG_BLOCKING);
499 if (dev->parent_phone < 0) {
500 printf(NAME ": pci_add_device failed to connect to the "
501 "parent's driver.\n");
[89ce401a]502 delete_pci_bus_data(bus_data);
[be942bc]503 return dev->parent_phone;
[8c06905]504 }
505
506 hw_resource_list_t hw_resources;
507
[f724e82]508 rc = hw_res_get_resource_list(dev->parent_phone, &hw_resources);
[be942bc]509 if (rc != EOK) {
[663f41c4]510 printf(NAME ": pci_add_device failed to get hw resources for "
511 "the device.\n");
[89ce401a]512 delete_pci_bus_data(bus_data);
[ffa2c8ef]513 async_hangup(dev->parent_phone);
[be942bc]514 return rc;
[3a5909f]515 }
[8c06905]516
[7e752b2]517 printf(NAME ": conf_addr = %" PRIx64 ".\n",
[663f41c4]518 hw_resources.resources[0].res.io_range.address);
[8c06905]519
520 assert(hw_resources.count > 0);
[3a5909f]521 assert(hw_resources.resources[0].type == IO_RANGE);
522 assert(hw_resources.resources[0].res.io_range.size == 8);
[8c06905]523
[663f41c4]524 bus_data->conf_io_addr =
525 (uint32_t) hw_resources.resources[0].res.io_range.address;
[8c06905]526
[178673c]527 if (pio_enable((void *)(uintptr_t)bus_data->conf_io_addr, 8,
[663f41c4]528 &bus_data->conf_addr_port)) {
[8c06905]529 printf(NAME ": failed to enable configuration ports.\n");
[89ce401a]530 delete_pci_bus_data(bus_data);
[ffa2c8ef]531 async_hangup(dev->parent_phone);
[f724e82]532 hw_res_clean_resource_list(&hw_resources);
[663f41c4]533 return EADDRNOTAVAIL;
[8c06905]534 }
[663f41c4]535 bus_data->conf_data_port = (char *) bus_data->conf_addr_port + 4;
[8c06905]536
537 dev->driver_data = bus_data;
538
[663f41c4]539 /* Enumerate child devices. */
[89ce401a]540 printf(NAME ": scanning the bus\n");
[5e598e0]541 pci_bus_scan(dev, 0);
[8c06905]542
[f724e82]543 hw_res_clean_resource_list(&hw_resources);
[8c06905]544
[df747b9c]545 return EOK;
[8c06905]546}
547
[663f41c4]548static void pciintel_init(void)
[3843ecb]549{
[50c57df]550 pci_child_ops.interfaces[HW_RES_DEV_IFACE] = &pciintel_child_hw_res_ops;
[3843ecb]551}
552
[713a4b9]553pci_dev_data_t *create_pci_dev_data(void)
554{
555 pci_dev_data_t *res = (pci_dev_data_t *) malloc(sizeof(pci_dev_data_t));
556
[8304889]557 if (res != NULL)
[713a4b9]558 memset(res, 0, sizeof(pci_dev_data_t));
559 return res;
560}
561
[d93aafed]562void init_pci_dev_data(pci_dev_data_t *dev_data, int bus, int dev, int fn)
[713a4b9]563{
[d93aafed]564 dev_data->bus = bus;
565 dev_data->dev = dev;
566 dev_data->fn = fn;
[713a4b9]567}
568
[d93aafed]569void delete_pci_dev_data(pci_dev_data_t *dev_data)
[713a4b9]570{
[d93aafed]571 if (dev_data != NULL) {
[f724e82]572 hw_res_clean_resource_list(&dev_data->hw_resources);
[d93aafed]573 free(dev_data);
[713a4b9]574 }
575}
576
577void create_pci_dev_name(device_t *dev)
578{
579 pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data;
580 char *name = NULL;
581
582 asprintf(&name, "%02x:%02x.%01x", dev_data->bus, dev_data->dev,
583 dev_data->fn);
584 dev->name = name;
585}
586
587bool pci_alloc_resource_list(device_t *dev)
588{
589 pci_dev_data_t *dev_data = (pci_dev_data_t *)dev->driver_data;
590
591 dev_data->hw_resources.resources =
592 (hw_resource_t *) malloc(PCI_MAX_HW_RES * sizeof(hw_resource_t));
593 return dev_data->hw_resources.resources != NULL;
594}
595
596void pci_clean_resource_list(device_t *dev)
597{
598 pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data;
599
[8304889]600 if (dev_data->hw_resources.resources != NULL) {
[713a4b9]601 free(dev_data->hw_resources.resources);
602 dev_data->hw_resources.resources = NULL;
603 }
604}
605
606/** Read the base address registers (BARs) of the device and adds the addresses
607 * to its hw resource list.
608 *
609 * @param dev the pci device.
610 */
611void pci_read_bars(device_t *dev)
612{
613 /*
614 * Position of the BAR in the PCI configuration address space of the
615 * device.
616 */
617 int addr = PCI_BASE_ADDR_0;
618
619 while (addr <= PCI_BASE_ADDR_5)
620 addr = pci_read_bar(dev, addr);
621}
622
623size_t pci_bar_mask_to_size(uint32_t mask)
624{
625 return ((mask & 0xfffffff0) ^ 0xffffffff) + 1;
626}
627
[8c06905]628int main(int argc, char *argv[])
629{
[3843ecb]630 printf(NAME ": HelenOS pci bus driver (intel method 1).\n");
631 pciintel_init();
[8c06905]632 return driver_main(&pci_driver);
633}
634
635/**
636 * @}
[472020fc]637 */
Note: See TracBrowser for help on using the repository browser.