Subversion Repositories Kolibri OS

Rev

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

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