Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2004-2014. All rights reserved.    ;;
  4. ;; Distributed under terms of the GNU General Public License       ;;
  5. ;;                                                                 ;;
  6. ;;  DEC 21x4x driver for KolibriOS                                 ;;
  7. ;;                                                                 ;;
  8. ;;  Based on dec21140.Asm from Solar OS by                         ;;
  9. ;;     Eugen Brasoveanu,                                           ;;
  10. ;;       Ontanu Bogdan Valentin                                    ;;
  11. ;;                                                                 ;;
  12. ;;  Written by hidnplayr@kolibrios.org                             ;;
  13. ;;                                                                 ;;
  14. ;;          GNU GENERAL PUBLIC LICENSE                             ;;
  15. ;;             Version 2, June 1991                                ;;
  16. ;;                                                                 ;;
  17. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  18.  
  19. format PE DLL native
  20. entry START
  21.  
  22.         CURRENT_API             = 0x0200
  23.         COMPATIBLE_API          = 0x0100
  24.         API_VERSION             = (COMPATIBLE_API shl 16) + CURRENT_API
  25.  
  26.         MAX_DEVICES             = 16
  27.  
  28.         RX_DES_COUNT            = 4     ; no of RX descriptors, must be power of 2
  29.         RX_BUFF_SIZE            = 2048  ; size of buffer for each descriptor, must be multiple of 4 and <= 2048 TDES1_TBS1_MASK
  30.  
  31.         TX_DES_COUNT            = 4     ; no of TX descriptors, must be power of 2
  32.         TX_BUFF_SIZE            = 2048  ; size of buffer for each descriptor, used for memory allocation only
  33.  
  34.         __DEBUG__               = 1
  35.         __DEBUG_LEVEL__         = 2     ; 1 = verbose, 2 = errors only
  36.  
  37. section '.flat' readable writable executable
  38.  
  39. include '../proc32.inc'
  40. include '../struct.inc'
  41. include '../macros.inc'
  42. include '../fdo.inc'
  43. include '../netdrv.inc'
  44.  
  45. ;-------------------------------------------
  46. ; configuration registers
  47. ;-------------------------------------------
  48. CFCS                    = 4             ; configuration and status register
  49.  
  50. CSR0                    = 0x00          ; Bus mode
  51. CSR1                    = 0x08          ; Transmit Poll Command
  52. CSR2                    = 0x10          ; Receive Poll Command
  53. CSR3                    = 0x18          ; Receive list base address
  54. CSR4                    = 0x20          ; Transmit list base address
  55. CSR5                    = 0x28          ; Status
  56. CSR6                    = 0x30          ; Operation mode
  57. CSR7                    = 0x38          ; Interrupt enable
  58. CSR8                    = 0x40          ; Missed frames and overflow counter
  59. CSR9                    = 0x48          ; Boot ROM, serial ROM, and MII management
  60. CSR10                   = 0x50          ; Boot ROM programming address
  61. CSR11                   = 0x58          ; General-purpose timer
  62. CSR12                   = 0x60          ; General-purpose port
  63. CSR13                   = 0x68
  64. CSR14                   = 0x70
  65. CSR15                   = 0x78          ; Watchdog timer
  66.  
  67. ;--------bits/commands of CSR0-------------------
  68. CSR0_RESET              = 1b
  69.  
  70. CSR0_WIE                = 1 shl 24      ; Write and Invalidate Enable
  71. CSR0_RLE                = 1 shl 23      ; PCI Read Line Enable
  72. CSR0_RML                = 1 shl 21      ; PCI Read Multiple
  73.  
  74. CSR0_CACHEALIGN_NONE    = 00b shl 14
  75. CSR0_CACHEALIGN_32      = 01b shl 14
  76. CSR0_CACHEALIGN_64      = 10b shl 14
  77. CSR0_CACHEALIGN_128     = 11b shl 14
  78.  
  79. ; using values from linux driver..
  80. CSR0_DEFAULT            = CSR0_WIE + CSR0_RLE + CSR0_RML + CSR0_CACHEALIGN_NONE
  81.  
  82. ;------- CSR5 -STATUS- bits --------------------------------
  83. CSR5_TI                 = 1 shl 0       ; Transmit interupt - frame transmition completed
  84. CSR5_TPS                = 1 shl 1       ; Transmit process stopped
  85. CSR5_TU                 = 1 shl 2       ; Transmit Buffer unavailable
  86. CSR5_TJT                = 1 shl 3       ; Transmit Jabber Timeout (transmitter had been excessively active)
  87. CSR5_UNF                = 1 shl 5       ; Transmit underflow - FIFO underflow
  88. CSR5_RI                 = 1 shl 6       ; Receive Interrupt
  89. CSR5_RU                 = 1 shl 7       ; Receive Buffer unavailable
  90. CSR5_RPS                = 1 shl 8       ; Receive Process stopped
  91. CSR5_RWT                = 1 shl 9       ; Receive Watchdow Timeout
  92. CSR5_ETI                = 1 shl 10      ; Early transmit Interrupt
  93. CSR5_GTE                = 1 shl 11      ; General Purpose Timer Expired
  94. CSR5_FBE                = 1 shl 13      ; Fatal bus error
  95. CSR5_ERI                = 1 shl 14      ; Early receive Interrupt
  96. CSR5_AIS                = 1 shl 15      ; Abnormal interrupt summary
  97. CSR5_NIS                = 1 shl 16      ; normal interrupt summary
  98. CSR5_RS_SH              = 17            ; Receive process state  -shift
  99. CSR5_RS_MASK            = 111b          ;                        -mask
  100. CSR5_TS_SH              = 20            ; Transmit process state -shift
  101. CSR5_TS_MASK            = 111b          ;                        -mask
  102. CSR5_EB_SH              = 23            ; Error bits             -shift
  103. CSR5_EB_MASK            = 111b          ; Error bits             -mask
  104.  
  105. ;CSR5 TS values
  106. CSR5_TS_STOPPED                 = 000b
  107. CSR5_TS_RUNNING_FETCHING_DESC   = 001b
  108. CSR5_TS_RUNNING_WAITING_TX      = 010b
  109. CSR5_TS_RUNNING_READING_BUFF    = 011b
  110. CSR5_TS_RUNNING_SETUP_PCKT      = 101b
  111. CSR5_TS_SUSPENDED               = 110b
  112. CSR5_TS_RUNNING_CLOSING_DESC    = 111b
  113.  
  114. ;------- CSR6 -OPERATION MODE- bits --------------------------------
  115. CSR6_HP                 = 1 shl 0       ; Hash/Perfect Receive Filtering mode
  116. CSR6_SR                 = 1 shl 1       ; Start/Stop receive
  117. CSR6_HO                 = 1 shl 2       ; Hash only Filtering mode
  118. CSR6_PB                 = 1 shl 3       ; Pass bad frames
  119. CSR6_IF                 = 1 shl 4       ; Inverse filtering
  120. CSR6_SB                 = 1 shl 5       ; Start/Stop backoff counter
  121. CSR6_PR                 = 1 shl 6       ; Promiscuos mode -default after reset
  122. CSR6_PM                 = 1 shl 7       ; Pass all multicast
  123. CSR6_F                  = 1 shl 9       ; Full Duplex mode
  124. CSR6_OM_SH              = 10            ; Operating Mode -shift
  125. CSR6_OM_MASK            = 11b           ;                -mask
  126. CSR6_FC                 = 1 shl 12      ; Force Collision Mode
  127. CSR6_ST                 = 1 shl 13      ; Start/Stop Transmission Command
  128. CSR6_TR_SH              = 14            ; Threshold Control      -shift
  129. CSR6_TR_MASK            = 11b           ;                        -mask
  130. CSR6_CA                 = 1 shl 17      ; Capture Effect Enable
  131. CSR6_PS                 = 1 shl 18      ; Port select SRL / MII/SYM
  132. CSR6_HBD                = 1 shl 19      ; Heartbeat Disable
  133. CSR6_SF                 = 1 shl 21      ; Store and Forward -transmit full packet only
  134. CSR6_TTM                = 1 shl 22      ; Transmit Threshold Mode -
  135. CSR6_PCS                = 1 shl 23      ; PCS active and MII/SYM port operates in symbol mode
  136. CSR6_SCR                = 1 shl 24      ; Scrambler Mode
  137. CSR6_MBO                = 1 shl 25      ; Must Be One
  138. CSR6_RA                 = 1 shl 30      ; Receive All
  139. CSR6_SC                 = 1 shl 31      ; Special Capture Effect Enable
  140.  
  141.  
  142. ;------- CSR7 -INTERRUPT ENABLE- bits --------------------------------
  143. CSR7_TI                 = 1 shl 0       ; transmit Interrupt Enable (set with CSR7<16> & CSR5<0> )
  144. CSR7_TS                 = 1 shl 1       ; transmit Stopped Enable (set with CSR7<15> & CSR5<1> )
  145. CSR7_TU                 = 1 shl 2       ; transmit buffer underrun Enable (set with CSR7<16> & CSR5<2> )
  146. CSR7_TJ                 = 1 shl 3       ; transmit jabber timeout enable (set with CSR7<15> & CSR5<3> )
  147. CSR7_UN                 = 1 shl 5       ; underflow Interrupt enable (set with CSR7<15> & CSR5<5> )
  148. CSR7_RI                 = 1 shl 6       ; receive Interrupt enable (set with CSR7<16> & CSR5<5> )
  149. CSR7_RU                 = 1 shl 7       ; receive buffer unavailable enable (set with CSR7<15> & CSR5<7> )
  150. CSR7_RS                 = 1 shl 8       ; Receive stopped enable (set with CSR7<15> & CSR5<8> )
  151. CSR7_RW                 = 1 shl 9       ; receive watchdog timeout enable (set with CSR7<15> & CSR5<9> )
  152. CSR7_ETE                = 1 shl 10      ; Early transmit Interrupt enable (set with CSR7<15> & CSR5<10> )
  153. CSR7_GPT                = 1 shl 11      ; general purpose timer enable (set with CSR7<15> & CSR5<11> )
  154. CSR7_FBE                = 1 shl 13      ; Fatal bus error enable (set with CSR7<15> & CSR5<13> )
  155. CSR7_ERE                = 1 shl 14      ; Early receive enable (set with CSR7<16> & CSR5<14> )
  156. CSR7_AI                 = 1 shl 15      ; Abnormal Interrupt Summary Enable (enables CSR5<0,3,7,8,9,10,13>)
  157. CSR7_NI                 = 1 shl 16      ; Normal Interrup Enable (enables CSR5<0,2,6,11,14>)
  158.  
  159. CSR7_DEFAULT            = CSR7_TI + CSR7_TS + CSR7_RI + CSR7_RS + CSR7_TU + CSR7_TJ + CSR7_UN + \
  160.                                         CSR7_RU + CSR7_RW + CSR7_FBE + CSR7_AI + CSR7_NI
  161. ;common to Rx and Tx
  162. DES0_OWN                = 1 shl 31              ; if set, the NIC controls the descriptor, otherwise driver 'owns' the descriptors
  163.  
  164. ;receive
  165. RDES0_ZER               = 1 shl 0               ; must be 0 if legal length :D
  166. RDES0_CE                = 1 shl 1               ; CRC error, valid only on last desc (RDES0<8>=1)
  167. RDES0_DB                = 1 shl 2               ; dribbling bit - not multiple of 8 bits, valid only on last desc (RDES0<8>=1)
  168. RDES0_RE                = 1 shl 3               ; Report on MII error.. i dont realy know what this means :P
  169. RDES0_RW                = 1 shl 4               ; received watchdog timer expiration - must set CSR5<9>, valid only on last desc (RDES0<8>=1)
  170. RDES0_FT                = 1 shl 5               ; frame type: 0->IEEE802.0 (len<1500) 1-> ETHERNET frame (len>1500), valid only on last desc (RDES0<8>=1)
  171. RDES0_CS                = 1 shl 6               ; Collision seen, valid only on last desc (RDES0<8>=1)
  172. RDES0_TL                = 1 shl 7               ; Too long(>1518)-NOT AN ERROR, valid only on last desc (RDES0<8>=1)
  173. RDES0_LS                = 1 shl 8               ; Last descriptor of current frame
  174. RDES0_FS                = 1 shl 9               ; First descriptor of current frame
  175. RDES0_MF                = 1 shl 10              ; Multicast frame, valid only on last desc (RDES0<8>=1)
  176. RDES0_RF                = 1 shl 11              ; Runt frame, valid only on last desc (RDES0<8>=1) and id overflow
  177. RDES0_DT_SERIAL         = 00b shl 12            ; Data type-Serial recv frame, valid only on last desc (RDES0<8>=1)
  178. RDES0_DT_INTERNAL       = 01b shl 12            ; Data type-Internal loopback recv frame, valid only on last desc (RDES0<8>=1)
  179. RDES0_DT_EXTERNAL       = 11b shl 12            ; Data type-External loopback recv frame, valid only on last desc (RDES0<8>=1)
  180. RDES0_DE                = 1 shl 14              ; Descriptor error - cant own a new desc and frame doesnt fit, valid only on last desc (RDES0<8>=1)
  181. RDES0_ES                = 1 shl 15              ; Error Summmary - bits 1+6+11+14, valid only on last desc (RDES0<8>=1)
  182. RDES0_FL_SH             = 16                    ; Field length shift, valid only on last desc (RDES0<8>=1)
  183. RDES0_FL_MASK           = 11111111111111b       ; Field length mask (+CRC), valid only on last desc (RDES0<8>=1)
  184. RDES0_FF                = 1 shl 30              ; Filtering fail-frame failed address recognition test(must CSR6<30>=1), valid only on last desc (RDES0<8>=1)
  185.  
  186. RDES1_RBS1_MASK         = 11111111111b          ; first buffer size MASK
  187. RDES1_RBS2_SH           = 11                    ; second buffer size SHIFT
  188. RDES1_RBS2_MASK         = 11111111111b          ; second buffer size MASK
  189. RDES1_RCH               = 1 shl 24              ; Second address chained - second address (buffer) is next desc address
  190. RDES1_RER               = 1 shl 25              ; Receive End of Ring - final descriptor, NIC must return to first desc
  191.  
  192. ;transmition
  193. TDES0_DE                = 1 shl 0               ; Deffered
  194. TDES0_UF                = 1 shl 1               ; Underflow error
  195. TDES0_LF                = 1 shl 2               ; Link fail report (only if CSR6<23>=1)
  196. TDES0_CC_SH             = 3                     ; Collision Count shift - no of collision before transmition
  197. TDES0_CC_MASK           = 1111b                 ; Collision Count mask
  198. TDES0_HF                = 1 shl 7               ; Heartbeat fail
  199. TDES0_EC                = 1 shl 8               ; Excessive Collisions - >16 collisions
  200. TDES0_LC                = 1 shl 9               ; Late collision
  201. TDES0_NC                = 1 shl 10              ; No carrier
  202. TDES0_LO                = 1 shl 11              ; Loss of carrier
  203. TDES0_TO                = 1 shl 14              ; Transmit Jabber Timeout
  204. TDES0_ES                = 1 shl 15              ; Error summary TDES0<1+8+9+10+11+14>=1
  205.  
  206. TDES1_TBS1_MASK         = 11111111111b          ; Buffer 1 size mask
  207. TDES1_TBS2_SH           = 11                    ; Buffer 2 size shift
  208. TDES1_TBS2_MASK         = 11111111111b          ; Buffer 2 size mask
  209. TDES1_FT0               = 1 shl 22              ; Filtering type 0
  210. TDES1_DPD               = 1 shl 23              ; Disabled padding for packets <64bytes, no padding
  211. TDES1_TCH               = 1 shl 24              ; Second address chained - second buffer pointer is to next desc
  212. TDES1_TER               = 1 shl 25              ; Transmit end of ring - final descriptor
  213. TDES1_AC                = 1 shl 26              ; Add CRC disable -pretty obvious
  214. TDES1_SET               = 1 shl 27              ; Setup packet
  215. TDES1_FT1               = 1 shl 28              ; Filtering type 1
  216. TDES1_FS                = 1 shl 29              ; First segment - buffer is first segment of frame
  217. TDES1_LS                = 1 shl 30              ; Last segment
  218. TDES1_IC                = 1 shl 31              ; Interupt on completion (CSR5<0>=1) valid when TDES1<30>=1
  219.  
  220. RX_MEM_TOTAL_SIZE       = RX_DES_COUNT*(sizeof.DES+RX_BUFF_SIZE)
  221. TX_MEM_TOTAL_SIZE       = TX_DES_COUNT*(sizeof.DES+TX_BUFF_SIZE)
  222.  
  223.  
  224. struct  device          ETH_DEVICE
  225.  
  226.         rx_p_des        dd ?    ; descriptors ring with received packets
  227.         tx_p_des        dd ?    ; descriptors ring with 'to transmit' packets
  228.         tx_free_des     dd ?    ; Tx descriptors available
  229.         tx_wr_des       dd ?    ; Tx current descriptor to write data to
  230.         tx_rd_des       dd ?    ; Tx current descriptor to read TX completion
  231.         rx_crt_des      dd ?    ; Rx current descriptor
  232.  
  233.         io_addr         dd ?
  234.         pci_bus         dd ?
  235.         pci_dev         dd ?
  236.         irq_line        db ?
  237.  
  238. ends
  239.  
  240. ;----------- descriptor structure ---------------------
  241. struct  DES
  242.         status          dd ?    ; bit 31 is 'own' and rest is 'status'
  243.         length          dd ?    ; control bits + bytes-count buffer 1 + bytes-count buffer 2
  244.         buffer1         dd ?    ; pointer to buffer1
  245.         buffer2         dd ?    ; pointer to buffer2 or in this case to next descriptor, as we use a chained structure
  246.         virtaddr        dd ?
  247.  
  248.         rb 0x40 - ($ and 0x3f)  ; align 64
  249. ends
  250.  
  251. ;=============================================================================
  252. ; serial ROM operations
  253. ;=============================================================================
  254. CSR9_SR                 = 1 shl 11        ; SROM Select
  255. CSR9_RD                 = 1 shl 14        ; ROM Read Operation
  256. CSR9_SROM_DO            = 1 shl 3         ; Data Out for SROM
  257. CSR9_SROM_DI            = 1 shl 2         ; Data In to SROM
  258. CSR9_SROM_CK            = 1 shl 1         ; clock for SROM
  259. CSR9_SROM_CS            = 1 shl 0         ; chip select.. always needed
  260.  
  261. ; assume dx is CSR9
  262. macro SROM_Delay {
  263.         push    eax
  264.         in      eax, dx
  265.         in      eax, dx
  266.         in      eax, dx
  267.         in      eax, dx
  268.         in      eax, dx
  269.         in      eax, dx
  270.         in      eax, dx
  271.         in      eax, dx
  272.         in      eax, dx
  273.         in      eax, dx
  274.         pop     eax
  275. }
  276.  
  277. ; assume dx is CSR9
  278. macro MDIO_Delay {
  279.         push    eax
  280.         in      eax, dx
  281.         pop     eax
  282. }
  283.  
  284. macro Bit_Set a_bit {
  285.         in      eax, dx
  286.         or      eax, a_bit
  287.         out     dx , eax
  288. }
  289.  
  290. macro Bit_Clear a_bit {
  291.         in      eax, dx
  292.         and     eax, not (a_bit)
  293.         out     dx, eax
  294. }
  295.  
  296.  
  297. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  298. ;;                        ;;
  299. ;; proc START             ;;
  300. ;;                        ;;
  301. ;; (standard driver proc) ;;
  302. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  303.  
  304. proc START c, reason:dword, cmdline:dword
  305.  
  306.         cmp     [reason], DRV_ENTRY
  307.         jne     .fail
  308.  
  309.         DEBUGF  2,"Loading driver\n"
  310.         invoke  RegService, my_service, service_proc
  311.         ret
  312.  
  313.   .fail:
  314.         xor     eax, eax
  315.         ret
  316.  
  317. endp
  318.  
  319.  
  320. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  321. ;;                        ;;
  322. ;; proc SERVICE_PROC      ;;
  323. ;;                        ;;
  324. ;; (standard driver proc) ;;
  325. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  326.  
  327. align 4
  328. proc service_proc stdcall, ioctl:dword
  329.  
  330.         mov     edx, [ioctl]
  331.         mov     eax, [edx + IOCTL.io_code]
  332.  
  333. ;------------------------------------------------------
  334.  
  335.         cmp     eax, 0 ;SRV_GETVERSION
  336.         jne     @F
  337.  
  338.         cmp     [edx + IOCTL.out_size], 4
  339.         jb      .fail
  340.         mov     eax, [edx + IOCTL.output]
  341.         mov     [eax], dword API_VERSION
  342.  
  343.         xor     eax, eax
  344.         ret
  345.  
  346. ;------------------------------------------------------
  347.   @@:
  348.         cmp     eax, 1 ;SRV_HOOK
  349.         jne     .fail
  350.  
  351.         cmp     [edx + IOCTL.inp_size], 3                     ; Data input must be at least 3 bytes
  352.         jb      .fail
  353.  
  354.         mov     eax, [edx + IOCTL.input]
  355.         cmp     byte [eax], 1                           ; 1 means device number and bus number (pci) are given
  356.         jne     .fail                                   ; other types arent supported for this card yet
  357.  
  358. ; check if the device is already listed
  359.  
  360.         mov     esi, device_list
  361.         mov     ecx, [devices]
  362.         test    ecx, ecx
  363.         jz      .firstdevice
  364.  
  365. ;        mov     eax, [edx + IOCTL.input]                ; get the pci bus and device numbers
  366.         mov     ax, [eax+1]                             ;
  367.   .nextdevice:
  368.         mov     ebx, [esi]
  369.         cmp     al, byte[ebx + device.pci_bus]
  370.         jne     @f
  371.         cmp     ah, byte[ebx + device.pci_dev]
  372.         je      .find_devicenum                         ; Device is already loaded, let's find it's device number
  373.        @@:
  374.         add     esi, 4
  375.         loop    .nextdevice
  376.  
  377.  
  378. ; This device doesnt have its own eth_device structure yet, lets create one
  379.   .firstdevice:
  380.         cmp     [devices], MAX_DEVICES                  ; First check if the driver can handle one more card
  381.         jae     .fail
  382.  
  383.         push    edx
  384.         invoke  KernelAlloc, sizeof.device              ; Allocate the buffer for eth_device structure
  385.         pop     edx
  386.         test    eax, eax
  387.         jz      .fail
  388.         mov     ebx, eax                                ; ebx is always used as a pointer to the structure (in driver, but also in kernel code)
  389.  
  390. ; Fill in the direct call addresses into the struct
  391.  
  392.         mov     [ebx + device.reset], reset
  393.         mov     [ebx + device.transmit], transmit
  394.         mov     [ebx + device.unload], unload
  395.         mov     [ebx + device.name], my_service
  396.  
  397. ; save the pci bus and device numbers
  398.  
  399.         mov     eax, [edx + IOCTL.input]
  400.         movzx   ecx, byte[eax+1]
  401.         mov     [ebx + device.pci_bus], ecx
  402.         movzx   ecx, byte[eax+2]
  403.         mov     [ebx + device.pci_dev], ecx
  404.  
  405. ; Now, it's time to find the base io addres of the PCI device
  406.  
  407.         stdcall PCI_find_io, [ebx + device.pci_bus], [ebx + device.pci_dev]
  408.         mov     [ebx + device.io_addr], eax
  409.  
  410. ; We've found the io address, find IRQ now
  411.  
  412.         invoke  PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.interrupt_line
  413.         mov     [ebx + device.irq_line], al
  414.  
  415.         DEBUGF  2,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
  416.         [ebx + device.pci_dev]:1,[ebx + device.pci_bus]:1,[ebx + device.irq_line]:1,[ebx + device.io_addr]:8
  417.  
  418.         allocate_and_clear [ebx + device.rx_p_des], RX_DES_COUNT*(sizeof.DES+RX_BUFF_SIZE), .err
  419.         allocate_and_clear [ebx + device.tx_p_des], TX_DES_COUNT*(sizeof.DES+TX_BUFF_SIZE), .err
  420.  
  421. ; Ok, the eth_device structure is ready, let's probe the device
  422. ; Because initialization fires IRQ, IRQ handler must be aware of this device
  423.         mov     eax, [devices]                                          ; Add the device structure to our device list
  424.         mov     [device_list+4*eax], ebx                                ; (IRQ handler uses this list to find device)
  425.         inc     [devices]                                               ;
  426.  
  427.         call    probe                                                   ; this function will output in eax
  428.         test    eax, eax
  429.         jnz     .err2                                                   ; If an error occured, exit
  430.  
  431.  
  432.         mov     [ebx + device.type], NET_TYPE_ETH
  433.         invoke  NetRegDev
  434.  
  435.         cmp     eax, -1
  436.         je      .destroy
  437.  
  438.         ret
  439.  
  440. ; If the device was already loaded, find the device number and return it in eax
  441.  
  442.   .find_devicenum:
  443.         DEBUGF  2,"Trying to find device number of already registered device\n"
  444.         invoke  NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
  445.                                                                         ; into a device number in edi
  446.         mov     eax, edi                                                ; Application wants it in eax instead
  447.         DEBUGF  2,"Kernel says: %u\n", eax
  448.         ret
  449.  
  450. ; If an error occured, remove all allocated data and exit (returning -1 in eax)
  451.  
  452.   .destroy:
  453.         ; todo: reset device into virgin state
  454.  
  455.   .err2:
  456.         dec     [devices]
  457.   .err:
  458.         DEBUGF  2,"removing device structure\n"
  459.         invoke  KernelFree, [ebx + device.rx_p_des]
  460.         invoke  KernelFree, [ebx + device.tx_p_des]
  461.         invoke  KernelFree, ebx
  462.  
  463.  
  464.   .fail:
  465.         or      eax, -1
  466.         ret
  467.  
  468. ;------------------------------------------------------
  469. endp
  470.  
  471.  
  472. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  473. ;;                                                                        ;;
  474. ;;        Actual Hardware dependent code starts here                      ;;
  475. ;;                                                                        ;;
  476. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  477.  
  478.  
  479.  
  480. align 4
  481. unload:
  482.         ; TODO: (in this particular order)
  483.         ;
  484.         ; - Stop the device
  485.         ; - Detach int handler
  486.         ; - Remove device from local list (RTL8139_LIST)
  487.         ; - call unregister function in kernel
  488.         ; - Remove all allocated structures and buffers the card used
  489.  
  490.         or      eax,-1
  491.  
  492. ret
  493.  
  494.  
  495. macro status {
  496.         set_io  [ebx + device.io_addr], CSR5
  497.         in      eax, dx
  498.         DEBUGF  1,"CSR5: %x\n", eax
  499. }
  500.  
  501.  
  502. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  503. ;;                                         ;;
  504. ;; Probe                                   ;;
  505. ;;                                         ;;
  506. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  507.  
  508. align 4
  509. probe:
  510.  
  511.         DEBUGF  2,"Probing dec21x4x device: "
  512.  
  513. ; Make the device a bus master
  514.         invoke  PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command
  515.         or      al, PCI_CMD_MASTER
  516.         invoke  PciWrite32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command, eax
  517.  
  518. ; Check the vendor/device ID
  519.         invoke  PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], 0                                ; get device/vendor id
  520.         DEBUGF  1,"Vendor id: 0x%x\n", ax
  521.  
  522.         cmp     ax, 0x1011
  523.         je      .dec
  524.         cmp     ax, 0x1317
  525.         je      .admtek
  526.         jmp     .notfound
  527.  
  528.   .dec:
  529.         shr     eax, 16
  530.         DEBUGF  1,"Vendor ok!, device id: 0x%x\n", ax                 ; TODO: use another method to detect chip!
  531.  
  532.         cmp     ax, 0x0009
  533.         je      .supported_device
  534.  
  535.         cmp     ax, 0x0019
  536.         je      .supported_device2
  537.  
  538.   .admtek:
  539.         shr     eax, 16
  540.         DEBUGF  1,"Vendor ok!, device id: 0x%x\n", ax
  541.  
  542.         cmp     ax, 0x0985
  543.         je      .supported_device
  544.  
  545.   .notfound:
  546.         DEBUGF  1,"Device not supported!\n"
  547.         or      eax, -1
  548.         ret
  549.  
  550.   .supported_device2:
  551.  
  552.         ; wake up the 21143
  553.  
  554.         xor     eax, eax
  555.         invoke  PciWrite32, [ebx + device.pci_bus], [ebx + device.pci_dev], 0x40, eax
  556.  
  557.  
  558.   .supported_device:
  559.         call    SROM_GetWidth           ; TODO: use this value returned in ecx
  560.                                         ; in the read_word routine!
  561.  
  562. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  563. ;;                                         ;;
  564. ;; Reset                                   ;;
  565. ;;                                         ;;
  566. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  567.  
  568. align 4
  569. reset:
  570.  
  571.         DEBUGF  2,"Resetting dec21x4x\n"
  572.  
  573. ;-----------------------------------------------------------
  574. ; board software reset - if fails, dont do nothing else
  575.  
  576.         set_io  [ebx + device.io_addr], 0
  577.         status
  578.         set_io  [ebx + device.io_addr], CSR0
  579.         mov     eax, CSR0_RESET
  580.         out     dx, eax
  581.  
  582. ; wait at least 50 PCI cycles
  583.         mov     esi, 1000
  584.         invoke  Sleep
  585.  
  586. ;-----------
  587. ; setup CSR0
  588.  
  589.         set_io  [ebx + device.io_addr], 0
  590.         status
  591.         set_io  [ebx + device.io_addr], CSR0
  592.         mov     eax, CSR0_DEFAULT
  593.         out     dx, eax
  594.  
  595.  
  596. ; wait at least 50 PCI cycles
  597.         mov     esi, 1000
  598.         invoke  Sleep
  599.  
  600. ;-----------------------------------
  601. ; Read mac from eeprom to driver ram
  602.  
  603.         call    read_mac_eeprom
  604.  
  605. ;--------------------------------
  606. ; insert irq handler on given irq
  607.  
  608.         movzx   eax, [ebx + device.irq_line]
  609.         DEBUGF  1,"Attaching int handler to irq %x\n", eax:1
  610.         invoke  AttachIntHandler, eax, int_handler, ebx
  611.         test    eax, eax
  612.         jnz     @f
  613.         DEBUGF  2,"Could not attach int handler!\n"
  614.         or      eax, -1
  615.         ret
  616.   @@:
  617.  
  618.         set_io  [ebx + device.io_addr], 0
  619.         status
  620.  
  621.         call    init_ring
  622.  
  623. ;--------------------------------------------
  624. ; setup CSR3 & CSR4 (pointers to descriptors)
  625.  
  626.         set_io  [ebx + device.io_addr], 0
  627.         status
  628.         set_io  [ebx + device.io_addr], CSR3
  629.         mov     eax, [ebx + device.rx_p_des]
  630.         invoke  GetPhysAddr
  631.         DEBUGF  1,"RX descriptor base address: %x\n", eax
  632.         out     dx, eax
  633.  
  634.         set_io  [ebx + device.io_addr], CSR4
  635.         mov     eax, [ebx + device.tx_p_des]
  636.         invoke  GetPhysAddr
  637.         DEBUGF  1,"TX descriptor base address: %x\n", eax
  638.         out     dx, eax
  639.  
  640. ;-------------------------------------------------------
  641. ; setup interrupt mask register -expect IRQs from now on
  642.  
  643.         status
  644.         DEBUGF  1,"Enabling interrupts\n"
  645.         set_io  [ebx + device.io_addr], CSR7
  646.         mov     eax, CSR7_DEFAULT
  647.         out     dx, eax
  648.         status
  649.  
  650. ;----------
  651. ; enable RX
  652.  
  653.         set_io  [ebx + device.io_addr], 0
  654.         status
  655.         DEBUGF  1,"Enable RX\n"
  656.  
  657.         set_io  [ebx + device.io_addr], CSR6
  658.         Bit_Set CSR6_SR; or CSR6_PR or CSR6_ST
  659.         DEBUGF  1,"CSR6: %x\n", eax
  660.  
  661.         status
  662.  
  663.         call    start_link
  664.  
  665. ; wait a bit
  666.         mov     esi, 500
  667.         invoke  Sleep
  668.  
  669. ;----------------------------------------------------
  670. ; send setup packet to notify the board about the MAC
  671.  
  672.         call    Send_Setup_Packet
  673.  
  674.         xor     eax, eax
  675. ; clear packet/byte counters
  676.  
  677.         lea     edi, [ebx + device.bytes_tx]
  678.         mov     ecx, 6
  679.         rep     stosd
  680.  
  681. ; Set the mtu, kernel will be able to send now
  682.         mov     [ebx + device.mtu], 1514
  683.  
  684. ; Set link state to unknown
  685.         mov     [ebx + device.state], ETH_LINK_UNKNOWN
  686.  
  687.         DEBUGF  1,"Reset done\n"
  688.  
  689.         ret
  690.  
  691.  
  692.  
  693. align 4
  694. init_ring:
  695.  
  696. ;------------------------------------------
  697. ; Setup RX descriptors (use chained method)
  698.  
  699.         mov     eax, [ebx + device.rx_p_des]
  700.         invoke  GetPhysAddr
  701.         mov     edx, eax
  702.         push    eax
  703.         lea     esi, [eax + RX_DES_COUNT*(sizeof.DES)]  ; jump over RX descriptors
  704.         mov     eax, [ebx + device.rx_p_des]
  705.         add     eax, RX_DES_COUNT*(sizeof.DES)          ; jump over RX descriptors
  706.         mov     edi, [ebx + device.rx_p_des]
  707.         mov     ecx, RX_DES_COUNT
  708.   .loop_rx_des:
  709.         add     edx, sizeof.DES
  710.         mov     [edi + DES.status], DES0_OWN            ; hardware owns buffer
  711.         mov     [edi + DES.length], 1984 + RDES1_RCH    ; only size of first buffer, chained buffers
  712.         mov     [edi + DES.buffer1], esi                ; hw buffer address
  713.         mov     [edi + DES.buffer2], edx                ; pointer to next descriptor
  714.         mov     [edi + DES.virtaddr], eax               ; virtual buffer address
  715.         DEBUGF  1,"RX desc: buff addr: %x, next desc: %x, real buff addr: %x, real descr addr: %x \n", esi, edx, eax, edi
  716.  
  717.         add     esi, RX_BUFF_SIZE
  718.         add     eax, RX_BUFF_SIZE
  719.         add     edi, sizeof.DES
  720.         dec     ecx
  721.         jnz     .loop_rx_des
  722.  
  723. ; set last descriptor as LAST
  724.         or      [edi - sizeof.DES + DES.length], RDES1_RER      ; EndOfRing
  725.         pop     [edi - sizeof.DES + DES.buffer2]                ; point it to the first descriptor
  726.  
  727. ;---------------------
  728. ; Setup TX descriptors
  729.  
  730.         mov     eax, [ebx + device.tx_p_des]
  731.         invoke  GetPhysAddr
  732.         mov     edx, eax
  733.         push    eax
  734.         lea     esi, [eax + TX_DES_COUNT*(sizeof.DES)]  ; jump over TX descriptors
  735.         mov     eax, [ebx + device.tx_p_des]
  736.         add     eax, TX_DES_COUNT*(sizeof.DES)          ; jump over TX descriptors
  737.         mov     edi, [ebx + device.tx_p_des]
  738.         mov     ecx, TX_DES_COUNT
  739.   .loop_tx_des:
  740.         add     edx, sizeof.DES
  741.         mov     [edi + DES.status], 0                   ; owned by driver
  742.         mov     [edi + DES.length], TDES1_TCH           ; chained method
  743.         mov     [edi + DES.buffer1], esi                ; pointer to buffer
  744.         mov     [edi + DES.buffer2], edx                ; pointer to next descr
  745.         mov     [edi + DES.virtaddr], eax
  746.         DEBUGF  1,"TX desc: buff addr: %x, next desc: %x, virt buff addr: %x, virt descr addr: %x \n", esi, edx, eax, edi
  747.  
  748.         add     esi, TX_BUFF_SIZE
  749.         add     eax, TX_BUFF_SIZE
  750.         add     edi, sizeof.DES
  751.         dec     ecx
  752.         jnz     .loop_tx_des
  753.        
  754. ; set last descriptor as LAST
  755.         or      [edi - sizeof.DES + DES.length], TDES1_TER      ; EndOfRing
  756.         pop     [edi - sizeof.DES + DES.buffer2]                ; point it to the first descriptor
  757.  
  758. ;------------------
  759. ; Reset descriptors
  760.  
  761.         mov     [ebx + device.tx_wr_des], 0
  762.         mov     [ebx + device.tx_rd_des], 0
  763.         mov     [ebx + device.rx_crt_des], 0
  764.         mov     [ebx + device.tx_free_des], TX_DES_COUNT
  765.  
  766.         ret
  767.  
  768.  
  769. align 4
  770. start_link:
  771.  
  772.         DEBUGF  1,"Starting link\n"
  773.  
  774.         ; TODO: write working code here
  775.  
  776.         ret
  777.  
  778. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  779. ;;                                         ;;
  780. ;; Send setup packet                       ;;
  781. ;;                                         ;;
  782. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  783.  
  784. align 4
  785. Send_Setup_Packet:
  786.  
  787.         DEBUGF  1,"Sending setup packet\n"
  788.  
  789. ; if no descriptors available, out
  790.         mov     ecx, 1000
  791. @@loop_wait_desc:
  792.         cmp     [ebx + device.tx_free_des], 0
  793.         jne     @f
  794.  
  795.         dec     ecx
  796.         jnz     @@loop_wait_desc
  797.  
  798.         mov     eax, -1
  799.         ret
  800.       @@:
  801.  
  802. ; go to current send descriptor
  803.         mov     edi, [ebx + device.tx_p_des]
  804.         mov     eax, [ebx + device.tx_wr_des]
  805.         DEBUGF  1,"Got free descriptor: %u (%x)", eax, edi
  806.         mov     edx, sizeof.DES
  807.         mul     edx
  808.         add     edi, eax
  809.         DEBUGF  1,"=>%x\n",  edi
  810.  
  811. ; if NOT sending FIRST setup packet, must set current descriptor to 0 size for both buffers,
  812. ;  and go to next descriptor for real setup packet...            ;; TODO: check if 2 descriptors are available
  813.  
  814. ;       cmp     [ebx + device.tx_packets], 0
  815. ;       je      .first
  816. ;              
  817. ;       and     [edi+DES.des1], 0
  818. ;       mov     [edi+DES.des0], DES0_OWN
  819. ;              
  820. ; go to next descriptor
  821. ;        inc     [ebx + device.tx_wr_des]
  822. ;        and     [ebx + device.tx_wr_des], TX_DES_COUNT-1
  823. ;
  824. ; dec free descriptors count
  825. ;        cmp     [ebx + device.tx_free_des], 0
  826. ;        jz      @f
  827. ;        dec     [ebx + device.tx_free_des]
  828. ;       @@:
  829. ;
  830. ;       ; recompute pointer to current descriptor
  831. ;       mov     edi, [ebx + device.tx_p_des]
  832. ;       mov     eax, [ebx + device.tx_wr_des]
  833. ;       mov     edx, DES.size
  834. ;       mul     edx
  835. ;       add     edi, eax
  836.  
  837.   .first:
  838.  
  839.         push    edi
  840. ; copy setup packet to current descriptor
  841.         mov     edi, [edi + DES.virtaddr]
  842. ; copy the address once
  843.         lea     esi, [ebx + device.mac]
  844.         DEBUGF  1,"copying packet to %x from %x\n", edi, esi
  845.         mov     ecx, 3  ; mac is 6 bytes thus 3 words
  846.   .loop:
  847.         DEBUGF  1,"%x ", [esi]:4
  848.         movsw
  849.         inc     edi
  850.         inc     edi
  851.         dec     ecx
  852.         jnz     .loop
  853.  
  854.         DEBUGF  1,"\n"
  855.  
  856. ; copy 15 times the broadcast address
  857.         mov     ecx, 3*15
  858.         mov     eax, 0xffffffff
  859.         rep     stosd
  860.  
  861.         pop     edi
  862.  
  863. ; setup descriptor
  864.         DEBUGF  1,"setting up descriptor\n"
  865.         mov     [edi + DES.length], TDES1_IC + TDES1_SET + TDES1_TCH + 192        ; size must be EXACTLY 192 bytes
  866.         mov     [edi + DES.status], DES0_OWN
  867.  
  868.         DEBUGF  1,"status: %x\n", [edi + DES.status]:8
  869.         DEBUGF  1,"length: %x\n", [edi + DES.length]:8
  870.         DEBUGF  1,"buffer1: %x\n", [edi + DES.buffer1]:8
  871.         DEBUGF  1,"buffer2: %x\n", [edi + DES.buffer2]:8
  872.  
  873. ; go to next descriptor
  874.         inc     [ebx + device.tx_wr_des]
  875.         and     [ebx + device.tx_wr_des], TX_DES_COUNT-1
  876.  
  877. ; dec free descriptors count
  878.         cmp     [ebx + device.tx_free_des], 0
  879.         jz      @f
  880.         dec     [ebx + device.tx_free_des]
  881.        @@:
  882.  
  883. ; start tx
  884.         set_io  [ebx + device.io_addr], 0
  885.         status
  886.         set_io  [ebx + device.io_addr], CSR6
  887.         in      eax, dx
  888.         test    eax, CSR6_ST            ; if NOT started, start now
  889.         jnz     .already_started
  890.         or      eax, CSR6_ST
  891.         DEBUGF  1,"Starting TX\n"
  892.         jmp     .do_it
  893.   .already_started:
  894.                                         ; if already started, issue a Transmit Poll command
  895.         set_io  [ebx + device.io_addr], CSR1
  896.         xor     eax, eax
  897.         DEBUGF  1,"Issuing transmit poll command\n"
  898.   .do_it:
  899.         out     dx, eax
  900.         status
  901.  
  902.         DEBUGF  1,"Sending setup packet, completed!\n"
  903.  
  904.         ret
  905.  
  906.  
  907.  
  908. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  909. ;;                                         ;;
  910. ;; Transmit                                ;;
  911. ;;                                         ;;
  912. ;; In: buffer pointer in [esp+4]           ;;
  913. ;;     size of buffer in [esp+8]           ;;
  914. ;;     pointer to device structure in ebx  ;;
  915. ;;                                         ;;
  916. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  917.  
  918. proc transmit stdcall bufferptr, buffersize
  919.  
  920.         pushf
  921.         cli
  922.  
  923.         DEBUGF  1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [buffersize]
  924.         mov     eax, [bufferptr]
  925.         DEBUGF  1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
  926.         [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
  927.         [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
  928.         [eax+13]:2,[eax+12]:2
  929.  
  930.         cmp     [buffersize], 1514
  931.         ja      .fail
  932.         cmp     [buffersize], 60
  933.         jb      .fail
  934.  
  935. ;--------------------------
  936. ; copy packet to crt buffer
  937.        
  938.         mov     eax, [ebx + device.tx_wr_des]
  939.         mov     edx, sizeof.DES
  940.         mul     edx
  941.         add     eax, [ebx + device.tx_p_des]
  942.         mov     edi, [eax + DES.virtaddr]               ; pointer to buffer
  943.         mov     esi, [bufferptr]
  944.         mov     ecx, [buffersize]
  945.         DEBUGF  1,"copying %u bytes from %x to %x\n", ecx, esi, edi
  946.         rep     movsb
  947.  
  948. ; set packet size
  949.         mov     ecx, [eax+DES.length]
  950.         and     ecx, TDES1_TER                          ; preserve 'End of Ring' bit
  951.         or      ecx, [buffersize]                       ; set size
  952.         or      ecx, TDES1_FS or TDES1_LS or TDES1_IC or TDES1_TCH    ; first descr, last descr, interrupt on complete, chained modus
  953.         mov     [eax + DES.length], ecx
  954.  
  955. ; set descriptor info
  956.         mov     [eax + DES.status], DES0_OWN            ; say it is now owned by the 21x4x
  957.  
  958. ; start tx
  959.         set_io  [ebx + device.io_addr], 0
  960.         status
  961.         set_io  [ebx + device.io_addr], CSR6
  962.         in      eax, dx
  963.         test    eax, CSR6_ST            ; if NOT started, start now
  964.         jnz     .already_started
  965.         or      eax, CSR6_ST
  966.         DEBUGF  1,"Starting TX\n"
  967.         jmp     .do_it
  968.   .already_started:
  969.                                         ; if already started, issues a Transmit Poll command
  970.         set_io  [ebx + device.io_addr], CSR1
  971.         mov     eax, -1
  972.   .do_it:
  973.         out     dx , eax
  974.  
  975. ; Update stats
  976.         inc     [ebx + device.packets_tx]
  977.         mov     eax, [buffersize]
  978.         add     dword [ebx + device.bytes_tx], eax
  979.         adc     dword [ebx + device.bytes_tx + 4], 0
  980.  
  981. ; go to next descriptor
  982.         inc     [ebx + device.tx_wr_des]
  983.         and     [ebx + device.tx_wr_des], TX_DES_COUNT-1
  984.  
  985. ; dec free descriptors count
  986.         test    [ebx + device.tx_free_des], -1
  987.         jz      .end
  988.         dec     [ebx + device.tx_free_des]
  989.   .end:
  990.         status
  991.  
  992.         DEBUGF  1,"transmit ok\n"
  993.         invoke  KernelFree, [bufferptr]
  994.         popf
  995.         xor     eax, eax
  996.         ret
  997.  
  998.   .fail:
  999.         DEBUGF  1,"transmit failed\n"
  1000.         invoke  KernelFree, [bufferptr]
  1001.         popf
  1002.         or      eax, -1
  1003.         ret
  1004.  
  1005. endp
  1006.  
  1007. ;;;;;;;;;;;;;;;;;;;;;;;
  1008. ;;                   ;;
  1009. ;; Interrupt handler ;;
  1010. ;;                   ;;
  1011. ;;;;;;;;;;;;;;;;;;;;;;;
  1012.  
  1013. align 4
  1014. int_handler:
  1015.  
  1016.         push    ebx esi edi
  1017.  
  1018.         DEBUGF  1,"\n%s int\n", my_service
  1019.  
  1020. ; find pointer of device wich made IRQ occur
  1021.  
  1022.         mov     ecx, [devices]
  1023.         test    ecx, ecx
  1024.         jz      .nothing
  1025.         mov     esi, device_list
  1026.   .nextdevice:
  1027.         mov     ebx, [esi]
  1028.  
  1029.         set_io  [ebx + device.io_addr], 0
  1030.         set_io  [ebx + device.io_addr], CSR5
  1031.         in      ax, dx
  1032.         test    ax, ax
  1033.         out     dx, ax                                  ; send it back to ACK
  1034.         jnz     .got_it
  1035.   .continue:
  1036.         add     esi, 4
  1037.         dec     ecx
  1038.         jnz     .nextdevice
  1039.   .nothing:
  1040.         pop     edi esi ebx
  1041.         xor     eax, eax
  1042.  
  1043.         ret                                             ; If no device was found, abort (The irq was probably for a device, not registered to this driver)
  1044.  
  1045.   .got_it:
  1046.  
  1047.         DEBUGF  1,"Device: %x CSR5: %x ", ebx, ax
  1048.  
  1049. ;----------------------------------
  1050. ; TX ok?
  1051.  
  1052.         test    ax, CSR5_TI
  1053.         jz      .not_tx
  1054.         push    ax esi ecx
  1055.  
  1056.         DEBUGF 1,"TX ok!\n"
  1057.                
  1058.         ; go to current descriptor
  1059.         mov     edi, [ebx + device.tx_p_des]
  1060.  
  1061.         mov     eax, [ebx + device.tx_rd_des]
  1062.         mov     edx, sizeof.DES
  1063.         mul     edx
  1064.         add     edi, eax
  1065.                
  1066.       .loop_tx:
  1067.                
  1068.         ; done if all desc are free
  1069.         cmp     [ebx + device.tx_free_des], TX_DES_COUNT
  1070.         jz      .end_tx
  1071.  
  1072.         mov     eax, [edi + DES.status]
  1073.  
  1074.         ; we stop at first desc that is owned be NIC
  1075.         test    eax, DES0_OWN
  1076.         jnz     .end_tx
  1077.  
  1078.         ; detect is setup packet
  1079.         cmp     eax, (0ffffffffh - DES0_OWN)            ; all other bits are 1
  1080.         jne     .not_setup_packet
  1081.         DEBUGF  1,"Setup Packet detected\n"
  1082.       .not_setup_packet:
  1083.  
  1084.         DEBUGF  1,"packet status: %x\n", eax
  1085.  
  1086.         ; next descriptor
  1087.         add     edi, sizeof.DES
  1088.         inc     [ebx + device.tx_rd_des]
  1089.         and     [ebx + device.tx_rd_des], TX_DES_COUNT-1
  1090.  
  1091.         ; inc free desc
  1092.         inc     [ebx + device.tx_free_des]
  1093.         cmp     [ebx + device.tx_free_des], TX_DES_COUNT
  1094.         jbe     @f
  1095.         mov     [ebx + device.tx_free_des], TX_DES_COUNT
  1096.        @@:
  1097.  
  1098.         jmp     .loop_tx
  1099.       .end_tx:
  1100.                
  1101.         ;------------------------------------------------------
  1102.         ; here must be called standard Ethernet Tx Irq Handler
  1103.         ;------------------------------------------------------
  1104.  
  1105.         pop     ecx esi ax
  1106.  
  1107. ;----------------------------------
  1108. ; RX irq
  1109.   .not_tx:
  1110.         test    ax, CSR5_RI
  1111.         jz      .not_rx
  1112.         push    ax esi ecx
  1113.  
  1114.         DEBUGF 1,"RX ok!\n"
  1115.  
  1116.         push    ebx
  1117.   .rx_loop:
  1118.         pop     ebx
  1119.  
  1120.         ; get current descriptor
  1121.         mov     edi, [ebx + device.rx_p_des]
  1122.         mov     eax, [ebx + device.rx_crt_des]
  1123.         mov     edx, sizeof.DES
  1124.         mul     edx
  1125.         add     edi, eax
  1126.  
  1127.         ; now check status
  1128.         mov     eax, [edi + DES.status]
  1129.  
  1130.         test    eax, DES0_OWN
  1131.         jnz     .end_rx                                 ; current desc is busy, nothing to do
  1132.  
  1133.         test    eax, RDES0_FS
  1134.         jz      .end_rx                                 ; current desc is NOT first packet, ERROR!
  1135.  
  1136.         test    eax, RDES0_LS                           ; if not last desc of packet, error for now
  1137.         jz      .end_rx
  1138.  
  1139.         test    eax, RDES0_ES
  1140.         jnz     .end_rx
  1141.  
  1142.         mov     esi, [edi + DES.virtaddr]
  1143.         mov     ecx, [edi + DES.status]
  1144.         shr     ecx, RDES0_FL_SH
  1145.         and     ecx, RDES0_FL_MASK
  1146.         sub     ecx, 4                                  ; crc, we dont need it
  1147.  
  1148.         DEBUGF  1,"Received packet!, size=%u, addr:%x\n", ecx, esi
  1149.  
  1150.         push    esi edi ecx
  1151.         invoke  KernelAlloc, ecx                        ; Allocate a buffer to put packet into
  1152.         pop     ecx edi esi
  1153.         test    eax, eax
  1154.         jz      .fail
  1155.  
  1156.         push    ebx
  1157.         push    dword .rx_loop
  1158.         push    ecx eax
  1159.         mov     edi, eax
  1160.  
  1161. ; update statistics
  1162.         inc     [ebx + device.packets_rx]
  1163.         add     dword [ebx + device.bytes_rx], ecx
  1164.         adc     dword [ebx + device.bytes_rx + 4], 0
  1165.  
  1166. ; copy packet data
  1167.         shr     cx , 1
  1168.         jnc     .nb
  1169.         movsb
  1170.   .nb:
  1171.         shr     cx , 1
  1172.         jnc     .nw
  1173.         movsw
  1174.   .nw:
  1175.         rep     movsd
  1176.  
  1177.         mov     [edi + DES.status], DES0_OWN            ; free descriptor
  1178.                
  1179.         inc     [ebx + device.rx_crt_des]                     ; next descriptor
  1180.         and     [ebx + device.rx_crt_des], RX_DES_COUNT-1
  1181.  
  1182.         jmp     [Eth_input]
  1183.  
  1184.   .end_rx:
  1185.   .fail:
  1186.         pop     ecx esi ax
  1187.   .not_rx:
  1188.  
  1189.         pop     edi esi ebx
  1190.         ret
  1191.  
  1192.  
  1193.  
  1194. align 4
  1195. write_mac:      ; in: mac pushed onto stack (as 3 words)
  1196.  
  1197.         DEBUGF  2,"Writing MAC: "
  1198.  
  1199. ; write data into driver cache
  1200.         mov     esi, esp
  1201.         lea     edi, [ebx + device.mac]
  1202.         movsd
  1203.         movsw
  1204.         add     esp, 6
  1205.        
  1206. ; send setup packet (only if driver is started)
  1207.         call    Send_Setup_Packet
  1208.  
  1209. align 4
  1210. read_mac:
  1211.  
  1212.         DEBUGF 1,"Read_mac\n"
  1213.  
  1214.         ret
  1215.  
  1216.  
  1217.  
  1218. align 4
  1219. read_mac_eeprom:
  1220.  
  1221.         DEBUGF 1,"Read_mac_eeprom\n"
  1222.  
  1223.         lea     edi, [ebx + device.mac]
  1224.         mov     esi, 20/2               ; read words, start address is 20
  1225.      .loop:
  1226.         push    esi edi
  1227.         call    SROM_Read_Word
  1228.         pop     edi esi
  1229.         stosw
  1230.         inc     esi
  1231.         cmp     esi, 26/2
  1232.         jb      .loop
  1233.  
  1234.         DEBUGF  2,"%x-%x-%x-%x-%x-%x\n",[edi-6]:2,[edi-5]:2,[edi-4]:2,[edi-3]:2,[edi-2]:2,[edi-1]:2
  1235.  
  1236.         ret
  1237.  
  1238. align 4
  1239. write_mac_eeprom:
  1240.  
  1241.         DEBUGF 1,"Write_mac_eeprom\n"
  1242.  
  1243.         ret
  1244.  
  1245.  
  1246. align 4
  1247. SROM_GetWidth:  ; should be 6 or 8 according to some manuals (returns in ecx)
  1248.  
  1249.         DEBUGF 1,"SROM_GetWidth\n"
  1250.  
  1251.         call    SROM_Idle
  1252.         call    SROM_EnterAccessMode
  1253.  
  1254. ;        set_io  [ebx + device.io_addr], 0
  1255. ;        set_io  [ebx + device.io_addr], CSR9
  1256.  
  1257.         ; send 110b
  1258.  
  1259.         in      eax, dx
  1260.         or      eax, CSR9_SROM_DI
  1261.         call    SROM_out
  1262.  
  1263.         in      eax, dx
  1264.         or      eax, CSR9_SROM_DI
  1265.         call    SROM_out
  1266.  
  1267.         in      eax, dx
  1268.         and     eax, not (CSR9_SROM_DI)
  1269.         call    SROM_out
  1270.        
  1271.         mov     ecx,1
  1272.   .loop2:
  1273.         Bit_Set CSR9_SROM_CK
  1274.         SROM_Delay
  1275.        
  1276.         in      eax, dx
  1277.         and     eax, CSR9_SROM_DO
  1278.         jnz     .not_zero
  1279.  
  1280.         Bit_Clear CSR9_SROM_CK
  1281.         SROM_Delay
  1282.         jmp     .end_loop2
  1283.   .not_zero:
  1284.        
  1285.         Bit_Clear CSR9_SROM_CK
  1286.         SROM_Delay
  1287.        
  1288.         inc     ecx
  1289.         cmp     ecx, 12
  1290.         jbe     .loop2
  1291.   .end_loop2:
  1292.        
  1293.         DEBUGF 1,"Srom width=%u\n", ecx
  1294.        
  1295.         call    SROM_Idle
  1296.         call    SROM_EnterAccessMode
  1297.         call    SROM_Idle
  1298.        
  1299.         ret
  1300.  
  1301.  
  1302. align 4
  1303. SROM_out:
  1304.  
  1305.         out     dx, eax
  1306.         SROM_Delay
  1307.         Bit_Set CSR9_SROM_CK
  1308.         SROM_Delay
  1309.         Bit_Clear CSR9_SROM_CK
  1310.         SROM_Delay
  1311.  
  1312.         ret
  1313.  
  1314.  
  1315.  
  1316. align 4
  1317. SROM_EnterAccessMode:
  1318.  
  1319.         DEBUGF 1,"SROM_EnterAccessMode\n"
  1320.  
  1321.         set_io  [ebx + device.io_addr], 0
  1322.         set_io  [ebx + device.io_addr], CSR9
  1323.         mov     eax, CSR9_SR
  1324.         out     dx, eax
  1325.         SROM_Delay
  1326.  
  1327.         Bit_Set CSR9_RD
  1328.         SROM_Delay
  1329.  
  1330.         Bit_Clear CSR9_SROM_CK
  1331.         SROM_Delay
  1332.  
  1333.         Bit_Set CSR9_SROM_CS
  1334.         SROM_Delay
  1335.        
  1336.         ret
  1337.  
  1338.  
  1339.  
  1340. align 4
  1341. SROM_Idle:
  1342.  
  1343.         DEBUGF 1,"SROM_Idle\n"
  1344.  
  1345.         call    SROM_EnterAccessMode
  1346.        
  1347. ;        set_io  [ebx + device.io_addr], 0
  1348. ;        set_io  [ebx + device.io_addr], CSR9
  1349.        
  1350.         mov     ecx, 25
  1351.      .loop_clk:
  1352.  
  1353.         Bit_Clear CSR9_SROM_CK
  1354.         SROM_Delay
  1355.         Bit_Set CSR9_SROM_CK
  1356.         SROM_Delay
  1357.        
  1358.         dec     ecx
  1359.         jnz     .loop_clk
  1360.  
  1361.        
  1362.         Bit_Clear CSR9_SROM_CK
  1363.         SROM_Delay
  1364.         Bit_Clear CSR9_SROM_CS
  1365.         SROM_Delay
  1366.        
  1367.         xor     eax, eax
  1368.         out     dx, eax
  1369.        
  1370.         ret
  1371.  
  1372.  
  1373. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1374. ;;                                                                      ;;
  1375. ;; Read serial EEprom word                                              ;;
  1376. ;;                                                                      ;;
  1377. ;; In: esi = read address                                               ;;
  1378. ;; OUT: ax = data word                                                  ;;
  1379. ;;                                                                      ;;
  1380. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1381. align 4
  1382. SROM_Read_Word:
  1383.  
  1384.         DEBUGF 1,"SROM_Read_word at: %x result: ", esi
  1385.  
  1386.         set_io  [ebx + device.io_addr], 0
  1387.         set_io  [ebx + device.io_addr], CSR9
  1388.  
  1389. ; enter access mode
  1390.         mov     eax, CSR9_SR + CSR9_RD
  1391.         out     dx , eax
  1392.         or      eax, CSR9_SROM_CS
  1393.         out     dx , eax
  1394.  
  1395.         ; TODO: change this hard-coded 6-bit stuff to use value from srom_getwidth
  1396.        
  1397. ; send read command "110b" + address to read from
  1398.         and     esi, 111111b
  1399.         or      esi, 110b shl 6
  1400.        
  1401.         mov     ecx, 1 shl 9
  1402.   .loop_cmd:
  1403.         mov     eax, CSR9_SR + CSR9_RD + CSR9_SROM_CS
  1404.         test    esi, ecx
  1405.         jz      @f
  1406.         or      eax, CSR9_SROM_DI
  1407.        @@:
  1408.         out     dx , eax
  1409.         SROM_Delay
  1410.         or      eax, CSR9_SROM_CK
  1411.         out     dx , eax
  1412.         SROM_Delay
  1413.        
  1414.         shr     ecx, 1
  1415.         jnz     .loop_cmd
  1416.  
  1417. ; read data from SROM
  1418.  
  1419.         xor     esi, esi
  1420.         mov     ecx, 17 ;;; TODO: figure out why 17, not 16
  1421.   .loop_read:
  1422.        
  1423.         mov     eax, CSR9_SR + CSR9_RD + CSR9_SROM_CS + CSR9_SROM_CK
  1424.         out     dx , eax
  1425.         SROM_Delay
  1426.        
  1427.         in      eax, dx
  1428.         and     eax, CSR9_SROM_DO
  1429.         shr     eax, 3
  1430.         shl     esi, 1
  1431.         or      esi, eax
  1432.        
  1433.         mov     eax, CSR9_SR + CSR9_RD + CSR9_SROM_CS
  1434.         out     dx , eax
  1435.         SROM_Delay
  1436.        
  1437.         dec     ecx
  1438.         jnz     .loop_read
  1439.        
  1440.         mov     eax, esi
  1441.  
  1442.         DEBUGF 1,"%x\n", ax
  1443.  
  1444.         ret
  1445.  
  1446.  
  1447.  
  1448.  
  1449.  
  1450.  
  1451.  
  1452. ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  1453.  
  1454.  
  1455.  
  1456. ;*********************************************************************
  1457. ;* Media Descriptor Code                                             *
  1458. ;*********************************************************************
  1459.  
  1460. ; MII transceiver control section.
  1461. ; Read and write the MII registers using software-generated serial
  1462. ; MDIO protocol.  See the MII specifications or DP83840A data sheet
  1463. ; for details.
  1464.  
  1465. ; The maximum data clock rate is 2.5 Mhz.  The minimum timing is usually
  1466. ; met by back-to-back PCI I/O cycles, but we insert a delay to avoid
  1467. ; "overclocking" issues or future 66Mhz PCI.
  1468.  
  1469. ; Read and write the MII registers using software-generated serial
  1470. ; MDIO protocol.  It is just different enough from the EEPROM protocol
  1471. ; to not share code.  The maxium data clock rate is 2.5 Mhz.
  1472.  
  1473. MDIO_SHIFT_CLK          =        0x10000
  1474. MDIO_DATA_WRITE0        =        0x00000
  1475. MDIO_DATA_WRITE1        =        0x20000
  1476. MDIO_ENB                =        0x00000         ; Ignore the 0x02000 databook setting.
  1477. MDIO_ENB_IN             =        0x40000
  1478. MDIO_DATA_READ          =        0x80000
  1479.  
  1480. ; MII transceiver control section.
  1481. ; Read and write the MII registers using software-generated serial
  1482. ; MDIO protocol.  See the MII specifications or DP83840A data sheet
  1483. ; for details.
  1484.  
  1485. align 4
  1486. mdio_read:      ; phy_id:edx, location:esi
  1487.  
  1488.         DEBUGF  1,"mdio read, phy=%x, location=%x", edx, esi
  1489.  
  1490.         shl     edx, 5
  1491.         or      esi, edx
  1492.         or      esi, 0xf6 shl 10
  1493.  
  1494.         set_io  [ebx + device.io_addr], 0
  1495.         set_io  [ebx + device.io_addr], CSR9
  1496.  
  1497. ;    if (tp->chip_id == LC82C168) {
  1498. ;        int i = 1000;
  1499. ;        outl(0x60020000 + (phy_id<<23) + (location<<18), ioaddr + 0xA0);
  1500. ;        inl(ioaddr + 0xA0);
  1501. ;        inl(ioaddr + 0xA0);
  1502. ;        while (--i > 0)
  1503. ;            if ( ! ((retval = inl(ioaddr + 0xA0)) & 0x80000000))
  1504. ;                return retval & 0xffff;
  1505. ;        return 0xffff;
  1506. ;    }
  1507. ;
  1508. ;    if (tp->chip_id == COMET) {
  1509. ;        if (phy_id == 1) {
  1510. ;            if (location < 7)
  1511. ;                return inl(ioaddr + 0xB4 + (location<<2));
  1512. ;            else if (location == 17)
  1513. ;                return inl(ioaddr + 0xD0);
  1514. ;            else if (location >= 29 && location <= 31)
  1515. ;                return inl(ioaddr + 0xD4 + ((location-29)<<2));
  1516. ;        }
  1517. ;        return 0xffff;
  1518. ;    }
  1519.  
  1520. ; Establish sync by sending at least 32 logic ones.
  1521.  
  1522.         mov     ecx, 32
  1523.   .loop:
  1524.         mov     eax, MDIO_ENB or MDIO_DATA_WRITE1
  1525.         out     dx, eax
  1526.         MDIO_Delay
  1527.  
  1528.         or      eax, MDIO_SHIFT_CLK
  1529.         out     dx, eax
  1530.         MDIO_Delay
  1531.  
  1532.         dec     ecx
  1533.         jnz     .loop
  1534.  
  1535.  
  1536. ; Shift the read command bits out.
  1537.  
  1538.         mov     ecx, 1 shl 15
  1539.   .loop2:
  1540.         mov     eax, MDIO_ENB
  1541.         test    esi, ecx
  1542.         jz      @f
  1543.         or      eax, MDIO_DATA_WRITE1
  1544.        @@:
  1545.         out     dx, eax
  1546.         MDIO_Delay
  1547.  
  1548.         or      eax, MDIO_SHIFT_CLK
  1549.         out     dx, eax
  1550.         MDIO_Delay
  1551.  
  1552.         shr     ecx, 1
  1553.         jnz     .loop2
  1554.  
  1555.  
  1556. ; Read the two transition, 16 data, and wire-idle bits.
  1557.  
  1558.         xor     esi, esi
  1559.         mov     ecx, 19
  1560.   .loop3:
  1561.         mov     eax, MDIO_ENB_IN
  1562.         out     dx, eax
  1563.         MDIO_Delay
  1564.  
  1565.         shl     esi, 1
  1566.         in      eax, dx
  1567.         test    eax, MDIO_DATA_READ
  1568.         jz      @f
  1569.         inc     esi
  1570.        @@:
  1571.  
  1572.         mov     eax, MDIO_ENB_IN or MDIO_SHIFT_CLK
  1573.         out     dx, eax
  1574.         MDIO_Delay
  1575.  
  1576.         dec     ecx
  1577.         jnz     .loop3
  1578.  
  1579.         shr     esi, 1
  1580.         movzx   eax, si
  1581.  
  1582.         DEBUGF  1,", data=%x\n", ax
  1583.  
  1584.         ret
  1585.  
  1586.  
  1587.  
  1588.  
  1589. align 4
  1590. mdio_write:     ;int phy_id: edx, int location: edi, int value: ax)
  1591.  
  1592.         DEBUGF  1,"mdio write, phy=%x, location=%x, data=%x\n", edx, edi, ax
  1593.  
  1594.         shl     edi, 18
  1595.         or      edi, 0x5002 shl 16
  1596.         shl     edx, 23
  1597.         or      edi, edx
  1598.         mov     di, ax
  1599.  
  1600.         set_io  [ebx + device.io_addr], 0
  1601.         set_io  [ebx + device.io_addr], CSR9
  1602.  
  1603. ;    if (tp->chip_id == LC82C168) {
  1604. ;        int i = 1000;
  1605. ;        outl(cmd, ioaddr + 0xA0);
  1606. ;        do
  1607. ;            if ( ! (inl(ioaddr + 0xA0) & 0x80000000))
  1608. ;                break;
  1609. ;        while (--i > 0);
  1610. ;        return;
  1611. ;    }
  1612.  
  1613. ;    if (tp->chip_id == COMET) {
  1614. ;        if (phy_id != 1)
  1615. ;            return;
  1616. ;        if (location < 7)
  1617. ;            outl(value, ioaddr + 0xB4 + (location<<2));
  1618. ;        else if (location == 17)
  1619. ;            outl(value, ioaddr + 0xD0);
  1620. ;        else if (location >= 29 && location <= 31)
  1621. ;            outl(value, ioaddr + 0xD4 + ((location-29)<<2));
  1622. ;        return;
  1623. ;    }
  1624.  
  1625.  
  1626. ; Establish sync by sending at least 32 logic ones.
  1627.  
  1628.         mov     ecx, 32
  1629.   .loop:
  1630.         mov     eax, MDIO_ENB or MDIO_DATA_WRITE1
  1631.         out     dx, eax
  1632.         MDIO_Delay
  1633.  
  1634.         or      eax, MDIO_SHIFT_CLK
  1635.         out     dx, eax
  1636.         MDIO_Delay
  1637.  
  1638.         dec     ecx
  1639.         jnz     .loop
  1640.  
  1641.  
  1642. ; Shift the command bits out.
  1643.  
  1644.         mov     ecx, 1 shl 31
  1645.   .loop2:
  1646.         mov     eax, MDIO_ENB
  1647.         test    edi, ecx
  1648.         jz      @f
  1649.         or      eax, MDIO_DATA_WRITE1
  1650.        @@:
  1651.         out     dx, eax
  1652.         MDIO_Delay
  1653.  
  1654.         or      eax, MDIO_SHIFT_CLK
  1655.         out     dx, eax
  1656.         MDIO_Delay
  1657.  
  1658.         shr     ecx, 1
  1659.         jnz     .loop2
  1660.  
  1661.  
  1662. ; Clear out extra bits.
  1663.  
  1664.         mov     ecx, 2
  1665.   .loop3:
  1666.         mov     eax, MDIO_ENB
  1667.         out     dx, eax
  1668.         MDIO_Delay
  1669.  
  1670.         or      eax, MDIO_SHIFT_CLK
  1671.         out     dx, eax
  1672.         MDIO_Delay
  1673.  
  1674.         dec     ecx
  1675.         jnz     .loop3
  1676.  
  1677.         ret
  1678.  
  1679.  
  1680. ; End of code
  1681.  
  1682. data fixups
  1683. end data
  1684.  
  1685. include '../peimport.inc'
  1686.  
  1687. my_service    db 'DEC21X4X',0                    ; max 16 chars include zero
  1688.  
  1689. include_debug_strings                           ; All data wich FDO uses will be included here
  1690.  
  1691. align 4
  1692. devices         dd 0
  1693. device_list     rd MAX_DEVICES                  ; This list contains all pointers to device structures the driver is handling
  1694.  
  1695.