Subversion Repositories Kolibri OS

Rev

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