Subversion Repositories Kolibri OS

Rev

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

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