Subversion Repositories Kolibri OS

Rev

Rev 1492 | 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: 1514 $
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
 
1514 hidnplayr 556
	mov	[device.type], NET_TYPE_ETH
557
	call	NetRegDev
558
 
1196 hidnplayr 559
	cmp	eax, -1
560
	je	.destroy
561
 
562
	ret
563
 
564
; If the device was already loaded, find the device number and return it in eax
565
 
566
  .find_devicenum:
567
	DEBUGF	1,"Trying to find device number of already registered device\n"
568
	mov	ebx, eax
1514 hidnplayr 569
	call	NetPtrToNum						; This kernel procedure converts a pointer to device struct in ebx
1196 hidnplayr 570
									; into a device number in edi
571
	mov	eax, edi						; Application wants it in eax instead
572
	DEBUGF	1,"Kernel says: %u\n", eax
573
	ret
574
 
575
; If an error occured, remove all allocated data and exit (returning -1 in eax)
576
 
577
  .destroy:
578
	; todo: reset device into virgin state
1201 clevermous 579
	dec	[PCNET_DEV]
1196 hidnplayr 580
  .err:
581
	DEBUGF	1,"Error, removing all data !\n"
1492 hidnplayr 582
	stdcall KernelFree, [device.rx_buffer]
583
	stdcall KernelFree, [device.tx_buffer]
1196 hidnplayr 584
	stdcall KernelFree, ebx
585
 
586
  .fail:
587
	or	eax, -1
588
	ret
589
 
590
;------------------------------------------------------
591
endp
592
 
593
 
594
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
595
;;                                                                        ;;
596
;;        Actual Hardware dependent code starts here                      ;;
597
;;                                                                        ;;
598
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
599
 
600
align 4
601
unload:
602
	; TODO: (in this particular order)
603
	;
604
	; - Stop the device
605
	; - Detach int handler
606
	; - Remove device from local list (RTL8139_LIST)
607
	; - call unregister function in kernel
608
	; - Remove all allocated structures and buffers the card used
609
 
610
	or	eax,-1
611
 
612
ret
613
 
614
 
615
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
616
;;
617
;;  probe: enables the device (if it really is a PCnet device)
618
;;
619
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
620
 
621
align 4
622
probe:
623
 
1492 hidnplayr 624
	make_bus_master [device.pci_bus], [device.pci_dev]
625
 
626
; first, fill in some of the structure variables
627
 
628
	mov	edi, [device.rx_ring]
629
	mov	ecx, PCNET_RX_RING_SIZE
630
	mov	eax, [device.rx_buffer]
631
	call	GetPgAddr
632
  .rx_init:
633
	mov	[edi + buf_head.base], eax
634
	mov	[edi + buf_head.length], PCNET_PKT_BUF_SZ_NEG
635
	mov	[edi + buf_head.status], 0x8000
636
	and	dword [edi + buf_head.msg_length], 0
637
	and	dword [edi + buf_head.reserved], 0
638
	add	eax, PCNET_PKT_BUF_SZ
639
;        inc     eax
640
	add	 edi, buf_head.size
641
	loop	 .rx_init
642
 
643
	mov	edi, [device.tx_ring]
644
	mov	ecx, PCNET_TX_RING_SIZE
645
	mov	eax, [device.tx_buffer]
646
	call	GetPgAddr
647
  .tx_init:
648
	mov	[edi + buf_head.base], eax
649
	and	dword [edi + buf_head.length], 0
650
	and	dword [edi + buf_head.msg_length], 0
651
	and	dword [edi + buf_head.reserved], 0
652
	add	eax, PCNET_PKT_BUF_SZ
653
	add	edi, buf_head.size
654
	loop	.tx_init
655
 
656
	mov	[device.tlen_rlen], (PCNET_TX_RING_LEN_BITS or PCNET_RX_RING_LEN_BITS)
657
 
658
	; First, we must try to use Word operations
659
	call	switch_to_wio
660
	set_io	0
1196 hidnplayr 661
	call	wio_reset
662
 
663
	xor	ecx, ecx
664
	call	wio_read_csr
665
	cmp	eax, 4
666
	jne	.try_dwio
667
 
668
	; Try Word I/O
669
	mov	ax , 88
670
	add	edx, PCNET_WIO_RAP
671
	out	dx , ax
672
	nop
673
	nop
674
	in	ax , dx
675
	sub	edx, PCNET_WIO_RAP
676
	cmp	ax , 88
677
	jne	.try_dwio
678
 
679
	DEBUGF 1,"Using WIO\n"
680
 
681
	call	switch_to_wio
682
 
683
	jmp	.L1
684
 
685
  .try_dwio:
686
	call	dwio_reset
687
 
1492 hidnplayr 688
	set_io	0
1196 hidnplayr 689
	xor	ecx, ecx
690
	call	dwio_read_csr
691
	cmp	eax, 4
692
	jne	.no_dev
693
 
694
	; Try Dword I/O
1492 hidnplayr 695
	set_io	PCNET_DWIO_RAP
1196 hidnplayr 696
	mov	eax, 88
697
	out	dx , eax
698
	nop
699
	nop
700
	in	eax, dx
1492 hidnplayr 701
	set_io	0
1196 hidnplayr 702
	and	eax, 0xffff
703
	cmp	eax, 88
704
	jne	.no_dev
705
 
706
	DEBUGF 1,"Using DWIO\n"
707
 
708
	call	switch_to_dwio
709
 
710
	jmp	.L1
711
 
712
  .no_dev:
713
	DEBUGF 1,"PCnet device not found!\n"
714
	mov	eax, 1
715
	ret
716
  .L1:
717
 
718
	mov	ecx, PCNET_CSR_CHIPID0
1492 hidnplayr 719
	call	[device.access_read_csr]
1196 hidnplayr 720
	mov	esi, eax
721
 
722
	mov	ecx, PCNET_CSR_CHIPID1
1492 hidnplayr 723
	call	[device.access_read_csr]
1196 hidnplayr 724
	shl	eax, 16
725
	or	eax, esi
726
 
727
	mov	ecx, eax
728
	and	ecx, 0xfff
729
	cmp	ecx, 3
730
	jne	.no_dev
731
 
732
	shr	eax, 12
733
	and	eax, 0xffff
1492 hidnplayr 734
	mov	[device.chip_version], eax
1196 hidnplayr 735
 
736
	DEBUGF 1,"chip version ok\n"
1492 hidnplayr 737
	mov	[device.fdx], 0
738
	mov	[device.mii], 0
739
	mov	[device.fset], 0
740
	mov	[device.dxsuflo], 0
741
	mov	[device.ltint], 0
1196 hidnplayr 742
 
743
	cmp	eax, 0x2420
744
	je	.L2
745
	cmp	eax, 0x2430
746
	je	.L2
747
 
1492 hidnplayr 748
	mov	[device.fdx], 1
1196 hidnplayr 749
 
750
	cmp	eax, 0x2621
751
	je	.L4
752
	cmp	eax, 0x2623
753
	je	.L5
754
	cmp	eax, 0x2624
755
	je	.L6
756
	cmp	eax, 0x2625
757
	je	.L7
758
	cmp	eax, 0x2626
759
	je	.L8
760
	cmp	eax, 0x2627
761
	je	.L9
762
 
763
	DEBUGF 1,"Invalid chip rev\n"
764
	jmp	.no_dev
765
  .L2:
1492 hidnplayr 766
	mov	[device.name], device_l2
1196 hidnplayr 767
	jmp	.L10
768
  .L4:
1492 hidnplayr 769
	mov	[device.name], device_l4
770
;        mov     [device.fdx], 1
1196 hidnplayr 771
	jmp	.L10
772
  .L5:
1492 hidnplayr 773
	mov	[device.name], device_l5
774
;        mov     [device.fdx], 1
775
	mov	[device.mii], 1
776
	mov	[device.fset], 1
777
	mov	[device.ltint], 1
1196 hidnplayr 778
	jmp	.L10
779
  .L6:
1492 hidnplayr 780
	mov	[device.name], device_l6
781
;        mov     [device.fdx], 1
782
	mov	[device.mii], 1
783
	mov	[device.fset], 1
1196 hidnplayr 784
	jmp	.L10
785
  .L7:
1492 hidnplayr 786
	mov	[device.name], device_l7
787
;        mov     [device.fdx], 1
788
	mov	[device.mii], 1
1196 hidnplayr 789
	jmp	.L10
790
  .L8:
1492 hidnplayr 791
	mov	[device.name], device_l8
792
;        mov     [device.fdx], 1
1196 hidnplayr 793
	mov	ecx, PCNET_CSR_RXPOLL
1492 hidnplayr 794
	call	[device.access_read_bcr]
795
	call	[device.access_write_bcr]
1196 hidnplayr 796
	jmp	.L10
797
  .L9:
1492 hidnplayr 798
	mov	[device.name], device_l9
799
;        mov     [device.fdx], 1
800
	mov	[device.mii], 1
1196 hidnplayr 801
  .L10:
1492 hidnplayr 802
	DEBUGF 1,"device name: %s\n",[device.name]
1196 hidnplayr 803
 
1492 hidnplayr 804
	cmp	[device.fset], 1
1196 hidnplayr 805
	jne	.L11
806
	mov	ecx, PCNET_BCR_BUSCTL
1492 hidnplayr 807
	call	[device.access_read_bcr]
1196 hidnplayr 808
	or	eax, 0x800
1492 hidnplayr 809
	call	[device.access_write_bcr]
1196 hidnplayr 810
 
811
	mov	ecx, PCNET_CSR_DMACTL
1492 hidnplayr 812
	call	[device.access_read_csr]
1196 hidnplayr 813
;        and     eax, 0xc00
814
;        or      eax, 0xc00
815
	mov	eax, 0xc00
1492 hidnplayr 816
	call	[device.access_write_csr]
1196 hidnplayr 817
 
1492 hidnplayr 818
	mov	[device.dxsuflo],1
819
	mov	[device.ltint],1
1196 hidnplayr 820
  .L11:
821
 
822
	DEBUGF 1,"PCI done\n"
823
	mov	eax, PCNET_PORT_ASEL
1492 hidnplayr 824
	mov	[device.options], eax
825
	mov	[device.mode_], word 0x0003
826
	mov	[device.tlen_rlen], word (PCNET_TX_RING_LEN_BITS or PCNET_RX_RING_LEN_BITS)
1196 hidnplayr 827
 
1492 hidnplayr 828
	mov	dword [device.filter], 0
829
	mov	dword [device.filter+4], 0
1196 hidnplayr 830
 
831
	mov	eax, PCNET_IMR
832
	mov	ecx, PCNET_CSR_IMR			; Write interrupt mask
1492 hidnplayr 833
	call	[device.access_write_csr]
1196 hidnplayr 834
 
835
 
836
 
837
 
838
 
1492 hidnplayr 839
align 4
1196 hidnplayr 840
reset:
841
 
842
; attach int handler
843
 
1492 hidnplayr 844
	movzx	eax, [device.irq_line]
1196 hidnplayr 845
	DEBUGF	1,"Attaching int handler to irq %x\n",eax:1
846
	stdcall AttachIntHandler, eax, int_handler, dword 0
847
	test	eax, eax
848
	jnz	@f
849
	DEBUGF	1,"\nCould not attach int handler!\n"
850
;        or      eax, -1
851
;        ret
852
  @@:
853
 
1492 hidnplayr 854
	set_io	0
855
	call	[device.access_reset]		; after a reset, device will be in WIO mode!
1196 hidnplayr 856
 
1492 hidnplayr 857
; Switch to dword operations
1196 hidnplayr 858
 
1492 hidnplayr 859
	DEBUGF 1,"Switching to 32-bit mode\n"
860
 
861
	mov	ecx, PCNET_DWIO_RDP
862
	mov	eax, 0
863
	call	wio_write_csr
864
 
865
	call	switch_to_dwio
866
 
867
; Lets find out if we are really in 32-bit mode now..
868
 
869
	set_io	0
870
	set_io	PCNET_DWIO_RAP
871
	mov	eax, 88
872
	out	dx , eax
873
	nop
874
	nop
875
	in	eax, dx
876
	set_io	0
877
	and	eax, 0xffff
878
	cmp	eax, 88
879
	je	.yes_dwio
880
 
881
	call	switch_to_wio			; it seem to have failed, reset device again and use wio
882
	set_io	0
883
	call	[device.access_reset]
884
 
885
  .yes_dwio:
886
 
1196 hidnplayr 887
	; set/reset autoselect bit
888
	mov	ecx, PCNET_BCR_MISCCFG
1492 hidnplayr 889
	call	[device.access_read_bcr]
1196 hidnplayr 890
	and	eax,not 2
1492 hidnplayr 891
	test	[device.options], PCNET_PORT_ASEL
1196 hidnplayr 892
	jz	.L1
893
	or	eax, 2
894
  .L1:
1492 hidnplayr 895
	call	[device.access_write_bcr]
1196 hidnplayr 896
 
897
 
898
	; Handle full duplex setting
1492 hidnplayr 899
	cmp	byte [device.full_duplex], 0
1196 hidnplayr 900
	je	.L2
901
	mov	ecx, PCNET_BCR_DUPLEX
1492 hidnplayr 902
	call	[device.access_read_bcr]
1196 hidnplayr 903
	and	eax, not 3
1492 hidnplayr 904
	test	[device.options], PCNET_PORT_FD
1196 hidnplayr 905
	jz	.L3
906
	or	eax, 1
1492 hidnplayr 907
	cmp	[device.options], PCNET_PORT_FD or PCNET_PORT_AUI
1196 hidnplayr 908
	jne	.L4
909
	or	eax, 2
910
	jmp	.L4
911
  .L3:
1492 hidnplayr 912
	test	[device.options], PCNET_PORT_ASEL
1196 hidnplayr 913
	jz	.L4
1492 hidnplayr 914
	cmp	[device.chip_version], 0x2627
1196 hidnplayr 915
	jne	.L4
916
	or	eax, 3
917
  .L4:
918
	mov	ecx, PCNET_BCR_DUPLEX
1492 hidnplayr 919
	call	[device.access_write_bcr]
1196 hidnplayr 920
  .L2:
921
 
922
 
923
	; set/reset GPSI bit in test register
924
	mov	ecx, 124
1492 hidnplayr 925
	call	[device.access_read_csr]
926
	mov	ecx, [device.options]
1196 hidnplayr 927
	and	ecx, PCNET_PORT_PORTSEL
928
	cmp	ecx, PCNET_PORT_GPSI
929
	jne	.L5
930
	or	eax, 0x10
931
  .L5:
1492 hidnplayr 932
	call	[device.access_write_csr]
933
	cmp	[device.mii], 0
1196 hidnplayr 934
	je	.L6
1492 hidnplayr 935
	test	[device.options], PCNET_PORT_ASEL
1196 hidnplayr 936
	jnz	.L6
937
	mov	ecx, PCNET_BCR_MIICTL
1492 hidnplayr 938
	call	[device.access_read_bcr]
1196 hidnplayr 939
	and	eax,not 0x38
1492 hidnplayr 940
	test	[device.options], PCNET_PORT_FD
1196 hidnplayr 941
	jz	.L7
942
	or	eax, 0x10
943
  .L7:
1492 hidnplayr 944
	test	[device.options], PCNET_PORT_100
1196 hidnplayr 945
	jz	.L8
946
	or	eax, 0x08
947
  .L8:
1492 hidnplayr 948
	call	[device.access_write_bcr]
1196 hidnplayr 949
	jmp	.L9
950
.L6:
1492 hidnplayr 951
	test	[device.options], PCNET_PORT_ASEL
1196 hidnplayr 952
	jz	.L9
953
	mov	ecx, PCNET_BCR_MIICTL
954
	DEBUGF 1,"ASEL, enable auto-negotiation\n"
1492 hidnplayr 955
	call	[device.access_read_bcr]
1196 hidnplayr 956
	and	eax, not 0x98
957
	or	eax, 0x20
1492 hidnplayr 958
	call	[device.access_write_bcr]
1196 hidnplayr 959
.L9:
1492 hidnplayr 960
	cmp	[device.ltint],0
1196 hidnplayr 961
	je	.L10
962
	mov	ecx,5
1492 hidnplayr 963
	call	[device.access_read_csr]
1196 hidnplayr 964
	or	eax,(1 shl 14)
1492 hidnplayr 965
	call	[device.access_write_csr]
1196 hidnplayr 966
.L10:
1492 hidnplayr 967
	mov	eax, [device.options]
968
	and	eax, PCNET_PORT_PORTSEL
969
	shl	eax, 7
970
	mov	[device.mode_], ax
971
	mov	dword [device.filter], -1
972
	mov	dword [device.filter+4], -1
1196 hidnplayr 973
 
1201 clevermous 974
	call	read_mac
1196 hidnplayr 975
 
1492 hidnplayr 976
	lea	esi, [device.mac]
977
	lea	edi, [device.phys_addr]
1201 clevermous 978
	movsd
979
	movsw
980
 
1492 hidnplayr 981
	lea	eax, [device.private]
1196 hidnplayr 982
	mov	ecx, eax
983
	and	ecx, 0xFFF ; KolibriOS PAGE SIZE
984
	call	GetPgAddr
985
	add	eax, ecx
986
 
987
	push	eax
988
	and	eax, 0xffff
989
	mov	ecx, 1
1492 hidnplayr 990
	call	[device.access_write_csr]
1196 hidnplayr 991
	pop	eax
992
	shr	eax,16
993
	mov	ecx,2
1492 hidnplayr 994
	call	[device.access_write_csr]
1196 hidnplayr 995
 
996
	mov	ecx,4
997
	mov	eax,0x0915
1492 hidnplayr 998
	call	[device.access_write_csr]
1196 hidnplayr 999
 
1000
	mov	ecx,0
1001
	mov	eax,1
1492 hidnplayr 1002
	call	[device.access_write_csr]
1196 hidnplayr 1003
 
1492 hidnplayr 1004
	mov	[device.tx_full],0
1005
	mov	[device.cur_rx],0
1006
	mov	[device.cur_tx],0
1007
	mov	[device.dirty_rx],0
1008
	mov	[device.dirty_tx],0
1196 hidnplayr 1009
 
1010
	mov	ecx,100
1011
.L11:
1012
	push	ecx
1492 hidnplayr 1013
	xor	ecx, ecx
1014
	call	[device.access_read_csr]
1196 hidnplayr 1015
	pop	ecx
1016
	test	ax,0x100
1017
	jnz	.L12
1018
	loop	.L11
1019
.L12:
1020
 
1492 hidnplayr 1021
	DEBUGF 1,"Starting up device\n"
1196 hidnplayr 1022
	xor	ecx, ecx
1023
	mov	eax, 0x0002
1492 hidnplayr 1024
	call	[device.access_write_csr]
1196 hidnplayr 1025
 
1026
	xor	ecx, ecx
1492 hidnplayr 1027
	call	[device.access_read_csr]
1196 hidnplayr 1028
 
1029
	xor	ecx, ecx
1030
	mov	eax, PCNET_CSR_INTEN or PCNET_CSR_START
1492 hidnplayr 1031
	call	[device.access_write_csr]
1196 hidnplayr 1032
 
1033
	DEBUGF 1,"PCNET reset complete\n"
1034
	xor	eax, eax
1492 hidnplayr 1035
; clear packet/byte counters
1036
	lea	edi, [device.bytes_tx]
1037
	mov	ecx, 6
1038
	rep	stosd
1039
 
1196 hidnplayr 1040
	ret
1041
 
1042
 
1043
 
1044
 
1045
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1046
;;                                         ;;
1047
;; Transmit                                ;;
1048
;;                                         ;;
1263 clevermous 1049
;; In: buffer pointer in [esp+4]           ;;
1254 hidnplayr 1050
;;     size of buffer in [esp+8]           ;;
1196 hidnplayr 1051
;;     pointer to device structure in ebx  ;;
1052
;;                                         ;;
1053
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1054
 
1055
align 4
1056
transmit:
1263 clevermous 1057
	DEBUGF	1,"Transmitting packet, buffer:%x, size:%u\n",[esp+4],[esp+8]
1254 hidnplayr 1058
	mov	eax, [esp+4]
1196 hidnplayr 1059
	DEBUGF	1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
1060
	[eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
1061
	[eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
1062
	[eax+13]:2,[eax+12]:2
1063
 
1254 hidnplayr 1064
	cmp	dword [esp+8], 1514
1196 hidnplayr 1065
	jg	.finish 			; packet is too long
1254 hidnplayr 1066
	cmp	dword [esp+8], 60
1196 hidnplayr 1067
	jl	.finish 			; packet is too short
1068
 
1069
; check descriptor
1492 hidnplayr 1070
	movzx	eax, [device.cur_tx]
1201 clevermous 1071
	imul	edi, eax, PCNET_PKT_BUF_SZ
1072
	shl	eax, 4
1492 hidnplayr 1073
	add	edi, [device.tx_buffer]
1074
	add	eax, [device.tx_ring]
1201 clevermous 1075
	test	byte [eax + buf_head.status + 1], 80h
1076
	jnz	.nospace
1077
; descriptor is free, copy data
1254 hidnplayr 1078
	mov	esi, [esp+4]
1079
	mov	ecx, [esp+8]
1201 clevermous 1080
	mov	edx, ecx
1081
	shr	ecx, 2
1082
	and	edx, 3
1083
	rep	movsd
1084
	mov	ecx, edx
1085
	rep	movsb
1086
; set length
1254 hidnplayr 1087
	mov	ecx, [esp+8]
1201 clevermous 1088
	neg	ecx
1089
	mov	[eax + buf_head.length], cx
1090
; put to transfer queue
1091
	mov	[eax + buf_head.status], 0x8300
1196 hidnplayr 1092
 
1093
; trigger an immediate send
1201 clevermous 1094
	xor	ecx, ecx	 ; CSR0
1492 hidnplayr 1095
	call	[device.access_read_csr]
1196 hidnplayr 1096
	or	eax, PCNET_CSR_TX
1492 hidnplayr 1097
	call	[device.access_write_csr]
1196 hidnplayr 1098
 
1099
; get next descriptor 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, ...
1492 hidnplayr 1100
	inc	[device.cur_tx]
1101
	and	[device.cur_tx], 3
1196 hidnplayr 1102
	DEBUGF	2," - Packet Sent! "
1103
 
1104
.finish:
1492 hidnplayr 1105
; update statistics
1106
	inc	[device.packets_tx]
1107
 
1108
	mov	ecx, [esp+8]
1109
	add	dword [device.bytes_tx], ecx
1110
	adc	dword [device.bytes_tx + 4], 0
1196 hidnplayr 1111
	DEBUGF	2," - Done!\n"
1112
	ret
1113
 
1201 clevermous 1114
.nospace:
1115
	DEBUGF	1, 'ERROR: no free transmit descriptors\n'
1116
; todo: maybe somehow notify the kernel about the error?
1117
	ret
1196 hidnplayr 1118
 
1119
 
1120
 
1121
;;;;;;;;;;;;;;;;;;;;;;;
1122
;;                   ;;
1123
;; Interrupt handler ;;
1124
;;                   ;;
1125
;;;;;;;;;;;;;;;;;;;;;;;
1126
 
1127
align 4
1128
int_handler:
1129
 
1492 hidnplayr 1130
	DEBUGF	1,"IRQ %x ", eax:2		; no, you cant replace 'eax:2' with 'al', this must be a bug in FDO
1196 hidnplayr 1131
 
1132
; find pointer of device wich made IRQ occur
1133
 
1134
	mov	esi, PCNET_LIST
1135
	mov	ecx, [PCNET_DEV]
1136
	test	ecx, ecx
1137
	jz	.abort
1138
  .nextdevice:
1492 hidnplayr 1139
	mov	ebx, [esi]
1140
	DEBUGF	1,"device=%x? ", ebx
1141
	set_io	0
1196 hidnplayr 1142
 
1143
	push	ecx
1201 clevermous 1144
	xor	ecx, ecx ; CSR0
1492 hidnplayr 1145
	call	[device.access_read_csr]       ; get IRQ reason
1196 hidnplayr 1146
	pop	ecx
1147
 
1492 hidnplayr 1148
	test	ax , ax
1149
	jnz	.got_it
1196 hidnplayr 1150
 
1151
	add	esi, 4
1152
	loop	.nextdevice
1153
 
1492 hidnplayr 1154
	ret					; If no device was found, abort (The irq was probably for a device, not registered to this driver
1196 hidnplayr 1155
 
1156
  .got_it:
1492 hidnplayr 1157
	DEBUGF	1,"yes, reason=%x ", ax
1196 hidnplayr 1158
;-------------------------------------------------------
1201 clevermous 1159
; Possible reasons:
1160
; initialization done - ignore
1161
; transmit done - ignore
1162
; packet received - handle
1163
; Clear ALL IRQ reasons.
1164
; N.B. One who wants to handle more than one reason must be ready
1165
; to two or more reasons in one IRQ.
1166
	xor	ecx, ecx
1492 hidnplayr 1167
	call	[device.access_write_csr]
1196 hidnplayr 1168
; Received packet ok?
1169
 
1170
	test	ax, PCNET_CSR_RINT
1171
	jz	@f
1172
 
1251 clevermous 1173
.receiver_test_loop:
1492 hidnplayr 1174
	movzx	eax, [device.cur_rx]
1196 hidnplayr 1175
;        and     eax, PCNET_RX_RING_MOD_MASK
1176
	mov	edi, eax
1177
 
1178
	imul	esi, eax, PCNET_PKT_BUF_SZ	;
1492 hidnplayr 1179
	add	esi, [device.rx_buffer] 	; esi now points to rx buffer
1196 hidnplayr 1180
 
1181
	shl	edi, 4				; desc * 16 (16 is size of one ring entry)
1492 hidnplayr 1182
	add	edi, [device.rx_ring]		; edi now points to current rx ring entry
1196 hidnplayr 1183
 
1184
	mov	cx , [edi + buf_head.status]
1185
 
1186
	test	cx , PCNET_RXSTAT_OWN		; If this bit is set, the controller OWN's the packet, if not, we do
1187
	jnz	.abort
1188
 
1201 clevermous 1189
	test	cx , PCNET_RXSTAT_ENP
1196 hidnplayr 1190
	jz	.abort
1191
 
1201 clevermous 1192
	test	cx , PCNET_RXSTAT_STP
1196 hidnplayr 1193
	jz	.abort
1194
 
1201 clevermous 1195
	movzx	ecx, [edi + buf_head.msg_length]	; get packet length in ecx
1196 hidnplayr 1196
	sub	ecx, 4				;
1197
 
1201 clevermous 1198
	push	ecx
1196 hidnplayr 1199
	stdcall KernelAlloc, ecx		; Allocate a buffer to put packet into
1201 clevermous 1200
	pop	ecx
1196 hidnplayr 1201
	test	eax, eax			; Test if we allocated succesfully
1202
	jz	.abort				;
1203
 
1251 clevermous 1204
	push	.receiver_test_loop		;
1196 hidnplayr 1205
	push	ecx				; for eth_receiver
1206
	push	eax				;
1207
 
1492 hidnplayr 1208
; update statistics
1209
	inc	[device.packets_rx]
1210
 
1211
	add	dword [device.bytes_rx], ecx
1212
	adc	dword [device.bytes_rx + 4], 0
1213
 
1196 hidnplayr 1214
	xchg	edi, eax
1492 hidnplayr 1215
 
1216
; copy packet data
1217
	shr	cx , 1
1218
	jnc	.nb
1219
	movsb
1220
  .nb:
1221
	shr	cx , 1
1222
	jnc	.nw
1223
	movsw
1224
  .nw:
1196 hidnplayr 1225
	rep	movsd
1226
 
1206 hidnplayr 1227
;       mov     word [eax + buf_head.length], PCNET_PKT_BUF_SZ_NEG
1201 clevermous 1228
	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 1229
 
1492 hidnplayr 1230
	inc	[device.cur_rx] 	  ; update descriptor
1231
	and	[device.cur_rx], 3	  ;
1196 hidnplayr 1232
 
1492 hidnplayr 1233
	DEBUGF	1,"Inserting packet\n"
1196 hidnplayr 1234
	jmp	EthReceiver			; Send the copied packet to kernel
1235
 
1236
  .abort:
1492 hidnplayr 1237
	DEBUGF	1,"done \n"
1196 hidnplayr 1238
  @@:
1239
 
1240
	ret
1241
 
1242
 
1243
 
1244
 
1245
;;;;;;;;;;;;;;;;;;;;;;;
1246
;;                   ;;
1247
;; Write MAC address ;;
1248
;;                   ;;
1249
;;;;;;;;;;;;;;;;;;;;;;;
1250
 
1251
align 4
1252
write_mac:	; in: mac pushed onto stack (as 3 words)
1253
 
1254
	DEBUGF	1,"Writing MAC: %x-%x-%x-%x-%x-%x",[esp+0]:2,[esp+1]:2,[esp+2]:2,[esp+3]:2,[esp+4]:2,[esp+5]:2
1255
 
1492 hidnplayr 1256
	mov	edx, [device.io_addr]
1257
	add	edx, 2
1196 hidnplayr 1258
	xor	eax, eax
1259
 
1260
	mov	ecx, PCNET_CSR_PAR0
1261
       @@:
1262
	pop	ax
1492 hidnplayr 1263
	call	[device.access_write_csr]
1196 hidnplayr 1264
	DEBUGF	1,"."
1265
	inc	ecx
1266
	cmp	ecx, PCNET_CSR_PAR2
1267
	jl	@r
1268
 
1269
	DEBUGF	1,"\n"
1270
 
1271
; Notice this procedure does not ret, but continues to read_mac instead.
1272
 
1273
;;;;;;;;;;;;;;;;;;;;;;
1274
;;                  ;;
1275
;; Read MAC address ;;
1276
;;                  ;;
1277
;;;;;;;;;;;;;;;;;;;;;;
1278
 
1492 hidnplayr 1279
read_mac:
1196 hidnplayr 1280
	DEBUGF	1,"Reading MAC"
1281
 
1492 hidnplayr 1282
	mov	edx, [device.io_addr]
1283
	add	edx, 6
1196 hidnplayr 1284
       @@:
1285
	dec	dx
1286
	dec	dx
1287
	in	ax, dx
1288
	push	ax
1289
	DEBUGF	1,"."
1492 hidnplayr 1290
	cmp	edx, [device.io_addr]
1196 hidnplayr 1291
	jg	@r
1292
 
1293
	DEBUGF	1," %x-%x-%x-%x-%x-%x\n",[esp+0]:2,[esp+1]:2,[esp+2]:2,[esp+3]:2,[esp+4]:2,[esp+5]:2
1294
 
1492 hidnplayr 1295
	lea	edi, [device.mac]
1196 hidnplayr 1296
	pop	ax
1297
	stosw
1298
	pop	ax
1299
	stosw
1300
	pop	ax
1301
	stosw
1302
 
1303
	ret
1304
 
1305
 
1306
switch_to_wio:
1492 hidnplayr 1307
	DEBUGF	1,"Switch to WIO\n"
1196 hidnplayr 1308
 
1492 hidnplayr 1309
	mov	[device.access_read_csr], wio_read_csr
1310
	mov	[device.access_write_csr], wio_write_csr
1311
	mov	[device.access_read_bcr], wio_read_bcr
1312
	mov	[device.access_write_bcr], wio_write_bcr
1313
	mov	[device.access_read_rap], wio_read_rap
1314
	mov	[device.access_write_rap], wio_write_rap
1315
	mov	[device.access_reset], wio_reset
1196 hidnplayr 1316
 
1317
	ret
1318
 
1319
switch_to_dwio:
1492 hidnplayr 1320
	DEBUGF	1,"Switch to DWIO\n"
1196 hidnplayr 1321
 
1492 hidnplayr 1322
	mov	[device.access_read_csr], dwio_read_csr
1323
	mov	[device.access_write_csr], dwio_write_csr
1324
	mov	[device.access_read_bcr], dwio_read_bcr
1325
	mov	[device.access_write_bcr], dwio_write_bcr
1326
	mov	[device.access_read_rap], dwio_read_rap
1327
	mov	[device.access_write_rap], dwio_write_rap
1328
	mov	[device.access_reset], dwio_reset
1196 hidnplayr 1329
 
1330
	ret
1331
 
1332
 
1333
 
1334
 
1335
 
1336
; ecx - index
1337
; return:
1338
; eax - data
1339
wio_read_csr:
1340
 
1341
	add	edx, PCNET_WIO_RAP
1342
	mov	ax , cx
1343
	out	dx , ax
1344
	add	edx, PCNET_WIO_RDP - PCNET_WIO_RAP
1345
	in	ax , dx
1346
	and	eax, 0xffff
1347
	sub	edx, PCNET_WIO_RDP
1348
 
1349
	ret
1350
 
1351
 
1352
; eax - data
1353
; ecx - index
1354
wio_write_csr:
1355
 
1356
	add	edx, PCNET_WIO_RAP
1357
	xchg	eax, ecx
1358
	out	dx , ax
1359
	xchg	eax, ecx
1360
	add	edx, PCNET_WIO_RDP - PCNET_WIO_RAP
1361
	out	dx , ax
1362
	sub	edx, PCNET_WIO_RDP
1363
 
1364
	ret
1365
 
1366
 
1367
; ecx - index
1368
; return:
1369
; eax - data
1370
wio_read_bcr:
1371
 
1372
	add	edx, PCNET_WIO_RAP
1373
	mov	ax , cx
1374
	out	dx , ax
1375
	add	edx, PCNET_WIO_BDP - PCNET_WIO_RAP
1376
	in	ax , dx
1377
	and	eax, 0xffff
1378
	sub	edx, PCNET_WIO_BDP
1379
 
1380
	ret
1381
 
1382
 
1383
; eax - data
1384
; ecx - index
1385
wio_write_bcr:
1386
 
1387
	add	edx, PCNET_WIO_RAP
1388
	xchg	eax, ecx
1389
	out	dx , ax
1390
	xchg	eax, ecx
1391
	add	edx, PCNET_WIO_BDP - PCNET_WIO_RAP
1392
	out	dx , ax
1393
	sub	edx, PCNET_WIO_BDP
1394
 
1395
	ret
1396
 
1397
 
1398
wio_read_rap:
1399
 
1400
	add	edx, PCNET_WIO_RAP
1401
	in	ax , dx
1402
	and	eax, 0xffff
1403
	sub	edx, PCNET_WIO_RAP
1404
 
1405
	ret
1406
 
1407
; eax - val
1408
wio_write_rap:
1409
 
1410
	add	edx, PCNET_WIO_RAP
1411
	out	dx , ax
1412
	sub	edx, PCNET_WIO_RAP
1413
 
1414
	ret
1415
 
1416
wio_reset:
1417
 
1418
	push	eax
1419
	add	edx, PCNET_WIO_RESET
1420
	in	ax , dx
1421
	pop	eax
1422
	sub	edx, PCNET_WIO_RESET
1423
 
1424
	ret
1425
 
1426
 
1427
; ecx - index
1428
; return:
1429
; eax - data
1430
dwio_read_csr:
1431
 
1432
	add	edx, PCNET_DWIO_RAP
1201 clevermous 1433
	mov	eax, ecx
1196 hidnplayr 1434
	out	dx , eax
1435
	add	edx, PCNET_DWIO_RDP - PCNET_DWIO_RAP
1436
	in	eax, dx
1437
	and	eax, 0xffff
1438
	sub	edx, PCNET_DWIO_RDP
1439
 
1440
	ret
1441
 
1442
 
1443
; ecx - index
1444
; eax - data
1445
dwio_write_csr:
1446
 
1447
	add	edx, PCNET_DWIO_RAP
1448
	xchg	eax, ecx
1449
	out	dx , eax
1450
	add	edx, PCNET_DWIO_RDP - PCNET_DWIO_RAP
1451
	xchg	eax, ecx
1452
	out	dx , eax
1453
	sub	edx, PCNET_DWIO_RDP
1454
 
1455
	ret
1456
 
1457
; ecx - index
1458
; return:
1459
; eax - data
1460
dwio_read_bcr:
1461
 
1462
	add	edx, PCNET_DWIO_RAP
1201 clevermous 1463
	mov	eax, ecx
1196 hidnplayr 1464
	out	dx , eax
1465
	add	edx, PCNET_DWIO_BDP - PCNET_DWIO_RAP
1466
	in	eax, dx
1467
	and	eax, 0xffff
1468
	sub	edx, PCNET_DWIO_BDP
1469
 
1470
	ret
1471
 
1472
 
1473
; ecx - index
1474
; eax - data
1475
dwio_write_bcr:
1476
 
1477
	add	edx, PCNET_DWIO_RAP
1478
	xchg	eax, ecx
1479
	out	dx , eax
1480
	add	edx, PCNET_DWIO_BDP - PCNET_DWIO_RAP
1481
	xchg	eax, ecx
1482
	out	dx , eax
1483
	sub	edx, PCNET_DWIO_BDP
1484
 
1485
	ret
1486
 
1487
 
1488
dwio_read_rap:
1489
 
1490
	add	edx, PCNET_DWIO_RAP
1491
	in	eax, dx
1492
	and	eax, 0xffff
1493
	sub	edx, PCNET_DWIO_RAP
1494
 
1495
	ret
1496
 
1497
 
1498
; eax - val
1499
dwio_write_rap:
1500
 
1501
	add	edx, PCNET_DWIO_RAP
1502
	out	dx , eax
1503
	sub	edx, PCNET_DWIO_RAP
1504
 
1505
	ret
1506
 
1507
 
1508
dwio_reset:
1509
 
1510
	push	eax
1511
	add	edx, PCNET_DWIO_RESET
1512
	in	eax, dx
1513
	pop	eax
1514
	sub	edx, PCNET_DWIO_RESET
1515
 
1516
	ret
1517
 
1518
 
1519
 
1520
; End of code
1521
 
1522
align 4 				      ; Place all initialised data here
1523
 
1524
PCNET_DEV     dd 0
1525
version       dd (5 shl 16) or (API_VERSION and 0xFFFF)
1526
my_service    db 'PCnet',0		      ; max 16 chars include zero
1527
 
1528
device_l2     db "PCnet/PCI 79C970",0
1529
device_l4     db "PCnet/PCI II 79C970A",0
1530
device_l5     db "PCnet/FAST 79C971",0
1531
device_l6     db "PCnet/FAST+ 79C972",0
1532
device_l7     db "PCnet/FAST III 79C973",0
1533
device_l8     db "PCnet/Home 79C978",0
1534
device_l9     db "PCnet/FAST III 79C975",0
1535
 
1536
options_mapping:
1537
dd PCNET_PORT_ASEL					;  0 Auto-select
1538
dd PCNET_PORT_AUI					;  1 BNC/AUI
1539
dd PCNET_PORT_AUI					;  2 AUI/BNC
1540
dd PCNET_PORT_ASEL					;  3 not supported
1541
dd PCNET_PORT_10BT or PCNET_PORT_FD			;  4 10baseT-FD
1542
dd PCNET_PORT_ASEL					;  5 not supported
1543
dd PCNET_PORT_ASEL					;  6 not supported
1544
dd PCNET_PORT_ASEL					;  7 not supported
1545
dd PCNET_PORT_ASEL					;  8 not supported
1546
dd PCNET_PORT_MII					;  9 MII 10baseT
1547
dd PCNET_PORT_MII or PCNET_PORT_FD			; 10 MII 10baseT-FD
1548
dd PCNET_PORT_MII					; 11 MII (autosel)
1549
dd PCNET_PORT_10BT					; 12 10BaseT
1550
dd PCNET_PORT_MII or PCNET_PORT_100			; 13 MII 100BaseTx
1551
dd PCNET_PORT_MII or PCNET_PORT_100 or PCNET_PORT_FD	; 14 MII 100BaseTx-FD
1552
dd PCNET_PORT_ASEL					; 15 not supported
1553
 
1554
include_debug_strings					; All data wich FDO uses will be included here
1555
 
1556
section '.data' data readable writable align 16 	; place all uninitialized data place here
1557
 
1558
PCNET_LIST rd MAX_PCNET 				; This list contains all pointers to device structures the driver is handling