Subversion Repositories Kolibri OS

Rev

Rev 3155 | Blame | Last modification | View Log | Download | RSS feed

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