Subversion Repositories Kolibri OS

Rev

Rev 1519 | 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
;;                                                                  ;;
1519 hidnplayr 6
;;  PCnet32 driver for KolibriOS                                    ;;
7
;;                                                                  ;;
8
;;  Based on the PCnet32 driver for MenuetOS, by Jarek Pelczar      ;;
9
;;                                                                  ;;
1196 hidnplayr 10
;;          GNU GENERAL PUBLIC LICENSE                              ;;
11
;;             Version 2, June 1991                                 ;;
12
;;                                                                  ;;
13
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
14
 
15
format MS COFF
16
 
17
	API_VERSION		equ 0x01000100
1519 hidnplayr 18
	DRIVER_VERSION		equ 5
1196 hidnplayr 19
 
1519 hidnplayr 20
	MAX_DEVICES		equ 16
21
 
1196 hidnplayr 22
	DEBUG			equ 1
23
	__DEBUG__		equ 1
24
	__DEBUG_LEVEL__ 	equ 1
25
 
1541 hidnplayr 26
	TX_RING_SIZE		equ 4
27
	RX_RING_SIZE		equ 4
28
	PKT_BUF_SZ		equ 1544
1196 hidnplayr 29
 
1541 hidnplayr 30
 
1196 hidnplayr 31
include 'proc32.inc'
32
include 'imports.inc'
33
include 'fdo.inc'
1492 hidnplayr 34
include 'netdrv.inc'
1196 hidnplayr 35
 
36
public START
37
public service_proc
38
public version
39
 
1541 hidnplayr 40
struc buf_head {
41
	.base		dd ?
42
	.length 	dw ?
43
	.status 	dw ?
44
	.msg_length	dw ?
45
	.misc		dw ?
46
	.reserved	dd ?
47
	.size:
48
}
1196 hidnplayr 49
 
1541 hidnplayr 50
virtual at 0
51
 buf_head buf_head
52
end virtual
53
 
1492 hidnplayr 54
virtual at ebx
1196 hidnplayr 55
 
1492 hidnplayr 56
	device:
1196 hidnplayr 57
 
1492 hidnplayr 58
	ETH_DEVICE
59
 
1519 hidnplayr 60
	.rx_buffer	dd ?
61
	.tx_buffer	dd ?
1196 hidnplayr 62
 
1519 hidnplayr 63
	.io_addr	dd ?
64
	.irq_line	db ?
65
	.pci_bus	db ?
66
	.pci_dev	db ?
1492 hidnplayr 67
			db ?	; align 4
1196 hidnplayr 68
 
1519 hidnplayr 69
	.access_read_csr	dd ?
70
	.access_write_csr	dd ?
71
	.access_read_bcr	dd ?
72
	.access_write_bcr	dd ?
73
	.access_read_rap	dd ?
74
	.access_write_rap	dd ?
75
	.access_reset		dd ?
1492 hidnplayr 76
 
1541 hidnplayr 77
	; The following fields up to .tx_ring_phys inclusive form
78
	; initialization block for hardware; do not modify  (must be 4-aligned)
1492 hidnplayr 79
 
1519 hidnplayr 80
	.private:
81
	.mode_		dw ?
82
	.tlen_rlen	dw ?
83
	.phys_addr	dp ?
84
	.reserved	dw ?
85
	.filter 	dq ?
86
	.rx_ring_phys	dd ?
87
	.tx_ring_phys	dd ?
1541 hidnplayr 88
 
89
	.rx_ring	rb RX_RING_SIZE * buf_head.size
90
	.tx_ring	rb TX_RING_SIZE * buf_head.size
91
 
1519 hidnplayr 92
	.cur_rx 	db ?
93
	.cur_tx 	db ?
94
	.dirty_rx	dd ?
95
	.dirty_tx	dd ?
96
	.tx_full	db ?
97
	.options	dd ?
98
	.full_duplex	db ?
99
	.chip_version	dd ?
100
	.mii		db ?
101
	.ltint		db ?
102
	.dxsuflo	db ?
103
	.fset		db ?
104
	.fdx		db ?
1196 hidnplayr 105
 
1519 hidnplayr 106
	.size = $ - device
1196 hidnplayr 107
 
108
end virtual
109
 
110
 
111
struc rx_desc_2 { ; Swstyle 2
112
 
113
	.rbadr		dd ?
114
	.status 	dd ?
115
	.rfrtag 	dd ?
116
 
117
; +--------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
118
; |Address |  31 |  30 |  29 |  28 |  27 |  26 |  25 |  24 |  23 |  22 |  21 |  20 |19-16|15-12|11-0 |
119
; +--------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
120
; |CRDA+00h|                                       RBADR[31:0]                                       |
121
; +--------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
122
; |CRDA+04h| OWN | ERR |FRAM |OFLO | CRC |BUFF | STP | ENP | BPE | PAM |LAFM | BAM | RES |1111 |BCNT |
123
; +--------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
124
; |CRDA+08h| RES |                              RFRTAG[14:0]                             |0000 |MCNT |
125
; +--------+-----+-----------------------------------------------------------------------+-----+-----+
126
; |CRDA+0Ch|                                    USER SPACE                               |     |     |
127
; +--------+-----------------------------------------------------------------------------+-----+-----+
128
 
129
}
130
 
131
struc rx_desc_3 {  ; Swstyle 3
132
 
133
	.mcnt		dd ?
134
	.status 	dd ?
135
	.rbadr		dd ?
136
 
137
; +--------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
138
; |Address |  31 |  30 |  29 |  28 |  27 |  26 |  25 |  24 |  23 |22-16|15-12|11-0 |
139
; +--------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
140
; |CRDA+00h|                      RES                      | RES | RES |0000 |MCNT |
141
; +--------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
142
; |CRDA+04h| OWN | ERR |FRAM |OFLO | CRC |BUFF | STP | ENP | BPE | RES |1111 |BCNT |
143
; +--------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
144
; |CRDA+08h|                            RBADR[31:0]                                |
145
; +--------+-----------------------------------------------------------------------+
146
; |CRDA+0Ch|                             USER SPACE                                |
147
; +--------+-----------------------------------------------------------------------+
148
 
149
}
150
 
151
virtual at 0
152
 rx_desc rx_desc_2
153
end virtual
154
 
1519 hidnplayr 155
	PORT_AUI		equ 0x00
156
	PORT_10BT		equ 0x01
157
	PORT_GPSI		equ 0x02
158
	PORT_MII		equ 0x03
159
	PORT_PORTSEL		equ 0x03
160
	PORT_ASEL		equ 0x04
161
	PORT_100		equ 0x40
162
	PORT_FD 		equ 0x80
1196 hidnplayr 163
 
1519 hidnplayr 164
	DMA_MASK		equ 0xffffffff
1196 hidnplayr 165
 
1519 hidnplayr 166
	LOG_TX_BUFFERS		equ 2
167
	LOG_RX_BUFFERS		equ 2
1196 hidnplayr 168
 
1519 hidnplayr 169
	TX_RING_MOD_MASK	equ (TX_RING_SIZE-1)
170
	TX_RING_LEN_BITS	equ (LOG_TX_BUFFERS shl 12)
1196 hidnplayr 171
 
1519 hidnplayr 172
	RX_RING_MOD_MASK	equ (RX_RING_SIZE-1)
173
	RX_RING_LEN_BITS	equ (LOG_RX_BUFFERS shl 4)
1196 hidnplayr 174
 
1519 hidnplayr 175
	WIO_RDP 		equ 0x10
176
	WIO_RAP 		equ 0x12
177
	WIO_RESET		equ 0x14
178
	WIO_BDP 		equ 0x16
179
	DWIO_RDP		equ 0x10
180
	DWIO_RAP		equ 0x14
181
	DWIO_RESET		equ 0x18
182
	DWIO_BDP		equ 0x1C
183
	TOTAL_SIZE		equ 0x20
1196 hidnplayr 184
 
185
; CSR registers
186
 
1519 hidnplayr 187
	CSR_CSR 		equ 0x00
188
	CSR_IAB0		equ 0x01
189
	CSR_IAB1		equ 0x02
190
	CSR_IMR 		equ 0x03
191
	CSR_TFEAT		equ 0x04
192
	CSR_EXTCTL1		equ 0x05
193
	CSR_DTBLLEN		equ 0x06
194
	CSR_EXTCTL2		equ 0x07
195
	CSR_MAR0		equ 0x08
196
	CSR_MAR1		equ 0x09
197
	CSR_MAR2		equ 0x0A
198
	CSR_MAR3		equ 0x0B
199
	CSR_PAR0		equ 0x0C
200
	CSR_PAR1		equ 0x0D
201
	CSR_PAR2		equ 0x0E
202
	CSR_MODE		equ 0x0F
203
	CSR_RXADDR0		equ 0x18
204
	CSR_RXADDR1		equ 0x19
205
	CSR_TXADDR0		equ 0x1E
206
	CSR_TXADDR1		equ 0x1F
207
	CSR_TXPOLL		equ 0x2F
208
	CSR_RXPOLL		equ 0x31
209
	CSR_RXRINGLEN		equ 0x4C
210
	CSR_TXRINGLEN		equ 0x4E
211
	CSR_DMACTL		equ 0x50
212
	CSR_BUSTIMER		equ 0x52
213
	CSR_MEMERRTIMEO 	equ 0x64
214
	CSR_ONNOWMISC		equ 0x74
215
	CSR_ADVFEAT		equ 0x7A
216
	CSR_MACCFG		equ 0x7D
217
	CSR_CHIPID0		equ 0x58
218
	CSR_CHIPID1		equ 0x59
1196 hidnplayr 219
 
220
; Control and Status Register (CSR0)
221
 
1519 hidnplayr 222
	CSR_INIT		equ 1 shl 0
223
	CSR_START		equ 1 shl 1
224
	CSR_STOP		equ 1 shl 2
225
	CSR_TX			equ 1 shl 3
226
	CSR_TXON		equ 1 shl 4
227
	CSR_RXON		equ 1 shl 5
228
	CSR_INTEN		equ 1 shl 6
229
	CSR_INTR		equ 1 shl 7
230
	CSR_IDONE		equ 1 shl 8
231
	CSR_TINT		equ 1 shl 9
232
	CSR_RINT		equ 1 shl 10
233
	CSR_MERR		equ 1 shl 11
234
	CSR_MISS		equ 1 shl 12
235
	CSR_CERR		equ 1 shl 13
1196 hidnplayr 236
 
237
; Interrupt masks and deferral control (CSR3)
238
 
1519 hidnplayr 239
	IMR_BSWAP		equ 0x0004
240
	IMR_ENMBA		equ 0x0008  ; enable modified backoff alg
241
	IMR_DXMT2PD		equ 0x0010
242
	IMR_LAPPEN		equ 0x0020  ; lookahead packet processing enb
243
	IMR_DXSUFLO		equ 0x0040  ; disable TX stop on underflow
244
	IMR_IDONE		equ 0x0100
245
	IMR_TINT		equ 0x0200
246
	IMR_RINT		equ 0x0400
247
	IMR_MERR		equ 0x0800
248
	IMR_MISS		equ 0x1000
1196 hidnplayr 249
 
1519 hidnplayr 250
	IMR			equ IMR_TINT+IMR_RINT+IMR_IDONE+IMR_MERR+IMR_MISS
1196 hidnplayr 251
 
252
; Test and features control (CSR4)
253
 
1519 hidnplayr 254
	TFEAT_TXSTRTMASK	equ 0x0004
255
	TFEAT_TXSTRT		equ 0x0008
256
	TFEAT_RXCCOFLOWM	equ 0x0010  ; Rx collision counter oflow
257
	TFEAT_RXCCOFLOW 	equ 0x0020
258
	TFEAT_UINT		equ 0x0040
259
	TFEAT_UINTREQ		equ 0x0080
260
	TFEAT_MISSOFLOWM	equ 0x0100
261
	TFEAT_MISSOFLOW 	equ 0x0200
262
	TFEAT_STRIP_FCS 	equ 0x0400
263
	TFEAT_PAD_TX		equ 0x0800
264
	TFEAT_TXDPOLL		equ 0x1000
265
	TFEAT_DMAPLUS		equ 0x4000
1196 hidnplayr 266
 
267
; Extended control and interrupt 1 (CSR5)
268
 
1519 hidnplayr 269
	EXTCTL1_SPND		equ 0x0001  ; suspend
270
	EXTCTL1_MPMODE		equ 0x0002  ; magic packet mode
271
	EXTCTL1_MPENB		equ 0x0004  ; magic packet enable
272
	EXTCTL1_MPINTEN 	equ 0x0008  ; magic packet interrupt enable
273
	EXTCTL1_MPINT		equ 0x0010  ; magic packet interrupt
274
	EXTCTL1_MPPLBA		equ 0x0020  ; magic packet phys. logical bcast
275
	EXTCTL1_EXDEFEN 	equ 0x0040  ; excessive deferral interrupt enb.
276
	EXTCTL1_EXDEF		equ 0x0080  ; excessive deferral interrupt
277
	EXTCTL1_SINTEN		equ 0x0400  ; system interrupt enable
278
	EXTCTL1_SINT		equ 0x0800  ; system interrupt
279
	EXTCTL1_LTINTEN 	equ 0x4000  ; last TX interrupt enb
280
	EXTCTL1_TXOKINTD	equ 0x8000  ; TX OK interrupt disable
1196 hidnplayr 281
 
282
; RX/TX descriptor len (CSR6)
283
 
1519 hidnplayr 284
	DTBLLEN_RLEN		equ 0x0F00
285
	DTBLLEN_TLEN		equ 0xF000
1196 hidnplayr 286
 
287
; Extended control and interrupt 2 (CSR7)
288
 
1519 hidnplayr 289
	EXTCTL2_MIIPDTINTE	equ 0x0001
290
	EXTCTL2_MIIPDTINT	equ 0x0002
291
	EXTCTL2_MCCIINTE	equ 0x0004
292
	EXTCTL2_MCCIINT 	equ 0x0008
293
	EXTCTL2_MCCINTE 	equ 0x0010
294
	EXTCTL2_MCCINT		equ 0x0020
295
	EXTCTL2_MAPINTE 	equ 0x0040
296
	EXTCTL2_MAPINT		equ 0x0080
297
	EXTCTL2_MREINTE 	equ 0x0100
298
	EXTCTL2_MREINT		equ 0x0200
299
	EXTCTL2_STINTE		equ 0x0400
300
	EXTCTL2_STINT		equ 0x0800
301
	EXTCTL2_RXDPOLL 	equ 0x1000
302
	EXTCTL2_RDMD		equ 0x2000
303
	EXTCTL2_RXFRTG		equ 0x4000
304
	EXTCTL2_FASTSPNDE	equ 0x8000
1196 hidnplayr 305
 
306
; Mode (CSR15)
307
 
1519 hidnplayr 308
	MODE_RXD		equ 0x0001  ; RX disable
309
	MODE_TXD		equ 0x0002  ; TX disable
310
	MODE_LOOP		equ 0x0004  ; loopback enable
311
	MODE_TXCRCD		equ 0x0008
312
	MODE_FORCECOLL		equ 0x0010
313
	MODE_RETRYD		equ 0x0020
314
	MODE_INTLOOP		equ 0x0040
315
	MODE_PORTSEL		equ 0x0180
316
	MODE_RXVPAD		equ 0x2000
317
	MODE_RXNOBROAD		equ 0x4000
318
	MODE_PROMISC		equ 0x8000
1196 hidnplayr 319
 
320
; BCR (Bus Control Registers)
321
 
1519 hidnplayr 322
	BCR_MMRA		equ 0x00    ; Master Mode Read Active
323
	BCR_MMW 		equ 0x01    ; Master Mode Write Active
324
	BCR_MISCCFG		equ 0x02
325
	BCR_LED0		equ 0x04
326
	BCR_LED1		equ 0x05
327
	BCR_LED2		equ 0x06
328
	BCR_LED3		equ 0x07
329
	BCR_DUPLEX		equ 0x09
330
	BCR_BUSCTL		equ 0x12
331
	BCR_EECTL		equ 0x13
332
	BCR_SSTYLE		equ 0x14
333
	BCR_PCILAT		equ 0x16
334
	BCR_PCISUBVENID 	equ 0x17
335
	BCR_PCISUBSYSID 	equ 0x18
336
	BCR_SRAMSIZE		equ 0x19
337
	BCR_SRAMBOUND		equ 0x1A
338
	BCR_SRAMCTL		equ 0x1B
339
	BCR_MIICTL		equ 0x20
340
	BCR_MIIADDR		equ 0x21
341
	BCR_MIIDATA		equ 0x22
342
	BCR_PCIVENID		equ 0x23
343
	BCR_PCIPCAP		equ 0x24
344
	BCR_DATA0		equ 0x25
345
	BCR_DATA1		equ 0x26
346
	BCR_DATA2		equ 0x27
347
	BCR_DATA3		equ 0x28
348
	BCR_DATA4		equ 0x29
349
	BCR_DATA5		equ 0x2A
350
	BCR_DATA6		equ 0x2B
351
	BCR_DATA7		equ 0x2C
352
	BCR_ONNOWPAT0		equ 0x2D
353
	BCR_ONNOWPAT1		equ 0x2E
354
	BCR_ONNOWPAT2		equ 0x2F
355
	BCR_PHYSEL		equ 0x31
1196 hidnplayr 356
 
357
; RX status register
358
 
1519 hidnplayr 359
	RXSTAT_BPE		equ 0x0080  ; bus parity error
360
	RXSTAT_ENP		equ 0x0100  ; end of packet
361
	RXSTAT_STP		equ 0x0200  ; start of packet
362
	RXSTAT_BUFF		equ 0x0400  ; buffer error
363
	RXSTAT_CRC		equ 0x0800  ; CRC error
364
	RXSTAT_OFLOW		equ 0x1000  ; rx overrun
365
	RXSTAT_FRAM		equ 0x2000  ; framing error
366
	RXSTAT_ERR		equ 0x4000  ; error summary
367
	RXSTAT_OWN		equ 0x8000
1196 hidnplayr 368
 
369
; TX status register
370
 
1519 hidnplayr 371
	TXSTAT_TRC		equ 0x0000000F	    ; transmit retries
372
	TXSTAT_RTRY		equ 0x04000000	    ; retry
373
	TXSTAT_LCAR		equ 0x08000000	    ; lost carrier
374
	TXSTAT_LCOL		equ 0x10000000	    ; late collision
375
	TXSTAT_EXDEF		equ 0x20000000	    ; excessive deferrals
376
	TXSTAT_UFLOW		equ 0x40000000	    ; transmit underrun
377
	TXSTAT_BUFF		equ 0x80000000	    ; buffer error
1196 hidnplayr 378
 
1519 hidnplayr 379
	TXCTL_OWN		equ 0x80000000
380
	TXCTL_ERR		equ 0x40000000	    ; error summary
381
	TXCTL_ADD_FCS		equ 0x20000000	    ; add FCS to pkt
382
	TXCTL_MORE_LTINT	equ 0x10000000
383
	TXCTL_ONE		equ 0x08000000
384
	TXCTL_DEF		equ 0x04000000
385
	TXCTL_STP		equ 0x02000000
386
	TXCTL_ENP		equ 0x01000000
387
	TXCTL_BPE		equ 0x00800000
388
	TXCTL_MBO		equ 0x0000F000
389
	TXCTL_BUFSZ		equ 0x00000FFF
1196 hidnplayr 390
 
1519 hidnplayr 391
	MAX_ETH_FRAME_SIZE	equ 1514
1196 hidnplayr 392
 
393
 
394
section '.flat' code readable align 16
395
 
396
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
397
;;                        ;;
398
;; proc START             ;;
399
;;                        ;;
400
;; (standard driver proc) ;;
401
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
402
 
1492 hidnplayr 403
align 4
1196 hidnplayr 404
proc START stdcall, state:dword
405
 
406
	cmp [state], 1
407
	jne .exit
408
 
409
  .entry:
410
 
1492 hidnplayr 411
	DEBUGF	1,"Loading PCnet driver\n"
1196 hidnplayr 412
	stdcall RegService, my_service, service_proc
413
	ret
414
 
415
  .fail:
416
  .exit:
417
	xor eax, eax
418
	ret
419
 
420
endp
421
 
422
 
423
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
424
;;                        ;;
425
;; proc SERVICE_PROC      ;;
426
;;                        ;;
427
;; (standard driver proc) ;;
428
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
429
 
430
align 4
431
proc service_proc stdcall, ioctl:dword
432
 
433
	mov	edx, [ioctl]
1492 hidnplayr 434
	mov	eax, [IOCTL.io_code]
1196 hidnplayr 435
 
436
;------------------------------------------------------
437
 
438
	cmp	eax, 0 ;SRV_GETVERSION
439
	jne	@F
440
 
1492 hidnplayr 441
	cmp	[IOCTL.out_size], 4
1196 hidnplayr 442
	jl	.fail
1492 hidnplayr 443
	mov	eax, [IOCTL.output]
1196 hidnplayr 444
	mov	[eax], dword API_VERSION
445
 
446
	xor	eax, eax
447
	ret
448
 
449
;------------------------------------------------------
450
  @@:
451
	cmp	eax, 1 ;SRV_HOOK
452
	jne	.fail
453
 
1492 hidnplayr 454
	cmp	[IOCTL.inp_size], 3			; Data input must be at least 3 bytes
1196 hidnplayr 455
	jl	.fail
456
 
1492 hidnplayr 457
	mov	eax, [IOCTL.input]
1196 hidnplayr 458
	cmp	byte [eax], 1				; 1 means device number and bus number (pci) are given
459
	jne	.fail					; other types arent supported for this card yet
460
 
461
; check if the device is already listed
462
 
1519 hidnplayr 463
	mov	ecx, [devices]
1196 hidnplayr 464
	test	ecx, ecx
465
	jz	.firstdevice
1492 hidnplayr 466
 
1519 hidnplayr 467
	mov	esi, device_list
1492 hidnplayr 468
;        mov     eax, [IOCTL.input]                      ; get the pci bus and device numbers
469
	mov	ax , [eax+1]				;
1196 hidnplayr 470
  .nextdevice:
1492 hidnplayr 471
	mov	ebx, [esi]
472
	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 473
	je	.find_devicenum 			; Device is already loaded, let's find it's device number
1492 hidnplayr 474
	add	esi, 4
1196 hidnplayr 475
	loop	.nextdevice
476
 
477
; This device doesnt have its own eth_device structure yet, lets create one
478
 
479
  .firstdevice:
1519 hidnplayr 480
	cmp	[devices], MAX_DEVICES			; First check if the driver can handle one more card
1196 hidnplayr 481
	jge	.fail
482
 
483
	push	edx
484
	stdcall KernelAlloc, device.size		; Allocate the buffer for eth_device structure
485
	pop	edx
486
	test	eax, eax
487
	jz	.fail
488
	mov	ebx, eax				; ebx is always used as a pointer to the structure (in driver, but also in kernel code)
489
 
490
; Fill in the direct call addresses into the struct
491
 
1492 hidnplayr 492
	mov	[device.reset], reset
493
	mov	[device.transmit], transmit
494
	mov	[device.get_MAC], read_mac
495
	mov	[device.set_MAC], write_mac
496
	mov	[device.unload], unload
497
	mov	[device.name], my_service
1196 hidnplayr 498
 
499
; save the pci bus and device numbers
500
 
1492 hidnplayr 501
	mov	eax, [IOCTL.input]
1196 hidnplayr 502
	mov	cl , [eax+1]
1492 hidnplayr 503
	mov	[device.pci_bus], cl
1196 hidnplayr 504
	mov	cl , [eax+2]
1492 hidnplayr 505
	mov	[device.pci_dev], cl
1196 hidnplayr 506
 
507
; Now, it's time to find the base io addres of the PCI device
508
 
1492 hidnplayr 509
	find_io [device.pci_bus], [device.pci_dev], [device.io_addr]
1196 hidnplayr 510
 
511
; We've found the io address, find IRQ now
512
 
1492 hidnplayr 513
	find_irq [device.pci_bus], [device.pci_dev], [device.irq_line]
1196 hidnplayr 514
 
515
	DEBUGF	1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
1492 hidnplayr 516
	[device.pci_dev]:1,[device.pci_bus]:1,[device.irq_line]:1,[device.io_addr]:4
1196 hidnplayr 517
 
1541 hidnplayr 518
	allocate_and_clear [device.tx_buffer], (RX_RING_SIZE * PKT_BUF_SZ), .err
1519 hidnplayr 519
	allocate_and_clear [device.rx_buffer], (TX_RING_SIZE * PKT_BUF_SZ), .err
1196 hidnplayr 520
 
521
; Ok, the eth_device structure is ready, let's probe the device
1201 clevermous 522
; Because initialization fires IRQ, IRQ handler must be aware of this device
1519 hidnplayr 523
	mov	eax, [devices]						; Add the device structure to our device list
524
	mov	[device_list+4*eax], ebx				; (IRQ handler uses this list to find device)
525
	inc	[devices]						;
1196 hidnplayr 526
 
527
	call	probe							; this function will output in eax
528
	test	eax, eax
1492 hidnplayr 529
	jnz	.destroy						; If an error occured, exit
1196 hidnplayr 530
 
1514 hidnplayr 531
	mov	[device.type], NET_TYPE_ETH
532
	call	NetRegDev
533
 
1196 hidnplayr 534
	cmp	eax, -1
535
	je	.destroy
536
 
537
	ret
538
 
539
; If the device was already loaded, find the device number and return it in eax
540
 
541
  .find_devicenum:
542
	DEBUGF	1,"Trying to find device number of already registered device\n"
543
	mov	ebx, eax
1514 hidnplayr 544
	call	NetPtrToNum						; This kernel procedure converts a pointer to device struct in ebx
1196 hidnplayr 545
									; into a device number in edi
546
	mov	eax, edi						; Application wants it in eax instead
547
	DEBUGF	1,"Kernel says: %u\n", eax
548
	ret
549
 
550
; If an error occured, remove all allocated data and exit (returning -1 in eax)
551
 
552
  .destroy:
553
	; todo: reset device into virgin state
1519 hidnplayr 554
	dec	[devices]
1196 hidnplayr 555
  .err:
556
	DEBUGF	1,"Error, removing all data !\n"
1492 hidnplayr 557
	stdcall KernelFree, [device.rx_buffer]
1541 hidnplayr 558
	stdcall KernelFree, [device.tx_buffer]
1196 hidnplayr 559
	stdcall KernelFree, ebx
560
 
561
  .fail:
562
	or	eax, -1
563
	ret
564
 
565
;------------------------------------------------------
566
endp
567
 
568
 
569
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
570
;;                                                                        ;;
571
;;        Actual Hardware dependent code starts here                      ;;
572
;;                                                                        ;;
573
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
574
 
575
align 4
576
unload:
577
	; TODO: (in this particular order)
578
	;
579
	; - Stop the device
580
	; - Detach int handler
581
	; - Remove device from local list (RTL8139_LIST)
582
	; - call unregister function in kernel
583
	; - Remove all allocated structures and buffers the card used
584
 
585
	or	eax,-1
586
 
587
ret
588
 
589
 
590
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
591
;;
592
;;  probe: enables the device (if it really is a PCnet device)
593
;;
594
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
595
 
596
align 4
597
probe:
598
 
1541 hidnplayr 599
; make the device a bus master
600
 
1492 hidnplayr 601
	make_bus_master [device.pci_bus], [device.pci_dev]
602
 
1541 hidnplayr 603
; create the RX-ring
1492 hidnplayr 604
 
1541 hidnplayr 605
	lea	edi, [device.rx_ring]
1519 hidnplayr 606
	mov	ecx, RX_RING_SIZE
1492 hidnplayr 607
	mov	eax, [device.rx_buffer]
608
	call	GetPgAddr
609
  .rx_init:
610
	mov	[edi + buf_head.base], eax
1541 hidnplayr 611
	mov	[edi + buf_head.length], - PKT_BUF_SZ
1492 hidnplayr 612
	mov	[edi + buf_head.status], 0x8000
613
	and	dword [edi + buf_head.msg_length], 0
614
	and	dword [edi + buf_head.reserved], 0
1519 hidnplayr 615
	add	eax, PKT_BUF_SZ
1541 hidnplayr 616
	add	edi, buf_head.size
617
	loop	.rx_init
1492 hidnplayr 618
 
1541 hidnplayr 619
	lea	eax, [device.rx_ring]
620
	GetRealAddr
621
	mov	[device.rx_ring_phys], eax
622
 
623
; create the Tx-ring
624
 
625
	lea	edi, [device.tx_ring]
1519 hidnplayr 626
	mov	ecx, TX_RING_SIZE
1492 hidnplayr 627
	mov	eax, [device.tx_buffer]
628
	call	GetPgAddr
629
  .tx_init:
630
	mov	[edi + buf_head.base], eax
631
	and	dword [edi + buf_head.length], 0
632
	and	dword [edi + buf_head.msg_length], 0
633
	and	dword [edi + buf_head.reserved], 0
1519 hidnplayr 634
	add	eax, PKT_BUF_SZ
1492 hidnplayr 635
	add	edi, buf_head.size
636
	loop	.tx_init
637
 
1541 hidnplayr 638
	lea	eax, [device.tx_ring]
639
	GetRealAddr
640
	mov	[device.tx_ring_phys], eax
641
 
1519 hidnplayr 642
	mov	[device.tlen_rlen], (TX_RING_LEN_BITS or RX_RING_LEN_BITS)
1492 hidnplayr 643
 
1541 hidnplayr 644
; First, we must try to use Word operations
1492 hidnplayr 645
	call	switch_to_wio
646
	set_io	0
1196 hidnplayr 647
	call	wio_reset
648
 
649
	xor	ecx, ecx
650
	call	wio_read_csr
651
	cmp	eax, 4
652
	jne	.try_dwio
653
 
654
	; Try Word I/O
1541 hidnplayr 655
	mov	ax, 88
656
	set_io	WIO_RAP
657
	out	dx, ax
1196 hidnplayr 658
	nop
659
	nop
1541 hidnplayr 660
	in	ax, dx
661
	set_io	0
662
	cmp	ax, 88
1196 hidnplayr 663
	jne	.try_dwio
664
 
1541 hidnplayr 665
	DEBUGF	1,"Using WIO\n"
1196 hidnplayr 666
 
667
	call	switch_to_wio
668
 
669
	jmp	.L1
670
 
1541 hidnplayr 671
; If WIO fails, try to use DWIO
1196 hidnplayr 672
  .try_dwio:
673
	call	dwio_reset
674
 
1492 hidnplayr 675
	set_io	0
1196 hidnplayr 676
	xor	ecx, ecx
677
	call	dwio_read_csr
678
	cmp	eax, 4
679
	jne	.no_dev
680
 
681
	; Try Dword I/O
1519 hidnplayr 682
	set_io	DWIO_RAP
1196 hidnplayr 683
	mov	eax, 88
1541 hidnplayr 684
	out	dx, eax
1196 hidnplayr 685
	nop
686
	nop
687
	in	eax, dx
1492 hidnplayr 688
	set_io	0
1541 hidnplayr 689
	cmp	ax, 88
1196 hidnplayr 690
	jne	.no_dev
691
 
1541 hidnplayr 692
	DEBUGF	1,"Using DWIO\n"
1196 hidnplayr 693
 
694
	call	switch_to_dwio
695
 
696
	jmp	.L1
697
 
1541 hidnplayr 698
; If both methods fail, something is wrong!
1196 hidnplayr 699
  .no_dev:
1541 hidnplayr 700
	DEBUGF	1,"PCnet device not found!\n"
701
	mov	eax, -1
1196 hidnplayr 702
	ret
1541 hidnplayr 703
 
1196 hidnplayr 704
  .L1:
1519 hidnplayr 705
	mov	ecx, CSR_CHIPID0
1492 hidnplayr 706
	call	[device.access_read_csr]
1196 hidnplayr 707
	mov	esi, eax
708
 
1519 hidnplayr 709
	mov	ecx, CSR_CHIPID1
1492 hidnplayr 710
	call	[device.access_read_csr]
1196 hidnplayr 711
	shl	eax, 16
712
	or	eax, esi
713
 
714
	mov	ecx, eax
715
	and	ecx, 0xfff
716
	cmp	ecx, 3
717
	jne	.no_dev
718
 
719
	shr	eax, 12
720
	and	eax, 0xffff
1492 hidnplayr 721
	mov	[device.chip_version], eax
1196 hidnplayr 722
 
1541 hidnplayr 723
	DEBUGF	1,"chip version: %x\n", eax
724
 
1492 hidnplayr 725
	mov	[device.fdx], 0
726
	mov	[device.mii], 0
727
	mov	[device.fset], 0
728
	mov	[device.dxsuflo], 0
729
	mov	[device.ltint], 0
1196 hidnplayr 730
 
731
	cmp	eax, 0x2420
732
	je	.L2
733
	cmp	eax, 0x2430
734
	je	.L2
735
 
1492 hidnplayr 736
	mov	[device.fdx], 1
1196 hidnplayr 737
 
738
	cmp	eax, 0x2621
739
	je	.L4
740
	cmp	eax, 0x2623
741
	je	.L5
742
	cmp	eax, 0x2624
743
	je	.L6
744
	cmp	eax, 0x2625
745
	je	.L7
746
	cmp	eax, 0x2626
747
	je	.L8
748
	cmp	eax, 0x2627
749
	je	.L9
750
 
1541 hidnplayr 751
	DEBUGF	1,"Invalid chip rev\n"
1196 hidnplayr 752
	jmp	.no_dev
753
  .L2:
1492 hidnplayr 754
	mov	[device.name], device_l2
1196 hidnplayr 755
	jmp	.L10
756
  .L4:
1492 hidnplayr 757
	mov	[device.name], device_l4
758
;        mov     [device.fdx], 1
1196 hidnplayr 759
	jmp	.L10
760
  .L5:
1492 hidnplayr 761
	mov	[device.name], device_l5
762
;        mov     [device.fdx], 1
763
	mov	[device.mii], 1
764
	mov	[device.fset], 1
765
	mov	[device.ltint], 1
1196 hidnplayr 766
	jmp	.L10
767
  .L6:
1492 hidnplayr 768
	mov	[device.name], device_l6
769
;        mov     [device.fdx], 1
770
	mov	[device.mii], 1
771
	mov	[device.fset], 1
1196 hidnplayr 772
	jmp	.L10
773
  .L7:
1492 hidnplayr 774
	mov	[device.name], device_l7
775
;        mov     [device.fdx], 1
776
	mov	[device.mii], 1
1196 hidnplayr 777
	jmp	.L10
778
  .L8:
1492 hidnplayr 779
	mov	[device.name], device_l8
780
;        mov     [device.fdx], 1
1519 hidnplayr 781
	mov	ecx, CSR_RXPOLL
1492 hidnplayr 782
	call	[device.access_read_bcr]
783
	call	[device.access_write_bcr]
1196 hidnplayr 784
	jmp	.L10
785
  .L9:
1492 hidnplayr 786
	mov	[device.name], device_l9
787
;        mov     [device.fdx], 1
788
	mov	[device.mii], 1
1196 hidnplayr 789
  .L10:
1541 hidnplayr 790
	DEBUGF	1,"device name: %s\n",[device.name]
1196 hidnplayr 791
 
1492 hidnplayr 792
	cmp	[device.fset], 1
1196 hidnplayr 793
	jne	.L11
1519 hidnplayr 794
	mov	ecx, BCR_BUSCTL
1492 hidnplayr 795
	call	[device.access_read_bcr]
1541 hidnplayr 796
	or	ax, 0x800
1492 hidnplayr 797
	call	[device.access_write_bcr]
1196 hidnplayr 798
 
1519 hidnplayr 799
	mov	ecx, CSR_DMACTL
1492 hidnplayr 800
	call	[device.access_read_csr]
1196 hidnplayr 801
	mov	eax, 0xc00
1492 hidnplayr 802
	call	[device.access_write_csr]
1196 hidnplayr 803
 
1492 hidnplayr 804
	mov	[device.dxsuflo],1
805
	mov	[device.ltint],1
1196 hidnplayr 806
  .L11:
807
 
1541 hidnplayr 808
	mov	eax, PORT_ASEL			; Auto-select
1492 hidnplayr 809
	mov	[device.options], eax
810
	mov	[device.mode_], word 0x0003
1519 hidnplayr 811
	mov	[device.tlen_rlen], word (TX_RING_LEN_BITS or RX_RING_LEN_BITS)
1196 hidnplayr 812
 
1492 hidnplayr 813
	mov	dword [device.filter], 0
814
	mov	dword [device.filter+4], 0
1196 hidnplayr 815
 
1519 hidnplayr 816
	mov	eax, IMR
1541 hidnplayr 817
	mov	ecx, CSR_IMR			; Write interrupt mask
1492 hidnplayr 818
	call	[device.access_write_csr]
1196 hidnplayr 819
 
820
 
1492 hidnplayr 821
align 4
1196 hidnplayr 822
reset:
823
 
1541 hidnplayr 824
	DEBUGF	1,"Resetting PCnet device: %x\n", ebx
825
 
1196 hidnplayr 826
; attach int handler
827
 
1492 hidnplayr 828
	movzx	eax, [device.irq_line]
1196 hidnplayr 829
	DEBUGF	1,"Attaching int handler to irq %x\n",eax:1
830
	stdcall AttachIntHandler, eax, int_handler, dword 0
831
	test	eax, eax
832
	jnz	@f
833
	DEBUGF	1,"\nCould not attach int handler!\n"
834
;        or      eax, -1
835
;        ret
836
  @@:
837
 
1492 hidnplayr 838
	set_io	0
839
	call	[device.access_reset]		; after a reset, device will be in WIO mode!
1196 hidnplayr 840
 
1492 hidnplayr 841
; Switch to dword operations
1196 hidnplayr 842
 
1541 hidnplayr 843
	DEBUGF	1,"Switching to 32-bit mode\n"
1492 hidnplayr 844
 
1519 hidnplayr 845
	mov	ecx, DWIO_RDP
1541 hidnplayr 846
	xor	eax, eax
1492 hidnplayr 847
	call	wio_write_csr
848
 
849
	call	switch_to_dwio
850
 
851
; Lets find out if we are really in 32-bit mode now..
852
 
853
	set_io	0
1519 hidnplayr 854
	set_io	DWIO_RAP
1492 hidnplayr 855
	mov	eax, 88
1541 hidnplayr 856
	out	dx, eax
1492 hidnplayr 857
	nop
858
	nop
859
	in	eax, dx
860
	set_io	0
1541 hidnplayr 861
	cmp	ax, 88
1492 hidnplayr 862
	je	.yes_dwio
863
 
1541 hidnplayr 864
	call	switch_to_wio			; it seems to have failed, reset device again and use wio
1492 hidnplayr 865
	set_io	0
866
	call	[device.access_reset]
867
 
868
  .yes_dwio:
1541 hidnplayr 869
	set_io	0
870
	mov	ecx, BCR_SSTYLE 		; Select Software style 2      ;;;
871
	mov	eax, 2
872
	call	[device.access_write_bcr]
1492 hidnplayr 873
 
1196 hidnplayr 874
	; set/reset autoselect bit
1519 hidnplayr 875
	mov	ecx, BCR_MISCCFG
1492 hidnplayr 876
	call	[device.access_read_bcr]
1541 hidnplayr 877
 
1519 hidnplayr 878
	test	[device.options], PORT_ASEL
1541 hidnplayr 879
	jnz	 .L1
880
	and	eax, not 2
1196 hidnplayr 881
  .L1:
1492 hidnplayr 882
	call	[device.access_write_bcr]
1196 hidnplayr 883
 
884
 
885
	; Handle full duplex setting
1492 hidnplayr 886
	cmp	byte [device.full_duplex], 0
1196 hidnplayr 887
	je	.L2
1519 hidnplayr 888
	mov	ecx, BCR_DUPLEX
1492 hidnplayr 889
	call	[device.access_read_bcr]
1196 hidnplayr 890
	and	eax, not 3
1519 hidnplayr 891
	test	[device.options], PORT_FD
1196 hidnplayr 892
	jz	.L3
893
	or	eax, 1
1519 hidnplayr 894
	cmp	[device.options], PORT_FD or PORT_AUI
1196 hidnplayr 895
	jne	.L4
896
	or	eax, 2
897
	jmp	.L4
898
  .L3:
1519 hidnplayr 899
	test	[device.options], PORT_ASEL
1196 hidnplayr 900
	jz	.L4
1492 hidnplayr 901
	cmp	[device.chip_version], 0x2627
1196 hidnplayr 902
	jne	.L4
903
	or	eax, 3
904
  .L4:
1519 hidnplayr 905
	mov	ecx, BCR_DUPLEX
1492 hidnplayr 906
	call	[device.access_write_bcr]
1196 hidnplayr 907
  .L2:
908
 
909
 
910
	; set/reset GPSI bit in test register
911
	mov	ecx, 124
1492 hidnplayr 912
	call	[device.access_read_csr]
913
	mov	ecx, [device.options]
1519 hidnplayr 914
	and	ecx, PORT_PORTSEL
915
	cmp	ecx, PORT_GPSI
1196 hidnplayr 916
	jne	.L5
917
	or	eax, 0x10
918
  .L5:
1492 hidnplayr 919
	call	[device.access_write_csr]
920
	cmp	[device.mii], 0
1196 hidnplayr 921
	je	.L6
1519 hidnplayr 922
	test	[device.options], PORT_ASEL
1196 hidnplayr 923
	jnz	.L6
1519 hidnplayr 924
	mov	ecx, BCR_MIICTL
1492 hidnplayr 925
	call	[device.access_read_bcr]
1196 hidnplayr 926
	and	eax,not 0x38
1519 hidnplayr 927
	test	[device.options], PORT_FD
1196 hidnplayr 928
	jz	.L7
929
	or	eax, 0x10
930
  .L7:
1519 hidnplayr 931
	test	[device.options], PORT_100
1196 hidnplayr 932
	jz	.L8
933
	or	eax, 0x08
934
  .L8:
1492 hidnplayr 935
	call	[device.access_write_bcr]
1196 hidnplayr 936
	jmp	.L9
937
.L6:
1519 hidnplayr 938
	test	[device.options], PORT_ASEL
1196 hidnplayr 939
	jz	.L9
1519 hidnplayr 940
	mov	ecx, BCR_MIICTL
1541 hidnplayr 941
	DEBUGF	1,"ASEL, enable auto-negotiation\n"
1492 hidnplayr 942
	call	[device.access_read_bcr]
1196 hidnplayr 943
	and	eax, not 0x98
944
	or	eax, 0x20
1492 hidnplayr 945
	call	[device.access_write_bcr]
1196 hidnplayr 946
.L9:
1492 hidnplayr 947
	cmp	[device.ltint],0
1196 hidnplayr 948
	je	.L10
949
	mov	ecx,5
1492 hidnplayr 950
	call	[device.access_read_csr]
1196 hidnplayr 951
	or	eax,(1 shl 14)
1492 hidnplayr 952
	call	[device.access_write_csr]
1196 hidnplayr 953
.L10:
1492 hidnplayr 954
	mov	eax, [device.options]
1519 hidnplayr 955
	and	eax, PORT_PORTSEL
1492 hidnplayr 956
	shl	eax, 7
957
	mov	[device.mode_], ax
958
	mov	dword [device.filter], -1
959
	mov	dword [device.filter+4], -1
1196 hidnplayr 960
 
1201 clevermous 961
	call	read_mac
1196 hidnplayr 962
 
1492 hidnplayr 963
	lea	esi, [device.mac]
964
	lea	edi, [device.phys_addr]
1201 clevermous 965
	movsd
966
	movsw
967
 
1492 hidnplayr 968
	lea	eax, [device.private]
1541 hidnplayr 969
	GetRealAddr
1196 hidnplayr 970
	push	eax
971
	and	eax, 0xffff
972
	mov	ecx, 1
1492 hidnplayr 973
	call	[device.access_write_csr]
1196 hidnplayr 974
	pop	eax
1541 hidnplayr 975
	shr	eax, 16
976
	mov	ecx, 2
1492 hidnplayr 977
	call	[device.access_write_csr]
1196 hidnplayr 978
 
1541 hidnplayr 979
	mov	ecx, 4
980
	mov	eax, 0x0915
1492 hidnplayr 981
	call	[device.access_write_csr]
1196 hidnplayr 982
 
1541 hidnplayr 983
	xor	ecx, ecx
984
	mov	eax, 1
1492 hidnplayr 985
	call	[device.access_write_csr]
1196 hidnplayr 986
 
1541 hidnplayr 987
	mov	[device.tx_full], 0
988
	mov	[device.cur_rx], 0
989
	mov	[device.cur_tx], 0
990
	mov	[device.dirty_rx], 0
991
	mov	[device.dirty_tx], 0
1196 hidnplayr 992
 
1541 hidnplayr 993
	mov	ecx, 100
1196 hidnplayr 994
.L11:
995
	push	ecx
1492 hidnplayr 996
	xor	ecx, ecx
997
	call	[device.access_read_csr]
1196 hidnplayr 998
	pop	ecx
1541 hidnplayr 999
	push	esi
1000
	mov	esi, 100
1001
	call	Sleep
1002
	pop	esi
1003
	test	ax, 0x100
1196 hidnplayr 1004
	jnz	.L12
1005
	loop	.L11
1006
.L12:
1007
 
1492 hidnplayr 1008
	DEBUGF 1,"Starting up device\n"
1196 hidnplayr 1009
	xor	ecx, ecx
1010
	mov	eax, 0x0002
1492 hidnplayr 1011
	call	[device.access_write_csr]
1196 hidnplayr 1012
 
1013
	xor	ecx, ecx
1492 hidnplayr 1014
	call	[device.access_read_csr]
1196 hidnplayr 1015
 
1016
	xor	ecx, ecx
1519 hidnplayr 1017
	mov	eax, CSR_INTEN or CSR_START
1492 hidnplayr 1018
	call	[device.access_write_csr]
1196 hidnplayr 1019
 
1020
	DEBUGF 1,"PCNET reset complete\n"
1021
	xor	eax, eax
1492 hidnplayr 1022
; clear packet/byte counters
1023
	lea	edi, [device.bytes_tx]
1024
	mov	ecx, 6
1025
	rep	stosd
1026
 
1519 hidnplayr 1027
; Set the mtu, kernel will be able to send now
1028
	mov	[device.mtu], 1514
1029
 
1196 hidnplayr 1030
	ret
1031
 
1032
 
1033
 
1034
 
1035
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1036
;;                                         ;;
1037
;; Transmit                                ;;
1038
;;                                         ;;
1263 clevermous 1039
;; In: buffer pointer in [esp+4]           ;;
1254 hidnplayr 1040
;;     size of buffer in [esp+8]           ;;
1196 hidnplayr 1041
;;     pointer to device structure in ebx  ;;
1042
;;                                         ;;
1043
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1044
 
1045
align 4
1046
transmit:
1541 hidnplayr 1047
	DEBUGF	1,"Transmitting packet, buffer:%x, size:%u\n", [esp+4], [esp+8]
1254 hidnplayr 1048
	mov	eax, [esp+4]
1196 hidnplayr 1049
	DEBUGF	1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
1050
	[eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
1051
	[eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
1052
	[eax+13]:2,[eax+12]:2
1053
 
1254 hidnplayr 1054
	cmp	dword [esp+8], 1514
1196 hidnplayr 1055
	jg	.finish 			; packet is too long
1254 hidnplayr 1056
	cmp	dword [esp+8], 60
1196 hidnplayr 1057
	jl	.finish 			; packet is too short
1058
 
1059
; check descriptor
1492 hidnplayr 1060
	movzx	eax, [device.cur_tx]
1519 hidnplayr 1061
	imul	edi, eax, PKT_BUF_SZ
1201 clevermous 1062
	shl	eax, 4
1492 hidnplayr 1063
	add	edi, [device.tx_buffer]
1541 hidnplayr 1064
 
1065
	lea	eax, [eax + device.tx_ring]
1066
 
1201 clevermous 1067
	test	byte [eax + buf_head.status + 1], 80h
1068
	jnz	.nospace
1519 hidnplayr 1069
 
1201 clevermous 1070
; descriptor is free, copy data
1254 hidnplayr 1071
	mov	esi, [esp+4]
1072
	mov	ecx, [esp+8]
1201 clevermous 1073
	mov	edx, ecx
1074
	shr	ecx, 2
1075
	and	edx, 3
1076
	rep	movsd
1077
	mov	ecx, edx
1078
	rep	movsb
1519 hidnplayr 1079
 
1201 clevermous 1080
; set length
1254 hidnplayr 1081
	mov	ecx, [esp+8]
1201 clevermous 1082
	neg	ecx
1083
	mov	[eax + buf_head.length], cx
1084
; put to transfer queue
1085
	mov	[eax + buf_head.status], 0x8300
1196 hidnplayr 1086
 
1087
; trigger an immediate send
1201 clevermous 1088
	xor	ecx, ecx	 ; CSR0
1492 hidnplayr 1089
	call	[device.access_read_csr]
1519 hidnplayr 1090
	or	eax, CSR_TX
1492 hidnplayr 1091
	call	[device.access_write_csr]
1196 hidnplayr 1092
 
1093
; get next descriptor 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, ...
1492 hidnplayr 1094
	inc	[device.cur_tx]
1095
	and	[device.cur_tx], 3
1196 hidnplayr 1096
	DEBUGF	2," - Packet Sent! "
1097
 
1098
.finish:
1492 hidnplayr 1099
; update statistics
1100
	inc	[device.packets_tx]
1101
 
1102
	mov	ecx, [esp+8]
1103
	add	dword [device.bytes_tx], ecx
1104
	adc	dword [device.bytes_tx + 4], 0
1196 hidnplayr 1105
	DEBUGF	2," - Done!\n"
1519 hidnplayr 1106
 
1541 hidnplayr 1107
	stdcall KernelFree, [esp+4]
1108
	ret	8
1196 hidnplayr 1109
 
1201 clevermous 1110
.nospace:
1111
	DEBUGF	1, 'ERROR: no free transmit descriptors\n'
1112
; todo: maybe somehow notify the kernel about the error?
1519 hidnplayr 1113
 
1541 hidnplayr 1114
	stdcall KernelFree, [esp+4]
1115
	ret	8
1196 hidnplayr 1116
 
1117
 
1118
 
1119
;;;;;;;;;;;;;;;;;;;;;;;
1120
;;                   ;;
1121
;; Interrupt handler ;;
1122
;;                   ;;
1123
;;;;;;;;;;;;;;;;;;;;;;;
1124
 
1125
align 4
1126
int_handler:
1127
 
1541 hidnplayr 1128
	DEBUGF	1,"IRQ=%x ", eax:2		; no, you cant replace 'eax:2' with 'al', this must be a bug in FDO
1196 hidnplayr 1129
 
1130
; find pointer of device wich made IRQ occur
1131
 
1519 hidnplayr 1132
	mov	esi, device_list
1133
	mov	ecx, [devices]
1196 hidnplayr 1134
	test	ecx, ecx
1135
	jz	.abort
1136
  .nextdevice:
1492 hidnplayr 1137
	mov	ebx, [esi]
1138
	set_io	0
1196 hidnplayr 1139
 
1140
	push	ecx
1201 clevermous 1141
	xor	ecx, ecx ; CSR0
1492 hidnplayr 1142
	call	[device.access_read_csr]       ; get IRQ reason
1196 hidnplayr 1143
	pop	ecx
1144
 
1492 hidnplayr 1145
	test	ax , ax
1146
	jnz	.got_it
1196 hidnplayr 1147
 
1148
	add	esi, 4
1149
	loop	.nextdevice
1150
 
1492 hidnplayr 1151
	ret					; If no device was found, abort (The irq was probably for a device, not registered to this driver
1196 hidnplayr 1152
 
1153
  .got_it:
1541 hidnplayr 1154
	DEBUGF	1,"csr=%x\n", ax
1196 hidnplayr 1155
;-------------------------------------------------------
1201 clevermous 1156
; Possible reasons:
1157
; initialization done - ignore
1158
; transmit done - ignore
1159
; packet received - handle
1160
; Clear ALL IRQ reasons.
1161
; N.B. One who wants to handle more than one reason must be ready
1162
; to two or more reasons in one IRQ.
1163
	xor	ecx, ecx
1492 hidnplayr 1164
	call	[device.access_write_csr]
1196 hidnplayr 1165
; Received packet ok?
1166
 
1519 hidnplayr 1167
	test	ax, CSR_RINT
1196 hidnplayr 1168
	jz	@f
1169
 
1541 hidnplayr 1170
	push	ax
1171
 
1172
	DEBUGF	1,"packet received!\n"
1173
 
1174
 .receiver_test_loop:
1492 hidnplayr 1175
	movzx	eax, [device.cur_rx]
1519 hidnplayr 1176
;        and     eax, RX_RING_MOD_MASK
1196 hidnplayr 1177
	mov	edi, eax
1178
 
1519 hidnplayr 1179
	imul	esi, eax, PKT_BUF_SZ	  ;
1492 hidnplayr 1180
	add	esi, [device.rx_buffer] 	; esi now points to rx buffer
1196 hidnplayr 1181
 
1182
	shl	edi, 4				; desc * 16 (16 is size of one ring entry)
1541 hidnplayr 1183
	lea	edi, [edi + device.rx_ring]	; edi now points to current rx ring entry
1196 hidnplayr 1184
 
1185
	mov	cx , [edi + buf_head.status]
1186
 
1519 hidnplayr 1187
	test	cx , RXSTAT_OWN 	  ; If this bit is set, the controller OWN's the packet, if not, we do
1196 hidnplayr 1188
	jnz	.abort
1189
 
1519 hidnplayr 1190
	test	cx , RXSTAT_ENP
1196 hidnplayr 1191
	jz	.abort
1192
 
1519 hidnplayr 1193
	test	cx , RXSTAT_STP
1196 hidnplayr 1194
	jz	.abort
1195
 
1201 clevermous 1196
	movzx	ecx, [edi + buf_head.msg_length]	; get packet length in ecx
1196 hidnplayr 1197
	sub	ecx, 4				;
1198
 
1201 clevermous 1199
	push	ecx
1196 hidnplayr 1200
	stdcall KernelAlloc, ecx		; Allocate a buffer to put packet into
1201 clevermous 1201
	pop	ecx
1196 hidnplayr 1202
	test	eax, eax			; Test if we allocated succesfully
1203
	jz	.abort				;
1204
 
1251 clevermous 1205
	push	.receiver_test_loop		;
1196 hidnplayr 1206
	push	ecx				; for eth_receiver
1207
	push	eax				;
1208
 
1492 hidnplayr 1209
; update statistics
1210
	inc	[device.packets_rx]
1211
 
1212
	add	dword [device.bytes_rx], ecx
1213
	adc	dword [device.bytes_rx + 4], 0
1214
 
1196 hidnplayr 1215
	xchg	edi, eax
1492 hidnplayr 1216
 
1217
; copy packet data
1218
	shr	cx , 1
1219
	jnc	.nb
1220
	movsb
1221
  .nb:
1222
	shr	cx , 1
1223
	jnc	.nw
1224
	movsw
1225
  .nw:
1196 hidnplayr 1226
	rep	movsd
1227
 
1519 hidnplayr 1228
;       mov     word [eax + buf_head.length], PKT_BUF_SZ_NEG
1229
	mov	word [eax + buf_head.status], RXSTAT_OWN      ; Set OWN bit back to 1 (controller may write to tx-buffer again now)
1196 hidnplayr 1230
 
1492 hidnplayr 1231
	inc	[device.cur_rx] 	  ; update descriptor
1232
	and	[device.cur_rx], 3	  ;
1196 hidnplayr 1233
 
1492 hidnplayr 1234
	DEBUGF	1,"Inserting packet\n"
1196 hidnplayr 1235
	jmp	EthReceiver			; Send the copied packet to kernel
1236
 
1237
  .abort:
1541 hidnplayr 1238
	pop	ax
1196 hidnplayr 1239
  @@:
1240
 
1541 hidnplayr 1241
	test	ax, IMR_TINT
1242
	jz	@f
1243
 
1244
	DEBUGF	1,"Transmit OK!\n"
1245
 
1246
  @@:
1247
 
1248
	test	ax, IMR_MISS
1249
	jz	@f
1250
 
1251
	DEBUGF	1,"We missed a frame! (RX ring full?)\n"
1252
 
1253
  @@:
1254
 
1255
	DEBUGF	1,"done\n"
1256
 
1196 hidnplayr 1257
	ret
1258
 
1259
 
1260
 
1261
 
1262
;;;;;;;;;;;;;;;;;;;;;;;
1263
;;                   ;;
1264
;; Write MAC address ;;
1265
;;                   ;;
1266
;;;;;;;;;;;;;;;;;;;;;;;
1267
 
1268
align 4
1269
write_mac:	; in: mac pushed onto stack (as 3 words)
1270
 
1271
	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
1272
 
1541 hidnplayr 1273
	set_io	0
1274
;        set_io  2
1196 hidnplayr 1275
	xor	eax, eax
1519 hidnplayr 1276
	mov	ecx, CSR_PAR0
1196 hidnplayr 1277
       @@:
1278
	pop	ax
1492 hidnplayr 1279
	call	[device.access_write_csr]
1196 hidnplayr 1280
	DEBUGF	1,"."
1281
	inc	ecx
1519 hidnplayr 1282
	cmp	ecx, CSR_PAR2
1196 hidnplayr 1283
	jl	@r
1284
 
1285
	DEBUGF	1,"\n"
1286
 
1287
; Notice this procedure does not ret, but continues to read_mac instead.
1288
 
1289
;;;;;;;;;;;;;;;;;;;;;;
1290
;;                  ;;
1291
;; Read MAC address ;;
1292
;;                  ;;
1293
;;;;;;;;;;;;;;;;;;;;;;
1294
 
1492 hidnplayr 1295
read_mac:
1196 hidnplayr 1296
	DEBUGF	1,"Reading MAC"
1297
 
1541 hidnplayr 1298
	set_io	0
1299
	set_io	6
1196 hidnplayr 1300
       @@:
1301
	dec	dx
1302
	dec	dx
1303
	in	ax, dx
1304
	push	ax
1305
	DEBUGF	1,"."
1492 hidnplayr 1306
	cmp	edx, [device.io_addr]
1196 hidnplayr 1307
	jg	@r
1308
 
1309
	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
1310
 
1492 hidnplayr 1311
	lea	edi, [device.mac]
1196 hidnplayr 1312
	pop	ax
1313
	stosw
1314
	pop	ax
1315
	stosw
1316
	pop	ax
1317
	stosw
1318
 
1319
	ret
1320
 
1321
 
1322
switch_to_wio:
1492 hidnplayr 1323
	DEBUGF	1,"Switch to WIO\n"
1196 hidnplayr 1324
 
1492 hidnplayr 1325
	mov	[device.access_read_csr], wio_read_csr
1326
	mov	[device.access_write_csr], wio_write_csr
1327
	mov	[device.access_read_bcr], wio_read_bcr
1328
	mov	[device.access_write_bcr], wio_write_bcr
1329
	mov	[device.access_read_rap], wio_read_rap
1330
	mov	[device.access_write_rap], wio_write_rap
1331
	mov	[device.access_reset], wio_reset
1196 hidnplayr 1332
 
1333
	ret
1334
 
1335
switch_to_dwio:
1492 hidnplayr 1336
	DEBUGF	1,"Switch to DWIO\n"
1196 hidnplayr 1337
 
1492 hidnplayr 1338
	mov	[device.access_read_csr], dwio_read_csr
1339
	mov	[device.access_write_csr], dwio_write_csr
1340
	mov	[device.access_read_bcr], dwio_read_bcr
1341
	mov	[device.access_write_bcr], dwio_write_bcr
1342
	mov	[device.access_read_rap], dwio_read_rap
1343
	mov	[device.access_write_rap], dwio_write_rap
1344
	mov	[device.access_reset], dwio_reset
1196 hidnplayr 1345
 
1346
	ret
1347
 
1348
 
1349
 
1350
 
1351
 
1352
; ecx - index
1353
; return:
1354
; eax - data
1355
wio_read_csr:
1356
 
1519 hidnplayr 1357
	add	edx, WIO_RAP
1196 hidnplayr 1358
	mov	ax , cx
1359
	out	dx , ax
1519 hidnplayr 1360
	add	edx, WIO_RDP - WIO_RAP
1196 hidnplayr 1361
	in	ax , dx
1362
	and	eax, 0xffff
1519 hidnplayr 1363
	sub	edx, WIO_RDP
1196 hidnplayr 1364
 
1365
	ret
1366
 
1367
 
1368
; eax - data
1369
; ecx - index
1370
wio_write_csr:
1371
 
1519 hidnplayr 1372
	add	edx, WIO_RAP
1196 hidnplayr 1373
	xchg	eax, ecx
1374
	out	dx , ax
1375
	xchg	eax, ecx
1519 hidnplayr 1376
	add	edx, WIO_RDP - WIO_RAP
1196 hidnplayr 1377
	out	dx , ax
1519 hidnplayr 1378
	sub	edx, WIO_RDP
1196 hidnplayr 1379
 
1380
	ret
1381
 
1382
 
1383
; ecx - index
1384
; return:
1385
; eax - data
1386
wio_read_bcr:
1387
 
1519 hidnplayr 1388
	add	edx, WIO_RAP
1196 hidnplayr 1389
	mov	ax , cx
1390
	out	dx , ax
1519 hidnplayr 1391
	add	edx, WIO_BDP - WIO_RAP
1196 hidnplayr 1392
	in	ax , dx
1393
	and	eax, 0xffff
1519 hidnplayr 1394
	sub	edx, WIO_BDP
1196 hidnplayr 1395
 
1396
	ret
1397
 
1398
 
1399
; eax - data
1400
; ecx - index
1401
wio_write_bcr:
1402
 
1519 hidnplayr 1403
	add	edx, WIO_RAP
1196 hidnplayr 1404
	xchg	eax, ecx
1405
	out	dx , ax
1406
	xchg	eax, ecx
1519 hidnplayr 1407
	add	edx, WIO_BDP - WIO_RAP
1196 hidnplayr 1408
	out	dx , ax
1519 hidnplayr 1409
	sub	edx, WIO_BDP
1196 hidnplayr 1410
 
1411
	ret
1412
 
1413
 
1414
wio_read_rap:
1415
 
1519 hidnplayr 1416
	add	edx, WIO_RAP
1196 hidnplayr 1417
	in	ax , dx
1418
	and	eax, 0xffff
1519 hidnplayr 1419
	sub	edx, WIO_RAP
1196 hidnplayr 1420
 
1421
	ret
1422
 
1423
; eax - val
1424
wio_write_rap:
1425
 
1519 hidnplayr 1426
	add	edx, WIO_RAP
1196 hidnplayr 1427
	out	dx , ax
1519 hidnplayr 1428
	sub	edx, WIO_RAP
1196 hidnplayr 1429
 
1430
	ret
1431
 
1432
wio_reset:
1433
 
1434
	push	eax
1519 hidnplayr 1435
	add	edx, WIO_RESET
1196 hidnplayr 1436
	in	ax , dx
1437
	pop	eax
1519 hidnplayr 1438
	sub	edx, WIO_RESET
1196 hidnplayr 1439
 
1440
	ret
1441
 
1442
 
1443
; ecx - index
1444
; return:
1445
; eax - data
1446
dwio_read_csr:
1447
 
1519 hidnplayr 1448
	add	edx, DWIO_RAP
1201 clevermous 1449
	mov	eax, ecx
1196 hidnplayr 1450
	out	dx , eax
1519 hidnplayr 1451
	add	edx, DWIO_RDP - DWIO_RAP
1196 hidnplayr 1452
	in	eax, dx
1453
	and	eax, 0xffff
1519 hidnplayr 1454
	sub	edx, DWIO_RDP
1196 hidnplayr 1455
 
1456
	ret
1457
 
1458
 
1459
; ecx - index
1460
; eax - data
1461
dwio_write_csr:
1462
 
1519 hidnplayr 1463
	add	edx, DWIO_RAP
1196 hidnplayr 1464
	xchg	eax, ecx
1465
	out	dx , eax
1519 hidnplayr 1466
	add	edx, DWIO_RDP - DWIO_RAP
1196 hidnplayr 1467
	xchg	eax, ecx
1468
	out	dx , eax
1519 hidnplayr 1469
	sub	edx, DWIO_RDP
1196 hidnplayr 1470
 
1471
	ret
1472
 
1473
; ecx - index
1474
; return:
1475
; eax - data
1476
dwio_read_bcr:
1477
 
1519 hidnplayr 1478
	add	edx, DWIO_RAP
1201 clevermous 1479
	mov	eax, ecx
1196 hidnplayr 1480
	out	dx , eax
1519 hidnplayr 1481
	add	edx, DWIO_BDP - DWIO_RAP
1196 hidnplayr 1482
	in	eax, dx
1483
	and	eax, 0xffff
1519 hidnplayr 1484
	sub	edx, DWIO_BDP
1196 hidnplayr 1485
 
1486
	ret
1487
 
1488
 
1489
; ecx - index
1490
; eax - data
1491
dwio_write_bcr:
1492
 
1519 hidnplayr 1493
	add	edx, DWIO_RAP
1196 hidnplayr 1494
	xchg	eax, ecx
1495
	out	dx , eax
1519 hidnplayr 1496
	add	edx, DWIO_BDP - DWIO_RAP
1196 hidnplayr 1497
	xchg	eax, ecx
1498
	out	dx , eax
1519 hidnplayr 1499
	sub	edx, DWIO_BDP
1196 hidnplayr 1500
 
1501
	ret
1502
 
1503
 
1504
dwio_read_rap:
1505
 
1519 hidnplayr 1506
	add	edx, DWIO_RAP
1196 hidnplayr 1507
	in	eax, dx
1508
	and	eax, 0xffff
1519 hidnplayr 1509
	sub	edx, DWIO_RAP
1196 hidnplayr 1510
 
1511
	ret
1512
 
1513
 
1514
; eax - val
1515
dwio_write_rap:
1516
 
1519 hidnplayr 1517
	add	edx, DWIO_RAP
1196 hidnplayr 1518
	out	dx , eax
1519 hidnplayr 1519
	sub	edx, DWIO_RAP
1196 hidnplayr 1520
 
1521
	ret
1522
 
1523
 
1524
dwio_reset:
1525
 
1526
	push	eax
1519 hidnplayr 1527
	add	edx, DWIO_RESET
1196 hidnplayr 1528
	in	eax, dx
1529
	pop	eax
1519 hidnplayr 1530
	sub	edx, DWIO_RESET
1196 hidnplayr 1531
 
1532
	ret
1533
 
1534
 
1535
 
1536
; End of code
1541 hidnplayr 1537
align 4 					  ; Place all initialised data here
1196 hidnplayr 1538
 
1519 hidnplayr 1539
devices       dd 0
1540
version       dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
1541 hidnplayr 1541
my_service    db 'PCnet',0			  ; max 16 chars include zero
1196 hidnplayr 1542
 
1543
device_l2     db "PCnet/PCI 79C970",0
1544
device_l4     db "PCnet/PCI II 79C970A",0
1545
device_l5     db "PCnet/FAST 79C971",0
1546
device_l6     db "PCnet/FAST+ 79C972",0
1547
device_l7     db "PCnet/FAST III 79C973",0
1548
device_l8     db "PCnet/Home 79C978",0
1549
device_l9     db "PCnet/FAST III 79C975",0
1550
 
1551
options_mapping:
1519 hidnplayr 1552
dd PORT_ASEL					  ;  0 Auto-select
1553
dd PORT_AUI					  ;  1 BNC/AUI
1554
dd PORT_AUI					  ;  2 AUI/BNC
1555
dd PORT_ASEL					  ;  3 not supported
1556
dd PORT_10BT or PORT_FD 			  ;  4 10baseT-FD
1557
dd PORT_ASEL					  ;  5 not supported
1558
dd PORT_ASEL					  ;  6 not supported
1559
dd PORT_ASEL					  ;  7 not supported
1560
dd PORT_ASEL					  ;  8 not supported
1561
dd PORT_MII					  ;  9 MII 10baseT
1562
dd PORT_MII or PORT_FD				  ; 10 MII 10baseT-FD
1563
dd PORT_MII					  ; 11 MII (autosel)
1564
dd PORT_10BT					  ; 12 10BaseT
1565
dd PORT_MII or PORT_100 			  ; 13 MII 100BaseTx
1566
dd PORT_MII or PORT_100 or PORT_FD		  ; 14 MII 100BaseTx-FD
1567
dd PORT_ASEL					  ; 15 not supported
1196 hidnplayr 1568
 
1569
include_debug_strings					; All data wich FDO uses will be included here
1570
 
1571
section '.data' data readable writable align 16 	; place all uninitialized data place here
1572
 
1519 hidnplayr 1573
device_list	 rd MAX_DEVICES 			; This list contains all pointers to device structures the driver is handling