Subversion Repositories Kolibri OS

Rev

Rev 4467 | Rev 5006 | 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
;;  Ethernet driver for KolibriOS                                     ;;
7
;;  This is an adaptation of MenuetOS driver with minimal changes.    ;;
8
;;  Changes were made by CleverMouse. Original copyright follows.     ;;
9
;;                                                                    ;;
10
;;  This driver is based on the SIS900 driver from                    ;;
11
;;  the etherboot 5.0.6 project. The copyright statement is           ;;
12
;;                                                                    ;;
13
;;          GNU GENERAL PUBLIC LICENSE                                ;;
14
;;             Version 2, June 1991                                   ;;
15
;;                                                                    ;;
16
;;  remaining parts Copyright 2004 Jason Delozier,                    ;;
17
;;   cordata51@hotmail.com                                            ;;
18
;;                                                                    ;;
19
;;  See file COPYING for details                                      ;;
20
;;                                                                    ;;
21
;;  Updates:                                                          ;;
22
;;    Revision Look up table and SIS635 Mac Address by Jarek Pelczar  ;;
23
;;                                                                    ;;
24
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
25
 
26
format MS COFF
27
 
28
        NUM_RX_DESC             = 4             ; Number of RX descriptors
29
        NUM_TX_DESC             = 4             ; Number of TX descriptors
30
        RX_BUFF_SZ              = 1520          ; Buffer size for each Rx buffer
31
        TX_BUFF_SZ              = 1516          ; Buffer size for each Tx buffer
32
        MAX_ETH_FRAME_SIZE      = 1516
33
 
34
        API_VERSION             = 0x01000100
35
        DRIVER_VERSION          = 5
36
 
37
        MAX_DEVICES             = 16
38
 
39
        DEBUG                   = 1
40
        __DEBUG__               = 1
41
        __DEBUG_LEVEL__         = 2
42
 
43
        DSIZE                   = 0x00000fff
44
        CRC_SIZE                = 4
45
        RFADDR_shift            = 16
46
 
47
; If you are having problems sending/receiving packet try changing the
48
; Max DMA Burst, Possible settings are as follows:
49
;
50
; 0x00000000 = 512 bytes
51
; 0x00100000 = 4 bytes
52
; 0x00200000 = 8 bytes
53
; 0x00300000 = 16 bytes
54
; 0x00400000 = 32 bytes
55
; 0x00500000 = 64 bytes
56
; 0x00600000 = 128 bytes
57
; 0x00700000 = 256 bytes
58
 
59
        RX_DMA                  = 0x00600000
60
        TX_DMA                  = 0x00600000
61
 
62
;-------------------------------------------------------------------------------------------------
63
; Symbolic offsets to registers.
64
        cr              = 0x0           ; Command Register
65
        cfg             = 0x4           ; Configuration Register
66
        mear            = 0x8           ; EEPROM Access Register
67
        ptscr           = 0xc           ; PCI Test Control Register
68
        isr             = 0x10          ; Interrupt Status Register
69
        imr             = 0x14          ; Interrupt Mask Register
70
        ier             = 0x18          ; Interrupt Enable Register
71
        epar            = 0x18          ; Enhanced PHY Access Register
72
        txdp            = 0x20          ; Transmit Descriptor Pointer Register
73
        txcfg           = 0x24          ; Transmit Configuration Register
74
        rxdp            = 0x30          ; Receive Descriptor Pointer Register
75
        rxcfg           = 0x34          ; Receive Configuration Register
76
        flctrl          = 0x38          ; Flow Control Register
77
        rxlen           = 0x3c          ; Receive Packet Length Register
78
        rfcr            = 0x48          ; Receive Filter Control Register
79
        rfdr            = 0x4C          ; Receive Filter Data Register
80
        pmctrl          = 0xB0          ; Power Management Control Register
81
        pmer            = 0xB4          ; Power Management Wake-up Event Register
82
 
83
; Command Register Bits
84
        RELOAD          = 0x00000400
85
        ACCESSMODE      = 0x00000200
86
        RESET           = 0x00000100
87
        SWI             = 0x00000080
88
        RxRESET         = 0x00000020
89
        TxRESET         = 0x00000010
90
        RxDIS           = 0x00000008
91
        RxENA           = 0x00000004
92
        TxDIS           = 0x00000002
93
        TxENA           = 0x00000001
94
 
95
; Configuration Register Bits
96
        DESCRFMT        = 0x00000100    ; 7016 specific
97
        REQALG          = 0x00000080
98
        SB              = 0x00000040
99
        POW             = 0x00000020
100
        EXD             = 0x00000010
101
        PESEL           = 0x00000008
102
        LPM             = 0x00000004
103
        BEM             = 0x00000001
104
        RND_CNT         = 0x00000400
105
        FAIR_BACKOFF    = 0x00000200
106
        EDB_MASTER_EN   = 0x00002000
107
 
108
; Eeprom Access Reigster Bits
109
        MDC             = 0x00000040
110
        MDDIR           = 0x00000020
111
        MDIO            = 0x00000010    ; 7016 specific
112
        EECS            = 0x00000008
113
        EECLK           = 0x00000004
114
        EEDO            = 0x00000002
115
        EEDI            = 0x00000001
116
 
117
; TX Configuration Register Bits
118
        ATP             = 0x10000000    ; Automatic Transmit Padding
119
        MLB             = 0x20000000    ; Mac Loopback Enable
120
        HBI             = 0x40000000    ; HeartBeat Ignore (Req for full-dup)
121
        CSI             = 0x80000000    ; CarrierSenseIgnore (Req for full-du
122
 
123
; RX Configuration Register Bits
124
        AJAB            = 0x08000000    ;
125
        ATX             = 0x10000000    ; Accept Transmit Packets
126
        ARP             = 0x40000000    ; accept runt packets (<64bytes)
127
        AEP             = 0x80000000    ; accept error packets
128
 
129
; Interrupt Register Bits
130
        WKEVT           = 0x10000000
131
        TxPAUSEEND      = 0x08000000
132
        TxPAUSE         = 0x04000000
133
        TxRCMP          = 0x02000000    ; Transmit Reset Complete
134
        RxRCMP          = 0x01000000    ; Receive Reset Complete
135
        DPERR           = 0x00800000
136
        SSERR           = 0x00400000
137
        RMABT           = 0x00200000
138
        RTABT           = 0x00100000
139
        RxSOVR          = 0x00010000
140
        HIBERR          = 0x00008000
141
        SWINT           = 0x00001000
142
        MIBINT          = 0x00000800
143
        TxURN           = 0x00000400
144
        TxIDLE          = 0x00000200
145
        TxERR           = 0x00000100
146
        TxDESC          = 0x00000080
147
        TxOK            = 0x00000040
148
        RxORN           = 0x00000020
149
        RxIDLE          = 0x00000010
150
        RxEARLY         = 0x00000008
151
        RxERR           = 0x00000004
152
        RxDESC          = 0x00000002
153
        RxOK            = 0x00000001
154
 
155
; Interrupt Enable Register Bits
156
        IE              = RxOK + TxOK
157
 
158
; Revision ID
159
        SIS900B_900_REV         = 0x03
160
        SIS630A_900_REV         = 0x80
161
        SIS630E_900_REV         = 0x81
162
        SIS630S_900_REV         = 0x82
163
        SIS630EA1_900_REV       = 0x83
164
        SIS630ET_900_REV        = 0x84
165
        SIS635A_900_REV         = 0x90
166
        SIS900_960_REV          = 0x91
167
 
168
; Receive Filter Control Register Bits
169
        RFEN            = 0x80000000            ; enable
170
        RFAAB           = 0x40000000            ; accept all broadcasts
171
        RFAAM           = 0x20000000            ; accept all multicasts
172
        RFAAP           = 0x10000000            ; accept all packets
173
 
174
; Reveive Filter Data Mask
175
        RFDAT           = 0x0000FFFF
176
 
177
; Eeprom Address
178
        EEPROMSignature = 0x00
179
        EEPROMVendorID  = 0x02
180
        EEPROMDeviceID  = 0x03
181
        EEPROMMACAddr   = 0x08
182
        EEPROMChecksum  = 0x0b
183
 
184
; The EEPROM commands include the alway-set leading bit.
185
        EEread          = 0x0180
186
        EEwrite         = 0x0140
187
        EEerase         = 0x01C0
188
        EEwriteEnable   = 0x0130
189
        EEwriteDisable  = 0x0100
190
        EEeraseAll      = 0x0120
191
        EEwriteAll      = 0x0110
192
        EEaddrMask      = 0x013F
193
        EEcmdShift      = 16
194
 
195
; For SiS962 or SiS963, request the eeprom software access
196
        EEREQ           = 0x00000400
197
        EEDONE          = 0x00000200
198
        EEGNT           = 0x00000100
199
 
4467 hidnplayr 200
include '../struct.inc'
201
include '../macros.inc'
3545 hidnplayr 202
include '../proc32.inc'
203
include '../imports.inc'
204
include '../fdo.inc'
205
include '../netdrv.inc'
206
 
207
public START
208
public version
209
 
210
 
211
virtual at ebx
212
        device:
213
 
214
        ETH_DEVICE
215
 
216
        .io_addr        dd ?
217
        .pci_bus        dd ?
218
        .pci_dev        dd ?
219
        .irq_line       db ?
220
        .cur_rx         db ?
221
        .cur_tx         db ?
222
        .last_tx        db ?
223
        .pci_revision   db ?
224
        .table_entries  db ?
225
        rb 2    ; alignment
226
 
227
        .txd            rd (4 * NUM_TX_DESC)
228
        .rxd            rd (4 * NUM_RX_DESC)
229
 
230
        .size = $ - device
231
 
232
end virtual
233
 
234
macro   ee_delay {
235
        push    eax
236
        in      eax, dx
237
        in      eax, dx
238
        in      eax, dx
239
        in      eax, dx
240
        in      eax, dx
241
        in      eax, dx
242
        in      eax, dx
243
        in      eax, dx
244
        in      eax, dx
245
        in      eax, dx
246
        pop     eax
247
}
248
 
249
 
250
section '.flat' code readable align 16
251
 
252
; Driver entry point - register our service when the driver is loading.
253
; TODO: add needed operations when unloading
254
START:
255
        cmp     dword [esp+4], 1
256
        jne     .exit
257
        stdcall RegService, my_service, service_proc
258
        ret     4
259
  .exit:
260
        xor     eax, eax
261
        ret     4
262
 
263
; Service procedure for the driver - handle all I/O requests for the driver.
264
; Currently handled requests are: SRV_GETVERSION = 0 and SRV_HOOK = 1.
265
service_proc:
266
; 1. Get parameter from the stack: [esp+4] is the first parameter,
267
;       pointer to IOCTL structure.
268
        mov     edx, [esp+4]    ; edx -> IOCTL
269
; 2. Get request code and select a handler for the code.
4470 hidnplayr 270
        mov     eax, [edx + IOCTL.io_code]
3545 hidnplayr 271
        test    eax, eax        ; check for SRV_GETVERSION
272
        jnz     @f
273
; 3. This is SRV_GETVERSION request, no input, 4 bytes output, API_VERSION.
274
; 3a. Output size must be at least 4 bytes.
4470 hidnplayr 275
        cmp     [edx + IOCTL.out_size], 4
3545 hidnplayr 276
        jb      .fail
277
; 3b. Write result to the output buffer.
4470 hidnplayr 278
        mov     eax, [edx + IOCTL.output]
3545 hidnplayr 279
        mov     [eax], dword API_VERSION
280
; 3c. Return success.
281
        xor     eax, eax
282
        ret     4
283
  @@:
284
        dec     eax     ; check for SRV_HOOK
285
        jnz     .fail
286
; 4. This is SRV_HOOK request, input defines the device to hook, no output.
287
; 4a. The driver works only with PCI devices,
288
;       so input must be at least 3 bytes long.
4470 hidnplayr 289
        cmp     [edx + IOCTL.inp_size], 3
3545 hidnplayr 290
        jb      .fail
291
; 4b. First byte of input is bus type, 1 stands for PCI.
4470 hidnplayr 292
        mov     eax, [edx + IOCTL.input]
3545 hidnplayr 293
        cmp     byte [eax], 1
294
        jne     .fail
295
; 4c. Second and third bytes of the input define the device: bus and dev.
296
;       Word in bx holds both bytes.
297
        mov     bx, [eax+1]
298
; 4d. Check if the device was already hooked,
299
;       scan through the list of known devices.
300
; check if the device is already listed
301
        mov     esi, device_list
302
        mov     ecx, [devices]
303
        test    ecx, ecx
304
        jz      .firstdevice
305
 
4470 hidnplayr 306
;        mov     eax, [edx + IOCTL.input]               ; get the pci bus and device numbers
3545 hidnplayr 307
        mov     ax, [eax+1]                            ;
308
  .nextdevice:
309
        mov     ebx, [esi]
310
        cmp     al, byte[device.pci_bus]
311
        jne     @f
312
        cmp     ah, byte[device.pci_dev]
313
        je      .find_devicenum                         ; Device is already loaded, let's find it's device number
314
       @@:
315
        add     esi, 4
316
        loop    .nextdevice
317
; 4e. This device doesn't have its own eth_device structure yet, let's create one
318
  .firstdevice:
319
; 4f. Check that we have place for new device.
320
        cmp     [devices], MAX_DEVICES
321
        jae     .fail
322
; 4g. Allocate memory for device descriptor and receive+transmit buffers.
323
; 4h. Zero the structure.
324
        allocate_and_clear ebx, device.size, .fail
325
; 4i. Save PCI coordinates
4470 hidnplayr 326
        mov     eax, [edx + IOCTL.input]
3545 hidnplayr 327
        movzx   ecx, byte[eax+1]
328
        mov     [device.pci_bus], ecx
329
        movzx   ecx, byte[eax+2]
330
        mov     [device.pci_dev], ecx
331
; 4j. Fill in the direct call addresses into the struct.
332
        mov     [device.reset], reset
333
        mov     [device.transmit], transmit
334
        mov     [device.unload], unload
335
        mov     [device.name], my_service
336
 
337
; 4k. Now, it's time to find the base io addres of the PCI device
338
; TODO: implement check if bus and dev exist on this machine
339
 
340
; Now, it's time to find the base io addres of the PCI device
341
        PCI_find_io
342
 
343
; We've found the io address, find IRQ now
344
        PCI_find_irq
345
 
346
; 4m. Add new device to the list (required for int_handler).
347
        mov     eax, [devices]
348
        mov     [device_list+4*eax], ebx
349
        inc     [devices]
350
 
351
; 4m. Ok, the eth_device structure is ready, let's probe the device
352
        call    probe
353
        test    eax, eax
354
        jnz     .destroy
355
; 4n. If device was successfully initialized, register it for the kernel.
356
 
357
        mov     [device.type], NET_TYPE_ETH
358
        call    NetRegDev
359
 
360
        cmp     eax, -1
361
        je      .destroy
362
 
363
        ret     4
364
 
365
; 5. If the device was already loaded, find the device number and return it in eax
366
 
367
  .find_devicenum:
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
371
        ret     4
372
 
373
; If an error occured, remove all allocated data and exit (returning -1 in eax)
374
 
375
  .destroy:
376
        dec     [devices]
377
        ; todo: reset device into virgin state
378
 
379
  .err:
380
        stdcall KernelFree, ebx
381
 
382
  .fail:
383
        xor     eax, eax
384
        ret     4
385
 
386
 
387
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
388
;;                                                                        ;;
389
;;        Actual Hardware dependent code starts here                      ;;
390
;;                                                                        ;;
391
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
392
 
393
unload:
394
        ; TODO: (in this particular order)
395
        ;
396
        ; - Stop the device
397
        ; - Detach int handler
398
        ; - Remove device from local list
399
        ; - call unregister function in kernel
400
        ; - Remove all allocated structures and buffers the card used
401
 
402
        or      eax,-1
403
 
404
ret
405
 
406
;***************************************************************************
407
;
408
; probe
409
;
410
; checks the card and enables it
411
;
412
; TODO: probe mii transceivers
413
;
414
;***************************************************************************
415
align 4
416
probe:
417
        DEBUGF  1, "Probe\n"
418
 
419
; wake up device   CHECKME
420
        stdcall PciWrite8, [device.pci_bus], [device.pci_dev], 0x40, 0
421
 
422
        PCI_make_bus_master
423
 
424
        PCI_adjust_latency 64
425
 
426
; Get Card Revision
427
        stdcall PciRead8, [device.pci_bus], [device.pci_dev], 0x08
428
        mov     [device.pci_revision], al       ; save the revision for later use
429
 
430
; Look up through the specific_table
431
        mov     esi, specific_table
432
  .tableloop:
433
        cmp     dword [esi], 0                  ; Check if we reached end of the list
434
        je      .notsupported
435
        cmp     al, [esi]                       ; Check if revision is OK
436
        je      .ok
437
        add     esi, 12                         ; Advance to next entry
438
        jmp     .tableloop
439
 
440
  .ok:
441
 
442
        call     dword[esi + 4]                 ; "get MAC" function
443
 
444
; Set table entries
445
        mov      [device.table_entries], 16
446
        cmp      [device.pci_revision], SIS635A_900_REV
447
        jae      @f
448
        cmp      [device.pci_revision], SIS900B_900_REV
449
        je       @f
450
        mov      [device.table_entries], 8
451
       @@:
452
 
453
; TODO: Probe for mii transceiver
454
 
455
        jmp     reset
456
 
457
  .notsupported:
458
        DEBUGF  1, "Device not supported\n"
459
        or      eax, -1
460
 
461
        ret
462
 
463
reset:
464
 
465
        DEBUGF  1, "reset\n"
466
 
467
        movzx   eax, [device.irq_line]
468
        stdcall AttachIntHandler, eax, int_handler, 0
469
 
470
;--------------------------------------------
471
; Disable Interrupts and reset Receive Filter
472
 
473
        set_io  0
474
        set_io  ier
475
        xor     eax, eax
476
        out     dx, eax
477
 
478
        set_io  imr
479
        out     dx, eax
480
 
481
        set_io  rfcr
482
        out     dx, eax
483
 
484
;-----------
485
; Reset Card
486
 
487
        set_io  cr
488
        in      eax, dx                         ; Get current Command Register
489
        or      eax, RESET + RxRESET + TxRESET  ; set flags
490
        out     dx, eax                         ; Write new Command Register
491
 
492
;----------
493
; Wait loop
494
 
495
        set_io  isr
496
        mov     ecx, 1000
497
  .loop:
498
        dec     ecx
499
        jz      .fail
500
        in      eax, dx                         ; read interrupt status
501
        test    eax, TxRCMP + RxRCMP
502
        jz      .loop
503
        DEBUGF  1, "status=%x\n", eax
504
 
505
;------------------------------------------------------
506
; Set Configuration Register depending on Card Revision
507
 
508
        set_io  cfg
509
        mov     eax, PESEL                      ; Configuration Register Bit
510
        cmp     [device.pci_revision], SIS635A_900_REV
511
        je      .match
512
        cmp     [device.pci_revision], SIS900B_900_REV ; Check card revision
513
        jne     .done
514
  .match:                                       ; Revision match
515
        or      eax, RND_CNT                    ; Configuration Register Bit
516
  .done:
517
        out     dx, eax
518
 
519
        DEBUGF  1, "Initialising RX Filter\n"
520
 
521
; Get Receive Filter Control Register
522
        set_io  rfcr
523
        in      eax, dx
524
        push    eax
525
 
526
; disable packet filtering before setting filter
527
        and     eax, not RFEN
528
        out     dx, eax
529
 
530
; load MAC addr to filter data register
531
        xor     ecx, ecx
532
  .macloop:
533
        mov     eax, ecx
534
        set_io  0
535
        set_io  rfcr
536
        shl     eax, 16                                             ; high word of eax tells card which mac byte to write
537
        out     dx, eax                                             ;
538
        set_io  rfdr
539
        mov     ax, word [device.mac + ecx*2]                       ; Get Mac ID word
540
        out     dx, ax                                              ; Send Mac ID
541
        inc     cl                                                  ; send next word
542
        cmp     cl, 3                                               ; more to send?
543
        jne     .macloop
544
 
545
; enable packet filtering
546
        pop     eax                     ; old register value
547
        set_io  rfcr
548
        or      eax, RFEN               ; enable filtering
549
        out     dx, eax                 ; set register
550
 
551
        DEBUGF  1, "Initialising TX Descriptors\n"
552
 
553
        mov     ecx, NUM_TX_DESC
554
        lea     esi, [device.txd]
555
  .txdescloop:
556
        lea     eax, [esi + 16]                 ; next ptr
557
        GetRealAddr
558
        mov     dword [esi], eax                ; link to next desc
559
        mov     dword [esi + 4], 0              ; status field
560
        mov     dword [esi + 8], 0              ; ptr to buffer
561
        add     esi, 16
562
        dec     ecx
563
        jnz     .txdescloop
564
 
565
        lea     eax, [device.txd]
566
        GetRealAddr
567
        mov     dword [esi - 16], eax           ; correct last descriptor link ptr
568
 
569
        set_io  txdp                            ; TX Descriptor Pointer
570
;        lea     eax, [device.txd]
571
;        GetRealAddr
572
        out     dx, eax
573
 
574
        mov     [device.cur_tx], 0              ; Set current tx descriptor to 0
575
        mov     [device.last_tx], 0
576
 
577
        DEBUGF  1, "Initialising RX Descriptors\n"
578
 
579
        mov     ecx, NUM_RX_DESC
580
        lea     esi, [device.rxd]
581
  .rxdescloop:
582
        lea     eax, [esi + 16]                 ; next ptr
583
        GetRealAddr
584
        mov     dword [esi], eax
585
        mov     dword [esi + 4], RX_BUFF_SZ     ; size
586
 
587
        push    ecx esi
588
        stdcall KernelAlloc, RX_BUFF_SZ
589
        pop     esi ecx
590
        test    eax, eax
591
        jz      .fail
592
        mov     dword [esi + 12], eax           ; address
593
        GetRealAddr
594
        mov     dword [esi + 8], eax            ; real address
595
        add     esi, 16
596
        dec     ecx
597
        jnz     .rxdescloop
598
 
599
        lea     eax, [device.rxd]
600
        GetRealAddr
601
        mov     dword [esi - 16], eax           ; correct last descriptor link ptr
602
 
603
        set_io  0
604
        set_io  rxdp
605
;        lea     eax, [device.rxd]
606
;        GetRealAddr
607
        out     dx, eax
608
 
609
        mov     [device.cur_rx], 0              ; Set current rx descriptor to 0
610
 
611
        DEBUGF  1, "setting RX mode\n"
612
 
613
        xor     cl, cl
614
  .rxfilterloop:
615
        set_io  0
616
        set_io  rfcr                    ; Receive Filter Control Reg offset
617
        mov     eax, 4                  ; determine table entry
618
        add     al, cl
619
        shl     eax, 16
620
        out     dx, eax                 ; tell card which entry to modify
621
 
622
        set_io  rfdr                    ; Receive Filter Control Reg offset
623
        mov     eax, 0xffff             ; entry value
624
        out     dx, ax                  ; write value to table in card
625
 
626
        inc     cl                      ; next entry
627
        cmp     cl, [device.table_entries]
628
        jb      .rxfilterloop
629
 
630
        set_io  rfcr                    ; Receive Filter Control Register offset
631
        mov     eax, RFAAB + RFAAM + RFAAP + RFEN
632
        out     dx, eax
633
 
634
        set_io  rxcfg                   ; Receive Config Register offset
635
        mov     eax, ATX + RX_DMA + 2   ; 0x2 : RX Drain Threshold = 8*8=64 bytes
636
        out     dx, eax
637
 
638
        DEBUGF  1, "setting TX mode\n"
639
 
640
        set_io  txcfg                   ; Transmit config Register offset
641
        mov     eax, ATP + HBI + CSI + TX_DMA + 0x120
642
                                        ; TX Fill threshold = 0x100
643
                                        ; TX Drain Threshold = 0x20
644
        out     dx, eax
645
 
646
        DEBUGF  1, "Enabling interrupts\n"
647
 
648
        set_io  imr
649
        mov     eax, IE                 ; Interrupt enable mask
650
        out     dx, eax
651
 
652
        set_io  cr
653
        in      eax, dx
654
        or      eax, RxENA              ; Enable Receive
655
        out     dx, eax
656
 
657
        set_io  ier                     ; Interrupt enable
658
        mov     eax, 1
659
        out     dx, eax
660
 
661
        mov     [device.mtu], 1514
662
 
663
; Set link state to unknown
664
        mov     [device.state], ETH_LINK_UNKOWN
665
 
666
        xor     eax, eax
667
        ret
668
 
669
  .fail:
670
        DEBUGF  1, "Resetting device failed\n"
671
        or      eax, -1
672
 
673
        ret
674
 
675
 
676
;***************************************************************************
677
;
678
; SIS960_get_mac_addr: - Get MAC address for SiS962 or SiS963 model
679
;
680
; SiS962 or SiS963 model, use EEPROM to store MAC address.
681
; EEPROM is shared by LAN and 1394.
682
; When access EEPROM, send EEREQ signal to hardware first, and wait for EEGNT.
683
; If EEGNT is ON, EEPROM is permitted to be accessed by LAN, otherwise is not.
684
; After MAC address is read from EEPROM, send
685
; EEDONE signal to refuse EEPROM access by LAN.
686
; The EEPROM map of SiS962 or SiS963 is different to SiS900.
687
; The signature field in SiS962 or SiS963 spec is meaningless.
688
;
689
; Return 0 is EAX = failure
690
;
691
;***************************************************************************
692
align 4
693
SIS960_get_mac_addr:
694
        DEBUGF  1, "SIS960 - get mac: "
695
 
696
;-------------------------------
697
; Send Request for eeprom access
698
 
699
        set_io  0
700
        set_io  mear            ; Eeprom access register
701
        mov     eax, EEREQ      ; Request access to eeprom
702
        out     dx, eax         ; Send request
703
 
704
;-----------------------------------------------------
705
; Loop 4000 times and if access not granted, error out
706
 
707
        mov     ecx, 4000
708
  .loop:
709
        in      eax, dx         ; get eeprom status
710
        test    eax, EEGNT      ; see if eeprom access granted flag is set
711
        jnz     .got_access     ; if it is, go access the eeprom
712
        loop    .loop           ; else keep waiting
713
 
714
        DEBUGF  1, "Access to EEprom failed!\n", 0
715
 
716
        set_io  mear            ; Eeprom access register
717
        mov     eax, EEDONE     ; tell eeprom we are done
718
        out     dx, eax
719
 
720
        or      eax, -1         ; error
721
        ret
722
 
723
  .got_access:
724
 
725
;------------------------------------------
726
; EEprom access granted, read MAC from card
727
 
728
    ; zero based so 3-16 bit reads will take place
729
 
730
        mov     ecx, 2
731
  .read_loop:
732
        mov     eax, EEPROMMACAddr      ; Base Mac Address
733
        add     eax, ecx                ; Current Mac Byte Offset
734
        push    ecx
735
        call    read_eeprom             ; try to read 16 bits
736
        pop     ecx
737
        mov     word [device.mac+ecx*2], ax     ; save 16 bits to the MAC ID varible
738
        dec     ecx                     ; one less word to read
739
        jns     .read_loop              ; if more read more
740
        mov     eax, 1                  ; return non-zero indicating success
741
 
742
        DEBUGF  2,"%x-%x-%x-%x-%x-%x\n",[device.mac]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2
743
 
744
;-------------------------------------
745
; Tell EEPROM We are Done Accessing It
746
 
747
  .done:
748
        set_io  0
749
        set_io  mear            ; Eeprom access register
750
        mov     eax, EEDONE     ; tell eeprom we are done
751
        out     dx, eax
752
 
753
        xor     eax, eax        ; ok
754
        ret
755
 
756
 
757
 
758
 
759
;***************************************************************************
760
;
761
; get_mac_addr: - Get MAC address for stand alone SiS900 model
762
;
763
; Older SiS900 and friends, use EEPROM to store MAC address.
764
;
765
;***************************************************************************
766
align 4
767
SIS900_get_mac_addr:
768
        DEBUGF  1, "SIS900 - get mac: "
769
 
770
;------------------------------------
771
; check to see if we have sane EEPROM
772
 
773
        mov     eax, EEPROMSignature  ; Base Eeprom Signature
774
        call    read_eeprom           ; try to read 16 bits
775
        cmp     ax, 0xffff
776
        je      .err
777
        test    ax, ax
778
        je      .err
779
 
780
;-----------
781
; Read MacID
782
 
783
; zero based so 3-16 bit reads will take place
784
 
785
        mov     ecx, 2
786
  .loop:
787
        mov     eax, EEPROMMACAddr      ; Base Mac Address
788
        add     eax, ecx                ; Current Mac Byte Offset
789
        push    ecx
790
        call    read_eeprom             ; try to read 16 bits
791
        pop     ecx
792
        mov     word [device.mac+ecx*2], ax     ; save 16 bits to the MAC ID storage
793
        dec     ecx                             ; one less word to read
794
        jns     .loop                           ; if more read more
795
 
796
        DEBUGF  2,"%x-%x-%x-%x-%x-%x\n",[device.mac]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2
797
 
798
        xor     eax, eax
799
        ret
800
 
801
 
802
  .err:
803
        DEBUGF  1, "Access to EEprom failed!\n", 0
804
 
805
        or      eax, -1
806
        ret
807
 
808
 
809
;***************************************************************************
810
;
811
; Get_Mac_SIS635_900_REV: - Get MAC address for model 635
812
;
813
;***************************************************************************
814
align 4
815
Get_Mac_SIS635_900_REV:
816
        DEBUGF  1, "SIS635 - get mac: "
817
 
818
        set_io  0
819
        set_io  rfcr
820
        in      eax, dx
821
        mov     esi, eax
822
 
823
        set_io  cr
824
        or      eax, RELOAD
825
        out     dx, eax
826
 
827
        xor     eax, eax
828
        out     dx, eax
829
 
830
;-----------------------------------------------
831
; Disable packet filtering before setting filter
832
 
833
        set_io  rfcr
834
        mov     eax, esi
835
        and     eax, not RFEN
836
        out     dx, eax
837
 
838
;---------------------------------
839
; Load MAC to filter data register
840
 
841
        xor     ecx, ecx
842
        lea     edi, [device.mac]
843
  .loop:
844
        set_io  0
845
        set_io  rfcr
846
        mov     eax, ecx
847
        shl     eax, RFADDR_shift
848
        out     dx, eax
849
 
850
        set_io  rfdr
851
        in      ax, dx
852
        stosw
853
        inc     ecx
854
        cmp     ecx, 3
855
        jb      .loop
856
 
857
;------------------------
858
; Enable packet filtering
859
 
860
        set_io  rfcr
861
        mov     eax, esi
862
        or      eax, RFEN
863
        out     dx, eax
864
 
865
        DEBUGF  2,"%x-%x-%x-%x-%x-%x\n",[device.mac]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2
866
 
867
        xor     eax, eax
868
        ret
869
 
870
;***************************************************************************
871
;
872
; read_eeprom
873
;
874
; reads and returns a given location from EEPROM
875
;
876
; IN:  si = addr
877
; OUT: ax = data
878
;
879
;***************************************************************************
880
align 4
881
read_eeprom:
882
 
883
        set_io  0
884
        set_io  mear
885
 
886
        xor     eax, eax              ; start send
887
        out     dx, eax
888
        ee_delay
889
 
890
        or      eax, EECLK
891
        out     dx, eax
892
        ee_delay
893
 
894
;------------------------------------
895
; Send the read command
896
 
897
        or      esi, EEread
898
        mov     ecx, 1 shl 9
899
 
900
  .loop:
901
        mov     eax, EECS
902
        test    esi, ecx
903
        jz      @f
904
        or      eax, EEDI
905
       @@:
906
        out     dx, eax
907
        ee_delay
908
 
909
        or      eax, EECLK
910
        out     dx, eax
911
        ee_delay
912
 
913
        shr     esi, 1
914
        jnc     .loop
915
 
916
        mov     eax, EECS
917
        out     dx, eax
918
        ee_delay
919
 
920
;------------------------
921
; Read 16-bits of data in
922
 
923
        xor     esi, esi
924
        mov     cx, 16
925
  .loop2:
926
        mov     eax, EECS
927
        out     dx, eax
928
        ee_delay
929
 
930
        or      eax, EECLK
931
        out     dx, eax
932
        ee_delay
933
 
934
        in      eax, dx
935
        shl     esi, 1
936
        test    eax, EEDO
937
        jz      @f
938
        inc     esi
939
       @@:
940
        loop    .loop2
941
 
942
;----------------------------
943
; Terminate the EEPROM access
944
 
945
        xor     eax, eax
946
        out     dx, eax
947
        ee_delay
948
 
949
        mov     eax, EECLK
950
        out     dx, eax
951
        ee_delay
952
 
953
        movzx   eax, si
954
 
955
        ret
956
 
957
 
958
 
959
align 4
960
write_mac:
961
        DEBUGF  1,'Setting MAC is not supported for SIS900 card.\n'
962
        add     esp, 6
963
        ret
964
 
965
 
966
 
967
 
968
;***************************************************************************
969
;   Function
970
;      transmit
971
;   Description
972
;      Transmits a packet of data via the ethernet card
973
;         buffer pointer in [esp+4]
974
;         size of buffer in [esp+8]
975
;         pointer to device structure in ebx
976
;
977
;***************************************************************************
978
align 4
979
transmit:
980
        DEBUGF  1,"Transmitting packet, buffer:%x, size:%u\n",[esp+4],[esp+8]
981
        mov     eax, [esp+4]
982
        DEBUGF  1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
983
        [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
984
        [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
985
        [eax+13]:2,[eax+12]:2
986
 
987
        cmp     dword [esp + 8], MAX_ETH_FRAME_SIZE
988
        ja      .error
989
        cmp     dword [esp + 8], 60
990
        jb      .error
991
 
992
        movzx   ecx, [device.cur_tx]
993
        shl     ecx, 4                  ; *16
994
        lea     ecx, [device.txd + ecx]
995
 
996
        test    dword [ecx + 4], 0x80000000     ; card owns descriptor ?
997
        jnz     .error
998
 
999
        mov     eax, [esp + 4]
1000
        mov     dword [ecx + 12], eax
1001
        GetRealAddr
1002
        mov     dword [ecx + 8], eax    ; buffer address
1003
 
1004
        mov     eax, [esp + 8]
1005
        and     eax, DSIZE
1006
        or      eax, 0x80000000         ; card owns descriptor
1007
        mov     dword [ecx + 4], eax    ; status field
1008
 
1009
        set_io  0
1010
        set_io  cr
1011
        in      eax, dx
1012
        or      eax, TxENA              ; Enable the transmit state machine
1013
        out     dx, eax
1014
 
1015
        inc     [device.cur_tx]
1016
        and     [device.cur_tx], NUM_TX_DESC-1
1017
 
1018
; update stats
1019
        mov     ecx, [esp + 8]
1020
        inc     [device.packets_tx]
1021
        add     dword [device.bytes_tx], ecx
1022
        adc     dword [device.bytes_tx + 4], 0
1023
 
1024
  .finish:
1025
        DEBUGF  1,"Packet sent!\n"
1026
        xor     eax, eax
1027
        ret     8
1028
 
1029
  .error:
1030
        DEBUGF  1,"ERROR!\n"
1031
        stdcall KernelFree, [esp+4]
1032
        or      eax, -1
1033
        ret     8
1034
 
1035
 
1036
;***************************************************************************
1037
;
1038
; int_handler
1039
;
1040
; handles received IRQs, which signal received packets
1041
;
1042
; Currently only supports one descriptor per packet, if packet is fragmented
1043
; between multiple descriptors you will lose part of the packet
1044
;
1045
;***************************************************************************
1046
 
1047
align 4
1048
int_handler:
1049
 
1050
        push    ebx esi edi
1051
 
1052
        DEBUGF  1,"\n%s int\n", my_service
1053
 
1054
; find pointer of device which made IRQ occur
1055
 
1056
        mov     ecx, [devices]
1057
        test    ecx, ecx
1058
        jz      .nothing
1059
        mov     esi, device_list
1060
  .nextdevice:
1061
        mov     ebx, [esi]
1062
 
1063
        set_io  0
1064
        set_io  isr
1065
        in      eax, dx                 ; note that this clears all interrupts
1066
        test    ax, IE
1067
        jnz     .got_it
1068
  .continue:
1069
        add     esi, 4
1070
        dec     ecx
1071
        jnz     .nextdevice
1072
  .nothing:
1073
        pop     edi esi ebx
1074
        xor     eax, eax
1075
 
1076
        ret
1077
 
1078
  .got_it:
1079
 
1080
        DEBUGF  1,"Device: %x Status: %x ", ebx, ax
1081
 
1082
        test    ax, RxOK
1083
        jz      .no_rx_
1084
 
1085
        push    ax
1086
 
1087
  .rx_loop:
1088
 
1089
;-----------
1090
; Get Status
1091
        movzx   eax, [device.cur_rx]                    ; find current descriptor
1092
        shl     eax, 4                                  ; * 16
1093
        mov     ecx, dword[device.rxd + eax + 4]        ; get receive status
1094
 
1095
;-------------------------------------------
1096
; Check RX_Status to see if packet is waiting
1097
        test    ecx, 0x80000000
1098
        jz      .no_rx
1099
 
1100
;----------------------------------------------
1101
; There is a packet waiting check it for errors
1102
        test    ecx, 0x67C0000                  ; see if there are any errors
1103
        jnz     .error_status
1104
 
1105
;---------------------
1106
; Check size of packet
1107
        and     ecx, DSIZE                      ; get packet size minus CRC
1108
        sub     ecx, CRC_SIZE                   ; make sure packet contains data
1109
        jbe     .error_size
1110
 
1111
; update statistics
1112
        inc     dword [device.packets_rx]
1113
        add     dword [device.bytes_rx], ecx
1114
        adc     dword [device.bytes_rx + 4], 0
1115
 
1116
        push    ebx
1117
        push    .return
1118
        push    ecx                             ; packet size
1119
        pushd   [device.rxd + eax + 12]         ; packet ptr
1120
        DEBUGF  1, "Packet received OK\n"
1121
        jmp     Eth_input
1122
  .return:
1123
        pop     ebx
1124
 
1125
; Reset status, allow ethernet card access to descriptor
1126
        stdcall KernelAlloc, RX_BUFF_SZ
1127
        test    eax, eax
1128
        jz      .fail
1129
        movzx   ecx, [device.cur_rx]
1130
        shl     ecx, 4                          ; *16
1131
        lea     ecx, [device.rxd + ecx]
1132
        mov     dword [ecx + 12], eax
1133
        GetRealAddr
1134
        mov     dword [ecx + 8], eax
1135
        mov     dword [ecx + 4], RX_BUFF_SZ
1136
 
1137
        inc     [device.cur_rx]                         ; get next descriptor
1138
        and     [device.cur_rx], NUM_RX_DESC-1          ; only 4 descriptors 0-3
1139
 
1140
        jmp     .rx_loop
1141
 
1142
  .no_rx:
1143
        set_io  0
1144
        set_io  cr
1145
        in      eax, dx
1146
        or      eax, RxENA                              ; Re-Enable the Receive state machine
1147
        out     dx, eax
1148
 
1149
        pop     ax
1150
 
1151
  .no_rx_:
1152
        test    ax, TxOK
1153
        jz      .no_tx
1154
 
1155
        DEBUGF  1, "TX ok!\n"
1156
 
1157
  .tx_loop:
1158
        movzx   ecx, [device.last_tx]
1159
        shl     ecx, 4                  ; *16
1160
        lea     ecx, [device.txd + ecx]
1161
 
1162
        test    dword [ecx + 4], 0x80000000   ; card owns descr
1163
        jnz     .no_tx
1164
        cmp     dword [ecx + 12], 0
1165
        je      .no_tx
1166
 
1167
        DEBUGF  1, "Freeing packet = %x\n", [ecx + 12]:8
1168
        push    dword [ecx + 12]
1169
        mov     dword [ecx + 12], 0
1170
        call    KernelFree
1171
 
1172
        inc     [device.last_tx]
1173
        and     [device.last_tx], NUM_TX_DESC-1
1174
        jmp     .tx_loop
1175
 
1176
  .no_tx:
1177
  .fail:
1178
        pop     edi esi ebx
1179
        xor     eax, eax
1180
        inc     eax
1181
 
1182
        ret
1183
 
1184
        ret
1185
 
1186
  .error_status:
1187
        DEBUGF  1, "Packet error: %x\n", ecx
1188
        jmp     .fail
1189
 
1190
  .error_size:
1191
        DEBUGF  1, "Packet too large/small\n"
1192
        jmp     .fail
1193
 
1194
 
1195
 
1196
 
1197
 
1198
; End of code
1199
 
1200
align 4                                         ; Place all initialised data here
1201
 
1202
devices         dd 0
1203
 
1204
specific_table:
1205
;    dd SIS630A_900_REV, Get_Mac_SIS630A_900_REV, 0
1206
;    dd SIS630E_900_REV, Get_Mac_SIS630E_900_REV, 0
1207
    dd SIS630S_900_REV, Get_Mac_SIS635_900_REV, 0
1208
    dd SIS630EA1_900_REV, Get_Mac_SIS635_900_REV, 0
1209
    dd SIS630ET_900_REV, Get_Mac_SIS635_900_REV, 0 ;SIS630ET_900_REV_SpecialFN
1210
    dd SIS635A_900_REV, Get_Mac_SIS635_900_REV, 0
1211
    dd SIS900_960_REV, SIS960_get_mac_addr, 0
1212
    dd SIS900B_900_REV, SIS900_get_mac_addr, 0
1213
    dd 0                                        ; end of list
1214
 
1215
version         dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
1216
my_service      db 'SIS900',0                  ; max 16 chars include zero
1217
 
1218
include_debug_strings                          ; All data wich FDO uses will be included here
1219
 
1220
section '.data' data readable writable align 16; place all uninitialized data place here
1221
 
1222
device_list     rd MAX_DEVICES                 ; This list contains all pointers to device structures the driver is handling
1223