Subversion Repositories Kolibri OS

Rev

Rev 1519 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

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