Subversion Repositories Kolibri OS

Rev

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