Subversion Repositories Kolibri OS

Rev

Rev 9232 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2004-2021. All rights reserved.    ;;
  4. ;; Distributed under terms of the GNU General Public License       ;;
  5. ;;                                                                 ;;
  6. ;; i8255x (Intel eepro 100) driver for KolibriOS                   ;;
  7. ;;                                                                 ;;
  8. ;;    Written by hidnplayr@kolibrios.org                           ;;
  9. ;;                                                                 ;;
  10. ;;          GNU GENERAL PUBLIC LICENSE                             ;;
  11. ;;             Version 2, June 1991                                ;;
  12. ;;                                                                 ;;
  13. ;; Some parts of this driver are based on the code of eepro100.c   ;;
  14. ;;  from linux.                                                    ;;
  15. ;;                                                                 ;;
  16. ;; Intel's programming manual for i8255x:                          ;;
  17. ;; http://www.intel.com/design/network/manuals/8255x_opensdm.htm   ;;
  18. ;;                                                                 ;;
  19. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  20.  
  21. ;TODO: use more RX buffers
  22.  
  23. format PE DLL native
  24. entry START
  25.  
  26.         CURRENT_API             = 0x0200
  27.         COMPATIBLE_API          = 0x0100
  28.         API_VERSION             = (COMPATIBLE_API shl 16) + CURRENT_API
  29.  
  30. ; configureable area
  31.  
  32.         MAX_DEVICES             = 16            ; Maximum number of devices this driver may handle
  33.  
  34.         TX_RING_SIZE            = 16            ; Number of packets in send ring buffer
  35.         RX_RING_SIZE            = 1             ; Number of packets in receive ring buffer
  36.  
  37.         __DEBUG__               = 1             ; 1 = on, 0 = off
  38.         __DEBUG_LEVEL__         = 2             ; 1 = verbose, 2 = errors only
  39.  
  40. ; end configureable area
  41.  
  42. section '.flat' readable writable executable
  43.  
  44. include '../proc32.inc'
  45. include '../struct.inc'
  46. include '../macros.inc'
  47. include '../fdo.inc'
  48. include '../netdrv.inc'
  49.  
  50. if (bsr TX_RING_SIZE)>(bsf TX_RING_SIZE)
  51.   display 'TX_RING_SIZE must be a power of two'
  52.   err
  53. end if
  54.  
  55. if (RX_RING_SIZE)<>(1)
  56.   display 'RX_RING_SIZE must be 1'
  57.   err
  58. end if
  59.  
  60. ; I/O registers
  61. REG_SCB_STATUS          = 0
  62. REG_SCB_CMD             = 2
  63. REG_SCB_PTR             = 4
  64. REG_PORT                = 8
  65. REG_EEPROM              = 14
  66. REG_MDI_CTRL            = 16
  67.  
  68. ; Port commands
  69. PORT_SOFT_RESET         = 0x0
  70. PORT_SELF_TEST          = 0x1
  71. PORT_SELECTIVE_RESET    = 0x2
  72. PORT_DUMP               = 0x3
  73. PORT_DUMP_WAKEUP        = 0x7
  74. PORT_PTR_MASK           = 0xfffffff0
  75.  
  76. ; Serial EEPROM
  77. EE_SK                   = 1 shl 0       ; serial clock
  78. EE_CS                   = 1 shl 1       ; chip select
  79. EE_DI                   = 1 shl 2       ; data in
  80. EE_DO                   = 1 shl 3       ; data out
  81. EE_MASK                 = EE_SK or EE_CS or EE_DI or EE_DO
  82. ; opcodes, first bit is start bit and must be 1
  83. EE_READ                 = 110b
  84. EE_WRITE                = 101b
  85. EE_ERASE                = 111b
  86.  
  87. ; The SCB accepts the following controls for the Tx and Rx units:
  88. CU_START                = 0x0010
  89. CU_RESUME               = 0x0020
  90. CU_STATSADDR            = 0x0040
  91. CU_SHOWSTATS            = 0x0050        ; Dump statistics counters.
  92. CU_CMD_BASE             = 0x0060        ; Base address to add CU commands.
  93. CU_DUMPSTATS            = 0x0070        ; Dump then reset stats counters.
  94.  
  95. RX_START                = 0x0001
  96. RX_RESUME               = 0x0002
  97. RX_ABORT                = 0x0004
  98. RX_ADDR_LOAD            = 0x0006
  99. RX_RESUMENR             = 0x0007
  100. INT_MASK                = 0x0100
  101. DRVR_INT                = 0x0200        ; Driver generated interrupt
  102.  
  103. PHY_100a                = 0x000003E0
  104. PHY_100c                = 0x035002A8
  105. PHY_82555_tx            = 0x015002A8
  106. PHY_nsc_tx              = 0x5C002000
  107. PHY_82562_et            = 0x033002A8
  108. PHY_82562_em            = 0x032002A8
  109. PHY_82562_ek            = 0x031002A8
  110. PHY_82562_eh            = 0x017002A8
  111. PHY_82552_v             = 0xd061004d
  112. PHY_unknown             = 0xFFFFFFFF
  113.  
  114. MAC_82557_D100_A        = 0
  115. MAC_82557_D100_B        = 1
  116. MAC_82557_D100_C        = 2
  117. MAC_82558_D101_A4       = 4
  118. MAC_82558_D101_B0       = 5
  119. MAC_82559_D101M         = 8
  120. MAC_82559_D101S         = 9
  121. MAC_82550_D102          = 12
  122. MAC_82550_D102_C        = 13
  123. MAC_82551_E             = 14
  124. MAC_82551_F             = 15
  125. MAC_82551_10            = 16
  126. MAC_unknown             = 0xFF
  127.  
  128. SCB_STATUS_RUS          = 111100b       ; RU Status
  129. RU_STATUS_IDLE          = 0000b shl 2
  130. RU_STATUS_SUSPENDED     = 0001b shl 2
  131. RU_STATUS_NO_RESOURCES  = 0010b shl 2
  132. RU_STATUS_READY         = 0100b shl 2
  133. SCB_STATUS_FCP          = 1 shl 8       ; Flow Control Pause
  134. SCB_STATUS_SWI          = 1 shl 10      ; Software Interrupt
  135. SCB_STATUS_MDI          = 1 shl 11      ; MDI read/write complete
  136. SCB_STATUS_RNR          = 1 shl 12      ; Receiver Not Ready
  137. SCB_STATUS_CNA          = 1 shl 13      ; Command unit Not Active
  138. SCB_STATUS_FR           = 1 shl 14      ; Frame received
  139. SCB_STATUS_CX_TNO       = 1 shl 15      ; Command finished / Transmit Not Okay
  140.  
  141. struct  rxfd
  142.  
  143.         status          dw ?
  144.         command         dw ?
  145.         link            dd ?
  146.         rx_buf_addr     dd ?
  147.         count           dw ?
  148.         size            dw ?
  149.         packet          rb 1500
  150.  
  151. ends
  152.  
  153. RXFD_STATUS_RC          = 1 shl 0       ; Receive collision
  154. RXFD_STATUS_IA          = 1 shl 1       ; IA mismatch
  155. RXFD_STATUS_NA          = 1 shl 2       ; No address match
  156. RXFD_STATUS_RE          = 1 shl 4       ; Receive Error
  157. RXFD_STATUS_TL          = 1 shl 5       ; Type/length
  158. RXFD_STATUS_FS          = 1 shl 7       ; Frame too short
  159. RXFD_STATUS_DMA_FAIL    = 1 shl 8       ; DMA overrun failure
  160. RXFD_STATUS_NR          = 1 shl 9       ; Out of buffer space; no resources
  161. RXFD_STATUS_MISA        = 1 shl 10      ; Alignment error
  162. RXFD_STATUS_CRC_ERR     = 1 shl 11      ; CRC error in aligned frame
  163. RXFD_STATUS_OK          = 1 shl 13      ; Frame received and stored
  164. RXFD_STATUS_C           = 1 shl 15      ; Completion of frame reception
  165.  
  166. RXFD_CMD_SF             = 1 shl 3
  167. RXFD_CMD_H              = 1 shl 4       ; Header RFD
  168. RXFD_CMD_SUSPEND        = 1 shl 14      ; Suspends RU after receiving the frame
  169. RXFD_CMD_EL             = 1 shl 15      ; Last RFD in RFA
  170.  
  171. struct  txfd
  172.  
  173.         status          dw ?
  174.         command         dw ?
  175.         link            dd ?
  176.         desc_addr       dd ?
  177.         count           dd ?
  178.  
  179.         buf_addr        dd ?
  180.         buf_size        dd ?
  181.         virt_addr       dd ?
  182.                         dd ?            ; alignment
  183.  
  184. ends
  185.  
  186. TXFD_CMD_IA             = 1 shl 0
  187. TXFD_CMD_CFG            = 1 shl 1
  188. TXFD_CMD_TX             = 1 shl 2
  189. TXFD_CMD_TX_FLEX        = 1 shl 3
  190. TXFD_CMD_SUSPEND        = 1 shl 14
  191.  
  192. struc   confcmd {
  193.  
  194.         .status         dw ?
  195.         .command        dw ?
  196.         .link           dd ?
  197.         .data           rb 64
  198.  
  199. }
  200.  
  201. struc   lstats {
  202.  
  203.         .tx_good_frames         dd ?
  204.         .tx_coll16_errs         dd ?
  205.         .tx_late_colls          dd ?
  206.         .tx_underruns           dd ?
  207.         .tx_lost_carrier        dd ?
  208.         .tx_deferred            dd ?
  209.         .tx_one_colls           dd ?
  210.         .tx_multi_colls         dd ?
  211.         .tx_total_colls         dd ?
  212.  
  213.         .rx_good_frames         dd ?
  214.         .rx_crc_errs            dd ?
  215.         .rx_align_errs          dd ?
  216.         .rx_resource_errs       dd ?
  217.         .rx_overrun_errs        dd ?
  218.         .rx_colls_errs          dd ?
  219.         .rx_runt_errs           dd ?
  220.  
  221. }
  222.  
  223. struct  device          ETH_DEVICE
  224.  
  225.         io_addr         dd ?
  226.         pci_bus         dd ?
  227.         pci_dev         dd ?
  228.         rx_desc         dd ?
  229.         cur_tx          dd ?
  230.         last_tx         dd ?
  231.         link_timer      dd ?
  232.         ee_bus_width    db ?
  233.         irq_line        db ?
  234.  
  235.         rb 0x100 - ($ and 0xff) ; align 256
  236.         tx_ring         rb TX_RING_SIZE*sizeof.txfd
  237.  
  238.         rb 0x100 - ($ and 0xff) ; align 256
  239.         confcmd         confcmd
  240.  
  241.         rb 0x100 - ($ and 0xff) ; align 256
  242.         lstats          lstats
  243.  
  244. ends
  245.  
  246. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  247. ;;                        ;;
  248. ;; proc START             ;;
  249. ;;                        ;;
  250. ;; (standard driver proc) ;;
  251. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  252.  
  253. proc START c, state:dword
  254.  
  255.         cmp [state], 1
  256.         jne .exit
  257.  
  258.   .entry:
  259.  
  260.         DEBUGF 1,"Loading driver\n"
  261.         invoke  RegService, my_service, service_proc
  262.         ret
  263.  
  264.   .fail:
  265.   .exit:
  266.         xor eax, eax
  267.         ret
  268.  
  269. endp
  270.  
  271.  
  272. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  273. ;;                        ;;
  274. ;; proc SERVICE_PROC      ;;
  275. ;;                        ;;
  276. ;; (standard driver proc) ;;
  277. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  278.  
  279. align 4
  280. proc service_proc stdcall, ioctl:dword
  281.  
  282.         mov     edx, [ioctl]
  283.         mov     eax, [edx + IOCTL.io_code]
  284.  
  285. ;------------------------------------------------------
  286.  
  287.         cmp     eax, 0 ;SRV_GETVERSION
  288.         jne     @F
  289.  
  290.         cmp     [edx + IOCTL.out_size], 4
  291.         jb      .fail
  292.         mov     eax, [edx + IOCTL.output]
  293.         mov     [eax], dword API_VERSION
  294.  
  295.         xor     eax, eax
  296.         ret
  297.  
  298. ;------------------------------------------------------
  299.   @@:
  300.         cmp     eax, 1 ;SRV_HOOK
  301.         jne     .fail
  302.  
  303.         cmp     [edx + IOCTL.inp_size], 3               ; Data input must be at least 3 bytes
  304.         jb      .fail
  305.  
  306.         mov     eax, [edx + IOCTL.input]
  307.         cmp     byte [eax], 1                           ; 1 means device number and bus number (pci) are given
  308.         jne     .fail                                   ; other types arent supported for this card yet
  309.  
  310. ; check if the device is already listed
  311.  
  312.         mov     esi, device_list
  313.         mov     ecx, [devices]
  314.         test    ecx, ecx
  315.         jz      .firstdevice
  316.  
  317. ;        mov     eax, [edx + IOCTL.input]                ; get the pci bus and device numbers
  318.         mov     ax , [eax+1]                            ;
  319.   .nextdevice:
  320.         mov     ebx, [esi]
  321.         cmp     al, byte[ebx + device.pci_bus]
  322.         jne     @f
  323.         cmp     ah, byte[ebx + device.pci_dev]
  324.         je      .find_devicenum                         ; Device is already loaded, let's find it's device number
  325.        @@:
  326.         add     esi, 4
  327.         loop    .nextdevice
  328.  
  329.  
  330. ; This device doesnt have its own eth_device structure yet, lets create one
  331.   .firstdevice:
  332.         cmp     [devices], MAX_DEVICES                  ; First check if the driver can handle one more card
  333.         jae     .fail
  334.  
  335.         allocate_and_clear ebx, sizeof.device, .fail      ; Allocate the buffer for device structure
  336.  
  337. ; Fill in the direct call addresses into the struct
  338.  
  339.         mov     [ebx + device.reset], reset
  340.         mov     [ebx + device.transmit], transmit
  341.         mov     [ebx + device.unload], unload
  342.         mov     [ebx + device.name], devicename
  343.  
  344. ; save the pci bus and device numbers
  345.  
  346.         mov     eax, [edx + IOCTL.input]
  347.         movzx   ecx, byte[eax+1]
  348.         mov     [ebx + device.pci_bus], ecx
  349.         movzx   ecx, byte[eax+2]
  350.         mov     [ebx + device.pci_dev], ecx
  351.  
  352. ; Now, it's time to find the base io addres of the PCI device
  353.  
  354.         stdcall PCI_find_io, [ebx + device.pci_bus], [ebx + device.pci_dev]
  355.         mov     [ebx + device.io_addr], eax
  356.  
  357. ; We've found the io address, find IRQ now
  358.  
  359.         invoke  PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.interrupt_line
  360.         mov     [ebx + device.irq_line], al
  361.  
  362.         DEBUGF  1,"Hooking into device, devfn:%x, bus:%x, irq:%x, addr:%x\n",\
  363.         [ebx + device.pci_dev]:2,[ebx + device.pci_bus]:2,[ebx + device.irq_line]:2,[ebx + device.io_addr]:4
  364.  
  365. ; Ok, the eth_device structure is ready, let's probe the device
  366.  
  367.         mov     eax, [devices]                                          ; Add the device structure to our device list
  368.         mov     [device_list+4*eax], ebx                                ; (IRQ handler uses this list to find device)
  369.         inc     [devices]                                               ;
  370.  
  371.         call    probe                                                   ; this function will output in eax
  372.         test    eax, eax
  373.         jnz     .err                                                 ; If an error occured, exit
  374.  
  375.         mov     [ebx + device.type], NET_TYPE_ETH
  376.         invoke  NetRegDev
  377.  
  378.         cmp     eax, -1
  379.         je      .err
  380.  
  381.         ret
  382.  
  383. ; If the device was already loaded, find the device number and return it in eax
  384.  
  385.   .find_devicenum:
  386.         DEBUGF  2,"Trying to find device number of already registered device\n"
  387.         invoke  NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
  388.                                                                         ; into a device number in edi
  389.         mov     eax, edi                                                ; Application wants it in eax instead
  390.         DEBUGF  2,"Kernel says: %u\n", eax
  391.         ret
  392.  
  393. ; If an error occured, remove all allocated data and exit (returning -1 in eax)
  394.   .err:
  395.         invoke  KernelFree, ebx
  396.  
  397.   .fail:
  398.         or      eax, -1
  399.         ret
  400.  
  401. ;------------------------------------------------------
  402. endp
  403.  
  404.  
  405.  
  406.  
  407.  
  408. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  409. ;;                                                                        ;;
  410. ;;        Actual Hardware dependent code starts here                      ;;
  411. ;;                                                                        ;;
  412. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  413.  
  414.  
  415. unload:
  416.  
  417.         cmp     [ebx + device.link_timer], 0
  418.         je      @f
  419.         invoke  CancelTimerHS, [ebx + device.link_timer]
  420.   @@:
  421.  
  422.         ; TODO: (in this particular order)
  423.         ;
  424.         ; - Stop the device
  425.         ; - Detach int handler
  426.         ; - Remove device from local list (device_list)
  427.         ; - call unregister function in kernel
  428.         ; - Remove all allocated structures and buffers the card used
  429.  
  430.         or      eax, -1
  431.         ret
  432.  
  433.  
  434. ;-------------
  435. ;
  436. ; Probe
  437. ;
  438. ;-------------
  439.  
  440. align 4
  441. probe:
  442.  
  443.         DEBUGF  1,"Probing\n"
  444.  
  445. ; Make the device a bus master
  446.         invoke  PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command
  447.         or      al, PCI_CMD_MASTER or PCI_CMD_PIO
  448.         invoke  PciWrite32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command, eax
  449.  
  450. ;---------------------------
  451. ; First, identify the device
  452.  
  453.         invoke  PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header.vendor_id ; get device/vendor id
  454.  
  455.         DEBUGF  1,"Vendor_id=0x%x\n", ax
  456.         cmp     ax, 0x8086
  457.         jne     .notfound
  458.         shr     eax, 16
  459.  
  460.         DEBUGF  1,"Device_id=0x%x\n", ax
  461.         mov     ecx, DEVICE_IDs
  462.         mov     edi, device_id_list
  463.         repne   scasw
  464.         jne     .notfound
  465.         jmp     .found
  466.  
  467.   .notfound:
  468.         DEBUGF  2,"Unsupported device!\n"
  469.         or      eax, -1
  470.         ret
  471.  
  472.   .found:
  473.  
  474.  
  475.  
  476. ;----------
  477. ;
  478. ;  Reset
  479. ;
  480. ;----------
  481.  
  482. align 4
  483. reset:
  484.  
  485. ; Stop link check timer if it was already running
  486.         cmp     [ebx + device.link_timer], 0
  487.         je      @f
  488.         invoke  CancelTimerHS, [ebx + device.link_timer]
  489.   @@:
  490.  
  491. ; attach int handler
  492.         movzx   eax, [ebx + device.irq_line]
  493.         DEBUGF  1,"Attaching int handler to irq %x\n", eax:1
  494.         invoke  AttachIntHandler, eax, int_handler, ebx
  495.         test    eax, eax
  496.         jnz     @f
  497.         DEBUGF  2,"Could not attach int handler!\n"
  498.         or      eax, -1
  499.         ret
  500.   @@:
  501.  
  502.         DEBUGF  1,"Resetting\n"
  503.  
  504. ;----------------
  505. ; Selective reset
  506.  
  507.         set_io  [ebx + device.io_addr], 0
  508.         set_io  [ebx + device.io_addr], REG_EEPROM
  509.         mov     eax, PORT_SELECTIVE_RESET
  510.         out     dx, eax
  511.  
  512.         mov     esi, 10
  513.         invoke  Sleep
  514.  
  515. ;-----------
  516. ; Soft reset
  517.  
  518.         set_io  [ebx + device.io_addr], REG_PORT
  519.         mov     eax, PORT_SOFT_RESET
  520.         out     dx, eax
  521.  
  522.         mov     esi, 10
  523.         invoke  Sleep
  524.  
  525. ;-------------
  526. ; Read PHY IDs
  527.  
  528.         mov     cx, 1
  529.         mov     dx, MII_PHYSID1
  530.         call    mdio_read
  531.         DEBUGF  1, "PHY ID1: 0x%x\n", ax
  532.  
  533.         mov     cx, 1
  534.         mov     dx, MII_PHYSID2
  535.         call    mdio_read
  536.         DEBUGF  1, "PHY ID2: 0x%x\n", ax
  537.  
  538. ;---------------------
  539. ; Read MAC from eeprom
  540.  
  541.         call    ee_get_width
  542.         call    mac_read_eeprom
  543.  
  544. ;---------------------------------
  545. ; Tell device where to store stats
  546.  
  547.         lea     eax, [ebx + device.lstats.tx_good_frames]      ; lstats
  548.         invoke  GetPhysAddr
  549.         set_io  [ebx + device.io_addr], 0
  550.         set_io  [ebx + device.io_addr], REG_SCB_PTR
  551.         out     dx, eax
  552.  
  553.         set_io  [ebx + device.io_addr], REG_SCB_CMD
  554.         mov     ax, CU_STATSADDR or INT_MASK
  555.         out     dx, ax
  556.         call    cmd_wait
  557.  
  558. ;------------------------
  559. ; setup RX base addr to 0
  560.  
  561.         set_io  [ebx + device.io_addr], REG_SCB_PTR
  562.         xor     eax, eax
  563.         out     dx, eax
  564.  
  565.         set_io  [ebx + device.io_addr], REG_SCB_CMD
  566.         mov     ax, RX_ADDR_LOAD or INT_MASK
  567.         out     dx, ax
  568.         call    cmd_wait
  569.  
  570. ;-----------------------------
  571. ; Create RX and TX descriptors
  572.  
  573.         call    init_rx_ring
  574.         test    eax, eax
  575.         jz      .error
  576.  
  577.         call    init_tx_ring
  578.  
  579.  
  580. ;---------
  581. ; Start RX
  582.  
  583.         DEBUGF  1, "Starting RX"
  584.  
  585.         set_io  [ebx + device.io_addr], 0
  586.         set_io  [ebx + device.io_addr], REG_SCB_PTR
  587.         mov     eax, [ebx + device.rx_desc]
  588.         invoke  GetPhysAddr
  589.         add     eax, NET_BUFF.data
  590.         out     dx, eax
  591.  
  592.         set_io  [ebx + device.io_addr], REG_SCB_CMD
  593.         mov     ax, RX_START or INT_MASK
  594.         out     dx, ax
  595.         call    cmd_wait
  596.  
  597. ;----------
  598. ; Set-up TX
  599.  
  600.         set_io  [ebx + device.io_addr], REG_SCB_PTR
  601.         xor     eax, eax
  602.         out     dx, eax
  603.  
  604.         set_io  [ebx + device.io_addr], REG_SCB_CMD
  605.         mov     ax, CU_CMD_BASE or INT_MASK
  606.         out     dx, ax
  607.         call    cmd_wait
  608.  
  609. ;-------------------------
  610. ; Individual address setup
  611.  
  612.         mov     [ebx + device.confcmd.command], TXFD_CMD_IA or TXFD_CMD_SUSPEND
  613.         mov     [ebx + device.confcmd.status], 0
  614.         lea     eax, [ebx + device.tx_ring]
  615.         invoke  GetPhysAddr
  616.         mov     [ebx + device.confcmd.link], eax
  617.         lea     edi, [ebx + device.confcmd.data]
  618.         lea     esi, [ebx + device.mac]
  619.         movsd
  620.         movsw
  621.  
  622.         set_io  [ebx + device.io_addr], REG_SCB_PTR
  623.         lea     eax, [ebx + device.confcmd.status]
  624.         invoke  GetPhysAddr
  625.         out     dx, eax
  626.  
  627.         set_io  [ebx + device.io_addr], REG_SCB_CMD
  628.         mov     ax, CU_START or INT_MASK
  629.         out     dx, ax
  630.         call    cmd_wait
  631.  
  632. ;-------------
  633. ; Configure CU
  634.  
  635.         mov     [ebx + device.confcmd.command], TXFD_CMD_CFG or TXFD_CMD_SUSPEND
  636.         mov     [ebx + device.confcmd.status], 0
  637.         lea     eax, [ebx + device.confcmd.status]
  638.         invoke  GetPhysAddr
  639.         mov     [ebx + device.confcmd.link], eax
  640.  
  641.         mov     esi, confcmd_data
  642.         lea     edi, [ebx + device.confcmd.data]
  643.         mov     ecx, 22
  644.         rep     movsb
  645.  
  646.         set_io  [ebx + device.io_addr], REG_SCB_PTR
  647.         lea     eax, [ebx + device.confcmd.status]
  648.         invoke  GetPhysAddr
  649.         out     dx, eax
  650.  
  651.         set_io  [ebx + device.io_addr], REG_SCB_CMD
  652.         mov     ax, CU_START                            ; expect Interrupts from now on
  653.         out     dx, ax
  654.         call    cmd_wait
  655.  
  656. ; Start media check timer
  657.         mov     [ebx + device.state], ETH_LINK_DOWN
  658.         invoke  TimerHS, 0, 50, check_media_mii, ebx
  659.         mov     [ebx + device.link_timer], eax
  660.  
  661.         mov     [ebx + device.mtu], 1514
  662.  
  663.         DEBUGF  1,"Reset complete\n"
  664.  
  665.         xor     eax, eax        ; indicate that we have successfully reset the card
  666.         ret
  667.  
  668.   .error:
  669.         or      eax, -1
  670.         ret
  671.  
  672.  
  673. align 4
  674. init_rx_ring:
  675.  
  676.         DEBUGF  1,"Creating ring\n"
  677.  
  678. ;---------------------
  679. ; build rxfd structure
  680.  
  681.         invoke  NetAlloc, 2000
  682.         test    eax, eax
  683.         jz      .out_of_mem
  684.         mov     [ebx + device.rx_desc], eax
  685.         mov     esi, eax
  686.         invoke  GetPhysAddr
  687.         add     eax, NET_BUFF.data
  688.         mov     [esi + sizeof.NET_BUFF + rxfd.status], 0
  689.         mov     [esi + sizeof.NET_BUFF + rxfd.command], RXFD_CMD_EL or RXFD_CMD_SUSPEND
  690.         mov     [esi + sizeof.NET_BUFF + rxfd.link], eax
  691.         mov     [esi + sizeof.NET_BUFF + rxfd.count], 0
  692.         mov     [esi + sizeof.NET_BUFF + rxfd.size], 1528
  693.  
  694.         ret
  695.  
  696.   .out_of_mem:
  697.         ret
  698.  
  699.  
  700.  
  701.  
  702. align 4
  703. init_tx_ring:
  704.  
  705.         DEBUGF  1,"Creating TX ring\n"
  706.  
  707.         lea     esi, [ebx + device.tx_ring]
  708.         mov     eax, esi
  709.         invoke  GetPhysAddr
  710.         mov     ecx, TX_RING_SIZE
  711.   .next_desc:
  712.         mov     [esi + txfd.status], 0
  713.         mov     [esi + txfd.command], 0
  714.         lea     edx, [eax + txfd.buf_addr]
  715.         mov     [esi + txfd.desc_addr], edx
  716.         add     eax, sizeof.txfd
  717.         mov     [esi + txfd.link], eax
  718.         mov     [esi + txfd.count], 0x01208000          ; One buffer, 0x20 bytes of transmit threshold, end of frame
  719.         add     esi, sizeof.txfd
  720.         dec     ecx
  721.         jnz     .next_desc
  722.  
  723.         lea     eax, [ebx + device.tx_ring]
  724.         invoke  GetPhysAddr
  725.         mov     dword[ebx + device.tx_ring + sizeof.txfd*(TX_RING_SIZE-1) + txfd.link], eax
  726.  
  727.         mov     [ebx + device.cur_tx], 0
  728.         mov     [ebx + device.last_tx], 0
  729.  
  730.         ret
  731.  
  732.  
  733. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  734. ;;                                         ;;
  735. ;; Transmit                                ;;
  736. ;;                                         ;;
  737. ;; In: pointer to device structure in ebx  ;;
  738. ;; Out: eax = 0 on success                 ;;
  739. ;;                                         ;;
  740. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  741. align 16
  742. proc transmit stdcall bufferptr
  743.  
  744.         spin_lock_irqsave
  745.  
  746.         mov     esi, [bufferptr]
  747.         DEBUGF  1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [esi + NET_BUFF.length]
  748.         lea     eax, [esi + NET_BUFF.data]
  749.         DEBUGF  1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
  750.         [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
  751.         [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
  752.         [eax+13]:2,[eax+12]:2
  753.  
  754.         cmp     [esi + NET_BUFF.length], 1514
  755.         ja      .error
  756.         cmp     [esi + NET_BUFF.length], 60
  757.         jb      .error
  758.  
  759.         ; Get current TX descriptor
  760.         mov     edi, [ebx + device.cur_tx]
  761.         mov     eax, sizeof.txfd
  762.         mul     edi
  763.         lea     edi, [ebx + device.tx_ring + eax]
  764.  
  765.         ; Check if current descriptor is free or still in use
  766.         cmp     [edi + txfd.status], 0
  767.         jne     .overrun
  768.  
  769.         ; Fill in status and command values
  770.         mov     [edi + txfd.status], 0
  771.         mov     [edi + txfd.command], TXFD_CMD_SUSPEND or TXFD_CMD_TX or TXFD_CMD_TX_FLEX
  772.         mov     [edi + txfd.count], 0x01208000
  773.  
  774.         ; Fill in buffer address and size
  775.         mov     [edi + txfd.virt_addr], esi
  776.         mov     eax, esi
  777.         add     eax, [esi + NET_BUFF.offset]
  778.         push    edi
  779.         invoke  GetPhysAddr
  780.         pop     edi
  781.         mov     [edi + txfd.buf_addr], eax
  782.         mov     ecx, [esi + NET_BUFF.length]
  783.         mov     [edi + txfd.buf_size], ecx
  784.  
  785.         ; Inform device of the new/updated transmit descriptor
  786.         mov     eax, edi
  787.         invoke  GetPhysAddr
  788.         set_io  [ebx + device.io_addr], 0
  789.         set_io  [ebx + device.io_addr], REG_SCB_PTR
  790.         out     dx, eax
  791.  
  792.         ; Start the transmit
  793.         set_io  [ebx + device.io_addr], REG_SCB_CMD
  794.         mov     ax, CU_START
  795.         out     dx, ax
  796.  
  797.         ; Update stats
  798.         inc     [ebx + device.packets_tx]
  799.         add     dword[ebx + device.bytes_tx], ecx
  800.         adc     dword[ebx + device.bytes_tx + 4], 0
  801.  
  802.         inc     [ebx + device.cur_tx]
  803.         and     [ebx + device.cur_tx], TX_RING_SIZE - 1
  804.  
  805.         ; Wait for command to complete
  806.         call    cmd_wait
  807.  
  808.         spin_unlock_irqrestore
  809.         xor     eax, eax
  810.         ret
  811.  
  812.   .error:
  813.         DEBUGF  2, "TX packet error\n"
  814.         inc     [ebx + device.packets_tx_err]
  815.         invoke  NetFree, [bufferptr]
  816.  
  817.         spin_unlock_irqrestore
  818.         or      eax, -1
  819.         ret
  820.  
  821.   .overrun:
  822.         DEBUGF  2, "TX overrun\n"
  823.         inc     [ebx + device.packets_tx_ovr]
  824.         invoke  NetFree, [bufferptr]
  825.  
  826.         spin_unlock_irqrestore
  827.         or      eax, -1
  828.         ret
  829.  
  830. endp
  831.  
  832.  
  833. ;;;;;;;;;;;;;;;;;;;;;;;
  834. ;;                   ;;
  835. ;; Interrupt handler ;;
  836. ;;                   ;;
  837. ;;;;;;;;;;;;;;;;;;;;;;;
  838. align 16
  839. int_handler:
  840.  
  841.         push    ebx esi edi
  842.  
  843.         mov     ebx, [esp+4*4]
  844.         DEBUGF  1,"INT for 0x%x\n", ebx
  845.  
  846. ; TODO? if we are paranoid, we can check that the value from ebx is present in the current device_list
  847.  
  848. ;        set_io  [ebx + device.io_addr], 0      ; REG_SCB_STATUS = 0
  849.         set_io  [ebx + device.io_addr], REG_SCB_STATUS
  850.         in      ax, dx
  851.         test    ax, ax
  852.         jz      .nothing
  853.         out     dx, ax                          ; send it back to ACK
  854.  
  855.         DEBUGF  1,"Status: %x\n", ax
  856.  
  857.         test    ax, SCB_STATUS_FR               ; did we receive a frame?
  858.         jz      .no_rx
  859.  
  860.         push    ax
  861.  
  862.         DEBUGF  1,"Receiving\n"
  863.  
  864.         push    ebx
  865.   .rx_loop:
  866.         pop     ebx
  867.  
  868.         mov     esi, [ebx + device.rx_desc]
  869.         test    [esi + sizeof.NET_BUFF + rxfd.status], RXFD_STATUS_C            ; Completed?
  870.         jz      .no_rx_
  871.         test    [esi + sizeof.NET_BUFF + rxfd.status], RXFD_STATUS_OK           ; OK?
  872.         jz      .not_ok
  873.  
  874.         DEBUGF  1,"rxfd status=0x%x\n", [esi + sizeof.NET_BUFF + rxfd.status]:4
  875.  
  876.         movzx   ecx, [esi + sizeof.NET_BUFF + rxfd.count]
  877.         and     ecx, 0x3fff
  878.  
  879.         push    ebx
  880.         push    .rx_loop
  881.         push    esi
  882.         mov     [esi + NET_BUFF.length], ecx
  883.         mov     [esi + NET_BUFF.device], ebx
  884.         mov     [esi + NET_BUFF.offset], NET_BUFF.data + rxfd.packet
  885.  
  886. ; Update stats
  887.         add     dword [ebx + device.bytes_rx], ecx
  888.         adc     dword [ebx + device.bytes_rx + 4], 0
  889.         inc     dword [ebx + device.packets_rx]
  890.  
  891. ; allocate new descriptor
  892.  
  893.         invoke  NetAlloc, 2000
  894.         test    eax, eax
  895.         jz      .out_of_mem
  896.         mov     [ebx + device.rx_desc], eax
  897.         mov     esi, eax
  898.         invoke  GetPhysAddr
  899.         add     eax, NET_BUFF.data
  900.         mov     [esi + sizeof.NET_BUFF + rxfd.status], 0
  901.         mov     [esi + sizeof.NET_BUFF + rxfd.command], RXFD_CMD_EL or RXFD_CMD_SUSPEND
  902.         mov     [esi + sizeof.NET_BUFF + rxfd.link], eax
  903.         mov     [esi + sizeof.NET_BUFF + rxfd.count], 0
  904.         mov     [esi + sizeof.NET_BUFF + rxfd.size], 1528
  905.  
  906. ; restart RX
  907.  
  908.         set_io  [ebx + device.io_addr], 0
  909.         set_io  [ebx + device.io_addr], REG_SCB_PTR
  910. ;        mov     eax, [ebx + device.rx_desc]
  911. ;        invoke  GetPhysAddr
  912. ;        add     eax, NET_BUFF.data
  913.         out     dx, eax
  914.  
  915.         set_io  [ebx + device.io_addr], REG_SCB_CMD
  916.         mov     ax, RX_START
  917.         out     dx, ax
  918.         call    cmd_wait
  919.   .out_of_mem:
  920.  
  921. ; Hand the frame over to the kernel
  922.         jmp     [EthInput]
  923.  
  924.   .not_ok:
  925. ; Reset the FD
  926.         mov     [esi + sizeof.NET_BUFF + rxfd.status], 0
  927.         mov     [esi + sizeof.NET_BUFF + rxfd.command], RXFD_CMD_EL or RXFD_CMD_SUSPEND
  928.         mov     [esi + sizeof.NET_BUFF + rxfd.count], 0
  929.  
  930. ; Restart RX
  931.         set_io  [ebx + device.io_addr], 0
  932.         set_io  [ebx + device.io_addr], REG_SCB_PTR
  933.         mov     eax, esi
  934.         invoke  GetPhysAddr
  935.         add     eax, NET_BUFF.data
  936.         out     dx, eax
  937.  
  938.         set_io  [ebx + device.io_addr], REG_SCB_CMD
  939.         mov     ax, RX_START
  940.         out     dx, ax
  941.         call    cmd_wait
  942.  
  943.         push    ebx
  944.         jmp     .rx_loop
  945.  
  946.   .no_rx_:
  947.         DEBUGF  1, "no more data\n"
  948.         pop     ax
  949.  
  950.   .no_rx:
  951.  
  952.         test    ax, SCB_STATUS_CNA
  953.         jz      .no_tx
  954.         DEBUGF  1, "Command completed\n"
  955.  
  956.         push    eax
  957.   .loop_tx:
  958.         mov     edi, [ebx + device.last_tx]
  959.         mov     eax, sizeof.txfd
  960.         mul     eax
  961.         lea     edi, [ebx + device.tx_ring + eax]
  962.  
  963.         cmp     [edi + txfd.status], 0
  964.         je      .tx_done
  965.  
  966.         cmp     [edi + txfd.virt_addr], 0
  967.         je      .tx_done
  968.  
  969.         DEBUGF  1,"Freeing buffer 0x%x\n", [edi + txfd.virt_addr]
  970.  
  971.         push    [edi + txfd.virt_addr]
  972.         mov     [edi + txfd.virt_addr], 0
  973.         invoke  NetFree
  974.  
  975.         inc     [ebx + device.last_tx]
  976.         and     [ebx + device.last_tx], TX_RING_SIZE - 1
  977.  
  978.         jmp     .loop_tx
  979.   .tx_done:
  980.         pop     eax
  981.   .no_tx:
  982.  
  983.         test    ax, RU_STATUS_NO_RESOURCES
  984.         jz      .not_out_of_resources
  985.  
  986.         DEBUGF  2, "Out of resources!\n"
  987.  
  988.   .not_out_of_resources:
  989.         pop     edi esi ebx
  990.         xor     eax, eax
  991.         inc     eax
  992.  
  993.         ret
  994.  
  995.   .nothing:
  996.         pop     edi esi ebx
  997.         xor     eax, eax
  998.  
  999.         ret
  1000.  
  1001.  
  1002.  
  1003. align 16
  1004. proc check_media_mii stdcall dev:dword
  1005.  
  1006.         spin_lock_irqsave
  1007.  
  1008.         mov     ebx, [dev]
  1009.  
  1010.         mov     ecx, 1  ;;;
  1011.         mov     edx, MII_BMSR
  1012.         call    mdio_read
  1013.  
  1014.         mov     ecx, 1  ;;;
  1015.         mov     edx, MII_BMSR
  1016.         call    mdio_read
  1017.  
  1018.         mov     ecx, eax
  1019.         and     eax, BMSR_LSTATUS
  1020.         shr     eax, 2
  1021.         cmp     eax, [ebx + device.state]
  1022.         jne     .changed
  1023.  
  1024.         spin_unlock_irqrestore
  1025.         ret
  1026.  
  1027.   .changed:
  1028.         test    eax, eax
  1029.         jz      .update
  1030.  
  1031.         test    ecx, BMSR_ANEGCOMPLETE
  1032.         jz      .update
  1033.  
  1034.         mov     ecx, 1  ;;;
  1035.         mov     edx, MII_ADVERTISE
  1036.         call    mdio_read
  1037.         mov     esi, eax
  1038.  
  1039.         mov     ecx, 1  ;;;
  1040.         mov     edx, MII_LPA
  1041.         call    mdio_read
  1042.         and     eax, esi
  1043.  
  1044.         test    eax, LPA_100FULL
  1045.         jz      @f
  1046.         mov     eax, ETH_LINK_SPEED_100M or ETH_LINK_FULL_DUPLEX
  1047.         jmp     .update
  1048.   @@:
  1049.  
  1050.         test    eax, LPA_100HALF
  1051.         jz      @f
  1052.         mov     eax, ETH_LINK_SPEED_100M
  1053.         jmp     .update
  1054.   @@:
  1055.  
  1056.         test    eax, LPA_10FULL
  1057.         jz      @f
  1058.         mov     eax, ETH_LINK_SPEED_10M or ETH_LINK_FULL_DUPLEX
  1059.         jmp     .update
  1060.   @@:
  1061.  
  1062.         test    eax, LPA_10HALF
  1063.         jz      @f
  1064.         mov     eax, ETH_LINK_SPEED_10M
  1065.         jmp     .update
  1066.   @@:
  1067.  
  1068.         mov     eax, ETH_LINK_UNKNOWN
  1069.  
  1070.   .update:
  1071.         mov     [ebx + device.state], eax
  1072.         invoke  NetLinkChanged
  1073.  
  1074.  
  1075.         spin_unlock_irqrestore
  1076.         ret
  1077.  
  1078.  
  1079. endp
  1080.  
  1081.  
  1082. align 4
  1083. cmd_wait:
  1084.  
  1085.         in      al, dx
  1086.         test    al, al
  1087.         jnz     cmd_wait
  1088.  
  1089.         ret
  1090.  
  1091.  
  1092.  
  1093. align 4
  1094. ee_read:        ; esi = address to read
  1095.  
  1096.         DEBUGF  1,"Eeprom read from 0x%x\n", esi
  1097.  
  1098.         set_io  [ebx + device.io_addr], 0
  1099.         set_io  [ebx + device.io_addr], REG_EEPROM
  1100.  
  1101. ;-----------------------------------------------------
  1102. ; Prepend start bit + read opcode to the address field
  1103. ; and shift it to the very left bits of esi
  1104.  
  1105.         mov     cl, 29
  1106.         sub     cl, [ebx + device.ee_bus_width]
  1107.         shl     esi, cl
  1108.         or      esi, EE_READ shl 29
  1109.  
  1110.         movzx   ecx, [ebx + device.ee_bus_width]
  1111.         add     ecx, 3
  1112.  
  1113.         mov     ax, 0x4800 + EE_CS
  1114.         out     dx, ax
  1115.         call    udelay
  1116.  
  1117. ;-----------------------
  1118. ; Write this to the chip
  1119.  
  1120.   .loop:
  1121.         mov     al, EE_CS
  1122.         shl     esi, 1
  1123.         jnc     @f
  1124.         or      al, EE_DI
  1125.        @@:
  1126.         out     dx, al
  1127.         call    udelay
  1128.  
  1129.         or      al, EE_SK
  1130.         out     dx, al
  1131.         call    udelay
  1132.  
  1133.         loop    .loop
  1134.  
  1135. ;------------------------------
  1136. ; Now read the data from eeprom
  1137.  
  1138.         xor     esi, esi
  1139.         mov     ecx, 16
  1140.  
  1141.   .loop2:
  1142.         shl     esi, 1
  1143.         mov     al, EE_CS
  1144.         out     dx, al
  1145.         call    udelay
  1146.  
  1147.         or      al, EE_SK
  1148.         out     dx, al
  1149.         call    udelay
  1150.  
  1151.         in      al, dx
  1152.         test    al, EE_DO
  1153.         jz      @f
  1154.         inc     esi
  1155.        @@:
  1156.  
  1157.         loop    .loop2
  1158.  
  1159. ;-----------------------
  1160. ; de-activate the eeprom
  1161.  
  1162.         xor     al, al
  1163.         out     dx, al
  1164.  
  1165.         DEBUGF  1,"0x%x\n", esi:4
  1166.         ret
  1167.  
  1168.  
  1169.  
  1170. align 4
  1171. ee_write:       ; esi = address to write to, di = data
  1172.  
  1173.         DEBUGF  1,"Eeprom write 0x%x to 0x%x\n", di, esi
  1174.  
  1175.         set_io  [ebx + device.io_addr], 0
  1176.         set_io  [ebx + device.io_addr], REG_EEPROM
  1177.  
  1178. ;-----------------------------------------------------
  1179. ; Prepend start bit + write opcode to the address field
  1180. ; and shift it to the very left bits of esi
  1181.  
  1182.         mov     cl, 29
  1183.         sub     cl, [ebx + device.ee_bus_width]
  1184.         shl     esi, cl
  1185.         or      esi, EE_WRITE shl 29
  1186.  
  1187.         movzx   ecx, [ebx + device.ee_bus_width]
  1188.         add     ecx, 3
  1189.  
  1190.         mov     ax, 0x4800 + EE_CS       ; enable chip
  1191.         out     dx, ax
  1192.  
  1193. ;-----------------------
  1194. ; Write this to the chip
  1195.  
  1196.   .loop:
  1197.         mov     al, EE_CS
  1198.         shl     esi, 1
  1199.         jnc     @f
  1200.         or      al, EE_DI
  1201.        @@:
  1202.         out     dx, al
  1203.         call    udelay
  1204.  
  1205.         or      al, EE_SK
  1206.         out     dx, al
  1207.         call    udelay
  1208.  
  1209.         loop    .loop
  1210.  
  1211. ;-----------------------------
  1212. ; Now write the data to eeprom
  1213.  
  1214.         mov     ecx, 16
  1215.  
  1216.   .loop2:
  1217.         mov     al, EE_CS
  1218.         shl     di, 1
  1219.         jnc     @f
  1220.         or      al, EE_DI
  1221.        @@:
  1222.         out     dx, al
  1223.         call    udelay
  1224.  
  1225.         or      al, EE_SK
  1226.         out     dx, al
  1227.         call    udelay
  1228.  
  1229.         loop    .loop2
  1230.  
  1231. ;-----------------------
  1232. ; de-activate the eeprom
  1233.  
  1234.         xor     al, al
  1235.         out     dx, al
  1236.  
  1237.  
  1238.         ret
  1239.  
  1240.  
  1241.  
  1242. align 4
  1243. ee_get_width:
  1244.  
  1245.         set_io  [ebx + device.io_addr], 0
  1246.         set_io  [ebx + device.io_addr], REG_EEPROM
  1247.  
  1248.         mov     ax, 0x4800 + EE_CS      ; activate eeprom
  1249.         out     dx, ax
  1250.         call    udelay
  1251.  
  1252.         mov     si, EE_READ shl 13
  1253.         xor     ecx, ecx
  1254.   .loop:
  1255.         mov     al, EE_CS
  1256.         shl     si, 1
  1257.         jnc     @f
  1258.         or      al, EE_DI
  1259.        @@:
  1260.         out     dx, ax
  1261.         call    udelay
  1262.  
  1263.         or      al, EE_SK
  1264.         out     dx, ax
  1265.         call    udelay
  1266.  
  1267.         inc     ecx
  1268.  
  1269.         cmp     ecx, 15
  1270.         jae     .give_up
  1271.  
  1272.         in      al, dx
  1273.         test    al, EE_DO
  1274.         jnz     .loop
  1275.  
  1276.         xor     al, al
  1277.         out     dx, al                  ; de-activate eeprom
  1278.  
  1279.         sub     cl, 3                   ; dont count the opcode bits
  1280.         mov     [ebx + device.ee_bus_width], cl
  1281.         DEBUGF  1, "Eeprom width=%u bit\n", ecx
  1282.  
  1283.         ret
  1284.  
  1285.   .give_up:
  1286.         DEBUGF  2, "Eeprom not found!\n"
  1287.         xor     al, al
  1288.         out     dx, al                  ; de-activate eeprom
  1289.  
  1290.         ret
  1291.  
  1292.  
  1293. ; Wait a minimum of 2µs
  1294. udelay:
  1295.         pusha
  1296.         mov     esi, 1
  1297.         invoke  Sleep
  1298.         popa
  1299.  
  1300.         ret
  1301.  
  1302.  
  1303.  
  1304. ; cx = phy addr
  1305. ; dx = phy reg addr
  1306.  
  1307. ; ax = data
  1308.  
  1309. align 4
  1310. mdio_read:
  1311.  
  1312.         DEBUGF  1,"MDIO read\n"
  1313.  
  1314.         shl     ecx, 21                 ; PHY addr
  1315.         mov     eax, ecx
  1316.         shl     edx, 16                 ; PHY reg addr
  1317.         or      eax, edx
  1318.         or      eax, 10b shl 26         ; read opcode
  1319.  
  1320.         set_io  [ebx + device.io_addr], 0
  1321.         set_io  [ebx + device.io_addr], REG_MDI_CTRL
  1322.         out     dx, eax
  1323.  
  1324.   .wait:
  1325.         call    udelay
  1326.         in      eax, dx
  1327.         test    eax, 1 shl 28           ; ready bit
  1328.         jz      .wait
  1329.  
  1330.         ret
  1331.  
  1332.  
  1333.  
  1334. ; ax = data
  1335. ; cx = phy addr
  1336. ; dx = phy reg addr
  1337.  
  1338. ; ax = data
  1339.  
  1340. align 4
  1341. mdio_write:
  1342.  
  1343.         DEBUGF  1,"MDIO write\n"
  1344.  
  1345.         and     eax, 0xffff
  1346.  
  1347.         shl     ecx, 21                 ; PHY addr
  1348.         shl     edx, 16                 ; PHY reg addr
  1349.  
  1350.         or      eax, ecx
  1351.         or      eax, edx
  1352.         or      eax, 01b shl 26         ; write opcode
  1353.  
  1354.         set_io  [ebx + device.io_addr], 0
  1355.         set_io  [ebx + device.io_addr], REG_MDI_CTRL
  1356.         out     dx, eax
  1357.  
  1358.   .wait:
  1359.         call    udelay
  1360.         in      eax, dx
  1361.         test    eax, 1 shl 28           ; ready bit
  1362.         jz      .wait
  1363.  
  1364.         ret
  1365.  
  1366.  
  1367. align 4
  1368. mac_read_eeprom:
  1369.  
  1370.         mov     esi, 0
  1371.         call    ee_read
  1372.         mov     word[ebx + device.mac], si
  1373.  
  1374.         mov     esi, 1
  1375.         call    ee_read
  1376.         mov     word[ebx + device.mac+2], si
  1377.  
  1378.         mov     esi, 2
  1379.         call    ee_read
  1380.         mov     word[ebx + device.mac+4], si
  1381.  
  1382.  
  1383.         ret
  1384.  
  1385.  
  1386. ; End of code
  1387.  
  1388.  
  1389. data fixups
  1390. end data
  1391.  
  1392. include '../peimport.inc'
  1393.  
  1394. my_service      db 'I8255X', 0                    ; max 16 chars include zero
  1395. devicename      db 'Intel Etherexpress pro/100', 0
  1396.  
  1397. confcmd_data    db 22, 0x08, 0, 0, 0, 0x80, 0x32, 0x03, 1
  1398.                 db 0, 0x2e, 0, 0x60, 0, 0xf2, 0x48, 0, 0x40, 0xf2
  1399.                 db 0x80, 0x3f, 0x05                                     ; 22 bytes total
  1400.  
  1401.  
  1402. device_id_list:
  1403. dw 0x1029
  1404. dw 0x1030
  1405. dw 0x1031
  1406. dw 0x1032
  1407. dw 0x1033
  1408. dw 0x1034
  1409. dw 0x1038
  1410. dw 0x1039
  1411. dw 0x103A
  1412. dw 0x103B
  1413. dw 0x103C
  1414. dw 0x103D
  1415. dw 0x103E
  1416. dw 0x1050
  1417. dw 0x1051
  1418. dw 0x1052
  1419. dw 0x1053
  1420. dw 0x1054
  1421. dw 0x1055
  1422. dw 0x1056
  1423. dw 0x1057
  1424. dw 0x1059
  1425. dw 0x1064
  1426. dw 0x1065
  1427. dw 0x1066
  1428. dw 0x1067
  1429. dw 0x1068
  1430. dw 0x1069
  1431. dw 0x106A
  1432. dw 0x106B
  1433. dw 0x1091
  1434. dw 0x1092
  1435. dw 0x1093
  1436. dw 0x1094
  1437. dw 0x1095
  1438. dw 0x10fe
  1439. dw 0x1209
  1440. dw 0x1229
  1441. dw 0x2449
  1442. dw 0x2459
  1443. dw 0x245D
  1444. dw 0x27DC
  1445.  
  1446. DEVICE_IDs = ($ - device_id_list) / 2
  1447.  
  1448. include_debug_strings                           ; All data wich FDO uses will be included here
  1449.  
  1450. align 4
  1451. devices         dd 0                              ; number of currently running devices
  1452. device_list     rd MAX_DEVICES                    ; This list contains all pointers to device structures the driver is handling
  1453.  
  1454.