00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231 #include "rtl_3c905cx_drv.h"
00232 #include "rt_pci.h"
00233 #include "netif/net_policy/FIFO_policy.h"
00234
00235 MODULE_LICENSE("GPL");
00236
00237 static struct net_policy_operations rt_3c905x_policy = {
00238 FIFO_add_frame_to_buffer,
00239 FIFO_extract_frame_of_buffer,
00240 FIFO_initialize_rx_buffer,
00241 FIFO_dealloc_rx_buffer,
00242 };
00243
00244 static struct fifo_rx_buffer_t rt_3c905x_rx_buffer;
00245
00246 static sem_t rt_3c905x_sem;
00247
00248 #define COM3_905C_MAJOR 204
00249 #define COM3_905C_NAME "eth"
00250 #define COM3_SIGNAL RTL_SIGUSR2
00251
00252 static int rt_3c905c_inside_the_interrupt_handler = 0, rt_3c905c_trying_to_close = 0;
00253 static int rt_3c905c_interrupted = 0, rt_3c905c_writting = 0;
00254
00255 static struct rtl_file_operations rtl_3COM905C_fops = {
00256 NULL,
00257 rtl_3COM905C_read,
00258 rtl_3COM905C_write,
00259 rtl_3COM905C_ioctl,
00260 NULL,
00261 rtl_3COM905C_open,
00262 rtl_3COM905C_release
00263 };
00264
00265 struct pci_dev *rt_3c905c_dev;
00266 static struct vortex_private rt_3c905c_vp;
00267 static unsigned char rt_3c905c_registered = 0x00, rt_3c905c_opened = 0x00;
00268 unsigned char rt_3c905c_ip_addr[2][4]={{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}};
00269 static int rt_3c905c_n_filters = 0;
00270
00271
00272
00273
00274
00275 int rt_3c905c_set_ip_filter(unsigned long ipaddr){
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 }
00288
00289
00290
00291
00292
00293 int rt_3c905c_obtain_mac_address(unsigned char *mac){
00294 int i;
00295 for(i=0; i<6; i++)
00296 mac[i]=rt_3c905c_vp.dev_addr[i];
00297 return 0;
00298 }
00299
00300
00301
00302
00303
00304
00305 static ssize_t rtl_3COM905C_read(struct rtl_file *filp, char *buf, size_t count, loff_t* ppos){
00306 sem_wait(&rt_3c905x_sem);
00307 return rt_3c905x_policy.extract_frame_of_buffer(&rt_3c905x_rx_buffer, buf);
00308 }
00309
00310
00311
00312
00313 static int rtl_3COM905C_ioctl(struct rtl_file * filp, unsigned int request, unsigned long other){
00314
00315 switch(request) {
00316 case 1:
00317 rt_3c905c_set_ip_filter(other);
00318 break;
00319 case 2:
00320 rt_3c905c_obtain_mac_address((unsigned char *)other);
00321 break;
00322 }
00323 return 0;
00324 }
00325
00326
00327
00328
00329 static int rtl_3COM905C_release (struct rtl_file *filp){
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 }
00347
00348
00349
00350
00351
00352
00353 static ssize_t rtl_3COM905C_write(struct rtl_file *filp, const char *buf, size_t count, loff_t* ppos)
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 }
00363
00364
00365
00366
00367
00368 static int rtl_3COM905C_open (struct rtl_file *filp){
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 }
00389
00390
00391
00392
00393 struct pci_dev *rtl_3COM905C_init_device(void){
00394 struct pci_dev *dev;
00395
00396
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
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 }
00410
00411
00412
00413
00414
00415
00416 int init_module(void){
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 }
00428
00429
00430
00431
00432
00433
00434 void cleanup_module(void){
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
00443
00444
00445
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 }
00470
00471
00472
00473
00474
00475
00476
00477 unsigned int boomerang_interrupt(unsigned int irq , struct pt_regs *regs){
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
00506 if (status & (HostError | RxEarly | StatsFull | IntReq)){
00507 rtl_printf("VORTEX_ERROR\n");
00508 vortex_error(dev, status);
00509 }
00510
00511
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
00518
00519
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 }
00527
00528
00529
00530
00531
00532 static int boomerang_rx(struct pci_dev *dev)
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
00545
00546
00547
00548
00549
00550
00551
00552
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
00565 if((buffer[12]==0x08) && (buffer[13]==0x06)){
00566
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
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))
00607 rt_3c905c_vp.stats.rx_packets++;
00608 }
00609
00610 entry = (++rt_3c905c_vp.cur_rx) % RX_RING_SIZE;
00611
00612
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;
00616 }
00617 return 0;
00618 }
00619
00620
00621
00622
00623
00624 int rtl_3COM905C_start_up_device(struct pci_dev *dev){
00625 struct vortex_chip_info * const vci = &vortex_info;
00626 unsigned int eeprom[0x40], checksum = 0;
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
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
00653 if (vci->flags & PCI_USES_MASTER)
00654 pci_set_master (dev);
00655
00656 rt_3c905c_vp.pdev = dev;
00657
00658
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
00681
00682 outw(base + i, ioaddr + Wn0EepromCmd);
00683
00684 for (timer = 10; timer >= 0; timer--) {
00685
00686
00687
00688 rtl_delay(162000);
00689
00690
00691
00692
00693
00694 if ((inw(ioaddr + Wn0EepromCmd) & 0x8000) == 0)
00695 break;
00696 }
00697
00698
00699 eeprom[i] = inw(ioaddr + Wn0EepromData);
00700 }
00701
00702 }
00703
00704
00705 for (i = 0; i < 0x18; i++)
00706 checksum ^= eeprom[i];
00707 checksum = (checksum ^ (checksum >> 8)) & 0xff;
00708 if (checksum != 0x00) {
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
00717 for (i = 0; i < 3; i++)
00718 ((u16 *)rt_3c905c_vp.dev_addr)[i] = htons(eeprom[i + 10]);
00719
00720
00721
00722
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;
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
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
00767
00768 rt_3c905c_vp.available_media = inw(ioaddr + Wn3_Options);
00769
00770 if ((rt_3c905c_vp.available_media & 0xff) == 0)
00771 rt_3c905c_vp.available_media = 0x40;
00772
00773
00774
00775 config = inl(ioaddr + Wn3_Config);
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
00799
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
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;
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 }
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 }
00860
00861
00862
00863
00864
00865 static void rtl_3COM905C_acpi_set_WOL(void)
00866 {
00867 long ioaddr = rt_3c905c_vp.ioaddr;
00868
00869
00870 EL3WINDOW(7);
00871 outw(2, ioaddr + 0x0c);
00872
00873 outw(SetRxFilter|RxStation|RxBroadcast, ioaddr + EL3_CMD);
00874 outw(RxEnable, ioaddr + EL3_CMD);
00875
00876
00877 rt_pci_enable_wake(rt_3c905c_vp.pdev, 0, 1);
00878 rt_pci_set_power_state(rt_3c905c_vp.pdev, 3);
00879 }
00880
00881
00882
00883
00884
00885 static int vortex_open(struct pci_dev *dev)
00886 {
00887 int i;
00888 int retval;
00889
00890
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) {
00898
00899
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;
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;
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
00926 rt_3c905c_vp.rx_ring[i-1].next = cpu_to_le32(rt_3c905c_vp.rx_ring_dma);
00927
00928
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;
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;
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
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 }
00967
00968
00969
00970
00971
00972 static void vortex_up(struct pci_dev *dev)
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);
00983 rt_pci_restore_state(dev, rt_3c905c_vp.power_state);
00984 }
00985
00986
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
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
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 ;
01019 else if ((mii_reg5 & 0x0100) != 0
01020 || (mii_reg5 & 0x00C0) == 0x0040)
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
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
01040
01041 rtl_3COM905C_issue_and_wait(RxReset|0x04);
01042
01043 outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD);
01044
01045 EL3WINDOW(4);
01046
01047
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
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
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
01080 EL3WINDOW(4);
01081 inb(ioaddr + 12);
01082
01083
01084 EL3WINDOW(7);
01085
01086 if (rt_3c905c_vp.full_bus_master_rx) {
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) {
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);
01096
01097 for (i = 0; i < RX_RING_SIZE; i++)
01098 rt_3c905c_vp.rx_ring[i].status = 0;
01099 outl(0, ioaddr + DownListPtr);
01100 }
01101
01102 rtl_3COM905C_set_rx_mode();
01103 outw(StatsDisable, ioaddr + EL3_CMD);
01104
01105 outw(RxEnable, ioaddr + EL3_CMD);
01106 outw(TxEnable, ioaddr + EL3_CMD);
01107
01108
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
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 }
01120
01121
01122
01123
01124
01125 static void
01126 rtl_3COM905C_issue_and_wait(int cmd)
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
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 }
01146
01147
01148
01149
01150
01151
01152
01153 static void rtl_3COM905C_set_rx_mode(void)
01154 {
01155 long ioaddr = rt_3c905c_vp.ioaddr;
01156 int new_mode;
01157
01158 new_mode = SetRxFilter|RxStation|RxBroadcast;
01159
01160 outw(new_mode, ioaddr + EL3_CMD);
01161 }
01162
01163
01164
01165
01166 static void vortex_down(struct pci_dev *dev)
01167 {
01168 long ioaddr = rt_3c905c_vp.ioaddr;
01169
01170
01171 outw(StatsDisable, ioaddr + EL3_CMD);
01172
01173
01174 outw(RxDisable, ioaddr + EL3_CMD);
01175 outw(TxDisable, ioaddr + EL3_CMD);
01176
01177 if (rt_3c905c_vp.if_port == XCVR_10base2)
01178
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 }
01193
01194
01195
01196
01197 static int vortex_close(struct pci_dev *dev)
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) {
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) {
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 }
01223
01224
01225
01226
01227
01228
01229 static void vortex_error(struct pci_dev *dev, int status)
01230 {
01231 long ioaddr = rt_3c905c_vp.ioaddr;
01232 int do_tx_reset = 0, reset_mask = 0;
01233
01234 if (status & RxEarly) {
01235 outw(AckIntr | RxEarly, ioaddr + EL3_CMD);
01236 }
01237 if (status & StatsFull) {
01238 static int DoneDidThat;
01239
01240 printk(KERN_DEBUG "%s: Updating stats.\n", dev->name);
01241
01242
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) {
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
01265 if (rt_3c905c_vp.full_bus_master_tx) {
01266 int bus_status = inl(ioaddr + PktStatus);
01267
01268
01269
01270 printk(KERN_ERR "%s: PCI bus error, bus status %8.8x\n", dev->name, bus_status);
01271
01272
01273 vortex_down(dev);
01274 rtl_3COM905C_issue_and_wait(TotalReset | 0xff);
01275 vortex_up(dev);
01276 } else if (fifo_diag & 0x0400)
01277 do_tx_reset = 1;
01278 if (fifo_diag & 0x3000) {
01279
01280 rtl_3COM905C_issue_and_wait(RxReset|0x07);
01281
01282 rtl_3COM905C_set_rx_mode();
01283 outw(RxEnable, ioaddr + EL3_CMD);
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 }
01293
01294
01295
01296
01297
01298 static void vortex_remove_one (struct pci_dev *pdev)
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);
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 }
01324
01325
01326
01327
01328
01329 static int rt_3c905c_send_packet(const char *buffer, size_t size)
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
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 }
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380 #define rtl_3COM905C_mdio_delay() inl(mdio_addr)
01381
01382 #define MDIO_SHIFT_CLK 0x01
01383 #define MDIO_DIR_WRITE 0x04
01384 #define MDIO_DATA_WRITE0 (0x00 | MDIO_DIR_WRITE)
01385 #define MDIO_DATA_WRITE1 (0x02 | MDIO_DIR_WRITE)
01386 #define MDIO_DATA_READ 0x02
01387 #define MDIO_ENB_IN 0x00
01388
01389
01390
01391
01392
01393 static void rtl_3COM905C_mdio_sync(long ioaddr, int bits)
01394 {
01395 long mdio_addr = ioaddr + Wn4_PhysicalMgmt;
01396
01397
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 }
01405
01406
01407 static int rtl_3COM905C_mdio_read(int phy_id, int location)
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
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
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 }
01437
01438
01439 static void rtl_3COM905C_mdio_write(int phy_id, int location, int value)
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
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
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 }
01466
01467