Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2004-2014. 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             = 6
  29.         NUM_RX_DESC             = 12
  30.  
  31. include '../struct.inc'
  32. include '../macros.inc'
  33. include '../proc32.inc'
  34. include '../imports.inc'
  35. include '../fdo.inc'
  36. include '../netdrv.inc'
  37.  
  38. public START
  39. public service_proc
  40. public version
  41.  
  42.  
  43. ; for different PHY
  44.  
  45.     MysonPHY            = 1
  46.     AhdocPHY            = 2
  47.     SeeqPHY             = 3
  48.     MarvellPHY          = 4
  49.     Myson981            = 5
  50.     LevelOnePHY         = 6
  51.     OtherPHY            = 10
  52.  
  53. ; Offsets to the Command and Status Registers.
  54.  
  55.     PAR0                = 0x0           ; physical address 0-3
  56.     PAR1                = 0x04          ; physical address 4-5
  57.     MAR0                = 0x08          ; multicast address 0-3
  58.     MAR1                = 0x0C          ; multicast address 4-7
  59.     FAR0                = 0x10          ; flow-control address 0-3
  60.     FAR1                = 0x14          ; flow-control address 4-5
  61.     TCRRCR              = 0x18          ; receive & transmit configuration
  62.     BCR                 = 0x1C          ; bus command
  63.     TXPDR               = 0x20          ; transmit polling demand
  64.     RXPDR               = 0x24          ; receive polling demand
  65.     RXCWP               = 0x28          ; receive current word pointer
  66.     TXLBA               = 0x2C          ; transmit list base address
  67.     RXLBA               = 0x30          ; receive list base address
  68.     ISR                 = 0x34          ; interrupt status
  69.     IMR                 = 0x38          ; interrupt mask
  70.     FTH                 = 0x3C          ; flow control high/low threshold
  71.     MANAGEMENT          = 0x40          ; bootrom/eeprom and mii management
  72.     TALLY               = 0x44          ; tally counters for crc and mpa
  73.     TSR                 = 0x48          ; tally counter for transmit status
  74.     BMCRSR              = 0x4c          ; basic mode control and status
  75.     PHYIDENTIFIER       = 0x50          ; phy identifier
  76.     ANARANLPAR          = 0x54          ; auto-negotiation advertisement and link partner ability
  77.     ANEROCR             = 0x58          ; auto-negotiation expansion and pci conf.
  78.     BPREMRPSR           = 0x5c          ; bypass & receive error mask and phy status
  79.  
  80. ; Bits in the interrupt status/enable registers.
  81.  
  82.     RFCON               = 0x00020000    ; receive flow control xon packet
  83.     RFCOFF              = 0x00010000    ; receive flow control xoff packet
  84.     LSCStatus           = 0x00008000    ; link status change
  85.     ANCStatus           = 0x00004000    ; autonegotiation completed
  86.     FBE                 = 0x00002000    ; fatal bus error
  87.     FBEMask             = 0x00001800    ; mask bit12-11
  88.     ParityErr           = 0x00000000    ; parity error
  89.     TargetErr           = 0x00001000    ; target abort
  90.     MasterErr           = 0x00000800    ; master error
  91.     TUNF                = 0x00000400    ; transmit underflow
  92.     ROVF                = 0x00000200    ; receive overflow
  93.     ETI                 = 0x00000100    ; transmit early int
  94.     ERI                 = 0x00000080    ; receive early int
  95.     CNTOVF              = 0x00000040    ; counter overflow
  96.     RBU                 = 0x00000020    ; receive buffer unavailable
  97.     TBU                 = 0x00000010    ; transmit buffer unavilable
  98.     TI                  = 0x00000008    ; transmit interrupt
  99.     RI                  = 0x00000004    ; receive interrupt
  100.     RxErr               = 0x00000002    ; receive error
  101.  
  102. ; Bits in the NetworkConfig register.
  103.  
  104.     RxModeMask          = 0xe0
  105.     AcceptAllPhys       = 0x80          ; promiscuous mode
  106.     AcceptBroadcast     = 0x40          ; accept broadcast
  107.     AcceptMulticast     = 0x20          ; accept mutlicast
  108.     AcceptRunt          = 0x08          ; receive runt pkt
  109.     ALP                 = 0x04          ; receive long pkt
  110.     AcceptErr           = 0x02          ; receive error pkt
  111.  
  112.     AcceptMyPhys        = 0x00000000
  113.     RxEnable            = 0x00000001
  114.     RxFlowCtrl          = 0x00002000
  115.     TxEnable            = 0x00040000
  116.     TxModeFDX           = 0x00100000
  117.     TxThreshold         = 0x00e00000
  118.  
  119.     PS1000              = 0x00010000
  120.     PS10                = 0x00080000
  121.     FD                  = 0x00100000
  122.  
  123.  
  124. ; Bits in network_desc.status
  125.  
  126.     RXOWN               = 0x80000000    ; own bit
  127.     FLNGMASK            = 0x0fff0000    ; frame length
  128.     FLNGShift           = 16
  129.     MARSTATUS           = 0x00004000    ; multicast address received
  130.     BARSTATUS           = 0x00002000    ; broadcast address received
  131.     PHYSTATUS           = 0x00001000    ; physical address received
  132.     RXFSD               = 0x00000800    ; first descriptor
  133.     RXLSD               = 0x00000400    ; last descriptor
  134.     ErrorSummary        = 0x80          ; error summary
  135.     RUNT                = 0x40          ; runt packet received
  136.     LONG                = 0x20          ; long packet received
  137.     FAE                 = 0x10          ; frame align error
  138.     CRC                 = 0x08          ; crc error
  139.     RXER                = 0x04          ; receive error
  140.  
  141. ; rx_desc_control_bits
  142.  
  143.     RXIC                = 0x00800000    ; interrupt control
  144.     RBSShift            = 0
  145.  
  146. ; tx_desc_status_bits
  147.  
  148.     TXOWN               = 0x80000000    ; own bit
  149.     JABTO               = 0x00004000    ; jabber timeout
  150.     CSL                 = 0x00002000    ; carrier sense lost
  151.     LC                  = 0x00001000    ; late collision
  152.     EC                  = 0x00000800    ; excessive collision
  153.     UDF                 = 0x00000400    ; fifo underflow
  154.     DFR                 = 0x00000200    ; deferred
  155.     HF                  = 0x00000100    ; heartbeat fail
  156.     NCRMask             = 0x000000ff    ; collision retry count
  157.     NCRShift            = 0
  158.  
  159. ; tx_desc_control_bits
  160.  
  161.     TXIC                = 0x80000000    ; interrupt control
  162.     ETIControl          = 0x40000000    ; early transmit interrupt
  163.     TXLD                = 0x20000000    ; last descriptor
  164.     TXFD                = 0x10000000    ; first descriptor
  165.     CRCEnable           = 0x08000000    ; crc control
  166.     PADEnable           = 0x04000000    ; padding control
  167.     RetryTxLC           = 0x02000000    ; retry late collision
  168.     PKTSMask            = 0x3ff800      ; packet size bit21-11
  169.     PKTSShift           = 11
  170.     TBSMask             = 0x000007ff    ; transmit buffer bit 10-0
  171.     TBSShift            = 0
  172.  
  173. ; BootROM/EEPROM/MII Management Register
  174.  
  175.     MASK_MIIR_MII_READ  = 0x00000000
  176.     MASK_MIIR_MII_WRITE = 0x00000008
  177.     MASK_MIIR_MII_MDO   = 0x00000004
  178.     MASK_MIIR_MII_MDI   = 0x00000002
  179.     MASK_MIIR_MII_MDC   = 0x00000001
  180.  
  181. ; ST+OP+PHYAD+REGAD+TA
  182.  
  183.     OP_READ             = 0x6000        ; ST:01+OP:10+PHYAD+REGAD+TA:Z0
  184.     OP_WRITE            = 0x5002        ; ST:01+OP:01+PHYAD+REGAD+TA:10
  185.  
  186. ; -------------------------------------------------------------------------
  187. ;      Constants for Myson PHY
  188. ; -------------------------------------------------------------------------
  189.  
  190.     MysonPHYID          = 0xd0000302
  191.     MysonPHYID0         = 0x0302
  192.     StatusRegister      = 18
  193.     SPEED100            = 0x0400        ; bit10
  194.     FULLMODE            = 0x0800        ; bit11
  195.  
  196. ; -------------------------------------------------------------------------
  197. ;      Constants for Seeq 80225 PHY
  198. ; -------------------------------------------------------------------------
  199.  
  200.     SeeqPHYID0          = 0x0016
  201.     MIIRegister18       = 18
  202.     SPD_DET_100         = 0x80
  203.     DPLX_DET_FULL       = 0x40
  204.  
  205. ; -------------------------------------------------------------------------
  206. ;      Constants for Ahdoc 101 PHY
  207. ; -------------------------------------------------------------------------
  208.  
  209.     AhdocPHYID0         = 0x0022
  210.     DiagnosticReg       = 18
  211.     DPLX_FULL           = 0x0800
  212.     Speed_100           = 0x0400
  213.  
  214. ; --------------------------------------------------------------------------
  215. ;      Constants
  216. ; --------------------------------------------------------------------------
  217.  
  218.     MarvellPHYID0               = 0x0141
  219.     LevelOnePHYID0              = 0x0013
  220.  
  221.     MII1000BaseTControlReg      = 9
  222.     MII1000BaseTStatusReg       = 10
  223.     SpecificReg                 = 17
  224.  
  225. ; for 1000BaseT Control Register
  226.  
  227.     PHYAbletoPerform1000FullDuplex = 0x0200
  228.     PHYAbletoPerform1000HalfDuplex = 0x0100
  229.     PHY1000AbilityMask             = 0x300
  230.  
  231. ; for phy specific status register, marvell phy.
  232.  
  233.     SpeedMask      = 0x0c000
  234.     Speed_1000M    = 0x08000
  235.     Speed_100M     = 0x4000
  236.     Speed_10M      = 0
  237.     Full_Duplex    = 0x2000
  238.  
  239. ; for phy specific status register, levelone phy
  240.  
  241.     LXT1000_100M   = 0x08000
  242.     LXT1000_1000M  = 0x0c000
  243.     LXT1000_Full   = 0x200
  244.  
  245. ; for PHY
  246.  
  247.     LinkIsUp       = 0x0004
  248.     LinkIsUp2      = 0x00040000
  249.  
  250.  
  251.  
  252. virtual at 0
  253.  
  254.         mtd_desc:
  255.         .status                 dd ?
  256.         .control                dd ?
  257.         .buffer                 dd ?
  258.         .next_desc              dd ?
  259.  
  260.         .next_desc_logical      dd ?
  261.         .skbuff                 dd ?
  262.  
  263.         .reserved1              dd ?
  264.         .reserved2              dd ?
  265.  
  266.         .size = $
  267.  
  268. end virtual
  269.  
  270.  
  271. virtual at ebx
  272.  
  273.         device:
  274.  
  275.         ETH_DEVICE
  276.  
  277.         .tx_desc        rb NUM_TX_DESC*mtd_desc.size
  278.         .rx_desc        rb NUM_RX_DESC*mtd_desc.size
  279.  
  280.         .io_addr        dd ?
  281.         .pci_bus        dd ?
  282.         .pci_dev        dd ?
  283.         .irq_line       db ?
  284.         .dev_id         dw ?
  285.  
  286.         .flags          dd ?
  287.  
  288.         .crvalue        dd ?
  289.         .bcrvalue       dd ?
  290.  
  291.         .cur_rx         dd ?
  292.         .cur_tx         dd ?
  293.  
  294. ; These values are keep track of the transceiver/media in use.
  295.  
  296.         .linkok         dd ?
  297.         .line_speed     dd ?
  298.         .duplexmode     dd ?
  299.         .default_port   dd ?
  300.         .PHYType        dd ?
  301.  
  302. ; MII transceiver section.
  303.  
  304.         .mii_cnt        dd ?    ; MII device addresses.
  305.         .phys           db ?    ; MII device addresses.
  306.  
  307.         device_size = $ - device
  308.  
  309. end virtual
  310.  
  311.  
  312.  
  313. section '.flat' code readable align 16
  314.  
  315. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  316. ;;                        ;;
  317. ;; proc START             ;;
  318. ;;                        ;;
  319. ;; (standard driver proc) ;;
  320. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  321.  
  322. align 4
  323. proc START stdcall, state:dword
  324.  
  325.         cmp [state], 1
  326.         jne .exit
  327.  
  328.   .entry:
  329.  
  330.         DEBUGF  2,"Loading driver\n"
  331.         stdcall RegService, my_service, service_proc
  332.         ret
  333.  
  334.   .fail:
  335.   .exit:
  336.         xor eax, eax
  337.         ret
  338.  
  339. endp
  340.  
  341.  
  342. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  343. ;;                        ;;
  344. ;; proc SERVICE_PROC      ;;
  345. ;;                        ;;
  346. ;; (standard driver proc) ;;
  347. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  348.  
  349. align 4
  350. proc service_proc stdcall, ioctl:dword
  351.  
  352.         mov     edx, [ioctl]
  353.         mov     eax, [edx + IOCTL.io_code]
  354.  
  355. ;------------------------------------------------------
  356.  
  357.         cmp     eax, 0 ;SRV_GETVERSION
  358.         jne     @F
  359.  
  360.         cmp     [edx + IOCTL.out_size], 4
  361.         jb      .fail
  362.         mov     eax, [edx + IOCTL.output]
  363.         mov     [eax], dword API_VERSION
  364.  
  365.         xor     eax, eax
  366.         ret
  367.  
  368. ;------------------------------------------------------
  369.   @@:
  370.         cmp     eax, 1 ;SRV_HOOK
  371.         jne     .fail
  372.  
  373.         cmp     [edx + IOCTL.inp_size], 3               ; Data input must be at least 3 bytes
  374.         jb      .fail
  375.  
  376.         mov     eax, [edx + IOCTL.input]
  377.         cmp     byte [eax], 1                           ; 1 means device number and bus number (pci) are given
  378.         jne     .fail                                   ; other types arent supported for this card yet
  379.  
  380. ; check if the device is already listed
  381.  
  382.         mov     esi, device_list
  383.         mov     ecx, [devices]
  384.         test    ecx, ecx
  385.         jz      .firstdevice
  386.  
  387. ;        mov     eax, [edx + IOCTL.input]                ; get the pci bus and device numbers
  388.         mov     ax, [eax+1]                             ;
  389.   .nextdevice:
  390.         mov     ebx, [esi]
  391.         cmp     al, byte[device.pci_bus]
  392.         jne     @f
  393.         cmp     ah, byte[device.pci_dev]
  394.         je      .find_devicenum                         ; Device is already loaded, let's find it's device number
  395.        @@:
  396.         add     esi, 4
  397.         loop    .nextdevice
  398.  
  399.  
  400. ; This device doesnt have its own eth_device structure yet, lets create one
  401.   .firstdevice:
  402.         cmp     [devices], MAX_DEVICES                  ; First check if the driver can handle one more card
  403.         jae     .fail
  404.  
  405.         allocate_and_clear ebx, device_size, .fail
  406.  
  407. ; Fill in the direct call addresses into the struct
  408.  
  409.         mov     [device.reset], reset
  410.         mov     [device.transmit], transmit
  411.         mov     [device.unload], unload
  412.         mov     [device.name], my_service
  413.  
  414. ; save the pci bus and device numbers
  415.  
  416.         mov     eax, [edx + IOCTL.input]
  417.         movzx   ecx, byte[eax+1]
  418.         mov     [device.pci_bus], ecx
  419.         movzx   ecx, byte[eax+2]
  420.         mov     [device.pci_dev], ecx
  421.  
  422. ; Now, it's time to find the base io addres of the PCI device
  423.  
  424.         PCI_find_io
  425.  
  426. ; We've found the io address, find IRQ now
  427.  
  428.         PCI_find_irq
  429.  
  430.         DEBUGF  2,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
  431.         [device.pci_dev]:1,[device.pci_bus]:1,[device.irq_line]:1,[device.io_addr]:8
  432.  
  433. ; Ok, the eth_device structure is ready, let's probe the device
  434. ; Because initialization fires IRQ, IRQ handler must be aware of this device
  435.         mov     eax, [devices]                                          ; Add the device structure to our device list
  436.         mov     [device_list+4*eax], ebx                                ; (IRQ handler uses this list to find device)
  437.         inc     [devices]                                               ;
  438.  
  439.         call    probe                                                   ; this function will output in eax
  440.         test    eax, eax
  441.         jnz     .err2                                                   ; If an error occured, exit
  442.  
  443.         mov     [device.type], NET_TYPE_ETH
  444.         call    NetRegDev
  445.  
  446.         cmp     eax, -1
  447.         je      .destroy
  448.  
  449.         ret
  450.  
  451. ; If the device was already loaded, find the device number and return it in eax
  452.  
  453.   .find_devicenum:
  454.         DEBUGF  2,"Trying to find device number of already registered device\n"
  455.         call    NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
  456.                                                                         ; into a device number in edi
  457.         mov     eax, edi                                                ; Application wants it in eax instead
  458.         DEBUGF  2,"Kernel says: %u\n", eax
  459.         ret
  460.  
  461. ; If an error occured, remove all allocated data and exit (returning -1 in eax)
  462.  
  463.   .destroy:
  464.         ; todo: reset device into virgin state
  465.  
  466.   .err2:
  467.         dec     [devices]
  468.   .err:
  469.         DEBUGF  2,"removing device structure\n"
  470.         stdcall KernelFree, ebx
  471.   .fail:
  472.         or      eax, -1
  473.         ret
  474.  
  475. ;------------------------------------------------------
  476. endp
  477.  
  478.  
  479. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  480. ;;                                                                        ;;
  481. ;;        Actual Hardware dependent code starts here                      ;;
  482. ;;                                                                        ;;
  483. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  484.  
  485.  
  486.  
  487. align 4
  488. unload:
  489.         ; TODO: (in this particular order)
  490.         ;
  491.         ; - Stop the device
  492.  
  493. ;    /* Disable Tx Rx*/
  494. ;    outl( mtdx.crvalue & (~TxEnable) & (~RxEnable), mtdx.ioaddr + TCRRCR );
  495. ;
  496. ;    /* Reset the chip to erase previous misconfiguration. */
  497. ;    mtd_reset(nic);
  498.  
  499.         ; - Detach int handler
  500.         ; - Remove device from local list (device_list)
  501.         ; - call unregister function in kernel
  502.         ; - Remove all allocated structures and buffers the card used
  503.  
  504.         or      eax,-1
  505.  
  506. ret
  507.  
  508.  
  509. ;-------
  510. ;
  511. ; PROBE
  512. ;
  513. ;-------
  514. align 4
  515. probe:
  516.  
  517.         DEBUGF  2,"Probing device\n"
  518.  
  519.         PCI_make_bus_master
  520.  
  521.         stdcall PciRead32, [device.pci_bus], [device.pci_dev], 0
  522.  
  523.         cmp     ax, 0x1516
  524.         jne     .notfound
  525.         shr     eax, 16
  526.         mov     [device.dev_id], ax
  527.  
  528.         cmp     ax, 0x0800
  529.         je      .has_mii_xcvr
  530.  
  531.         cmp     ax, 0x0803
  532.         je      .has_chip_xcvr
  533.  
  534.         cmp     ax, 0x0891
  535.         je      .has_mii_xcvr
  536.  
  537.   .notfound:
  538.         DEBUGF  1,"Device not supported!\n"
  539.         xor     eax, eax
  540.         dec     eax
  541.         ret
  542.  
  543.   .has_chip_xcvr:
  544.         DEBUGF  1,"Device has chip xcvr\n"
  545.  
  546.         jmp     .xcvr_set
  547.  
  548.   .has_mii_xcvr:
  549.         DEBUGF  1,"Device has mii xcvr\n"
  550.  
  551.   .xcvr_set:
  552.  
  553.         call    read_mac
  554.  
  555. ; Reset the chip to erase previous misconfiguration.
  556.  
  557.         set_io  0
  558.         set_io  BCR
  559.         xor     eax, eax
  560.         inc     eax
  561.         out     dx, eax
  562.  
  563. ; find the connected MII xcvrs
  564.  
  565.         cmp     [device.dev_id], 0x0803
  566.         je      .is_803
  567.  
  568. ;        int     phy, phy_idx =   0;
  569. ;
  570. ;        for (phy =   1; phy < 32 && phy_idx < 1; phy++) {
  571. ;            int mii_status =   mdio_read(nic, phy, 1);
  572. ;
  573. ;            if (mii_status !=   0xffff && mii_status !=   0x0000) {
  574. ;                mtdx.phys[phy_idx] =   phy;
  575. ;
  576. ;                DBG ( "%s: MII PHY found at address %d, status "
  577. ;                      "0x%4.4x.\n", mtdx.nic_name, phy, mii_status );
  578. ;                /* get phy type */
  579. ;                {
  580. ;                    unsigned int data;
  581. ;
  582. ;                    data =   mdio_read(nic, mtdx.phys[phy_idx], 2);
  583. ;                    if (data equ=   SeeqPHYID0)
  584. ;                        mtdx.PHYType =   SeeqPHY;
  585. ;                    else if (data equ=   AhdocPHYID0)
  586. ;                        mtdx.PHYType =   AhdocPHY;
  587. ;                    else if (data equ=   MarvellPHYID0)
  588. ;                        mtdx.PHYType =   MarvellPHY;
  589. ;                    else if (data equ=   MysonPHYID0)
  590. ;                        mtdx.PHYType =   Myson981;
  591. ;                    else if (data equ=   LevelOnePHYID0)
  592. ;                        mtdx.PHYType =   LevelOnePHY;
  593. ;                    else
  594. ;                        mtdx.PHYType =   OtherPHY;
  595. ;                }
  596. ;                phy_idx++;
  597. ;            }
  598. ;        }
  599. ;
  600. ;        mtdx.mii_cnt =   phy_idx;
  601. ;        if (phy_idx equ=   0) {
  602. ;            printf("%s: MII PHY not found -- this device may "
  603. ;                   "not operate correctly.\n", mtdx.nic_name);
  604. ;        }
  605.  
  606.         jmp     .no_803
  607.  
  608.   .is_803:
  609.  
  610.         mov     [device.phys], 32
  611.  
  612. ; get phy type
  613.         set_io  0
  614.         set_io  PHYIDENTIFIER
  615.         in      eax, dx
  616.  
  617.         cmp     eax, MysonPHYID
  618.         jne     @f
  619.  
  620.         mov     [device.PHYType], MysonPHY
  621.         DEBUGF  1,"MysonPHY\n"
  622.         jmp     .no_803
  623.  
  624.        @@:
  625.         mov     [device.PHYType], OtherPHY
  626.         DEBUGF  1,"OtherPHY\n"
  627.  
  628.   .no_803:
  629.  
  630. ;-------
  631. ;
  632. ; RESET
  633. ;
  634. ;-------
  635. align 4
  636. reset:
  637.  
  638.         DEBUGF  1,"Resetting\n"
  639.  
  640. ;--------------------------------
  641. ; insert irq handler on given irq
  642.  
  643.         movzx   eax, [device.irq_line]
  644.         DEBUGF  1,"Attaching int handler to irq %x\n", eax:1
  645.         stdcall AttachIntHandler, eax, int_handler, dword 0
  646.         test    eax, eax
  647.         jnz     @f
  648.         DEBUGF  1,"Could not attach int handler!\n"
  649.         or      eax, -1
  650.         ret
  651.   @@:
  652.  
  653. ; Reset the chip to erase previous misconfiguration.
  654.  
  655.         set_io  0
  656.         set_io  BCR
  657.         xor     eax, eax
  658.         inc     eax
  659.         out     dx, eax
  660.  
  661.         call    init_ring
  662.  
  663. ; Initialize other registers.
  664. ; Configure the PCI bus bursts and FIFO thresholds.
  665.  
  666.         mov     [device.bcrvalue], 0x10         ; little-endian, 8 burst length
  667.         mov     [device.crvalue], 0xa00         ; 128 burst length
  668.  
  669.         cmp     [device.dev_id], 0x891
  670.         jne     @f
  671.         or      [device.bcrvalue], 0x200       ; set PROG bit
  672.         or      [device.crvalue], 0x02000000   ; set enhanced bit
  673.        @@:
  674.  
  675.         or      [device.crvalue], RxEnable + TxThreshold + TxEnable
  676.  
  677.         call    set_rx_mode
  678.  
  679.         set_io  0
  680.         set_io  BCR
  681.         mov     eax, [device.bcrvalue]
  682.         out     dx, eax
  683.  
  684.         set_io  TCRRCR
  685.         mov     eax, [device.crvalue]
  686.         out     dx, eax
  687.  
  688.         call    getlinkstatus
  689.         call    getlinktype
  690.  
  691. ; Restart Rx engine if stopped.
  692.  
  693.         set_io  0
  694.         set_io  RXPDR
  695.         xor     eax, eax
  696.         out     dx, eax
  697.  
  698. ; Enable interrupts
  699.  
  700.         set_io  0
  701.         set_io  ISR
  702.         mov     eax, FBE or TUNF or CNTOVF or RBU or TI or RI
  703.         out     dx, eax
  704.         set_io  IMR
  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.         mov     [esi + mtd_desc.skbuff], 0
  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.  
  1017.         test    [esi + mtd_desc.status], TXOWN
  1018.         jnz     .fail
  1019.  
  1020.         push    [esi + mtd_desc.next_desc_logical]
  1021.         pop     [device.cur_tx]
  1022.  
  1023.         mov     eax, [esp + 4]
  1024.         mov     [esi + mtd_desc.skbuff], eax
  1025.         GetRealAddr
  1026.         mov     [esi + mtd_desc.buffer], eax
  1027.  
  1028.         mov     eax, [esp + 8]
  1029.         mov     ecx, eax
  1030.         shl     eax, PKTSShift               ; packet size
  1031.         shl     ecx, TBSShift
  1032.         or      eax, ecx
  1033.         or      eax, TXIC + TXLD + TXFD + CRCEnable + PADEnable
  1034.         mov     [esi + mtd_desc.control], eax
  1035.         mov     [esi + mtd_desc.status], TXOWN
  1036.  
  1037. ; Update stats
  1038.         inc     [device.packets_tx]
  1039.         mov     eax, [esp+8]
  1040.         add     dword [device.bytes_tx], eax
  1041.         adc     dword [device.bytes_tx + 4], 0
  1042.  
  1043. ; TX Poll
  1044.         set_io  0
  1045.         set_io  TXPDR
  1046.         xor     eax, eax
  1047.         out     dx, eax
  1048.  
  1049.         DEBUGF  1,"transmit ok\n"
  1050.         xor     eax, eax
  1051.         ret     8
  1052.  
  1053.   .fail:
  1054.         DEBUGF  1,"transmit failed\n"
  1055.         stdcall KernelFree, [esp + 4]
  1056.         or      eax, -1
  1057.         ret     8
  1058.  
  1059.  
  1060.  
  1061. align 4
  1062. read_mac:
  1063.  
  1064.         set_io  0
  1065.         set_io  PAR0
  1066.         lea     edi, [device.mac]
  1067.         insd
  1068.         set_io  PAR1
  1069.         insw
  1070.         DEBUGF  1,"MAC = %x-%x-%x-%x-%x-%x\n",\
  1071.         [device.mac+0]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2
  1072.  
  1073.         ret
  1074.  
  1075. align 4
  1076. write_mac:
  1077.  
  1078.         ret
  1079.  
  1080.  
  1081.  
  1082. ;;;;;;;;;;;;;;;;;;;;;;;
  1083. ;;                   ;;
  1084. ;; Interrupt handler ;;
  1085. ;;                   ;;
  1086. ;;;;;;;;;;;;;;;;;;;;;;;
  1087.  
  1088. align 4
  1089. int_handler:
  1090.  
  1091.         push    ebx esi edi
  1092.  
  1093.         DEBUGF  1,"INT\n"
  1094.  
  1095. ; find pointer of device wich made IRQ occur
  1096.  
  1097.         mov     ecx, [devices]
  1098.         test    ecx, ecx
  1099.         jz      .nothing
  1100.         mov     esi, device_list
  1101.   .nextdevice:
  1102.         mov     ebx, [esi]
  1103.  
  1104.         set_io  0
  1105.         set_io  ISR
  1106.         in      eax, dx
  1107.         out     dx, eax                                 ; send it back to ACK
  1108.         test    eax, eax
  1109.         jnz     .got_it
  1110.   .continue:
  1111.         add     esi, 4
  1112.         dec     ecx
  1113.         jnz     .nextdevice
  1114.   .nothing:
  1115.         pop     edi esi ebx
  1116.         xor     eax, eax
  1117.  
  1118.         ret                                             ; If no device was found, abort (The irq was probably for a device, not registered to this driver)
  1119.  
  1120.   .got_it:
  1121.  
  1122.         DEBUGF  1,"Device: %x Status: %x\n", ebx, ax
  1123.  
  1124.         test    ax, RI  ; receive interrupt
  1125.         jz      .no_rx
  1126.         push    ax
  1127.   .rx_loop:
  1128.         mov     esi, [device.cur_rx]
  1129.         test    [esi + mtd_desc.status], RXOWN
  1130.         jnz     .fail_rx
  1131.  
  1132.         push    ebx
  1133.         push    .rx_complete
  1134.  
  1135.         mov     ecx, [esi + mtd_desc.status]
  1136.         shr     ecx, FLNGShift
  1137.         sub     ecx, 4                  ; we dont need CRC
  1138.         push    ecx
  1139.         DEBUGF  1,"Received %u bytes\n", ecx
  1140.  
  1141. ; Update stats
  1142.         add     dword[device.bytes_rx], ecx
  1143.         adc     dword[device.bytes_rx + 4], 0
  1144.         inc     [device.packets_rx]
  1145.  
  1146.         push    [esi + mtd_desc.skbuff]
  1147.         jmp     Eth_input
  1148.  
  1149.   .rx_complete:
  1150.         pop     ebx
  1151.         mov     esi, [device.cur_rx]
  1152.         mov     [esi + mtd_desc.control], 1536 shl RBSShift
  1153.         push    esi
  1154.         stdcall KernelAlloc, 1536
  1155.         pop     esi
  1156.         mov     [esi + mtd_desc.skbuff], eax
  1157.         call    GetPgAddr
  1158.         mov     [esi + mtd_desc.buffer], eax
  1159.         mov     [esi + mtd_desc.status], RXOWN
  1160.  
  1161.         push    [esi + mtd_desc.next_desc_logical]
  1162.         pop     [device.cur_rx]
  1163.  
  1164.         jmp     .rx_loop
  1165. ;
  1166. ;    while( ( mtdx.cur_rx->status & RXOWN ) == 0 )
  1167. ;    {
  1168. ;        mtdx.cur_rx->status = RXOWN;
  1169. ;        mtdx.cur_rx = mtdx.cur_rx->next_desc_logical;
  1170. ;    }
  1171. ;
  1172. ;    /* Restart Rx engine if stopped. */
  1173. ;    outl(0, mtdx.ioaddr + RXPDR);
  1174.  
  1175.   .fail_rx:
  1176.         DEBUGF  1,"RX done\n"
  1177.         pop     ax
  1178.  
  1179.   .no_rx:
  1180.         test    ax, TI ; transmit interrupt
  1181.         jz      .no_tx
  1182.         DEBUGF  1,"TX\n"
  1183.         push    ax
  1184.         lea     esi, [device.tx_desc]
  1185.         mov     ecx, NUM_TX_DESC
  1186.   .tx_loop:
  1187.         test    [esi + mtd_desc.status], TXOWN
  1188.         jnz     .skip_this_one
  1189.         mov     eax, [esi + mtd_desc.skbuff]
  1190.         test    eax, eax
  1191.         je      .skip_this_one
  1192.         mov     [esi + mtd_desc.skbuff], 0
  1193.         DEBUGF  1,"freeing buffer: 0x%x\n", eax
  1194.         stdcall KernelFree, eax
  1195.   .skip_this_one:
  1196.         mov     esi, [esi + mtd_desc.next_desc_logical]
  1197.         loop    .tx_loop
  1198.         pop     ax
  1199.  
  1200.   .no_tx:
  1201. ;        test    ax, TBU
  1202. ;        jz      .no_tbu
  1203. ;        DEBUGF  2,"Transmit buffer unavailable!\n"
  1204. ;  .no_tbu:
  1205.  
  1206.   .fail:
  1207.         pop     edi esi ebx
  1208.         xor     eax, eax
  1209.         inc     eax
  1210.  
  1211.         ret
  1212.  
  1213.  
  1214. ; End of code
  1215.  
  1216. align 4                                         ; Place all initialised data here
  1217.  
  1218. devices       dd 0
  1219. version       dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
  1220. my_service    db 'mtd80x',0                    ; max 16 chars include zero
  1221.  
  1222.  
  1223. ;   0x1516, 0x0800, "MTD800", "Myson MTD800"
  1224. ;   0x1516, 0x0803, "MTD803", "Surecom EP-320X"
  1225. ;   0x1516, 0x0891, "MTD891", "Myson MTD891"
  1226.  
  1227.  
  1228. include_debug_strings                           ; All data wich FDO uses will be included here
  1229.  
  1230. section '.data' data readable writable align 16 ; place all uninitialized data place here
  1231.  
  1232. device_list rd MAX_DEVICES                     ; This list contains all pointers to device structures the driver is handling
  1233.  
  1234.  
  1235.