00001
00002
00011
00012
00013
00014
00015
00016
00017 #include <l4/env/errno.h>
00018 #include <l4/sys/types.h>
00019 #include <l4/generic_io/types.h>
00020 #include <l4/generic_io/generic_io-server.h>
00021
00022
00023 #include "io.h"
00024 #include "pci.h"
00025 #include "res.h"
00026 #include "pcilib.h"
00027 #include "pcilib_pci.h"
00028 #include "__config.h"
00029 #include "__macros.h"
00030
00032 static inline void * _pci_get_addr(l4_io_pdev_t pdev)
00033 {
00034 return pci_find_slot(pdev>>8, pdev&0xff);
00035 }
00036
00058 long
00059 l4_io_pci_find_device_component (CORBA_Object _dice_corba_obj,
00060 unsigned short vendor_id,
00061 unsigned short device_id,
00062 l4_io_pdev_t start_at,
00063 l4_io_pci_dev_t *pci_dev,
00064 CORBA_Server_Environment *_dice_corba_env)
00065 {
00066 void *from, *pdev;
00067 unsigned int vendor = vendor_id;
00068 unsigned int device = device_id;
00069
00070 if (vendor == 0xffff)
00071 vendor = ~0;
00072 if (device == 0xffff)
00073 device = ~0;
00074
00075 LOGd(DEBUG_PCI, "find [%04x/%04x] start at %x:%02x.%x ... ",
00076 vendor_id, device_id, start_at>>8, (start_at&0xff)>>3, start_at&7);
00077
00078 if (!(from = _pci_get_addr(start_at)))
00079 return -L4_EINVAL;
00080
00081 pdev = pci_find_device(vendor, device, from);
00082
00083 if (!pdev)
00084 {
00085 LOGd(DEBUG_PCI, "unsuccessfull\n");
00086 return -L4_ENOTFOUND;
00087 }
00088
00089 memset(pci_dev, 0, sizeof(l4_io_pci_dev_t));
00090 pci_dev->handle = PCI_linux_to_io(pdev, (void *) pci_dev);
00091
00092 #if DEBUG_PCI
00093 printf("successfull (pdev=%x:%02x.%x)\n",
00094 pci_dev->handle>>8, (pci_dev->handle&0xff)>>3, pci_dev->handle&7);
00095 #endif
00096
00097 return 0;
00098 }
00099
00112 long
00113 l4_io_pci_find_slot_component (CORBA_Object _dice_corba_obj,
00114 unsigned long bus,
00115 unsigned long slot,
00116 l4_io_pci_dev_t *pci_dev,
00117 CORBA_Server_Environment *_dice_corba_env)
00118 {
00119 void *pdev;
00120
00121 LOGd(DEBUG_PCI, "find %02lx:%02lx ... ", bus, slot);
00122
00123 pdev = pci_find_slot(bus, slot);
00124
00125 if (!pdev)
00126 {
00127 LOGd(DEBUG_PCI, "unsuccessfull");
00128 return -L4_ENOTFOUND;
00129 }
00130
00131 memset(pci_dev, 0, sizeof(l4_io_pci_dev_t));
00132 pci_dev->handle = PCI_linux_to_io(pdev, (void *) pci_dev);
00133
00134 LOGd(DEBUG_PCI, "successfull (pdev=%x:%02x.%x)",
00135 pci_dev->handle>>8, (pci_dev->handle&0xff)>>3, pci_dev->handle&7);
00136
00137 return 0;
00138 }
00139
00152 long
00153 l4_io_pci_find_class_component (CORBA_Object _dice_corba_obj,
00154 unsigned long class_id,
00155 l4_io_pdev_t start_at,
00156 l4_io_pci_dev_t *pci_dev,
00157 CORBA_Server_Environment *_dice_corba_env)
00158 {
00159 void *from = NULL, *pdev;
00160 unsigned int class = class_id;
00161
00162 class &= 0x00ffffff;
00163
00164 LOGd(DEBUG_PCI, "find <%06lx> start at %x:%02x.%x ... ",
00165 class_id, start_at>>8, (start_at&0xff)>>3, start_at&7);
00166
00167 if (start_at && !(from = _pci_get_addr(start_at)))
00168 return -L4_EINVAL;
00169
00170 pdev = pci_find_class(class, from);
00171
00172 if (!pdev)
00173 {
00174 LOGd(DEBUG_PCI, "unsuccessfull");
00175 return -L4_ENOTFOUND;
00176 }
00177
00178 memset(pci_dev, 0, sizeof(l4_io_pci_dev_t));
00179 pci_dev->handle = PCI_linux_to_io(pdev, (void *) pci_dev);
00180
00181 LOGd(DEBUG_PCI, "successfull (pdev=%x:%02x.%x)",
00182 pci_dev->handle>>8, (pci_dev->handle&0xff)>>3, pci_dev->handle&7);
00183
00184 return 0;
00185 }
00204 long
00205 l4_io_pci_read_config_byte_component (CORBA_Object _dice_corba_obj,
00206 l4_io_pdev_t pdev,
00207 long offset,
00208 unsigned char *val,
00209 CORBA_Server_Environment *_dice_corba_env)
00210 {
00211 void *pci_dev = _pci_get_addr(pdev);
00212
00213 LOGd(DEBUG_PCI_RW, "read %x:%02x.%x byte %ld%s",
00214 pdev>>8, (pdev&0xff)>>3, pdev&7, offset, pci_dev ? "" : " INVALID");
00215
00216 if (!pci_dev)
00217 return -L4_EINVAL;
00218
00219 return pci_read_config_byte(pci_dev, offset, val);
00220 }
00221
00234 long
00235 l4_io_pci_read_config_word_component (CORBA_Object _dice_corba_obj,
00236 l4_io_pdev_t pdev,
00237 long offset,
00238 unsigned short *val,
00239 CORBA_Server_Environment *_dice_corba_env)
00240 {
00241 void *pci_dev = _pci_get_addr(pdev);
00242
00243 LOGd(DEBUG_PCI_RW, "read %x:%02x.%x word %ld%s",
00244 pdev>>8, (pdev&0xff)>>3, pdev&7, offset, pci_dev ? "" : " INVALID");
00245
00246 if (!pci_dev)
00247 return -L4_EINVAL;
00248
00249 return pci_read_config_word(pci_dev, offset, val);
00250 }
00251
00264 long
00265 l4_io_pci_read_config_dword_component (CORBA_Object _dice_corba_obj,
00266 l4_io_pdev_t pdev,
00267 long offset,
00268 l4_uint32_t *val,
00269 CORBA_Server_Environment *_dice_corba_env)
00270 {
00271 void *pci_dev = _pci_get_addr(pdev);
00272
00273 LOGd(DEBUG_PCI_RW, "read %x:%02x.%x dword %ld%s",
00274 pdev>>8, (pdev&0xff)>>3, pdev&7, offset, pci_dev ? "" : " INVALID");
00275
00276 if (!pci_dev)
00277 return -L4_EINVAL;
00278
00279 return pci_read_config_dword(pci_dev, offset, val);
00280 }
00303 long
00304 l4_io_pci_write_config_byte_component (CORBA_Object _dice_corba_obj,
00305 l4_io_pdev_t pdev,
00306 long offset,
00307 unsigned char val,
00308 CORBA_Server_Environment *_dice_corba_env)
00309 {
00310 void *pci_dev = _pci_get_addr(pdev);
00311
00312 LOGd(DEBUG_PCI_RW, "write %x:%02x.%x byte %ld (val 0x%02x)%s",
00313 pdev>>8, (pdev&0xff)>>3, pdev&7, offset, val, pci_dev ? "" : " INVALID");
00314
00315 if (!pci_dev)
00316 return -L4_EINVAL;
00317
00318 if (pci_write_config_byte(pci_dev, offset, val))
00319 {
00320 #if DEBUG_PCI_RW
00321 LOG_Error("writing PCI configuration register");
00322 #endif
00323 return -L4_EUNKNOWN;
00324 }
00325
00326 return 0;
00327 }
00328
00341 long
00342 l4_io_pci_write_config_word_component (CORBA_Object _dice_corba_obj,
00343 l4_io_pdev_t pdev,
00344 long offset,
00345 unsigned short val,
00346 CORBA_Server_Environment *_dice_corba_env)
00347 {
00348 void *pci_dev = _pci_get_addr(pdev);
00349
00350 LOGd(DEBUG_PCI_RW, "write %x:%02x.%x word %ld (val 0x%02x)%s",
00351 pdev>>8, (pdev&0xff)>>3, pdev&7, offset, val, pci_dev ? "" : " INVALID");
00352
00353 if (!pci_dev)
00354 return -L4_EINVAL;
00355
00356 if (pci_write_config_word(pci_dev, offset, val))
00357 {
00358 #if DEBUG_PCI_RW
00359 LOG_Error("writing PCI configuration register");
00360 #endif
00361 return -L4_EUNKNOWN;
00362 }
00363
00364 return 0;
00365 }
00366
00379 long
00380 l4_io_pci_write_config_dword_component (CORBA_Object _dice_corba_obj,
00381 l4_io_pdev_t pdev,
00382 long offset,
00383 unsigned long val,
00384 CORBA_Server_Environment *_dice_corba_env)
00385 {
00386 void *pci_dev = _pci_get_addr(pdev);
00387
00388 LOGd(DEBUG_PCI_RW, "write %x:%02x.%x dword %ld (val 0x%02lx)%s",
00389 pdev>>8, (pdev&0xff)>>3, pdev&7, offset, val, pci_dev ? "" : " INVALID");
00390
00391 if (!pci_dev)
00392 return -L4_EINVAL;
00393
00394 if (pci_write_config_dword(pci_dev, offset, val))
00395 {
00396 #if DEBUG_PCI_RW
00397 LOG_Error("writing PCI configuration register");
00398 #endif
00399 return -L4_EUNKNOWN;
00400 }
00401
00402 return 0;
00403 }
00421 long
00422 l4_io_pci_enable_device_component (CORBA_Object _dice_corba_obj,
00423 l4_io_pdev_t pdev,
00424 CORBA_Server_Environment *_dice_corba_env)
00425 {
00426 int err;
00427 void *pci_dev = _pci_get_addr(pdev);
00428
00429 if (!pci_dev)
00430 return -L4_EINVAL;
00431
00432 err = pci_enable_device(pci_dev);
00433
00434 if (err)
00435 {
00436 LOGd(DEBUG_PCI, "enable %x:%02x.%x unsuccessfull (err=%d)",
00437 pdev>>8, (pdev&0xff)>>3, pdev&7, err);
00438 return err;
00439 }
00440
00441 LOGd(DEBUG_PCI, "enable %x:%02x.%x successfull",
00442 pdev>>8, (pdev&0xff)>>3, pdev&7);
00443
00444 return 0;
00445 }
00446
00457 long
00458 l4_io_pci_disable_device_component (CORBA_Object _dice_corba_obj,
00459 l4_io_pdev_t pdev,
00460 CORBA_Server_Environment *_dice_corba_env)
00461 {
00462 void *pci_dev = _pci_get_addr(pdev);
00463
00464 if (!pci_dev)
00465 return -L4_EINVAL;
00466
00467 pci_disable_device(pci_dev);
00468
00469 LOGd(DEBUG_PCI, "disable %x:%02x.%x successfull",
00470 pdev>>8, (pdev&0xff)>>3, pdev&7);
00471
00472 return 0;
00473 }
00474
00485 long
00486 l4_io_pci_set_master_component (CORBA_Object _dice_corba_obj,
00487 l4_io_pdev_t pdev,
00488 CORBA_Server_Environment *_dice_corba_env)
00489 {
00490 void *pci_dev = _pci_get_addr(pdev);
00491
00492 if (!pci_dev)
00493 return -L4_EINVAL;
00494
00495 pci_set_master(pci_dev);
00496
00497 LOGd(DEBUG_PCI, "busmastering for %x:%02x.%x enabled",
00498 pdev>>8, (pdev&0xff)>>3, pdev&7);
00499
00500 return 0;
00501 }
00502
00515 long
00516 l4_io_pci_set_power_state_component (CORBA_Object _dice_corba_obj,
00517 l4_io_pdev_t pdev,
00518 int *state,
00519 CORBA_Server_Environment *_dice_corba_env)
00520 {
00521 int old;
00522 void *pci_dev = _pci_get_addr(pdev);
00523
00524 if (!pci_dev)
00525 return -L4_EINVAL;
00526
00527 old = pci_set_power_state(pci_dev, *state);
00528
00529 LOGd(DEBUG_PCI, "%x:%02x.%x goes from %d to %d PM",
00530 pdev>>8, (pdev&0xff)>>3, pdev&7, old, *state);
00531
00532 *state = old;
00533
00534 return 0;
00535 }
00544 int io_pci_init(int list)
00545 {
00546 int err;
00547 unsigned long vaddr = 0;
00548
00549
00550 if ((err=bios_map_area(&vaddr)))
00551 return err;
00552
00553 LOGd(DEBUG_PCI, "BIOS mapped at %p", (void*)vaddr);
00554
00555
00556 return PCI_init(list);
00557 }