Subversion Repositories Kolibri OS

Rev

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