Subversion Repositories Kolibri OS

Rev

Rev 2220 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

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