Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
3545 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
4467 hidnplayr 3
;; Copyright (C) KolibriOS team 2004-2014. All rights reserved.    ;;
3545 hidnplayr 4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
6
;;  RTL8029/ne2000 driver for KolibriOS                            ;;
7
;;                                                                 ;;
8
;;  based on RTL8029.asm driver for menuetos                       ;;
9
;;  and realtek8029.asm for SolarOS by Eugen Brasoveanu            ;;
10
;;                                                                 ;;
11
;;    Written by hidnplayr@kolibrios.org                           ;;
12
;;     with help from CleverMouse                                  ;;
13
;;                                                                 ;;
14
;;          GNU GENERAL PUBLIC LICENSE                             ;;
15
;;             Version 2, June 1991                                ;;
16
;;                                                                 ;;
17
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
18
 
19
format MS COFF
20
 
21
        API_VERSION             = 0x01000100
22
        DRIVER_VERSION          = 5
23
 
24
        MAX_DEVICES             = 16
25
 
26
        DEBUG                   = 1
27
        __DEBUG__               = 1
3856 hidnplayr 28
        __DEBUG_LEVEL__         = 2             ; 1 = verbose, 2 = errors only
3545 hidnplayr 29
 
4467 hidnplayr 30
include '../struct.inc'
31
include '../macros.inc'
3545 hidnplayr 32
include '../proc32.inc'
33
include '../imports.inc'
34
include '../fdo.inc'
35
include '../netdrv.inc'
36
 
37
virtual at ebx
38
 
39
        device:
40
 
41
        ETH_DEVICE
42
 
43
        .io_addr        dd ?
44
        .irq_line       db ?
45
        .pci_bus        dd ?
46
        .pci_dev        dd ?
47
 
48
        .flags          db ?
49
        .vendor         db ?
50
 
51
        .memsize        db ?
52
        .rx_start       db ?
53
        .tx_start       db ?
54
        .bmem           dd ?
55
        .rmem           dd ?
56
 
57
        .size = $ - device
58
 
59
end virtual
60
 
61
 
62
public START
63
public service_proc
64
public version
65
 
66
        P0_COMMAND              = 0x00
67
        P0_PSTART               = 0x01
68
        P0_PSTOP                = 0x02
69
        P0_BOUND                = 0x03
70
        P0_TSR                  = 0x04
71
        P0_TPSR                 = 0x04
72
        P0_TBCR0                = 0x05
73
        P0_TBCR1                = 0x06
74
        P0_ISR                  = 0x07
75
        P0_RSAR0                = 0x08
76
        P0_RSAR1                = 0x09
77
        P0_RBCR0                = 0x0A
78
        P0_RBCR1                = 0x0B
79
        P0_RSR                  = 0x0C
80
        P0_RCR                  = 0x0C
81
        P0_TCR                  = 0x0D
82
        P0_DCR                  = 0x0E
83
        P0_IMR                  = 0x0F
84
 
85
        P1_COMMAND              = 0x00
86
        P1_PAR0                 = 0x01
87
        P1_PAR1                 = 0x02
88
        P1_PAR2                 = 0x03
89
        P1_PAR3                 = 0x04
90
        P1_PAR4                 = 0x05
91
        P1_PAR5                 = 0x06
92
        P1_CURR                 = 0x07
93
        P1_MAR0                 = 0x08
94
 
95
        CMD_PS0                 = 0x00          ; Page 0 select
96
        CMD_PS1                 = 0x40          ; Page 1 select
97
        CMD_PS2                 = 0x80          ; Page 2 select
98
        CMD_RD2                 = 0x20          ; Remote DMA control
99
        CMD_RD1                 = 0x10
100
        CMD_RD0                 = 0x08
101
        CMD_TXP                 = 0x04          ; transmit packet
102
        CMD_STA                 = 0x02          ; start
103
        CMD_STP                 = 0x01          ; stop
104
 
105
        CMD_RDMA_READ           = 001b shl 3
106
        CMD_RDMA_WRITE          = 010b shl 3
107
        CMD_RDMA_SEND_PACKET    = 011b shl 3
108
        CMD_RDMA_ABORT          = 100b shl 3    ; really is 1xx, Abort/Complete Remote DMA
109
;        RDMA_MASK               = 111b shl 3    ; internal, mask
110
 
111
        RCR_MON                 = 0x20          ; monitor mode
112
 
113
        DCR_FT1                 = 0x40
114
        DCR_LS                  = 0x08          ; Loopback select
115
        DCR_WTS                 = 0x01          ; Word transfer select
116
 
117
        ISR_PRX                 = 0x01          ; successful recv
118
        ISR_PTX                 = 0x02          ; successful xmit
119
        ISR_RXE                 = 0x04          ; receive error
120
        ISR_TXE                 = 0x08          ; transmit error
121
        ISR_OVW                 = 0x10          ; Overflow
122
        ISR_CNT                 = 0x20          ; Counter overflow
123
        ISR_RDC                 = 0x40          ; Remote DMA complete
124
        ISR_RST                 = 0x80          ; reset
125
 
126
        IRQ_MASK                = ISR_PRX ;+ ISR_PTX ;+ ISR_RDC + ISR_PTX + ISR_TXE
127
 
128
        RSTAT_PRX               = 1 shl 0       ; successful recv
129
        RSTAT_CRC               = 1 shl 1       ; CRC error
130
        RSTAT_FAE               = 1 shl 2       ; Frame alignment error
131
        RSTAT_OVER              = 1 shl 3       ; FIFO overrun
132
 
133
        TXBUF_SIZE              = 6
134
        RXBUF_END               = 32
135
        PAGE_SIZE               = 256
136
 
137
        ETH_ZLEN                = 60
138
        ETH_FRAME_LEN           = 1514
139
 
140
        FLAG_PIO                = 1 shl 0
141
        FLAG_16BIT              = 1 shl 1
142
 
143
        VENDOR_NONE             = 0
144
        VENDOR_WD               = 1
145
        VENDOR_NOVELL           = 2
146
        VENDOR_3COM             = 3
147
 
148
        NE_ASIC                 = 0x10
149
        NE_RESET                = 0x0F          ; Used to reset card
150
        NE_DATA                 = 0x00          ; Used to read/write NIC mem
151
 
152
        MEM_8k                  = 32
153
        MEM_16k                 = 64
154
        MEM_32k                 = 128
155
 
156
        ISA_MAX_ADDR            = 0x400
157
 
158
 
159
 
160
section '.flat' code readable align 16
161
 
162
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
163
;;
164
;; proc START
165
;;
166
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
167
 
168
align 4
169
proc START stdcall, state:dword
170
 
171
        cmp     [state], 1
172
        jne     .exit
173
  .entry:
3856 hidnplayr 174
        DEBUGF  1, "Loading driver\n"
3545 hidnplayr 175
        stdcall RegService, my_service, service_proc
176
        ret
177
  .fail:
178
  .exit:
179
        xor     eax, eax
180
        ret
181
 
182
endp
183
 
184
 
185
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
186
;;
187
;; proc SERVICE_PROC
188
;;
189
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
190
 
191
align 4
192
proc service_proc stdcall, ioctl:dword
193
 
194
        mov     edx, [ioctl]
4470 hidnplayr 195
        mov     eax, [edx + IOCTL.io_code]
3545 hidnplayr 196
 
197
;------------------------------------------------------
198
                       ;---------------
199
        cmp     eax, 0 ;SRV_GETVERSION
200
        jne     @F     ;---------------
201
 
4470 hidnplayr 202
        cmp     [edx + IOCTL.out_size], 4
3545 hidnplayr 203
        jb      .fail
4470 hidnplayr 204
        mov     eax, [edx + IOCTL.output]
3545 hidnplayr 205
        mov     [eax], dword API_VERSION
206
 
207
        xor     eax, eax
208
        ret
209
 
210
;------------------------------------------------------
211
  @@:                  ;---------
212
        cmp     eax, 1 ;SRV_HOOK
213
        jne     @F     ;---------
214
 
3856 hidnplayr 215
        DEBUGF  1, "Checking if device is already listed..\n"
3545 hidnplayr 216
 
4470 hidnplayr 217
        mov     eax, [edx + IOCTL.input]
3545 hidnplayr 218
 
4470 hidnplayr 219
        cmp     [edx + IOCTL.inp_size], 3
3545 hidnplayr 220
        jb      .fail
221
        cmp     byte [eax], 1
222
        je      .pci
223
 
4470 hidnplayr 224
        cmp     [edx + IOCTL.inp_size], 4
3545 hidnplayr 225
        jb      .fail
226
        cmp     byte [eax], 0
227
        je      .isa
228
 
229
        jmp     .fail
230
 
231
  .pci:
232
 
233
; check if the device is already listed
234
 
235
        mov     esi, device_list
236
        mov     ecx, [devices]
237
        test    ecx, ecx
238
        jz      .firstdevice_pci
239
 
240
        mov     ax, [eax+1]                             ; get the pci bus and device numbers
241
  .nextdevice:
242
        mov     ebx, [esi]
243
        cmp     al, byte[device.pci_bus]
244
        jne     @f
245
        cmp     ah, byte[device.pci_dev]
246
        je      .find_devicenum                         ; Device is already loaded, let's find it's device number
247
       @@:
248
        add     esi, 4
249
        loop    .nextdevice
250
 
251
  .firstdevice_pci:
252
        call    create_new_struct
253
 
4470 hidnplayr 254
        mov     eax, [edx + IOCTL.input]
3545 hidnplayr 255
        movzx   ecx, byte[eax+1]
256
        mov     [device.pci_bus], ecx
257
        movzx   ecx, byte[eax+2]
258
        mov     [device.pci_dev], ecx
259
 
260
; Now, it's time to find the base io addres of the PCI device
261
 
262
        PCI_find_io
263
 
264
; We've found the io address, find IRQ now
265
 
266
        PCI_find_irq
267
 
268
        jmp     .hook
269
 
270
  .isa:
271
 
272
        mov     esi, device_list
273
        mov     ecx, [devices]
274
        test    ecx, ecx
275
        jz      .firstdevice_isa
276
        mov     al, [eax+3]
277
        movzx   edi, word [eax+1]
278
  .nextdevice_isa:
279
        mov     ebx, [esi]
280
        cmp     edi, [device.io_addr]
281
        jne     .maybenext
282
        cmp     al, [device.irq_line]
283
        je      find_device_num
284
  .maybenext:
285
        add     esi, 4
286
        loop    .nextdevice_isa
287
 
288
 
289
 
290
  .firstdevice_isa:
291
        call    create_new_struct
292
 
4470 hidnplayr 293
        mov     eax, [edx + IOCTL.input]
3545 hidnplayr 294
        movzx   ecx, word [eax+1]
295
        mov     [device.io_addr], ecx
296
        mov     cl, [eax+3]
297
        mov     [device.irq_line], cl
298
 
299
  .hook:
300
 
3856 hidnplayr 301
        DEBUGF  1, "Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
3545 hidnplayr 302
        [device.pci_dev]:1,[device.pci_bus]:1,[device.irq_line]:1,[device.io_addr]:4
303
 
304
        call    probe                                                   ; this function will output in eax
305
        test    eax, eax
306
        jnz     .err                                                    ; If an error occured, exit
307
 
308
        mov     eax, [devices]
309
        mov     [device_list+4*eax], ebx
310
        inc     [devices]
311
 
312
        mov     [device.type], NET_TYPE_ETH
313
        call    NetRegDev
314
 
315
        cmp     eax, -1
316
        jz      .err
317
        ret
318
 
319
 
320
; If the device was already loaded, find the device number and return it in eax
321
 
322
  .find_devicenum:
3856 hidnplayr 323
        DEBUGF  1, "Trying to find device number of already registered device\n"
3545 hidnplayr 324
        call    NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
325
                                                                        ; into a device number in edi
326
        mov     eax, edi                                                ; Application wants it in eax instead
3856 hidnplayr 327
        DEBUGF  1, "Kernel says: %u\n", eax
3545 hidnplayr 328
        ret
329
 
330
  .err:
3856 hidnplayr 331
        DEBUGF  2, "Failed, removing device structure\n"
3545 hidnplayr 332
        stdcall KernelFree, ebx
333
 
334
        jmp     .fail
335
 
336
;------------------------------------------------------
337
  @@:
338
.fail:
339
        or      eax, -1
340
        ret
341
 
342
;------------------------------------------------------
343
endp
344
 
345
 
346
create_new_struct:
347
 
348
        cmp     [devices], MAX_DEVICES
349
        jae     .fail
350
 
351
        allocate_and_clear ebx, device.size, .fail      ; Allocate the buffer for device structure
352
 
353
        mov     [device.reset], reset
354
        mov     [device.transmit], transmit
355
        mov     [device.unload], unload
356
        mov     [device.name], my_service
357
 
358
        ret
359
 
360
  .fail:
361
        add     esp, 4                                  ; return to caller of 'hook'
362
        or      eax, -1
363
        ret
364
 
365
find_device_num:
366
 
3856 hidnplayr 367
        DEBUGF  1, "Trying to find device number of already registered device\n"
3545 hidnplayr 368
        mov     ebx, eax
369
        call    NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
370
                                                                        ; into a device number in edi
371
        mov     eax, edi                                                ; Application wants it in eax instead
3856 hidnplayr 372
        DEBUGF  1, "Kernel says: %u\n", eax
3545 hidnplayr 373
        ret
374
 
375
 
376
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
377
;;                                                                        ;;
378
;;        Actual Hardware dependent code starts here                      ;;
379
;;                                                                        ;;
380
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
381
 
382
 
383
unload:   ; TODO
384
        or      eax, -1
385
        ret
386
 
387
 
388
 
389
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
390
;;
391
;;  probe: enables the device and clears the rx buffer
392
;;
393
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
394
 
395
probe:
396
        mov     [device.vendor], VENDOR_NONE
397
        mov     [device.bmem], 0
398
 
3856 hidnplayr 399
        DEBUGF  1, "Trying 16-bit mode\n"
3545 hidnplayr 400
 
401
        mov     [device.flags], FLAG_16BIT + FLAG_PIO
402
        mov     [device.memsize], MEM_32k
403
        mov     [device.tx_start], 64
404
        mov     [device.rx_start], TXBUF_SIZE + 64
405
 
406
        set_io  0
407
        set_io  P0_DCR
408
        mov     al, DCR_WTS + DCR_FT1 + DCR_LS  ; word transfer select +
409
        out     dx, al
410
 
411
        set_io  P0_PSTART
412
        mov     al, MEM_16k
413
        out     dx, al
414
 
415
        set_io  P0_PSTOP
416
        mov     al, MEM_32k
417
        out     dx, al
418
 
419
        mov     esi, my_service
420
        mov     di, 16384
421
        mov     cx, 14
422
        call    PIO_write
423
 
424
        mov     si, 16384
425
        mov     cx, 14
426
        sub     esp, 16
427
        mov     edi, esp
428
        call    PIO_read
429
 
430
        mov     esi, esp
431
        add     esp, 16
432
        mov     edi, my_service
433
        mov     ecx, 13
434
        repe    cmpsb
435
        je      ep_set_vendor
436
 
3856 hidnplayr 437
        DEBUGF  1, "16-bit mode failed\n"
438
        DEBUGF  1, "Trying 8-bit mode\n"
3545 hidnplayr 439
 
440
        mov     [device.flags], FLAG_PIO
441
        mov     [device.memsize], MEM_16k
442
        mov     [device.tx_start], 32
443
        mov     [device.rx_start], TXBUF_SIZE + 32
444
 
445
        set_io  NE_ASIC + NE_RESET
446
        in      al, dx
447
        out     dx, al
448
 
449
        in      al, 0x84
450
 
451
        set_io  P0_COMMAND
452
        mov     al, CMD_RD2 + CMD_STP
453
        out     dx, al
454
 
455
        set_io  P0_RCR
456
        mov     al, RCR_MON
457
        out     dx, al
458
 
459
        set_io  P0_DCR
460
        mov     al, DCR_FT1 + DCR_LS
461
        out     dx, al
462
 
463
        set_io  P0_PSTART
464
        mov     al, MEM_8k
465
        out     dx, al
466
 
467
        set_io  P0_PSTOP
468
        mov     al, MEM_16k
469
        out     dx, al
470
 
471
        mov     esi, my_service
472
        mov     di, 8192
473
        mov     cx, 14
474
        call    PIO_write
475
 
476
        mov     si, 8192
477
        mov     cx, 14
478
        sub     esp, 16
479
        mov     edi, esp
480
        call    PIO_read
481
 
482
        mov     esi, my_service
483
        mov     edi, esp
484
        add     esp, 16
485
        mov     ecx, 13
486
        repe    cmpsb
487
        je      ep_set_vendor
488
 
3856 hidnplayr 489
        DEBUGF  2, "This is not a valid ne2000 device!\n"
3545 hidnplayr 490
        or      eax, -1
491
        ret
492
 
493
 
494
ep_set_vendor:
495
 
3856 hidnplayr 496
        DEBUGF  1, "Mode ok\n"
3545 hidnplayr 497
 
498
        cmp     [device.io_addr], ISA_MAX_ADDR
499
        jbe     .isa
500
 
3856 hidnplayr 501
        DEBUGF  1, "Card is using PCI bus\n"
3545 hidnplayr 502
 
503
        mov     [device.vendor], VENDOR_NOVELL  ;;; FIXME
504
        jmp     ep_check_have_vendor
505
 
506
  .isa:
3856 hidnplayr 507
        DEBUGF  1, "Card is using ISA bus\n"
3545 hidnplayr 508
 
509
        mov     [device.vendor], VENDOR_NOVELL
510
 
511
ep_check_have_vendor:
512
 
513
 
514
        mov     al, [device.vendor]
515
        cmp     al, VENDOR_NONE
516
;        je      exit
517
 
518
        cmp     al, VENDOR_3COM
519
        je      reset
520
 
521
        mov     eax, [device.bmem]
522
        mov     [device.rmem], eax
523
 
524
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
525
;;
526
;;   reset: Place the chip into a virgin state
527
;;
528
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
529
 
530
reset:
3856 hidnplayr 531
        DEBUGF  1, "Resetting device\n"
3545 hidnplayr 532
 
533
; attach int handler
534
        movzx   eax, [device.irq_line]
3856 hidnplayr 535
        DEBUGF  1, "Attaching int handler to irq %x\n", eax:1
3545 hidnplayr 536
        stdcall AttachIntHandler, eax, int_handler, dword 0
3856 hidnplayr 537
        test    eax, eax
538
        jnz     @f
539
        DEBUGF  2, "Could not attach int handler!\n"
540
;        or      eax, -1
541
;        ret
542
       @@:
3545 hidnplayr 543
 
544
; Stop card + DMA
545
        set_io  0
546
;        set_io  P0_COMMAND
547
        mov     al, CMD_PS0 + CMD_RDMA_ABORT + CMD_STP
548
        out     dx, al
549
 
550
; initialize DCR
551
        set_io  P0_DCR
552
        mov     al, DCR_FT1 + DCR_LS
553
        test    [device.flags], FLAG_16BIT
554
        jz      @f
555
        or      al, DCR_WTS                     ; word transfer select
556
      @@:
557
        out     dx, al
558
 
559
; clear remote bytes count
560
        set_io  P0_RBCR0
561
        xor     al, al
562
        out     dx, al
563
 
564
        set_io  P0_RBCR1
565
        out     dx, al
566
 
567
; initialize Receive configuration register (until all init is done)
568
        set_io  P0_RCR
569
        mov     al, 0x20        ; monitor mode
570
        out     dx, al
571
 
572
; transmit configuration register to monitor mode (until all ini is done)
573
        set_io  P0_TCR
574
        mov     al, 2           ; internal loopback
575
        out     dx, al
576
 
577
; clear interupt status
578
        set_io  P0_ISR
579
        mov     al, 0xff
580
        out     dx, al
581
 
582
; clear IRQ mask                        ;;;;; CHECKME ;;;;;
583
        set_io  P0_IMR
584
        xor     al, al
585
        out     dx, al
586
 
587
; set transmit pointer
588
        set_io  P0_TPSR
589
        mov     al, [device.tx_start]
590
        out     dx, al
591
 
592
; set pagestart pointer
593
        set_io  P0_PSTART
594
        mov     al, [device.rx_start]
595
        out     dx, al
596
 
597
; set pagestop pointer
598
        set_io  P0_PSTOP
599
        mov     al, [device.memsize]
600
        out     dx, al
601
 
602
; set boundary pointer
603
        set_io  P0_BOUND
604
        mov     al, [device.memsize]
605
        dec     al
606
        out     dx, al
607
 
608
; set curr pointer
609
        set_io  P0_COMMAND
610
        mov     al, CMD_PS1 ;+ CMD_RD2 + CMD_STP ; page 1, stop mode
611
        out     dx, al
612
 
613
        set_io  P1_CURR
614
        mov     al, [device.rx_start]
615
        out     dx, al
616
 
617
        set_io  P0_COMMAND
618
        mov     al, CMD_PS0 ;+ CMD_RD2 + CMD_STA ; go to page 0, start mode
619
        out     dx, al
620
 
621
; Read MAC address and set it to registers
622
        call    read_mac
623
        push    .macret
624
        sub     esp, 6
625
        lea     esi, [device.mac]
626
        mov     edi, esp
627
        movsd
628
        movsw
629
        jmp     write_mac
630
  .macret:
631
 
632
; set IRQ mask
633
        set_io  0
634
        set_io  P0_IMR
635
        mov     al, IRQ_MASK
636
        out     dx, al
637
 
638
; start mode
639
        set_io  P0_COMMAND
640
        mov     al, CMD_STA
641
        out     dx, al
642
 
643
; clear transmit control register
644
        set_io  P0_TCR
645
        xor     al, al                  ; no loopback
646
        out     dx, al
647
 
648
; set receive control register ;;;;
649
        set_io  P0_RCR
650
        mov     al, 4                   ; accept broadcast
651
        out     dx, al
652
 
653
; clear packet/byte counters
654
        xor     eax, eax
655
        lea     edi, [device.bytes_tx]
656
        mov     ecx, 6
657
        rep     stosd
658
 
659
; Set the mtu, kernel will be able to send now
660
        mov     [device.mtu], ETH_FRAME_LEN
661
 
662
; Set link state to unknown
663
        mov     [device.state], ETH_LINK_UNKOWN
664
 
665
; Indicate that we have successfully reset the card
666
        xor     eax, eax
3856 hidnplayr 667
        DEBUGF  1, "Done!\n"
3545 hidnplayr 668
 
669
        ret
670
 
671
 
672
 
673
;***************************************************************************
674
;   Function
675
;      transmit
676
; buffer in [esp+4], size in [esp+8], pointer to device struct in ebx
677
;***************************************************************************
678
 
679
align 4
680
transmit:
681
 
682
        mov     esi, [esp + 4]
683
        mov     ecx, [esp + 8]
3856 hidnplayr 684
        DEBUGF  1, "Transmitting packet, buffer:%x, size:%u\n",esi, ecx
685
        DEBUGF  1, "To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
3545 hidnplayr 686
        [esi+0]:2,[esi+1]:2,[esi+2]:2,[esi+3]:2,[esi+4]:2,[esi+5]:2,[esi+6]:2,[esi+7]:2,[esi+8]:2,[esi+9]:2,[esi+10]:2,[esi+11]:2,[esi+13]:2,[esi+12]:2
687
 
688
        cmp     ecx, ETH_FRAME_LEN
689
        ja      .err ; packet is too long
690
        cmp     ecx, ETH_ZLEN
691
        jb      .err ; packet is too short
692
 
693
        movzx   edi, [device.tx_start]
694
        shl     edi, 8
695
        push    cx
696
        call    PIO_write
697
        pop     cx
698
 
699
        set_io  0
700
;        set_io  P0_COMMAND
701
        mov     al, CMD_PS0 + CMD_RD2 + CMD_STA
702
        out     dx, al
703
 
704
        set_io  P0_TPSR
705
        mov     al, [device.tx_start]
706
        out     dx, al
707
 
708
        set_io  P0_TBCR0
709
        mov     al, cl
710
        out     dx, al
711
 
712
        set_io  P0_TBCR1
713
        mov     al, ch
714
        out     dx, al
715
 
716
        set_io  P0_COMMAND
717
        mov     al, CMD_PS0 + CMD_TXP + CMD_RD2 + CMD_STA
718
        out     dx, al
719
 
3856 hidnplayr 720
        DEBUGF  1, "Packet Sent!\n"
3545 hidnplayr 721
 
722
        inc     [device.packets_tx]
723
        mov     eax, [esp + 8]                   ; Get packet size in eax
724
 
725
        add     dword [device.bytes_tx], eax
726
        adc     dword [device.bytes_tx + 4], 0
727
 
728
        stdcall KernelFree, [esp+4]
729
        xor     eax, eax
730
        ret     8
731
 
3619 hidnplayr 732
  .err:
3856 hidnplayr 733
        DEBUGF  2, "Transmit error!\n"
4334 hidnplayr 734
        stdcall KernelFree, [esp+4]
3545 hidnplayr 735
        or      eax, -1
736
        ret     8
737
 
738
 
739
 
740
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
741
;
742
; Interrupt handler
743
;
744
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
745
 
746
align 4
747
int_handler:
748
 
749
        push    ebx esi edi
750
 
3856 hidnplayr 751
        DEBUGF  1, "INT\n"
3545 hidnplayr 752
 
753
; find pointer of device wich made INT occur
754
 
755
        mov     ecx, [devices]
756
        test    ecx, ecx
757
        jz      .nothing
758
        mov     esi, device_list
759
  .nextdevice:
760
        mov     ebx, [esi]
761
 
762
        set_io  0
763
;        set_io  P0_COMMAND
764
        mov     al, CMD_PS0
765
        out     dx, al
766
 
767
        set_io  P0_ISR
768
        in      al, dx
769
        test    al, al
770
        jnz     .got_it
771
  .continue:
772
        add     esi, 4
773
        dec     ecx
774
        jnz     .nextdevice
775
  .nothing:
776
        pop     edi esi ebx
777
        xor     eax, eax
778
 
779
        ret
780
 
781
  .got_it:
782
 
3856 hidnplayr 783
        DEBUGF  1, "Device=%x status=%x\n", ebx, eax:2
3545 hidnplayr 784
 
785
        push    ebx
786
 
787
        test    al, ISR_PRX     ; packet received ok ?
788
        jz      .no_rx
789
 
790
        test    [device.flags], FLAG_PIO
791
        jz      .no_rx          ; FIXME: Only PIO mode supported for now
792
 
793
;
794
 
795
        pushd   .no_rx
796
 
797
; allocate a buffer
798
 
799
        stdcall KernelAlloc, ETH_FRAME_LEN
800
        test    eax, eax
801
        jz      .fail_2
802
        pushd   0
803
        push    eax
804
 
805
; read offset for current packet from device
806
 
807
        set_io  0
808
        set_io  P0_BOUND        ; boundary ptr is offset to next packet we need to read.
809
        in      al, dx
810
        inc     al
811
 
812
        cmp     al, [device.memsize]
813
        jb      @f
814
        mov     al, [device.rx_start]
815
       @@:
816
        mov     ch, al
817
 
818
        set_io  P0_COMMAND
819
        mov     al, CMD_PS1
820
        out     dx, al
821
 
822
        set_io  P1_CURR
823
        in      al, dx          ; get current page in cl
824
        mov     cl, al
825
 
826
        set_io  P1_COMMAND
827
        mov     al, CMD_PS0
828
        out     dx, al
829
 
830
        cmp     cl, [device.memsize]
831
        jb      @f
832
        mov     cl, [device.rx_start]
833
       @@:
834
 
835
        cmp     cl, ch
836
        je      .fail
837
 
838
        movzx   esi, ch                         ; we are using 256 byte pages
839
        shl     esi, 8                          ; esi now holds the offset for current packet
840
 
841
; Get packet header in eax
842
 
843
        sub     esp, 4                          ; reserve 4 bytes on stack to put packet header in
844
        mov     edi, esp
845
        mov     cx, 4
846
        call    PIO_read
847
 
848
        mov     ecx, [esp]                      ; ecx now contains packet header
849
 
850
; check if packet is ok
851
 
852
        test    ecx, RSTAT_PRX
853
        jz      .fail_3
854
 
855
; calculate packet length in ecx
856
 
857
        shr     ecx, 16
858
        sub     ecx, 4                          ; CRC doesnt count as data byte
859
        mov     [esp + 4 + 4], ecx
860
 
861
; check if packet size is ok
862
 
863
        cmp     ecx, ETH_ZLEN
864
        jb      .fail_3
865
        cmp     ecx, ETH_FRAME_LEN
866
        ja      .fail_3
867
 
868
; update stats
869
 
3856 hidnplayr 870
        DEBUGF  1, "Received %u bytes\n", ecx
3545 hidnplayr 871
 
872
        add     dword[device.bytes_rx], ecx
873
        adc     dword[device.bytes_rx + 4], 0
874
        inc     [device.packets_rx]
875
 
876
; update read and write pointers
877
 
878
        add     esi, 4
879
        mov     edi, [esp + 4]
880
 
881
; now check if we can read all data at once (if we cross the end boundary, we need to wrap back to the beginning)
882
 
883
        xor     eax, eax
884
        mov     ah, [device.memsize]
885
        sub     eax, esi
886
        cmp     ecx, eax                ; eax = number of bytes till end of buffer, ecx = bytes we need to read
887
        jbe     .no_wrap
888
 
889
; Read first part
890
 
891
        sub     ecx, eax
892
        push    ecx
893
        mov     ecx, eax
894
 
895
        call    PIO_read                ; Read the data
896
 
897
; update pointers
898
 
899
        add     edi, ecx
900
        pop     ecx
901
 
902
        movzx   esi, [device.rx_start]
903
        shl     esi, 8
904
 
905
; now read second part (or only part)
906
 
907
  .no_wrap:
908
        call    PIO_read                ; Read the data
909
 
910
; update boundary pointer
911
 
912
        pop     eax
913
        mov     al, ah
914
        cmp     al, [device.rx_start]
915
        jne     @f
916
        mov     al, [device.memsize]
917
       @@:
918
 
919
        set_io  0
920
        set_io  P0_BOUND
921
        dec     al
922
        out     dx, al
923
 
924
; now send the data to the kernel
925
 
926
        jmp     Eth_input
927
 
928
  .fail_3:
929
        add     esp, 4
930
  .fail:
931
        add     esp, 8
932
  .fail_2:
933
 
934
 
935
  .no_rx:
936
        pop     ebx
3856 hidnplayr 937
        DEBUGF  1, "done\n"
3545 hidnplayr 938
 
939
        set_io  0
940
        set_io  P0_ISR
941
        mov     al, 0xff
942
        out     dx, al
943
 
944
        pop     edi esi ebx
945
 
946
        ret
947
 
948
 
949
 
950
 
951
 
952
;;;;;;;;;;;;;;;;;;;;;;;
953
;;                   ;;
954
;; Write MAC address ;;
955
;;                   ;;
956
;;;;;;;;;;;;;;;;;;;;;;;
957
 
958
align 4
959
write_mac:      ; in: mac on stack (6 bytes)
960
 
3856 hidnplayr 961
        DEBUGF  1, "Writing MAC\n"
3545 hidnplayr 962
 
963
        set_io  0
964
        mov     al, CMD_PS1; + CMD_RD2 + CMD_STP
965
        out     dx, al
966
 
967
        set_io  P1_PAR0
968
        mov     esi, esp
969
        mov     cx, 6
970
 @@:
971
        lodsb
972
        out     dx, al
973
        inc     dx
974
        loopw   @r
975
 
976
        add     esp, 6
977
 
978
; Notice this procedure does not ret, but continues to read_mac instead.
979
 
980
;;;;;;;;;;;;;;;;;;;;;;
981
;;                  ;;
982
;; Read MAC address ;;
983
;;                  ;;
984
;;;;;;;;;;;;;;;;;;;;;;
985
 
986
read_mac:
987
 
3856 hidnplayr 988
        DEBUGF  1, "Reading MAC\n"
3545 hidnplayr 989
 
990
        xor     esi, esi
991
        mov     cx, 16
992
        sub     esp, 16
993
        mov     edi, esp
994
        call    PIO_read
995
 
996
        mov     esi, esp
997
        add     esp, 16
998
        lea     edi, [device.mac]
999
        mov     ecx, 6
1000
  .loop:
1001
        movsb
1002
        test    [device.flags], FLAG_16BIT
1003
        jz      .8bit
1004
        inc     esi
1005
  .8bit:
1006
        loop    .loop
1007
 
3856 hidnplayr 1008
        DEBUGF  1, "MAC=%x-%x-%x-%x-%x-%x\n",\
3545 hidnplayr 1009
        [device.mac]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2
1010
 
1011
        ret
1012
 
1013
 
1014
;***************************************************************************
1015
;
1016
;   PIO_read
1017
;
1018
;   Description
1019
;       Read a frame from the ethernet card via Programmed I/O
1020
;      src in si
1021
;      cnt in cx
1022
;       dst in edi
1023
;***************************************************************************
1024
PIO_read:
1025
 
3856 hidnplayr 1026
        DEBUGF  1, "PIO Read from %x to %x, %u bytes ", si, edi, cx
3545 hidnplayr 1027
 
1028
; start DMA
1029
        set_io  0
1030
;        set_io  P0_COMMAND
1031
        mov     al, CMD_RD2 + CMD_STA
1032
        out     dx, al
1033
 
1034
; set length of data we're interested in
1035
        set_io  P0_RBCR0
1036
        mov     al, cl
1037
        out     dx, al
1038
 
1039
        set_io  P0_RBCR1
1040
        mov     al, ch
1041
        out     dx, al
1042
 
1043
; set offset of what we want to read
1044
        set_io  P0_RSAR0
1045
        mov     ax, si
1046
        out     dx, al
1047
 
1048
        set_io  P0_RSAR1
1049
        shr     ax, 8
1050
        out     dx, al
1051
 
1052
; start DMA read
1053
        set_io  P0_COMMAND
1054
        mov     al, CMD_RD0 + CMD_STA
1055
        out     dx, al
1056
 
1057
        set_io  NE_ASIC
1058
 
1059
        test    [device.flags], FLAG_16BIT
1060
        jz      .8bits
1061
 
3856 hidnplayr 1062
        DEBUGF  1, "(16-bit mode)\n"
3545 hidnplayr 1063
 
1064
        shr     cx, 1   ; note that if the number was odd, carry flag will be set
1065
        pushf
1066
 
1067
  .16bits:
1068
        in      ax, dx
1069
        stosw
1070
        loopw   .16bits
1071
 
1072
        inc     cx
1073
        popf
1074
        jnc     .done
1075
        jmp     .8bits_
1076
 
1077
  .8bits:
3856 hidnplayr 1078
        DEBUGF  1, "(8-bit mode)\n"
3545 hidnplayr 1079
 
1080
  .8bits_:
1081
        in      al, dx
1082
        stosb
1083
        loopw   .8bits_
1084
 
1085
 
1086
  .done:
1087
;        set_io  0
1088
;        set_io  P0_ISR
1089
;
1090
;  .dmawait:                             ; Wait for Remote DMA Complete
1091
;        in      al, dx
1092
;        test    al, ISR_RDC
1093
;        jz      .dmawait
1094
;        and     al, not ISR_RDC
1095
;        out     dx, al                  ; clear the bit
1096
 
1097
        ret
1098
 
1099
 
1100
 
1101
 
1102
;***************************************************************************
1103
;
1104
;   PIO_write
1105
;
1106
;   Description
1107
;       writes a frame to the ethernet card via Programmed I/O
1108
;      dst in di
1109
;      cnt in cx
1110
;       src in esi
1111
;***************************************************************************
1112
PIO_write:
1113
 
3856 hidnplayr 1114
        DEBUGF  1, "Eth PIO Write from %x to %x, %u bytes ", esi, di, cx
3545 hidnplayr 1115
 
1116
        set_io  0
1117
;        set_io  P0_COMMAND
1118
        mov     al, CMD_RD2 + CMD_STA
1119
        out     dx, al
1120
 
1121
        set_io  P0_ISR
1122
        mov     al, ISR_RDC
1123
        out     dx, al
1124
 
1125
        set_io  P0_RBCR0
1126
        mov     al, cl
1127
        out     dx, al
1128
 
1129
        set_io  P0_RBCR1
1130
        mov     al, ch
1131
        out     dx, al
1132
 
1133
        mov     ax, di
1134
        set_io  P0_RSAR0
1135
        out     dx, al
1136
        shr     ax, 8
1137
        set_io  P0_RSAR1
1138
        out     dx, al
1139
 
1140
        set_io  P0_COMMAND
1141
        mov     al, CMD_RD1 + CMD_STA
1142
        out     dx, al
1143
 
1144
        set_io  NE_ASIC
1145
        test    [device.flags], FLAG_16BIT
1146
        jz      .8_bit
1147
 
3856 hidnplayr 1148
        DEBUGF  1, "(16-bit mode)\n"
3545 hidnplayr 1149
 
1150
        shr     cx, 1   ; note that if the number was odd, carry flag will be set
1151
        pushf           ; save the flags for later
1152
 
1153
  .16bit:
1154
        lodsw
1155
        out     dx, ax
1156
        loopw   .16bit
1157
 
1158
        popf
1159
        jnc     .done
1160
        inc     cx
1161
        jmp     .8_bit_
1162
 
1163
  .8_bit:
1164
 
3856 hidnplayr 1165
        DEBUGF  1, "(8-bit mode)\n"
3545 hidnplayr 1166
 
1167
  .8_bit_:
1168
        lodsb
1169
        out     dx, al
1170
        loopw   .8_bit_
1171
 
1172
  .done:
1173
;        set_io  0
1174
;        set_io  P0_ISR
1175
;  .dmawait:                             ; Wait for Remote DMA Complete
1176
;        in      al, dx
1177
;        test    al, ISR_RDC
1178
;        jz      .dmawait
1179
;        and     al, not ISR_RDC
1180
;        out     dx, al                  ; clear the bit
1181
 
1182
        ret
1183
 
1184
 
1185
 
1186
;all initialized data place here
1187
align 4
1188
 
1189
devices         dd 0
1190
version         dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
4627 hidnplayr 1191
my_service      db 'RTL8029',0  ;max 16 chars include zero
3545 hidnplayr 1192
 
1193
;device_1        db 'Realtek 8029',0
1194
;device_2        db 'Realtek 8019',0
1195
;device_3        db 'Realtek 8019AS',0
1196
;device_4        db 'ne2000',0
1197
;device_5        db 'DP8390',0
1198
 
1199
include_debug_strings
1200
 
1201
section '.data' data readable writable align 16  ;place all uninitialized data place here
1202
 
1203
device_list     rd MAX_DEVICES
1204