Subversion Repositories Kolibri OS

Rev

Rev 4629 | Rev 5005 | 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
        mov     esi, device_list
272
        mov     ecx, [devices]
273
        test    ecx, ecx
274
        jz      .firstdevice_isa
4974 hidnplayr 275
        movzx   edi, word [eax+1]
3545 hidnplayr 276
        mov     al, [eax+3]
277
  .nextdevice_isa:
278
        mov     ebx, [esi]
279
        cmp     edi, [device.io_addr]
280
        jne     .maybenext
281
        cmp     al, [device.irq_line]
282
        je      find_device_num
283
  .maybenext:
284
        add     esi, 4
285
        loop    .nextdevice_isa
286
 
287
 
288
 
289
  .firstdevice_isa:
290
        call    create_new_struct
291
 
4470 hidnplayr 292
        mov     eax, [edx + IOCTL.input]
4974 hidnplayr 293
        movzx   ecx, word[eax+1]
3545 hidnplayr 294
        mov     [device.io_addr], ecx
295
        mov     cl, [eax+3]
296
        mov     [device.irq_line], cl
297
 
298
  .hook:
299
 
3856 hidnplayr 300
        DEBUGF  1, "Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
3545 hidnplayr 301
        [device.pci_dev]:1,[device.pci_bus]:1,[device.irq_line]:1,[device.io_addr]:4
302
 
303
        call    probe                                                   ; this function will output in eax
304
        test    eax, eax
305
        jnz     .err                                                    ; If an error occured, exit
306
 
307
        mov     eax, [devices]
308
        mov     [device_list+4*eax], ebx
309
        inc     [devices]
310
 
311
        mov     [device.type], NET_TYPE_ETH
312
        call    NetRegDev
313
 
314
        cmp     eax, -1
315
        jz      .err
316
        ret
317
 
318
 
319
; If the device was already loaded, find the device number and return it in eax
320
 
321
  .find_devicenum:
3856 hidnplayr 322
        DEBUGF  1, "Trying to find device number of already registered device\n"
3545 hidnplayr 323
        call    NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
324
                                                                        ; into a device number in edi
325
        mov     eax, edi                                                ; Application wants it in eax instead
3856 hidnplayr 326
        DEBUGF  1, "Kernel says: %u\n", eax
3545 hidnplayr 327
        ret
328
 
329
  .err:
3856 hidnplayr 330
        DEBUGF  2, "Failed, removing device structure\n"
3545 hidnplayr 331
        stdcall KernelFree, ebx
332
 
333
        jmp     .fail
334
 
335
;------------------------------------------------------
336
  @@:
337
.fail:
338
        or      eax, -1
339
        ret
340
 
341
;------------------------------------------------------
342
endp
343
 
344
 
345
create_new_struct:
346
 
347
        cmp     [devices], MAX_DEVICES
348
        jae     .fail
349
 
350
        allocate_and_clear ebx, device.size, .fail      ; Allocate the buffer for device structure
351
 
352
        mov     [device.reset], reset
353
        mov     [device.transmit], transmit
354
        mov     [device.unload], unload
355
        mov     [device.name], my_service
356
 
357
        ret
358
 
359
  .fail:
360
        add     esp, 4                                  ; return to caller of 'hook'
361
        or      eax, -1
362
        ret
363
 
364
find_device_num:
365
 
3856 hidnplayr 366
        DEBUGF  1, "Trying to find device number of already registered device\n"
3545 hidnplayr 367
        mov     ebx, eax
368
        call    NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
369
                                                                        ; into a device number in edi
370
        mov     eax, edi                                                ; Application wants it in eax instead
3856 hidnplayr 371
        DEBUGF  1, "Kernel says: %u\n", eax
3545 hidnplayr 372
        ret
373
 
374
 
375
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
376
;;                                                                        ;;
377
;;        Actual Hardware dependent code starts here                      ;;
378
;;                                                                        ;;
379
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
380
 
381
 
382
unload:   ; TODO
383
        or      eax, -1
384
        ret
385
 
386
 
387
 
388
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
389
;;
390
;;  probe: enables the device and clears the rx buffer
391
;;
392
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
393
 
394
probe:
395
        mov     [device.vendor], VENDOR_NONE
396
        mov     [device.bmem], 0
397
 
3856 hidnplayr 398
        DEBUGF  1, "Trying 16-bit mode\n"
3545 hidnplayr 399
 
400
        mov     [device.flags], FLAG_16BIT + FLAG_PIO
401
        mov     [device.memsize], MEM_32k
402
        mov     [device.tx_start], 64
403
        mov     [device.rx_start], TXBUF_SIZE + 64
404
 
405
        set_io  0
406
        set_io  P0_DCR
407
        mov     al, DCR_WTS + DCR_FT1 + DCR_LS  ; word transfer select +
408
        out     dx, al
409
 
410
        set_io  P0_PSTART
411
        mov     al, MEM_16k
412
        out     dx, al
413
 
414
        set_io  P0_PSTOP
415
        mov     al, MEM_32k
416
        out     dx, al
417
 
418
        mov     esi, my_service
419
        mov     di, 16384
420
        mov     cx, 14
421
        call    PIO_write
422
 
423
        mov     si, 16384
424
        mov     cx, 14
425
        sub     esp, 16
426
        mov     edi, esp
427
        call    PIO_read
428
 
429
        mov     esi, esp
430
        add     esp, 16
431
        mov     edi, my_service
432
        mov     ecx, 13
433
        repe    cmpsb
434
        je      ep_set_vendor
435
 
3856 hidnplayr 436
        DEBUGF  1, "16-bit mode failed\n"
437
        DEBUGF  1, "Trying 8-bit mode\n"
3545 hidnplayr 438
 
439
        mov     [device.flags], FLAG_PIO
440
        mov     [device.memsize], MEM_16k
441
        mov     [device.tx_start], 32
442
        mov     [device.rx_start], TXBUF_SIZE + 32
443
 
444
        set_io  NE_ASIC + NE_RESET
445
        in      al, dx
446
        out     dx, al
447
 
448
        in      al, 0x84
449
 
450
        set_io  P0_COMMAND
451
        mov     al, CMD_RD2 + CMD_STP
452
        out     dx, al
453
 
454
        set_io  P0_RCR
455
        mov     al, RCR_MON
456
        out     dx, al
457
 
458
        set_io  P0_DCR
459
        mov     al, DCR_FT1 + DCR_LS
460
        out     dx, al
461
 
462
        set_io  P0_PSTART
463
        mov     al, MEM_8k
464
        out     dx, al
465
 
466
        set_io  P0_PSTOP
467
        mov     al, MEM_16k
468
        out     dx, al
469
 
470
        mov     esi, my_service
471
        mov     di, 8192
472
        mov     cx, 14
473
        call    PIO_write
474
 
475
        mov     si, 8192
476
        mov     cx, 14
477
        sub     esp, 16
478
        mov     edi, esp
479
        call    PIO_read
480
 
481
        mov     esi, my_service
482
        mov     edi, esp
483
        add     esp, 16
484
        mov     ecx, 13
485
        repe    cmpsb
486
        je      ep_set_vendor
487
 
3856 hidnplayr 488
        DEBUGF  2, "This is not a valid ne2000 device!\n"
3545 hidnplayr 489
        or      eax, -1
490
        ret
491
 
492
 
493
ep_set_vendor:
494
 
3856 hidnplayr 495
        DEBUGF  1, "Mode ok\n"
3545 hidnplayr 496
 
497
        cmp     [device.io_addr], ISA_MAX_ADDR
498
        jbe     .isa
499
 
3856 hidnplayr 500
        DEBUGF  1, "Card is using PCI bus\n"
3545 hidnplayr 501
 
502
        mov     [device.vendor], VENDOR_NOVELL  ;;; FIXME
503
        jmp     ep_check_have_vendor
504
 
505
  .isa:
3856 hidnplayr 506
        DEBUGF  1, "Card is using ISA bus\n"
3545 hidnplayr 507
 
508
        mov     [device.vendor], VENDOR_NOVELL
509
 
510
ep_check_have_vendor:
511
 
512
 
513
        mov     al, [device.vendor]
514
        cmp     al, VENDOR_NONE
515
;        je      exit
516
 
517
        cmp     al, VENDOR_3COM
518
        je      reset
519
 
520
        mov     eax, [device.bmem]
521
        mov     [device.rmem], eax
522
 
523
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
524
;;
525
;;   reset: Place the chip into a virgin state
526
;;
527
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
528
 
529
reset:
3856 hidnplayr 530
        DEBUGF  1, "Resetting device\n"
3545 hidnplayr 531
 
532
; attach int handler
533
        movzx   eax, [device.irq_line]
3856 hidnplayr 534
        DEBUGF  1, "Attaching int handler to irq %x\n", eax:1
3545 hidnplayr 535
        stdcall AttachIntHandler, eax, int_handler, dword 0
3856 hidnplayr 536
        test    eax, eax
537
        jnz     @f
538
        DEBUGF  2, "Could not attach int handler!\n"
539
;        or      eax, -1
540
;        ret
541
       @@:
3545 hidnplayr 542
 
543
; Stop card + DMA
544
        set_io  0
545
;        set_io  P0_COMMAND
546
        mov     al, CMD_PS0 + CMD_RDMA_ABORT + CMD_STP
547
        out     dx, al
548
 
549
; initialize DCR
550
        set_io  P0_DCR
551
        mov     al, DCR_FT1 + DCR_LS
552
        test    [device.flags], FLAG_16BIT
553
        jz      @f
554
        or      al, DCR_WTS                     ; word transfer select
555
      @@:
556
        out     dx, al
557
 
558
; clear remote bytes count
559
        set_io  P0_RBCR0
560
        xor     al, al
561
        out     dx, al
562
 
563
        set_io  P0_RBCR1
564
        out     dx, al
565
 
566
; initialize Receive configuration register (until all init is done)
567
        set_io  P0_RCR
568
        mov     al, 0x20        ; monitor mode
569
        out     dx, al
570
 
571
; transmit configuration register to monitor mode (until all ini is done)
572
        set_io  P0_TCR
573
        mov     al, 2           ; internal loopback
574
        out     dx, al
575
 
576
; clear interupt status
577
        set_io  P0_ISR
578
        mov     al, 0xff
579
        out     dx, al
580
 
581
; clear IRQ mask                        ;;;;; CHECKME ;;;;;
582
        set_io  P0_IMR
583
        xor     al, al
584
        out     dx, al
585
 
586
; set transmit pointer
587
        set_io  P0_TPSR
588
        mov     al, [device.tx_start]
589
        out     dx, al
590
 
591
; set pagestart pointer
592
        set_io  P0_PSTART
593
        mov     al, [device.rx_start]
594
        out     dx, al
595
 
596
; set pagestop pointer
597
        set_io  P0_PSTOP
598
        mov     al, [device.memsize]
599
        out     dx, al
600
 
601
; set boundary pointer
602
        set_io  P0_BOUND
603
        mov     al, [device.memsize]
604
        dec     al
605
        out     dx, al
606
 
607
; set curr pointer
608
        set_io  P0_COMMAND
609
        mov     al, CMD_PS1 ;+ CMD_RD2 + CMD_STP ; page 1, stop mode
610
        out     dx, al
611
 
612
        set_io  P1_CURR
613
        mov     al, [device.rx_start]
614
        out     dx, al
615
 
616
        set_io  P0_COMMAND
617
        mov     al, CMD_PS0 ;+ CMD_RD2 + CMD_STA ; go to page 0, start mode
618
        out     dx, al
619
 
620
; Read MAC address and set it to registers
621
        call    read_mac
622
        push    .macret
623
        sub     esp, 6
624
        lea     esi, [device.mac]
625
        mov     edi, esp
626
        movsd
627
        movsw
628
        jmp     write_mac
629
  .macret:
630
 
631
; set IRQ mask
632
        set_io  0
633
        set_io  P0_IMR
634
        mov     al, IRQ_MASK
635
        out     dx, al
636
 
637
; start mode
638
        set_io  P0_COMMAND
639
        mov     al, CMD_STA
640
        out     dx, al
641
 
642
; clear transmit control register
643
        set_io  P0_TCR
644
        xor     al, al                  ; no loopback
645
        out     dx, al
646
 
647
; set receive control register ;;;;
648
        set_io  P0_RCR
649
        mov     al, 4                   ; accept broadcast
650
        out     dx, al
651
 
652
; clear packet/byte counters
653
        xor     eax, eax
654
        lea     edi, [device.bytes_tx]
655
        mov     ecx, 6
656
        rep     stosd
657
 
658
; Set the mtu, kernel will be able to send now
659
        mov     [device.mtu], ETH_FRAME_LEN
660
 
661
; Set link state to unknown
662
        mov     [device.state], ETH_LINK_UNKOWN
663
 
664
; Indicate that we have successfully reset the card
665
        xor     eax, eax
3856 hidnplayr 666
        DEBUGF  1, "Done!\n"
3545 hidnplayr 667
 
668
        ret
669
 
670
 
671
 
672
;***************************************************************************
673
;   Function
674
;      transmit
675
; buffer in [esp+4], size in [esp+8], pointer to device struct in ebx
676
;***************************************************************************
677
 
678
align 4
679
transmit:
680
 
681
        mov     esi, [esp + 4]
682
        mov     ecx, [esp + 8]
3856 hidnplayr 683
        DEBUGF  1, "Transmitting packet, buffer:%x, size:%u\n",esi, ecx
684
        DEBUGF  1, "To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
3545 hidnplayr 685
        [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
686
 
687
        cmp     ecx, ETH_FRAME_LEN
688
        ja      .err ; packet is too long
689
        cmp     ecx, ETH_ZLEN
690
        jb      .err ; packet is too short
691
 
692
        movzx   edi, [device.tx_start]
693
        shl     edi, 8
694
        push    cx
695
        call    PIO_write
696
        pop     cx
697
 
698
        set_io  0
699
;        set_io  P0_COMMAND
700
        mov     al, CMD_PS0 + CMD_RD2 + CMD_STA
701
        out     dx, al
702
 
703
        set_io  P0_TPSR
704
        mov     al, [device.tx_start]
705
        out     dx, al
706
 
707
        set_io  P0_TBCR0
708
        mov     al, cl
709
        out     dx, al
710
 
711
        set_io  P0_TBCR1
712
        mov     al, ch
713
        out     dx, al
714
 
715
        set_io  P0_COMMAND
716
        mov     al, CMD_PS0 + CMD_TXP + CMD_RD2 + CMD_STA
717
        out     dx, al
718
 
3856 hidnplayr 719
        DEBUGF  1, "Packet Sent!\n"
3545 hidnplayr 720
 
721
        inc     [device.packets_tx]
722
        mov     eax, [esp + 8]                   ; Get packet size in eax
723
 
724
        add     dword [device.bytes_tx], eax
725
        adc     dword [device.bytes_tx + 4], 0
726
 
727
        stdcall KernelFree, [esp+4]
728
        xor     eax, eax
729
        ret     8
730
 
3619 hidnplayr 731
  .err:
3856 hidnplayr 732
        DEBUGF  2, "Transmit error!\n"
4334 hidnplayr 733
        stdcall KernelFree, [esp+4]
3545 hidnplayr 734
        or      eax, -1
735
        ret     8
736
 
737
 
738
 
739
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
740
;
741
; Interrupt handler
742
;
743
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
744
 
745
align 4
746
int_handler:
747
 
748
        push    ebx esi edi
749
 
3856 hidnplayr 750
        DEBUGF  1, "INT\n"
3545 hidnplayr 751
 
752
; find pointer of device wich made INT occur
753
 
754
        mov     ecx, [devices]
755
        test    ecx, ecx
756
        jz      .nothing
757
        mov     esi, device_list
758
  .nextdevice:
759
        mov     ebx, [esi]
760
 
761
        set_io  0
762
;        set_io  P0_COMMAND
763
        mov     al, CMD_PS0
764
        out     dx, al
765
 
766
        set_io  P0_ISR
767
        in      al, dx
768
        test    al, al
769
        jnz     .got_it
770
  .continue:
771
        add     esi, 4
772
        dec     ecx
773
        jnz     .nextdevice
774
  .nothing:
775
        pop     edi esi ebx
776
        xor     eax, eax
777
 
778
        ret
779
 
780
  .got_it:
781
 
3856 hidnplayr 782
        DEBUGF  1, "Device=%x status=%x\n", ebx, eax:2
3545 hidnplayr 783
 
784
        push    ebx
785
 
786
        test    al, ISR_PRX     ; packet received ok ?
787
        jz      .no_rx
788
 
789
        test    [device.flags], FLAG_PIO
790
        jz      .no_rx          ; FIXME: Only PIO mode supported for now
791
 
792
;
793
 
794
        pushd   .no_rx
795
 
796
; allocate a buffer
797
 
798
        stdcall KernelAlloc, ETH_FRAME_LEN
799
        test    eax, eax
800
        jz      .fail_2
801
        pushd   0
802
        push    eax
803
 
804
; read offset for current packet from device
805
 
806
        set_io  0
807
        set_io  P0_BOUND        ; boundary ptr is offset to next packet we need to read.
808
        in      al, dx
809
        inc     al
810
 
811
        cmp     al, [device.memsize]
812
        jb      @f
813
        mov     al, [device.rx_start]
814
       @@:
815
        mov     ch, al
816
 
817
        set_io  P0_COMMAND
818
        mov     al, CMD_PS1
819
        out     dx, al
820
 
821
        set_io  P1_CURR
822
        in      al, dx          ; get current page in cl
823
        mov     cl, al
824
 
825
        set_io  P1_COMMAND
826
        mov     al, CMD_PS0
827
        out     dx, al
828
 
829
        cmp     cl, [device.memsize]
830
        jb      @f
831
        mov     cl, [device.rx_start]
832
       @@:
833
 
834
        cmp     cl, ch
835
        je      .fail
836
 
837
        movzx   esi, ch                         ; we are using 256 byte pages
838
        shl     esi, 8                          ; esi now holds the offset for current packet
839
 
840
; Get packet header in eax
841
 
842
        sub     esp, 4                          ; reserve 4 bytes on stack to put packet header in
843
        mov     edi, esp
844
        mov     cx, 4
845
        call    PIO_read
846
 
847
        mov     ecx, [esp]                      ; ecx now contains packet header
848
 
849
; check if packet is ok
850
 
851
        test    ecx, RSTAT_PRX
852
        jz      .fail_3
853
 
854
; calculate packet length in ecx
855
 
856
        shr     ecx, 16
857
        sub     ecx, 4                          ; CRC doesnt count as data byte
858
        mov     [esp + 4 + 4], ecx
859
 
860
; check if packet size is ok
861
 
862
        cmp     ecx, ETH_ZLEN
863
        jb      .fail_3
864
        cmp     ecx, ETH_FRAME_LEN
865
        ja      .fail_3
866
 
867
; update stats
868
 
3856 hidnplayr 869
        DEBUGF  1, "Received %u bytes\n", ecx
3545 hidnplayr 870
 
871
        add     dword[device.bytes_rx], ecx
872
        adc     dword[device.bytes_rx + 4], 0
873
        inc     [device.packets_rx]
874
 
875
; update read and write pointers
876
 
877
        add     esi, 4
878
        mov     edi, [esp + 4]
879
 
880
; now check if we can read all data at once (if we cross the end boundary, we need to wrap back to the beginning)
881
 
882
        xor     eax, eax
883
        mov     ah, [device.memsize]
884
        sub     eax, esi
885
        cmp     ecx, eax                ; eax = number of bytes till end of buffer, ecx = bytes we need to read
886
        jbe     .no_wrap
887
 
888
; Read first part
889
 
890
        sub     ecx, eax
891
        push    ecx
892
        mov     ecx, eax
893
 
894
        call    PIO_read                ; Read the data
895
 
896
; update pointers
897
 
898
        add     edi, ecx
899
        pop     ecx
900
 
901
        movzx   esi, [device.rx_start]
902
        shl     esi, 8
903
 
904
; now read second part (or only part)
905
 
906
  .no_wrap:
907
        call    PIO_read                ; Read the data
908
 
909
; update boundary pointer
910
 
911
        pop     eax
912
        mov     al, ah
913
        cmp     al, [device.rx_start]
914
        jne     @f
915
        mov     al, [device.memsize]
916
       @@:
917
 
918
        set_io  0
919
        set_io  P0_BOUND
920
        dec     al
921
        out     dx, al
922
 
923
; now send the data to the kernel
924
 
925
        jmp     Eth_input
926
 
927
  .fail_3:
928
        add     esp, 4
929
  .fail:
930
        add     esp, 8
931
  .fail_2:
932
 
933
 
934
  .no_rx:
935
        pop     ebx
3856 hidnplayr 936
        DEBUGF  1, "done\n"
3545 hidnplayr 937
 
938
        set_io  0
939
        set_io  P0_ISR
940
        mov     al, 0xff
941
        out     dx, al
942
 
943
        pop     edi esi ebx
944
 
945
        ret
946
 
947
 
948
 
949
 
950
 
951
;;;;;;;;;;;;;;;;;;;;;;;
952
;;                   ;;
953
;; Write MAC address ;;
954
;;                   ;;
955
;;;;;;;;;;;;;;;;;;;;;;;
956
 
957
align 4
958
write_mac:      ; in: mac on stack (6 bytes)
959
 
3856 hidnplayr 960
        DEBUGF  1, "Writing MAC\n"
3545 hidnplayr 961
 
962
        set_io  0
963
        mov     al, CMD_PS1; + CMD_RD2 + CMD_STP
964
        out     dx, al
965
 
966
        set_io  P1_PAR0
967
        mov     esi, esp
968
        mov     cx, 6
969
 @@:
970
        lodsb
971
        out     dx, al
972
        inc     dx
973
        loopw   @r
974
 
975
        add     esp, 6
976
 
977
; Notice this procedure does not ret, but continues to read_mac instead.
978
 
979
;;;;;;;;;;;;;;;;;;;;;;
980
;;                  ;;
981
;; Read MAC address ;;
982
;;                  ;;
983
;;;;;;;;;;;;;;;;;;;;;;
984
 
985
read_mac:
986
 
3856 hidnplayr 987
        DEBUGF  1, "Reading MAC\n"
3545 hidnplayr 988
 
989
        xor     esi, esi
990
        mov     cx, 16
991
        sub     esp, 16
992
        mov     edi, esp
993
        call    PIO_read
994
 
995
        mov     esi, esp
996
        add     esp, 16
997
        lea     edi, [device.mac]
998
        mov     ecx, 6
999
  .loop:
1000
        movsb
1001
        test    [device.flags], FLAG_16BIT
1002
        jz      .8bit
1003
        inc     esi
1004
  .8bit:
1005
        loop    .loop
1006
 
3856 hidnplayr 1007
        DEBUGF  1, "MAC=%x-%x-%x-%x-%x-%x\n",\
3545 hidnplayr 1008
        [device.mac]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2
1009
 
1010
        ret
1011
 
1012
 
1013
;***************************************************************************
1014
;
1015
;   PIO_read
1016
;
1017
;   Description
1018
;       Read a frame from the ethernet card via Programmed I/O
1019
;      src in si
1020
;      cnt in cx
1021
;       dst in edi
1022
;***************************************************************************
1023
PIO_read:
1024
 
3856 hidnplayr 1025
        DEBUGF  1, "PIO Read from %x to %x, %u bytes ", si, edi, cx
3545 hidnplayr 1026
 
1027
; start DMA
1028
        set_io  0
1029
;        set_io  P0_COMMAND
1030
        mov     al, CMD_RD2 + CMD_STA
1031
        out     dx, al
1032
 
1033
; set length of data we're interested in
1034
        set_io  P0_RBCR0
1035
        mov     al, cl
1036
        out     dx, al
1037
 
1038
        set_io  P0_RBCR1
1039
        mov     al, ch
1040
        out     dx, al
1041
 
1042
; set offset of what we want to read
1043
        set_io  P0_RSAR0
1044
        mov     ax, si
1045
        out     dx, al
1046
 
1047
        set_io  P0_RSAR1
1048
        shr     ax, 8
1049
        out     dx, al
1050
 
1051
; start DMA read
1052
        set_io  P0_COMMAND
1053
        mov     al, CMD_RD0 + CMD_STA
1054
        out     dx, al
1055
 
1056
        set_io  NE_ASIC
1057
 
1058
        test    [device.flags], FLAG_16BIT
1059
        jz      .8bits
1060
 
3856 hidnplayr 1061
        DEBUGF  1, "(16-bit mode)\n"
3545 hidnplayr 1062
 
1063
        shr     cx, 1   ; note that if the number was odd, carry flag will be set
1064
        pushf
1065
 
1066
  .16bits:
1067
        in      ax, dx
1068
        stosw
1069
        loopw   .16bits
1070
 
1071
        inc     cx
1072
        popf
1073
        jnc     .done
1074
        jmp     .8bits_
1075
 
1076
  .8bits:
3856 hidnplayr 1077
        DEBUGF  1, "(8-bit mode)\n"
3545 hidnplayr 1078
 
1079
  .8bits_:
1080
        in      al, dx
1081
        stosb
1082
        loopw   .8bits_
1083
 
1084
 
1085
  .done:
1086
;        set_io  0
1087
;        set_io  P0_ISR
1088
;
1089
;  .dmawait:                             ; Wait for Remote DMA Complete
1090
;        in      al, dx
1091
;        test    al, ISR_RDC
1092
;        jz      .dmawait
1093
;        and     al, not ISR_RDC
1094
;        out     dx, al                  ; clear the bit
1095
 
1096
        ret
1097
 
1098
 
1099
 
1100
 
1101
;***************************************************************************
1102
;
1103
;   PIO_write
1104
;
1105
;   Description
1106
;       writes a frame to the ethernet card via Programmed I/O
1107
;      dst in di
1108
;      cnt in cx
1109
;       src in esi
1110
;***************************************************************************
1111
PIO_write:
1112
 
3856 hidnplayr 1113
        DEBUGF  1, "Eth PIO Write from %x to %x, %u bytes ", esi, di, cx
3545 hidnplayr 1114
 
1115
        set_io  0
1116
;        set_io  P0_COMMAND
1117
        mov     al, CMD_RD2 + CMD_STA
1118
        out     dx, al
1119
 
1120
        set_io  P0_ISR
1121
        mov     al, ISR_RDC
1122
        out     dx, al
1123
 
1124
        set_io  P0_RBCR0
1125
        mov     al, cl
1126
        out     dx, al
1127
 
1128
        set_io  P0_RBCR1
1129
        mov     al, ch
1130
        out     dx, al
1131
 
1132
        mov     ax, di
1133
        set_io  P0_RSAR0
1134
        out     dx, al
1135
        shr     ax, 8
1136
        set_io  P0_RSAR1
1137
        out     dx, al
1138
 
1139
        set_io  P0_COMMAND
1140
        mov     al, CMD_RD1 + CMD_STA
1141
        out     dx, al
1142
 
1143
        set_io  NE_ASIC
1144
        test    [device.flags], FLAG_16BIT
1145
        jz      .8_bit
1146
 
3856 hidnplayr 1147
        DEBUGF  1, "(16-bit mode)\n"
3545 hidnplayr 1148
 
1149
        shr     cx, 1   ; note that if the number was odd, carry flag will be set
1150
        pushf           ; save the flags for later
1151
 
1152
  .16bit:
1153
        lodsw
1154
        out     dx, ax
1155
        loopw   .16bit
1156
 
1157
        popf
1158
        jnc     .done
1159
        inc     cx
1160
        jmp     .8_bit_
1161
 
1162
  .8_bit:
1163
 
3856 hidnplayr 1164
        DEBUGF  1, "(8-bit mode)\n"
3545 hidnplayr 1165
 
1166
  .8_bit_:
1167
        lodsb
1168
        out     dx, al
1169
        loopw   .8_bit_
1170
 
1171
  .done:
1172
;        set_io  0
1173
;        set_io  P0_ISR
1174
;  .dmawait:                             ; Wait for Remote DMA Complete
1175
;        in      al, dx
1176
;        test    al, ISR_RDC
1177
;        jz      .dmawait
1178
;        and     al, not ISR_RDC
1179
;        out     dx, al                  ; clear the bit
1180
 
1181
        ret
1182
 
1183
 
1184
 
4629 hidnplayr 1185
; place all initialized data here
3545 hidnplayr 1186
align 4
1187
 
1188
devices         dd 0
1189
version         dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
4629 hidnplayr 1190
my_service      db 'RTL8029',0          ; max 16 chars include zero
3545 hidnplayr 1191
 
1192
;device_1        db 'Realtek 8029',0
1193
;device_2        db 'Realtek 8019',0
1194
;device_3        db 'Realtek 8019AS',0
1195
;device_4        db 'ne2000',0
1196
;device_5        db 'DP8390',0
1197
 
1198
include_debug_strings
1199
 
4629 hidnplayr 1200
section '.data' data readable writable align 16
1201
; place all uninitialized data here
3545 hidnplayr 1202
 
1203
device_list     rd MAX_DEVICES
1204