Subversion Repositories Kolibri OS

Rev

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

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