Subversion Repositories Kolibri OS

Rev

Rev 1541 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1196 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                  ;;
1519 hidnplayr 3
;; Copyright (C) KolibriOS team 2004-2010. All rights reserved.     ;;
1196 hidnplayr 4
;; Distributed under terms of the GNU General Public License        ;;
5
;;                                                                  ;;
1564 hidnplayr 6
;;  PCnet driver for KolibriOS                                      ;;
1519 hidnplayr 7
;;                                                                  ;;
1564 hidnplayr 8
;;  By hidnplayr & clevermouse                                      ;;
9
;;                                                                  ;;
1519 hidnplayr 10
;;  Based on the PCnet32 driver for MenuetOS, by Jarek Pelczar      ;;
11
;;                                                                  ;;
1196 hidnplayr 12
;;          GNU GENERAL PUBLIC LICENSE                              ;;
13
;;             Version 2, June 1991                                 ;;
14
;;                                                                  ;;
15
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
16
 
1564 hidnplayr 17
; $Revision: 1564 $
18
 
1196 hidnplayr 19
format MS COFF
20
 
21
	API_VERSION		equ 0x01000100
22
 
23
	DEBUG			equ 1
24
	__DEBUG__		equ 1
25
	__DEBUG_LEVEL__ 	equ 1
26
 
1564 hidnplayr 27
	MAX_DEVICES equ 4
28
	MAX_ETH_FRAME_SIZE equ 1514
1196 hidnplayr 29
 
30
include 'proc32.inc'
31
include 'imports.inc'
32
include 'fdo.inc'
1492 hidnplayr 33
include 'netdrv.inc'
1196 hidnplayr 34
 
1564 hidnplayr 35
 
1196 hidnplayr 36
public START
37
public service_proc
38
public version
39
 
40
 
1492 hidnplayr 41
virtual at ebx
1196 hidnplayr 42
 
1492 hidnplayr 43
	device:
1196 hidnplayr 44
 
1492 hidnplayr 45
	ETH_DEVICE
46
 
1564 hidnplayr 47
; device specific
1196 hidnplayr 48
 
1564 hidnplayr 49
      .private:
50
      .mode_		dw ?
51
      .tlen_rlen	dw ?
52
      .phys_addr	dp ?
53
      .reserved 	dw ?
54
      .filter		dq ?
55
      .rx_ring_phys	dd ?
56
      .tx_ring_phys	dd ?
1196 hidnplayr 57
 
1564 hidnplayr 58
      .cur_rx		db ?
59
      .cur_tx		db ?
60
      .dirty_rx 	dd ?
61
      .dirty_tx 	dd ?
62
      .tx_full		db ?
63
      .options		dd ?
64
      .full_duplex	db ?
65
      .chip_version	dd ?
66
      .mii		db ?
67
      .ltint		db ?
68
      .dxsuflo		db ?
69
      .fset		db ?
70
      .fdx		db ?
1492 hidnplayr 71
 
1564 hidnplayr 72
      .rx_buffer	dd ?
73
      .tx_buffer	dd ?
1492 hidnplayr 74
 
1564 hidnplayr 75
      .io_addr		dd ?
76
      .irq_line 	db ?
77
      .pci_bus		db ?
78
      .pci_dev		db ?
1541 hidnplayr 79
 
80
 
1564 hidnplayr 81
      .access_read_csr		dd ?
82
      .access_write_csr 	dd ?
83
      .access_read_bcr		dd ?
84
      .access_write_bcr 	dd ?
85
      .access_read_rap		dd ?
86
      .access_write_rap 	dd ?
87
      .access_reset		dd ?
1196 hidnplayr 88
 
1564 hidnplayr 89
      device_size	= $ - device
1196 hidnplayr 90
 
91
end virtual
92
 
1564 hidnplayr 93
struc buf_head {
94
	.base		dd ?
95
	.length 	dw ?
96
	.status 	dw ?
97
	.msg_length	dw ?
98
	.misc		dw ?
99
	.reserved	dd ?
1196 hidnplayr 100
 
1564 hidnplayr 101
	.size:
1196 hidnplayr 102
}
103
 
104
virtual at 0
1564 hidnplayr 105
 buf_head buf_head
1196 hidnplayr 106
end virtual
107
 
1564 hidnplayr 108
	PCNET_PORT_AUI		      equ 0x00
109
	PCNET_PORT_10BT 	      equ 0x01
110
	PCNET_PORT_GPSI 	      equ 0x02
111
	PCNET_PORT_MII		      equ 0x03
112
	PCNET_PORT_PORTSEL	      equ 0x03
113
	PCNET_PORT_ASEL 	      equ 0x04
114
	PCNET_PORT_100		      equ 0x40
115
	PCNET_PORT_FD		      equ 0x80
1196 hidnplayr 116
 
1564 hidnplayr 117
	PCNET_DMA_MASK		      equ 0xffffffff
1196 hidnplayr 118
 
1564 hidnplayr 119
	PCNET_LOG_TX_BUFFERS	      equ 2
120
	PCNET_LOG_RX_BUFFERS	      equ 2
1196 hidnplayr 121
 
1564 hidnplayr 122
	PCNET_TX_RING_SIZE	      equ 4
123
	PCNET_TX_RING_MOD_MASK	      equ (PCNET_TX_RING_SIZE-1)
124
	PCNET_TX_RING_LEN_BITS	      equ (PCNET_LOG_TX_BUFFERS shl 12)
1196 hidnplayr 125
 
1564 hidnplayr 126
	PCNET_RX_RING_SIZE	      equ 4
127
	PCNET_RX_RING_MOD_MASK	      equ (PCNET_RX_RING_SIZE-1)
128
	PCNET_RX_RING_LEN_BITS	      equ (PCNET_LOG_RX_BUFFERS shl 4)
1196 hidnplayr 129
 
1564 hidnplayr 130
	PCNET_PKT_BUF_SZ	      equ 1544
131
	PCNET_PKT_BUF_SZ_NEG	      equ 0xf9f8
1196 hidnplayr 132
 
1564 hidnplayr 133
	PCNET_WIO_RDP		      equ 0x10
134
	PCNET_WIO_RAP		      equ 0x12
135
	PCNET_WIO_RESET 	      equ 0x14
136
	PCNET_WIO_BDP		      equ 0x16
137
	PCNET_DWIO_RDP		      equ 0x10
138
	PCNET_DWIO_RAP		      equ 0x14
139
	PCNET_DWIO_RESET	      equ 0x18
140
	PCNET_DWIO_BDP		      equ 0x1C
141
	PCNET_TOTAL_SIZE	      equ 0x20
142
 
1196 hidnplayr 143
; CSR registers
144
 
1564 hidnplayr 145
	PCNET_CSR_CSR		      equ 0x00
146
	PCNET_CSR_IAB0		      equ 0x01
147
	PCNET_CSR_IAB1		      equ 0x02
148
	PCNET_CSR_IMR		      equ 0x03
149
	PCNET_CSR_TFEAT 	      equ 0x04
150
	PCNET_CSR_EXTCTL1	      equ 0x05
151
	PCNET_CSR_DTBLLEN	      equ 0x06
152
	PCNET_CSR_EXTCTL2	      equ 0x07
153
	PCNET_CSR_MAR0		      equ 0x08
154
	PCNET_CSR_MAR1		      equ 0x09
155
	PCNET_CSR_MAR2		      equ 0x0A
156
	PCNET_CSR_MAR3		      equ 0x0B
157
	PCNET_CSR_PAR0		      equ 0x0C
158
	PCNET_CSR_PAR1		      equ 0x0D
159
	PCNET_CSR_PAR2		      equ 0x0E
160
	PCNET_CSR_MODE		      equ 0x0F
161
	PCNET_CSR_RXADDR0	      equ 0x18
162
	PCNET_CSR_RXADDR1	      equ 0x19
163
	PCNET_CSR_TXADDR0	      equ 0x1E
164
	PCNET_CSR_TXADDR1	      equ 0x1F
165
	PCNET_CSR_TXPOLL	      equ 0x2F
166
	PCNET_CSR_RXPOLL	      equ 0x31
167
	PCNET_CSR_RXRINGLEN	      equ 0x4C
168
	PCNET_CSR_TXRINGLEN	      equ 0x4E
169
	PCNET_CSR_DMACTL	      equ 0x50
170
	PCNET_CSR_BUSTIMER	      equ 0x52
171
	PCNET_CSR_MEMERRTIMEO	      equ 0x64
172
	PCNET_CSR_ONNOWMISC	      equ 0x74
173
	PCNET_CSR_ADVFEAT	      equ 0x7A
174
	PCNET_CSR_MACCFG	      equ 0x7D
175
	PCNET_CSR_CHIPID0	      equ 0x58
176
	PCNET_CSR_CHIPID1	      equ 0x59
1196 hidnplayr 177
 
178
; Control and Status Register (CSR0)
179
 
1564 hidnplayr 180
	PCNET_CSR_INIT		      equ 1 shl 0
181
	PCNET_CSR_START 	      equ 1 shl 1
182
	PCNET_CSR_STOP		      equ 1 shl 2
183
	PCNET_CSR_TX		      equ 1 shl 3
184
	PCNET_CSR_TXON		      equ 1 shl 4
185
	PCNET_CSR_RXON		      equ 1 shl 5
186
	PCNET_CSR_INTEN 	      equ 1 shl 6
187
	PCNET_CSR_INTR		      equ 1 shl 7
188
	PCNET_CSR_IDONE 	      equ 1 shl 8
189
	PCNET_CSR_TINT		      equ 1 shl 9
190
	PCNET_CSR_RINT		      equ 1 shl 10
191
	PCNET_CSR_MERR		      equ 1 shl 11
192
	PCNET_CSR_MISS		      equ 1 shl 12
193
	PCNET_CSR_CERR		      equ 1 shl 13
1196 hidnplayr 194
 
195
; Interrupt masks and deferral control (CSR3)
196
 
1564 hidnplayr 197
	PCNET_IMR_BSWAP 	      equ 0x0004
198
	PCNET_IMR_ENMBA 	      equ 0x0008  ; enable modified backoff alg
199
	PCNET_IMR_DXMT2PD	      equ 0x0010
200
	PCNET_IMR_LAPPEN	      equ 0x0020  ; lookahead packet processing enb
201
	PCNET_IMR_DXSUFLO	      equ 0x0040  ; disable TX stop on underflow
202
	PCNET_IMR_IDONE 	      equ 0x0100
203
	PCNET_IMR_TINT		      equ 0x0200
204
	PCNET_IMR_RINT		      equ 0x0400
205
	PCNET_IMR_MERR		      equ 0x0800
206
	PCNET_IMR_MISS		      equ 0x1000
1196 hidnplayr 207
 
1564 hidnplayr 208
	PCNET_IMR		      equ PCNET_IMR_TINT+PCNET_IMR_RINT+PCNET_IMR_IDONE+PCNET_IMR_MERR+PCNET_IMR_MISS
1196 hidnplayr 209
 
210
; Test and features control (CSR4)
211
 
1564 hidnplayr 212
	PCNET_TFEAT_TXSTRTMASK	      equ 0x0004
213
	PCNET_TFEAT_TXSTRT	      equ 0x0008
214
	PCNET_TFEAT_RXCCOFLOWM	      equ 0x0010  ; Rx collision counter oflow
215
	PCNET_TFEAT_RXCCOFLOW	      equ 0x0020
216
	PCNET_TFEAT_UINT	      equ 0x0040
217
	PCNET_TFEAT_UINTREQ	      equ 0x0080
218
	PCNET_TFEAT_MISSOFLOWM	      equ 0x0100
219
	PCNET_TFEAT_MISSOFLOW	      equ 0x0200
220
	PCNET_TFEAT_STRIP_FCS	      equ 0x0400
221
	PCNET_TFEAT_PAD_TX	      equ 0x0800
222
	PCNET_TFEAT_TXDPOLL	      equ 0x1000
223
	PCNET_TFEAT_DMAPLUS	      equ 0x4000
1196 hidnplayr 224
 
225
; Extended control and interrupt 1 (CSR5)
226
 
1564 hidnplayr 227
	PCNET_EXTCTL1_SPND	      equ 0x0001  ; suspend
228
	PCNET_EXTCTL1_MPMODE	      equ 0x0002  ; magic packet mode
229
	PCNET_EXTCTL1_MPENB	      equ 0x0004  ; magic packet enable
230
	PCNET_EXTCTL1_MPINTEN	      equ 0x0008  ; magic packet interrupt enable
231
	PCNET_EXTCTL1_MPINT	      equ 0x0010  ; magic packet interrupt
232
	PCNET_EXTCTL1_MPPLBA	      equ 0x0020  ; magic packet phys. logical bcast
233
	PCNET_EXTCTL1_EXDEFEN	      equ 0x0040  ; excessive deferral interrupt enb.
234
	PCNET_EXTCTL1_EXDEF	      equ 0x0080  ; excessive deferral interrupt
235
	PCNET_EXTCTL1_SINTEN	      equ 0x0400  ; system interrupt enable
236
	PCNET_EXTCTL1_SINT	      equ 0x0800  ; system interrupt
237
	PCNET_EXTCTL1_LTINTEN	      equ 0x4000  ; last TX interrupt enb
238
	PCNET_EXTCTL1_TXOKINTD	      equ 0x8000  ; TX OK interrupt disable
1196 hidnplayr 239
 
240
; RX/TX descriptor len (CSR6)
241
 
1564 hidnplayr 242
	PCNET_DTBLLEN_RLEN	      equ 0x0F00
243
	PCNET_DTBLLEN_TLEN	      equ 0xF000
1196 hidnplayr 244
 
245
; Extended control and interrupt 2 (CSR7)
246
 
1564 hidnplayr 247
	PCNET_EXTCTL2_MIIPDTINTE      equ 0x0001
248
	PCNET_EXTCTL2_MIIPDTINT       equ 0x0002
249
	PCNET_EXTCTL2_MCCIINTE	      equ 0x0004
250
	PCNET_EXTCTL2_MCCIINT	      equ 0x0008
251
	PCNET_EXTCTL2_MCCINTE	      equ 0x0010
252
	PCNET_EXTCTL2_MCCINT	      equ 0x0020
253
	PCNET_EXTCTL2_MAPINTE	      equ 0x0040
254
	PCNET_EXTCTL2_MAPINT	      equ 0x0080
255
	PCNET_EXTCTL2_MREINTE	      equ 0x0100
256
	PCNET_EXTCTL2_MREINT	      equ 0x0200
257
	PCNET_EXTCTL2_STINTE	      equ 0x0400
258
	PCNET_EXTCTL2_STINT	      equ 0x0800
259
	PCNET_EXTCTL2_RXDPOLL	      equ 0x1000
260
	PCNET_EXTCTL2_RDMD	      equ 0x2000
261
	PCNET_EXTCTL2_RXFRTG	      equ 0x4000
262
	PCNET_EXTCTL2_FASTSPNDE       equ 0x8000
1196 hidnplayr 263
 
264
; Mode (CSR15)
265
 
1564 hidnplayr 266
	PCNET_MODE_RXD		      equ 0x0001  ; RX disable
267
	PCNET_MODE_TXD		      equ 0x0002  ; TX disable
268
	PCNET_MODE_LOOP 	      equ 0x0004  ; loopback enable
269
	PCNET_MODE_TXCRCD	      equ 0x0008
270
	PCNET_MODE_FORCECOLL	      equ 0x0010
271
	PCNET_MODE_RETRYD	      equ 0x0020
272
	PCNET_MODE_INTLOOP	      equ 0x0040
273
	PCNET_MODE_PORTSEL	      equ 0x0180
274
	PCNET_MODE_RXVPAD	      equ 0x2000
275
	PCNET_MODE_RXNOBROAD	      equ 0x4000
276
	PCNET_MODE_PROMISC	      equ 0x8000
1196 hidnplayr 277
 
278
; BCR (Bus Control Registers)
279
 
1564 hidnplayr 280
	PCNET_BCR_MMRA		      equ 0x00	  ; Master Mode Read Active
281
	PCNET_BCR_MMW		      equ 0x01	  ; Master Mode Write Active
282
	PCNET_BCR_MISCCFG	      equ 0x02
283
	PCNET_BCR_LED0		      equ 0x04
284
	PCNET_BCR_LED1		      equ 0x05
285
	PCNET_BCR_LED2		      equ 0x06
286
	PCNET_BCR_LED3		      equ 0x07
287
	PCNET_BCR_DUPLEX	      equ 0x09
288
	PCNET_BCR_BUSCTL	      equ 0x12
289
	PCNET_BCR_EECTL 	      equ 0x13
290
	PCNET_BCR_SSTYLE	      equ 0x14
291
	PCNET_BCR_PCILAT	      equ 0x16
292
	PCNET_BCR_PCISUBVENID	      equ 0x17
293
	PCNET_BCR_PCISUBSYSID	      equ 0x18
294
	PCNET_BCR_SRAMSIZE	      equ 0x19
295
	PCNET_BCR_SRAMBOUND	      equ 0x1A
296
	PCNET_BCR_SRAMCTL	      equ 0x1B
297
	PCNET_BCR_MIICTL	      equ 0x20
298
	PCNET_BCR_MIIADDR	      equ 0x21
299
	PCNET_BCR_MIIDATA	      equ 0x22
300
	PCNET_BCR_PCIVENID	      equ 0x23
301
	PCNET_BCR_PCIPCAP	      equ 0x24
302
	PCNET_BCR_DATA0 	      equ 0x25
303
	PCNET_BCR_DATA1 	      equ 0x26
304
	PCNET_BCR_DATA2 	      equ 0x27
305
	PCNET_BCR_DATA3 	      equ 0x28
306
	PCNET_BCR_DATA4 	      equ 0x29
307
	PCNET_BCR_DATA5 	      equ 0x2A
308
	PCNET_BCR_DATA6 	      equ 0x2B
309
	PCNET_BCR_DATA7 	      equ 0x2C
310
	PCNET_BCR_ONNOWPAT0	      equ 0x2D
311
	PCNET_BCR_ONNOWPAT1	      equ 0x2E
312
	PCNET_BCR_ONNOWPAT2	      equ 0x2F
313
	PCNET_BCR_PHYSEL	      equ 0x31
1196 hidnplayr 314
 
315
; RX status register
316
 
1564 hidnplayr 317
	PCNET_RXSTAT_BPE	      equ 0x0080  ; bus parity error
318
	PCNET_RXSTAT_ENP	      equ 0x0100  ; end of packet
319
	PCNET_RXSTAT_STP	      equ 0x0200  ; start of packet
320
	PCNET_RXSTAT_BUFF	      equ 0x0400  ; buffer error
321
	PCNET_RXSTAT_CRC	      equ 0x0800  ; CRC error
322
	PCNET_RXSTAT_OFLOW	      equ 0x1000  ; rx overrun
323
	PCNET_RXSTAT_FRAM	      equ 0x2000  ; framing error
324
	PCNET_RXSTAT_ERR	      equ 0x4000  ; error summary
325
	PCNET_RXSTAT_OWN	      equ 0x8000
1196 hidnplayr 326
 
327
; TX status register
328
 
1564 hidnplayr 329
	PCNET_TXSTAT_TRC	      equ 0x0000000F	  ; transmit retries
330
	PCNET_TXSTAT_RTRY	      equ 0x04000000	  ; retry
331
	PCNET_TXSTAT_LCAR	      equ 0x08000000	  ; lost carrier
332
	PCNET_TXSTAT_LCOL	      equ 0x10000000	  ; late collision
333
	PCNET_TXSTAT_EXDEF	      equ 0x20000000	  ; excessive deferrals
334
	PCNET_TXSTAT_UFLOW	      equ 0x40000000	  ; transmit underrun
335
	PCNET_TXSTAT_BUFF	      equ 0x80000000	  ; buffer error
1196 hidnplayr 336
 
1564 hidnplayr 337
	PCNET_TXCTL_OWN 	      equ 0x80000000
338
	PCNET_TXCTL_ERR 	      equ 0x40000000	  ; error summary
339
	PCNET_TXCTL_ADD_FCS	      equ 0x20000000	  ; add FCS to pkt
340
	PCNET_TXCTL_MORE_LTINT	      equ 0x10000000
341
	PCNET_TXCTL_ONE 	      equ 0x08000000
342
	PCNET_TXCTL_DEF 	      equ 0x04000000
343
	PCNET_TXCTL_STP 	      equ 0x02000000
344
	PCNET_TXCTL_ENP 	      equ 0x01000000
345
	PCNET_TXCTL_BPE 	      equ 0x00800000
346
	PCNET_TXCTL_MBO 	      equ 0x0000F000
347
	PCNET_TXCTL_BUFSZ	      equ 0x00000FFF
1196 hidnplayr 348
 
349
 
350
 
1564 hidnplayr 351
 
1196 hidnplayr 352
section '.flat' code readable align 16
353
 
354
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
355
;;                        ;;
356
;; proc START             ;;
357
;;                        ;;
358
;; (standard driver proc) ;;
359
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
360
 
361
proc START stdcall, state:dword
362
 
363
	cmp [state], 1
364
	jne .exit
365
 
366
  .entry:
367
 
1564 hidnplayr 368
	DEBUGF 1,"Loading PCnet driver\n"
1196 hidnplayr 369
	stdcall RegService, my_service, service_proc
370
	ret
371
 
372
  .fail:
373
  .exit:
374
	xor eax, eax
375
	ret
376
 
377
endp
378
 
379
 
380
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
381
;;                        ;;
382
;; proc SERVICE_PROC      ;;
383
;;                        ;;
384
;; (standard driver proc) ;;
385
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
386
 
387
align 4
388
proc service_proc stdcall, ioctl:dword
389
 
390
	mov	edx, [ioctl]
1492 hidnplayr 391
	mov	eax, [IOCTL.io_code]
1196 hidnplayr 392
 
393
;------------------------------------------------------
394
 
395
	cmp	eax, 0 ;SRV_GETVERSION
396
	jne	@F
397
 
1492 hidnplayr 398
	cmp	[IOCTL.out_size], 4
1196 hidnplayr 399
	jl	.fail
1492 hidnplayr 400
	mov	eax, [IOCTL.output]
1196 hidnplayr 401
	mov	[eax], dword API_VERSION
402
 
403
	xor	eax, eax
404
	ret
405
 
406
;------------------------------------------------------
407
  @@:
408
	cmp	eax, 1 ;SRV_HOOK
409
	jne	.fail
410
 
1564 hidnplayr 411
	cmp	[IOCTL.inp_size], 3		  ; Data input must be at least 3 bytes
1196 hidnplayr 412
	jl	.fail
413
 
1492 hidnplayr 414
	mov	eax, [IOCTL.input]
1196 hidnplayr 415
	cmp	byte [eax], 1				; 1 means device number and bus number (pci) are given
416
	jne	.fail					; other types arent supported for this card yet
417
 
418
; check if the device is already listed
419
 
1519 hidnplayr 420
	mov	ecx, [devices]
1196 hidnplayr 421
	test	ecx, ecx
422
	jz	.firstdevice
1492 hidnplayr 423
 
1519 hidnplayr 424
	mov	esi, device_list
1492 hidnplayr 425
;        mov     eax, [IOCTL.input]                      ; get the pci bus and device numbers
426
	mov	ax , [eax+1]				;
1196 hidnplayr 427
  .nextdevice:
1492 hidnplayr 428
	mov	ebx, [esi]
429
	cmp	ax , word [device.pci_bus]		; compare with pci and device num in device list (notice the usage of word instead of byte)
1196 hidnplayr 430
	je	.find_devicenum 			; Device is already loaded, let's find it's device number
1492 hidnplayr 431
	add	esi, 4
1196 hidnplayr 432
	loop	.nextdevice
433
 
434
; This device doesnt have its own eth_device structure yet, lets create one
435
 
436
  .firstdevice:
1519 hidnplayr 437
	cmp	[devices], MAX_DEVICES			; First check if the driver can handle one more card
1196 hidnplayr 438
	jge	.fail
439
 
1564 hidnplayr 440
	allocate_and_clear ebx, device_size, .fail
1196 hidnplayr 441
 
442
; Fill in the direct call addresses into the struct
443
 
1492 hidnplayr 444
	mov	[device.reset], reset
445
	mov	[device.transmit], transmit
446
	mov	[device.get_MAC], read_mac
447
	mov	[device.set_MAC], write_mac
448
	mov	[device.unload], unload
449
	mov	[device.name], my_service
1196 hidnplayr 450
 
451
; save the pci bus and device numbers
452
 
1492 hidnplayr 453
	mov	eax, [IOCTL.input]
1196 hidnplayr 454
	mov	cl , [eax+1]
1492 hidnplayr 455
	mov	[device.pci_bus], cl
1196 hidnplayr 456
	mov	cl , [eax+2]
1492 hidnplayr 457
	mov	[device.pci_dev], cl
1196 hidnplayr 458
 
459
; Now, it's time to find the base io addres of the PCI device
460
 
1492 hidnplayr 461
	find_io [device.pci_bus], [device.pci_dev], [device.io_addr]
1196 hidnplayr 462
 
463
; We've found the io address, find IRQ now
464
 
1492 hidnplayr 465
	find_irq [device.pci_bus], [device.pci_dev], [device.irq_line]
1196 hidnplayr 466
 
467
	DEBUGF	1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
1492 hidnplayr 468
	[device.pci_dev]:1,[device.pci_bus]:1,[device.irq_line]:1,[device.io_addr]:4
1196 hidnplayr 469
 
1564 hidnplayr 470
	allocate_and_clear [device.tx_buffer], PCNET_RX_RING_SIZE * (PCNET_PKT_BUF_SZ + buf_head.size), .err
471
	allocate_and_clear [device.rx_buffer], PCNET_TX_RING_SIZE * (PCNET_PKT_BUF_SZ + buf_head.size), .err
1196 hidnplayr 472
 
473
; Ok, the eth_device structure is ready, let's probe the device
1201 clevermous 474
; Because initialization fires IRQ, IRQ handler must be aware of this device
1564 hidnplayr 475
	mov	eax, [devices]					      ; Add the device structure to our device list
476
	mov	[device_list+4*eax], ebx				 ; (IRQ handler uses this list to find device)
477
	inc	[devices]					      ;
1196 hidnplayr 478
 
479
	call	probe							; this function will output in eax
480
	test	eax, eax
1564 hidnplayr 481
	jnz	.destroy							; If an error occured, exit
1196 hidnplayr 482
 
1514 hidnplayr 483
	mov	[device.type], NET_TYPE_ETH
484
	call	NetRegDev
1196 hidnplayr 485
	cmp	eax, -1
486
	je	.destroy
487
 
488
	ret
489
 
490
; If the device was already loaded, find the device number and return it in eax
491
 
492
  .find_devicenum:
493
	DEBUGF	1,"Trying to find device number of already registered device\n"
494
	mov	ebx, eax
1514 hidnplayr 495
	call	NetPtrToNum						; This kernel procedure converts a pointer to device struct in ebx
1196 hidnplayr 496
									; into a device number in edi
497
	mov	eax, edi						; Application wants it in eax instead
498
	DEBUGF	1,"Kernel says: %u\n", eax
499
	ret
500
 
501
; If an error occured, remove all allocated data and exit (returning -1 in eax)
502
 
503
  .destroy:
504
	; todo: reset device into virgin state
1564 hidnplayr 505
 
1519 hidnplayr 506
	dec	[devices]
1196 hidnplayr 507
  .err:
508
	DEBUGF	1,"Error, removing all data !\n"
1492 hidnplayr 509
	stdcall KernelFree, [device.rx_buffer]
1541 hidnplayr 510
	stdcall KernelFree, [device.tx_buffer]
1196 hidnplayr 511
	stdcall KernelFree, ebx
512
 
513
  .fail:
514
	or	eax, -1
515
	ret
516
 
517
;------------------------------------------------------
518
endp
519
 
520
 
521
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
522
;;                                                                        ;;
523
;;        Actual Hardware dependent code starts here                      ;;
524
;;                                                                        ;;
525
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
526
 
527
align 4
528
unload:
529
	; TODO: (in this particular order)
530
	;
531
	; - Stop the device
532
	; - Detach int handler
533
	; - Remove device from local list (RTL8139_LIST)
534
	; - call unregister function in kernel
535
	; - Remove all allocated structures and buffers the card used
536
 
537
	or	eax,-1
538
 
539
ret
540
 
541
 
542
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
543
;;
544
;;  probe: enables the device (if it really is a PCnet device)
545
;;
546
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
547
 
548
align 4
549
probe:
1564 hidnplayr 550
	mov	edx, [device.io_addr]
1196 hidnplayr 551
 
552
	call	wio_reset
553
 
554
	xor	ecx, ecx
555
	call	wio_read_csr
556
	cmp	eax, 4
557
	jne	.try_dwio
558
 
559
	; Try Word I/O
1564 hidnplayr 560
	mov	ax , 88
561
	add	edx, PCNET_WIO_RAP
562
	out	dx , ax
1196 hidnplayr 563
	nop
564
	nop
1564 hidnplayr 565
	in	ax , dx
566
	sub	edx, PCNET_WIO_RAP
567
	cmp	ax , 88
1196 hidnplayr 568
	jne	.try_dwio
569
 
570
	call	switch_to_wio
571
 
572
	jmp	.L1
573
 
574
  .try_dwio:
575
	call	dwio_reset
576
 
577
	xor	ecx, ecx
578
	call	dwio_read_csr
579
	cmp	eax, 4
580
	jne	.no_dev
581
 
582
	; Try Dword I/O
1564 hidnplayr 583
	add	edx, PCNET_DWIO_RAP
1196 hidnplayr 584
	mov	eax, 88
1564 hidnplayr 585
	out	dx , eax
1196 hidnplayr 586
	nop
587
	nop
588
	in	eax, dx
1564 hidnplayr 589
	sub	edx, PCNET_DWIO_RAP
590
	and	eax, 0xffff
591
	cmp	eax, 88
1196 hidnplayr 592
	jne	.no_dev
593
 
594
	call	switch_to_dwio
595
 
596
	jmp	.L1
597
 
598
  .no_dev:
1564 hidnplayr 599
	DEBUGF 1,"PCnet device not found!\n"
600
	mov	eax, 1
1196 hidnplayr 601
	ret
1564 hidnplayr 602
  .L1:
1541 hidnplayr 603
 
1564 hidnplayr 604
	mov	ecx, PCNET_CSR_CHIPID0
1492 hidnplayr 605
	call	[device.access_read_csr]
1196 hidnplayr 606
	mov	esi, eax
607
 
1564 hidnplayr 608
	mov	ecx, PCNET_CSR_CHIPID1
1492 hidnplayr 609
	call	[device.access_read_csr]
1196 hidnplayr 610
	shl	eax, 16
611
	or	eax, esi
612
 
613
	mov	ecx, eax
614
	and	ecx, 0xfff
615
	cmp	ecx, 3
616
	jne	.no_dev
617
 
618
	shr	eax, 12
619
	and	eax, 0xffff
1492 hidnplayr 620
	mov	[device.chip_version], eax
1196 hidnplayr 621
 
1564 hidnplayr 622
	DEBUGF 1,"chip version ok\n"
1492 hidnplayr 623
	mov	[device.fdx], 0
624
	mov	[device.mii], 0
625
	mov	[device.fset], 0
626
	mov	[device.dxsuflo], 0
627
	mov	[device.ltint], 0
1196 hidnplayr 628
 
629
	cmp	eax, 0x2420
630
	je	.L2
631
	cmp	eax, 0x2430
632
	je	.L2
633
 
1492 hidnplayr 634
	mov	[device.fdx], 1
1196 hidnplayr 635
 
636
	cmp	eax, 0x2621
637
	je	.L4
638
	cmp	eax, 0x2623
639
	je	.L5
640
	cmp	eax, 0x2624
641
	je	.L6
642
	cmp	eax, 0x2625
643
	je	.L7
644
	cmp	eax, 0x2626
645
	je	.L8
646
	cmp	eax, 0x2627
647
	je	.L9
648
 
1564 hidnplayr 649
	DEBUGF 1,"Invalid chip rev\n"
1196 hidnplayr 650
	jmp	.no_dev
651
  .L2:
1492 hidnplayr 652
	mov	[device.name], device_l2
1196 hidnplayr 653
	jmp	.L10
654
  .L4:
1492 hidnplayr 655
	mov	[device.name], device_l4
656
;        mov     [device.fdx], 1
1196 hidnplayr 657
	jmp	.L10
658
  .L5:
1492 hidnplayr 659
	mov	[device.name], device_l5
660
;        mov     [device.fdx], 1
661
	mov	[device.mii], 1
662
	mov	[device.fset], 1
663
	mov	[device.ltint], 1
1196 hidnplayr 664
	jmp	.L10
665
  .L6:
1492 hidnplayr 666
	mov	[device.name], device_l6
667
;        mov     [device.fdx], 1
668
	mov	[device.mii], 1
669
	mov	[device.fset], 1
1196 hidnplayr 670
	jmp	.L10
671
  .L7:
1492 hidnplayr 672
	mov	[device.name], device_l7
673
;        mov     [device.fdx], 1
674
	mov	[device.mii], 1
1196 hidnplayr 675
	jmp	.L10
676
  .L8:
1492 hidnplayr 677
	mov	[device.name], device_l8
678
;        mov     [device.fdx], 1
1564 hidnplayr 679
	mov	ecx, PCNET_CSR_RXPOLL
680
	call	dword [device.access_read_bcr]
681
	call	dword [device.access_write_bcr]
1196 hidnplayr 682
	jmp	.L10
683
  .L9:
1492 hidnplayr 684
	mov	[device.name], device_l9
685
;        mov     [device.fdx], 1
686
	mov	[device.mii], 1
1196 hidnplayr 687
  .L10:
1564 hidnplayr 688
	DEBUGF 1,"device name: %s\n",[device.name]
1196 hidnplayr 689
 
1492 hidnplayr 690
	cmp	[device.fset], 1
1196 hidnplayr 691
	jne	.L11
1564 hidnplayr 692
	mov	ecx, PCNET_BCR_BUSCTL
1492 hidnplayr 693
	call	[device.access_read_bcr]
1564 hidnplayr 694
	or	eax, 0x800
1492 hidnplayr 695
	call	[device.access_write_bcr]
1196 hidnplayr 696
 
1564 hidnplayr 697
	mov	ecx, PCNET_CSR_DMACTL
1492 hidnplayr 698
	call	[device.access_read_csr]
1564 hidnplayr 699
;        and     eax, 0xc00
700
;        or      eax, 0xc00
1196 hidnplayr 701
	mov	eax, 0xc00
1492 hidnplayr 702
	call	[device.access_write_csr]
1196 hidnplayr 703
 
1492 hidnplayr 704
	mov	[device.dxsuflo],1
705
	mov	[device.ltint],1
1196 hidnplayr 706
  .L11:
707
 
1564 hidnplayr 708
	make_bus_master [device.pci_bus], [device.pci_dev]
709
 
710
	mov	eax, PCNET_PORT_ASEL
1492 hidnplayr 711
	mov	[device.options], eax
712
	mov	[device.mode_], word 0x0003
1564 hidnplayr 713
	mov	[device.tlen_rlen], word (PCNET_TX_RING_LEN_BITS or PCNET_RX_RING_LEN_BITS)
1196 hidnplayr 714
 
1492 hidnplayr 715
	mov	dword [device.filter], 0
716
	mov	dword [device.filter+4], 0
1196 hidnplayr 717
 
1564 hidnplayr 718
	mov	eax, PCNET_IMR
719
	mov	ecx, PCNET_CSR_IMR			; Write interrupt mask
1492 hidnplayr 720
	call	[device.access_write_csr]
1196 hidnplayr 721
 
1492 hidnplayr 722
align 4
1196 hidnplayr 723
reset:
724
 
725
; attach int handler
726
 
1492 hidnplayr 727
	movzx	eax, [device.irq_line]
1196 hidnplayr 728
	DEBUGF	1,"Attaching int handler to irq %x\n",eax:1
729
	stdcall AttachIntHandler, eax, int_handler, dword 0
730
	test	eax, eax
731
	jnz	@f
732
	DEBUGF	1,"\nCould not attach int handler!\n"
733
;        or      eax, -1
734
;        ret
735
  @@:
736
 
1564 hidnplayr 737
	mov	edx, [device.io_addr]
1492 hidnplayr 738
	call	[device.access_reset]
739
 
1564 hidnplayr 740
	; Switch pcnet32 to 32bit mode
741
	mov	ecx, PCNET_BCR_SSTYLE
1541 hidnplayr 742
	mov	eax, 2
743
	call	[device.access_write_bcr]
1492 hidnplayr 744
 
1196 hidnplayr 745
	; set/reset autoselect bit
1564 hidnplayr 746
	mov	ecx, PCNET_BCR_MISCCFG
1492 hidnplayr 747
	call	[device.access_read_bcr]
1564 hidnplayr 748
	and	eax,not 2
749
	test	[device.options], PCNET_PORT_ASEL
750
	jz	.L1
751
	or	eax, 2
1196 hidnplayr 752
  .L1:
1492 hidnplayr 753
	call	[device.access_write_bcr]
1196 hidnplayr 754
 
755
 
756
	; Handle full duplex setting
1492 hidnplayr 757
	cmp	byte [device.full_duplex], 0
1196 hidnplayr 758
	je	.L2
1564 hidnplayr 759
	mov	ecx, PCNET_BCR_DUPLEX
1492 hidnplayr 760
	call	[device.access_read_bcr]
1196 hidnplayr 761
	and	eax, not 3
1564 hidnplayr 762
	test	[device.options], PCNET_PORT_FD
1196 hidnplayr 763
	jz	.L3
764
	or	eax, 1
1564 hidnplayr 765
	cmp	[device.options], PCNET_PORT_FD or PCNET_PORT_AUI
1196 hidnplayr 766
	jne	.L4
767
	or	eax, 2
768
	jmp	.L4
769
  .L3:
1564 hidnplayr 770
	test	[device.options], PCNET_PORT_ASEL
1196 hidnplayr 771
	jz	.L4
1492 hidnplayr 772
	cmp	[device.chip_version], 0x2627
1196 hidnplayr 773
	jne	.L4
774
	or	eax, 3
775
  .L4:
1564 hidnplayr 776
	mov	ecx, PCNET_BCR_DUPLEX
1492 hidnplayr 777
	call	[device.access_write_bcr]
1196 hidnplayr 778
  .L2:
779
 
780
 
781
	; set/reset GPSI bit in test register
782
	mov	ecx, 124
1492 hidnplayr 783
	call	[device.access_read_csr]
784
	mov	ecx, [device.options]
1564 hidnplayr 785
	and	ecx, PCNET_PORT_PORTSEL
786
	cmp	ecx, PCNET_PORT_GPSI
1196 hidnplayr 787
	jne	.L5
788
	or	eax, 0x10
789
  .L5:
1492 hidnplayr 790
	call	[device.access_write_csr]
791
	cmp	[device.mii], 0
1196 hidnplayr 792
	je	.L6
1564 hidnplayr 793
	test	[device.options], PCNET_PORT_ASEL
1196 hidnplayr 794
	jnz	.L6
1564 hidnplayr 795
	mov	ecx, PCNET_BCR_MIICTL
1492 hidnplayr 796
	call	[device.access_read_bcr]
1196 hidnplayr 797
	and	eax,not 0x38
1564 hidnplayr 798
	test	[device.options], PCNET_PORT_FD
1196 hidnplayr 799
	jz	.L7
800
	or	eax, 0x10
801
  .L7:
1564 hidnplayr 802
	test	[device.options], PCNET_PORT_100
1196 hidnplayr 803
	jz	.L8
804
	or	eax, 0x08
805
  .L8:
1492 hidnplayr 806
	call	[device.access_write_bcr]
1196 hidnplayr 807
	jmp	.L9
808
.L6:
1564 hidnplayr 809
	test	[device.options], PCNET_PORT_ASEL
1196 hidnplayr 810
	jz	.L9
1564 hidnplayr 811
	mov	ecx, PCNET_BCR_MIICTL
812
	DEBUGF 1,"ASEL, enable auto-negotiation\n"
1492 hidnplayr 813
	call	[device.access_read_bcr]
1196 hidnplayr 814
	and	eax, not 0x98
815
	or	eax, 0x20
1492 hidnplayr 816
	call	[device.access_write_bcr]
1196 hidnplayr 817
.L9:
1492 hidnplayr 818
	cmp	[device.ltint],0
1196 hidnplayr 819
	je	.L10
820
	mov	ecx,5
1492 hidnplayr 821
	call	[device.access_read_csr]
1196 hidnplayr 822
	or	eax,(1 shl 14)
1492 hidnplayr 823
	call	[device.access_write_csr]
1196 hidnplayr 824
.L10:
1564 hidnplayr 825
	mov	eax,[device.options]
826
	and	eax,PCNET_PORT_PORTSEL
827
	shl	eax,7
828
	mov	[device.mode_],ax
1492 hidnplayr 829
	mov	dword [device.filter], -1
830
	mov	dword [device.filter+4], -1
1196 hidnplayr 831
 
1201 clevermous 832
	call	read_mac
1196 hidnplayr 833
 
1492 hidnplayr 834
	lea	esi, [device.mac]
835
	lea	edi, [device.phys_addr]
1201 clevermous 836
	movsd
837
	movsw
838
 
1564 hidnplayr 839
	call	init_ring
840
 
1492 hidnplayr 841
	lea	eax, [device.private]
1541 hidnplayr 842
	GetRealAddr
1564 hidnplayr 843
 
1196 hidnplayr 844
	push	eax
845
	and	eax, 0xffff
846
	mov	ecx, 1
1492 hidnplayr 847
	call	[device.access_write_csr]
1196 hidnplayr 848
	pop	eax
1564 hidnplayr 849
	shr	eax,16
850
	mov	ecx,2
1492 hidnplayr 851
	call	[device.access_write_csr]
1196 hidnplayr 852
 
1564 hidnplayr 853
	mov	ecx,4
854
	mov	eax,0x0915
1492 hidnplayr 855
	call	[device.access_write_csr]
1196 hidnplayr 856
 
1564 hidnplayr 857
	mov	ecx,0
858
	mov	eax,1
1492 hidnplayr 859
	call	[device.access_write_csr]
1196 hidnplayr 860
 
1564 hidnplayr 861
	mov	[device.tx_full],0
862
	mov	[device.cur_rx],0
863
	mov	[device.cur_tx],0
864
	mov	[device.dirty_rx],0
865
	mov	[device.dirty_tx],0
1196 hidnplayr 866
 
1564 hidnplayr 867
	mov	ecx,100
1196 hidnplayr 868
.L11:
869
	push	ecx
1564 hidnplayr 870
	xor	ecx,ecx
1492 hidnplayr 871
	call	[device.access_read_csr]
1196 hidnplayr 872
	pop	ecx
1564 hidnplayr 873
	test	ax,0x100
1196 hidnplayr 874
	jnz	.L12
875
	loop	.L11
876
.L12:
877
 
1564 hidnplayr 878
	DEBUGF 1,"hardware reset\n"
1196 hidnplayr 879
	xor	ecx, ecx
880
	mov	eax, 0x0002
1492 hidnplayr 881
	call	[device.access_write_csr]
1196 hidnplayr 882
 
883
	xor	ecx, ecx
1492 hidnplayr 884
	call	[device.access_read_csr]
1196 hidnplayr 885
 
886
	xor	ecx, ecx
1564 hidnplayr 887
	mov	eax, PCNET_CSR_INTEN or PCNET_CSR_START
1492 hidnplayr 888
	call	[device.access_write_csr]
1196 hidnplayr 889
 
1564 hidnplayr 890
; Set the mtu, kernel will be able to send now
891
	mov	[device.mtu], 1514
892
 
1196 hidnplayr 893
	DEBUGF 1,"PCNET reset complete\n"
894
	xor	eax, eax
1564 hidnplayr 895
	ret
1492 hidnplayr 896
 
1519 hidnplayr 897
 
1564 hidnplayr 898
align 4
899
init_ring:
900
 
901
	mov	ecx, PCNET_RX_RING_SIZE
902
	mov	edi, [device.rx_buffer]
903
	mov	eax, edi
904
	GetRealAddr
905
	mov	[device.rx_ring_phys], eax
906
	add	eax, PCNET_RX_RING_SIZE * buf_head.size
907
  .rx_init:
908
	mov	[edi + buf_head.base], eax
909
	mov	[edi + buf_head.length], PCNET_PKT_BUF_SZ_NEG
910
	mov	[edi + buf_head.status], 0x8000
911
	and	dword [edi + buf_head.msg_length], 0
912
	and	dword [edi + buf_head.reserved], 0
913
	add	eax, PCNET_PKT_BUF_SZ
914
	add	edi, buf_head.size
915
	loop	.rx_init
916
 
917
	mov	ecx, PCNET_TX_RING_SIZE
918
	mov	edi, [device.tx_buffer]
919
	mov	eax, edi
920
	GetRealAddr
921
	mov	[device.tx_ring_phys], eax
922
	add	eax, PCNET_TX_RING_SIZE * buf_head.size
923
  .tx_init:
924
	mov	[edi + buf_head.base], eax
925
	and	dword [edi + buf_head.length], 0
926
	and	dword [edi + buf_head.msg_length], 0
927
	and	dword [edi + buf_head.reserved], 0
928
	add	eax, PCNET_PKT_BUF_SZ
929
	add	edi, buf_head.size
930
	loop	.tx_init
931
 
932
	mov	[device.tlen_rlen], (PCNET_TX_RING_LEN_BITS or PCNET_RX_RING_LEN_BITS)
933
 
1196 hidnplayr 934
	ret
935
 
936
 
937
 
938
 
939
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
940
;;                                         ;;
941
;; Transmit                                ;;
942
;;                                         ;;
1263 clevermous 943
;; In: buffer pointer in [esp+4]           ;;
1254 hidnplayr 944
;;     size of buffer in [esp+8]           ;;
1196 hidnplayr 945
;;     pointer to device structure in ebx  ;;
946
;;                                         ;;
947
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
948
 
949
align 4
950
transmit:
1564 hidnplayr 951
	DEBUGF	1,"Transmitting packet, buffer:%x, size:%u\n",[esp+4],[esp+8]
1254 hidnplayr 952
	mov	eax, [esp+4]
1196 hidnplayr 953
	DEBUGF	1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
954
	[eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
955
	[eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
956
	[eax+13]:2,[eax+12]:2
957
 
1254 hidnplayr 958
	cmp	dword [esp+8], 1514
1196 hidnplayr 959
	jg	.finish 			; packet is too long
1254 hidnplayr 960
	cmp	dword [esp+8], 60
1196 hidnplayr 961
	jl	.finish 			; packet is too short
962
 
963
; check descriptor
1492 hidnplayr 964
	movzx	eax, [device.cur_tx]
1564 hidnplayr 965
	imul	edi, eax, PCNET_PKT_BUF_SZ
1201 clevermous 966
	shl	eax, 4
1564 hidnplayr 967
	add	eax, [device.tx_buffer]
1492 hidnplayr 968
	add	edi, [device.tx_buffer]
1564 hidnplayr 969
	add	edi, PCNET_TX_RING_SIZE * buf_head.size
1541 hidnplayr 970
 
1201 clevermous 971
	test	byte [eax + buf_head.status + 1], 80h
972
	jnz	.nospace
973
; descriptor is free, copy data
1254 hidnplayr 974
	mov	esi, [esp+4]
975
	mov	ecx, [esp+8]
1201 clevermous 976
	mov	edx, ecx
977
	shr	ecx, 2
978
	and	edx, 3
979
	rep	movsd
980
	mov	ecx, edx
981
	rep	movsb
982
; set length
1254 hidnplayr 983
	mov	ecx, [esp+8]
1201 clevermous 984
	neg	ecx
985
	mov	[eax + buf_head.length], cx
986
; put to transfer queue
987
	mov	[eax + buf_head.status], 0x8300
1196 hidnplayr 988
 
989
; trigger an immediate send
1201 clevermous 990
	xor	ecx, ecx	 ; CSR0
1492 hidnplayr 991
	call	[device.access_read_csr]
1564 hidnplayr 992
	or	eax, PCNET_CSR_TX
1492 hidnplayr 993
	call	[device.access_write_csr]
1196 hidnplayr 994
 
995
; get next descriptor 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, ...
1492 hidnplayr 996
	inc	[device.cur_tx]
997
	and	[device.cur_tx], 3
1196 hidnplayr 998
	DEBUGF	2," - Packet Sent! "
999
 
1000
.finish:
1001
	DEBUGF	2," - Done!\n"
1541 hidnplayr 1002
	stdcall KernelFree, [esp+4]
1003
	ret	8
1196 hidnplayr 1004
 
1201 clevermous 1005
.nospace:
1006
	DEBUGF	1, 'ERROR: no free transmit descriptors\n'
1007
; todo: maybe somehow notify the kernel about the error?
1541 hidnplayr 1008
	stdcall KernelFree, [esp+4]
1009
	ret	8
1196 hidnplayr 1010
 
1011
 
1012
 
1013
;;;;;;;;;;;;;;;;;;;;;;;
1014
;;                   ;;
1015
;; Interrupt handler ;;
1016
;;                   ;;
1017
;;;;;;;;;;;;;;;;;;;;;;;
1018
 
1019
align 4
1020
int_handler:
1021
 
1564 hidnplayr 1022
;       DEBUGF  1,"IRQ %x ",eax:2                   ; no, you cant replace 'eax:2' with 'al', this must be a bug in FDO
1196 hidnplayr 1023
 
1024
; find pointer of device wich made IRQ occur
1025
 
1519 hidnplayr 1026
	mov	esi, device_list
1027
	mov	ecx, [devices]
1196 hidnplayr 1028
	test	ecx, ecx
1029
	jz	.abort
1030
  .nextdevice:
1564 hidnplayr 1031
	mov	ebx, dword [esi]
1032
	mov	edx, [device.io_addr]	  ; get IRQ reason
1196 hidnplayr 1033
 
1034
	push	ecx
1201 clevermous 1035
	xor	ecx, ecx ; CSR0
1564 hidnplayr 1036
	call	[device.access_read_csr]
1196 hidnplayr 1037
	pop	ecx
1038
 
1564 hidnplayr 1039
	test	al , al
1040
	js	.got_it
1196 hidnplayr 1041
 
1042
	add	esi, 4
1043
	loop	.nextdevice
1044
 
1564 hidnplayr 1045
	ret					    ; If no device was found, abort (The irq was probably for a device, not registered to this driver
1196 hidnplayr 1046
 
1047
  .got_it:
1048
;-------------------------------------------------------
1201 clevermous 1049
; Possible reasons:
1050
; initialization done - ignore
1051
; transmit done - ignore
1052
; packet received - handle
1053
; Clear ALL IRQ reasons.
1054
; N.B. One who wants to handle more than one reason must be ready
1055
; to two or more reasons in one IRQ.
1056
	xor	ecx, ecx
1492 hidnplayr 1057
	call	[device.access_write_csr]
1196 hidnplayr 1058
; Received packet ok?
1059
 
1564 hidnplayr 1060
	test	ax, PCNET_CSR_RINT
1196 hidnplayr 1061
	jz	@f
1062
 
1564 hidnplayr 1063
.receiver_test_loop:
1492 hidnplayr 1064
	movzx	eax, [device.cur_rx]
1564 hidnplayr 1065
;        and     eax, PCNET_RX_RING_MOD_MASK
1196 hidnplayr 1066
	mov	edi, eax
1067
 
1564 hidnplayr 1068
	imul	esi, eax, PCNET_PKT_BUF_SZ	;
1492 hidnplayr 1069
	add	esi, [device.rx_buffer] 	; esi now points to rx buffer
1564 hidnplayr 1070
	add	esi, PCNET_RX_RING_SIZE * buf_head.size
1196 hidnplayr 1071
 
1072
	shl	edi, 4				; desc * 16 (16 is size of one ring entry)
1564 hidnplayr 1073
	add	edi, [device.rx_buffer]     ; edi now points to current rx ring entry
1196 hidnplayr 1074
 
1075
	mov	cx , [edi + buf_head.status]
1076
 
1564 hidnplayr 1077
	test	cx , PCNET_RXSTAT_OWN		; If this bit is set, the controller OWN's the packet, if not, we do
1196 hidnplayr 1078
	jnz	.abort
1079
 
1564 hidnplayr 1080
	test	cx , PCNET_RXSTAT_ENP
1196 hidnplayr 1081
	jz	.abort
1082
 
1564 hidnplayr 1083
	test	cx , PCNET_RXSTAT_STP
1196 hidnplayr 1084
	jz	.abort
1085
 
1201 clevermous 1086
	movzx	ecx, [edi + buf_head.msg_length]	; get packet length in ecx
1196 hidnplayr 1087
	sub	ecx, 4				;
1088
 
1201 clevermous 1089
	push	ecx
1196 hidnplayr 1090
	stdcall KernelAlloc, ecx		; Allocate a buffer to put packet into
1201 clevermous 1091
	pop	ecx
1196 hidnplayr 1092
	test	eax, eax			; Test if we allocated succesfully
1093
	jz	.abort				;
1094
 
1251 clevermous 1095
	push	.receiver_test_loop		;
1196 hidnplayr 1096
	push	ecx				; for eth_receiver
1097
	push	eax				;
1098
 
1099
	xchg	edi, eax
1564 hidnplayr 1100
	push	ecx
1101
	shr	ecx, 2
1102
	cld
1196 hidnplayr 1103
	rep	movsd
1564 hidnplayr 1104
	pop	ecx
1105
	and	ecx, 3
1106
	rep	movsb
1196 hidnplayr 1107
 
1564 hidnplayr 1108
;       mov     word [eax + buf_head.length], PCNET_PKT_BUF_SZ_NEG
1109
	mov	word [eax + buf_head.status], PCNET_RXSTAT_OWN	    ; Set OWN bit back to 1 (controller may write to tx-buffer again now)
1196 hidnplayr 1110
 
1492 hidnplayr 1111
	inc	[device.cur_rx] 	  ; update descriptor
1112
	and	[device.cur_rx], 3	  ;
1196 hidnplayr 1113
 
1114
	jmp	EthReceiver			; Send the copied packet to kernel
1115
 
1116
  .abort:
1117
 
1541 hidnplayr 1118
  @@:
1119
 
1196 hidnplayr 1120
	ret
1121
 
1122
 
1123
 
1124
 
1125
;;;;;;;;;;;;;;;;;;;;;;;
1126
;;                   ;;
1127
;; Write MAC address ;;
1128
;;                   ;;
1129
;;;;;;;;;;;;;;;;;;;;;;;
1130
 
1131
align 4
1132
write_mac:	; in: mac pushed onto stack (as 3 words)
1133
 
1134
	DEBUGF	1,"Writing MAC: %x-%x-%x-%x-%x-%x",[esp+0]:2,[esp+1]:2,[esp+2]:2,[esp+3]:2,[esp+4]:2,[esp+5]:2
1135
 
1564 hidnplayr 1136
	mov	edx, [device.io_addr]
1137
	add	dx, 2
1196 hidnplayr 1138
	xor	eax, eax
1564 hidnplayr 1139
 
1140
	mov	ecx, PCNET_CSR_PAR0
1196 hidnplayr 1141
       @@:
1142
	pop	ax
1492 hidnplayr 1143
	call	[device.access_write_csr]
1196 hidnplayr 1144
	DEBUGF	1,"."
1145
	inc	ecx
1564 hidnplayr 1146
	cmp	ecx, PCNET_CSR_PAR2
1196 hidnplayr 1147
	jl	@r
1148
 
1149
	DEBUGF	1,"\n"
1150
 
1151
; Notice this procedure does not ret, but continues to read_mac instead.
1152
 
1153
;;;;;;;;;;;;;;;;;;;;;;
1154
;;                  ;;
1155
;; Read MAC address ;;
1156
;;                  ;;
1157
;;;;;;;;;;;;;;;;;;;;;;
1564 hidnplayr 1158
align 4
1492 hidnplayr 1159
read_mac:
1196 hidnplayr 1160
	DEBUGF	1,"Reading MAC"
1161
 
1564 hidnplayr 1162
	mov	edx, [device.io_addr]
1163
	add	dx, 6
1196 hidnplayr 1164
       @@:
1165
	dec	dx
1166
	dec	dx
1167
	in	ax, dx
1168
	push	ax
1169
	DEBUGF	1,"."
1492 hidnplayr 1170
	cmp	edx, [device.io_addr]
1196 hidnplayr 1171
	jg	@r
1172
 
1173
	DEBUGF	1," %x-%x-%x-%x-%x-%x\n",[esp+0]:2,[esp+1]:2,[esp+2]:2,[esp+3]:2,[esp+4]:2,[esp+5]:2
1174
 
1492 hidnplayr 1175
	lea	edi, [device.mac]
1196 hidnplayr 1176
	pop	ax
1177
	stosw
1178
	pop	ax
1179
	stosw
1180
	pop	ax
1181
	stosw
1182
 
1183
	ret
1184
 
1564 hidnplayr 1185
align 4
1196 hidnplayr 1186
switch_to_wio:
1187
 
1564 hidnplayr 1188
	DEBUGF	1,"Switching to 16-bit mode\n"
1189
 
1492 hidnplayr 1190
	mov	[device.access_read_csr], wio_read_csr
1191
	mov	[device.access_write_csr], wio_write_csr
1192
	mov	[device.access_read_bcr], wio_read_bcr
1193
	mov	[device.access_write_bcr], wio_write_bcr
1194
	mov	[device.access_read_rap], wio_read_rap
1195
	mov	[device.access_write_rap], wio_write_rap
1196
	mov	[device.access_reset], wio_reset
1196 hidnplayr 1197
 
1198
	ret
1199
 
1564 hidnplayr 1200
align 4
1196 hidnplayr 1201
switch_to_dwio:
1202
 
1564 hidnplayr 1203
	DEBUGF	1,"Switching to 32-bit mode\n"
1204
 
1492 hidnplayr 1205
	mov	[device.access_read_csr], dwio_read_csr
1206
	mov	[device.access_write_csr], dwio_write_csr
1207
	mov	[device.access_read_bcr], dwio_read_bcr
1208
	mov	[device.access_write_bcr], dwio_write_bcr
1209
	mov	[device.access_read_rap], dwio_read_rap
1210
	mov	[device.access_write_rap], dwio_write_rap
1211
	mov	[device.access_reset], dwio_reset
1196 hidnplayr 1212
 
1213
	ret
1214
 
1215
 
1216
; ecx - index
1217
; return:
1218
; eax - data
1564 hidnplayr 1219
align 4
1196 hidnplayr 1220
wio_read_csr:
1221
 
1564 hidnplayr 1222
	add	edx, PCNET_WIO_RAP
1196 hidnplayr 1223
	mov	ax , cx
1224
	out	dx , ax
1564 hidnplayr 1225
	add	edx, PCNET_WIO_RDP - PCNET_WIO_RAP
1196 hidnplayr 1226
	in	ax , dx
1227
	and	eax, 0xffff
1564 hidnplayr 1228
	sub	edx, PCNET_WIO_RDP
1196 hidnplayr 1229
 
1230
	ret
1231
 
1232
 
1233
; eax - data
1234
; ecx - index
1564 hidnplayr 1235
align 4
1196 hidnplayr 1236
wio_write_csr:
1237
 
1564 hidnplayr 1238
	add	edx, PCNET_WIO_RAP
1196 hidnplayr 1239
	xchg	eax, ecx
1240
	out	dx , ax
1241
	xchg	eax, ecx
1564 hidnplayr 1242
	add	edx, PCNET_WIO_RDP - PCNET_WIO_RAP
1196 hidnplayr 1243
	out	dx , ax
1564 hidnplayr 1244
	sub	edx, PCNET_WIO_RDP
1196 hidnplayr 1245
 
1246
	ret
1247
 
1248
 
1249
; ecx - index
1250
; return:
1251
; eax - data
1564 hidnplayr 1252
align 4
1196 hidnplayr 1253
wio_read_bcr:
1254
 
1564 hidnplayr 1255
	add	edx, PCNET_WIO_RAP
1196 hidnplayr 1256
	mov	ax , cx
1257
	out	dx , ax
1564 hidnplayr 1258
	add	edx, PCNET_WIO_BDP - PCNET_WIO_RAP
1196 hidnplayr 1259
	in	ax , dx
1260
	and	eax, 0xffff
1564 hidnplayr 1261
	sub	edx, PCNET_WIO_BDP
1196 hidnplayr 1262
 
1263
	ret
1264
 
1265
 
1266
; eax - data
1267
; ecx - index
1564 hidnplayr 1268
align 4
1196 hidnplayr 1269
wio_write_bcr:
1270
 
1564 hidnplayr 1271
	add	edx, PCNET_WIO_RAP
1196 hidnplayr 1272
	xchg	eax, ecx
1273
	out	dx , ax
1274
	xchg	eax, ecx
1564 hidnplayr 1275
	add	edx, PCNET_WIO_BDP - PCNET_WIO_RAP
1196 hidnplayr 1276
	out	dx , ax
1564 hidnplayr 1277
	sub	edx, PCNET_WIO_BDP
1196 hidnplayr 1278
 
1279
	ret
1280
 
1564 hidnplayr 1281
align 4
1196 hidnplayr 1282
wio_read_rap:
1283
 
1564 hidnplayr 1284
	add	edx, PCNET_WIO_RAP
1196 hidnplayr 1285
	in	ax , dx
1286
	and	eax, 0xffff
1564 hidnplayr 1287
	sub	edx, PCNET_WIO_RAP
1196 hidnplayr 1288
 
1289
	ret
1290
 
1291
; eax - val
1564 hidnplayr 1292
align 4
1196 hidnplayr 1293
wio_write_rap:
1294
 
1564 hidnplayr 1295
	add	edx, PCNET_WIO_RAP
1196 hidnplayr 1296
	out	dx , ax
1564 hidnplayr 1297
	sub	edx, PCNET_WIO_RAP
1196 hidnplayr 1298
 
1299
	ret
1300
 
1564 hidnplayr 1301
align 4
1196 hidnplayr 1302
wio_reset:
1303
 
1304
	push	eax
1564 hidnplayr 1305
	add	edx, PCNET_WIO_RESET
1196 hidnplayr 1306
	in	ax , dx
1307
	pop	eax
1564 hidnplayr 1308
	sub	edx, PCNET_WIO_RESET
1196 hidnplayr 1309
 
1310
	ret
1311
 
1312
 
1564 hidnplayr 1313
 
1196 hidnplayr 1314
; ecx - index
1315
; return:
1316
; eax - data
1564 hidnplayr 1317
align 4
1196 hidnplayr 1318
dwio_read_csr:
1319
 
1564 hidnplayr 1320
	add	edx, PCNET_DWIO_RAP
1201 clevermous 1321
	mov	eax, ecx
1196 hidnplayr 1322
	out	dx , eax
1564 hidnplayr 1323
	add	edx, PCNET_DWIO_RDP - PCNET_DWIO_RAP
1196 hidnplayr 1324
	in	eax, dx
1325
	and	eax, 0xffff
1564 hidnplayr 1326
	sub	edx, PCNET_DWIO_RDP
1196 hidnplayr 1327
 
1328
	ret
1329
 
1330
 
1331
; ecx - index
1332
; eax - data
1564 hidnplayr 1333
align 4
1196 hidnplayr 1334
dwio_write_csr:
1335
 
1564 hidnplayr 1336
	add	edx, PCNET_DWIO_RAP
1196 hidnplayr 1337
	xchg	eax, ecx
1338
	out	dx , eax
1564 hidnplayr 1339
	add	edx, PCNET_DWIO_RDP - PCNET_DWIO_RAP
1196 hidnplayr 1340
	xchg	eax, ecx
1341
	out	dx , eax
1564 hidnplayr 1342
	sub	edx, PCNET_DWIO_RDP
1196 hidnplayr 1343
 
1344
	ret
1345
 
1346
; ecx - index
1347
; return:
1348
; eax - data
1564 hidnplayr 1349
align 4
1196 hidnplayr 1350
dwio_read_bcr:
1351
 
1564 hidnplayr 1352
	add	edx, PCNET_DWIO_RAP
1201 clevermous 1353
	mov	eax, ecx
1196 hidnplayr 1354
	out	dx , eax
1564 hidnplayr 1355
	add	edx, PCNET_DWIO_BDP - PCNET_DWIO_RAP
1196 hidnplayr 1356
	in	eax, dx
1357
	and	eax, 0xffff
1564 hidnplayr 1358
	sub	edx, PCNET_DWIO_BDP
1196 hidnplayr 1359
 
1360
	ret
1361
 
1362
 
1363
; ecx - index
1364
; eax - data
1564 hidnplayr 1365
align 4
1196 hidnplayr 1366
dwio_write_bcr:
1367
 
1564 hidnplayr 1368
	add	edx, PCNET_DWIO_RAP
1196 hidnplayr 1369
	xchg	eax, ecx
1370
	out	dx , eax
1564 hidnplayr 1371
	add	edx, PCNET_DWIO_BDP - PCNET_DWIO_RAP
1196 hidnplayr 1372
	xchg	eax, ecx
1373
	out	dx , eax
1564 hidnplayr 1374
	sub	edx, PCNET_DWIO_BDP
1196 hidnplayr 1375
 
1376
	ret
1377
 
1564 hidnplayr 1378
align 4
1196 hidnplayr 1379
dwio_read_rap:
1380
 
1564 hidnplayr 1381
	add	edx, PCNET_DWIO_RAP
1196 hidnplayr 1382
	in	eax, dx
1383
	and	eax, 0xffff
1564 hidnplayr 1384
	sub	edx, PCNET_DWIO_RAP
1196 hidnplayr 1385
 
1386
	ret
1387
 
1388
 
1389
; eax - val
1564 hidnplayr 1390
align 4
1196 hidnplayr 1391
dwio_write_rap:
1392
 
1564 hidnplayr 1393
	add	edx, PCNET_DWIO_RAP
1196 hidnplayr 1394
	out	dx , eax
1564 hidnplayr 1395
	sub	edx, PCNET_DWIO_RAP
1196 hidnplayr 1396
 
1397
	ret
1398
 
1564 hidnplayr 1399
align 4
1196 hidnplayr 1400
dwio_reset:
1401
 
1402
	push	eax
1564 hidnplayr 1403
	add	edx, PCNET_DWIO_RESET
1196 hidnplayr 1404
	in	eax, dx
1405
	pop	eax
1564 hidnplayr 1406
	sub	edx, PCNET_DWIO_RESET
1196 hidnplayr 1407
 
1408
	ret
1409
 
1410
 
1411
 
1412
; End of code
1413
 
1564 hidnplayr 1414
align 4 				      ; Place all initialised data here
1196 hidnplayr 1415
 
1564 hidnplayr 1416
devices     dd 0
1417
version       dd (5 shl 16) or (API_VERSION and 0xFFFF)
1418
my_service    db 'PCnet',0		      ; max 16 chars include zero
1419
 
1196 hidnplayr 1420
device_l2     db "PCnet/PCI 79C970",0
1421
device_l4     db "PCnet/PCI II 79C970A",0
1422
device_l5     db "PCnet/FAST 79C971",0
1423
device_l6     db "PCnet/FAST+ 79C972",0
1424
device_l7     db "PCnet/FAST III 79C973",0
1425
device_l8     db "PCnet/Home 79C978",0
1426
device_l9     db "PCnet/FAST III 79C975",0
1427
 
1428
options_mapping:
1564 hidnplayr 1429
dd PCNET_PORT_ASEL					;  0 Auto-select
1430
dd PCNET_PORT_AUI					;  1 BNC/AUI
1431
dd PCNET_PORT_AUI					;  2 AUI/BNC
1432
dd PCNET_PORT_ASEL					;  3 not supported
1433
dd PCNET_PORT_10BT or PCNET_PORT_FD			;  4 10baseT-FD
1434
dd PCNET_PORT_ASEL					;  5 not supported
1435
dd PCNET_PORT_ASEL					;  6 not supported
1436
dd PCNET_PORT_ASEL					;  7 not supported
1437
dd PCNET_PORT_ASEL					;  8 not supported
1438
dd PCNET_PORT_MII					;  9 MII 10baseT
1439
dd PCNET_PORT_MII or PCNET_PORT_FD			; 10 MII 10baseT-FD
1440
dd PCNET_PORT_MII					; 11 MII (autosel)
1441
dd PCNET_PORT_10BT					; 12 10BaseT
1442
dd PCNET_PORT_MII or PCNET_PORT_100			; 13 MII 100BaseTx
1443
dd PCNET_PORT_MII or PCNET_PORT_100 or PCNET_PORT_FD	; 14 MII 100BaseTx-FD
1444
dd PCNET_PORT_ASEL					; 15 not supported
1196 hidnplayr 1445
 
1446
include_debug_strings					; All data wich FDO uses will be included here
1447
 
1448
section '.data' data readable writable align 16 	; place all uninitialized data place here
1449
 
1564 hidnplayr 1450
device_list rd MAX_DEVICES				   ; This list contains all pointers to device structures the driver is handling