Subversion Repositories Kolibri OS

Rev

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

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