Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                    ;;
  3. ;; Copyright (C) KolibriOS team 2004-2013. All rights reserved.       ;;
  4. ;; Distributed under terms of the GNU General Public License          ;;
  5. ;;                                                                    ;;
  6. ;;  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__         = 2
  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        dd ?
  217.         .pci_dev        dd ?
  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.         rb 2    ; alignment
  225.  
  226.         .txd            rd (4 * NUM_TX_DESC)
  227.         .rxd            rd (4 * NUM_RX_DESC)
  228.  
  229.         .size = $ - device
  230.  
  231. end virtual
  232.  
  233. macro   ee_delay {
  234.         push    eax
  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.         in      eax, dx
  245.         pop     eax
  246. }
  247.  
  248.  
  249. section '.flat' code readable align 16
  250.  
  251. ; Driver entry point - register our service when the driver is loading.
  252. ; TODO: add needed operations when unloading
  253. START:
  254.         cmp     dword [esp+4], 1
  255.         jne     .exit
  256.         stdcall RegService, my_service, service_proc
  257.         ret     4
  258.   .exit:
  259.         xor     eax, eax
  260.         ret     4
  261.  
  262. ; Service procedure for the driver - handle all I/O requests for the driver.
  263. ; Currently handled requests are: SRV_GETVERSION = 0 and SRV_HOOK = 1.
  264. service_proc:
  265. ; 1. Get parameter from the stack: [esp+4] is the first parameter,
  266. ;       pointer to IOCTL structure.
  267.         mov     edx, [esp+4]    ; edx -> IOCTL
  268. ; 2. Get request code and select a handler for the code.
  269.         mov     eax, [IOCTL.io_code]
  270.         test    eax, eax        ; check for SRV_GETVERSION
  271.         jnz     @f
  272. ; 3. This is SRV_GETVERSION request, no input, 4 bytes output, API_VERSION.
  273. ; 3a. Output size must be at least 4 bytes.
  274.         cmp     [IOCTL.out_size], 4
  275.         jb      .fail
  276. ; 3b. Write result to the output buffer.
  277.         mov     eax, [IOCTL.output]
  278.         mov     [eax], dword API_VERSION
  279. ; 3c. Return success.
  280.         xor     eax, eax
  281.         ret     4
  282.   @@:
  283.         dec     eax     ; check for SRV_HOOK
  284.         jnz     .fail
  285. ; 4. This is SRV_HOOK request, input defines the device to hook, no output.
  286. ; 4a. The driver works only with PCI devices,
  287. ;       so input must be at least 3 bytes long.
  288.         cmp     [IOCTL.inp_size], 3
  289.         jb      .fail
  290. ; 4b. First byte of input is bus type, 1 stands for PCI.
  291.         mov     eax, [IOCTL.input]
  292.         cmp     byte [eax], 1
  293.         jne     .fail
  294. ; 4c. Second and third bytes of the input define the device: bus and dev.
  295. ;       Word in bx holds both bytes.
  296.         mov     bx, [eax+1]
  297. ; 4d. Check if the device was already hooked,
  298. ;       scan through the list of known devices.
  299. ; check if the device is already listed
  300.         mov     esi, device_list
  301.         mov     ecx, [devices]
  302.         test    ecx, ecx
  303.         jz      .firstdevice
  304.  
  305. ;        mov     eax, [IOCTL.input]                      ; get the pci bus and device numbers
  306.         mov     ax, [eax+1]                            ;
  307.   .nextdevice:
  308.         mov     ebx, [esi]
  309.         cmp     al, byte[device.pci_bus]
  310.         jne     @f
  311.         cmp     ah, byte[device.pci_dev]
  312.         je      .find_devicenum                         ; Device is already loaded, let's find it's device number
  313.        @@:
  314.         add     esi, 4
  315.         loop    .nextdevice
  316. ; 4e. This device doesn't have its own eth_device structure yet, let's create one
  317.   .firstdevice:
  318. ; 4f. Check that we have place for new device.
  319.         cmp     [devices], MAX_DEVICES
  320.         jae     .fail
  321. ; 4g. Allocate memory for device descriptor and receive+transmit buffers.
  322. ; 4h. Zero the structure.
  323.         allocate_and_clear ebx, device.size, .fail
  324. ; 4i. Save PCI coordinates
  325.         mov     eax, [IOCTL.input]
  326.         movzx   ecx, byte[eax+1]
  327.         mov     [device.pci_bus], ecx
  328.         movzx   ecx, byte[eax+2]
  329.         mov     [device.pci_dev], ecx
  330. ; 4j. Fill in the direct call addresses into the struct.
  331.         mov     [device.reset], reset
  332.         mov     [device.transmit], transmit
  333.         mov     [device.unload], unload
  334.         mov     [device.name], my_service
  335.  
  336. ; 4k. Now, it's time to find the base io addres of the PCI device
  337. ; TODO: implement check if bus and dev exist on this machine
  338.  
  339. ; Now, it's time to find the base io addres of the PCI device
  340.         PCI_find_io
  341.  
  342. ; We've found the io address, find IRQ now
  343.         PCI_find_irq
  344.  
  345. ; 4m. Add new device to the list (required for int_handler).
  346.         mov     eax, [devices]
  347.         mov     [device_list+4*eax], ebx
  348.         inc     [devices]
  349.  
  350. ; 4m. Ok, the eth_device structure is ready, let's probe the device
  351.         call    probe
  352.         test    eax, eax
  353.         jnz     .destroy
  354. ; 4n. If device was successfully initialized, register it for the kernel.
  355.  
  356.         mov     [device.type], NET_TYPE_ETH
  357.         call    NetRegDev
  358.  
  359.         cmp     eax, -1
  360.         je      .destroy
  361.  
  362.         ret     4
  363.  
  364. ; 5. If the device was already loaded, find the device number and return it in eax
  365.  
  366.   .find_devicenum:
  367.         call    NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
  368.                                                                         ; into a device number in edi
  369.         mov     eax, edi                                                ; Application wants it in eax instead
  370.         ret     4
  371.  
  372. ; If an error occured, remove all allocated data and exit (returning -1 in eax)
  373.  
  374.   .destroy:
  375.         dec     [devices]
  376.         ; todo: reset device into virgin state
  377.  
  378.   .err:
  379.         stdcall KernelFree, ebx
  380.  
  381.   .fail:
  382.         xor     eax, eax
  383.         ret     4
  384.  
  385.  
  386. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  387. ;;                                                                        ;;
  388. ;;        Actual Hardware dependent code starts here                      ;;
  389. ;;                                                                        ;;
  390. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  391.  
  392. unload:
  393.         ; TODO: (in this particular order)
  394.         ;
  395.         ; - Stop the device
  396.         ; - Detach int handler
  397.         ; - Remove device from local list
  398.         ; - call unregister function in kernel
  399.         ; - Remove all allocated structures and buffers the card used
  400.  
  401.         or      eax,-1
  402.  
  403. ret
  404.  
  405. ;***************************************************************************
  406. ;
  407. ; probe
  408. ;
  409. ; checks the card and enables it
  410. ;
  411. ; TODO: probe mii transceivers
  412. ;
  413. ;***************************************************************************
  414. align 4
  415. probe:
  416.         DEBUGF  1, "Probe\n"
  417.  
  418. ; wake up device   CHECKME
  419.         stdcall PciWrite8, [device.pci_bus], [device.pci_dev], 0x40, 0
  420.  
  421.         PCI_make_bus_master
  422.  
  423.         PCI_adjust_latency 64
  424.  
  425. ; Get Card Revision
  426.         stdcall PciRead8, [device.pci_bus], [device.pci_dev], 0x08
  427.         mov     [device.pci_revision], al       ; save the revision for later use
  428.  
  429. ; Look up through the specific_table
  430.         mov     esi, specific_table
  431.   .tableloop:
  432.         cmp     dword [esi], 0                  ; Check if we reached end of the list
  433.         je      .notsupported
  434.         cmp     al, [esi]                       ; Check if revision is OK
  435.         je      .ok
  436.         add     esi, 12                         ; Advance to next entry
  437.         jmp     .tableloop
  438.  
  439.   .ok:
  440.  
  441.         call     dword[esi + 4]                 ; "get MAC" function
  442.  
  443. ; Set table entries
  444.         mov      [device.table_entries], 16
  445.         cmp      [device.pci_revision], SIS635A_900_REV
  446.         jae      @f
  447.         cmp      [device.pci_revision], SIS900B_900_REV
  448.         je       @f
  449.         mov      [device.table_entries], 8
  450.        @@:
  451.  
  452. ; TODO: Probe for mii transceiver
  453.  
  454.         jmp     reset
  455.  
  456.   .notsupported:
  457.         DEBUGF  1, "Device not supported\n"
  458.         or      eax, -1
  459.  
  460.         ret
  461.  
  462. reset:
  463.  
  464.         DEBUGF  1, "reset\n"
  465.  
  466.         movzx   eax, [device.irq_line]
  467.         stdcall AttachIntHandler, eax, int_handler, 0
  468.  
  469. ;--------------------------------------------
  470. ; Disable Interrupts and reset Receive Filter
  471.  
  472.         set_io  0
  473.         set_io  ier
  474.         xor     eax, eax
  475.         out     dx, eax
  476.  
  477.         set_io  imr
  478.         out     dx, eax
  479.  
  480.         set_io  rfcr
  481.         out     dx, eax
  482.  
  483. ;-----------
  484. ; Reset Card
  485.  
  486.         set_io  cr
  487.         in      eax, dx                         ; Get current Command Register
  488.         or      eax, RESET + RxRESET + TxRESET  ; set flags
  489.         out     dx, eax                         ; Write new Command Register
  490.  
  491. ;----------
  492. ; Wait loop
  493.  
  494.         set_io  isr
  495.         mov     ecx, 1000
  496.   .loop:
  497.         dec     ecx
  498.         jz      .fail
  499.         in      eax, dx                         ; read interrupt status
  500.         test    eax, TxRCMP + RxRCMP
  501.         jz      .loop
  502.         DEBUGF  1, "status=%x\n", eax
  503.  
  504. ;------------------------------------------------------
  505. ; Set Configuration Register depending on Card Revision
  506.  
  507.         set_io  cfg
  508.         mov     eax, PESEL                      ; Configuration Register Bit
  509.         cmp     [device.pci_revision], SIS635A_900_REV
  510.         je      .match
  511.         cmp     [device.pci_revision], SIS900B_900_REV ; Check card revision
  512.         jne     .done
  513.   .match:                                       ; Revision match
  514.         or      eax, RND_CNT                    ; Configuration Register Bit
  515.   .done:
  516.         out     dx, eax
  517.  
  518.         DEBUGF  1, "Initialising RX Filter\n"
  519.  
  520. ; Get Receive Filter Control Register
  521.         set_io  rfcr
  522.         in      eax, dx
  523.         push    eax
  524.  
  525. ; disable packet filtering before setting filter
  526.         and     eax, not RFEN
  527.         out     dx, eax
  528.  
  529. ; load MAC addr to filter data register
  530.         xor     ecx, ecx
  531.   .macloop:
  532.         mov     eax, ecx
  533.         set_io  0
  534.         set_io  rfcr
  535.         shl     eax, 16                                             ; high word of eax tells card which mac byte to write
  536.         out     dx, eax                                             ;
  537.         set_io  rfdr
  538.         mov     ax, word [device.mac + ecx*2]                       ; Get Mac ID word
  539.         out     dx, ax                                              ; Send Mac ID
  540.         inc     cl                                                  ; send next word
  541.         cmp     cl, 3                                               ; more to send?
  542.         jne     .macloop
  543.  
  544. ; enable packet filtering
  545.         pop     eax                     ; old register value
  546.         set_io  rfcr
  547.         or      eax, RFEN               ; enable filtering
  548.         out     dx, eax                 ; set register
  549.  
  550.         DEBUGF  1, "Initialising TX Descriptors\n"
  551.  
  552.         mov     ecx, NUM_TX_DESC
  553.         lea     esi, [device.txd]
  554.   .txdescloop:
  555.         lea     eax, [esi + 16]                 ; next ptr
  556.         GetRealAddr
  557.         mov     dword [esi], eax                ; link to next desc
  558.         mov     dword [esi + 4], 0              ; status field
  559.         mov     dword [esi + 8], 0              ; ptr to buffer
  560.         add     esi, 16
  561.         dec     ecx
  562.         jnz     .txdescloop
  563.  
  564.         lea     eax, [device.txd]
  565.         GetRealAddr
  566.         mov     dword [esi - 16], eax           ; correct last descriptor link ptr
  567.  
  568.         set_io  txdp                            ; TX Descriptor Pointer
  569. ;        lea     eax, [device.txd]
  570. ;        GetRealAddr
  571.         out     dx, eax
  572.  
  573.         mov     [device.cur_tx], 0              ; Set current tx descriptor to 0
  574.         mov     [device.last_tx], 0
  575.  
  576.         DEBUGF  1, "Initialising RX Descriptors\n"
  577.  
  578.         mov     ecx, NUM_RX_DESC
  579.         lea     esi, [device.rxd]
  580.   .rxdescloop:
  581.         lea     eax, [esi + 16]                 ; next ptr
  582.         GetRealAddr
  583.         mov     dword [esi], eax
  584.         mov     dword [esi + 4], RX_BUFF_SZ     ; size
  585.  
  586.         push    ecx esi
  587.         stdcall KernelAlloc, RX_BUFF_SZ
  588.         pop     esi ecx
  589.         test    eax, eax
  590.         jz      .fail
  591.         mov     dword [esi + 12], eax           ; address
  592.         GetRealAddr
  593.         mov     dword [esi + 8], eax            ; real address
  594.         add     esi, 16
  595.         dec     ecx
  596.         jnz     .rxdescloop
  597.  
  598.         lea     eax, [device.rxd]
  599.         GetRealAddr
  600.         mov     dword [esi - 16], eax           ; correct last descriptor link ptr
  601.  
  602.         set_io  0
  603.         set_io  rxdp
  604. ;        lea     eax, [device.rxd]
  605. ;        GetRealAddr
  606.         out     dx, eax
  607.  
  608.         mov     [device.cur_rx], 0              ; Set current rx descriptor to 0
  609.  
  610.         DEBUGF  1, "setting RX mode\n"
  611.  
  612.         xor     cl, cl
  613.   .rxfilterloop:
  614.         set_io  0
  615.         set_io  rfcr                    ; Receive Filter Control Reg offset
  616.         mov     eax, 4                  ; determine table entry
  617.         add     al, cl
  618.         shl     eax, 16
  619.         out     dx, eax                 ; tell card which entry to modify
  620.  
  621.         set_io  rfdr                    ; Receive Filter Control Reg offset
  622.         mov     eax, 0xffff             ; entry value
  623.         out     dx, ax                  ; write value to table in card
  624.  
  625.         inc     cl                      ; next entry
  626.         cmp     cl, [device.table_entries]
  627.         jb      .rxfilterloop
  628.  
  629.         set_io  rfcr                    ; Receive Filter Control Register offset
  630.         mov     eax, RFAAB + RFAAM + RFAAP + RFEN
  631.         out     dx, eax
  632.  
  633.         set_io  rxcfg                   ; Receive Config Register offset
  634.         mov     eax, ATX + RX_DMA + 2   ; 0x2 : RX Drain Threshold = 8*8=64 bytes
  635.         out     dx, eax
  636.  
  637.         DEBUGF  1, "setting TX mode\n"
  638.  
  639.         set_io  txcfg                   ; Transmit config Register offset
  640.         mov     eax, ATP + HBI + CSI + TX_DMA + 0x120
  641.                                         ; TX Fill threshold = 0x100
  642.                                         ; TX Drain Threshold = 0x20
  643.         out     dx, eax
  644.  
  645.         DEBUGF  1, "Enabling interrupts\n"
  646.  
  647.         set_io  imr
  648.         mov     eax, IE                 ; Interrupt enable mask
  649.         out     dx, eax
  650.  
  651.         set_io  cr
  652.         in      eax, dx
  653.         or      eax, RxENA              ; Enable Receive
  654.         out     dx, eax
  655.  
  656.         set_io  ier                     ; Interrupt enable
  657.         mov     eax, 1
  658.         out     dx, eax
  659.  
  660.         mov     [device.mtu], 1514
  661.  
  662. ; Set link state to unknown
  663.         mov     [device.state], ETH_LINK_UNKOWN
  664.  
  665.         xor     eax, eax
  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.         push    ebx esi edi
  1050.  
  1051.         DEBUGF  1,"\n%s int\n", my_service
  1052.  
  1053. ; find pointer of device which made IRQ occur
  1054.  
  1055.         mov     ecx, [devices]
  1056.         test    ecx, ecx
  1057.         jz      .nothing
  1058.         mov     esi, device_list
  1059.   .nextdevice:
  1060.         mov     ebx, [esi]
  1061.  
  1062.         set_io  0
  1063.         set_io  isr
  1064.         in      eax, dx                 ; note that this clears all interrupts
  1065.         test    ax, IE
  1066.         jnz     .got_it
  1067.   .continue:
  1068.         add     esi, 4
  1069.         dec     ecx
  1070.         jnz     .nextdevice
  1071.   .nothing:
  1072.         pop     edi esi ebx
  1073.         xor     eax, eax
  1074.  
  1075.         ret
  1076.  
  1077.   .got_it:
  1078.  
  1079.         DEBUGF  1,"Device: %x Status: %x ", ebx, ax
  1080.  
  1081.         test    ax, RxOK
  1082.         jz      .no_rx_
  1083.  
  1084.         push    ax
  1085.  
  1086.   .rx_loop:
  1087.  
  1088. ;-----------
  1089. ; Get Status
  1090.         movzx   eax, [device.cur_rx]                    ; find current descriptor
  1091.         shl     eax, 4                                  ; * 16
  1092.         mov     ecx, dword[device.rxd + eax + 4]        ; get receive status
  1093.  
  1094. ;-------------------------------------------
  1095. ; Check RX_Status to see if packet is waiting
  1096.         test    ecx, 0x80000000
  1097.         jz      .no_rx
  1098.  
  1099. ;----------------------------------------------
  1100. ; There is a packet waiting check it for errors
  1101.         test    ecx, 0x67C0000                  ; see if there are any errors
  1102.         jnz     .error_status
  1103.  
  1104. ;---------------------
  1105. ; Check size of packet
  1106.         and     ecx, DSIZE                      ; get packet size minus CRC
  1107.         sub     ecx, CRC_SIZE                   ; make sure packet contains data
  1108.         jbe     .error_size
  1109.  
  1110. ; update statistics
  1111.         inc     dword [device.packets_rx]
  1112.         add     dword [device.bytes_rx], ecx
  1113.         adc     dword [device.bytes_rx + 4], 0
  1114.  
  1115.         push    ebx
  1116.         push    .return
  1117.         push    ecx                             ; packet size
  1118.         pushd   [device.rxd + eax + 12]         ; packet ptr
  1119.         DEBUGF  1, "Packet received OK\n"
  1120.         jmp     Eth_input
  1121.   .return:
  1122.         pop     ebx
  1123.  
  1124. ; Reset status, allow ethernet card access to descriptor
  1125.         stdcall KernelAlloc, RX_BUFF_SZ
  1126.         test    eax, eax
  1127.         jz      .fail
  1128.         movzx   ecx, [device.cur_rx]
  1129.         shl     ecx, 4                          ; *16
  1130.         lea     ecx, [device.rxd + ecx]
  1131.         mov     dword [ecx + 12], eax
  1132.         GetRealAddr
  1133.         mov     dword [ecx + 8], eax
  1134.         mov     dword [ecx + 4], RX_BUFF_SZ
  1135.  
  1136.         inc     [device.cur_rx]                         ; get next descriptor
  1137.         and     [device.cur_rx], NUM_RX_DESC-1          ; only 4 descriptors 0-3
  1138.  
  1139.         jmp     .rx_loop
  1140.  
  1141.   .no_rx:
  1142.         set_io  0
  1143.         set_io  cr
  1144.         in      eax, dx
  1145.         or      eax, RxENA                              ; Re-Enable the Receive state machine
  1146.         out     dx, eax
  1147.  
  1148.         pop     ax
  1149.  
  1150.   .no_rx_:
  1151.         test    ax, TxOK
  1152.         jz      .no_tx
  1153.  
  1154.         DEBUGF  1, "TX ok!\n"
  1155.  
  1156.   .tx_loop:
  1157.         movzx   ecx, [device.last_tx]
  1158.         shl     ecx, 4                  ; *16
  1159.         lea     ecx, [device.txd + ecx]
  1160.  
  1161.         test    dword [ecx + 4], 0x80000000   ; card owns descr
  1162.         jnz     .no_tx
  1163.         cmp     dword [ecx + 12], 0
  1164.         je      .no_tx
  1165.  
  1166.         DEBUGF  1, "Freeing packet = %x\n", [ecx + 12]:8
  1167.         push    dword [ecx + 12]
  1168.         mov     dword [ecx + 12], 0
  1169.         call    KernelFree
  1170.  
  1171.         inc     [device.last_tx]
  1172.         and     [device.last_tx], NUM_TX_DESC-1
  1173.         jmp     .tx_loop
  1174.  
  1175.   .no_tx:
  1176.   .fail:
  1177.         pop     edi esi ebx
  1178.         xor     eax, eax
  1179.         inc     eax
  1180.  
  1181.         ret
  1182.  
  1183.         ret
  1184.  
  1185.   .error_status:
  1186.         DEBUGF  1, "Packet error: %x\n", ecx
  1187.         jmp     .fail
  1188.  
  1189.   .error_size:
  1190.         DEBUGF  1, "Packet too large/small\n"
  1191.         jmp     .fail
  1192.  
  1193.  
  1194.  
  1195.  
  1196.  
  1197. ; End of code
  1198.  
  1199. align 4                                         ; Place all initialised data here
  1200.  
  1201. devices         dd 0
  1202.  
  1203. specific_table:
  1204. ;    dd SIS630A_900_REV, Get_Mac_SIS630A_900_REV, 0
  1205. ;    dd SIS630E_900_REV, Get_Mac_SIS630E_900_REV, 0
  1206.     dd SIS630S_900_REV, Get_Mac_SIS635_900_REV, 0
  1207.     dd SIS630EA1_900_REV, Get_Mac_SIS635_900_REV, 0
  1208.     dd SIS630ET_900_REV, Get_Mac_SIS635_900_REV, 0 ;SIS630ET_900_REV_SpecialFN
  1209.     dd SIS635A_900_REV, Get_Mac_SIS635_900_REV, 0
  1210.     dd SIS900_960_REV, SIS960_get_mac_addr, 0
  1211.     dd SIS900B_900_REV, SIS900_get_mac_addr, 0
  1212.     dd 0                                        ; end of list
  1213.  
  1214. version         dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
  1215. my_service      db 'SIS900',0                  ; max 16 chars include zero
  1216.  
  1217. include_debug_strings                          ; All data wich FDO uses will be included here
  1218.  
  1219. section '.data' data readable writable align 16; place all uninitialized data place here
  1220.  
  1221. device_list     rd MAX_DEVICES                 ; This list contains all pointers to device structures the driver is handling
  1222.  
  1223.