00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00036 #include <errno.h>
00037 #include <assert.h>
00038 #include <as.h>
00039 #include <devman.h>
00040 #include <ddi.h>
00041 #include <libarch/ddi.h>
00042 #include <device/hw_res.h>
00043
00044 #include <usb/debug.h>
00045 #include <pci_dev_iface.h>
00046
00047 #include "pci.h"
00048
00057 int pci_get_my_registers(ddf_dev_t *dev,
00058 uintptr_t *mem_reg_address, size_t *mem_reg_size, int *irq_no)
00059 {
00060 assert(dev);
00061 assert(mem_reg_address);
00062 assert(mem_reg_size);
00063 assert(irq_no);
00064
00065 int parent_phone = devman_parent_device_connect(dev->handle,
00066 IPC_FLAG_BLOCKING);
00067 if (parent_phone < 0) {
00068 return parent_phone;
00069 }
00070
00071 int rc;
00072
00073 hw_resource_list_t hw_resources;
00074 rc = hw_res_get_resource_list(parent_phone, &hw_resources);
00075 if (rc != EOK) {
00076 async_hangup(parent_phone);
00077 return rc;
00078 }
00079
00080 uintptr_t mem_address = 0;
00081 size_t mem_size = 0;
00082 bool mem_found = false;
00083
00084 int irq = 0;
00085 bool irq_found = false;
00086
00087 size_t i;
00088 for (i = 0; i < hw_resources.count; i++) {
00089 hw_resource_t *res = &hw_resources.resources[i];
00090 switch (res->type)
00091 {
00092 case INTERRUPT:
00093 irq = res->res.interrupt.irq;
00094 irq_found = true;
00095 usb_log_debug2("Found interrupt: %d.\n", irq);
00096 break;
00097
00098 case MEM_RANGE:
00099 if (res->res.mem_range.address != 0
00100 && res->res.mem_range.size != 0 ) {
00101 mem_address = res->res.mem_range.address;
00102 mem_size = res->res.mem_range.size;
00103 usb_log_debug2("Found mem: %p %zu.\n",
00104 (void *) mem_address, mem_size);
00105 mem_found = true;
00106 }
00107 default:
00108 break;
00109 }
00110 }
00111
00112 if (mem_found && irq_found) {
00113 *mem_reg_address = mem_address;
00114 *mem_reg_size = mem_size;
00115 *irq_no = irq;
00116 rc = EOK;
00117 } else {
00118 rc = ENOENT;
00119 }
00120
00121 async_hangup(parent_phone);
00122 return rc;
00123 }
00124
00130 int pci_enable_interrupts(ddf_dev_t *device)
00131 {
00132 int parent_phone =
00133 devman_parent_device_connect(device->handle, IPC_FLAG_BLOCKING);
00134 if (parent_phone < 0) {
00135 return parent_phone;
00136 }
00137 bool enabled = hw_res_enable_interrupt(parent_phone);
00138 async_hangup(parent_phone);
00139 return enabled ? EOK : EIO;
00140 }