Subversion Repositories Kolibri OS

Rev

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

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