Subversion Repositories Kolibri OS

Rev

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

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