Subversion Repositories Kolibri OS

Rev

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