Subversion Repositories Kolibri OS

Rev

Rev 1561 | 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             equ 0x01000100
  20.         DRIVER_VERSION          equ 5
  21.  
  22.         MAX_DEVICES             equ 16
  23.  
  24.         DEBUG                   equ 1
  25.         __DEBUG__               equ 1
  26.         __DEBUG_LEVEL__         equ 1
  27.  
  28.         NUM_TX_DESC             equ 4
  29.         NUM_RX_DESC             equ 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            equ 1
  44.     AhdocPHY            equ 2
  45.     SeeqPHY             equ 3
  46.     MarvellPHY          equ 4
  47.     Myson981            equ 5
  48.     LevelOnePHY         equ 6
  49.     OtherPHY            equ 10
  50.  
  51. ; Offsets to the Command and Status Registers.
  52.  
  53.     PAR0                equ 0x0        ; physical address 0-3
  54.     PAR1                equ 0x04       ; physical address 4-5
  55.     MAR0                equ 0x08       ; multicast address 0-3
  56.     MAR1                equ 0x0C       ; multicast address 4-7
  57.     FAR0                equ 0x10       ; flow-control address 0-3
  58.     FAR1                equ 0x14       ; flow-control address 4-5
  59.     TCRRCR              equ 0x18       ; receive & transmit configuration
  60.     BCR                 equ 0x1C       ; bus command
  61.     TXPDR               equ 0x20       ; transmit polling demand
  62.     RXPDR               equ 0x24       ; receive polling demand
  63.     RXCWP               equ 0x28       ; receive current word pointer
  64.     TXLBA               equ 0x2C       ; transmit list base address
  65.     RXLBA               equ 0x30       ; receive list base address
  66.     ISR                 equ 0x34       ; interrupt status
  67.     IMR                 equ 0x38       ; interrupt mask
  68.     FTH                 equ 0x3C       ; flow control high/low threshold
  69.     MANAGEMENT          equ 0x40       ; bootrom/eeprom and mii management
  70.     TALLY               equ 0x44       ; tally counters for crc and mpa
  71.     TSR                 equ 0x48       ; tally counter for transmit status
  72.     BMCRSR              equ 0x4c       ; basic mode control and status
  73.     PHYIDENTIFIER       equ 0x50       ; phy identifier
  74.     ANARANLPAR          equ 0x54       ; auto-negotiation advertisement and link partner ability
  75.     ANEROCR             equ 0x58       ; auto-negotiation expansion and pci conf.
  76.     BPREMRPSR           equ 0x5c       ; bypass & receive error mask and phy status
  77.  
  78. ; Bits in the interrupt status/enable registers.
  79.  
  80.     RFCON               equ 0x00020000 ; receive flow control xon packet
  81.     RFCOFF              equ 0x00010000 ; receive flow control xoff packet
  82.     LSCStatus           equ 0x00008000 ; link status change
  83.     ANCStatus           equ 0x00004000 ; autonegotiation completed
  84.     FBE                 equ 0x00002000 ; fatal bus error
  85.     FBEMask             equ 0x00001800 ; mask bit12-11
  86.     ParityErr           equ 0x00000000 ; parity error
  87.     TargetErr           equ 0x00001000 ; target abort
  88.     MasterErr           equ 0x00000800 ; master error
  89.     TUNF                equ 0x00000400 ; transmit underflow
  90.     ROVF                equ 0x00000200 ; receive overflow
  91.     ETI                 equ 0x00000100 ; transmit early int
  92.     ERI                 equ 0x00000080 ; receive early int
  93.     CNTOVF              equ 0x00000040 ; counter overflow
  94.     RBU                 equ 0x00000020 ; receive buffer unavailable
  95.     TBU                 equ 0x00000010 ; transmit buffer unavilable
  96.     TI                  equ 0x00000008 ; transmit interrupt
  97.     RI                  equ 0x00000004 ; receive interrupt
  98.     RxErr               equ 0x00000002 ; receive error
  99.  
  100. ; Bits in the NetworkConfig register.
  101.  
  102.     RxModeMask          equ 0xe0
  103.     AcceptAllPhys       equ 0x80        ; promiscuous mode
  104.     AcceptBroadcast     equ 0x40        ; accept broadcast
  105.     AcceptMulticast     equ 0x20        ; accept mutlicast
  106.     AcceptRunt          equ 0x08        ; receive runt pkt
  107.     ALP                 equ 0x04        ; receive long pkt
  108.     AcceptErr           equ 0x02        ; receive error pkt
  109.  
  110.     AcceptMyPhys        equ 0x00000000
  111.     RxEnable            equ 0x00000001
  112.     RxFlowCtrl          equ 0x00002000
  113.     TxEnable            equ 0x00040000
  114.     TxModeFDX           equ 0x00100000
  115.     TxThreshold         equ 0x00e00000
  116.  
  117.     PS1000              equ 0x00010000
  118.     PS10                equ 0x00080000
  119.     FD                  equ 0x00100000
  120.  
  121.  
  122. ; Bits in network_desc.status
  123.  
  124.     RXOWN               equ 0x80000000 ; own bit
  125.     FLNGMASK            equ 0x0fff0000 ; frame length
  126.     FLNGShift           equ 16
  127.     MARSTATUS           equ 0x00004000 ; multicast address received
  128.     BARSTATUS           equ 0x00002000 ; broadcast address received
  129.     PHYSTATUS           equ 0x00001000 ; physical address received
  130.     RXFSD               equ 0x00000800 ; first descriptor
  131.     RXLSD               equ 0x00000400 ; last descriptor
  132.     ErrorSummary        equ 0x80       ; error summary
  133.     RUNT                equ 0x40       ; runt packet received
  134.     LONG                equ 0x20       ; long packet received
  135.     FAE                 equ 0x10       ; frame align error
  136.     CRC                 equ 0x08       ; crc error
  137.     RXER                equ 0x04       ; receive error
  138.  
  139. ; rx_desc_control_bits
  140.  
  141.     RXIC                equ 0x00800000 ; interrupt control
  142.     RBSShift            equ 0
  143.  
  144. ; tx_desc_status_bits
  145.  
  146.     TXOWN               equ 0x80000000 ; own bit
  147.     JABTO               equ 0x00004000 ; jabber timeout
  148.     CSL                 equ 0x00002000 ; carrier sense lost
  149.     LC                  equ 0x00001000 ; late collision
  150.     EC                  equ 0x00000800 ; excessive collision
  151.     UDF                 equ 0x00000400 ; fifo underflow
  152.     DFR                 equ 0x00000200 ; deferred
  153.     HF                  equ 0x00000100 ; heartbeat fail
  154.     NCRMask             equ 0x000000ff ; collision retry count
  155.     NCRShift            equ 0
  156.  
  157. ; tx_desc_control_bits
  158.  
  159.     TXIC                equ 0x80000000 ; interrupt control
  160.     ETIControl          equ 0x40000000 ; early transmit interrupt
  161.     TXLD                equ 0x20000000 ; last descriptor
  162.     TXFD                equ 0x10000000 ; first descriptor
  163.     CRCEnable           equ 0x08000000 ; crc control
  164.     PADEnable           equ 0x04000000 ; padding control
  165.     RetryTxLC           equ 0x02000000 ; retry late collision
  166.     PKTSMask            equ 0x3ff800   ; packet size bit21-11
  167.     PKTSShift           equ 11
  168.     TBSMask             equ 0x000007ff ; transmit buffer bit 10-0
  169.     TBSShift            equ 0
  170.  
  171. ; BootROM/EEPROM/MII Management Register
  172.  
  173.     MASK_MIIR_MII_READ  equ 0x00000000
  174.     MASK_MIIR_MII_WRITE equ 0x00000008
  175.     MASK_MIIR_MII_MDO   equ 0x00000004
  176.     MASK_MIIR_MII_MDI   equ 0x00000002
  177.     MASK_MIIR_MII_MDC   equ 0x00000001
  178.  
  179. ; ST+OP+PHYAD+REGAD+TA
  180.  
  181.     OP_READ             equ 0x6000 ; ST:01+OP:10+PHYAD+REGAD+TA:Z0
  182.     OP_WRITE            equ 0x5002 ; ST:01+OP:01+PHYAD+REGAD+TA:10
  183.  
  184. ; -------------------------------------------------------------------------
  185. ;      Constants for Myson PHY
  186. ; -------------------------------------------------------------------------
  187.  
  188.     MysonPHYID          equ 0xd0000302
  189.     MysonPHYID0         equ 0x0302
  190.     StatusRegister      equ 18
  191.     SPEED100            equ 0x0400 ; bit10
  192.     FULLMODE            equ 0x0800 ; bit11
  193.  
  194. ; -------------------------------------------------------------------------
  195. ;      Constants for Seeq 80225 PHY
  196. ; -------------------------------------------------------------------------
  197.  
  198.     SeeqPHYID0          equ 0x0016
  199.     MIIRegister18       equ 18
  200.     SPD_DET_100         equ 0x80
  201.     DPLX_DET_FULL       equ 0x40
  202.  
  203. ; -------------------------------------------------------------------------
  204. ;      Constants for Ahdoc 101 PHY
  205. ; -------------------------------------------------------------------------
  206.  
  207.     AhdocPHYID0         equ 0x0022
  208.     DiagnosticReg       equ 18
  209.     DPLX_FULL           equ 0x0800
  210.     Speed_100           equ 0x0400
  211.  
  212. ; --------------------------------------------------------------------------
  213. ;      Constants
  214. ; --------------------------------------------------------------------------
  215.  
  216.     MarvellPHYID0       equ 0x0141
  217.     LevelOnePHYID0      equ 0x0013
  218.  
  219.     MII1000BaseTControlReg      equ 9
  220.     MII1000BaseTStatusReg       equ 10
  221.     SpecificReg         equ 17
  222.  
  223. ; for 1000BaseT Control Register
  224.  
  225.     PHYAbletoPerform1000FullDuplex equ 0x0200
  226.     PHYAbletoPerform1000HalfDuplex equ 0x0100
  227.     PHY1000AbilityMask             equ 0x300
  228.  
  229. ; for phy specific status register, marvell phy.
  230.  
  231.     SpeedMask      equ 0x0c000
  232.     Speed_1000M    equ 0x08000
  233.     Speed_100M     equ 0x4000
  234.     Speed_10M      equ 0
  235.     Full_Duplex    equ 0x2000
  236.  
  237. ; for phy specific status register, levelone phy
  238.  
  239.     LXT1000_100M   equ 0x08000
  240.     LXT1000_1000M  equ 0x0c000
  241.     LXT1000_Full   equ 0x200
  242.  
  243. ; for PHY
  244.  
  245.     LinkIsUp       equ 0x0004
  246.     LinkIsUp2      equ 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 equ 0;
  568. ;
  569. ;        for (phy equ 1; phy < 32 && phy_idx < 1; phy++) {
  570. ;            int mii_status equ mdio_read(nic, phy, 1);
  571. ;
  572. ;            if (mii_status !equ 0xffff && mii_status !equ 0x0000) {
  573. ;                mtdx.phys[phy_idx] equ 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 equ mdio_read(nic, mtdx.phys[phy_idx], 2);
  582. ;                    if (data equequ SeeqPHYID0)
  583. ;                        mtdx.PHYType equ SeeqPHY;
  584. ;                    else if (data equequ AhdocPHYID0)
  585. ;                        mtdx.PHYType equ AhdocPHY;
  586. ;                    else if (data equequ MarvellPHYID0)
  587. ;                        mtdx.PHYType equ MarvellPHY;
  588. ;                    else if (data equequ MysonPHYID0)
  589. ;                        mtdx.PHYType equ Myson981;
  590. ;                    else if (data equequ LevelOnePHYID0)
  591. ;                        mtdx.PHYType equ LevelOnePHY;
  592. ;                    else
  593. ;                        mtdx.PHYType equ OtherPHY;
  594. ;                }
  595. ;                phy_idx++;
  596. ;            }
  597. ;        }
  598. ;
  599. ;        mtdx.mii_cnt equ phy_idx;
  600. ;        if (phy_idx equequ 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 equ 0; i < DelayTime; ++i) {
  851. ;            if (mdio_read(nic, mtdx.phys[0], MII_BMSR) & BMSR_LSTATUS) {
  852. ;                mtdx.linkok equ 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 equ half duplex
  882.         test    eax, FD
  883.         jne     @f
  884.         DEBUGF  1,"full duplex\n"
  885.         inc     [device.duplexmode]     ; 2 equ full duplex
  886.        @@:
  887.  
  888.         mov     [device.line_speed], 1  ; 1 equ 10M
  889.         test    eax, PS10
  890.         jne     @f
  891.         DEBUGF  1,"100mbit\n"
  892.         inc     [device.line_speed]     ; 2 equ 100M
  893.        @@:
  894.  
  895.         ret
  896.  
  897.   .no_myson_phy:
  898.  
  899.         DEBUGF  1,"no myson phy\n"
  900.  
  901. ;        if (mtdx.PHYType equequ SeeqPHY) { /* this PHY is SEEQ 80225 */
  902. ;            unsigned int data;
  903. ;
  904. ;            data equ mdio_read(dev, mtdx.phys[0], MIIRegister18);
  905. ;            if (data & SPD_DET_100)
  906. ;                mtdx.line_speed equ 2; /* 100M */
  907. ;            else
  908. ;                mtdx.line_speed equ 1; /* 10M */
  909. ;            if (data & DPLX_DET_FULL)
  910. ;                mtdx.duplexmode equ 2; /* full duplex mode */
  911. ;            else
  912. ;                mtdx.duplexmode equ 1; /* half duplex mode */
  913. ;        } else if (mtdx.PHYType equequ AhdocPHY) {
  914. ;            unsigned int data;
  915. ;
  916. ;            data equ mdio_read(dev, mtdx.phys[0], DiagnosticReg);
  917. ;            if (data & Speed_100)
  918. ;                mtdx.line_speed equ 2; /* 100M */
  919. ;            else
  920. ;                mtdx.line_speed equ 1; /* 10M */
  921. ;            if (data & DPLX_FULL)
  922. ;                mtdx.duplexmode equ 2; /* full duplex mode */
  923. ;            else
  924. ;                mtdx.duplexmode equ 1; /* half duplex mode */
  925. ;        }
  926. ;        else if (mtdx.PHYType equequ MarvellPHY) {
  927. ;            unsigned int data;
  928. ;
  929. ;            data equ mdio_read(dev, mtdx.phys[0], SpecificReg);
  930. ;            if (data & Full_Duplex)
  931. ;                mtdx.duplexmode equ 2; /* full duplex mode */
  932. ;            else
  933. ;                mtdx.duplexmode equ 1; /* half duplex mode */
  934. ;            data &equ SpeedMask;
  935. ;            if (data equequ Speed_1000M)
  936. ;                mtdx.line_speed equ 3; /* 1000M */
  937. ;            else if (data equequ Speed_100M)
  938. ;                mtdx.line_speed equ 2; /* 100M */
  939. ;            else
  940. ;                mtdx.line_speed equ 1; /* 10M */
  941. ;        }
  942. ;        else if (mtdx.PHYType equequ Myson981) {
  943. ;            unsigned int data;
  944. ;
  945. ;            data equ mdio_read(dev, mtdx.phys[0], StatusRegister);
  946. ;
  947. ;            if (data & SPEED100)
  948. ;                mtdx.line_speed equ 2;
  949. ;            else
  950. ;                mtdx.line_speed equ 1;
  951. ;
  952. ;            if (data & FULLMODE)
  953. ;                mtdx.duplexmode equ 2;
  954. ;            else
  955. ;                mtdx.duplexmode equ 1;
  956. ;        }
  957. ;        else if (mtdx.PHYType equequ LevelOnePHY) {
  958. ;            unsigned int data;
  959. ;
  960. ;            data equ mdio_read(dev, mtdx.phys[0], SpecificReg);
  961. ;            if (data & LXT1000_Full)
  962. ;                mtdx.duplexmode equ 2; /* full duplex mode */
  963. ;            else
  964. ;                mtdx.duplexmode equ 1; /* half duplex mode */
  965. ;            data &equ SpeedMask;
  966. ;            if (data equequ LXT1000_1000M)
  967. ;                mtdx.line_speed equ 3; /* 1000M */
  968. ;            else if (data equequ LXT1000_100M)
  969. ;                mtdx.line_speed equ 2; /* 100M */
  970. ;            else
  971.  ;               mtdx.line_speed equ 1; /* 10M */
  972.   ;      }
  973.  
  974. ;        // chage crvalue
  975. ;        // mtdx.crvalue&equ(~PS10)&(~FD);
  976. ;        mtdx.crvalue &equ (~PS10) & (~FD) & (~PS1000);
  977. ;        if (mtdx.line_speed equequ 1)
  978. ;            mtdx.crvalue |equ PS10;
  979. ;        else if (mtdx.line_speed equequ 3)
  980. ;            mtdx.crvalue |equ PS1000;
  981. ;        if (mtdx.duplexmode equequ 2)
  982. ;            mtdx.crvalue |equ 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,"\nIRQ %x\n",eax:2                       ; no, you cant replace 'eax:2' with 'al', this must be a bug in FDO
  1103.  
  1104. ; find pointer of device wich made IRQ occur
  1105.  
  1106.         mov     ecx, [devices]
  1107.         test    ecx, ecx
  1108.         jz      .fail
  1109.         mov     esi, device_list
  1110.   .nextdevice:
  1111.         mov     ebx, dword [esi]
  1112.  
  1113.         set_io  0
  1114.         set_io  ISR
  1115.         in      eax, dx
  1116.         out     dx , eax                                ; send it back to ACK
  1117.  ;       and     eax,  ; int mask
  1118.         test    eax, eax
  1119.         jnz     .got_it
  1120.  
  1121.   .continue:
  1122.         add     esi, 4
  1123.         dec     ecx
  1124.         jnz     .nextdevice
  1125.  
  1126.         ret                                             ; If no device was found, abort (The irq was probably for a device, not registered to this driver)
  1127.  
  1128.   .got_it:
  1129.  
  1130.         DEBUGF  1,"Status=%x\n", eax
  1131.  
  1132.         test    ax, RI  ; receive interrupt
  1133.         jz      .no_rx
  1134.  
  1135.         DEBUGF  1,"Receive interrupt\n"
  1136.   .rx:
  1137.         push    ax
  1138.  
  1139.   .rx_loop:
  1140.         mov     esi, [device.cur_rx]
  1141.  
  1142.         test    [esi + mtd_desc.status], RXOWN
  1143.         jnz     .fail_rx
  1144.  
  1145.         push    .rx_complete
  1146.  
  1147.         mov     ecx, [esi + mtd_desc.status]
  1148.         shr     ecx, FLNGShift
  1149.         sub     ecx, 4                  ; we dont need CRC
  1150.         push    ecx
  1151.  
  1152. ;-------------
  1153. ; Update stats
  1154.  
  1155.         add     dword [device.bytes_rx], ecx
  1156.         adc     dword [device.bytes_rx + 4], 0
  1157.         inc     dword [device.packets_rx]
  1158.  
  1159.  
  1160.         push    [esi + mtd_desc.skbuff]
  1161.  
  1162.         jmp     EthReceiver
  1163.  
  1164.   .rx_complete:
  1165.         mov     esi, [device.cur_rx]
  1166.  
  1167.         mov     [esi + mtd_desc.control], 1536 shl RBSShift
  1168.  
  1169.         stdcall KernelAlloc, 1536
  1170.         mov     [esi + mtd_desc.skbuff], eax
  1171.         call    GetPgAddr
  1172.         mov     [esi + mtd_desc.buffer], eax
  1173.  
  1174.         mov     [esi + mtd_desc.status], RXOWN
  1175.  
  1176.         mov     eax, [esi + mtd_desc.next_desc_logical]
  1177.         mov     [device.cur_rx], eax
  1178.  
  1179.         jmp     .rx_loop
  1180. ;
  1181. ;    while( ( mtdx.cur_rx->status & RXOWN ) == 0 )
  1182. ;    {
  1183. ;        mtdx.cur_rx->status = RXOWN;
  1184. ;        mtdx.cur_rx = mtdx.cur_rx->next_desc_logical;
  1185. ;    }
  1186. ;
  1187. ;    /* Restart Rx engine if stopped. */
  1188. ;    outl(0, mtdx.ioaddr + RXPDR);
  1189.  
  1190.   .fail_rx:
  1191.         DEBUGF  1,"RX failed\n"
  1192.  
  1193.         pop     ax
  1194.   .no_rx:
  1195.  
  1196.         test    ax, TI ; transmit interrupt
  1197.         jz      .no_tx
  1198.  
  1199.         DEBUGF  1,"Transmit interrupt\n"
  1200.         push    ax
  1201.  
  1202.         lea     esi, [device.tx_desc]
  1203.         mov     ecx, NUM_TX_DESC
  1204.   .tx_loop:
  1205.  
  1206.         test    [esi + mtd_desc.status], TXOWN
  1207.         jnz     .skip_this_one
  1208.  
  1209.         mov     eax, [esi + mtd_desc.skbuff]
  1210.         test    eax, eax
  1211.         je      .skip_this_one
  1212.  
  1213.         mov     [esi + mtd_desc.skbuff], 0
  1214.  
  1215.         DEBUGF  1,"freeing buffer:%x\n", eax
  1216.         stdcall KernelFree, eax
  1217.  
  1218.   .skip_this_one:
  1219.         mov     esi, [esi + mtd_desc.next_desc_logical]
  1220.         loop    .tx_loop
  1221.  
  1222.         pop     ax
  1223.  
  1224.   .no_tx:
  1225.  
  1226.         test    ax, TBU
  1227.         jz      .no_tbu
  1228.  
  1229.         DEBUGF  1,"Transmit buffer unavailable!\n"
  1230.  
  1231.   .no_tbu:
  1232.  
  1233.   .fail:
  1234.  
  1235.         ret
  1236.  
  1237.  
  1238. ; End of code
  1239.  
  1240. align 4                                         ; Place all initialised data here
  1241.  
  1242. devices       dd 0
  1243. version       dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
  1244. my_service    db 'mtd80x',0                    ; max 16 chars include zero
  1245.  
  1246.  
  1247. ;   0x1516, 0x0800, "MTD800", "Myson MTD800"
  1248. ;   0x1516, 0x0803, "MTD803", "Surecom EP-320X"
  1249. ;   0x1516, 0x0891, "MTD891", "Myson MTD891"
  1250.  
  1251.  
  1252. include_debug_strings                           ; All data wich FDO uses will be included here
  1253.  
  1254. section '.data' data readable writable align 16 ; place all uninitialized data place here
  1255.  
  1256. device_list rd MAX_DEVICES                     ; This list contains all pointers to device structures the driver is handling
  1257.  
  1258.  
  1259.