#include "rtl_3c905cx_drv.h"
#include "rt_pci.h"
#include "netif/net_policy/FIFO_policy.h"
Include dependency graph for rtl_3c905cx_drv.c:
Go to the source code of this file.
Defines | |
#define | COM3_905C_MAJOR 204 |
#define | COM3_905C_NAME "eth" |
#define | COM3_SIGNAL RTL_SIGUSR2 |
#define | rtl_3COM905C_mdio_delay() inl(mdio_addr) |
#define | MDIO_SHIFT_CLK 0x01 |
#define | MDIO_DIR_WRITE 0x04 |
#define | MDIO_DATA_WRITE0 (0x00 | MDIO_DIR_WRITE) |
#define | MDIO_DATA_WRITE1 (0x02 | MDIO_DIR_WRITE) |
#define | MDIO_DATA_READ 0x02 |
#define | MDIO_ENB_IN 0x00 |
Functions | |
MODULE_LICENSE ("GPL") | |
int | rt_3c905c_set_ip_filter (unsigned long ipaddr) |
int | rt_3c905c_obtain_mac_address (unsigned char *mac) |
ssize_t | rtl_3COM905C_read (struct rtl_file *filp, char *buf, size_t count, loff_t *ppos) |
int | rtl_3COM905C_ioctl (struct rtl_file *filp, unsigned int request, unsigned long other) |
int | rtl_3COM905C_release (struct rtl_file *filp) |
ssize_t | rtl_3COM905C_write (struct rtl_file *filp, const char *buf, size_t count, loff_t *ppos) |
int | rtl_3COM905C_open (struct rtl_file *filp) |
pci_dev * | rtl_3COM905C_init_device (void) |
int | init_module (void) |
void | cleanup_module (void) |
unsigned int | boomerang_interrupt (unsigned int irq, struct pt_regs *regs) |
int | boomerang_rx (struct pci_dev *dev) |
int | rtl_3COM905C_start_up_device (struct pci_dev *dev) |
void | rtl_3COM905C_acpi_set_WOL (void) |
int | vortex_open (struct pci_dev *dev) |
void | vortex_up (struct pci_dev *dev) |
void | rtl_3COM905C_issue_and_wait (int cmd) |
void | rtl_3COM905C_set_rx_mode (void) |
void | vortex_down (struct pci_dev *dev) |
int | vortex_close (struct pci_dev *dev) |
void | vortex_error (struct pci_dev *dev, int status) |
void | vortex_remove_one (struct pci_dev *pdev) |
int | rt_3c905c_send_packet (const char *buffer, size_t size) |
void | rtl_3COM905C_mdio_sync (long ioaddr, int bits) |
int | rtl_3COM905C_mdio_read (int phy_id, int location) |
void | rtl_3COM905C_mdio_write (int phy_id, int location, int value) |
Variables | |
net_policy_operations | rt_3c905x_policy |
fifo_rx_buffer_t | rt_3c905x_rx_buffer |
sem_t | rt_3c905x_sem |
int | rt_3c905c_inside_the_interrupt_handler = 0 rt_3c905c_trying_to_close = 0 |
int | rt_3c905c_interrupted = 0 rt_3c905c_writting = 0 |
rtl_file_operations | rtl_3COM905C_fops |
pci_dev * | rt_3c905c_dev |
vortex_private | rt_3c905c_vp |
unsigned char | rt_3c905c_registered = 0x00 rt_3c905c_opened = 0x00 |
unsigned char | rt_3c905c_ip_addr [2][4] = {{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}} |
int | rt_3c905c_n_filters = 0 |
|
Definition at line 248 of file rtl_3c905cx_drv.c. Referenced by cleanup_module(), init_module(), and rtl_3COM905C_open(). |
|
Definition at line 249 of file rtl_3c905cx_drv.c. |
|
Definition at line 250 of file rtl_3c905cx_drv.c. |
|
Definition at line 1386 of file rtl_3c905cx_drv.c. Referenced by rtl_3COM905C_mdio_read(). |
|
Definition at line 1384 of file rtl_3c905cx_drv.c. Referenced by rtl_3COM905C_mdio_read(), and rtl_3COM905C_mdio_write(). |
|
Definition at line 1385 of file rtl_3c905cx_drv.c. Referenced by rtl_3COM905C_mdio_read(), rtl_3COM905C_mdio_sync(), and rtl_3COM905C_mdio_write(). |
|
Definition at line 1383 of file rtl_3c905cx_drv.c. |
|
Definition at line 1387 of file rtl_3c905cx_drv.c. Referenced by rtl_3COM905C_mdio_read(), and rtl_3COM905C_mdio_write(). |
|
Definition at line 1382 of file rtl_3c905cx_drv.c. Referenced by rtl_3COM905C_mdio_read(), rtl_3COM905C_mdio_sync(), and rtl_3COM905C_mdio_write(). |
|
Definition at line 1380 of file rtl_3c905cx_drv.c. Referenced by rtl_3COM905C_mdio_read(), rtl_3COM905C_mdio_sync(), and rtl_3COM905C_mdio_write(). |
|
Definition at line 477 of file rtl_3c905cx_drv.c. References AckIntr, boomerang_rx(), vortex_private::cb_fn_base, vortex_private::cur_rx, DownComplete, EL3_CMD, EL3_STATUS, HostError, IntLatch, IntReq, vortex_private::ioaddr, vortex_private::pdev, rt_3c905c_dev, rt_3c905c_inside_the_interrupt_handler, rt_3c905c_interrupted, rt_3c905c_vp, rtl_3COM905C_issue_and_wait(), vortex_private::rx_packets, vortex_private::rx_ring, RX_RING_SIZE, RxEarly, StatsFull, status, UpComplete, UpStall, UpUnstall, and vortex_error(). Referenced by vortex_open().
00477 { 00478 long ioaddr = rt_3c905c_vp.ioaddr; 00479 int status = inw(ioaddr + EL3_STATUS); 00480 int work_done = max_interrupt_work; 00481 struct pci_dev *dev = rt_3c905c_dev; 00482 00483 rt_3c905c_inside_the_interrupt_handler = 1; 00484 rt_3c905c_interrupted++; 00485 if(rt_3c905c_writting & rt_3c905c_interrupted) 00486 rtl_printf("I've been interrupted %d times\n",rt_3c905c_interrupted); 00487 00488 if (status & UpComplete) { 00489 rt_3c905c_vp.rx_packets++; 00490 rtl_3COM905C_issue_and_wait(UpStall); 00491 while(rt_3c905c_vp.rx_ring[rt_3c905c_vp.cur_rx % RX_RING_SIZE].status & 0x00008000){ 00492 boomerang_rx(dev); 00493 outw(AckIntr | UpComplete, ioaddr + EL3_CMD); 00494 if (--work_done < 0) 00495 break; 00496 } 00497 outw(UpUnstall, ioaddr + EL3_CMD); 00498 } 00499 00500 if (status & DownComplete){ 00501 rtl_printf("Se acaba de enviar el paquete\n"); 00502 outw(AckIntr | DownComplete, ioaddr + EL3_CMD); 00503 } 00504 00505 /* Check for all uncommon interrupts at once. */ 00506 if (status & (HostError | RxEarly | StatsFull | IntReq)){ 00507 rtl_printf("VORTEX_ERROR\n"); 00508 vortex_error(dev, status); 00509 } 00510 00511 /* Acknowledge the IRQ. */ 00512 outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD); 00513 if (rt_3c905c_vp.cb_fn_base){ 00514 writel(0x8000, rt_3c905c_vp.cb_fn_base + 4); 00515 } 00516 00517 /* We must be sure that we're out of the interrupt handler before cleanup_modules */ 00518 /* is executed. If cleanup_modules is being executed, we don't have to enable the */ 00519 /* irq. If enabled, then the system could crash. */ 00520 if(!rt_3c905c_trying_to_close) 00521 rtl_hard_enable_irq(rt_3c905c_vp.pdev->irq); 00522 00523 rt_3c905c_interrupted--; 00524 00525 return (rt_3c905c_inside_the_interrupt_handler = 0); 00526 } |
Here is the call graph for this function:
|
Definition at line 532 of file rtl_3c905cx_drv.c. References net_policy_operations::add_frame_to_buffer, buffer, vortex_private::cur_rx, vortex_private::dev_addr, vortex_private::dirty_rx, rt_3c905c_ip_addr, rt_3c905c_n_filters, rt_3c905c_vp, rt_3c905x_policy, rt_3c905x_rx_buffer, rt_3c905x_sem, vortex_private::rx_frames_for_us, vortex_private::rx_ring, RX_RING_SIZE, vortex_private::rx_skbuff, RxDComplete, RxDError, vortex_private::stats, and boom_rx_desc::status.
00533 { 00534 int entry = rt_3c905c_vp.cur_rx % RX_RING_SIZE; 00535 int rx_status; 00536 int rx_work_limit = rt_3c905c_vp.dirty_rx + RX_RING_SIZE - rt_3c905c_vp.cur_rx; 00537 int i,j; 00538 unsigned char *buffer; 00539 int temp = rt_3c905c_vp.rx_ring[entry].status & 0x1fff; 00540 unsigned char mine = 0x01, multicast_packet= 0x01, arp_request_for_me = 0x01 ; 00541 00542 buffer =rt_3c905c_vp.rx_skbuff[entry]; 00543 00544 /* A NIC receives all the packets in the LAN so we will receive an interrupt for each one of those. */ 00545 /* As we only want those packets sent to us we must filter them. So, we will only receive packets */ 00546 /* directly sent us (i.e. destination address is ours) and those ARP frames which ask for our MAC. */ 00547 /* An ARP improvement consist on receive all ARP request packets in the LAN, so, at least, we could */ 00548 /* know the pair IP and MAC address of those computers performing the request. As most of the */ 00549 /* frames in a LAN are ARP request frames the overhead produced by receiving all of them would be */ 00550 /* considerable, so we won't bother with this improvement. */ 00551 00552 //Is this frame for us?? 00553 for(i=0; i<6; i++){ 00554 if(buffer[i] == rt_3c905c_vp.dev_addr[i]) 00555 continue; 00556 else{ 00557 mine = 0x00; 00558 break; 00559 } 00560 } 00561 00562 if(mine == 0x01) goto accept_frame; 00563 00564 // Is an ARP frame??? 00565 if((buffer[12]==0x08) && (buffer[13]==0x06)){ 00566 // It asks for my IP?? 00567 for(j=0; j<rt_3c905c_n_filters; j++){ 00568 for(i=0; i<4;i++){ 00569 if(buffer[38+i]==rt_3c905c_ip_addr[j][i]) 00570 continue; 00571 else{ 00572 arp_request_for_me = 0x00; 00573 break; 00574 } 00575 } 00576 } 00577 }else 00578 arp_request_for_me = 0x00; 00579 00580 // Is it a multicast frame?? 00581 for(i=0; i<6; i++){ 00582 if(buffer[i] == 0xff) 00583 continue; 00584 else{ 00585 multicast_packet = 0x00; 00586 break; 00587 } 00588 } 00589 00590 accept_frame: 00591 00592 if((mine == 0x01) || ((multicast_packet==0x01) && (arp_request_for_me==0x01))){ 00593 rt_3c905c_vp.rx_frames_for_us++; 00594 00595 if(rt_3c905x_policy.add_frame_to_buffer((void *) &rt_3c905x_rx_buffer,buffer,temp)== 0){ 00596 sem_post(&rt_3c905x_sem); 00597 00598 rtl_schedule(); 00599 } 00600 } 00601 00602 while ((rx_status = le32_to_cpu(rt_3c905c_vp.rx_ring[entry].status)) & RxDComplete){ 00603 00604 if (--rx_work_limit < 0) 00605 break; 00606 if (!(rx_status & RxDError)) /* Error, update stats. */ 00607 rt_3c905c_vp.stats.rx_packets++; 00608 } 00609 00610 entry = (++rt_3c905c_vp.cur_rx) % RX_RING_SIZE; 00611 00612 /* Refill the Rx ring buffers. */ 00613 for (; rt_3c905c_vp.cur_rx - rt_3c905c_vp.dirty_rx > 0; rt_3c905c_vp.dirty_rx++) { 00614 entry = rt_3c905c_vp.dirty_rx % RX_RING_SIZE; 00615 rt_3c905c_vp.rx_ring[entry].status = 0; /* Clear complete bit. */ 00616 } 00617 return 0; 00618 } |
|
Definition at line 434 of file rtl_3c905cx_drv.c. References COM3_905C_MAJOR, COM3_905C_NAME, DownStall, vortex_private::pdev, rt_3c905c_inside_the_interrupt_handler, rt_3c905c_registered, rt_3c905c_vp, rtl_3COM905C_issue_and_wait(), and UpStall.
00434 { 00435 int inside = 1; 00436 rtl_irqstate_t state; 00437 00438 if((rt_3c905c_opened == 0x01) || rt_3c905c_inside_the_interrupt_handler){ 00439 00440 rt_3c905c_trying_to_close = 1; 00441 00442 /* Since inside the interrupt handler there's a call to the scheduler, there may */ 00443 /* be an execution of the interrupt handler that hasn't been completely executed. */ 00444 /* The card cannot be released in that case, so we must be sure that there is no */ 00445 /* interrupt handler execution pending. Otherwise, that may crash the system. */ 00446 while(inside){ 00447 rtl_no_interrupts(state); 00448 00449 if(rt_3c905c_inside_the_interrupt_handler){ 00450 rtl_restore_interrupts(state); 00451 usleep(10); 00452 }else{ 00453 rtl_hard_disable_irq(rt_3c905c_vp.pdev->irq); 00454 rtl_restore_interrupts(state); 00455 inside = 0; 00456 } 00457 } 00458 00459 rtl_3COM905C_issue_and_wait(UpStall); 00460 rtl_3COM905C_issue_and_wait(DownStall); 00461 } 00462 00463 if(rt_3c905c_registered == 0x01){ 00464 printk("Unregistering device /dev/%s\n",COM3_905C_NAME); 00465 rtl_unregister_rtldev(COM3_905C_MAJOR,COM3_905C_NAME); 00466 } 00467 00468 printk("\n\n\nRT-Linux driver for the Ethernet Card 3Com905c-x being removed\n\n\n"); 00469 } |
Here is the call graph for this function:
|
Definition at line 416 of file rtl_3c905cx_drv.c. References COM3_905C_MAJOR, COM3_905C_NAME, rt_3c905c_registered, and rtl_3COM905C_fops.
00416 { 00417 printk("\n\n\nRT-Linux driver for the Ethernet Card 3Com905c-x being loaded\n\n\n"); 00418 00419 if (rtl_register_rtldev (COM3_905C_MAJOR, COM3_905C_NAME, &rtl_3COM905C_fops)) { 00420 printk ("RTLinux /dev/%s: unable to get RTLinux major %d\n", COM3_905C_NAME, COM3_905C_MAJOR); 00421 return -EIO; 00422 }else{ 00423 printk("Registered device 3Com905C-X: /dev/%s major number %d\n",COM3_905C_NAME, COM3_905C_MAJOR); 00424 rt_3c905c_registered = 0x01; 00425 return 0; 00426 } 00427 } |
|
|
|
Definition at line 293 of file rtl_3c905cx_drv.c. References vortex_private::dev_addr, and rt_3c905c_vp. Referenced by rtl_3COM905C_ioctl().
00293 { 00294 int i; 00295 for(i=0; i<6; i++) 00296 mac[i]=rt_3c905c_vp.dev_addr[i]; 00297 return 0; 00298 } |
|
Definition at line 1329 of file rtl_3c905cx_drv.c. References buffer, vortex_private::cur_tx, DownListPtr, DownStall, DownUnstall, EL3_CMD, vortex_private::ioaddr, LAST_FRAG, boom_tx_desc::next, vortex_private::queued_packet, rt_3c905c_vp, rtl_3COM905C_issue_and_wait(), vortex_private::tx_ring, vortex_private::tx_ring_dma, TX_RING_SIZE, and vortex_private::tx_skbuff.
01330 { 01331 long ioaddr = rt_3c905c_vp.ioaddr; 01332 unsigned char *buff; 01333 int entry = rt_3c905c_vp.cur_tx % TX_RING_SIZE; 01334 int previous = (rt_3c905c_vp.cur_tx + TX_RING_SIZE - 1) % TX_RING_SIZE; 01335 struct boom_tx_desc *actual = &rt_3c905c_vp.tx_ring[entry]; 01336 01337 rt_3c905c_writting = 1; 01338 01339 /* Wait for the stall to complete. */ 01340 rtl_3COM905C_issue_and_wait(DownStall); 01341 01342 buff = rt_3c905c_vp.tx_skbuff[entry]; 01343 01344 if(buff) 01345 memcpy(buff, buffer, size); 01346 01347 actual->length = cpu_to_le32(size | LAST_FRAG); 01348 01349 if (inl(ioaddr + DownListPtr) == 0) { 01350 outl(rt_3c905c_vp.tx_ring_dma + entry * sizeof(struct boom_tx_desc), ioaddr + DownListPtr); 01351 { 01352 int tmp = previous; 01353 01354 while((rt_3c905c_vp.tx_ring[tmp].next != 0) && (tmp != entry)){ 01355 rt_3c905c_vp.tx_ring[tmp].next = 0; 01356 tmp = (tmp + TX_RING_SIZE - 1) % TX_RING_SIZE; 01357 } 01358 } 01359 rt_3c905c_vp.queued_packet++; 01360 }else 01361 rt_3c905c_vp.tx_ring[previous].next = cpu_to_le32(rt_3c905c_vp.tx_ring_dma + sizeof(struct boom_tx_desc) * entry); 01362 01363 outw(DownUnstall, ioaddr + EL3_CMD); 01364 01365 rt_3c905c_vp.cur_tx++; 01366 01367 rt_3c905c_writting = 0; 01368 01369 return size; 01370 } |
Here is the call graph for this function:
|
Definition at line 275 of file rtl_3c905cx_drv.c. References ipaddr, rt_3c905c_ip_addr, and rt_3c905c_n_filters. Referenced by rtl_3COM905C_ioctl().
00275 { 00276 if(rt_3c905c_n_filters<=1){ 00277 rt_3c905c_ip_addr[rt_3c905c_n_filters][0]=ipaddr & 0x000000ff; 00278 rt_3c905c_ip_addr[rt_3c905c_n_filters][1]= (ipaddr >> 8) & 0x000000ff; 00279 rt_3c905c_ip_addr[rt_3c905c_n_filters][2]= (ipaddr >> 16) & 0x000000ff; 00280 rt_3c905c_ip_addr[rt_3c905c_n_filters][3]= (ipaddr >> 24) & 0x000000ff; 00281 rt_3c905c_n_filters++; 00282 return 0; 00283 } 00284 00285 rtl_printf("You cannot set more than 2 IP filters !!"); 00286 return -1; 00287 } |
|
Definition at line 865 of file rtl_3c905cx_drv.c. References EL3_CMD, EL3WINDOW, vortex_private::ioaddr, vortex_private::pdev, rt_3c905c_vp, rt_pci_enable_wake(), rt_pci_set_power_state(), RxBroadcast, RxEnable, RxStation, and SetRxFilter. Referenced by rtl_3COM905C_start_up_device(), and vortex_down().
00866 { 00867 long ioaddr = rt_3c905c_vp.ioaddr; 00868 00869 /* Power up on: 1==Downloaded Filter, 2==Magic Packets, 4==Link Status. */ 00870 EL3WINDOW(7); 00871 outw(2, ioaddr + 0x0c); 00872 /* The RxFilter must accept the WOL frames. */ 00873 outw(SetRxFilter|RxStation|RxBroadcast, ioaddr + EL3_CMD); //RxMulticast 00874 outw(RxEnable, ioaddr + EL3_CMD); 00875 00876 /* Change the power state to D3; RxEnable doesn't take effect. */ 00877 rt_pci_enable_wake(rt_3c905c_vp.pdev, 0, 1); 00878 rt_pci_set_power_state(rt_3c905c_vp.pdev, 3); 00879 } |
Here is the call graph for this function:
|
Definition at line 393 of file rtl_3c905cx_drv.c. References COM3_DEVICE_ID, COM3_VENDOR_ID, net_policy_operations::initialize_rx_buffer, NULL, rt_3c905x_policy, rt_3c905x_rx_buffer, rt_pci_enable_device(), and rt_pci_find_device(). Referenced by rtl_3COM905C_open().
00393 { 00394 struct pci_dev *dev; 00395 00396 /* First of all, we must get a pointer to the pci_dev structure */ 00397 if((dev = rt_pci_find_device(COM3_VENDOR_ID, COM3_DEVICE_ID, NULL))== NULL) 00398 return NULL; 00399 00400 rt_3c905x_policy.initialize_rx_buffer(&rt_3c905x_rx_buffer); 00401 00402 /* Let's enable the device */ 00403 if (rt_pci_enable_device(dev)){ 00404 rtl_printf("PCI ERROR: Can't enable device 3Com905C-X\n"); 00405 return NULL; 00406 } 00407 00408 return dev; 00409 } |
Here is the call graph for this function:
|
Definition at line 313 of file rtl_3c905cx_drv.c. References rt_3c905c_obtain_mac_address(), and rt_3c905c_set_ip_filter().
00313 { 00314 00315 switch(request) { 00316 case 1: /* set_ip_filter */ 00317 rt_3c905c_set_ip_filter(other); 00318 break; 00319 case 2: /* obtain_mac_address */ 00320 rt_3c905c_obtain_mac_address((unsigned char *)other); 00321 break; 00322 } 00323 return 0; 00324 } |
Here is the call graph for this function:
|
Definition at line 1126 of file rtl_3c905cx_drv.c. References CmdInProgress, EL3_CMD, EL3_STATUS, vortex_private::ioaddr, and rt_3c905c_vp.
01127 { 01128 int i; 01129 01130 outw(cmd, rt_3c905c_vp.ioaddr + EL3_CMD); 01131 for (i = 0; i < 2000; i++) { 01132 if (!(inw(rt_3c905c_vp.ioaddr + EL3_STATUS) & CmdInProgress)) 01133 return; 01134 } 01135 01136 /* OK, that didn't work. Do it the slow way. One second */ 01137 for (i = 0; i < 100000; i++) { 01138 if (!(inw(rt_3c905c_vp.ioaddr + EL3_STATUS) & CmdInProgress)) { 01139 return; 01140 } 01141 usleep(10); 01142 } 01143 printk(KERN_ERR ": command 0x%04x did not complete! Status=0x%x\n", 01144 cmd, inw(rt_3c905c_vp.ioaddr + EL3_STATUS)); 01145 } |
|
Definition at line 1407 of file rtl_3c905cx_drv.c. References vortex_private::ioaddr, MDIO_DATA_READ, MDIO_DATA_WRITE0, MDIO_DATA_WRITE1, MDIO_ENB_IN, MDIO_SHIFT_CLK, rt_3c905c_vp, rtl_3COM905C_mdio_delay, rtl_3COM905C_mdio_sync(), and Wn4_PhysicalMgmt.
01408 { 01409 int i; 01410 long ioaddr = rt_3c905c_vp.ioaddr; 01411 int read_cmd = (0xf6 << 10) | (phy_id << 5) | location; 01412 unsigned int retval = 0; 01413 long mdio_addr = ioaddr + Wn4_PhysicalMgmt; 01414 01415 if (mii_preamble_required) 01416 rtl_3COM905C_mdio_sync(ioaddr, 32); 01417 01418 /* Shift the read command bits out. */ 01419 for (i = 14; i >= 0; i--) { 01420 int dataval = (read_cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0; 01421 outw(dataval, mdio_addr); 01422 rtl_3COM905C_mdio_delay(); 01423 outw(dataval | MDIO_SHIFT_CLK, mdio_addr); 01424 rtl_3COM905C_mdio_delay(); 01425 } 01426 /* Read the two transition, 16 data, and wire-idle bits. */ 01427 for (i = 19; i > 0; i--) { 01428 outw(MDIO_ENB_IN, mdio_addr); 01429 rtl_3COM905C_mdio_delay(); 01430 retval = (retval << 1) | ((inw(mdio_addr) & MDIO_DATA_READ) ? 1 : 0); 01431 outw(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr); 01432 rtl_3COM905C_mdio_delay(); 01433 } 01434 01435 return retval & 0x20000 ? 0xffff : retval>>1 & 0xffff; 01436 } |
Here is the call graph for this function:
|
Definition at line 1393 of file rtl_3c905cx_drv.c. References MDIO_DATA_WRITE1, MDIO_SHIFT_CLK, rtl_3COM905C_mdio_delay, and Wn4_PhysicalMgmt.
01394 { 01395 long mdio_addr = ioaddr + Wn4_PhysicalMgmt; 01396 01397 /* Establish sync by sending at least 32 logic ones. */ 01398 while (-- bits >= 0) { 01399 outw(MDIO_DATA_WRITE1, mdio_addr); 01400 rtl_3COM905C_mdio_delay(); 01401 outw(MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr); 01402 rtl_3COM905C_mdio_delay(); 01403 } 01404 } |
|
Definition at line 1439 of file rtl_3c905cx_drv.c. References vortex_private::ioaddr, MDIO_DATA_WRITE0, MDIO_DATA_WRITE1, MDIO_ENB_IN, MDIO_SHIFT_CLK, rt_3c905c_vp, rtl_3COM905C_mdio_delay, rtl_3COM905C_mdio_sync(), and Wn4_PhysicalMgmt.
01440 { 01441 long ioaddr = rt_3c905c_vp.ioaddr; 01442 int write_cmd = 0x50020000 | (phy_id << 23) | (location << 18) | value; 01443 long mdio_addr = ioaddr + Wn4_PhysicalMgmt; 01444 int i; 01445 01446 if (mii_preamble_required) 01447 rtl_3COM905C_mdio_sync(ioaddr, 32); 01448 01449 /* Shift the command bits out. */ 01450 for (i = 31; i >= 0; i--) { 01451 int dataval = (write_cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0; 01452 outw(dataval, mdio_addr); 01453 rtl_3COM905C_mdio_delay(); 01454 outw(dataval | MDIO_SHIFT_CLK, mdio_addr); 01455 rtl_3COM905C_mdio_delay(); 01456 } 01457 /* Leave the interface idle. */ 01458 for (i = 1; i >= 0; i--) { 01459 outw(MDIO_ENB_IN, mdio_addr); 01460 rtl_3COM905C_mdio_delay(); 01461 outw(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr); 01462 rtl_3COM905C_mdio_delay(); 01463 } 01464 return; 01465 } |
Here is the call graph for this function:
|
Definition at line 368 of file rtl_3c905cx_drv.c. References COM3_905C_MAJOR, NULL, rt_3c905c_dev, rt_3c905x_sem, rtl_3COM905C_init_device(), rtl_3COM905C_release(), and rtl_3COM905C_start_up_device().
00368 { 00369 00370 rtl_3COM905C_release (filp); 00371 00372 if(rt_3c905c_opened == 0x00){ 00373 if((rt_3c905c_dev = rtl_3COM905C_init_device())!=NULL){ 00374 00375 sem_init(&rt_3c905x_sem, 0, 0); 00376 00377 rtl_3COM905C_start_up_device(rt_3c905c_dev); 00378 rt_3c905c_opened = 0x01; 00379 return COM3_905C_MAJOR; 00380 }else{ 00381 rtl_printf("ERROR: Couldn't initialize device 3Com905C-X\n"); 00382 return -1; 00383 } 00384 }else{ 00385 rtl_printf("Device 3Com905C-X is already opened\n"); 00386 return -1; 00387 } 00388 } |
Here is the call graph for this function:
|
Definition at line 305 of file rtl_3c905cx_drv.c. References net_policy_operations::extract_frame_of_buffer, rt_3c905x_policy, rt_3c905x_rx_buffer, and rt_3c905x_sem.
00305 { 00306 sem_wait(&rt_3c905x_sem); 00307 return rt_3c905x_policy.extract_frame_of_buffer(&rt_3c905x_rx_buffer, buf); 00308 } |
|
Definition at line 329 of file rtl_3c905cx_drv.c. References net_policy_operations::dealloc_rx_buffer, rt_3c905c_dev, rt_3c905x_policy, rt_3c905x_rx_buffer, rt_3c905x_sem, vortex_close(), and vortex_remove_one().
00329 { 00330 00331 rtl_irqstate_t state; 00332 rtl_no_interrupts(state); 00333 00334 vortex_close(rt_3c905c_dev); 00335 00336 vortex_remove_one(rt_3c905c_dev); 00337 00338 if(rt_3c905c_opened == 0x01){ 00339 sem_destroy(&rt_3c905x_sem); 00340 rt_3c905x_policy.dealloc_rx_buffer(&rt_3c905x_rx_buffer); 00341 } 00342 00343 rt_3c905c_opened = 0x00; 00344 rtl_restore_interrupts(state); 00345 return 0; 00346 } |
Here is the call graph for this function:
|
Definition at line 1153 of file rtl_3c905cx_drv.c. References EL3_CMD, vortex_private::ioaddr, rt_3c905c_vp, RxBroadcast, RxStation, and SetRxFilter. Referenced by vortex_error(), and vortex_up().
01154 { 01155 long ioaddr = rt_3c905c_vp.ioaddr; 01156 int new_mode; 01157 01158 new_mode = SetRxFilter|RxStation|RxBroadcast;//RxMulticast|RxBroadcast; 01159 01160 outw(new_mode, ioaddr + EL3_CMD); 01161 } |
|
Definition at line 624 of file rtl_3c905cx_drv.c. References vortex_private::advertising, vortex_private::autoselect, AUTOSELECT, vortex_private::available_media, vortex_private::bus_master, vortex_private::capabilities, CapBusMaster, vortex_private::card_idx, vortex_private::cb_fn_base, vortex_private::default_media, vortex_private::dev_addr, vortex_private::drv_flags, EEPROM_8BIT, EEPROM_OFFSET, EEPROM_Read, EL3WINDOW, vortex_private::enable_wol, vortex_private::full_bus_master_rx, vortex_private::full_bus_master_tx, vortex_private::full_duplex, HAS_CB_FNS, vortex_private::has_nway, HAS_NWAY, htons, vortex_private::if_port, vortex_private::info1, vortex_private::info2, INVERT_LED_PWR, INVERT_MII_PWR, vortex_private::io_size, vortex_private::ioaddr, IS_TORNADO, vortex_private::media_override, vortex_private::mtu, vortex_private::must_free_region, NULL, PCI_USES_MASTER, vortex_private::pdev, vortex_private::phys, vortex_private::pm_state_valid, vortex_private::power_state, rt_3c905c_vp, rt_pci_resource_start, rt_pci_save_state(), rtl_3COM905C_acpi_set_WOL(), rtl_3COM905C_mdio_read(), rtl_3COM905C_mdio_write(), vortex_private::rx_ring, vortex_private::rx_ring_dma, RX_RING_SIZE, vortex_private::tx_ring, vortex_private::tx_ring_dma, TX_RING_SIZE, vortex_open(), Wn0EepromCmd, Wn0EepromData, Wn2_ResetOptions, Wn3_Config, Wn3_Options, Wn4_NetDiag, XCVR, XCVR_MII, and XCVR_NWAY. Referenced by rtl_3COM905C_open().
00624 { 00625 struct vortex_chip_info * const vci = &vortex_info; 00626 unsigned int eeprom[0x40], checksum = 0; /* EEPROM contents */ 00627 char *print_name; 00628 int retval; 00629 long ioaddr; 00630 int i,step; 00631 00632 print_name = dev ? dev->slot_name : "3c59x"; 00633 00634 ioaddr = rt_pci_resource_start(dev, 0); 00635 00636 rt_3c905c_vp.drv_flags = vci->drv_flags; 00637 rt_3c905c_vp.has_nway = (vci->drv_flags & HAS_NWAY) ? 1 : 0; 00638 rt_3c905c_vp.io_size = vci->io_size; 00639 rt_3c905c_vp.card_idx = 0; 00640 rt_3c905c_vp.ioaddr = ioaddr; 00641 rt_3c905c_vp.media_override = 7; 00642 rt_3c905c_vp.mtu = mtu; 00643 00644 print_name = dev ? dev->slot_name : "3c59x"; 00645 00646 /* PCI-only startup logic */ 00647 if (dev) { 00648 if (request_region(ioaddr, vci->io_size, print_name) != NULL){ 00649 rt_3c905c_vp.must_free_region = 1; 00650 } 00651 00652 /* enable bus-mastering if necessary */ 00653 if (vci->flags & PCI_USES_MASTER) 00654 pci_set_master (dev); 00655 00656 rt_3c905c_vp.pdev = dev; 00657 00658 /* Makes sure rings are at least 16 byte aligned. */ 00659 rt_3c905c_vp.rx_ring = pci_alloc_consistent(dev, sizeof(struct boom_rx_desc) * RX_RING_SIZE, &rt_3c905c_vp.rx_ring_dma); 00660 rt_3c905c_vp.tx_ring = pci_alloc_consistent(dev, sizeof(struct boom_tx_desc) * TX_RING_SIZE, &rt_3c905c_vp.tx_ring_dma); 00661 00662 retval = -ENOMEM; 00663 if ((rt_3c905c_vp.rx_ring == 0) || (rt_3c905c_vp.tx_ring == 0)) 00664 goto free_region; 00665 00666 EL3WINDOW(0); 00667 { 00668 int base; 00669 00670 if (vci->drv_flags & EEPROM_8BIT) 00671 base = 0x230; 00672 else if (vci->drv_flags & EEPROM_OFFSET) 00673 base = EEPROM_Read + 0x30; 00674 else 00675 base = EEPROM_Read; 00676 00677 for (i = 0; i < 0x40; i++) { 00678 int timer; 00679 00680 /* This means that we want to read EepromCommand Register and disable writting */ 00681 /* Issuing ReadRegister & WriteDisable */ 00682 outw(base + i, ioaddr + Wn0EepromCmd); 00683 00684 for (timer = 10; timer >= 0; timer--) { 00685 00686 /* The read data is available through the EepromData register 162us after */ 00687 /* the ReadRegister command has been issued */ 00688 rtl_delay(162000); 00689 00690 /* Bit 15th (eepromBusy) of EepromCommand register is a read-only bit asserted */ 00691 /* during the execution of EEProm commands. Further commans should not be issued */ 00692 /* to the EepromCommand register, nor should data be read from the EepromData */ 00693 /* register while this bit is true */ 00694 if ((inw(ioaddr + Wn0EepromCmd) & 0x8000) == 0) 00695 break; 00696 } 00697 00698 /* Save the contents of the 3C90xC NIC's EEPROM */ 00699 eeprom[i] = inw(ioaddr + Wn0EepromData); 00700 } 00701 00702 }//EL3WINDOW(0) configuration finished 00703 00704 /* EEPROM can be checksummed in order to assure that reading was OK */ 00705 for (i = 0; i < 0x18; i++) 00706 checksum ^= eeprom[i]; 00707 checksum = (checksum ^ (checksum >> 8)) & 0xff; 00708 if (checksum != 0x00) { /* Grrr, needless incompatible change 3Com. */ 00709 while (i < 0x21) 00710 checksum ^= eeprom[i++]; 00711 checksum = (checksum ^ (checksum >> 8)) & 0xff; 00712 } 00713 if ((checksum != 0x00) && !(vci->drv_flags & IS_TORNADO)) 00714 printk(" ***INVALID CHECKSUM %4.4x*** ", checksum); 00715 00716 /* Save HW address into dev_addr (MAC address in format 00:04:75:bd:ea:e7) */ 00717 for (i = 0; i < 3; i++) 00718 ((u16 *)rt_3c905c_vp.dev_addr)[i] = htons(eeprom[i + 10]); 00719 00720 /* This writes into the StationAddress register the NIC's HW address in order */ 00721 /* to define the individual destination address that the NIC responds to when */ 00722 /* receiving packets */ 00723 EL3WINDOW(2); 00724 for (i = 0; i < 6; i++) 00725 outb(rt_3c905c_vp.dev_addr[i], ioaddr + i); 00726 00727 EL3WINDOW(4); 00728 step = (inb(ioaddr + Wn4_NetDiag) & 0x1e) >> 1; 00729 00730 if (dev && vci->drv_flags & HAS_CB_FNS) { 00731 unsigned long fn_st_addr; /* Cardbus function status space */ 00732 unsigned short n; 00733 00734 fn_st_addr = pci_resource_start (dev, 2); 00735 if (fn_st_addr) { 00736 rt_3c905c_vp.cb_fn_base = ioremap(fn_st_addr, 128); 00737 retval = -ENOMEM; 00738 if (!rt_3c905c_vp.cb_fn_base) 00739 goto free_ring; 00740 } 00741 00742 EL3WINDOW(2); 00743 00744 n = inw(ioaddr + Wn2_ResetOptions) & ~0x4010; 00745 if (rt_3c905c_vp.drv_flags & INVERT_LED_PWR) 00746 n |= 0x10; 00747 if (rt_3c905c_vp.drv_flags & INVERT_MII_PWR) 00748 n |= 0x4000; 00749 outw(n, ioaddr + Wn2_ResetOptions); 00750 } 00751 00752 /* Extract our information from the EEPROM data. */ 00753 rt_3c905c_vp.info1 = eeprom[13]; 00754 rt_3c905c_vp.info2 = eeprom[15]; 00755 rt_3c905c_vp.capabilities = eeprom[16]; 00756 00757 if (rt_3c905c_vp.info1 & 0x8000){ 00758 rt_3c905c_vp.full_duplex = 1; 00759 printk(KERN_INFO "Full duplex capable\n"); 00760 } 00761 00762 { 00763 unsigned int config; 00764 EL3WINDOW(3); 00765 00766 /* This reads the MediaOptions register which shows what physical media */ 00767 /* connections are available in the NIC */ 00768 rt_3c905c_vp.available_media = inw(ioaddr + Wn3_Options); //Wn3_Options = 8 vp.available_media = 0xa 00769 00770 if ((rt_3c905c_vp.available_media & 0xff) == 0) /* Broken 3c916 */ 00771 rt_3c905c_vp.available_media = 0x40; 00772 00773 /* This reads the InternalConfig register which provides a way to set */ 00774 /* NIC-specific, non-host-related configuration settings */ 00775 config = inl(ioaddr + Wn3_Config); //Wn3_Config = 0 00776 00777 rt_3c905c_vp.default_media = XCVR(config); 00778 if (rt_3c905c_vp.default_media == XCVR_NWAY) 00779 rt_3c905c_vp.has_nway = 1; 00780 rt_3c905c_vp.autoselect = AUTOSELECT(config); 00781 } 00782 00783 if (rt_3c905c_vp.media_override != 7) { 00784 rt_3c905c_vp.if_port = rt_3c905c_vp.media_override; 00785 } else 00786 rt_3c905c_vp.if_port = rt_3c905c_vp.default_media; 00787 00788 if (rt_3c905c_vp.if_port == XCVR_MII || rt_3c905c_vp.if_port == XCVR_NWAY) { 00789 int phy, phy_idx = 0; 00790 EL3WINDOW(4); 00791 mii_preamble_required++; 00792 mii_preamble_required++; 00793 rtl_3COM905C_mdio_read(24, 1); 00794 for (phy = 0; phy < 32 && phy_idx < 1; phy++) { 00795 int mii_status, phyx; 00796 00797 /* 00798 * For the 3c905CX we look at index 24 first, because it bogusly 00799 * reports an external PHY at all indices 00800 */ 00801 if (phy == 0) 00802 phyx = 24; 00803 else if (phy <= 24) 00804 phyx = phy - 1; 00805 else 00806 phyx = phy; 00807 mii_status = rtl_3COM905C_mdio_read(phyx, 1); 00808 if (mii_status && mii_status != 0xffff) { 00809 rt_3c905c_vp.phys[phy_idx++] = phyx; 00810 00811 if ((mii_status & 0x0040) == 0) 00812 mii_preamble_required++; 00813 } 00814 } 00815 mii_preamble_required--; 00816 if (phy_idx == 0) { 00817 rt_3c905c_vp.phys[0] = 24; 00818 } else { 00819 rt_3c905c_vp.advertising = rtl_3COM905C_mdio_read(rt_3c905c_vp.phys[0], 4); 00820 if (rt_3c905c_vp.full_duplex) { 00821 /* Only advertise the FD media types. */ 00822 rt_3c905c_vp.advertising &= ~0x02A0; 00823 rtl_3COM905C_mdio_write(rt_3c905c_vp.phys[0], 4, rt_3c905c_vp.advertising); 00824 } 00825 } 00826 } 00827 if (rt_3c905c_vp.capabilities & CapBusMaster) { 00828 rt_3c905c_vp.full_bus_master_tx = 1; 00829 00830 rt_3c905c_vp.full_bus_master_rx = (rt_3c905c_vp.info2 & 1) ? 1 : 2; 00831 rt_3c905c_vp.bus_master = 0; /* AKPM: vortex only */ 00832 } 00833 if (rt_3c905c_vp.pdev && rt_3c905c_vp.enable_wol) { 00834 rt_3c905c_vp.pm_state_valid = 1; 00835 rt_pci_save_state(dev, rt_3c905c_vp.power_state); 00836 rtl_3COM905C_acpi_set_WOL(); 00837 } 00838 vortex_open(dev); 00839 00840 }// if(dev) 00841 00842 return 0; 00843 00844 free_ring: 00845 00846 pci_free_consistent(dev, sizeof(struct boom_rx_desc) * RX_RING_SIZE, rt_3c905c_vp.rx_ring, rt_3c905c_vp.rx_ring_dma); 00847 pci_free_consistent(dev, sizeof(struct boom_tx_desc) * TX_RING_SIZE, rt_3c905c_vp.tx_ring, rt_3c905c_vp.tx_ring_dma); 00848 00849 return -1; 00850 00851 free_region: 00852 if (rt_3c905c_vp.must_free_region){ 00853 release_region(ioaddr, vci->io_size); 00854 rt_3c905c_vp.must_free_region = 0; 00855 } 00856 printk("vortex_probe1 fails. Returns %d\n", retval); 00857 00858 return -1; 00859 } |
Here is the call graph for this function:
|
Definition at line 353 of file rtl_3c905cx_drv.c. References rt_3c905c_send_packet().
00354 { 00355 ssize_t tmp; 00356 rtl_irqstate_t state; 00357 00358 rtl_no_interrupts(state); 00359 tmp=rt_3c905c_send_packet(buf,count); 00360 rtl_restore_interrupts(state); 00361 return tmp; 00362 } |
Here is the call graph for this function:
|
Definition at line 1197 of file rtl_3c905cx_drv.c. References vortex_private::full_bus_master_rx, vortex_private::full_bus_master_tx, vortex_private::must_free_irq, rt_3c905c_vp, rtl_free, RX_RING_SIZE, vortex_private::rx_skbuff, TX_RING_SIZE, vortex_private::tx_skbuff, and vortex_down().
01198 { 01199 int i; 01200 01201 vortex_down(dev); 01202 01203 if(rt_3c905c_vp.must_free_irq){ 01204 rtl_free_irq(dev->irq); 01205 rt_3c905c_vp.must_free_irq = 0; 01206 } 01207 01208 if (rt_3c905c_vp.full_bus_master_rx) { /* Free Boomerang bus master Rx buffers. */ 01209 for (i = 0; i < RX_RING_SIZE; i++) 01210 if (rt_3c905c_vp.rx_skbuff[i]) { 01211 rtl_free(rt_3c905c_vp.rx_skbuff[i]); 01212 } 01213 } 01214 if (rt_3c905c_vp.full_bus_master_tx) { /* Free Boomerang bus master Tx buffers. */ 01215 for (i = 0; i < TX_RING_SIZE; i++) 01216 if (rt_3c905c_vp.tx_skbuff[i]) { 01217 rtl_free(rt_3c905c_vp.tx_skbuff[i]); 01218 } 01219 } 01220 01221 return 0; 01222 } |
Here is the call graph for this function:
|
Definition at line 1166 of file rtl_3c905cx_drv.c. References DownListPtr, EL3_CMD, vortex_private::enable_wol, vortex_private::full_bus_master_rx, vortex_private::full_bus_master_tx, vortex_private::if_port, vortex_private::ioaddr, vortex_private::pdev, vortex_private::power_state, rt_3c905c_vp, rt_pci_save_state(), rtl_3COM905C_acpi_set_WOL(), RxDisable, SetIntrEnb, StatsDisable, StopCoax, TxDisable, UpListPtr, and XCVR_10base2.
01167 { 01168 long ioaddr = rt_3c905c_vp.ioaddr; 01169 01170 /* Turn off statistics ASAP. We update rt_3c905c_vp->stats below. */ 01171 outw(StatsDisable, ioaddr + EL3_CMD); 01172 01173 /* Disable the receiver and transmitter. */ 01174 outw(RxDisable, ioaddr + EL3_CMD); 01175 outw(TxDisable, ioaddr + EL3_CMD); 01176 01177 if (rt_3c905c_vp.if_port == XCVR_10base2) 01178 /* Turn off thinnet power. Green! */ 01179 outw(StopCoax, ioaddr + EL3_CMD); 01180 01181 outw(SetIntrEnb | 0x0000, ioaddr + EL3_CMD); 01182 01183 if (rt_3c905c_vp.full_bus_master_rx) 01184 outl(0, ioaddr + UpListPtr); 01185 if (rt_3c905c_vp.full_bus_master_tx) 01186 outl(0, ioaddr + DownListPtr); 01187 01188 if (rt_3c905c_vp.pdev && rt_3c905c_vp.enable_wol) { 01189 rt_pci_save_state(rt_3c905c_vp.pdev, rt_3c905c_vp.power_state); 01190 rtl_3COM905C_acpi_set_WOL(); 01191 } 01192 } |
Here is the call graph for this function:
|
Definition at line 1229 of file rtl_3c905cx_drv.c. References AckIntr, EL3_CMD, EL3_STATUS, EL3WINDOW, vortex_private::full_bus_master_tx, HostError, vortex_private::intr_enable, IntReq, vortex_private::ioaddr, PktStatus, rt_3c905c_vp, rtl_3COM905C_issue_and_wait(), rtl_3COM905C_set_rx_mode(), RxEarly, RxEnable, RxReset, SetIntrEnb, StatsFull, status, vortex_private::status_enable, TotalReset, TxEnable, TxReset, vortex_down(), vortex_up(), and Wn4_FIFODiag.
01230 { 01231 long ioaddr = rt_3c905c_vp.ioaddr; 01232 int do_tx_reset = 0, reset_mask = 0; 01233 01234 if (status & RxEarly) { /* Rx early is unused. */ 01235 outw(AckIntr | RxEarly, ioaddr + EL3_CMD); 01236 } 01237 if (status & StatsFull) { /* Empty statistics. */ 01238 static int DoneDidThat; 01239 01240 printk(KERN_DEBUG "%s: Updating stats.\n", dev->name); 01241 /* HACK: Disable statistics as an interrupt source. */ 01242 /* This occurs when we have the wrong media type! */ 01243 if (DoneDidThat == 0 && 01244 inw(ioaddr + EL3_STATUS) & StatsFull) { 01245 printk(KERN_WARNING "%s: Updating statistics failed, disabling " 01246 "stats as an interrupt source.\n", dev->name); 01247 EL3WINDOW(5); 01248 outw(SetIntrEnb | (inw(ioaddr + 10) & ~StatsFull), ioaddr + EL3_CMD); 01249 rt_3c905c_vp.intr_enable &= ~StatsFull; 01250 EL3WINDOW(7); 01251 DoneDidThat++; 01252 } 01253 } 01254 if (status & IntReq) { /* Restore all interrupt sources. */ 01255 outw(rt_3c905c_vp.status_enable, ioaddr + EL3_CMD); 01256 outw(rt_3c905c_vp.intr_enable, ioaddr + EL3_CMD); 01257 } 01258 if (status & HostError) { 01259 u16 fifo_diag; 01260 EL3WINDOW(4); 01261 fifo_diag = inw(ioaddr + Wn4_FIFODiag); 01262 printk(KERN_ERR "%s: Host error, FIFO diagnostic register %4.4x.\n", 01263 dev->name, fifo_diag); 01264 /* Adapter failure requires Tx/Rx reset and reinit. */ 01265 if (rt_3c905c_vp.full_bus_master_tx) { 01266 int bus_status = inl(ioaddr + PktStatus); 01267 /* 0x80000000 PCI master abort. */ 01268 /* 0x40000000 PCI target abort. */ 01269 01270 printk(KERN_ERR "%s: PCI bus error, bus status %8.8x\n", dev->name, bus_status); 01271 01272 /* In this case, blow the card away */ 01273 vortex_down(dev); 01274 rtl_3COM905C_issue_and_wait(TotalReset | 0xff); 01275 vortex_up(dev); /* AKPM: bug. vortex_up() assumes that the rx ring is full. It may not be. */ 01276 } else if (fifo_diag & 0x0400) 01277 do_tx_reset = 1; 01278 if (fifo_diag & 0x3000) { 01279 /* Reset Rx fifo and upload logic */ 01280 rtl_3COM905C_issue_and_wait(RxReset|0x07); 01281 /* Set the Rx filter to the current state. */ 01282 rtl_3COM905C_set_rx_mode(); 01283 outw(RxEnable, ioaddr + EL3_CMD); /* Re-enable the receiver. */ 01284 outw(AckIntr | HostError, ioaddr + EL3_CMD); 01285 } 01286 } 01287 01288 if (do_tx_reset) { 01289 rtl_3COM905C_issue_and_wait(TxReset|reset_mask); 01290 outw(TxEnable, ioaddr + EL3_CMD); 01291 } 01292 } |
Here is the call graph for this function:
|
Definition at line 885 of file rtl_3c905cx_drv.c. References boom_tx_desc::addr, boom_rx_desc::addr, boomerang_interrupt(), vortex_private::full_bus_master_rx, LAST_FRAG, boom_tx_desc::length, boom_rx_desc::length, vortex_private::must_free_irq, boom_tx_desc::next, boom_rx_desc::next, NULL, vortex_private::pdev, PKT_BUF_SZ, rt_3c905c_vp, rtl_free, rtl_malloc, vortex_private::rx_ring, vortex_private::rx_ring_dma, RX_RING_SIZE, vortex_private::rx_skbuff, boom_tx_desc::status, boom_rx_desc::status, vortex_private::tx_ring, vortex_private::tx_ring_dma, TX_RING_SIZE, vortex_private::tx_skbuff, and vortex_up().
00886 { 00887 int i; 00888 int retval; 00889 00890 /* Use the now-standard shared IRQ implementation. */ 00891 if ((retval = rtl_request_irq(dev->irq, &boomerang_interrupt))) { 00892 printk(KERN_ERR "%s: Could not reserve IRQ %d\n", dev->name, dev->irq); 00893 goto out; 00894 }else 00895 rt_3c905c_vp.must_free_irq = 1; 00896 00897 if (rt_3c905c_vp.full_bus_master_rx) { /* Boomerang bus master. */ 00898 00899 /* RX RING INITIALIZATION */ 00900 for (i = 0; i < RX_RING_SIZE; i++) { 00901 unsigned char *skb; 00902 rt_3c905c_vp.rx_ring[i].next = cpu_to_le32(rt_3c905c_vp.rx_ring_dma + sizeof(struct boom_rx_desc) * (i+1)); 00903 rt_3c905c_vp.rx_ring[i].status = 0; /* Clear complete bit. */ 00904 rt_3c905c_vp.rx_ring[i].length = cpu_to_le32(PKT_BUF_SZ | LAST_FRAG); 00905 skb = rtl_malloc(PKT_BUF_SZ); 00906 rt_3c905c_vp.rx_skbuff[i] = skb; 00907 if (skb == NULL) 00908 break; /* Bad news! */ 00909 rt_3c905c_vp.rx_ring[i].addr = cpu_to_le32(pci_map_single(rt_3c905c_vp.pdev, skb, PKT_BUF_SZ, PCI_DMA_FROMDEVICE)); 00910 } 00911 00912 if (i != RX_RING_SIZE) { 00913 int j; 00914 printk(KERN_EMERG "%s: no memory for rx ring\n", dev->name); 00915 for (j = 0; j < i; j++) { 00916 if (rt_3c905c_vp.rx_skbuff[j]) { 00917 rtl_free(rt_3c905c_vp.rx_skbuff[j]); 00918 rt_3c905c_vp.rx_skbuff[j] = 0; 00919 } 00920 } 00921 retval = -ENOMEM; 00922 goto out_free_irq; 00923 } 00924 00925 /* Wrap the ring. */ 00926 rt_3c905c_vp.rx_ring[i-1].next = cpu_to_le32(rt_3c905c_vp.rx_ring_dma); 00927 00928 /* TX RING INITIALIZATION */ 00929 for (i = 0; i < TX_RING_SIZE; i++) { 00930 unsigned char *skb; 00931 rt_3c905c_vp.tx_ring[i].next = 0; 00932 rt_3c905c_vp.tx_ring[i].status = 0; /* Clear complete bit. */ 00933 rt_3c905c_vp.tx_ring[i].length = cpu_to_le32(PKT_BUF_SZ | LAST_FRAG); 00934 skb = rtl_malloc(PKT_BUF_SZ); 00935 rt_3c905c_vp.tx_skbuff[i] = skb; 00936 if (skb == NULL) 00937 break; /* Bad news! */ 00938 rt_3c905c_vp.tx_ring[i].addr = cpu_to_le32(pci_map_single(rt_3c905c_vp.pdev, skb, PKT_BUF_SZ, PCI_DMA_FROMDEVICE)); 00939 } 00940 00941 00942 if (i != TX_RING_SIZE) { 00943 int j; 00944 printk(KERN_EMERG "%s: no memory for tx ring\n", dev->name); 00945 for (j = 0; j < i; j++) { 00946 if (rt_3c905c_vp.tx_skbuff[j]) { 00947 rtl_free(rt_3c905c_vp.tx_skbuff[j]); 00948 rt_3c905c_vp.tx_skbuff[j] = 0; 00949 } 00950 } 00951 retval = -ENOMEM; 00952 goto out_free_irq; 00953 } 00954 00955 /* Wrap the ring. */ 00956 rt_3c905c_vp.tx_ring[i-1].next = cpu_to_le32(rt_3c905c_vp.tx_ring_dma); 00957 } 00958 00959 vortex_up(dev); 00960 return 0; 00961 00962 out_free_irq: 00963 rtl_free_irq(dev->irq); 00964 out: 00965 return retval; 00966 } |
Here is the call graph for this function:
|
Here is the call graph for this function:
|
Definition at line 972 of file rtl_3c905cx_drv.c. References AckIntr, vortex_private::autoselect, vortex_private::available_media, BFINS, vortex_private::cb_fn_base, vortex_private::cur_rx, vortex_private::cur_tx, vortex_private::default_media, vortex_private::dev_addr, vortex_private::dirty_rx, vortex_private::dirty_tx, DownComplete, DownListPtr, vortex_private::drv_flags, EL3_CMD, EL3WINDOW, vortex_private::enable_wol, vortex_private::flow_ctrl, vortex_private::force_fd, vortex_private::full_bus_master_rx, vortex_private::full_bus_master_tx, vortex_private::full_duplex, vortex_private::has_nway, vortex_private::if_port, vortex_private::info1, IntLatch, vortex_private::intr_enable, IntReq, INVERT_LED_PWR, INVERT_MII_PWR, vortex_private::ioaddr, IS_BOOMERANG, Media_10TP, vortex_private::media_override, Media_SQE, vortex_private::mtu, vortex_private::partner_flow_ctrl, vortex_private::pdev, vortex_private::phys, PKT_BUF_SZ, vortex_private::power_state, rt_3c905c_vp, rt_pci_restore_state(), rt_pci_set_power_state(), rtl_3COM905C_issue_and_wait(), rtl_3COM905C_mdio_read(), rtl_3COM905C_set_rx_mode(), vortex_private::rx_frames_for_us, vortex_private::rx_packets, vortex_private::rx_ring, vortex_private::rx_ring_dma, RX_RING_SIZE, RxComplete, RxEarly, RxEnable, RxReset, SetIntrEnb, SetStatusEnb, StartCoax, StatsDisable, boom_rx_desc::status, vortex_private::status_enable, TxAvailable, TxEnable, TxFreeThreshold, TxReset, UpComplete, UpListPtr, Wn2_ResetOptions, Wn3_Config, Wn3_MAC_Ctrl, Wn4_Media, XCVR_100baseTx, XCVR_10base2, XCVR_MII, and XCVR_NWAY.
00973 { 00974 long ioaddr = rt_3c905c_vp.ioaddr; 00975 unsigned int config; 00976 int i; 00977 00978 rt_3c905c_vp.rx_packets = 0; 00979 rt_3c905c_vp.rx_frames_for_us = 0; 00980 00981 if (rt_3c905c_vp.pdev && rt_3c905c_vp.enable_wol) { 00982 rt_pci_set_power_state(dev, 0); /* Go active */ 00983 rt_pci_restore_state(dev, rt_3c905c_vp.power_state); 00984 } 00985 00986 /* Before initializing select the active media port. */ 00987 EL3WINDOW(3); 00988 config = inl(ioaddr + Wn3_Config); 00989 00990 if (rt_3c905c_vp.media_override != 7) { 00991 rt_3c905c_vp.if_port = rt_3c905c_vp.media_override; 00992 } else if (rt_3c905c_vp.autoselect) { 00993 if (rt_3c905c_vp.has_nway) { 00994 } else { 00995 /* Find first available media type, starting with 100baseTx. */ 00996 rt_3c905c_vp.if_port = XCVR_100baseTx; 00997 while (! (rt_3c905c_vp.available_media & media_tbl[rt_3c905c_vp.if_port].mask)) 00998 rt_3c905c_vp.if_port = media_tbl[rt_3c905c_vp.if_port].next; 00999 } 01000 } else { 01001 rt_3c905c_vp.if_port = rt_3c905c_vp.default_media; 01002 01003 } 01004 01005 rt_3c905c_vp.full_duplex = rt_3c905c_vp.force_fd; 01006 01007 config = BFINS(config, rt_3c905c_vp.if_port, 20, 4); 01008 01009 outl(config, ioaddr + Wn3_Config); 01010 01011 if (rt_3c905c_vp.if_port == XCVR_MII || rt_3c905c_vp.if_port == XCVR_NWAY) { 01012 int mii_reg1, mii_reg5; 01013 EL3WINDOW(4); 01014 /* Read BMSR (reg1) only to clear old status. */ 01015 mii_reg1 = rtl_3COM905C_mdio_read(rt_3c905c_vp.phys[0], 1); 01016 mii_reg5 = rtl_3COM905C_mdio_read(rt_3c905c_vp.phys[0], 5); 01017 if (mii_reg5 == 0xffff || mii_reg5 == 0x0000) 01018 ; /* No MII device or no link partner report */ 01019 else if ((mii_reg5 & 0x0100) != 0 /* 100baseTx-FD */ 01020 || (mii_reg5 & 0x00C0) == 0x0040) /* 10T-FD, but not 100-HD */ 01021 rt_3c905c_vp.full_duplex = 1; 01022 rt_3c905c_vp.partner_flow_ctrl = ((mii_reg5 & 0x0400) != 0); 01023 01024 EL3WINDOW(3); 01025 } 01026 01027 rt_3c905c_vp.full_duplex = 1; 01028 01029 /* Set the full-duplex bit. */ 01030 01031 outw( ((rt_3c905c_vp.info1 & 0x8000) || rt_3c905c_vp.full_duplex ? 0x20 : 0) | 01032 (rt_3c905c_vp.mtu > 1500 ? 0x40 : 0) | 01033 ((rt_3c905c_vp.full_duplex && rt_3c905c_vp.flow_ctrl && rt_3c905c_vp.partner_flow_ctrl) ? 0x100 : 0), 01034 ioaddr + Wn3_MAC_Ctrl); 01035 01036 rtl_3COM905C_issue_and_wait(TxReset); 01037 01038 /* 01039 * Don't reset the PHY - that upsets autonegotiation during DHCP operations. 01040 */ 01041 rtl_3COM905C_issue_and_wait(RxReset|0x04); 01042 01043 outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD); 01044 01045 EL3WINDOW(4); 01046 01047 /* Set the station address and mask in window 2 each time opened. */ 01048 EL3WINDOW(2); 01049 for (i = 0; i < 6; i++) 01050 outb(rt_3c905c_vp.dev_addr[i], ioaddr + i); 01051 for (; i < 12; i+=2) 01052 outw(0, ioaddr + i); 01053 01054 if (rt_3c905c_vp.cb_fn_base) { 01055 unsigned short n = inw(ioaddr + Wn2_ResetOptions) & ~0x4010; 01056 if (rt_3c905c_vp.drv_flags & INVERT_LED_PWR) 01057 n |= 0x10; 01058 if (rt_3c905c_vp.drv_flags & INVERT_MII_PWR) 01059 n |= 0x4000; 01060 outw(n, ioaddr + Wn2_ResetOptions); 01061 } 01062 01063 if (rt_3c905c_vp.if_port == XCVR_10base2) 01064 /* Start the thinnet transceiver. We should really wait 50ms...*/ 01065 outw(StartCoax, ioaddr + EL3_CMD); 01066 if (rt_3c905c_vp.if_port != XCVR_NWAY) { 01067 EL3WINDOW(4); 01068 outw((inw(ioaddr + Wn4_Media) & ~(Media_10TP|Media_SQE)) | 01069 media_tbl[rt_3c905c_vp.if_port].media_bits, ioaddr + Wn4_Media); 01070 } 01071 01072 /* RTOS and statistic??? Let's disable stats. */ 01073 outw(StatsDisable, ioaddr + EL3_CMD); 01074 EL3WINDOW(6); 01075 for (i = 0; i < 10; i++) 01076 inb(ioaddr + i); 01077 inw(ioaddr + 10); 01078 inw(ioaddr + 12); 01079 /* New: On the Vortex we must also clear the BadSSD counter. */ 01080 EL3WINDOW(4); 01081 inb(ioaddr + 12); 01082 01083 /* Switch to register set 7 for normal use. */ 01084 EL3WINDOW(7); 01085 01086 if (rt_3c905c_vp.full_bus_master_rx) { /* Boomerang bus master. */ 01087 rt_3c905c_vp.cur_rx = rt_3c905c_vp.dirty_rx = rt_3c905c_vp.cur_tx = 0; 01088 01089 outl(rt_3c905c_vp.rx_ring_dma, ioaddr + UpListPtr); 01090 } 01091 if (rt_3c905c_vp.full_bus_master_tx) { /* Boomerang bus master Tx. */ 01092 rt_3c905c_vp.cur_tx = rt_3c905c_vp.dirty_tx = 0; 01093 if (rt_3c905c_vp.drv_flags & IS_BOOMERANG) 01094 01095 outb(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold); /* Room for a packet. */ 01096 /* Clear the Rx, Tx rings. */ 01097 for (i = 0; i < RX_RING_SIZE; i++) /* AKPM: this is done in vortex_open, too */ 01098 rt_3c905c_vp.rx_ring[i].status = 0; 01099 outl(0, ioaddr + DownListPtr); 01100 } 01101 /* Set receiver mode: presumably accept b-case and phys addr only. */ 01102 rtl_3COM905C_set_rx_mode(); 01103 outw(StatsDisable, ioaddr + EL3_CMD); /* Turn off statistics ASAP. */ 01104 01105 outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */ 01106 outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */ 01107 01108 /* Allow status bits to be seen. */ 01109 rt_3c905c_vp.status_enable = SetStatusEnb | 01110 (rt_3c905c_vp.full_bus_master_rx ? UpComplete : RxComplete) | DownComplete; 01111 rt_3c905c_vp.intr_enable = SetIntrEnb | UpComplete | DownComplete; 01112 outw(rt_3c905c_vp.status_enable, ioaddr + EL3_CMD); 01113 /* Ack all pending events, and set active indicator mask. */ 01114 outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq, 01115 ioaddr + EL3_CMD); 01116 outw(rt_3c905c_vp.intr_enable, ioaddr + EL3_CMD); 01117 if (rt_3c905c_vp.cb_fn_base) 01118 writel(0x8000, rt_3c905c_vp.cb_fn_base + 4); 01119 } |
Here is the call graph for this function:
|
Definition at line 265 of file rtl_3c905cx_drv.c. Referenced by boomerang_interrupt(), rtl_3COM905C_open(), and rtl_3COM905C_release(). |
|
Definition at line 252 of file rtl_3c905cx_drv.c. Referenced by boomerang_interrupt(), and cleanup_module(). |
|
Definition at line 253 of file rtl_3c905cx_drv.c. Referenced by boomerang_interrupt(). |
|
Definition at line 268 of file rtl_3c905cx_drv.c. Referenced by boomerang_rx(), and rt_3c905c_set_ip_filter(). |
|
Definition at line 269 of file rtl_3c905cx_drv.c. Referenced by boomerang_rx(), and rt_3c905c_set_ip_filter(). |
|
Definition at line 267 of file rtl_3c905cx_drv.c. Referenced by cleanup_module(), and init_module(). |
|
|
Initial value: { FIFO_add_frame_to_buffer, FIFO_extract_frame_of_buffer, FIFO_initialize_rx_buffer, FIFO_dealloc_rx_buffer, } Definition at line 237 of file rtl_3c905cx_drv.c. Referenced by boomerang_rx(), rtl_3COM905C_init_device(), rtl_3COM905C_read(), and rtl_3COM905C_release(). |
|
Definition at line 244 of file rtl_3c905cx_drv.c. Referenced by boomerang_rx(), rtl_3COM905C_init_device(), rtl_3COM905C_read(), and rtl_3COM905C_release(). |
|
Definition at line 246 of file rtl_3c905cx_drv.c. Referenced by boomerang_rx(), rtl_3COM905C_open(), rtl_3COM905C_read(), and rtl_3COM905C_release(). |
|
Initial value: { NULL, rtl_3COM905C_read, rtl_3COM905C_write, rtl_3COM905C_ioctl, NULL, rtl_3COM905C_open, rtl_3COM905C_release } Definition at line 255 of file rtl_3c905cx_drv.c. Referenced by init_module(). |