Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
3545 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                  ;;
5363 yogev_ezra 3
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved.     ;;
3545 hidnplayr 4
;; Distributed under terms of the GNU General Public License        ;;
5
;;                                                                  ;;
6
;;  AMD PCnet driver for KolibriOS                                  ;;
7
;;                                                                  ;;
8
;;  By hidnplayr & clevermouse                                      ;;
9
;;                                                                  ;;
10
;;  Based on the PCnet32 driver for MenuetOS, by Jarek Pelczar      ;;
11
;;                                                                  ;;
12
;;          GNU GENERAL PUBLIC LICENSE                              ;;
13
;;             Version 2, June 1991                                 ;;
14
;;                                                                  ;;
15
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
16
 
4532 hidnplayr 17
format PE DLL native
18
entry START
3545 hidnplayr 19
 
4532 hidnplayr 20
        CURRENT_API             = 0x0200
21
        COMPATIBLE_API          = 0x0100
22
        API_VERSION             = (COMPATIBLE_API shl 16) + CURRENT_API
3545 hidnplayr 23
 
4532 hidnplayr 24
        MAX_DEVICES             = 16
25
 
3545 hidnplayr 26
        __DEBUG__               = 1
4582 hidnplayr 27
        __DEBUG_LEVEL__         = 2             ; 1 = verbose, 2 = errors only
3545 hidnplayr 28
 
29
        TX_RING_SIZE            = 4
30
        RX_RING_SIZE            = 4
31
 
4532 hidnplayr 32
section '.flat' readable writable executable
33
 
4467 hidnplayr 34
include '../struct.inc'
35
include '../macros.inc'
3545 hidnplayr 36
include '../proc32.inc'
37
include '../fdo.inc'
5074 hidnplayr 38
include '../netdrv.inc'
3545 hidnplayr 39
 
40
 
41
        PORT_AUI                = 0x00
42
        PORT_10BT               = 0x01
43
        PORT_GPSI               = 0x02
44
        PORT_MII                = 0x03
45
        PORT_PORTSEL            = 0x03
46
        PORT_ASEL               = 0x04
47
        PORT_100                = 0x40
48
        PORT_FD                 = 0x80
49
 
50
        DMA_MASK                = 0xffffffff
51
 
52
        LOG_TX_BUFFERS          = 2             ; FIXME
53
        LOG_RX_BUFFERS          = 2
54
 
55
        TX_RING_MOD_MASK        = (TX_RING_SIZE-1)
56
        TX_RING_LEN_BITS        = (LOG_TX_BUFFERS shl 12)
57
 
58
        RX_RING_MOD_MASK        = (RX_RING_SIZE-1)
59
        RX_RING_LEN_BITS        = (LOG_RX_BUFFERS shl 4)
60
 
61
        PKT_BUF_SZ              = 1544
62
 
63
        WIO_RDP                 = 0x10
64
        WIO_RAP                 = 0x12
65
        WIO_RESET               = 0x14
66
        WIO_BDP                 = 0x16
67
 
68
        DWIO_RDP                = 0x10
69
        DWIO_RAP                = 0x14
70
        DWIO_RESET              = 0x18
71
        DWIO_BDP                = 0x1C
72
 
73
; CSR registers
74
 
75
        CSR_CSR                 = 0x00
76
        CSR_IAB0                = 0x01
77
        CSR_IAB1                = 0x02
78
        CSR_IMR                 = 0x03
79
        CSR_TFEAT               = 0x04
80
        CSR_EXTCTL1             = 0x05
81
        CSR_DTBLLEN             = 0x06
82
        CSR_EXTCTL2             = 0x07
83
        CSR_MAR0                = 0x08
84
        CSR_MAR1                = 0x09
85
        CSR_MAR2                = 0x0A
86
        CSR_MAR3                = 0x0B
87
        CSR_PAR0                = 0x0C
88
        CSR_PAR1                = 0x0D
89
        CSR_PAR2                = 0x0E
90
        CSR_MODE                = 0x0F
91
        CSR_RXADDR0             = 0x18
92
        CSR_RXADDR1             = 0x19
93
        CSR_TXADDR0             = 0x1E
94
        CSR_TXADDR1             = 0x1F
95
        CSR_TXPOLL              = 0x2F
96
        CSR_RXPOLL              = 0x31
97
        CSR_RXRINGLEN           = 0x4C
98
        CSR_TXRINGLEN           = 0x4E
99
        CSR_DMACTL              = 0x50
100
        CSR_BUSTIMER            = 0x52
101
        CSR_MEMERRTIMEO         = 0x64
102
        CSR_ONNOWMISC           = 0x74
103
        CSR_ADVFEAT             = 0x7A
104
        CSR_MACCFG              = 0x7D
105
        CSR_CHIPID0             = 0x58
106
        CSR_CHIPID1             = 0x59
107
 
108
; Control and Status Register (CSR0)
109
 
5004 hidnplayr 110
        CSR_INIT                = 0x0001 ;1 shl 0
111
        CSR_START               = 0x0002 ;1 shl 1
112
        CSR_STOP                = 0x0004 ;1 shl 2
113
        CSR_TX                  = 0x0008 ;1 shl 3
114
        CSR_TXON                = 0x0010 ;1 shl 4
115
        CSR_RXON                = 0x0020 ;1 shl 5
116
        CSR_INTEN               = 0x0040 ;1 shl 6
117
        CSR_INTR                = 0x0080 ;1 shl 7
118
        CSR_IDONE               = 0x0100 ;1 shl 8
119
        CSR_TINT                = 0x0200 ;1 shl 9
120
        CSR_RINT                = 0x0400 ;1 shl 10
121
        CSR_MERR                = 0x0800 ;1 shl 11
122
        CSR_MISS                = 0x1000 ;1 shl 12
123
        CSR_CERR                = 0x2000 ;1 shl 13
3545 hidnplayr 124
 
125
; Interrupt masks and deferral control (CSR3)
126
 
127
        IMR_BSWAP               = 0x0004
128
        IMR_ENMBA               = 0x0008  ; enable modified backoff alg
129
        IMR_DXMT2PD             = 0x0010
130
        IMR_LAPPEN              = 0x0020  ; lookahead packet processing enb
131
        IMR_DXSUFLO             = 0x0040  ; disable TX stop on underflow
132
        IMR_IDONE               = 0x0100
133
        IMR_TINT                = 0x0200
134
        IMR_RINT                = 0x0400
135
        IMR_MERR                = 0x0800
136
        IMR_MISS                = 0x1000
137
 
5004 hidnplayr 138
        ; Masked interrupts will be disabled.
139
        IMR                     = 0 ;IMR_IDONE ;or IMR_TINT or IMR_RINT or IMR_MERR or IMR_MISS
3545 hidnplayr 140
 
141
; Test and features control (CSR4)
142
 
143
        TFEAT_TXSTRTMASK        = 0x0004
144
        TFEAT_TXSTRT            = 0x0008
145
        TFEAT_RXCCOFLOWM        = 0x0010  ; Rx collision counter oflow
146
        TFEAT_RXCCOFLOW         = 0x0020
147
        TFEAT_UINT              = 0x0040
148
        TFEAT_UINTREQ           = 0x0080
149
        TFEAT_MISSOFLOWM        = 0x0100
150
        TFEAT_MISSOFLOW         = 0x0200
151
        TFEAT_STRIP_FCS         = 0x0400
152
        TFEAT_PAD_TX            = 0x0800
153
        TFEAT_TXDPOLL           = 0x1000
154
        TFEAT_DMAPLUS           = 0x4000
155
 
156
; Extended control and interrupt 1 (CSR5)
157
 
158
        EXTCTL1_SPND            = 0x0001  ; suspend
159
        EXTCTL1_MPMODE          = 0x0002  ; magic packet mode
160
        EXTCTL1_MPENB           = 0x0004  ; magic packet enable
161
        EXTCTL1_MPINTEN         = 0x0008  ; magic packet interrupt enable
162
        EXTCTL1_MPINT           = 0x0010  ; magic packet interrupt
163
        EXTCTL1_MPPLBA          = 0x0020  ; magic packet phys. logical bcast
164
        EXTCTL1_EXDEFEN         = 0x0040  ; excessive deferral interrupt enb.
165
        EXTCTL1_EXDEF           = 0x0080  ; excessive deferral interrupt
166
        EXTCTL1_SINTEN          = 0x0400  ; system interrupt enable
167
        EXTCTL1_SINT            = 0x0800  ; system interrupt
168
        EXTCTL1_LTINTEN         = 0x4000  ; last TX interrupt enb
169
        EXTCTL1_TXOKINTD        = 0x8000  ; TX OK interrupt disable
170
 
171
; RX/TX descriptor len (CSR6)
172
 
173
        DTBLLEN_RLEN            = 0x0F00
174
        DTBLLEN_TLEN            = 0xF000
175
 
176
; Extended control and interrupt 2 (CSR7)
177
 
178
        EXTCTL2_MIIPDTINTE      = 0x0001
179
        EXTCTL2_MIIPDTINT       = 0x0002
180
        EXTCTL2_MCCIINTE        = 0x0004
181
        EXTCTL2_MCCIINT         = 0x0008
182
        EXTCTL2_MCCINTE         = 0x0010
183
        EXTCTL2_MCCINT          = 0x0020
184
        EXTCTL2_MAPINTE         = 0x0040
185
        EXTCTL2_MAPINT          = 0x0080
186
        EXTCTL2_MREINTE         = 0x0100
187
        EXTCTL2_MREINT          = 0x0200
188
        EXTCTL2_STINTE          = 0x0400
189
        EXTCTL2_STINT           = 0x0800
190
        EXTCTL2_RXDPOLL         = 0x1000
191
        EXTCTL2_RDMD            = 0x2000
192
        EXTCTL2_RXFRTG          = 0x4000
193
        EXTCTL2_FASTSPNDE       = 0x8000
194
 
195
; Mode (CSR15)
196
 
197
        MODE_RXD                = 0x0001  ; RX disable
198
        MODE_TXD                = 0x0002  ; TX disable
199
        MODE_LOOP               = 0x0004  ; loopback enable
200
        MODE_TXCRCD             = 0x0008
201
        MODE_FORCECOLL          = 0x0010
202
        MODE_RETRYD             = 0x0020
203
        MODE_INTLOOP            = 0x0040
204
        MODE_PORTSEL            = 0x0180
205
        MODE_RXVPAD             = 0x2000
206
        MODE_RXNOBROAD          = 0x4000
207
        MODE_PROMISC            = 0x8000
208
 
209
; BCR (Bus Control Registers)
210
 
211
        BCR_MMRA                = 0x00    ; Master Mode Read Active
212
        BCR_MMW                 = 0x01    ; Master Mode Write Active
213
        BCR_MISCCFG             = 0x02
214
        BCR_LED0                = 0x04
215
        BCR_LED1                = 0x05
216
        BCR_LED2                = 0x06
217
        BCR_LED3                = 0x07
218
        BCR_DUPLEX              = 0x09
219
        BCR_BUSCTL              = 0x12
220
        BCR_EECTL               = 0x13
221
        BCR_SSTYLE              = 0x14
222
        BCR_PCILAT              = 0x16
223
        BCR_PCISUBVENID         = 0x17
224
        BCR_PCISUBSYSID         = 0x18
225
        BCR_SRAMSIZE            = 0x19
226
        BCR_SRAMBOUND           = 0x1A
227
        BCR_SRAMCTL             = 0x1B
228
        BCR_MIICTL              = 0x20
229
        BCR_MIIADDR             = 0x21
230
        BCR_MIIDATA             = 0x22
231
        BCR_PCIVENID            = 0x23
232
        BCR_PCIPCAP             = 0x24
233
        BCR_DATA0               = 0x25
234
        BCR_DATA1               = 0x26
235
        BCR_DATA2               = 0x27
236
        BCR_DATA3               = 0x28
237
        BCR_DATA4               = 0x29
238
        BCR_DATA5               = 0x2A
239
        BCR_DATA6               = 0x2B
240
        BCR_DATA7               = 0x2C
241
        BCR_ONNOWPAT0           = 0x2D
242
        BCR_ONNOWPAT1           = 0x2E
243
        BCR_ONNOWPAT2           = 0x2F
244
        BCR_PHYSEL              = 0x31
245
 
246
; RX status register
247
 
248
        RXSTAT_BPE              = 0x0080        ; bus parity error
249
        RXSTAT_ENP              = 0x0100        ; end of packet
250
        RXSTAT_STP              = 0x0200        ; start of packet
251
        RXSTAT_BUFF             = 0x0400        ; buffer error
252
        RXSTAT_CRC              = 0x0800        ; CRC error
253
        RXSTAT_OFLOW            = 0x1000        ; rx overrun
254
        RXSTAT_FRAM             = 0x2000        ; framing error
255
        RXSTAT_ERR              = 0x4000        ; error summary
256
        RXSTAT_OWN              = 0x8000
257
 
258
; TX status register
259
 
260
        TXSTAT_TRC              = 0x0000000F    ; transmit retries
261
        TXSTAT_RTRY             = 0x04000000    ; retry
262
        TXSTAT_LCAR             = 0x08000000    ; lost carrier
263
        TXSTAT_LCOL             = 0x10000000    ; late collision
264
        TXSTAT_EXDEF            = 0x20000000    ; excessive deferrals
265
        TXSTAT_UFLOW            = 0x40000000    ; transmit underrun
266
        TXSTAT_BUFF             = 0x80000000    ; buffer error
267
 
268
        TXCTL_OWN               = 0x8000
269
        TXCTL_ERR               = 0x4000        ; error summary
270
        TXCTL_ADD_FCS           = 0x2000        ; add FCS to pkt
271
        TXCTL_MORE_LTINT        = 0x1000
272
        TXCTL_ONE               = 0x0800
273
        TXCTL_DEF               = 0x0400
274
        TXCTL_STP               = 0x0200
275
        TXCTL_ENP               = 0x0100
276
        TXCTL_BPE               = 0x0080
277
 
278
        TXCTL_MBO               = 0x0000F000
279
        TXCTL_BUFSZ             = 0x00000FFF
280
 
281
        MAX_PHYS                = 32
282
 
283
 
4532 hidnplayr 284
struct  device          ETH_DEVICE
3545 hidnplayr 285
 
4532 hidnplayr 286
        rb 0x100-($ and 0xff)   ; align 256
3545 hidnplayr 287
 
4532 hidnplayr 288
; Pcnet configuration structure
289
        mode            dw ?
290
        tlen_rlen       dw ?
291
        phys_addr       dp ?
292
        reserved        dw ?
293
        filter          dq ?
294
        rx_ring_phys    dd ?
295
        tx_ring_phys    dd ?
296
; end of pcnet config struct
3545 hidnplayr 297
 
4532 hidnplayr 298
        rb 0x100-($ and 0xff)   ; align 256
3545 hidnplayr 299
 
4532 hidnplayr 300
        rx_ring         rb RX_RING_SIZE * sizeof.descriptor
3545 hidnplayr 301
 
4532 hidnplayr 302
        rb 0x100-($ and 0xff)   ; align 256
3545 hidnplayr 303
 
4532 hidnplayr 304
        tx_ring         rb TX_RING_SIZE * sizeof.descriptor
3545 hidnplayr 305
 
4532 hidnplayr 306
        cur_rx          db ?
307
        cur_tx          db ?
308
        last_tx         db ?
309
        options         dd ?
310
        full_duplex     db ?
311
        chip_version    dw ?
312
        mii             db ?
313
        ltint           db ?
314
        dxsuflo         db ?
315
        fset            db ?
316
        fdx             db ?
3545 hidnplayr 317
 
4532 hidnplayr 318
        io_addr         dd ?
319
        irq_line        db ?
320
        pci_bus         dd ?
321
        pci_dev         dd ?
3545 hidnplayr 322
 
4532 hidnplayr 323
        phy             dw ?
3545 hidnplayr 324
 
4532 hidnplayr 325
        read_csr        dd ?
326
        write_csr       dd ?
327
        read_bcr        dd ?
328
        write_bcr       dd ?
329
        read_rap        dd ?
330
        write_rap       dd ?
331
        sw_reset        dd ?
3545 hidnplayr 332
 
4532 hidnplayr 333
ends
3545 hidnplayr 334
 
4532 hidnplayr 335
struct  descriptor
3545 hidnplayr 336
 
4532 hidnplayr 337
        base            dd ?
338
        length          dw ?
339
        status          dw ?
340
        msg_length      dw ?
341
        misc            dw ?
342
        virtual         dd ?
3545 hidnplayr 343
 
4532 hidnplayr 344
ends
3545 hidnplayr 345
 
346
 
347
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
348
;;                        ;;
349
;; proc START             ;;
350
;;                        ;;
351
;; (standard driver proc) ;;
352
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
353
 
4532 hidnplayr 354
proc START c, reason:dword, cmdline:dword
3545 hidnplayr 355
 
4532 hidnplayr 356
        cmp     [reason], DRV_ENTRY
357
        jne     .fail
3545 hidnplayr 358
 
4532 hidnplayr 359
        DEBUGF  2,"Loading driver\n"
360
        invoke  RegService, my_service, service_proc
3545 hidnplayr 361
        ret
362
 
363
  .fail:
364
        xor eax, eax
365
        ret
366
 
367
endp
368
 
369
 
370
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
371
;;                        ;;
372
;; proc SERVICE_PROC      ;;
373
;;                        ;;
374
;; (standard driver proc) ;;
375
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
376
 
377
align 4
378
proc service_proc stdcall, ioctl:dword
379
 
380
        mov     edx, [ioctl]
4470 hidnplayr 381
        mov     eax, [edx + IOCTL.io_code]
3545 hidnplayr 382
 
383
;------------------------------------------------------
384
 
385
        cmp     eax, 0 ;SRV_GETVERSION
386
        jne     @F
387
 
4470 hidnplayr 388
        cmp     [edx + IOCTL.out_size], 4
3545 hidnplayr 389
        jb      .fail
4470 hidnplayr 390
        mov     eax, [edx + IOCTL.output]
3545 hidnplayr 391
        mov     [eax], dword API_VERSION
392
 
393
        xor     eax, eax
394
        ret
395
 
396
;------------------------------------------------------
397
  @@:
398
        cmp     eax, 1 ;SRV_HOOK
399
        jne     .fail
400
 
4532 hidnplayr 401
        cmp     [edx + IOCTL.inp_size], 3               ; Data input must be at least 3 bytes
3545 hidnplayr 402
        jb      .fail
403
 
4470 hidnplayr 404
        mov     eax, [edx + IOCTL.input]
4532 hidnplayr 405
        cmp     byte[eax], 1                            ; 1 means device number and bus number (pci) are given
3545 hidnplayr 406
        jne     .fail                                   ; other types arent supported for this card yet
407
 
408
; check if the device is already listed
409
 
410
        mov     ecx, [devices]
411
        test    ecx, ecx
412
        jz      .firstdevice
413
 
414
        mov     esi, device_list
4470 hidnplayr 415
;        mov     eax, [edx + IOCTL.input]                ; get the pci bus and device numbers
416
        mov     ax, [eax+1]                             ;
3545 hidnplayr 417
  .nextdevice:
418
        mov     ebx, [esi]
4532 hidnplayr 419
        cmp     al, byte[ebx + device.pci_bus]
3545 hidnplayr 420
        jne     @f
4532 hidnplayr 421
        cmp     ah, byte[ebx + device.pci_dev]
3545 hidnplayr 422
        je      .find_devicenum                         ; Device is already loaded, let's find it's device number
423
       @@:
424
        add     esi, 4
425
        loop    .nextdevice
426
 
427
; This device doesnt have its own eth_device structure yet, lets create one
428
 
429
  .firstdevice:
430
        cmp     [devices], MAX_DEVICES                  ; First check if the driver can handle one more card
431
        jae     .fail
432
 
4532 hidnplayr 433
        allocate_and_clear ebx, sizeof.device, .fail
3545 hidnplayr 434
 
435
; Fill in the direct call addresses into the struct
436
 
4532 hidnplayr 437
        mov     [ebx + device.reset], reset
438
        mov     [ebx + device.transmit], transmit
439
        mov     [ebx + device.unload], unload
440
        mov     [ebx + device.name], my_service
3545 hidnplayr 441
 
442
; save the pci bus and device numbers
443
 
4470 hidnplayr 444
        mov     eax, [edx + IOCTL.input]
3545 hidnplayr 445
        movzx   ecx, byte[eax+1]
4532 hidnplayr 446
        mov     [ebx + device.pci_bus], ecx
3545 hidnplayr 447
        movzx   ecx, byte[eax+2]
4532 hidnplayr 448
        mov     [ebx + device.pci_dev], ecx
3545 hidnplayr 449
 
450
; Now, it's time to find the base io addres of the PCI device
451
 
4532 hidnplayr 452
        stdcall PCI_find_io, [ebx + device.pci_bus], [ebx + device.pci_dev]
453
        mov     [ebx + device.io_addr], eax
3545 hidnplayr 454
 
455
; We've found the io address, find IRQ now
456
 
4532 hidnplayr 457
        invoke  PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.interrupt_line
458
        mov     [ebx + device.irq_line], al
3545 hidnplayr 459
 
460
        DEBUGF  1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
4532 hidnplayr 461
        [ebx + device.pci_dev]:1,[ebx + device.pci_bus]:1,[ebx + device.irq_line]:1,[ebx + device.io_addr]:4
3545 hidnplayr 462
 
463
; Ok, the eth_device structure is ready, let's probe the device
464
; Because initialization fires IRQ, IRQ handler must be aware of this device
465
        mov     eax, [devices]                                          ; Add the device structure to our device list
466
        mov     [device_list+4*eax], ebx                                ; (IRQ handler uses this list to find device)
467
        inc     [devices]                                               ;
468
 
469
        call    probe                                                   ; this function will output in eax
470
        test    eax, eax
471
        jnz     .destroy                                                ; If an error occured, exit
472
 
4532 hidnplayr 473
        mov     [ebx + device.type], NET_TYPE_ETH
474
        invoke  NetRegDev
3545 hidnplayr 475
        cmp     eax, -1
476
        je      .destroy
477
 
478
        ret
479
 
480
; If the device was already loaded, find the device number and return it in eax
481
 
482
  .find_devicenum:
483
        DEBUGF  1,"Trying to find device number of already registered device\n"
4532 hidnplayr 484
        invoke  NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
3545 hidnplayr 485
                                                                        ; into a device number in edi
486
        mov     eax, edi                                                ; Application wants it in eax instead
487
        DEBUGF  1,"Kernel says: %u\n", eax
488
        ret
489
 
490
; If an error occured, remove all allocated data and exit (returning -1 in eax)
491
 
492
  .destroy:
493
        ; todo: reset device into virgin state
494
 
495
        dec     [devices]
496
  .err:
3855 hidnplayr 497
        DEBUGF  2,"Error, removing all data !\n"
4532 hidnplayr 498
        invoke  KernelFree, ebx
3545 hidnplayr 499
 
500
  .fail:
501
        or      eax, -1
502
        ret
503
 
504
;------------------------------------------------------
505
endp
506
 
507
 
508
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
509
;;                                                                        ;;
510
;;        Actual Hardware dependent code starts here                      ;;
511
;;                                                                        ;;
512
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
513
 
514
align 4
515
unload:
516
        ; TODO: (in this particular order)
517
        ;
518
        ; - Stop the device
519
        ; - Detach int handler
4532 hidnplayr 520
        ; - Remove device from local list (device_list)
3545 hidnplayr 521
        ; - call unregister function in kernel
522
        ; - Remove all allocated structures and buffers the card used
523
 
524
        or      eax,-1
525
 
526
ret
527
 
528
 
529
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
530
;;
531
;;  probe: enables the device (if it really is a PCnet device)
532
;;
533
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
534
 
535
align 4
536
probe:
537
 
4532 hidnplayr 538
        mov     edx, [ebx + device.io_addr]
3545 hidnplayr 539
 
540
        call    wio_reset
541
 
542
        xor     ecx, ecx
543
        call    wio_read_csr
544
        cmp     eax, 4
545
        jne     .try_dwio
546
 
547
        ; Try Word I/O
548
        mov     ax, 88
549
        add     edx, WIO_RAP
550
        out     dx, ax
551
        nop
552
        nop
553
        in      ax, dx
554
        sub     edx, WIO_RAP
555
        cmp     ax, 88
556
        jne     .try_dwio
557
 
558
        call    switch_to_wio
559
 
560
        jmp     .L1
561
 
562
  .try_dwio:
563
        call    dwio_reset
564
 
565
        xor     ecx, ecx
566
        call    dwio_read_csr
567
        cmp     eax, 4
568
        jne     .no_dev
569
 
570
        ; Try Dword I/O
571
        add     edx, DWIO_RAP
572
        mov     eax, 88
573
        out     dx, eax
574
        nop
575
        nop
576
        in      eax, dx
577
        sub     edx, DWIO_RAP
578
        and     eax, 0xffff
579
        cmp     eax, 88
580
        jne     .no_dev
581
 
582
        call    switch_to_dwio
583
 
584
        jmp     .L1
585
 
586
  .no_dev:
4532 hidnplayr 587
        DEBUGF  2,"device not found!\n"
3545 hidnplayr 588
        mov     eax, 1
589
        ret
590
 
591
  .L1:
592
        mov     ecx, CSR_CHIPID0
4532 hidnplayr 593
        call    [ebx + device.read_csr]
3545 hidnplayr 594
 
595
        mov     esi, eax
596
        shr     esi, 12
597
 
598
        and     ax, 0xfff
599
        cmp     ax, 3
600
        jne     .no_dev
601
 
602
        mov     ecx, CSR_CHIPID1
4532 hidnplayr 603
        call    [ebx + device.read_csr]
3545 hidnplayr 604
        shl     eax, 4
605
        or      eax, esi
4532 hidnplayr 606
        mov     [ebx + device.chip_version], ax
3545 hidnplayr 607
 
4532 hidnplayr 608
        mov     [ebx + device.fdx], 0
609
        mov     [ebx + device.mii], 0
610
        mov     [ebx + device.fset], 0
611
        mov     [ebx + device.dxsuflo], 0
612
        mov     [ebx + device.ltint], 0
3545 hidnplayr 613
 
614
        cmp     ax, 0x2420
615
        je      .L2
616
        cmp     ax, 0x2430
617
        je      .L2
618
 
4532 hidnplayr 619
        mov     [ebx + device.fdx], 1
3545 hidnplayr 620
 
621
        cmp     ax, 0x2621
622
        je      .L4
623
        cmp     ax, 0x2623
624
        je      .L5
625
        cmp     ax, 0x2624
626
        je      .L6
627
        cmp     ax, 0x2625
628
        je      .L7
629
        cmp     ax, 0x2626
630
        je      .L8
631
        cmp     ax, 0x2627
632
        je      .L9
633
 
5065 hidnplayr 634
        DEBUGF  2,"Invalid chip rev\n"
3545 hidnplayr 635
        jmp     .no_dev
636
  .L2:
4532 hidnplayr 637
        mov     [ebx + device.name], device_l2
3545 hidnplayr 638
        jmp     .L10
639
  .L4:
4532 hidnplayr 640
        mov     [ebx + device.name], device_l4
641
;        mov     [ebx + device.fdx], 1
3545 hidnplayr 642
        jmp     .L10
643
  .L5:
4532 hidnplayr 644
        mov     [ebx + device.name], device_l5
645
;        mov     [ebx + device.fdx], 1
646
        mov     [ebx + device.mii], 1
647
        mov     [ebx + device.fset], 1
648
        mov     [ebx + device.ltint], 1
3545 hidnplayr 649
        jmp     .L10
650
  .L6:
4532 hidnplayr 651
        mov     [ebx + device.name], device_l6
652
;        mov     [ebx + device.fdx], 1
653
        mov     [ebx + device.mii], 1
654
        mov     [ebx + device.fset], 1
3545 hidnplayr 655
        jmp     .L10
656
  .L7:
4532 hidnplayr 657
        mov     [ebx + device.name], device_l7
658
;        mov     [ebx + device.fdx], 1
659
        mov     [ebx + device.mii], 1
3545 hidnplayr 660
        jmp     .L10
661
  .L8:
4532 hidnplayr 662
        mov     [ebx + device.name], device_l8
663
;        mov     [ebx + device.fdx], 1
3545 hidnplayr 664
        mov     ecx, CSR_RXPOLL
4532 hidnplayr 665
        call    dword [ebx + device.read_bcr]
666
        call    dword [ebx + device.write_bcr]
3545 hidnplayr 667
        jmp     .L10
668
  .L9:
4532 hidnplayr 669
        mov     [ebx + device.name], device_l9
670
;        mov     [ebx + device.fdx], 1
671
        mov     [ebx + device.mii], 1
3545 hidnplayr 672
  .L10:
4532 hidnplayr 673
        DEBUGF  1,"device name: %s\n", [ebx + device.name]
3545 hidnplayr 674
 
4532 hidnplayr 675
        cmp     [ebx + device.fset], 1
3545 hidnplayr 676
        jne     .L11
677
        mov     ecx, BCR_BUSCTL
4532 hidnplayr 678
        call    [ebx + device.read_bcr]
3545 hidnplayr 679
        or      eax, 0x800
4532 hidnplayr 680
        call    [ebx + device.write_bcr]
3545 hidnplayr 681
 
682
        mov     ecx, CSR_DMACTL
4532 hidnplayr 683
        call    [ebx + device.read_csr]
3545 hidnplayr 684
;        and     eax, 0xc00
685
;        or      eax, 0xc00
686
        mov     eax, 0xc00
4532 hidnplayr 687
        call    [ebx + device.write_csr]
3545 hidnplayr 688
 
4532 hidnplayr 689
        mov     [ebx + device.dxsuflo],1
690
        mov     [ebx + device.ltint],1
3545 hidnplayr 691
  .L11:
692
 
4532 hidnplayr 693
; Make the device a bus master
694
        invoke  PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command
695
        or      al, PCI_CMD_MASTER
696
        invoke  PciWrite32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command, eax
3545 hidnplayr 697
 
4532 hidnplayr 698
        mov     [ebx + device.options], PORT_ASEL
699
        mov     [ebx + device.mode], MODE_RXD + MODE_TXD     ; disable receive and transmit
700
        mov     [ebx + device.tlen_rlen], (TX_RING_LEN_BITS or RX_RING_LEN_BITS)
3545 hidnplayr 701
 
4532 hidnplayr 702
        mov     dword[ebx + device.filter], 0
703
        mov     dword[ebx + device.filter+4], 0
3545 hidnplayr 704
 
705
align 4
706
reset:
707
 
708
; attach int handler
709
 
4532 hidnplayr 710
        movzx   eax, [ebx + device.irq_line]
3545 hidnplayr 711
        DEBUGF  1,"Attaching int handler to irq %x\n", eax:1
4532 hidnplayr 712
        invoke  AttachIntHandler, eax, int_handler, ebx
3545 hidnplayr 713
        test    eax, eax
714
        jnz     @f
3855 hidnplayr 715
        DEBUGF  2,"Could not attach int handler!\n"
4532 hidnplayr 716
        or      eax, -1
717
        ret
3545 hidnplayr 718
  @@:
719
 
4532 hidnplayr 720
        mov     edx, [ebx + device.io_addr]
721
        call    [ebx + device.sw_reset]
3545 hidnplayr 722
 
723
        ; Switch pcnet32 to 32bit mode
724
        mov     ecx, BCR_SSTYLE
725
        mov     eax, 2
4532 hidnplayr 726
        call    [ebx + device.write_bcr]
3545 hidnplayr 727
 
728
        ; set/reset autoselect bit
729
        mov     ecx, BCR_MISCCFG
4532 hidnplayr 730
        call    [ebx + device.read_bcr]
3545 hidnplayr 731
        and     eax, not 2
4532 hidnplayr 732
        test    [ebx + device.options], PORT_ASEL
3545 hidnplayr 733
        jz      @f
734
        or      eax, 2
735
  @@:
4532 hidnplayr 736
        call    [ebx + device.write_bcr]
3545 hidnplayr 737
 
738
        ; Handle full duplex setting
4532 hidnplayr 739
        cmp     byte [ebx + device.full_duplex], 0
3545 hidnplayr 740
        je      .duplex_ok
741
        mov     ecx, BCR_DUPLEX
4532 hidnplayr 742
        call    [ebx + device.read_bcr]
3545 hidnplayr 743
        and     eax, not 3
4532 hidnplayr 744
        test    [ebx + device.options], PORT_FD
3545 hidnplayr 745
        jz      @f
746
        or      eax, 1
4532 hidnplayr 747
        cmp     [ebx + device.options], PORT_FD or PORT_AUI
3545 hidnplayr 748
        jne     .set_duplex
749
        or      eax, 2
750
        jmp     .set_duplex
751
  @@:
4532 hidnplayr 752
        test    [ebx + device.options], PORT_ASEL
3545 hidnplayr 753
        jz      .set_duplex
4532 hidnplayr 754
        cmp     [ebx + device.chip_version], 0x2627
3545 hidnplayr 755
        jne     .set_duplex
756
        or      eax, 3
757
  .set_duplex:
758
        mov     ecx, BCR_DUPLEX
4532 hidnplayr 759
        call    [ebx + device.write_bcr]
3545 hidnplayr 760
  .duplex_ok:
761
 
762
        ; set/reset GPSI bit in test register
763
        mov     ecx, 124
4532 hidnplayr 764
        call    [ebx + device.read_csr]
765
        mov     ecx, [ebx + device.options]
3545 hidnplayr 766
        and     ecx, PORT_PORTSEL
767
        cmp     ecx, PORT_GPSI
768
        jne     @f
769
        or      eax, 0x10
770
  @@:
4532 hidnplayr 771
        call    [ebx + device.write_csr]
772
        cmp     [ebx + device.mii], 0
3545 hidnplayr 773
        je      .L6
4532 hidnplayr 774
        test    [ebx + device.options], PORT_ASEL
3545 hidnplayr 775
        jnz     .L6
776
        mov     ecx, BCR_MIICTL
4532 hidnplayr 777
        call    [ebx + device.read_bcr]
3545 hidnplayr 778
        and     eax, not 0x38
4532 hidnplayr 779
        test    [ebx + device.options], PORT_FD
3545 hidnplayr 780
        jz      @f
781
        or      eax, 0x10
782
  @@:
4532 hidnplayr 783
        test    [ebx + device.options], PORT_100
3545 hidnplayr 784
        jz      @f
785
        or      eax, 0x08
786
  @@:
4532 hidnplayr 787
        call    [ebx + device.write_bcr]
3545 hidnplayr 788
        jmp     .L9
789
  .L6:
4532 hidnplayr 790
        test    [ebx + device.options], PORT_ASEL
3545 hidnplayr 791
        jz      .L9
792
        mov     ecx, BCR_MIICTL
3855 hidnplayr 793
        DEBUGF  1,"ASEL, enable auto-negotiation\n"
4532 hidnplayr 794
        call    [ebx + device.read_bcr]
3545 hidnplayr 795
        and     eax, not 0x98
796
        or      eax, 0x20
4532 hidnplayr 797
        call    [ebx + device.write_bcr]
3545 hidnplayr 798
  .L9:
4532 hidnplayr 799
        cmp     [ebx + device.ltint], 0
3545 hidnplayr 800
        je      @f
801
        mov     ecx, 5
4532 hidnplayr 802
        call    [ebx + device.read_csr]
3545 hidnplayr 803
        or      eax, (1 shl 14)
4532 hidnplayr 804
        call    [ebx + device.write_csr]
3545 hidnplayr 805
  @@:
4532 hidnplayr 806
        mov     eax, [ebx + device.options]
3545 hidnplayr 807
        and     eax, PORT_PORTSEL
808
        shl     eax, 7
4532 hidnplayr 809
        mov     [ebx + device.mode], ax
810
        mov     dword [ebx + device.filter], -1
811
        mov     dword [ebx + device.filter+4], -1
3545 hidnplayr 812
 
813
 
814
 
815
;-----------------------------
816
 
4532 hidnplayr 817
        test    [ebx + device.mii], 1
3545 hidnplayr 818
        jz      .no_mii
819
 
4532 hidnplayr 820
        mov     [ebx + device.phy], 0
3545 hidnplayr 821
 
822
  .mii_loop:
823
        mov     ecx, MII_PHYSID1
824
        call    mdio_read
825
        cmp     ax, 0xffff
826
        je      .next
827
 
828
        DEBUGF  1, "0x%x\n", ax
829
 
830
        mov     ecx, MII_PHYSID2
831
        call    mdio_read
832
        cmp     ax, 0xffff
833
        je      .next
834
 
835
        DEBUGF  1, "0x%x\n", ax
836
 
837
        jmp     .got_phy
838
 
4532 hidnplayr 839
        cmp     [ebx + device.phy], 31
3545 hidnplayr 840
        jne     .next
4532 hidnplayr 841
        mov     ax, [ebx + device.chip_version]
3545 hidnplayr 842
        inc     ax
843
        and     ax, 0xfffe
844
        cmp     ax, 0x2624              ; 79c971 & 79c972 have phantom phy at id 31
845
        je      .got_phy
846
 
847
  .next:
4532 hidnplayr 848
        inc     [ebx + device.phy]
849
        cmp     [ebx + device.phy], MAX_PHYS
3545 hidnplayr 850
        jb      .mii_loop
851
 
3855 hidnplayr 852
        DEBUGF  2, "No PHY found!\n"
3545 hidnplayr 853
        or      eax, -1
854
        ret
855
 
856
  .got_phy:
4532 hidnplayr 857
        DEBUGF  1, "Found PHY at 0x%x\n", [ebx + device.phy]:4
3545 hidnplayr 858
 
859
  .no_mii:
860
 
861
;-----------------------------------------------
862
 
863
        call    read_mac
864
 
4532 hidnplayr 865
        lea     esi, [ebx + device.mac]
866
        lea     edi, [ebx + device.phys_addr]
3545 hidnplayr 867
        movsd
868
        movsw
869
 
870
        call    init_ring
871
 
4532 hidnplayr 872
        mov     edx, [ebx + device.io_addr]   ; init ring destroys edx
3545 hidnplayr 873
 
4532 hidnplayr 874
        lea     eax, [ebx + device.mode]
875
        invoke  GetPhysAddr
3545 hidnplayr 876
        push    eax
877
        and     eax, 0xffff
878
        mov     ecx, 1
4532 hidnplayr 879
        call    [ebx + device.write_csr]
3545 hidnplayr 880
        pop     eax
881
        shr     eax, 16
882
        mov     ecx, 2
4532 hidnplayr 883
        call    [ebx + device.write_csr]
3545 hidnplayr 884
 
885
        mov     ecx, 4
886
        mov     eax, 0x0915
4532 hidnplayr 887
        call    [ebx + device.write_csr]
3545 hidnplayr 888
 
889
; Set the interrupt mask
890
        mov     ecx, CSR_IMR
891
        mov     eax, IMR
4532 hidnplayr 892
        call    [ebx + device.write_csr]
3545 hidnplayr 893
 
894
; Initialise the device
895
        xor     ecx, ecx
896
        mov     eax, CSR_INIT
4532 hidnplayr 897
        call    [ebx + device.write_csr]
3545 hidnplayr 898
 
899
        mov     esi, 100
900
;        xor     ecx, ecx
901
  @@:
4532 hidnplayr 902
        call    [ebx + device.read_csr]
3545 hidnplayr 903
        test    ax, CSR_IDONE
904
        jnz     @f
905
 
906
        dec     esi
907
        jnz     @r
3855 hidnplayr 908
        DEBUGF  2,"Initialize timeout!\n"
3545 hidnplayr 909
  @@:
910
 
911
; Start the device and enable interrupts
912
        xor     ecx, ecx
913
        mov     eax, CSR_START + CSR_INTEN
4532 hidnplayr 914
        call    [ebx + device.write_csr]
3545 hidnplayr 915
 
916
; Set the mtu, kernel will be able to send now
4532 hidnplayr 917
        mov     [ebx + device.mtu], 1514
3545 hidnplayr 918
 
919
; get link status
4580 hidnplayr 920
        mov     [ebx + device.state], ETH_LINK_UNKNOWN
3545 hidnplayr 921
 
922
        call    check_media
923
 
3855 hidnplayr 924
        DEBUGF  1,"reset complete\n"
3545 hidnplayr 925
        xor     eax, eax
926
        ret
927
 
928
 
929
align 4
930
init_ring:
931
 
3855 hidnplayr 932
        DEBUGF  1,"init ring\n"
3545 hidnplayr 933
 
4532 hidnplayr 934
        lea     edi, [ebx + device.rx_ring]
3545 hidnplayr 935
        mov     eax, edi
4532 hidnplayr 936
        invoke  GetPhysAddr
937
        mov     [ebx + device.rx_ring_phys], eax
3545 hidnplayr 938
        mov     ecx, RX_RING_SIZE
939
  .rx_init:
940
        push    ecx
4532 hidnplayr 941
        invoke  KernelAlloc, PKT_BUF_SZ
3545 hidnplayr 942
        pop     ecx
943
        mov     [edi + descriptor.virtual], eax
4532 hidnplayr 944
        invoke  GetPhysAddr
3545 hidnplayr 945
        mov     [edi + descriptor.base], eax
946
        mov     [edi + descriptor.length], - PKT_BUF_SZ
947
        mov     [edi + descriptor.status], RXSTAT_OWN
4532 hidnplayr 948
        mov     dword[edi + descriptor.msg_length], 0    ; also clears misc field
949
        add     edi, sizeof.descriptor
3545 hidnplayr 950
        dec     ecx
951
        jnz     .rx_init
952
 
4532 hidnplayr 953
        lea     edi, [ebx + device.tx_ring]
3545 hidnplayr 954
        mov     eax, edi
4532 hidnplayr 955
        invoke  GetPhysAddr
956
        mov     [ebx + device.tx_ring_phys], eax
3545 hidnplayr 957
        mov     ecx, TX_RING_SIZE
958
  .tx_init:
959
        mov     [edi + descriptor.status], 0
4532 hidnplayr 960
        add     edi, sizeof.descriptor
3545 hidnplayr 961
        dec     ecx
962
        jnz     .tx_init
963
 
4532 hidnplayr 964
        mov     [ebx + device.tlen_rlen], (TX_RING_LEN_BITS or RX_RING_LEN_BITS)
3545 hidnplayr 965
 
4532 hidnplayr 966
        mov     [ebx + device.cur_tx], 0
967
        mov     [ebx + device.last_tx], 0
968
        mov     [ebx + device.cur_rx], 0
3545 hidnplayr 969
 
970
        ret
971
 
972
 
973
 
974
 
975
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
976
;;                                         ;;
977
;; Transmit                                ;;
978
;;                                         ;;
4532 hidnplayr 979
;; In: pointer to device structure in ebx  ;;
3545 hidnplayr 980
;;                                         ;;
981
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
982
 
4532 hidnplayr 983
proc transmit stdcall bufferptr, buffersize
984
 
985
        pushf
986
        cli
987
 
988
        DEBUGF  1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [buffersize]
989
        mov     eax, [bufferptr]
3545 hidnplayr 990
        DEBUGF  1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
991
        [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
992
        [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
993
        [eax+13]:2,[eax+12]:2
994
 
4532 hidnplayr 995
        cmp     [buffersize], 1514
996
        ja      .fail
997
        cmp     [buffersize], 60
998
        jb      .fail
3545 hidnplayr 999
 
1000
; check descriptor
4532 hidnplayr 1001
        lea     edi, [ebx + device.tx_ring]
1002
        movzx   eax, [ebx + device.cur_tx]
3545 hidnplayr 1003
        shl     eax, 4
1004
        add     edi, eax
1005
 
1006
        test    [edi + descriptor.status], TXCTL_OWN
4532 hidnplayr 1007
        jnz     .fail
3545 hidnplayr 1008
; descriptor is free, use it
4532 hidnplayr 1009
        mov     eax, [bufferptr]
3545 hidnplayr 1010
        mov     [edi + descriptor.virtual], eax
4532 hidnplayr 1011
        invoke  GetPhysAddr
3545 hidnplayr 1012
        mov     [edi + descriptor.base], eax
1013
; set length
4532 hidnplayr 1014
        mov     eax, [buffersize]
3545 hidnplayr 1015
        neg     eax
1016
        mov     [edi + descriptor.length], ax
1017
; put to transfer queue
1018
        mov     [edi + descriptor.status], TXCTL_OWN + TXCTL_STP + TXCTL_ENP
1019
 
1020
; trigger an immediate send
4532 hidnplayr 1021
        mov     edx, [ebx + device.io_addr]
3545 hidnplayr 1022
        xor     ecx, ecx                        ; CSR0
4532 hidnplayr 1023
        call    [ebx + device.read_csr]
3545 hidnplayr 1024
        or      eax, CSR_TX
4532 hidnplayr 1025
        call    [ebx + device.write_csr]
3545 hidnplayr 1026
 
1027
; get next descriptor 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, ...
4532 hidnplayr 1028
        inc     [ebx + device.cur_tx]
1029
        and     [ebx + device.cur_tx], TX_RING_SIZE - 1
3545 hidnplayr 1030
 
1031
; Update stats
4532 hidnplayr 1032
        inc     [ebx + device.packets_tx]
1033
        mov     eax, [buffersize]
1034
        add     dword[ebx + device.bytes_tx], eax
1035
        adc     dword[ebx + device.bytes_tx + 4], 0
3545 hidnplayr 1036
 
1037
  .finish:
4532 hidnplayr 1038
        popf
3545 hidnplayr 1039
        xor     eax, eax
4532 hidnplayr 1040
        ret
3545 hidnplayr 1041
 
4532 hidnplayr 1042
  .fail:
1043
        DEBUGF  2, "Send failed\n"
1044
        invoke  KernelFree, [bufferptr]
1045
        popf
3545 hidnplayr 1046
        or      eax, -1
4532 hidnplayr 1047
        ret
3545 hidnplayr 1048
 
4532 hidnplayr 1049
endp
3545 hidnplayr 1050
 
1051
 
1052
;;;;;;;;;;;;;;;;;;;;;;;
1053
;;                   ;;
1054
;; Interrupt handler ;;
1055
;;                   ;;
1056
;;;;;;;;;;;;;;;;;;;;;;;
1057
 
1058
align 4
1059
int_handler:
1060
 
1061
        push    ebx esi edi
1062
 
3855 hidnplayr 1063
        DEBUGF  1,"INT\n"
3545 hidnplayr 1064
 
1065
; find pointer of device wich made IRQ occur
1066
 
1067
        mov     ecx, [devices]
1068
        test    ecx, ecx
1069
        jz      .nothing
1070
        mov     esi, device_list
1071
  .nextdevice:
1072
        mov     ebx, [esi]
4532 hidnplayr 1073
        mov     edx, [ebx + device.io_addr]
3545 hidnplayr 1074
        push    ecx
1075
        xor     ecx, ecx                        ; CSR0
4532 hidnplayr 1076
        call    [ebx + device.read_csr]         ; get IRQ reason
1077
        call    [ebx + device.write_csr]        ; write it back to ACK
3545 hidnplayr 1078
        pop     ecx
5004 hidnplayr 1079
;;;        and     ax, CSR_RINT or CSR_TINT
1080
        test    ax, ax
3545 hidnplayr 1081
        jnz     .got_it
1082
  .continue:
1083
        add     esi, 4
1084
        dec     ecx
1085
        jnz     .nextdevice
1086
  .nothing:
1087
        pop     edi esi ebx
1088
        xor     eax, eax
1089
 
1090
        ret
1091
 
1092
  .got_it:
5065 hidnplayr 1093
        DEBUGF  1,"Device: %x status: %x\n", ebx, eax:4
3545 hidnplayr 1094
 
1095
        push    ax
1096
        test    ax, CSR_RINT
1097
        jz      .not_receive
1098
 
1099
        push    ebx
1100
  .rx_loop:
1101
        pop     ebx
4532 hidnplayr 1102
        movzx   eax, [ebx + device.cur_rx]
3545 hidnplayr 1103
        shl     eax, 4
4532 hidnplayr 1104
        lea     edi, [ebx + device.rx_ring]
3545 hidnplayr 1105
        add     edi, eax                        ; edi now points to current rx ring entry
1106
 
1107
        mov     ax, [edi + descriptor.status]
1108
        DEBUGF  1,"RX packet status: %x\n", eax:4
1109
 
1110
        test    ax, RXSTAT_OWN                  ; If this bit is set, the controller OWN's the packet, if not, we do
1111
        jnz     .not_receive
1112
 
1113
        test    ax, RXSTAT_ENP
1114
        jz      .not_receive
1115
 
1116
        test    ax, RXSTAT_STP
1117
        jz      .not_receive
1118
 
1119
        movzx   ecx, [edi + descriptor.msg_length]      ; get packet length in ecx
4532 hidnplayr 1120
        sub     ecx, 4                                  ; We dont need the CRC
1121
        DEBUGF  1,"Got %u bytes\n", ecx
3545 hidnplayr 1122
 
1123
; Set pointers for ETH_input
1124
        push    ebx
1125
 
1126
        push    .rx_loop                                ; return address
1127
        push    ecx                                     ; packet size
1128
        push    [edi + descriptor.virtual]              ; packet address
1129
 
1130
; Update stats
4532 hidnplayr 1131
        add     dword[ebx + device.bytes_rx], ecx
1132
        adc     dword[ebx + device.bytes_rx + 4], 0
1133
        inc     [ebx + device.packets_rx]
3545 hidnplayr 1134
 
1135
; now allocate a new buffer
4532 hidnplayr 1136
        invoke  KernelAlloc, PKT_BUF_SZ                 ; Allocate a buffer for the next packet
3545 hidnplayr 1137
        mov     [edi + descriptor.virtual], eax         ; set virtual address
4532 hidnplayr 1138
        invoke  GetPhysAddr
1139
        mov     [edi + descriptor.base], eax            ; and physical address
3545 hidnplayr 1140
        mov     [edi + descriptor.status], RXSTAT_OWN   ; give it back to PCnet controller
1141
 
4532 hidnplayr 1142
        inc     [ebx + device.cur_rx]                   ; set next receive descriptor
1143
        and     [ebx + device.cur_rx], RX_RING_SIZE - 1
3545 hidnplayr 1144
 
4532 hidnplayr 1145
        jmp     [Eth_input]
3545 hidnplayr 1146
 
1147
  .not_receive:
1148
        pop     ax
1149
 
1150
        test    ax, CSR_TINT
1151
        jz      .not_transmit
1152
 
1153
  .tx_loop:
4532 hidnplayr 1154
        lea     edi, [ebx + device.tx_ring]
1155
        movzx   eax, [ebx + device.last_tx]
3545 hidnplayr 1156
        shl     eax, 4
1157
        add     edi, eax
1158
 
1159
        test    [edi + descriptor.status], TXCTL_OWN
1160
        jnz     .not_transmit
1161
 
1162
        mov     eax, [edi + descriptor.virtual]
1163
        test    eax, eax
1164
        jz      .not_transmit
1165
 
1166
        mov     [edi + descriptor.virtual], 0
1167
 
1168
        DEBUGF  1,"Removing packet %x from memory\n", eax
1169
 
4532 hidnplayr 1170
        invoke  KernelFree, eax
3545 hidnplayr 1171
 
4532 hidnplayr 1172
        inc     [ebx + device.last_tx]
1173
        and     [ebx + device.last_tx], TX_RING_SIZE - 1
3545 hidnplayr 1174
        jmp     .tx_loop
1175
 
1176
  .not_transmit:
1177
        pop     edi esi ebx
1178
        xor     eax, eax
1179
        inc     eax
1180
 
1181
        ret
1182
 
1183
 
1184
 
1185
 
1186
;;;;;;;;;;;;;;;;;;;;;;;
1187
;;                   ;;
1188
;; Write MAC address ;;
1189
;;                   ;;
1190
;;;;;;;;;;;;;;;;;;;;;;;
1191
 
1192
align 4
1193
write_mac:      ; in: mac pushed onto stack (as 3 words)
1194
 
4532 hidnplayr 1195
        DEBUGF  1,"Writing MAC: %x-%x-%x-%x-%x-%x\n",\
1196
        [esp+0]:2,[esp+1]:2,[esp+2]:2,[esp+3]:2,[esp+4]:2,[esp+5]:2
3545 hidnplayr 1197
 
4532 hidnplayr 1198
        mov     edx, [ebx + device.io_addr]
3545 hidnplayr 1199
        add     dx, 2
1200
        xor     eax, eax
1201
 
1202
        mov     ecx, CSR_PAR0
1203
       @@:
1204
        pop     ax
4532 hidnplayr 1205
        call    [ebx + device.write_csr]
3545 hidnplayr 1206
        inc     ecx
1207
        cmp     ecx, CSR_PAR2
1208
        jb      @r
1209
 
1210
; Notice this procedure does not ret, but continues to read_mac instead.
1211
 
1212
;;;;;;;;;;;;;;;;;;;;;;
1213
;;                  ;;
1214
;; Read MAC address ;;
1215
;;                  ;;
1216
;;;;;;;;;;;;;;;;;;;;;;
1217
align 4
1218
read_mac:
4532 hidnplayr 1219
        DEBUGF  1,"Reading MAC\n"
3545 hidnplayr 1220
 
4532 hidnplayr 1221
        mov     edx, [ebx + device.io_addr]
1222
        lea     edi, [ebx + device.mac]
3545 hidnplayr 1223
        in      ax, dx
4532 hidnplayr 1224
        stosw
3545 hidnplayr 1225
 
4532 hidnplayr 1226
        inc     dx
1227
        inc     dx
1228
        in      ax, dx
1229
        stosw
3545 hidnplayr 1230
 
4532 hidnplayr 1231
        inc     dx
1232
        inc     dx
1233
        in      ax, dx
3545 hidnplayr 1234
        stosw
1235
 
4532 hidnplayr 1236
        DEBUGF  1,"MAC = %x-%x-%x-%x-%x-%x\n",\
1237
        [ebx + device.mac+0]:2,[ebx + device.mac+1]:2,[ebx + device.mac+2]:2,\
1238
        [ebx + device.mac+3]:2,[ebx + device.mac+4]:2,[ebx + device.mac+5]:2
1239
 
3545 hidnplayr 1240
        ret
1241
 
1242
align 4
1243
switch_to_wio:
1244
 
1245
        DEBUGF  1,"Switching to 16-bit mode\n"
1246
 
4532 hidnplayr 1247
        mov     [ebx + device.read_csr], wio_read_csr
1248
        mov     [ebx + device.write_csr], wio_write_csr
1249
        mov     [ebx + device.read_bcr], wio_read_bcr
1250
        mov     [ebx + device.write_bcr], wio_write_bcr
1251
        mov     [ebx + device.read_rap], wio_read_rap
1252
        mov     [ebx + device.write_rap], wio_write_rap
1253
        mov     [ebx + device.sw_reset], wio_reset
3545 hidnplayr 1254
 
1255
        ret
1256
 
1257
align 4
1258
switch_to_dwio:
1259
 
1260
        DEBUGF  1,"Switching to 32-bit mode\n"
1261
 
4532 hidnplayr 1262
        mov     [ebx + device.read_csr], dwio_read_csr
1263
        mov     [ebx + device.write_csr], dwio_write_csr
1264
        mov     [ebx + device.read_bcr], dwio_read_bcr
1265
        mov     [ebx + device.write_bcr], dwio_write_bcr
1266
        mov     [ebx + device.read_rap], dwio_read_rap
1267
        mov     [ebx + device.write_rap], dwio_write_rap
1268
        mov     [ebx + device.sw_reset], dwio_reset
3545 hidnplayr 1269
 
1270
        ret
1271
 
1272
 
1273
; ecx - index
1274
; return:
1275
; eax - data
1276
align 4
1277
wio_read_csr:
1278
 
1279
        add     edx, WIO_RAP
1280
        mov     ax, cx
1281
        out     dx, ax
1282
        add     edx, WIO_RDP - WIO_RAP
1283
        in      ax, dx
1284
        and     eax, 0xffff
1285
        sub     edx, WIO_RDP
1286
 
1287
        ret
1288
 
1289
 
1290
; eax - data
1291
; ecx - index
1292
align 4
1293
wio_write_csr:
1294
 
1295
        add     edx, WIO_RAP
1296
        xchg    eax, ecx
1297
        out     dx, ax
1298
        xchg    eax, ecx
1299
        add     edx, WIO_RDP - WIO_RAP
1300
        out     dx, ax
1301
        sub     edx, WIO_RDP
1302
 
1303
        ret
1304
 
1305
 
1306
; ecx - index
1307
; return:
1308
; eax - data
1309
align 4
1310
wio_read_bcr:
1311
 
1312
        add     edx, WIO_RAP
1313
        mov     ax, cx
1314
        out     dx, ax
1315
        add     edx, WIO_BDP - WIO_RAP
1316
        in      ax, dx
1317
        and     eax, 0xffff
1318
        sub     edx, WIO_BDP
1319
 
1320
        ret
1321
 
1322
 
1323
; eax - data
1324
; ecx - index
1325
align 4
1326
wio_write_bcr:
1327
 
1328
        add     edx, WIO_RAP
1329
        xchg    eax, ecx
1330
        out     dx, ax
1331
        xchg    eax, ecx
1332
        add     edx, WIO_BDP - WIO_RAP
1333
        out     dx, ax
1334
        sub     edx, WIO_BDP
1335
 
1336
        ret
1337
 
1338
align 4
1339
wio_read_rap:
1340
 
1341
        add     edx, WIO_RAP
1342
        in      ax, dx
1343
        and     eax, 0xffff
1344
        sub     edx, WIO_RAP
1345
 
1346
        ret
1347
 
1348
; eax - val
1349
align 4
1350
wio_write_rap:
1351
 
1352
        add     edx, WIO_RAP
1353
        out     dx, ax
1354
        sub     edx, WIO_RAP
1355
 
1356
        ret
1357
 
1358
align 4
1359
wio_reset:
1360
 
1361
        push    eax
1362
        add     edx, WIO_RESET
1363
        in      ax, dx
1364
        pop     eax
1365
        sub     edx, WIO_RESET
1366
 
1367
        ret
1368
 
1369
 
1370
 
1371
; ecx - index
1372
; return:
1373
; eax - data
1374
align 4
1375
dwio_read_csr:
1376
 
1377
        add     edx, DWIO_RAP
1378
        mov     eax, ecx
1379
        out     dx, eax
1380
        add     edx, DWIO_RDP - DWIO_RAP
1381
        in      eax, dx
1382
        and     eax, 0xffff
1383
        sub     edx, DWIO_RDP
1384
 
1385
        ret
1386
 
1387
 
1388
; ecx - index
1389
; eax - data
1390
align 4
1391
dwio_write_csr:
1392
 
1393
        add     edx, DWIO_RAP
1394
        xchg    eax, ecx
1395
        out     dx, eax
1396
        add     edx, DWIO_RDP - DWIO_RAP
1397
        xchg    eax, ecx
1398
        out     dx, eax
1399
        sub     edx, DWIO_RDP
1400
 
1401
        ret
1402
 
1403
; ecx - index
1404
; return:
1405
; eax - data
1406
align 4
1407
dwio_read_bcr:
1408
 
1409
        add     edx, DWIO_RAP
1410
        mov     eax, ecx
1411
        out     dx, eax
1412
        add     edx, DWIO_BDP - DWIO_RAP
1413
        in      eax, dx
1414
        and     eax, 0xffff
1415
        sub     edx, DWIO_BDP
1416
 
1417
        ret
1418
 
1419
 
1420
; ecx - index
1421
; eax - data
1422
align 4
1423
dwio_write_bcr:
1424
 
1425
        add     edx, DWIO_RAP
1426
        xchg    eax, ecx
1427
        out     dx, eax
1428
        add     edx, DWIO_BDP - DWIO_RAP
1429
        xchg    eax, ecx
1430
        out     dx, eax
1431
        sub     edx, DWIO_BDP
1432
 
1433
        ret
1434
 
1435
align 4
1436
dwio_read_rap:
1437
 
1438
        add     edx, DWIO_RAP
1439
        in      eax, dx
1440
        and     eax, 0xffff
1441
        sub     edx, DWIO_RAP
1442
 
1443
        ret
1444
 
1445
 
1446
; eax - val
1447
align 4
1448
dwio_write_rap:
1449
 
1450
        add     edx, DWIO_RAP
1451
        out     dx, eax
1452
        sub     edx, DWIO_RAP
1453
 
1454
        ret
1455
 
1456
align 4
1457
dwio_reset:
1458
 
1459
        push    eax
1460
        add     edx, DWIO_RESET
1461
        in      eax, dx
1462
        pop     eax
1463
        sub     edx, DWIO_RESET
1464
 
1465
        ret
1466
 
1467
 
1468
align 4
1469
mdio_read:
1470
 
1471
        and     ecx, 0x1f
4532 hidnplayr 1472
        mov     ax, [ebx + device.phy]
3545 hidnplayr 1473
        and     ax, 0x1f
1474
        shl     ax, 5
1475
        or      ax, cx
1476
 
1477
        mov     ecx, BCR_MIIADDR
4532 hidnplayr 1478
        call    [ebx + device.write_bcr]
3545 hidnplayr 1479
 
1480
        mov     ecx, BCR_MIIDATA
4532 hidnplayr 1481
        call    [ebx + device.read_bcr]
3545 hidnplayr 1482
 
1483
        ret
1484
 
1485
 
1486
align 4
1487
mdio_write:
1488
 
1489
        push    eax
1490
        and     ecx, 0x1f
4532 hidnplayr 1491
        mov     ax, [ebx + device.phy]
3545 hidnplayr 1492
        and     ax, 0x1f
1493
        shl     ax, 5
1494
        or      ax, cx
1495
 
1496
        mov     ecx, BCR_MIIADDR
4532 hidnplayr 1497
        call    [ebx + device.write_bcr]
3545 hidnplayr 1498
 
1499
        pop     eax
1500
        mov     ecx, BCR_MIIDATA
4532 hidnplayr 1501
        call    [ebx + device.write_bcr]
3545 hidnplayr 1502
 
1503
        ret
1504
 
1505
 
1506
align 4
1507
check_media:
1508
 
1509
        DEBUGF  1, "check_media\n"
1510
 
4532 hidnplayr 1511
        test    [ebx + device.mii], 1
3855 hidnplayr 1512
        jnz     mii_link_ok
3545 hidnplayr 1513
 
1514
        mov     ecx, BCR_LED0
4532 hidnplayr 1515
        call    [ebx + device.read_bcr]
3545 hidnplayr 1516
        cmp     eax, 0xc0
1517
 
5004 hidnplayr 1518
        DEBUGF  2, "link status=0x%x\n", ax
3545 hidnplayr 1519
 
1520
        ret
1521
 
1522
 
1523
 
1524
; End of code
1525
 
1526
 
4532 hidnplayr 1527
data fixups
1528
end data
3545 hidnplayr 1529
 
4532 hidnplayr 1530
include '../peimport.inc'
1531
 
4629 hidnplayr 1532
my_service    db 'PCNET32',0            ; max 16 chars include zero
4532 hidnplayr 1533
 
3545 hidnplayr 1534
device_l2     db "PCnet/PCI 79C970",0
1535
device_l4     db "PCnet/PCI II 79C970A",0
1536
device_l5     db "PCnet/FAST 79C971",0
1537
device_l6     db "PCnet/FAST+ 79C972",0
1538
device_l7     db "PCnet/FAST III 79C973",0
1539
device_l8     db "PCnet/Home 79C978",0
1540
device_l9     db "PCnet/FAST III 79C975",0
1541
 
1542
options_mapping:
1543
dd PORT_ASEL                            ; 0 Auto-select
1544
dd PORT_AUI                             ; 1 BNC/AUI
1545
dd PORT_AUI                             ; 2 AUI/BNC
1546
dd PORT_ASEL                            ; 3 not supported
1547
dd PORT_10BT or PORT_FD                 ; 4 10baseT-FD
1548
dd PORT_ASEL                            ; 5 not supported
1549
dd PORT_ASEL                            ; 6 not supported
1550
dd PORT_ASEL                            ; 7 not supported
1551
dd PORT_ASEL                            ; 8 not supported
1552
dd PORT_MII                             ; 9 MII 10baseT
1553
dd PORT_MII or PORT_FD                  ; 10 MII 10baseT-FD
1554
dd PORT_MII                             ; 11 MII (autosel)
1555
dd PORT_10BT                            ; 12 10BaseT
1556
dd PORT_MII or PORT_100                 ; 13 MII 100BaseTx
1557
dd PORT_MII or PORT_100 or PORT_FD      ; 14 MII 100BaseTx-FD
1558
dd PORT_ASEL                            ; 15 not supported
1559
 
1560
include_debug_strings                                   ; All data wich FDO uses will be included here
1561
 
1562
 
4532 hidnplayr 1563
align 4
1564
devices     dd 0
3545 hidnplayr 1565
device_list rd MAX_DEVICES                              ; This list contains all pointers to device structures the driver is handling