Subversion Repositories Kolibri OS

Rev

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

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