Subversion Repositories Kolibri OS

Rev

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