Subversion Repositories Kolibri OS

Rev

Rev 5127 | Rev 5522 | 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
 
140
MAX_BUF_SIZE    = 0x600                 ; 1536
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
399
        ; - Remove device from local list (RTL8139_LIST)
400
        ; - call unregister function in kernel
401
        ; - Remove all allocated structures and buffers the card used
402
 
403
        or      eax,-1
404
 
405
ret
406
 
407
 
408
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
409
;;
4450 hidnplayr 410
;;  probe: enables the device (if it really is R6040)
3545 hidnplayr 411
;;
412
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
413
 
414
align 4
415
probe:
4597 hidnplayr 416
        DEBUGF  1,"Probing\n"
3545 hidnplayr 417
 
4597 hidnplayr 418
; Make the device a bus master
419
        invoke  PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command
420
        or      al, PCI_CMD_MASTER
421
        invoke  PciWrite32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command, eax
3545 hidnplayr 422
 
423
        ; If PHY status change register is still set to zero
424
        ; it means the bootloader didn't initialize it
425
 
4597 hidnplayr 426
        set_io  [ebx + device.io_addr], 0
427
        set_io  [ebx + device.io_addr], PHY_CC
3545 hidnplayr 428
        in      ax, dx
429
        test    ax, ax
430
        jnz     @f
431
        mov     ax, 0x9F07
432
        out     dx, ax
433
     @@:
434
 
435
        call    read_mac
436
 
437
        ; Some bootloaders/BIOSes do not initialize MAC address, warn about that
438
        and     eax, 0xFF
4597 hidnplayr 439
        or      eax, dword [ebx + device.mac]
3545 hidnplayr 440
        test    eax, eax
441
        jnz     @f
4439 hidnplayr 442
        DEBUGF  2, "MAC address not initialized!\n"
3545 hidnplayr 443
 
444
     @@:
445
        ; Init RDC private data
4597 hidnplayr 446
        mov     [ebx + device.mcr0], MCR0_XMTEN or MCR0_RCVEN
447
        mov     [ebx + device.phy_addr], PHY1_ADDR
448
        mov     [ebx + device.switch_sig], 0
3545 hidnplayr 449
 
450
        ; Check the vendor ID on the PHY, if 0xFFFF assume none attached
4597 hidnplayr 451
        stdcall phy_read, [ebx + device.phy_addr], 2
3545 hidnplayr 452
        cmp     ax, 0xFFFF
453
        jne     @f
4450 hidnplayr 454
        DEBUGF  2, "Failed to detect an attached PHY!\n"
3545 hidnplayr 455
        mov     eax, -1
456
        ret
457
     @@:
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
465
 
466
        ; Read the PHY ID
4597 hidnplayr 467
        mov     [ebx + device.phy_mode], MCR0_FD
3545 hidnplayr 468
        stdcall phy_read, 0, 2
4597 hidnplayr 469
        mov     [ebx + device.switch_sig], ax
3545 hidnplayr 470
        cmp     ax, ICPLUS_PHY_ID
471
        jne     @f
472
        stdcall phy_write, 29, 31, 0x175C ; Enable registers
473
        jmp     .phy_readen
474
      @@:
475
 
476
        ; PHY Mode Check
4597 hidnplayr 477
        stdcall phy_write, [ebx + device.phy_addr], 4, PHY_CAP
478
        stdcall phy_write, [ebx + device.phy_addr], 0, PHY_MODE
3545 hidnplayr 479
 
480
      if PHY_MODE = 0x3100
481
        call    phy_mode_chk
4597 hidnplayr 482
        mov     [ebx + device.phy_mode], ax
3545 hidnplayr 483
        jmp     .phy_readen
484
      end if
485
 
486
      if not (PHY_MODE and 0x0100)
4597 hidnplayr 487
        mov     [ebx + device.phy_mode], 0
3545 hidnplayr 488
      end if
489
 
490
      .phy_readen:
491
 
492
        ; Set duplex mode
4597 hidnplayr 493
        mov     ax, [ebx + device.phy_mode]
494
        or      [ebx + device.mcr0], ax
3545 hidnplayr 495
 
496
        ; improve performance (by RDC guys)
497
        stdcall phy_read, 30, 17
498
        or      ax, 0x4000
499
        stdcall phy_write, 30, 17, eax
500
 
501
        stdcall phy_read, 30, 17
502
        and     ax, not 0x2000
503
        stdcall phy_write, 30, 17, eax
504
 
505
        stdcall phy_write, 0, 19, 0x0000
506
        stdcall phy_write, 0, 30, 0x01F0
507
 
508
        ; Initialize all Mac registers
509
        call    init_mac_regs
510
 
511
 
512
align 4
513
reset:
514
 
4597 hidnplayr 515
        DEBUGF  1,"Resetting\n"
3545 hidnplayr 516
 
517
        ; Mask off Interrupt
518
        xor     ax, ax
4597 hidnplayr 519
        set_io  [ebx + device.io_addr], 0
520
        set_io  [ebx + device.io_addr], MIER
3545 hidnplayr 521
        out     dx, ax
522
 
523
; attach int handler
524
 
4597 hidnplayr 525
        movzx   eax, [ebx + device.irq_line]
4439 hidnplayr 526
        DEBUGF  1,"Attaching int handler to irq %x\n", eax:1
4597 hidnplayr 527
        invoke  AttachIntHandler, eax, int_handler, ebx
3545 hidnplayr 528
        test    eax, eax
529
        jnz     @f
4439 hidnplayr 530
        DEBUGF  2,"Could not attach int handler!\n"
4597 hidnplayr 531
        or      eax, -1
532
        ret
3545 hidnplayr 533
       @@:
534
 
535
        ;Reset RDC MAC
536
        mov     eax, MAC_RST
4597 hidnplayr 537
        set_io  [ebx + device.io_addr], 0
538
        set_io  [ebx + device.io_addr], MCR1
3545 hidnplayr 539
        out     dx, ax
540
 
541
        mov     ecx, 2048 ;limit
542
  .read:
543
        in      ax, dx
544
        test    ax, 0x1
545
        jnz      @f
546
        dec     ecx
547
        test    ecx, ecx
548
        jnz     .read
549
  @@:
550
        ;Reset internal state machine
551
        mov     ax,  2
4597 hidnplayr 552
        set_io  [ebx + device.io_addr], MAC_SM
3545 hidnplayr 553
        out     dx, ax
554
 
555
        xor     ax, ax
556
        out     dx, ax
557
 
558
        mov     esi, 5
4597 hidnplayr 559
        invoke  Sleep
3545 hidnplayr 560
 
561
        ;MAC Bus Control Register
562
        mov     ax, MBCR_DEFAULT
4597 hidnplayr 563
        set_io  [ebx + device.io_addr], 0
564
        set_io  [ebx + device.io_addr], MBCR
3545 hidnplayr 565
        out     dx, ax
566
 
567
        ;Buffer Size Register
568
        mov     ax, MAX_BUF_SIZE
4597 hidnplayr 569
        set_io  [ebx + device.io_addr], MR_BSR
3545 hidnplayr 570
        out     dx, ax
571
 
572
        ;Write TX ring start address
4597 hidnplayr 573
        lea     eax, [ebx + device.tx_ring]
574
        invoke  GetPhysAddr
575
        set_io  [ebx + device.io_addr], MTD_SA0
3545 hidnplayr 576
        out     dx, ax
577
        shr     eax, 16
4597 hidnplayr 578
        set_io  [ebx + device.io_addr], MTD_SA1
3545 hidnplayr 579
        out     dx, ax
580
 
581
        ;Write RX ring start address
4597 hidnplayr 582
        lea     eax, [ebx + device.rx_ring]
583
        invoke  GetPhysAddr
584
        set_io  [ebx + device.io_addr], MRD_SA0
3545 hidnplayr 585
        out     dx, ax
586
        shr     eax, 16
4597 hidnplayr 587
        set_io  [ebx + device.io_addr], MRD_SA1
3545 hidnplayr 588
        out     dx, ax
589
 
590
        ;Set interrupt waiting time and packet numbers
591
        xor     ax, ax
4597 hidnplayr 592
        set_io  [ebx + device.io_addr], MT_ICR
3545 hidnplayr 593
        out     dx, ax
594
 
595
        ;Enable interrupts
596
        mov     ax, INT_MASK
4597 hidnplayr 597
        set_io  [ebx + device.io_addr], MIER
3545 hidnplayr 598
        out     dx, ax
599
 
4439 hidnplayr 600
        ;Enable RX
4597 hidnplayr 601
        mov     ax, [ebx + device.mcr0]
4439 hidnplayr 602
        or      ax, MCR0_RCVEN
4597 hidnplayr 603
        set_io  [ebx + device.io_addr], 0
3545 hidnplayr 604
        out     dx, ax
605
 
606
        ;Let TX poll the descriptors
4597 hidnplayr 607
        ;we may got called by tx_timeout which has left some unset tx buffers
3545 hidnplayr 608
        xor     ax, ax
609
        inc     ax
4597 hidnplayr 610
        set_io  [ebx + device.io_addr], MTPR
3545 hidnplayr 611
        out     dx, ax
612
 
613
; Set the mtu, kernel will be able to send now
4597 hidnplayr 614
        mov     [ebx + device.mtu], 1514
3545 hidnplayr 615
 
616
; Set link state to unknown
4597 hidnplayr 617
        mov     [ebx + device.state], ETH_LINK_UNKNOWN
3545 hidnplayr 618
 
619
        DEBUGF  1,"Reset ok\n"
620
        xor     eax, eax
621
        ret
622
 
623
 
624
 
625
align 4
626
init_txbufs:
627
 
628
        DEBUGF  1,"Init TxBufs\n"
629
 
4597 hidnplayr 630
        lea     esi, [ebx + device.tx_ring]
631
        lea     eax, [ebx + device.tx_ring + sizeof.x_head]
632
        invoke  GetPhysAddr
3545 hidnplayr 633
        mov     ecx, TX_RING_SIZE
634
 
635
    .next_desc:
636
        mov     [esi + x_head.ndesc], eax
637
        mov     [esi + x_head.skb_ptr], 0
638
        mov     [esi + x_head.status], DSC_OWNER_MAC
4597 hidnplayr 639
        add     eax, sizeof.x_head
640
        add     esi, sizeof.x_head
3545 hidnplayr 641
        dec     ecx
642
        jnz     .next_desc
643
 
4597 hidnplayr 644
        lea     eax, [ebx + device.tx_ring]
645
        invoke  GetPhysAddr
646
        mov     dword[ebx + device.tx_ring + sizeof.x_head*(TX_RING_SIZE-1) + x_head.ndesc], eax
3545 hidnplayr 647
 
648
        ret
649
 
650
 
651
 
652
align 4
653
init_rxbufs:
654
 
655
        DEBUGF  1,"Init RxBufs\n"
656
 
4597 hidnplayr 657
        lea     esi, [ebx + device.rx_ring]
658
        lea     eax, [ebx + device.rx_ring + sizeof.x_head]
659
        invoke  GetPhysAddr
3545 hidnplayr 660
        mov     edx, eax
661
        mov     ecx, RX_RING_SIZE
662
 
663
    .next_desc:
4439 hidnplayr 664
        mov     [esi + x_head.ndesc], edx
3545 hidnplayr 665
 
4439 hidnplayr 666
        push    esi ecx edx
4597 hidnplayr 667
        invoke  KernelAlloc, MAX_BUF_SIZE
4439 hidnplayr 668
        pop     edx ecx esi
3545 hidnplayr 669
 
670
        mov     [esi + x_head.skb_ptr], eax
4597 hidnplayr 671
        invoke  GetPhysAddr
3545 hidnplayr 672
        mov     [esi + x_head.buf], eax
673
        mov     [esi + x_head.status], DSC_OWNER_MAC
674
 
4597 hidnplayr 675
        add     edx, sizeof.x_head
676
        add     esi, sizeof.x_head
3545 hidnplayr 677
 
678
        dec     ecx
679
        jnz     .next_desc
680
 
4439 hidnplayr 681
; complete the ring by linking the last to the first
4597 hidnplayr 682
        lea     eax, [ebx + device.rx_ring]
683
        invoke  GetPhysAddr
684
        mov     dword[ebx + device.rx_ring + sizeof.x_head*(RX_RING_SIZE-1) + x_head.ndesc], eax
3545 hidnplayr 685
 
686
        ret
687
 
688
 
689
 
690
align 4
691
phy_mode_chk:
692
 
693
        DEBUGF  1,"Checking PHY mode\n"
694
 
695
        ; PHY Link Status Check
4597 hidnplayr 696
        stdcall phy_read, [ebx + device.phy_addr], MII_BMSR
4450 hidnplayr 697
        test    ax, BMSR_LSTATUS
3545 hidnplayr 698
        jz      .ret_0x8000
699
 
700
        ; PHY Chip Auto-Negotiation Status
4450 hidnplayr 701
        test    ax, BMSR_ANEGCOMPLETE
3545 hidnplayr 702
        jnz     .auto_nego
703
 
704
        ; Force Mode
4597 hidnplayr 705
        stdcall phy_read, [ebx + device.phy_addr], MII_BMCR
4450 hidnplayr 706
        test    ax, BMCR_FULLDPLX
3545 hidnplayr 707
        jnz     .ret_0x8000
708
 
709
  .auto_nego:
710
        ; Auto Negotiation Mode
4597 hidnplayr 711
        stdcall phy_read, [ebx + device.phy_addr], MII_LPA
4450 hidnplayr 712
        mov     cx, ax
4597 hidnplayr 713
        stdcall phy_read, [ebx + device.phy_addr], MII_ADVERTISE
4450 hidnplayr 714
        and     ax, cx
715
        test    ax, ADVERTISE_10FULL + ADVERTISE_100FULL
3545 hidnplayr 716
        jnz     .ret_0x8000
717
 
718
        xor     eax, eax
719
        ret
720
 
721
  .ret_0x8000:
722
        mov     eax, 0x8000
723
        ret
724
 
725
 
726
 
727
 
728
 
729
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
730
;;                                         ;;
731
;; Transmit                                ;;
732
;;                                         ;;
4597 hidnplayr 733
;; In: pointer to device structure in ebx  ;;
3545 hidnplayr 734
;;                                         ;;
735
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4597 hidnplayr 736
 
737
proc transmit stdcall bufferptr, buffersize
738
 
739
        pushf
740
        cli
741
 
742
        DEBUGF  1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [buffersize]
743
        mov     eax, [bufferptr]
4439 hidnplayr 744
        DEBUGF  1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
3545 hidnplayr 745
        [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
746
        [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
747
        [eax+13]:2,[eax+12]:2
748
 
4597 hidnplayr 749
        cmp     [buffersize], 1514
3545 hidnplayr 750
        ja      .fail
4597 hidnplayr 751
        cmp     [buffersize], 60
3545 hidnplayr 752
        jb      .fail
753
 
4597 hidnplayr 754
        movzx   edi, [ebx + device.cur_tx]
3545 hidnplayr 755
        shl     edi, 5
756
        add     edi, ebx
4597 hidnplayr 757
        add     edi, device.tx_ring
3545 hidnplayr 758
 
4439 hidnplayr 759
        DEBUGF  1,"TX buffer status: 0x%x\n", [edi + x_head.status]:4
3545 hidnplayr 760
 
761
        test    [edi + x_head.status], DSC_OWNER_MAC    ; check if buffer is available
762
        jnz     .wait_to_send
763
 
764
  .do_send:
4439 hidnplayr 765
        DEBUGF  1,"Sending now\n"
3545 hidnplayr 766
 
4597 hidnplayr 767
        mov     eax, [bufferptr]
3545 hidnplayr 768
        mov     [edi + x_head.skb_ptr], eax
4597 hidnplayr 769
        invoke  GetPhysAddr
3545 hidnplayr 770
        mov     [edi + x_head.buf], eax
4597 hidnplayr 771
        mov     ecx, [buffersize]
3545 hidnplayr 772
        mov     [edi + x_head.len], cx
773
        mov     [edi + x_head.status], DSC_OWNER_MAC
774
 
775
        ; Trigger the MAC to check the TX descriptor
776
        mov     ax, 0x01
4597 hidnplayr 777
        set_io  [ebx + device.io_addr], 0
778
        set_io  [ebx + device.io_addr], MTPR
3545 hidnplayr 779
        out     dx, ax
780
 
4597 hidnplayr 781
        inc     [ebx + device.cur_tx]
782
        and     [ebx + device.cur_tx], TX_RING_SIZE - 1
3545 hidnplayr 783
 
784
; Update stats
4597 hidnplayr 785
        inc     [ebx + device.packets_tx]
786
        mov     eax, [buffersize]
787
        add     dword[ebx + device.bytes_tx], eax
788
        adc     dword[ebx + device.bytes_tx + 4], 0
3545 hidnplayr 789
 
5127 hidnplayr 790
        popf
4450 hidnplayr 791
        xor     eax, eax
4597 hidnplayr 792
        ret
3545 hidnplayr 793
 
794
  .wait_to_send:
4439 hidnplayr 795
        DEBUGF  1,"Waiting for TX buffer\n"
3545 hidnplayr 796
 
4597 hidnplayr 797
        invoke  GetTimerTicks           ; returns in eax
3545 hidnplayr 798
        lea     edx, [eax + 100]
799
     .l2:
800
        test    [edi + x_head.status], DSC_OWNER_MAC
801
        jz      .do_send
802
        mov     esi, 10
4597 hidnplayr 803
        invoke  Sleep
804
        invoke  GetTimerTicks
3545 hidnplayr 805
        cmp     edx, eax
806
        jb      .l2
807
 
4439 hidnplayr 808
        DEBUGF  2,"Send timeout\n"
3545 hidnplayr 809
  .fail:
4439 hidnplayr 810
        DEBUGF  2,"Send failed\n"
4597 hidnplayr 811
        invoke  KernelFree, [bufferptr]
812
        popf
4334 hidnplayr 813
        or      eax, -1
4597 hidnplayr 814
        ret
3545 hidnplayr 815
 
4597 hidnplayr 816
endp
3545 hidnplayr 817
 
818
 
819
 
820
;;;;;;;;;;;;;;;;;;;;;;;
821
;;                   ;;
822
;; Interrupt handler ;;
823
;;                   ;;
824
;;;;;;;;;;;;;;;;;;;;;;;
825
 
826
align 4
827
int_handler:
828
 
829
        push    ebx esi edi
830
 
4439 hidnplayr 831
        DEBUGF  1,"int\n"
3545 hidnplayr 832
 
833
; Find pointer of device wich made IRQ occur
834
 
835
        mov     ecx, [devices]
836
        test    ecx, ecx
837
        jz      .nothing
838
        mov     esi, device_list
839
  .nextdevice:
840
        mov     ebx, [esi]
841
 
4597 hidnplayr 842
        set_io  [ebx + device.io_addr], 0
843
        set_io  [ebx + device.io_addr], MISR
3545 hidnplayr 844
        in      ax, dx
845
        out     dx, ax                  ; send it back to ACK
846
        test    ax, ax
847
        jnz     .got_it
848
  .continue:
849
        add     esi, 4
850
        dec     ecx
851
        jnz     .nextdevice
852
  .nothing:
853
        pop     edi esi ebx
854
        xor     eax, eax
855
 
4597 hidnplayr 856
        ret                             ; If no device was found, abort
3545 hidnplayr 857
 
858
; At this point, test for all possible reasons, and handle accordingly
859
 
860
  .got_it:
861
 
4439 hidnplayr 862
        DEBUGF  1,"Device: %x Status: %x\n", ebx, ax
3545 hidnplayr 863
 
864
        push ax
865
 
4439 hidnplayr 866
        test    word[esp], RX_FINISH
3545 hidnplayr 867
        jz      .no_RX
868
 
869
        push    ebx
870
  .more_RX:
871
        pop     ebx
872
 
873
        ; Find the current RX descriptor
4597 hidnplayr 874
        movzx   edx, [ebx + device.cur_rx]
3545 hidnplayr 875
        shl     edx, 5
4597 hidnplayr 876
        lea     edx, [ebx + device.rx_ring + edx]
3545 hidnplayr 877
 
878
        ; Check the descriptor status
879
        mov     cx, [edx + x_head.status]
880
        test    cx, DSC_OWNER_MAC
881
        jnz     .no_RX
882
 
4439 hidnplayr 883
        DEBUGF  1,"packet status=0x%x\n", cx
3545 hidnplayr 884
 
885
        test    cx, DSC_RX_ERR          ; Global error status set
886
        jnz     .no_RX
887
 
888
        ; Packet successfully received
889
        movzx   ecx, [edx + x_head.len]
890
        and     ecx, 0xFFF
891
        sub     ecx, 4                  ; Do not count the CRC
892
 
4439 hidnplayr 893
        ; Update stats
4597 hidnplayr 894
        add     dword[ebx + device.bytes_rx], ecx
895
        adc     dword[ebx + device.bytes_rx + 4], 0
896
        inc     dword[ebx + device.packets_rx]
3545 hidnplayr 897
 
898
        ; Push packet size and pointer, kernel will need it..
899
        push    ebx
900
        push    .more_RX
901
 
902
        push    ecx
903
        push    [edx + x_head.skb_ptr]
904
 
4439 hidnplayr 905
        DEBUGF  1,"packet ptr=0x%x\n", [edx + x_head.skb_ptr]
3545 hidnplayr 906
 
907
        ; reset the RX descriptor
908
        push    edx
4597 hidnplayr 909
        invoke  KernelAlloc, MAX_BUF_SIZE
3545 hidnplayr 910
        pop     edx
911
        mov     [edx + x_head.skb_ptr], eax
4597 hidnplayr 912
        invoke  GetPhysAddr
3545 hidnplayr 913
        mov     [edx + x_head.buf], eax
914
        mov     [edx + x_head.status], DSC_OWNER_MAC
915
 
916
        ; Use next descriptor next time
4597 hidnplayr 917
        inc     [ebx + device.cur_rx]
918
        and     [ebx + device.cur_rx], RX_RING_SIZE - 1
3545 hidnplayr 919
 
920
        ; At last, send packet to kernel
4597 hidnplayr 921
        jmp     [Eth_input]
3545 hidnplayr 922
 
923
 
924
  .no_RX:
925
 
4439 hidnplayr 926
        test    word[esp], TX_FINISH
3545 hidnplayr 927
        jz      .no_TX
928
 
929
      .loop_tx:
4597 hidnplayr 930
        movzx   edi, [ebx + device.last_tx]
3545 hidnplayr 931
        shl     edi, 5
4597 hidnplayr 932
        lea     edi, [ebx + device.tx_ring + edi]
3545 hidnplayr 933
 
934
        test    [edi + x_head.status], DSC_OWNER_MAC
935
        jnz     .no_TX
936
 
937
        cmp     [edi + x_head.skb_ptr], 0
938
        je      .no_TX
939
 
4439 hidnplayr 940
        DEBUGF  1,"Freeing buffer 0x%x\n", [edi + x_head.skb_ptr]
3545 hidnplayr 941
 
942
        push    [edi + x_head.skb_ptr]
943
        mov     [edi + x_head.skb_ptr], 0
4597 hidnplayr 944
        invoke  KernelFree
3545 hidnplayr 945
 
4597 hidnplayr 946
        inc     [ebx + device.last_tx]
947
        and     [ebx + device.last_tx], TX_RING_SIZE - 1
3545 hidnplayr 948
 
949
        jmp     .loop_tx
950
 
951
  .no_TX:
4439 hidnplayr 952
        test    word[esp], RX_NO_DESC
953
        jz      .no_rxdesc
954
 
955
        DEBUGF  2, "No more RX descriptors!\n"
956
 
957
  .no_rxdesc:
958
        test    word[esp], RX_FIFO_FULL
959
        jz      .no_rxfifo
960
 
961
        DEBUGF  2, "RX FIFO full!\n"
962
 
963
  .no_rxfifo:
964
        test    word[esp], RX_EARLY
965
        jz      .no_rxearly
966
 
4450 hidnplayr 967
        DEBUGF  2, "RX early\n"
4439 hidnplayr 968
 
969
  .no_rxearly:
970
        test    word[esp], TX_EARLY
971
        jz      .no_txearly
972
 
4450 hidnplayr 973
        DEBUGF  2, "TX early\n"
4439 hidnplayr 974
 
975
  .no_txearly:
976
        test    word[esp], EVENT_OVRFL
977
        jz      .no_ovrfl
978
 
979
        DEBUGF  2, "Event counter overflow!\n"
980
 
981
  .no_ovrfl:
982
        test    word[esp], LINK_CHANGED
983
        jz      .no_link
984
 
4450 hidnplayr 985
        DEBUGF  2, "Link changed\n"
4439 hidnplayr 986
 
987
  .no_link:
3545 hidnplayr 988
        pop     ax
989
 
990
        pop     edi esi ebx
991
 
992
        ret
993
 
994
 
995
 
996
 
997
align 4
998
init_mac_regs:
999
 
4439 hidnplayr 1000
        DEBUGF  1,"initializing MAC regs\n"
3545 hidnplayr 1001
 
1002
        ; MAC operation register
1003
        mov     ax, 1
4597 hidnplayr 1004
        set_io  [ebx + device.io_addr], 0
1005
        set_io  [ebx + device.io_addr], MCR1
3545 hidnplayr 1006
        out     dx, ax
1007
        ; Reset MAC
1008
        mov     ax, 2
4597 hidnplayr 1009
        set_io  [ebx + device.io_addr], MAC_SM
3545 hidnplayr 1010
        out     dx, ax
1011
        ; Reset internal state machine
1012
        xor     ax, ax
1013
        out     dx, ax
1014
        mov     esi, 5
4597 hidnplayr 1015
        invoke  Sleep
3545 hidnplayr 1016
 
1017
        call    read_mac
1018
 
1019
        ret
1020
 
1021
 
1022
 
1023
 
1024
; Read a word data from PHY Chip
1025
 
1026
align 4
1027
proc  phy_read stdcall, phy_addr:dword, reg:dword
1028
 
4439 hidnplayr 1029
        DEBUGF  1,"PHY read, addr=0x%x reg=0x%x\n", [phy_addr]:8, [reg]:8
3545 hidnplayr 1030
 
1031
        mov     eax, [phy_addr]
1032
        shl     eax, 8
1033
        add     eax, [reg]
1034
        add     eax, MDIO_READ
4597 hidnplayr 1035
        set_io  [ebx + device.io_addr], 0
1036
        set_io  [ebx + device.io_addr], MMDIO
3545 hidnplayr 1037
        out     dx, ax
1038
 
1039
        ;Wait for the read bit to be cleared.
1040
        mov     ecx, 2048 ;limit
1041
  .read:
1042
        in      ax, dx
1043
        test    ax, MDIO_READ
1044
        jz      @f
1045
        dec     ecx
1046
        jnz     .read
1047
  @@:
1048
 
4597 hidnplayr 1049
        set_io  [ebx + device.io_addr],   MMRD
3545 hidnplayr 1050
        in      ax, dx
1051
        and     eax, 0xFFFF
1052
 
4439 hidnplayr 1053
        DEBUGF  1,"PHY read, val=0x%x\n", eax:4
3545 hidnplayr 1054
 
1055
        ret
1056
 
1057
endp
1058
 
1059
 
1060
 
1061
 
1062
; Write a word data to PHY Chip
1063
 
1064
align 4
1065
proc  phy_write stdcall, phy_addr:dword, reg:dword, val:dword
1066
 
4597 hidnplayr 1067
        DEBUGF  1,"PHY write, addr=0x%x reg=0x%x val=0x%x\n", \
1068
        [phy_addr]:8, [reg]:8, [val]:8
3545 hidnplayr 1069
 
1070
        mov     eax, [val]
4597 hidnplayr 1071
        set_io  [ebx + device.io_addr], 0
1072
        set_io  [ebx + device.io_addr], MMWD
3545 hidnplayr 1073
        out     dx, ax
1074
 
1075
        ;Write the command to the MDIO bus
1076
        mov     eax, [phy_addr]
1077
        shl     eax, 8
1078
        add     eax, [reg]
1079
        add     eax, MDIO_WRITE
4597 hidnplayr 1080
        set_io  [ebx + device.io_addr], MMDIO
3545 hidnplayr 1081
        out     dx, ax
1082
 
1083
        ;Wait for the write bit to be cleared.
1084
        mov     ecx, 2048 ;limit
1085
  .write:
1086
        in      ax, dx
1087
        test    ax, MDIO_WRITE
1088
        jz      @f
1089
        dec     ecx
1090
        jnz     .write
1091
  @@:
1092
 
4439 hidnplayr 1093
        DEBUGF  1,"PHY write ok\n"
3545 hidnplayr 1094
 
1095
        ret
1096
endp
1097
 
1098
 
1099
 
1100
align 4
1101
read_mac:
1102
 
4450 hidnplayr 1103
        DEBUGF  1,"Reading MAC:\n"
3545 hidnplayr 1104
 
1105
        mov     cx, 3
4597 hidnplayr 1106
        lea     edi, [ebx + device.mac]
1107
        set_io  [ebx + device.io_addr], 0
1108
        set_io  [ebx + device.io_addr], MID_0L
3545 hidnplayr 1109
     .mac:
1110
        in      ax, dx
1111
        stosw
1112
        inc     dx
1113
        inc     dx
1114
        dec     cx
1115
        jnz     .mac
1116
 
4597 hidnplayr 1117
        DEBUGF  1,"%x-%x-%x-%x-%x-%x\n",\
1118
        [edi-6]:2, [edi-5]:2, [edi-4]:2, [edi-3]:2, [edi-2]:2, [edi-1]:2
3545 hidnplayr 1119
 
1120
        ret
1121
 
1122
 
1123
 
1124
 
1125
; End of code
1126
 
4597 hidnplayr 1127
data fixups
1128
end data
3545 hidnplayr 1129
 
4597 hidnplayr 1130
include '../peimport.inc'
1131
 
3545 hidnplayr 1132
my_service      db 'R6040',0                    ; max 16 chars include zero
1133
 
4597 hidnplayr 1134
include_debug_strings
3545 hidnplayr 1135
 
4597 hidnplayr 1136
align 4
1137
devices         dd 0
3545 hidnplayr 1138
device_list     rd MAX_DEVICES                  ; This list contains all pointers to device structures the driver is handling
1139