Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2004-2014. 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 separate descriptors in memory instead of placing them in front of packets!
  22.  
  23.  
  24. format PE DLL native
  25. entry START
  26.  
  27.         CURRENT_API             = 0x0200
  28.         COMPATIBLE_API          = 0x0100
  29.         API_VERSION             = (COMPATIBLE_API shl 16) + CURRENT_API
  30.  
  31.         MAX_DEVICES             = 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_pe.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. 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. macro delay {
  191.         push    eax
  192.         in      ax, dx
  193.         in      ax, dx
  194.         in      ax, dx
  195.         in      ax, dx
  196.         in      ax, dx
  197.         in      ax, dx
  198.         in      ax, dx
  199.         in      ax, dx
  200.         in      ax, dx
  201.         in      ax, dx
  202.         pop     eax
  203. }
  204.  
  205. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  206. ;;                        ;;
  207. ;; proc START             ;;
  208. ;;                        ;;
  209. ;; (standard driver proc) ;;
  210. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  211.  
  212. proc START c, state:dword
  213.  
  214.         cmp [state], 1
  215.         jne .exit
  216.  
  217.   .entry:
  218.  
  219.         DEBUGF 1,"Loading driver\n"
  220.         invoke  RegService, my_service, service_proc
  221.         ret
  222.  
  223.   .fail:
  224.   .exit:
  225.         xor eax, eax
  226.         ret
  227.  
  228. endp
  229.  
  230.  
  231. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  232. ;;                        ;;
  233. ;; proc SERVICE_PROC      ;;
  234. ;;                        ;;
  235. ;; (standard driver proc) ;;
  236. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  237.  
  238. align 4
  239. proc service_proc stdcall, ioctl:dword
  240.  
  241.         mov     edx, [ioctl]
  242.         mov     eax, [edx + IOCTL.io_code]
  243.  
  244. ;------------------------------------------------------
  245.  
  246.         cmp     eax, 0 ;SRV_GETVERSION
  247.         jne     @F
  248.  
  249.         cmp     [edx + IOCTL.out_size], 4
  250.         jb      .fail
  251.         mov     eax, [edx + IOCTL.output]
  252.         mov     [eax], dword API_VERSION
  253.  
  254.         xor     eax, eax
  255.         ret
  256.  
  257. ;------------------------------------------------------
  258.   @@:
  259.         cmp     eax, 1 ;SRV_HOOK
  260.         jne     .fail
  261.  
  262.         cmp     [edx + IOCTL.inp_size], 3               ; Data input must be at least 3 bytes
  263.         jb      .fail
  264.  
  265.         mov     eax, [edx + IOCTL.input]
  266.         cmp     byte [eax], 1                           ; 1 means device number and bus number (pci) are given
  267.         jne     .fail                                   ; other types arent supported for this card yet
  268.  
  269. ; check if the device is already listed
  270.  
  271.         mov     esi, device_list
  272.         mov     ecx, [devices]
  273.         test    ecx, ecx
  274.         jz      .firstdevice
  275.  
  276. ;        mov     eax, [edx + IOCTL.input]                ; get the pci bus and device numbers
  277.         mov     ax , [eax+1]                            ;
  278.   .nextdevice:
  279.         mov     ebx, [esi]
  280.         cmp     al, byte[ebx + device.pci_bus]
  281.         jne     @f
  282.         cmp     ah, byte[ebx + device.pci_dev]
  283.         je      .find_devicenum                         ; Device is already loaded, let's find it's device number
  284.        @@:
  285.         add     esi, 4
  286.         loop    .nextdevice
  287.  
  288.  
  289. ; This device doesnt have its own eth_device structure yet, lets create one
  290.   .firstdevice:
  291.         cmp     [devices], MAX_DEVICES                  ; First check if the driver can handle one more card
  292.         jae     .fail
  293.  
  294.         allocate_and_clear ebx, sizeof.device, .fail      ; Allocate the buffer for device structure
  295.  
  296. ; Fill in the direct call addresses into the struct
  297.  
  298.         mov     [ebx + device.reset], reset
  299.         mov     [ebx + device.transmit], transmit
  300.         mov     [ebx + device.unload], unload
  301.         mov     [ebx + device.name], my_service
  302.  
  303. ; save the pci bus and device numbers
  304.  
  305.         mov     eax, [edx + IOCTL.input]
  306.         movzx   ecx, byte[eax+1]
  307.         mov     [ebx + device.pci_bus], ecx
  308.         movzx   ecx, byte[eax+2]
  309.         mov     [ebx + device.pci_dev], ecx
  310.  
  311. ; Now, it's time to find the base io addres of the PCI device
  312.  
  313.         stdcall PCI_find_io, [ebx + device.pci_bus], [ebx + device.pci_dev]
  314.         mov     [ebx + device.io_addr], eax
  315.  
  316. ; We've found the io address, find IRQ now
  317.  
  318.         invoke  PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.interrupt_line
  319.         mov     [ebx + device.irq_line], al
  320.  
  321.         DEBUGF  1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
  322.         [ebx + device.pci_dev]:1,[ebx + device.pci_bus]:1,[ebx + device.irq_line]:1,[ebx + device.io_addr]:4
  323.  
  324. ; Ok, the eth_device structure is ready, let's probe the device
  325.  
  326.         pushf
  327.         cli                     ; disable ints untilm initialisation is done
  328.  
  329.         call    probe                                                   ; this function will output in eax
  330.         test    eax, eax
  331.         jnz     .err                                                    ; If an error occured, exit
  332.  
  333.         mov     eax, [devices]                                          ; Add the device structure to our device list
  334.         mov     [device_list+4*eax], ebx                                ; (IRQ handler uses this list to find device)
  335.         inc     [devices]                                               ;
  336.  
  337.         popf
  338.  
  339.         mov     [ebx + device.type], NET_TYPE_ETH
  340.         invoke  NetRegDev
  341.  
  342.         cmp     eax, -1
  343.         je      .err
  344.  
  345.         ret
  346.  
  347. ; If the device was already loaded, find the device number and return it in eax
  348.  
  349.   .find_devicenum:
  350.         DEBUGF  2,"Trying to find device number of already registered device\n"
  351.         invoke  NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
  352.                                                                         ; into a device number in edi
  353.         mov     eax, edi                                                ; Application wants it in eax instead
  354.         DEBUGF  2,"Kernel says: %u\n", eax
  355.         ret
  356.  
  357. ; If an error occured, remove all allocated data and exit (returning -1 in eax)
  358.  
  359.   .err:
  360.         invoke  KernelFree, ebx
  361.  
  362.   .fail:
  363.         or      eax, -1
  364.         ret
  365.  
  366. ;------------------------------------------------------
  367. endp
  368.  
  369.  
  370.  
  371.  
  372.  
  373. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  374. ;;                                                                        ;;
  375. ;;        Actual Hardware dependent code starts here                      ;;
  376. ;;                                                                        ;;
  377. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  378.  
  379.  
  380. unload:
  381.         ; TODO: (in this particular order)
  382.         ;
  383.         ; - Stop the device
  384.         ; - Detach int handler
  385.         ; - Remove device from local list (device_list)
  386.         ; - call unregister function in kernel
  387.         ; - Remove all allocated structures and buffers the card used
  388.  
  389.         or      eax,-1
  390.  
  391. ret
  392.  
  393.  
  394. ;-------------
  395. ;
  396. ; Probe
  397. ;
  398. ;-------------
  399.  
  400. align 4
  401. probe:
  402.  
  403.         DEBUGF  1,"Probing\n"
  404.  
  405. ; Make the device a bus master
  406.         invoke  PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command
  407.         or      al, PCI_CMD_MASTER
  408.         invoke  PciWrite32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command, eax
  409.  
  410. ;---------------------------
  411. ; First, identify the device
  412.  
  413.         invoke  PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header.vendor_id ; get device/vendor id
  414.  
  415.         DEBUGF  1,"Vendor_id=0x%x\n", ax
  416.  
  417.         cmp     ax, 0x8086
  418.         jne     .notfound
  419.         shr     eax, 16
  420.  
  421.         DEBUGF  1,"Device_id=0x%x\n", ax
  422.  
  423.         mov     ecx, DEVICE_IDs
  424.         mov     edi, device_id_list
  425.         repne   scasw
  426.         jne     .notfound
  427.         jmp     .found
  428.  
  429.   .notfound:
  430.         DEBUGF  2,"Unsupported device!\n"
  431.         or      eax, -1
  432.         ret
  433.  
  434.   .found:
  435.  
  436.         call    ee_get_width
  437.         call    MAC_read_eeprom
  438.  
  439.         ;;; TODO: detect phy
  440.  
  441.  
  442.  
  443. ;----------
  444. ;
  445. ;  Reset
  446. ;
  447. ;----------
  448.  
  449. align 4
  450. reset:
  451.  
  452.         movzx   eax, [ebx + device.irq_line]
  453.         DEBUGF  1,"Attaching int handler to irq %x\n", eax:1
  454.         invoke  AttachIntHandler, eax, int_handler, ebx
  455.         test    eax, eax
  456.         jnz     @f
  457.         DEBUGF  2,"Could not attach int handler!\n"
  458.         or      eax, -1
  459.         ret
  460.   @@:
  461.  
  462.         DEBUGF  1,"Resetting\n"
  463.  
  464. ;---------------
  465. ; reset the card
  466.  
  467.         set_io  [ebx + device.io_addr], 0
  468.         set_io  [ebx + device.io_addr], reg_port
  469.         xor     eax, eax        ; Software Reset
  470.         out     dx, eax
  471.  
  472.         mov     esi, 10
  473.         invoke  Sleep           ; Give the card time to warm up.
  474.  
  475. ;---------------------------------
  476. ; Tell device where to store stats
  477.  
  478.         lea     eax, [ebx + device.lstats.tx_good_frames]      ; lstats
  479.         invoke  GetPhysAddr
  480.         set_io  [ebx + device.io_addr], 0
  481.         set_io  [ebx + device.io_addr], reg_scb_ptr
  482.         out     dx, eax
  483.  
  484.         mov     ax, INT_MASK + CU_STATSADDR
  485.         set_io  [ebx + device.io_addr], reg_scb_cmd
  486.         out     dx, ax
  487.         call    cmd_wait
  488.  
  489. ;-----------------
  490. ; setup RX
  491.  
  492.         set_io  [ebx + device.io_addr], reg_scb_ptr
  493.         xor     eax, eax
  494.         out     dx, eax
  495.  
  496.         set_io  [ebx + device.io_addr], reg_scb_cmd
  497.         mov     ax, INT_MASK + RX_ADDR_LOAD
  498.         out     dx, ax
  499.         call    cmd_wait
  500.  
  501. ;-----------------------------
  502. ; Create RX and TX descriptors
  503.  
  504.         call    create_ring
  505.  
  506. ; RX start
  507.  
  508.         set_io  [ebx + device.io_addr], 0
  509.         set_io  [ebx + device.io_addr], reg_scb_ptr
  510.         mov     eax, [ebx + device.rx_desc]
  511.         invoke  GetPhysAddr
  512.         out     dx, eax
  513.  
  514.         mov     ax, INT_MASK + RX_START
  515.         set_io  [ebx + device.io_addr], reg_scb_cmd
  516.         out     dx, ax
  517.         call    cmd_wait
  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, INT_MASK + CU_CMD_BASE
  527.         out     dx, ax
  528.         call    cmd_wait
  529.  
  530. ;  --------------------
  531.  
  532.         mov     [ebx + device.confcmd.command], CmdConfigure + Cmdsuspend
  533.         mov     [ebx + device.confcmd.status], 0
  534.         lea     eax, [ebx + device.txfd.status]
  535.         invoke  GetPhysAddr
  536.         mov     [ebx + device.confcmd.link], eax
  537.  
  538.         mov     esi, confcmd_data
  539.         lea     edi, [ebx + device.confcmd.data]
  540.         mov     ecx, 22
  541.         rep     movsb
  542.  
  543.         mov     byte[ebx + device.confcmd.data + 1], 0x88  ; fifo of 8 each
  544.         mov     byte[ebx + device.confcmd.data + 4], 0
  545.         mov     byte[ebx + device.confcmd.data + 5], 0x80
  546.         mov     byte[ebx + device.confcmd.data + 15], 0x48
  547.         mov     byte[ebx + device.confcmd.data + 19], 0x80
  548.         mov     byte[ebx + device.confcmd.data + 21], 0x05
  549.  
  550.         mov     [ebx + device.txfd.command], CmdIASetup
  551.         mov     [ebx + device.txfd.status], 0
  552.         lea     eax, [ebx + device.confcmd.status]
  553.         invoke  GetPhysAddr
  554.         mov     [ebx + device.txfd.link], eax
  555.  
  556. ;;; copy in our MAC
  557.  
  558.         lea     edi, [ebx + device.txfd.desc_addr]
  559.         lea     esi, [ebx + device.mac]
  560.         movsd
  561.         movsw
  562.  
  563.         set_io  [ebx + device.io_addr], reg_scb_ptr
  564.         lea     eax, [ebx + device.txfd.status]
  565.         invoke  GetPhysAddr
  566.         out     dx, eax
  567.  
  568. ; Start CU & enable ints
  569.  
  570.         set_io  [ebx + device.io_addr], reg_scb_cmd
  571.         mov     ax, CU_START
  572.         out     dx, ax
  573.         call    cmd_wait
  574.  
  575. ;-----------------------
  576. ; build txfd structure (again!)
  577.  
  578.         lea     eax, [ebx + device.txfd.status]
  579.         invoke  GetPhysAddr
  580.         mov     [ebx + device.txfd.link], eax
  581.         mov     [ebx + device.txfd.count], 0x02208000
  582.         lea     eax, [ebx + device.txfd.buf_addr0]
  583.         invoke  GetPhysAddr
  584.         mov     [ebx + device.txfd.desc_addr], eax
  585.  
  586. ; Indicate that we have successfully reset the card
  587.  
  588.         DEBUGF  1,"Reset complete\n"
  589.  
  590.         mov     [ebx + device.mtu], 1514
  591.  
  592. ; Set link state to unknown
  593.         mov     [ebx + device.state], ETH_LINK_UNKNOWN
  594.  
  595.         xor     eax, eax        ; indicate that we have successfully reset the card
  596.         ret
  597.  
  598.  
  599. align 4
  600. create_ring:
  601.  
  602.         DEBUGF  1,"Creating ring\n"
  603.  
  604. ;---------------------
  605. ; build rxfd structure
  606.  
  607.         invoke  KernelAlloc, 2000
  608.         mov     [ebx + device.rx_desc], eax
  609.         mov     esi, eax
  610.         invoke  GetPhysAddr
  611.         mov     [esi + rxfd.status], 0x0000
  612.         mov     [esi + rxfd.command], 0x0000
  613.         mov     [esi + rxfd.link], eax
  614.         mov     [esi + rxfd.count], 0
  615.         mov     [esi + rxfd.size], 1528
  616.  
  617. ;-----------------------
  618. ; build txfd structure
  619.  
  620.         lea     eax, [ebx + device.txfd.status]
  621.         invoke  GetPhysAddr
  622.         mov     [ebx + device.txfd.link], eax
  623.         mov     [ebx + device.txfd.count], 0x02208000
  624.         lea     eax, [ebx + device.txfd.buf_addr0]
  625.         invoke  GetPhysAddr
  626.         mov     [ebx + device.txfd.desc_addr], eax
  627.  
  628.         ret
  629.  
  630.  
  631.  
  632. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  633. ;;                                         ;;
  634. ;; Transmit                                ;;
  635. ;;                                         ;;
  636. ;; In: pointer to device structure in ebx  ;;
  637. ;;                                         ;;
  638. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  639.  
  640. proc transmit stdcall bufferptr, buffersize
  641.  
  642.         pushf
  643.         cli
  644.  
  645.         DEBUGF  1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [buffersize]
  646.         mov     eax, [bufferptr]
  647.         DEBUGF  1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
  648.         [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
  649.         [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
  650.         [eax+13]:2,[eax+12]:2
  651.  
  652.         cmp     [buffersize], 1514
  653.         ja      .fail
  654.         cmp     [buffersize], 60
  655.         jb      .fail
  656.  
  657.         ;;; TODO: check if current descriptor is in use
  658.         ; fill in buffer address and size
  659.         mov     [ebx + device.last_tx_buffer], eax
  660.         invoke  GetPhysAddr
  661.         mov     [ebx + device.txfd.buf_addr0], eax
  662.         mov     ecx, [buffersize]
  663.         mov     [ebx + device.txfd.buf_size0], ecx
  664.  
  665.         mov     [ebx + device.txfd.status], 0
  666.         mov     [ebx + device.txfd.command], Cmdsuspend + CmdTx + CmdTxFlex + 1 shl 15 ;;; EL bit
  667.  ;       mov     [txfd.count], 0x02208000   ;;;;;;;;;;;
  668.  
  669.         ; Inform device of the new/updated transmit descriptor
  670.         lea     eax, [ebx + device.txfd.status]
  671.         invoke  GetPhysAddr
  672.         set_io  [ebx + device.io_addr], 0
  673.         set_io  [ebx + device.io_addr], reg_scb_ptr
  674.         out     dx, eax
  675.  
  676.         ; Start the transmit
  677.         mov     ax, CU_START
  678.         set_io  [ebx + device.io_addr], reg_scb_cmd
  679.         out     dx, ax
  680.         call    cmd_wait
  681.  
  682. ; Update stats
  683.         inc     [ebx + device.packets_tx]
  684.         mov     ecx, [buffersize]
  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  KernelFree, [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 + 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 + rxfd.status]:4
  760.  
  761.         movzx   ecx, [esi + rxfd.count]
  762.         and     ecx, 0x3fff
  763.  
  764.         push    ebx
  765.         push    .rx_loop
  766.         push    ecx
  767.         add     esi, rxfd.packet
  768.         push    esi
  769.  
  770. ; Update stats
  771.         add     dword [ebx + device.bytes_rx], ecx
  772.         adc     dword [ebx + device.bytes_rx + 4], 0
  773.         inc     dword [ebx + device.packets_rx]
  774.  
  775. ; allocate new descriptor
  776.  
  777.         invoke  KernelAlloc, 2000
  778.         mov     [ebx + device.rx_desc], eax
  779.         mov     esi, eax
  780.         invoke  GetPhysAddr
  781.         mov     [esi + rxfd.status], 0x0000
  782.         mov     [esi + rxfd.command], 0xc000    ; End of list + Suspend
  783.         mov     [esi + rxfd.link], eax
  784.         mov     [esi + rxfd.count], 0
  785.         mov     [esi + rxfd.size], 1528
  786.  
  787. ; restart RX
  788.  
  789.         set_io  [ebx + device.io_addr], 0
  790.         set_io  [ebx + device.io_addr], reg_scb_ptr
  791. ;        lea     eax, [ebx + device.rx_desc]
  792. ;        invoke  GetPhysAddr
  793.         out     dx, eax
  794.  
  795.         set_io  [ebx + device.io_addr], reg_scb_cmd
  796.         mov     ax, RX_START
  797.         out     dx, ax
  798.         call    cmd_wait
  799.  
  800. ; And give packet to kernel
  801.         jmp     [Eth_input]
  802.  
  803.   .nodata:
  804.         DEBUGF  1, "no more data\n"
  805.         pop     ax
  806.  
  807.   .no_rx:
  808.  
  809. ; Cleanup after TX
  810.         cmp     [ebx + device.txfd.status], 0
  811.         je      .done
  812.         cmp     [ebx + device.last_tx_buffer], 0
  813.         je      .done
  814.         push    ax
  815.         DEBUGF  1, "Removing packet 0x%x from RAM!\n", [ebx + device.last_tx_buffer]
  816.         invoke  KernelFree, [ebx + device.last_tx_buffer]
  817.         mov     [ebx + device.last_tx_buffer], 0
  818.         pop     ax
  819.  
  820.   .done:
  821.         and     ax, 00111100b
  822.         cmp     ax, 00001000b
  823.         jne     .fail
  824.  
  825.         DEBUGF  1, "out of resources!\n"
  826. ; Restart the RX
  827.  
  828. ; allocate new descriptor
  829.  
  830.         invoke  KernelAlloc, 2000
  831.         mov     [ebx + device.rx_desc], eax
  832.         mov     esi, eax
  833.         invoke  GetPhysAddr
  834.         mov     [esi + rxfd.status], 0x0000
  835.         mov     [esi + rxfd.command], 0xc000    ; End of list + Suspend
  836.         mov     [esi + rxfd.link], eax
  837.         mov     [esi + rxfd.count], 0
  838.         mov     [esi + rxfd.size], 1528
  839.  
  840. ; restart RX
  841.  
  842.         set_io  [ebx + device.io_addr], 0
  843.         set_io  [ebx + device.io_addr], reg_scb_ptr
  844. ;        lea     eax, [ebx + device.rx_desc]
  845. ;        invoke  GetPhysAddr
  846.         out     dx, eax
  847.  
  848.         set_io  [ebx + device.io_addr], reg_scb_cmd
  849.         mov     ax, RX_START
  850.         out     dx, ax
  851.         call    cmd_wait
  852.  
  853.   .fail:
  854.         pop     edi esi ebx
  855.         xor     eax, eax
  856.         inc     eax
  857.  
  858.         ret
  859.  
  860.  
  861.  
  862.  
  863. align 4
  864. cmd_wait:
  865.  
  866.         in      al, dx
  867.         test    al, al
  868.         jnz     cmd_wait
  869.  
  870.         ret
  871.  
  872.  
  873.  
  874.  
  875.  
  876.  
  877. align 4
  878. ee_read:        ; esi = address to read
  879.  
  880.         DEBUGF  1,"Eeprom read from 0x%x\n", esi
  881.  
  882.         set_io  [ebx + device.io_addr], 0
  883.         set_io  [ebx + device.io_addr], reg_eeprom
  884.  
  885. ;-----------------------------------------------------
  886. ; Prepend start bit + read opcode to the address field
  887. ; and shift it to the very left bits of esi
  888.  
  889.         mov     cl, 29
  890.         sub     cl, [ebx + device.ee_bus_width]
  891.         shl     esi, cl
  892.         or      esi, EE_READ shl 29
  893.  
  894.         movzx   ecx, [ebx + device.ee_bus_width]
  895.         add     ecx, 3
  896.  
  897.         mov     al, EE_CS
  898.         out     dx, al
  899.         delay
  900.  
  901. ;-----------------------
  902. ; Write this to the chip
  903.  
  904.   .loop:
  905.         mov     al, EE_CS + EE_SK
  906.         shl     esi, 1
  907.         jnc     @f
  908.         or      al, EE_DI
  909.        @@:
  910.         out     dx, al
  911.         delay
  912.  
  913.         and     al, not EE_SK
  914.         out     dx, al
  915.         delay
  916.  
  917.         loop    .loop
  918.  
  919. ;------------------------------
  920. ; Now read the data from eeprom
  921.  
  922.         xor     esi, esi
  923.         mov     ecx, 16
  924.  
  925.   .loop2:
  926.         shl     esi, 1
  927.         mov     al, EE_CS + EE_SK
  928.         out     dx, al
  929.         delay
  930.  
  931.         in      al, dx
  932.         test    al, EE_DO
  933.         jz      @f
  934.         inc     esi
  935.        @@:
  936.  
  937.         mov     al, EE_CS
  938.         out     dx, al
  939.         delay
  940.  
  941.         loop    .loop2
  942.  
  943. ;-----------------------
  944. ; de-activate the eeprom
  945.  
  946.         xor     ax, ax
  947.         out     dx, ax
  948.  
  949.  
  950.         DEBUGF  1,"0x%x\n", esi:4
  951.         ret
  952.  
  953.  
  954.  
  955. align 4
  956. ee_write:       ; esi = address to write to, di = data
  957.  
  958.         DEBUGF  1,"Eeprom write 0x%x to 0x%x\n", di, esi
  959.  
  960.         set_io  [ebx + device.io_addr], 0
  961.         set_io  [ebx + device.io_addr], reg_eeprom
  962.  
  963. ;-----------------------------------------------------
  964. ; Prepend start bit + write opcode to the address field
  965. ; and shift it to the very left bits of esi
  966.  
  967.         mov     cl, 29
  968.         sub     cl, [ebx + device.ee_bus_width]
  969.         shl     esi, cl
  970.         or      esi, EE_WRITE shl 29
  971.  
  972.         movzx   ecx, [ebx + device.ee_bus_width]
  973.         add     ecx, 3
  974.  
  975.         mov     al, EE_CS       ; enable chip
  976.         out     dx, al
  977.  
  978. ;-----------------------
  979. ; Write this to the chip
  980.  
  981.   .loop:
  982.         mov     al, EE_CS + EE_SK
  983.         shl     esi, 1
  984.         jnc     @f
  985.         or      al, EE_DI
  986.        @@:
  987.         out     dx, al
  988.         delay
  989.  
  990.         and     al, not EE_SK
  991.         out     dx, al
  992.         delay
  993.  
  994.         loop    .loop
  995.  
  996. ;-----------------------------
  997. ; Now write the data to eeprom
  998.  
  999.         mov     ecx, 16
  1000.  
  1001.   .loop2:
  1002.         mov     al, EE_CS + EE_SK
  1003.         shl     di, 1
  1004.         jnc     @f
  1005.         or      al, EE_DI
  1006.        @@:
  1007.         out     dx, al
  1008.         delay
  1009.  
  1010.         and     al, not EE_SK
  1011.         out     dx, al
  1012.         delay
  1013.  
  1014.         loop    .loop2
  1015.  
  1016. ;-----------------------
  1017. ; de-activate the eeprom
  1018.  
  1019.         xor     al, al
  1020.         out     dx, al
  1021.  
  1022.  
  1023.         ret
  1024.  
  1025.  
  1026.  
  1027. align 4
  1028. ee_get_width:
  1029.  
  1030.         set_io  [ebx + device.io_addr], 0
  1031.         set_io  [ebx + device.io_addr], reg_eeprom
  1032.  
  1033.         mov     al, EE_CS      ; activate eeprom
  1034.         out     dx, al
  1035.         delay
  1036.  
  1037.         mov     si, EE_READ shl 13
  1038.         xor     ecx, ecx
  1039.   .loop:
  1040.         mov     al, EE_CS + EE_SK
  1041.         shl     si, 1
  1042.         jnc     @f
  1043.         or      al, EE_DI
  1044.        @@:
  1045.         out     dx, al
  1046.         delay
  1047.  
  1048.         and     al, not EE_SK
  1049.         out     dx, al
  1050.         delay
  1051.  
  1052.         inc     ecx
  1053.  
  1054.         cmp     ecx, 15
  1055.         jae     .give_up
  1056.  
  1057.         in      al, dx
  1058.         test    al, EE_DO
  1059.         jnz     .loop
  1060.  
  1061.         xor     al, al
  1062.         out     dx, al          ; de-activate eeprom
  1063.  
  1064.         sub     cl, 3           ; dont count the opcode bits
  1065.         mov     [ebx + device.ee_bus_width], cl
  1066.         DEBUGF  1, "Eeprom width=%u bit\n", ecx
  1067.  
  1068.         ret
  1069.  
  1070.   .give_up:
  1071.         DEBUGF  2, "Eeprom not found!\n"
  1072.  
  1073.         xor     al, al
  1074.         out     dx, al          ; de-activate eeprom
  1075.  
  1076.         ret
  1077.  
  1078.  
  1079.  
  1080. ; cx = phy addr
  1081. ; dx = phy reg addr
  1082.  
  1083. ; ax = data
  1084.  
  1085. align 4
  1086. mdio_read:
  1087.  
  1088.         DEBUGF  1,"MDIO read\n"
  1089.  
  1090.         shl     ecx, 21                 ; PHY addr
  1091.         shl     edx, 16                 ; PHY reg addr
  1092.  
  1093.         mov     eax, ecx
  1094.         or      eax, edx
  1095.         or      eax, 10b shl 26         ; read opcode
  1096.  
  1097.         set_io  [ebx + device.io_addr], 0
  1098.         set_io  [ebx + device.io_addr], reg_mdi_ctrl
  1099.         out     dx, eax
  1100.  
  1101.   .wait:
  1102.         delay
  1103.         in      eax, dx
  1104.         test    eax, 1 shl 28           ; ready bit
  1105.         jz      .wait
  1106.  
  1107.         ret
  1108.  
  1109. ; ax = data
  1110. ; cx = phy addr
  1111. ; dx = phy reg addr
  1112.  
  1113. ; ax = data
  1114.  
  1115. align 4
  1116. mdio_write:
  1117.  
  1118.         DEBUGF  1,"MDIO write\n"
  1119.  
  1120.         and     eax, 0xffff
  1121.  
  1122.         shl     ecx, 21                 ; PHY addr
  1123.         shl     edx, 16                 ; PHY reg addr
  1124.  
  1125.         or      eax, ecx
  1126.         or      eax, edx
  1127.         or      eax, 01b shl 26         ; write opcode
  1128.  
  1129.         set_io  [ebx + device.io_addr], 0
  1130.         set_io  [ebx + device.io_addr], reg_mdi_ctrl
  1131.         out     dx, eax
  1132.  
  1133.   .wait:
  1134.         delay
  1135.         in      eax, dx
  1136.         test    eax, 1 shl 28           ; ready bit
  1137.         jz      .wait
  1138.  
  1139.         ret
  1140.  
  1141. read_mac:
  1142.  
  1143.         ret
  1144.  
  1145.  
  1146.  
  1147. align 4
  1148. MAC_read_eeprom:
  1149.  
  1150.         mov     esi, 0
  1151.         call    ee_read
  1152.         mov     word[ebx + device.mac], si
  1153.  
  1154.         mov     esi, 1
  1155.         call    ee_read
  1156.         mov     word[ebx + device.mac+2], si
  1157.  
  1158.         mov     esi, 2
  1159.         call    ee_read
  1160.         mov     word[ebx + device.mac+4], si
  1161.  
  1162.  
  1163.         ret
  1164.  
  1165.  
  1166. align 4
  1167. MAC_write:
  1168.  
  1169. ;;;;
  1170.  
  1171.         ret
  1172.  
  1173.  
  1174.  
  1175.  
  1176. ; End of code
  1177.  
  1178.  
  1179. data fixups
  1180. end data
  1181.  
  1182. include '../peimport.inc'
  1183.  
  1184. my_service      db 'I8255X', 0                    ; max 16 chars include zero
  1185. devicename      db 'Intel Etherexpress pro/100', 0
  1186.  
  1187. confcmd_data    db 22, 0x08, 0, 0, 0, 0x80, 0x32, 0x03, 1
  1188.                 db 0, 0x2e, 0, 0x60, 0, 0xf2, 0x48, 0, 0x40, 0xf2
  1189.                 db 0x80, 0x3f, 0x05                                     ; 22 bytes total
  1190.  
  1191.  
  1192. device_id_list:
  1193.  
  1194.         dw 0x1029
  1195.         dw 0x1030
  1196.         dw 0x1031
  1197.         dw 0x1032
  1198.         dw 0x1033
  1199.         dw 0x1034
  1200.         dw 0x1038
  1201.         dw 0x1039
  1202.         dw 0x103A
  1203.         dw 0x103B
  1204.         dw 0x103C
  1205.         dw 0x103D
  1206.         dw 0x103E
  1207.         dw 0x1050
  1208.         dw 0x1051
  1209.         dw 0x1052
  1210.         dw 0x1053
  1211.         dw 0x1054
  1212.         dw 0x1055
  1213.         dw 0x1056
  1214.         dw 0x1057
  1215.         dw 0x1059
  1216.         dw 0x1064
  1217.         dw 0x1065
  1218.         dw 0x1066
  1219.         dw 0x1067
  1220.         dw 0x1068
  1221.         dw 0x1069
  1222.         dw 0x106A
  1223.         dw 0x106B
  1224.         dw 0x1091
  1225.         dw 0x1092
  1226.         dw 0x1093
  1227.         dw 0x1094
  1228.         dw 0x1095
  1229.         dw 0x10fe
  1230.         dw 0x1209
  1231.         dw 0x1229
  1232.         dw 0x2449
  1233.         dw 0x2459
  1234.         dw 0x245D
  1235.         dw 0x27DC
  1236.  
  1237. DEVICE_IDs = ($ - device_id_list) / 2
  1238.  
  1239. include_debug_strings                           ; All data wich FDO uses will be included here
  1240.  
  1241. align 4
  1242. devices         dd 0                              ; number of currently running devices
  1243. device_list     rd MAX_DEVICES                    ; This list contains all pointers to device structures the driver is handling
  1244.  
  1245.