Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

rtl_3c905cx_drv.c File Reference

#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


Define Documentation

#define COM3_905C_MAJOR   204
 

Definition at line 248 of file rtl_3c905cx_drv.c.

Referenced by cleanup_module(), init_module(), and rtl_3COM905C_open().

#define COM3_905C_NAME   "eth"
 

Definition at line 249 of file rtl_3c905cx_drv.c.

#define COM3_SIGNAL   RTL_SIGUSR2
 

Definition at line 250 of file rtl_3c905cx_drv.c.

#define MDIO_DATA_READ   0x02
 

Definition at line 1386 of file rtl_3c905cx_drv.c.

Referenced by rtl_3COM905C_mdio_read().

#define MDIO_DATA_WRITE0   (0x00 | MDIO_DIR_WRITE)
 

Definition at line 1384 of file rtl_3c905cx_drv.c.

Referenced by rtl_3COM905C_mdio_read(), and rtl_3COM905C_mdio_write().

#define MDIO_DATA_WRITE1   (0x02 | MDIO_DIR_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().

#define MDIO_DIR_WRITE   0x04
 

Definition at line 1383 of file rtl_3c905cx_drv.c.

#define MDIO_ENB_IN   0x00
 

Definition at line 1387 of file rtl_3c905cx_drv.c.

Referenced by rtl_3COM905C_mdio_read(), and rtl_3COM905C_mdio_write().

#define MDIO_SHIFT_CLK   0x01
 

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().

 
#define rtl_3COM905C_mdio_delay  )     inl(mdio_addr)
 

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().


Function Documentation

unsigned int boomerang_interrupt unsigned int  irq,
struct pt_regs *  regs
 

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:

int boomerang_rx struct pci_dev *  dev  )  [static]
 

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 }

void cleanup_module void   ) 
 

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:

int init_module void   ) 
 

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 }

MODULE_LICENSE "GPL"   ) 
 

int rt_3c905c_obtain_mac_address unsigned char *  mac  ) 
 

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 }

int rt_3c905c_send_packet const char *  buffer,
size_t  size
[static]
 

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:

int rt_3c905c_set_ip_filter unsigned long  ipaddr  ) 
 

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 }

void rtl_3COM905C_acpi_set_WOL void   )  [static]
 

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:

struct pci_dev* rtl_3COM905C_init_device void   ) 
 

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:

int rtl_3COM905C_ioctl struct rtl_file *  filp,
unsigned int  request,
unsigned long  other
[static]
 

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:

void rtl_3COM905C_issue_and_wait int  cmd  )  [static]
 

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 }

int rtl_3COM905C_mdio_read int  phy_id,
int  location
[static]
 

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:

void rtl_3COM905C_mdio_sync long  ioaddr,
int  bits
[static]
 

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 }

void rtl_3COM905C_mdio_write int  phy_id,
int  location,
int  value
[static]
 

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:

int rtl_3COM905C_open struct rtl_file *  filp  )  [static]
 

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:

ssize_t rtl_3COM905C_read struct rtl_file *  filp,
char *  buf,
size_t  count,
loff_t *  ppos
[static]
 

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 }

int rtl_3COM905C_release struct rtl_file *  filp  )  [static]
 

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:

void rtl_3COM905C_set_rx_mode void   )  [static]
 

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 }

int rtl_3COM905C_start_up_device struct pci_dev *  dev  ) 
 

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:

ssize_t rtl_3COM905C_write struct rtl_file *  filp,
const char *  buf,
size_t  count,
loff_t *  ppos
[static]
 

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:

int vortex_close struct pci_dev *  dev  )  [static]
 

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:

void vortex_down struct pci_dev *  dev  )  [static]
 

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:

void vortex_error struct pci_dev *  dev,
int  status
[static]
 

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:

int vortex_open struct pci_dev *  dev  )  [static]
 

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:

void vortex_remove_one struct pci_dev *  pdev  )  [static]
 

Definition at line 1298 of file rtl_3c905cx_drv.c.

References EL3_CMD, vortex_private::enable_wol, vortex_private::io_size, vortex_private::ioaddr, vortex_private::must_free_region, vortex_private::pdev, vortex_private::pm_state_valid, vortex_private::power_state, rt_3c905c_vp, rt_pci_set_power_state(), vortex_private::rx_ring, vortex_private::rx_ring_dma, RX_RING_SIZE, TotalReset, vortex_private::tx_ring, vortex_private::tx_ring_dma, and TX_RING_SIZE.

01299 {
01300   
01301   outw(TotalReset|0x14, rt_3c905c_vp.ioaddr + EL3_CMD);
01302   
01303   if (rt_3c905c_vp.pdev && rt_3c905c_vp.enable_wol) {
01304     rt_pci_set_power_state(rt_3c905c_vp.pdev, 0);       /* Go active */
01305     if (rt_3c905c_vp.pm_state_valid)
01306       pci_restore_state(rt_3c905c_vp.pdev, rt_3c905c_vp.power_state);
01307   }
01308   
01309   pci_free_consistent(pdev,
01310                       sizeof(struct boom_rx_desc) * RX_RING_SIZE,
01311                       rt_3c905c_vp.rx_ring,
01312                       rt_3c905c_vp.rx_ring_dma);
01313 
01314   pci_free_consistent(pdev,
01315                       sizeof(struct boom_tx_desc) * TX_RING_SIZE,
01316                       rt_3c905c_vp.tx_ring,
01317                       rt_3c905c_vp.tx_ring_dma);
01318 
01319   if (rt_3c905c_vp.must_free_region){
01320     release_region(rt_3c905c_vp.ioaddr, rt_3c905c_vp.io_size);
01321     rt_3c905c_vp.must_free_region = 0;
01322   }
01323 }

Here is the call graph for this function:

void vortex_up struct pci_dev *  dev  )  [static]
 

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:


Variable Documentation

struct pci_dev* rt_3c905c_dev
 

Definition at line 265 of file rtl_3c905cx_drv.c.

Referenced by boomerang_interrupt(), rtl_3COM905C_open(), and rtl_3COM905C_release().

int rt_3c905c_inside_the_interrupt_handler = 0 rt_3c905c_trying_to_close = 0 [static]
 

Definition at line 252 of file rtl_3c905cx_drv.c.

Referenced by boomerang_interrupt(), and cleanup_module().

int rt_3c905c_interrupted = 0 rt_3c905c_writting = 0 [static]
 

Definition at line 253 of file rtl_3c905cx_drv.c.

Referenced by boomerang_interrupt().

unsigned char rt_3c905c_ip_addr[2][4] = {{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}
 

Definition at line 268 of file rtl_3c905cx_drv.c.

Referenced by boomerang_rx(), and rt_3c905c_set_ip_filter().

int rt_3c905c_n_filters = 0 [static]
 

Definition at line 269 of file rtl_3c905cx_drv.c.

Referenced by boomerang_rx(), and rt_3c905c_set_ip_filter().

unsigned char rt_3c905c_registered = 0x00 rt_3c905c_opened = 0x00 [static]
 

Definition at line 267 of file rtl_3c905cx_drv.c.

Referenced by cleanup_module(), and init_module().

struct vortex_private rt_3c905c_vp [static]
 

Definition at line 266 of file rtl_3c905cx_drv.c.

Referenced by boomerang_interrupt(), boomerang_rx(), cleanup_module(), rt_3c905c_obtain_mac_address(), rt_3c905c_send_packet(), rtl_3COM905C_acpi_set_WOL(), rtl_3COM905C_issue_and_wait(), rtl_3COM905C_mdio_read(), rtl_3COM905C_mdio_write(), rtl_3COM905C_set_rx_mode(), rtl_3COM905C_start_up_device(), vortex_close(), vortex_down(), vortex_error(), vortex_open(), vortex_remove_one(), and vortex_up().

struct net_policy_operations rt_3c905x_policy [static]
 

Initial value:

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().

struct fifo_rx_buffer_t rt_3c905x_rx_buffer [static]
 

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().

sem_t rt_3c905x_sem [static]
 

Definition at line 246 of file rtl_3c905cx_drv.c.

Referenced by boomerang_rx(), rtl_3COM905C_open(), rtl_3COM905C_read(), and rtl_3COM905C_release().

struct rtl_file_operations rtl_3COM905C_fops [static]
 

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().


Generated on Wed Jan 14 12:59:10 2004 for RTL-lwIP-0.4 by doxygen 1.3.4