Subversion Repositories Kolibri OS

Rev

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

  1. $Revision: 431 $
  2. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3. ;;                                                                  ;;
  4. ;; Copyright (C) KolibriOS team 2004-2007. All rights reserved.     ;;
  5. ;; Distributed under terms of the GNU General Public License        ;;
  6. ;;                                                                  ;;
  7. ;;  PCNET32.INC                                                     ;;
  8. ;;                                                                  ;;
  9. ;;  Ethernet driver for Menuet OS                                   ;;
  10. ;;                                                                  ;;
  11. ;;  Version 1.0  31 July 2004                                       ;;
  12. ;;                                                                  ;;
  13. ;;  This driver is based on the PCNet32 driver from                 ;;
  14. ;;  the etherboot 5.0.6 project. The copyright statement is         ;;
  15. ;;                                                                  ;;
  16. ;;          GNU GENERAL PUBLIC LICENSE                              ;;
  17. ;;             Version 2, June 1991                                 ;;
  18. ;;                                                                  ;;
  19. ;;  remaining parts Copyright 2004 Jarek Pelczar,                   ;;
  20. ;;   jpelczar@interia.pl                                            ;;
  21. ;;                                                                  ;;
  22. ;;  See file COPYING for details                                    ;;
  23. ;;                                                                  ;;
  24. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  25. ;macro PutStr X
  26. ;{
  27. ; local .__xyz1
  28. ; local .__xyz2
  29. ; push esi
  30. ; mov esi,.__xyz1
  31. ; call sys_msg_board_str
  32. ; push eax
  33. ; mov eax,1
  34. ; call delay_hs
  35. ; pop eax
  36. ; jmp .__xyz2
  37. ;.__xyz1:
  38. ; db X
  39. ; db 13,10,0
  40. ;.__xyz2:
  41. ; pop esi
  42. ;}
  43. PCNET32_PORT_AUI      equ 0x00
  44. PCNET32_PORT_10BT     equ 0x01
  45. PCNET32_PORT_GPSI     equ 0x02
  46. PCNET32_PORT_MII      equ 0x03
  47. PCNET32_PORT_PORTSEL  equ 0x03
  48. PCNET32_PORT_ASEL     equ 0x04
  49. PCNET32_PORT_100      equ 0x40
  50. PCNET32_PORT_FD       equ 0x80
  51. PCNET32_DMA_MASK      equ 0xffffffff
  52. PCNET32_LOG_TX_BUFFERS  equ 1
  53. PCNET32_LOG_RX_BUFFERS  equ 2
  54. PCNET32_TX_RING_SIZE            equ (1 shl PCNET32_LOG_TX_BUFFERS)
  55. PCNET32_TX_RING_MOD_MASK        equ (PCNET32_TX_RING_SIZE-1)
  56. PCNET32_TX_RING_LEN_BITS        equ 0
  57. PCNET32_RX_RING_SIZE            equ (1 shl PCNET32_LOG_RX_BUFFERS)
  58. PCNET32_RX_RING_MOD_MASK        equ (PCNET32_RX_RING_SIZE-1)
  59. PCNET32_RX_RING_LEN_BITS        equ (PCNET32_LOG_RX_BUFFERS shl 4)
  60. PCNET32_PKT_BUF_SZ              equ 1544
  61. PCNET32_PKT_BUF_SZ_NEG          equ 0xf9f8
  62. pcnet32_txb equ (eth_data_start)
  63. pcnet32_rxb equ ((pcnet32_txb+(PCNET32_PKT_BUF_SZ*PCNET32_TX_RING_SIZE)+0xf) and 0xfffffff0)
  64. pcnet32_tx_ring equ ((pcnet32_rxb+(PCNET32_PKT_BUF_SZ*PCNET32_RX_RING_SIZE)+0xf) and 0xfffffff0)
  65. pcnet32_rx_ring equ ((pcnet32_tx_ring+(16*PCNET32_TX_RING_SIZE)+0xf) and 0xfffffff0)
  66. virtual at ((pcnet32_rx_ring+(16*PCNET32_RX_RING_SIZE)+0xf) and 0xfffffff0)
  67. pcnet32_private:
  68. .mode                   dw ?
  69. .tlen_rlen              dw ?
  70. .phys_addr              db ?,?,?,?,?,?
  71. .reserved               dw ?
  72. .filter                 dd ?,?
  73. .rx_ring                dd ?
  74. .tx_ring                dd ?
  75. .cur_rx                 dd ?
  76. .cur_tx                 dd ?
  77. .dirty_rx               dd ?
  78. .dirty_tx               dd ?
  79. .tx_full                db ?
  80. .options                dd ?
  81. .full_duplex            db ?
  82. .chip_version           dd ?
  83. .mii                    db ?
  84. .ltint                  db ?
  85. .dxsuflo                db ?
  86. .fset                   db ?
  87. .fdx                    db ?
  88. end virtual
  89. virtual at 0
  90. pcnet32_rx_head:
  91. .base           dd ?
  92. .buf_length     dw ?
  93. .status         dw ?
  94. .msg_length     dd ?
  95. .reserved       dd ?
  96. end virtual
  97. virtual at 0
  98. pcnet32_tx_head:
  99. .base           dd ?
  100. .length         dw ?
  101. .status         dw ?
  102. .misc           dd ?
  103. .reserved       dd ?
  104. end virtual
  105.  
  106. uglobal
  107. pcnet32_access:
  108. .read_csr               dd ?
  109. .write_csr              dd ?
  110. .read_bcr               dd ?
  111. .write_bcr              dd ?
  112. .read_rap               dd ?
  113. .write_rap              dd ?
  114. .reset                  dd ?
  115. endg
  116.  
  117. iglobal
  118. pcnet32_options_mapping:
  119. dd PCNET32_PORT_ASEL    ;  0 Auto-select
  120. dd PCNET32_PORT_AUI     ;  1 BNC/AUI
  121. dd PCNET32_PORT_AUI     ;  2 AUI/BNC
  122. dd PCNET32_PORT_ASEL    ;  3 not supported
  123. dd PCNET32_PORT_10BT or PCNET32_PORT_FD ;  4 10baseT-FD
  124. dd PCNET32_PORT_ASEL    ;  5 not supported
  125. dd PCNET32_PORT_ASEL    ;  6 not supported
  126. dd PCNET32_PORT_ASEL    ;  7 not supported
  127. dd PCNET32_PORT_ASEL    ;  8 not supported
  128. dd PCNET32_PORT_MII     ;  9 MII 10baseT
  129. dd PCNET32_PORT_MII or PCNET32_PORT_FD  ; 10 MII 10baseT-FD
  130. dd PCNET32_PORT_MII     ; 11 MII (autosel)
  131. dd PCNET32_PORT_10BT    ; 12 10BaseT
  132. dd PCNET32_PORT_MII or PCNET32_PORT_100 ; 13 MII 100BaseTx
  133. dd PCNET32_PORT_MII or PCNET32_PORT_100 or PCNET32_PORT_FD      ; 14 MII 100BaseTx-FD
  134. dd PCNET32_PORT_ASEL    ; 15 not supported
  135. endg
  136.  
  137. PCNET32_WIO_RDP         equ 0x10
  138. PCNET32_WIO_RAP         equ 0x12
  139. PCNET32_WIO_RESET       equ 0x14
  140. PCNET32_WIO_BDP         equ 0x16
  141. PCNET32_DWIO_RDP        equ 0x10
  142. PCNET32_DWIO_RAP        equ 0x14
  143. PCNET32_DWIO_RESET      equ 0x18
  144. PCNET32_DWIO_BDP        equ 0x1C
  145. PCNET32_TOTAL_SIZE      equ 0x20
  146. ; ebx - index
  147. ; return:
  148. ; eax - data
  149. pcnet32_wio_read_csr:
  150.     push edx
  151.     lea edx,[ebp+PCNET32_WIO_RAP]
  152.     mov ax,bx
  153.     out dx,ax
  154.     lea edx,[ebp+PCNET32_WIO_RDP]
  155.     in ax,dx
  156.     and eax,0xffff
  157.     pop edx
  158.     ret
  159. ; eax - data
  160. ; ebx - index
  161. pcnet32_wio_write_csr:
  162.     push edx
  163.     lea edx,[ebp+PCNET32_WIO_RAP]
  164.     xchg eax,ebx
  165.     out dx,ax
  166.     xchg eax,ebx
  167.     lea edx,[ebp+PCNET32_WIO_RDP]
  168.     out dx,ax
  169.     pop edx
  170.     ret
  171. ; ebx - index
  172. ; return:
  173. ; eax - data
  174. pcnet32_wio_read_bcr:
  175.     push edx
  176.     lea edx,[ebp+PCNET32_WIO_RAP]
  177.     mov ax,bx
  178.     out dx,ax
  179.     lea edx,[ebp+PCNET32_WIO_BDP]
  180.     in ax,dx
  181.     and eax,0xffff
  182.     pop edx
  183.     ret
  184. ; eax - data
  185. ; ebx - index
  186. pcnet32_wio_write_bcr:
  187.     push edx
  188.     lea edx,[ebp+PCNET32_WIO_RAP]
  189.     xchg eax,ebx
  190.     out dx,ax
  191.     xchg eax,ebx
  192.     lea edx,[ebp+PCNET32_WIO_BDP]
  193.     out dx,ax
  194.     pop edx
  195.     ret
  196. pcnet32_wio_read_rap:
  197.     push edx
  198.     lea edx,[ebp+PCNET32_WIO_RAP]
  199.     in ax,dx
  200.     and eax,0xffff
  201.     pop edx
  202.     ret
  203. ; eax - val
  204. pcnet32_wio_write_rap:
  205.     push edx
  206.     lea edx,[ebp+PCNET32_WIO_RAP]
  207.     out dx,ax
  208.     pop edx
  209.     ret
  210. pcnet32_wio_reset:
  211.     push edx
  212.     push eax
  213.     lea edx,[ebp+PCNET32_WIO_RESET]
  214.     in ax,dx
  215.     pop eax
  216.     pop edx
  217.     ret
  218. pcnet32_wio_check:
  219.     push edx
  220.     mov ax,88
  221.     lea edx,[ebp+PCNET32_WIO_RAP]
  222.     out dx,ax
  223.     nop
  224.     nop
  225.     in ax,dx
  226.     cmp ax,88
  227.     sete al
  228.     pop edx
  229.     ret
  230.  
  231. iglobal
  232. pcnet32_wio:
  233.     dd pcnet32_wio_read_csr
  234.     dd pcnet32_wio_write_csr
  235.     dd pcnet32_wio_read_bcr
  236.     dd pcnet32_wio_write_bcr
  237.     dd pcnet32_wio_read_rap
  238.     dd pcnet32_wio_write_rap
  239.     dd pcnet32_wio_reset
  240. endg
  241.  
  242. ; ebx - index
  243. ; return:
  244. ; eax - data
  245. pcnet32_dwio_read_csr:
  246.     push edx
  247.     lea edx,[ebp+PCNET32_DWIO_RAP]
  248.     mov ebx,eax
  249.     out dx,eax
  250.     lea edx,[ebp+PCNET32_DWIO_RDP]
  251.     in eax,dx
  252.     and eax,0xffff
  253.     pop edx
  254.     ret
  255. ; ebx - index
  256. ; eax - data
  257. pcnet32_dwio_write_csr:
  258.     push edx
  259.     lea edx,[ebp+PCNET32_DWIO_RAP]
  260.     xchg eax,ebx
  261.     out dx,eax
  262.     lea edx,[ebp+PCNET32_DWIO_RDP]
  263.     xchg eax,ebx
  264.     out dx,eax
  265.     pop edx
  266.     ret
  267. ; ebx - index
  268. ; return:
  269. ; eax - data
  270. pcnet32_dwio_read_bcr:
  271.     push edx
  272.     lea edx,[ebp+PCNET32_DWIO_RAP]
  273.     mov ebx,eax
  274.     out dx,eax
  275.     lea edx,[ebp+PCNET32_DWIO_BDP]
  276.     in eax,dx
  277.     and eax,0xffff
  278.     pop edx
  279.     ret
  280. ; ebx - index
  281. ; eax - data
  282. pcnet32_dwio_write_bcr:
  283.     push edx
  284.     lea edx,[ebp+PCNET32_DWIO_RAP]
  285.     xchg eax,ebx
  286.     out dx,eax
  287.     lea edx,[ebp+PCNET32_DWIO_BDP]
  288.     xchg eax,ebx
  289.     out dx,eax
  290.     pop edx
  291.     ret
  292. pcnet32_dwio_read_rap:
  293.     push edx
  294.     lea edx,[ebp+PCNET32_DWIO_RAP]
  295.     in eax,dx
  296.     and eax,0xffff
  297.     pop edx
  298.     ret
  299. ; eax - val
  300. pcnet32_dwio_write_rap:
  301.     push edx
  302.     lea edx,[ebp+PCNET32_DWIO_RAP]
  303.     out dx,eax
  304.     pop edx
  305.     ret
  306. pcnet32_dwio_reset:
  307.     push edx
  308.     push eax
  309.     lea edx,[ebp+PCNET32_DWIO_RESET]
  310.     in eax,dx
  311.     pop eax
  312.     pop edx
  313.     ret
  314. pcnet32_dwio_check:
  315.     push edx
  316.     lea edx,[PCNET32_DWIO_RAP]
  317.     mov eax,88
  318.     out dx,eax
  319.     nop
  320.     nop
  321.     in eax,dx
  322.     and eax,0xffff
  323.     cmp eax,88
  324.     sete al
  325.     pop edx
  326.     ret
  327.  
  328. iglobal
  329. pcnet32_dwio:
  330.     dd pcnet32_dwio_read_csr
  331.     dd pcnet32_dwio_write_csr
  332.     dd pcnet32_dwio_read_bcr
  333.     dd pcnet32_dwio_write_bcr
  334.     dd pcnet32_dwio_read_rap
  335.     dd pcnet32_dwio_write_rap
  336.     dd pcnet32_dwio_reset
  337. endg
  338.  
  339. pcnet32_init_ring:
  340.     mov [pcnet32_private.tx_full],0
  341.     mov [pcnet32_private.cur_rx],0
  342.     mov [pcnet32_private.cur_tx],0
  343.     mov [pcnet32_private.dirty_rx],0
  344.     mov [pcnet32_private.dirty_tx],0
  345.     mov edi,pcnet32_rx_ring
  346.     mov ecx,PCNET32_RX_RING_SIZE
  347.     mov ebx,pcnet32_rxb
  348. .rx_init:
  349.     mov [edi+pcnet32_rx_head.base],ebx
  350.     mov [edi+pcnet32_rx_head.buf_length],word PCNET32_PKT_BUF_SZ_NEG
  351.     mov [edi+pcnet32_rx_head.status],word 0x8000
  352.     add ebx,PCNET32_PKT_BUF_SZ
  353. ;    inc ebx
  354.     add edi,16
  355.     loop .rx_init
  356.     mov edi,pcnet32_tx_ring
  357.     mov ecx,PCNET32_TX_RING_SIZE
  358. .tx_init:
  359.     mov [edi+pcnet32_tx_head.base],dword 0
  360.     mov [edi+pcnet32_tx_head.status],word 0
  361.     add edi,16
  362.     loop .tx_init
  363.     mov [pcnet32_private.tlen_rlen],(PCNET32_TX_RING_LEN_BITS or PCNET32_RX_RING_LEN_BITS)
  364.     mov esi,node_addr
  365.     mov edi,pcnet32_private.phys_addr
  366.     cld
  367.     movsd
  368.     movsw
  369.     mov dword [pcnet32_private.rx_ring],pcnet32_rx_ring
  370.     mov dword [pcnet32_private.tx_ring],pcnet32_tx_ring
  371.     ret
  372. pcnet32_reset:
  373.     ; Reset PCNET32
  374.     mov ebp,[io_addr]
  375.     call dword [pcnet32_access.reset]
  376.     ; set 32bit mode
  377.     mov ebx,20
  378.     mov eax,2
  379.     call dword [pcnet32_access.write_bcr]
  380.     ; set/reset autoselect bit
  381.     mov ebx,2
  382.     call dword [pcnet32_access.read_bcr]
  383.     and eax,not 2
  384.     test [pcnet32_private.options],PCNET32_PORT_ASEL
  385.     jz .L1
  386.     or eax,2
  387. .L1:
  388.     call dword [pcnet32_access.write_bcr]
  389.     ; Handle full duplex setting
  390.     cmp byte [pcnet32_private.full_duplex],0
  391.     je .L2
  392.     mov ebx,9
  393.     call dword [pcnet32_access.read_bcr]
  394.     and eax,not 3
  395.     test [pcnet32_private.options],PCNET32_PORT_FD
  396.     jz .L3
  397.     or eax,1
  398.     cmp [pcnet32_private.options],PCNET32_PORT_FD or PCNET32_PORT_AUI
  399.     jne .L4
  400.     or eax,2
  401.     jmp .L4
  402. .L3:
  403.     test [pcnet32_private.options],PCNET32_PORT_ASEL
  404.     jz .L4
  405.     cmp [pcnet32_private.chip_version],0x2627
  406.     jne .L4
  407.     or eax,3
  408. .L4:
  409.     mov ebx,9
  410.     call dword [pcnet32_access.write_bcr]
  411. .L2:
  412.     ; set/reset GPSI bit
  413.     mov ebx,124
  414.     call dword [pcnet32_access.read_csr]
  415.     mov ecx,[pcnet32_private.options]
  416.     and ecx,PCNET32_PORT_PORTSEL
  417.     cmp ecx,PCNET32_PORT_GPSI
  418.     jne .L5
  419.     or eax,0x10
  420. .L5:
  421.     call dword [pcnet32_access.write_csr]
  422.     cmp [pcnet32_private.mii],0
  423.     je .L6
  424.     test [pcnet32_private.options],PCNET32_PORT_ASEL
  425.     jnz .L6
  426.     mov ebx,32
  427.     call dword [pcnet32_access.read_bcr]
  428.     and eax,not 0x38
  429.     test [pcnet32_private.options],PCNET32_PORT_FD
  430.     jz .L7
  431.     or eax,0x10
  432. .L7:
  433.     test [pcnet32_private.options],PCNET32_PORT_100
  434.     jz .L8
  435.     or eax,0x08
  436. .L8:
  437.     call dword [pcnet32_access.write_bcr]
  438.     jmp .L9
  439. .L6:
  440.     test [pcnet32_private.options],PCNET32_PORT_ASEL
  441.     jz .L9
  442.     mov ebx,32
  443. ;    PutStr "ASEL, enable auto-negotiation"
  444.     call dword [pcnet32_access.read_bcr]
  445.     and eax,not 0x98
  446.     or eax,0x20
  447.     call dword [pcnet32_access.write_bcr]
  448. .L9:
  449.     cmp [pcnet32_private.ltint],0
  450.     je .L10
  451.     mov ebx,5
  452.     call dword [pcnet32_access.read_csr]
  453.     or eax,(1 shl 14)
  454.     call dword [pcnet32_access.write_csr]
  455. .L10:
  456.     mov eax,[pcnet32_private.options]
  457.     and eax,PCNET32_PORT_PORTSEL
  458.     shl eax,7
  459.     mov [pcnet32_private.mode],ax
  460.     mov [pcnet32_private.filter],dword 0xffffffff
  461.     mov [pcnet32_private.filter+4],dword 0xffffffff
  462.     call pcnet32_init_ring
  463.     mov ebx,1
  464.     mov eax,pcnet32_private
  465.     and eax,0xffff
  466.     call dword [pcnet32_access.write_csr]
  467.     mov eax,pcnet32_private
  468.     mov ebx,2
  469.     shr eax,16
  470.     call dword [pcnet32_access.write_csr]
  471.     mov ebx,4
  472.     mov eax,0x0915
  473.     call dword [pcnet32_access.write_csr]
  474.     mov ebx,0
  475.     mov eax,1
  476.     call dword [pcnet32_access.write_csr]
  477.     mov ecx,100
  478. .L11:
  479.     xor ebx,ebx
  480.     call dword [pcnet32_access.read_csr]
  481.     test ax,0x100
  482.     jnz .L12
  483.     loop .L11
  484. .L12:
  485. ;    PutStr "hardware reset"
  486.     xor ebx,ebx
  487.     mov eax,0x0002
  488.     call dword [pcnet32_access.write_csr]
  489.     xor ebx,ebx
  490.     call dword [pcnet32_access.read_csr]
  491. ;    PutStr "PCNET reset complete"
  492.     ret
  493. pcnet32_adjust_pci_device:
  494.    ;*******Get current setting************************
  495.    mov     al, 2                                        ;read a word
  496.    mov     bh, [pci_dev]
  497.    mov     ah, [pci_bus]
  498.    mov     bl, 0x04                                 ;from command Register
  499.    call    pci_read_reg
  500.    ;******see if its already set as bus master********
  501.    mov      bx, ax
  502.    and      bx,5
  503.    cmp      bx,5
  504.    je       pcnet32_adjust_pci_device_Latency
  505.    ;******Make card a bus master*******
  506.    mov      cx, ax                              ;value to write
  507.    mov     bh, [pci_dev]
  508.    mov     al, 2                                ;write a word
  509.    or       cx,5
  510.    mov     ah, [pci_bus]
  511.    mov     bl, 0x04                             ;to command register
  512.    call    pci_write_reg
  513.    ;******Check latency setting***********
  514. pcnet32_adjust_pci_device_Latency:
  515.    ;*******Get current latency setting************************
  516. ;   mov     al, 1                                       ;read a byte
  517. ;   mov     bh, [pci_dev]
  518. ;   mov     ah, [pci_bus]
  519. ;   mov     bl, 0x0D                                ;from Lantency Timer Register
  520. ;   call    pci_read_reg
  521.    ;******see if its aat least 64 clocks********
  522. ;   cmp      ax,64
  523. ;   jge      pcnet32_adjust_pci_device_Done
  524.    ;******Set latency to 32 clocks*******
  525. ;   mov     cx, 64                              ;value to write
  526. ;   mov     bh, [pci_dev]
  527. ;   mov     al, 1                               ;write a byte
  528. ;   mov     ah, [pci_bus]
  529. ;   mov     bl, 0x0D                            ;to Lantency Timer Register
  530. ;   call    pci_write_reg
  531.    ;******Check latency setting***********
  532. pcnet32_adjust_pci_device_Done:
  533.    ret
  534. pcnet32_probe:
  535.     mov ebp,[io_addr]
  536.     call pcnet32_wio_reset
  537.     xor ebx,ebx
  538.     call pcnet32_wio_read_csr
  539.     cmp eax,4
  540.     jne .try_dwio
  541.     call pcnet32_wio_check
  542.     and al,al
  543.     jz .try_dwio
  544. ;    PutStr "Using WIO"
  545.     mov esi,pcnet32_wio
  546.     jmp .L1
  547. .try_dwio:
  548.     call pcnet32_dwio_reset
  549.     xor ebx,ebx
  550.     call pcnet32_dwio_read_csr
  551.     cmp eax,4
  552.     jne .no_dev
  553.     call pcnet32_dwio_check
  554.     and al,al
  555.     jz .no_dev
  556. ;    PutStr "Using DWIO"
  557.     mov esi,pcnet32_dwio
  558.     jmp .L1
  559. .no_dev:
  560. ;    PutStr "PCNET32 not found"
  561.     ret
  562. .L1:
  563.     mov edi,pcnet32_access
  564.     mov ecx,7
  565.     cld
  566.     rep movsd
  567.     mov ebx,88
  568.     call dword [pcnet32_access.read_csr]
  569.     mov ecx,eax
  570.     mov ebx,89
  571.     call dword [pcnet32_access.read_csr]
  572.     shl eax,16
  573.     or eax,ecx
  574.     mov ecx,eax
  575.     and ecx,0xfff
  576.     cmp ecx,3
  577.     jne .no_dev
  578.     shr eax,12
  579.     and eax,0xffff
  580.     mov [pcnet32_private.chip_version],eax
  581. ;    PutStr "PCNET32 chip version OK"
  582.     mov [pcnet32_private.fdx],0
  583.     mov [pcnet32_private.mii],0
  584.     mov [pcnet32_private.fset],0
  585.     mov [pcnet32_private.dxsuflo],0
  586.     mov [pcnet32_private.ltint],0
  587.     mov eax,[pcnet32_private.chip_version]
  588.     cmp eax,0x2420
  589.     je .L2
  590.     cmp eax,0x2430
  591.     je .L3
  592.     cmp eax,0x2621
  593.     je .L4
  594.     cmp eax,0x2623
  595.     je .L5
  596.     cmp eax,0x2624
  597.     je .L6
  598.     cmp eax,0x2625
  599.     je .L7
  600.     cmp eax,0x2626
  601.     je .L8
  602.     cmp eax,0x2627
  603.     je .L9
  604. ;    PutStr "Invalid chip rev"
  605.     jmp .no_dev
  606. .L2:
  607. ;    PutStr "PCnet/PCI 79C970"
  608.     jmp .L10
  609. .L3:
  610. ;    PutStr "PCnet/PCI 79C970"
  611.     jmp .L10
  612. .L4:
  613. ;    PutStr "PCnet/PCI II 79C970A"
  614.     mov [pcnet32_private.fdx],1
  615.     jmp .L10
  616. .L5:
  617. ;    PutStr "PCnet/FAST 79C971"
  618.     mov [pcnet32_private.fdx],1
  619.     mov [pcnet32_private.mii],1
  620.     mov [pcnet32_private.fset],1
  621.     mov [pcnet32_private.ltint],1
  622.     jmp .L10
  623. .L6:
  624. ;    PutStr "PCnet/FAST+ 79C972"
  625.     mov [pcnet32_private.fdx],1
  626.     mov [pcnet32_private.mii],1
  627.     mov [pcnet32_private.fset],1
  628.     jmp .L10
  629. .L7:
  630. ;    PutStr "PCnet/FAST III 79C973"
  631.     mov [pcnet32_private.fdx],1
  632.     mov [pcnet32_private.mii],1
  633.     jmp .L10
  634. .L8:
  635. ;    PutStr "PCnet/Home 79C978"
  636.     mov [pcnet32_private.fdx],1
  637.     mov ebx,49
  638.     call dword [pcnet32_access.read_bcr]
  639.     call dword [pcnet32_access.write_bcr]
  640.     jmp .L10
  641. .L9:
  642. ;    PutStr "PCnet/FAST III 79C975"
  643.     mov [pcnet32_private.fdx],1
  644.     mov [pcnet32_private.mii],1
  645. .L10:
  646.     cmp [pcnet32_private.fset],1
  647.     jne .L11
  648.     mov ebx,18
  649.     call dword [pcnet32_access.read_bcr]
  650.     or eax,0x800
  651.     call dword [pcnet32_access.write_bcr]
  652.     mov ebx,80
  653.     call dword [pcnet32_access.read_csr]
  654.     and eax,0xc00
  655.     or eax,0xc00
  656.     call dword [pcnet32_access.write_csr]
  657.     mov [pcnet32_private.dxsuflo],1
  658.     mov [pcnet32_private.ltint],1
  659. .L11:
  660.     ; read MAC
  661.     mov edi,node_addr
  662.     mov edx,ebp
  663.     mov ecx,6
  664. .Lmac:
  665.     in al,dx
  666.     stosb
  667.     inc edx
  668.     loop .Lmac
  669. ;    PutStr "MAC read"
  670.     call pcnet32_adjust_pci_device
  671. ;    PutStr "PCI done"
  672.     mov eax,PCNET32_PORT_ASEL
  673.     mov [pcnet32_private.options],eax
  674.     mov [pcnet32_private.mode],word 0x0003
  675.     mov [pcnet32_private.tlen_rlen],word (PCNET32_TX_RING_LEN_BITS or PCNET32_RX_RING_LEN_BITS)
  676.     mov esi,node_addr
  677.     mov edi,pcnet32_private.phys_addr
  678.     cld
  679.     movsd
  680.     movsw
  681.     mov [pcnet32_private.filter],dword 0
  682.     mov [pcnet32_private.filter+4],dword 0
  683.     mov dword [pcnet32_private.rx_ring],pcnet32_rx_ring
  684.     mov dword [pcnet32_private.tx_ring],pcnet32_tx_ring
  685. ;    PutStr "Switching to 32"
  686.     mov ebx,20
  687.     mov eax,2
  688.     call dword [pcnet32_access.write_bcr]
  689.     mov ebx,1
  690.     mov eax,(pcnet32_private and 0xffff)
  691.     call dword [pcnet32_access.write_csr]
  692.     mov ebx,2
  693.     mov eax,(pcnet32_private shr 16) and 0xffff
  694.     call dword [pcnet32_access.write_csr]
  695.     mov ebx,0
  696.     mov eax,1
  697.     call dword [pcnet32_access.write_csr]
  698.     mov esi,1
  699.     call delay_ms
  700.     call pcnet32_reset
  701.     mov eax, [pci_data]
  702.     mov [eth_status], eax
  703.     ret
  704. pcnet32_poll:
  705.     xor eax,eax
  706.     mov [eth_rx_data_len],ax
  707.     mov eax,[pcnet32_private.cur_rx]
  708.     and eax,PCNET32_RX_RING_MOD_MASK
  709.     mov ebx,eax
  710.     imul esi,eax,PCNET32_PKT_BUF_SZ
  711.     add esi,pcnet32_rxb
  712.     shl ebx,4
  713.     add ebx,pcnet32_rx_ring
  714.     mov cx,[ebx+pcnet32_rx_head.status]
  715.     test cx,0x8000
  716.     jnz .L1
  717.     cmp ch,3
  718.     jne .L1
  719. ;    PutStr "PCNETRX"
  720.     mov ecx,[ebx+pcnet32_rx_head.msg_length]
  721.     and ecx,0xfff
  722.     sub ecx,4
  723.     mov [eth_rx_data_len],cx
  724.     push ecx
  725.     shr ecx,2
  726.     mov edi,Ether_buffer
  727.     cld
  728.     rep movsd
  729.     pop ecx
  730.     and ecx,3
  731.     rep movsb
  732.     mov [ebx+pcnet32_rx_head.buf_length],word PCNET32_PKT_BUF_SZ_NEG
  733.     or [ebx+pcnet32_rx_head.status],word 0x8000
  734.     inc [pcnet32_private.cur_rx]
  735. .L1:
  736.     ret
  737. ;         Pointer to 48 bit destination address in edi
  738. ;         Type of packet in bx
  739. ;         size of packet in ecx
  740. ;         pointer to packet data in esi
  741. pcnet32_xmit:
  742.     push edi
  743.     push esi
  744.     push ebx
  745.     push ecx
  746. ;    PutStr "PCNETTX"
  747.     mov esi,edi
  748.     mov edi,[pcnet32_private.cur_tx]
  749.     imul edi,PCNET32_PKT_BUF_SZ
  750.     add edi,pcnet32_txb ; edi=ptxb
  751.     mov eax,edi
  752.     cld         ; copy MAC
  753.     movsd
  754.     movsw
  755.     mov esi,node_addr
  756.     cld
  757.     movsd
  758.     movsw
  759.     mov [edi],bx
  760.     add edi,2
  761.     mov esi,[esp+8]
  762.     mov ecx,[esp]
  763.     push ecx
  764.     shr ecx,2
  765.     cld
  766.     rep movsd
  767.     pop ecx
  768.     and ecx,3
  769.     rep movsb
  770. ;    mov ecx,[esp]
  771. ;    add ecx,14 ; ETH_HLEN
  772. ;    xor eax,eax
  773. ; pad to min length (60=ETH_ZLEN)
  774. ;    cmp ecx,60
  775. ;    jae .L1
  776. ;    sub ecx,60
  777. ;    cld
  778. ;    rep stosb
  779. ;.L1:
  780.     mov edi,pcnet32_tx_ring+0   ; entry=0
  781.     mov ecx,[esp]
  782.     add ecx,14
  783.     cmp cx,60
  784.     jae .L1
  785.     mov cx,60
  786. .L1:
  787.     neg cx
  788.     mov [edi+pcnet32_tx_head.length],cx
  789.     mov [edi+pcnet32_tx_head.misc],dword 0
  790.     mov [edi+pcnet32_tx_head.base],eax
  791.     mov [edi+pcnet32_tx_head.status],word 0x8300
  792.     ; trigger an immediate send poll
  793.     mov ebx,0
  794.     mov eax,0x0008      ; 0x0048
  795.     mov ebp,[io_addr]
  796.     call dword [pcnet32_access.write_csr]
  797.     mov dword [pcnet32_private.cur_tx],0
  798.     ; wait for TX to complete
  799.     mov ecx,[timer_ticks];[0xfdf0]
  800.     add ecx,100
  801. .L2:
  802.     mov ax,[edi+pcnet32_tx_head.status]
  803.     test ax,0x8000
  804.     jz .L3
  805.     cmp ecx,[timer_ticks];[0xfdf0]
  806.     jb .L4
  807.     mov esi,10
  808.     call delay_ms
  809.     jnz .L2
  810. .L4:
  811. ;    PutStr "PCNET: Send timeout"
  812. .L3:
  813.     mov dword [edi+pcnet32_tx_head.base],0
  814.     pop ecx
  815.     pop ebx
  816.     pop esi
  817.     pop edi
  818.     ret
  819.