Subversion Repositories Kolibri OS

Rev

Rev 3545 | Rev 3685 | 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
30
        __DEBUG_LEVEL__         = 2
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
 
240
        DEBUGF  2, "Loading %s driver\n", my_service
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
 
339
        DEBUGF  2, "Hooking into device, dev:%x, bus:%x, irq:%x, I/O addr:%x\n",\
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
 
359
        mov     [device.type], NET_TYPE_ETH
360
        call    NetRegDev
361
 
362
        cmp     eax, -1
363
        je      .destroy
364
 
365
        ret
366
 
367
; If the device was already loaded, find the device number and return it in eax
368
 
369
  .find_devicenum:
370
        DEBUGF  2, "Trying to find device number of already registered device\n"
371
        call    NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
372
                                                                        ; into a device number in edi
373
        mov     eax, edi                                                ; Application wants it in eax instead
374
        DEBUGF  2, "Kernel says: %u\n", eax
375
        ret
376
 
377
; If an error occured, remove all allocated data and exit (returning -1 in eax)
378
 
379
  .destroy:
380
        ; todo: reset device into virgin state
381
 
382
  .err:
383
        stdcall KernelFree, [device.rx_buffer]
384
        stdcall KernelFree, ebx
385
 
386
  .fail:
387
        or      eax, -1
388
        ret
389
 
390
;------------------------------------------------------
391
endp
392
 
393
 
394
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
395
;;                                                                        ;;
396
;;        Actual Hardware dependent code starts here                      ;;
397
;;                                                                        ;;
398
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
399
 
400
align 4
401
unload:
402
        ; TODO: (in this particular order)
403
        ;
404
        ; - Stop the device
405
        ; - Detach int handler
406
        ; - Remove device from local list (RTL8139_LIST)
407
        ; - call unregister function in kernel
408
        ; - Remove all allocated structures and buffers the card used
409
 
410
        or      eax, -1
411
 
412
ret
413
 
414
 
415
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
416
;;
417
;;  probe: enables the device (if it really is RTL8139)
418
;;
419
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
420
 
421
align 4
422
probe:
423
        DEBUGF  2, "Probing %s device\n", my_service
424
 
425
        PCI_make_bus_master
426
 
427
; get chip version
428
        set_io  0
429
        set_io  REG_TXCONFIG + 2
430
        in      ax, dx
431
        shr     ah, 2
432
        shr     ax, 6
433
        and     al, 01111111b
434
 
435
; now find it in our array
436
        mov     ecx, HW_VER_ARRAY_SIZE-1
437
  .chip_ver_loop:
438
        cmp     al, [hw_ver_array + ecx]
439
        je      .chip_ver_found
440
        dec     ecx
441
        jns     .chip_ver_loop
442
  .unknown:
443
        mov     ecx, 8
444
  .chip_ver_found:
445
        cmp     ecx, 8
446
        ja      .unknown
447
 
448
        mov     [device.hw_ver_id], cl
449
 
450
        mov     ecx, [crosslist+ecx*4]
451
        mov     [device.name], ecx
452
 
453
        DEBUGF  2, "Chip version: %s\n", ecx
454
 
455
; wake up the chip
456
        set_io  0
457
        set_io  REG_HLTCLK
458
        mov     al, 'R'         ; run the clock
459
        out     dx, al
460
 
461
; unlock config and BMCR registers
462
        set_io  REG_9346CR
463
        mov     al, (1 shl BIT_93C46_EEM1) or (1 shl BIT_93C46_EEM0)
464
        out     dx, al
465
 
466
; enable power management
467
        set_io  REG_CONFIG1
468
        in      al, dx
469
        cmp     [device.hw_ver_id], IDX_RTL8139B
470
        jae     .new_chip
471
; wake up older chips
472
        and     al, not ((1 shl BIT_SLEEP) or (1 shl BIT_PWRDWN))
473
        out     dx, al
474
        jmp     .finish_wake_up
475
 
476
; set LWAKE pin to active high (default value).
477
; it is for Wake-On-LAN functionality of some motherboards.
478
; this signal is used to inform the motherboard to execute a wake-up process.
479
; only at newer chips.
480
  .new_chip:
481
        or      al, (1 shl BIT_PMEn)
482
        and     al, not (1 shl BIT_LWACT)
483
        out     dx, al
484
 
485
        set_io  REG_CONFIG4
486
        in      al, dx
487
        and     al, not (1 shl BIT_LWPTN)
488
        out     dx, al
489
 
490
; lock config and BMCR registers
491
  .finish_wake_up:
492
        xor     al, al
493
        set_io  0
494
        set_io  REG_9346CR
495
        out     dx, al
496
        DEBUGF  2, "done!\n"
497
 
498
 
499
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
500
;;
501
;;   reset: Set up all registers and descriptors, clear some values
502
;;
503
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
504
 
505
reset:
506
        DEBUGF  2, "Reset\n"
507
 
508
; attach int handler
509
        movzx   eax, [device.irq_line]
510
        DEBUGF  1, "Attaching int handler to irq %x\n", eax:1
511
        stdcall AttachIntHandler, eax, int_handler, dword 0
512
        test    eax, eax
513
        jnz     @f
514
        DEBUGF  1, "\nCould not attach int handler!\n"
515
;        or      eax, -1
516
;        ret
517
       @@:
518
 
519
; reset chip
520
        DEBUGF  1, "Resetting chip\n"
521
        set_io  0
522
        set_io  REG_COMMAND
523
        mov     al, 1 shl BIT_RST
524
        out     dx, al
525
        mov     cx, 1000                ; wait no longer for the reset
526
  .wait_for_reset:
527
        in      al, dx
528
        test    al, 1 shl BIT_RST
529
        jz      .reset_completed        ; RST remains 1 during reset
530
        dec     cx
531
        jns     .wait_for_reset
532
        DEBUGF  1, "Reset timeout!\n"
533
  .reset_completed:
534
 
535
; unlock config and BMCR registers
536
        set_io  REG_9346CR
537
        mov     al, (1 shl BIT_93C46_EEM1) or (1 shl BIT_93C46_EEM0)
538
        out     dx, al
539
 
540
; initialize multicast registers (no filtering)
541
        mov     eax, 0xffffffff
542
        set_io  REG_MAR0
543
        out     dx, eax
544
        set_io  REG_MAR4
545
        out     dx, eax
546
 
547
; enable Rx/Tx
548
 
549
        mov     al, (1 shl BIT_RE) or (1 shl BIT_TE)
550
        set_io  REG_COMMAND
551
        out     dx, al
552
 
553
; Rxbuffer size, unlimited dma burst, no wrapping, no rx threshold
554
; accept broadcast packets, accept physical match packets
555
        mov     ax, RX_CONFIG
556
        set_io  REG_RXCONFIG
557
        out     dx, ax
558
 
559
; 1024 bytes DMA burst, total retries = 16 + 8 * 16 = 144
560
        mov     eax, (TX_MXDMA shl BIT_TX_MXDMA) or (TXRR shl BIT_TXRR) or BIT_IFG1 or BIT_IFG0
561
        set_io  REG_TXCONFIG
562
        out     dx, eax
563
 
564
; enable auto negotiation
565
        set_io  REG_BMCR
566
        in      ax, dx
567
        or      ax, (1 shl BIT_ANE)
568
        out     dx, ax
569
 
570
; set auto negotiation advertisement
571
        set_io  REG_ANAR
572
        in      ax, dx
573
        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)
574
        out     dx, ax
575
 
576
; lock config and BMCR registers
577
        xor     eax, eax
578
        set_io  REG_9346CR
579
        out     dx, al
580
 
581
; init RX/TX pointers
582
        mov     [device.rx_data_offset], eax
583
        mov     [device.curr_tx_desc], al
584
;        set_io  REG_CAPR
585
;        out     dx, ax
586
 
587
; clear packet/byte counters
588
        lea     edi, [device.bytes_tx]
589
        mov     ecx, 6
590
        rep     stosd
591
 
592
; clear missing packet counter
593
        set_io  REG_MPC
594
        out     dx, eax
595
 
596
; set RxBuffer address, init RX buffer offset
597
        mov     eax, [device.rx_buffer]
598
        mov     dword[eax], 0                   ; clear receive flags for first packet (really needed??)
599
        DEBUGF  2, "RX buffer virtual addr=0x%x\n", eax
600
        GetRealAddr
601
        DEBUGF  2, "RX buffer real addr=0x%x\n", eax
602
        set_io  REG_RBSTART
603
        out     dx, eax
604
 
605
; Read MAC address
606
        call    read_mac
607
 
608
; enable interrupts
609
        set_io  0
610
        set_io  REG_IMR
611
        mov     ax, INTERRUPT_MASK
612
        out     dx, ax
613
 
614
; Set the mtu, kernel will be able to send now
615
        mov     [device.mtu], 1514
616
 
617
        call    cable
618
 
619
; Indicate that we have successfully reset the card
620
        xor     eax, eax
621
        ret
622
 
623
 
624
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
625
;;                                         ;;
626
;; Transmit                                ;;
627
;;                                         ;;
628
;; In: buffer pointer in [esp+4]           ;;
629
;;     size of buffer in [esp+8]           ;;
630
;;     pointer to device structure in ebx  ;;
631
;;                                         ;;
632
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
633
align 4
634
transmit:
635
        DEBUGF  1, "\nTransmitting packet, buffer:%x, size:%u\n", [esp+4], [esp+8]
636
        mov     eax, [esp+4]
637
        DEBUGF  1, "To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
638
        [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
639
        [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
640
        [eax+13]:2,[eax+12]:2
641
 
642
        cmp     dword [esp+8], MAX_ETH_FRAME_SIZE
643
        ja      .fail
644
        cmp     dword [esp+8], 60
645
        jb      .fail
646
 
647
; check if we own the current discriptor
648
        set_io  0
649
        set_io  REG_TSD0
650
        movzx   ecx, [device.curr_tx_desc]
651
        shl     ecx, 2
652
        add     edx, ecx
653
        in      eax, dx
654
        test    eax, (1 shl BIT_OWN)
655
        jz      .wait_to_send
656
 
657
  .send_packet:
658
; get next descriptor
659
        inc     [device.curr_tx_desc]
660
        and     [device.curr_tx_desc], NUM_TX_DESC-1
661
 
662
; Update stats
663
        inc     [device.packets_tx]
664
        mov     eax, [esp+8]
665
        add     dword [device.bytes_tx], eax
666
        adc     dword [device.bytes_tx+4], 0
667
 
668
; Set the buffer address
669
        set_io  REG_TSAD0
670
        mov     eax, [esp+4]
671
        mov     [device.TX_DESC+ecx], eax
672
        GetRealAddr
673
        out     dx, eax
674
 
675
; And the size of the buffer
676
        set_io  REG_TSD0
677
        mov     eax, [esp+8]
678
        or      eax, (ERTXTH shl BIT_ERTXTH)    ; Early threshold
679
        out     dx, eax
680
 
681
        DEBUGF  1, "Packet Sent!\n"
682
        xor     eax, eax
683
        ret     8
684
 
685
  .wait_to_send:
686
        DEBUGF  1, "Waiting for timeout\n"
687
 
688
        push    edx
689
        mov     esi, 30
690
        stdcall Sleep
691
        pop     edx
692
 
693
        in      ax, dx
694
        test    ax, (1 shl BIT_OWN)
695
        jnz     .send_packet
696
 
697
        pusha
698
        call    reset                            ; if chip hung, reset it
699
        popa
700
 
701
        jmp     .send_packet
702
 
703
  .fail:
704
        DEBUGF  1, "failed!\n"
705
        stdcall KernelFree, [esp+4]
706
        or      eax, -1
707
        ret     8
708
 
709
 
710
 
711
 
712
 
713
;;;;;;;;;;;;;;;;;;;;;;;
714
;;                   ;;
715
;; Interrupt handler ;;
716
;;                   ;;
717
;;;;;;;;;;;;;;;;;;;;;;;
718
 
719
align 4
720
int_handler:
721
 
722
        push    ebx esi edi
723
 
724
        DEBUGF  1, "\n%s int\n", my_service
725
 
726
; find pointer of device wich made IRQ occur
727
        mov     ecx, [devices]
728
        test    ecx, ecx
729
        jz      .nothing
730
        mov     esi, device_list
731
  .nextdevice:
732
        mov     ebx, [esi]
733
 
734
        set_io  0
735
        set_io  REG_ISR
736
        in      ax, dx                          ; Get interrupt status
737
        out     dx, ax                          ; send it back to ACK
738
        test    ax, ax
739
        jnz     .got_it
740
  .continue:
741
        add     esi, 4
742
        dec     ecx
743
        jnz     .nextdevice
744
  .nothing:
745
        pop     edi esi ebx
746
        xor     eax, eax
747
 
748
        ret                                     ; If no device was found, abort (The irq was probably for a device, not registered to this driver)
749
 
750
  .got_it:
751
 
752
        DEBUGF  1, "Device: %x Status: %x\n", ebx, ax
753
 
754
;----------------------------------------------------
755
; Received packet ok?
756
 
757
        test    ax, ISR_ROK
758
        jz      @f
759
        push    ax
760
 
761
  .receive:
762
        set_io  0
763
        set_io  REG_COMMAND
764
        in      al, dx
765
        test    al, BUFE                        ; test if RX buffer is empty
766
        jnz     .finish
767
 
768
        DEBUGF  1, "RX: "
769
 
770
        mov     eax, [device.rx_buffer]
771
        add     eax, [device.rx_data_offset]
772
        test    byte [eax], (1 shl BIT_ROK)     ; check if packet is ok
773
        jz      .reset_rx
774
 
775
; packet is ok, copy it
776
        movzx   ecx, word [eax+2]               ; packet length
777
        sub     cx, 4                           ; don't copy CRC
778
 
779
; Update stats
780
        add     dword [device.bytes_rx], ecx
781
        adc     dword [device.bytes_rx + 4], 0
782
        inc     [device.packets_rx]
783
 
784
        DEBUGF  1, "Received %u bytes\n", ecx
785
 
786
        push    ebx eax ecx
787
        stdcall KernelAlloc, ecx                ; Allocate a buffer to put packet into
788
        pop     ecx
789
        test    eax, eax                        ; Test if we allocated succesfully
790
        jz      .abort
791
 
792
        mov     edi, eax                        ; Where we will copy too
793
 
794
        mov     esi, [esp]                      ; The buffer we will copy from
795
        add     esi, 4                          ; Dont copy CRC
796
 
797
        push    dword .abort                    ; Kernel will return to this address after EthReceiver
798
        push    ecx edi                         ; Save buffer pointer and size, to pass to kernel
799
 
800
  .copy:
801
        shr     ecx, 1
802
        jnc     .nb
803
        movsb
804
  .nb:
805
        shr     ecx, 1
806
        jnc     .nw
807
        movsw
808
  .nw:
809
        jz      .nd
810
        rep     movsd
811
  .nd:
812
 
813
        jmp     Eth_input                       ; Send it to kernel
814
 
815
  .abort:
816
        pop     eax ebx
817
                                                ; update eth_data_start_offset
818
        movzx   eax, word [eax+2]               ; packet length
819
        add     eax, [device.rx_data_offset]
820
        add     eax, 4+3                        ; packet header is 4 bytes long + dword alignment
821
        and     eax, not 3                      ; dword alignment
822
 
823
        cmp     eax, RX_BUFFER_SIZE
824
        jb      .no_wrap
3635 hidnplayr 825
        DEBUGF  1, "Wrapping"
3545 hidnplayr 826
        sub     eax, RX_BUFFER_SIZE
827
  .no_wrap:
828
        mov     [device.rx_data_offset], eax
829
        DEBUGF  1, "New RX ptr: %d\n", eax
830
 
831
        set_io  0
832
        set_io  REG_CAPR                        ; update 'Current Address of Packet Read register'
833
        sub     eax, 0x10                       ; value 0x10 is a constant for CAPR
834
        out     dx , ax
835
 
836
        jmp     .receive                        ; check for multiple packets
837
 
838
  .reset_rx:
839
        test    byte [eax], (1 shl BIT_CRC)
840
        jz      .no_crc_error
841
        DEBUGF  2, "\nCRC error!\n"
842
 
843
  .no_crc_error:
844
        test    byte [eax], (1 shl BIT_FAE)
845
        jz      .no_fae_error
846
        DEBUGF  1, "\nFrame alignment error!\n"
847
 
848
  .no_fae_error:
849
        DEBUGF  1, "Reset RX\n"
850
        in      al, dx                          ; read command register
851
        push    ax
852
        and     al, not (1 shl BIT_RE)          ; Clear the RE bit
853
        out     dx, al
854
        pop     ax
855
        out     dx, al                          ; write original command back
856
 
857
        add     edx, REG_RXCONFIG - REG_COMMAND         ; Restore RX configuration
858
        mov     ax, RX_CONFIG
859
        out     dx, ax
860
 
861
  .finish:
862
        pop     ax
863
 
864
;----------------------------------------------------
865
; Transmit ok / Transmit error
866
  @@:
867
        test    ax, ISR_TOK + ISR_TER
868
        jz      @f
869
 
870
        push    ax
871
        mov     ecx, (NUM_TX_DESC-1)*4
872
  .txdescloop:
873
        set_io  0
874
        set_io  REG_TSD0
875
        add     edx, ecx
876
        in      eax, dx
877
 
878
        test    eax, TSR_OWN                    ; DMA operation completed
879
        jz      .notthisone
880
 
881
        cmp     [device.TX_DESC+ecx], 0
882
        je      .notthisone
883
 
884
;  .notxd:
885
;        test    eax, TSR_TUN
886
;        jz      .nobun
887
;        DEBUGF  2, "TX: FIFO Buffer underrun!\n"
888
;
889
;  .nobun:
890
;        test    eax, TSR_OWC
891
;        jz      .noowc
892
;        DEBUGF  2, "TX: OWC!\n"
893
;
894
;  .noowc:
895
;        test    eax, TSR_TABT
896
;        jz      .notabt
897
;        DEBUGF  2, "TX: TABT!\n"
898
;
899
;  .notabt:
900
;        test    eax, TSR_CRS
901
;        jz      .nocsl
902
;        DEBUGF  2, "TX: Carrier Sense Lost!\n"
903
;
904
;  .nocsl:
905
 
906
        DEBUGF  1, "TX OK: free buffer %x\n", [device.TX_DESC+ecx]:8
907
        push    ecx ebx
908
        stdcall KernelFree, [device.TX_DESC+ecx]
909
        pop     ebx ecx
910
        mov     [device.TX_DESC+ecx], 0
911
 
912
  .notthisone:
913
        sub     ecx, 4
914
        ja      .txdescloop
915
        pop     ax
916
 
917
;----------------------------------------------------
918
; Rx buffer overflow ?
919
  @@:
920
        test    ax, ISR_RXOVW
921
        jz      @f
922
 
923
        push    ax
924
        DEBUGF  2, "RX-buffer overflow!\n"
925
 
926
        set_io  0
927
        set_io  REG_ISR
928
        mov     ax, ISR_FIFOOVW or ISR_RXOVW
929
        out     dx, ax
930
        pop     ax
931
 
932
;----------------------------------------------------
933
; Packet underrun?
934
  @@:
935
        test    ax, ISR_PUN
936
        jz      @f
937
 
938
        DEBUGF  2, "Packet underrun!\n"
939
 
940
;----------------------------------------------------
941
; Receive FIFO overflow ?
942
  @@:
943
        test    ax, ISR_FIFOOVW
944
        jz      @f
945
 
946
        push    ax
947
        DEBUGF  2, "RX fifo overflow!\n"
948
 
949
        set_io  0
950
        set_io  REG_ISR
951
        mov     ax, ISR_FIFOOVW or ISR_RXOVW
952
        out     dx, ax
953
        pop     ax
954
 
955
;----------------------------------------------------
956
; Something about Cable changed ?
957
  @@:
958
        test    ax, ISR_LENCHG
959
        jz      .fail
960
 
961
        call    cable
962
 
963
  .fail:
3635 hidnplayr 964
        DEBUGF  1, "\n"
3545 hidnplayr 965
        pop     edi esi ebx
966
        xor     eax, eax
967
        inc     eax
968
 
969
        ret
970
 
971
 
972
 
973
 
974
;;;;;;;;;;;;;;;;;;;;;;;;;
975
;;                     ;;
976
;; Update Cable status ;;
977
;;                     ;;
978
;;;;;;;;;;;;;;;;;;;;;;;;;
979
 
980
align 4
981
cable:
982
        DEBUGF  1, "Updating Cable status\n"
983
 
984
        set_io  0
985
        set_io  REG_MSR
986
        in      al, dx
987
 
988
        test    al, 1 shl 2             ; 0 = link ok 1 = link fail
989
        jnz     .notconnected
990
 
991
        test    al, 1 shl 3             ; 0 = 100 Mbps 1 = 10 Mbps
992
        jnz     .10mbps
993
 
994
  .100mbps:
995
        mov     [device.state], ETH_LINK_100M
996
        call    NetLinkChanged
997
 
998
        ret
999
 
1000
  .10mbps:
1001
        mov     [device.state], ETH_LINK_10M
1002
        call    NetLinkChanged
1003
 
1004
        ret
1005
 
1006
  .notconnected:
1007
        mov     [device.state], ETH_LINK_DOWN
1008
        call    NetLinkChanged
1009
 
1010
        ret
1011
 
1012
 
1013
 
1014
;;;;;;;;;;;;;;;;;;;;;;;
1015
;;                   ;;
1016
;; Write MAC address ;;
1017
;;                   ;;
1018
;;;;;;;;;;;;;;;;;;;;;;;
1019
 
1020
align 4
1021
write_mac:      ; in: mac pushed onto stack (as 3 words)
1022
 
1023
        DEBUGF  2, "Writing MAC: "
1024
 
1025
; disable all in command registers
1026
        set_io  0
1027
        set_io  REG_9346CR
1028
        xor     eax, eax
1029
        out     dx, al
1030
 
1031
        set_io  REG_IMR
1032
        xor     eax, eax
1033
        out     dx, ax
1034
 
1035
        set_io  REG_ISR
1036
        mov     eax, -1
1037
        out     dx, ax
1038
 
1039
; enable writing
1040
        set_io  REG_9346CR
1041
        mov     eax, REG_9346CR_WE
1042
        out     dx, al
1043
 
1044
 ; write the mac ...
1045
        set_io  REG_IDR0
1046
        pop     eax
1047
        out     dx, eax
1048
 
1049
        set_io  REG_IDR0+4
1050
        xor     eax, eax
1051
        pop     ax
1052
        out     dx, eax
1053
 
1054
; disable writing
1055
        set_io  REG_9346CR
1056
        xor     eax, eax
1057
        out     dx, al
1058
 
1059
        DEBUGF  2, "ok!\n"
1060
 
1061
; Notice this procedure does not ret, but continues to read_mac instead.
1062
 
1063
 
1064
;;;;;;;;;;;;;;;;;;;;;;
1065
;;                  ;;
1066
;; Read MAC address ;;
1067
;;                  ;;
1068
;;;;;;;;;;;;;;;;;;;;;;
1069
 
1070
read_mac:
1071
        DEBUGF  2, "Reading MAC: "
1072
 
1073
        set_io  0
1074
        lea     edi, [device.mac]
1075
        in      eax, dx
1076
        stosd
1077
        add     edx, 4
1078
        in      ax, dx
1079
        stosw
1080
 
1081
        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
1082
 
1083
        ret
1084
 
1085
 
1086
; End of code
1087
 
1088
section '.data' data readable writable align 16 ; place all uninitialized data place here
1089
align 4                                         ; Place all initialised data here
1090
 
1091
devices         dd 0
1092
version         dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
1093
my_service      db 'RTL8139',0                    ; max 16 chars include zero
1094
 
1095
device_1        db 'Realtek 8139',0
1096
device_2        db 'Realtek 8139A',0
1097
device_3        db 'Realtek 8139B',0
1098
device_4        db 'Realtek 8139C',0
1099
device_5        db 'Realtek 8100',0
1100
device_6        db 'Realtek 8139D',0
1101
device_7        db 'Realtek 8139CP',0
1102
device_8        db 'Realtek 8101',0
1103
device_unknown  db 'Unknown RTL8139 clone', 0
1104
 
1105
crosslist:
1106
        dd device_1
1107
        dd device_2
1108
        dd device_3
1109
        dd device_4
1110
        dd device_5
1111
        dd device_6
1112
        dd device_7
1113
        dd device_8
1114
        dd device_unknown
1115
 
1116
hw_ver_array:                    ; This array is used by the probe routine to find out wich version of the RTL8139 we are working with
1117
        db VER_RTL8139
1118
        db VER_RTL8139A
1119
        db VER_RTL8139B
1120
        db VER_RTL8139C
1121
        db VER_RTL8100
1122
        db VER_RTL8139D
1123
        db VER_RTL8139CP
1124
        db VER_RTL8101
1125
        db 0
1126
 
1127
HW_VER_ARRAY_SIZE = $-hw_ver_array
1128
 
1129
include_debug_strings                           ; All data wich FDO uses will be included here
1130
 
1131
device_list     rd MAX_DEVICES                   ; This list contains all pointers to device structures the driver is handling
1132