Subversion Repositories Kolibri OS

Rev

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

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