Subversion Repositories Kolibri OS

Rev

Rev 5525 | Rev 5561 | 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.         mov     [ebx + device.rx_desc], eax
  826.         mov     esi, eax
  827.         invoke  GetPhysAddr
  828.         add     eax, NET_BUFF.data
  829.         mov     [esi + sizeof.NET_BUFF + rxfd.status], 0x0000
  830.         mov     [esi + sizeof.NET_BUFF + rxfd.command], 0xc000    ; End of list + Suspend
  831.         mov     [esi + sizeof.NET_BUFF + rxfd.link], eax
  832.         mov     [esi + sizeof.NET_BUFF + rxfd.count], 0
  833.         mov     [esi + sizeof.NET_BUFF + rxfd.size], 1528
  834.  
  835. ; restart RX
  836.  
  837.         set_io  [ebx + device.io_addr], 0
  838.         set_io  [ebx + device.io_addr], reg_scb_ptr
  839. ;        mov     eax, [ebx + device.rx_desc]
  840. ;        invoke  GetPhysAddr
  841. ;        add     eax, NET_BUFF.data
  842.         out     dx, eax
  843.  
  844.         set_io  [ebx + device.io_addr], reg_scb_cmd
  845.         mov     ax, RX_START
  846.         out     dx, ax
  847.         call    cmd_wait
  848.  
  849. ; And give packet to kernel
  850.         jmp     [EthInput]
  851.  
  852.   .nodata:
  853.         DEBUGF  1, "no more data\n"
  854.         pop     ax
  855.  
  856.   .no_rx:
  857.  
  858.         test    ax, 1 shl 13
  859.         jz      .no_tx
  860.         DEBUGF  1, "Command completed\n"
  861.  
  862.         push    eax
  863.   .loop_tx:
  864.         mov     edi, [ebx + device.last_tx]
  865.         mov     eax, sizeof.txfd
  866.         mul     eax
  867.         lea     edi, [ebx + device.tx_ring + eax]
  868.  
  869.         cmp     [edi + txfd.status], 0
  870.         je      .tx_done
  871.  
  872.         cmp     [edi + txfd.virt_addr], 0
  873.         je      .tx_done
  874.  
  875.         DEBUGF  1,"Freeing buffer 0x%x\n", [edi + txfd.virt_addr]
  876.  
  877.         push    [edi + txfd.virt_addr]
  878.         mov     [edi + txfd.virt_addr], 0
  879.         invoke  NetFree
  880.  
  881.         inc     [ebx + device.last_tx]
  882.         and     [ebx + device.last_tx], TX_RING_SIZE - 1
  883.  
  884.         jmp     .loop_tx
  885.   .tx_done:
  886.         pop     eax
  887.   .no_tx:
  888.  
  889.         and     ax, 00111100b
  890.         cmp     ax, 00001000b
  891.         jne     .fail
  892.  
  893.         DEBUGF  2, "Out of resources!\n"
  894.  
  895. ;        call    init_rx_ring
  896. ;        test    eax, eax
  897. ;        jz      .fail
  898.  
  899. ; restart RX
  900.         set_io  [ebx + device.io_addr], 0
  901.         set_io  [ebx + device.io_addr], reg_scb_ptr
  902.         mov     eax, [ebx + device.rx_desc]
  903.         invoke  GetPhysAddr
  904.         add     eax, NET_BUFF.data
  905.         out     dx, eax
  906.  
  907.         set_io  [ebx + device.io_addr], reg_scb_cmd
  908.         mov     ax, RX_START
  909.         out     dx, ax
  910.         call    cmd_wait
  911.  
  912.   .fail:
  913.         pop     edi esi ebx
  914.         xor     eax, eax
  915.         inc     eax
  916.  
  917.         ret
  918.  
  919.  
  920.  
  921.  
  922. align 4
  923. cmd_wait:
  924.  
  925.         in      al, dx
  926.         test    al, al
  927.         jnz     cmd_wait
  928.  
  929.         ret
  930.  
  931.  
  932.  
  933.  
  934.  
  935.  
  936. align 4
  937. ee_read:        ; esi = address to read
  938.  
  939.         DEBUGF  1,"Eeprom read from 0x%x\n", esi
  940.  
  941.         set_io  [ebx + device.io_addr], 0
  942.         set_io  [ebx + device.io_addr], reg_eeprom
  943.  
  944. ;-----------------------------------------------------
  945. ; Prepend start bit + read opcode to the address field
  946. ; and shift it to the very left bits of esi
  947.  
  948.         mov     cl, 29
  949.         sub     cl, [ebx + device.ee_bus_width]
  950.         shl     esi, cl
  951.         or      esi, EE_READ shl 29
  952.  
  953.         movzx   ecx, [ebx + device.ee_bus_width]
  954.         add     ecx, 3
  955.  
  956.         mov     al, EE_CS
  957.         out     dx, al
  958.         call    udelay
  959.  
  960. ;-----------------------
  961. ; Write this to the chip
  962.  
  963.   .loop:
  964.         mov     al, EE_CS + EE_SK
  965.         shl     esi, 1
  966.         jnc     @f
  967.         or      al, EE_DI
  968.        @@:
  969.         out     dx, al
  970.         call    udelay
  971.  
  972.         and     al, not EE_SK
  973.         out     dx, al
  974.         call    udelay
  975.  
  976.         loop    .loop
  977.  
  978. ;------------------------------
  979. ; Now read the data from eeprom
  980.  
  981.         xor     esi, esi
  982.         mov     ecx, 16
  983.  
  984.   .loop2:
  985.         shl     esi, 1
  986.         mov     al, EE_CS + EE_SK
  987.         out     dx, al
  988.         call    udelay
  989.  
  990.         in      al, dx
  991.         test    al, EE_DO
  992.         jz      @f
  993.         inc     esi
  994.        @@:
  995.  
  996.         mov     al, EE_CS
  997.         out     dx, al
  998.         call    udelay
  999.  
  1000.         loop    .loop2
  1001.  
  1002. ;-----------------------
  1003. ; de-activate the eeprom
  1004.  
  1005.         xor     ax, ax
  1006.         out     dx, ax
  1007.  
  1008.  
  1009.         DEBUGF  1,"0x%x\n", esi:4
  1010.         ret
  1011.  
  1012.  
  1013.  
  1014. align 4
  1015. ee_write:       ; esi = address to write to, di = data
  1016.  
  1017.         DEBUGF  1,"Eeprom write 0x%x to 0x%x\n", di, esi
  1018.  
  1019.         set_io  [ebx + device.io_addr], 0
  1020.         set_io  [ebx + device.io_addr], reg_eeprom
  1021.  
  1022. ;-----------------------------------------------------
  1023. ; Prepend start bit + write opcode to the address field
  1024. ; and shift it to the very left bits of esi
  1025.  
  1026.         mov     cl, 29
  1027.         sub     cl, [ebx + device.ee_bus_width]
  1028.         shl     esi, cl
  1029.         or      esi, EE_WRITE shl 29
  1030.  
  1031.         movzx   ecx, [ebx + device.ee_bus_width]
  1032.         add     ecx, 3
  1033.  
  1034.         mov     al, EE_CS       ; enable chip
  1035.         out     dx, al
  1036.  
  1037. ;-----------------------
  1038. ; Write this to the chip
  1039.  
  1040.   .loop:
  1041.         mov     al, EE_CS + EE_SK
  1042.         shl     esi, 1
  1043.         jnc     @f
  1044.         or      al, EE_DI
  1045.        @@:
  1046.         out     dx, al
  1047.         call    udelay
  1048.  
  1049.         and     al, not EE_SK
  1050.         out     dx, al
  1051.         call    udelay
  1052.  
  1053.         loop    .loop
  1054.  
  1055. ;-----------------------------
  1056. ; Now write the data to eeprom
  1057.  
  1058.         mov     ecx, 16
  1059.  
  1060.   .loop2:
  1061.         mov     al, EE_CS + EE_SK
  1062.         shl     di, 1
  1063.         jnc     @f
  1064.         or      al, EE_DI
  1065.        @@:
  1066.         out     dx, al
  1067.         call    udelay
  1068.  
  1069.         and     al, not EE_SK
  1070.         out     dx, al
  1071.         call    udelay
  1072.  
  1073.         loop    .loop2
  1074.  
  1075. ;-----------------------
  1076. ; de-activate the eeprom
  1077.  
  1078.         xor     al, al
  1079.         out     dx, al
  1080.  
  1081.  
  1082.         ret
  1083.  
  1084.  
  1085.  
  1086. align 4
  1087. ee_get_width:
  1088.  
  1089.         set_io  [ebx + device.io_addr], 0
  1090.         set_io  [ebx + device.io_addr], reg_eeprom
  1091.  
  1092.         mov     al, EE_CS      ; activate eeprom
  1093.         out     dx, al
  1094.         call    udelay
  1095.  
  1096.         mov     si, EE_READ shl 13
  1097.         xor     ecx, ecx
  1098.   .loop:
  1099.         mov     al, EE_CS + EE_SK
  1100.         shl     si, 1
  1101.         jnc     @f
  1102.         or      al, EE_DI
  1103.        @@:
  1104.         out     dx, al
  1105.         call    udelay
  1106.  
  1107.         and     al, not EE_SK
  1108.         out     dx, al
  1109.         call    udelay
  1110.  
  1111.         inc     ecx
  1112.  
  1113.         cmp     ecx, 15
  1114.         jae     .give_up
  1115.  
  1116.         in      al, dx
  1117.         test    al, EE_DO
  1118.         jnz     .loop
  1119.  
  1120.         xor     al, al
  1121.         out     dx, al          ; de-activate eeprom
  1122.  
  1123.         sub     cl, 3           ; dont count the opcode bits
  1124.         mov     [ebx + device.ee_bus_width], cl
  1125.         DEBUGF  1, "Eeprom width=%u bit\n", ecx
  1126.  
  1127.         ret
  1128.  
  1129.   .give_up:
  1130.         DEBUGF  2, "Eeprom not found!\n"
  1131.  
  1132.         xor     al, al
  1133.         out     dx, al          ; de-activate eeprom
  1134.  
  1135.         ret
  1136.  
  1137.  
  1138. ; Wait a minimum of 2µs
  1139. udelay:
  1140.         pusha
  1141.         mov     esi, 1
  1142.         invoke  Sleep
  1143.         popa
  1144.  
  1145.         ret
  1146.  
  1147.  
  1148.  
  1149. ; cx = phy addr
  1150. ; dx = phy reg addr
  1151.  
  1152. ; ax = data
  1153.  
  1154. align 4
  1155. mdio_read:
  1156.  
  1157.         DEBUGF  1,"MDIO read\n"
  1158.  
  1159.         shl     ecx, 21                 ; PHY addr
  1160.         shl     edx, 16                 ; PHY reg addr
  1161.  
  1162.         mov     eax, ecx
  1163.         or      eax, edx
  1164.         or      eax, 10b shl 26         ; read opcode
  1165.  
  1166.         set_io  [ebx + device.io_addr], 0
  1167.         set_io  [ebx + device.io_addr], reg_mdi_ctrl
  1168.         out     dx, eax
  1169.  
  1170.   .wait:
  1171.         call    udelay
  1172.         in      eax, dx
  1173.         test    eax, 1 shl 28           ; ready bit
  1174.         jz      .wait
  1175.  
  1176.         ret
  1177.  
  1178. ; ax = data
  1179. ; cx = phy addr
  1180. ; dx = phy reg addr
  1181.  
  1182. ; ax = data
  1183.  
  1184. align 4
  1185. mdio_write:
  1186.  
  1187.         DEBUGF  1,"MDIO write\n"
  1188.  
  1189.         and     eax, 0xffff
  1190.  
  1191.         shl     ecx, 21                 ; PHY addr
  1192.         shl     edx, 16                 ; PHY reg addr
  1193.  
  1194.         or      eax, ecx
  1195.         or      eax, edx
  1196.         or      eax, 01b shl 26         ; write opcode
  1197.  
  1198.         set_io  [ebx + device.io_addr], 0
  1199.         set_io  [ebx + device.io_addr], reg_mdi_ctrl
  1200.         out     dx, eax
  1201.  
  1202.   .wait:
  1203.         call    udelay
  1204.         in      eax, dx
  1205.         test    eax, 1 shl 28           ; ready bit
  1206.         jz      .wait
  1207.  
  1208.         ret
  1209.  
  1210. read_mac:
  1211.  
  1212.         ret
  1213.  
  1214.  
  1215.  
  1216. align 4
  1217. MAC_read_eeprom:
  1218.  
  1219.         mov     esi, 0
  1220.         call    ee_read
  1221.         mov     word[ebx + device.mac], si
  1222.  
  1223.         mov     esi, 1
  1224.         call    ee_read
  1225.         mov     word[ebx + device.mac+2], si
  1226.  
  1227.         mov     esi, 2
  1228.         call    ee_read
  1229.         mov     word[ebx + device.mac+4], si
  1230.  
  1231.  
  1232.         ret
  1233.  
  1234.  
  1235. align 4
  1236. MAC_write:
  1237.  
  1238. ;;;;
  1239.  
  1240.         ret
  1241.  
  1242.  
  1243.  
  1244.  
  1245. ; End of code
  1246.  
  1247.  
  1248. data fixups
  1249. end data
  1250.  
  1251. include '../peimport.inc'
  1252.  
  1253. my_service      db 'I8255X', 0                    ; max 16 chars include zero
  1254. devicename      db 'Intel Etherexpress pro/100', 0
  1255.  
  1256. confcmd_data    db 22, 0x08, 0, 0, 0, 0x80, 0x32, 0x03, 1
  1257.                 db 0, 0x2e, 0, 0x60, 0, 0xf2, 0x48, 0, 0x40, 0xf2
  1258.                 db 0x80, 0x3f, 0x05                                     ; 22 bytes total
  1259.  
  1260.  
  1261. device_id_list:
  1262.  
  1263.         dw 0x1029
  1264.         dw 0x1030
  1265.         dw 0x1031
  1266.         dw 0x1032
  1267.         dw 0x1033
  1268.         dw 0x1034
  1269.         dw 0x1038
  1270.         dw 0x1039
  1271.         dw 0x103A
  1272.         dw 0x103B
  1273.         dw 0x103C
  1274.         dw 0x103D
  1275.         dw 0x103E
  1276.         dw 0x1050
  1277.         dw 0x1051
  1278.         dw 0x1052
  1279.         dw 0x1053
  1280.         dw 0x1054
  1281.         dw 0x1055
  1282.         dw 0x1056
  1283.         dw 0x1057
  1284.         dw 0x1059
  1285.         dw 0x1064
  1286.         dw 0x1065
  1287.         dw 0x1066
  1288.         dw 0x1067
  1289.         dw 0x1068
  1290.         dw 0x1069
  1291.         dw 0x106A
  1292.         dw 0x106B
  1293.         dw 0x1091
  1294.         dw 0x1092
  1295.         dw 0x1093
  1296.         dw 0x1094
  1297.         dw 0x1095
  1298.         dw 0x10fe
  1299.         dw 0x1209
  1300.         dw 0x1229
  1301.         dw 0x2449
  1302.         dw 0x2459
  1303.         dw 0x245D
  1304.         dw 0x27DC
  1305.  
  1306. DEVICE_IDs = ($ - device_id_list) / 2
  1307.  
  1308. include_debug_strings                           ; All data wich FDO uses will be included here
  1309.  
  1310. align 4
  1311. devices         dd 0                              ; number of currently running devices
  1312. device_list     rd MAX_DEVICES                    ; This list contains all pointers to device structures the driver is handling
  1313.  
  1314.