Subversion Repositories Kolibri OS

Rev

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

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