Subversion Repositories Kolibri OS

Rev

Rev 2935 | Blame | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2004-2010. 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        db ?
  280.         .pci_dev        db ?
  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 mtd80x driver\n"
  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.         jl      .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.         jl      .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     ax , word [device.pci_bus]              ; compare with pci and device num in device list (notice the usage of word instead of byte)
  390.         je      .find_devicenum                         ; Device is already loaded, let's find it's device number
  391.         add     esi, 4
  392.         loop    .nextdevice
  393.  
  394.  
  395. ; This device doesnt have its own eth_device structure yet, lets create one
  396.   .firstdevice:
  397.         cmp     [devices], MAX_DEVICES                  ; First check if the driver can handle one more card
  398.         jge     .fail
  399.  
  400.         allocate_and_clear ebx, device_size, .fail
  401.  
  402. ; Fill in the direct call addresses into the struct
  403.  
  404.         mov     [device.reset], reset
  405.         mov     [device.transmit], transmit
  406.         mov     [device.get_MAC], read_mac
  407.         mov     [device.set_MAC], write_mac
  408.         mov     [device.unload], unload
  409.         mov     [device.name], my_service
  410.  
  411. ; save the pci bus and device numbers
  412.  
  413.         mov     eax, [IOCTL.input]
  414.         mov     cl , [eax+1]
  415.         mov     [device.pci_bus], cl
  416.         mov     cl , [eax+2]
  417.         mov     [device.pci_dev], cl
  418.  
  419. ; Now, it's time to find the base io addres of the PCI device
  420.  
  421.         find_io [device.pci_bus], [device.pci_dev], [device.io_addr]
  422.  
  423. ; We've found the io address, find IRQ now
  424.  
  425.         find_irq [device.pci_bus], [device.pci_dev], [device.irq_line]
  426.  
  427.         DEBUGF  2,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
  428.         [device.pci_dev]:1,[device.pci_bus]:1,[device.irq_line]:1,[device.io_addr]:8
  429.  
  430. ; Ok, the eth_device structure is ready, let's probe the device
  431. ; Because initialization fires IRQ, IRQ handler must be aware of this device
  432.         mov     eax, [devices]                                          ; Add the device structure to our device list
  433.         mov     [device_list+4*eax], ebx                                ; (IRQ handler uses this list to find device)
  434.         inc     [devices]                                               ;
  435.  
  436.         call    probe                                                   ; this function will output in eax
  437.         test    eax, eax
  438.         jnz     .err2                                                   ; If an error occured, exit
  439.  
  440.         mov     [device.type], NET_TYPE_ETH
  441.         call    NetRegDev
  442.  
  443.         cmp     eax, -1
  444.         je      .destroy
  445.  
  446.         ret
  447.  
  448. ; If the device was already loaded, find the device number and return it in eax
  449.  
  450.   .find_devicenum:
  451.         DEBUGF  2,"Trying to find device number of already registered device\n"
  452.         call    NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
  453.                                                                         ; into a device number in edi
  454.         mov     eax, edi                                                ; Application wants it in eax instead
  455.         DEBUGF  2,"Kernel says: %u\n", eax
  456.         ret
  457.  
  458. ; If an error occured, remove all allocated data and exit (returning -1 in eax)
  459.  
  460.   .destroy:
  461.         ; todo: reset device into virgin state
  462.  
  463.   .err2:
  464.         dec     [devices]
  465.   .err:
  466.         DEBUGF  2,"removing device structure\n"
  467.         stdcall KernelFree, ebx
  468.   .fail:
  469.         or      eax, -1
  470.         ret
  471.  
  472. ;------------------------------------------------------
  473. endp
  474.  
  475.  
  476. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  477. ;;                                                                        ;;
  478. ;;        Actual Hardware dependent code starts here                      ;;
  479. ;;                                                                        ;;
  480. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  481.  
  482.  
  483.  
  484. align 4
  485. unload:
  486.         ; TODO: (in this particular order)
  487.         ;
  488.         ; - Stop the device
  489.  
  490. ;    /* Disable Tx Rx*/
  491. ;    outl( mtdx.crvalue & (~TxEnable) & (~RxEnable), mtdx.ioaddr + TCRRCR );
  492. ;
  493. ;    /* Reset the chip to erase previous misconfiguration. */
  494. ;    mtd_reset(nic);
  495.  
  496.         ; - Detach int handler
  497.         ; - Remove device from local list (device_list)
  498.         ; - call unregister function in kernel
  499.         ; - Remove all allocated structures and buffers the card used
  500.  
  501.         or      eax,-1
  502.  
  503. ret
  504.  
  505.  
  506. ;-------
  507. ;
  508. ; PROBE
  509. ;
  510. ;-------
  511. align 4
  512. probe:
  513.  
  514.         DEBUGF  2,"Probing mtd80x device\n"
  515.  
  516.         make_bus_master [device.pci_bus], [device.pci_dev]
  517.  
  518.         movzx   eax, [device.pci_bus]
  519.         movzx   ecx, [device.pci_dev]
  520.         stdcall PciRead32, eax ,ecx ,0
  521.  
  522.         cmp     ax , 0x1516
  523.         jne     .notfound
  524.         shr     eax, 16
  525.         mov     [device.dev_id], ax
  526.  
  527.         cmp     ax, 0x0800
  528.         je      .has_mii_xcvr
  529.  
  530.         cmp     ax, 0x0803
  531.         je      .has_chip_xcvr
  532.  
  533.         cmp     ax, 0x0891
  534.         je      .has_mii_xcvr
  535.  
  536.   .notfound:
  537.         DEBUGF  1,"Device not supported!\n"
  538.         xor     eax, eax
  539.         dec     eax
  540.         ret
  541.  
  542.   .has_chip_xcvr:
  543.         DEBUGF  1,"Device has chip xcvr\n"
  544.  
  545.         jmp     .xcvr_set
  546.  
  547.   .has_mii_xcvr:
  548.         DEBUGF  1,"Device has mii xcvr\n"
  549.  
  550.   .xcvr_set:
  551.  
  552.         call    read_mac
  553.  
  554. ; Reset the chip to erase previous misconfiguration.
  555.  
  556.         set_io  0
  557.         set_io  BCR
  558.         xor     eax, eax
  559.         inc     eax
  560.         out     dx, eax
  561.  
  562. ; find the connected MII xcvrs
  563.  
  564.         cmp     [device.dev_id], 0x0803
  565.         je      .is_803
  566.  
  567. ;        int     phy, phy_idx =   0;
  568. ;
  569. ;        for (phy =   1; phy < 32 && phy_idx < 1; phy++) {
  570. ;            int mii_status =   mdio_read(nic, phy, 1);
  571. ;
  572. ;            if (mii_status !=   0xffff && mii_status !=   0x0000) {
  573. ;                mtdx.phys[phy_idx] =   phy;
  574. ;
  575. ;                DBG ( "%s: MII PHY found at address %d, status "
  576. ;                      "0x%4.4x.\n", mtdx.nic_name, phy, mii_status );
  577. ;                /* get phy type */
  578. ;                {
  579. ;                    unsigned int data;
  580. ;
  581. ;                    data =   mdio_read(nic, mtdx.phys[phy_idx], 2);
  582. ;                    if (data equ=   SeeqPHYID0)
  583. ;                        mtdx.PHYType =   SeeqPHY;
  584. ;                    else if (data equ=   AhdocPHYID0)
  585. ;                        mtdx.PHYType =   AhdocPHY;
  586. ;                    else if (data equ=   MarvellPHYID0)
  587. ;                        mtdx.PHYType =   MarvellPHY;
  588. ;                    else if (data equ=   MysonPHYID0)
  589. ;                        mtdx.PHYType =   Myson981;
  590. ;                    else if (data equ=   LevelOnePHYID0)
  591. ;                        mtdx.PHYType =   LevelOnePHY;
  592. ;                    else
  593. ;                        mtdx.PHYType =   OtherPHY;
  594. ;                }
  595. ;                phy_idx++;
  596. ;            }
  597. ;        }
  598. ;
  599. ;        mtdx.mii_cnt =   phy_idx;
  600. ;        if (phy_idx equ=   0) {
  601. ;            printf("%s: MII PHY not found -- this device may "
  602. ;                   "not operate correctly.\n", mtdx.nic_name);
  603. ;        }
  604.  
  605.         jmp     .no_803
  606.  
  607.   .is_803:
  608.  
  609.         mov     [device.phys], 32
  610.  
  611. ; get phy type
  612.         set_io  0
  613.         set_io  PHYIDENTIFIER
  614.         in      eax, dx
  615.  
  616.         cmp     eax, MysonPHYID
  617.         jne     @f
  618.  
  619.         mov     [device.PHYType], MysonPHY
  620.         DEBUGF  1,"MysonPHY\n"
  621.         jmp     .no_803
  622.  
  623.        @@:
  624.         mov     [device.PHYType], OtherPHY
  625.         DEBUGF  1,"OtherPHY\n"
  626.  
  627.   .no_803:
  628.  
  629. ;-------
  630. ;
  631. ; RESET
  632. ;
  633. ;-------
  634. align 4
  635. reset:
  636.  
  637.         DEBUGF  1,"Resetting mtd80x\n"
  638.  
  639. ;--------------------------------
  640. ; insert irq handler on given irq
  641.  
  642.         movzx   eax, [device.irq_line]
  643.         DEBUGF  1,"Attaching int handler to irq %x\n", eax:1
  644.         stdcall AttachIntHandler, eax, int_handler, dword 0
  645.         test    eax, eax
  646.         jnz     @f
  647.         DEBUGF  1,"\nCould not attach int handler!\n"
  648. ;        or      eax, -1
  649. ;        ret
  650.   @@:
  651.  
  652. ; Reset the chip to erase previous misconfiguration.
  653.  
  654.         set_io  0
  655.         set_io  BCR
  656.         xor     eax, eax
  657.         inc     eax
  658.         out     dx, eax
  659.  
  660.         call    init_ring
  661.  
  662. ; Initialize other registers.
  663. ; Configure the PCI bus bursts and FIFO thresholds.
  664.  
  665.         mov     [device.bcrvalue], 0x10 ; little-endian, 8 burst length
  666.         mov     [device.crvalue], 0xa00 ; 128 burst length
  667.  
  668.         cmp     [device.dev_id], 0x891
  669.         jne     @f
  670.         or      [device.bcrvalue], 0x200       ; set PROG bit
  671.         or      [device.crvalue], 0x02000000   ; set enhanced bit
  672.        @@:
  673.  
  674.         or      [device.crvalue], RxEnable + TxThreshold + TxEnable
  675.  
  676.         call    set_rx_mode
  677.  
  678.         set_io  0
  679.         set_io  BCR
  680.         mov     eax, [device.bcrvalue]
  681.         out     dx, eax
  682.  
  683.         set_io  TCRRCR
  684.         mov     eax, [device.crvalue]
  685.         out     dx, eax
  686.  
  687.         call    getlinkstatus
  688.         call    getlinktype
  689.  
  690. ; Restart Rx engine if stopped.
  691.  
  692.         set_io  0
  693.         set_io  RXPDR
  694.         xor     eax, eax
  695.         out     dx, eax
  696.  
  697. ; Enable interrupts
  698.  
  699.         set_io  0
  700.         set_io  ISR
  701.         mov     eax, (FBE or TUNF or CNTOVF or RBU or TI or RI)
  702.         out     dx, eax
  703.  
  704.         set_io  IMR
  705. ;        mov     eax, (FBE or TUNF or CNTOVF or RBU or TI or RI)
  706.         out     dx, eax
  707.  
  708. ; clear packet/byte counters
  709.  
  710.         xor     eax, eax
  711.         lea     edi, [device.bytes_tx]
  712.         mov     ecx, 6
  713.         rep     stosd
  714.  
  715.         mov     [device.mtu], 1514
  716.         xor     eax, eax
  717.  
  718.         ret
  719.  
  720.  
  721.  
  722.  
  723. align 4
  724. init_ring:
  725.  
  726.         DEBUGF  1,"initializing rx and tx ring\n"
  727.  
  728. ; Initialize all Rx descriptors
  729.  
  730.         lea     esi, [device.rx_desc]
  731.         mov     [device.cur_rx], esi
  732.         mov     ecx, NUM_RX_DESC
  733.   .rx_desc_loop:
  734.         mov     [esi + mtd_desc.status], RXOWN
  735.         mov     [esi + mtd_desc.control], 1536 shl RBSShift
  736.  
  737.         lea     eax, [esi + mtd_desc.size]
  738.         mov     [esi + mtd_desc.next_desc_logical], eax
  739.         push    ecx esi
  740.         GetRealAddr
  741.         mov     [esi + mtd_desc.next_desc], eax
  742.  
  743.         stdcall KernelAlloc, 1536
  744.         pop     esi
  745.         push    esi
  746.         mov     [esi + mtd_desc.skbuff], eax
  747.         call    GetPgAddr
  748.         pop     esi ecx
  749.         mov     [esi + mtd_desc.buffer], eax
  750.  
  751.         add     esi, mtd_desc.size
  752.         loop    .rx_desc_loop
  753.  
  754. ; Mark the last entry as wrapping the ring.
  755.  
  756.         lea     eax, [device.rx_desc]
  757.         mov     [esi - mtd_desc.size + mtd_desc.next_desc_logical], eax
  758.         push    esi
  759.         GetRealAddr
  760.         pop     esi
  761.         mov     [esi - mtd_desc.size + mtd_desc.next_desc], eax
  762.  
  763.         set_io  0
  764.         set_io  RXLBA
  765.         out     dx, eax
  766.  
  767. ; Initialize all Tx descriptors
  768.  
  769.         lea     esi, [device.tx_desc]
  770.         mov     [device.cur_tx], esi
  771.         mov     ecx, NUM_TX_DESC
  772.   .tx_desc_loop:
  773.         mov     [esi + mtd_desc.status], 0
  774.  
  775.         lea     eax, [esi + mtd_desc.size]
  776.         mov     [esi + mtd_desc.next_desc_logical], eax
  777.         push    ecx esi
  778.         GetRealAddr
  779.         pop     esi ecx
  780.         mov     [esi + mtd_desc.next_desc], eax
  781.  
  782.         add     esi, mtd_desc.size
  783.         loop    .tx_desc_loop
  784.  
  785. ; Mark the last entry as wrapping the ring.
  786.  
  787.         lea     eax, [device.tx_desc]
  788.         mov     [esi - mtd_desc.size + mtd_desc.next_desc_logical], eax
  789.         push    esi
  790.         GetRealAddr
  791.         pop     esi
  792.         mov     [esi - mtd_desc.size + mtd_desc.next_desc], eax
  793.  
  794.         set_io  0
  795.         set_io  TXLBA
  796.         out     dx, eax
  797.  
  798.         ret
  799.  
  800.  
  801. align 4
  802. set_rx_mode:
  803.  
  804.         DEBUGF  1,"Setting RX mode\n"
  805.  
  806. ; Too many to match, or accept all multicasts.
  807.  
  808.         set_io  0
  809.         set_io  MAR0
  810.         xor     eax, eax
  811.         not     eax
  812.         out     dx, eax
  813.         set_io  MAR1
  814.         out     dx, eax
  815.  
  816.         and     [device.crvalue], not (RxModeMask)
  817.         or      [device.crvalue], AcceptBroadcast + AcceptMulticast + AcceptMyPhys
  818.  
  819.         ret
  820.  
  821.  
  822. align 4
  823. getlinkstatus:
  824.  
  825.         DEBUGF  1,"Getting link status\n"
  826.  
  827.         mov     [device.linkok], 0
  828.  
  829.         cmp     [device.PHYType], MysonPHY
  830.         jne     .no_myson_phy
  831.  
  832.         set_io  0
  833.         set_io  BMCRSR
  834.         mov     ecx, 1000
  835.   .loop1:
  836.         in      eax, dx
  837.         test    eax, LinkIsUp2
  838.         jnz     .link_ok
  839.  
  840.         push    ecx edx ebx
  841.         mov     esi, 10
  842.         call    Sleep
  843.         pop     ebx edx ecx
  844.         loop    .loop1
  845.  
  846.         ret
  847.  
  848.   .no_myson_phy:
  849.  
  850. ;        for (i =   0; i < DelayTime; ++i) {
  851. ;            if (mdio_read(nic, mtdx.phys[0], MII_BMSR) & BMSR_LSTATUS) {
  852. ;                mtdx.linkok =   1;
  853. ;                return;
  854. ;            }
  855. ;            m80x_delay(100);
  856.  
  857.         ret
  858.  
  859.   .link_ok:
  860.         DEBUGF  1,"Link is up\n"
  861.         inc     [device.linkok]
  862.         ret
  863.  
  864.  
  865.  
  866.  
  867. align 4
  868. getlinktype:
  869.  
  870.         DEBUGF  1,"Getting link type\n"
  871.  
  872.         cmp     [device.PHYType], MysonPHY
  873.         jne     .no_myson_phy
  874.  
  875.         DEBUGF  1,"myson PHY\n"
  876.  
  877.         set_io  0
  878.         set_io  TCRRCR
  879.         in      eax, dx
  880.  
  881.         mov     [device.duplexmode], 1  ; 1 =   half duplex
  882.         test    eax, FD
  883.         jne     @f
  884.         DEBUGF  1,"full duplex\n"
  885.         inc     [device.duplexmode]     ; 2 =   full duplex
  886.        @@:
  887.  
  888.         mov     [device.line_speed], 1  ; 1 =   10M
  889.         test    eax, PS10
  890.         jne     @f
  891.         DEBUGF  1,"100mbit\n"
  892.         inc     [device.line_speed]     ; 2 =   100M
  893.        @@:
  894.  
  895.         ret
  896.  
  897.   .no_myson_phy:
  898.  
  899.         DEBUGF  1,"no myson phy\n"
  900.  
  901. ;        if (mtdx.PHYType equ=   SeeqPHY) { /* this PHY is SEEQ 80225 */
  902. ;            unsigned int data;
  903. ;
  904. ;            data =   mdio_read(dev, mtdx.phys[0], MIIRegister18);
  905. ;            if (data & SPD_DET_100)
  906. ;                mtdx.line_speed =   2; /* 100M */
  907. ;            else
  908. ;                mtdx.line_speed =   1; /* 10M */
  909. ;            if (data & DPLX_DET_FULL)
  910. ;                mtdx.duplexmode =   2; /* full duplex mode */
  911. ;            else
  912. ;                mtdx.duplexmode =   1; /* half duplex mode */
  913. ;        } else if (mtdx.PHYType equ=   AhdocPHY) {
  914. ;            unsigned int data;
  915. ;
  916. ;            data =   mdio_read(dev, mtdx.phys[0], DiagnosticReg);
  917. ;            if (data & Speed_100)
  918. ;                mtdx.line_speed =   2; /* 100M */
  919. ;            else
  920. ;                mtdx.line_speed =   1; /* 10M */
  921. ;            if (data & DPLX_FULL)
  922. ;                mtdx.duplexmode =   2; /* full duplex mode */
  923. ;            else
  924. ;                mtdx.duplexmode =   1; /* half duplex mode */
  925. ;        }
  926. ;        else if (mtdx.PHYType equ=   MarvellPHY) {
  927. ;            unsigned int data;
  928. ;
  929. ;            data =   mdio_read(dev, mtdx.phys[0], SpecificReg);
  930. ;            if (data & Full_Duplex)
  931. ;                mtdx.duplexmode =   2; /* full duplex mode */
  932. ;            else
  933. ;                mtdx.duplexmode =   1; /* half duplex mode */
  934. ;            data &=   SpeedMask;
  935. ;            if (data equ=   Speed_1000M)
  936. ;                mtdx.line_speed =   3; /* 1000M */
  937. ;            else if (data equ=   Speed_100M)
  938. ;                mtdx.line_speed =   2; /* 100M */
  939. ;            else
  940. ;                mtdx.line_speed =   1; /* 10M */
  941. ;        }
  942. ;        else if (mtdx.PHYType equ=   Myson981) {
  943. ;            unsigned int data;
  944. ;
  945. ;            data =   mdio_read(dev, mtdx.phys[0], StatusRegister);
  946. ;
  947. ;            if (data & SPEED100)
  948. ;                mtdx.line_speed =   2;
  949. ;            else
  950. ;                mtdx.line_speed =   1;
  951. ;
  952. ;            if (data & FULLMODE)
  953. ;                mtdx.duplexmode =   2;
  954. ;            else
  955. ;                mtdx.duplexmode =   1;
  956. ;        }
  957. ;        else if (mtdx.PHYType equ=   LevelOnePHY) {
  958. ;            unsigned int data;
  959. ;
  960. ;            data =   mdio_read(dev, mtdx.phys[0], SpecificReg);
  961. ;            if (data & LXT1000_Full)
  962. ;                mtdx.duplexmode =   2; /* full duplex mode */
  963. ;            else
  964. ;                mtdx.duplexmode =   1; /* half duplex mode */
  965. ;            data &=   SpeedMask;
  966. ;            if (data equ=   LXT1000_1000M)
  967. ;                mtdx.line_speed =   3; /* 1000M */
  968. ;            else if (data equ=   LXT1000_100M)
  969. ;                mtdx.line_speed =   2; /* 100M */
  970. ;            else
  971.  ;               mtdx.line_speed =   1; /* 10M */
  972.   ;      }
  973.  
  974. ;        // chage crvalue
  975. ;        // mtdx.crvalue&equ(~PS10)&(~FD);
  976. ;        mtdx.crvalue &=   (~PS10) & (~FD) & (~PS1000);
  977. ;        if (mtdx.line_speed equ=   1)
  978. ;            mtdx.crvalue |=   PS10;
  979. ;        else if (mtdx.line_speed equ=   3)
  980. ;            mtdx.crvalue |=   PS1000;
  981. ;        if (mtdx.duplexmode equ=   2)
  982. ;            mtdx.crvalue |=   FD;
  983. ;
  984.  
  985.         ret
  986.  
  987.  
  988.  
  989.  
  990. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  991. ;;                                         ;;
  992. ;; Transmit                                ;;
  993. ;;                                         ;;
  994. ;; In: buffer pointer in [esp+4]           ;;
  995. ;;     size of buffer in [esp+8]           ;;
  996. ;;     pointer to device structure in ebx  ;;
  997. ;;                                         ;;
  998. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  999.  
  1000. align 4
  1001. transmit:
  1002.  
  1003.         DEBUGF  1,"Transmitting packet, buffer:%x, size:%u\n",[esp+4],[esp+8]
  1004.         mov     eax, [esp+4]
  1005.         DEBUGF  1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
  1006.         [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
  1007.         [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
  1008.         [eax+13]:2,[eax+12]:2
  1009.  
  1010.         cmp     dword [esp+8], 1514
  1011.         ja      .fail
  1012.  
  1013.         mov     esi, [device.cur_tx]
  1014.         push    [esi + mtd_desc.next_desc_logical]
  1015.         pop     [device.cur_tx]
  1016.  
  1017.         ; todo: check if descriptor is not owned by the device!
  1018.  
  1019.         mov     eax, [esp + 4]
  1020.         mov     [esi + mtd_desc.skbuff], eax
  1021.         GetRealAddr
  1022.         mov     [esi + mtd_desc.buffer], eax
  1023.  
  1024.         mov     eax, [esp + 8]
  1025.         shl     eax, PKTSShift               ; packet size
  1026.         or      eax, TXLD + TXFD + CRCEnable + PADEnable + TXIC + 1536 shl TBSShift ; buffer size
  1027.         mov     [esi + mtd_desc.control], eax
  1028.  
  1029.         mov     [esi + mtd_desc.status], TXOWN
  1030.  
  1031. ;-------------
  1032. ; Update stats
  1033.  
  1034.         inc     [device.packets_tx]
  1035.         mov     eax, [esp+8]
  1036.         add     dword [device.bytes_tx], eax
  1037.         adc     dword [device.bytes_tx + 4], 0
  1038.  
  1039. ; Point to transmit descriptor
  1040.  
  1041.         set_io  0
  1042.         set_io  TXLBA
  1043.         mov     eax, esi
  1044.         GetRealAddr
  1045.         out     dx, eax
  1046.  
  1047. ;        set_io  TCRRCR
  1048. ;        mov     eax, [device.crvalue]
  1049. ;        out     dx, eax
  1050.  
  1051. ; Wake the potentially-idle transmit channel.
  1052.  
  1053.         set_io  TXPDR           ; TX Poll
  1054.         xor     eax, eax
  1055.         out     dx, eax
  1056.  
  1057.         DEBUGF  1,"transmit ok\n"
  1058.         xor     eax, eax
  1059.         ret     8
  1060.  
  1061.   .fail:
  1062.         DEBUGF  1,"transmit failed\n"
  1063.         or      eax, -1
  1064.         stdcall KernelFree, [esp + 4]
  1065.         ret     8
  1066.  
  1067.  
  1068.  
  1069. align 4
  1070. read_mac:
  1071.  
  1072.         set_io  0
  1073.         set_io  PAR0
  1074.         lea     edi, [device.mac]
  1075.         insd
  1076.         stosd
  1077.         set_io  PAR1
  1078.         insw
  1079.         stosw
  1080.  
  1081.         DEBUGF  1,"MAC = %x-%x-%x-%x-%x-%x\n",\
  1082.         [device.mac+0]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2
  1083.  
  1084.         ret
  1085.  
  1086. align 4
  1087. write_mac:
  1088.  
  1089.         ret
  1090.  
  1091.  
  1092.  
  1093. ;;;;;;;;;;;;;;;;;;;;;;;
  1094. ;;                   ;;
  1095. ;; Interrupt handler ;;
  1096. ;;                   ;;
  1097. ;;;;;;;;;;;;;;;;;;;;;;;
  1098.  
  1099. align 4
  1100. int_handler:
  1101.  
  1102.         DEBUGF  1,"\n%s int\n", my_service
  1103.  
  1104. ; find pointer of device wich made IRQ occur
  1105.  
  1106.         mov     ecx, [devices]
  1107.         test    ecx, ecx
  1108.         jz      .nothing
  1109.         mov     esi, device_list
  1110.   .nextdevice:
  1111.         mov     ebx, [esi]
  1112.  
  1113.         set_io  0
  1114.         set_io  ISR
  1115.         in      eax, dx
  1116.         out     dx, eax                                 ; send it back to ACK
  1117.         test    eax, eax
  1118.         jnz     .got_it
  1119.   .continue:
  1120.         add     esi, 4
  1121.         dec     ecx
  1122.         jnz     .nextdevice
  1123.   .nothing:
  1124.         ret                                             ; If no device was found, abort (The irq was probably for a device, not registered to this driver)
  1125.  
  1126.   .got_it:
  1127.  
  1128.         DEBUGF  1,"Device: %x Status: %x ", ebx, ax
  1129.  
  1130.         test    ax, RI  ; receive interrupt
  1131.         jz      .no_rx
  1132.  
  1133.         DEBUGF  1,"Receive interrupt\n"
  1134.   .rx:
  1135.         push    ax
  1136.  
  1137.   .rx_loop:
  1138.         mov     esi, [device.cur_rx]
  1139.  
  1140.         test    [esi + mtd_desc.status], RXOWN
  1141.         jnz     .fail_rx
  1142.  
  1143.         push    .rx_complete
  1144.  
  1145.         mov     ecx, [esi + mtd_desc.status]
  1146.         shr     ecx, FLNGShift
  1147.         sub     ecx, 4                  ; we dont need CRC
  1148.         push    ecx
  1149.  
  1150. ;-------------
  1151. ; Update stats
  1152.  
  1153.         add     dword [device.bytes_rx], ecx
  1154.         adc     dword [device.bytes_rx + 4], 0
  1155.         inc     dword [device.packets_rx]
  1156.  
  1157.  
  1158.         push    [esi + mtd_desc.skbuff]
  1159.  
  1160.         jmp     Eth_input
  1161.  
  1162.   .rx_complete:
  1163.         mov     esi, [device.cur_rx]
  1164.  
  1165.         mov     [esi + mtd_desc.control], 1536 shl RBSShift
  1166.  
  1167.         stdcall KernelAlloc, 1536
  1168.         mov     [esi + mtd_desc.skbuff], eax
  1169.         call    GetPgAddr
  1170.         mov     [esi + mtd_desc.buffer], eax
  1171.  
  1172.         mov     [esi + mtd_desc.status], RXOWN
  1173.  
  1174.         mov     eax, [esi + mtd_desc.next_desc_logical]
  1175.         mov     [device.cur_rx], eax
  1176.  
  1177.         jmp     .rx_loop
  1178. ;
  1179. ;    while( ( mtdx.cur_rx->status & RXOWN ) == 0 )
  1180. ;    {
  1181. ;        mtdx.cur_rx->status = RXOWN;
  1182. ;        mtdx.cur_rx = mtdx.cur_rx->next_desc_logical;
  1183. ;    }
  1184. ;
  1185. ;    /* Restart Rx engine if stopped. */
  1186. ;    outl(0, mtdx.ioaddr + RXPDR);
  1187.  
  1188.   .fail_rx:
  1189.         DEBUGF  1,"RX failed\n"
  1190.  
  1191.         pop     ax
  1192.   .no_rx:
  1193.  
  1194.         test    ax, TI ; transmit interrupt
  1195.         jz      .no_tx
  1196.  
  1197.         DEBUGF  1,"Transmit interrupt\n"
  1198.         push    ax
  1199.  
  1200.         lea     esi, [device.tx_desc]
  1201.         mov     ecx, NUM_TX_DESC
  1202.   .tx_loop:
  1203.  
  1204.         test    [esi + mtd_desc.status], TXOWN
  1205.         jnz     .skip_this_one
  1206.  
  1207.         mov     eax, [esi + mtd_desc.skbuff]
  1208.         test    eax, eax
  1209.         je      .skip_this_one
  1210.  
  1211.         mov     [esi + mtd_desc.skbuff], 0
  1212.  
  1213.         DEBUGF  1,"freeing buffer:%x\n", eax
  1214.         stdcall KernelFree, eax
  1215.  
  1216.   .skip_this_one:
  1217.         mov     esi, [esi + mtd_desc.next_desc_logical]
  1218.         loop    .tx_loop
  1219.  
  1220.         pop     ax
  1221.  
  1222.   .no_tx:
  1223.  
  1224.         test    ax, TBU
  1225.         jz      .no_tbu
  1226.  
  1227.         DEBUGF  1,"Transmit buffer unavailable!\n"
  1228.  
  1229.   .no_tbu:
  1230.  
  1231.   .fail:
  1232.  
  1233.         ret
  1234.  
  1235.  
  1236. ; End of code
  1237.  
  1238. align 4                                         ; Place all initialised data here
  1239.  
  1240. devices       dd 0
  1241. version       dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
  1242. my_service    db 'mtd80x',0                    ; max 16 chars include zero
  1243.  
  1244.  
  1245. ;   0x1516, 0x0800, "MTD800", "Myson MTD800"
  1246. ;   0x1516, 0x0803, "MTD803", "Surecom EP-320X"
  1247. ;   0x1516, 0x0891, "MTD891", "Myson MTD891"
  1248.  
  1249.  
  1250. include_debug_strings                           ; All data wich FDO uses will be included here
  1251.  
  1252. section '.data' data readable writable align 16 ; place all uninitialized data place here
  1253.  
  1254. device_list rd MAX_DEVICES                     ; This list contains all pointers to device structures the driver is handling
  1255.  
  1256.  
  1257.