Subversion Repositories Kolibri OS

Rev

Rev 3155 | Blame | 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__         =   1
  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.get_MAC], read_mac
  410.         mov     [device.set_MAC], write_mac
  411.         mov     [device.unload], unload
  412.         mov     [device.name], my_service
  413.  
  414. ; save the pci bus and device numbers
  415.  
  416.         mov     eax, [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 mtd80x 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 mtd80x\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,"\nCould 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.  
  705.         set_io  IMR
  706. ;        mov     eax, (FBE or TUNF or CNTOVF or RBU or TI or RI)
  707.         out     dx, eax
  708.  
  709. ; clear packet/byte counters
  710.  
  711.         xor     eax, eax
  712.         lea     edi, [device.bytes_tx]
  713.         mov     ecx, 6
  714.         rep     stosd
  715.  
  716.         mov     [device.mtu], 1514
  717.         xor     eax, eax
  718.  
  719.         ret
  720.  
  721.  
  722.  
  723.  
  724. align 4
  725. init_ring:
  726.  
  727.         DEBUGF  1,"initializing rx and tx ring\n"
  728.  
  729. ; Initialize all Rx descriptors
  730.  
  731.         lea     esi, [device.rx_desc]
  732.         mov     [device.cur_rx], esi
  733.         mov     ecx, NUM_RX_DESC
  734.   .rx_desc_loop:
  735.         mov     [esi + mtd_desc.status], RXOWN
  736.         mov     [esi + mtd_desc.control], 1536 shl RBSShift
  737.  
  738.         lea     eax, [esi + mtd_desc.size]
  739.         mov     [esi + mtd_desc.next_desc_logical], eax
  740.         push    ecx esi
  741.         GetRealAddr
  742.         mov     [esi + mtd_desc.next_desc], eax
  743.  
  744.         stdcall KernelAlloc, 1536
  745.         pop     esi
  746.         push    esi
  747.         mov     [esi + mtd_desc.skbuff], eax
  748.         call    GetPgAddr
  749.         pop     esi ecx
  750.         mov     [esi + mtd_desc.buffer], eax
  751.  
  752.         add     esi, mtd_desc.size
  753.         loop    .rx_desc_loop
  754.  
  755. ; Mark the last entry as wrapping the ring.
  756.  
  757.         lea     eax, [device.rx_desc]
  758.         mov     [esi - mtd_desc.size + mtd_desc.next_desc_logical], eax
  759.         push    esi
  760.         GetRealAddr
  761.         pop     esi
  762.         mov     [esi - mtd_desc.size + mtd_desc.next_desc], eax
  763.  
  764.         set_io  0
  765.         set_io  RXLBA
  766.         out     dx, eax
  767.  
  768. ; Initialize all Tx descriptors
  769.  
  770.         lea     esi, [device.tx_desc]
  771.         mov     [device.cur_tx], esi
  772.         mov     ecx, NUM_TX_DESC
  773.   .tx_desc_loop:
  774.         mov     [esi + mtd_desc.status], 0
  775.  
  776.         lea     eax, [esi + mtd_desc.size]
  777.         mov     [esi + mtd_desc.next_desc_logical], eax
  778.         push    ecx esi
  779.         GetRealAddr
  780.         pop     esi ecx
  781.         mov     [esi + mtd_desc.next_desc], eax
  782.  
  783.         add     esi, mtd_desc.size
  784.         loop    .tx_desc_loop
  785.  
  786. ; Mark the last entry as wrapping the ring.
  787.  
  788.         lea     eax, [device.tx_desc]
  789.         mov     [esi - mtd_desc.size + mtd_desc.next_desc_logical], eax
  790.         push    esi
  791.         GetRealAddr
  792.         pop     esi
  793.         mov     [esi - mtd_desc.size + mtd_desc.next_desc], eax
  794.  
  795.         set_io  0
  796.         set_io  TXLBA
  797.         out     dx, eax
  798.  
  799.         ret
  800.  
  801.  
  802. align 4
  803. set_rx_mode:
  804.  
  805.         DEBUGF  1,"Setting RX mode\n"
  806.  
  807. ; Too many to match, or accept all multicasts.
  808.  
  809.         set_io  0
  810.         set_io  MAR0
  811.         xor     eax, eax
  812.         not     eax
  813.         out     dx, eax
  814.         set_io  MAR1
  815.         out     dx, eax
  816.  
  817.         and     [device.crvalue], not (RxModeMask)
  818.         or      [device.crvalue], AcceptBroadcast + AcceptMulticast + AcceptMyPhys
  819.  
  820.         ret
  821.  
  822.  
  823. align 4
  824. getlinkstatus:
  825.  
  826.         DEBUGF  1,"Getting link status\n"
  827.  
  828.         mov     [device.linkok], 0
  829.  
  830.         cmp     [device.PHYType], MysonPHY
  831.         jne     .no_myson_phy
  832.  
  833.         set_io  0
  834.         set_io  BMCRSR
  835.         mov     ecx, 1000
  836.   .loop1:
  837.         in      eax, dx
  838.         test    eax, LinkIsUp2
  839.         jnz     .link_ok
  840.  
  841.         push    ecx edx ebx
  842.         mov     esi, 10
  843.         call    Sleep
  844.         pop     ebx edx ecx
  845.         loop    .loop1
  846.  
  847.         ret
  848.  
  849.   .no_myson_phy:
  850.  
  851. ;        for (i =   0; i < DelayTime; ++i) {
  852. ;            if (mdio_read(nic, mtdx.phys[0], MII_BMSR) & BMSR_LSTATUS) {
  853. ;                mtdx.linkok =   1;
  854. ;                return;
  855. ;            }
  856. ;            m80x_delay(100);
  857.  
  858.         ret
  859.  
  860.   .link_ok:
  861.         DEBUGF  1,"Link is up\n"
  862.         inc     [device.linkok]
  863.         ret
  864.  
  865.  
  866.  
  867.  
  868. align 4
  869. getlinktype:
  870.  
  871.         DEBUGF  1,"Getting link type\n"
  872.  
  873.         cmp     [device.PHYType], MysonPHY
  874.         jne     .no_myson_phy
  875.  
  876.         DEBUGF  1,"myson PHY\n"
  877.  
  878.         set_io  0
  879.         set_io  TCRRCR
  880.         in      eax, dx
  881.  
  882.         mov     [device.duplexmode], 1  ; 1 =   half duplex
  883.         test    eax, FD
  884.         jne     @f
  885.         DEBUGF  1,"full duplex\n"
  886.         inc     [device.duplexmode]     ; 2 =   full duplex
  887.        @@:
  888.  
  889.         mov     [device.line_speed], 1  ; 1 =   10M
  890.         test    eax, PS10
  891.         jne     @f
  892.         DEBUGF  1,"100mbit\n"
  893.         inc     [device.line_speed]     ; 2 =   100M
  894.        @@:
  895.  
  896.         ret
  897.  
  898.   .no_myson_phy:
  899.  
  900.         DEBUGF  1,"no myson phy\n"
  901.  
  902. ;        if (mtdx.PHYType equ=   SeeqPHY) { /* this PHY is SEEQ 80225 */
  903. ;            unsigned int data;
  904. ;
  905. ;            data =   mdio_read(dev, mtdx.phys[0], MIIRegister18);
  906. ;            if (data & SPD_DET_100)
  907. ;                mtdx.line_speed =   2; /* 100M */
  908. ;            else
  909. ;                mtdx.line_speed =   1; /* 10M */
  910. ;            if (data & DPLX_DET_FULL)
  911. ;                mtdx.duplexmode =   2; /* full duplex mode */
  912. ;            else
  913. ;                mtdx.duplexmode =   1; /* half duplex mode */
  914. ;        } else if (mtdx.PHYType equ=   AhdocPHY) {
  915. ;            unsigned int data;
  916. ;
  917. ;            data =   mdio_read(dev, mtdx.phys[0], DiagnosticReg);
  918. ;            if (data & Speed_100)
  919. ;                mtdx.line_speed =   2; /* 100M */
  920. ;            else
  921. ;                mtdx.line_speed =   1; /* 10M */
  922. ;            if (data & DPLX_FULL)
  923. ;                mtdx.duplexmode =   2; /* full duplex mode */
  924. ;            else
  925. ;                mtdx.duplexmode =   1; /* half duplex mode */
  926. ;        }
  927. ;        else if (mtdx.PHYType equ=   MarvellPHY) {
  928. ;            unsigned int data;
  929. ;
  930. ;            data =   mdio_read(dev, mtdx.phys[0], SpecificReg);
  931. ;            if (data & Full_Duplex)
  932. ;                mtdx.duplexmode =   2; /* full duplex mode */
  933. ;            else
  934. ;                mtdx.duplexmode =   1; /* half duplex mode */
  935. ;            data &=   SpeedMask;
  936. ;            if (data equ=   Speed_1000M)
  937. ;                mtdx.line_speed =   3; /* 1000M */
  938. ;            else if (data equ=   Speed_100M)
  939. ;                mtdx.line_speed =   2; /* 100M */
  940. ;            else
  941. ;                mtdx.line_speed =   1; /* 10M */
  942. ;        }
  943. ;        else if (mtdx.PHYType equ=   Myson981) {
  944. ;            unsigned int data;
  945. ;
  946. ;            data =   mdio_read(dev, mtdx.phys[0], StatusRegister);
  947. ;
  948. ;            if (data & SPEED100)
  949. ;                mtdx.line_speed =   2;
  950. ;            else
  951. ;                mtdx.line_speed =   1;
  952. ;
  953. ;            if (data & FULLMODE)
  954. ;                mtdx.duplexmode =   2;
  955. ;            else
  956. ;                mtdx.duplexmode =   1;
  957. ;        }
  958. ;        else if (mtdx.PHYType equ=   LevelOnePHY) {
  959. ;            unsigned int data;
  960. ;
  961. ;            data =   mdio_read(dev, mtdx.phys[0], SpecificReg);
  962. ;            if (data & LXT1000_Full)
  963. ;                mtdx.duplexmode =   2; /* full duplex mode */
  964. ;            else
  965. ;                mtdx.duplexmode =   1; /* half duplex mode */
  966. ;            data &=   SpeedMask;
  967. ;            if (data equ=   LXT1000_1000M)
  968. ;                mtdx.line_speed =   3; /* 1000M */
  969. ;            else if (data equ=   LXT1000_100M)
  970. ;                mtdx.line_speed =   2; /* 100M */
  971. ;            else
  972.  ;               mtdx.line_speed =   1; /* 10M */
  973.   ;      }
  974.  
  975. ;        // chage crvalue
  976. ;        // mtdx.crvalue&equ(~PS10)&(~FD);
  977. ;        mtdx.crvalue &=   (~PS10) & (~FD) & (~PS1000);
  978. ;        if (mtdx.line_speed equ=   1)
  979. ;            mtdx.crvalue |=   PS10;
  980. ;        else if (mtdx.line_speed equ=   3)
  981. ;            mtdx.crvalue |=   PS1000;
  982. ;        if (mtdx.duplexmode equ=   2)
  983. ;            mtdx.crvalue |=   FD;
  984. ;
  985.  
  986.         ret
  987.  
  988.  
  989.  
  990.  
  991. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  992. ;;                                         ;;
  993. ;; Transmit                                ;;
  994. ;;                                         ;;
  995. ;; In: buffer pointer in [esp+4]           ;;
  996. ;;     size of buffer in [esp+8]           ;;
  997. ;;     pointer to device structure in ebx  ;;
  998. ;;                                         ;;
  999. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1000.  
  1001. align 4
  1002. transmit:
  1003.  
  1004.         DEBUGF  1,"Transmitting packet, buffer:%x, size:%u\n",[esp+4],[esp+8]
  1005.         mov     eax, [esp+4]
  1006.         DEBUGF  1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
  1007.         [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
  1008.         [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
  1009.         [eax+13]:2,[eax+12]:2
  1010.  
  1011.         cmp     dword [esp+8], 1514
  1012.         ja      .fail
  1013.  
  1014.         mov     esi, [device.cur_tx]
  1015.         push    [esi + mtd_desc.next_desc_logical]
  1016.         pop     [device.cur_tx]
  1017.  
  1018.         ; todo: check if descriptor is not owned by the device!
  1019.  
  1020.         mov     eax, [esp + 4]
  1021.         mov     [esi + mtd_desc.skbuff], eax
  1022.         GetRealAddr
  1023.         mov     [esi + mtd_desc.buffer], eax
  1024.  
  1025.         mov     eax, [esp + 8]
  1026.         shl     eax, PKTSShift               ; packet size
  1027.         or      eax, TXLD + TXFD + CRCEnable + PADEnable + TXIC + 1536 shl TBSShift ; buffer size
  1028.         mov     [esi + mtd_desc.control], eax
  1029.  
  1030.         mov     [esi + mtd_desc.status], TXOWN
  1031.  
  1032. ;-------------
  1033. ; Update stats
  1034.  
  1035.         inc     [device.packets_tx]
  1036.         mov     eax, [esp+8]
  1037.         add     dword [device.bytes_tx], eax
  1038.         adc     dword [device.bytes_tx + 4], 0
  1039.  
  1040. ; Point to transmit descriptor
  1041.  
  1042.         set_io  0
  1043.         set_io  TXLBA
  1044.         mov     eax, esi
  1045.         GetRealAddr
  1046.         out     dx, eax
  1047.  
  1048. ;        set_io  TCRRCR
  1049. ;        mov     eax, [device.crvalue]
  1050. ;        out     dx, eax
  1051.  
  1052. ; Wake the potentially-idle transmit channel.
  1053.  
  1054.         set_io  TXPDR           ; TX Poll
  1055.         xor     eax, eax
  1056.         out     dx, eax
  1057.  
  1058.         DEBUGF  1,"transmit ok\n"
  1059.         xor     eax, eax
  1060.         ret     8
  1061.  
  1062.   .fail:
  1063.         DEBUGF  1,"transmit failed\n"
  1064.         or      eax, -1
  1065.         stdcall KernelFree, [esp + 4]
  1066.         ret     8
  1067.  
  1068.  
  1069.  
  1070. align 4
  1071. read_mac:
  1072.  
  1073.         set_io  0
  1074.         set_io  PAR0
  1075.         lea     edi, [device.mac]
  1076.         insd
  1077.         stosd
  1078.         set_io  PAR1
  1079.         insw
  1080.         stosw
  1081.  
  1082.         DEBUGF  1,"MAC = %x-%x-%x-%x-%x-%x\n",\
  1083.         [device.mac+0]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2
  1084.  
  1085.         ret
  1086.  
  1087. align 4
  1088. write_mac:
  1089.  
  1090.         ret
  1091.  
  1092.  
  1093.  
  1094. ;;;;;;;;;;;;;;;;;;;;;;;
  1095. ;;                   ;;
  1096. ;; Interrupt handler ;;
  1097. ;;                   ;;
  1098. ;;;;;;;;;;;;;;;;;;;;;;;
  1099.  
  1100. align 4
  1101. int_handler:
  1102.  
  1103.         DEBUGF  1,"\n%s int\n", my_service
  1104.  
  1105. ; find pointer of device wich made IRQ occur
  1106.  
  1107.         mov     ecx, [devices]
  1108.         test    ecx, ecx
  1109.         jz      .nothing
  1110.         mov     esi, device_list
  1111.   .nextdevice:
  1112.         mov     ebx, [esi]
  1113.  
  1114.         set_io  0
  1115.         set_io  ISR
  1116.         in      eax, dx
  1117.         out     dx, eax                                 ; send it back to ACK
  1118.         test    eax, eax
  1119.         jnz     .got_it
  1120.   .continue:
  1121.         add     esi, 4
  1122.         dec     ecx
  1123.         jnz     .nextdevice
  1124.   .nothing:
  1125.         ret                                             ; If no device was found, abort (The irq was probably for a device, not registered to this driver)
  1126.  
  1127.   .got_it:
  1128.  
  1129.         DEBUGF  1,"Device: %x Status: %x ", ebx, ax
  1130.  
  1131.         test    ax, RI  ; receive interrupt
  1132.         jz      .no_rx
  1133.  
  1134.         DEBUGF  1,"Receive interrupt\n"
  1135.   .rx:
  1136.         push    ax
  1137.  
  1138.   .rx_loop:
  1139.         mov     esi, [device.cur_rx]
  1140.  
  1141.         test    [esi + mtd_desc.status], RXOWN
  1142.         jnz     .fail_rx
  1143.  
  1144.         push    .rx_complete
  1145.  
  1146.         mov     ecx, [esi + mtd_desc.status]
  1147.         shr     ecx, FLNGShift
  1148.         sub     ecx, 4                  ; we dont need CRC
  1149.         push    ecx
  1150.  
  1151. ;-------------
  1152. ; Update stats
  1153.  
  1154.         add     dword [device.bytes_rx], ecx
  1155.         adc     dword [device.bytes_rx + 4], 0
  1156.         inc     dword [device.packets_rx]
  1157.  
  1158.  
  1159.         push    [esi + mtd_desc.skbuff]
  1160.  
  1161.         jmp     Eth_input
  1162.  
  1163.   .rx_complete:
  1164.         mov     esi, [device.cur_rx]
  1165.  
  1166.         mov     [esi + mtd_desc.control], 1536 shl RBSShift
  1167.  
  1168.         stdcall KernelAlloc, 1536
  1169.         mov     [esi + mtd_desc.skbuff], eax
  1170.         call    GetPgAddr
  1171.         mov     [esi + mtd_desc.buffer], eax
  1172.  
  1173.         mov     [esi + mtd_desc.status], RXOWN
  1174.  
  1175.         mov     eax, [esi + mtd_desc.next_desc_logical]
  1176.         mov     [device.cur_rx], eax
  1177.  
  1178.         jmp     .rx_loop
  1179. ;
  1180. ;    while( ( mtdx.cur_rx->status & RXOWN ) == 0 )
  1181. ;    {
  1182. ;        mtdx.cur_rx->status = RXOWN;
  1183. ;        mtdx.cur_rx = mtdx.cur_rx->next_desc_logical;
  1184. ;    }
  1185. ;
  1186. ;    /* Restart Rx engine if stopped. */
  1187. ;    outl(0, mtdx.ioaddr + RXPDR);
  1188.  
  1189.   .fail_rx:
  1190.         DEBUGF  1,"RX failed\n"
  1191.  
  1192.         pop     ax
  1193.   .no_rx:
  1194.  
  1195.         test    ax, TI ; transmit interrupt
  1196.         jz      .no_tx
  1197.  
  1198.         DEBUGF  1,"Transmit interrupt\n"
  1199.         push    ax
  1200.  
  1201.         lea     esi, [device.tx_desc]
  1202.         mov     ecx, NUM_TX_DESC
  1203.   .tx_loop:
  1204.  
  1205.         test    [esi + mtd_desc.status], TXOWN
  1206.         jnz     .skip_this_one
  1207.  
  1208.         mov     eax, [esi + mtd_desc.skbuff]
  1209.         test    eax, eax
  1210.         je      .skip_this_one
  1211.  
  1212.         mov     [esi + mtd_desc.skbuff], 0
  1213.  
  1214.         DEBUGF  1,"freeing buffer:%x\n", eax
  1215.         stdcall KernelFree, eax
  1216.  
  1217.   .skip_this_one:
  1218.         mov     esi, [esi + mtd_desc.next_desc_logical]
  1219.         loop    .tx_loop
  1220.  
  1221.         pop     ax
  1222.  
  1223.   .no_tx:
  1224.  
  1225.         test    ax, TBU
  1226.         jz      .no_tbu
  1227.  
  1228.         DEBUGF  1,"Transmit buffer unavailable!\n"
  1229.  
  1230.   .no_tbu:
  1231.  
  1232.   .fail:
  1233.  
  1234.         ret
  1235.  
  1236.  
  1237. ; End of code
  1238.  
  1239. align 4                                         ; Place all initialised data here
  1240.  
  1241. devices       dd 0
  1242. version       dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
  1243. my_service    db 'mtd80x',0                    ; max 16 chars include zero
  1244.  
  1245.  
  1246. ;   0x1516, 0x0800, "MTD800", "Myson MTD800"
  1247. ;   0x1516, 0x0803, "MTD803", "Surecom EP-320X"
  1248. ;   0x1516, 0x0891, "MTD891", "Myson MTD891"
  1249.  
  1250.  
  1251. include_debug_strings                           ; All data wich FDO uses will be included here
  1252.  
  1253. section '.data' data readable writable align 16 ; place all uninitialized data place here
  1254.  
  1255. device_list rd MAX_DEVICES                     ; This list contains all pointers to device structures the driver is handling
  1256.  
  1257.  
  1258.