Subversion Repositories Kolibri OS

Rev

Rev 2852 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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