Subversion Repositories Kolibri OS

Rev

Rev 9149 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
3545 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
9149 hidnplayr 3
;; Copyright (C) KolibriOS team 2004-2021. All rights reserved.    ;;
3545 hidnplayr 4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
6
;;  Realtek 8139 driver for KolibriOS                              ;;
7
;;                                                                 ;;
8
;;  based on RTL8139.asm driver for menuetos                       ;;
9
;;  and realtek8139.asm for SolarOS by Eugen Brasoveanu            ;;
10
;;                                                                 ;;
11
;;    Written by hidnplayr@kolibrios.org                           ;;
12
;;                                                                 ;;
13
;;          GNU GENERAL PUBLIC LICENSE                             ;;
14
;;             Version 2, June 1991                                ;;
15
;;                                                                 ;;
16
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
17
 
9161 hidnplayr 18
; TODO: test for RX-overrun
19
 
5045 hidnplayr 20
format PE DLL native
21
entry START
3545 hidnplayr 22
 
5045 hidnplayr 23
        CURRENT_API             = 0x0200
24
        COMPATIBLE_API          = 0x0100
25
        API_VERSION             = (COMPATIBLE_API shl 16) + CURRENT_API
3545 hidnplayr 26
 
9161 hidnplayr 27
; configureable area
28
 
3545 hidnplayr 29
        MAX_DEVICES             = 16
30
 
5045 hidnplayr 31
        RBLEN                   = 3     ; Receive buffer size: 0==8K 1==16k 2==32k 3==64k
3545 hidnplayr 32
 
5045 hidnplayr 33
        TXRR                    = 8     ; total retries = 16+(TXRR*16)
34
        TX_MXDMA                = 6     ; 0=16 1=32 2=64 3=128 4=256 5=512 6=1024 7=2048
35
        ERTXTH                  = 8     ; in unit of 32 bytes e.g:(8*32)=256
36
        RX_MXDMA                = 7     ; 0=16 1=32 2=64 3=128 4=256 5=512 6=1024 7=unlimited
37
        RXFTH                   = 7     ; 0=16 1=32 2=64 3=128 4=256 5=512 6=1024 7=no threshold
3857 hidnplayr 38
 
3545 hidnplayr 39
        __DEBUG__               = 1
5045 hidnplayr 40
        __DEBUG_LEVEL__         = 2     ; 1 = verbose, 2 = errors only
3545 hidnplayr 41
 
9161 hidnplayr 42
; end configureable area
43
 
5045 hidnplayr 44
section '.flat' readable writable executable
45
 
46
include '../proc32.inc'
4467 hidnplayr 47
include '../struct.inc'
48
include '../macros.inc'
3545 hidnplayr 49
include '../fdo.inc'
5074 hidnplayr 50
include '../netdrv.inc'
3545 hidnplayr 51
 
52
        REG_IDR0                = 0x00
53
        REG_MAR0                = 0x08 ; multicast filter register 0
54
        REG_MAR4                = 0x0c ; multicast filter register 4
55
        REG_TSD0                = 0x10 ; transmit status of descriptor
56
        REG_TSAD0               = 0x20 ; transmit start address of descriptor
57
        REG_RBSTART             = 0x30 ; RxBuffer start address
58
        REG_COMMAND             = 0x37 ; command register
59
        REG_CAPR                = 0x38 ; current address of packet read (word) R/W
60
        REG_IMR                 = 0x3c ; interrupt mask register
61
        REG_ISR                 = 0x3e ; interrupt status register
62
        REG_TXCONFIG            = 0x40 ; transmit configuration register
63
        REG_RXCONFIG            = 0x44 ; receive configuration register 0
64
        REG_MPC                 = 0x4c ; missed packet counter
65
        REG_9346CR              = 0x50 ; serial eeprom 93C46 command register
66
        REG_CONFIG1             = 0x52 ; configuration register 1
6227 hidnplayr 67
        REG_MSR                 = 0x58 ; Media Status register
3545 hidnplayr 68
        REG_CONFIG4             = 0x5a ; configuration register 4
69
        REG_HLTCLK              = 0x5b ; undocumented halt clock register
70
        REG_BMCR                = 0x62 ; basic mode control register
71
        REG_ANAR                = 0x66 ; auto negotiation advertisement register
72
        REG_9346CR_WE           = 11b shl 6
73
 
74
        BIT_RUNT                = 4 ; total packet length < 64 bytes
75
        BIT_LONG                = 3 ; total packet length > 4k
76
        BIT_CRC                 = 2 ; crc error occured
77
        BIT_FAE                 = 1 ; frame alignment error occured
78
        BIT_ROK                 = 0 ; received packet is ok
79
 
80
        BIT_RST                 = 4 ; reset bit
81
        BIT_RE                  = 3 ; receiver enabled
82
        BIT_TE                  = 2 ; transmitter enabled
83
        BUFE                    = 1 ; rx buffer is empty, no packet stored
84
 
85
        BIT_ISR_TOK             = 2 ; transmit ok
86
        BIT_ISR_RER             = 1 ; receive error interrupt
87
        BIT_ISR_ROK             = 0 ; receive ok
88
 
89
        BIT_TX_MXDMA            = 8 ; Max DMA burst size per Tx DMA burst
90
        BIT_TXRR                = 4 ; Tx Retry count 16+(TXRR*16)
91
 
92
        BIT_RXFTH               = 13 ; Rx fifo threshold
93
        BIT_RBLEN               = 11 ; Ring buffer length indicator
94
        BIT_RX_MXDMA            = 8 ; Max DMA burst size per Rx DMA burst
95
        BIT_NOWRAP              = 7 ; transfered data wrapping
96
        BIT_9356SEL             = 6 ; eeprom selector 9346/9356
97
        BIT_AER                 = 5 ; accept error packets
98
        BIT_AR                  = 4 ; accept runt packets
99
        BIT_AB                  = 3 ; accept broadcast packets
100
        BIT_AM                  = 2 ; accept multicast packets
101
        BIT_APM                 = 1 ; accept physical match packets
102
        BIT_AAP                 = 0 ; accept all packets
103
 
104
        BIT_93C46_EEM1          = 7 ; RTL8139 eeprom operating mode1
105
        BIT_93C46_EEM0          = 6 ; RTL8139 eeprom operating mode0
106
        BIT_93C46_EECS          = 3 ; chip select
107
        BIT_93C46_EESK          = 2 ; serial data clock
108
        BIT_93C46_EEDI          = 1 ; serial data input
109
        BIT_93C46_EEDO          = 0 ; serial data output
110
 
111
        BIT_LWACT               = 4 ; see REG_CONFIG1
112
        BIT_SLEEP               = 1 ; sleep bit at older chips
113
        BIT_PWRDWN              = 0 ; power down bit at older chips
114
        BIT_PMEn                = 0 ; power management enabled
115
 
116
        BIT_LWPTN               = 2 ; see REG_CONFIG4
117
 
118
        BIT_ERTXTH              = 16 ; early TX threshold
119
        BIT_TOK                 = 15 ; transmit ok
120
        BIT_OWN                 = 13 ; tx DMA operation is completed
121
 
122
        BIT_ANE                 = 12 ; auto negotiation enable
123
 
124
        BIT_TXFD                = 8 ; 100base-T full duplex
125
        BIT_TX                  = 7 ; 100base-T
126
        BIT_10FD                = 6 ; 10base-T full duplex
127
        BIT_10                  = 5 ; 10base-T
128
        BIT_SELECTOR            = 0 ; binary encoded selector CSMA/CD=00001
129
 
6229 hidnplayr 130
        BIT_IFG1                = 1 shl 25
131
        BIT_IFG0                = 1 shl 24
3545 hidnplayr 132
 
133
        RX_CONFIG               = (RBLEN shl BIT_RBLEN) or \
134
                                  (RX_MXDMA shl BIT_RX_MXDMA) or \
135
                                  (1 shl BIT_NOWRAP) or \
136
                                  (RXFTH shl BIT_RXFTH) or\
3857 hidnplayr 137
                                  (1 shl BIT_AB) or \                   ; Accept broadcast packets
138
                                  (1 shl BIT_APM) or \                  ; Accept physical match packets
139
                                  (1 shl BIT_AER) or \                  ; Accept error packets
140
                                  (1 shl BIT_AR) or \                   ; Accept Runt packets (smaller then 64 bytes)
141
                                  (1 shl BIT_AM)                        ; Accept multicast packets
3545 hidnplayr 142
 
3857 hidnplayr 143
        RX_BUFFER_SIZE          = (8192 shl RBLEN);+16+1500
144
        NUM_TX_DESC             = 4                                     ; not user selectable
3545 hidnplayr 145
 
146
        EE_93C46_REG_ETH_ID     = 7 ; MAC offset
147
        EE_93C46_READ_CMD       = (6 shl 6) ; 110b + 6bit address
148
        EE_93C56_READ_CMD       = (6 shl 8) ; 110b + 8bit address
149
        EE_93C46_CMD_LENGTH     = 9  ; start bit + cmd + 6bit address
150
        EE_93C56_CMD_LENGTH     = 11 ; start bit + cmd + 8bit ddress
151
 
6227 hidnplayr 152
; See chapter "5.7 Transmit Configuration Register" of RTL8139D(L).pdf
6711 hidnplayr 153
        VER_RTL8139             = 1000000b
154
        VER_RTL8139_K           = 1100000b
3545 hidnplayr 155
        VER_RTL8139A            = 1110000b
6711 hidnplayr 156
        VER_RTL8139A_G          = 1110010b
3545 hidnplayr 157
        VER_RTL8139B            = 1111000b
6711 hidnplayr 158
        VER_RTL8130             = 1111100b
3545 hidnplayr 159
        VER_RTL8139C            = 1110100b
160
        VER_RTL8100             = 1111010b
6711 hidnplayr 161
        VER_RTL8100_8139D       = 1110101b
6713 hidnplayr 162
        VER_RTL8139CP           = 1110110b
3545 hidnplayr 163
        VER_RTL8101             = 1110111b
164
 
6711 hidnplayr 165
        IDX_UNKNOWN             = 0
166
        IDX_RTL8139             = 1
167
        IDX_RTL8139_K           = 2
168
        IDX_RTL8139A            = 3
169
        IDX_RTL8139A_G          = 4
170
        IDX_RTL8139B            = 5
171
        IDX_RTL8130             = 6
172
        IDX_RTL8139C            = 7
173
        IDX_RTL8100             = 8
174
        IDX_RTL8100_8139D       = 9
6713 hidnplayr 175
        IDX_RTL8139CP           = 10
176
        IDX_RTL8101             = 11
3545 hidnplayr 177
 
6713 hidnplayr 178
        HW_VERSIONS             = 11
6711 hidnplayr 179
 
3545 hidnplayr 180
        ISR_SERR                = 1 shl 15
181
        ISR_TIMEOUT             = 1 shl 14
182
        ISR_LENCHG              = 1 shl 13
183
        ISR_FIFOOVW             = 1 shl 6
184
        ISR_PUN                 = 1 shl 5
185
        ISR_RXOVW               = 1 shl 4
186
        ISR_TER                 = 1 shl 3
187
        ISR_TOK                 = 1 shl 2
188
        ISR_RER                 = 1 shl 1
189
        ISR_ROK                 = 1 shl 0
190
 
191
        INTERRUPT_MASK          = ISR_ROK or \
3857 hidnplayr 192
                                  ISR_RER or \
193
                                  ISR_TOK or \
194
                                  ISR_TER or \
3545 hidnplayr 195
                                  ISR_RXOVW or \
196
                                  ISR_PUN or \
197
                                  ISR_FIFOOVW or \
198
                                  ISR_LENCHG or \
3857 hidnplayr 199
                                  ISR_TIMEOUT or \
200
                                  ISR_SERR
3545 hidnplayr 201
 
202
        TSR_OWN                 = 1 shl 13
203
        TSR_TUN                 = 1 shl 14
204
        TSR_TOK                 = 1 shl 15
205
 
206
        TSR_CDH                 = 1 shl 28
207
        TSR_OWC                 = 1 shl 29
208
        TSR_TABT                = 1 shl 30
209
        TSR_CRS                 = 1 shl 31
210
 
211
 
5045 hidnplayr 212
struct  device          ETH_DEVICE
3545 hidnplayr 213
 
5045 hidnplayr 214
        io_addr         dd ?
215
        pci_bus         dd ?
216
        pci_dev         dd ?
217
        irq_line        db ?
218
                        rb 3    ; align 4
3545 hidnplayr 219
 
5045 hidnplayr 220
        rx_buffer       dd ?
221
        rx_data_offset  dd ?
222
        curr_tx_desc    db ?
223
        hw_ver_id       db ?
224
                        rb 2    ; align 4
3545 hidnplayr 225
 
5045 hidnplayr 226
        TX_DESC         rd NUM_TX_DESC
3545 hidnplayr 227
 
5045 hidnplayr 228
ends
3545 hidnplayr 229
 
230
 
231
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
232
;;                        ;;
233
;; proc START             ;;
234
;;                        ;;
235
;; (standard driver proc) ;;
236
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
237
 
5045 hidnplayr 238
proc START c, reason:dword, cmdline:dword
3545 hidnplayr 239
 
5045 hidnplayr 240
        cmp     [reason], DRV_ENTRY
241
        jne     .fail
3545 hidnplayr 242
 
5045 hidnplayr 243
        DEBUGF  2,"Loading driver\n"
244
        invoke  RegService, my_service, service_proc
3545 hidnplayr 245
        ret
246
 
247
  .fail:
248
        xor     eax, eax
249
        ret
250
 
251
endp
252
 
253
 
254
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
255
;;                        ;;
256
;; proc SERVICE_PROC      ;;
257
;;                        ;;
258
;; (standard driver proc) ;;
259
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
260
 
261
proc service_proc stdcall, ioctl:dword
262
 
263
        mov     edx, [ioctl]
4470 hidnplayr 264
        mov     eax, [edx + IOCTL.io_code]
3545 hidnplayr 265
 
266
;------------------------------------------------------
267
 
268
        cmp     eax, 0 ;SRV_GETVERSION
269
        jne     @F
270
 
4470 hidnplayr 271
        cmp     [edx + IOCTL.out_size], 4
3545 hidnplayr 272
        jb      .fail
4470 hidnplayr 273
        mov     eax, [edx + IOCTL.output]
3545 hidnplayr 274
        mov     [eax], dword API_VERSION
275
 
276
        xor     eax, eax
277
        ret
278
 
279
;------------------------------------------------------
280
  @@:
281
        cmp     eax, 1 ;SRV_HOOK
282
        jne     .fail
283
 
4470 hidnplayr 284
        cmp     [edx + IOCTL.inp_size], 3               ; Data input must be at least 3 bytes
3545 hidnplayr 285
        jb      .fail
286
 
4470 hidnplayr 287
        mov     eax, [edx + IOCTL.input]
3545 hidnplayr 288
        cmp     byte [eax], 1                           ; 1 means device number and bus number (pci) are given
289
        jne     .fail                                   ; other types arent supported for this card yet
290
 
291
; check if the device is already listed
292
 
293
        mov     esi, device_list
294
        mov     ecx, [devices]
295
        test    ecx, ecx
296
        jz      .firstdevice
297
 
298
        mov     ax, [eax+1]                             ; get the pci bus and device numbers
299
  .nextdevice:
300
        mov     ebx, [esi]
5045 hidnplayr 301
        cmp     al, byte[ebx + device.pci_bus]
3545 hidnplayr 302
        jne     @f
5045 hidnplayr 303
        cmp     ah, byte[ebx + device.pci_dev]
3545 hidnplayr 304
        je      .find_devicenum                         ; Device is already loaded, let's find it's device number
305
       @@:
306
        add     esi, 4
307
        loop    .nextdevice
308
 
309
 
310
; This device doesnt have its own eth_device structure yet, lets create one
311
  .firstdevice:
312
        cmp     [devices], MAX_DEVICES                  ; First check if the driver can handle one more card
313
        jae     .fail
314
 
6711 hidnplayr 315
        allocate_and_clear ebx, sizeof.device, .fail    ; Allocate the buffer for device structure
3545 hidnplayr 316
 
317
; Fill in the direct call addresses into the struct
318
 
5045 hidnplayr 319
        mov     [ebx + device.reset], reset
320
        mov     [ebx + device.transmit], transmit
321
        mov     [ebx + device.unload], unload
322
        mov     [ebx + device.name], my_service
3545 hidnplayr 323
 
324
; save the pci bus and device numbers
325
 
4470 hidnplayr 326
        mov     eax, [edx + IOCTL.input]
3545 hidnplayr 327
        movzx   ecx, byte[eax+1]
5045 hidnplayr 328
        mov     [ebx + device.pci_bus], ecx
3545 hidnplayr 329
        movzx   ecx, byte[eax+2]
5045 hidnplayr 330
        mov     [ebx + device.pci_dev], ecx
3545 hidnplayr 331
 
332
; Now, it's time to find the base io addres of the PCI device
333
 
5045 hidnplayr 334
        stdcall PCI_find_io, [ebx + device.pci_bus], [ebx + device.pci_dev]
335
        mov     [ebx + device.io_addr], eax
3545 hidnplayr 336
 
337
; We've found the io address, find IRQ now
338
 
5045 hidnplayr 339
        invoke  PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.interrupt_line
340
        mov     [ebx + device.irq_line], al
3545 hidnplayr 341
 
6711 hidnplayr 342
        DEBUGF  1, "Hooking into device, devfn:%x, bus:%x, irq:%x, I/O addr:%x\n",\
343
        [ebx + device.pci_dev]:2,[ebx + device.pci_bus]:2,[ebx + device.irq_line]:2,[ebx + device.io_addr]:4
3545 hidnplayr 344
 
345
; Allocate the receive buffer
346
 
5045 hidnplayr 347
        invoke  CreateRingBuffer, dword (RX_BUFFER_SIZE), dword PG_SW
3545 hidnplayr 348
        test    eax, eax
349
        jz      .err
5045 hidnplayr 350
        mov     [ebx + device.rx_buffer], eax
3545 hidnplayr 351
 
352
; Ok, the eth_device structure is ready, let's probe the device
353
 
354
        call    probe                                                   ; this function will output in eax
355
        test    eax, eax
356
        jnz     .err                                                    ; If an error occured, exit
357
 
358
        mov     eax, [devices]                                          ; Add the device structure to our device list
359
        mov     [device_list+4*eax], ebx                                ; (IRQ handler uses this list to find device)
360
        inc     [devices]                                               ;
361
 
3685 hidnplayr 362
        call    reset
363
        test    eax, eax
364
        jnz     .destroy
365
 
5045 hidnplayr 366
        mov     [ebx + device.type], NET_TYPE_ETH
367
        invoke  NetRegDev
3545 hidnplayr 368
 
369
        cmp     eax, -1
370
        je      .destroy
371
 
372
        ret
373
 
374
; If the device was already loaded, find the device number and return it in eax
375
 
376
  .find_devicenum:
3856 hidnplayr 377
        DEBUGF  1, "Trying to find device number of already registered device\n"
5045 hidnplayr 378
        invoke  NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
3545 hidnplayr 379
                                                                        ; into a device number in edi
380
        mov     eax, edi                                                ; Application wants it in eax instead
3856 hidnplayr 381
        DEBUGF  1, "Kernel says: %u\n", eax
3545 hidnplayr 382
        ret
383
 
384
; If an error occured, remove all allocated data and exit (returning -1 in eax)
385
  .destroy:
6682 hidnplayr 386
        ; unregister device from device_list
387
        mov     eax, [devices]
388
        mov     dword[device_list-4+4*eax], 0
389
        dec     [devices]
3545 hidnplayr 390
 
391
  .err:
6711 hidnplayr 392
        DEBUGF  2, "Fatal error occured, aborting\n"
5045 hidnplayr 393
        invoke  KernelFree, [ebx + device.rx_buffer]
394
        invoke  KernelFree, ebx
3545 hidnplayr 395
 
396
  .fail:
397
        or      eax, -1
398
        ret
399
 
400
;------------------------------------------------------
401
endp
402
 
403
 
404
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
405
;;                                                                        ;;
406
;;        Actual Hardware dependent code starts here                      ;;
407
;;                                                                        ;;
408
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
409
 
410
align 4
411
unload:
412
        ; TODO: (in this particular order)
413
        ;
414
        ; - Stop the device
415
        ; - Detach int handler
416
        ; - Remove device from local list (RTL8139_LIST)
417
        ; - call unregister function in kernel
418
        ; - Remove all allocated structures and buffers the card used
419
 
420
        or      eax, -1
5522 hidnplayr 421
        ret
3545 hidnplayr 422
 
423
 
424
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
425
;;
426
;;  probe: enables the device (if it really is RTL8139)
427
;;
428
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
429
 
430
align 4
431
probe:
3856 hidnplayr 432
        DEBUGF  1, "Probing\n"
3545 hidnplayr 433
 
5045 hidnplayr 434
; Make the device a bus master
435
        invoke  PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command
6711 hidnplayr 436
        or      al, PCI_CMD_MASTER or PCI_CMD_PIO
5045 hidnplayr 437
        invoke  PciWrite32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command, eax
3545 hidnplayr 438
 
6711 hidnplayr 439
; wake up old chips
440
        set_io  [ebx + device.io_addr], 0
441
        set_io  [ebx + device.io_addr], REG_HLTCLK
442
        mov     al, 'R'         ; run the clock
443
        out     dx, al
444
 
3545 hidnplayr 445
; get chip version
6713 hidnplayr 446
        set_io  [ebx + device.io_addr], 0
447
        set_io  [ebx + device.io_addr], REG_TXCONFIG + 2
448
        in      ax, dx
3545 hidnplayr 449
        shr     ah, 2
450
        shr     ax, 6
6711 hidnplayr 451
        and     al, 0x7f
452
        DEBUGF  1, "Chip version: %x\n", eax:2
3545 hidnplayr 453
 
454
; now find it in our array
6711 hidnplayr 455
        mov     ecx, HW_VERSIONS
456
  @@:
3545 hidnplayr 457
        cmp     al, [hw_ver_array + ecx]
6711 hidnplayr 458
        je      @f
3545 hidnplayr 459
        dec     ecx
6711 hidnplayr 460
        jnz     @r
461
  @@:
5045 hidnplayr 462
        mov     [ebx + device.hw_ver_id], cl
6711 hidnplayr 463
        mov     ecx, [hw_ver_names+ecx*4]
5045 hidnplayr 464
        mov     [ebx + device.name], ecx
3856 hidnplayr 465
        DEBUGF  1, "Chip version: %s\n", ecx
3545 hidnplayr 466
 
6711 hidnplayr 467
        cmp     [ebx + device.hw_ver_id], IDX_RTL8139B
468
        jae     .new_chip
3545 hidnplayr 469
 
6711 hidnplayr 470
; wake up older chips
471
  .old_chip:
472
        DEBUGF  1, "Wake up chip old style\n"
5045 hidnplayr 473
        set_io  [ebx + device.io_addr], REG_CONFIG1
3545 hidnplayr 474
        in      al, dx
475
        and     al, not ((1 shl BIT_SLEEP) or (1 shl BIT_PWRDWN))
476
        out     dx, al
6711 hidnplayr 477
        jmp     .done
3545 hidnplayr 478
 
479
; set LWAKE pin to active high (default value).
480
; it is for Wake-On-LAN functionality of some motherboards.
481
; this signal is used to inform the motherboard to execute a wake-up process.
482
; only at newer chips.
483
  .new_chip:
6711 hidnplayr 484
        DEBUGF  1, "Wake up chip new style\n"
485
; unlock config and BMCR registers
486
        set_io  [ebx + device.io_addr], 0
487
        set_io  [ebx + device.io_addr], REG_9346CR
488
        mov     al, (1 shl BIT_93C46_EEM1) or (1 shl BIT_93C46_EEM0)
489
        out     dx, al
490
 
491
;
492
        set_io  [ebx + device.io_addr], REG_CONFIG1
493
        in      al, dx
3545 hidnplayr 494
        or      al, (1 shl BIT_PMEn)
495
        and     al, not (1 shl BIT_LWACT)
496
        out     dx, al
497
 
6711 hidnplayr 498
;
5045 hidnplayr 499
        set_io  [ebx + device.io_addr], REG_CONFIG4
3545 hidnplayr 500
        in      al, dx
501
        and     al, not (1 shl BIT_LWPTN)
502
        out     dx, al
503
 
504
; lock config and BMCR registers
505
        xor     al, al
5045 hidnplayr 506
        set_io  [ebx + device.io_addr], REG_9346CR
3545 hidnplayr 507
        out     dx, al
6711 hidnplayr 508
 
509
  .done:
3856 hidnplayr 510
        DEBUGF  1, "probing done!\n"
3685 hidnplayr 511
        xor     eax, eax
512
        ret
513
 
514
 
3545 hidnplayr 515
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
516
;;
517
;;   reset: Set up all registers and descriptors, clear some values
518
;;
519
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
520
 
521
reset:
3856 hidnplayr 522
        DEBUGF  1, "Reset\n"
3545 hidnplayr 523
 
524
; reset chip
525
        DEBUGF  1, "Resetting chip\n"
5045 hidnplayr 526
        set_io  [ebx + device.io_addr], 0
527
        set_io  [ebx + device.io_addr], REG_COMMAND
3545 hidnplayr 528
        mov     al, 1 shl BIT_RST
529
        out     dx, al
530
        mov     cx, 1000                ; wait no longer for the reset
6711 hidnplayr 531
  @@:
3545 hidnplayr 532
        in      al, dx
533
        test    al, 1 shl BIT_RST
6711 hidnplayr 534
        jz      @f                      ; RST remains 1 during reset
3545 hidnplayr 535
        dec     cx
6711 hidnplayr 536
        jnz     @r
3856 hidnplayr 537
        DEBUGF  2, "Reset timeout!\n"
6682 hidnplayr 538
        or      eax, -1
539
        ret
6711 hidnplayr 540
  @@:
3545 hidnplayr 541
 
3858 hidnplayr 542
; Read MAC address
543
        call    read_mac
544
 
6682 hidnplayr 545
; attach int handler
546
        movzx   eax, [ebx + device.irq_line]
547
        DEBUGF  1, "Attaching int handler to irq %x\n", eax:1
548
        invoke  AttachIntHandler, eax, int_handler, ebx
549
        test    eax, eax
550
        jnz     @f
551
        DEBUGF  2, "Could not attach int handler!\n"
552
        or      eax, -1
553
        ret
6711 hidnplayr 554
  @@:
6682 hidnplayr 555
 
3545 hidnplayr 556
; unlock config and BMCR registers
5045 hidnplayr 557
        set_io  [ebx + device.io_addr], 0
558
        set_io  [ebx + device.io_addr], REG_9346CR
3545 hidnplayr 559
        mov     al, (1 shl BIT_93C46_EEM1) or (1 shl BIT_93C46_EEM0)
560
        out     dx, al
561
 
562
; initialize multicast registers (no filtering)
563
        mov     eax, 0xffffffff
5045 hidnplayr 564
        set_io  [ebx + device.io_addr], REG_MAR0
3545 hidnplayr 565
        out     dx, eax
5045 hidnplayr 566
        set_io  [ebx + device.io_addr], REG_MAR4
3545 hidnplayr 567
        out     dx, eax
568
 
569
; enable Rx/Tx
570
        mov     al, (1 shl BIT_RE) or (1 shl BIT_TE)
5045 hidnplayr 571
        set_io  [ebx + device.io_addr], REG_COMMAND
3545 hidnplayr 572
        out     dx, al
573
 
574
; Rxbuffer size, unlimited dma burst, no wrapping, no rx threshold
575
; accept broadcast packets, accept physical match packets
3858 hidnplayr 576
        mov     eax, RX_CONFIG
5045 hidnplayr 577
        set_io  [ebx + device.io_addr], REG_RXCONFIG
3858 hidnplayr 578
        out     dx, eax
3545 hidnplayr 579
 
580
; 1024 bytes DMA burst, total retries = 16 + 8 * 16 = 144
581
        mov     eax, (TX_MXDMA shl BIT_TX_MXDMA) or (TXRR shl BIT_TXRR) or BIT_IFG1 or BIT_IFG0
5045 hidnplayr 582
        set_io  [ebx + device.io_addr], REG_TXCONFIG
3545 hidnplayr 583
        out     dx, eax
584
 
585
; enable auto negotiation
5045 hidnplayr 586
        set_io  [ebx + device.io_addr], REG_BMCR
3545 hidnplayr 587
        in      ax, dx
588
        or      ax, (1 shl BIT_ANE)
589
        out     dx, ax
590
 
591
; set auto negotiation advertisement
5045 hidnplayr 592
        set_io  [ebx + device.io_addr], REG_ANAR
3545 hidnplayr 593
        in      ax, dx
594
        or      ax, (1 shl BIT_SELECTOR) or (1 shl BIT_10) or (1 shl BIT_10FD) or (1 shl BIT_TX) or (1 shl BIT_TXFD)
595
        out     dx, ax
596
 
597
; lock config and BMCR registers
598
        xor     eax, eax
5045 hidnplayr 599
        set_io  [ebx + device.io_addr], REG_9346CR
3545 hidnplayr 600
        out     dx, al
601
 
602
; init RX/TX pointers
5045 hidnplayr 603
        mov     [ebx + device.rx_data_offset], eax
604
        mov     [ebx + device.curr_tx_desc], al
605
;        set_io  [ebx + device.io_addr], REG_CAPR
3545 hidnplayr 606
;        out     dx, ax
607
 
608
; clear packet/byte counters
5045 hidnplayr 609
        lea     edi, [ebx + device.bytes_tx]
3545 hidnplayr 610
        mov     ecx, 6
611
        rep     stosd
612
 
613
; clear missing packet counter
5045 hidnplayr 614
        set_io  [ebx + device.io_addr], REG_MPC
3545 hidnplayr 615
        out     dx, eax
616
 
617
; set RxBuffer address, init RX buffer offset
5045 hidnplayr 618
        mov     eax, [ebx + device.rx_buffer]
3545 hidnplayr 619
        mov     dword[eax], 0                   ; clear receive flags for first packet (really needed??)
3685 hidnplayr 620
        DEBUGF  1, "RX buffer virtual addr=0x%x\n", eax
5045 hidnplayr 621
        invoke  GetPhysAddr
3857 hidnplayr 622
        DEBUGF  1, "RX buffer physical addr=0x%x\n", eax
5045 hidnplayr 623
        set_io  [ebx + device.io_addr], REG_RBSTART
3545 hidnplayr 624
        out     dx, eax
625
 
626
; enable interrupts
5045 hidnplayr 627
        set_io  [ebx + device.io_addr], 0
628
        set_io  [ebx + device.io_addr], REG_IMR
3545 hidnplayr 629
        mov     ax, INTERRUPT_MASK
630
        out     dx, ax
631
 
632
; Set the mtu, kernel will be able to send now
5045 hidnplayr 633
        mov     [ebx + device.mtu], 1514
3545 hidnplayr 634
 
6711 hidnplayr 635
; Detect current link status
6227 hidnplayr 636
        call    link
3545 hidnplayr 637
 
638
; Indicate that we have successfully reset the card
639
        xor     eax, eax
640
        ret
641
 
642
 
643
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
644
;;                                         ;;
645
;; Transmit                                ;;
646
;;                                         ;;
5522 hidnplayr 647
;; In: pointer to device structure in ebx  ;;
9161 hidnplayr 648
;; Out: eax = 0 on success                 ;;
3545 hidnplayr 649
;;                                         ;;
650
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9161 hidnplayr 651
align 16
5522 hidnplayr 652
proc transmit stdcall bufferptr
5045 hidnplayr 653
 
9161 hidnplayr 654
        spin_lock_irqsave
5045 hidnplayr 655
 
5522 hidnplayr 656
        mov     esi, [bufferptr]
657
        DEBUGF  1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [esi + NET_BUFF.length]
658
        lea     eax, [esi + NET_BUFF.data]
5045 hidnplayr 659
        DEBUGF  1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
3545 hidnplayr 660
        [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
661
        [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
662
        [eax+13]:2,[eax+12]:2
663
 
5522 hidnplayr 664
        cmp     [esi + NET_BUFF.length], 1514
9161 hidnplayr 665
        ja      .error
5522 hidnplayr 666
        cmp     [esi + NET_BUFF.length], 60
9161 hidnplayr 667
        jb      .error
3545 hidnplayr 668
 
669
; check if we own the current discriptor
5045 hidnplayr 670
        set_io  [ebx + device.io_addr], 0
671
        set_io  [ebx + device.io_addr], REG_TSD0
672
        movzx   ecx, [ebx + device.curr_tx_desc]
3545 hidnplayr 673
        shl     ecx, 2
674
        add     edx, ecx
675
        in      eax, dx
676
        test    eax, (1 shl BIT_OWN)
9161 hidnplayr 677
        jz      .overrun
3545 hidnplayr 678
 
679
; Set the buffer address
5045 hidnplayr 680
        set_io  [ebx + device.io_addr], REG_TSAD0
5522 hidnplayr 681
        mov     [ebx + device.TX_DESC+ecx], esi
682
        mov     eax, esi
683
        add     eax, [eax + NET_BUFF.offset]
5045 hidnplayr 684
        invoke  GetPhysAddr
3545 hidnplayr 685
        out     dx, eax
686
 
687
; And the size of the buffer
5045 hidnplayr 688
        set_io  [ebx + device.io_addr], REG_TSD0
5522 hidnplayr 689
        mov     eax, [esi + NET_BUFF.length]
3545 hidnplayr 690
        or      eax, (ERTXTH shl BIT_ERTXTH)    ; Early threshold
691
        out     dx, eax
692
 
5522 hidnplayr 693
; get next descriptor
694
        inc     [ebx + device.curr_tx_desc]
695
        and     [ebx + device.curr_tx_desc], NUM_TX_DESC-1
696
 
697
; Update stats
698
        inc     [ebx + device.packets_tx]
9161 hidnplayr 699
        mov     eax, [esi + NET_BUFF.length]
700
        add     dword[ebx + device.bytes_tx], eax
701
        adc     dword[ebx + device.bytes_tx + 4], 0
5522 hidnplayr 702
 
9161 hidnplayr 703
        spin_unlock_irqrestore
3545 hidnplayr 704
        xor     eax, eax
5045 hidnplayr 705
        ret
3545 hidnplayr 706
 
9161 hidnplayr 707
  .error:
708
        DEBUGF  2, "TX packet error\n"
709
        inc     [ebx + device.packets_tx_err]
710
        invoke  NetFree, [bufferptr]
3545 hidnplayr 711
 
9161 hidnplayr 712
        spin_unlock_irqrestore
713
        or      eax, -1
714
        ret
3545 hidnplayr 715
 
9161 hidnplayr 716
  .overrun:
717
        DEBUGF  2, "TX overrun\n"
718
        inc     [ebx + device.packets_tx_ovr]
719
        invoke  NetFree, [bufferptr]
3545 hidnplayr 720
 
9161 hidnplayr 721
        spin_unlock_irqrestore
3545 hidnplayr 722
        or      eax, -1
5045 hidnplayr 723
        ret
3545 hidnplayr 724
 
5045 hidnplayr 725
endp
3545 hidnplayr 726
 
727
 
728
 
729
 
5045 hidnplayr 730
 
3545 hidnplayr 731
;;;;;;;;;;;;;;;;;;;;;;;
732
;;                   ;;
733
;; Interrupt handler ;;
734
;;                   ;;
735
;;;;;;;;;;;;;;;;;;;;;;;
9161 hidnplayr 736
align 16
3545 hidnplayr 737
int_handler:
738
 
739
        push    ebx esi edi
740
 
9161 hidnplayr 741
        mov     ebx, [esp+4*4]
742
        DEBUGF  1,"INT for 0x%x\n", ebx
3545 hidnplayr 743
 
9161 hidnplayr 744
; TODO? if we are paranoid, we can check that the value from ebx is present in the current device_list
3545 hidnplayr 745
 
5045 hidnplayr 746
        set_io  [ebx + device.io_addr], 0
747
        set_io  [ebx + device.io_addr], REG_ISR
3545 hidnplayr 748
        in      ax, dx                          ; Get interrupt status
749
        test    ax, ax
9161 hidnplayr 750
        jz      .nothing
3545 hidnplayr 751
 
9161 hidnplayr 752
        out     dx, ax                          ; ACK interrupt
753
        DEBUGF  1, "Status: %x\n", ax
3545 hidnplayr 754
 
755
;----------------------------------------------------
756
; Received packet ok?
757
 
758
        test    ax, ISR_ROK
759
        jz      @f
760
        push    ax
761
 
762
  .receive:
5045 hidnplayr 763
        set_io  [ebx + device.io_addr], 0
764
        set_io  [ebx + device.io_addr], REG_COMMAND
3545 hidnplayr 765
        in      al, dx
766
        test    al, BUFE                        ; test if RX buffer is empty
767
        jnz     .finish
768
 
3856 hidnplayr 769
        DEBUGF  1, "RX:\n"
3545 hidnplayr 770
 
5045 hidnplayr 771
        mov     eax, [ebx + device.rx_buffer]
772
        add     eax, [ebx + device.rx_data_offset]
3545 hidnplayr 773
        test    byte [eax], (1 shl BIT_ROK)     ; check if packet is ok
774
        jz      .reset_rx
775
 
776
; packet is ok, copy it
777
        movzx   ecx, word [eax+2]               ; packet length
778
        sub     cx, 4                           ; don't copy CRC
779
 
780
; Update stats
5045 hidnplayr 781
        add     dword [ebx + device.bytes_rx], ecx
782
        adc     dword [ebx + device.bytes_rx + 4], 0
783
        inc     [ebx + device.packets_rx]
3545 hidnplayr 784
 
785
        DEBUGF  1, "Received %u bytes\n", ecx
786
 
787
        push    ebx eax ecx
5522 hidnplayr 788
        add     ecx, NET_BUFF.data
789
        invoke  NetAlloc, ecx                   ; Allocate a buffer to put packet into
3545 hidnplayr 790
        pop     ecx
791
        test    eax, eax                        ; Test if we allocated succesfully
792
        jz      .abort
5522 hidnplayr 793
        mov     [eax + NET_BUFF.length], ecx
794
        mov     [eax + NET_BUFF.device], ebx
795
        mov     [eax + NET_BUFF.offset], NET_BUFF.data
3545 hidnplayr 796
 
5522 hidnplayr 797
        lea     edi, [eax + NET_BUFF.data]      ; Where we will copy too
3545 hidnplayr 798
        mov     esi, [esp]                      ; The buffer we will copy from
799
        add     esi, 4                          ; Dont copy CRC
800
 
5522 hidnplayr 801
        push    .abort                          ; return addr for Eth_input
802
        push    eax                             ; buffer ptr for Eth_input
3545 hidnplayr 803
 
804
  .copy:
805
        shr     ecx, 1
806
        jnc     .nb
807
        movsb
808
  .nb:
809
        shr     ecx, 1
810
        jnc     .nw
811
        movsw
812
  .nw:
813
        jz      .nd
814
        rep     movsd
815
  .nd:
816
 
5522 hidnplayr 817
        jmp     [EthInput]                      ; Send it to kernel
3545 hidnplayr 818
 
819
  .abort:
820
        pop     eax ebx
821
                                                ; update eth_data_start_offset
822
        movzx   eax, word [eax+2]               ; packet length
5045 hidnplayr 823
        add     eax, [ebx + device.rx_data_offset]
3545 hidnplayr 824
        add     eax, 4+3                        ; packet header is 4 bytes long + dword alignment
825
        and     eax, not 3                      ; dword alignment
826
 
827
        cmp     eax, RX_BUFFER_SIZE
828
        jb      .no_wrap
3856 hidnplayr 829
        DEBUGF  1, "Wrapping\n"
3545 hidnplayr 830
        sub     eax, RX_BUFFER_SIZE
831
  .no_wrap:
5045 hidnplayr 832
        mov     [ebx + device.rx_data_offset], eax
3545 hidnplayr 833
        DEBUGF  1, "New RX ptr: %d\n", eax
834
 
5045 hidnplayr 835
        set_io  [ebx + device.io_addr], 0
836
        set_io  [ebx + device.io_addr], REG_CAPR                        ; update 'Current Address of Packet Read register'
3545 hidnplayr 837
        sub     eax, 0x10                       ; value 0x10 is a constant for CAPR
3857 hidnplayr 838
        out     dx, ax
3545 hidnplayr 839
 
840
        jmp     .receive                        ; check for multiple packets
841
 
842
  .reset_rx:
843
        test    byte [eax], (1 shl BIT_CRC)
844
        jz      .no_crc_error
3856 hidnplayr 845
        DEBUGF  2, "RX: CRC error!\n"
3545 hidnplayr 846
 
847
  .no_crc_error:
848
        test    byte [eax], (1 shl BIT_FAE)
849
        jz      .no_fae_error
3856 hidnplayr 850
        DEBUGF  2, "RX: Frame alignment error!\n"
3545 hidnplayr 851
 
852
  .no_fae_error:
853
        DEBUGF  1, "Reset RX\n"
854
        in      al, dx                          ; read command register
855
        push    ax
856
        and     al, not (1 shl BIT_RE)          ; Clear the RE bit
857
        out     dx, al
858
        pop     ax
859
        out     dx, al                          ; write original command back
860
 
861
        add     edx, REG_RXCONFIG - REG_COMMAND         ; Restore RX configuration
862
        mov     ax, RX_CONFIG
863
        out     dx, ax
864
 
865
  .finish:
866
        pop     ax
9161 hidnplayr 867
  @@:
3545 hidnplayr 868
 
869
;----------------------------------------------------
870
; Transmit ok / Transmit error
871
        test    ax, ISR_TOK + ISR_TER
872
        jz      @f
873
 
3857 hidnplayr 874
        DEBUGF  1, "Transmit done!\n"
875
 
3545 hidnplayr 876
        push    ax
877
        mov     ecx, (NUM_TX_DESC-1)*4
878
  .txdescloop:
5045 hidnplayr 879
        set_io  [ebx + device.io_addr], 0
880
        set_io  [ebx + device.io_addr], REG_TSD0
3545 hidnplayr 881
        add     edx, ecx
882
        in      eax, dx
883
 
884
        test    eax, TSR_OWN                    ; DMA operation completed
885
        jz      .notthisone
886
 
5045 hidnplayr 887
        cmp     [ebx + device.TX_DESC+ecx], 0
3545 hidnplayr 888
        je      .notthisone
889
 
3857 hidnplayr 890
        DEBUGF  1, "TSD: 0x%x\n", eax
3545 hidnplayr 891
 
3857 hidnplayr 892
        test    eax, TSR_TUN
893
        jz      .no_bun
894
        DEBUGF  2, "TX: FIFO Buffer underrun!\n"
895
 
896
  .no_bun:
897
        test    eax, TSR_OWC
898
        jz      .no_owc
899
        DEBUGF  2, "TX: OWC!\n"
900
 
901
  .no_owc:
902
        test    eax, TSR_TABT
903
        jz      .no_tabt
904
        DEBUGF  2, "TX: TABT!\n"
905
 
906
  .no_tabt:
907
        test    eax, TSR_CRS
908
        jz      .no_csl
909
        DEBUGF  2, "TX: Carrier Sense Lost!\n"
910
 
911
  .no_csl:
912
        test    eax, TSR_TOK
913
        jz      .no_tok
914
        DEBUGF  1, "TX: Transmit OK!\n"
915
 
916
  .no_tok:
5045 hidnplayr 917
        DEBUGF  1, "free transmit buffer 0x%x\n", [ebx + device.TX_DESC+ecx]:8
3545 hidnplayr 918
        push    ecx ebx
5522 hidnplayr 919
        invoke  NetFree, [ebx + device.TX_DESC+ecx]
3545 hidnplayr 920
        pop     ebx ecx
5045 hidnplayr 921
        mov     [ebx + device.TX_DESC+ecx], 0
3545 hidnplayr 922
 
923
  .notthisone:
924
        sub     ecx, 4
3857 hidnplayr 925
        jae     .txdescloop
3545 hidnplayr 926
        pop     ax
9161 hidnplayr 927
  @@:
3545 hidnplayr 928
 
929
;----------------------------------------------------
930
; Rx buffer overflow ?
931
        test    ax, ISR_RXOVW
932
        jz      @f
933
 
934
        push    ax
3856 hidnplayr 935
        DEBUGF  2, "RX:buffer overflow!\n"
3545 hidnplayr 936
 
5045 hidnplayr 937
        set_io  [ebx + device.io_addr], 0
938
        set_io  [ebx + device.io_addr], REG_ISR
6227 hidnplayr 939
        mov     ax, ISR_FIFOOVW or ISR_RXOVW or ISR_ROK
3545 hidnplayr 940
        out     dx, ax
941
        pop     ax
9161 hidnplayr 942
  @@:
3545 hidnplayr 943
 
944
;----------------------------------------------------
945
; Packet underrun?
946
        test    ax, ISR_PUN
947
        jz      @f
948
 
4449 hidnplayr 949
        DEBUGF  1, "Packet underrun or link changed!\n"
3545 hidnplayr 950
 
6227 hidnplayr 951
        call    link
9161 hidnplayr 952
  @@:
4449 hidnplayr 953
 
3545 hidnplayr 954
;----------------------------------------------------
955
; Receive FIFO overflow ?
956
        test    ax, ISR_FIFOOVW
957
        jz      @f
958
 
959
        push    ax
4449 hidnplayr 960
        DEBUGF  2, "RX fifo overflow!\n"
3545 hidnplayr 961
 
5045 hidnplayr 962
        set_io  [ebx + device.io_addr], 0
963
        set_io  [ebx + device.io_addr], REG_ISR
6227 hidnplayr 964
        mov     ax, ISR_FIFOOVW or ISR_RXOVW or ISR_ROK
3545 hidnplayr 965
        out     dx, ax
966
        pop     ax
9161 hidnplayr 967
  @@:
3545 hidnplayr 968
 
969
;----------------------------------------------------
4449 hidnplayr 970
; cable length changed ?
3545 hidnplayr 971
        test    ax, ISR_LENCHG
9161 hidnplayr 972
        jz      @f
3545 hidnplayr 973
 
4449 hidnplayr 974
        DEBUGF  2, "Cable length changed!\n"
975
 
6227 hidnplayr 976
        call    link
9161 hidnplayr 977
  @@:
3545 hidnplayr 978
 
979
        pop     edi esi ebx
980
        xor     eax, eax
981
        inc     eax
982
 
983
        ret
984
 
9161 hidnplayr 985
  .nothing:
986
        pop     edi esi ebx
987
        xor     eax, eax
3545 hidnplayr 988
 
9161 hidnplayr 989
        ret
3545 hidnplayr 990
 
991
 
9161 hidnplayr 992
 
6227 hidnplayr 993
;;;;;;;;;;;;;;;;;;;;;;;
994
;;                   ;;
995
;; Check link status ;;
996
;;                   ;;
997
;;;;;;;;;;;;;;;;;;;;;;;
3545 hidnplayr 998
 
999
align 4
6227 hidnplayr 1000
link:
3857 hidnplayr 1001
        DEBUGF  1, "Checking link status:\n"
3545 hidnplayr 1002
 
5045 hidnplayr 1003
        set_io  [ebx + device.io_addr], 0
1004
        set_io  [ebx + device.io_addr], REG_MSR
6227 hidnplayr 1005
        in      ax, dx
3545 hidnplayr 1006
 
1007
        test    al, 1 shl 2             ; 0 = link ok 1 = link fail
1008
        jnz     .notconnected
1009
 
9149 hidnplayr 1010
        mov     ecx, ETH_LINK_SPEED_10M
3545 hidnplayr 1011
        test    al, 1 shl 3             ; 0 = 100 Mbps 1 = 10 Mbps
6227 hidnplayr 1012
        jnz     @f
9149 hidnplayr 1013
        mov     ecx, ETH_LINK_SPEED_100M
6227 hidnplayr 1014
  @@:
3545 hidnplayr 1015
 
6227 hidnplayr 1016
        set_io  [ebx + device.io_addr], REG_BMCR
1017
        in      ax, dx
1018
        test    ax, 1 shl 8             ; Duplex mode
1019
        jz      @f
9149 hidnplayr 1020
        or      ecx, ETH_LINK_FULL_DUPLEX
6227 hidnplayr 1021
  @@:
3545 hidnplayr 1022
 
6227 hidnplayr 1023
        mov     [ebx + device.state], ecx
5045 hidnplayr 1024
        invoke  NetLinkChanged
6227 hidnplayr 1025
        DEBUGF  2, "link is up\n"
3545 hidnplayr 1026
        ret
1027
 
1028
  .notconnected:
5045 hidnplayr 1029
        mov     [ebx + device.state], ETH_LINK_DOWN
1030
        invoke  NetLinkChanged
6227 hidnplayr 1031
        DEBUGF  2, "link is down\n"
3545 hidnplayr 1032
        ret
1033
 
1034
 
1035
 
1036
;;;;;;;;;;;;;;;;;;;;;;;
1037
;;                   ;;
1038
;; Write MAC address ;;
1039
;;                   ;;
1040
;;;;;;;;;;;;;;;;;;;;;;;
1041
 
1042
align 4
1043
write_mac:      ; in: mac pushed onto stack (as 3 words)
1044
 
3856 hidnplayr 1045
        DEBUGF  1, "Writing MAC\n"
3545 hidnplayr 1046
 
1047
; disable all in command registers
5045 hidnplayr 1048
        set_io  [ebx + device.io_addr], 0
1049
        set_io  [ebx + device.io_addr], REG_9346CR
3545 hidnplayr 1050
        xor     eax, eax
1051
        out     dx, al
1052
 
5045 hidnplayr 1053
        set_io  [ebx + device.io_addr], REG_IMR
3545 hidnplayr 1054
        xor     eax, eax
1055
        out     dx, ax
1056
 
5045 hidnplayr 1057
        set_io  [ebx + device.io_addr], REG_ISR
3545 hidnplayr 1058
        mov     eax, -1
1059
        out     dx, ax
1060
 
1061
; enable writing
5045 hidnplayr 1062
        set_io  [ebx + device.io_addr], REG_9346CR
3545 hidnplayr 1063
        mov     eax, REG_9346CR_WE
1064
        out     dx, al
1065
 
1066
 ; write the mac ...
5045 hidnplayr 1067
        set_io  [ebx + device.io_addr], REG_IDR0
3545 hidnplayr 1068
        pop     eax
1069
        out     dx, eax
1070
 
5045 hidnplayr 1071
        set_io  [ebx + device.io_addr], REG_IDR0+4
3545 hidnplayr 1072
        xor     eax, eax
1073
        pop     ax
1074
        out     dx, eax
1075
 
1076
; disable writing
5045 hidnplayr 1077
        set_io  [ebx + device.io_addr], REG_9346CR
3545 hidnplayr 1078
        xor     eax, eax
1079
        out     dx, al
1080
 
3856 hidnplayr 1081
        DEBUGF  1, "MAC write ok!\n"
3545 hidnplayr 1082
 
1083
; Notice this procedure does not ret, but continues to read_mac instead.
1084
 
1085
 
1086
;;;;;;;;;;;;;;;;;;;;;;
1087
;;                  ;;
1088
;; Read MAC address ;;
1089
;;                  ;;
1090
;;;;;;;;;;;;;;;;;;;;;;
1091
 
1092
read_mac:
3857 hidnplayr 1093
        DEBUGF  1, "Reading MAC:\n"
3545 hidnplayr 1094
 
5045 hidnplayr 1095
        set_io  [ebx + device.io_addr], 0
1096
        lea     edi, [ebx + device.mac]
3545 hidnplayr 1097
        in      eax, dx
1098
        stosd
1099
        add     edx, 4
1100
        in      ax, dx
1101
        stosw
1102
 
3857 hidnplayr 1103
        DEBUGF  1, "%x-%x-%x-%x-%x-%x\n",[edi-6]:2,[edi-5]:2,[edi-4]:2,[edi-3]:2,[edi-2]:2,[edi-1]:2
3545 hidnplayr 1104
 
1105
        ret
1106
 
1107
 
1108
; End of code
1109
 
5045 hidnplayr 1110
data fixups
1111
end data
3545 hidnplayr 1112
 
5045 hidnplayr 1113
include '../peimport.inc'
1114
 
3545 hidnplayr 1115
my_service      db 'RTL8139',0                    ; max 16 chars include zero
1116
 
6711 hidnplayr 1117
sz_unknown              db 'Unknown RTL8139 clone', 0
1118
sz_RTL8139              db 'Realtek 8139',0
1119
sz_RTL8139_K            db 'Realtek 8139 rev K',0
1120
sz_RTL8139A             db 'Realtek 8139A',0
1121
sz_RTL8139A_G           db 'Realtek 8139A rev G',0
1122
sz_RTL8139B             db 'Realtek 8139B',0
1123
sz_RTL8130              db 'Realtek 8130',0
1124
sz_RTL8139C             db 'Realtek 8139C',0
1125
sz_RTL8100              db 'Realtek 8100',0
1126
sz_RTL8100_8139D        db 'Realtek 8100B / 8139D',0
6713 hidnplayr 1127
sz_RTL8139CP            db 'Realtek 8139CP', 0
6711 hidnplayr 1128
sz_RTL8101              db 'Realtek 8101',0
3545 hidnplayr 1129
 
6711 hidnplayr 1130
hw_ver_names:
1131
        dd sz_unknown
1132
        dd sz_RTL8139
1133
        dd sz_RTL8139_K
1134
        dd sz_RTL8139A
1135
        dd sz_RTL8139A_G
1136
        dd sz_RTL8139B
1137
        dd sz_RTL8130
1138
        dd sz_RTL8139C
1139
        dd sz_RTL8100
1140
        dd sz_RTL8100_8139D
6713 hidnplayr 1141
        dd sz_RTL8139CP
6711 hidnplayr 1142
        dd sz_RTL8101
3545 hidnplayr 1143
 
6711 hidnplayr 1144
hw_ver_array:                   ; This array is used by the probe routine to find out wich version of the RTL8139 we are working with
1145
        db 0
3545 hidnplayr 1146
        db VER_RTL8139
6711 hidnplayr 1147
        db VER_RTL8139_K
3545 hidnplayr 1148
        db VER_RTL8139A
6711 hidnplayr 1149
        db VER_RTL8139A_G
3545 hidnplayr 1150
        db VER_RTL8139B
6711 hidnplayr 1151
        db VER_RTL8130
3545 hidnplayr 1152
        db VER_RTL8139C
1153
        db VER_RTL8100
6711 hidnplayr 1154
        db VER_RTL8100_8139D
6713 hidnplayr 1155
        db VER_RTL8139CP
3545 hidnplayr 1156
        db VER_RTL8101
1157
 
6711 hidnplayr 1158
include_debug_strings           ; All data wich FDO uses will be included here
3545 hidnplayr 1159
 
5045 hidnplayr 1160
align 4
1161
devices         dd 0
6711 hidnplayr 1162
device_list     rd MAX_DEVICES  ; This list contains all pointers to device structures the driver is handling
3545 hidnplayr 1163