1 /* Copyright (c) 2003-2011 2 * Stefano Ceccherini <stefano.ceccherini@gmail.com>. All rights reserved. 3 * This file is released under the MIT license 4 */ 5 #include <KernelExport.h> 6 #include <Errors.h> 7 #include <stdlib.h> 8 #include <stdio.h> 9 #include <string.h> 10 11 #include <net/if_media.h> 12 13 #include "debug.h" 14 #include "device.h" 15 #include "driver.h" 16 #include "interface.h" 17 #include "wb840.h" 18 19 20 #define MAX_CARDS 4 21 22 extern char* gDevNameList[]; 23 extern pci_info* gDevList[]; 24 25 static int32 sOpenMask = 0; 26 27 static status_t 28 wb840_open(const char* name, uint32 flags, void** cookie) 29 { 30 char* deviceName = NULL; 31 int32 i; 32 int32 mask; 33 struct wb_device* data; 34 status_t status; 35 36 LOG((DEVICE_NAME ": open()\n")); 37 38 for (i = 0; (deviceName = gDevNameList[i]) != NULL; i++) { 39 if (!strcmp(name, deviceName)) 40 break; 41 } 42 43 if (deviceName == NULL) { 44 LOG(("invalid device name")); 45 return EINVAL; 46 } 47 48 // There can be only one access at time 49 mask = 1L << i; 50 if (atomic_or(&sOpenMask, mask) & mask) 51 return B_BUSY; 52 53 // Allocate a wb_device structure 54 if (!(data = (wb_device*)calloc(1, sizeof(wb_device)))) { 55 sOpenMask &= ~(1L << i); 56 return B_NO_MEMORY; 57 } 58 59 *cookie = data; 60 61 #ifdef DEBUG 62 load_driver_symbols("wb840"); 63 #endif 64 65 data->devId = i; 66 data->pciInfo = gDevList[i]; 67 data->deviceName = gDevNameList[i]; 68 data->blockFlag = 0; 69 data->reg_base = data->pciInfo->u.h0.base_registers[0]; 70 data->wb_cachesize = gPci->read_pci_config(data->pciInfo->bus, 71 data->pciInfo->device, data->pciInfo->function, PCI_line_size, 72 sizeof(PCI_line_size)) & 0xff; 73 74 wb_read_eeprom(data, &data->MAC_Address, 0, 3, false); 75 76 status = wb_create_semaphores(data); 77 if (status < B_OK) { 78 LOG((DEVICE_NAME": couldn't create semaphores\n")); 79 goto err; 80 } 81 82 status = wb_stop(data); 83 if (status < B_OK) { 84 LOG((DEVICE_NAME": can't stop device\n")); 85 goto err1; 86 } 87 88 status = wb_initPHYs(data); 89 if (status < B_OK) { 90 LOG((DEVICE_NAME": can't init PHYs\n")); 91 goto err1; 92 } 93 94 wb_init(data); 95 96 /* Setup interrupts */ 97 data->irq = data->pciInfo->u.h0.interrupt_line; 98 status = install_io_interrupt_handler(data->irq, wb_interrupt, data, 0); 99 if (status < B_OK) { 100 LOG((DEVICE_NAME 101 ": can't install interrupt handler: %s\n", strerror(status))); 102 goto err1; 103 } 104 105 LOG((DEVICE_NAME ": interrupts installed at irq line %x\n", data->irq)); 106 107 status = wb_create_rings(data); 108 if (status < B_OK) { 109 LOG((DEVICE_NAME": can't create ring buffers\n")); 110 goto err2; 111 } 112 113 wb_enable_interrupts(data); 114 115 WB_SETBIT(data->reg_base + WB_NETCFG, WB_NETCFG_RX_ON); 116 write32(data->reg_base + WB_RXSTART, 0xFFFFFFFF); 117 WB_SETBIT(data->reg_base + WB_NETCFG, WB_NETCFG_TX_ON); 118 119 add_timer(&data->timer, wb_tick, 1000000LL, B_PERIODIC_TIMER); 120 121 return B_OK; // Everything after this line is an error 122 123 err2: 124 remove_io_interrupt_handler(data->irq, wb_interrupt, data); 125 126 err1: 127 wb_delete_semaphores(data); 128 129 err: 130 sOpenMask &= ~(1L << i); 131 132 free(data); 133 LOG(("wb840: Open Failed\n")); 134 135 return status; 136 } 137 138 139 static status_t 140 wb840_read(void* cookie, off_t position, void* buf, size_t* num_bytes) 141 { 142 wb_device* device = (wb_device*)cookie; 143 int16 current; 144 status_t status; 145 size_t size; 146 int32 blockFlag; 147 uint32 check; 148 149 LOG((DEVICE_NAME ": read()\n")); 150 151 blockFlag = device->blockFlag; 152 153 if (atomic_or(&device->rxLock, 1)) { 154 *num_bytes = 0; 155 return B_ERROR; 156 } 157 158 status = acquire_sem_etc(device->rxSem, 1, B_CAN_INTERRUPT | blockFlag, 0); 159 if (status < B_OK) { 160 atomic_and(&device->rxLock, 0); 161 *num_bytes = 0; 162 return status; 163 } 164 165 current = device->rxCurrent; 166 check = device->rxDescriptor[current].wb_status; 167 if (check & WB_RXSTAT_OWN) { 168 LOG((DEVICE_NAME ":ERROR: read: buffer %d still in use: %x\n", 169 (int)current, (int)status)); 170 atomic_and(&device->rxLock, 0); 171 *num_bytes = 0; 172 return B_BUSY; 173 } 174 175 if (check & (WB_RXSTAT_RXERR | WB_RXSTAT_CRCERR | WB_RXSTAT_RUNT)) { 176 LOG(("Error read: packet with errors.")); 177 *num_bytes = 0; 178 } else { 179 size = WB_RXBYTES(check); 180 size -= CRC_SIZE; 181 LOG((DEVICE_NAME": received %ld bytes\n", size)); 182 if (size > WB_MAX_FRAMELEN || size > *num_bytes) { 183 LOG(("ERROR: Bad frame size: %ld", size)); 184 size = *num_bytes; 185 } 186 *num_bytes = size; 187 memcpy(buf, (void*)device->rxBuffer[current], size); 188 } 189 190 device->rxCurrent = (current + 1) & WB_RX_CNT_MASK; 191 { 192 cpu_status former; 193 former = disable_interrupts(); 194 acquire_spinlock(&device->rxSpinlock); 195 196 // release buffer to ring 197 wb_put_rx_descriptor(&device->rxDescriptor[current]); 198 device->rxFree++; 199 200 release_spinlock(&device->rxSpinlock); 201 restore_interrupts(former); 202 } 203 204 atomic_and(&device->rxLock, 0); 205 206 return B_OK; 207 } 208 209 210 static status_t 211 wb840_write(void* cookie, off_t position, const void* buffer, size_t* num_bytes) 212 { 213 wb_device* device = (wb_device*)cookie; 214 status_t status = B_OK; 215 uint16 frameSize; 216 int16 current; 217 uint32 check; 218 219 LOG((DEVICE_NAME ": write()\n")); 220 221 atomic_add(&device->txLock, 1); 222 223 if (*num_bytes > WB_MAX_FRAMELEN) 224 *num_bytes = WB_MAX_FRAMELEN; 225 226 frameSize = *num_bytes; 227 current = device->txCurrent; 228 229 // block until a free tx descriptor is available 230 status = acquire_sem_etc(device->txSem, 1, B_TIMEOUT, ETHER_TRANSMIT_TIMEOUT); 231 if (status < B_OK) { 232 write32(device->reg_base + WB_TXSTART, 0xFFFFFFFF); 233 LOG((DEVICE_NAME": write: acquiring sem failed: %ld, %s\n", 234 status, strerror(status))); 235 atomic_add(&device->txLock, -1); 236 *num_bytes = 0; 237 return status; 238 } 239 240 check = device->txDescriptor[current].wb_status; 241 if (check & WB_TXSTAT_OWN) { 242 // descriptor is still in use 243 dprintf(DEVICE_NAME ": card owns buffer %d\n", (int)current); 244 atomic_add(&device->txLock, -1); 245 *num_bytes = 0; 246 return B_ERROR; 247 } 248 249 /* Copy data to tx buffer */ 250 memcpy((void*)device->txBuffer[current], buffer, frameSize); 251 device->txCurrent = (current + 1) & WB_TX_CNT_MASK; 252 LOG((DEVICE_NAME ": %d bytes written\n", frameSize)); 253 254 { 255 cpu_status former = disable_interrupts(); 256 acquire_spinlock(&device->txSpinlock); 257 258 device->txDescriptor[current].wb_ctl = WB_TXCTL_TLINK | frameSize; 259 device->txDescriptor[current].wb_ctl |= WB_TXCTL_FIRSTFRAG 260 | WB_TXCTL_LASTFRAG; 261 device->txDescriptor[current].wb_status = WB_TXSTAT_OWN; 262 device->txSent++; 263 264 release_spinlock(&device->txSpinlock); 265 restore_interrupts(former); 266 } 267 268 // re-enable transmit state machine 269 write32(device->reg_base + WB_TXSTART, 0xFFFFFFFF); 270 271 atomic_add(&device->txLock, -1); 272 273 return B_OK; 274 } 275 276 277 static status_t 278 wb840_control (void* cookie, uint32 op, void* arg, size_t len) 279 { 280 wb_device* data = (wb_device*)cookie; 281 282 LOG((DEVICE_NAME ": control()\n")); 283 switch (op) { 284 case ETHER_INIT: 285 LOG(("%s: ETHER_INIT\n", data->deviceName)); 286 return B_OK; 287 288 case ETHER_GETADDR: 289 LOG(("%s: ETHER_GETADDR\n", data->deviceName)); 290 memcpy(arg, &data->MAC_Address, sizeof(data->MAC_Address)); 291 print_address(arg); 292 return B_OK; 293 294 case ETHER_NONBLOCK: 295 LOG(("ETHER_NON_BLOCK\n")); 296 data->blockFlag = *(int32*)arg ? B_TIMEOUT : 0; 297 return B_OK; 298 299 case ETHER_GETFRAMESIZE: 300 LOG(("ETHER_GETFRAMESIZE\n")); 301 *(uint32 *)arg = WB_MAX_FRAMELEN; 302 return B_OK; 303 304 case ETHER_GET_LINK_STATE: 305 { 306 ether_link_state_t state; 307 LOG(("ETHER_GET_LINK_STATE")); 308 309 state.media = (data->link ? IFM_ACTIVE : 0) | IFM_ETHER 310 | (data->full_duplex ? IFM_FULL_DUPLEX : IFM_HALF_DUPLEX) 311 | (data->speed == LINK_SPEED_100_MBIT ? IFM_100_TX : IFM_10_T); 312 state.speed = data->speed == LINK_SPEED_100_MBIT 313 ? 100000000 : 10000000; 314 state.quality = 1000; 315 316 return user_memcpy(arg, &state, sizeof(ether_link_state_t)); 317 } 318 319 case ETHER_ADDMULTI: 320 LOG(("ETHER_ADDMULTI\n")); 321 break; 322 323 case ETHER_REMMULTI: 324 LOG(("ETHER_REMMULTI\n")); 325 break; 326 327 case ETHER_SETPROMISC: 328 LOG(("ETHER_SETPROMISC\n")); 329 break; 330 331 default: 332 LOG(("Invalid command\n")); 333 break; 334 } 335 336 return B_ERROR; 337 } 338 339 340 static status_t 341 wb840_close(void* cookie) 342 { 343 wb_device* device = (wb_device*)cookie; 344 345 LOG((DEVICE_NAME ": close()\n")); 346 347 cancel_timer(&device->timer); 348 349 wb_stop(device); 350 351 write32(device->reg_base + WB_TXADDR, 0x00000000); 352 write32(device->reg_base + WB_RXADDR, 0x00000000); 353 354 wb_disable_interrupts(device); 355 remove_io_interrupt_handler(device->irq, wb_interrupt, device); 356 357 delete_sem(device->rxSem); 358 delete_sem(device->txSem); 359 360 return B_OK; 361 } 362 363 364 static status_t 365 wb840_free(void* cookie) 366 { 367 wb_device* device = (wb_device*)cookie; 368 369 LOG((DEVICE_NAME ": free()\n")); 370 371 sOpenMask &= ~(1L << device->devId); 372 373 wb_delete_rings(device); 374 free(device->firstPHY); 375 free(device); 376 377 return B_OK; 378 } 379 380 381 device_hooks 382 gDeviceHooks = { 383 wb840_open, /* -> open entry point */ 384 wb840_close, /* -> close entry point */ 385 wb840_free, /* -> free cookie */ 386 wb840_control, /* -> control entry point */ 387 wb840_read, /* -> read entry point */ 388 wb840_write, /* -> write entry point */ 389 NULL, 390 NULL, 391 NULL, 392 NULL 393 }; 394