Subversion Repositories Kolibri OS

Rev

Rev 9147 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 9147 Rev 9149
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
2
;;                                                                 ;;
3
;; Copyright (C) KolibriOS team 2004-2021. All rights reserved.    ;;
3
;; Copyright (C) KolibriOS team 2004-2021. All rights reserved.    ;;
4
;; Distributed under terms of the GNU General Public License       ;;
4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
5
;;                                                                 ;;
6
;;  i8254x driver for KolibriOS                                    ;;
6
;;  i8254x driver for KolibriOS                                    ;;
7
;;                                                                 ;;
7
;;                                                                 ;;
8
;;  based on i8254x.asm from baremetal os                          ;;
8
;;  based on i8254x.asm from baremetal os                          ;;
9
;;                                                                 ;;
9
;;                                                                 ;;
10
;;    Written by hidnplayr (hidnplayr@gmail.com)                   ;;
10
;;    Written by hidnplayr (hidnplayr@gmail.com)                   ;;
11
;;                                                                 ;;
11
;;                                                                 ;;
12
;;          GNU GENERAL PUBLIC LICENSE                             ;;
12
;;          GNU GENERAL PUBLIC LICENSE                             ;;
13
;;             Version 2, June 1991                                ;;
13
;;             Version 2, June 1991                                ;;
14
;;                                                                 ;;
14
;;                                                                 ;;
15
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
15
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
16
 
16
 
17
format PE DLL native
17
format PE DLL native
18
entry START
18
entry START
19
 
19
 
20
        CURRENT_API             = 0x0200
20
        CURRENT_API             = 0x0200
21
        COMPATIBLE_API          = 0x0100
21
        COMPATIBLE_API          = 0x0100
22
        API_VERSION             = (COMPATIBLE_API shl 16) + CURRENT_API
22
        API_VERSION             = (COMPATIBLE_API shl 16) + CURRENT_API
23
 
23
 
24
        MAX_DEVICES             = 16
24
        MAX_DEVICES             = 16
25
 
25
 
26
        __DEBUG__               = 1
26
        __DEBUG__               = 1
27
        __DEBUG_LEVEL__         = 2             ; 1 = verbose, 2 = errors only
27
        __DEBUG_LEVEL__         = 2             ; 1 = verbose, 2 = errors only
28
 
28
 
29
        MAX_PKT_SIZE            = 1514          ; Maximum packet size
29
        MAX_PKT_SIZE            = 1514          ; Maximum packet size
30
 
30
 
31
        RX_RING_SIZE            = 64             ; Must be a power of 2, and minimum 8
31
        RX_RING_SIZE            = 64             ; Must be a power of 2, and minimum 8
32
        TX_RING_SIZE            = 64             ; Must be a power of 2, and minimum 8
32
        TX_RING_SIZE            = 64             ; Must be a power of 2, and minimum 8
33
 
33
 
34
section '.flat' readable writable executable
34
section '.flat' readable writable executable
35
 
35
 
36
include '../proc32.inc'
36
include '../proc32.inc'
37
include '../struct.inc'
37
include '../struct.inc'
38
include '../macros.inc'
38
include '../macros.inc'
39
include '../fdo.inc'
39
include '../fdo.inc'
40
include '../netdrv.inc'
40
include '../netdrv.inc'
41
 
41
 
42
; Register list
42
; Register list
43
REG_CTRL                = 0x0000 ; Control Register
43
REG_CTRL                = 0x0000 ; Control Register
44
REG_STATUS              = 0x0008 ; Device Status Register
44
REG_STATUS              = 0x0008 ; Device Status Register
45
REG_CTRLEXT             = 0x0018 ; Extended Control Register
45
REG_CTRLEXT             = 0x0018 ; Extended Control Register
46
REG_MDIC                = 0x0020 ; MDI Control Register
46
REG_MDIC                = 0x0020 ; MDI Control Register
47
REG_FCAL                = 0x0028 ; Flow Control Address Low
47
REG_FCAL                = 0x0028 ; Flow Control Address Low
48
REG_FCAH                = 0x002C ; Flow Control Address High
48
REG_FCAH                = 0x002C ; Flow Control Address High
49
REG_FCT                 = 0x0030 ; Flow Control Type
49
REG_FCT                 = 0x0030 ; Flow Control Type
50
REG_VET                 = 0x0038 ; VLAN Ether Type
50
REG_VET                 = 0x0038 ; VLAN Ether Type
51
REG_ICR                 = 0x00C0 ; Interrupt Cause Read
51
REG_ICR                 = 0x00C0 ; Interrupt Cause Read
52
REG_ITR                 = 0x00C4 ; Interrupt Throttling Register
52
REG_ITR                 = 0x00C4 ; Interrupt Throttling Register
53
REG_ICS                 = 0x00C8 ; Interrupt Cause Set Register
53
REG_ICS                 = 0x00C8 ; Interrupt Cause Set Register
54
REG_IMS                 = 0x00D0 ; Interrupt Mask Set/Read Register
54
REG_IMS                 = 0x00D0 ; Interrupt Mask Set/Read Register
55
REG_IMC                 = 0x00D8 ; Interrupt Mask Clear Register
55
REG_IMC                 = 0x00D8 ; Interrupt Mask Clear Register
56
REG_RCTL                = 0x0100 ; Receive Control Register
56
REG_RCTL                = 0x0100 ; Receive Control Register
57
REG_FCTTV               = 0x0170 ; Flow Control Transmit Timer Value
57
REG_FCTTV               = 0x0170 ; Flow Control Transmit Timer Value
58
REG_TXCW                = 0x0178 ; Transmit Configuration Word
58
REG_TXCW                = 0x0178 ; Transmit Configuration Word
59
REG_RXCW                = 0x0180 ; Receive Configuration Word
59
REG_RXCW                = 0x0180 ; Receive Configuration Word
60
REG_TCTL                = 0x0400 ; Transmit Control Register
60
REG_TCTL                = 0x0400 ; Transmit Control Register
61
REG_TIPG                = 0x0410 ; Transmit Inter Packet Gap
61
REG_TIPG                = 0x0410 ; Transmit Inter Packet Gap
62
 
62
 
63
REG_LEDCTL              = 0x0E00 ; LED Control
63
REG_LEDCTL              = 0x0E00 ; LED Control
64
REG_PBA                 = 0x1000 ; Packet Buffer Allocation
64
REG_PBA                 = 0x1000 ; Packet Buffer Allocation
65
 
65
 
66
REG_RDBAL               = 0x2800 ; RX Descriptor Base Address Low
66
REG_RDBAL               = 0x2800 ; RX Descriptor Base Address Low
67
REG_RDBAH               = 0x2804 ; RX Descriptor Base Address High
67
REG_RDBAH               = 0x2804 ; RX Descriptor Base Address High
68
REG_RDLEN               = 0x2808 ; RX Descriptor Length
68
REG_RDLEN               = 0x2808 ; RX Descriptor Length
69
REG_RDH                 = 0x2810 ; RX Descriptor Head
69
REG_RDH                 = 0x2810 ; RX Descriptor Head
70
REG_RDT                 = 0x2818 ; RX Descriptor Tail
70
REG_RDT                 = 0x2818 ; RX Descriptor Tail
71
REG_RDTR                = 0x2820 ; RX Delay Timer Register
71
REG_RDTR                = 0x2820 ; RX Delay Timer Register
72
REG_RXDCTL              = 0x3828 ; RX Descriptor Control
72
REG_RXDCTL              = 0x3828 ; RX Descriptor Control
73
REG_RADV                = 0x282C ; RX Int. Absolute Delay Timer
73
REG_RADV                = 0x282C ; RX Int. Absolute Delay Timer
74
REG_RSRPD               = 0x2C00 ; RX Small Packet Detect Interrupt
74
REG_RSRPD               = 0x2C00 ; RX Small Packet Detect Interrupt
75
 
75
 
76
REG_TXDMAC              = 0x3000 ; TX DMA Control
76
REG_TXDMAC              = 0x3000 ; TX DMA Control
77
REG_TDBAL               = 0x3800 ; TX Descriptor Base Address Low
77
REG_TDBAL               = 0x3800 ; TX Descriptor Base Address Low
78
REG_TDBAH               = 0x3804 ; TX Descriptor Base Address High
78
REG_TDBAH               = 0x3804 ; TX Descriptor Base Address High
79
REG_TDLEN               = 0x3808 ; TX Descriptor Length
79
REG_TDLEN               = 0x3808 ; TX Descriptor Length
80
REG_TDH                 = 0x3810 ; TX Descriptor Head
80
REG_TDH                 = 0x3810 ; TX Descriptor Head
81
REG_TDT                 = 0x3818 ; TX Descriptor Tail
81
REG_TDT                 = 0x3818 ; TX Descriptor Tail
82
REG_TIDV                = 0x3820 ; TX Interrupt Delay Value
82
REG_TIDV                = 0x3820 ; TX Interrupt Delay Value
83
REG_TXDCTL              = 0x3828 ; TX Descriptor Control
83
REG_TXDCTL              = 0x3828 ; TX Descriptor Control
84
REG_TADV                = 0x382C ; TX Absolute Interrupt Delay Value
84
REG_TADV                = 0x382C ; TX Absolute Interrupt Delay Value
85
REG_TSPMT               = 0x3830 ; TCP Segmentation Pad & Min Threshold
85
REG_TSPMT               = 0x3830 ; TCP Segmentation Pad & Min Threshold
86
 
86
 
87
REG_RXCSUM              = 0x5000 ; RX Checksum Control
87
REG_RXCSUM              = 0x5000 ; RX Checksum Control
88
 
88
 
89
; Register list for i8254x
89
; Register list for i8254x
90
I82542_REG_RDTR         = 0x0108 ; RX Delay Timer Register
90
I82542_REG_RDTR         = 0x0108 ; RX Delay Timer Register
91
I82542_REG_RDBAL        = 0x0110 ; RX Descriptor Base Address Low
91
I82542_REG_RDBAL        = 0x0110 ; RX Descriptor Base Address Low
92
I82542_REG_RDBAH        = 0x0114 ; RX Descriptor Base Address High
92
I82542_REG_RDBAH        = 0x0114 ; RX Descriptor Base Address High
93
I82542_REG_RDLEN        = 0x0118 ; RX Descriptor Length
93
I82542_REG_RDLEN        = 0x0118 ; RX Descriptor Length
94
I82542_REG_RDH          = 0x0120 ; RDH for i82542
94
I82542_REG_RDH          = 0x0120 ; RDH for i82542
95
I82542_REG_RDT          = 0x0128 ; RDT for i82542
95
I82542_REG_RDT          = 0x0128 ; RDT for i82542
96
I82542_REG_TDBAL        = 0x0420 ; TX Descriptor Base Address Low
96
I82542_REG_TDBAL        = 0x0420 ; TX Descriptor Base Address Low
97
I82542_REG_TDBAH        = 0x0424 ; TX Descriptor Base Address Low
97
I82542_REG_TDBAH        = 0x0424 ; TX Descriptor Base Address Low
98
I82542_REG_TDLEN        = 0x0428 ; TX Descriptor Length
98
I82542_REG_TDLEN        = 0x0428 ; TX Descriptor Length
99
I82542_REG_TDH          = 0x0430 ; TDH for i82542
99
I82542_REG_TDH          = 0x0430 ; TDH for i82542
100
I82542_REG_TDT          = 0x0438 ; TDT for i82542
100
I82542_REG_TDT          = 0x0438 ; TDT for i82542
101
 
101
 
102
; CTRL - Control Register (0x0000)
102
; CTRL - Control Register (0x0000)
103
CTRL_FD                 = 0x00000001 ; Full Duplex
103
CTRL_FD                 = 0x00000001 ; Full Duplex
104
CTRL_LRST               = 0x00000008 ; Link Reset
104
CTRL_LRST               = 0x00000008 ; Link Reset
105
CTRL_ASDE               = 0x00000020 ; Auto-speed detection
105
CTRL_ASDE               = 0x00000020 ; Auto-speed detection
106
CTRL_SLU                = 0x00000040 ; Set Link Up
106
CTRL_SLU                = 0x00000040 ; Set Link Up
107
CTRL_ILOS               = 0x00000080 ; Invert Loss of Signal
107
CTRL_ILOS               = 0x00000080 ; Invert Loss of Signal
108
CTRL_SPEED_MASK         = 0x00000300 ; Speed selection
108
CTRL_SPEED_MASK         = 0x00000300 ; Speed selection
109
CTRL_SPEED_SHIFT        = 8
109
CTRL_SPEED_SHIFT        = 8
110
CTRL_FRCSPD             = 0x00000800 ; Force Speed
110
CTRL_FRCSPD             = 0x00000800 ; Force Speed
111
CTRL_FRCDPLX            = 0x00001000 ; Force Duplex
111
CTRL_FRCDPLX            = 0x00001000 ; Force Duplex
112
CTRL_SDP0_DATA          = 0x00040000 ; SDP0 data
112
CTRL_SDP0_DATA          = 0x00040000 ; SDP0 data
113
CTRL_SDP1_DATA          = 0x00080000 ; SDP1 data
113
CTRL_SDP1_DATA          = 0x00080000 ; SDP1 data
114
CTRL_SDP0_IODIR         = 0x00400000 ; SDP0 direction
114
CTRL_SDP0_IODIR         = 0x00400000 ; SDP0 direction
115
CTRL_SDP1_IODIR         = 0x00800000 ; SDP1 direction
115
CTRL_SDP1_IODIR         = 0x00800000 ; SDP1 direction
116
CTRL_RST                = 0x04000000 ; Device Reset
116
CTRL_RST                = 0x04000000 ; Device Reset
117
CTRL_RFCE               = 0x08000000 ; RX Flow Ctrl Enable
117
CTRL_RFCE               = 0x08000000 ; RX Flow Ctrl Enable
118
CTRL_TFCE               = 0x10000000 ; TX Flow Ctrl Enable
118
CTRL_TFCE               = 0x10000000 ; TX Flow Ctrl Enable
119
CTRL_VME                = 0x40000000 ; VLAN Mode Enable
119
CTRL_VME                = 0x40000000 ; VLAN Mode Enable
120
CTRL_PHY_RST            = 0x80000000 ; PHY reset
120
CTRL_PHY_RST            = 0x80000000 ; PHY reset
121
 
121
 
122
; STATUS - Device Status Register (0x0008)
122
; STATUS - Device Status Register (0x0008)
123
STATUS_FD               = 0x00000001 ; Full Duplex
123
STATUS_FD               = 0x00000001 ; Full Duplex
124
STATUS_LU               = 0x00000002 ; Link Up
124
STATUS_LU               = 0x00000002 ; Link Up
125
STATUS_TXOFF            = 0x00000010 ; Transmit paused
125
STATUS_TXOFF            = 0x00000010 ; Transmit paused
126
STATUS_TBIMODE          = 0x00000020 ; TBI Mode
126
STATUS_TBIMODE          = 0x00000020 ; TBI Mode
127
STATUS_SPEED_MASK       = 0x000000C0 ; Link Speed setting
127
STATUS_SPEED_MASK       = 0x000000C0 ; Link Speed setting
128
STATUS_SPEED_SHIFT      = 6
128
STATUS_SPEED_SHIFT      = 6
129
STATUS_ASDV_MASK        = 0x00000300 ; Auto Speed Detection
129
STATUS_ASDV_MASK        = 0x00000300 ; Auto Speed Detection
130
STATUS_ASDV_SHIFT       = 8
130
STATUS_ASDV_SHIFT       = 8
131
STATUS_PCI66            = 0x00000800 ; PCI bus speed
131
STATUS_PCI66            = 0x00000800 ; PCI bus speed
132
STATUS_BUS64            = 0x00001000 ; PCI bus width
132
STATUS_BUS64            = 0x00001000 ; PCI bus width
133
STATUS_PCIX_MODE        = 0x00002000 ; PCI-X mode
133
STATUS_PCIX_MODE        = 0x00002000 ; PCI-X mode
134
STATUS_PCIXSPD_MASK     = 0x0000C000 ; PCI-X speed
134
STATUS_PCIXSPD_MASK     = 0x0000C000 ; PCI-X speed
135
STATUS_PCIXSPD_SHIFT    = 14
135
STATUS_PCIXSPD_SHIFT    = 14
136
 
136
 
137
; CTRL_EXT - Extended Device Control Register (0x0018)
137
; CTRL_EXT - Extended Device Control Register (0x0018)
138
CTRLEXT_PHY_INT         = 0x00000020 ; PHY interrupt
138
CTRLEXT_PHY_INT         = 0x00000020 ; PHY interrupt
139
CTRLEXT_SDP6_DATA       = 0x00000040 ; SDP6 data
139
CTRLEXT_SDP6_DATA       = 0x00000040 ; SDP6 data
140
CTRLEXT_SDP7_DATA       = 0x00000080 ; SDP7 data
140
CTRLEXT_SDP7_DATA       = 0x00000080 ; SDP7 data
141
CTRLEXT_SDP6_IODIR      = 0x00000400 ; SDP6 direction
141
CTRLEXT_SDP6_IODIR      = 0x00000400 ; SDP6 direction
142
CTRLEXT_SDP7_IODIR      = 0x00000800 ; SDP7 direction
142
CTRLEXT_SDP7_IODIR      = 0x00000800 ; SDP7 direction
143
CTRLEXT_ASDCHK          = 0x00001000 ; Auto-Speed Detect Chk
143
CTRLEXT_ASDCHK          = 0x00001000 ; Auto-Speed Detect Chk
144
CTRLEXT_EE_RST          = 0x00002000 ; EEPROM reset
144
CTRLEXT_EE_RST          = 0x00002000 ; EEPROM reset
145
CTRLEXT_SPD_BYPS        = 0x00008000 ; Speed Select Bypass
145
CTRLEXT_SPD_BYPS        = 0x00008000 ; Speed Select Bypass
146
CTRLEXT_RO_DIS          = 0x00020000 ; Relaxed Ordering Dis.
146
CTRLEXT_RO_DIS          = 0x00020000 ; Relaxed Ordering Dis.
147
CTRLEXT_LNKMOD_MASK     = 0x00C00000 ; Link Mode
147
CTRLEXT_LNKMOD_MASK     = 0x00C00000 ; Link Mode
148
CTRLEXT_LNKMOD_SHIFT    = 22
148
CTRLEXT_LNKMOD_SHIFT    = 22
149
 
149
 
150
; MDIC - MDI Control Register (0x0020)
150
; MDIC - MDI Control Register (0x0020)
151
MDIC_DATA_MASK          = 0x0000FFFF ; Data
151
MDIC_DATA_MASK          = 0x0000FFFF ; Data
152
MDIC_REG_MASK           = 0x001F0000 ; PHY Register
152
MDIC_REG_MASK           = 0x001F0000 ; PHY Register
153
MDIC_REG_SHIFT          = 16
153
MDIC_REG_SHIFT          = 16
154
MDIC_PHY_MASK           = 0x03E00000 ; PHY Address
154
MDIC_PHY_MASK           = 0x03E00000 ; PHY Address
155
MDIC_PHY_SHIFT          = 21
155
MDIC_PHY_SHIFT          = 21
156
MDIC_OP_MASK            = 0x0C000000 ; Opcode
156
MDIC_OP_MASK            = 0x0C000000 ; Opcode
157
MDIC_OP_SHIFT           = 26
157
MDIC_OP_SHIFT           = 26
158
MDIC_R                  = 0x10000000 ; Ready
158
MDIC_R                  = 0x10000000 ; Ready
159
MDIC_I                  = 0x20000000 ; Interrupt Enable
159
MDIC_I                  = 0x20000000 ; Interrupt Enable
160
MDIC_E                  = 0x40000000 ; Error
160
MDIC_E                  = 0x40000000 ; Error
161
 
161
 
162
; ICR - Interrupt Cause Read (0x00c0)
162
; ICR - Interrupt Cause Read (0x00c0)
163
ICR_TXDW                = 0x00000001 ; TX Desc Written back
163
ICR_TXDW                = 0x00000001 ; TX Desc Written back
164
ICR_TXQE                = 0x00000002 ; TX Queue Empty
164
ICR_TXQE                = 0x00000002 ; TX Queue Empty
165
ICR_LSC                 = 0x00000004 ; Link Status Change
165
ICR_LSC                 = 0x00000004 ; Link Status Change
166
ICR_RXSEQ               = 0x00000008 ; RX Sence Error
166
ICR_RXSEQ               = 0x00000008 ; RX Sence Error
167
ICR_RXDMT0              = 0x00000010 ; RX Desc min threshold reached
167
ICR_RXDMT0              = 0x00000010 ; RX Desc min threshold reached
168
ICR_RXO                 = 0x00000040 ; RX Overrun
168
ICR_RXO                 = 0x00000040 ; RX Overrun
169
ICR_RXT0                = 0x00000080 ; RX Timer Interrupt
169
ICR_RXT0                = 0x00000080 ; RX Timer Interrupt
170
ICR_MDAC                = 0x00000200 ; MDIO Access Complete
170
ICR_MDAC                = 0x00000200 ; MDIO Access Complete
171
ICR_RXCFG               = 0x00000400
171
ICR_RXCFG               = 0x00000400
172
ICR_PHY_INT             = 0x00001000 ; PHY Interrupt
172
ICR_PHY_INT             = 0x00001000 ; PHY Interrupt
173
ICR_GPI_SDP6            = 0x00002000 ; GPI on SDP6
173
ICR_GPI_SDP6            = 0x00002000 ; GPI on SDP6
174
ICR_GPI_SDP7            = 0x00004000 ; GPI on SDP7
174
ICR_GPI_SDP7            = 0x00004000 ; GPI on SDP7
175
ICR_TXD_LOW             = 0x00008000 ; TX Desc low threshold hit
175
ICR_TXD_LOW             = 0x00008000 ; TX Desc low threshold hit
176
ICR_SRPD                = 0x00010000 ; Small RX packet detected
176
ICR_SRPD                = 0x00010000 ; Small RX packet detected
177
 
177
 
178
; RCTL - Receive Control Register (0x0100)
178
; RCTL - Receive Control Register (0x0100)
179
RCTL_EN                 = 0x00000002 ; Receiver Enable
179
RCTL_EN                 = 0x00000002 ; Receiver Enable
180
RCTL_SBP                = 0x00000004 ; Store Bad Packets
180
RCTL_SBP                = 0x00000004 ; Store Bad Packets
181
RCTL_UPE                = 0x00000008 ; Unicast Promiscuous Enabled
181
RCTL_UPE                = 0x00000008 ; Unicast Promiscuous Enabled
182
RCTL_MPE                = 0x00000010 ; Xcast Promiscuous Enabled
182
RCTL_MPE                = 0x00000010 ; Xcast Promiscuous Enabled
183
RCTL_LPE                = 0x00000020 ; Long Packet Reception Enable
183
RCTL_LPE                = 0x00000020 ; Long Packet Reception Enable
184
RCTL_LBM_MASK           = 0x000000C0 ; Loopback Mode
184
RCTL_LBM_MASK           = 0x000000C0 ; Loopback Mode
185
RCTL_LBM_SHIFT          = 6
185
RCTL_LBM_SHIFT          = 6
186
RCTL_RDMTS_MASK         = 0x00000300 ; RX Desc Min Threshold Size
186
RCTL_RDMTS_MASK         = 0x00000300 ; RX Desc Min Threshold Size
187
RCTL_RDMTS_SHIFT        = 8
187
RCTL_RDMTS_SHIFT        = 8
188
RCTL_MO_MASK            = 0x00003000 ; Multicast Offset
188
RCTL_MO_MASK            = 0x00003000 ; Multicast Offset
189
RCTL_MO_SHIFT           = 12
189
RCTL_MO_SHIFT           = 12
190
RCTL_BAM                = 0x00008000 ; Broadcast Accept Mode
190
RCTL_BAM                = 0x00008000 ; Broadcast Accept Mode
191
RCTL_BSIZE_MASK         = 0x00030000 ; RX Buffer Size
191
RCTL_BSIZE_MASK         = 0x00030000 ; RX Buffer Size
192
RCTL_BSIZE_SHIFT        = 16
192
RCTL_BSIZE_SHIFT        = 16
193
RCTL_VFE                = 0x00040000 ; VLAN Filter Enable
193
RCTL_VFE                = 0x00040000 ; VLAN Filter Enable
194
RCTL_CFIEN              = 0x00080000 ; CFI Enable
194
RCTL_CFIEN              = 0x00080000 ; CFI Enable
195
RCTL_CFI                = 0x00100000 ; Canonical Form Indicator Bit
195
RCTL_CFI                = 0x00100000 ; Canonical Form Indicator Bit
196
RCTL_DPF                = 0x00400000 ; Discard Pause Frames
196
RCTL_DPF                = 0x00400000 ; Discard Pause Frames
197
RCTL_PMCF               = 0x00800000 ; Pass MAC Control Frames
197
RCTL_PMCF               = 0x00800000 ; Pass MAC Control Frames
198
RCTL_BSEX               = 0x02000000 ; Buffer Size Extension
198
RCTL_BSEX               = 0x02000000 ; Buffer Size Extension
199
RCTL_SECRC              = 0x04000000 ; Strip Ethernet CRC
199
RCTL_SECRC              = 0x04000000 ; Strip Ethernet CRC
200
 
200
 
201
; TCTL - Transmit Control Register (0x0400)
201
; TCTL - Transmit Control Register (0x0400)
202
TCTL_EN                 = 0x00000002 ; Transmit Enable
202
TCTL_EN                 = 0x00000002 ; Transmit Enable
203
TCTL_PSP                = 0x00000008 ; Pad short packets
203
TCTL_PSP                = 0x00000008 ; Pad short packets
204
TCTL_SWXOFF             = 0x00400000 ; Software XOFF Transmission
204
TCTL_SWXOFF             = 0x00400000 ; Software XOFF Transmission
205
 
205
 
206
; PBA - Packet Buffer Allocation (0x1000)
206
; PBA - Packet Buffer Allocation (0x1000)
207
PBA_RXA_MASK            = 0x0000FFFF ; RX Packet Buffer
207
PBA_RXA_MASK            = 0x0000FFFF ; RX Packet Buffer
208
PBA_RXA_SHIFT           = 0
208
PBA_RXA_SHIFT           = 0
209
PBA_TXA_MASK            = 0xFFFF0000 ; TX Packet Buffer
209
PBA_TXA_MASK            = 0xFFFF0000 ; TX Packet Buffer
210
PBA_TXA_SHIFT           = 16
210
PBA_TXA_SHIFT           = 16
211
 
211
 
212
; Flow Control Type
212
; Flow Control Type
213
FCT_TYPE_DEFAULT        = 0x8808
213
FCT_TYPE_DEFAULT        = 0x8808
214
 
214
 
215
 
215
 
216
 
216
 
217
; === TX Descriptor ===
217
; === TX Descriptor ===
218
 
218
 
219
struct TDESC
219
struct TDESC
220
        addr_l          dd ?
220
        addr_l          dd ?
221
        addr_h          dd ?
221
        addr_h          dd ?
222
        length_cso_cmd  dd ?    ; 16 bits length + 8 bits cso + 8 bits cmd
222
        length_cso_cmd  dd ?    ; 16 bits length + 8 bits cso + 8 bits cmd
223
        status          dd ?    ; status, checksum start field, special
223
        status          dd ?    ; status, checksum start field, special
224
ends
224
ends
225
 
225
 
226
; TX Packet Length (word 2)
226
; TX Packet Length (word 2)
227
TXDESC_LEN_MASK         = 0x0000ffff
227
TXDESC_LEN_MASK         = 0x0000ffff
228
 
228
 
229
; TX Descriptor CMD field (word 2)
229
; TX Descriptor CMD field (word 2)
230
TXDESC_IDE              = 0x80000000 ; Interrupt Delay Enable
230
TXDESC_IDE              = 0x80000000 ; Interrupt Delay Enable
231
TXDESC_VLE              = 0x40000000 ; VLAN Packet Enable
231
TXDESC_VLE              = 0x40000000 ; VLAN Packet Enable
232
TXDESC_DEXT             = 0x20000000 ; Extension
232
TXDESC_DEXT             = 0x20000000 ; Extension
233
TXDESC_RPS              = 0x10000000 ; Report Packet Sent
233
TXDESC_RPS              = 0x10000000 ; Report Packet Sent
234
TXDESC_RS               = 0x08000000 ; Report Status
234
TXDESC_RS               = 0x08000000 ; Report Status
235
TXDESC_IC               = 0x04000000 ; Insert Checksum
235
TXDESC_IC               = 0x04000000 ; Insert Checksum
236
TXDESC_IFCS             = 0x02000000 ; Insert FCS
236
TXDESC_IFCS             = 0x02000000 ; Insert FCS
237
TXDESC_EOP              = 0x01000000 ; End Of Packet
237
TXDESC_EOP              = 0x01000000 ; End Of Packet
238
 
238
 
239
; TX Descriptor STA field (word 3)
239
; TX Descriptor STA field (word 3)
240
TXDESC_TU               = 0x00000008 ; Transmit Underrun
240
TXDESC_TU               = 0x00000008 ; Transmit Underrun
241
TXDESC_LC               = 0x00000004 ; Late Collision
241
TXDESC_LC               = 0x00000004 ; Late Collision
242
TXDESC_EC               = 0x00000002 ; Excess Collisions
242
TXDESC_EC               = 0x00000002 ; Excess Collisions
243
TXDESC_DD               = 0x00000001 ; Descriptor Done
243
TXDESC_DD               = 0x00000001 ; Descriptor Done
244
 
244
 
245
 
245
 
246
 
246
 
247
; === RX Descriptor ===
247
; === RX Descriptor ===
248
 
248
 
249
struct RDESC
249
struct RDESC
250
        addr_l          dd ?
250
        addr_l          dd ?
251
        addr_h          dd ?
251
        addr_h          dd ?
252
        status_l        dd ?
252
        status_l        dd ?
253
        status_h        dd ?
253
        status_h        dd ?
254
ends
254
ends
255
 
255
 
256
; RX Packet Length (word 2)
256
; RX Packet Length (word 2)
257
RXDESC_LEN_MASK         = 0x0000ffff
257
RXDESC_LEN_MASK         = 0x0000ffff
258
 
258
 
259
; RX Descriptor STA field (word 3)
259
; RX Descriptor STA field (word 3)
260
RXDESC_PIF              = 0x00000080 ; Passed In-exact Filter
260
RXDESC_PIF              = 0x00000080 ; Passed In-exact Filter
261
RXDESC_IPCS             = 0x00000040 ; IP cksum calculated
261
RXDESC_IPCS             = 0x00000040 ; IP cksum calculated
262
RXDESC_TCPCS            = 0x00000020 ; TCP cksum calculated
262
RXDESC_TCPCS            = 0x00000020 ; TCP cksum calculated
263
RXDESC_VP               = 0x00000008 ; Packet is 802.1Q
263
RXDESC_VP               = 0x00000008 ; Packet is 802.1Q
264
RXDESC_IXSM             = 0x00000004 ; Ignore cksum indication
264
RXDESC_IXSM             = 0x00000004 ; Ignore cksum indication
265
RXDESC_EOP              = 0x00000002 ; End Of Packet
265
RXDESC_EOP              = 0x00000002 ; End Of Packet
266
RXDESC_DD               = 0x00000001 ; Descriptor Done
266
RXDESC_DD               = 0x00000001 ; Descriptor Done
267
 
267
 
268
struct  device          ETH_DEVICE
268
struct  device          ETH_DEVICE
269
 
269
 
270
        mmio_addr       dd ?
270
        mmio_addr       dd ?
271
        pci_bus         dd ?
271
        pci_bus         dd ?
272
        pci_dev         dd ?
272
        pci_dev         dd ?
273
        irq_line        db ?
273
        irq_line        db ?
274
 
274
 
275
        cur_rx          dd ?
275
        cur_rx          dd ?
276
        cur_tx          dd ?
276
        cur_tx          dd ?
277
        last_tx         dd ?
277
        last_tx         dd ?
278
 
278
 
279
        rb 0x100 - ($ and 0xff) ; align 256
279
        rb 0x100 - ($ and 0xff) ; align 256
280
        rx_desc         rb RX_RING_SIZE*sizeof.RDESC*2
280
        rx_desc         rb RX_RING_SIZE*sizeof.RDESC*2
281
 
281
 
282
        rb 0x100 - ($ and 0xff) ; align 256
282
        rb 0x100 - ($ and 0xff) ; align 256
283
        tx_desc         rb TX_RING_SIZE*sizeof.TDESC*2
283
        tx_desc         rb TX_RING_SIZE*sizeof.TDESC*2
284
 
284
 
285
ends
285
ends
286
 
286
 
287
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
287
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
288
;;                        ;;
288
;;                        ;;
289
;; proc START             ;;
289
;; proc START             ;;
290
;;                        ;;
290
;;                        ;;
291
;; (standard driver proc) ;;
291
;; (standard driver proc) ;;
292
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
292
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
293
 
293
 
294
proc START c, reason:dword, cmdline:dword
294
proc START c, reason:dword, cmdline:dword
295
 
295
 
296
        cmp     [reason], DRV_ENTRY
296
        cmp     [reason], DRV_ENTRY
297
        jne     .fail
297
        jne     .fail
298
 
298
 
299
        DEBUGF  1,"Loading driver\n"
299
        DEBUGF  1,"Loading driver\n"
300
        invoke  RegService, my_service, service_proc
300
        invoke  RegService, my_service, service_proc
301
        ret
301
        ret
302
 
302
 
303
  .fail:
303
  .fail:
304
        xor     eax, eax
304
        xor     eax, eax
305
        ret
305
        ret
306
 
306
 
307
endp
307
endp
308
 
308
 
309
 
309
 
310
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
310
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
311
;;                        ;;
311
;;                        ;;
312
;; proc SERVICE_PROC      ;;
312
;; proc SERVICE_PROC      ;;
313
;;                        ;;
313
;;                        ;;
314
;; (standard driver proc) ;;
314
;; (standard driver proc) ;;
315
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
315
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
316
 
316
 
317
align 4
317
align 4
318
proc service_proc stdcall, ioctl:dword
318
proc service_proc stdcall, ioctl:dword
319
 
319
 
320
        mov     edx, [ioctl]
320
        mov     edx, [ioctl]
321
        mov     eax, [edx + IOCTL.io_code]
321
        mov     eax, [edx + IOCTL.io_code]
322
 
322
 
323
;------------------------------------------------------
323
;------------------------------------------------------
324
 
324
 
325
        cmp     eax, 0 ;SRV_GETVERSION
325
        cmp     eax, 0 ;SRV_GETVERSION
326
        jne     @F
326
        jne     @F
327
 
327
 
328
        cmp     [edx + IOCTL.out_size], 4
328
        cmp     [edx + IOCTL.out_size], 4
329
        jb      .fail
329
        jb      .fail
330
        mov     eax, [edx + IOCTL.output]
330
        mov     eax, [edx + IOCTL.output]
331
        mov     dword[eax], API_VERSION
331
        mov     dword[eax], API_VERSION
332
 
332
 
333
        xor     eax, eax
333
        xor     eax, eax
334
        ret
334
        ret
335
 
335
 
336
;------------------------------------------------------
336
;------------------------------------------------------
337
  @@:
337
  @@:
338
        cmp     eax, 1 ;SRV_HOOK
338
        cmp     eax, 1 ;SRV_HOOK
339
        jne     .fail
339
        jne     .fail
340
 
340
 
341
        cmp     [edx + IOCTL.inp_size], 3               ; Data input must be at least 3 bytes
341
        cmp     [edx + IOCTL.inp_size], 3               ; Data input must be at least 3 bytes
342
        jb      .fail
342
        jb      .fail
343
 
343
 
344
        mov     eax, [edx + IOCTL.input]
344
        mov     eax, [edx + IOCTL.input]
345
        cmp     byte[eax], 1                            ; 1 means device number and bus number (pci) are given
345
        cmp     byte[eax], 1                            ; 1 means device number and bus number (pci) are given
346
        jne     .fail                                   ; other types arent supported for this card yet
346
        jne     .fail                                   ; other types arent supported for this card yet
347
 
347
 
348
; check if the device is already listed
348
; check if the device is already listed
349
 
349
 
350
        mov     esi, device_list
350
        mov     esi, device_list
351
        mov     ecx, [devices]
351
        mov     ecx, [devices]
352
        test    ecx, ecx
352
        test    ecx, ecx
353
        jz      .firstdevice
353
        jz      .firstdevice
354
 
354
 
355
;        mov     eax, [edx + IOCTL.input]                ; get the pci bus and device numbers
355
;        mov     eax, [edx + IOCTL.input]                ; get the pci bus and device numbers
356
        mov     ax, [eax+1]                             ;
356
        mov     ax, [eax+1]                             ;
357
  .nextdevice:
357
  .nextdevice:
358
        mov     ebx, [esi]
358
        mov     ebx, [esi]
359
        cmp     al, byte[ebx + device.pci_bus]
359
        cmp     al, byte[ebx + device.pci_bus]
360
        jne     .next
360
        jne     .next
361
        cmp     ah, byte[ebx + device.pci_dev]
361
        cmp     ah, byte[ebx + device.pci_dev]
362
        je      .find_devicenum                         ; Device is already loaded, let's find it's device number
362
        je      .find_devicenum                         ; Device is already loaded, let's find it's device number
363
  .next:
363
  .next:
364
        add     esi, 4
364
        add     esi, 4
365
        loop    .nextdevice
365
        loop    .nextdevice
366
 
366
 
367
 
367
 
368
; This device doesnt have its own eth_device structure yet, lets create one
368
; This device doesnt have its own eth_device structure yet, lets create one
369
  .firstdevice:
369
  .firstdevice:
370
        cmp     [devices], MAX_DEVICES                  ; First check if the driver can handle one more card
370
        cmp     [devices], MAX_DEVICES                  ; First check if the driver can handle one more card
371
        jae     .fail
371
        jae     .fail
372
 
372
 
373
        allocate_and_clear ebx, sizeof.device, .fail    ; Allocate the buffer for device structure
373
        allocate_and_clear ebx, sizeof.device, .fail    ; Allocate the buffer for device structure
374
 
374
 
375
; Fill in the direct call addresses into the struct
375
; Fill in the direct call addresses into the struct
376
 
376
 
377
        mov     [ebx + device.reset], reset
377
        mov     [ebx + device.reset], reset
378
        mov     [ebx + device.transmit], transmit
378
        mov     [ebx + device.transmit], transmit
379
        mov     [ebx + device.unload], unload
379
        mov     [ebx + device.unload], unload
380
        mov     [ebx + device.name], my_service
380
        mov     [ebx + device.name], my_service
381
 
381
 
382
; save the pci bus and device numbers
382
; save the pci bus and device numbers
383
 
383
 
384
        mov     eax, [edx + IOCTL.input]
384
        mov     eax, [edx + IOCTL.input]
385
        movzx   ecx, byte[eax+1]
385
        movzx   ecx, byte[eax+1]
386
        mov     [ebx + device.pci_bus], ecx
386
        mov     [ebx + device.pci_bus], ecx
387
        movzx   ecx, byte[eax+2]
387
        movzx   ecx, byte[eax+2]
388
        mov     [ebx + device.pci_dev], ecx
388
        mov     [ebx + device.pci_dev], ecx
389
 
389
 
390
; Now, it's time to find the base mmio addres of the PCI device
390
; Now, it's time to find the base mmio addres of the PCI device
391
 
391
 
392
        stdcall PCI_find_mmio, [ebx + device.pci_bus], [ebx + device.pci_dev] ; returns in eax
392
        stdcall PCI_find_mmio, [ebx + device.pci_bus], [ebx + device.pci_dev] ; returns in eax
393
        test    eax, eax
393
        test    eax, eax
394
        jz      .destroy
394
        jz      .destroy
395
 
395
 
396
; Create virtual mapping of the physical memory
396
; Create virtual mapping of the physical memory
397
 
397
 
398
        invoke  MapIoMem, eax, 10000h, PG_SW+PG_NOCACHE
398
        invoke  MapIoMem, eax, 10000h, PG_SW+PG_NOCACHE
399
        mov     [ebx + device.mmio_addr], eax
399
        mov     [ebx + device.mmio_addr], eax
400
 
400
 
401
; We've found the mmio address, find IRQ now
401
; We've found the mmio address, find IRQ now
402
 
402
 
403
        invoke  PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.interrupt_line
403
        invoke  PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.interrupt_line
404
        mov     [ebx + device.irq_line], al
404
        mov     [ebx + device.irq_line], al
405
 
405
 
406
        DEBUGF  1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
406
        DEBUGF  1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
407
        [ebx + device.pci_dev]:1,[ebx + device.pci_bus]:1,[ebx + device.irq_line]:1,[ebx + device.mmio_addr]:8
407
        [ebx + device.pci_dev]:1,[ebx + device.pci_bus]:1,[ebx + device.irq_line]:1,[ebx + device.mmio_addr]:8
408
 
408
 
409
; Ok, the eth_device structure is ready, let's probe the device
409
; Ok, the eth_device structure is ready, let's probe the device
410
        call    probe                                   ; this function will output in eax
410
        call    probe                                   ; this function will output in eax
411
        test    eax, eax
411
        test    eax, eax
412
        jnz     .err                                    ; If an error occured, exit
412
        jnz     .err                                    ; If an error occured, exit
413
 
413
 
414
        mov     eax, [devices]                          ; Add the device structure to our device list
414
        mov     eax, [devices]                          ; Add the device structure to our device list
415
        mov     [device_list+4*eax], ebx                ; (IRQ handler uses this list to find device)
415
        mov     [device_list+4*eax], ebx                ; (IRQ handler uses this list to find device)
416
        inc     [devices]                               ;
416
        inc     [devices]                               ;
417
 
417
 
418
        call    start_i8254x
418
        call    start_i8254x
419
        test    eax, eax
419
        test    eax, eax
420
        jnz     .destroy
420
        jnz     .destroy
421
 
421
 
422
        mov     [ebx + device.type], NET_TYPE_ETH
422
        mov     [ebx + device.type], NET_TYPE_ETH
423
        invoke  NetRegDev
423
        invoke  NetRegDev
424
        cmp     eax, -1
424
        cmp     eax, -1
425
        je      .destroy
425
        je      .destroy
426
 
426
 
427
        ret
427
        ret
428
 
428
 
429
; If the device was already loaded, find the device number and return it in eax
429
; If the device was already loaded, find the device number and return it in eax
430
 
430
 
431
  .find_devicenum:
431
  .find_devicenum:
432
        DEBUGF  1,"Trying to find device number of already registered device\n"
432
        DEBUGF  1,"Trying to find device number of already registered device\n"
433
        invoke  NetPtrToNum                             ; This kernel procedure converts a pointer to device struct in ebx
433
        invoke  NetPtrToNum                             ; This kernel procedure converts a pointer to device struct in ebx
434
                                                        ; into a device number in edi
434
                                                        ; into a device number in edi
435
        mov     eax, edi                                ; Application wants it in eax instead
435
        mov     eax, edi                                ; Application wants it in eax instead
436
        DEBUGF  1,"Kernel says: %u\n", eax
436
        DEBUGF  1,"Kernel says: %u\n", eax
437
        ret
437
        ret
438
 
438
 
439
; If an error occured, remove all allocated data and exit (returning -1 in eax)
439
; If an error occured, remove all allocated data and exit (returning -1 in eax)
440
 
440
 
441
  .destroy:
441
  .destroy:
442
        ; todo: reset device into virgin state
442
        ; todo: reset device into virgin state
443
 
443
 
444
  .err:
444
  .err:
445
        invoke  KernelFree, ebx
445
        invoke  KernelFree, ebx
446
 
446
 
447
  .fail:
447
  .fail:
448
        DEBUGF  2,"Loading driver failed\n"
448
        DEBUGF  2,"Loading driver failed\n"
449
        or      eax, -1
449
        or      eax, -1
450
        ret
450
        ret
451
 
451
 
452
;------------------------------------------------------
452
;------------------------------------------------------
453
endp
453
endp
454
 
454
 
455
 
455
 
456
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
456
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
457
;;                                                                        ;;
457
;;                                                                        ;;
458
;;        Actual Hardware dependent code starts here                      ;;
458
;;        Actual Hardware dependent code starts here                      ;;
459
;;                                                                        ;;
459
;;                                                                        ;;
460
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
460
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
461
 
461
 
462
 
462
 
463
align 4
463
align 4
464
unload:
464
unload:
465
 
465
 
466
        DEBUGF  1,"Unload\n"
466
        DEBUGF  1,"Unload\n"
467
 
467
 
468
        ; TODO: (in this particular order)
468
        ; TODO: (in this particular order)
469
        ;
469
        ;
470
        ; - Stop the device
470
        ; - Stop the device
471
        ; - Detach int handler
471
        ; - Detach int handler
472
        ; - Remove device from local list (device_list)
472
        ; - Remove device from local list (device_list)
473
        ; - call unregister function in kernel
473
        ; - call unregister function in kernel
474
        ; - Remove all allocated structures and buffers the card used
474
        ; - Remove all allocated structures and buffers the card used
475
 
475
 
476
        or      eax, -1
476
        or      eax, -1
477
        ret
477
        ret
478
 
478
 
479
 
479
 
480
 
480
 
481
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
481
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
482
;;
482
;;
483
;;  probe: enables the device (if it really is I8254X)
483
;;  probe: enables the device (if it really is I8254X)
484
;;
484
;;
485
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
485
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
486
align 4
486
align 4
487
probe:
487
probe:
488
 
488
 
489
        DEBUGF  1,"Probe\n"
489
        DEBUGF  1,"Probe\n"
490
 
490
 
491
; Make the device a bus master
491
; Make the device a bus master
492
        invoke  PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command
492
        invoke  PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command
493
        or      al, PCI_CMD_MASTER
493
        or      al, PCI_CMD_MASTER
494
        invoke  PciWrite32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command, eax
494
        invoke  PciWrite32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command, eax
495
 
495
 
496
        ; TODO: validate the device
496
        ; TODO: validate the device
497
 
497
 
498
        call    read_mac
498
        call    read_mac
499
 
499
 
500
        movzx   eax, [ebx + device.irq_line]
500
        movzx   eax, [ebx + device.irq_line]
501
        DEBUGF  1,"Attaching int handler to irq %x\n", eax:1
501
        DEBUGF  1,"Attaching int handler to irq %x\n", eax:1
502
        invoke  AttachIntHandler, eax, int_handler, ebx
502
        invoke  AttachIntHandler, eax, int_handler, ebx
503
        test    eax, eax
503
        test    eax, eax
504
        jnz     @f
504
        jnz     @f
505
        DEBUGF  2,"Could not attach int handler!\n"
505
        DEBUGF  2,"Could not attach int handler!\n"
506
        or      eax, -1
506
        or      eax, -1
507
        ret
507
        ret
508
  @@:
508
  @@:
509
 
509
 
510
 
510
 
511
reset_dontstart:
511
reset_dontstart:
512
        DEBUGF  1,"Reset\n"
512
        DEBUGF  1,"Reset\n"
513
 
513
 
514
        mov     esi, [ebx + device.mmio_addr]
514
        mov     esi, [ebx + device.mmio_addr]
515
 
515
 
516
        or      dword[esi + REG_CTRL], CTRL_RST         ; reset device
516
        or      dword[esi + REG_CTRL], CTRL_RST         ; reset device
517
  .loop:
517
  .loop:
518
        push    esi
518
        push    esi
519
        xor     esi, esi
519
        xor     esi, esi
520
        inc     esi
520
        inc     esi
521
        invoke  Sleep
521
        invoke  Sleep
522
        pop     esi
522
        pop     esi
523
        test    dword[esi + REG_CTRL], CTRL_RST
523
        test    dword[esi + REG_CTRL], CTRL_RST
524
        jnz     .loop
524
        jnz     .loop
525
 
525
 
526
        mov     dword[esi + REG_IMC], 0xffffffff        ; Disable all interrupt causes
526
        mov     dword[esi + REG_IMC], 0xffffffff        ; Disable all interrupt causes
527
        mov     eax, dword [esi + REG_ICR]              ; Clear any pending interrupts
527
        mov     eax, dword [esi + REG_ICR]              ; Clear any pending interrupts
528
        mov     dword[esi + REG_ITR], 0                 ; Disable interrupt throttling logic
528
        mov     dword[esi + REG_ITR], 0                 ; Disable interrupt throttling logic
529
 
529
 
530
        mov     dword[esi + REG_PBA], 0x00000004        ; PBA: set the RX buffer size to 4KB (TX buffer is calculated as 64-RX buffer)
530
        mov     dword[esi + REG_PBA], 0x00000004        ; PBA: set the RX buffer size to 4KB (TX buffer is calculated as 64-RX buffer)
531
        mov     dword[esi + REG_RDTR], 0                ; RDTR: set no delay
531
        mov     dword[esi + REG_RDTR], 0                ; RDTR: set no delay
532
 
532
 
533
        mov     dword[esi + REG_TXCW], 0x00008060       ; TXCW: TxConfigWord (Half/Full duplex, Next Page Reqest)
533
        mov     dword[esi + REG_TXCW], 0x00008060       ; TXCW: TxConfigWord (Half/Full duplex, Next Page Reqest)
534
 
534
 
535
        mov     eax, [esi + REG_CTRL]
535
        mov     eax, [esi + REG_CTRL]
536
        or      eax, 1 shl 6 + 1 shl 5
536
        or      eax, 1 shl 6 + 1 shl 5
537
        and     eax, not (1 shl 3 + 1 shl 7 + 1 shl 30 + 1 shl 31)
537
        and     eax, not (1 shl 3 + 1 shl 7 + 1 shl 30 + 1 shl 31)
538
        mov     dword [esi + REG_CTRL], eax             ; CTRL: clear LRST, set SLU and ASDE, clear RSTPHY, VME, and ILOS
538
        mov     dword [esi + REG_CTRL], eax             ; CTRL: clear LRST, set SLU and ASDE, clear RSTPHY, VME, and ILOS
539
 
539
 
540
        lea     edi, [esi + 0x5200]                     ; MTA: reset
540
        lea     edi, [esi + 0x5200]                     ; MTA: reset
541
        mov     eax, 0xffffffff
541
        mov     eax, 0xffffffff
542
        stosd
542
        stosd
543
        stosd
543
        stosd
544
        stosd
544
        stosd
545
        stosd
545
        stosd
546
 
546
 
547
        call    init_rx
547
        call    init_rx
548
        test    eax, eax
548
        test    eax, eax
549
        jnz     .fail
549
        jnz     .fail
550
        call    init_tx
550
        call    init_tx
551
 
551
 
552
        xor     eax, eax
552
        xor     eax, eax
553
  .fail:
553
  .fail:
554
        ret
554
        ret
555
 
555
 
556
 
556
 
557
 
557
 
558
align 4
558
align 4
559
init_rx:
559
init_rx:
560
 
560
 
561
        lea     edi, [ebx + device.rx_desc]
561
        lea     edi, [ebx + device.rx_desc]
562
        mov     ecx, RX_RING_SIZE
562
        mov     ecx, RX_RING_SIZE
563
  .loop:
563
  .loop:
564
        push    ecx
564
        push    ecx
565
        push    edi
565
        push    edi
566
        invoke  NetAlloc, MAX_PKT_SIZE+NET_BUFF.data
566
        invoke  NetAlloc, MAX_PKT_SIZE+NET_BUFF.data
567
        test    eax, eax
567
        test    eax, eax
568
        jz      .out_of_mem
568
        jz      .out_of_mem
569
        DEBUGF  1,"RX buffer: 0x%x\n", eax
569
        DEBUGF  1,"RX buffer: 0x%x\n", eax
570
        pop     edi
570
        pop     edi
571
        mov     dword[edi + RX_RING_SIZE*sizeof.RDESC], eax
571
        mov     dword[edi + RX_RING_SIZE*sizeof.RDESC], eax
572
        push    edi
572
        push    edi
573
        invoke  GetPhysAddr
573
        invoke  GetPhysAddr
574
        pop     edi
574
        pop     edi
575
        add     eax, NET_BUFF.data
575
        add     eax, NET_BUFF.data
576
        mov     [edi + RDESC.addr_l], eax
576
        mov     [edi + RDESC.addr_l], eax
577
        mov     [edi + RDESC.addr_h], 0
577
        mov     [edi + RDESC.addr_h], 0
578
        mov     [edi + RDESC.status_l], 0
578
        mov     [edi + RDESC.status_l], 0
579
        mov     [edi + RDESC.status_h], 0
579
        mov     [edi + RDESC.status_h], 0
580
        add     edi, sizeof.RDESC
580
        add     edi, sizeof.RDESC
581
        pop     ecx
581
        pop     ecx
582
        dec     ecx
582
        dec     ecx
583
        jnz     .loop
583
        jnz     .loop
584
 
584
 
585
        mov     [ebx + device.cur_rx], 0
585
        mov     [ebx + device.cur_rx], 0
586
 
586
 
587
        lea     eax, [ebx + device.rx_desc]
587
        lea     eax, [ebx + device.rx_desc]
588
        invoke  GetPhysAddr
588
        invoke  GetPhysAddr
589
        mov     dword[esi + REG_RDBAL], eax                             ; Receive Descriptor Base Address Low
589
        mov     dword[esi + REG_RDBAL], eax                             ; Receive Descriptor Base Address Low
590
        mov     dword[esi + REG_RDBAH], 0                               ; Receive Descriptor Base Address High
590
        mov     dword[esi + REG_RDBAH], 0                               ; Receive Descriptor Base Address High
591
        mov     dword[esi + REG_RDLEN], RX_RING_SIZE*sizeof.RDESC       ; Receive Descriptor Length
591
        mov     dword[esi + REG_RDLEN], RX_RING_SIZE*sizeof.RDESC       ; Receive Descriptor Length
592
        mov     dword[esi + REG_RDH], 0                                 ; Receive Descriptor Head
592
        mov     dword[esi + REG_RDH], 0                                 ; Receive Descriptor Head
593
        mov     dword[esi + REG_RDT], RX_RING_SIZE-1                    ; Receive Descriptor Tail
593
        mov     dword[esi + REG_RDT], RX_RING_SIZE-1                    ; Receive Descriptor Tail
594
        mov     dword[esi + REG_RCTL], RCTL_SBP or RCTL_BAM or RCTL_SECRC or RCTL_UPE or RCTL_MPE
594
        mov     dword[esi + REG_RCTL], RCTL_SBP or RCTL_BAM or RCTL_SECRC or RCTL_UPE or RCTL_MPE
595
        ; Store Bad Packets, Broadcast Accept Mode, Strip Ethernet CRC from incoming packet, Promiscuous mode
595
        ; Store Bad Packets, Broadcast Accept Mode, Strip Ethernet CRC from incoming packet, Promiscuous mode
596
        xor     eax, eax        ; success!
596
        xor     eax, eax        ; success!
597
        ret
597
        ret
598
 
598
 
599
  .out_of_mem:
599
  .out_of_mem:
600
        DEBUGF  2,"Out of memory!\n"
600
        DEBUGF  2,"Out of memory!\n"
601
        pop     edi ecx
601
        pop     edi ecx
602
        or      eax, -1         ; error!
602
        or      eax, -1         ; error!
603
        ret
603
        ret
604
 
604
 
605
 
605
 
606
 
606
 
607
align 4
607
align 4
608
init_tx:
608
init_tx:
609
 
609
 
610
        lea     edi, [ebx + device.tx_desc]
610
        lea     edi, [ebx + device.tx_desc]
611
        mov     ecx, TX_RING_SIZE
611
        mov     ecx, TX_RING_SIZE
612
  .loop:
612
  .loop:
613
        mov     [edi + TDESC.addr_l], eax
613
        mov     [edi + TDESC.addr_l], eax
614
        mov     [edi + TDESC.addr_h], 0
614
        mov     [edi + TDESC.addr_h], 0
615
        mov     [edi + TDESC.length_cso_cmd], 0
615
        mov     [edi + TDESC.length_cso_cmd], 0
616
        mov     [edi + TDESC.status], 0
616
        mov     [edi + TDESC.status], 0
617
        add     edi, sizeof.TDESC
617
        add     edi, sizeof.TDESC
618
        dec     ecx
618
        dec     ecx
619
        jnz     .loop
619
        jnz     .loop
620
 
620
 
621
        mov     [ebx + device.cur_tx], 0
621
        mov     [ebx + device.cur_tx], 0
622
        mov     [ebx + device.last_tx], 0
622
        mov     [ebx + device.last_tx], 0
623
 
623
 
624
        lea     eax, [ebx + device.tx_desc]
624
        lea     eax, [ebx + device.tx_desc]
625
        invoke  GetPhysAddr
625
        invoke  GetPhysAddr
626
        mov     dword[esi + REG_TDBAL], eax                             ; Transmit Descriptor Base Address Low
626
        mov     dword[esi + REG_TDBAL], eax                             ; Transmit Descriptor Base Address Low
627
        mov     dword[esi + REG_TDBAH], 0                               ; Transmit Descriptor Base Address High
627
        mov     dword[esi + REG_TDBAH], 0                               ; Transmit Descriptor Base Address High
628
        mov     dword[esi + REG_TDLEN], RX_RING_SIZE*sizeof.TDESC       ; Transmit Descriptor Length
628
        mov     dword[esi + REG_TDLEN], RX_RING_SIZE*sizeof.TDESC       ; Transmit Descriptor Length
629
        mov     dword[esi + REG_TDH], 0                                 ; Transmit Descriptor Head
629
        mov     dword[esi + REG_TDH], 0                                 ; Transmit Descriptor Head
630
        mov     dword[esi + REG_TDT], 0                                 ; Transmit Descriptor Tail
630
        mov     dword[esi + REG_TDT], 0                                 ; Transmit Descriptor Tail
631
        mov     dword[esi + REG_TCTL], 0x010400fa                       ; Enabled, Pad Short Packets, 15 retrys, 64-byte COLD, Re-transmit on Late Collision
631
        mov     dword[esi + REG_TCTL], 0x010400fa                       ; Enabled, Pad Short Packets, 15 retrys, 64-byte COLD, Re-transmit on Late Collision
632
        mov     dword[esi + REG_TIPG], 0x0060200A                       ; IPGT 10, IPGR1 8, IPGR2 6
632
        mov     dword[esi + REG_TIPG], 0x0060200A                       ; IPGT 10, IPGR1 8, IPGR2 6
633
 
633
 
634
        ret
634
        ret
635
 
635
 
636
 
636
 
637
align 4
637
align 4
638
reset:
638
reset:
639
        call    reset_dontstart
639
        call    reset_dontstart
640
        test    eax, eax
640
        test    eax, eax
641
        je      start_i8254x
641
        je      start_i8254x
642
 
642
 
643
        ret
643
        ret
644
 
644
 
645
align 4
645
align 4
646
start_i8254x:
646
start_i8254x:
647
 
647
 
648
        mov     esi, [ebx + device.mmio_addr]
648
        mov     esi, [ebx + device.mmio_addr]
649
        or      dword[esi + REG_RCTL], RCTL_EN          ; Enable the receiver
649
        or      dword[esi + REG_RCTL], RCTL_EN          ; Enable the receiver
650
 
650
 
651
        xor     eax, eax
651
        xor     eax, eax
652
        mov     [esi + REG_RDTR], eax                   ; Clear the Receive Delay Timer Register
652
        mov     [esi + REG_RDTR], eax                   ; Clear the Receive Delay Timer Register
653
        mov     [esi + REG_RADV], eax                   ; Clear the Receive Interrupt Absolute Delay Timer
653
        mov     [esi + REG_RADV], eax                   ; Clear the Receive Interrupt Absolute Delay Timer
654
        mov     [esi + REG_RSRPD], eax                  ; Clear the Receive Small Packet Detect Interrupt
654
        mov     [esi + REG_RSRPD], eax                  ; Clear the Receive Small Packet Detect Interrupt
655
 
655
 
656
        mov     dword[esi + REG_IMS], 0x1F6DC           ; Enable interrupt types
656
        mov     dword[esi + REG_IMS], 0x1F6DC           ; Enable interrupt types
657
        mov     eax, [esi + REG_ICR]                    ; Clear pending interrupts
657
        mov     eax, [esi + REG_ICR]                    ; Clear pending interrupts
658
 
658
 
659
        mov     [ebx + device.mtu], 1514
659
        mov     [ebx + device.mtu], 1514
660
        call    link_status
660
        call    link_status
661
 
661
 
662
        xor     eax, eax
662
        xor     eax, eax
663
        ret
663
        ret
664
 
664
 
665
 
665
 
666
 
666
 
667
 
667
 
668
align 4
668
align 4
669
read_mac:
669
read_mac:
670
 
670
 
671
        DEBUGF  1,"Read MAC\n"
671
        DEBUGF  1,"Read MAC\n"
672
 
672
 
673
        mov     esi, [ebx + device.mmio_addr]
673
        mov     esi, [ebx + device.mmio_addr]
674
 
674
 
675
        mov     eax, [esi+0x5400]                       ; RAL
675
        mov     eax, [esi+0x5400]                       ; RAL
676
        test    eax, eax
676
        test    eax, eax
677
        jz      .try_eeprom
677
        jz      .try_eeprom
678
 
678
 
679
        mov     dword[ebx + device.mac], eax
679
        mov     dword[ebx + device.mac], eax
680
        mov     eax, [esi+0x5404]                       ; RAH
680
        mov     eax, [esi+0x5404]                       ; RAH
681
        mov     word[ebx + device.mac+4], ax
681
        mov     word[ebx + device.mac+4], ax
682
 
682
 
683
        jmp     .mac_ok
683
        jmp     .mac_ok
684
 
684
 
685
  .try_eeprom:
685
  .try_eeprom:
686
        mov     dword[esi+0x14], 0x00000001
686
        mov     dword[esi+0x14], 0x00000001
687
        mov     eax, [esi+0x14]
687
        mov     eax, [esi+0x14]
688
        shr     eax, 16
688
        shr     eax, 16
689
        mov     word[ebx + device.mac], ax
689
        mov     word[ebx + device.mac], ax
690
 
690
 
691
        mov     dword[esi+0x14], 0x00000101
691
        mov     dword[esi+0x14], 0x00000101
692
        mov     eax, [esi+0x14]
692
        mov     eax, [esi+0x14]
693
        shr     eax, 16
693
        shr     eax, 16
694
        mov     word[ebx + device.mac+2], ax
694
        mov     word[ebx + device.mac+2], ax
695
 
695
 
696
        mov     dword[esi+0x14], 0x00000201
696
        mov     dword[esi+0x14], 0x00000201
697
        mov     eax, [esi+0x14]
697
        mov     eax, [esi+0x14]
698
        shr     eax, 16
698
        shr     eax, 16
699
        mov     word[ebx + device.mac+4], ax
699
        mov     word[ebx + device.mac+4], ax
700
 
700
 
701
  .mac_ok:
701
  .mac_ok:
702
        DEBUGF  1,"MAC = %x-%x-%x-%x-%x-%x\n",\
702
        DEBUGF  1,"MAC = %x-%x-%x-%x-%x-%x\n",\
703
        [ebx + device.mac+0]:2,[ebx + device.mac+1]:2,[ebx + device.mac+2]:2,\
703
        [ebx + device.mac+0]:2,[ebx + device.mac+1]:2,[ebx + device.mac+2]:2,\
704
        [ebx + device.mac+3]:2,[ebx + device.mac+4]:2,[ebx + device.mac+5]:2
704
        [ebx + device.mac+3]:2,[ebx + device.mac+4]:2,[ebx + device.mac+5]:2
705
 
705
 
706
        ret
706
        ret
707
 
707
 
708
 
708
 
709
link_status:
709
link_status:
710
 
710
 
711
        DEBUGF  1,"Verifying link status\n"
711
        DEBUGF  1,"Verifying link status\n"
712
 
712
 
713
        xor     ecx, ecx                        ; ETH_LINK_DOWN
713
        xor     ecx, ecx                        ; ETH_LINK_DOWN
714
        mov     esi, [ebx + device.mmio_addr]
714
        mov     esi, [ebx + device.mmio_addr]
715
        mov     eax, [esi + REG_STATUS]
715
        mov     eax, [esi + REG_STATUS]
716
        test    eax, STATUS_LU
716
        test    eax, STATUS_LU
717
        jz      .ok
717
        jz      .ok
718
 
718
 
719
        test    eax, STATUS_FD
719
        test    eax, STATUS_FD
720
        jz      @f
720
        jz      @f
721
        or      cl, ETH_LINK_FD
721
        or      cl, ETH_LINK_FULL_DUPLEX
722
  @@:
722
  @@:
723
        shr     eax, STATUS_SPEED_SHIFT
723
        shr     eax, STATUS_SPEED_SHIFT
724
        and     al, 3
724
        and     al, 3
725
        test    al, al
725
        test    al, al
726
        jnz     @f
726
        jnz     @f
727
        or      cl, ETH_LINK_10M
727
        or      cl, ETH_LINK_SPEED_10M
728
        jmp     .ok
728
        jmp     .ok
729
  @@:
729
  @@:
730
        cmp     al, 1
730
        cmp     al, 1
731
        jne     @f
731
        jne     @f
732
        or      cl, ETH_LINK_100M
732
        or      cl, ETH_LINK_SPEED_100M
733
        jmp     .ok
733
        jmp     .ok
734
  @@:
734
  @@:
735
        or      cl, ETH_LINK_1G
735
        or      cl, ETH_LINK_SPEED_1G
736
;        jmp     .ok
736
;        jmp     .ok
737
 
737
 
738
  .ok:
738
  .ok:
739
        mov     [ebx + device.state], ecx
739
        mov     [ebx + device.state], ecx
740
        invoke  NetLinkChanged
740
        invoke  NetLinkChanged
741
        ret
741
        ret
742
 
742
 
743
 
743
 
744
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
744
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
745
;;                                         ;;
745
;;                                         ;;
746
;; Transmit                                ;;
746
;; Transmit                                ;;
747
;;                                         ;;
747
;;                                         ;;
748
;; In:  ebx = pointer to device structure  ;;
748
;; In:  ebx = pointer to device structure  ;;
749
;; Out: eax = 0 on success                 ;;
749
;; Out: eax = 0 on success                 ;;
750
;;                                         ;;
750
;;                                         ;;
751
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
751
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
752
align 16
752
align 16
753
proc transmit stdcall bufferptr
753
proc transmit stdcall bufferptr
754
 
754
 
755
        spin_lock_irqsave
755
        spin_lock_irqsave
756
 
756
 
757
        mov     esi, [bufferptr]
757
        mov     esi, [bufferptr]
758
        DEBUGF  1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [esi + NET_BUFF.length]
758
        DEBUGF  1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [esi + NET_BUFF.length]
759
        lea     eax, [esi + NET_BUFF.data]
759
        lea     eax, [esi + NET_BUFF.data]
760
        DEBUGF  1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
760
        DEBUGF  1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
761
        [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
761
        [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
762
        [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
762
        [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
763
        [eax+13]:2,[eax+12]:2
763
        [eax+13]:2,[eax+12]:2
764
 
764
 
765
        cmp     [esi + NET_BUFF.length], 1514
765
        cmp     [esi + NET_BUFF.length], 1514
766
        ja      .fail
766
        ja      .fail
767
        cmp     [esi + NET_BUFF.length], 60
767
        cmp     [esi + NET_BUFF.length], 60
768
        jb      .fail
768
        jb      .fail
769
 
769
 
770
; Program the descriptor (use legacy mode)
770
; Program the descriptor (use legacy mode)
771
        mov     edi, [ebx + device.cur_tx]
771
        mov     edi, [ebx + device.cur_tx]
772
        DEBUGF  1, "Using TX desc: %u\n", edi
772
        DEBUGF  1, "Using TX desc: %u\n", edi
773
        shl     edi, 4                                          ; edi = edi * sizeof.TDESC
773
        shl     edi, 4                                          ; edi = edi * sizeof.TDESC
774
        lea     edi, [ebx + device.tx_desc + edi]
774
        lea     edi, [ebx + device.tx_desc + edi]
775
        mov     eax, esi
775
        mov     eax, esi
776
        mov     dword[edi + TX_RING_SIZE*sizeof.TDESC], eax     ; Store the data location (for driver)
776
        mov     dword[edi + TX_RING_SIZE*sizeof.TDESC], eax     ; Store the data location (for driver)
777
        add     eax, [eax + NET_BUFF.offset]
777
        add     eax, [eax + NET_BUFF.offset]
778
        invoke  GetPhysAddr
778
        invoke  GetPhysAddr
779
        mov     [edi + TDESC.addr_l], eax                       ; Data location (for hardware)
779
        mov     [edi + TDESC.addr_l], eax                       ; Data location (for hardware)
780
        mov     [edi + TDESC.addr_h], 0
780
        mov     [edi + TDESC.addr_h], 0
781
 
781
 
782
        mov     ecx, [esi + NET_BUFF.length]
782
        mov     ecx, [esi + NET_BUFF.length]
783
        or      ecx, TXDESC_EOP + TXDESC_IFCS + TXDESC_RS
783
        or      ecx, TXDESC_EOP + TXDESC_IFCS + TXDESC_RS
784
        mov     [edi + TDESC.length_cso_cmd], ecx
784
        mov     [edi + TDESC.length_cso_cmd], ecx
785
        mov     [edi + TDESC.status], 0
785
        mov     [edi + TDESC.status], 0
786
 
786
 
787
; Tell i8254x wich descriptor(s) we programmed, by moving the tail
787
; Tell i8254x wich descriptor(s) we programmed, by moving the tail
788
        mov     edi, [ebx + device.mmio_addr]
788
        mov     edi, [ebx + device.mmio_addr]
789
        mov     eax, [ebx + device.cur_tx]
789
        mov     eax, [ebx + device.cur_tx]
790
        inc     eax
790
        inc     eax
791
        and     eax, TX_RING_SIZE-1
791
        and     eax, TX_RING_SIZE-1
792
        mov     [ebx + device.cur_tx], eax
792
        mov     [ebx + device.cur_tx], eax
793
        mov     dword[edi + REG_TDT], eax                        ; TDT - Transmit Descriptor Tail
793
        mov     dword[edi + REG_TDT], eax                        ; TDT - Transmit Descriptor Tail
794
 
794
 
795
; Update stats
795
; Update stats
796
        inc     [ebx + device.packets_tx]
796
        inc     [ebx + device.packets_tx]
797
        mov     eax, [esi + NET_BUFF.length]
797
        mov     eax, [esi + NET_BUFF.length]
798
        add     dword[ebx + device.bytes_tx], eax
798
        add     dword[ebx + device.bytes_tx], eax
799
        adc     dword[ebx + device.bytes_tx + 4], 0
799
        adc     dword[ebx + device.bytes_tx + 4], 0
800
 
800
 
801
        call    clean_tx
801
        call    clean_tx
802
 
802
 
803
        spin_unlock_irqrestore
803
        spin_unlock_irqrestore
804
        xor     eax, eax
804
        xor     eax, eax
805
        ret
805
        ret
806
 
806
 
807
  .fail:
807
  .fail:
808
        call    clean_tx
808
        call    clean_tx
809
 
809
 
810
        DEBUGF  2,"Send failed\n"
810
        DEBUGF  2,"Send failed\n"
811
        invoke  NetFree, [bufferptr]
811
        invoke  NetFree, [bufferptr]
812
        spin_unlock_irqrestore
812
        spin_unlock_irqrestore
813
        or      eax, -1
813
        or      eax, -1
814
        ret
814
        ret
815
 
815
 
816
endp
816
endp
817
 
817
 
818
 
818
 
819
;;;;;;;;;;;;;;;;;;;;;;;
819
;;;;;;;;;;;;;;;;;;;;;;;
820
;;                   ;;
820
;;                   ;;
821
;; Interrupt handler ;;
821
;; Interrupt handler ;;
822
;;                   ;;
822
;;                   ;;
823
;;;;;;;;;;;;;;;;;;;;;;;
823
;;;;;;;;;;;;;;;;;;;;;;;
824
align 16
824
align 16
825
int_handler:
825
int_handler:
826
 
826
 
827
        push    ebx esi edi
827
        push    ebx esi edi
828
 
828
 
829
        mov     ebx, [esp+4*4]
829
        mov     ebx, [esp+4*4]
830
        DEBUGF  1,"INT for 0x%x\n", ebx
830
        DEBUGF  1,"INT for 0x%x\n", ebx
831
 
831
 
832
; TODO? if we are paranoid, we can check that the value from ebx is present in the current device_list
832
; TODO? if we are paranoid, we can check that the value from ebx is present in the current device_list
833
 
833
 
834
        mov     edi, [ebx + device.mmio_addr]
834
        mov     edi, [ebx + device.mmio_addr]
835
        mov     eax, [edi + REG_ICR]
835
        mov     eax, [edi + REG_ICR]
836
        cmp     eax, 0xffffffff         ; if so, hardware is no longer present
836
        cmp     eax, 0xffffffff         ; if so, hardware is no longer present
837
        je      .nothing                ;
837
        je      .nothing                ;
838
        test    eax, eax
838
        test    eax, eax
839
        jz      .nothing
839
        jz      .nothing
840
 
840
 
841
        DEBUGF  1,"Status: %x\n", eax
841
        DEBUGF  1,"Status: %x\n", eax
842
 
842
 
843
;---------
843
;---------
844
; RX done?
844
; RX done?
845
 
845
 
846
        test    eax, ICR_RXDMT0 + ICR_RXT0
846
        test    eax, ICR_RXDMT0 + ICR_RXT0
847
        jz      .no_rx
847
        jz      .no_rx
848
 
848
 
849
        push    eax ebx
849
        push    eax ebx
850
  .retaddr:
850
  .retaddr:
851
        pop     ebx eax
851
        pop     ebx eax
852
; Get last descriptor addr
852
; Get last descriptor addr
853
        mov     esi, [ebx + device.cur_rx]
853
        mov     esi, [ebx + device.cur_rx]
854
        shl     esi, 4                                  ; esi = esi * sizeof.RDESC
854
        shl     esi, 4                                  ; esi = esi * sizeof.RDESC
855
        lea     esi, [ebx + device.rx_desc + esi]
855
        lea     esi, [ebx + device.rx_desc + esi]
856
        cmp     byte[esi + RDESC.status_h], 0           ; Check status field
856
        cmp     byte[esi + RDESC.status_h], 0           ; Check status field
857
        je      .no_rx
857
        je      .no_rx
858
 
858
 
859
        push    eax ebx
859
        push    eax ebx
860
        push    .retaddr
860
        push    .retaddr
861
        movzx   ecx, word[esi + 8]                      ; Get the packet length
861
        movzx   ecx, word[esi + 8]                      ; Get the packet length
862
        DEBUGF  1,"got %u bytes\n", ecx
862
        DEBUGF  1,"got %u bytes\n", ecx
863
        mov     eax, [esi + RX_RING_SIZE*sizeof.RDESC]  ; Get packet pointer
863
        mov     eax, [esi + RX_RING_SIZE*sizeof.RDESC]  ; Get packet pointer
864
        push    eax
864
        push    eax
865
        mov     [eax + NET_BUFF.length], ecx
865
        mov     [eax + NET_BUFF.length], ecx
866
        mov     [eax + NET_BUFF.device], ebx
866
        mov     [eax + NET_BUFF.device], ebx
867
        mov     [eax + NET_BUFF.offset], NET_BUFF.data
867
        mov     [eax + NET_BUFF.offset], NET_BUFF.data
868
 
868
 
869
; Update stats
869
; Update stats
870
        add     dword[ebx + device.bytes_rx], ecx
870
        add     dword[ebx + device.bytes_rx], ecx
871
        adc     dword[ebx + device.bytes_rx + 4], 0
871
        adc     dword[ebx + device.bytes_rx + 4], 0
872
        inc     [ebx + device.packets_rx]
872
        inc     [ebx + device.packets_rx]
873
 
873
 
874
; Allocate new descriptor
874
; Allocate new descriptor
875
        push    esi
875
        push    esi
876
        invoke  NetAlloc, MAX_PKT_SIZE+NET_BUFF.data
876
        invoke  NetAlloc, MAX_PKT_SIZE+NET_BUFF.data
877
        pop     esi
877
        pop     esi
878
        test    eax, eax
878
        test    eax, eax
879
        jz      .out_of_mem
879
        jz      .out_of_mem
880
        mov     dword[esi + RX_RING_SIZE*sizeof.RDESC], eax
880
        mov     dword[esi + RX_RING_SIZE*sizeof.RDESC], eax
881
        invoke  GetPhysAddr
881
        invoke  GetPhysAddr
882
        add     eax, NET_BUFF.data
882
        add     eax, NET_BUFF.data
883
        mov     [esi + RDESC.addr_l], eax
883
        mov     [esi + RDESC.addr_l], eax
884
        mov     [esi + RDESC.status_l], 0
884
        mov     [esi + RDESC.status_l], 0
885
        mov     [esi + RDESC.status_h], 0
885
        mov     [esi + RDESC.status_h], 0
886
 
886
 
887
; Move the receive descriptor tail
887
; Move the receive descriptor tail
888
        mov     esi, [ebx + device.mmio_addr]
888
        mov     esi, [ebx + device.mmio_addr]
889
        mov     eax, [ebx + device.cur_rx]
889
        mov     eax, [ebx + device.cur_rx]
890
        mov     [esi + REG_RDT], eax
890
        mov     [esi + REG_RDT], eax
891
 
891
 
892
; Move to next rx desc
892
; Move to next rx desc
893
        inc     [ebx + device.cur_rx]
893
        inc     [ebx + device.cur_rx]
894
        and     [ebx + device.cur_rx], RX_RING_SIZE-1
894
        and     [ebx + device.cur_rx], RX_RING_SIZE-1
895
 
895
 
896
        jmp     [EthInput]
896
        jmp     [EthInput]
897
 
897
 
898
  .out_of_mem:
898
  .out_of_mem:
899
        DEBUGF  2,"Out of memory!\n"
899
        DEBUGF  2,"Out of memory!\n"
900
 
900
 
901
; Move to next rx desc
901
; Move to next rx desc
902
        inc     [ebx + device.cur_rx]
902
        inc     [ebx + device.cur_rx]
903
        and     [ebx + device.cur_rx], RX_RING_SIZE-1
903
        and     [ebx + device.cur_rx], RX_RING_SIZE-1
904
 
904
 
905
        jmp     [EthInput]
905
        jmp     [EthInput]
906
  .no_rx:
906
  .no_rx:
907
 
907
 
908
;--------------
908
;--------------
909
; Link Changed?
909
; Link Changed?
910
 
910
 
911
        test    eax, ICR_LSC
911
        test    eax, ICR_LSC
912
        jz      .no_link
912
        jz      .no_link
913
 
913
 
914
        DEBUGF  2,"Link Changed\n"
914
        DEBUGF  2,"Link Changed\n"
915
 
915
 
916
        call    link_status
916
        call    link_status
917
 
917
 
918
  .no_link:
918
  .no_link:
919
 
919
 
920
;---------------
920
;---------------
921
; Transmit done?
921
; Transmit done?
922
 
922
 
923
        test    eax, ICR_TXDW
923
        test    eax, ICR_TXDW
924
        jz      .no_tx
924
        jz      .no_tx
925
 
925
 
926
        DEBUGF  1,"Transmit done\n"
926
        DEBUGF  1,"Transmit done\n"
927
 
927
 
928
;        call    clean_tx
928
;        call    clean_tx
929
 
929
 
930
  .no_tx:
930
  .no_tx:
931
 
931
 
932
        pop     edi esi ebx
932
        pop     edi esi ebx
933
        xor     eax, eax
933
        xor     eax, eax
934
        inc     eax
934
        inc     eax
935
        ret
935
        ret
936
 
936
 
937
  .nothing:
937
  .nothing:
938
        pop     edi esi ebx
938
        pop     edi esi ebx
939
        xor     eax, eax
939
        xor     eax, eax
940
 
940
 
941
        ret
941
        ret
942
 
942
 
943
 
943
 
944
 
944
 
945
clean_tx:
945
clean_tx:
946
 
946
 
947
  .txdesc_loop:
947
  .txdesc_loop:
948
        mov     edi, [ebx + device.last_tx]
948
        mov     edi, [ebx + device.last_tx]
949
        shl     edi, 4                                  ; edi = edi * sizeof.TDESC
949
        shl     edi, 4                                  ; edi = edi * sizeof.TDESC
950
        lea     edi, [ebx + device.tx_desc + edi]
950
        lea     edi, [ebx + device.tx_desc + edi]
951
        test    [edi + TDESC.status], TXDESC_DD         ; Descriptor done?
951
        test    [edi + TDESC.status], TXDESC_DD         ; Descriptor done?
952
        jz      .no_tx
952
        jz      .no_tx
953
        cmp     dword[edi + TX_RING_SIZE*sizeof.TDESC], 0
953
        cmp     dword[edi + TX_RING_SIZE*sizeof.TDESC], 0
954
        je      .no_tx
954
        je      .no_tx
955
 
955
 
956
        DEBUGF  1,"Cleaning up TX desc: 0x%x\n", edi
956
        DEBUGF  1,"Cleaning up TX desc: 0x%x\n", edi
957
 
957
 
958
        push    ebx
958
        push    ebx
959
        push    dword[edi + TX_RING_SIZE*sizeof.TDESC]
959
        push    dword[edi + TX_RING_SIZE*sizeof.TDESC]
960
        mov     dword[edi + TX_RING_SIZE*sizeof.TDESC], 0
960
        mov     dword[edi + TX_RING_SIZE*sizeof.TDESC], 0
961
        invoke  NetFree
961
        invoke  NetFree
962
        pop     ebx
962
        pop     ebx
963
 
963
 
964
        inc     [ebx + device.last_tx]
964
        inc     [ebx + device.last_tx]
965
        and     [ebx + device.last_tx], TX_RING_SIZE-1
965
        and     [ebx + device.last_tx], TX_RING_SIZE-1
966
        jmp     .txdesc_loop
966
        jmp     .txdesc_loop
967
 
967
 
968
  .no_tx:
968
  .no_tx:
969
 
969
 
970
        ret
970
        ret
971
 
971
 
972
 
972
 
973
 
973
 
974
 
974
 
975
; End of code
975
; End of code
976
 
976
 
977
data fixups
977
data fixups
978
end data
978
end data
979
 
979
 
980
include '../peimport.inc'
980
include '../peimport.inc'
981
 
981
 
982
include_debug_strings
982
include_debug_strings
983
my_service      db 'I8254X', 0          ; max 16 chars include zero
983
my_service      db 'I8254X', 0          ; max 16 chars include zero
984
 
984
 
985
align 4
985
align 4
986
devices         dd 0
986
devices         dd 0
987
device_list     rd MAX_DEVICES          ; This list contains all pointers to device structures the driver is handling
987
device_list     rd MAX_DEVICES          ; This list contains all pointers to device structures the driver is handling