1/* 2 Driver for Intel(R) PRO/Wireless 2100 devices. 3 Copyright (C) 2006 Michael Lotz <mmlr@mlotz.ch> 4 Released under the terms of the MIT license. 5*/ 6 7#include <Drivers.h> 8#include <KernelExport.h> 9#include <PCI.h> 10#include <stdio.h> 11#include <string.h> 12 13#include "driver.h" 14#include "ipw2100.h" 15#include "kernel_cpp.h" 16 17 18status_t ipw2100_open(const char *name, uint32 flags, void **cookie); 19status_t ipw2100_close(void *cookie); 20status_t ipw2100_free(void *cookie); 21status_t ipw2100_control(void *cookie, uint32 op, void *args, size_t length); 22status_t ipw2100_read(void *cookie, off_t position, void *buffer, size_t *numBytes); 23status_t ipw2100_write(void *cookie, off_t position, const void *buffer, size_t *numBytes); 24 25 26int32 api_version = B_CUR_DRIVER_API_VERSION; 27 28 29pci_module_info *gPCIModule; 30char *gDeviceNameList[MAX_INSTANCES + 1]; 31pci_info *gDeviceList[MAX_INSTANCES]; 32int32 gOpenMask = 0; 33 34device_hooks gDeviceHooks = { 35 ipw2100_open, 36 ipw2100_close, 37 ipw2100_free, 38 ipw2100_control, 39 ipw2100_read, 40 ipw2100_write 41}; 42 43 44const char * 45identify_device(const pci_info *info) 46{ 47 if (info->vendor_id != VENDOR_ID_INTEL) 48 return NULL; 49 50 switch (info->device_id) { 51 case 0x1043: return "Intel(R) PRO/Wireless 2100"; 52 } 53 54 return NULL; 55} 56 57 58status_t 59init_hardware() 60{ 61#ifdef TRACE_IPW2100 62 set_dprintf_enabled(true); 63#endif 64 65 //TRACE((DRIVER_NAME": init hardware\n")); 66 67 pci_module_info *module; 68 status_t result = get_module(B_PCI_MODULE_NAME, (module_info **)&module); 69 if (result < B_OK) 70 return result; 71 72 int32 index = 0; 73 result = B_ERROR; 74 pci_info info; 75 while (module->get_nth_pci_info(index++, &info) == B_OK) { 76 const char *deviceName = identify_device(&info); 77 if (deviceName) { 78 TRACE((DRIVER_NAME": found device \"%s\"\n", deviceName)); 79 result = B_OK; 80 break; 81 } 82 } 83 84 put_module(B_PCI_MODULE_NAME); 85 return result; 86} 87 88 89status_t 90init_driver() 91{ 92 TRACE((DRIVER_NAME": init driver\n")); 93 94 for (int32 i = 0; i < MAX_INSTANCES; i++) 95 gDeviceList[i] = NULL; 96 for (int32 i = 0; i < MAX_INSTANCES + 1; i++) 97 gDeviceNameList[i] = NULL; 98 99 pci_info *info = new pci_info; 100 if (!info) 101 return B_NO_MEMORY; 102 103 status_t result = get_module(B_PCI_MODULE_NAME, (module_info **)&gPCIModule); 104 if (result < B_OK) { 105 delete info; 106 return result; 107 } 108 109 int32 index = 0; 110 int32 count = 0; 111 while (gPCIModule->get_nth_pci_info(index++, info) == B_OK 112 && count < MAX_INSTANCES) { 113 const char *deviceName = identify_device(info); 114 if (!deviceName) 115 continue; 116 117 char publishName[64]; 118 sprintf(publishName, "net/ipw2100/%ld", count); 119 120 gDeviceList[count] = info; 121 gDeviceNameList[count] = strdup(publishName); 122 123 info = new pci_info; 124 if (!info) 125 goto error_out_of_memory; 126 127 dprintf(DRIVER_NAME": will publish an \"%s\" as device %ld to /dev/%s\n", deviceName, count, publishName); 128 count++; 129 } 130 131 delete info; 132 return B_OK; 133 134error_out_of_memory: 135 for (int32 i = 0; i < MAX_INSTANCES; i++) { 136 free(gDeviceNameList[i]); 137 delete gDeviceList[i]; 138 gDeviceNameList[i] = NULL; 139 gDeviceList[i] = NULL; 140 } 141 142 put_module(B_PCI_MODULE_NAME); 143 return B_ERROR; 144} 145 146 147void 148uninit_driver() 149{ 150 TRACE((DRIVER_NAME": uninit driver\n")); 151 for (int32 i = 0; i < MAX_INSTANCES; i++) { 152 free(gDeviceNameList[i]); 153 delete gDeviceList[i]; 154 gDeviceNameList[i] = NULL; 155 gDeviceList[i] = NULL; 156 } 157 158 put_module(B_PCI_MODULE_NAME); 159} 160 161 162const char ** 163publish_devices(void) 164{ 165 //TRACE((DRIVER_NAME": publish devices\n")); 166 return (const char **)gDeviceNameList; 167} 168 169 170device_hooks * 171find_device(const char *name) 172{ 173 //TRACE((DRIVER_NAME": find device \"%s\"\n", name)); 174 175 for (int32 i = 0; i < MAX_INSTANCES; i++) { 176 if (strcmp(gDeviceNameList[i], name) == 0) 177 return &gDeviceHooks; 178 } 179 180 TRACE_ALWAYS((DRIVER_NAME": couldn't find device \"%s\"\n", name)); 181 return NULL; 182} 183 184 185//#pragma mark - 186 187 188status_t 189ipw2100_open(const char *name, uint32 flags, void **cookie) 190{ 191 //TRACE((DRIVER_NAME": open device\n")); 192 int32 deviceID = -1; 193 for (int32 i = 0; i < MAX_INSTANCES && gDeviceNameList[i]; i++) { 194 if (strcmp(gDeviceNameList[i], name) == 0) { 195 deviceID = i; 196 break; 197 } 198 } 199 200 if (deviceID < 0) 201 return B_ERROR; 202 203 // allow only one concurrent access 204 int32 mask = 1 << deviceID; 205 if (atomic_or(&gOpenMask, mask) & mask) 206 return B_BUSY; 207 208 IPW2100 *device = new IPW2100(deviceID, gDeviceList[deviceID], gPCIModule); 209 status_t result = device->InitCheck(); 210 if (device->InitCheck() < B_OK) { 211 delete device; 212 return result; 213 } 214 215 *cookie = (void *)device; 216 return device->Open(flags); 217} 218 219 220status_t 221ipw2100_close(void *cookie) 222{ 223 //TRACE((DRIVER_NAME": close device\n")); 224 IPW2100 *device = (IPW2100 *)cookie; 225 return device->Close(); 226} 227 228 229status_t 230ipw2100_free(void *cookie) 231{ 232 //TRACE((DRIVER_NAME": free device\n")); 233 IPW2100 *device = (IPW2100 *)cookie; 234 235 int32 mask = 1 << device->DeviceID(); 236 237 device->Free(); 238 delete device; 239 240 atomic_and(&gOpenMask, ~mask); 241 return B_OK; 242} 243 244 245status_t 246ipw2100_control(void *cookie, uint32 op, void *args, size_t length) 247{ 248 //TRACE((DRIVER_NAME": control device\n")); 249 IPW2100 *device = (IPW2100 *)cookie; 250 return device->Control(op, args, length); 251} 252 253 254status_t 255ipw2100_read(void *cookie, off_t position, void *buffer, size_t *numBytes) 256{ 257 //TRACE((DRIVER_NAME": read device\n")); 258 IPW2100 *device = (IPW2100 *)cookie; 259 return device->Read(position, buffer, numBytes); 260} 261 262 263status_t 264ipw2100_write(void *cookie, off_t position, const void *buffer, size_t *numBytes) 265{ 266 //TRACE((DRIVER_NAME": write device\n")); 267 IPW2100 *device = (IPW2100 *)cookie; 268 return device->Write(position, buffer, numBytes); 269} 270