Subversion Repositories Kolibri OS

Rev

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

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