Subversion Repositories Kolibri OS

Rev

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