Subversion Repositories Kolibri OS

Rev

Rev 4449 | 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
;;                                                                 ;;
4449 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
;;  Realtek 8139 driver for KolibriOS                              ;;
7
;;                                                                 ;;
8
;;  based on RTL8139.asm driver for menuetos                       ;;
9
;;  and realtek8139.asm for SolarOS by Eugen Brasoveanu            ;;
10
;;                                                                 ;;
11
;;    Written by hidnplayr@kolibrios.org                           ;;
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
        RBLEN                   = 3 ; Receive buffer size: 0==8K 1==16k 2==32k 3==64k
26
 
3857 hidnplayr 27
        TXRR                    = 8 ; total retries = 16+(TXRR*16)
28
        TX_MXDMA                = 6 ; 0=16 1=32 2=64 3=128 4=256 5=512 6=1024 7=2048
29
        ERTXTH                  = 8 ; in unit of 32 bytes e.g:(8*32)=256
30
        RX_MXDMA                = 7 ; 0=16 1=32 2=64 3=128 4=256 5=512 6=1024 7=unlimited
31
        RXFTH                   = 7 ; 0=16 1=32 2=64 3=128 4=256 5=512 6=1024 7=no threshold
32
 
3545 hidnplayr 33
        DEBUG                   = 1
34
        __DEBUG__               = 1
3856 hidnplayr 35
        __DEBUG_LEVEL__         = 2             ; 1 = verbose, 2 = errors only
3545 hidnplayr 36
 
4467 hidnplayr 37
include '../struct.inc'
38
include '../macros.inc'
3545 hidnplayr 39
include '../proc32.inc'
40
include '../imports.inc'
41
include '../fdo.inc'
42
include '../netdrv.inc'
43
 
44
public START
45
public service_proc
46
public version
47
 
48
        REG_IDR0                = 0x00
49
        REG_MAR0                = 0x08 ; multicast filter register 0
50
        REG_MAR4                = 0x0c ; multicast filter register 4
51
        REG_TSD0                = 0x10 ; transmit status of descriptor
52
        REG_TSAD0               = 0x20 ; transmit start address of descriptor
53
        REG_RBSTART             = 0x30 ; RxBuffer start address
54
        REG_COMMAND             = 0x37 ; command register
55
        REG_CAPR                = 0x38 ; current address of packet read (word) R/W
56
        REG_IMR                 = 0x3c ; interrupt mask register
57
        REG_ISR                 = 0x3e ; interrupt status register
58
        REG_TXCONFIG            = 0x40 ; transmit configuration register
59
        REG_RXCONFIG            = 0x44 ; receive configuration register 0
60
        REG_MPC                 = 0x4c ; missed packet counter
61
        REG_9346CR              = 0x50 ; serial eeprom 93C46 command register
62
        REG_CONFIG1             = 0x52 ; configuration register 1
63
        REG_MSR                 = 0x58
64
        REG_CONFIG4             = 0x5a ; configuration register 4
65
        REG_HLTCLK              = 0x5b ; undocumented halt clock register
66
        REG_BMCR                = 0x62 ; basic mode control register
67
        REG_ANAR                = 0x66 ; auto negotiation advertisement register
68
        REG_9346CR_WE           = 11b shl 6
69
 
70
        BIT_RUNT                = 4 ; total packet length < 64 bytes
71
        BIT_LONG                = 3 ; total packet length > 4k
72
        BIT_CRC                 = 2 ; crc error occured
73
        BIT_FAE                 = 1 ; frame alignment error occured
74
        BIT_ROK                 = 0 ; received packet is ok
75
 
76
        BIT_RST                 = 4 ; reset bit
77
        BIT_RE                  = 3 ; receiver enabled
78
        BIT_TE                  = 2 ; transmitter enabled
79
        BUFE                    = 1 ; rx buffer is empty, no packet stored
80
 
81
        BIT_ISR_TOK             = 2 ; transmit ok
82
        BIT_ISR_RER             = 1 ; receive error interrupt
83
        BIT_ISR_ROK             = 0 ; receive ok
84
 
85
        BIT_TX_MXDMA            = 8 ; Max DMA burst size per Tx DMA burst
86
        BIT_TXRR                = 4 ; Tx Retry count 16+(TXRR*16)
87
 
88
        BIT_RXFTH               = 13 ; Rx fifo threshold
89
        BIT_RBLEN               = 11 ; Ring buffer length indicator
90
        BIT_RX_MXDMA            = 8 ; Max DMA burst size per Rx DMA burst
91
        BIT_NOWRAP              = 7 ; transfered data wrapping
92
        BIT_9356SEL             = 6 ; eeprom selector 9346/9356
93
        BIT_AER                 = 5 ; accept error packets
94
        BIT_AR                  = 4 ; accept runt packets
95
        BIT_AB                  = 3 ; accept broadcast packets
96
        BIT_AM                  = 2 ; accept multicast packets
97
        BIT_APM                 = 1 ; accept physical match packets
98
        BIT_AAP                 = 0 ; accept all packets
99
 
100
        BIT_93C46_EEM1          = 7 ; RTL8139 eeprom operating mode1
101
        BIT_93C46_EEM0          = 6 ; RTL8139 eeprom operating mode0
102
        BIT_93C46_EECS          = 3 ; chip select
103
        BIT_93C46_EESK          = 2 ; serial data clock
104
        BIT_93C46_EEDI          = 1 ; serial data input
105
        BIT_93C46_EEDO          = 0 ; serial data output
106
 
107
        BIT_LWACT               = 4 ; see REG_CONFIG1
108
        BIT_SLEEP               = 1 ; sleep bit at older chips
109
        BIT_PWRDWN              = 0 ; power down bit at older chips
110
        BIT_PMEn                = 0 ; power management enabled
111
 
112
        BIT_LWPTN               = 2 ; see REG_CONFIG4
113
 
114
        BIT_ERTXTH              = 16 ; early TX threshold
115
        BIT_TOK                 = 15 ; transmit ok
116
        BIT_OWN                 = 13 ; tx DMA operation is completed
117
 
118
        BIT_ANE                 = 12 ; auto negotiation enable
119
 
120
        BIT_TXFD                = 8 ; 100base-T full duplex
121
        BIT_TX                  = 7 ; 100base-T
122
        BIT_10FD                = 6 ; 10base-T full duplex
123
        BIT_10                  = 5 ; 10base-T
124
        BIT_SELECTOR            = 0 ; binary encoded selector CSMA/CD=00001
125
 
126
        BIT_IFG1                = 25
127
        BIT_IFG0                = 24
128
 
129
        RX_CONFIG               = (RBLEN shl BIT_RBLEN) or \
130
                                  (RX_MXDMA shl BIT_RX_MXDMA) or \
131
                                  (1 shl BIT_NOWRAP) or \
132
                                  (RXFTH shl BIT_RXFTH) or\
3857 hidnplayr 133
                                  (1 shl BIT_AB) or \                   ; Accept broadcast packets
134
                                  (1 shl BIT_APM) or \                  ; Accept physical match packets
135
                                  (1 shl BIT_AER) or \                  ; Accept error packets
136
                                  (1 shl BIT_AR) or \                   ; Accept Runt packets (smaller then 64 bytes)
137
                                  (1 shl BIT_AM)                        ; Accept multicast packets
3545 hidnplayr 138
 
3857 hidnplayr 139
        RX_BUFFER_SIZE          = (8192 shl RBLEN);+16+1500
3545 hidnplayr 140
        MAX_ETH_FRAME_SIZE      = 1514
3857 hidnplayr 141
        NUM_TX_DESC             = 4                                     ; not user selectable
3545 hidnplayr 142
 
143
        EE_93C46_REG_ETH_ID     = 7 ; MAC offset
144
        EE_93C46_READ_CMD       = (6 shl 6) ; 110b + 6bit address
145
        EE_93C56_READ_CMD       = (6 shl 8) ; 110b + 8bit address
146
        EE_93C46_CMD_LENGTH     = 9  ; start bit + cmd + 6bit address
147
        EE_93C56_CMD_LENGTH     = 11 ; start bit + cmd + 8bit ddress
148
 
149
        VER_RTL8139             = 1100000b
150
        VER_RTL8139A            = 1110000b
151
        VER_RTL8139AG           = 1110100b
152
        VER_RTL8139B            = 1111000b
153
        VER_RTL8130             = VER_RTL8139B
154
        VER_RTL8139C            = 1110100b
155
        VER_RTL8100             = 1111010b
156
        VER_RTL8100B            = 1110101b
157
        VER_RTL8139D            = VER_RTL8100B
158
        VER_RTL8139CP           = 1110110b
159
        VER_RTL8101             = 1110111b
160
 
161
        IDX_RTL8139             = 0
162
        IDX_RTL8139A            = 1
163
        IDX_RTL8139B            = 2
164
        IDX_RTL8139C            = 3
165
        IDX_RTL8100             = 4
166
        IDX_RTL8139D            = 5
167
        IDX_RTL8139D            = 6
168
        IDX_RTL8101             = 7
169
 
170
        ISR_SERR                = 1 shl 15
171
        ISR_TIMEOUT             = 1 shl 14
172
        ISR_LENCHG              = 1 shl 13
173
        ISR_FIFOOVW             = 1 shl 6
174
        ISR_PUN                 = 1 shl 5
175
        ISR_RXOVW               = 1 shl 4
176
        ISR_TER                 = 1 shl 3
177
        ISR_TOK                 = 1 shl 2
178
        ISR_RER                 = 1 shl 1
179
        ISR_ROK                 = 1 shl 0
180
 
181
        INTERRUPT_MASK          = ISR_ROK or \
3857 hidnplayr 182
                                  ISR_RER or \
183
                                  ISR_TOK or \
184
                                  ISR_TER or \
3545 hidnplayr 185
                                  ISR_RXOVW or \
186
                                  ISR_PUN or \
187
                                  ISR_FIFOOVW or \
188
                                  ISR_LENCHG or \
3857 hidnplayr 189
                                  ISR_TIMEOUT or \
190
                                  ISR_SERR
3545 hidnplayr 191
 
3857 hidnplayr 192
 
193
 
3545 hidnplayr 194
        TSR_OWN                 = 1 shl 13
195
        TSR_TUN                 = 1 shl 14
196
        TSR_TOK                 = 1 shl 15
197
 
198
        TSR_CDH                 = 1 shl 28
199
        TSR_OWC                 = 1 shl 29
200
        TSR_TABT                = 1 shl 30
201
        TSR_CRS                 = 1 shl 31
202
 
203
 
204
virtual at ebx
205
 
206
        device:
207
 
208
        ETH_DEVICE
209
 
210
        .rx_buffer      dd ?
211
 
212
        .rx_data_offset dd ?
213
        .io_addr        dd ?
214
 
215
        .curr_tx_desc   db ?
216
        .pci_bus        dd ?
217
        .pci_dev        dd ?
218
        .irq_line       db ?
219
        .hw_ver_id      db ?
220
 
3635 hidnplayr 221
                        db ?    ; align 4
3545 hidnplayr 222
        .TX_DESC        rd NUM_TX_DESC
223
 
224
        .size = $ - device
225
 
226
end virtual
227
 
228
 
229
 
230
section '.flat' code readable align 16
231
 
232
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
233
;;                        ;;
234
;; proc START             ;;
235
;;                        ;;
236
;; (standard driver proc) ;;
237
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
238
 
239
align 4
240
proc START stdcall, state:dword
241
 
242
        cmp     [state], 1
243
        jne     .exit
244
 
245
  .entry:
246
 
4449 hidnplayr 247
        DEBUGF  2, "Loading driver\n"
3545 hidnplayr 248
        stdcall RegService, my_service, service_proc
249
        ret
250
 
251
  .fail:
252
  .exit:
253
        xor     eax, eax
254
        ret
255
 
256
endp
257
 
258
 
259
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
260
;;                        ;;
261
;; proc SERVICE_PROC      ;;
262
;;                        ;;
263
;; (standard driver proc) ;;
264
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
265
 
266
align 4
267
proc service_proc stdcall, ioctl:dword
268
 
269
        mov     edx, [ioctl]
270
        mov     eax, [IOCTL.io_code]
271
 
272
;------------------------------------------------------
273
 
274
        cmp     eax, 0 ;SRV_GETVERSION
275
        jne     @F
276
 
277
        cmp     [IOCTL.out_size], 4
278
        jb      .fail
279
        mov     eax, [IOCTL.output]
280
        mov     [eax], dword API_VERSION
281
 
282
        xor     eax, eax
283
        ret
284
 
285
;------------------------------------------------------
286
  @@:
287
        cmp     eax, 1 ;SRV_HOOK
288
        jne     .fail
289
 
290
        cmp     [IOCTL.inp_size], 3                     ; Data input must be at least 3 bytes
291
        jb      .fail
292
 
293
        mov     eax, [IOCTL.input]
294
        cmp     byte [eax], 1                           ; 1 means device number and bus number (pci) are given
295
        jne     .fail                                   ; other types arent supported for this card yet
296
 
297
; check if the device is already listed
298
 
299
        mov     esi, device_list
300
        mov     ecx, [devices]
301
        test    ecx, ecx
302
        jz      .firstdevice
303
 
304
        mov     ax, [eax+1]                             ; get the pci bus and device numbers
305
  .nextdevice:
306
        mov     ebx, [esi]
307
        cmp     al, byte[device.pci_bus]
308
        jne     @f
309
        cmp     ah, byte[device.pci_dev]
310
        je      .find_devicenum                         ; Device is already loaded, let's find it's device number
311
       @@:
312
        add     esi, 4
313
        loop    .nextdevice
314
 
315
 
316
; This device doesnt have its own eth_device structure yet, lets create one
317
  .firstdevice:
318
        cmp     [devices], MAX_DEVICES                  ; First check if the driver can handle one more card
319
        jae     .fail
320
 
321
        allocate_and_clear ebx, device.size, .fail      ; Allocate the buffer for device structure
322
 
323
; Fill in the direct call addresses into the struct
324
 
325
        mov     [device.reset], reset
326
        mov     [device.transmit], transmit
327
        mov     [device.unload], unload
328
        mov     [device.name], my_service
329
 
330
; save the pci bus and device numbers
331
 
332
        mov     eax, [IOCTL.input]
333
        movzx   ecx, byte[eax+1]
334
        mov     [device.pci_bus], ecx
335
        movzx   ecx, byte[eax+2]
336
        mov     [device.pci_dev], ecx
337
 
338
; Now, it's time to find the base io addres of the PCI device
339
 
340
        PCI_find_io
341
 
342
; We've found the io address, find IRQ now
343
 
344
        PCI_find_irq
345
 
3856 hidnplayr 346
        DEBUGF  1, "Hooking into device, dev:%x, bus:%x, irq:%x, I/O addr:%x\n",\
3545 hidnplayr 347
        [device.pci_dev]:1,[device.pci_bus]:1,[device.irq_line]:1,[device.io_addr]:4
348
 
349
; Allocate the receive buffer
350
 
351
        stdcall CreateRingBuffer, dword (RX_BUFFER_SIZE), dword PG_SW
352
        test    eax, eax
353
        jz      .err
354
        mov     [device.rx_buffer], eax
355
 
356
; Ok, the eth_device structure is ready, let's probe the device
357
 
358
        call    probe                                                   ; this function will output in eax
359
        test    eax, eax
360
        jnz     .err                                                    ; If an error occured, exit
361
 
362
        mov     eax, [devices]                                          ; Add the device structure to our device list
363
        mov     [device_list+4*eax], ebx                                ; (IRQ handler uses this list to find device)
364
        inc     [devices]                                               ;
365
 
3685 hidnplayr 366
        call    reset
367
        test    eax, eax
368
        jnz     .destroy
369
 
3545 hidnplayr 370
        mov     [device.type], NET_TYPE_ETH
371
        call    NetRegDev
372
 
373
        cmp     eax, -1
374
        je      .destroy
375
 
376
        ret
377
 
378
; If the device was already loaded, find the device number and return it in eax
379
 
380
  .find_devicenum:
3856 hidnplayr 381
        DEBUGF  1, "Trying to find device number of already registered device\n"
3545 hidnplayr 382
        call    NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
383
                                                                        ; into a device number in edi
384
        mov     eax, edi                                                ; Application wants it in eax instead
3856 hidnplayr 385
        DEBUGF  1, "Kernel says: %u\n", eax
3545 hidnplayr 386
        ret
387
 
388
; If an error occured, remove all allocated data and exit (returning -1 in eax)
389
 
390
  .destroy:
3685 hidnplayr 391
        ; todo: unregister device from device_list
3545 hidnplayr 392
        ; todo: reset device into virgin state
393
 
394
  .err:
3856 hidnplayr 395
        DEBUGF  2, "Error, removing all data !\n"
3545 hidnplayr 396
        stdcall KernelFree, [device.rx_buffer]
397
        stdcall KernelFree, ebx
398
 
399
  .fail:
400
        or      eax, -1
401
        ret
402
 
403
;------------------------------------------------------
404
endp
405
 
406
 
407
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
408
;;                                                                        ;;
409
;;        Actual Hardware dependent code starts here                      ;;
410
;;                                                                        ;;
411
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
412
 
413
align 4
414
unload:
415
        ; TODO: (in this particular order)
416
        ;
417
        ; - Stop the device
418
        ; - Detach int handler
419
        ; - Remove device from local list (RTL8139_LIST)
420
        ; - call unregister function in kernel
421
        ; - Remove all allocated structures and buffers the card used
422
 
423
        or      eax, -1
424
 
425
ret
426
 
427
 
428
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
429
;;
430
;;  probe: enables the device (if it really is RTL8139)
431
;;
432
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
433
 
434
align 4
435
probe:
3856 hidnplayr 436
        DEBUGF  1, "Probing\n"
3545 hidnplayr 437
 
438
        PCI_make_bus_master
439
 
440
; get chip version
441
        set_io  0
442
        set_io  REG_TXCONFIG + 2
443
        in      ax, dx
444
        shr     ah, 2
445
        shr     ax, 6
446
        and     al, 01111111b
447
 
448
; now find it in our array
449
        mov     ecx, HW_VER_ARRAY_SIZE-1
450
  .chip_ver_loop:
451
        cmp     al, [hw_ver_array + ecx]
452
        je      .chip_ver_found
453
        dec     ecx
454
        jns     .chip_ver_loop
455
  .unknown:
456
        mov     ecx, 8
457
  .chip_ver_found:
458
        cmp     ecx, 8
459
        ja      .unknown
460
 
461
        mov     [device.hw_ver_id], cl
462
 
463
        mov     ecx, [crosslist+ecx*4]
464
        mov     [device.name], ecx
465
 
3856 hidnplayr 466
        DEBUGF  1, "Chip version: %s\n", ecx
3545 hidnplayr 467
 
468
; wake up the chip
469
        set_io  0
470
        set_io  REG_HLTCLK
471
        mov     al, 'R'         ; run the clock
472
        out     dx, al
473
 
474
; unlock config and BMCR registers
475
        set_io  REG_9346CR
476
        mov     al, (1 shl BIT_93C46_EEM1) or (1 shl BIT_93C46_EEM0)
477
        out     dx, al
478
 
479
; enable power management
480
        set_io  REG_CONFIG1
481
        in      al, dx
482
        cmp     [device.hw_ver_id], IDX_RTL8139B
483
        jae     .new_chip
484
; wake up older chips
485
        and     al, not ((1 shl BIT_SLEEP) or (1 shl BIT_PWRDWN))
486
        out     dx, al
487
        jmp     .finish_wake_up
488
 
489
; set LWAKE pin to active high (default value).
490
; it is for Wake-On-LAN functionality of some motherboards.
491
; this signal is used to inform the motherboard to execute a wake-up process.
492
; only at newer chips.
493
  .new_chip:
494
        or      al, (1 shl BIT_PMEn)
495
        and     al, not (1 shl BIT_LWACT)
496
        out     dx, al
497
 
498
        set_io  REG_CONFIG4
499
        in      al, dx
500
        and     al, not (1 shl BIT_LWPTN)
501
        out     dx, al
502
 
503
; lock config and BMCR registers
504
  .finish_wake_up:
505
        xor     al, al
506
        set_io  0
507
        set_io  REG_9346CR
508
        out     dx, al
3856 hidnplayr 509
        DEBUGF  1, "probing done!\n"
3545 hidnplayr 510
 
3685 hidnplayr 511
        xor     eax, eax
3545 hidnplayr 512
 
3685 hidnplayr 513
        ret
514
 
515
 
3545 hidnplayr 516
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
517
;;
518
;;   reset: Set up all registers and descriptors, clear some values
519
;;
520
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
521
 
522
reset:
3856 hidnplayr 523
        DEBUGF  1, "Reset\n"
3545 hidnplayr 524
 
525
; attach int handler
526
        movzx   eax, [device.irq_line]
527
        DEBUGF  1, "Attaching int handler to irq %x\n", eax:1
528
        stdcall AttachIntHandler, eax, int_handler, dword 0
529
        test    eax, eax
530
        jnz     @f
3856 hidnplayr 531
        DEBUGF  2, "Could not attach int handler!\n"
3545 hidnplayr 532
;        or      eax, -1
533
;        ret
534
       @@:
535
 
536
; reset chip
537
        DEBUGF  1, "Resetting chip\n"
538
        set_io  0
539
        set_io  REG_COMMAND
540
        mov     al, 1 shl BIT_RST
541
        out     dx, al
542
        mov     cx, 1000                ; wait no longer for the reset
543
  .wait_for_reset:
544
        in      al, dx
545
        test    al, 1 shl BIT_RST
546
        jz      .reset_completed        ; RST remains 1 during reset
547
        dec     cx
548
        jns     .wait_for_reset
3856 hidnplayr 549
        DEBUGF  2, "Reset timeout!\n"
3545 hidnplayr 550
  .reset_completed:
551
 
3858 hidnplayr 552
; Read MAC address
553
        call    read_mac
554
 
3545 hidnplayr 555
; unlock config and BMCR registers
3858 hidnplayr 556
        set_io  0
3545 hidnplayr 557
        set_io  REG_9346CR
558
        mov     al, (1 shl BIT_93C46_EEM1) or (1 shl BIT_93C46_EEM0)
559
        out     dx, al
560
 
561
; initialize multicast registers (no filtering)
562
        mov     eax, 0xffffffff
563
        set_io  REG_MAR0
564
        out     dx, eax
565
        set_io  REG_MAR4
566
        out     dx, eax
567
 
568
; enable Rx/Tx
569
        mov     al, (1 shl BIT_RE) or (1 shl BIT_TE)
570
        set_io  REG_COMMAND
571
        out     dx, al
572
 
573
; Rxbuffer size, unlimited dma burst, no wrapping, no rx threshold
574
; accept broadcast packets, accept physical match packets
3858 hidnplayr 575
        mov     eax, RX_CONFIG
3545 hidnplayr 576
        set_io  REG_RXCONFIG
3858 hidnplayr 577
        out     dx, eax
3545 hidnplayr 578
 
579
; 1024 bytes DMA burst, total retries = 16 + 8 * 16 = 144
580
        mov     eax, (TX_MXDMA shl BIT_TX_MXDMA) or (TXRR shl BIT_TXRR) or BIT_IFG1 or BIT_IFG0
581
        set_io  REG_TXCONFIG
582
        out     dx, eax
583
 
584
; enable auto negotiation
585
        set_io  REG_BMCR
586
        in      ax, dx
587
        or      ax, (1 shl BIT_ANE)
588
        out     dx, ax
589
 
590
; set auto negotiation advertisement
591
        set_io  REG_ANAR
592
        in      ax, dx
593
        or      ax, (1 shl BIT_SELECTOR) or (1 shl BIT_10) or (1 shl BIT_10FD) or (1 shl BIT_TX) or (1 shl BIT_TXFD)
594
        out     dx, ax
595
 
596
; lock config and BMCR registers
597
        xor     eax, eax
598
        set_io  REG_9346CR
599
        out     dx, al
600
 
601
; init RX/TX pointers
602
        mov     [device.rx_data_offset], eax
603
        mov     [device.curr_tx_desc], al
604
;        set_io  REG_CAPR
605
;        out     dx, ax
606
 
607
; clear packet/byte counters
608
        lea     edi, [device.bytes_tx]
609
        mov     ecx, 6
610
        rep     stosd
611
 
612
; clear missing packet counter
613
        set_io  REG_MPC
614
        out     dx, eax
615
 
616
; set RxBuffer address, init RX buffer offset
617
        mov     eax, [device.rx_buffer]
618
        mov     dword[eax], 0                   ; clear receive flags for first packet (really needed??)
3685 hidnplayr 619
        DEBUGF  1, "RX buffer virtual addr=0x%x\n", eax
3545 hidnplayr 620
        GetRealAddr
3857 hidnplayr 621
        DEBUGF  1, "RX buffer physical addr=0x%x\n", eax
3545 hidnplayr 622
        set_io  REG_RBSTART
623
        out     dx, eax
624
 
625
; enable interrupts
626
        set_io  0
627
        set_io  REG_IMR
628
        mov     ax, INTERRUPT_MASK
629
        out     dx, ax
630
 
631
; Set the mtu, kernel will be able to send now
632
        mov     [device.mtu], 1514
633
 
634
        call    cable
635
 
636
; Indicate that we have successfully reset the card
637
        xor     eax, eax
638
        ret
639
 
640
 
641
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
642
;;                                         ;;
643
;; Transmit                                ;;
644
;;                                         ;;
645
;; In: buffer pointer in [esp+4]           ;;
646
;;     size of buffer in [esp+8]           ;;
647
;;     pointer to device structure in ebx  ;;
648
;;                                         ;;
649
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
650
align 4
651
transmit:
3856 hidnplayr 652
        DEBUGF  1, "Transmitting packet, buffer:%x, size:%u\n", [esp+4], [esp+8]
3545 hidnplayr 653
        mov     eax, [esp+4]
654
        DEBUGF  1, "To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
655
        [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
656
        [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
657
        [eax+13]:2,[eax+12]:2
658
 
659
        cmp     dword [esp+8], MAX_ETH_FRAME_SIZE
660
        ja      .fail
661
        cmp     dword [esp+8], 60
662
        jb      .fail
663
 
664
; check if we own the current discriptor
665
        set_io  0
666
        set_io  REG_TSD0
667
        movzx   ecx, [device.curr_tx_desc]
668
        shl     ecx, 2
669
        add     edx, ecx
670
        in      eax, dx
671
        test    eax, (1 shl BIT_OWN)
672
        jz      .wait_to_send
673
 
674
  .send_packet:
675
; get next descriptor
676
        inc     [device.curr_tx_desc]
677
        and     [device.curr_tx_desc], NUM_TX_DESC-1
678
 
679
; Update stats
680
        inc     [device.packets_tx]
681
        mov     eax, [esp+8]
682
        add     dword [device.bytes_tx], eax
683
        adc     dword [device.bytes_tx+4], 0
684
 
685
; Set the buffer address
686
        set_io  REG_TSAD0
687
        mov     eax, [esp+4]
688
        mov     [device.TX_DESC+ecx], eax
689
        GetRealAddr
690
        out     dx, eax
691
 
692
; And the size of the buffer
693
        set_io  REG_TSD0
694
        mov     eax, [esp+8]
695
        or      eax, (ERTXTH shl BIT_ERTXTH)    ; Early threshold
696
        out     dx, eax
697
 
698
        DEBUGF  1, "Packet Sent!\n"
699
        xor     eax, eax
700
        ret     8
701
 
702
  .wait_to_send:
703
        DEBUGF  1, "Waiting for timeout\n"
704
 
705
        push    edx
706
        mov     esi, 30
707
        stdcall Sleep
708
        pop     edx
709
 
710
        in      ax, dx
711
        test    ax, (1 shl BIT_OWN)
712
        jnz     .send_packet
713
 
714
        pusha
715
        call    reset                            ; if chip hung, reset it
716
        popa
717
 
718
        jmp     .send_packet
719
 
720
  .fail:
3856 hidnplayr 721
        DEBUGF  2, "transmit failed!\n"
3545 hidnplayr 722
        stdcall KernelFree, [esp+4]
723
        or      eax, -1
724
        ret     8
725
 
726
 
727
 
728
 
729
 
730
;;;;;;;;;;;;;;;;;;;;;;;
731
;;                   ;;
732
;; Interrupt handler ;;
733
;;                   ;;
734
;;;;;;;;;;;;;;;;;;;;;;;
735
 
736
align 4
737
int_handler:
738
 
739
        push    ebx esi edi
740
 
3856 hidnplayr 741
        DEBUGF  1, "INT\n"
3545 hidnplayr 742
 
743
; find pointer of device wich made IRQ occur
744
        mov     ecx, [devices]
745
        test    ecx, ecx
746
        jz      .nothing
747
        mov     esi, device_list
748
  .nextdevice:
749
        mov     ebx, [esi]
750
 
751
        set_io  0
752
        set_io  REG_ISR
753
        in      ax, dx                          ; Get interrupt status
754
        out     dx, ax                          ; send it back to ACK
755
        test    ax, ax
756
        jnz     .got_it
757
  .continue:
758
        add     esi, 4
759
        dec     ecx
760
        jnz     .nextdevice
761
  .nothing:
762
        pop     edi esi ebx
763
        xor     eax, eax
764
 
765
        ret                                     ; If no device was found, abort (The irq was probably for a device, not registered to this driver)
766
 
767
  .got_it:
768
 
769
        DEBUGF  1, "Device: %x Status: %x\n", ebx, ax
770
 
771
;----------------------------------------------------
772
; Received packet ok?
773
 
774
        test    ax, ISR_ROK
775
        jz      @f
776
        push    ax
777
 
778
  .receive:
779
        set_io  0
780
        set_io  REG_COMMAND
781
        in      al, dx
782
        test    al, BUFE                        ; test if RX buffer is empty
783
        jnz     .finish
784
 
3856 hidnplayr 785
        DEBUGF  1, "RX:\n"
3545 hidnplayr 786
 
787
        mov     eax, [device.rx_buffer]
788
        add     eax, [device.rx_data_offset]
789
        test    byte [eax], (1 shl BIT_ROK)     ; check if packet is ok
790
        jz      .reset_rx
791
 
792
; packet is ok, copy it
793
        movzx   ecx, word [eax+2]               ; packet length
794
        sub     cx, 4                           ; don't copy CRC
795
 
796
; Update stats
797
        add     dword [device.bytes_rx], ecx
798
        adc     dword [device.bytes_rx + 4], 0
799
        inc     [device.packets_rx]
800
 
801
        DEBUGF  1, "Received %u bytes\n", ecx
802
 
803
        push    ebx eax ecx
804
        stdcall KernelAlloc, ecx                ; Allocate a buffer to put packet into
805
        pop     ecx
806
        test    eax, eax                        ; Test if we allocated succesfully
807
        jz      .abort
808
 
809
        mov     edi, eax                        ; Where we will copy too
810
 
811
        mov     esi, [esp]                      ; The buffer we will copy from
812
        add     esi, 4                          ; Dont copy CRC
813
 
814
        push    dword .abort                    ; Kernel will return to this address after EthReceiver
815
        push    ecx edi                         ; Save buffer pointer and size, to pass to kernel
816
 
817
  .copy:
818
        shr     ecx, 1
819
        jnc     .nb
820
        movsb
821
  .nb:
822
        shr     ecx, 1
823
        jnc     .nw
824
        movsw
825
  .nw:
826
        jz      .nd
827
        rep     movsd
828
  .nd:
829
 
830
        jmp     Eth_input                       ; Send it to kernel
831
 
832
  .abort:
833
        pop     eax ebx
834
                                                ; update eth_data_start_offset
835
        movzx   eax, word [eax+2]               ; packet length
836
        add     eax, [device.rx_data_offset]
837
        add     eax, 4+3                        ; packet header is 4 bytes long + dword alignment
838
        and     eax, not 3                      ; dword alignment
839
 
840
        cmp     eax, RX_BUFFER_SIZE
841
        jb      .no_wrap
3856 hidnplayr 842
        DEBUGF  1, "Wrapping\n"
3545 hidnplayr 843
        sub     eax, RX_BUFFER_SIZE
844
  .no_wrap:
845
        mov     [device.rx_data_offset], eax
846
        DEBUGF  1, "New RX ptr: %d\n", eax
847
 
848
        set_io  0
849
        set_io  REG_CAPR                        ; update 'Current Address of Packet Read register'
850
        sub     eax, 0x10                       ; value 0x10 is a constant for CAPR
3857 hidnplayr 851
        out     dx, ax
3545 hidnplayr 852
 
853
        jmp     .receive                        ; check for multiple packets
854
 
855
  .reset_rx:
856
        test    byte [eax], (1 shl BIT_CRC)
857
        jz      .no_crc_error
3856 hidnplayr 858
        DEBUGF  2, "RX: CRC error!\n"
3545 hidnplayr 859
 
860
  .no_crc_error:
861
        test    byte [eax], (1 shl BIT_FAE)
862
        jz      .no_fae_error
3856 hidnplayr 863
        DEBUGF  2, "RX: Frame alignment error!\n"
3545 hidnplayr 864
 
865
  .no_fae_error:
866
        DEBUGF  1, "Reset RX\n"
867
        in      al, dx                          ; read command register
868
        push    ax
869
        and     al, not (1 shl BIT_RE)          ; Clear the RE bit
870
        out     dx, al
871
        pop     ax
872
        out     dx, al                          ; write original command back
873
 
874
        add     edx, REG_RXCONFIG - REG_COMMAND         ; Restore RX configuration
875
        mov     ax, RX_CONFIG
876
        out     dx, ax
877
 
878
  .finish:
879
        pop     ax
880
 
881
;----------------------------------------------------
882
; Transmit ok / Transmit error
883
  @@:
884
        test    ax, ISR_TOK + ISR_TER
885
        jz      @f
886
 
3857 hidnplayr 887
        DEBUGF  1, "Transmit done!\n"
888
 
3545 hidnplayr 889
        push    ax
890
        mov     ecx, (NUM_TX_DESC-1)*4
891
  .txdescloop:
892
        set_io  0
893
        set_io  REG_TSD0
894
        add     edx, ecx
895
        in      eax, dx
896
 
897
        test    eax, TSR_OWN                    ; DMA operation completed
898
        jz      .notthisone
899
 
900
        cmp     [device.TX_DESC+ecx], 0
901
        je      .notthisone
902
 
3857 hidnplayr 903
        DEBUGF  1, "TSD: 0x%x\n", eax
3545 hidnplayr 904
 
3857 hidnplayr 905
        test    eax, TSR_TUN
906
        jz      .no_bun
907
        DEBUGF  2, "TX: FIFO Buffer underrun!\n"
908
 
909
  .no_bun:
910
        test    eax, TSR_OWC
911
        jz      .no_owc
912
        DEBUGF  2, "TX: OWC!\n"
913
 
914
  .no_owc:
915
        test    eax, TSR_TABT
916
        jz      .no_tabt
917
        DEBUGF  2, "TX: TABT!\n"
918
 
919
  .no_tabt:
920
        test    eax, TSR_CRS
921
        jz      .no_csl
922
        DEBUGF  2, "TX: Carrier Sense Lost!\n"
923
 
924
  .no_csl:
925
        test    eax, TSR_TOK
926
        jz      .no_tok
927
        DEBUGF  1, "TX: Transmit OK!\n"
928
 
929
  .no_tok:
930
        DEBUGF  1, "free transmit buffer 0x%x\n", [device.TX_DESC+ecx]:8
3545 hidnplayr 931
        push    ecx ebx
932
        stdcall KernelFree, [device.TX_DESC+ecx]
933
        pop     ebx ecx
934
        mov     [device.TX_DESC+ecx], 0
935
 
936
  .notthisone:
937
        sub     ecx, 4
3857 hidnplayr 938
        jae     .txdescloop
3545 hidnplayr 939
        pop     ax
940
 
941
;----------------------------------------------------
942
; Rx buffer overflow ?
943
  @@:
944
        test    ax, ISR_RXOVW
945
        jz      @f
946
 
947
        push    ax
3856 hidnplayr 948
        DEBUGF  2, "RX:buffer overflow!\n"
3545 hidnplayr 949
 
950
        set_io  0
951
        set_io  REG_ISR
952
        mov     ax, ISR_FIFOOVW or ISR_RXOVW
953
        out     dx, ax
954
        pop     ax
955
 
956
;----------------------------------------------------
957
; Packet underrun?
958
  @@:
959
        test    ax, ISR_PUN
960
        jz      @f
961
 
4449 hidnplayr 962
        DEBUGF  1, "Packet underrun or link changed!\n"
3545 hidnplayr 963
 
4449 hidnplayr 964
        call    cable
965
 
3545 hidnplayr 966
;----------------------------------------------------
967
; Receive FIFO overflow ?
968
  @@:
969
        test    ax, ISR_FIFOOVW
970
        jz      @f
971
 
972
        push    ax
4449 hidnplayr 973
        DEBUGF  2, "RX fifo overflow!\n"
3545 hidnplayr 974
 
975
        set_io  0
976
        set_io  REG_ISR
977
        mov     ax, ISR_FIFOOVW or ISR_RXOVW
978
        out     dx, ax
979
        pop     ax
980
 
981
;----------------------------------------------------
4449 hidnplayr 982
; cable length changed ?
3545 hidnplayr 983
  @@:
984
        test    ax, ISR_LENCHG
985
        jz      .fail
986
 
4449 hidnplayr 987
        DEBUGF  2, "Cable length changed!\n"
988
 
3545 hidnplayr 989
        call    cable
990
 
991
  .fail:
992
        pop     edi esi ebx
993
        xor     eax, eax
994
        inc     eax
995
 
996
        ret
997
 
998
 
999
 
1000
 
1001
;;;;;;;;;;;;;;;;;;;;;;;;;
1002
;;                     ;;
1003
;; Update Cable status ;;
1004
;;                     ;;
1005
;;;;;;;;;;;;;;;;;;;;;;;;;
1006
 
1007
align 4
1008
cable:
3857 hidnplayr 1009
        DEBUGF  1, "Checking link status:\n"
3545 hidnplayr 1010
 
1011
        set_io  0
1012
        set_io  REG_MSR
1013
        in      al, dx
1014
 
1015
        test    al, 1 shl 2             ; 0 = link ok 1 = link fail
1016
        jnz     .notconnected
1017
 
1018
        test    al, 1 shl 3             ; 0 = 100 Mbps 1 = 10 Mbps
1019
        jnz     .10mbps
1020
 
1021
  .100mbps:
1022
        mov     [device.state], ETH_LINK_100M
1023
        call    NetLinkChanged
4449 hidnplayr 1024
        DEBUGF  2, "link changed to 100 mbit\n"
3545 hidnplayr 1025
 
1026
        ret
1027
 
1028
  .10mbps:
1029
        mov     [device.state], ETH_LINK_10M
1030
        call    NetLinkChanged
4449 hidnplayr 1031
        DEBUGF  2, "link changed to 10 mbit\n"
3545 hidnplayr 1032
 
1033
        ret
1034
 
1035
  .notconnected:
1036
        mov     [device.state], ETH_LINK_DOWN
1037
        call    NetLinkChanged
4449 hidnplayr 1038
        DEBUGF  2, "no link\n"
3545 hidnplayr 1039
 
1040
        ret
1041
 
1042
 
1043
 
1044
;;;;;;;;;;;;;;;;;;;;;;;
1045
;;                   ;;
1046
;; Write MAC address ;;
1047
;;                   ;;
1048
;;;;;;;;;;;;;;;;;;;;;;;
1049
 
1050
align 4
1051
write_mac:      ; in: mac pushed onto stack (as 3 words)
1052
 
3856 hidnplayr 1053
        DEBUGF  1, "Writing MAC\n"
3545 hidnplayr 1054
 
1055
; disable all in command registers
1056
        set_io  0
1057
        set_io  REG_9346CR
1058
        xor     eax, eax
1059
        out     dx, al
1060
 
1061
        set_io  REG_IMR
1062
        xor     eax, eax
1063
        out     dx, ax
1064
 
1065
        set_io  REG_ISR
1066
        mov     eax, -1
1067
        out     dx, ax
1068
 
1069
; enable writing
1070
        set_io  REG_9346CR
1071
        mov     eax, REG_9346CR_WE
1072
        out     dx, al
1073
 
1074
 ; write the mac ...
1075
        set_io  REG_IDR0
1076
        pop     eax
1077
        out     dx, eax
1078
 
1079
        set_io  REG_IDR0+4
1080
        xor     eax, eax
1081
        pop     ax
1082
        out     dx, eax
1083
 
1084
; disable writing
1085
        set_io  REG_9346CR
1086
        xor     eax, eax
1087
        out     dx, al
1088
 
3856 hidnplayr 1089
        DEBUGF  1, "MAC write ok!\n"
3545 hidnplayr 1090
 
1091
; Notice this procedure does not ret, but continues to read_mac instead.
1092
 
1093
 
1094
;;;;;;;;;;;;;;;;;;;;;;
1095
;;                  ;;
1096
;; Read MAC address ;;
1097
;;                  ;;
1098
;;;;;;;;;;;;;;;;;;;;;;
1099
 
1100
read_mac:
3857 hidnplayr 1101
        DEBUGF  1, "Reading MAC:\n"
3545 hidnplayr 1102
 
1103
        set_io  0
1104
        lea     edi, [device.mac]
1105
        in      eax, dx
1106
        stosd
1107
        add     edx, 4
1108
        in      ax, dx
1109
        stosw
1110
 
3857 hidnplayr 1111
        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 1112
 
1113
        ret
1114
 
1115
 
1116
; End of code
1117
 
1118
section '.data' data readable writable align 16 ; place all uninitialized data place here
1119
align 4                                         ; Place all initialised data here
1120
 
1121
devices         dd 0
1122
version         dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
1123
my_service      db 'RTL8139',0                    ; max 16 chars include zero
1124
 
1125
device_1        db 'Realtek 8139',0
1126
device_2        db 'Realtek 8139A',0
1127
device_3        db 'Realtek 8139B',0
1128
device_4        db 'Realtek 8139C',0
1129
device_5        db 'Realtek 8100',0
1130
device_6        db 'Realtek 8139D',0
1131
device_7        db 'Realtek 8139CP',0
1132
device_8        db 'Realtek 8101',0
1133
device_unknown  db 'Unknown RTL8139 clone', 0
1134
 
1135
crosslist:
1136
        dd device_1
1137
        dd device_2
1138
        dd device_3
1139
        dd device_4
1140
        dd device_5
1141
        dd device_6
1142
        dd device_7
1143
        dd device_8
1144
        dd device_unknown
1145
 
1146
hw_ver_array:                    ; This array is used by the probe routine to find out wich version of the RTL8139 we are working with
1147
        db VER_RTL8139
1148
        db VER_RTL8139A
1149
        db VER_RTL8139B
1150
        db VER_RTL8139C
1151
        db VER_RTL8100
1152
        db VER_RTL8139D
1153
        db VER_RTL8139CP
1154
        db VER_RTL8101
1155
        db 0
1156
 
1157
HW_VER_ARRAY_SIZE = $-hw_ver_array
1158
 
1159
include_debug_strings                           ; All data wich FDO uses will be included here
1160
 
1161
device_list     rd MAX_DEVICES                   ; This list contains all pointers to device structures the driver is handling
1162