Subversion Repositories Kolibri OS

Rev

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.         mov     ebx, eax
  453.         call    NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
  454.                                                                         ; into a device number in edi
  455.         mov     eax, edi                                                ; Application wants it in eax instead
  456.         DEBUGF  2,"Kernel says: %u\n", eax
  457.         ret
  458.  
  459. ; If an error occured, remove all allocated data and exit (returning -1 in eax)
  460.  
  461.   .destroy:
  462.         ; todo: reset device into virgin state
  463.  
  464.   .err2:
  465.         dec     [devices]
  466.   .err:
  467.         DEBUGF  2,"removing device structure\n"
  468.         stdcall KernelFree, ebx
  469.   .fail:
  470.         or      eax, -1
  471.         ret
  472.  
  473. ;------------------------------------------------------
  474. endp
  475.  
  476.  
  477. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  478. ;;                                                                        ;;
  479. ;;        Actual Hardware dependent code starts here                      ;;
  480. ;;                                                                        ;;
  481. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  482.  
  483.  
  484.  
  485. align 4
  486. unload:
  487.         ; TODO: (in this particular order)
  488.         ;
  489.         ; - Stop the device
  490.  
  491. ;    /* Disable Tx Rx*/
  492. ;    outl( mtdx.crvalue & (~TxEnable) & (~RxEnable), mtdx.ioaddr + TCRRCR );
  493. ;
  494. ;    /* Reset the chip to erase previous misconfiguration. */
  495. ;    mtd_reset(nic);
  496.  
  497.         ; - Detach int handler
  498.         ; - Remove device from local list (device_list)
  499.         ; - call unregister function in kernel
  500.         ; - Remove all allocated structures and buffers the card used
  501.  
  502.         or      eax,-1
  503.  
  504. ret
  505.  
  506.  
  507. ;-------
  508. ;
  509. ; PROBE
  510. ;
  511. ;-------
  512. align 4
  513. probe:
  514.  
  515.         DEBUGF  2,"Probing mtd80x device\n"
  516.  
  517.         make_bus_master [device.pci_bus], [device.pci_dev]
  518.  
  519.         movzx   eax, [device.pci_bus]
  520.         movzx   ecx, [device.pci_dev]
  521.         stdcall PciRead32, eax ,ecx ,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 equ 0;
  569. ;
  570. ;        for (phy equ 1; phy < 32 && phy_idx < 1; phy++) {
  571. ;            int mii_status equ mdio_read(nic, phy, 1);
  572. ;
  573. ;            if (mii_status !equ 0xffff && mii_status !equ 0x0000) {
  574. ;                mtdx.phys[phy_idx] equ 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 equ mdio_read(nic, mtdx.phys[phy_idx], 2);
  583. ;                    if (data equequ SeeqPHYID0)
  584. ;                        mtdx.PHYType equ SeeqPHY;
  585. ;                    else if (data equequ AhdocPHYID0)
  586. ;                        mtdx.PHYType equ AhdocPHY;
  587. ;                    else if (data equequ MarvellPHYID0)
  588. ;                        mtdx.PHYType equ MarvellPHY;
  589. ;                    else if (data equequ MysonPHYID0)
  590. ;                        mtdx.PHYType equ Myson981;
  591. ;                    else if (data equequ LevelOnePHYID0)
  592. ;                        mtdx.PHYType equ LevelOnePHY;
  593. ;                    else
  594. ;                        mtdx.PHYType equ OtherPHY;
  595. ;                }
  596. ;                phy_idx++;
  597. ;            }
  598. ;        }
  599. ;
  600. ;        mtdx.mii_cnt equ phy_idx;
  601. ;        if (phy_idx equequ 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 equ 0; i < DelayTime; ++i) {
  852. ;            if (mdio_read(nic, mtdx.phys[0], MII_BMSR) & BMSR_LSTATUS) {
  853. ;                mtdx.linkok equ 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 equ half duplex
  883.         test    eax, FD
  884.         jne     @f
  885.         DEBUGF  1,"full duplex\n"
  886.         inc     [device.duplexmode]     ; 2 equ full duplex
  887.        @@:
  888.  
  889.         mov     [device.line_speed], 1  ; 1 equ 10M
  890.         test    eax, PS10
  891.         jne     @f
  892.         DEBUGF  1,"100mbit\n"
  893.         inc     [device.line_speed]     ; 2 equ 100M
  894.        @@:
  895.  
  896.         ret
  897.  
  898.   .no_myson_phy:
  899.  
  900.         DEBUGF  1,"no myson phy\n"
  901.  
  902. ;        if (mtdx.PHYType equequ SeeqPHY) { /* this PHY is SEEQ 80225 */
  903. ;            unsigned int data;
  904. ;
  905. ;            data equ mdio_read(dev, mtdx.phys[0], MIIRegister18);
  906. ;            if (data & SPD_DET_100)
  907. ;                mtdx.line_speed equ 2; /* 100M */
  908. ;            else
  909. ;                mtdx.line_speed equ 1; /* 10M */
  910. ;            if (data & DPLX_DET_FULL)
  911. ;                mtdx.duplexmode equ 2; /* full duplex mode */
  912. ;            else
  913. ;                mtdx.duplexmode equ 1; /* half duplex mode */
  914. ;        } else if (mtdx.PHYType equequ AhdocPHY) {
  915. ;            unsigned int data;
  916. ;
  917. ;            data equ mdio_read(dev, mtdx.phys[0], DiagnosticReg);
  918. ;            if (data & Speed_100)
  919. ;                mtdx.line_speed equ 2; /* 100M */
  920. ;            else
  921. ;                mtdx.line_speed equ 1; /* 10M */
  922. ;            if (data & DPLX_FULL)
  923. ;                mtdx.duplexmode equ 2; /* full duplex mode */
  924. ;            else
  925. ;                mtdx.duplexmode equ 1; /* half duplex mode */
  926. ;        }
  927. ;        else if (mtdx.PHYType equequ MarvellPHY) {
  928. ;            unsigned int data;
  929. ;
  930. ;            data equ mdio_read(dev, mtdx.phys[0], SpecificReg);
  931. ;            if (data & Full_Duplex)
  932. ;                mtdx.duplexmode equ 2; /* full duplex mode */
  933. ;            else
  934. ;                mtdx.duplexmode equ 1; /* half duplex mode */
  935. ;            data &equ SpeedMask;
  936. ;            if (data equequ Speed_1000M)
  937. ;                mtdx.line_speed equ 3; /* 1000M */
  938. ;            else if (data equequ Speed_100M)
  939. ;                mtdx.line_speed equ 2; /* 100M */
  940. ;            else
  941. ;                mtdx.line_speed equ 1; /* 10M */
  942. ;        }
  943. ;        else if (mtdx.PHYType equequ Myson981) {
  944. ;            unsigned int data;
  945. ;
  946. ;            data equ mdio_read(dev, mtdx.phys[0], StatusRegister);
  947. ;
  948. ;            if (data & SPEED100)
  949. ;                mtdx.line_speed equ 2;
  950. ;            else
  951. ;                mtdx.line_speed equ 1;
  952. ;
  953. ;            if (data & FULLMODE)
  954. ;                mtdx.duplexmode equ 2;
  955. ;            else
  956. ;                mtdx.duplexmode equ 1;
  957. ;        }
  958. ;        else if (mtdx.PHYType equequ LevelOnePHY) {
  959. ;            unsigned int data;
  960. ;
  961. ;            data equ mdio_read(dev, mtdx.phys[0], SpecificReg);
  962. ;            if (data & LXT1000_Full)
  963. ;                mtdx.duplexmode equ 2; /* full duplex mode */
  964. ;            else
  965. ;                mtdx.duplexmode equ 1; /* half duplex mode */
  966. ;            data &equ SpeedMask;
  967. ;            if (data equequ LXT1000_1000M)
  968. ;                mtdx.line_speed equ 3; /* 1000M */
  969. ;            else if (data equequ LXT1000_100M)
  970. ;                mtdx.line_speed equ 2; /* 100M */
  971. ;            else
  972.  ;               mtdx.line_speed equ 1; /* 10M */
  973.   ;      }
  974.  
  975. ;        // chage crvalue
  976. ;        // mtdx.crvalue&equ(~PS10)&(~FD);
  977. ;        mtdx.crvalue &equ (~PS10) & (~FD) & (~PS1000);
  978. ;        if (mtdx.line_speed equequ 1)
  979. ;            mtdx.crvalue |equ PS10;
  980. ;        else if (mtdx.line_speed equequ 3)
  981. ;            mtdx.crvalue |equ PS1000;
  982. ;        if (mtdx.duplexmode equequ 2)
  983. ;            mtdx.crvalue |equ 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,"\nIRQ %x\n",eax:2                       ; no, you cant replace 'eax:2' with 'al', this must be a bug in FDO
  1104.  
  1105. ; find pointer of device wich made IRQ occur
  1106.  
  1107.         mov     ecx, [devices]
  1108.         test    ecx, ecx
  1109.         jz      .fail
  1110.         mov     esi, device_list
  1111.   .nextdevice:
  1112.         mov     ebx, dword [esi]
  1113.  
  1114.         set_io  0
  1115.         set_io  ISR
  1116.         in      eax, dx
  1117.         out     dx , eax                                ; send it back to ACK
  1118.  ;       and     eax,  ; int mask
  1119.         test    eax, eax
  1120.         jnz     .got_it
  1121.  
  1122.   .continue:
  1123.         add     esi, 4
  1124.         dec     ecx
  1125.         jnz     .nextdevice
  1126.  
  1127.         ret                                             ; If no device was found, abort (The irq was probably for a device, not registered to this driver)
  1128.  
  1129.   .got_it:
  1130.  
  1131.         DEBUGF  1,"Status=%x\n", eax
  1132.  
  1133.         test    ax, RI  ; receive interrupt
  1134.         jz      .no_rx
  1135.  
  1136.         DEBUGF  1,"Receive interrupt\n"
  1137.   .rx:
  1138.         push    ax
  1139.  
  1140.   .rx_loop:
  1141.         mov     esi, [device.cur_rx]
  1142.  
  1143.         test    [esi + mtd_desc.status], RXOWN
  1144.         jnz     .fail_rx
  1145.  
  1146.         push    .rx_complete
  1147.  
  1148.         mov     ecx, [esi + mtd_desc.status]
  1149.         shr     ecx, FLNGShift
  1150.         sub     ecx, 4                  ; we dont need CRC
  1151.         push    ecx
  1152.  
  1153. ;-------------
  1154. ; Update stats
  1155.  
  1156.         add     dword [device.bytes_rx], ecx
  1157.         adc     dword [device.bytes_rx + 4], 0
  1158.         inc     dword [device.packets_rx]
  1159.  
  1160.  
  1161.         push    [esi + mtd_desc.skbuff]
  1162.  
  1163.         jmp     EthReceiver
  1164.  
  1165.   .rx_complete:
  1166.         mov     esi, [device.cur_rx]
  1167.  
  1168.         mov     [esi + mtd_desc.control], 1536 shl RBSShift
  1169.  
  1170.         stdcall KernelAlloc, 1536
  1171.         mov     [esi + mtd_desc.skbuff], eax
  1172.         call    GetPgAddr
  1173.         mov     [esi + mtd_desc.buffer], eax
  1174.  
  1175.         mov     [esi + mtd_desc.status], RXOWN
  1176.  
  1177.         mov     eax, [esi + mtd_desc.next_desc_logical]
  1178.         mov     [device.cur_rx], eax
  1179.  
  1180.         jmp     .rx_loop
  1181. ;
  1182. ;    while( ( mtdx.cur_rx->status & RXOWN ) == 0 )
  1183. ;    {
  1184. ;        mtdx.cur_rx->status = RXOWN;
  1185. ;        mtdx.cur_rx = mtdx.cur_rx->next_desc_logical;
  1186. ;    }
  1187. ;
  1188. ;    /* Restart Rx engine if stopped. */
  1189. ;    outl(0, mtdx.ioaddr + RXPDR);
  1190.  
  1191.   .fail_rx:
  1192.         DEBUGF  1,"RX failed\n"
  1193.  
  1194.         pop     ax
  1195.   .no_rx:
  1196.  
  1197.         test    ax, TI ; transmit interrupt
  1198.         jz      .no_tx
  1199.  
  1200.         DEBUGF  1,"Transmit interrupt\n"
  1201.         push    ax
  1202.  
  1203.         lea     esi, [device.tx_desc]
  1204.         mov     ecx, NUM_TX_DESC
  1205.   .tx_loop:
  1206.  
  1207.         test    [esi + mtd_desc.status], TXOWN
  1208.         jnz     .skip_this_one
  1209.  
  1210.         mov     eax, [esi + mtd_desc.skbuff]
  1211.         test    eax, eax
  1212.         je      .skip_this_one
  1213.  
  1214.         mov     [esi + mtd_desc.skbuff], 0
  1215.  
  1216.         DEBUGF  1,"freeing buffer:%x\n", eax
  1217.         stdcall KernelFree, eax
  1218.  
  1219.   .skip_this_one:
  1220.         mov     esi, [esi + mtd_desc.next_desc_logical]
  1221.         loop    .tx_loop
  1222.  
  1223.         pop     ax
  1224.  
  1225.   .no_tx:
  1226.  
  1227.         test    ax, TBU
  1228.         jz      .no_tbu
  1229.  
  1230.         DEBUGF  1,"Transmit buffer unavailable!\n"
  1231.  
  1232.   .no_tbu:
  1233.  
  1234.   .fail:
  1235.  
  1236.         ret
  1237.  
  1238.  
  1239. ; End of code
  1240.  
  1241. align 4                                         ; Place all initialised data here
  1242.  
  1243. devices       dd 0
  1244. version       dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
  1245. my_service    db 'mtd80x',0                    ; max 16 chars include zero
  1246.  
  1247.  
  1248. ;   0x1516, 0x0800, "MTD800", "Myson MTD800"
  1249. ;   0x1516, 0x0803, "MTD803", "Surecom EP-320X"
  1250. ;   0x1516, 0x0891, "MTD891", "Myson MTD891"
  1251.  
  1252.  
  1253. include_debug_strings                           ; All data wich FDO uses will be included here
  1254.  
  1255. section '.data' data readable writable align 16 ; place all uninitialized data place here
  1256.  
  1257. device_list rd MAX_DEVICES                     ; This list contains all pointers to device structures the driver is handling
  1258.  
  1259.  
  1260.