Subversion Repositories Kolibri OS

Rev

Rev 4334 | Go to most recent revision | Details | Last modification | View Log | RSS feed

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