Subversion Repositories Kolibri OS

Rev

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