Subversion Repositories Kolibri OS

Rev

Rev 5363 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                    ;;
  3. ;; Copyright (C) KolibriOS team 2004-2015. All rights reserved.       ;;
  4. ;; Distributed under terms of the GNU General Public License          ;;
  5. ;;                                                                    ;;
  6. ;;  Ethernet driver for KolibriOS                                     ;;
  7. ;;  This is an adaptation of MenuetOS driver with minimal changes.    ;;
  8. ;;  Changes were made by CleverMouse. Original copyright follows.     ;;
  9. ;;                                                                    ;;
  10. ;;  This driver is based on the SIS900 driver from                    ;;
  11. ;;  the etherboot 5.0.6 project. The copyright statement is           ;;
  12. ;;                                                                    ;;
  13. ;;          GNU GENERAL PUBLIC LICENSE                                ;;
  14. ;;             Version 2, June 1991                                   ;;
  15. ;;                                                                    ;;
  16. ;;  remaining parts Copyright 2004 Jason Delozier,                    ;;
  17. ;;   cordata51@hotmail.com                                            ;;
  18. ;;                                                                    ;;
  19. ;;  See file COPYING for details                                      ;;
  20. ;;                                                                    ;;
  21. ;;  Updates:                                                          ;;
  22. ;;    Revision Look up table and SIS635 Mac Address by Jarek Pelczar  ;;
  23. ;;                                                                    ;;
  24. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  25.  
  26. format PE DLL native
  27. entry START
  28.  
  29.         CURRENT_API             = 0x0200
  30.         COMPATIBLE_API          = 0x0100
  31.         API_VERSION             = (COMPATIBLE_API shl 16) + CURRENT_API
  32.  
  33.         NUM_RX_DESC             = 4             ; Number of RX descriptors
  34.         NUM_TX_DESC             = 4             ; Number of TX descriptors
  35.         RX_BUFF_SZ              = 1520          ; Buffer size for each Rx buffer
  36.  
  37.         MAX_DEVICES             = 16
  38.  
  39.         __DEBUG__               = 1
  40.         __DEBUG_LEVEL__         = 2             ; 1 = verbose, 2 = errors only
  41.  
  42.         DSIZE                   = 0x00000fff
  43.         CRC_SIZE                = 4
  44.         RFADDR_shift            = 16
  45.  
  46. ; If you are having problems sending/receiving packet try changing the
  47. ; Max DMA Burst, Possible settings are as follows:
  48. ;
  49. ; 0x00000000 = 512 bytes
  50. ; 0x00100000 = 4 bytes
  51. ; 0x00200000 = 8 bytes
  52. ; 0x00300000 = 16 bytes
  53. ; 0x00400000 = 32 bytes
  54. ; 0x00500000 = 64 bytes
  55. ; 0x00600000 = 128 bytes
  56. ; 0x00700000 = 256 bytes
  57.  
  58.         RX_DMA                  = 0x00600000
  59.         TX_DMA                  = 0x00600000
  60.  
  61. ;-------------------------------------------------------------------------------------------------
  62. ; Symbolic offsets to registers.
  63.         cr              = 0x0           ; Command Register
  64.         cfg             = 0x4           ; Configuration Register
  65.         mear            = 0x8           ; EEPROM Access Register
  66.         ptscr           = 0xc           ; PCI Test Control Register
  67.         isr             = 0x10          ; Interrupt Status Register
  68.         imr             = 0x14          ; Interrupt Mask Register
  69.         ier             = 0x18          ; Interrupt Enable Register
  70.         epar            = 0x18          ; Enhanced PHY Access Register
  71.         txdp            = 0x20          ; Transmit Descriptor Pointer Register
  72.         txcfg           = 0x24          ; Transmit Configuration Register
  73.         rxdp            = 0x30          ; Receive Descriptor Pointer Register
  74.         rxcfg           = 0x34          ; Receive Configuration Register
  75.         flctrl          = 0x38          ; Flow Control Register
  76.         rxlen           = 0x3c          ; Receive Packet Length Register
  77.         rfcr            = 0x48          ; Receive Filter Control Register
  78.         rfdr            = 0x4C          ; Receive Filter Data Register
  79.         pmctrl          = 0xB0          ; Power Management Control Register
  80.         pmer            = 0xB4          ; Power Management Wake-up Event Register
  81.  
  82. ; Command Register Bits
  83.         RELOAD          = 0x00000400
  84.         ACCESSMODE      = 0x00000200
  85.         RESET           = 0x00000100
  86.         SWI             = 0x00000080
  87.         RxRESET         = 0x00000020
  88.         TxRESET         = 0x00000010
  89.         RxDIS           = 0x00000008
  90.         RxENA           = 0x00000004
  91.         TxDIS           = 0x00000002
  92.         TxENA           = 0x00000001
  93.  
  94. ; Configuration Register Bits
  95.         DESCRFMT        = 0x00000100    ; 7016 specific
  96.         REQALG          = 0x00000080
  97.         SB              = 0x00000040
  98.         POW             = 0x00000020
  99.         EXD             = 0x00000010
  100.         PESEL           = 0x00000008
  101.         LPM             = 0x00000004
  102.         BEM             = 0x00000001
  103.         RND_CNT         = 0x00000400
  104.         FAIR_BACKOFF    = 0x00000200
  105.         EDB_MASTER_EN   = 0x00002000
  106.  
  107. ; Eeprom Access Reigster Bits
  108.         MDC             = 0x00000040
  109.         MDDIR           = 0x00000020
  110.         MDIO            = 0x00000010    ; 7016 specific
  111.         EECS            = 0x00000008
  112.         EECLK           = 0x00000004
  113.         EEDO            = 0x00000002
  114.         EEDI            = 0x00000001
  115.  
  116. ; TX Configuration Register Bits
  117.         ATP             = 0x10000000    ; Automatic Transmit Padding
  118.         MLB             = 0x20000000    ; Mac Loopback Enable
  119.         HBI             = 0x40000000    ; HeartBeat Ignore (Req for full-dup)
  120.         CSI             = 0x80000000    ; CarrierSenseIgnore (Req for full-du
  121.  
  122. ; RX Configuration Register Bits
  123.         AJAB            = 0x08000000    ;
  124.         ATX             = 0x10000000    ; Accept Transmit Packets
  125.         ARP             = 0x40000000    ; accept runt packets (<64bytes)
  126.         AEP             = 0x80000000    ; accept error packets
  127.  
  128. ; Interrupt Register Bits
  129.         WKEVT           = 0x10000000
  130.         TxPAUSEEND      = 0x08000000
  131.         TxPAUSE         = 0x04000000
  132.         TxRCMP          = 0x02000000    ; Transmit Reset Complete
  133.         RxRCMP          = 0x01000000    ; Receive Reset Complete
  134.         DPERR           = 0x00800000
  135.         SSERR           = 0x00400000
  136.         RMABT           = 0x00200000
  137.         RTABT           = 0x00100000
  138.         RxSOVR          = 0x00010000
  139.         HIBERR          = 0x00008000
  140.         SWINT           = 0x00001000
  141.         MIBINT          = 0x00000800
  142.         TxURN           = 0x00000400
  143.         TxIDLE          = 0x00000200
  144.         TxERR           = 0x00000100
  145.         TxDESC          = 0x00000080
  146.         TxOK            = 0x00000040
  147.         RxORN           = 0x00000020
  148.         RxIDLE          = 0x00000010
  149.         RxEARLY         = 0x00000008
  150.         RxERR           = 0x00000004
  151.         RxDESC          = 0x00000002
  152.         RxOK            = 0x00000001
  153.  
  154. ; Interrupt Enable Register Bits
  155.         IE              = RxOK + TxOK
  156.  
  157. ; Revision ID
  158.         SIS900B_900_REV         = 0x03
  159.         SIS630A_900_REV         = 0x80
  160.         SIS630E_900_REV         = 0x81
  161.         SIS630S_900_REV         = 0x82
  162.         SIS630EA1_900_REV       = 0x83
  163.         SIS630ET_900_REV        = 0x84
  164.         SIS635A_900_REV         = 0x90
  165.         SIS900_960_REV          = 0x91
  166.  
  167. ; Receive Filter Control Register Bits
  168.         RFEN            = 0x80000000            ; enable
  169.         RFAAB           = 0x40000000            ; accept all broadcasts
  170.         RFAAM           = 0x20000000            ; accept all multicasts
  171.         RFAAP           = 0x10000000            ; accept all packets
  172.  
  173. ; Reveive Filter Data Mask
  174.         RFDAT           = 0x0000FFFF
  175.  
  176. ; Eeprom Address
  177.         EEPROMSignature = 0x00
  178.         EEPROMVendorID  = 0x02
  179.         EEPROMDeviceID  = 0x03
  180.         EEPROMMACAddr   = 0x08
  181.         EEPROMChecksum  = 0x0b
  182.  
  183. ; The EEPROM commands include the alway-set leading bit.
  184.         EEread          = 0x0180
  185.         EEwrite         = 0x0140
  186.         EEerase         = 0x01C0
  187.         EEwriteEnable   = 0x0130
  188.         EEwriteDisable  = 0x0100
  189.         EEeraseAll      = 0x0120
  190.         EEwriteAll      = 0x0110
  191.         EEaddrMask      = 0x013F
  192.         EEcmdShift      = 16
  193.  
  194. ; For SiS962 or SiS963, request the eeprom software access
  195.         EEREQ           = 0x00000400
  196.         EEDONE          = 0x00000200
  197.         EEGNT           = 0x00000100
  198.  
  199. section '.flat' readable writable executable
  200.  
  201. include '../proc32.inc'
  202. include '../struct.inc'
  203. include '../macros.inc'
  204. include '../fdo.inc'
  205. include '../netdrv.inc'
  206.  
  207.  
  208. struct  device          ETH_DEVICE
  209.  
  210.         io_addr         dd ?
  211.         pci_bus         dd ?
  212.         pci_dev         dd ?
  213.         irq_line        db ?
  214.         cur_rx          db ?
  215.         cur_tx          db ?
  216.         last_tx         db ?
  217.         pci_revision    db ?
  218.         table_entries   db ?
  219.  
  220.         rb 0x100 - ($ and 0xff) ; align 256
  221.         txd             rd (4 * NUM_TX_DESC)
  222.         rxd             rd (4 * NUM_RX_DESC)
  223.  
  224. ends
  225.  
  226. macro   ee_delay {
  227.         push    eax
  228.         in      eax, dx
  229.         in      eax, dx
  230.         in      eax, dx
  231.         in      eax, dx
  232.         in      eax, dx
  233.         in      eax, dx
  234.         in      eax, dx
  235.         in      eax, dx
  236.         in      eax, dx
  237.         in      eax, dx
  238.         pop     eax
  239. }
  240.  
  241. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  242. ;;                        ;;
  243. ;; proc START             ;;
  244. ;;                        ;;
  245. ;; (standard driver proc) ;;
  246. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  247.  
  248. ; Driver entry point - register our service when the driver is loading.
  249. ; TODO: add needed operations when unloading
  250.  
  251. proc START c, reason:dword, cmdline:dword
  252.  
  253.         cmp     [reason], DRV_ENTRY
  254.         jne     .fail
  255.  
  256.         DEBUGF  2,"Loading driver\n"
  257.         invoke  RegService, my_service, service_proc
  258.         ret
  259.  
  260.   .fail:
  261.         xor     eax, eax
  262.         ret
  263.  
  264. endp
  265.  
  266.  
  267. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  268. ;;                        ;;
  269. ;; proc SERVICE_PROC      ;;
  270. ;;                        ;;
  271. ;; (standard driver proc) ;;
  272. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  273.  
  274. ; Service procedure for the driver - handle all I/O requests for the driver.
  275. ; Currently handled requests are: SRV_GETVERSION = 0 and SRV_HOOK = 1.
  276. service_proc:
  277. ; 1. Get parameter from the stack: [esp+4] is the first parameter,
  278. ;       pointer to IOCTL structure.
  279.         mov     edx, [esp+4]    ; edx -> IOCTL
  280. ; 2. Get request code and select a handler for the code.
  281.         mov     eax, [edx + IOCTL.io_code]
  282.         test    eax, eax        ; check for SRV_GETVERSION
  283.         jnz     @f
  284. ; 3. This is SRV_GETVERSION request, no input, 4 bytes output, API_VERSION.
  285. ; 3a. Output size must be at least 4 bytes.
  286.         cmp     [edx + IOCTL.out_size], 4
  287.         jb      .fail
  288. ; 3b. Write result to the output buffer.
  289.         mov     eax, [edx + IOCTL.output]
  290.         mov     [eax], dword API_VERSION
  291. ; 3c. Return success.
  292.         xor     eax, eax
  293.         ret     4
  294.   @@:
  295.         dec     eax     ; check for SRV_HOOK
  296.         jnz     .fail
  297. ; 4. This is SRV_HOOK request, input defines the device to hook, no output.
  298. ; 4a. The driver works only with PCI devices,
  299. ;       so input must be at least 3 bytes long.
  300.         cmp     [edx + IOCTL.inp_size], 3
  301.         jb      .fail
  302. ; 4b. First byte of input is bus type, 1 stands for PCI.
  303.         mov     eax, [edx + IOCTL.input]
  304.         cmp     byte [eax], 1
  305.         jne     .fail
  306. ; 4c. Second and third bytes of the input define the device: bus and dev.
  307. ;       Word in bx holds both bytes.
  308.         mov     bx, [eax+1]
  309. ; 4d. Check if the device was already hooked,
  310. ;       scan through the list of known devices.
  311. ; check if the device is already listed
  312.         mov     esi, device_list
  313.         mov     ecx, [devices]
  314.         test    ecx, ecx
  315.         jz      .firstdevice
  316.  
  317. ;        mov     eax, [edx + IOCTL.input]                ; get the pci bus and device numbers
  318.         mov     ax, [eax+1]                             ;
  319.   .nextdevice:
  320.         mov     ebx, [esi]
  321.         cmp     al, byte[ebx + device.pci_bus]
  322.         jne     @f
  323.         cmp     ah, byte[ebx + device.pci_dev]
  324.         je      .find_devicenum                         ; Device is already loaded, let's find it's device number
  325.        @@:
  326.         add     esi, 4
  327.         loop    .nextdevice
  328. ; 4e. This device doesn't have its own eth_device structure yet, let's create one
  329.   .firstdevice:
  330. ; 4f. Check that we have place for new device.
  331.         cmp     [devices], MAX_DEVICES
  332.         jae     .fail
  333. ; 4g. Allocate memory for device descriptor and receive+transmit buffers.
  334. ; 4h. Zero the structure.
  335.         allocate_and_clear ebx, sizeof.device, .fail
  336. ; 4i. Save PCI coordinates
  337.         mov     eax, [edx + IOCTL.input]
  338.         movzx   ecx, byte[eax+1]
  339.         mov     [ebx + device.pci_bus], ecx
  340.         movzx   ecx, byte[eax+2]
  341.         mov     [ebx + device.pci_dev], ecx
  342. ; 4j. Fill in the direct call addresses into the struct.
  343.         mov     [ebx + device.reset], reset
  344.         mov     [ebx + device.transmit], transmit
  345.         mov     [ebx + device.unload], unload
  346.         mov     [ebx + device.name], my_service
  347.  
  348. ; 4k. Now, it's time to find the base io addres of the PCI device
  349. ; TODO: implement check if bus and dev exist on this machine
  350.  
  351. ; Now, it's time to find the base io addres of the PCI device
  352.         stdcall PCI_find_io, [ebx + device.pci_bus], [ebx + device.pci_dev]
  353.         mov     [ebx + device.io_addr], eax
  354.  
  355. ; We've found the io address, find IRQ now
  356.  
  357.         invoke  PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.interrupt_line
  358.         mov     [ebx + device.irq_line], al
  359.  
  360. ; 4m. Add new device to the list (required for int_handler).
  361.         mov     eax, [devices]
  362.         mov     [device_list+4*eax], ebx
  363.         inc     [devices]
  364.  
  365. ; 4m. Ok, the eth_device structure is ready, let's probe the device
  366.         call    probe
  367.         test    eax, eax
  368.         jnz     .destroy
  369. ; 4n. If device was successfully initialized, register it for the kernel.
  370.  
  371.         mov     [ebx + device.type], NET_TYPE_ETH
  372.         invoke  NetRegDev
  373.  
  374.         cmp     eax, -1
  375.         je      .destroy
  376.  
  377.         ret     4
  378.  
  379. ; 5. If the device was already loaded, find the device number and return it in eax
  380.  
  381.   .find_devicenum:
  382.         invoke  NetPtrToNum                             ; This kernel procedure converts a pointer to device struct in ebx
  383.                                                         ; into a device number in edi
  384.         mov     eax, edi                                ; Application wants it in eax instead
  385.         ret     4
  386.  
  387. ; If an error occured, remove all allocated data and exit (returning -1 in eax)
  388.  
  389.   .destroy:
  390.         dec     [devices]
  391.         ; todo: reset device into virgin state
  392.  
  393.   .err:
  394.         invoke  KernelFree, ebx
  395.  
  396.   .fail:
  397.         xor     eax, eax
  398.         ret     4
  399.  
  400.  
  401. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  402. ;;                                                                        ;;
  403. ;;        Actual Hardware dependent code starts here                      ;;
  404. ;;                                                                        ;;
  405. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  406.  
  407. unload:
  408.         ; TODO: (in this particular order)
  409.         ;
  410.         ; - Stop the device
  411.         ; - Detach int handler
  412.         ; - Remove device from local list
  413.         ; - call unregister function in kernel
  414.         ; - Remove all allocated structures and buffers the card used
  415.  
  416.         or      eax, -1
  417.         ret
  418.  
  419. ;***************************************************************************
  420. ;
  421. ; probe
  422. ;
  423. ; checks the card and enables it
  424. ;
  425. ; TODO: probe mii transceivers
  426. ;
  427. ;***************************************************************************
  428. align 4
  429. probe:
  430.         DEBUGF  1, "Probe\n"
  431.  
  432. ; wake up device
  433. ; TODO: check capabilities pointer instead of using hardcoded offset.
  434.         invoke  PciWrite8, [ebx + device.pci_bus], [ebx + device.pci_dev], 0x40, 0
  435.  
  436. ; Make the device a bus master
  437.         invoke  PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command
  438.         or      al, PCI_CMD_MASTER
  439.         invoke  PciWrite32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command, eax
  440.  
  441. ; Adjust PCI latency to be at least 64
  442.         invoke  PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.max_latency
  443.         cmp     al, 64
  444.         jae     @f
  445.         mov     al, 64
  446.         invoke  PciWrite8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.max_latency, eax
  447.   @@:
  448.  
  449. ; Get Card Revision
  450.         invoke  PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], 0x08
  451.         mov     [ebx + device.pci_revision], al         ; save the revision for later use
  452.  
  453. ; Look up through the specific_table
  454.         mov     esi, specific_table
  455.   .tableloop:
  456.         cmp     dword[esi], 0                           ; Check if we reached end of the list
  457.         je      .notsupported
  458.         cmp     al, [esi]                               ; Check if revision is OK
  459.         je      .ok
  460.         add     esi, 12                                 ; Advance to next entry
  461.         jmp     .tableloop
  462.   .ok:
  463.         call     dword[esi + 4]                         ; "get MAC" function
  464.  
  465. ; Set table entries
  466.         mov      [ebx + device.table_entries], 16
  467.         cmp      [ebx + device.pci_revision], SIS635A_900_REV
  468.         jae      @f
  469.         cmp      [ebx + device.pci_revision], SIS900B_900_REV
  470.         je       @f
  471.         mov      [ebx + device.table_entries], 8
  472.        @@:
  473.  
  474. ; TODO: Probe for mii transceiver
  475.         jmp     reset
  476.  
  477.   .notsupported:
  478.         DEBUGF  2, "Device not supported\n"
  479.         or      eax, -1
  480.  
  481.         ret
  482.  
  483. reset:
  484.  
  485.         DEBUGF  1, "reset\n"
  486.  
  487.         movzx   eax, [ebx + device.irq_line]
  488.         invoke  AttachIntHandler, eax, int_handler, ebx
  489.         test    eax, eax
  490.         jnz     @f
  491.         DEBUGF  2,"Could not attach int handler!\n"
  492.         or      eax, -1
  493.         ret
  494.        @@:  
  495.  
  496. ;--------------------------------------------
  497. ; Disable Interrupts and reset Receive Filter
  498.  
  499.         set_io  [ebx + device.io_addr], 0
  500.         set_io  [ebx + device.io_addr], ier
  501.         xor     eax, eax
  502.         out     dx, eax
  503.  
  504.         set_io  [ebx + device.io_addr], imr
  505.         out     dx, eax
  506.  
  507.         set_io  [ebx + device.io_addr], rfcr
  508.         out     dx, eax
  509.  
  510. ;-----------
  511. ; Reset Card
  512.  
  513.         set_io  [ebx + device.io_addr], cr
  514.         in      eax, dx                                 ; Get current Command Register
  515.         or      eax, RESET + RxRESET + TxRESET          ; set flags
  516.         out     dx, eax                                 ; Write new Command Register
  517.  
  518. ;----------
  519. ; Wait loop
  520.  
  521.         set_io  [ebx + device.io_addr], isr
  522.         mov     ecx, 1000
  523.   .loop:
  524.         dec     ecx
  525.         jz      .fail
  526.         in      eax, dx                                 ; read interrupt status
  527.         test    eax, TxRCMP + RxRCMP
  528.         jz      .loop
  529.         DEBUGF  1, "status=%x\n", eax
  530.  
  531. ;------------------------------------------------------
  532. ; Set Configuration Register depending on Card Revision
  533.  
  534.         set_io  [ebx + device.io_addr], cfg
  535.         mov     eax, PESEL                              ; Configuration Register Bit
  536.         cmp     [ebx + device.pci_revision], SIS635A_900_REV
  537.         je      .match
  538.         cmp     [ebx + device.pci_revision], SIS900B_900_REV ; Check card revision
  539.         jne     .done
  540.   .match:                                               ; Revision match
  541.         or      eax, RND_CNT                            ; Configuration Register Bit
  542.   .done:
  543.         out     dx, eax
  544.  
  545.         DEBUGF  1, "Initialising RX Filter\n"
  546.  
  547. ; Get Receive Filter Control Register
  548.         set_io  [ebx + device.io_addr], rfcr
  549.         in      eax, dx
  550.         push    eax
  551.  
  552. ; disable packet filtering before setting filter
  553.         and     eax, not RFEN
  554.         out     dx, eax
  555.  
  556. ; load MAC addr to filter data register
  557.         xor     ecx, ecx
  558.   .macloop:
  559.         mov     eax, ecx
  560.         set_io  [ebx + device.io_addr], 0
  561.         set_io  [ebx + device.io_addr], rfcr
  562.         shl     eax, 16                                 ; high word of eax tells card which mac byte to write
  563.         out     dx, eax                                 ;
  564.         set_io  [ebx + device.io_addr], rfdr
  565.         mov     ax, word [ebx + device.mac + ecx*2]     ; Get Mac ID word
  566.         out     dx, ax                                  ; Send Mac ID
  567.         inc     cl                                      ; send next word
  568.         cmp     cl, 3                                   ; more to send?
  569.         jne     .macloop
  570.  
  571. ; enable packet filtering
  572.         pop     eax                                     ; old register value
  573.         set_io  [ebx + device.io_addr], rfcr
  574.         or      eax, RFEN                               ; enable filtering
  575.         out     dx, eax                                 ; set register
  576.  
  577.         DEBUGF  1, "Initialising TX Descriptors\n"
  578.  
  579.         mov     ecx, NUM_TX_DESC
  580.         lea     esi, [ebx + device.txd]
  581.   .txdescloop:
  582.         lea     eax, [esi + 16]                         ; next ptr
  583.         invoke  GetPhysAddr
  584.         mov     dword[esi], eax                         ; link to next desc
  585.         mov     dword[esi + 4], 0                       ; status field
  586.         mov     dword[esi + 8], 0                       ; ptr to buffer
  587.         add     esi, 16
  588.         dec     ecx
  589.         jnz     .txdescloop
  590.  
  591.         lea     eax, [ebx + device.txd]
  592.         invoke  GetPhysAddr
  593.         mov     dword[esi - 16], eax                    ; correct last descriptor link ptr
  594.  
  595.         set_io  [ebx + device.io_addr], txdp            ; TX Descriptor Pointer
  596. ;        lea     eax, [ebx + device.txd]
  597. ;        invoke  GetPhysAddr
  598.         out     dx, eax
  599.  
  600.         mov     [ebx + device.cur_tx], 0                ; Set current tx descriptor to 0
  601.         mov     [ebx + device.last_tx], 0
  602.  
  603.         DEBUGF  1, "Initialising RX Descriptors\n"
  604.  
  605.         mov     ecx, NUM_RX_DESC
  606.         lea     esi, [ebx + device.rxd]
  607.   .rxdescloop:
  608.         lea     eax, [esi + 16]                         ; next ptr
  609.         invoke  GetPhysAddr
  610.         mov     dword [esi], eax
  611.         mov     dword [esi + 4], RX_BUFF_SZ             ; size
  612.  
  613.         push    ecx esi
  614.         invoke  NetAlloc, RX_BUFF_SZ+NET_BUFF.data
  615.         pop     esi ecx
  616.         test    eax, eax
  617.         jz      .fail
  618.         mov     dword [esi + 12], eax                   ; address
  619.         invoke  GetPhysAddr
  620.         add     eax, NET_BUFF.data
  621.         mov     dword [esi + 8], eax                    ; real address
  622.         add     esi, 16
  623.         dec     ecx
  624.         jnz     .rxdescloop
  625.  
  626.         lea     eax, [ebx + device.rxd]
  627.         invoke  GetPhysAddr
  628.         mov     dword [esi - 16], eax                   ; correct last descriptor link ptr
  629.  
  630.         set_io  [ebx + device.io_addr], 0
  631.         set_io  [ebx + device.io_addr], rxdp
  632. ;        lea     eax, [ebx + device.rxd]
  633. ;        invoke  GetPhysAddr
  634.         out     dx, eax
  635.  
  636.         mov     [ebx + device.cur_rx], 0                ; Set current rx descriptor to 0
  637.  
  638.         DEBUGF  1, "setting RX mode\n"
  639.  
  640.         xor     cl, cl
  641.   .rxfilterloop:
  642.         set_io  [ebx + device.io_addr], 0
  643.         set_io  [ebx + device.io_addr], rfcr            ; Receive Filter Control Reg offset
  644.         mov     eax, 4                                  ; determine table entry
  645.         add     al, cl
  646.         shl     eax, 16
  647.         out     dx, eax                                 ; tell card which entry to modify
  648.  
  649.         set_io  [ebx + device.io_addr], rfdr            ; Receive Filter Control Reg offset
  650.         mov     eax, 0xffff                             ; entry value
  651.         out     dx, ax                                  ; write value to table in card
  652.  
  653.         inc     cl                                      ; next entry
  654.         cmp     cl, [ebx + device.table_entries]
  655.         jb      .rxfilterloop
  656.  
  657.         set_io  [ebx + device.io_addr], rfcr            ; Receive Filter Control Register offset
  658.         mov     eax, RFAAB + RFAAM + RFAAP + RFEN
  659.         out     dx, eax
  660.  
  661.         set_io  [ebx + device.io_addr], rxcfg           ; Receive Config Register offset
  662.         mov     eax, ATX + RX_DMA + 2                   ; 0x2 : RX Drain Threshold = 8*8=64 bytes
  663.         out     dx, eax
  664.  
  665.         DEBUGF  1, "setting TX mode\n"
  666.  
  667.         set_io  [ebx + device.io_addr], txcfg           ; Transmit config Register offset
  668.         mov     eax, ATP + HBI + CSI + TX_DMA + 0x120   ; TX Fill threshold = 0x100
  669.                                                         ; TX Drain Threshold = 0x20
  670.         out     dx, eax
  671.  
  672.         DEBUGF  1, "Enabling interrupts\n"
  673.  
  674.         set_io  [ebx + device.io_addr], imr
  675.         mov     eax, IE                                 ; Interrupt enable mask
  676.         out     dx, eax
  677.  
  678.         set_io  [ebx + device.io_addr], cr
  679.         in      eax, dx
  680.         or      eax, RxENA                              ; Enable Receive
  681.         out     dx, eax
  682.  
  683.         set_io  [ebx + device.io_addr], ier             ; Interrupt enable
  684.         mov     eax, 1
  685.         out     dx, eax
  686.  
  687.         mov     [ebx + device.mtu], 1514
  688.  
  689. ; Set link state to unknown
  690.         mov     [ebx + device.state], ETH_LINK_UNKNOWN
  691.  
  692.         xor     eax, eax
  693.         ret
  694.  
  695.   .fail:
  696.         DEBUGF  2, "Resetting device failed\n"
  697.         or      eax, -1
  698.  
  699.         ret
  700.  
  701.  
  702. ;***************************************************************************
  703. ;
  704. ; SIS960_get_mac_addr: - Get MAC address for SiS962 or SiS963 model
  705. ;
  706. ; SiS962 or SiS963 model, use EEPROM to store MAC address.
  707. ; EEPROM is shared by LAN and 1394.
  708. ; When access EEPROM, send EEREQ signal to hardware first, and wait for EEGNT.
  709. ; If EEGNT is ON, EEPROM is permitted to be accessed by LAN, otherwise is not.
  710. ; After MAC address is read from EEPROM, send
  711. ; EEDONE signal to refuse EEPROM access by LAN.
  712. ; The EEPROM map of SiS962 or SiS963 is different to SiS900.
  713. ; The signature field in SiS962 or SiS963 spec is meaningless.
  714. ;
  715. ; Return 0 is EAX = failure
  716. ;
  717. ;***************************************************************************
  718. align 4
  719. SIS960_get_mac_addr:
  720.         DEBUGF  1, "SIS960 - get mac:\n"
  721.  
  722. ;-------------------------------
  723. ; Send Request for eeprom access
  724.  
  725.         set_io  [ebx + device.io_addr], 0
  726.         set_io  [ebx + device.io_addr], mear            ; Eeprom access register
  727.         mov     eax, EEREQ                              ; Request access to eeprom
  728.         out     dx, eax                                 ; Send request
  729.  
  730. ;-----------------------------------------------------
  731. ; Loop 4000 times and if access not granted, error out
  732.  
  733.         mov     ecx, 4000
  734.   .loop:
  735.         in      eax, dx                                 ; get eeprom status
  736.         test    eax, EEGNT                              ; see if eeprom access granted flag is set
  737.         jnz     .got_access                             ; if it is, go access the eeprom
  738.         loop    .loop                                   ; else keep waiting
  739.  
  740.         DEBUGF  2, "Access to EEprom failed!\n", 0
  741.  
  742.         set_io  [ebx + device.io_addr], mear            ; Eeprom access register
  743.         mov     eax, EEDONE                             ; tell eeprom we are done
  744.         out     dx, eax
  745.  
  746.         or      eax, -1                                 ; error
  747.         ret
  748.  
  749.   .got_access:
  750.  
  751. ;------------------------------------------
  752. ; EEprom access granted, read MAC from card
  753.  
  754.     ; zero based so 3-16 bit reads will take place
  755.  
  756.         mov     ecx, 2
  757.   .read_loop:
  758.         mov     eax, EEPROMMACAddr                      ; Base Mac Address
  759.         add     eax, ecx                                ; Current Mac Byte Offset
  760.         push    ecx
  761.         call    read_eeprom                             ; try to read 16 bits
  762.         pop     ecx
  763.         mov     word [ebx + device.mac+ecx*2], ax       ; save 16 bits to the MAC ID varible
  764.         dec     ecx                                     ; one less word to read
  765.         jns     .read_loop                              ; if more read more
  766.         mov     eax, 1                                  ; return non-zero indicating success
  767.  
  768.         DEBUGF  1,"%x-%x-%x-%x-%x-%x\n",\
  769.         [ebx + device.mac]:2,[ebx + device.mac+1]:2,[ebx + device.mac+2]:2,[ebx + device.mac+3]:2,[ebx + device.mac+4]:2,[ebx + device.mac+5]:2
  770.  
  771. ;-------------------------------------
  772. ; Tell EEPROM We are Done Accessing It
  773.  
  774.   .done:
  775.         set_io  [ebx + device.io_addr], 0
  776.         set_io  [ebx + device.io_addr], mear            ; Eeprom access register
  777.         mov     eax, EEDONE                             ; tell eeprom we are done
  778.         out     dx, eax
  779.  
  780.         xor     eax, eax                                ; ok
  781.         ret
  782.  
  783.  
  784.  
  785.  
  786. ;***************************************************************************
  787. ;
  788. ; get_mac_addr: - Get MAC address for stand alone SiS900 model
  789. ;
  790. ; Older SiS900 and friends, use EEPROM to store MAC address.
  791. ;
  792. ;***************************************************************************
  793. align 4
  794. SIS900_get_mac_addr:
  795.         DEBUGF  1, "SIS900 - get mac:\n"
  796.  
  797. ;------------------------------------
  798. ; check to see if we have sane EEPROM
  799.  
  800.         mov     eax, EEPROMSignature                    ; Base Eeprom Signature
  801.         call    read_eeprom                             ; try to read 16 bits
  802.         cmp     ax, 0xffff
  803.         je      .err
  804.         test    ax, ax
  805.         je      .err
  806.  
  807. ;-----------
  808. ; Read MacID
  809.  
  810. ; zero based so 3-16 bit reads will take place
  811.  
  812.         mov     ecx, 2
  813.   .loop:
  814.         mov     eax, EEPROMMACAddr                      ; Base Mac Address
  815.         add     eax, ecx                                ; Current Mac Byte Offset
  816.         push    ecx
  817.         call    read_eeprom                             ; try to read 16 bits
  818.         pop     ecx
  819.         mov     word [ebx + device.mac+ecx*2], ax       ; save 16 bits to the MAC ID storage
  820.         dec     ecx                                     ; one less word to read
  821.         jns     .loop                                   ; if more read more
  822.  
  823.         DEBUGF  1,"%x-%x-%x-%x-%x-%x\n",\
  824.         [ebx + device.mac]:2,[ebx + device.mac+1]:2,[ebx + device.mac+2]:2,[ebx + device.mac+3]:2,[ebx + device.mac+4]:2,[ebx + device.mac+5]:2
  825.  
  826.         xor     eax, eax
  827.         ret
  828.  
  829.  
  830.   .err:
  831.         DEBUGF  1, "Access to EEprom failed!\n", 0
  832.  
  833.         or      eax, -1
  834.         ret
  835.  
  836.  
  837. ;***************************************************************************
  838. ;
  839. ; Get_Mac_SIS635_900_REV: - Get MAC address for model 635
  840. ;
  841. ;***************************************************************************
  842. align 4
  843. Get_Mac_SIS635_900_REV:
  844.         DEBUGF  1, "SIS635 - get mac:\n"
  845.  
  846.         set_io  [ebx + device.io_addr], 0
  847.         set_io  [ebx + device.io_addr], rfcr
  848.         in      eax, dx
  849.         mov     esi, eax
  850.  
  851.         set_io  [ebx + device.io_addr], cr
  852.         or      eax, RELOAD
  853.         out     dx, eax
  854.  
  855.         xor     eax, eax
  856.         out     dx, eax
  857.  
  858. ;-----------------------------------------------
  859. ; Disable packet filtering before setting filter
  860.  
  861.         set_io  [ebx + device.io_addr], rfcr
  862.         mov     eax, esi
  863.         and     eax, not RFEN
  864.         out     dx, eax
  865.  
  866. ;---------------------------------
  867. ; Load MAC to filter data register
  868.  
  869.         xor     ecx, ecx
  870.         lea     edi, [ebx + device.mac]
  871.   .loop:
  872.         set_io  [ebx + device.io_addr], 0
  873.         set_io  [ebx + device.io_addr], rfcr
  874.         mov     eax, ecx
  875.         shl     eax, RFADDR_shift
  876.         out     dx, eax
  877.  
  878.         set_io  [ebx + device.io_addr], rfdr
  879.         in      ax, dx
  880.         stosw
  881.         inc     ecx
  882.         cmp     ecx, 3
  883.         jb      .loop
  884.  
  885. ;------------------------
  886. ; Enable packet filtering
  887.  
  888.         set_io  [ebx + device.io_addr], rfcr
  889.         mov     eax, esi
  890.         or      eax, RFEN
  891.         out     dx, eax
  892.  
  893.         DEBUGF  1,"%x-%x-%x-%x-%x-%x\n",\
  894.         [ebx + device.mac]:2,[ebx + device.mac+1]:2,[ebx + device.mac+2]:2,[ebx + device.mac+3]:2,[ebx + device.mac+4]:2,[ebx + device.mac+5]:2
  895.  
  896.         xor     eax, eax
  897.         ret
  898.  
  899. ;***************************************************************************
  900. ;
  901. ; read_eeprom
  902. ;
  903. ; reads and returns a given location from EEPROM
  904. ;
  905. ; IN:  si = addr
  906. ; OUT: ax = data
  907. ;
  908. ;***************************************************************************
  909. align 4
  910. read_eeprom:
  911.  
  912.         set_io  [ebx + device.io_addr], 0
  913.         set_io  [ebx + device.io_addr], mear
  914.  
  915.         xor     eax, eax                                ; start send
  916.         out     dx, eax
  917.         ee_delay
  918.  
  919.         or      eax, EECLK
  920.         out     dx, eax
  921.         ee_delay
  922.  
  923. ;------------------------------------
  924. ; Send the read command
  925.  
  926.         or      esi, EEread
  927.         mov     ecx, 1 shl 9
  928.  
  929.   .loop:
  930.         mov     eax, EECS
  931.         test    esi, ecx
  932.         jz      @f
  933.         or      eax, EEDI
  934.        @@:
  935.         out     dx, eax
  936.         ee_delay
  937.  
  938.         or      eax, EECLK
  939.         out     dx, eax
  940.         ee_delay
  941.  
  942.         shr     esi, 1
  943.         jnc     .loop
  944.  
  945.         mov     eax, EECS
  946.         out     dx, eax
  947.         ee_delay
  948.  
  949. ;------------------------
  950. ; Read 16-bits of data in
  951.  
  952.         xor     esi, esi
  953.         mov     cx, 16
  954.   .loop2:
  955.         mov     eax, EECS
  956.         out     dx, eax
  957.         ee_delay
  958.  
  959.         or      eax, EECLK
  960.         out     dx, eax
  961.         ee_delay
  962.  
  963.         in      eax, dx
  964.         shl     esi, 1
  965.         test    eax, EEDO
  966.         jz      @f
  967.         inc     esi
  968.        @@:
  969.         loop    .loop2
  970.  
  971. ;----------------------------
  972. ; Terminate the EEPROM access
  973.  
  974.         xor     eax, eax
  975.         out     dx, eax
  976.         ee_delay
  977.  
  978.         mov     eax, EECLK
  979.         out     dx, eax
  980.         ee_delay
  981.  
  982.         movzx   eax, si
  983.  
  984.         ret
  985.  
  986.  
  987.  
  988. align 4
  989. write_mac:
  990.         DEBUGF  2,'Setting MAC is not supported for SIS900 card.\n'
  991.         add     esp, 6
  992.         ret
  993.  
  994.  
  995.  
  996.  
  997. ;***************************************************************************
  998. ;   Function
  999. ;      transmit
  1000. ;   Description
  1001. ;      Transmits a packet of data via the ethernet card
  1002. ;         buffer pointer in [esp+4]
  1003. ;         size of buffer in [esp+8]
  1004. ;         pointer to device structure in ebx
  1005. ;
  1006. ;***************************************************************************
  1007. align 4
  1008.  
  1009. proc transmit stdcall bufferptr
  1010.  
  1011.         pushf
  1012.         cli
  1013.  
  1014.         mov     esi, [bufferptr]
  1015.         DEBUGF  1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [esi + NET_BUFF.length]
  1016.         lea     eax, [esi + NET_BUFF.data]
  1017.         DEBUGF  1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
  1018.         [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
  1019.         [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
  1020.         [eax+13]:2,[eax+12]:2
  1021.  
  1022.         cmp     [esi + NET_BUFF.length], 1514
  1023.         ja      .fail
  1024.         cmp     [esi + NET_BUFF.length], 60
  1025.         jb      .fail
  1026.  
  1027.         movzx   ecx, [ebx + device.cur_tx]
  1028.         shl     ecx, 4                                  ; *16
  1029.         lea     ecx, [ebx + device.txd + ecx]
  1030.  
  1031.         test    dword[ecx + 4], 0x80000000              ; card owns descriptor ?
  1032.         jnz     .fail
  1033.  
  1034.         mov     eax, esi
  1035.         mov     dword[ecx + 12], eax
  1036.         add     eax, [eax + NET_BUFF.offset]
  1037.         invoke  GetPhysAddr
  1038.         mov     dword[ecx + 8], eax                     ; buffer address
  1039.  
  1040.         mov     eax, [esi + NET_BUFF.length]
  1041.         and     eax, DSIZE
  1042.         or      eax, 0x80000000                         ; card owns descriptor
  1043.         mov     dword[ecx + 4], eax                     ; status field
  1044.  
  1045.         set_io  [ebx + device.io_addr], 0
  1046.         set_io  [ebx + device.io_addr], cr
  1047.         in      eax, dx
  1048.         or      eax, TxENA                              ; Enable the transmit state machine
  1049.         out     dx, eax
  1050.  
  1051.         inc     [ebx + device.cur_tx]
  1052.         and     [ebx + device.cur_tx], NUM_TX_DESC-1
  1053.  
  1054. ; update stats
  1055.         mov     ecx, [esi + NET_BUFF.length]
  1056.         inc     [ebx + device.packets_tx]
  1057.         add     dword [ebx + device.bytes_tx], ecx
  1058.         adc     dword [ebx + device.bytes_tx + 4], 0
  1059.  
  1060.         DEBUGF  1,"Transmit OK\n"
  1061.         popf
  1062.         xor     eax, eax
  1063.         ret
  1064.  
  1065.   .fail:
  1066.         DEBUGF  2,"Transmit failed\n"
  1067.         invoke  NetFree, [bufferptr]
  1068.         popf
  1069.         or      eax, -1
  1070.         ret
  1071.  
  1072. endp
  1073.  
  1074.  
  1075. ;***************************************************************************
  1076. ;
  1077. ; int_handler
  1078. ;
  1079. ; handles received IRQs, which signal received packets
  1080. ;
  1081. ; Currently only supports one descriptor per packet, if packet is fragmented
  1082. ; between multiple descriptors you will lose part of the packet
  1083. ;
  1084. ;***************************************************************************
  1085.  
  1086. align 4
  1087. int_handler:
  1088.  
  1089.         push    ebx esi edi
  1090.  
  1091.         DEBUGF  1,"INT\n"
  1092.  
  1093. ; find pointer of device which made IRQ occur
  1094.  
  1095.         mov     ecx, [devices]
  1096.         test    ecx, ecx
  1097.         jz      .nothing
  1098.         mov     esi, device_list
  1099.   .nextdevice:
  1100.         mov     ebx, [esi]
  1101.  
  1102.         set_io  [ebx + device.io_addr], 0
  1103.         set_io  [ebx + device.io_addr], isr
  1104.         in      eax, dx                                 ; note that this clears all interrupts
  1105.         test    ax, IE
  1106.         jnz     .got_it
  1107.   .continue:
  1108.         add     esi, 4
  1109.         dec     ecx
  1110.         jnz     .nextdevice
  1111.   .nothing:
  1112.         pop     edi esi ebx
  1113.         xor     eax, eax
  1114.  
  1115.         ret
  1116.  
  1117.   .got_it:
  1118.  
  1119.         DEBUGF  1,"Device: %x Status: %x\n", ebx, ax
  1120.  
  1121.         test    ax, RxOK
  1122.         jz      .no_rx_
  1123.  
  1124.         push    ax
  1125.  
  1126.   .rx_loop:
  1127.  
  1128. ;-----------
  1129. ; Get Status
  1130.         movzx   eax, [ebx + device.cur_rx]              ; find current descriptor
  1131.         shl     eax, 4                                  ; * 16
  1132.         mov     ecx, dword[ebx + device.rxd + eax + 4]  ; get receive status
  1133.  
  1134. ;-------------------------------------------
  1135. ; Check RX_Status to see if packet is waiting
  1136.         test    ecx, 0x80000000
  1137.         jz      .no_rx
  1138.  
  1139. ;----------------------------------------------
  1140. ; There is a packet waiting check it for errors
  1141.         test    ecx, 0x67C0000                          ; see if there are any errors
  1142.         jnz     .error_status
  1143.  
  1144. ;---------------------
  1145. ; Check size of packet
  1146.         and     ecx, DSIZE                              ; get packet size minus CRC
  1147.         sub     ecx, CRC_SIZE                           ; make sure packet contains data
  1148.         jbe     .error_size
  1149.  
  1150. ; update statistics
  1151.         inc     dword [ebx + device.packets_rx]
  1152.         add     dword [ebx + device.bytes_rx], ecx
  1153.         adc     dword [ebx + device.bytes_rx + 4], 0
  1154.  
  1155.         push    ebx
  1156.         push    .return                                 ; return addr
  1157.         mov     eax, [ebx + device.rxd + eax + 12]
  1158.         push    eax                                     ; packet ptr
  1159.         mov     [eax + NET_BUFF.length], ecx
  1160.         mov     [eax + NET_BUFF.device], ebx
  1161.         mov     [eax + NET_BUFF.offset], NET_BUFF.data
  1162.         DEBUGF  1, "Packet received OK\n"
  1163.         jmp     [EthInput]
  1164.   .return:
  1165.         pop     ebx
  1166.  
  1167. ; Reset status, allow ethernet card access to descriptor
  1168.         invoke  NetAlloc, RX_BUFF_SZ + NET_BUFF.data
  1169.         test    eax, eax
  1170.         jz      .fail
  1171.         movzx   ecx, [ebx + device.cur_rx]
  1172.         shl     ecx, 4                                  ; *16
  1173.         lea     ecx, [ebx + device.rxd + ecx]
  1174.         mov     dword [ecx + 12], eax
  1175.         invoke  GetPhysAddr
  1176.         add     eax, NET_BUFF.data
  1177.         mov     dword [ecx + 8], eax
  1178.         mov     dword [ecx + 4], RX_BUFF_SZ
  1179.  
  1180.         inc     [ebx + device.cur_rx]                   ; get next descriptor
  1181.         and     [ebx + device.cur_rx], NUM_RX_DESC-1    ; only 4 descriptors 0-3
  1182.  
  1183.         jmp     .rx_loop
  1184.  
  1185.   .no_rx:
  1186.         set_io  [ebx + device.io_addr], 0
  1187.         set_io  [ebx + device.io_addr], cr
  1188.         in      eax, dx
  1189.         or      eax, RxENA                              ; Re-Enable the Receive state machine
  1190.         out     dx, eax
  1191.  
  1192.         pop     ax
  1193.  
  1194.   .no_rx_:
  1195.         test    ax, TxOK
  1196.         jz      .no_tx
  1197.  
  1198.         DEBUGF  1, "TX ok!\n"
  1199.  
  1200.   .tx_loop:
  1201.         movzx   ecx, [ebx + device.last_tx]
  1202.         shl     ecx, 4                  ; *16
  1203.         lea     ecx, [ebx + device.txd + ecx]
  1204.  
  1205.         test    dword[ecx + 4], 0x80000000              ; card owns descr
  1206.         jnz     .no_tx
  1207.         cmp     dword[ecx + 12], 0
  1208.         je      .no_tx
  1209.  
  1210.         DEBUGF  1, "Freeing packet = %x\n", [ecx + 12]:8
  1211.         push    dword[ecx + 12]
  1212.         mov     dword[ecx + 12], 0
  1213.         invoke  NetFree
  1214.  
  1215.         inc     [ebx + device.last_tx]
  1216.         and     [ebx + device.last_tx], NUM_TX_DESC-1
  1217.         jmp     .tx_loop
  1218.  
  1219.   .no_tx:
  1220.   .fail:
  1221.         pop     edi esi ebx
  1222.         xor     eax, eax
  1223.         inc     eax
  1224.  
  1225.         ret
  1226.  
  1227.         ret
  1228.  
  1229.   .error_status:
  1230.         DEBUGF  2, "Packet error: %x\n", ecx
  1231.         jmp     .fail
  1232.  
  1233.   .error_size:
  1234.         DEBUGF  2, "Packet too large/small\n"
  1235.         jmp     .fail
  1236.  
  1237.  
  1238.  
  1239.  
  1240.  
  1241. ; End of code
  1242.  
  1243. data fixups
  1244. end data
  1245.  
  1246. include '../peimport.inc'
  1247.  
  1248. my_service      db 'SIS900',0                           ; max 16 chars include zero
  1249.  
  1250. specific_table:
  1251. ;    dd SIS630A_900_REV, Get_Mac_SIS630A_900_REV, 0
  1252. ;    dd SIS630E_900_REV, Get_Mac_SIS630E_900_REV, 0
  1253.     dd SIS630S_900_REV, Get_Mac_SIS635_900_REV, 0
  1254.     dd SIS630EA1_900_REV, Get_Mac_SIS635_900_REV, 0
  1255.     dd SIS630ET_900_REV, Get_Mac_SIS635_900_REV, 0      ; SIS630ET_900_REV_SpecialFN
  1256.     dd SIS635A_900_REV, Get_Mac_SIS635_900_REV, 0
  1257.     dd SIS900_960_REV, SIS960_get_mac_addr, 0
  1258.     dd SIS900B_900_REV, SIS900_get_mac_addr, 0
  1259.     dd 0                                                ; end of list
  1260.  
  1261. include_debug_strings                                   ; All data wich FDO uses will be included here
  1262.  
  1263. align 4
  1264. devices         dd 0
  1265. device_list     rd MAX_DEVICES                          ; This list contains all pointers to device structures the driver is handling
  1266.  
  1267.