Subversion Repositories Kolibri OS

Rev

Rev 4467 | Rev 4582 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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