Subversion Repositories Kolibri OS

Rev

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

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