Subversion Repositories Kolibri OS

Rev

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

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