Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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