Subversion Repositories Kolibri OS

Rev

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