Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
3545 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
5363 yogev_ezra 3
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved.    ;;
3545 hidnplayr 4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
6
;;  R6040 driver for KolibriOS                                     ;;
7
;;                                                                 ;;
8
;;  based on R6040.c from linux                                    ;;
9
;;                                                                 ;;
10
;;    Written by Asper (asper.85@mail.ru)                          ;;
11
;;            and hidnplayr (hidnplayr@gmail.com)                  ;;
12
;;                                                                 ;;
13
;;          GNU GENERAL PUBLIC LICENSE                             ;;
14
;;             Version 2, June 1991                                ;;
15
;;                                                                 ;;
16
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
17
 
4597 hidnplayr 18
format PE DLL native
19
entry START
3545 hidnplayr 20
 
4597 hidnplayr 21
        CURRENT_API             = 0x0200
22
        COMPATIBLE_API          = 0x0100
23
        API_VERSION             = (COMPATIBLE_API shl 16) + CURRENT_API
3545 hidnplayr 24
 
25
        MAX_DEVICES             = 16
26
 
27
        __DEBUG__               = 1
28
        __DEBUG_LEVEL__         = 2
29
 
30
        W_MAX_TIMEOUT           = 0x0FFF        ; max time out delay time
31
 
32
        TX_TIMEOUT              = 6000          ; Time before concluding the transmitter is hung, in ms
33
 
34
        TX_RING_SIZE            = 4             ; RING sizes must be a power of 2
35
        RX_RING_SIZE            = 4
36
 
37
        RX_BUF_LEN_IDX          = 3             ; 0==8K, 1==16K, 2==32K, 3==64K
38
 
39
; Threshold is bytes transferred to chip before transmission starts.
40
 
41
        TX_FIFO_THRESH          = 256           ; In bytes, rounded down to 32 byte units.
42
 
43
; The following settings are log_2(bytes)-4:  0 == 16 bytes .. 6==1024.
44
 
45
        RX_FIFO_THRESH          = 4             ; Rx buffer level before first PCI xfer.
46
        RX_DMA_BURST            = 4             ; Maximum PCI burst, '4' is 256 bytes
47
        TX_DMA_BURST            = 4
48
 
4597 hidnplayr 49
section '.flat' readable writable executable
3545 hidnplayr 50
 
4597 hidnplayr 51
include '../proc32.inc'
4467 hidnplayr 52
include '../struct.inc'
53
include '../macros.inc'
3545 hidnplayr 54
include '../fdo.inc'
5074 hidnplayr 55
include '../netdrv.inc'
3545 hidnplayr 56
 
57
; Operational parameters that usually are not changed.
58
 
4439 hidnplayr 59
PHY1_ADDR       = 1                     ; For MAC1
60
PHY2_ADDR       = 3                     ; For MAC2
61
PHY_MODE        = 0x3100                ; PHY CHIP Register 0
62
PHY_CAP         = 0x01E1                ; PHY CHIP Register 4
3545 hidnplayr 63
 
64
;**************************************************************************
65
; RDC R6040 Register Definitions
66
;**************************************************************************
67
 
4439 hidnplayr 68
MCR0            = 0x00                  ; Control register 0
69
MCR0_RCVEN      = 0x0002                ; Receive enable
70
MCR0_PROMISC    = 0x0020                ; Promiscuous mode
71
MCR0_HASH_EN    = 0x0100                ; Enable multicast hash table function
72
MCR0_XMTEN      = 0x1000                ; Transmission enable
73
MCR0_FD         = 0x8000                ; Full/Half Duplex mode
3545 hidnplayr 74
 
4439 hidnplayr 75
MCR1            = 0x01                  ; Control register 1
76
MAC_RST         = 0x0001                ; Reset the MAC
3545 hidnplayr 77
 
4439 hidnplayr 78
MBCR            = 0x08                  ; Bus control
79
MT_ICR          = 0x0C                  ; TX interrupt control
80
MR_ICR          = 0x10                  ; RX interrupt control
81
MTPR            = 0x14                  ; TX poll command register
82
MR_BSR          = 0x18                  ; RX buffer size
83
MR_DCR          = 0x1A                  ; RX descriptor control
84
MLSR            = 0x1C                  ; Last status
85
 
86
MMDIO           = 0x20                  ; MDIO control register
87
MDIO_WRITE      = 0x4000                ; MDIO write
88
MDIO_READ       = 0x2000                ; MDIO read
89
MMRD            = 0x24                  ; MDIO read data register
90
MMWD            = 0x28                  ; MDIO write data register
91
 
92
MTD_SA0         = 0x2C                  ; TX descriptor start address 0
93
MTD_SA1         = 0x30                  ; TX descriptor start address 1
94
MRD_SA0         = 0x34                  ; RX descriptor start address 0
95
MRD_SA1         = 0x38                  ; RX descriptor start address 1
96
 
97
MISR            = 0x3C                  ; Status register
98
MIER            = 0x40                  ; INT enable register
99
MSK_INT         = 0x0000                ; Mask off interrupts
100
RX_FINISH       = 0x0001                ; RX finished
101
RX_NO_DESC      = 0x0002                ; No RX descriptor available
102
RX_FIFO_FULL    = 0x0004                ; RX FIFO full
103
RX_EARLY        = 0x0008                ; RX early
104
TX_FINISH       = 0x0010                ; TX finished
105
TX_EARLY        = 0x0080                ; TX early
106
EVENT_OVRFL     = 0x0100                ; Event counter overflow
107
LINK_CHANGED    = 0x0200                ; PHY link changed
108
 
109
ME_CISR         = 0x44                  ; Event counter INT status
110
ME_CIER         = 0x48                  ; Event counter INT enable
111
MR_CNT          = 0x50                  ; Successfully received packet counter
112
ME_CNT0         = 0x52                  ; Event counter 0
113
ME_CNT1         = 0x54                  ; Event counter 1
114
ME_CNT2         = 0x56                  ; Event counter 2
115
ME_CNT3         = 0x58                  ; Event counter 3
116
MT_CNT          = 0x5A                  ; Successfully transmit packet counter
117
ME_CNT4         = 0x5C                  ; Event counter 4
118
MP_CNT          = 0x5E                  ; Pause frame counter register
119
MAR0            = 0x60                  ; Hash table 0
120
MAR1            = 0x62                  ; Hash table 1
121
MAR2            = 0x64                  ; Hash table 2
122
MAR3            = 0x66                  ; Hash table 3
123
MID_0L          = 0x68                  ; Multicast address MID0 Low
124
MID_0M          = 0x6A                  ; Multicast address MID0 Medium
125
MID_0H          = 0x6C                  ; Multicast address MID0 High
126
MID_1L          = 0x70                  ; MID1 Low
127
MID_1M          = 0x72                  ; MID1 Medium
128
MID_1H          = 0x74                  ; MID1 High
129
MID_2L          = 0x78                  ; MID2 Low
130
MID_2M          = 0x7A                  ; MID2 Medium
131
MID_2H          = 0x7C                  ; MID2 High
132
MID_3L          = 0x80                  ; MID3 Low
133
MID_3M          = 0x82                  ; MID3 Medium
134
MID_3H          = 0x84                  ; MID3 High
135
PHY_CC          = 0x88                  ; PHY status change configuration register
136
PHY_ST          = 0x8A                  ; PHY status register
137
MAC_SM          = 0xAC                  ; MAC status machine
138
MAC_ID          = 0xBE                  ; Identifier register
139
 
5522 hidnplayr 140
MAX_BUF_SIZE    = 1514
4439 hidnplayr 141
 
142
MBCR_DEFAULT    = 0x012A                ; MAC Bus Control Register
143
MCAST_MAX       = 3                     ; Max number multicast addresses to filter
144
 
3545 hidnplayr 145
;Descriptor status
4439 hidnplayr 146
DSC_OWNER_MAC   = 0x8000                ; MAC is the owner of this descriptor
147
DSC_RX_OK       = 0x4000                ; RX was successfull
148
DSC_RX_ERR      = 0x0800                ; RX PHY error
149
DSC_RX_ERR_DRI  = 0x0400                ; RX dribble packet
150
DSC_RX_ERR_BUF  = 0x0200                ; RX length exceeds buffer size
151
DSC_RX_ERR_LONG = 0x0100                ; RX length > maximum packet length
152
DSC_RX_ERR_RUNT = 0x0080                ; RX packet length < 64 byte
153
DSC_RX_ERR_CRC  = 0x0040                ; RX CRC error
154
DSC_RX_BCAST    = 0x0020                ; RX broadcast (no error)
155
DSC_RX_MCAST    = 0x0010                ; RX multicast (no error)
156
DSC_RX_MCH_HIT  = 0x0008                ; RX multicast hit in hash table (no error)
157
DSC_RX_MIDH_HIT = 0x0004                ; RX MID table hit (no error)
158
DSC_RX_IDX_MID_MASK  = 3                ; RX mask for the index of matched MIDx
3545 hidnplayr 159
 
160
;PHY settings
161
ICPLUS_PHY_ID   = 0x0243
162
 
163
RX_INTS         = RX_FIFO_FULL or RX_NO_DESC or RX_FINISH
164
TX_INTS         = TX_FINISH
165
INT_MASK        = RX_INTS or TX_INTS
166
 
167
RX_BUF_LEN      equ (8192 << RX_BUF_LEN_IDX)    ; Size of the in-memory receive ring.
168
 
169
IO_SIZE         = 256       ; RDC MAC I/O Size
170
MAX_MAC         = 2         ; MAX RDC MAC
171
 
4597 hidnplayr 172
struct  x_head
3545 hidnplayr 173
 
4597 hidnplayr 174
        status          dw ?   ;0-1
175
        len             dw ?   ;2-3
176
        buf             dd ?   ;4-7
177
        ndesc           dd ?   ;8-B
178
        rev1            dd ?   ;C-F
179
        vbufp           dd ?   ;10-13
180
        vndescp         dd ?   ;14-17
181
        skb_ptr         dd ?   ;18-1B
182
        rev2            dd ?   ;1C-1F
3545 hidnplayr 183
 
4597 hidnplayr 184
ends
3545 hidnplayr 185
 
186
 
4597 hidnplayr 187
struct  device          ETH_DEVICE
3545 hidnplayr 188
 
4597 hidnplayr 189
        io_addr         dd ?
190
        pci_bus         dd ?
191
        pci_dev         dd ?
192
        irq_line        db ?
193
                        rb 3    ; align 4
3545 hidnplayr 194
 
4597 hidnplayr 195
        cur_rx          dw ?
196
        cur_tx          dw ?
197
        last_tx         dw ?
198
        phy_addr        dd ?
199
        phy_mode        dw ?
200
        mcr0            dw ?
201
        mcr1            dw ?
202
        switch_sig      dw ?
3545 hidnplayr 203
 
4597 hidnplayr 204
        rb 0x100 - ($ and 0xff) ; align 256
205
        tx_ring         rb ((TX_RING_SIZE*sizeof.x_head+32) and 0xfffffff0)
206
        rx_ring         rb ((RX_RING_SIZE*sizeof.x_head+32) and 0xfffffff0)
3545 hidnplayr 207
 
4597 hidnplayr 208
ends
3545 hidnplayr 209
 
210
 
211
 
212
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
213
;;                        ;;
214
;; proc START             ;;
215
;;                        ;;
216
;; (standard driver proc) ;;
217
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
218
 
4597 hidnplayr 219
proc START c, reason:dword, cmdline:dword
3545 hidnplayr 220
 
4597 hidnplayr 221
        cmp     [reason], DRV_ENTRY
222
        jne     .fail
3545 hidnplayr 223
 
5003 hidnplayr 224
        DEBUGF  2,"Loading driver\n"
4597 hidnplayr 225
        invoke  RegService, my_service, service_proc
3545 hidnplayr 226
        ret
227
 
228
  .fail:
4597 hidnplayr 229
        xor     eax, eax
3545 hidnplayr 230
        ret
231
 
232
endp
233
 
234
 
235
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
236
;;                        ;;
237
;; proc SERVICE_PROC      ;;
238
;;                        ;;
239
;; (standard driver proc) ;;
240
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
241
 
242
proc service_proc stdcall, ioctl:dword
243
 
244
        mov     edx, [ioctl]
4470 hidnplayr 245
        mov     eax, [edx + IOCTL.io_code]
3545 hidnplayr 246
 
247
;------------------------------------------------------
248
 
249
        cmp     eax, 0 ;SRV_GETVERSION
250
        jne     @F
251
 
4470 hidnplayr 252
        cmp     [edx + IOCTL.out_size], 4
3545 hidnplayr 253
        jb      .fail
4470 hidnplayr 254
        mov     eax, [edx + IOCTL.output]
3545 hidnplayr 255
        mov     [eax], dword API_VERSION
256
 
257
        xor     eax, eax
258
        ret
259
 
260
;------------------------------------------------------
261
  @@:
262
        cmp     eax, 1 ;SRV_HOOK
263
        jne     .fail
264
 
4597 hidnplayr 265
        cmp     [edx + IOCTL.inp_size], 3               ; Data input must be at least 3 bytes
3545 hidnplayr 266
        jb      .fail
267
 
4470 hidnplayr 268
        mov     eax, [edx + IOCTL.input]
3545 hidnplayr 269
        cmp     byte [eax], 1                           ; 1 means device number and bus number (pci) are given
270
        jne     .fail                                   ; other types arent supported for this card yet
271
 
272
; check if the device is already listed
273
 
274
        mov     esi, device_list
275
        mov     ecx, [devices]
276
        test    ecx, ecx
277
        jz      .firstdevice
278
 
4597 hidnplayr 279
;        mov     eax, [edx + IOCTL.input]               ; get the pci bus and device numbers
3545 hidnplayr 280
        mov     ax , [eax+1]                            ;
281
  .nextdevice:
282
        mov     ebx, [esi]
4597 hidnplayr 283
        cmp     al, byte[ebx + device.pci_bus]
3545 hidnplayr 284
        jne     @f
4597 hidnplayr 285
        cmp     ah, byte[ebx + device.pci_dev]
3545 hidnplayr 286
        je      .find_devicenum                         ; Device is already loaded, let's find it's device number
287
       @@:
288
        add     esi, 4
289
        loop    .nextdevice
290
 
291
 
292
; This device doesnt have its own eth_device structure yet, lets create one
293
  .firstdevice:
294
        cmp     [devices], MAX_DEVICES                  ; First check if the driver can handle one more card
295
        jae     .fail
296
 
4597 hidnplayr 297
        allocate_and_clear ebx, sizeof.device, .fail    ; Allocate the buffer for device structure
3545 hidnplayr 298
 
299
; Fill in the direct call addresses into the struct
300
 
4597 hidnplayr 301
        mov     [ebx + device.reset], reset
302
        mov     [ebx + device.transmit], transmit
303
        mov     [ebx + device.unload], unload
304
        mov     [ebx + device.name], my_service
3545 hidnplayr 305
 
306
; save the pci bus and device numbers
307
 
4470 hidnplayr 308
        mov     eax, [edx + IOCTL.input]
3545 hidnplayr 309
        movzx   ecx, byte[eax+1]
4597 hidnplayr 310
        mov     [ebx + device.pci_bus], ecx
3545 hidnplayr 311
        movzx   ecx, byte[eax+2]
4597 hidnplayr 312
        mov     [ebx + device.pci_dev], ecx
3545 hidnplayr 313
 
314
; Now, it's time to find the base io addres of the PCI device
315
 
4597 hidnplayr 316
        stdcall PCI_find_io, [ebx + device.pci_bus], [ebx + device.pci_dev]
317
        mov     [ebx + device.io_addr], eax
3545 hidnplayr 318
 
319
; We've found the io address, find IRQ now
320
 
4597 hidnplayr 321
        invoke  PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.interrupt_line
322
        mov     [ebx + device.irq_line], al
3545 hidnplayr 323
 
324
        DEBUGF  1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
4597 hidnplayr 325
        [ebx + device.pci_dev]:1,[ebx + device.pci_bus]:1,[ebx + device.irq_line]:1,[ebx + device.io_addr]:8
3545 hidnplayr 326
 
327
; Ok, the eth_device structure is ready, let's probe the device
328
 
329
        mov     eax, [devices]                                          ; Add the device structure to our device list
330
        mov     [device_list+4*eax], ebx                                ; (IRQ handler uses this list to find device)
331
        inc     [devices]                                               ;
332
 
4597 hidnplayr 333
        call    probe                                                   ; this function will output in eax
334
        test    eax, eax
335
        jnz     .err2
3545 hidnplayr 336
 
5003 hidnplayr 337
        DEBUGF  2,"Initialised OK\n"
338
 
4597 hidnplayr 339
        mov     [ebx + device.type], NET_TYPE_ETH
340
        invoke  NetRegDev
341
 
3545 hidnplayr 342
        cmp     eax, -1
343
        je      .destroy
344
 
345
        ret
346
 
347
; If the device was already loaded, find the device number and return it in eax
348
 
349
  .find_devicenum:
4597 hidnplayr 350
        DEBUGF  2,"Trying to find device number of already registered device\n"
351
        invoke  NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
3545 hidnplayr 352
                                                                        ; into a device number in edi
353
        mov     eax, edi                                                ; Application wants it in eax instead
4597 hidnplayr 354
        DEBUGF  2,"Kernel says: %u\n", eax
3545 hidnplayr 355
        ret
356
 
357
; If an error occured, remove all allocated data and exit (returning -1 in eax)
358
 
359
  .destroy:
360
        ; todo: reset device into virgin state
361
 
4597 hidnplayr 362
  .err2:
363
        dec     [devices]
3545 hidnplayr 364
  .err:
4597 hidnplayr 365
        invoke  KernelFree, ebx
3545 hidnplayr 366
  .fail:
4597 hidnplayr 367
        DEBUGF  2, "Failed to load\n"
3545 hidnplayr 368
        or      eax, -1
369
        ret
370
 
371
;------------------------------------------------------
372
endp
373
 
374
 
375
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
376
;;                                                                        ;;
377
;;        Actual Hardware dependent code starts here                      ;;
378
;;                                                                        ;;
379
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
380
 
381
 
4450 hidnplayr 382
;mdio_read:
4597 hidnplayr 383
;        stdcall phy_read, [ebx + device.io_addr], [ebx + device.phy_addr], ecx
3545 hidnplayr 384
 
4450 hidnplayr 385
;        ret
3545 hidnplayr 386
 
4450 hidnplayr 387
;mdio_write:
4597 hidnplayr 388
;        stdcall phy_write, [ebx + device.io_addr], [ebx + device.phy_addr], ecx, eax
3545 hidnplayr 389
 
4450 hidnplayr 390
;        ret
391
 
392
 
3545 hidnplayr 393
align 4
394
unload:
395
        ; TODO: (in this particular order)
396
        ;
397
        ; - Stop the device
398
        ; - Detach int handler
5522 hidnplayr 399
        ; - Remove device from local list (device_list)
3545 hidnplayr 400
        ; - call unregister function in kernel
401
        ; - Remove all allocated structures and buffers the card used
402
 
5522 hidnplayr 403
        or      eax, -1
404
        ret
3545 hidnplayr 405
 
406
 
407
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
408
;;
4450 hidnplayr 409
;;  probe: enables the device (if it really is R6040)
3545 hidnplayr 410
;;
411
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
412
 
413
align 4
414
probe:
4597 hidnplayr 415
        DEBUGF  1,"Probing\n"
3545 hidnplayr 416
 
4597 hidnplayr 417
; Make the device a bus master
418
        invoke  PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command
419
        or      al, PCI_CMD_MASTER
420
        invoke  PciWrite32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command, eax
3545 hidnplayr 421
 
422
        ; If PHY status change register is still set to zero
423
        ; it means the bootloader didn't initialize it
424
 
4597 hidnplayr 425
        set_io  [ebx + device.io_addr], 0
426
        set_io  [ebx + device.io_addr], PHY_CC
3545 hidnplayr 427
        in      ax, dx
428
        test    ax, ax
429
        jnz     @f
430
        mov     ax, 0x9F07
431
        out     dx, ax
5522 hidnplayr 432
  @@:
3545 hidnplayr 433
 
434
        call    read_mac
435
 
436
        ; Some bootloaders/BIOSes do not initialize MAC address, warn about that
437
        and     eax, 0xFF
4597 hidnplayr 438
        or      eax, dword [ebx + device.mac]
3545 hidnplayr 439
        test    eax, eax
440
        jnz     @f
4439 hidnplayr 441
        DEBUGF  2, "MAC address not initialized!\n"
3545 hidnplayr 442
 
5522 hidnplayr 443
  @@:
3545 hidnplayr 444
        ; Init RDC private data
4597 hidnplayr 445
        mov     [ebx + device.mcr0], MCR0_XMTEN or MCR0_RCVEN
446
        mov     [ebx + device.phy_addr], PHY1_ADDR
447
        mov     [ebx + device.switch_sig], 0
3545 hidnplayr 448
 
449
        ; Check the vendor ID on the PHY, if 0xFFFF assume none attached
4597 hidnplayr 450
        stdcall phy_read, [ebx + device.phy_addr], 2
3545 hidnplayr 451
        cmp     ax, 0xFFFF
452
        jne     @f
4450 hidnplayr 453
        DEBUGF  2, "Failed to detect an attached PHY!\n"
5522 hidnplayr 454
  .err:
3545 hidnplayr 455
        mov     eax, -1
456
        ret
5522 hidnplayr 457
  @@:
3545 hidnplayr 458
 
459
        ; Set MAC address
460
        call    init_mac_regs
461
 
462
        ; Initialize and alloc RX/TX buffers
463
        call    init_txbufs
464
        call    init_rxbufs
5522 hidnplayr 465
        test    eax, eax
466
        jnz     .err
3545 hidnplayr 467
 
468
        ; Read the PHY ID
4597 hidnplayr 469
        mov     [ebx + device.phy_mode], MCR0_FD
3545 hidnplayr 470
        stdcall phy_read, 0, 2
4597 hidnplayr 471
        mov     [ebx + device.switch_sig], ax
3545 hidnplayr 472
        cmp     ax, ICPLUS_PHY_ID
473
        jne     @f
474
        stdcall phy_write, 29, 31, 0x175C ; Enable registers
475
        jmp     .phy_readen
5522 hidnplayr 476
  @@:
3545 hidnplayr 477
 
478
        ; PHY Mode Check
4597 hidnplayr 479
        stdcall phy_write, [ebx + device.phy_addr], 4, PHY_CAP
480
        stdcall phy_write, [ebx + device.phy_addr], 0, PHY_MODE
3545 hidnplayr 481
 
482
      if PHY_MODE = 0x3100
483
        call    phy_mode_chk
4597 hidnplayr 484
        mov     [ebx + device.phy_mode], ax
3545 hidnplayr 485
        jmp     .phy_readen
486
      end if
487
 
488
      if not (PHY_MODE and 0x0100)
4597 hidnplayr 489
        mov     [ebx + device.phy_mode], 0
3545 hidnplayr 490
      end if
491
 
5522 hidnplayr 492
  .phy_readen:
3545 hidnplayr 493
 
494
        ; Set duplex mode
4597 hidnplayr 495
        mov     ax, [ebx + device.phy_mode]
496
        or      [ebx + device.mcr0], ax
3545 hidnplayr 497
 
498
        ; improve performance (by RDC guys)
499
        stdcall phy_read, 30, 17
500
        or      ax, 0x4000
501
        stdcall phy_write, 30, 17, eax
502
 
503
        stdcall phy_read, 30, 17
504
        and     ax, not 0x2000
505
        stdcall phy_write, 30, 17, eax
506
 
507
        stdcall phy_write, 0, 19, 0x0000
508
        stdcall phy_write, 0, 30, 0x01F0
509
 
510
        ; Initialize all Mac registers
511
        call    init_mac_regs
512
 
513
 
514
align 4
515
reset:
516
 
4597 hidnplayr 517
        DEBUGF  1,"Resetting\n"
3545 hidnplayr 518
 
519
        ; Mask off Interrupt
520
        xor     ax, ax
4597 hidnplayr 521
        set_io  [ebx + device.io_addr], 0
522
        set_io  [ebx + device.io_addr], MIER
3545 hidnplayr 523
        out     dx, ax
524
 
525
; attach int handler
526
 
4597 hidnplayr 527
        movzx   eax, [ebx + device.irq_line]
4439 hidnplayr 528
        DEBUGF  1,"Attaching int handler to irq %x\n", eax:1
4597 hidnplayr 529
        invoke  AttachIntHandler, eax, int_handler, ebx
3545 hidnplayr 530
        test    eax, eax
531
        jnz     @f
4439 hidnplayr 532
        DEBUGF  2,"Could not attach int handler!\n"
4597 hidnplayr 533
        or      eax, -1
534
        ret
5522 hidnplayr 535
  @@:
3545 hidnplayr 536
 
537
        ;Reset RDC MAC
538
        mov     eax, MAC_RST
4597 hidnplayr 539
        set_io  [ebx + device.io_addr], 0
540
        set_io  [ebx + device.io_addr], MCR1
3545 hidnplayr 541
        out     dx, ax
542
 
543
        mov     ecx, 2048 ;limit
544
  .read:
545
        in      ax, dx
546
        test    ax, 0x1
547
        jnz      @f
548
        dec     ecx
549
        test    ecx, ecx
550
        jnz     .read
551
  @@:
552
        ;Reset internal state machine
553
        mov     ax,  2
4597 hidnplayr 554
        set_io  [ebx + device.io_addr], MAC_SM
3545 hidnplayr 555
        out     dx, ax
556
 
557
        xor     ax, ax
558
        out     dx, ax
559
 
560
        mov     esi, 5
4597 hidnplayr 561
        invoke  Sleep
3545 hidnplayr 562
 
563
        ;MAC Bus Control Register
564
        mov     ax, MBCR_DEFAULT
4597 hidnplayr 565
        set_io  [ebx + device.io_addr], 0
566
        set_io  [ebx + device.io_addr], MBCR
3545 hidnplayr 567
        out     dx, ax
568
 
569
        ;Buffer Size Register
570
        mov     ax, MAX_BUF_SIZE
4597 hidnplayr 571
        set_io  [ebx + device.io_addr], MR_BSR
3545 hidnplayr 572
        out     dx, ax
573
 
574
        ;Write TX ring start address
4597 hidnplayr 575
        lea     eax, [ebx + device.tx_ring]
576
        invoke  GetPhysAddr
577
        set_io  [ebx + device.io_addr], MTD_SA0
3545 hidnplayr 578
        out     dx, ax
579
        shr     eax, 16
4597 hidnplayr 580
        set_io  [ebx + device.io_addr], MTD_SA1
3545 hidnplayr 581
        out     dx, ax
582
 
583
        ;Write RX ring start address
4597 hidnplayr 584
        lea     eax, [ebx + device.rx_ring]
585
        invoke  GetPhysAddr
586
        set_io  [ebx + device.io_addr], MRD_SA0
3545 hidnplayr 587
        out     dx, ax
588
        shr     eax, 16
4597 hidnplayr 589
        set_io  [ebx + device.io_addr], MRD_SA1
3545 hidnplayr 590
        out     dx, ax
591
 
592
        ;Set interrupt waiting time and packet numbers
593
        xor     ax, ax
4597 hidnplayr 594
        set_io  [ebx + device.io_addr], MT_ICR
3545 hidnplayr 595
        out     dx, ax
596
 
597
        ;Enable interrupts
598
        mov     ax, INT_MASK
4597 hidnplayr 599
        set_io  [ebx + device.io_addr], MIER
3545 hidnplayr 600
        out     dx, ax
601
 
4439 hidnplayr 602
        ;Enable RX
4597 hidnplayr 603
        mov     ax, [ebx + device.mcr0]
4439 hidnplayr 604
        or      ax, MCR0_RCVEN
4597 hidnplayr 605
        set_io  [ebx + device.io_addr], 0
3545 hidnplayr 606
        out     dx, ax
607
 
608
        ;Let TX poll the descriptors
4597 hidnplayr 609
        ;we may got called by tx_timeout which has left some unset tx buffers
3545 hidnplayr 610
        xor     ax, ax
611
        inc     ax
4597 hidnplayr 612
        set_io  [ebx + device.io_addr], MTPR
3545 hidnplayr 613
        out     dx, ax
614
 
615
; Set the mtu, kernel will be able to send now
4597 hidnplayr 616
        mov     [ebx + device.mtu], 1514
3545 hidnplayr 617
 
618
; Set link state to unknown
4597 hidnplayr 619
        mov     [ebx + device.state], ETH_LINK_UNKNOWN
3545 hidnplayr 620
 
621
        DEBUGF  1,"Reset ok\n"
622
        xor     eax, eax
623
        ret
624
 
625
 
626
 
627
align 4
628
init_txbufs:
629
 
630
        DEBUGF  1,"Init TxBufs\n"
631
 
4597 hidnplayr 632
        lea     esi, [ebx + device.tx_ring]
633
        lea     eax, [ebx + device.tx_ring + sizeof.x_head]
634
        invoke  GetPhysAddr
3545 hidnplayr 635
        mov     ecx, TX_RING_SIZE
636
 
5522 hidnplayr 637
  .next_desc:
3545 hidnplayr 638
        mov     [esi + x_head.ndesc], eax
639
        mov     [esi + x_head.skb_ptr], 0
640
        mov     [esi + x_head.status], DSC_OWNER_MAC
4597 hidnplayr 641
        add     eax, sizeof.x_head
642
        add     esi, sizeof.x_head
3545 hidnplayr 643
        dec     ecx
644
        jnz     .next_desc
645
 
4597 hidnplayr 646
        lea     eax, [ebx + device.tx_ring]
647
        invoke  GetPhysAddr
648
        mov     dword[ebx + device.tx_ring + sizeof.x_head*(TX_RING_SIZE-1) + x_head.ndesc], eax
3545 hidnplayr 649
 
650
        ret
651
 
652
 
653
 
654
align 4
655
init_rxbufs:
656
 
657
        DEBUGF  1,"Init RxBufs\n"
658
 
4597 hidnplayr 659
        lea     esi, [ebx + device.rx_ring]
660
        lea     eax, [ebx + device.rx_ring + sizeof.x_head]
661
        invoke  GetPhysAddr
3545 hidnplayr 662
        mov     edx, eax
663
        mov     ecx, RX_RING_SIZE
664
 
5522 hidnplayr 665
  .next_desc:
4439 hidnplayr 666
        mov     [esi + x_head.ndesc], edx
667
        push    esi ecx edx
5522 hidnplayr 668
        invoke  NetAlloc, MAX_BUF_SIZE+NET_BUFF.data
4439 hidnplayr 669
        pop     edx ecx esi
5522 hidnplayr 670
        test    eax, eax
671
        jz      .out_of_mem
3545 hidnplayr 672
        mov     [esi + x_head.skb_ptr], eax
4597 hidnplayr 673
        invoke  GetPhysAddr
5522 hidnplayr 674
        add     eax, NET_BUFF.data
3545 hidnplayr 675
        mov     [esi + x_head.buf], eax
676
        mov     [esi + x_head.status], DSC_OWNER_MAC
677
 
4597 hidnplayr 678
        add     edx, sizeof.x_head
679
        add     esi, sizeof.x_head
3545 hidnplayr 680
        dec     ecx
681
        jnz     .next_desc
682
 
4439 hidnplayr 683
; complete the ring by linking the last to the first
4597 hidnplayr 684
        lea     eax, [ebx + device.rx_ring]
685
        invoke  GetPhysAddr
686
        mov     dword[ebx + device.rx_ring + sizeof.x_head*(RX_RING_SIZE-1) + x_head.ndesc], eax
3545 hidnplayr 687
 
5522 hidnplayr 688
        xor     eax, eax
3545 hidnplayr 689
        ret
690
 
5522 hidnplayr 691
  .out_of_mem:
692
        or      eax, -1
693
        ret
3545 hidnplayr 694
 
695
 
5522 hidnplayr 696
 
3545 hidnplayr 697
align 4
698
phy_mode_chk:
699
 
700
        DEBUGF  1,"Checking PHY mode\n"
701
 
702
        ; PHY Link Status Check
4597 hidnplayr 703
        stdcall phy_read, [ebx + device.phy_addr], MII_BMSR
4450 hidnplayr 704
        test    ax, BMSR_LSTATUS
3545 hidnplayr 705
        jz      .ret_0x8000
706
 
707
        ; PHY Chip Auto-Negotiation Status
4450 hidnplayr 708
        test    ax, BMSR_ANEGCOMPLETE
3545 hidnplayr 709
        jnz     .auto_nego
710
 
711
        ; Force Mode
4597 hidnplayr 712
        stdcall phy_read, [ebx + device.phy_addr], MII_BMCR
4450 hidnplayr 713
        test    ax, BMCR_FULLDPLX
3545 hidnplayr 714
        jnz     .ret_0x8000
715
 
716
  .auto_nego:
717
        ; Auto Negotiation Mode
4597 hidnplayr 718
        stdcall phy_read, [ebx + device.phy_addr], MII_LPA
4450 hidnplayr 719
        mov     cx, ax
4597 hidnplayr 720
        stdcall phy_read, [ebx + device.phy_addr], MII_ADVERTISE
4450 hidnplayr 721
        and     ax, cx
722
        test    ax, ADVERTISE_10FULL + ADVERTISE_100FULL
3545 hidnplayr 723
        jnz     .ret_0x8000
724
 
725
        xor     eax, eax
726
        ret
727
 
728
  .ret_0x8000:
729
        mov     eax, 0x8000
730
        ret
731
 
732
 
733
 
734
 
735
 
736
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
737
;;                                         ;;
738
;; Transmit                                ;;
739
;;                                         ;;
4597 hidnplayr 740
;; In: pointer to device structure in ebx  ;;
3545 hidnplayr 741
;;                                         ;;
742
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4597 hidnplayr 743
 
5522 hidnplayr 744
proc transmit stdcall bufferptr
4597 hidnplayr 745
 
746
        pushf
747
        cli
748
 
5522 hidnplayr 749
        mov     esi, [bufferptr]
750
        DEBUGF  1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [esi + NET_BUFF.length]
751
        lea     eax, [esi + NET_BUFF.data]
4439 hidnplayr 752
        DEBUGF  1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
3545 hidnplayr 753
        [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
754
        [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
755
        [eax+13]:2,[eax+12]:2
756
 
5522 hidnplayr 757
        cmp     [esi + NET_BUFF.length], 1514
3545 hidnplayr 758
        ja      .fail
5522 hidnplayr 759
        cmp     [esi + NET_BUFF.length], 60
3545 hidnplayr 760
        jb      .fail
761
 
4597 hidnplayr 762
        movzx   edi, [ebx + device.cur_tx]
3545 hidnplayr 763
        shl     edi, 5
764
        add     edi, ebx
4597 hidnplayr 765
        add     edi, device.tx_ring
3545 hidnplayr 766
 
4439 hidnplayr 767
        DEBUGF  1,"TX buffer status: 0x%x\n", [edi + x_head.status]:4
3545 hidnplayr 768
 
769
        test    [edi + x_head.status], DSC_OWNER_MAC    ; check if buffer is available
770
        jnz     .wait_to_send
771
 
772
  .do_send:
4439 hidnplayr 773
        DEBUGF  1,"Sending now\n"
3545 hidnplayr 774
 
5522 hidnplayr 775
        mov     [edi + x_head.skb_ptr], esi
776
        mov     eax, esi
777
        add     eax, [eax + NET_BUFF.offset]
4597 hidnplayr 778
        invoke  GetPhysAddr
3545 hidnplayr 779
        mov     [edi + x_head.buf], eax
5522 hidnplayr 780
        mov     ecx, [esi + NET_BUFF.length]
3545 hidnplayr 781
        mov     [edi + x_head.len], cx
782
        mov     [edi + x_head.status], DSC_OWNER_MAC
783
 
784
        ; Trigger the MAC to check the TX descriptor
785
        mov     ax, 0x01
4597 hidnplayr 786
        set_io  [ebx + device.io_addr], 0
787
        set_io  [ebx + device.io_addr], MTPR
3545 hidnplayr 788
        out     dx, ax
789
 
4597 hidnplayr 790
        inc     [ebx + device.cur_tx]
791
        and     [ebx + device.cur_tx], TX_RING_SIZE - 1
3545 hidnplayr 792
 
793
; Update stats
4597 hidnplayr 794
        inc     [ebx + device.packets_tx]
5522 hidnplayr 795
        mov     eax, [esi + NET_BUFF.length]
4597 hidnplayr 796
        add     dword[ebx + device.bytes_tx], eax
797
        adc     dword[ebx + device.bytes_tx + 4], 0
3545 hidnplayr 798
 
5127 hidnplayr 799
        popf
4450 hidnplayr 800
        xor     eax, eax
4597 hidnplayr 801
        ret
3545 hidnplayr 802
 
803
  .wait_to_send:
4439 hidnplayr 804
        DEBUGF  1,"Waiting for TX buffer\n"
4597 hidnplayr 805
        invoke  GetTimerTicks           ; returns in eax
3545 hidnplayr 806
        lea     edx, [eax + 100]
5522 hidnplayr 807
  .l2:
808
        mov     esi, [bufferptr]
3545 hidnplayr 809
        test    [edi + x_head.status], DSC_OWNER_MAC
810
        jz      .do_send
5522 hidnplayr 811
        popf
3545 hidnplayr 812
        mov     esi, 10
4597 hidnplayr 813
        invoke  Sleep
814
        invoke  GetTimerTicks
5522 hidnplayr 815
        pushf
816
        cli
3545 hidnplayr 817
        cmp     edx, eax
818
        jb      .l2
819
 
4439 hidnplayr 820
        DEBUGF  2,"Send timeout\n"
3545 hidnplayr 821
  .fail:
4439 hidnplayr 822
        DEBUGF  2,"Send failed\n"
5522 hidnplayr 823
        invoke  NetFree, [bufferptr]
4597 hidnplayr 824
        popf
4334 hidnplayr 825
        or      eax, -1
4597 hidnplayr 826
        ret
3545 hidnplayr 827
 
4597 hidnplayr 828
endp
3545 hidnplayr 829
 
830
 
831
 
832
;;;;;;;;;;;;;;;;;;;;;;;
833
;;                   ;;
834
;; Interrupt handler ;;
835
;;                   ;;
836
;;;;;;;;;;;;;;;;;;;;;;;
837
 
838
align 4
839
int_handler:
840
 
841
        push    ebx esi edi
842
 
4439 hidnplayr 843
        DEBUGF  1,"int\n"
3545 hidnplayr 844
 
845
; Find pointer of device wich made IRQ occur
846
 
847
        mov     ecx, [devices]
848
        test    ecx, ecx
849
        jz      .nothing
850
        mov     esi, device_list
851
  .nextdevice:
852
        mov     ebx, [esi]
853
 
4597 hidnplayr 854
        set_io  [ebx + device.io_addr], 0
855
        set_io  [ebx + device.io_addr], MISR
3545 hidnplayr 856
        in      ax, dx
857
        out     dx, ax                  ; send it back to ACK
858
        test    ax, ax
859
        jnz     .got_it
860
  .continue:
861
        add     esi, 4
862
        dec     ecx
863
        jnz     .nextdevice
864
  .nothing:
865
        pop     edi esi ebx
866
        xor     eax, eax
867
 
4597 hidnplayr 868
        ret                             ; If no device was found, abort
3545 hidnplayr 869
 
870
; At this point, test for all possible reasons, and handle accordingly
871
 
872
  .got_it:
873
 
4439 hidnplayr 874
        DEBUGF  1,"Device: %x Status: %x\n", ebx, ax
3545 hidnplayr 875
 
876
        push ax
877
 
4439 hidnplayr 878
        test    word[esp], RX_FINISH
3545 hidnplayr 879
        jz      .no_RX
880
 
881
        push    ebx
882
  .more_RX:
883
        pop     ebx
884
 
885
        ; Find the current RX descriptor
4597 hidnplayr 886
        movzx   edx, [ebx + device.cur_rx]
3545 hidnplayr 887
        shl     edx, 5
4597 hidnplayr 888
        lea     edx, [ebx + device.rx_ring + edx]
3545 hidnplayr 889
 
890
        ; Check the descriptor status
891
        mov     cx, [edx + x_head.status]
892
        test    cx, DSC_OWNER_MAC
893
        jnz     .no_RX
894
 
4439 hidnplayr 895
        DEBUGF  1,"packet status=0x%x\n", cx
3545 hidnplayr 896
 
897
        test    cx, DSC_RX_ERR          ; Global error status set
898
        jnz     .no_RX
899
 
900
        ; Packet successfully received
901
        movzx   ecx, [edx + x_head.len]
902
        and     ecx, 0xFFF
903
        sub     ecx, 4                  ; Do not count the CRC
904
 
5522 hidnplayr 905
        DEBUGF  1,"packet ptr=0x%x size=%u\n", [edx + x_head.skb_ptr], ecx
906
 
4439 hidnplayr 907
        ; Update stats
4597 hidnplayr 908
        add     dword[ebx + device.bytes_rx], ecx
909
        adc     dword[ebx + device.bytes_rx + 4], 0
910
        inc     dword[ebx + device.packets_rx]
3545 hidnplayr 911
 
912
        push    ebx
5522 hidnplayr 913
        ; Push packet ptr and return addr for Eth_input
3545 hidnplayr 914
        push    .more_RX
5522 hidnplayr 915
        mov     eax, [edx + x_head.skb_ptr]
916
        push    eax
917
        mov     [eax + NET_BUFF.length], ecx
918
        mov     [eax + NET_BUFF.device], ebx
919
        mov     [eax + NET_BUFF.offset], NET_BUFF.data
3545 hidnplayr 920
 
5522 hidnplayr 921
        ; reset the RX descriptor (alloc new buffer)
3545 hidnplayr 922
        push    edx
5522 hidnplayr 923
        invoke  NetAlloc, MAX_BUF_SIZE+NET_BUFF.data
3545 hidnplayr 924
        pop     edx
925
        mov     [edx + x_head.skb_ptr], eax
4597 hidnplayr 926
        invoke  GetPhysAddr
5522 hidnplayr 927
        add     eax, NET_BUFF.data
3545 hidnplayr 928
        mov     [edx + x_head.buf], eax
929
        mov     [edx + x_head.status], DSC_OWNER_MAC
930
 
931
        ; Use next descriptor next time
4597 hidnplayr 932
        inc     [ebx + device.cur_rx]
933
        and     [ebx + device.cur_rx], RX_RING_SIZE - 1
3545 hidnplayr 934
 
935
        ; At last, send packet to kernel
5522 hidnplayr 936
        jmp     [EthInput]
3545 hidnplayr 937
 
938
 
939
  .no_RX:
4439 hidnplayr 940
        test    word[esp], TX_FINISH
3545 hidnplayr 941
        jz      .no_TX
942
 
5522 hidnplayr 943
  .loop_tx:
4597 hidnplayr 944
        movzx   edi, [ebx + device.last_tx]
3545 hidnplayr 945
        shl     edi, 5
4597 hidnplayr 946
        lea     edi, [ebx + device.tx_ring + edi]
3545 hidnplayr 947
 
948
        test    [edi + x_head.status], DSC_OWNER_MAC
949
        jnz     .no_TX
950
 
951
        cmp     [edi + x_head.skb_ptr], 0
952
        je      .no_TX
953
 
4439 hidnplayr 954
        DEBUGF  1,"Freeing buffer 0x%x\n", [edi + x_head.skb_ptr]
3545 hidnplayr 955
 
956
        push    [edi + x_head.skb_ptr]
957
        mov     [edi + x_head.skb_ptr], 0
5522 hidnplayr 958
        invoke  NetFree
3545 hidnplayr 959
 
4597 hidnplayr 960
        inc     [ebx + device.last_tx]
961
        and     [ebx + device.last_tx], TX_RING_SIZE - 1
3545 hidnplayr 962
 
963
        jmp     .loop_tx
964
 
965
  .no_TX:
4439 hidnplayr 966
        test    word[esp], RX_NO_DESC
967
        jz      .no_rxdesc
968
 
969
        DEBUGF  2, "No more RX descriptors!\n"
970
 
971
  .no_rxdesc:
972
        test    word[esp], RX_FIFO_FULL
973
        jz      .no_rxfifo
974
 
975
        DEBUGF  2, "RX FIFO full!\n"
976
 
977
  .no_rxfifo:
978
        test    word[esp], RX_EARLY
979
        jz      .no_rxearly
980
 
4450 hidnplayr 981
        DEBUGF  2, "RX early\n"
4439 hidnplayr 982
 
983
  .no_rxearly:
984
        test    word[esp], TX_EARLY
985
        jz      .no_txearly
986
 
4450 hidnplayr 987
        DEBUGF  2, "TX early\n"
4439 hidnplayr 988
 
989
  .no_txearly:
990
        test    word[esp], EVENT_OVRFL
991
        jz      .no_ovrfl
992
 
993
        DEBUGF  2, "Event counter overflow!\n"
994
 
995
  .no_ovrfl:
996
        test    word[esp], LINK_CHANGED
997
        jz      .no_link
998
 
4450 hidnplayr 999
        DEBUGF  2, "Link changed\n"
4439 hidnplayr 1000
 
1001
  .no_link:
3545 hidnplayr 1002
        pop     ax
1003
 
1004
        pop     edi esi ebx
1005
 
1006
        ret
1007
 
1008
 
1009
 
1010
 
1011
align 4
1012
init_mac_regs:
1013
 
4439 hidnplayr 1014
        DEBUGF  1,"initializing MAC regs\n"
3545 hidnplayr 1015
 
1016
        ; MAC operation register
1017
        mov     ax, 1
4597 hidnplayr 1018
        set_io  [ebx + device.io_addr], 0
1019
        set_io  [ebx + device.io_addr], MCR1
3545 hidnplayr 1020
        out     dx, ax
1021
        ; Reset MAC
1022
        mov     ax, 2
4597 hidnplayr 1023
        set_io  [ebx + device.io_addr], MAC_SM
3545 hidnplayr 1024
        out     dx, ax
1025
        ; Reset internal state machine
1026
        xor     ax, ax
1027
        out     dx, ax
1028
        mov     esi, 5
4597 hidnplayr 1029
        invoke  Sleep
3545 hidnplayr 1030
 
1031
        call    read_mac
1032
 
1033
        ret
1034
 
1035
 
1036
 
1037
 
1038
; Read a word data from PHY Chip
1039
 
1040
align 4
1041
proc  phy_read stdcall, phy_addr:dword, reg:dword
1042
 
4439 hidnplayr 1043
        DEBUGF  1,"PHY read, addr=0x%x reg=0x%x\n", [phy_addr]:8, [reg]:8
3545 hidnplayr 1044
 
1045
        mov     eax, [phy_addr]
1046
        shl     eax, 8
1047
        add     eax, [reg]
1048
        add     eax, MDIO_READ
4597 hidnplayr 1049
        set_io  [ebx + device.io_addr], 0
1050
        set_io  [ebx + device.io_addr], MMDIO
3545 hidnplayr 1051
        out     dx, ax
1052
 
1053
        ;Wait for the read bit to be cleared.
1054
        mov     ecx, 2048 ;limit
1055
  .read:
1056
        in      ax, dx
1057
        test    ax, MDIO_READ
1058
        jz      @f
1059
        dec     ecx
1060
        jnz     .read
1061
  @@:
1062
 
4597 hidnplayr 1063
        set_io  [ebx + device.io_addr],   MMRD
3545 hidnplayr 1064
        in      ax, dx
1065
        and     eax, 0xFFFF
1066
 
4439 hidnplayr 1067
        DEBUGF  1,"PHY read, val=0x%x\n", eax:4
3545 hidnplayr 1068
 
1069
        ret
1070
 
1071
endp
1072
 
1073
 
1074
 
1075
 
1076
; Write a word data to PHY Chip
1077
 
1078
align 4
1079
proc  phy_write stdcall, phy_addr:dword, reg:dword, val:dword
1080
 
4597 hidnplayr 1081
        DEBUGF  1,"PHY write, addr=0x%x reg=0x%x val=0x%x\n", \
1082
        [phy_addr]:8, [reg]:8, [val]:8
3545 hidnplayr 1083
 
1084
        mov     eax, [val]
4597 hidnplayr 1085
        set_io  [ebx + device.io_addr], 0
1086
        set_io  [ebx + device.io_addr], MMWD
3545 hidnplayr 1087
        out     dx, ax
1088
 
1089
        ;Write the command to the MDIO bus
1090
        mov     eax, [phy_addr]
1091
        shl     eax, 8
1092
        add     eax, [reg]
1093
        add     eax, MDIO_WRITE
4597 hidnplayr 1094
        set_io  [ebx + device.io_addr], MMDIO
3545 hidnplayr 1095
        out     dx, ax
1096
 
1097
        ;Wait for the write bit to be cleared.
1098
        mov     ecx, 2048 ;limit
1099
  .write:
1100
        in      ax, dx
1101
        test    ax, MDIO_WRITE
1102
        jz      @f
1103
        dec     ecx
1104
        jnz     .write
1105
  @@:
1106
 
4439 hidnplayr 1107
        DEBUGF  1,"PHY write ok\n"
3545 hidnplayr 1108
 
1109
        ret
1110
endp
1111
 
1112
 
1113
 
1114
align 4
1115
read_mac:
1116
 
4450 hidnplayr 1117
        DEBUGF  1,"Reading MAC:\n"
3545 hidnplayr 1118
 
1119
        mov     cx, 3
4597 hidnplayr 1120
        lea     edi, [ebx + device.mac]
1121
        set_io  [ebx + device.io_addr], 0
1122
        set_io  [ebx + device.io_addr], MID_0L
5522 hidnplayr 1123
  .loop:
3545 hidnplayr 1124
        in      ax, dx
1125
        stosw
1126
        inc     dx
1127
        inc     dx
1128
        dec     cx
5522 hidnplayr 1129
        jnz     .loop
3545 hidnplayr 1130
 
4597 hidnplayr 1131
        DEBUGF  1,"%x-%x-%x-%x-%x-%x\n",\
1132
        [edi-6]:2, [edi-5]:2, [edi-4]:2, [edi-3]:2, [edi-2]:2, [edi-1]:2
3545 hidnplayr 1133
 
1134
        ret
1135
 
1136
 
1137
 
1138
 
1139
; End of code
1140
 
4597 hidnplayr 1141
data fixups
1142
end data
3545 hidnplayr 1143
 
4597 hidnplayr 1144
include '../peimport.inc'
1145
 
3545 hidnplayr 1146
my_service      db 'R6040',0                    ; max 16 chars include zero
1147
 
4597 hidnplayr 1148
include_debug_strings
3545 hidnplayr 1149
 
4597 hidnplayr 1150
align 4
1151
devices         dd 0
3545 hidnplayr 1152
device_list     rd MAX_DEVICES                  ; This list contains all pointers to device structures the driver is handling
1153