Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2004-2014. All rights reserved.    ;;
  4. ;; Distributed under terms of the GNU General Public License       ;;
  5. ;;                                                                 ;;
  6. ;;  MTD80x driver for KolibriOS                                    ;;
  7. ;;                                                                 ;;
  8. ;;  Based on mtd80x.c from the etherboot project                   ;;
  9. ;;                                                                 ;;
  10. ;;  Written by hidnplayr@kolibrios.org                             ;;
  11. ;;                                                                 ;;
  12. ;;          GNU GENERAL PUBLIC LICENSE                             ;;
  13. ;;             Version 2, June 1991                                ;;
  14. ;;                                                                 ;;
  15. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  16.  
  17. format PE DLL native
  18. entry START
  19.  
  20.         CURRENT_API             = 0x0200
  21.         COMPATIBLE_API          = 0x0100
  22.         API_VERSION             = (COMPATIBLE_API shl 16) + CURRENT_API
  23.  
  24.         MAX_DEVICES             = 16
  25.  
  26.         DEBUG                   = 1
  27.         __DEBUG__               = 1
  28.         __DEBUG_LEVEL__         = 2
  29.  
  30.         NUM_TX_DESC             = 6
  31.         NUM_RX_DESC             = 12
  32.  
  33. section '.flat' readable writable executable
  34.  
  35. include '../proc32.inc'
  36. include '../struct.inc'
  37. include '../macros.inc'
  38. include '../fdo.inc'
  39. include '../netdrv_pe.inc'
  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. struct  descriptor
  251.         status                  dd ?
  252.         control                 dd ?
  253.         buffer                  dd ?
  254.         next_desc               dd ?
  255.  
  256.         next_desc_logical       dd ?
  257.         skbuff                  dd ?
  258.         reserved1               dd ?
  259.         reserved2               dd ?
  260. ends
  261.  
  262.  
  263. struct  device          ETH_DEVICE
  264.  
  265.         io_addr         dd ?
  266.         pci_bus         dd ?
  267.         pci_dev         dd ?
  268.         irq_line        db ?
  269.         dev_id          dw ?
  270.         flags           dd ?
  271.         crvalue         dd ?
  272.         bcrvalue        dd ?
  273.         cur_rx          dd ?
  274.         cur_tx          dd ?
  275.         default_port    dd ?
  276.         PHYType         dd ?
  277.  
  278. ; MII transceiver section.
  279.         mii_cnt         dd ?    ; MII device addresses.
  280.         phys            db ?    ; MII device addresses.
  281.  
  282. ; descriptors
  283.         rb 0x100 - ($ and 0xff) ; align 256
  284.         tx_desc         rb NUM_TX_DESC*sizeof.descriptor
  285.         rx_desc         rb NUM_RX_DESC*sizeof.descriptor
  286.  
  287. ends
  288.  
  289.  
  290. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  291. ;;                        ;;
  292. ;; proc START             ;;
  293. ;;                        ;;
  294. ;; (standard driver proc) ;;
  295. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  296.  
  297. proc START c, reason:dword, cmdline:dword
  298.  
  299.         cmp     [reason], DRV_ENTRY
  300.         jne     .fail
  301.  
  302.         DEBUGF  1,"Loading driver\n"
  303.         invoke  RegService, my_service, service_proc
  304.         ret
  305.  
  306.   .fail:
  307.         xor     eax, eax
  308.         ret
  309.  
  310. endp
  311.  
  312.  
  313. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  314. ;;                        ;;
  315. ;; proc SERVICE_PROC      ;;
  316. ;;                        ;;
  317. ;; (standard driver proc) ;;
  318. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  319.  
  320. proc service_proc stdcall, ioctl:dword
  321.  
  322.         mov     edx, [ioctl]
  323.         mov     eax, [edx + IOCTL.io_code]
  324.  
  325. ;------------------------------------------------------
  326.  
  327.         cmp     eax, 0 ;SRV_GETVERSION
  328.         jne     @F
  329.  
  330.         cmp     [edx + IOCTL.out_size], 4
  331.         jb      .fail
  332.         mov     eax, [edx + IOCTL.output]
  333.         mov     [eax], dword API_VERSION
  334.  
  335.         xor     eax, eax
  336.         ret
  337.  
  338. ;------------------------------------------------------
  339.   @@:
  340.         cmp     eax, 1 ;SRV_HOOK
  341.         jne     .fail
  342.  
  343.         cmp     [edx + IOCTL.inp_size], 3               ; Data input must be at least 3 bytes
  344.         jb      .fail
  345.  
  346.         mov     eax, [edx + IOCTL.input]
  347.         cmp     byte [eax], 1                           ; 1 means device number and bus number (pci) are given
  348.         jne     .fail                                   ; other types arent supported for this card yet
  349.  
  350. ; check if the device is already listed
  351.  
  352.         mov     esi, device_list
  353.         mov     ecx, [devices]
  354.         test    ecx, ecx
  355.         jz      .firstdevice
  356.  
  357. ;        mov     eax, [edx + IOCTL.input]                ; get the pci bus and device numbers
  358.         mov     ax, [eax+1]                             ;
  359.   .nextdevice:
  360.         mov     ebx, [esi]
  361.         cmp     al, byte[ebx + device.pci_bus]
  362.         jne     @f
  363.         cmp     ah, byte[ebx + device.pci_dev]
  364.         je      .find_devicenum                         ; Device is already loaded, let's find it's device number
  365.        @@:
  366.         add     esi, 4
  367.         loop    .nextdevice
  368.  
  369.  
  370. ; This device doesnt have its own eth_device structure yet, lets create one
  371.   .firstdevice:
  372.         cmp     [devices], MAX_DEVICES                  ; First check if the driver can handle one more card
  373.         jae     .fail
  374.  
  375.         allocate_and_clear ebx, sizeof.device, .fail
  376.  
  377. ; Fill in the direct call addresses into the struct
  378.  
  379.         mov     [ebx + device.reset], reset
  380.         mov     [ebx + device.transmit], transmit
  381.         mov     [ebx + device.unload], unload
  382.         mov     [ebx + device.name], my_service
  383.  
  384. ; save the pci bus and device numbers
  385.  
  386.         mov     eax, [edx + IOCTL.input]
  387.         movzx   ecx, byte[eax+1]
  388.         mov     [ebx + device.pci_bus], ecx
  389.         movzx   ecx, byte[eax+2]
  390.         mov     [ebx + device.pci_dev], ecx
  391.  
  392. ; Now, it's time to find the base io addres of the PCI device
  393.  
  394.         stdcall PCI_find_io, [ebx + device.pci_bus], [ebx + device.pci_dev]
  395.         mov     [ebx + device.io_addr], eax
  396.  
  397. ; We've found the io address, find IRQ now
  398.  
  399.         invoke  PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.interrupt_line
  400.         mov     [ebx + device.irq_line], al
  401.  
  402.         DEBUGF  1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
  403.         [ebx + device.pci_dev]:1,[ebx + device.pci_bus]:1,[ebx + device.irq_line]:1,[ebx + device.io_addr]:8
  404.  
  405. ; Ok, the eth_device structure is ready, let's probe the device
  406. ; Because initialization fires IRQ, IRQ handler must be aware of this device
  407.         mov     eax, [devices]                                          ; Add the device structure to our device list
  408.         mov     [device_list+4*eax], ebx                                ; (IRQ handler uses this list to find device)
  409.         inc     [devices]                                               ;
  410.  
  411.         call    probe                                                   ; this function will output in eax
  412.         test    eax, eax
  413.         jnz     .err2                                                   ; If an error occured, exit
  414.  
  415.         mov     [ebx + device.type], NET_TYPE_ETH
  416.         invoke  NetRegDev
  417.  
  418.         cmp     eax, -1
  419.         je      .destroy
  420.  
  421.         ret
  422.  
  423. ; If the device was already loaded, find the device number and return it in eax
  424.  
  425.   .find_devicenum:
  426.         DEBUGF  2,"Trying to find device number of already registered device\n"
  427.         invoke  NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
  428.                                                                         ; into a device number in edi
  429.         mov     eax, edi                                                ; Application wants it in eax instead
  430.         DEBUGF  2,"Kernel says: %u\n", eax
  431.         ret
  432.  
  433. ; If an error occured, remove all allocated data and exit (returning -1 in eax)
  434.  
  435.   .destroy:
  436.         ; todo: reset device into virgin state
  437.  
  438.   .err2:
  439.         dec     [devices]
  440.   .err:
  441.         DEBUGF  2,"removing device structure\n"
  442.         invoke  KernelFree, ebx
  443.   .fail:
  444.         or      eax, -1
  445.         ret
  446.  
  447. ;------------------------------------------------------
  448. endp
  449.  
  450.  
  451. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  452. ;;                                                                        ;;
  453. ;;        Actual Hardware dependent code starts here                      ;;
  454. ;;                                                                        ;;
  455. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  456.  
  457.  
  458.  
  459. align 4
  460. unload:
  461.         ; TODO: (in this particular order)
  462.         ;
  463.         ; - Stop the device
  464.  
  465. ;    /* Disable Tx Rx*/
  466. ;    outl( mtdx.crvalue & (~TxEnable) & (~RxEnable), mtdx.ioaddr + TCRRCR );
  467. ;
  468. ;    /* Reset the chip to erase previous misconfiguration. */
  469. ;    mtd_reset(nic);
  470.  
  471.         ; - Detach int handler
  472.         ; - Remove device from local list (device_list)
  473.         ; - call unregister function in kernel
  474.         ; - Remove all allocated structures and buffers the card used
  475.  
  476.         or      eax, -1
  477.  
  478. ret
  479.  
  480.  
  481. ;-------
  482. ;
  483. ; PROBE
  484. ;
  485. ;-------
  486. align 4
  487. probe:
  488.  
  489.         DEBUGF  1,"Probing\n"
  490.  
  491. ; Make the device a bus master
  492.         invoke  PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command
  493.         or      al, PCI_CMD_MASTER
  494.         invoke  PciWrite32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command, eax
  495.  
  496. ; Check vendor/device id's
  497.         invoke PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], 0
  498.         cmp     ax, 0x1516
  499.         jne     .notfound
  500.         shr     eax, 16
  501.         mov     [ebx + device.dev_id], ax
  502.         cmp     ax, 0x0800
  503.         je      .mtd800
  504.         cmp     ax, 0x0803
  505.         je      .mtd803
  506.         cmp     ax, 0x0891
  507.         je      .mtd891
  508.  
  509.   .notfound:
  510.         DEBUGF  2,"Device not supported!\n"
  511.         xor     eax, eax
  512.         dec     eax
  513.         ret
  514.  
  515.   .mtd803:
  516.         mov     [ebx + device.name], sz_mtd803
  517.         DEBUGF  1,"Device has chip xcvr\n"
  518.         jmp     .xcvr_set
  519.  
  520.   .mtd800:
  521.         DEBUGF  1,"Device has mii xcvr\n"
  522.         mov     [ebx + device.name], sz_mtd800
  523.         jmp     .xcvr_set
  524.  
  525.   .mtd891:
  526.         DEBUGF  1,"Device has mii xcvr\n"
  527.         mov     [ebx + device.name], sz_mtd800
  528.  
  529.   .xcvr_set:
  530.         call    read_mac
  531.  
  532. ; Reset the chip to erase previous misconfiguration.
  533.         set_io  [ebx + device.io_addr], 0
  534.         set_io  [ebx + device.io_addr], BCR
  535.         xor     eax, eax
  536.         inc     eax
  537.         out     dx, eax
  538.  
  539. ; find the connected MII xcvrs
  540.         cmp     [ebx + device.dev_id], 0x0803
  541.         je      .is_803
  542.  
  543. ;        int     phy, phy_idx =   0;
  544. ;
  545. ;        for (phy =   1; phy < 32 && phy_idx < 1; phy++) {
  546. ;            int mii_status =   mdio_read(nic, phy, 1);
  547. ;
  548. ;            if (mii_status !=   0xffff && mii_status !=   0x0000) {
  549. ;                mtdx.phys[phy_idx] =   phy;
  550. ;
  551. ;                DBG ( "%s: MII PHY found at address %d, status "
  552. ;                      "0x%4.4x.\n", mtdx.nic_name, phy, mii_status );
  553. ;                /* get phy type */
  554. ;                {
  555. ;                    unsigned int data;
  556. ;
  557. ;                    data =   mdio_read(nic, mtdx.phys[phy_idx], 2);
  558. ;                    if (data equ=   SeeqPHYID0)
  559. ;                        mtdx.PHYType =   SeeqPHY;
  560. ;                    else if (data equ=   AhdocPHYID0)
  561. ;                        mtdx.PHYType =   AhdocPHY;
  562. ;                    else if (data equ=   MarvellPHYID0)
  563. ;                        mtdx.PHYType =   MarvellPHY;
  564. ;                    else if (data equ=   MysonPHYID0)
  565. ;                        mtdx.PHYType =   Myson981;
  566. ;                    else if (data equ=   LevelOnePHYID0)
  567. ;                        mtdx.PHYType =   LevelOnePHY;
  568. ;                    else
  569. ;                        mtdx.PHYType =   OtherPHY;
  570. ;                }
  571. ;                phy_idx++;
  572. ;            }
  573. ;        }
  574. ;
  575. ;        mtdx.mii_cnt =   phy_idx;
  576. ;        if (phy_idx equ=   0) {
  577. ;            printf("%s: MII PHY not found -- this device may "
  578. ;                   "not operate correctly.\n", mtdx.nic_name);
  579. ;        }
  580.  
  581.         jmp     .no_803
  582.  
  583.   .is_803:
  584.         mov     [ebx + device.phys], 32
  585.  
  586. ; get phy type
  587.         set_io  [ebx + device.io_addr], 0
  588.         set_io  [ebx + device.io_addr], PHYIDENTIFIER
  589.         in      eax, dx
  590.  
  591.         cmp     eax, MysonPHYID
  592.         jne     @f
  593.         mov     [ebx + device.PHYType], MysonPHY
  594.         DEBUGF  1,"Myson PHY\n"
  595.         jmp     .no_803
  596.        @@:
  597.  
  598.         mov     [ebx + device.PHYType], OtherPHY
  599.         DEBUGF  1,"Other PHY\n"
  600.   .no_803:
  601.  
  602. ;-------
  603. ;
  604. ; RESET
  605. ;
  606. ;-------
  607. align 4
  608. reset:
  609.  
  610.         DEBUGF  1,"Resetting\n"
  611.  
  612. ; attach irq handler
  613.         movzx   eax, [ebx + device.irq_line]
  614.         DEBUGF  1,"Attaching int handler to irq %x\n", eax:1
  615.         invoke  AttachIntHandler, eax, int_handler, ebx
  616.         test    eax, eax
  617.         jnz     @f
  618.         DEBUGF  2,"Could not attach int handler!\n"
  619.         or      eax, -1
  620.         ret
  621.   @@:
  622.  
  623. ; Reset the chip to erase previous misconfiguration.
  624.         set_io  [ebx + device.io_addr], 0
  625.         set_io  [ebx + device.io_addr], BCR
  626.         xor     eax, eax
  627.         inc     eax
  628.         out     dx, eax
  629.  
  630.         call    init_ring
  631.  
  632. ; Initialize other registers.
  633. ; Configure the PCI bus bursts and FIFO thresholds.
  634.         mov     [ebx + device.bcrvalue], 0x10         ; little-endian, 8 burst length
  635.         mov     [ebx + device.crvalue], 0xa00         ; 128 burst length
  636.  
  637.         cmp     [ebx + device.dev_id], 0x891
  638.         jne     @f
  639.         or      [ebx + device.bcrvalue], 0x200       ; set PROG bit
  640.         or      [ebx + device.crvalue], 0x02000000   ; set enhanced bit
  641.        @@:
  642.         or      [ebx + device.crvalue], RxEnable + TxThreshold + TxEnable
  643.  
  644.         call    set_rx_mode
  645.  
  646.         set_io  [ebx + device.io_addr], 0
  647.         set_io  [ebx + device.io_addr], BCR
  648.         mov     eax, [ebx + device.bcrvalue]
  649.         out     dx, eax
  650.  
  651.         set_io  [ebx + device.io_addr], TCRRCR
  652.         mov     eax, [ebx + device.crvalue]
  653.         out     dx, eax
  654.  
  655.         call    getlinkstatus
  656.  
  657. ; Restart Rx engine if stopped.
  658.         set_io  [ebx + device.io_addr], 0
  659.         set_io  [ebx + device.io_addr], RXPDR
  660.         xor     eax, eax
  661.         out     dx, eax
  662.  
  663. ; Enable interrupts
  664.         set_io  [ebx + device.io_addr], ISR
  665.         mov     eax, FBE or TUNF or CNTOVF or RBU or TI or RI
  666.         out     dx, eax
  667.         set_io  [ebx + device.io_addr], IMR
  668.         out     dx, eax
  669.  
  670. ; clear packet/byte counters
  671.         xor     eax, eax
  672.         lea     edi, [ebx + device.bytes_tx]
  673.         mov     ecx, 6
  674.         rep     stosd
  675.  
  676.         mov     [ebx + device.mtu], 1514
  677.         xor     eax, eax
  678.         ret
  679.  
  680.  
  681.  
  682.  
  683. align 4
  684. init_ring:
  685.  
  686.         DEBUGF  1,"initializing rx and tx ring\n"
  687.  
  688. ; Initialize all Rx descriptors
  689.         lea     esi, [ebx + device.rx_desc]
  690.         mov     [ebx + device.cur_rx], esi
  691.         mov     ecx, NUM_RX_DESC
  692.   .rx_desc_loop:
  693.         mov     [esi + descriptor.status], RXOWN
  694.         mov     [esi + descriptor.control], 1536 shl RBSShift
  695.  
  696.         lea     eax, [esi + sizeof.descriptor]
  697.         mov     [esi + descriptor.next_desc_logical], eax
  698.         push    ecx esi
  699.         invoke  GetPhysAddr
  700.         mov     [esi + descriptor.next_desc], eax
  701.  
  702.         invoke  KernelAlloc, 1536
  703.         pop     esi
  704.         push    esi
  705.         mov     [esi + descriptor.skbuff], eax
  706.         invoke  GetPgAddr
  707.         pop     esi ecx
  708.         mov     [esi + descriptor.buffer], eax
  709.  
  710.         add     esi, sizeof.descriptor
  711.         loop    .rx_desc_loop
  712.  
  713. ; Mark the last entry as wrapping the ring.
  714.         lea     eax, [ebx + device.rx_desc]
  715.         mov     [esi - sizeof.descriptor + descriptor.next_desc_logical], eax
  716.         push    esi
  717.         invoke  GetPhysAddr
  718.         pop     esi
  719.         mov     [esi - sizeof.descriptor + descriptor.next_desc], eax
  720.  
  721.         set_io  [ebx + device.io_addr],   0
  722.         set_io  [ebx + device.io_addr],   RXLBA
  723.         out     dx, eax
  724.  
  725. ; Initialize all Tx descriptors
  726.         lea     esi, [ebx + device.tx_desc]
  727.         mov     [ebx + device.cur_tx], esi
  728.         mov     ecx, NUM_TX_DESC
  729.   .tx_desc_loop:
  730.         mov     [esi + descriptor.status], 0
  731.  
  732.         lea     eax, [esi + sizeof.descriptor]
  733.         mov     [esi + descriptor.next_desc_logical], eax
  734.         push    ecx esi
  735.         invoke  GetPhysAddr
  736.         pop     esi ecx
  737.         mov     [esi + descriptor.next_desc], eax
  738.         mov     [esi + descriptor.skbuff], 0
  739.         add     esi, sizeof.descriptor
  740.         loop    .tx_desc_loop
  741.  
  742. ; Mark the last entry as wrapping the ring.
  743.         lea     eax, [ebx + device.tx_desc]
  744.         mov     [esi - sizeof.descriptor + descriptor.next_desc_logical], eax
  745.         push    esi
  746.         invoke  GetPhysAddr
  747.         pop     esi
  748.         mov     [esi - sizeof.descriptor + descriptor.next_desc], eax
  749.  
  750.         set_io  [ebx + device.io_addr],   0
  751.         set_io  [ebx + device.io_addr],   TXLBA
  752.         out     dx, eax
  753.  
  754.         ret
  755.  
  756.  
  757. align 4
  758. set_rx_mode:
  759.  
  760.         DEBUGF  1,"Setting RX mode\n"
  761.  
  762. ; Too many to match, or accept all multicasts.
  763.         set_io  [ebx + device.io_addr], 0
  764.         set_io  [ebx + device.io_addr], MAR0
  765.         xor     eax, eax
  766.         not     eax
  767.         out     dx, eax
  768.         set_io  [ebx + device.io_addr], MAR1
  769.         out     dx, eax
  770.  
  771.         and     [ebx + device.crvalue], not (RxModeMask)
  772.         or      [ebx + device.crvalue], AcceptBroadcast + AcceptMulticast + AcceptMyPhys
  773.  
  774.         ret
  775.  
  776.  
  777. align 4
  778. getlinkstatus:
  779.  
  780.         DEBUGF  1,"Getting link status\n"
  781.  
  782.         mov     [ebx + device.state], ETH_LINK_DOWN     ; assume link is dead
  783.  
  784.         cmp     [ebx + device.PHYType], MysonPHY
  785.         jne     .no_myson_phy
  786.         set_io  [ebx + device.io_addr], 0
  787.         set_io  [ebx + device.io_addr], BMCRSR
  788.         in      eax, dx
  789.         test    eax, LinkIsUp2
  790.         jnz     getlinktype
  791.         ret
  792.  
  793.   .no_myson_phy:
  794.         set_io  [ebx + device.io_addr], 0
  795.         set_io  [ebx + device.io_addr], BMCRSR
  796.         in      eax, dx
  797.         test    eax, LinkIsUp
  798.         jnz     getlinktype
  799.         ret
  800.  
  801. getlinktype:
  802.  
  803.         DEBUGF  1,"Getting link type\n"
  804.         cmp     [ebx + device.PHYType], MysonPHY
  805.         jne     .no_myson_phy
  806.  
  807.         DEBUGF  1,"myson PHY\n"
  808.         set_io  [ebx + device.io_addr], 0
  809.         set_io  [ebx + device.io_addr], TCRRCR
  810.         in      eax, dx
  811.         test    eax, FD
  812.         jz      @f
  813.         DEBUGF  1,"full duplex\n"
  814.         or      [ebx + device.state], ETH_LINK_FD
  815.        @@:
  816.         test    eax, PS10
  817.         jnz     @f
  818.         DEBUGF  1,"100mbit\n"
  819.         or      [ebx + device.state], ETH_LINK_100M
  820.         ret
  821.        @@:
  822.         DEBUGF  1,"10mbit\n"
  823.         or      [ebx + device.state], ETH_LINK_10M
  824.         ret
  825.  
  826.   .no_myson_phy:
  827.         DEBUGF  1,"not a myson PHY\n"
  828.         mov     [ebx + device.state], ETH_LINK_UNKNOWN
  829.  
  830. ;        if (mtdx.PHYType equ=   SeeqPHY) { /* this PHY is SEEQ 80225 */
  831. ;            unsigned int data;
  832. ;
  833. ;            data =   mdio_read(dev, mtdx.phys[0], MIIRegister18);
  834. ;            if (data & SPD_DET_100)
  835. ;                mtdx.line_speed =   2; /* 100M */
  836. ;            else
  837. ;                mtdx.line_speed =   1; /* 10M */
  838. ;            if (data & DPLX_DET_FULL)
  839. ;                mtdx.duplexmode =   2; /* full duplex mode */
  840. ;            else
  841. ;                mtdx.duplexmode =   1; /* half duplex mode */
  842. ;        } else if (mtdx.PHYType equ=   AhdocPHY) {
  843. ;            unsigned int data;
  844. ;
  845. ;            data =   mdio_read(dev, mtdx.phys[0], DiagnosticReg);
  846. ;            if (data & Speed_100)
  847. ;                mtdx.line_speed =   2; /* 100M */
  848. ;            else
  849. ;                mtdx.line_speed =   1; /* 10M */
  850. ;            if (data & DPLX_FULL)
  851. ;                mtdx.duplexmode =   2; /* full duplex mode */
  852. ;            else
  853. ;                mtdx.duplexmode =   1; /* half duplex mode */
  854. ;        }
  855. ;        else if (mtdx.PHYType equ=   MarvellPHY) {
  856. ;            unsigned int data;
  857. ;
  858. ;            data =   mdio_read(dev, mtdx.phys[0], SpecificReg);
  859. ;            if (data & Full_Duplex)
  860. ;                mtdx.duplexmode =   2; /* full duplex mode */
  861. ;            else
  862. ;                mtdx.duplexmode =   1; /* half duplex mode */
  863. ;            data &=   SpeedMask;
  864. ;            if (data equ=   Speed_1000M)
  865. ;                mtdx.line_speed =   3; /* 1000M */
  866. ;            else if (data equ=   Speed_100M)
  867. ;                mtdx.line_speed =   2; /* 100M */
  868. ;            else
  869. ;                mtdx.line_speed =   1; /* 10M */
  870. ;        }
  871. ;        else if (mtdx.PHYType equ=   Myson981) {
  872. ;            unsigned int data;
  873. ;
  874. ;            data =   mdio_read(dev, mtdx.phys[0], StatusRegister);
  875. ;
  876. ;            if (data & SPEED100)
  877. ;                mtdx.line_speed =   2;
  878. ;            else
  879. ;                mtdx.line_speed =   1;
  880. ;
  881. ;            if (data & FULLMODE)
  882. ;                mtdx.duplexmode =   2;
  883. ;            else
  884. ;                mtdx.duplexmode =   1;
  885. ;        }
  886. ;        else if (mtdx.PHYType equ=   LevelOnePHY) {
  887. ;            unsigned int data;
  888. ;
  889. ;            data =   mdio_read(dev, mtdx.phys[0], SpecificReg);
  890. ;            if (data & LXT1000_Full)
  891. ;                mtdx.duplexmode =   2; /* full duplex mode */
  892. ;            else
  893. ;                mtdx.duplexmode =   1; /* half duplex mode */
  894. ;            data &=   SpeedMask;
  895. ;            if (data equ=   LXT1000_1000M)
  896. ;                mtdx.line_speed =   3; /* 1000M */
  897. ;            else if (data equ=   LXT1000_100M)
  898. ;                mtdx.line_speed =   2; /* 100M */
  899. ;            else
  900.  ;               mtdx.line_speed =   1; /* 10M */
  901.   ;      }
  902.  
  903. ;        // chage crvalue
  904. ;        // mtdx.crvalue&equ(~PS10)&(~FD);
  905. ;        mtdx.crvalue &=   (~PS10) & (~FD) & (~PS1000);
  906. ;        if (mtdx.line_speed equ=   1)
  907. ;            mtdx.crvalue |=   PS10;
  908. ;        else if (mtdx.line_speed equ=   3)
  909. ;            mtdx.crvalue |=   PS1000;
  910. ;        if (mtdx.duplexmode equ=   2)
  911. ;            mtdx.crvalue |=   FD;
  912.  
  913.         ret
  914.  
  915.  
  916.  
  917.  
  918. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  919. ;;                                         ;;
  920. ;; Transmit                                ;;
  921. ;;                                         ;;
  922. ;; In: buffer pointer in [esp+4]           ;;
  923. ;;     size of buffer in [esp+8]           ;;
  924. ;;     pointer to device structure in ebx  ;;
  925. ;;                                         ;;
  926. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  927.  
  928. proc transmit stdcall bufferptr, buffersize
  929.  
  930.         pushf
  931.         cli
  932.  
  933.         DEBUGF  1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [buffersize]
  934.         mov     eax, [bufferptr]
  935.         DEBUGF  1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
  936.         [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
  937.         [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
  938.         [eax+13]:2,[eax+12]:2
  939.  
  940.         cmp     [buffersize], 1514
  941.         ja      .fail
  942.         cmp     [buffersize], 60
  943.         jb      .fail
  944.  
  945.         mov     esi, [ebx + device.cur_tx]
  946.  
  947.         test    [esi + descriptor.status], TXOWN
  948.         jnz     .fail
  949.  
  950.         push    [esi + descriptor.next_desc_logical]
  951.         pop     [ebx + device.cur_tx]
  952.  
  953.         mov     eax, [bufferptr]
  954.         mov     [esi + descriptor.skbuff], eax
  955.         invoke  GetPhysAddr
  956.         mov     [esi + descriptor.buffer], eax
  957.  
  958.         mov     eax, [buffersize]
  959.         mov     ecx, eax
  960.         shl     eax, PKTSShift               ; packet size
  961.         shl     ecx, TBSShift
  962.         or      eax, ecx
  963.         or      eax, TXIC + TXLD + TXFD + CRCEnable + PADEnable
  964.         mov     [esi + descriptor.control], eax
  965.         mov     [esi + descriptor.status], TXOWN
  966.  
  967. ; Update stats
  968.         inc     [ebx + device.packets_tx]
  969.         mov     eax, [buffersize]
  970.         add     dword[ebx + device.bytes_tx], eax
  971.         adc     dword[ebx + device.bytes_tx + 4], 0
  972.  
  973. ; TX Poll
  974.         set_io  [ebx + device.io_addr], 0
  975.         set_io  [ebx + device.io_addr], TXPDR
  976.         xor     eax, eax
  977.         out     dx, eax
  978.  
  979.         DEBUGF  1,"Transmit OK\n"
  980.         popf
  981.         xor     eax, eax
  982.         ret
  983.  
  984.   .fail:
  985.         DEBUGF  2,"Transmit failed\n"
  986.         invoke  KernelFree, [bufferptr]
  987.         popf
  988.         or      eax, -1
  989.         ret
  990.  
  991. endp
  992.  
  993.  
  994.  
  995. align 4
  996. read_mac:
  997.  
  998.         set_io  [ebx + device.io_addr], 0
  999.         set_io  [ebx + device.io_addr], PAR0
  1000.         lea     edi, [ebx + device.mac]
  1001.         insd
  1002.         set_io  [ebx + device.io_addr], PAR1
  1003.         insw
  1004.         DEBUGF  1,"MAC = %x-%x-%x-%x-%x-%x\n",\
  1005.         [ebx + device.mac+0]:2,[ebx + device.mac+1]:2,[ebx + device.mac+2]:2,[ebx + device.mac+3]:2,[ebx + device.mac+4]:2,[ebx + device.mac+5]:2
  1006.  
  1007.         ret
  1008.  
  1009. align 4
  1010. write_mac:
  1011.  
  1012.         ret
  1013.  
  1014.  
  1015.  
  1016. ;;;;;;;;;;;;;;;;;;;;;;;
  1017. ;;                   ;;
  1018. ;; Interrupt handler ;;
  1019. ;;                   ;;
  1020. ;;;;;;;;;;;;;;;;;;;;;;;
  1021.  
  1022. align 4
  1023. int_handler:
  1024.  
  1025.         push    ebx esi edi
  1026.  
  1027.         DEBUGF  1,"INT\n"
  1028.  
  1029. ; find pointer of device wich made IRQ occur
  1030.  
  1031.         mov     ecx, [devices]
  1032.         test    ecx, ecx
  1033.         jz      .nothing
  1034.         mov     esi, device_list
  1035.   .nextdevice:
  1036.         mov     ebx, [esi]
  1037.  
  1038.         set_io  [ebx + device.io_addr], 0
  1039.         set_io  [ebx + device.io_addr], ISR
  1040.         in      eax, dx
  1041.         out     dx, eax                                 ; send it back to ACK
  1042.         test    eax, eax
  1043.         jnz     .got_it
  1044.   .continue:
  1045.         add     esi, 4
  1046.         dec     ecx
  1047.         jnz     .nextdevice
  1048.   .nothing:
  1049.         pop     edi esi ebx
  1050.         xor     eax, eax
  1051.  
  1052.         ret                                             ; If no device was found, abort (The irq was probably for a device, not registered to this driver)
  1053.  
  1054.   .got_it:
  1055.  
  1056.         DEBUGF  1,"Device: %x Status: %x\n", ebx, ax
  1057.  
  1058.         test    ax, RI  ; receive interrupt
  1059.         jz      .no_rx
  1060.         push    ax
  1061.   .rx_loop:
  1062.         mov     esi, [ebx + device.cur_rx]
  1063.         test    [esi + descriptor.status], RXOWN
  1064.         jnz     .rx_done
  1065.  
  1066.         push    ebx
  1067.         push    .rx_complete
  1068.  
  1069.         mov     ecx, [esi + descriptor.status]
  1070.         shr     ecx, FLNGShift
  1071.         sub     ecx, 4                  ; we dont need CRC
  1072.         push    ecx
  1073.         DEBUGF  1,"Received %u bytes\n", ecx
  1074.  
  1075. ; Update stats
  1076.         add     dword[ebx + device.bytes_rx], ecx
  1077.         adc     dword[ebx + device.bytes_rx + 4], 0
  1078.         inc     [ebx + device.packets_rx]
  1079.  
  1080.         push    [esi + descriptor.skbuff]
  1081.         jmp     [Eth_input]
  1082.  
  1083.   .rx_complete:
  1084.         pop     ebx
  1085.         mov     esi, [ebx + device.cur_rx]
  1086.         mov     [esi + descriptor.control], 1536 shl RBSShift
  1087.         push    esi
  1088.         invoke  KernelAlloc, 1536
  1089.         pop     esi
  1090.         mov     [esi + descriptor.skbuff], eax
  1091.         invoke  GetPgAddr
  1092.         mov     [esi + descriptor.buffer], eax
  1093.         mov     [esi + descriptor.status], RXOWN
  1094.  
  1095.         push    [esi + descriptor.next_desc_logical]
  1096.         pop     [ebx + device.cur_rx]
  1097.  
  1098.         jmp     .rx_loop
  1099.  
  1100.   .rx_done:
  1101.         DEBUGF  1,"RX done\n"
  1102.  
  1103. ; Restart Rx engine if stopped.
  1104.         set_io  [ebx + device.io_addr], 0
  1105.         set_io  [ebx + device.io_addr], RXPDR
  1106.         xor     eax, eax
  1107.         out     dx, eax
  1108.  
  1109.         pop     ax
  1110.   .no_rx:
  1111.  
  1112.         test    ax, TI ; transmit interrupt
  1113.         jz      .no_tx
  1114.         DEBUGF  1,"TX\n"
  1115.         push    ax
  1116.         lea     esi, [ebx + device.tx_desc]
  1117.         mov     ecx, NUM_TX_DESC
  1118.   .tx_loop:
  1119.         test    [esi + descriptor.status], TXOWN
  1120.         jnz     .skip_this_one
  1121.         mov     eax, [esi + descriptor.skbuff]
  1122.         test    eax, eax
  1123.         je      .skip_this_one
  1124.         mov     [esi + descriptor.skbuff], 0
  1125.         DEBUGF  1,"freeing buffer: 0x%x\n", eax
  1126.         invoke  KernelFree, eax
  1127.   .skip_this_one:
  1128.         mov     esi, [esi + descriptor.next_desc_logical]
  1129.         loop    .tx_loop
  1130.         pop     ax
  1131.   .no_tx:
  1132.  
  1133.         test    ax, LSCStatus
  1134.         jz      .no_link_change
  1135.         push    ax
  1136.         call    getlinkstatus
  1137.         pop     ax
  1138.   .no_link_change:
  1139.  
  1140. ;        test    ax, TBU
  1141. ;        jz      .no_tbu
  1142. ;        DEBUGF  2,"Transmit buffer unavailable!\n"
  1143. ;  .no_tbu:
  1144.  
  1145.   .fail:
  1146.         pop     edi esi ebx
  1147.         xor     eax, eax
  1148.         inc     eax
  1149.  
  1150.         ret
  1151.  
  1152.  
  1153. ; End of code
  1154.  
  1155.  
  1156. data fixups
  1157. end data
  1158.  
  1159. include '../peimport.inc'
  1160.  
  1161. my_service      db 'mtd80x',0                   ; max 16 chars include zero
  1162.  
  1163. sz_mtd800       db "Myson MTD800", 0
  1164. sz_mtd803       db "Surecom EP-320X", 0
  1165. sz_mtd891       db "Myson MTD891", 0
  1166.  
  1167.  
  1168. include_debug_strings                           ; All data wich FDO uses will be included here
  1169.  
  1170. align 4
  1171. devices       dd 0
  1172. device_list   rd MAX_DEVICES                    ; This list contains all pointers to device structures the driver is handling
  1173.  
  1174.  
  1175.