Subversion Repositories Kolibri OS

Rev

Rev 4467 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2004-2013. All rights reserved.    ;;
  4. ;; Distributed under terms of the GNU General Public License       ;;
  5. ;;                                                                 ;;
  6. ;;  MTD80x driver for KolibriOS                                    ;;
  7. ;;                                                                 ;;
  8. ;;  Based on mtd80x.c from the etherboot project                   ;;
  9. ;;                                                                 ;;
  10. ;;  Written by hidnplayr@kolibrios.org                             ;;
  11. ;;                                                                 ;;
  12. ;;          GNU GENERAL PUBLIC LICENSE                             ;;
  13. ;;             Version 2, June 1991                                ;;
  14. ;;                                                                 ;;
  15. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  16.  
  17. format MS COFF
  18.  
  19.         API_VERSION             = 0x01000100
  20.         DRIVER_VERSION          = 5
  21.  
  22.         MAX_DEVICES             = 16
  23.  
  24.         DEBUG                   = 1
  25.         __DEBUG__               = 1
  26.         __DEBUG_LEVEL__         = 2
  27.  
  28.         NUM_TX_DESC             = 4
  29.         NUM_RX_DESC             = 4
  30.  
  31. include '../proc32.inc'
  32. include '../imports.inc'
  33. include '../fdo.inc'
  34. include '../netdrv.inc'
  35.  
  36. public START
  37. public service_proc
  38. public version
  39.  
  40.  
  41. ; for different PHY
  42.  
  43.     MysonPHY            = 1
  44.     AhdocPHY            = 2
  45.     SeeqPHY             = 3
  46.     MarvellPHY          = 4
  47.     Myson981            = 5
  48.     LevelOnePHY         = 6
  49.     OtherPHY            = 10
  50.  
  51. ; Offsets to the Command and Status Registers.
  52.  
  53.     PAR0                = 0x0           ; physical address 0-3
  54.     PAR1                = 0x04          ; physical address 4-5
  55.     MAR0                = 0x08          ; multicast address 0-3
  56.     MAR1                = 0x0C          ; multicast address 4-7
  57.     FAR0                = 0x10          ; flow-control address 0-3
  58.     FAR1                = 0x14          ; flow-control address 4-5
  59.     TCRRCR              = 0x18          ; receive & transmit configuration
  60.     BCR                 = 0x1C          ; bus command
  61.     TXPDR               = 0x20          ; transmit polling demand
  62.     RXPDR               = 0x24          ; receive polling demand
  63.     RXCWP               = 0x28          ; receive current word pointer
  64.     TXLBA               = 0x2C          ; transmit list base address
  65.     RXLBA               = 0x30          ; receive list base address
  66.     ISR                 = 0x34          ; interrupt status
  67.     IMR                 = 0x38          ; interrupt mask
  68.     FTH                 = 0x3C          ; flow control high/low threshold
  69.     MANAGEMENT          = 0x40          ; bootrom/eeprom and mii management
  70.     TALLY               = 0x44          ; tally counters for crc and mpa
  71.     TSR                 = 0x48          ; tally counter for transmit status
  72.     BMCRSR              = 0x4c          ; basic mode control and status
  73.     PHYIDENTIFIER       = 0x50          ; phy identifier
  74.     ANARANLPAR          = 0x54          ; auto-negotiation advertisement and link partner ability
  75.     ANEROCR             = 0x58          ; auto-negotiation expansion and pci conf.
  76.     BPREMRPSR           = 0x5c          ; bypass & receive error mask and phy status
  77.  
  78. ; Bits in the interrupt status/enable registers.
  79.  
  80.     RFCON               = 0x00020000    ; receive flow control xon packet
  81.     RFCOFF              = 0x00010000    ; receive flow control xoff packet
  82.     LSCStatus           = 0x00008000    ; link status change
  83.     ANCStatus           = 0x00004000    ; autonegotiation completed
  84.     FBE                 = 0x00002000    ; fatal bus error
  85.     FBEMask             = 0x00001800    ; mask bit12-11
  86.     ParityErr           = 0x00000000    ; parity error
  87.     TargetErr           = 0x00001000    ; target abort
  88.     MasterErr           = 0x00000800    ; master error
  89.     TUNF                = 0x00000400    ; transmit underflow
  90.     ROVF                = 0x00000200    ; receive overflow
  91.     ETI                 = 0x00000100    ; transmit early int
  92.     ERI                 = 0x00000080    ; receive early int
  93.     CNTOVF              = 0x00000040    ; counter overflow
  94.     RBU                 = 0x00000020    ; receive buffer unavailable
  95.     TBU                 = 0x00000010    ; transmit buffer unavilable
  96.     TI                  = 0x00000008    ; transmit interrupt
  97.     RI                  = 0x00000004    ; receive interrupt
  98.     RxErr               = 0x00000002    ; receive error
  99.  
  100. ; Bits in the NetworkConfig register.
  101.  
  102.     RxModeMask          = 0xe0
  103.     AcceptAllPhys       = 0x80          ; promiscuous mode
  104.     AcceptBroadcast     = 0x40          ; accept broadcast
  105.     AcceptMulticast     = 0x20          ; accept mutlicast
  106.     AcceptRunt          = 0x08          ; receive runt pkt
  107.     ALP                 = 0x04          ; receive long pkt
  108.     AcceptErr           = 0x02          ; receive error pkt
  109.  
  110.     AcceptMyPhys        = 0x00000000
  111.     RxEnable            = 0x00000001
  112.     RxFlowCtrl          = 0x00002000
  113.     TxEnable            = 0x00040000
  114.     TxModeFDX           = 0x00100000
  115.     TxThreshold         = 0x00e00000
  116.  
  117.     PS1000              = 0x00010000
  118.     PS10                = 0x00080000
  119.     FD                  = 0x00100000
  120.  
  121.  
  122. ; Bits in network_desc.status
  123.  
  124.     RXOWN               = 0x80000000    ; own bit
  125.     FLNGMASK            = 0x0fff0000    ; frame length
  126.     FLNGShift           = 16
  127.     MARSTATUS           = 0x00004000    ; multicast address received
  128.     BARSTATUS           = 0x00002000    ; broadcast address received
  129.     PHYSTATUS           = 0x00001000    ; physical address received
  130.     RXFSD               = 0x00000800    ; first descriptor
  131.     RXLSD               = 0x00000400    ; last descriptor
  132.     ErrorSummary        = 0x80          ; error summary
  133.     RUNT                = 0x40          ; runt packet received
  134.     LONG                = 0x20          ; long packet received
  135.     FAE                 = 0x10          ; frame align error
  136.     CRC                 = 0x08          ; crc error
  137.     RXER                = 0x04          ; receive error
  138.  
  139. ; rx_desc_control_bits
  140.  
  141.     RXIC                = 0x00800000    ; interrupt control
  142.     RBSShift            = 0
  143.  
  144. ; tx_desc_status_bits
  145.  
  146.     TXOWN               = 0x80000000    ; own bit
  147.     JABTO               = 0x00004000    ; jabber timeout
  148.     CSL                 = 0x00002000    ; carrier sense lost
  149.     LC                  = 0x00001000    ; late collision
  150.     EC                  = 0x00000800    ; excessive collision
  151.     UDF                 = 0x00000400    ; fifo underflow
  152.     DFR                 = 0x00000200    ; deferred
  153.     HF                  = 0x00000100    ; heartbeat fail
  154.     NCRMask             = 0x000000ff    ; collision retry count
  155.     NCRShift            = 0
  156.  
  157. ; tx_desc_control_bits
  158.  
  159.     TXIC                = 0x80000000    ; interrupt control
  160.     ETIControl          = 0x40000000    ; early transmit interrupt
  161.     TXLD                = 0x20000000    ; last descriptor
  162.     TXFD                = 0x10000000    ; first descriptor
  163.     CRCEnable           = 0x08000000    ; crc control
  164.     PADEnable           = 0x04000000    ; padding control
  165.     RetryTxLC           = 0x02000000    ; retry late collision
  166.     PKTSMask            = 0x3ff800      ; packet size bit21-11
  167.     PKTSShift           = 11
  168.     TBSMask             = 0x000007ff    ; transmit buffer bit 10-0
  169.     TBSShift            = 0
  170.  
  171. ; BootROM/EEPROM/MII Management Register
  172.  
  173.     MASK_MIIR_MII_READ  = 0x00000000
  174.     MASK_MIIR_MII_WRITE = 0x00000008
  175.     MASK_MIIR_MII_MDO   = 0x00000004
  176.     MASK_MIIR_MII_MDI   = 0x00000002
  177.     MASK_MIIR_MII_MDC   = 0x00000001
  178.  
  179. ; ST+OP+PHYAD+REGAD+TA
  180.  
  181.     OP_READ             = 0x6000        ; ST:01+OP:10+PHYAD+REGAD+TA:Z0
  182.     OP_WRITE            = 0x5002        ; ST:01+OP:01+PHYAD+REGAD+TA:10
  183.  
  184. ; -------------------------------------------------------------------------
  185. ;      Constants for Myson PHY
  186. ; -------------------------------------------------------------------------
  187.  
  188.     MysonPHYID          = 0xd0000302
  189.     MysonPHYID0         = 0x0302
  190.     StatusRegister      = 18
  191.     SPEED100            = 0x0400        ; bit10
  192.     FULLMODE            = 0x0800        ; bit11
  193.  
  194. ; -------------------------------------------------------------------------
  195. ;      Constants for Seeq 80225 PHY
  196. ; -------------------------------------------------------------------------
  197.  
  198.     SeeqPHYID0          = 0x0016
  199.     MIIRegister18       = 18
  200.     SPD_DET_100         = 0x80
  201.     DPLX_DET_FULL       = 0x40
  202.  
  203. ; -------------------------------------------------------------------------
  204. ;      Constants for Ahdoc 101 PHY
  205. ; -------------------------------------------------------------------------
  206.  
  207.     AhdocPHYID0         = 0x0022
  208.     DiagnosticReg       = 18
  209.     DPLX_FULL           = 0x0800
  210.     Speed_100           = 0x0400
  211.  
  212. ; --------------------------------------------------------------------------
  213. ;      Constants
  214. ; --------------------------------------------------------------------------
  215.  
  216.     MarvellPHYID0               = 0x0141
  217.     LevelOnePHYID0              = 0x0013
  218.  
  219.     MII1000BaseTControlReg      = 9
  220.     MII1000BaseTStatusReg       = 10
  221.     SpecificReg                 = 17
  222.  
  223. ; for 1000BaseT Control Register
  224.  
  225.     PHYAbletoPerform1000FullDuplex = 0x0200
  226.     PHYAbletoPerform1000HalfDuplex = 0x0100
  227.     PHY1000AbilityMask             = 0x300
  228.  
  229. ; for phy specific status register, marvell phy.
  230.  
  231.     SpeedMask      = 0x0c000
  232.     Speed_1000M    = 0x08000
  233.     Speed_100M     = 0x4000
  234.     Speed_10M      = 0
  235.     Full_Duplex    = 0x2000
  236.  
  237. ; for phy specific status register, levelone phy
  238.  
  239.     LXT1000_100M   = 0x08000
  240.     LXT1000_1000M  = 0x0c000
  241.     LXT1000_Full   = 0x200
  242.  
  243. ; for PHY
  244.  
  245.     LinkIsUp       = 0x0004
  246.     LinkIsUp2      = 0x00040000
  247.  
  248.  
  249.  
  250. virtual at 0
  251.  
  252.         mtd_desc:
  253.         .status                 dd ?
  254.         .control                dd ?
  255.         .buffer                 dd ?
  256.         .next_desc              dd ?
  257.  
  258.         .next_desc_logical      dd ?
  259.         .skbuff                 dd ?
  260.  
  261.         .reserved1              dd ?
  262.         .reserved2              dd ?
  263.  
  264.         .size = $
  265.  
  266. end virtual
  267.  
  268.  
  269. virtual at ebx
  270.  
  271.         device:
  272.  
  273.         ETH_DEVICE
  274.  
  275.         .tx_desc        rb NUM_TX_DESC*mtd_desc.size
  276.         .rx_desc        rb NUM_RX_DESC*mtd_desc.size
  277.  
  278.         .io_addr        dd ?
  279.         .pci_bus        dd ?
  280.         .pci_dev        dd ?
  281.         .irq_line       db ?
  282.         .dev_id         dw ?
  283.  
  284.         .flags          dd ?
  285.  
  286.         .crvalue        dd ?
  287.         .bcrvalue       dd ?
  288.  
  289.         .cur_rx         dd ?
  290.         .cur_tx         dd ?
  291.  
  292. ; These values are keep track of the transceiver/media in use.
  293.  
  294.         .linkok         dd ?
  295.         .line_speed     dd ?
  296.         .duplexmode     dd ?
  297.         .default_port   dd ?
  298.         .PHYType        dd ?
  299.  
  300. ; MII transceiver section.
  301.  
  302.         .mii_cnt        dd ?    ; MII device addresses.
  303.         .phys           db ?    ; MII device addresses.
  304.  
  305.         device_size = $ - device
  306.  
  307. end virtual
  308.  
  309.  
  310.  
  311. section '.flat' code readable align 16
  312.  
  313. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  314. ;;                        ;;
  315. ;; proc START             ;;
  316. ;;                        ;;
  317. ;; (standard driver proc) ;;
  318. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  319.  
  320. align 4
  321. proc START stdcall, state:dword
  322.  
  323.         cmp [state], 1
  324.         jne .exit
  325.  
  326.   .entry:
  327.  
  328.         DEBUGF  2,"Loading %s driver\n", my_service
  329.         stdcall RegService, my_service, service_proc
  330.         ret
  331.  
  332.   .fail:
  333.   .exit:
  334.         xor eax, eax
  335.         ret
  336.  
  337. endp
  338.  
  339.  
  340. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  341. ;;                        ;;
  342. ;; proc SERVICE_PROC      ;;
  343. ;;                        ;;
  344. ;; (standard driver proc) ;;
  345. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  346.  
  347. align 4
  348. proc service_proc stdcall, ioctl:dword
  349.  
  350.         mov     edx, [ioctl]
  351.         mov     eax, [IOCTL.io_code]
  352.  
  353. ;------------------------------------------------------
  354.  
  355.         cmp     eax, 0 ;SRV_GETVERSION
  356.         jne     @F
  357.  
  358.         cmp     [IOCTL.out_size], 4
  359.         jb      .fail
  360.         mov     eax, [IOCTL.output]
  361.         mov     [eax], dword API_VERSION
  362.  
  363.         xor     eax, eax
  364.         ret
  365.  
  366. ;------------------------------------------------------
  367.   @@:
  368.         cmp     eax, 1 ;SRV_HOOK
  369.         jne     .fail
  370.  
  371.         cmp     [IOCTL.inp_size], 3                     ; Data input must be at least 3 bytes
  372.         jb      .fail
  373.  
  374.         mov     eax, [IOCTL.input]
  375.         cmp     byte [eax], 1                           ; 1 means device number and bus number (pci) are given
  376.         jne     .fail                                   ; other types arent supported for this card yet
  377.  
  378. ; check if the device is already listed
  379.  
  380.         mov     esi, device_list
  381.         mov     ecx, [devices]
  382.         test    ecx, ecx
  383.         jz      .firstdevice
  384.  
  385. ;        mov     eax, [IOCTL.input]                     ; get the pci bus and device numbers
  386.         mov     ax , [eax+1]                            ;
  387.   .nextdevice:
  388.         mov     ebx, [esi]
  389.         cmp     al, byte[device.pci_bus]
  390.         jne     @f
  391.         cmp     ah, byte[device.pci_dev]
  392.         je      .find_devicenum                         ; Device is already loaded, let's find it's device number
  393.        @@:
  394.         add     esi, 4
  395.         loop    .nextdevice
  396.  
  397.  
  398. ; This device doesnt have its own eth_device structure yet, lets create one
  399.   .firstdevice:
  400.         cmp     [devices], MAX_DEVICES                  ; First check if the driver can handle one more card
  401.         jae     .fail
  402.  
  403.         allocate_and_clear ebx, device_size, .fail
  404.  
  405. ; Fill in the direct call addresses into the struct
  406.  
  407.         mov     [device.reset], reset
  408.         mov     [device.transmit], transmit
  409.         mov     [device.unload], unload
  410.         mov     [device.name], my_service
  411.  
  412. ; save the pci bus and device numbers
  413.  
  414.         mov     eax, [IOCTL.input]
  415.         movzx   ecx, byte[eax+1]
  416.         mov     [device.pci_bus], ecx
  417.         movzx   ecx, byte[eax+2]
  418.         mov     [device.pci_dev], ecx
  419.  
  420. ; Now, it's time to find the base io addres of the PCI device
  421.  
  422.         PCI_find_io
  423.  
  424. ; We've found the io address, find IRQ now
  425.  
  426.         PCI_find_irq
  427.  
  428.         DEBUGF  2,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
  429.         [device.pci_dev]:1,[device.pci_bus]:1,[device.irq_line]:1,[device.io_addr]:8
  430.  
  431. ; Ok, the eth_device structure is ready, let's probe the device
  432. ; Because initialization fires IRQ, IRQ handler must be aware of this device
  433.         mov     eax, [devices]                                          ; Add the device structure to our device list
  434.         mov     [device_list+4*eax], ebx                                ; (IRQ handler uses this list to find device)
  435.         inc     [devices]                                               ;
  436.  
  437.         call    probe                                                   ; this function will output in eax
  438.         test    eax, eax
  439.         jnz     .err2                                                   ; If an error occured, exit
  440.  
  441.         mov     [device.type], NET_TYPE_ETH
  442.         call    NetRegDev
  443.  
  444.         cmp     eax, -1
  445.         je      .destroy
  446.  
  447.         ret
  448.  
  449. ; If the device was already loaded, find the device number and return it in eax
  450.  
  451.   .find_devicenum:
  452.         DEBUGF  2,"Trying to find device number of already registered device\n"
  453.         call    NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
  454.                                                                         ; into a device number in edi
  455.         mov     eax, edi                                                ; Application wants it in eax instead
  456.         DEBUGF  2,"Kernel says: %u\n", eax
  457.         ret
  458.  
  459. ; If an error occured, remove all allocated data and exit (returning -1 in eax)
  460.  
  461.   .destroy:
  462.         ; todo: reset device into virgin state
  463.  
  464.   .err2:
  465.         dec     [devices]
  466.   .err:
  467.         DEBUGF  2,"removing device structure\n"
  468.         stdcall KernelFree, ebx
  469.   .fail:
  470.         or      eax, -1
  471.         ret
  472.  
  473. ;------------------------------------------------------
  474. endp
  475.  
  476.  
  477. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  478. ;;                                                                        ;;
  479. ;;        Actual Hardware dependent code starts here                      ;;
  480. ;;                                                                        ;;
  481. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  482.  
  483.  
  484.  
  485. align 4
  486. unload:
  487.         ; TODO: (in this particular order)
  488.         ;
  489.         ; - Stop the device
  490.  
  491. ;    /* Disable Tx Rx*/
  492. ;    outl( mtdx.crvalue & (~TxEnable) & (~RxEnable), mtdx.ioaddr + TCRRCR );
  493. ;
  494. ;    /* Reset the chip to erase previous misconfiguration. */
  495. ;    mtd_reset(nic);
  496.  
  497.         ; - Detach int handler
  498.         ; - Remove device from local list (device_list)
  499.         ; - call unregister function in kernel
  500.         ; - Remove all allocated structures and buffers the card used
  501.  
  502.         or      eax,-1
  503.  
  504. ret
  505.  
  506.  
  507. ;-------
  508. ;
  509. ; PROBE
  510. ;
  511. ;-------
  512. align 4
  513. probe:
  514.  
  515.         DEBUGF  2,"Probing mtd80x device\n"
  516.  
  517.         PCI_make_bus_master
  518.  
  519.         stdcall PciRead32, [device.pci_bus], [device.pci_dev], 0
  520.  
  521.         cmp     ax, 0x1516
  522.         jne     .notfound
  523.         shr     eax, 16
  524.         mov     [device.dev_id], ax
  525.  
  526.         cmp     ax, 0x0800
  527.         je      .has_mii_xcvr
  528.  
  529.         cmp     ax, 0x0803
  530.         je      .has_chip_xcvr
  531.  
  532.         cmp     ax, 0x0891
  533.         je      .has_mii_xcvr
  534.  
  535.   .notfound:
  536.         DEBUGF  1,"Device not supported!\n"
  537.         xor     eax, eax
  538.         dec     eax
  539.         ret
  540.  
  541.   .has_chip_xcvr:
  542.         DEBUGF  1,"Device has chip xcvr\n"
  543.  
  544.         jmp     .xcvr_set
  545.  
  546.   .has_mii_xcvr:
  547.         DEBUGF  1,"Device has mii xcvr\n"
  548.  
  549.   .xcvr_set:
  550.  
  551.         call    read_mac
  552.  
  553. ; Reset the chip to erase previous misconfiguration.
  554.  
  555.         set_io  0
  556.         set_io  BCR
  557.         xor     eax, eax
  558.         inc     eax
  559.         out     dx, eax
  560.  
  561. ; find the connected MII xcvrs
  562.  
  563.         cmp     [device.dev_id], 0x0803
  564.         je      .is_803
  565.  
  566. ;        int     phy, phy_idx =   0;
  567. ;
  568. ;        for (phy =   1; phy < 32 && phy_idx < 1; phy++) {
  569. ;            int mii_status =   mdio_read(nic, phy, 1);
  570. ;
  571. ;            if (mii_status !=   0xffff && mii_status !=   0x0000) {
  572. ;                mtdx.phys[phy_idx] =   phy;
  573. ;
  574. ;                DBG ( "%s: MII PHY found at address %d, status "
  575. ;                      "0x%4.4x.\n", mtdx.nic_name, phy, mii_status );
  576. ;                /* get phy type */
  577. ;                {
  578. ;                    unsigned int data;
  579. ;
  580. ;                    data =   mdio_read(nic, mtdx.phys[phy_idx], 2);
  581. ;                    if (data equ=   SeeqPHYID0)
  582. ;                        mtdx.PHYType =   SeeqPHY;
  583. ;                    else if (data equ=   AhdocPHYID0)
  584. ;                        mtdx.PHYType =   AhdocPHY;
  585. ;                    else if (data equ=   MarvellPHYID0)
  586. ;                        mtdx.PHYType =   MarvellPHY;
  587. ;                    else if (data equ=   MysonPHYID0)
  588. ;                        mtdx.PHYType =   Myson981;
  589. ;                    else if (data equ=   LevelOnePHYID0)
  590. ;                        mtdx.PHYType =   LevelOnePHY;
  591. ;                    else
  592. ;                        mtdx.PHYType =   OtherPHY;
  593. ;                }
  594. ;                phy_idx++;
  595. ;            }
  596. ;        }
  597. ;
  598. ;        mtdx.mii_cnt =   phy_idx;
  599. ;        if (phy_idx equ=   0) {
  600. ;            printf("%s: MII PHY not found -- this device may "
  601. ;                   "not operate correctly.\n", mtdx.nic_name);
  602. ;        }
  603.  
  604.         jmp     .no_803
  605.  
  606.   .is_803:
  607.  
  608.         mov     [device.phys], 32
  609.  
  610. ; get phy type
  611.         set_io  0
  612.         set_io  PHYIDENTIFIER
  613.         in      eax, dx
  614.  
  615.         cmp     eax, MysonPHYID
  616.         jne     @f
  617.  
  618.         mov     [device.PHYType], MysonPHY
  619.         DEBUGF  1,"MysonPHY\n"
  620.         jmp     .no_803
  621.  
  622.        @@:
  623.         mov     [device.PHYType], OtherPHY
  624.         DEBUGF  1,"OtherPHY\n"
  625.  
  626.   .no_803:
  627.  
  628. ;-------
  629. ;
  630. ; RESET
  631. ;
  632. ;-------
  633. align 4
  634. reset:
  635.  
  636.         DEBUGF  1,"Resetting mtd80x\n"
  637.  
  638. ;--------------------------------
  639. ; insert irq handler on given irq
  640.  
  641.         movzx   eax, [device.irq_line]
  642.         DEBUGF  1,"Attaching int handler to irq %x\n", eax:1
  643.         stdcall AttachIntHandler, eax, int_handler, dword 0
  644.         test    eax, eax
  645.         jnz     @f
  646.         DEBUGF  1,"\nCould not attach int handler!\n"
  647. ;        or      eax, -1
  648. ;        ret
  649.   @@:
  650.  
  651. ; Reset the chip to erase previous misconfiguration.
  652.  
  653.         set_io  0
  654.         set_io  BCR
  655.         xor     eax, eax
  656.         inc     eax
  657.         out     dx, eax
  658.  
  659.         call    init_ring
  660.  
  661. ; Initialize other registers.
  662. ; Configure the PCI bus bursts and FIFO thresholds.
  663.  
  664.         mov     [device.bcrvalue], 0x10 ; little-endian, 8 burst length
  665.         mov     [device.crvalue], 0xa00 ; 128 burst length
  666.  
  667.         cmp     [device.dev_id], 0x891
  668.         jne     @f
  669.         or      [device.bcrvalue], 0x200       ; set PROG bit
  670.         or      [device.crvalue], 0x02000000   ; set enhanced bit
  671.        @@:
  672.  
  673.         or      [device.crvalue], RxEnable + TxThreshold + TxEnable
  674.  
  675.         call    set_rx_mode
  676.  
  677.         set_io  0
  678.         set_io  BCR
  679.         mov     eax, [device.bcrvalue]
  680.         out     dx, eax
  681.  
  682.         set_io  TCRRCR
  683.         mov     eax, [device.crvalue]
  684.         out     dx, eax
  685.  
  686.         call    getlinkstatus
  687.         call    getlinktype
  688.  
  689. ; Restart Rx engine if stopped.
  690.  
  691.         set_io  0
  692.         set_io  RXPDR
  693.         xor     eax, eax
  694.         out     dx, eax
  695.  
  696. ; Enable interrupts
  697.  
  698.         set_io  0
  699.         set_io  ISR
  700.         mov     eax, (FBE or TUNF or CNTOVF or RBU or TI or RI)
  701.         out     dx, eax
  702.  
  703.         set_io  IMR
  704. ;        mov     eax, (FBE or TUNF or CNTOVF or RBU or TI or RI)
  705.         out     dx, eax
  706.  
  707. ; clear packet/byte counters
  708.  
  709.         xor     eax, eax
  710.         lea     edi, [device.bytes_tx]
  711.         mov     ecx, 6
  712.         rep     stosd
  713.  
  714.         mov     [device.mtu], 1514
  715.  
  716. ; Set link state to unknown
  717.         mov     [device.state], ETH_LINK_UNKOWN
  718.  
  719.         xor     eax, eax
  720.         ret
  721.  
  722.  
  723.  
  724.  
  725. align 4
  726. init_ring:
  727.  
  728.         DEBUGF  1,"initializing rx and tx ring\n"
  729.  
  730. ; Initialize all Rx descriptors
  731.  
  732.         lea     esi, [device.rx_desc]
  733.         mov     [device.cur_rx], esi
  734.         mov     ecx, NUM_RX_DESC
  735.   .rx_desc_loop:
  736.         mov     [esi + mtd_desc.status], RXOWN
  737.         mov     [esi + mtd_desc.control], 1536 shl RBSShift
  738.  
  739.         lea     eax, [esi + mtd_desc.size]
  740.         mov     [esi + mtd_desc.next_desc_logical], eax
  741.         push    ecx esi
  742.         GetRealAddr
  743.         mov     [esi + mtd_desc.next_desc], eax
  744.  
  745.         stdcall KernelAlloc, 1536
  746.         pop     esi
  747.         push    esi
  748.         mov     [esi + mtd_desc.skbuff], eax
  749.         call    GetPgAddr
  750.         pop     esi ecx
  751.         mov     [esi + mtd_desc.buffer], eax
  752.  
  753.         add     esi, mtd_desc.size
  754.         loop    .rx_desc_loop
  755.  
  756. ; Mark the last entry as wrapping the ring.
  757.  
  758.         lea     eax, [device.rx_desc]
  759.         mov     [esi - mtd_desc.size + mtd_desc.next_desc_logical], eax
  760.         push    esi
  761.         GetRealAddr
  762.         pop     esi
  763.         mov     [esi - mtd_desc.size + mtd_desc.next_desc], eax
  764.  
  765.         set_io  0
  766.         set_io  RXLBA
  767.         out     dx, eax
  768.  
  769. ; Initialize all Tx descriptors
  770.  
  771.         lea     esi, [device.tx_desc]
  772.         mov     [device.cur_tx], esi
  773.         mov     ecx, NUM_TX_DESC
  774.   .tx_desc_loop:
  775.         mov     [esi + mtd_desc.status], 0
  776.  
  777.         lea     eax, [esi + mtd_desc.size]
  778.         mov     [esi + mtd_desc.next_desc_logical], eax
  779.         push    ecx esi
  780.         GetRealAddr
  781.         pop     esi ecx
  782.         mov     [esi + mtd_desc.next_desc], eax
  783.  
  784.         add     esi, mtd_desc.size
  785.         loop    .tx_desc_loop
  786.  
  787. ; Mark the last entry as wrapping the ring.
  788.  
  789.         lea     eax, [device.tx_desc]
  790.         mov     [esi - mtd_desc.size + mtd_desc.next_desc_logical], eax
  791.         push    esi
  792.         GetRealAddr
  793.         pop     esi
  794.         mov     [esi - mtd_desc.size + mtd_desc.next_desc], eax
  795.  
  796.         set_io  0
  797.         set_io  TXLBA
  798.         out     dx, eax
  799.  
  800.         ret
  801.  
  802.  
  803. align 4
  804. set_rx_mode:
  805.  
  806.         DEBUGF  1,"Setting RX mode\n"
  807.  
  808. ; Too many to match, or accept all multicasts.
  809.  
  810.         set_io  0
  811.         set_io  MAR0
  812.         xor     eax, eax
  813.         not     eax
  814.         out     dx, eax
  815.         set_io  MAR1
  816.         out     dx, eax
  817.  
  818.         and     [device.crvalue], not (RxModeMask)
  819.         or      [device.crvalue], AcceptBroadcast + AcceptMulticast + AcceptMyPhys
  820.  
  821.         ret
  822.  
  823.  
  824. align 4
  825. getlinkstatus:
  826.  
  827.         DEBUGF  1,"Getting link status\n"
  828.  
  829.         mov     [device.linkok], 0
  830.  
  831.         cmp     [device.PHYType], MysonPHY
  832.         jne     .no_myson_phy
  833.  
  834.         set_io  0
  835.         set_io  BMCRSR
  836.         mov     ecx, 1000
  837.   .loop1:
  838.         in      eax, dx
  839.         test    eax, LinkIsUp2
  840.         jnz     .link_ok
  841.  
  842.         push    ecx edx ebx
  843.         mov     esi, 10
  844.         call    Sleep
  845.         pop     ebx edx ecx
  846.         loop    .loop1
  847.  
  848.         ret
  849.  
  850.   .no_myson_phy:
  851.  
  852. ;        for (i =   0; i < DelayTime; ++i) {
  853. ;            if (mdio_read(nic, mtdx.phys[0], MII_BMSR) & BMSR_LSTATUS) {
  854. ;                mtdx.linkok =   1;
  855. ;                return;
  856. ;            }
  857. ;            m80x_delay(100);
  858.  
  859.         ret
  860.  
  861.   .link_ok:
  862.         DEBUGF  1,"Link is up\n"
  863.         inc     [device.linkok]
  864.         ret
  865.  
  866.  
  867.  
  868.  
  869. align 4
  870. getlinktype:
  871.  
  872.         DEBUGF  1,"Getting link type\n"
  873.  
  874.         cmp     [device.PHYType], MysonPHY
  875.         jne     .no_myson_phy
  876.  
  877.         DEBUGF  1,"myson PHY\n"
  878.  
  879.         set_io  0
  880.         set_io  TCRRCR
  881.         in      eax, dx
  882.  
  883.         mov     [device.duplexmode], 1  ; 1 =   half duplex
  884.         test    eax, FD
  885.         jne     @f
  886.         DEBUGF  1,"full duplex\n"
  887.         inc     [device.duplexmode]     ; 2 =   full duplex
  888.        @@:
  889.  
  890.         mov     [device.line_speed], 1  ; 1 =   10M
  891.         test    eax, PS10
  892.         jne     @f
  893.         DEBUGF  1,"100mbit\n"
  894.         inc     [device.line_speed]     ; 2 =   100M
  895.        @@:
  896.  
  897.         ret
  898.  
  899.   .no_myson_phy:
  900.  
  901.         DEBUGF  1,"no myson phy\n"
  902.  
  903. ;        if (mtdx.PHYType equ=   SeeqPHY) { /* this PHY is SEEQ 80225 */
  904. ;            unsigned int data;
  905. ;
  906. ;            data =   mdio_read(dev, mtdx.phys[0], MIIRegister18);
  907. ;            if (data & SPD_DET_100)
  908. ;                mtdx.line_speed =   2; /* 100M */
  909. ;            else
  910. ;                mtdx.line_speed =   1; /* 10M */
  911. ;            if (data & DPLX_DET_FULL)
  912. ;                mtdx.duplexmode =   2; /* full duplex mode */
  913. ;            else
  914. ;                mtdx.duplexmode =   1; /* half duplex mode */
  915. ;        } else if (mtdx.PHYType equ=   AhdocPHY) {
  916. ;            unsigned int data;
  917. ;
  918. ;            data =   mdio_read(dev, mtdx.phys[0], DiagnosticReg);
  919. ;            if (data & Speed_100)
  920. ;                mtdx.line_speed =   2; /* 100M */
  921. ;            else
  922. ;                mtdx.line_speed =   1; /* 10M */
  923. ;            if (data & DPLX_FULL)
  924. ;                mtdx.duplexmode =   2; /* full duplex mode */
  925. ;            else
  926. ;                mtdx.duplexmode =   1; /* half duplex mode */
  927. ;        }
  928. ;        else if (mtdx.PHYType equ=   MarvellPHY) {
  929. ;            unsigned int data;
  930. ;
  931. ;            data =   mdio_read(dev, mtdx.phys[0], SpecificReg);
  932. ;            if (data & Full_Duplex)
  933. ;                mtdx.duplexmode =   2; /* full duplex mode */
  934. ;            else
  935. ;                mtdx.duplexmode =   1; /* half duplex mode */
  936. ;            data &=   SpeedMask;
  937. ;            if (data equ=   Speed_1000M)
  938. ;                mtdx.line_speed =   3; /* 1000M */
  939. ;            else if (data equ=   Speed_100M)
  940. ;                mtdx.line_speed =   2; /* 100M */
  941. ;            else
  942. ;                mtdx.line_speed =   1; /* 10M */
  943. ;        }
  944. ;        else if (mtdx.PHYType equ=   Myson981) {
  945. ;            unsigned int data;
  946. ;
  947. ;            data =   mdio_read(dev, mtdx.phys[0], StatusRegister);
  948. ;
  949. ;            if (data & SPEED100)
  950. ;                mtdx.line_speed =   2;
  951. ;            else
  952. ;                mtdx.line_speed =   1;
  953. ;
  954. ;            if (data & FULLMODE)
  955. ;                mtdx.duplexmode =   2;
  956. ;            else
  957. ;                mtdx.duplexmode =   1;
  958. ;        }
  959. ;        else if (mtdx.PHYType equ=   LevelOnePHY) {
  960. ;            unsigned int data;
  961. ;
  962. ;            data =   mdio_read(dev, mtdx.phys[0], SpecificReg);
  963. ;            if (data & LXT1000_Full)
  964. ;                mtdx.duplexmode =   2; /* full duplex mode */
  965. ;            else
  966. ;                mtdx.duplexmode =   1; /* half duplex mode */
  967. ;            data &=   SpeedMask;
  968. ;            if (data equ=   LXT1000_1000M)
  969. ;                mtdx.line_speed =   3; /* 1000M */
  970. ;            else if (data equ=   LXT1000_100M)
  971. ;                mtdx.line_speed =   2; /* 100M */
  972. ;            else
  973.  ;               mtdx.line_speed =   1; /* 10M */
  974.   ;      }
  975.  
  976. ;        // chage crvalue
  977. ;        // mtdx.crvalue&equ(~PS10)&(~FD);
  978. ;        mtdx.crvalue &=   (~PS10) & (~FD) & (~PS1000);
  979. ;        if (mtdx.line_speed equ=   1)
  980. ;            mtdx.crvalue |=   PS10;
  981. ;        else if (mtdx.line_speed equ=   3)
  982. ;            mtdx.crvalue |=   PS1000;
  983. ;        if (mtdx.duplexmode equ=   2)
  984. ;            mtdx.crvalue |=   FD;
  985. ;
  986.  
  987.         ret
  988.  
  989.  
  990.  
  991.  
  992. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  993. ;;                                         ;;
  994. ;; Transmit                                ;;
  995. ;;                                         ;;
  996. ;; In: buffer pointer in [esp+4]           ;;
  997. ;;     size of buffer in [esp+8]           ;;
  998. ;;     pointer to device structure in ebx  ;;
  999. ;;                                         ;;
  1000. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1001.  
  1002. align 4
  1003. transmit:
  1004.  
  1005.         DEBUGF  1,"Transmitting packet, buffer:%x, size:%u\n",[esp+4],[esp+8]
  1006.         mov     eax, [esp+4]
  1007.         DEBUGF  1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
  1008.         [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
  1009.         [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
  1010.         [eax+13]:2,[eax+12]:2
  1011.  
  1012.         cmp     dword [esp+8], 1514
  1013.         ja      .fail
  1014.  
  1015.         mov     esi, [device.cur_tx]
  1016.         push    [esi + mtd_desc.next_desc_logical]
  1017.         pop     [device.cur_tx]
  1018.  
  1019.         ; todo: check if descriptor is not owned by the device!
  1020.  
  1021.         mov     eax, [esp + 4]
  1022.         mov     [esi + mtd_desc.skbuff], eax
  1023.         GetRealAddr
  1024.         mov     [esi + mtd_desc.buffer], eax
  1025.  
  1026.         mov     eax, [esp + 8]
  1027.         shl     eax, PKTSShift               ; packet size
  1028.         or      eax, TXLD + TXFD + CRCEnable + PADEnable + TXIC + 1536 shl TBSShift ; buffer size
  1029.         mov     [esi + mtd_desc.control], eax
  1030.  
  1031.         mov     [esi + mtd_desc.status], TXOWN
  1032.  
  1033. ;-------------
  1034. ; Update stats
  1035.  
  1036.         inc     [device.packets_tx]
  1037.         mov     eax, [esp+8]
  1038.         add     dword [device.bytes_tx], eax
  1039.         adc     dword [device.bytes_tx + 4], 0
  1040.  
  1041. ; Point to transmit descriptor
  1042.  
  1043.         set_io  0
  1044.         set_io  TXLBA
  1045.         mov     eax, esi
  1046.         GetRealAddr
  1047.         out     dx, eax
  1048.  
  1049. ;        set_io  TCRRCR
  1050. ;        mov     eax, [device.crvalue]
  1051. ;        out     dx, eax
  1052.  
  1053. ; Wake the potentially-idle transmit channel.
  1054.  
  1055.         set_io  TXPDR           ; TX Poll
  1056.         xor     eax, eax
  1057.         out     dx, eax
  1058.  
  1059.         DEBUGF  1,"transmit ok\n"
  1060.         xor     eax, eax
  1061.         ret     8
  1062.  
  1063.   .fail:
  1064.         DEBUGF  1,"transmit failed\n"
  1065.         or      eax, -1
  1066.         stdcall KernelFree, [esp + 4]
  1067.         ret     8
  1068.  
  1069.  
  1070.  
  1071. align 4
  1072. read_mac:
  1073.  
  1074.         set_io  0
  1075.         set_io  PAR0
  1076.         lea     edi, [device.mac]
  1077.         insd
  1078.         stosd
  1079.         set_io  PAR1
  1080.         insw
  1081.         stosw
  1082.  
  1083.         DEBUGF  1,"MAC = %x-%x-%x-%x-%x-%x\n",\
  1084.         [device.mac+0]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2
  1085.  
  1086.         ret
  1087.  
  1088. align 4
  1089. write_mac:
  1090.  
  1091.         ret
  1092.  
  1093.  
  1094.  
  1095. ;;;;;;;;;;;;;;;;;;;;;;;
  1096. ;;                   ;;
  1097. ;; Interrupt handler ;;
  1098. ;;                   ;;
  1099. ;;;;;;;;;;;;;;;;;;;;;;;
  1100.  
  1101. align 4
  1102. int_handler:
  1103.  
  1104.         push    ebx esi edi
  1105.  
  1106.         DEBUGF  1,"\n%s int\n", my_service
  1107.  
  1108. ; find pointer of device wich made IRQ occur
  1109.  
  1110.         mov     ecx, [devices]
  1111.         test    ecx, ecx
  1112.         jz      .nothing
  1113.         mov     esi, device_list
  1114.   .nextdevice:
  1115.         mov     ebx, [esi]
  1116.  
  1117.         set_io  0
  1118.         set_io  ISR
  1119.         in      eax, dx
  1120.         out     dx, eax                                 ; send it back to ACK
  1121.         test    eax, eax
  1122.         jnz     .got_it
  1123.   .continue:
  1124.         add     esi, 4
  1125.         dec     ecx
  1126.         jnz     .nextdevice
  1127.   .nothing:
  1128.         pop     edi esi ebx
  1129.         xor     eax, eax
  1130.  
  1131.         ret                                             ; If no device was found, abort (The irq was probably for a device, not registered to this driver)
  1132.  
  1133.   .got_it:
  1134.  
  1135.         DEBUGF  1,"Device: %x Status: %x ", ebx, ax
  1136.  
  1137.         test    ax, RI  ; receive interrupt
  1138.         jz      .no_rx
  1139.  
  1140.         DEBUGF  1,"Receive interrupt\n"
  1141.   .rx:
  1142.         push    ax
  1143.  
  1144.   .rx_loop:
  1145.         mov     esi, [device.cur_rx]
  1146.  
  1147.         test    [esi + mtd_desc.status], RXOWN
  1148.         jnz     .fail_rx
  1149.  
  1150.         push    .rx_complete
  1151.  
  1152.         mov     ecx, [esi + mtd_desc.status]
  1153.         shr     ecx, FLNGShift
  1154.         sub     ecx, 4                  ; we dont need CRC
  1155.         push    ecx
  1156.  
  1157. ;-------------
  1158. ; Update stats
  1159.  
  1160.         add     dword [device.bytes_rx], ecx
  1161.         adc     dword [device.bytes_rx + 4], 0
  1162.         inc     dword [device.packets_rx]
  1163.  
  1164.  
  1165.         push    [esi + mtd_desc.skbuff]
  1166.  
  1167.         jmp     Eth_input
  1168.  
  1169.   .rx_complete:
  1170.         mov     esi, [device.cur_rx]
  1171.  
  1172.         mov     [esi + mtd_desc.control], 1536 shl RBSShift
  1173.  
  1174.         stdcall KernelAlloc, 1536
  1175.         mov     [esi + mtd_desc.skbuff], eax
  1176.         call    GetPgAddr
  1177.         mov     [esi + mtd_desc.buffer], eax
  1178.  
  1179.         mov     [esi + mtd_desc.status], RXOWN
  1180.  
  1181.         mov     eax, [esi + mtd_desc.next_desc_logical]
  1182.         mov     [device.cur_rx], eax
  1183.  
  1184.         jmp     .rx_loop
  1185. ;
  1186. ;    while( ( mtdx.cur_rx->status & RXOWN ) == 0 )
  1187. ;    {
  1188. ;        mtdx.cur_rx->status = RXOWN;
  1189. ;        mtdx.cur_rx = mtdx.cur_rx->next_desc_logical;
  1190. ;    }
  1191. ;
  1192. ;    /* Restart Rx engine if stopped. */
  1193. ;    outl(0, mtdx.ioaddr + RXPDR);
  1194.  
  1195.   .fail_rx:
  1196.         DEBUGF  1,"RX failed\n"
  1197.  
  1198.         pop     ax
  1199.   .no_rx:
  1200.  
  1201.         test    ax, TI ; transmit interrupt
  1202.         jz      .no_tx
  1203.  
  1204.         DEBUGF  1,"Transmit interrupt\n"
  1205.         push    ax
  1206.  
  1207.         lea     esi, [device.tx_desc]
  1208.         mov     ecx, NUM_TX_DESC
  1209.   .tx_loop:
  1210.  
  1211.         test    [esi + mtd_desc.status], TXOWN
  1212.         jnz     .skip_this_one
  1213.  
  1214.         mov     eax, [esi + mtd_desc.skbuff]
  1215.         test    eax, eax
  1216.         je      .skip_this_one
  1217.  
  1218.         mov     [esi + mtd_desc.skbuff], 0
  1219.  
  1220.         DEBUGF  1,"freeing buffer:%x\n", eax
  1221.         stdcall KernelFree, eax
  1222.  
  1223.   .skip_this_one:
  1224.         mov     esi, [esi + mtd_desc.next_desc_logical]
  1225.         loop    .tx_loop
  1226.  
  1227.         pop     ax
  1228.  
  1229.   .no_tx:
  1230.  
  1231.         test    ax, TBU
  1232.         jz      .no_tbu
  1233.  
  1234.         DEBUGF  1,"Transmit buffer unavailable!\n"
  1235.  
  1236.   .no_tbu:
  1237.  
  1238.   .fail:
  1239.         pop     edi esi ebx
  1240.         xor     eax, eax
  1241.         inc     eax
  1242.  
  1243.         ret
  1244.  
  1245.  
  1246. ; End of code
  1247.  
  1248. align 4                                         ; Place all initialised data here
  1249.  
  1250. devices       dd 0
  1251. version       dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
  1252. my_service    db 'mtd80x',0                    ; max 16 chars include zero
  1253.  
  1254.  
  1255. ;   0x1516, 0x0800, "MTD800", "Myson MTD800"
  1256. ;   0x1516, 0x0803, "MTD803", "Surecom EP-320X"
  1257. ;   0x1516, 0x0891, "MTD891", "Myson MTD891"
  1258.  
  1259.  
  1260. include_debug_strings                           ; All data wich FDO uses will be included here
  1261.  
  1262. section '.data' data readable writable align 16 ; place all uninitialized data place here
  1263.  
  1264. device_list rd MAX_DEVICES                     ; This list contains all pointers to device structures the driver is handling
  1265.  
  1266.  
  1267.