Subversion Repositories Kolibri OS

Rev

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