Subversion Repositories Kolibri OS

Rev

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