Subversion Repositories Kolibri OS

Rev

Rev 4467 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
3545 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                    ;;
3
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved.       ;;
4
;; Distributed under terms of the GNU General Public License          ;;
5
;;                                                                    ;;
6
;;  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
 
200
 
201
include '../proc32.inc'
202
include '../imports.inc'
203
include '../fdo.inc'
204
include '../netdrv.inc'
205
 
206
public START
207
public version
208
 
209
 
210
virtual at ebx
211
        device:
212
 
213
        ETH_DEVICE
214
 
215
        .io_addr        dd ?
216
        .pci_bus        dd ?
217
        .pci_dev        dd ?
218
        .irq_line       db ?
219
        .cur_rx         db ?
220
        .cur_tx         db ?
221
        .last_tx        db ?
222
        .pci_revision   db ?
223
        .table_entries  db ?
224
        rb 2    ; alignment
225
 
226
        .txd            rd (4 * NUM_TX_DESC)
227
        .rxd            rd (4 * NUM_RX_DESC)
228
 
229
        .size = $ - device
230
 
231
end virtual
232
 
233
macro   ee_delay {
234
        push    eax
235
        in      eax, dx
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
        pop     eax
246
}
247
 
248
 
249
section '.flat' code readable align 16
250
 
251
; Driver entry point - register our service when the driver is loading.
252
; TODO: add needed operations when unloading
253
START:
254
        cmp     dword [esp+4], 1
255
        jne     .exit
256
        stdcall RegService, my_service, service_proc
257
        ret     4
258
  .exit:
259
        xor     eax, eax
260
        ret     4
261
 
262
; Service procedure for the driver - handle all I/O requests for the driver.
263
; Currently handled requests are: SRV_GETVERSION = 0 and SRV_HOOK = 1.
264
service_proc:
265
; 1. Get parameter from the stack: [esp+4] is the first parameter,
266
;       pointer to IOCTL structure.
267
        mov     edx, [esp+4]    ; edx -> IOCTL
268
; 2. Get request code and select a handler for the code.
269
        mov     eax, [IOCTL.io_code]
270
        test    eax, eax        ; check for SRV_GETVERSION
271
        jnz     @f
272
; 3. This is SRV_GETVERSION request, no input, 4 bytes output, API_VERSION.
273
; 3a. Output size must be at least 4 bytes.
274
        cmp     [IOCTL.out_size], 4
275
        jb      .fail
276
; 3b. Write result to the output buffer.
277
        mov     eax, [IOCTL.output]
278
        mov     [eax], dword API_VERSION
279
; 3c. Return success.
280
        xor     eax, eax
281
        ret     4
282
  @@:
283
        dec     eax     ; check for SRV_HOOK
284
        jnz     .fail
285
; 4. This is SRV_HOOK request, input defines the device to hook, no output.
286
; 4a. The driver works only with PCI devices,
287
;       so input must be at least 3 bytes long.
288
        cmp     [IOCTL.inp_size], 3
289
        jb      .fail
290
; 4b. First byte of input is bus type, 1 stands for PCI.
291
        mov     eax, [IOCTL.input]
292
        cmp     byte [eax], 1
293
        jne     .fail
294
; 4c. Second and third bytes of the input define the device: bus and dev.
295
;       Word in bx holds both bytes.
296
        mov     bx, [eax+1]
297
; 4d. Check if the device was already hooked,
298
;       scan through the list of known devices.
299
; check if the device is already listed
300
        mov     esi, device_list
301
        mov     ecx, [devices]
302
        test    ecx, ecx
303
        jz      .firstdevice
304
 
305
;        mov     eax, [IOCTL.input]                      ; get the pci bus and device numbers
306
        mov     ax, [eax+1]                            ;
307
  .nextdevice:
308
        mov     ebx, [esi]
309
        cmp     al, byte[device.pci_bus]
310
        jne     @f
311
        cmp     ah, byte[device.pci_dev]
312
        je      .find_devicenum                         ; Device is already loaded, let's find it's device number
313
       @@:
314
        add     esi, 4
315
        loop    .nextdevice
316
; 4e. This device doesn't have its own eth_device structure yet, let's create one
317
  .firstdevice:
318
; 4f. Check that we have place for new device.
319
        cmp     [devices], MAX_DEVICES
320
        jae     .fail
321
; 4g. Allocate memory for device descriptor and receive+transmit buffers.
322
; 4h. Zero the structure.
323
        allocate_and_clear ebx, device.size, .fail
324
; 4i. Save PCI coordinates
325
        mov     eax, [IOCTL.input]
326
        movzx   ecx, byte[eax+1]
327
        mov     [device.pci_bus], ecx
328
        movzx   ecx, byte[eax+2]
329
        mov     [device.pci_dev], ecx
330
; 4j. Fill in the direct call addresses into the struct.
331
        mov     [device.reset], reset
332
        mov     [device.transmit], transmit
333
        mov     [device.unload], unload
334
        mov     [device.name], my_service
335
 
336
; 4k. Now, it's time to find the base io addres of the PCI device
337
; TODO: implement check if bus and dev exist on this machine
338
 
339
; Now, it's time to find the base io addres of the PCI device
340
        PCI_find_io
341
 
342
; We've found the io address, find IRQ now
343
        PCI_find_irq
344
 
345
; 4m. Add new device to the list (required for int_handler).
346
        mov     eax, [devices]
347
        mov     [device_list+4*eax], ebx
348
        inc     [devices]
349
 
350
; 4m. Ok, the eth_device structure is ready, let's probe the device
351
        call    probe
352
        test    eax, eax
353
        jnz     .destroy
354
; 4n. If device was successfully initialized, register it for the kernel.
355
 
356
        mov     [device.type], NET_TYPE_ETH
357
        call    NetRegDev
358
 
359
        cmp     eax, -1
360
        je      .destroy
361
 
362
        ret     4
363
 
364
; 5. If the device was already loaded, find the device number and return it in eax
365
 
366
  .find_devicenum:
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
        ret     4
371
 
372
; If an error occured, remove all allocated data and exit (returning -1 in eax)
373
 
374
  .destroy:
375
        dec     [devices]
376
        ; todo: reset device into virgin state
377
 
378
  .err:
379
        stdcall KernelFree, ebx
380
 
381
  .fail:
382
        xor     eax, eax
383
        ret     4
384
 
385
 
386
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
387
;;                                                                        ;;
388
;;        Actual Hardware dependent code starts here                      ;;
389
;;                                                                        ;;
390
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
391
 
392
unload:
393
        ; TODO: (in this particular order)
394
        ;
395
        ; - Stop the device
396
        ; - Detach int handler
397
        ; - Remove device from local list
398
        ; - call unregister function in kernel
399
        ; - Remove all allocated structures and buffers the card used
400
 
401
        or      eax,-1
402
 
403
ret
404
 
405
;***************************************************************************
406
;
407
; probe
408
;
409
; checks the card and enables it
410
;
411
; TODO: probe mii transceivers
412
;
413
;***************************************************************************
414
align 4
415
probe:
416
        DEBUGF  1, "Probe\n"
417
 
418
; wake up device   CHECKME
419
        stdcall PciWrite8, [device.pci_bus], [device.pci_dev], 0x40, 0
420
 
421
        PCI_make_bus_master
422
 
423
        PCI_adjust_latency 64
424
 
425
; Get Card Revision
426
        stdcall PciRead8, [device.pci_bus], [device.pci_dev], 0x08
427
        mov     [device.pci_revision], al       ; save the revision for later use
428
 
429
; Look up through the specific_table
430
        mov     esi, specific_table
431
  .tableloop:
432
        cmp     dword [esi], 0                  ; Check if we reached end of the list
433
        je      .notsupported
434
        cmp     al, [esi]                       ; Check if revision is OK
435
        je      .ok
436
        add     esi, 12                         ; Advance to next entry
437
        jmp     .tableloop
438
 
439
  .ok:
440
 
441
        call     dword[esi + 4]                 ; "get MAC" function
442
 
443
; Set table entries
444
        mov      [device.table_entries], 16
445
        cmp      [device.pci_revision], SIS635A_900_REV
446
        jae      @f
447
        cmp      [device.pci_revision], SIS900B_900_REV
448
        je       @f
449
        mov      [device.table_entries], 8
450
       @@:
451
 
452
; TODO: Probe for mii transceiver
453
 
454
        jmp     reset
455
 
456
  .notsupported:
457
        DEBUGF  1, "Device not supported\n"
458
        or      eax, -1
459
 
460
        ret
461
 
462
reset:
463
 
464
        DEBUGF  1, "reset\n"
465
 
466
        movzx   eax, [device.irq_line]
467
        stdcall AttachIntHandler, eax, int_handler, 0
468
 
469
;--------------------------------------------
470
; Disable Interrupts and reset Receive Filter
471
 
472
        set_io  0
473
        set_io  ier
474
        xor     eax, eax
475
        out     dx, eax
476
 
477
        set_io  imr
478
        out     dx, eax
479
 
480
        set_io  rfcr
481
        out     dx, eax
482
 
483
;-----------
484
; Reset Card
485
 
486
        set_io  cr
487
        in      eax, dx                         ; Get current Command Register
488
        or      eax, RESET + RxRESET + TxRESET  ; set flags
489
        out     dx, eax                         ; Write new Command Register
490
 
491
;----------
492
; Wait loop
493
 
494
        set_io  isr
495
        mov     ecx, 1000
496
  .loop:
497
        dec     ecx
498
        jz      .fail
499
        in      eax, dx                         ; read interrupt status
500
        test    eax, TxRCMP + RxRCMP
501
        jz      .loop
502
        DEBUGF  1, "status=%x\n", eax
503
 
504
;------------------------------------------------------
505
; Set Configuration Register depending on Card Revision
506
 
507
        set_io  cfg
508
        mov     eax, PESEL                      ; Configuration Register Bit
509
        cmp     [device.pci_revision], SIS635A_900_REV
510
        je      .match
511
        cmp     [device.pci_revision], SIS900B_900_REV ; Check card revision
512
        jne     .done
513
  .match:                                       ; Revision match
514
        or      eax, RND_CNT                    ; Configuration Register Bit
515
  .done:
516
        out     dx, eax
517
 
518
        DEBUGF  1, "Initialising RX Filter\n"
519
 
520
; Get Receive Filter Control Register
521
        set_io  rfcr
522
        in      eax, dx
523
        push    eax
524
 
525
; disable packet filtering before setting filter
526
        and     eax, not RFEN
527
        out     dx, eax
528
 
529
; load MAC addr to filter data register
530
        xor     ecx, ecx
531
  .macloop:
532
        mov     eax, ecx
533
        set_io  0
534
        set_io  rfcr
535
        shl     eax, 16                                             ; high word of eax tells card which mac byte to write
536
        out     dx, eax                                             ;
537
        set_io  rfdr
538
        mov     ax, word [device.mac + ecx*2]                       ; Get Mac ID word
539
        out     dx, ax                                              ; Send Mac ID
540
        inc     cl                                                  ; send next word
541
        cmp     cl, 3                                               ; more to send?
542
        jne     .macloop
543
 
544
; enable packet filtering
545
        pop     eax                     ; old register value
546
        set_io  rfcr
547
        or      eax, RFEN               ; enable filtering
548
        out     dx, eax                 ; set register
549
 
550
        DEBUGF  1, "Initialising TX Descriptors\n"
551
 
552
        mov     ecx, NUM_TX_DESC
553
        lea     esi, [device.txd]
554
  .txdescloop:
555
        lea     eax, [esi + 16]                 ; next ptr
556
        GetRealAddr
557
        mov     dword [esi], eax                ; link to next desc
558
        mov     dword [esi + 4], 0              ; status field
559
        mov     dword [esi + 8], 0              ; ptr to buffer
560
        add     esi, 16
561
        dec     ecx
562
        jnz     .txdescloop
563
 
564
        lea     eax, [device.txd]
565
        GetRealAddr
566
        mov     dword [esi - 16], eax           ; correct last descriptor link ptr
567
 
568
        set_io  txdp                            ; TX Descriptor Pointer
569
;        lea     eax, [device.txd]
570
;        GetRealAddr
571
        out     dx, eax
572
 
573
        mov     [device.cur_tx], 0              ; Set current tx descriptor to 0
574
        mov     [device.last_tx], 0
575
 
576
        DEBUGF  1, "Initialising RX Descriptors\n"
577
 
578
        mov     ecx, NUM_RX_DESC
579
        lea     esi, [device.rxd]
580
  .rxdescloop:
581
        lea     eax, [esi + 16]                 ; next ptr
582
        GetRealAddr
583
        mov     dword [esi], eax
584
        mov     dword [esi + 4], RX_BUFF_SZ     ; size
585
 
586
        push    ecx esi
587
        stdcall KernelAlloc, RX_BUFF_SZ
588
        pop     esi ecx
589
        test    eax, eax
590
        jz      .fail
591
        mov     dword [esi + 12], eax           ; address
592
        GetRealAddr
593
        mov     dword [esi + 8], eax            ; real address
594
        add     esi, 16
595
        dec     ecx
596
        jnz     .rxdescloop
597
 
598
        lea     eax, [device.rxd]
599
        GetRealAddr
600
        mov     dword [esi - 16], eax           ; correct last descriptor link ptr
601
 
602
        set_io  0
603
        set_io  rxdp
604
;        lea     eax, [device.rxd]
605
;        GetRealAddr
606
        out     dx, eax
607
 
608
        mov     [device.cur_rx], 0              ; Set current rx descriptor to 0
609
 
610
        DEBUGF  1, "setting RX mode\n"
611
 
612
        xor     cl, cl
613
  .rxfilterloop:
614
        set_io  0
615
        set_io  rfcr                    ; Receive Filter Control Reg offset
616
        mov     eax, 4                  ; determine table entry
617
        add     al, cl
618
        shl     eax, 16
619
        out     dx, eax                 ; tell card which entry to modify
620
 
621
        set_io  rfdr                    ; Receive Filter Control Reg offset
622
        mov     eax, 0xffff             ; entry value
623
        out     dx, ax                  ; write value to table in card
624
 
625
        inc     cl                      ; next entry
626
        cmp     cl, [device.table_entries]
627
        jb      .rxfilterloop
628
 
629
        set_io  rfcr                    ; Receive Filter Control Register offset
630
        mov     eax, RFAAB + RFAAM + RFAAP + RFEN
631
        out     dx, eax
632
 
633
        set_io  rxcfg                   ; Receive Config Register offset
634
        mov     eax, ATX + RX_DMA + 2   ; 0x2 : RX Drain Threshold = 8*8=64 bytes
635
        out     dx, eax
636
 
637
        DEBUGF  1, "setting TX mode\n"
638
 
639
        set_io  txcfg                   ; Transmit config Register offset
640
        mov     eax, ATP + HBI + CSI + TX_DMA + 0x120
641
                                        ; TX Fill threshold = 0x100
642
                                        ; TX Drain Threshold = 0x20
643
        out     dx, eax
644
 
645
        DEBUGF  1, "Enabling interrupts\n"
646
 
647
        set_io  imr
648
        mov     eax, IE                 ; Interrupt enable mask
649
        out     dx, eax
650
 
651
        set_io  cr
652
        in      eax, dx
653
        or      eax, RxENA              ; Enable Receive
654
        out     dx, eax
655
 
656
        set_io  ier                     ; Interrupt enable
657
        mov     eax, 1
658
        out     dx, eax
659
 
660
        mov     [device.mtu], 1514
661
 
662
; Set link state to unknown
663
        mov     [device.state], ETH_LINK_UNKOWN
664
 
665
        xor     eax, eax
666
        ret
667
 
668
  .fail:
669
        DEBUGF  1, "Resetting device failed\n"
670
        or      eax, -1
671
 
672
        ret
673
 
674
 
675
;***************************************************************************
676
;
677
; SIS960_get_mac_addr: - Get MAC address for SiS962 or SiS963 model
678
;
679
; SiS962 or SiS963 model, use EEPROM to store MAC address.
680
; EEPROM is shared by LAN and 1394.
681
; When access EEPROM, send EEREQ signal to hardware first, and wait for EEGNT.
682
; If EEGNT is ON, EEPROM is permitted to be accessed by LAN, otherwise is not.
683
; After MAC address is read from EEPROM, send
684
; EEDONE signal to refuse EEPROM access by LAN.
685
; The EEPROM map of SiS962 or SiS963 is different to SiS900.
686
; The signature field in SiS962 or SiS963 spec is meaningless.
687
;
688
; Return 0 is EAX = failure
689
;
690
;***************************************************************************
691
align 4
692
SIS960_get_mac_addr:
693
        DEBUGF  1, "SIS960 - get mac: "
694
 
695
;-------------------------------
696
; Send Request for eeprom access
697
 
698
        set_io  0
699
        set_io  mear            ; Eeprom access register
700
        mov     eax, EEREQ      ; Request access to eeprom
701
        out     dx, eax         ; Send request
702
 
703
;-----------------------------------------------------
704
; Loop 4000 times and if access not granted, error out
705
 
706
        mov     ecx, 4000
707
  .loop:
708
        in      eax, dx         ; get eeprom status
709
        test    eax, EEGNT      ; see if eeprom access granted flag is set
710
        jnz     .got_access     ; if it is, go access the eeprom
711
        loop    .loop           ; else keep waiting
712
 
713
        DEBUGF  1, "Access to EEprom failed!\n", 0
714
 
715
        set_io  mear            ; Eeprom access register
716
        mov     eax, EEDONE     ; tell eeprom we are done
717
        out     dx, eax
718
 
719
        or      eax, -1         ; error
720
        ret
721
 
722
  .got_access:
723
 
724
;------------------------------------------
725
; EEprom access granted, read MAC from card
726
 
727
    ; zero based so 3-16 bit reads will take place
728
 
729
        mov     ecx, 2
730
  .read_loop:
731
        mov     eax, EEPROMMACAddr      ; Base Mac Address
732
        add     eax, ecx                ; Current Mac Byte Offset
733
        push    ecx
734
        call    read_eeprom             ; try to read 16 bits
735
        pop     ecx
736
        mov     word [device.mac+ecx*2], ax     ; save 16 bits to the MAC ID varible
737
        dec     ecx                     ; one less word to read
738
        jns     .read_loop              ; if more read more
739
        mov     eax, 1                  ; return non-zero indicating success
740
 
741
        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
742
 
743
;-------------------------------------
744
; Tell EEPROM We are Done Accessing It
745
 
746
  .done:
747
        set_io  0
748
        set_io  mear            ; Eeprom access register
749
        mov     eax, EEDONE     ; tell eeprom we are done
750
        out     dx, eax
751
 
752
        xor     eax, eax        ; ok
753
        ret
754
 
755
 
756
 
757
 
758
;***************************************************************************
759
;
760
; get_mac_addr: - Get MAC address for stand alone SiS900 model
761
;
762
; Older SiS900 and friends, use EEPROM to store MAC address.
763
;
764
;***************************************************************************
765
align 4
766
SIS900_get_mac_addr:
767
        DEBUGF  1, "SIS900 - get mac: "
768
 
769
;------------------------------------
770
; check to see if we have sane EEPROM
771
 
772
        mov     eax, EEPROMSignature  ; Base Eeprom Signature
773
        call    read_eeprom           ; try to read 16 bits
774
        cmp     ax, 0xffff
775
        je      .err
776
        test    ax, ax
777
        je      .err
778
 
779
;-----------
780
; Read MacID
781
 
782
; zero based so 3-16 bit reads will take place
783
 
784
        mov     ecx, 2
785
  .loop:
786
        mov     eax, EEPROMMACAddr      ; Base Mac Address
787
        add     eax, ecx                ; Current Mac Byte Offset
788
        push    ecx
789
        call    read_eeprom             ; try to read 16 bits
790
        pop     ecx
791
        mov     word [device.mac+ecx*2], ax     ; save 16 bits to the MAC ID storage
792
        dec     ecx                             ; one less word to read
793
        jns     .loop                           ; if more read more
794
 
795
        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
796
 
797
        xor     eax, eax
798
        ret
799
 
800
 
801
  .err:
802
        DEBUGF  1, "Access to EEprom failed!\n", 0
803
 
804
        or      eax, -1
805
        ret
806
 
807
 
808
;***************************************************************************
809
;
810
; Get_Mac_SIS635_900_REV: - Get MAC address for model 635
811
;
812
;***************************************************************************
813
align 4
814
Get_Mac_SIS635_900_REV:
815
        DEBUGF  1, "SIS635 - get mac: "
816
 
817
        set_io  0
818
        set_io  rfcr
819
        in      eax, dx
820
        mov     esi, eax
821
 
822
        set_io  cr
823
        or      eax, RELOAD
824
        out     dx, eax
825
 
826
        xor     eax, eax
827
        out     dx, eax
828
 
829
;-----------------------------------------------
830
; Disable packet filtering before setting filter
831
 
832
        set_io  rfcr
833
        mov     eax, esi
834
        and     eax, not RFEN
835
        out     dx, eax
836
 
837
;---------------------------------
838
; Load MAC to filter data register
839
 
840
        xor     ecx, ecx
841
        lea     edi, [device.mac]
842
  .loop:
843
        set_io  0
844
        set_io  rfcr
845
        mov     eax, ecx
846
        shl     eax, RFADDR_shift
847
        out     dx, eax
848
 
849
        set_io  rfdr
850
        in      ax, dx
851
        stosw
852
        inc     ecx
853
        cmp     ecx, 3
854
        jb      .loop
855
 
856
;------------------------
857
; Enable packet filtering
858
 
859
        set_io  rfcr
860
        mov     eax, esi
861
        or      eax, RFEN
862
        out     dx, eax
863
 
864
        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
865
 
866
        xor     eax, eax
867
        ret
868
 
869
;***************************************************************************
870
;
871
; read_eeprom
872
;
873
; reads and returns a given location from EEPROM
874
;
875
; IN:  si = addr
876
; OUT: ax = data
877
;
878
;***************************************************************************
879
align 4
880
read_eeprom:
881
 
882
        set_io  0
883
        set_io  mear
884
 
885
        xor     eax, eax              ; start send
886
        out     dx, eax
887
        ee_delay
888
 
889
        or      eax, EECLK
890
        out     dx, eax
891
        ee_delay
892
 
893
;------------------------------------
894
; Send the read command
895
 
896
        or      esi, EEread
897
        mov     ecx, 1 shl 9
898
 
899
  .loop:
900
        mov     eax, EECS
901
        test    esi, ecx
902
        jz      @f
903
        or      eax, EEDI
904
       @@:
905
        out     dx, eax
906
        ee_delay
907
 
908
        or      eax, EECLK
909
        out     dx, eax
910
        ee_delay
911
 
912
        shr     esi, 1
913
        jnc     .loop
914
 
915
        mov     eax, EECS
916
        out     dx, eax
917
        ee_delay
918
 
919
;------------------------
920
; Read 16-bits of data in
921
 
922
        xor     esi, esi
923
        mov     cx, 16
924
  .loop2:
925
        mov     eax, EECS
926
        out     dx, eax
927
        ee_delay
928
 
929
        or      eax, EECLK
930
        out     dx, eax
931
        ee_delay
932
 
933
        in      eax, dx
934
        shl     esi, 1
935
        test    eax, EEDO
936
        jz      @f
937
        inc     esi
938
       @@:
939
        loop    .loop2
940
 
941
;----------------------------
942
; Terminate the EEPROM access
943
 
944
        xor     eax, eax
945
        out     dx, eax
946
        ee_delay
947
 
948
        mov     eax, EECLK
949
        out     dx, eax
950
        ee_delay
951
 
952
        movzx   eax, si
953
 
954
        ret
955
 
956
 
957
 
958
align 4
959
write_mac:
960
        DEBUGF  1,'Setting MAC is not supported for SIS900 card.\n'
961
        add     esp, 6
962
        ret
963
 
964
 
965
 
966
 
967
;***************************************************************************
968
;   Function
969
;      transmit
970
;   Description
971
;      Transmits a packet of data via the ethernet card
972
;         buffer pointer in [esp+4]
973
;         size of buffer in [esp+8]
974
;         pointer to device structure in ebx
975
;
976
;***************************************************************************
977
align 4
978
transmit:
979
        DEBUGF  1,"Transmitting packet, buffer:%x, size:%u\n",[esp+4],[esp+8]
980
        mov     eax, [esp+4]
981
        DEBUGF  1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
982
        [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
983
        [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
984
        [eax+13]:2,[eax+12]:2
985
 
986
        cmp     dword [esp + 8], MAX_ETH_FRAME_SIZE
987
        ja      .error
988
        cmp     dword [esp + 8], 60
989
        jb      .error
990
 
991
        movzx   ecx, [device.cur_tx]
992
        shl     ecx, 4                  ; *16
993
        lea     ecx, [device.txd + ecx]
994
 
995
        test    dword [ecx + 4], 0x80000000     ; card owns descriptor ?
996
        jnz     .error
997
 
998
        mov     eax, [esp + 4]
999
        mov     dword [ecx + 12], eax
1000
        GetRealAddr
1001
        mov     dword [ecx + 8], eax    ; buffer address
1002
 
1003
        mov     eax, [esp + 8]
1004
        and     eax, DSIZE
1005
        or      eax, 0x80000000         ; card owns descriptor
1006
        mov     dword [ecx + 4], eax    ; status field
1007
 
1008
        set_io  0
1009
        set_io  cr
1010
        in      eax, dx
1011
        or      eax, TxENA              ; Enable the transmit state machine
1012
        out     dx, eax
1013
 
1014
        inc     [device.cur_tx]
1015
        and     [device.cur_tx], NUM_TX_DESC-1
1016
 
1017
; update stats
1018
        mov     ecx, [esp + 8]
1019
        inc     [device.packets_tx]
1020
        add     dword [device.bytes_tx], ecx
1021
        adc     dword [device.bytes_tx + 4], 0
1022
 
1023
  .finish:
1024
        DEBUGF  1,"Packet sent!\n"
1025
        xor     eax, eax
1026
        ret     8
1027
 
1028
  .error:
1029
        DEBUGF  1,"ERROR!\n"
1030
        stdcall KernelFree, [esp+4]
1031
        or      eax, -1
1032
        ret     8
1033
 
1034
 
1035
;***************************************************************************
1036
;
1037
; int_handler
1038
;
1039
; handles received IRQs, which signal received packets
1040
;
1041
; Currently only supports one descriptor per packet, if packet is fragmented
1042
; between multiple descriptors you will lose part of the packet
1043
;
1044
;***************************************************************************
1045
 
1046
align 4
1047
int_handler:
1048
 
1049
        push    ebx esi edi
1050
 
1051
        DEBUGF  1,"\n%s int\n", my_service
1052
 
1053
; find pointer of device which made IRQ occur
1054
 
1055
        mov     ecx, [devices]
1056
        test    ecx, ecx
1057
        jz      .nothing
1058
        mov     esi, device_list
1059
  .nextdevice:
1060
        mov     ebx, [esi]
1061
 
1062
        set_io  0
1063
        set_io  isr
1064
        in      eax, dx                 ; note that this clears all interrupts
1065
        test    ax, IE
1066
        jnz     .got_it
1067
  .continue:
1068
        add     esi, 4
1069
        dec     ecx
1070
        jnz     .nextdevice
1071
  .nothing:
1072
        pop     edi esi ebx
1073
        xor     eax, eax
1074
 
1075
        ret
1076
 
1077
  .got_it:
1078
 
1079
        DEBUGF  1,"Device: %x Status: %x ", ebx, ax
1080
 
1081
        test    ax, RxOK
1082
        jz      .no_rx_
1083
 
1084
        push    ax
1085
 
1086
  .rx_loop:
1087
 
1088
;-----------
1089
; Get Status
1090
        movzx   eax, [device.cur_rx]                    ; find current descriptor
1091
        shl     eax, 4                                  ; * 16
1092
        mov     ecx, dword[device.rxd + eax + 4]        ; get receive status
1093
 
1094
;-------------------------------------------
1095
; Check RX_Status to see if packet is waiting
1096
        test    ecx, 0x80000000
1097
        jz      .no_rx
1098
 
1099
;----------------------------------------------
1100
; There is a packet waiting check it for errors
1101
        test    ecx, 0x67C0000                  ; see if there are any errors
1102
        jnz     .error_status
1103
 
1104
;---------------------
1105
; Check size of packet
1106
        and     ecx, DSIZE                      ; get packet size minus CRC
1107
        sub     ecx, CRC_SIZE                   ; make sure packet contains data
1108
        jbe     .error_size
1109
 
1110
; update statistics
1111
        inc     dword [device.packets_rx]
1112
        add     dword [device.bytes_rx], ecx
1113
        adc     dword [device.bytes_rx + 4], 0
1114
 
1115
        push    ebx
1116
        push    .return
1117
        push    ecx                             ; packet size
1118
        pushd   [device.rxd + eax + 12]         ; packet ptr
1119
        DEBUGF  1, "Packet received OK\n"
1120
        jmp     Eth_input
1121
  .return:
1122
        pop     ebx
1123
 
1124
; Reset status, allow ethernet card access to descriptor
1125
        stdcall KernelAlloc, RX_BUFF_SZ
1126
        test    eax, eax
1127
        jz      .fail
1128
        movzx   ecx, [device.cur_rx]
1129
        shl     ecx, 4                          ; *16
1130
        lea     ecx, [device.rxd + ecx]
1131
        mov     dword [ecx + 12], eax
1132
        GetRealAddr
1133
        mov     dword [ecx + 8], eax
1134
        mov     dword [ecx + 4], RX_BUFF_SZ
1135
 
1136
        inc     [device.cur_rx]                         ; get next descriptor
1137
        and     [device.cur_rx], NUM_RX_DESC-1          ; only 4 descriptors 0-3
1138
 
1139
        jmp     .rx_loop
1140
 
1141
  .no_rx:
1142
        set_io  0
1143
        set_io  cr
1144
        in      eax, dx
1145
        or      eax, RxENA                              ; Re-Enable the Receive state machine
1146
        out     dx, eax
1147
 
1148
        pop     ax
1149
 
1150
  .no_rx_:
1151
        test    ax, TxOK
1152
        jz      .no_tx
1153
 
1154
        DEBUGF  1, "TX ok!\n"
1155
 
1156
  .tx_loop:
1157
        movzx   ecx, [device.last_tx]
1158
        shl     ecx, 4                  ; *16
1159
        lea     ecx, [device.txd + ecx]
1160
 
1161
        test    dword [ecx + 4], 0x80000000   ; card owns descr
1162
        jnz     .no_tx
1163
        cmp     dword [ecx + 12], 0
1164
        je      .no_tx
1165
 
1166
        DEBUGF  1, "Freeing packet = %x\n", [ecx + 12]:8
1167
        push    dword [ecx + 12]
1168
        mov     dword [ecx + 12], 0
1169
        call    KernelFree
1170
 
1171
        inc     [device.last_tx]
1172
        and     [device.last_tx], NUM_TX_DESC-1
1173
        jmp     .tx_loop
1174
 
1175
  .no_tx:
1176
  .fail:
1177
        pop     edi esi ebx
1178
        xor     eax, eax
1179
        inc     eax
1180
 
1181
        ret
1182
 
1183
        ret
1184
 
1185
  .error_status:
1186
        DEBUGF  1, "Packet error: %x\n", ecx
1187
        jmp     .fail
1188
 
1189
  .error_size:
1190
        DEBUGF  1, "Packet too large/small\n"
1191
        jmp     .fail
1192
 
1193
 
1194
 
1195
 
1196
 
1197
; End of code
1198
 
1199
align 4                                         ; Place all initialised data here
1200
 
1201
devices         dd 0
1202
 
1203
specific_table:
1204
;    dd SIS630A_900_REV, Get_Mac_SIS630A_900_REV, 0
1205
;    dd SIS630E_900_REV, Get_Mac_SIS630E_900_REV, 0
1206
    dd SIS630S_900_REV, Get_Mac_SIS635_900_REV, 0
1207
    dd SIS630EA1_900_REV, Get_Mac_SIS635_900_REV, 0
1208
    dd SIS630ET_900_REV, Get_Mac_SIS635_900_REV, 0 ;SIS630ET_900_REV_SpecialFN
1209
    dd SIS635A_900_REV, Get_Mac_SIS635_900_REV, 0
1210
    dd SIS900_960_REV, SIS960_get_mac_addr, 0
1211
    dd SIS900B_900_REV, SIS900_get_mac_addr, 0
1212
    dd 0                                        ; end of list
1213
 
1214
version         dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
1215
my_service      db 'SIS900',0                  ; max 16 chars include zero
1216
 
1217
include_debug_strings                          ; All data wich FDO uses will be included here
1218
 
1219
section '.data' data readable writable align 16; place all uninitialized data place here
1220
 
1221
device_list     rd MAX_DEVICES                 ; This list contains all pointers to device structures the driver is handling
1222