Subversion Repositories Kolibri OS

Rev

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