Subversion Repositories Kolibri OS

Rev

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

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