Subversion Repositories Kolibri OS

Rev

Rev 3635 | Rev 3856 | 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
 
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:
374
        DEBUGF  2, "Trying to find device number of already registered device\n"
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
378
        DEBUGF  2, "Kernel says: %u\n", eax
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:
388
        stdcall KernelFree, [device.rx_buffer]
389
        stdcall KernelFree, ebx
390
 
391
  .fail:
392
        or      eax, -1
393
        ret
394
 
395
;------------------------------------------------------
396
endp
397
 
398
 
399
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
400
;;                                                                        ;;
401
;;        Actual Hardware dependent code starts here                      ;;
402
;;                                                                        ;;
403
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
404
 
405
align 4
406
unload:
407
        ; TODO: (in this particular order)
408
        ;
409
        ; - Stop the device
410
        ; - Detach int handler
411
        ; - Remove device from local list (RTL8139_LIST)
412
        ; - call unregister function in kernel
413
        ; - Remove all allocated structures and buffers the card used
414
 
415
        or      eax, -1
416
 
417
ret
418
 
419
 
420
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
421
;;
422
;;  probe: enables the device (if it really is RTL8139)
423
;;
424
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
425
 
426
align 4
427
probe:
428
        DEBUGF  2, "Probing %s device\n", my_service
429
 
430
        PCI_make_bus_master
431
 
432
; get chip version
433
        set_io  0
434
        set_io  REG_TXCONFIG + 2
435
        in      ax, dx
436
        shr     ah, 2
437
        shr     ax, 6
438
        and     al, 01111111b
439
 
440
; now find it in our array
441
        mov     ecx, HW_VER_ARRAY_SIZE-1
442
  .chip_ver_loop:
443
        cmp     al, [hw_ver_array + ecx]
444
        je      .chip_ver_found
445
        dec     ecx
446
        jns     .chip_ver_loop
447
  .unknown:
448
        mov     ecx, 8
449
  .chip_ver_found:
450
        cmp     ecx, 8
451
        ja      .unknown
452
 
453
        mov     [device.hw_ver_id], cl
454
 
455
        mov     ecx, [crosslist+ecx*4]
456
        mov     [device.name], ecx
457
 
458
        DEBUGF  2, "Chip version: %s\n", ecx
459
 
460
; wake up the chip
461
        set_io  0
462
        set_io  REG_HLTCLK
463
        mov     al, 'R'         ; run the clock
464
        out     dx, al
465
 
466
; unlock config and BMCR registers
467
        set_io  REG_9346CR
468
        mov     al, (1 shl BIT_93C46_EEM1) or (1 shl BIT_93C46_EEM0)
469
        out     dx, al
470
 
471
; enable power management
472
        set_io  REG_CONFIG1
473
        in      al, dx
474
        cmp     [device.hw_ver_id], IDX_RTL8139B
475
        jae     .new_chip
476
; wake up older chips
477
        and     al, not ((1 shl BIT_SLEEP) or (1 shl BIT_PWRDWN))
478
        out     dx, al
479
        jmp     .finish_wake_up
480
 
481
; set LWAKE pin to active high (default value).
482
; it is for Wake-On-LAN functionality of some motherboards.
483
; this signal is used to inform the motherboard to execute a wake-up process.
484
; only at newer chips.
485
  .new_chip:
486
        or      al, (1 shl BIT_PMEn)
487
        and     al, not (1 shl BIT_LWACT)
488
        out     dx, al
489
 
490
        set_io  REG_CONFIG4
491
        in      al, dx
492
        and     al, not (1 shl BIT_LWPTN)
493
        out     dx, al
494
 
495
; lock config and BMCR registers
496
  .finish_wake_up:
497
        xor     al, al
498
        set_io  0
499
        set_io  REG_9346CR
500
        out     dx, al
501
        DEBUGF  2, "done!\n"
502
 
3685 hidnplayr 503
        xor     eax, eax
3545 hidnplayr 504
 
3685 hidnplayr 505
        ret
506
 
507
 
3545 hidnplayr 508
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
509
;;
510
;;   reset: Set up all registers and descriptors, clear some values
511
;;
512
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
513
 
514
reset:
515
        DEBUGF  2, "Reset\n"
516
 
517
; attach int handler
518
        movzx   eax, [device.irq_line]
519
        DEBUGF  1, "Attaching int handler to irq %x\n", eax:1
520
        stdcall AttachIntHandler, eax, int_handler, dword 0
521
        test    eax, eax
522
        jnz     @f
523
        DEBUGF  1, "\nCould not attach int handler!\n"
524
;        or      eax, -1
525
;        ret
526
       @@:
527
 
528
; reset chip
529
        DEBUGF  1, "Resetting chip\n"
530
        set_io  0
531
        set_io  REG_COMMAND
532
        mov     al, 1 shl BIT_RST
533
        out     dx, al
534
        mov     cx, 1000                ; wait no longer for the reset
535
  .wait_for_reset:
536
        in      al, dx
537
        test    al, 1 shl BIT_RST
538
        jz      .reset_completed        ; RST remains 1 during reset
539
        dec     cx
540
        jns     .wait_for_reset
541
        DEBUGF  1, "Reset timeout!\n"
542
  .reset_completed:
543
 
544
; unlock config and BMCR registers
545
        set_io  REG_9346CR
546
        mov     al, (1 shl BIT_93C46_EEM1) or (1 shl BIT_93C46_EEM0)
547
        out     dx, al
548
 
549
; initialize multicast registers (no filtering)
550
        mov     eax, 0xffffffff
551
        set_io  REG_MAR0
552
        out     dx, eax
553
        set_io  REG_MAR4
554
        out     dx, eax
555
 
556
; enable Rx/Tx
557
 
558
        mov     al, (1 shl BIT_RE) or (1 shl BIT_TE)
559
        set_io  REG_COMMAND
560
        out     dx, al
561
 
562
; Rxbuffer size, unlimited dma burst, no wrapping, no rx threshold
563
; accept broadcast packets, accept physical match packets
564
        mov     ax, RX_CONFIG
565
        set_io  REG_RXCONFIG
566
        out     dx, ax
567
 
568
; 1024 bytes DMA burst, total retries = 16 + 8 * 16 = 144
569
        mov     eax, (TX_MXDMA shl BIT_TX_MXDMA) or (TXRR shl BIT_TXRR) or BIT_IFG1 or BIT_IFG0
570
        set_io  REG_TXCONFIG
571
        out     dx, eax
572
 
573
; enable auto negotiation
574
        set_io  REG_BMCR
575
        in      ax, dx
576
        or      ax, (1 shl BIT_ANE)
577
        out     dx, ax
578
 
579
; set auto negotiation advertisement
580
        set_io  REG_ANAR
581
        in      ax, dx
582
        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)
583
        out     dx, ax
584
 
585
; lock config and BMCR registers
586
        xor     eax, eax
587
        set_io  REG_9346CR
588
        out     dx, al
589
 
590
; init RX/TX pointers
591
        mov     [device.rx_data_offset], eax
592
        mov     [device.curr_tx_desc], al
593
;        set_io  REG_CAPR
594
;        out     dx, ax
595
 
596
; clear packet/byte counters
597
        lea     edi, [device.bytes_tx]
598
        mov     ecx, 6
599
        rep     stosd
600
 
601
; clear missing packet counter
602
        set_io  REG_MPC
603
        out     dx, eax
604
 
605
; set RxBuffer address, init RX buffer offset
606
        mov     eax, [device.rx_buffer]
607
        mov     dword[eax], 0                   ; clear receive flags for first packet (really needed??)
3685 hidnplayr 608
        DEBUGF  1, "RX buffer virtual addr=0x%x\n", eax
3545 hidnplayr 609
        GetRealAddr
3685 hidnplayr 610
        DEBUGF  1, "RX buffer real addr=0x%x\n", eax
3545 hidnplayr 611
        set_io  REG_RBSTART
612
        out     dx, eax
613
 
614
; Read MAC address
615
        call    read_mac
616
 
617
; enable interrupts
618
        set_io  0
619
        set_io  REG_IMR
620
        mov     ax, INTERRUPT_MASK
621
        out     dx, ax
622
 
623
; Set the mtu, kernel will be able to send now
624
        mov     [device.mtu], 1514
625
 
626
        call    cable
627
 
628
; Indicate that we have successfully reset the card
629
        xor     eax, eax
630
        ret
631
 
632
 
633
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
634
;;                                         ;;
635
;; Transmit                                ;;
636
;;                                         ;;
637
;; In: buffer pointer in [esp+4]           ;;
638
;;     size of buffer in [esp+8]           ;;
639
;;     pointer to device structure in ebx  ;;
640
;;                                         ;;
641
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
642
align 4
643
transmit:
644
        DEBUGF  1, "\nTransmitting packet, buffer:%x, size:%u\n", [esp+4], [esp+8]
645
        mov     eax, [esp+4]
646
        DEBUGF  1, "To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
647
        [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
648
        [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
649
        [eax+13]:2,[eax+12]:2
650
 
651
        cmp     dword [esp+8], MAX_ETH_FRAME_SIZE
652
        ja      .fail
653
        cmp     dword [esp+8], 60
654
        jb      .fail
655
 
656
; check if we own the current discriptor
657
        set_io  0
658
        set_io  REG_TSD0
659
        movzx   ecx, [device.curr_tx_desc]
660
        shl     ecx, 2
661
        add     edx, ecx
662
        in      eax, dx
663
        test    eax, (1 shl BIT_OWN)
664
        jz      .wait_to_send
665
 
666
  .send_packet:
667
; get next descriptor
668
        inc     [device.curr_tx_desc]
669
        and     [device.curr_tx_desc], NUM_TX_DESC-1
670
 
671
; Update stats
672
        inc     [device.packets_tx]
673
        mov     eax, [esp+8]
674
        add     dword [device.bytes_tx], eax
675
        adc     dword [device.bytes_tx+4], 0
676
 
677
; Set the buffer address
678
        set_io  REG_TSAD0
679
        mov     eax, [esp+4]
680
        mov     [device.TX_DESC+ecx], eax
681
        GetRealAddr
682
        out     dx, eax
683
 
684
; And the size of the buffer
685
        set_io  REG_TSD0
686
        mov     eax, [esp+8]
687
        or      eax, (ERTXTH shl BIT_ERTXTH)    ; Early threshold
688
        out     dx, eax
689
 
690
        DEBUGF  1, "Packet Sent!\n"
691
        xor     eax, eax
692
        ret     8
693
 
694
  .wait_to_send:
695
        DEBUGF  1, "Waiting for timeout\n"
696
 
697
        push    edx
698
        mov     esi, 30
699
        stdcall Sleep
700
        pop     edx
701
 
702
        in      ax, dx
703
        test    ax, (1 shl BIT_OWN)
704
        jnz     .send_packet
705
 
706
        pusha
707
        call    reset                            ; if chip hung, reset it
708
        popa
709
 
710
        jmp     .send_packet
711
 
712
  .fail:
713
        DEBUGF  1, "failed!\n"
714
        stdcall KernelFree, [esp+4]
715
        or      eax, -1
716
        ret     8
717
 
718
 
719
 
720
 
721
 
722
;;;;;;;;;;;;;;;;;;;;;;;
723
;;                   ;;
724
;; Interrupt handler ;;
725
;;                   ;;
726
;;;;;;;;;;;;;;;;;;;;;;;
727
 
728
align 4
729
int_handler:
730
 
731
        push    ebx esi edi
732
 
733
        DEBUGF  1, "\n%s int\n", my_service
734
 
735
; find pointer of device wich made IRQ occur
736
        mov     ecx, [devices]
737
        test    ecx, ecx
738
        jz      .nothing
739
        mov     esi, device_list
740
  .nextdevice:
741
        mov     ebx, [esi]
742
 
743
        set_io  0
744
        set_io  REG_ISR
745
        in      ax, dx                          ; Get interrupt status
746
        out     dx, ax                          ; send it back to ACK
747
        test    ax, ax
748
        jnz     .got_it
749
  .continue:
750
        add     esi, 4
751
        dec     ecx
752
        jnz     .nextdevice
753
  .nothing:
754
        pop     edi esi ebx
755
        xor     eax, eax
756
 
757
        ret                                     ; If no device was found, abort (The irq was probably for a device, not registered to this driver)
758
 
759
  .got_it:
760
 
761
        DEBUGF  1, "Device: %x Status: %x\n", ebx, ax
762
 
763
;----------------------------------------------------
764
; Received packet ok?
765
 
766
        test    ax, ISR_ROK
767
        jz      @f
768
        push    ax
769
 
770
  .receive:
771
        set_io  0
772
        set_io  REG_COMMAND
773
        in      al, dx
774
        test    al, BUFE                        ; test if RX buffer is empty
775
        jnz     .finish
776
 
777
        DEBUGF  1, "RX: "
778
 
779
        mov     eax, [device.rx_buffer]
780
        add     eax, [device.rx_data_offset]
781
        test    byte [eax], (1 shl BIT_ROK)     ; check if packet is ok
782
        jz      .reset_rx
783
 
784
; packet is ok, copy it
785
        movzx   ecx, word [eax+2]               ; packet length
786
        sub     cx, 4                           ; don't copy CRC
787
 
788
; Update stats
789
        add     dword [device.bytes_rx], ecx
790
        adc     dword [device.bytes_rx + 4], 0
791
        inc     [device.packets_rx]
792
 
793
        DEBUGF  1, "Received %u bytes\n", ecx
794
 
795
        push    ebx eax ecx
796
        stdcall KernelAlloc, ecx                ; Allocate a buffer to put packet into
797
        pop     ecx
798
        test    eax, eax                        ; Test if we allocated succesfully
799
        jz      .abort
800
 
801
        mov     edi, eax                        ; Where we will copy too
802
 
803
        mov     esi, [esp]                      ; The buffer we will copy from
804
        add     esi, 4                          ; Dont copy CRC
805
 
806
        push    dword .abort                    ; Kernel will return to this address after EthReceiver
807
        push    ecx edi                         ; Save buffer pointer and size, to pass to kernel
808
 
809
  .copy:
810
        shr     ecx, 1
811
        jnc     .nb
812
        movsb
813
  .nb:
814
        shr     ecx, 1
815
        jnc     .nw
816
        movsw
817
  .nw:
818
        jz      .nd
819
        rep     movsd
820
  .nd:
821
 
822
        jmp     Eth_input                       ; Send it to kernel
823
 
824
  .abort:
825
        pop     eax ebx
826
                                                ; update eth_data_start_offset
827
        movzx   eax, word [eax+2]               ; packet length
828
        add     eax, [device.rx_data_offset]
829
        add     eax, 4+3                        ; packet header is 4 bytes long + dword alignment
830
        and     eax, not 3                      ; dword alignment
831
 
832
        cmp     eax, RX_BUFFER_SIZE
833
        jb      .no_wrap
3635 hidnplayr 834
        DEBUGF  1, "Wrapping"
3545 hidnplayr 835
        sub     eax, RX_BUFFER_SIZE
836
  .no_wrap:
837
        mov     [device.rx_data_offset], eax
838
        DEBUGF  1, "New RX ptr: %d\n", eax
839
 
840
        set_io  0
841
        set_io  REG_CAPR                        ; update 'Current Address of Packet Read register'
842
        sub     eax, 0x10                       ; value 0x10 is a constant for CAPR
843
        out     dx , ax
844
 
845
        jmp     .receive                        ; check for multiple packets
846
 
847
  .reset_rx:
848
        test    byte [eax], (1 shl BIT_CRC)
849
        jz      .no_crc_error
850
        DEBUGF  2, "\nCRC error!\n"
851
 
852
  .no_crc_error:
853
        test    byte [eax], (1 shl BIT_FAE)
854
        jz      .no_fae_error
855
        DEBUGF  1, "\nFrame alignment error!\n"
856
 
857
  .no_fae_error:
858
        DEBUGF  1, "Reset RX\n"
859
        in      al, dx                          ; read command register
860
        push    ax
861
        and     al, not (1 shl BIT_RE)          ; Clear the RE bit
862
        out     dx, al
863
        pop     ax
864
        out     dx, al                          ; write original command back
865
 
866
        add     edx, REG_RXCONFIG - REG_COMMAND         ; Restore RX configuration
867
        mov     ax, RX_CONFIG
868
        out     dx, ax
869
 
870
  .finish:
871
        pop     ax
872
 
873
;----------------------------------------------------
874
; Transmit ok / Transmit error
875
  @@:
876
        test    ax, ISR_TOK + ISR_TER
877
        jz      @f
878
 
879
        push    ax
880
        mov     ecx, (NUM_TX_DESC-1)*4
881
  .txdescloop:
882
        set_io  0
883
        set_io  REG_TSD0
884
        add     edx, ecx
885
        in      eax, dx
886
 
887
        test    eax, TSR_OWN                    ; DMA operation completed
888
        jz      .notthisone
889
 
890
        cmp     [device.TX_DESC+ecx], 0
891
        je      .notthisone
892
 
893
;  .notxd:
894
;        test    eax, TSR_TUN
895
;        jz      .nobun
896
;        DEBUGF  2, "TX: FIFO Buffer underrun!\n"
897
;
898
;  .nobun:
899
;        test    eax, TSR_OWC
900
;        jz      .noowc
901
;        DEBUGF  2, "TX: OWC!\n"
902
;
903
;  .noowc:
904
;        test    eax, TSR_TABT
905
;        jz      .notabt
906
;        DEBUGF  2, "TX: TABT!\n"
907
;
908
;  .notabt:
909
;        test    eax, TSR_CRS
910
;        jz      .nocsl
911
;        DEBUGF  2, "TX: Carrier Sense Lost!\n"
912
;
913
;  .nocsl:
914
 
915
        DEBUGF  1, "TX OK: free buffer %x\n", [device.TX_DESC+ecx]:8
916
        push    ecx ebx
917
        stdcall KernelFree, [device.TX_DESC+ecx]
918
        pop     ebx ecx
919
        mov     [device.TX_DESC+ecx], 0
920
 
921
  .notthisone:
922
        sub     ecx, 4
923
        ja      .txdescloop
924
        pop     ax
925
 
926
;----------------------------------------------------
927
; Rx buffer overflow ?
928
  @@:
929
        test    ax, ISR_RXOVW
930
        jz      @f
931
 
932
        push    ax
933
        DEBUGF  2, "RX-buffer overflow!\n"
934
 
935
        set_io  0
936
        set_io  REG_ISR
937
        mov     ax, ISR_FIFOOVW or ISR_RXOVW
938
        out     dx, ax
939
        pop     ax
940
 
941
;----------------------------------------------------
942
; Packet underrun?
943
  @@:
944
        test    ax, ISR_PUN
945
        jz      @f
946
 
947
        DEBUGF  2, "Packet underrun!\n"
948
 
949
;----------------------------------------------------
950
; Receive FIFO overflow ?
951
  @@:
952
        test    ax, ISR_FIFOOVW
953
        jz      @f
954
 
955
        push    ax
956
        DEBUGF  2, "RX fifo overflow!\n"
957
 
958
        set_io  0
959
        set_io  REG_ISR
960
        mov     ax, ISR_FIFOOVW or ISR_RXOVW
961
        out     dx, ax
962
        pop     ax
963
 
964
;----------------------------------------------------
965
; Something about Cable changed ?
966
  @@:
967
        test    ax, ISR_LENCHG
968
        jz      .fail
969
 
970
        call    cable
971
 
972
  .fail:
3635 hidnplayr 973
        DEBUGF  1, "\n"
3545 hidnplayr 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
 
1032
        DEBUGF  2, "Writing MAC: "
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
 
1068
        DEBUGF  2, "ok!\n"
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:
1080
        DEBUGF  2, "Reading MAC: "
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