Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
3545 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
3
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
6
;;  3Com network driver for KolibriOS                           ;;
7
;;                                                              ;;
8
;;  Ported to KolibriOS net-branch by hidnplayr (28/05/10)      ;;
9
;;                                                              ;;
10
;;  Thanks to: scrap metal recyclers, whom provide me with      ;;
11
;;                         loads of hardware                    ;;
12
;;             diamond: who makes me understand KolibriOS       ;;
13
;;                                                              ;;
14
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
15
 
16
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
17
;;                                                                         ;;
18
;;  3C59X.INC                                                              ;;
19
;;                                                                         ;;
20
;;  Ethernet driver for Menuet OS                                          ;;
21
;;                                                                         ;;
22
;;  Driver for 3Com fast etherlink 3c59x and                               ;;
23
;;         etherlink XL 3c900 and 3c905 cards                              ;;
24
;;  References:                                                            ;;
25
;;    www.3Com.com - data sheets                                           ;;
26
;;    DP83840A.pdf - ethernet physical layer                               ;;
27
;;    3c59x.c - linux driver                                               ;;
28
;;    ethernet driver template by Mike Hibbett                             ;;
29
;;                                                                         ;;
30
;;  Credits                                                                ;;
31
;;   Mike Hibbett,                                                         ;;
32
;;         who kindly supplied me with a 3Com905C-TX-M card                ;;
33
;;                                                                         ;;
34
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
35
;;
36
;; Copyright (c) 2004, Endre Kozma 
37
;; All rights reserved.
38
;;
39
;; Redistribution  and  use  in  source  and  binary  forms, with or without
40
;; modification, are permitted provided  that  the following  conditions are
41
;; met:
42
;;
43
;; 1. Redistributions of source code must retain the above  copyright notice,
44
;;    this list of conditions and the following disclaimer.
45
;;
46
;; 2. Redistributions  in  binary form  must  reproduce  the above copyright
47
;;    notice, this  list of conditions  and the  following disclaimer in the
48
;;    documentation and/or other  materials  provided with  the distribution.
49
;;
50
;; 3. The name of the author may not be used to  endorse or promote products
51
;;    derived from this software without  specific prior  written permission.
52
;;
53
;; THIS SOFTWARE IS  PROVIDED  BY  THE  AUTHOR  ``AS IS'' AND ANY EXPRESS OR
54
;; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
55
;; OF  MERCHANTABILITY AND FITNESS  FOR A PARTICULAR  PURPOSE ARE DISCLAIMED.
56
;; IN  NO  EVENT  SHALL  THE  AUTHOR  BE  LIABLE  FOR  ANY  DIRECT, INDIRECT,
57
;; INCIDENTAL, SPECIAL, EXEMPLARY, OR  CONSEQUENTIAL DAMAGES (INCLUDING, BUT
58
;; NOT LIMITED TO, PROCUREMENT OF  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
59
;; DATA, OR  PROFITS; OR  BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON ANY
60
;; THEORY OF  LIABILITY, WHETHER IN  CONTRACT,  STRICT  LIABILITY,  OR  TORT
61
;; (INCLUDING NEGLIGENCE OR OTHERWISE)  ARISING IN ANY WAY OUT OF THE USE OF
62
;; THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
63
;;
64
;;  History
65
;;  =======
66
;;  $Log: 3C59X.INC,v $
67
;;  Revision 1.3  2004/07/11 12:21:12  kozma
68
;;  Support of vortex chips (3c59x) added.
69
;;  Support of 3c920 and 3c982 added.
70
;;  Corrections.
71
;;
72
;;  Revision 1.2  2004/06/12 19:40:20  kozma
73
;;  Function e3c59x_set_available_media added in order to set
74
;;  the default media in case auto detection finds no valid link.
75
;;  Incorrect mii check removed (3c900 Cyclone works now).
76
;;  Cleanups.
77
;;
78
;;  Revision 1.1  2004/06/12 18:27:15  kozma
79
;;  Initial revision
80
;;
81
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
82
 
83
format MS COFF
84
 
85
        API_VERSION             = 0x01000100
86
        DRIVER_VERSION          = 5
87
 
88
        MAX_DEVICES             = 16
89
        FORCE_FD                = 0     ; forcing full duplex mode makes sense at some cards and link types
90
        PROMISCIOUS             = 0     ; enables promiscous mode
91
 
92
        DEBUG                   = 1
93
        __DEBUG__               = 1
94
        __DEBUG_LEVEL__         = 2
95
 
96
include '../proc32.inc'
97
include '../imports.inc'
98
include '../fdo.inc'
99
include '../netdrv.inc'
100
 
101
public START
102
public service_proc
103
public version
104
 
105
struc DPD {     ; Download Packet Descriptor
106
 
107
        .next_ptr               dd ?
108
        .frame_start_hdr        dd ?
109
        .frag_addr              dd ?    ; for packet data
110
        .frag_len               dd ?    ; for packet data
111
        .realaddr               dd ?
112
        .size                   = 32
113
}
114
 
115
virtual at 0
116
  dpd DPD
117
end virtual
118
 
119
 
120
struc UPD {     ; Upload Packet Descriptor
121
 
122
        .next_ptr               dd ?
123
        .pkt_status             dd ?
124
        .frag_addr              dd ?
125
        .frag_len               dd ?    ; for packet data
126
        .realaddr               dd ?
127
        .size           = 32
128
 
129
}
130
 
131
virtual at 0
132
  upd UPD
133
end virtual
134
 
135
; Registers
136
        REG_POWER_MGMT_CTRL     = 0x7c
137
        REG_UP_LIST_PTR         = 0x38
138
        REG_UP_PKT_STATUS       = 0x30
139
        REG_TX_FREE_THRESH      = 0x2f
140
        REG_DN_LIST_PTR         = 0x24
141
        REG_DMA_CTRL            = 0x20
142
        REG_TX_STATUS           = 0x1b
143
        REG_RX_STATUS           = 0x18
144
        REG_TX_DATA             = 0x10
145
 
146
; Common window registers
147
        REG_INT_STATUS          = 0xe
148
        REG_COMMAND             = 0xe
149
 
150
; Register window 7
151
        REG_MASTER_STATUS       = 0xc
152
        REG_POWER_MGMT_EVENT    = 0xc
153
        REG_MASTER_LEN          = 0x6
154
        REG_VLAN_ETHER_TYPE     = 0x4
155
        REG_VLAN_MASK           = 0x0
156
        REG_MASTER_ADDRESS      = 0x0
157
 
158
; Register window 6
159
        REG_BYTES_XMITTED_OK    = 0xc
160
        REG_BYTES_RCVD_OK       = 0xa
161
        REG_UPPER_FRAMES_OK     = 0x9
162
        REG_FRAMES_DEFERRED     = 0x8
163
        REG_FRAMES_RCVD_OK      = 0x7
164
        REG_FRAMES_XMITTED_OK   = 0x6
165
        REG_RX_OVERRUNS         = 0x5
166
        REG_LATE_COLLISIONS     = 0x4
167
        REG_SINGLE_COLLISIONS   = 0x3
168
        REG_MULTIPLE_COLLISIONS = 0x2
169
        REG_SQE_ERRORS          = 0x1
170
        REG_CARRIER_LOST        = 0x0
171
 
172
; Register window 5
173
        REG_INDICATION_ENABLE   = 0xc
174
        REG_INTERRUPT_ENABLE    = 0xa
175
        REG_TX_RECLAIM_THRESH   = 0x9
176
        REG_RX_FILTER           = 0x8
177
        REG_RX_EARLY_THRESH     = 0x6
178
        REG_TX_START_THRESH     = 0x0
179
 
180
; Register window 4
181
        REG_UPPER_BYTES_OK      = 0xe
182
        REG_BAD_SSD             = 0xc
183
        REG_MEDIA_STATUS        = 0xa
184
        REG_PHYSICAL_MGMT       = 0x8
185
        REG_NETWORK_DIAGNOSTIC  = 0x6
186
        REG_FIFO_DIAGNOSTIC     = 0x4
187
        REG_VCO_DIAGNOSTIC      = 0x2   ; may not supported
188
 
189
; Bits in register window 4
190
        BIT_AUTOSELECT          = 24
191
 
192
; Register window 3
193
        REG_TX_FREE             = 0xc
194
        REG_RX_FREE             = 0xa
195
        REG_MEDIA_OPTIONS       = 0x8
196
        REG_MAC_CONTROL         = 0x6
197
        REG_MAX_PKT_SIZE        = 0x4
198
        REG_INTERNAL_CONFIG     = 0x0
199
 
200
; Register window 2
201
        REG_RESET_OPTIONS       = 0xc
202
        REG_STATION_MASK_HI     = 0xa
203
        REG_STATION_MASK_MID    = 0x8
204
        REG_STATION_MASK_LO     = 0x6
205
        REG_STATION_ADDRESS_HI  = 0x4
206
        REG_STATION_ADDRESS_MID = 0x2
207
        REG_STATION_ADDRESS_LO  = 0x0
208
 
209
; Register window 1
210
        REG_TRIGGER_BITS        = 0xc
211
        REG_SOS_BITS            = 0xa
212
        REG_WAKE_ON_TIMER       = 0x8
213
        REG_SMB_RXBYTES         = 0x7
214
        REG_SMB_DIAG            = 0x5
215
        REG_SMB_ARB             = 0x4
216
        REG_SMB_STATUS          = 0x2
217
        REG_SMB_ADDRESS         = 0x1
218
        REG_SMB_FIFO_DATA       = 0x0
219
 
220
; Register window 0
221
        REG_EEPROM_DATA         = 0xc
222
        REG_EEPROM_COMMAND      = 0xa
223
        REG_BIOS_ROM_DATA       = 0x8
224
        REG_BIOS_ROM_ADDR       = 0x4
225
 
226
; Physical management bits
227
        BIT_MGMT_DIR            = 2     ; drive with the data written in mgmtData
228
        BIT_MGMT_DATA           = 1     ; MII management data bit
229
        BIT_MGMT_CLK            = 0     ; MII management clock
230
 
231
; MII commands
232
        MII_CMD_MASK            = (1111b shl 10)
233
        MII_CMD_READ            = (0110b shl 10)
234
        MII_CMD_WRITE           = (0101b shl 10)
235
 
236
; MII registers
237
        REG_MII_BMCR            = 0     ; basic mode control register
238
        REG_MII_BMSR            = 1     ; basic mode status register
239
        REG_MII_ANAR            = 4     ; auto negotiation advertisement register
240
        REG_MII_ANLPAR          = 5     ; auto negotiation link partner ability register
241
        REG_MII_ANER            = 6     ; auto negotiation expansion register
242
 
243
; MII bits
244
        BIT_MII_AUTONEG_COMPLETE        = 5     ; auto-negotiation complete
245
        BIT_MII_PREAMBLE_SUPPRESSION    = 6
246
 
247
; eeprom bits and commands
248
        EEPROM_CMD_READ         = 0x80
249
        EEPROM_BIT_BUSY         = 15
250
 
251
; eeprom registers
252
        EEPROM_REG_OEM_NODE_ADDR= 0xa
253
        EEPROM_REG_CAPABILITIES = 0x10
254
 
255
; Commands for command register
256
        SELECT_REGISTER_WINDOW  = (1 shl 11)
257
 
258
        IS_VORTEX               = 0x1
259
        IS_BOOMERANG            = 0x2
260
        IS_CYCLONE              = 0x4
261
        IS_TORNADO              = 0x8
262
        EEPROM_8BIT             = 0x10
263
        HAS_PWR_CTRL            = 0x20
264
        HAS_MII                 = 0x40
265
        HAS_NWAY                = 0x80
266
        HAS_CB_FNS              = 0x100
267
        INVERT_MII_PWR          = 0x200
268
        INVERT_LED_PWR          = 0x400
269
        MAX_COLLISION_RESET     = 0x800
270
        EEPROM_OFFSET           = 0x1000
271
        HAS_HWCKSM              = 0x2000
272
        EXTRA_PREAMBLE          = 0x4000
273
 
274
; Status
275
        IntLatch                = 0x0001
276
        HostError               = 0x0002
277
        TxComplete              = 0x0004
278
        TxAvailable             = 0x0008
279
        RxComplete              = 0x0010
280
        RxEarly                 = 0x0020
281
        IntReq                  = 0x0040
282
        StatsFull               = 0x0080
283
        DMADone                 = 0x0100
284
        DownComplete            = 0x0200
285
        UpComplete              = 0x0400
286
        DMAInProgress           = 0x0800        ; 1 shl 11  (DMA controller is still busy)
287
        CmdInProgress           = 0x1000        ; 1 shl 12  (EL3_CMD is still busy)
288
 
289
        S_5_INTS                = HostError + RxEarly + UpComplete + DownComplete ;+ TxComplete + RxComplete  + TxAvailable
290
 
291
; Commands
292
        TotalReset              = 0 shl 11
293
        SelectWindow            = 1 shl 11
294
        StartCoax               = 2 shl 11
295
        RxDisable               = 3 shl 11
296
        RxEnable                = 4 shl 11
297
        RxReset                 = 5 shl 11
298
        UpStall                 = 6 shl 11
299
        UpUnstall               = (6 shl 11)+1
300
        DownStall               = (6 shl 11)+2
301
        DownUnstall             = (6 shl 11)+3
302
        RxDiscard               = 8 shl 11
303
        TxEnable                = 9 shl 11
304
        TxDisable               = 10 shl 11
305
        TxReset                 = 11 shl 11
306
        FakeIntr                = 12 shl 11
307
        AckIntr                 = 13 shl 11
308
        SetIntrEnb              = 14 shl 11
309
        SetStatusEnb            = 15 shl 11
310
        SetRxFilter             = 16 shl 11
311
        SetRxThreshold          = 17 shl 11
312
        SetTxThreshold          = 18 shl 11
313
        SetTxStart              = 19 shl 11
314
        StartDMAUp              = 20 shl 11
315
        StartDMADown            = (20 shl 11)+1
316
        StatsEnable             = 21 shl 11
317
        StatsDisable            = 22 shl 11
318
        StopCoax                = 23 shl 11
319
        SetFilterBit            = 25 shl 11
320
 
321
; Rx mode bits
322
        RxStation               = 1
323
        RxMulticast             = 2
324
        RxBroadcast             = 4
325
        RxProm                  = 8
326
 
327
; RX/TX buffers sizes
328
        MAX_ETH_PKT_SIZE        = 1536          ; max packet size
329
        NUM_RX_DESC             = 4             ; a power of 2 number
330
        NUM_TX_DESC             = 4             ; a power of 2 number
331
        MAX_ETH_FRAME_SIZE      = 1520          ; size of ethernet frame + bytes alignment
332
 
333
virtual at ebx
334
 
335
        device:
336
 
337
        ETH_DEVICE
338
 
339
        .dpd_buffer       rd (dpd.size*NUM_TX_DESC)/4
340
        .upd_buffer       rd (upd.size*NUM_RX_DESC)/4
341
        .curr_upd         dd ?
342
        .prev_dpd         dd ?
343
 
344
        .io_addr          dd ?
345
        .pci_bus          dd ?
346
        .pci_dev          dd ?
347
        .irq_line         db ?
348
                rb 3    ; alignment
349
 
350
        .prev_tx_frame            dd ?
351
        .ver_id                   db ?
352
        .full_bus_master          db ?
353
        .has_hwcksm               db ?
354
        .preamble                 db ?
355
        .dn_list_ptr_cleared      db ?
356
 
357
        .size = $ - device
358
 
359
end virtual
360
 
361
section '.flat' code readable align 16
362
 
363
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
364
;;                        ;;
365
;; proc START             ;;
366
;;                        ;;
367
;; (standard driver proc) ;;
368
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
369
 
370
align 4
371
proc START stdcall, state:dword
372
 
373
        cmp [state], 1
374
        jne .exit
375
 
376
  .entry:
377
 
3880 hidnplayr 378
        DEBUGF 1,"Loading driver\n"
3545 hidnplayr 379
        stdcall RegService, my_service, service_proc
380
        ret
381
 
382
  .fail:
383
  .exit:
384
        xor eax, eax
385
        ret
386
 
387
endp
388
 
389
 
390
 
391
 
392
 
393
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
394
;;                        ;;
395
;; proc SERVICE_PROC      ;;
396
;;                        ;;
397
;; (standard driver proc) ;;
398
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
399
 
400
align 4
401
proc service_proc stdcall, ioctl:dword
402
 
403
        mov     edx, [ioctl]
404
        mov     eax, [IOCTL.io_code]
405
 
406
;------------------------------------------------------
407
 
408
        cmp     eax, 0 ;SRV_GETVERSION
409
        jne     @F
410
 
411
        cmp     [IOCTL.out_size], 4
412
        jb      .fail
413
        mov     eax, [IOCTL.output]
414
        mov     [eax], dword API_VERSION
415
 
416
        xor     eax, eax
417
        ret
418
 
419
;------------------------------------------------------
420
  @@:
421
        cmp     eax, 1 ;SRV_HOOK
422
        jne     .fail
423
 
424
        cmp     [IOCTL.inp_size], 3               ; Data input must be at least 3 bytes
425
        jb      .fail
426
 
427
        mov     eax, [IOCTL.input]
428
        cmp     byte [eax], 1                           ; 1 means device number and bus number (pci) are given
429
        jne     .fail                                   ; other types of this hardware dont exist
430
 
431
; check if the device is already listed
432
 
433
        mov     ecx, [VORTEX_DEVICES]
434
        test    ecx, ecx
435
        jz      .maybeboomerang
436
 
437
        mov     esi, VORTEX_LIST
438
        mov     eax, [IOCTL.input]                      ; get the pci bus and device numbers
439
        mov     ax , [eax+1]                            ;
440
  .nextdevice:
441
        mov     ebx, [esi]
442
        cmp     al, byte[device.pci_bus]
443
        jne     @f
444
        cmp     ah, byte[device.pci_dev]
445
        je      .find_devicenum                         ; Device is already loaded, let's find it's device number
446
       @@:
447
        add     esi, 4
448
        loop    .nextdevice
449
 
450
 
451
  .maybeboomerang:
452
        mov     ecx, [BOOMERANG_DEVICES]
453
        test    ecx, ecx
454
        jz      .firstdevice
455
 
456
        mov     esi, BOOMERANG_LIST
457
        mov     eax, [IOCTL.input]                      ; get the pci bus and device numbers
458
        mov     ax , [eax+1]                            ;
459
  .nextdevice2:
460
        mov     ebx, [esi]
461
        cmp     al, byte[device.pci_bus]
462
        jne     @f
463
        cmp     ah, byte[device.pci_dev]
464
        je      .find_devicenum                         ; Device is already loaded, let's find it's device number
465
       @@:
466
        add     esi, 4
467
        loop    .nextdevice2
468
 
469
 
470
; This device doesnt have its own eth_device structure yet, lets create one
471
  .firstdevice:
472
        mov     ecx, [BOOMERANG_DEVICES]
473
        add     ecx, [VORTEX_DEVICES]
474
        cmp     ecx, MAX_DEVICES                        ; First check if the driver can handle one more card
475
        jae     .fail
476
 
477
        allocate_and_clear ebx, device.size, .fail      ; Allocate the buffer for device structure
478
 
479
; Fill in the direct call addresses into the struct
480
 
481
        mov     [device.reset], reset
482
        mov     [device.transmit], null_op
483
        mov     [device.unload], null_op
484
        mov     [device.name], my_service
485
 
486
; save the pci bus and device numbers
487
 
488
        mov     eax, [IOCTL.input]
489
        movzx   ecx, byte[eax+1]
490
        mov     [device.pci_bus], ecx
491
        movzx   ecx, byte[eax+2]
492
        mov     [device.pci_dev], ecx
493
 
494
; Now, it's time to find the base io addres of the PCI device
495
        PCI_find_io
496
 
497
; We've found the io address, find IRQ now
498
        PCI_find_irq
499
 
500
        DEBUGF  1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
501
        [device.pci_dev]:1,[device.pci_bus]:1,[device.irq_line]:1,[device.io_addr]:4
502
 
503
; Ok, the eth_device structure is ready, let's probe the device
504
        call    probe                                                   ; this function will output in eax
505
        test    eax, eax
506
        jnz     .err                                                    ; If an error occured, exit
507
 
508
 
509
        movzx   ecx, [device.ver_id]
510
        test    word [hw_versions+2+ecx*4], IS_VORTEX
511
        jz      .not_vortex
512
 
513
        mov     eax, [VORTEX_DEVICES]                                   ; Add the device structure to our device list
514
        mov     [VORTEX_LIST+4*eax], ebx                                ; (IRQ handler uses this list to find device)
515
        inc     [VORTEX_DEVICES]                                        ;
516
 
517
  .register:
518
        mov     [device.type], NET_TYPE_ETH
519
        call    NetRegDev
520
 
521
        cmp     eax, -1
522
        je      .destroy
523
 
524
        call    start_device
525
        ret
526
 
527
  .not_vortex:
528
        mov     eax, [BOOMERANG_DEVICES]                                          ; Add the device structure to our device list
529
        mov     [BOOMERANG_LIST+4*eax], ebx                                ; (IRQ handler uses this list to find device)
530
        inc     [BOOMERANG_DEVICES]
531
 
532
        jmp     .register
533
 
534
; If the device was already loaded, find the device number and return it in eax
535
 
536
  .find_devicenum:
537
        DEBUGF  1,"Trying to find device number of already registered device\n"
538
        call    NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
539
                                                                        ; into a device number in edi
540
        mov     eax, edi                                                ; Application wants it in eax instead
541
        DEBUGF  1,"Kernel says: %u\n", eax
542
        ret
543
 
544
; If an error occured, remove all allocated data and exit (returning -1 in eax)
545
 
546
  .destroy:
547
        ; todo: reset device into virgin state
548
 
549
  .err:
550
        stdcall KernelFree, ebx
551
 
552
 
553
  .fail:
554
        or      eax, -1
555
        ret
556
 
557
;------------------------------------------------------
558
endp
559
 
560
 
561
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
562
;;                                                                        ;;
563
;;        Actual Hardware dependent code starts here                      ;;
564
;;                                                                        ;;
565
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
566
 
567
 
568
 
569
 
570
 
571
;***************************************************************************
572
;   Function
573
;      probe
574
;   Description
575
;      Searches for an ethernet card, enables it and clears the rx buffer
576
;   Destroyed registers
577
;      eax, ebx, ecx, edx, edi, esi
578
;
579
;***************************************************************************
580
 
581
align 4
582
probe:
583
 
584
        DEBUGF  1,"Probing 3com card\n"
585
 
586
        PCI_make_bus_master
587
 
588
; wake up the card
589
        call    wake_up
590
 
591
        stdcall PciRead32, [device.pci_bus], [device.pci_dev], 0                                ; get device/vendor id
592
 
593
        DEBUGF  1,"Vendor id: 0x%x\n", ax
594
 
595
        cmp     ax, 0x10B7
596
        jne     .notfound
597
        shr     eax, 16
598
 
599
        DEBUGF  1,"Vendor ok!, device id: 0x%x\n", ax
600
 
601
; get chip version
602
        mov     ecx, HW_VERSIONS_SIZE/4-1
603
  .loop:
604
        cmp     ax, [hw_versions+ecx*4]
605
        jz      .found
606
        loop    .loop
607
  .notfound:
3880 hidnplayr 608
        DEBUGF  2,"Device id not found in list!\n"
3545 hidnplayr 609
        or      eax, -1
610
        ret
611
  .found:
612
        mov     esi, [hw_str+ecx*4]
613
        DEBUGF  1,"Hardware type: %s\n", esi
614
        mov     [device.name], esi
615
 
616
        mov     [device.ver_id], cl
617
        test    word [hw_versions+2+ecx*4], HAS_HWCKSM
618
        setnz   [device.has_hwcksm]
619
; set pci latency for vortex cards
620
        test    word [hw_versions+2+ecx*4], IS_VORTEX
621
        jz      .not_vortex
622
 
623
        mov     eax, 11111000b ; 248 = max latency
624
        stdcall PciWrite32, [device.pci_bus], [device.pci_dev], PCI_REG_LATENCY, eax
625
 
626
  .not_vortex:
627
; set RX/TX functions
628
        mov     ax, EEPROM_REG_CAPABILITIES
629
        call    read_eeprom
630
        test    al, 100000b ; full bus master?
631
        setnz   [device.full_bus_master]
632
        jnz     .boomerang_func
633
        mov     [device.transmit], vortex_transmit
3880 hidnplayr 634
        DEBUGF  2,"Device is a vortex type\n"
635
        DEBUGF  2,"I'm sorry but vortex code hasnt been tested yet\n"
636
        DEBUGF  2,"Please contact me on hidnplayr@kolibrios.org\n"
637
        DEBUGF  2,"If you can help me finish it!\n"
3545 hidnplayr 638
        or      eax, -1
639
        ret
640
        jmp     @f
641
  .boomerang_func: ; full bus master, so use boomerang functions
642
        mov     [device.transmit], boomerang_transmit
643
        DEBUGF  1,"Device is a boomerang type\n"
644
       @@:
645
        call    read_mac_eeprom
646
 
647
        test    byte [device.full_bus_master], 0xff
648
        jz      .set_preamble
649
; switch to register window 2
650
        set_io  0
651
        set_io  REG_COMMAND
652
        mov     ax, SELECT_REGISTER_WINDOW+2
653
        out     dx, ax
654
; activate xcvr by setting some magic bits
655
        set_io  REG_RESET_OPTIONS
656
        in      ax, dx
657
        and     ax, not 0x4010
658
        movzx   ecx, [device.ver_id]
659
        test    word [ecx*4+hw_versions+2], INVERT_LED_PWR
660
        jz      @f
661
        or      al, 0x10
662
       @@:
663
        test    word [ecx*4+hw_versions+2], INVERT_MII_PWR
664
        jz      @f
665
        or      ah, 0x40
666
       @@:
667
        out     dx, ax
668
  .set_preamble:
669
; use preamble as default
670
        mov     byte [device.preamble], 1 ; enable preamble
671
 
672
        call    global_reset
673
 
674
;--------------------------
675
; RESET
676
 
677
align 4
678
reset:
679
 
680
        movzx   eax, [device.irq_line]
681
        DEBUGF  1,"Attaching int handler to irq %x\n",eax:1
682
 
683
        movzx   ecx, [device.ver_id]
684
        test    word [hw_versions+2+ecx*4], IS_VORTEX
685
        jz      .not_vortex
686
 
687
        mov     esi, int_vortex
688
        jmp     .reg_int
689
 
690
.not_vortex:
691
        mov     esi, int_boomerang
692
 
693
.reg_int:
694
        stdcall AttachIntHandler, eax, esi, dword 0
695
        test    eax, eax
696
        jnz     @f
3880 hidnplayr 697
        DEBUGF  2,"Could not attach int handler!\n"
3545 hidnplayr 698
;        or      eax, -1
699
;        ret
700
  @@:
701
 
702
        set_io  0
703
        set_io  REG_COMMAND
704
        mov     ax, SELECT_REGISTER_WINDOW + 0
705
        out     dx, ax
706
 
707
        mov     ax, StopCoax
708
        out     dx, ax                        ; stop transceiver
709
 
710
        mov     ax, SELECT_REGISTER_WINDOW + 4
711
        out     dx, ax                        ; disable UTP
712
 
713
        set_io  REG_MEDIA_STATUS
714
        mov     ax, 0x0
715
 
716
        set_io  REG_COMMAND
717
        mov     ax, SELECT_REGISTER_WINDOW + 0
718
        out     dx, ax
719
 
720
        set_io  REG_FIFO_DIAGNOSTIC
721
        mov     ax, 0
722
        out     dx, ax                        ; disable card
723
 
724
        mov     ax, 1
725
        out     dx, ax                        ; enable card
726
 
727
        call    write_mac
728
 
729
 
730
;<<<<<<<<<<<<<<
731
 
732
        set_io  REG_COMMAND
733
        mov     ax, SELECT_REGISTER_WINDOW + 1
734
        out     dx, ax
735
 
736
        mov     ecx, 32
737
        set_io  0x0b
738
  .loop:
739
        in      al, dx
740
        loop    .loop
741
 
742
; Get rid of stray ints
743
        set_io  REG_COMMAND
744
        mov     ax, AckIntr + 0xff
745
        out     dx, ax
746
 
747
        mov     ax, SetStatusEnb + S_5_INTS
748
        out     dx, ax
749
 
750
        mov     ax, SetIntrEnb + S_5_INTS
751
        out     dx, ax
752
 
753
        call    set_rx_mode
754
        call    set_active_port
755
 
756
;>>>>>>>>>>
757
 
758
        call    create_rx_ring
759
        call    rx_reset
760
        call    tx_reset
761
 
762
;>>>>>>>>>>>>>>>>>>
763
 
764
        xor     eax, eax
765
; clear packet/byte counters
766
 
767
        lea     edi, [device.bytes_tx]
768
        mov     ecx, 6
769
        rep     stosd
770
 
771
; Set the mtu, kernel will be able to send now
772
        mov     [device.mtu], 1514
773
 
774
        ret
775
 
776
 
777
 
778
 
779
 
780
align 4
781
start_device:
782
        DEBUGF  1,"Starting the device\n"
783
 
784
        set_io  0
785
        set_io  REG_COMMAND
786
        mov     ax, SetTxThreshold + 60 ;2047 ; recommended by the manual :)
787
        out     dx, ax
788
 
789
        call    check_tx_status
790
 
791
        set_io  0
792
        set_io  REG_COMMAND
793
; switch to register window 4
794
        mov     ax, SELECT_REGISTER_WINDOW+4
795
        out     dx, ax
796
 
797
; wait for linkDetect
798
        set_io  REG_MEDIA_STATUS
799
        mov     ecx, 20 ; wait for max 2s
800
  .link_detect_loop:
801
        mov     esi, 100
802
        call    Sleep ; 100 ms
803
        in      ax, dx
804
        test    ah, 1000b ; linkDetect
805
        jnz     @f
806
        loop    .link_detect_loop
3880 hidnplayr 807
        DEBUGF  2,"Link detect timed-out!\n"
3545 hidnplayr 808
       @@:
809
 
810
; print link type
811
        xor     eax, eax
812
        bsr     ax, word [device.state]
813
        jz      @f
814
        sub     ax, 4
815
       @@:
816
 
817
        mov     esi, [link_str+eax*4]
818
        DEBUGF  1,"Established Link type: %s\n", esi
819
 
820
; enable interrupts
821
 
822
        set_io  REG_COMMAND
823
        mov     ax, SELECT_REGISTER_WINDOW + 1
824
        out     dx, ax
825
 
826
        mov     ax, AckIntr + 0xff
827
        out     dx, ax
828
 
829
        mov     ax, SetStatusEnb + S_5_INTS
830
        out     dx, ax
831
 
832
        mov     ax, SetIntrEnb + S_5_INTS
833
        out     dx, ax
834
 
835
; Start RX/TX
836
 
837
        set_io  0
838
        set_io  REG_COMMAND
839
        mov     ax, RxEnable
840
        out     dx, ax
841
 
842
        mov     ax, TxEnable
843
        out     dx, ax
844
 
845
        set_io  REG_COMMAND
846
        mov     ax, SetRxThreshold + 208
847
        out     dx, ax
848
 
849
        mov     ax, SetTxThreshold + 60 ;16 ; recommended by the manual :)
850
        out     dx, ax
851
 
852
        mov     ax, SELECT_REGISTER_WINDOW + 1
853
        out     dx, ax
854
 
855
        ret
856
 
857
 
858
 
859
 
860
 
861
 
862
 
863
align 4
864
set_rx_mode:
865
 
866
        DEBUGF  1,"Setting RX mode\n"
867
 
868
        set_io  0
869
        set_io  REG_COMMAND
870
 
871
if      defined PROMISCIOUS
872
        mov     ax, SetRxFilter + RxStation + RxMulticast + RxBroadcast + RxProm
873
else if  defined ALLMULTI
874
        mov     ax, SetRxFilter + RxStation + RxMulticast + RxBroadcast
875
else
876
        mov     ax, SetRxFilter + RxStation + RxBroadcast
877
end if
878
        out     dx, ax
879
 
880
        ret
881
 
882
 
883
 
884
 
885
 
886
;***************************************************************************
887
;   Function
888
;      global_reset
889
;   Description
890
;      resets the device
891
;   Parameters:
3880 hidnplayr 892
;
3545 hidnplayr 893
;   Return value:
894
;   Destroyed registers
895
;      ax, ecx, edx, esi
896
;
897
;***************************************************************************1
898
 
899
align 4
900
global_reset:
901
 
902
        DEBUGF 1,"Global reset..\n"
903
 
904
; GlobalReset
905
        set_io  0
906
        set_io  REG_COMMAND
907
        xor     eax, eax
908
;       or      al, 0x14
909
        out     dx, ax
910
; wait for GlobalReset to complete
911
        mov     ecx, 64000
912
  .loop:
913
        in      ax , dx
914
        test    ah , 10000b ; check CmdInProgress
915
        loopz   .loop
916
 
917
        DEBUGF 1,"Waiting for nic to boot..\n"
918
; wait for 2 seconds for NIC to boot
919
        mov     esi, 2000
920
        call    Sleep ; 2 seconds
921
 
922
        DEBUGF 1,"Ok!\n"
923
 
924
        ret
925
 
926
 
927
 
928
;***************************************************************************
929
;   Function
930
;      tx_reset
931
;   Description
932
;      resets and enables transmitter engine
933
;
934
;***************************************************************************
935
 
936
align 4
937
tx_reset:
938
        DEBUGF 1,"tx reset\n"
939
 
940
; TxReset
941
        set_io  0
942
        set_io  REG_COMMAND
943
        mov     ax, TxReset
944
        out     dx, ax
945
; Wait for TxReset to complete
946
        mov     ecx, 200000
947
.tx_reset_loop:
948
        in      ax, dx
949
        test    ah, 10000b ; check CmdInProgress
950
        jz      .tx_set_prev
951
        dec     ecx
952
        jnz     .tx_reset_loop
953
.tx_set_prev:
954
; init last_dpd
955
        lea     eax, [device.dpd_buffer + (NUM_TX_DESC-1)*dpd.size]
956
        mov     [device.prev_dpd], eax
957
 
958
.tx_enable:
959
        ret
960
 
961
 
962
 
963
;***************************************************************************
964
;   Function
965
;      rx_reset
966
;   Description
967
;      resets and enables receiver engine
968
;
969
;***************************************************************************
970
 
971
align 4
972
rx_reset:
973
 
974
        DEBUGF 1,"rx reset\n"
975
 
976
        set_io  0
977
        set_io  REG_COMMAND
978
        mov     ax, RxReset or 0x4
979
        out     dx, ax
980
 
981
; wait for RxReset to complete
982
        mov     ecx, 200000
983
  .loop:
984
        in      ax, dx
985
        test    ah, 10000b ; check CmdInProgress
986
        jz      .done
987
        dec     ecx
988
        jnz     .loop
989
  .done:
990
 
991
        lea     eax, [device.upd_buffer]
992
        mov     [device.curr_upd], eax
993
        GetRealAddr
994
        set_io  0
995
        set_io  REG_UP_LIST_PTR
996
        out     dx, eax
997
 
998
  .rx_enable:
999
        ret
1000
 
1001
 
1002
align 4
1003
create_rx_ring:
1004
; create upd ring
1005
        lea     eax, [device.upd_buffer]
1006
        GetRealAddr
1007
        mov     edi, eax                                                ; real addr of first descr
1008
 
1009
        lea     esi, [device.upd_buffer]                                ; ptr to first descr
1010
        lea     edx, [device.upd_buffer + (NUM_RX_DESC-1)*upd.size]     ; ptr to last descr
1011
 
1012
        mov     ecx, NUM_RX_DESC
1013
 
1014
  .upd_loop:
1015
        mov     [edx + upd.next_ptr], edi
1016
 
1017
        push    ecx edx
1018
        stdcall KernelAlloc, MAX_ETH_FRAME_SIZE
1019
        pop     edx ecx
1020
        mov     [esi + upd.realaddr], eax
1021
        call    GetPgAddr
1022
        mov     [esi + upd.frag_addr], eax
1023
        and     [esi + upd.pkt_status], 0
1024
        mov     [esi + upd.frag_len], MAX_ETH_FRAME_SIZE or (1 shl 31)
1025
 
1026
        DEBUGF  1,"UPD: lin=%x phys=%x len=%x next ptr=%x\n", [esi+upd.realaddr]:8, [esi+upd.frag_addr]:8, [esi+upd.frag_len]:8, edi
1027
        DEBUGF  1,"UPD: cur=%x prev=%x\n", esi, edx
1028
 
1029
        mov     edx, esi
1030
        add     esi, upd.size
1031
        add     edi, upd.size
1032
        dec     ecx
1033
        jnz     .upd_loop
1034
 
1035
        ret
1036
 
1037
 
1038
 
1039
;---------------------------------------------------------------------------
1040
;   Function
1041
;      try_link_detect
1042
;   Description
1043
;      try_link_detect checks if link exists
1044
;   Parameters
1045
;      ebx = device structure
1046
;   Return value
1047
;      al - 0 ; no link detected
1048
;      al - 1 ; link detected
1049
;   Destroyed registers
1050
;      eax, ebx, ecx, edx, edi, esi
1051
;
1052
;---------------------------------------------------------------------------
1053
 
1054
align 4
1055
try_link_detect:
1056
 
1057
        DEBUGF  1,"trying to detect link\n"
1058
 
1059
; create self-directed packet
1060
        stdcall KernelAlloc, 20 ; create a buffer for the self-directed packet
1061
        test    eax, eax
1062
        jz      .fail
1063
 
1064
        pushd   20              ; Packet parameters for device.transmit
1065
        push    eax             ;
1066
 
1067
        mov     edi, eax
1068
 
1069
        lea     esi, [device.mac]
1070
        movsw
1071
        movsd
1072
        sub     esi, 6
1073
        movsw
1074
        movsd
1075
        mov     ax , 0x0608
1076
        stosw
1077
 
1078
; download self-directed packet
1079
        call    [device.transmit]
1080
 
1081
; switch to register window 4
1082
        set_io  0
1083
        set_io  REG_COMMAND
1084
        mov     ax, SELECT_REGISTER_WINDOW+4
1085
        out     dx, ax
1086
 
1087
; See if we have received the packet by now..
1088
        cmp     [device.packets_rx], 0
1089
        jnz     .link_detected
1090
 
1091
; switch to register window 4
1092
        set_io  REG_COMMAND
1093
        mov     ax, SELECT_REGISTER_WINDOW+4
1094
        out     dx, ax
1095
 
1096
; read linkbeatdetect
1097
        set_io  REG_MEDIA_STATUS
1098
        in      ax, dx
1099
        test    ah, 1000b ; test linkBeatDetect
1100
        jnz     .link_detected
1101
        xor     al, al
1102
        jmp     .finish
1103
 
1104
  .link_detected:
1105
        DEBUGF  1,"link detected!\n"
1106
        setb    al
1107
 
1108
  .finish:
1109
        test    al, al
1110
        jz      @f
1111
        or      byte [device.state+1], 100b
1112
       @@:
1113
        ret
1114
 
1115
  .fail:
1116
        ret
1117
 
1118
 
1119
 
1120
;***************************************************************************
1121
;   Function
1122
;      try_phy
1123
;   Description
1124
;      try_phy checks the auto-negotiation function
1125
;      in the PHY at PHY index. It can also be extended to
1126
;      include link detection for non-IEEE 802.3u
1127
;      auto-negotiation devices, for instance the BCM5000.              ; TODO: BCM5000
1128
;   Parameters
1129
;       ah - PHY index
1130
;       ebx - device stucture
1131
;   Return value
1132
;      al - 0 link is auto-negotiated
1133
;      al - 1 no link is auto-negotiated
1134
;   Destroyed registers
1135
;       eax, ebx, ecx, edx, esi
1136
;
1137
;***************************************************************************
1138
 
1139
align 4
1140
try_phy:
1141
 
1142
        DEBUGF 1,"PHY=%u\n", ah
1143
        DEBUGF 1,"Detecting if device is auto-negotiation capable\n"
1144
 
1145
        mov     al, REG_MII_BMCR
1146
        push    eax
1147
        call    mdio_read       ; returns with window #4
1148
        or      ah , 0x80       ; software reset
1149
        mov     esi, eax
1150
        mov     eax, dword [esp]
1151
        call    mdio_write      ; returns with window #4
1152
 
1153
; wait for reset to complete
1154
        mov     esi, 2000
1155
        stdcall Sleep      ; 2s
1156
        mov     eax, [esp]
1157
        call    mdio_read       ; returns with window #4
1158
        test    ah , 0x80
1159
        jnz     .fail1
1160
        mov     eax, [esp]
1161
 
1162
; wait for a while after reset
1163
        mov     esi, 20
1164
        stdcall Sleep      ; 20ms
1165
        mov     eax, [esp]
1166
        mov     al , REG_MII_BMSR
1167
        call    mdio_read        ; returns with window #4
1168
        test    al , 1           ; extended capability supported?
1169
        jz      .fail2
1170
 
1171
; auto-neg capable?
1172
        test    al , 1000b
1173
        jz      .fail2           ; not auto-negotiation capable
1174
 
1175
        DEBUGF  1,"Device is auto-negotiation capable\n"
1176
 
1177
; auto-neg complete?
1178
        test    al , 100000b
1179
        jnz     .auto_neg_ok
1180
 
1181
        DEBUGF  1,"Restarting auto-negotiation\n"
1182
 
1183
; restart auto-negotiation
1184
        mov     eax, [esp]
1185
        mov     al , REG_MII_ANAR
1186
        push    eax
1187
        call    mdio_read       ; returns with window #4
1188
        or      ax , 1111b shl 5; advertise only 10base-T and 100base-TX
1189
        mov     esi, eax
1190
        pop     eax
1191
        call    mdio_write      ; returns with window #4
1192
        mov     eax, [esp]
1193
        call    mdio_read       ; returns with window #4
1194
        mov     esi, eax
1195
        or      bh , 10010b     ; restart auto-negotiation
1196
        mov     eax, [esp]
1197
        call    mdio_write      ; returns with window #4
1198
        mov     esi, 4000
1199
        stdcall Sleep  ; 4 seconds
1200
        mov     eax, [esp]
1201
        mov     al , REG_MII_BMSR
1202
        call    mdio_read ; returns with window #4
1203
        test    al , 100000b ; auto-neg complete?
1204
        jnz     .auto_neg_ok
1205
        jmp     .fail3
1206
  .auto_neg_ok:
1207
 
1208
        DEBUGF  1,"Auto-negotiation complete\n"
1209
 
1210
; compare advertisement and link partner ability registers
1211
        mov     eax, [esp]
1212
        mov     al , REG_MII_ANAR
1213
        call    mdio_read       ; returns with window #4
1214
        xchg    eax, [esp]
1215
        mov     al , REG_MII_ANLPAR
1216
        call    mdio_read       ; returns with window #4
1217
        pop     esi
1218
        and     eax, esi
1219
        and     eax, 1111100000b
1220
        push    eax
1221
 
1222
        mov     word[device.state+2], ax
1223
 
1224
; switch to register window 3
1225
        set_io  0
1226
        set_io  REG_COMMAND
1227
        mov     ax , SELECT_REGISTER_WINDOW+3
1228
        out     dx , ax
1229
 
1230
; set full-duplex mode
1231
        set_io  REG_MAC_CONTROL
1232
        in      ax , dx
1233
        and     ax , not 0x120  ; clear full duplex and flow control
1234
        pop     esi
1235
        test    esi, 1010b shl 5; check for full-duplex
1236
        jz      .half_duplex
1237
        or      ax , 0x120      ; set full duplex and flow control
1238
  .half_duplex:
1239
        DEBUGF 1,"Using half-duplex\n"
1240
        out     dx , ax
1241
        mov     al , 1
1242
        ret
1243
 
1244
 
1245
  .fail1:
3880 hidnplayr 1246
        DEBUGF  2,"reset failed!\n"
3545 hidnplayr 1247
        pop     eax
1248
        xor     al, al
1249
        ret
1250
 
1251
  .fail2:
3880 hidnplayr 1252
        DEBUGF  2,"This device is not auto-negotiation capable!\n"
3545 hidnplayr 1253
        pop     eax
1254
        xor     al, al
1255
        ret
1256
 
1257
  .fail3:
3880 hidnplayr 1258
        DEBUGF  2,"auto-negotiation reset failed!\n"
3545 hidnplayr 1259
        pop     eax
1260
        xor     al, al
1261
        ret
1262
 
1263
 
1264
 
1265
;***************************************************************************
1266
;   Function
1267
;      try_mii
1268
;   Description
1269
;      try_MII checks the on-chip auto-negotiation logic
1270
;      or an off-chip MII PHY, depending upon what is set in
1271
;      xcvrSelect by the caller.
1272
;      It exits when it finds the first device with a good link.
1273
;   Parameters
3880 hidnplayr 1274
;
3545 hidnplayr 1275
;   Return value
1276
;      al - 0
1277
;      al - 1
1278
;   Destroyed registers
1279
;      eax, ebx, ecx, edx, esi
1280
;
1281
;***************************************************************************
1282
 
1283
align 4
1284
try_mii:
1285
 
1286
        DEBUGF  1,"trying to find MII PHY\n"
1287
 
1288
; switch to register window 3
1289
        set_io  0
1290
        set_io  REG_COMMAND
1291
        mov     ax, SELECT_REGISTER_WINDOW+3
1292
        out     dx, ax
1293
        set_io  REG_INTERNAL_CONFIG
1294
        in      eax, dx
1295
        and     eax, (1111b shl 20)
1296
        cmp     eax, (1000b shl 20) ; is auto-negotiation set?
1297
        jne     .mii_device
1298
 
1299
        DEBUGF  1,"auto-negotiation is set\n"
1300
; switch to register window 4
1301
        set_io  REG_COMMAND
1302
        mov     ax , SELECT_REGISTER_WINDOW+4
1303
        out     dx , ax
1304
 
1305
; PHY==24 is the on-chip auto-negotiation logic
1306
; it supports only 10base-T and 100base-TX
1307
        mov     ah , 24
1308
        call    try_phy
1309
        test    al , al
1310
        jz      .fail_finish
1311
 
1312
        mov     cl , 24
1313
        jmp     .check_preamble
1314
 
1315
  .mii_device:
1316
        cmp     eax, (0110b shl 20)
1317
        jne     .fail_finish
1318
 
1319
        set_io  0
1320
        set_io  REG_COMMAND
1321
        mov     ax , SELECT_REGISTER_WINDOW+4
1322
        out     dx , ax
1323
 
1324
        set_io  REG_PHYSICAL_MGMT
1325
        in      ax , dx
1326
        and     al , (1 shl BIT_MGMT_DIR) or (1 shl BIT_MGMT_DATA)
1327
        cmp     al , (1 shl BIT_MGMT_DATA)
1328
        je      .search_for_phy
1329
 
1330
        xor     al , al
1331
        ret
1332
 
1333
  .search_for_phy:
1334
; search for PHY
1335
        mov     cx , 31
1336
  .search_phy_loop:
1337
        DEBUGF  1,"Searching the PHY\n"
1338
        cmp     cx , 24
1339
        je      .next_phy
1340
        mov     ah , cl ; ah = phy
1341
        mov     al , REG_MII_BMCR ; al = Basic Mode Status Register
1342
        push    cx
1343
        call    mdio_read
1344
        pop     cx
1345
        test    ax , ax
1346
        jz      .next_phy
1347
        cmp     ax , 0xffff
1348
        je      .next_phy
1349
        mov     ah , cl ; ah = phy
1350
        push    cx
1351
        call    try_phy
1352
        pop     cx
1353
        test    al , al
1354
        jnz     .check_preamble
1355
  .next_phy:
1356
        loopw   .search_phy_loop
1357
 
1358
  .fail_finish:
1359
        xor     al, al
1360
        ret
1361
 
1362
; epilog
1363
  .check_preamble:
1364
        DEBUGF  1,"Using PHY: %u\nChecking PreAmble\n", cl
1365
        push    eax ; eax contains the return value of try_phy
1366
; check hard coded preamble forcing
1367
        movzx   eax, [device.ver_id]
1368
        test    word [eax*4+hw_versions+2], EXTRA_PREAMBLE
1369
        setnz   [device.preamble] ; force preamble
1370
        jnz     .finish
1371
 
1372
; check mii for preamble suppression
1373
        mov     ah, cl
1374
        mov     al, REG_MII_BMSR
1375
        call    mdio_read
1376
        test    al, 1000000b ; preamble suppression?
1377
        setz    [device.preamble] ; no
1378
 
1379
  .finish:
1380
        pop     eax
1381
        ret
1382
 
1383
 
1384
 
1385
;***************************************************************************
1386
;   Function
1387
;      test_packet
1388
;   Description
1389
;      try_loopback try a loopback packet for 10BASE2 or AUI port
1390
;   Parameters
1391
;      ebx = device structure
1392
;
1393
;***************************************************************************
1394
 
1395
align 4
1396
test_packet:
1397
 
1398
        DEBUGF 1,"sending test packet\n"
1399
 
1400
; switch to register window 3
1401
        set_io  0
1402
        set_io  REG_COMMAND
1403
        mov     ax, SELECT_REGISTER_WINDOW+3
1404
        out     dx, ax
1405
 
1406
; set fullDuplexEnable in MacControl register
1407
        set_io  REG_MAC_CONTROL
1408
        in      ax, dx
1409
        or      ax, 0x120
1410
        out     dx, ax
1411
 
1412
; switch to register window 5
1413
        set_io  REG_COMMAND
1414
        mov     ax, SELECT_REGISTER_WINDOW+5
1415
        out     dx, ax
1416
 
1417
; set RxFilter to enable individual address matches
1418
        mov     ax, (10000b shl 11)
1419
        set_io  REG_RX_FILTER
1420
        in      al, dx
1421
        or      al, 1
1422
        set_io  REG_COMMAND
1423
        out     dx, ax
1424
 
1425
; issue RxEnable and TxEnable
1426
        call    rx_reset
1427
        call    tx_reset
1428
 
1429
; create self-directed packet
1430
        stdcall KernelAlloc, 20 ; create a buffer for the self-directed packet
1431
        test    eax, eax
1432
        jz      .fail
1433
 
1434
        pushd   20              ; Packet parameters for device.transmit
1435
        push    eax             ;
1436
 
1437
        mov     edi, eax
1438
        lea     esi, [device.mac]
1439
        movsw
1440
        movsd
1441
        sub     esi, 6
1442
        movsw
1443
        movsd
1444
        mov     ax , 0x0608
1445
        stosw
1446
 
1447
; download self-directed packet
1448
        call    [device.transmit]
1449
 
1450
; wait for 2s
1451
        mov     esi, 2000
1452
        call    Sleep
1453
 
1454
; check if self-directed packet is received
1455
        mov     eax, [device.packets_rx]
1456
        test    eax, eax
1457
        jnz     .finish
1458
 
1459
; switch to register window 3
1460
        set_io  0
1461
        set_io  REG_COMMAND
1462
        mov     ax, SELECT_REGISTER_WINDOW+3
1463
        out     dx, ax
1464
 
1465
; clear fullDuplexEnable in MacControl register
1466
        set_io  REG_MAC_CONTROL
1467
        in      ax , dx
1468
        and     ax , not 0x120
1469
        out     dx , ax
1470
  .fail:
1471
        xor     eax, eax
1472
 
1473
  .finish:
1474
        ret
1475
 
1476
 
1477
 
1478
;***************************************************************************
1479
;   Function
1480
;      try_loopback
1481
;   Description
1482
;      tries a loopback packet for 10BASE2 or AUI port
1483
;   Parameters
1484
;      al -  0: 10Mbps AUI connector
1485
;            1: 10BASE-2
3880 hidnplayr 1486
;
3545 hidnplayr 1487
;   Return value
1488
;      al - 0
1489
;      al - 1
1490
;   Destroyed registers
1491
;      eax, ebx, ecx, edx, edi, esi
1492
;
1493
;***************************************************************************
1494
 
1495
align 4
1496
try_loopback:
1497
 
1498
        DEBUGF 1,"trying loopback\n"
1499
 
1500
        push    eax
1501
; switch to register window 3
1502
        set_io  0
1503
        set_io  REG_COMMAND
1504
        mov     ax, SELECT_REGISTER_WINDOW+3
1505
        out     dx, ax
1506
        mov     eax, [esp]
1507
 
1508
        mov     cl, al
1509
        inc     cl
1510
        shl     cl, 3
1511
        or      byte [device.state+1], cl
1512
 
1513
        test    al, al ; aui or coax?
1514
        jz      .complete_loopback
1515
; enable 100BASE-2 DC-DC converter
1516
        mov     ax, (10b shl 11) ; EnableDcConverter
1517
        out     dx, ax
1518
  .complete_loopback:
1519
 
1520
        mov     cx, 2 ; give a port 3 chances to complete a loopback
1521
  .next_try:
1522
        push    ecx
1523
        call    test_packet
1524
        pop     ecx
1525
        test    eax, eax
1526
        loopzw  .next_try
1527
 
1528
  .finish:
1529
        xchg    eax, [esp]
1530
        test    al, al
1531
        jz      .aui_finish
1532
 
1533
; issue DisableDcConverter command
1534
        set_io  0
1535
        set_io  REG_COMMAND
1536
        mov     ax, (10111b shl 11)
1537
        out     dx, ax
1538
  .aui_finish:
1539
        pop     eax ; al contains the result of operation
1540
 
1541
        test    al, al
1542
        jnz     @f
1543
        and     byte [device.state+1], not 11000b
1544
       @@:
1545
 
1546
        ret
1547
 
1548
 
1549
;***************************************************************************
1550
;   Function
1551
;      set_active_port
1552
;   Description
1553
;      It selects the media port (transceiver) to be used
1554
;   Return value:
1555
;   Destroyed registers
1556
;      eax, ebx, ecx, edx, edi, esi
1557
;
1558
;***************************************************************************
1559
 
1560
align 4
1561
set_active_port:
1562
 
1563
        DEBUGF 1,"Trying to find the active port\n"
1564
 
1565
; switch to register window 3
1566
        set_io  0
1567
        set_io  REG_COMMAND
1568
        mov     ax, SELECT_REGISTER_WINDOW + 3
1569
        out     dx, ax
1570
 
1571
        set_io  REG_INTERNAL_CONFIG
1572
        in      eax, dx
1573
        test    eax, (1 shl 24) ; check if autoselect enable
1574
        jz      .set_first_available_media
1575
 
1576
; check 100BASE-TX and 10BASE-T
1577
        set_io  REG_MEDIA_OPTIONS
1578
        in      ax, dx
1579
        test    al, 1010b       ; check whether 100BASE-TX or 10BASE-T available
1580
        jz      .mii_device     ; they are not available
1581
 
1582
; set auto-negotiation
1583
        set_io  REG_INTERNAL_CONFIG
1584
        in      eax, dx
1585
        and     eax, not (1111b shl 20)
1586
        or      eax, (1000b shl 20)
1587
        out     dx, eax
1588
        call    try_mii
1589
        test    al, al
1590
        jz      .mii_device
1591
        DEBUGF 1,"Using auto negotiation\n"
1592
        ret
1593
 
1594
  .mii_device:
1595
; switch to register window 3
1596
        set_io  0
1597
; check for off-chip mii device
1598
        set_io  REG_MEDIA_OPTIONS
1599
        in      ax, dx
1600
        test    al, 1000000b ; check miiDevice
1601
        jz      .base_fx
1602
        set_io  REG_INTERNAL_CONFIG
1603
        in      eax, dx
1604
        and     eax, not (1111b shl 20)
1605
        or      eax, (0110b shl 20) ; set MIIDevice
1606
        out     dx, eax
1607
        call    try_mii
1608
        test    al, al
1609
        jz      .base_fx
1610
        DEBUGF 1,"Using off-chip mii device\n"
1611
        ret
1612
 
1613
  .base_fx:
1614
; switch to register window 3
1615
        set_io  0
1616
; check for 100BASE-FX
1617
        set_io  REG_MEDIA_OPTIONS
1618
        in      ax, dx ; read media option register
1619
        test    al, 100b ; check 100BASE-FX
1620
        jz      .aui_enable
1621
        set_io  REG_INTERNAL_CONFIG
1622
        in      eax, dx
1623
        and     eax, not (1111b shl 20)
1624
        or      eax, (0101b shl 20) ; set 100base-FX
1625
        out     dx, eax
1626
        call    try_link_detect
1627
        test    al, al
1628
        jz      .aui_enable
1629
        DEBUGF 1,"Using 100Base-FX\n"
1630
        ret
1631
 
1632
  .aui_enable:
1633
; switch to register window 3
1634
        set_io  0
1635
; check for 10Mbps AUI connector
1636
        set_io  REG_MEDIA_OPTIONS
1637
        in      ax, dx ; read media option register
1638
        test    al, 100000b ; check 10Mbps AUI connector
1639
        jz      .coax_available
1640
        set_io  REG_INTERNAL_CONFIG
1641
        in      eax, dx
1642
        and     eax, not (1111b shl 20)
1643
        or      eax, (0001b shl 20) ; set 10Mbps AUI connector
1644
        out     dx, eax
1645
        xor     al, al ; try 10Mbps AUI connector
1646
        call    try_loopback
1647
        test    al, al
1648
        jz      .coax_available
1649
        DEBUGF 1,"Using 10Mbps aui\n"
1650
        ret
1651
 
1652
  .coax_available:
1653
; switch to register window 3
1654
        set_io  0
1655
; check for coaxial 10BASE-2 port
1656
        set_io  REG_MEDIA_OPTIONS
1657
        in      ax, dx ; read media option register
1658
        test    al, 10000b ; check 10BASE-2
1659
        jz      .set_first_available_media
1660
 
1661
        set_io  REG_INTERNAL_CONFIG
1662
        in      eax, dx
1663
        and     eax, not (1111b shl 20)
1664
        or      eax, (0011b shl 20) ; set 10BASE-2
1665
        out     dx, eax
1666
        mov     al, 1
1667
        call    try_loopback
1668
        test    al, al
1669
        jz      .set_first_available_media
1670
        DEBUGF 1,"Using 10BASE-2 port\n"
1671
        ret
1672
 
1673
  .set_first_available_media:
1674
        DEBUGF  1,"Using the first available media\n"
1675
 
1676
;***************************************************************************
1677
;   Function
1678
;      set_available_media
1679
;   Description
1680
;      sets the first available media
1681
;   Parameters
1682
;      ebx - ptr to device struct
1683
;   Return value
1684
;      al - 0
1685
;      al - 1
1686
;   Destroyed registers
1687
;      eax, edx
1688
;
1689
;***************************************************************************
1690
 
1691
align 4
1692
set_available_media:
1693
 
1694
        DEBUGF  1,"Setting the available media\n"
1695
; switch to register window 3
1696
        set_io  0
1697
        set_io  REG_COMMAND
1698
        mov     ax, SELECT_REGISTER_WINDOW+3
1699
        out     dx, ax
1700
 
1701
        set_io  REG_MEDIA_OPTIONS
1702
        in      ax, dx
1703
        DEBUGF  1,"available media:%x\n", al
1704
        mov     cl, al
1705
 
1706
        set_io  REG_INTERNAL_CONFIG
1707
        in      eax, dx
1708
        and     eax, not (1111b shl 20) ; these bits hold the 'transceiver select' value
1709
 
1710
        test    cl, 10b         ; baseTXAvailable
1711
        jz      @f
1712
 
1713
        DEBUGF  1,"base TX is available\n"
1714
        or      eax, (100b shl 20)
1715
if defined FORCE_FD
1716
        mov     word [device.state], (1 shl 8)
1717
else
1718
        mov     word [device.mode], (1 shl 7)
1719
end if
1720
        jmp     .set_media
1721
       @@:
1722
 
1723
        test    cl, 100b        ; baseFXAvailable
1724
        jz      @f
1725
 
1726
        DEBUGF  1,"base FX is available\n"
1727
        or      eax, (101b shl 20)
1728
        mov     word [device.state], (1 shl 10)
1729
        jmp     .set_media
1730
       @@:
1731
 
1732
        test    cl, 1000000b    ; miiDevice
1733
        jz      @f
1734
 
1735
        DEBUGF  1,"mii-device is available\n"
1736
        or      eax, (0110b shl 20)
1737
        mov     word [device.state], (1 shl 13)
1738
        jmp     .set_media
1739
       @@:
1740
 
1741
        test    cl, 1000b       ; 10bTAvailable
1742
        jz      @f
1743
 
1744
        DEBUGF  1,"10base-T is available\n"
1745
  .set_default:
1746
if FORCE_FD
1747
        mov     word [device.state], (1 shl 6)
1748
else
1749
        mov     word [device.state], (1 shl 5)
1750
end if
1751
        jmp     .set_media
1752
       @@:
1753
 
1754
        test    cl, 10000b      ; coaxAvailable
1755
        jz      @f
1756
 
1757
        DEBUGF  1,"coax is available\n"
1758
        push    eax
1759
        set_io  REG_COMMAND
1760
        mov     ax, (10b shl 11) ; EnableDcConverter
1761
        out     dx, ax
1762
        pop     eax
1763
 
1764
        or      eax, (11b shl 20)
1765
        mov     word [device.state], (1 shl 12)
1766
        jmp     .set_media
1767
       @@:
1768
 
1769
        test    cl, 10000b      ; auiAvailable
1770
        jz      .set_default
1771
 
1772
        DEBUGF  1,"AUI is available\n"
1773
        or      eax, (1 shl 20)
1774
        mov     word [device.state], (1 shl 11)
1775
 
1776
  .set_media:
1777
        set_io  0
1778
        set_io  REG_INTERNAL_CONFIG
1779
        out     dx, eax
1780
 
1781
if FORCE_FD
1782
        DEBUGF  1,"Forcing full duplex\n"
1783
        set_io  REG_MAC_CONTROL
1784
        in      ax, dx
1785
        or      ax, 0x120
1786
        out     dx, ax
1787
end if
1788
 
1789
        mov     al, 1
1790
        ret
1791
 
1792
 
1793
 
1794
;***************************************************************************
1795
;   Function
1796
;      wake_up
1797
;   Description
1798
;      set the power state to D0
1799
;
1800
;***************************************************************************
1801
 
1802
align 4
1803
wake_up:
1804
 
1805
        DEBUGF 1,"Waking up NIC: "
1806
 
1807
; wake up - we directly do it by programming PCI
1808
; check if the device is power management capable
1809
        stdcall PciRead32, [device.pci_bus], [device.pci_dev], PCI_REG_STATUS
1810
 
1811
        test    al, 10000b      ; is there "new capabilities" linked list?
1812
        jz      .device_awake
1813
 
1814
; search for power management register
1815
        stdcall PciRead16, [device.pci_bus], [device.pci_dev], PCI_REG_CAP_PTR
1816
        cmp     al, 0x3f
1817
        jbe     .device_awake
1818
 
1819
; traverse the list
1820
        movzx   esi, al
1821
  .pm_loop:
1822
        stdcall PciRead32, [device.pci_bus], [device.pci_dev], esi
1823
 
1824
        cmp     al , 1
1825
        je      .set_pm_state
1826
 
1827
        movzx   esi, ah
1828
 
1829
        test    ah , ah
1830
        jnz     .pm_loop
1831
        jmp     .device_awake
1832
 
1833
; waku up the device if necessary
1834
  .set_pm_state:
1835
 
1836
        add     esi, PCI_REG_PM_CTRL
1837
        stdcall PciRead32, [device.pci_bus], [device.pci_dev], esi
1838
        test    al, 3
1839
        jz      .device_awake
1840
        and     al, not 11b ; set state to D0
1841
        stdcall PciWrite32, [device.pci_bus], [device.pci_dev], esi, eax
1842
 
1843
  .device_awake:
1844
        DEBUGF 1,"Device is awake\n"
1845
 
1846
        ret
1847
 
1848
 
1849
 
1850
 
1851
;***************************************************************************
1852
;   Function
1853
;      write_eeprom
1854
;   Description
1855
;      reads eeprom
1856
;      Note : the caller must switch to the register window 0
1857
;             before calling this function
1858
;   Parameters:
1859
;      ax - register to be read (only the first 63 words can be read)
1860
;      cx - value to be read into the register
1861
;   Return value:
1862
;      ax - word read
1863
;   Destroyed registers
1864
;      ax, ebx, edx
1865
;
1866
;***************************************************************************
1867
;       align 4
1868
;write_eeprom:
1869
;       mov     edx, [io_addr]
1870
;       add     edx, REG_EEPROM_COMMAND
1871
;       cmp     ah, 11b
1872
;       ja      .finish ; address may have a value of maximal 1023
1873
;       shl     ax, 2
1874
;       shr     al, 2
1875
;       push    eax
1876
;; wait for busy
1877
;       mov     ebx, 0xffff
1878
;@@:
1879
;       in      ax, dx
1880
;       test    ah, 0x80
1881
;       jz      .write_enable
1882
;       dec     ebx
1883
;       jns     @r
1884
;; write enable
1885
;.write_enable:
1886
;       xor     eax, eax
1887
;       mov     eax, (11b shl 4)
1888
;       out     dx, ax
1889
;; wait for busy
1890
;       mov     ebx, 0xffff
1891
;@@:
1892
;       in      ax, dx
1893
;       test    ah, 0x80
1894
;       jz      .erase_loop
1895
;       dec     ebx
1896
;       jns     @r
1897
;.erase_loop:
1898
;       pop     eax
1899
;       push    eax
1900
;       or      ax, (11b shl 6) ; erase register
1901
;       out     dx, ax
1902
;       mov     ebx, 0xffff
1903
;@@:
1904
;       in      ax, dx
1905
;       test    ah, 0x80
1906
;       jz      .write_reg
1907
;       dec     ebx
1908
;       jns     @r
1909
;.write_reg:
1910
;       add     edx, REG_EEPROM_DATA-REG_EEPROM_COMMAND
1911
;       mov     eax, ecx
1912
;       out     dx, ax
1913
;; write enable
1914
;       add     edx, REG_EEPROM_COMMAND-REG_EEPROM_DATA
1915
;       xor     eax, eax
1916
;       mov     eax, (11b shl 4)
1917
;       out     dx, ax
1918
; wait for busy
1919
;       mov     ebx, 0xffff
1920
;@@:
1921
;       in      ax, dx
1922
;       test    ah, 0x80
1923
;       jz      .issue_write_reg
1924
;       dec     ebx
1925
;       jns     @r
1926
;.issue_write_reg:
1927
;       pop     eax
1928
;       or      ax, 01b shl 6
1929
;       out     dx, ax
1930
;.finish:
1931
;       ret
1932
 
1933
 
1934
;***************************************************************************
1935
;   Function
1936
;      read_eeprom
1937
;   Description
1938
;      reads eeprom
1939
;   Parameters:
1940
;       ax - register to be read (only the first 63 words can be read)
1941
;      ebx = driver structure
1942
;   Return value:
1943
;      ax - word read
1944
;   Destroyed registers
1945
;      ax, ebx, edx
1946
;
1947
;***************************************************************************
1948
 
1949
align 4
1950
read_eeprom:
1951
 
1952
        DEBUGF 1,"Reading from eeprom.. "
1953
 
1954
        push    eax
1955
; switch to register window 0
1956
        set_io  0
1957
        set_io  REG_COMMAND
1958
        mov     ax, SELECT_REGISTER_WINDOW+0
1959
        out     dx, ax
1960
        pop     eax
1961
        and     ax, 111111b ; take only the first 6 bits into account
1962
        movzx   esi, [device.ver_id]
1963
 
1964
        test    word [esi*4+hw_versions+2], EEPROM_8BIT
1965
        jz      @f
1966
        add     ax, 0x230 ; hardware constant
1967
        jmp     .read
1968
@@:
1969
 
1970
        add     ax, EEPROM_CMD_READ
1971
        test    word [esi*4+hw_versions+2], EEPROM_OFFSET
1972
        jz      .read
1973
        add     ax, 0x30
1974
.read:
1975
 
1976
        set_io  REG_EEPROM_COMMAND
1977
        out     dx, ax
1978
        mov     ecx, 0xffff ; duration of about 162 us ;-)
1979
.wait_for_reading:
1980
        in      ax, dx
1981
        test    ah, 0x80 ; check bit eepromBusy
1982
        jz      .read_data
1983
        loop    .wait_for_reading
1984
.read_data:
1985
        set_io  REG_EEPROM_DATA
1986
        in      ax, dx
1987
 
1988
        DEBUGF 1,"ok!\n"
1989
 
1990
        ret
1991
 
1992
;***************************************************************************
1993
;   Function
1994
;      mdio_sync
1995
;   Description
1996
;      initial synchronization
1997
;   Parameters
3880 hidnplayr 1998
;
3545 hidnplayr 1999
;   Return value
2000
;   Destroyed registers
2001
;      ax, edx, cl
2002
;
2003
;***************************************************************************
2004
 
2005
align 4
2006
mdio_sync:
2007
 
2008
        DEBUGF 1,"syncing mdio\n"
2009
 
2010
; switch to register window 4
2011
        set_io  0
2012
        set_io  REG_COMMAND
2013
        mov     ax, SELECT_REGISTER_WINDOW+4
2014
        out     dx, ax
2015
        cmp     [device.preamble], 0
2016
        je      .no_preamble
2017
; send 32 logic ones
2018
        set_io  REG_PHYSICAL_MGMT
2019
        mov     ecx, 31
2020
  .loop:
2021
        mov     ax, (1 shl BIT_MGMT_DATA) or (1 shl BIT_MGMT_DIR)
2022
        out     dx, ax
2023
        in      ax, dx ; delay
2024
        mov     ax, (1 shl BIT_MGMT_DATA) or (1 shl BIT_MGMT_DIR) or (1 shl BIT_MGMT_CLK)
2025
        out     dx, ax
2026
        in      ax, dx ; delay
2027
        loop    .loop
2028
  .no_preamble:
2029
 
2030
        ret
2031
 
2032
;***************************************************************************
2033
;   Function
2034
;      mdio_read
2035
;   Description
2036
;      read MII register
2037
;      see page 16 in D83840A.pdf
2038
;   Parameters
2039
;       ah - PHY addr
2040
;       al - register addr
2041
;      ebx = device structure
2042
;   Return value
2043
;      ax - register read
2044
;
2045
;***************************************************************************
2046
 
2047
align 4
2048
mdio_read:
2049
 
2050
        DEBUGF 1,"Reading MII registers\n"
2051
 
2052
        push    eax
2053
        call    mdio_sync ; returns with window #4
2054
        pop     eax
2055
        set_io  0
2056
        set_io  REG_PHYSICAL_MGMT
2057
        shl     al, 3
2058
        shr     ax, 3
2059
        and     ax, not MII_CMD_MASK
2060
        or      ax, MII_CMD_READ
2061
 
2062
        mov     esi, eax
2063
        mov     ecx, 13
2064
  .cmd_loop:
2065
        mov     ax, (1 shl BIT_MGMT_DIR) ; write mii
2066
        bt      esi, ecx
2067
        jnc     .zero_bit
2068
        or      al, (1 shl BIT_MGMT_DATA)
2069
 
2070
  .zero_bit:
2071
        out     dx, ax
2072
        push    ax
2073
        in      ax, dx ; delay
2074
        pop     ax
2075
        or      al, (1 shl BIT_MGMT_CLK) ; write
2076
        out     dx, ax
2077
        in      ax, dx ; delay
2078
        loop    .cmd_loop
2079
 
2080
; read data (18 bits with the two transition bits)
2081
        mov     ecx, 17
2082
        xor     esi, esi
2083
  .read_loop:
2084
        shl     esi, 1
2085
        xor     eax, eax ; read comand
2086
        out     dx, ax
2087
        in      ax, dx ; delay
2088
        in      ax, dx
2089
        test    al, (1 shl BIT_MGMT_DATA)
2090
        jz      .dont_set
2091
        inc     esi
2092
  .dont_set:
2093
        mov     ax, (1 shl BIT_MGMT_CLK)
2094
        out     dx, ax
2095
        in      ax, dx ; delay
2096
        loop    .read_loop
2097
        mov     eax, esi
2098
 
2099
        ret
2100
 
2101
 
2102
 
2103
;***************************************************************************
2104
;   Function
2105
;      mdio_write
2106
;   Description
2107
;      write MII register
2108
;      see page 16 in D83840A.pdf
2109
;   Parameters
2110
;       ah - PHY addr
2111
;       al - register addr
2112
;       si - word to be written
2113
;   Return value
2114
;      ax - register read
2115
;
2116
;***************************************************************************
2117
 
2118
align 4
2119
mdio_write:
2120
 
2121
        DEBUGF 1,"Writing MII registers\n"
2122
 
2123
        push    eax
2124
        call    mdio_sync
2125
        pop     eax
2126
        set_io  0
2127
        set_io  REG_PHYSICAL_MGMT
2128
        shl     al, 3
2129
        shr     ax, 3
2130
        and     ax, not MII_CMD_MASK
2131
        or      ax, MII_CMD_WRITE
2132
        shl     eax, 2
2133
        or      eax, 10b ; transition bits
2134
        shl     eax, 16
2135
        mov     ax, si
2136
        mov     esi, eax
2137
        mov     ecx, 31
2138
 
2139
  .cmd_loop:
2140
        mov     ax, (1 shl BIT_MGMT_DIR) ; write mii
2141
        bt      esi, ecx
2142
        jnc     @f
2143
        or      al, (1 shl BIT_MGMT_DATA)
2144
       @@:
2145
        out     dx, ax
2146
        push    eax
2147
        in      ax, dx ; delay
2148
        pop     eax
2149
        or      al, (1 shl BIT_MGMT_CLK) ; write
2150
        out     dx, ax
2151
        in      ax, dx ; delay
2152
        loop    .cmd_loop
2153
 
2154
        ret
2155
 
2156
 
2157
;***************************************************************************
2158
;   Function
2159
;      check_tx_status
2160
;   Description
2161
;      Checks TxStatus queue.
2162
;   Return value
2163
;      al - 0 no error was found
2164
;      al - 1 error was found TxReset was needed
2165
;   Destroyed registers
3880 hidnplayr 2166
;      eax, ecx, edx
3545 hidnplayr 2167
;
2168
;***************************************************************************
2169
 
2170
align 4
2171
check_tx_status:
2172
 
2173
        DEBUGF 1,"Checking TX status\n"
2174
 
2175
; clear TxStatus queue
2176
        set_io  0
2177
        set_io  REG_TX_STATUS
2178
        mov     ecx, 31 ; max number of queue entries
2179
 
2180
  .tx_status_loop:
2181
        in      al, dx
2182
        test    al, al
2183
        jz      .finish ; no error
2184
        test    al, 0x3f
2185
        jnz     .error
2186
  .no_error_found:
2187
; clear current TxStatus entry which advances the next one
2188
        xor     al, al
2189
        out     dx, al
2190
        loop    .tx_status_loop
2191
 
2192
  .finish:
2193
 
2194
        ret
2195
 
2196
  .error:
2197
        call    tx_reset
2198
        ret
2199
 
2200
 
2201
 
2202
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2203
;;                                         ;;
2204
;; Transmit (vortex)                       ;;
2205
;;                                         ;;
2206
;; In: buffer pointer in [esp+4]           ;;
2207
;;     size of buffer in [esp+8]           ;;
2208
;;     pointer to device structure in ebx  ;;
2209
;;                                         ;;
2210
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2211
 
2212
align 4
2213
vortex_transmit:
2214
 
2215
        DEBUGF 1,"Sending packet (vortex)\n"
2216
 
2217
        cmp     dword [esp+8], MAX_ETH_FRAME_SIZE
2218
        ja      .finish ; packet is too long
2219
 
2220
        call    check_tx_status
2221
 
2222
; switch to register window 7
2223
        set_io  0
2224
        set_io  REG_COMMAND
2225
        mov     ax, SELECT_REGISTER_WINDOW+7
2226
        out     dx, ax
2227
; check for master operation in progress
2228
        set_io  REG_MASTER_STATUS
2229
        in      ax, dx
2230
        test    ah, 0x80
2231
        jnz     .finish ; no DMA for sending
2232
; program frame address to be sent
2233
        set_io  REG_MASTER_ADDRESS
2234
        mov     eax, [esp+4]
2235
        call    GetPgAddr
2236
        out     dx, eax
2237
; program frame length
2238
        set_io  REG_MASTER_LEN
2239
        mov     eax, [esp+8]
2240
;;;        and     eax, not 3
2241
        out     dx, ax
2242
; start DMA Down
2243
        set_io  REG_COMMAND
2244
        mov     ax, (10100b shl 11) + 1 ; StartDMADown
2245
        out     dx, ax
2246
.finish:
2247
        call    KernelFree
2248
        add     esp, 4
2249
        ret
2250
 
2251
 
2252
 
2253
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2254
;;                                         ;;
2255
;; Transmit (boomerang)                    ;;
2256
;;                                         ;;
2257
;; In: buffer pointer in [esp+4]           ;;
2258
;;     size of buffer in [esp+8]           ;;
2259
;;     pointer to device structure in ebx  ;;
2260
;;                                         ;;
2261
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2262
 
2263
align 4
2264
boomerang_transmit:
2265
 
2266
        DEBUGF  1,"Transmitting packet, buffer:%x, size:%u\n",[esp+4],[esp+8]
2267
        mov     eax, [esp+4]
2268
        DEBUGF  1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
2269
        [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
2270
        [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
2271
        [eax+13]:2,[eax+12]:2
2272
 
2273
        cmp     dword [esp+8], MAX_ETH_FRAME_SIZE
2274
        ja      .fail
2275
 
2276
        call    check_tx_status
2277
 
2278
; calculate descriptor address
2279
        mov     esi, [device.prev_dpd]
2280
        DEBUGF  1,"Previous DPD: %x\n", esi
2281
        add     esi, dpd.size
2282
        lea     ecx, [device.dpd_buffer + (NUM_TX_DESC)*dpd.size]
2283
        cmp     esi, ecx
2284
        jb      @f
2285
        lea     esi, [device.dpd_buffer]        ; Wrap if needed
2286
       @@:
2287
        DEBUGF  1,"Found a free DPD: %x\n", esi
2288
 
2289
; check DnListPtr
2290
        set_io  0
2291
        set_io  REG_DN_LIST_PTR
2292
        in      eax, dx
2293
; mark if Dn_List_Ptr is cleared
2294
        test    eax, eax
2295
        setz    [device.dn_list_ptr_cleared]
2296
 
2297
; finish if no more free descriptor is available - FIXME!
2298
;        cmp     eax, esi
2299
;        jz      .finish
2300
 
2301
; update statistics
2302
        inc     [device.packets_tx]
2303
        mov     ecx, [esp+8]            ; buffer size
2304
        add     dword [device.bytes_tx], ecx
2305
        adc     dword [device.bytes_tx + 4], 0
2306
 
2307
; program DPD
2308
        and     [esi+dpd.next_ptr], 0
2309
        mov     eax, [esp+4]            ; Tx buffer address
2310
        mov     [esi+dpd.realaddr], eax
2311
        call    GetPgAddr
2312
        mov     [esi+dpd.frag_addr], eax
2313
        mov     ecx, [esp+8]            ; packet size
2314
        or      ecx, 0x80000000         ; last fragment
2315
        mov     [esi+dpd.frag_len], ecx
2316
 
2317
        mov     ecx, [esp+8]            ; packet size
2318
;        or      ecx, 0x8000             ; transmission complete notification
2319
 
2320
        or      ecx, 1 shl 31
2321
 
2322
;        test    byte [device.has_hwcksm], 0xff
2323
;        jz      @f
2324
;        or      ecx, (1 shl 26)         ; set AddTcpChecksum
2325
;@@:
2326
        mov     [esi+dpd.frame_start_hdr], ecx
2327
 
2328
        DEBUGF  1,"DPD: lin=%x phys=%x len=%x start hdr=%x\n", [esi+dpd.realaddr]:8, [esi+dpd.frag_addr]:8, [esi+dpd.frag_len]:8, [esi+dpd.frame_start_hdr]:8
2329
 
2330
; calculate physical address of dpd
2331
        mov     eax, esi
2332
        GetRealAddr
2333
        cmp     [device.dn_list_ptr_cleared], 0
2334
        jz      .add_to_list
2335
 
2336
; write Dn_List_Ptr
2337
        DEBUGF  1,"DPD phys addr=%x\n", eax
2338
        set_io  0
2339
        set_io  REG_DN_LIST_PTR
2340
        out     dx, eax
2341
        jmp     .finish
2342
 
2343
  .add_to_list:
2344
        DEBUGF  1,"Adding To list\n"
2345
        push    eax
2346
; DnStall
2347
        set_io  0
2348
        set_io  REG_COMMAND
2349
        mov     ax, ((110b shl 11)+2)
2350
        out     dx, ax
2351
 
2352
; wait for DnStall to complete
2353
        DEBUGF  1,"Waiting for DnStall\n"
2354
        mov     ecx, 6000
2355
  .wait_for_stall:
2356
        in      ax, dx                  ; read REG_INT_STATUS
2357
        test    ah, 10000b
2358
        jz      .dnstall_ok
2359
        dec     ecx
2360
        jnz     .wait_for_stall
2361
 
2362
  .dnstall_ok:
2363
        DEBUGF  1,"DnStall ok!\n"
2364
        mov     ecx, [device.prev_dpd]
2365
        mov     [ecx+dpd.next_ptr], eax
2366
 
2367
        set_io  0
2368
        set_io  REG_DN_LIST_PTR
2369
        in      eax, dx
2370
        test    eax, eax
2371
        pop     eax
2372
        jnz     .dnunstall
2373
 
2374
; if Dn_List_Ptr has been cleared fill it up
2375
        DEBUGF  1,"DnList Ptr has been cleared\n"
2376
        out     dx, eax
2377
 
2378
  .dnunstall:
2379
; DnUnStall
2380
        set_io  0
2381
        set_io  REG_COMMAND
2382
        mov     ax, ((110b shl 11)+3)
2383
        out     dx, ax
2384
 
2385
  .finish:
2386
        mov     [device.prev_dpd], esi
2387
        xor     eax, eax
2388
        ret     8
2389
 
2390
  .fail:
2391
        stdcall KernelFree, [esp+4]
2392
        or      eax, -1
2393
        ret     8
2394
 
2395
 
2396
;---------------------------------
2397
; Write MAC
2398
 
2399
align 4
2400
write_mac:
2401
 
2402
        DEBUGF 1,"Writing mac\n"
2403
 
2404
        set_io  0
2405
        set_io  REG_COMMAND
2406
 
2407
; switch to register window 2
2408
        mov     ax, SELECT_REGISTER_WINDOW+2
2409
        out     dx, ax
2410
 
2411
; write MAC addres back into the station address registers
2412
        set_io  REG_STATION_ADDRESS_LO
2413
        lea     esi, [device.mac]
2414
        outsw
2415
        inc     dx
2416
        inc     dx
2417
        outsw
2418
        inc     dx
2419
        inc     dx
2420
        outsw
2421
 
2422
 
2423
;----------------------------
2424
; Read MAC
2425
 
2426
align 4
2427
read_mac:
2428
 
2429
        set_io  0
2430
        set_io  REG_COMMAND
2431
 
2432
; switch to register window 2
2433
        mov     ax, SELECT_REGISTER_WINDOW+2
2434
        out     dx, ax
2435
 
2436
; write MAC addres back into the station address registers
2437
        set_io  REG_STATION_ADDRESS_LO
2438
        lea     edi, [device.mac]
2439
        insw
2440
        inc     dx
2441
        inc     dx
2442
        insw
2443
        inc     dx
2444
        inc     dx
2445
        insw
2446
 
2447
        DEBUGF 1,"%x-%x-%x-%x-%x-%x\n",[device.mac]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2
2448
 
2449
        ret
2450
 
2451
 
2452
;------------------------------------
2453
; Read MAC from eeprom
2454
 
2455
align 4
2456
read_mac_eeprom:        ; Tested - ok
2457
 
2458
        DEBUGF 1,"Reading mac from eeprom\n"
2459
 
2460
; read MAC from eeprom
2461
        mov     ecx, 3
2462
  .mac_loop:
2463
        lea     ax, [EEPROM_REG_OEM_NODE_ADDR+ecx-1]
2464
        push    ecx
2465
        call    read_eeprom
2466
        pop     ecx
2467
        xchg    ah, al ; htons
2468
        mov     word [device.mac+ecx*2-2], ax
2469
        loop    .mac_loop
2470
 
2471
        DEBUGF 1,"%x-%x-%x-%x-%x-%x\n",[device.mac]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2
2472
 
2473
        ret
2474
 
2475
 
2476
 
2477
 
2478
 
2479
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2480
;;                          ;;
2481
;; Vortex Interrupt handler ;;
2482
;;                          ;;
2483
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2484
 
2485
align 4
2486
int_vortex:
2487
 
2488
        push    ebx esi edi
2489
 
3880 hidnplayr 2490
        DEBUGF  1,"INT\n"
3545 hidnplayr 2491
 
2492
; find pointer of device wich made IRQ occur
2493
 
2494
        mov     esi, VORTEX_LIST
2495
        mov     ecx, [VORTEX_DEVICES]
2496
        test    ecx, ecx
2497
        jz      .nothing
2498
  .nextdevice:
2499
        mov     ebx, dword [esi]
2500
 
2501
 
2502
        set_io  0
2503
        set_io  REG_INT_STATUS
2504
        in      ax, dx
2505
        and     ax, S_5_INTS
2506
        jnz     .nothing
2507
 
2508
        add     esi, 4
2509
 
2510
        test    ax , ax
2511
        jnz     .got_it
2512
        loop    .nextdevice
2513
 
2514
  .nothing:
2515
        pop     edi esi ebx
2516
        xor     eax, eax
2517
 
2518
        ret
2519
 
2520
.got_it:
2521
 
2522
        DEBUGF  1,"Device: %x Status: %x ",ebx,eax:4
2523
 
2524
        test    ax, RxComplete
2525
        jz      .noRX
2526
 
2527
        set_io  0
2528
  .rx_status_loop:
2529
; examine RxStatus
2530
        set_io  REG_RX_STATUS
2531
        in      ax, dx
2532
        test    ax, ax
2533
        jz      .finish
2534
 
2535
        test    ah, 0x80 ; rxIncomplete
2536
        jnz     .finish
2537
 
2538
        test    ah, 0x40
2539
        jz      .check_length
2540
 
2541
; discard the top frame received advancing the next one
2542
        set_io  REG_COMMAND
2543
        mov     ax, (01000b shl 11)
2544
        out     dx, ax
2545
        jmp     .rx_status_loop
2546
 
2547
  .check_length:
2548
        and     eax, 0x1fff
2549
        cmp     eax, MAX_ETH_PKT_SIZE
2550
        ja      .discard_frame ; frame is too long discard it
2551
 
2552
  .check_dma:
2553
        mov     ecx, eax
2554
; switch to register window 7
2555
        set_io  0
2556
        set_io  REG_COMMAND
2557
        mov     ax, SELECT_REGISTER_WINDOW+7
2558
        out     dx, ax
2559
; check for master operation in progress
2560
        set_io  REG_MASTER_STATUS
2561
        in      ax, dx
2562
 
2563
        test    ah, 0x80
2564
        jnz     .finish
2565
 
2566
  .read_frame:
2567
; program buffer address to read in
2568
        push    ecx
2569
        stdcall KernelAlloc, MAX_ETH_FRAME_SIZE
2570
        pop     ecx
2571
        test    eax, eax
2572
        jz      .finish
2573
 
2574
        push    .discard_frame
2575
        push    ecx
2576
        push    eax
2577
;        zero_to_dma eax
2578
        set_io  REG_MASTER_ADDRESS
2579
        out     dx, eax
2580
 
2581
; program frame length
2582
        set_io  REG_MASTER_LEN
2583
        mov     ax, 1560
2584
        out     dx, ax
2585
 
2586
; start DMA Up
2587
        set_io  REG_COMMAND
2588
        mov     ax, (10100b shl 11) ; StartDMAUp
2589
        out     dx, ax
2590
 
2591
; check for master operation in progress
2592
        set_io  REG_MASTER_STATUS   ; TODO: use timeout and reset after timeout expired
2593
  .dma_loop:
2594
        in      ax, dx
2595
        test    ah, 0x80
2596
        jnz     .dma_loop
2597
 
2598
; registrate the received packet to kernel
2599
        jmp     Eth_input
2600
 
2601
; discard the top frame received
2602
  .discard_frame:
2603
        set_io  0
2604
        set_io  REG_COMMAND
2605
        mov     ax, (01000b shl 11)
2606
        out     dx, ax
2607
 
2608
  .finish:
2609
 
2610
 
2611
.noRX:
2612
 
2613
        test    ax, DMADone
2614
        jz      .noDMA
2615
 
2616
        push    ax
2617
 
2618
        set_io  0
2619
        set_io  12
2620
        in      ax, dx
2621
        test    ax, 0x1000
2622
        jz      .nodmaclear
2623
 
2624
        mov     ax, 0x1000
2625
        out     dx, ax
2626
 
2627
  .nodmaclear:
2628
 
2629
        pop     ax
2630
 
2631
        DEBUGF  1, "DMA Done!\n", cx
2632
 
2633
 
2634
 
2635
.noDMA:
2636
 
2637
 
2638
 
2639
.ACK:
2640
        set_io  0
2641
        set_io  REG_COMMAND
2642
        mov     ax, AckIntr + IntReq + IntLatch
2643
        out     dx, ax
2644
 
2645
        pop     edi esi ebx
2646
 
2647
        ret
2648
 
2649
 
2650
 
2651
 
2652
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2653
;;                             ;;
2654
;; Boomerang Interrupt handler ;;
2655
;;                             ;;
2656
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2657
 
2658
align 4
2659
int_boomerang:
2660
 
2661
        push    ebx esi edi
2662
 
3880 hidnplayr 2663
        DEBUGF  1,"INT\n"
3545 hidnplayr 2664
 
2665
; find pointer of device wich made IRQ occur
2666
 
2667
        mov     ecx, [BOOMERANG_DEVICES]
2668
        test    ecx, ecx
2669
        jz      .nothing
2670
        mov     esi, BOOMERANG_LIST
2671
  .nextdevice:
2672
        mov     ebx, [esi]
2673
 
2674
        set_io  0
2675
        set_io  REG_INT_STATUS
2676
        in      ax, dx
2677
        test    ax, ax
2678
        jnz     .got_it
2679
  .continue:
2680
        add     esi, 4
2681
        dec     ecx
2682
        jnz     .nextdevice
2683
  .nothing:
2684
        pop     edi esi ebx
2685
        xor     eax, eax
2686
 
2687
        ret
2688
 
2689
  .got_it:
2690
 
2691
        DEBUGF  1,"Device: %x Status: %x ", ebx, ax
2692
        push    ax
2693
 
2694
; disable all INTS
2695
 
2696
        set_io  REG_COMMAND
2697
        mov     ax, SetIntrEnb
2698
        out     dx, ax
2699
 
2700
;--------------------------------------------------------------------------
2701
        test    word[esp], UpComplete
2702
        jz      .noRX
2703
 
2704
        push    ebx
2705
 
2706
  .receive:
2707
        DEBUGF  1,"UpComplete\n"
2708
 
2709
; check if packet is uploaded
2710
        mov     esi, [device.curr_upd]
2711
        test    byte [esi+upd.pkt_status+1], 0x80 ; upPktComplete
2712
        jz      .finish
2713
        DEBUGF  1, "Current upd: %x\n", esi
2714
; packet is uploaded check for any error
2715
  .check_error:
2716
        test    byte [esi+upd.pkt_status+1], 0x40 ; upError
2717
        jz      .copy_packet_length
2718
        DEBUGF  1,"Error in packet\n"
2719
        and     [esi+upd.pkt_status], 0           ; mark packet as read
2720
        jmp     .finish
2721
  .copy_packet_length:
2722
        mov     ecx, [esi+upd.pkt_status]
2723
        and     ecx, 0x1fff
2724
 
2725
;        cmp     ecx, MAX_ETH_PKT_SIZE
2726
;        jbe     .copy_packet
2727
;        and     [esi+upd.pkt_status], 0
2728
;        jmp     .finish
2729
;  .copy_packet:
2730
 
2731
        DEBUGF  1, "Received %u bytes in buffer %x\n", ecx, [esi+upd.realaddr]:8
2732
 
2733
        push    dword .loop ;.finish
2734
        push    ecx
2735
        push    [esi+upd.realaddr]
2736
 
2737
; update statistics
2738
        inc     [device.packets_rx]
2739
        add     dword [device.bytes_rx], ecx
2740
        adc     dword [device.bytes_rx + 4], 0
2741
 
2742
; update UPD (Alloc new buffer for next packet)
2743
        stdcall KernelAlloc, MAX_ETH_FRAME_SIZE
2744
        mov     [esi + upd.realaddr], eax
2745
        GetRealAddr
2746
        mov     [esi + upd.frag_addr], eax
2747
        and     [esi + upd.pkt_status], 0
2748
        mov     [esi + upd.frag_len], MAX_ETH_FRAME_SIZE or (1 shl 31)
2749
 
2750
; Update UPD pointer
2751
        add     esi, upd.size
2752
        lea     ecx, [device.upd_buffer+(NUM_RX_DESC)*upd.size]
2753
        cmp     esi, ecx
2754
        jb      @f
2755
        lea     esi, [device.upd_buffer]
2756
       @@:
2757
        mov     [device.curr_upd], esi
2758
        DEBUGF  1, "Next upd: %x\n", esi
2759
 
2760
        jmp     Eth_input
2761
  .loop:
2762
 
2763
        mov     ebx, [esp]
2764
        jmp     .receive
2765
 
2766
  .finish:
2767
        pop     ebx
2768
 
2769
; check if the NIC is in the upStall state
2770
        set_io  0
2771
        set_io  REG_UP_PKT_STATUS
2772
        in      eax, dx
2773
        test    ah, 0x20             ; UpStalled
2774
        jz      .noUpUnStall
2775
 
2776
        DEBUGF  1, "upUnStalling\n"
2777
; issue upUnStall command
2778
        set_io  REG_COMMAND
2779
        mov     ax, ((11b shl 12)+1) ; upUnStall
2780
        out     dx, ax
2781
 
2782
        ;;;; FIXME: make upunstall work
2783
 
2784
  .noUpUnStall:
2785
.noRX:
2786
        test    word[esp], DownComplete
2787
        jz      .noTX
2788
        DEBUGF  1, "Downcomplete!\n"
2789
 
2790
        mov     ecx, NUM_TX_DESC
2791
        lea     esi, [device.dpd_buffer]
2792
  .txloop:
2793
        test    [esi+dpd.frame_start_hdr], 1 shl 31
2794
        jz      .maybenext
2795
 
2796
        and     [esi+dpd.frame_start_hdr], 0
2797
        push    ecx
2798
        stdcall KernelFree, [esi+dpd.realaddr]
2799
        pop     ecx
2800
 
2801
  .maybenext:
2802
        add     esi, dpd.size
2803
        dec     ecx
2804
        jnz     .txloop
2805
 
2806
.noTX:
2807
        pop     ax
2808
 
2809
        set_io  0
2810
        set_io  REG_COMMAND
2811
        or      ax, AckIntr
2812
        out     dx, ax
2813
 
2814
        set_io  REG_INT_STATUS
2815
        in      ax, dx
2816
        test    ax, S_5_INTS
2817
        jnz     .got_it
2818
 
2819
;re-enable ints
2820
        set_io  REG_COMMAND
2821
        mov     ax, SetIntrEnb + S_5_INTS
2822
        out     dx, ax
2823
 
2824
        pop     edi esi ebx
2825
 
2826
        ret
2827
 
2828
 
2829
 
2830
 
2831
; End of code
2832
align 4                                         ; Place all initialised data here
2833
 
2834
macro strtbl name, [string]
2835
{
2836
common
2837
        label name dword
2838
forward
2839
        local label
2840
        dd label
2841
forward
2842
        label db string, 0
2843
}
2844
 
2845
VORTEX_DEVICES       dd 0
2846
BOOMERANG_DEVICES    dd 0
2847
version              dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
2848
my_service           db '3C59X',0                    ; max 16 chars include zero
2849
 
2850
 
2851
strtbl link_str, \
2852
        "No valid link type detected", \
2853
        "10BASE-T half duplex", \
2854
        "10BASE-T full-duplex", \
2855
        "100BASE-TX half duplex", \
2856
        "100BASE-TX full duplex", \
2857
        "100BASE-T4", \
2858
        "100BASE-FX", \
2859
        "10Mbps AUI", \
2860
        "10Mbps COAX (BNC)", \
2861
        "miiDevice - not supported"
2862
 
2863
strtbl hw_str, \
2864
        "3c590 Vortex 10Mbps", \
2865
        "3c592 EISA 10Mbps Demon/Vortex", \
2866
        "3c597 EISA Fast Demon/Vortex", \
2867
        "3c595 Vortex 100baseTx", \
2868
        "3c595 Vortex 100baseT4", \
2869
        "3c595 Vortex 100base-MII", \
2870
        "3c900 Boomerang 10baseT", \
2871
        "3c900 Boomerang 10Mbps Combo", \
2872
        "3c900 Cyclone 10Mbps TPO", \
2873
        "3c900 Cyclone 10Mbps Combo", \
2874
        "3c900 Cyclone 10Mbps TPC", \
2875
        "3c900B-FL Cyclone 10base-FL", \
2876
        "3c905 Boomerang 100baseTx", \
2877
        "3c905 Boomerang 100baseT4", \
2878
        "3c905B Cyclone 100baseTx", \
2879
        "3c905B Cyclone 10/100/BNC", \
2880
        "3c905B-FX Cyclone 100baseFx", \
2881
        "3c905C Tornado", \
2882
        "3c980 Cyclone", \
2883
        "3c982 Dual Port Server Cyclone", \
2884
        "3cSOHO100-TX Hurricane", \
2885
        "3c555 Laptop Hurricane", \
2886
        "3c556 Laptop Tornado", \
2887
        "3c556B Laptop Hurricane", \
2888
        "3c575 [Megahertz] 10/100 LAN CardBus", \
2889
        "3c575 Boomerang CardBus", \
2890
        "3CCFE575BT Cyclone CardBus", \
2891
        "3CCFE575CT Tornado CardBus", \
2892
        "3CCFE656 Cyclone CardBus", \
2893
        "3CCFEM656B Cyclone+Winmodem CardBus", \
2894
        "3CXFEM656C Tornado+Winmodem CardBus", \
2895
        "3c450 HomePNA Tornado", \
2896
        "3c920 Tornado", \
2897
        "3c982 Hydra Dual Port A", \
2898
        "3c982 Hydra Dual Port B", \
2899
        "3c905B-T4", \
2900
        "3c920B-EMB-WNM Tornado"
2901
 
2902
 
2903
 
2904
align 4
2905
hw_versions:
2906
dw 0x5900, IS_VORTEX                                                                                                            ; 3c590 Vortex 10Mbps
2907
dw 0x5920, IS_VORTEX                                                                                                            ; 3c592 EISA 10Mbps Demon/Vortex
2908
dw 0x5970, IS_VORTEX                                                                                                            ; 3c597 EISA Fast Demon/Vortex
2909
dw 0x5950, IS_VORTEX                                                                                                            ; 3c595 Vortex 100baseTx
2910
dw 0x5951, IS_VORTEX                                                                                                            ; 3c595 Vortex 100baseT4
2911
dw 0x5952, IS_VORTEX                                                                                                            ; 3c595 Vortex 100base-MII
2912
dw 0x9000, IS_BOOMERANG                                                                                                         ; 3c900 Boomerang 10baseT
2913
dw 0x9001, IS_BOOMERANG                                                                                                         ; 3c900 Boomerang 10Mbps Combo
2914
dw 0x9004, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM                                                                                 ; 3c900 Cyclone 10Mbps TPO
2915
dw 0x9005, IS_CYCLONE or HAS_HWCKSM                                                                                             ; 3c900 Cyclone 10Mbps Combo
2916
dw 0x9006, IS_CYCLONE or HAS_HWCKSM                                                                                             ; 3c900 Cyclone 10Mbps TPC
2917
dw 0x900A, IS_CYCLONE or HAS_HWCKSM                                                                                             ; 3c900B-FL Cyclone 10base-FL
2918
dw 0x9050, IS_BOOMERANG or HAS_MII                                                                                              ; 3c905 Boomerang 100baseTx
2919
dw 0x9051, IS_BOOMERANG or HAS_MII                                                                                              ; 3c905 Boomerang 100baseT4
2920
dw 0x9055, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM or EXTRA_PREAMBLE                                                               ; 3c905B Cyclone 100baseTx
2921
dw 0x9058, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM                                                                                 ; 3c905B Cyclone 10/100/BNC
2922
dw 0x905A, IS_CYCLONE or HAS_HWCKSM                                                                                             ; 3c905B-FX Cyclone 100baseFx
2923
dw 0x9200, IS_TORNADO or HAS_NWAY or HAS_HWCKSM                                                                                 ; 3c905C Tornado
2924
dw 0x9800, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM                                                                                 ; 3c980 Cyclone
2925
dw 0x9805, IS_TORNADO or HAS_NWAY or HAS_HWCKSM                                                                                 ; 3c982 Dual Port Server Cyclone
2926
dw 0x7646, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM                                                                                 ; 3cSOHO100-TX Hurricane
2927
dw 0x5055, IS_CYCLONE or EEPROM_8BIT or HAS_HWCKSM                                                                              ; 3c555 Laptop Hurricane
2928
dw 0x6055, IS_TORNADO or HAS_NWAY or EEPROM_8BIT or HAS_CB_FNS or INVERT_MII_PWR or HAS_HWCKSM                                  ; 3c556 Laptop Tornado
2929
dw 0x6056, IS_TORNADO or HAS_NWAY or EEPROM_OFFSET or HAS_CB_FNS or INVERT_MII_PWR or HAS_HWCKSM                                ; 3c556B Laptop Hurricane
2930
dw 0x5b57, IS_BOOMERANG or HAS_MII or EEPROM_8BIT                                                                               ; 3c575 [Megahertz] 10/100 LAN CardBus
2931
dw 0x5057, IS_BOOMERANG or HAS_MII or EEPROM_8BIT                                                                               ; 3c575 Boomerang CardBus
2932
dw 0x5157, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_LED_PWR or HAS_HWCKSM                                  ; 3CCFE575BT Cyclone CardBus
2933
dw 0x5257, IS_TORNADO or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR or MAX_COLLISION_RESET or HAS_HWCKSM           ; 3CCFE575CT Tornado CardBus
2934
dw 0x6560, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR or INVERT_LED_PWR or HAS_HWCKSM                ; 3CCFE656 Cyclone CardBus
2935
dw 0x6562, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR or INVERT_LED_PWR or HAS_HWCKSM                ; 3CCFEM656B Cyclone+Winmodem CardBus
2936
dw 0x6564, IS_TORNADO or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR or MAX_COLLISION_RESET or HAS_HWCKSM           ; 3CXFEM656C Tornado+Winmodem CardBus
2937
dw 0x4500, IS_TORNADO or HAS_NWAY or HAS_HWCKSM                                                                                 ; 3c450 HomePNA Tornado
2938
dw 0x9201, IS_TORNADO or HAS_NWAY or HAS_HWCKSM                                                                                 ; 3c920 Tornado
2939
dw 0x1201, IS_TORNADO or HAS_HWCKSM or HAS_NWAY                                                                                 ; 3c982 Hydra Dual Port A
2940
dw 0x1202, IS_TORNADO or HAS_HWCKSM or HAS_NWAY                                                                                 ; 3c982 Hydra Dual Port B
2941
dw 0x9056, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM or EXTRA_PREAMBLE                                                               ; 3c905B-T4
2942
dw 0x9210, IS_TORNADO or HAS_NWAY or HAS_HWCKSM                                                                                 ; 3c920B-EMB-WNM Tornado
2943
HW_VERSIONS_SIZE = $ - hw_versions
2944
 
2945
include_debug_strings                           ; All data wich FDO uses will be included here
2946
 
2947
section '.data' data readable writable align 16 ; place all uninitialized data place here
2948
 
2949
VORTEX_LIST    rd MAX_DEVICES                   ; This list contains all pointers to device structures the driver is handling
2950
BOOMERANG_LIST rd MAX_DEVICES
2951
 
2952
 
2953
 
2954