Subversion Repositories Kolibri OS

Rev

Rev 5194 | Rev 5363 | 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
;; i8255x (Intel eepro 100) driver for KolibriOS                   ;;
7
;;                                                                 ;;
8
;;    Written by hidnplayr@kolibrios.org                           ;;
9
;;                                                                 ;;
10
;;          GNU GENERAL PUBLIC LICENSE                             ;;
11
;;             Version 2, June 1991                                ;;
12
;;                                                                 ;;
13
;; Some parts of this driver are based on the code of eepro100.c   ;;
14
;;  from linux.                                                    ;;
15
;;                                                                 ;;
16
;; Intel's programming manual for i8255x:                          ;;
17
;; http://www.intel.com/design/network/manuals/8255x_opensdm.htm   ;;
18
;;                                                                 ;;
19
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
20
 
21
; TODO: use separate descriptors in memory instead of placing them in front of packets!
22
 
23
 
4581 hidnplayr 24
format PE DLL native
25
entry START
3545 hidnplayr 26
 
4581 hidnplayr 27
        CURRENT_API             = 0x0200
28
        COMPATIBLE_API          = 0x0100
29
        API_VERSION             = (COMPATIBLE_API shl 16) + CURRENT_API
3545 hidnplayr 30
 
31
        MAX_DEVICES             = 16
32
 
33
        DEBUG                   = 1
34
        __DEBUG__               = 1
4582 hidnplayr 35
        __DEBUG_LEVEL__         = 2             ; 1 = verbose, 2 = errors only
3545 hidnplayr 36
 
4581 hidnplayr 37
section '.flat' readable writable executable
38
 
39
include '../proc32.inc'
4467 hidnplayr 40
include '../struct.inc'
41
include '../macros.inc'
3545 hidnplayr 42
include '../fdo.inc'
5074 hidnplayr 43
include '../netdrv.inc'
3545 hidnplayr 44
 
45
; Serial EEPROM
46
 
47
EE_SK           = 1 shl 0      ; serial clock
48
EE_CS           = 1 shl 1      ; chip select
49
EE_DI           = 1 shl 2      ; data in
50
EE_DO           = 1 shl 3      ; data out
51
EE_MASK         = EE_SK + EE_CS + EE_DI + EE_DO
52
 
53
; opcodes, first bit is start bit and must be 1
54
EE_READ         = 110b
55
EE_WRITE        = 101b
56
EE_ERASE        = 111b
57
 
58
; The SCB accepts the following controls for the Tx and Rx units:
59
 
60
CU_START        = 0x0010
61
CU_RESUME       = 0x0020
62
CU_STATSADDR    = 0x0040
63
CU_SHOWSTATS    = 0x0050        ; Dump statistics counters.
64
CU_CMD_BASE     = 0x0060        ; Base address to add CU commands.
65
CU_DUMPSTATS    = 0x0070        ; Dump then reset stats counters.
66
 
67
RX_START        = 0x0001
68
RX_RESUME       = 0x0002
69
RX_ABORT        = 0x0004
70
RX_ADDR_LOAD    = 0x0006
71
RX_RESUMENR     = 0x0007
72
INT_MASK        = 0x0100
73
DRVR_INT        = 0x0200        ; Driver generated interrupt
74
 
75
CmdIASetup      = 0x0001
76
CmdConfigure    = 0x0002
77
CmdTx           = 0x0004
78
CmdTxFlex       = 0x0008
79
Cmdsuspend      = 0x4000
80
 
81
reg_scb_status  = 0
82
reg_scb_cmd     = 2
83
reg_scb_ptr     = 4
84
reg_port        = 8
85
reg_eeprom      = 14
86
reg_mdi_ctrl    = 16
87
 
4581 hidnplayr 88
phy_100a        = 0x000003E0
89
phy_100c        = 0x035002A8
90
phy_82555_tx    = 0x015002A8
91
phy_nsc_tx      = 0x5C002000
92
phy_82562_et    = 0x033002A8
93
phy_82562_em    = 0x032002A8
94
phy_82562_ek    = 0x031002A8
95
phy_82562_eh    = 0x017002A8
96
phy_82552_v     = 0xd061004d
97
phy_unknown     = 0xFFFFFFFF
3545 hidnplayr 98
 
4581 hidnplayr 99
mac_82557_D100_A        = 0
100
mac_82557_D100_B        = 1
101
mac_82557_D100_C        = 2
102
mac_82558_D101_A4       = 4
103
mac_82558_D101_B0       = 5
104
mac_82559_D101M         = 8
105
mac_82559_D101S         = 9
106
mac_82550_D102          = 12
107
mac_82550_D102_C        = 13
108
mac_82551_E             = 14
109
mac_82551_F             = 15
110
mac_82551_10            = 16
111
mac_unknown             = 0xFF
112
 
113
struct  rxfd
114
 
115
        status          dw ?
116
        command         dw ?
117
        link            dd ?
118
        rx_buf_addr     dd ?
119
        count           dw ?
120
        size            dw ?
121
        packet          rb 1500
122
 
123
ends
124
 
125
struc   txfd {
126
 
127
        .status         dw ?
128
        .command        dw ?
129
        .link           dd ?
130
        .desc_addr      dd ?
131
        .count          dd ?
132
 
133
        .buf_addr0      dd ?
134
        .buf_size0      dd ?
135
 
136
}
137
 
138
struc   confcmd {
139
 
140
        .status         dw ?
141
        .command        dw ?
142
        .link           dd ?
143
        .data           rb 64
144
 
145
}
146
 
147
struc   lstats {
148
 
149
        .tx_good_frames         dd ?
150
        .tx_coll16_errs         dd ?
151
        .tx_late_colls          dd ?
152
        .tx_underruns           dd ?
153
        .tx_lost_carrier        dd ?
154
        .tx_deferred            dd ?
155
        .tx_one_colls           dd ?
156
        .tx_multi_colls         dd ?
157
        .tx_total_colls         dd ?
158
 
159
        .rx_good_frames         dd ?
160
        .rx_crc_errs            dd ?
161
        .rx_align_errs          dd ?
162
        .rx_resource_errs       dd ?
163
        .rx_overrun_errs        dd ?
164
        .rx_colls_errs          dd ?
165
        .rx_runt_errs           dd ?
166
 
167
}
168
 
169
struct  device          ETH_DEVICE
170
 
171
        io_addr         dd ?
172
        pci_bus         dd ?
173
        pci_dev         dd ?
174
        rx_desc         dd ?
175
        last_tx_buffer  dd ?
176
        ee_bus_width    db ?
177
        irq_line        db ?
178
 
179
        rb 0x100 - ($ and 0xff) ; align 256
180
        txfd            txfd
181
 
182
        rb 0x100 - ($ and 0xff) ; align 256
183
        confcmd         confcmd
184
 
185
        rb 0x100 - ($ and 0xff) ; align 256
186
        lstats          lstats
187
 
188
ends
189
 
3545 hidnplayr 190
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
191
;;                        ;;
192
;; proc START             ;;
193
;;                        ;;
194
;; (standard driver proc) ;;
195
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
196
 
4581 hidnplayr 197
proc START c, state:dword
3545 hidnplayr 198
 
199
        cmp [state], 1
200
        jne .exit
201
 
202
  .entry:
203
 
3845 hidnplayr 204
        DEBUGF 1,"Loading driver\n"
4581 hidnplayr 205
        invoke  RegService, my_service, service_proc
3545 hidnplayr 206
        ret
207
 
208
  .fail:
209
  .exit:
210
        xor eax, eax
211
        ret
212
 
213
endp
214
 
215
 
216
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
217
;;                        ;;
218
;; proc SERVICE_PROC      ;;
219
;;                        ;;
220
;; (standard driver proc) ;;
221
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
222
 
223
align 4
224
proc service_proc stdcall, ioctl:dword
225
 
226
        mov     edx, [ioctl]
4470 hidnplayr 227
        mov     eax, [edx + IOCTL.io_code]
3545 hidnplayr 228
 
229
;------------------------------------------------------
230
 
231
        cmp     eax, 0 ;SRV_GETVERSION
232
        jne     @F
233
 
4470 hidnplayr 234
        cmp     [edx + IOCTL.out_size], 4
3545 hidnplayr 235
        jb      .fail
4470 hidnplayr 236
        mov     eax, [edx + IOCTL.output]
3545 hidnplayr 237
        mov     [eax], dword API_VERSION
238
 
239
        xor     eax, eax
240
        ret
241
 
242
;------------------------------------------------------
243
  @@:
244
        cmp     eax, 1 ;SRV_HOOK
245
        jne     .fail
246
 
4470 hidnplayr 247
        cmp     [edx + IOCTL.inp_size], 3               ; Data input must be at least 3 bytes
3545 hidnplayr 248
        jb      .fail
249
 
4470 hidnplayr 250
        mov     eax, [edx + IOCTL.input]
3545 hidnplayr 251
        cmp     byte [eax], 1                           ; 1 means device number and bus number (pci) are given
252
        jne     .fail                                   ; other types arent supported for this card yet
253
 
254
; check if the device is already listed
255
 
256
        mov     esi, device_list
257
        mov     ecx, [devices]
258
        test    ecx, ecx
259
        jz      .firstdevice
260
 
4470 hidnplayr 261
;        mov     eax, [edx + IOCTL.input]                ; get the pci bus and device numbers
3545 hidnplayr 262
        mov     ax , [eax+1]                            ;
263
  .nextdevice:
264
        mov     ebx, [esi]
4581 hidnplayr 265
        cmp     al, byte[ebx + device.pci_bus]
3545 hidnplayr 266
        jne     @f
4581 hidnplayr 267
        cmp     ah, byte[ebx + device.pci_dev]
3545 hidnplayr 268
        je      .find_devicenum                         ; Device is already loaded, let's find it's device number
269
       @@:
270
        add     esi, 4
271
        loop    .nextdevice
272
 
273
 
274
; This device doesnt have its own eth_device structure yet, lets create one
275
  .firstdevice:
276
        cmp     [devices], MAX_DEVICES                  ; First check if the driver can handle one more card
277
        jae     .fail
278
 
4581 hidnplayr 279
        allocate_and_clear ebx, sizeof.device, .fail      ; Allocate the buffer for device structure
3545 hidnplayr 280
 
281
; Fill in the direct call addresses into the struct
282
 
4581 hidnplayr 283
        mov     [ebx + device.reset], reset
284
        mov     [ebx + device.transmit], transmit
285
        mov     [ebx + device.unload], unload
286
        mov     [ebx + device.name], my_service
3545 hidnplayr 287
 
288
; save the pci bus and device numbers
289
 
4470 hidnplayr 290
        mov     eax, [edx + IOCTL.input]
3545 hidnplayr 291
        movzx   ecx, byte[eax+1]
4581 hidnplayr 292
        mov     [ebx + device.pci_bus], ecx
3545 hidnplayr 293
        movzx   ecx, byte[eax+2]
4581 hidnplayr 294
        mov     [ebx + device.pci_dev], ecx
3545 hidnplayr 295
 
296
; Now, it's time to find the base io addres of the PCI device
297
 
4581 hidnplayr 298
        stdcall PCI_find_io, [ebx + device.pci_bus], [ebx + device.pci_dev]
299
        mov     [ebx + device.io_addr], eax
3545 hidnplayr 300
 
301
; We've found the io address, find IRQ now
302
 
4581 hidnplayr 303
        invoke  PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.interrupt_line
304
        mov     [ebx + device.irq_line], al
3545 hidnplayr 305
 
3845 hidnplayr 306
        DEBUGF  1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
4581 hidnplayr 307
        [ebx + device.pci_dev]:1,[ebx + device.pci_bus]:1,[ebx + device.irq_line]:1,[ebx + device.io_addr]:4
3545 hidnplayr 308
 
309
; Ok, the eth_device structure is ready, let's probe the device
310
 
311
        pushf
4581 hidnplayr 312
        cli                     ; disable ints untilm initialisation is done
3545 hidnplayr 313
 
314
        call    probe                                                   ; this function will output in eax
315
        test    eax, eax
316
        jnz     .err                                                    ; If an error occured, exit
317
 
318
        mov     eax, [devices]                                          ; Add the device structure to our device list
319
        mov     [device_list+4*eax], ebx                                ; (IRQ handler uses this list to find device)
320
        inc     [devices]                                               ;
321
 
322
        popf
323
 
4581 hidnplayr 324
        mov     [ebx + device.type], NET_TYPE_ETH
325
        invoke  NetRegDev
3545 hidnplayr 326
 
327
        cmp     eax, -1
328
        je      .err
329
 
330
        ret
331
 
332
; If the device was already loaded, find the device number and return it in eax
333
 
334
  .find_devicenum:
335
        DEBUGF  2,"Trying to find device number of already registered device\n"
4581 hidnplayr 336
        invoke  NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
3545 hidnplayr 337
                                                                        ; into a device number in edi
338
        mov     eax, edi                                                ; Application wants it in eax instead
339
        DEBUGF  2,"Kernel says: %u\n", eax
340
        ret
341
 
342
; If an error occured, remove all allocated data and exit (returning -1 in eax)
343
 
344
  .err:
4581 hidnplayr 345
        invoke  KernelFree, ebx
3545 hidnplayr 346
 
347
  .fail:
348
        or      eax, -1
349
        ret
350
 
351
;------------------------------------------------------
352
endp
353
 
354
 
355
 
356
 
357
 
358
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
359
;;                                                                        ;;
360
;;        Actual Hardware dependent code starts here                      ;;
361
;;                                                                        ;;
362
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
363
 
364
 
365
unload:
366
        ; TODO: (in this particular order)
367
        ;
368
        ; - Stop the device
369
        ; - Detach int handler
370
        ; - Remove device from local list (device_list)
371
        ; - call unregister function in kernel
372
        ; - Remove all allocated structures and buffers the card used
373
 
374
        or      eax,-1
375
 
376
ret
377
 
378
 
379
;-------------
380
;
381
; Probe
382
;
383
;-------------
384
 
385
align 4
386
probe:
387
 
3845 hidnplayr 388
        DEBUGF  1,"Probing\n"
3545 hidnplayr 389
 
4581 hidnplayr 390
; Make the device a bus master
391
        invoke  PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command
392
        or      al, PCI_CMD_MASTER
393
        invoke  PciWrite32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command, eax
3545 hidnplayr 394
 
395
;---------------------------
396
; First, identify the device
397
 
4581 hidnplayr 398
        invoke  PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header.vendor_id ; get device/vendor id
3545 hidnplayr 399
 
400
        DEBUGF  1,"Vendor_id=0x%x\n", ax
401
 
402
        cmp     ax, 0x8086
403
        jne     .notfound
404
        shr     eax, 16
405
 
406
        DEBUGF  1,"Device_id=0x%x\n", ax
407
 
408
        mov     ecx, DEVICE_IDs
409
        mov     edi, device_id_list
410
        repne   scasw
411
        jne     .notfound
412
        jmp     .found
413
 
414
  .notfound:
3845 hidnplayr 415
        DEBUGF  2,"Unsupported device!\n"
3545 hidnplayr 416
        or      eax, -1
417
        ret
418
 
419
  .found:
420
 
421
        call    ee_get_width
422
        call    MAC_read_eeprom
423
 
424
        ;;; TODO: detect phy
425
 
426
 
427
 
428
;----------
429
;
430
;  Reset
431
;
432
;----------
433
 
434
align 4
435
reset:
436
 
4581 hidnplayr 437
        movzx   eax, [ebx + device.irq_line]
3545 hidnplayr 438
        DEBUGF  1,"Attaching int handler to irq %x\n", eax:1
4581 hidnplayr 439
        invoke  AttachIntHandler, eax, int_handler, ebx
3545 hidnplayr 440
        test    eax, eax
441
        jnz     @f
3845 hidnplayr 442
        DEBUGF  2,"Could not attach int handler!\n"
4581 hidnplayr 443
        or      eax, -1
444
        ret
3545 hidnplayr 445
  @@:
446
 
3845 hidnplayr 447
        DEBUGF  1,"Resetting\n"
3545 hidnplayr 448
 
449
;---------------
450
; reset the card
451
 
4581 hidnplayr 452
        set_io  [ebx + device.io_addr], 0
453
        set_io  [ebx + device.io_addr], reg_port
3545 hidnplayr 454
        xor     eax, eax        ; Software Reset
455
        out     dx, eax
456
 
457
        mov     esi, 10
4581 hidnplayr 458
        invoke  Sleep           ; Give the card time to warm up.
3545 hidnplayr 459
 
460
;---------------------------------
461
; Tell device where to store stats
462
 
4581 hidnplayr 463
        lea     eax, [ebx + device.lstats.tx_good_frames]      ; lstats
464
        invoke  GetPhysAddr
465
        set_io  [ebx + device.io_addr], 0
466
        set_io  [ebx + device.io_addr], reg_scb_ptr
3545 hidnplayr 467
        out     dx, eax
468
 
469
        mov     ax, INT_MASK + CU_STATSADDR
4581 hidnplayr 470
        set_io  [ebx + device.io_addr], reg_scb_cmd
3545 hidnplayr 471
        out     dx, ax
472
        call    cmd_wait
473
 
474
;-----------------
475
; setup RX
476
 
4581 hidnplayr 477
        set_io  [ebx + device.io_addr], reg_scb_ptr
3545 hidnplayr 478
        xor     eax, eax
479
        out     dx, eax
480
 
4581 hidnplayr 481
        set_io  [ebx + device.io_addr], reg_scb_cmd
3545 hidnplayr 482
        mov     ax, INT_MASK + RX_ADDR_LOAD
483
        out     dx, ax
484
        call    cmd_wait
485
 
486
;-----------------------------
487
; Create RX and TX descriptors
488
 
489
        call    create_ring
490
 
491
; RX start
492
 
4581 hidnplayr 493
        set_io  [ebx + device.io_addr], 0
494
        set_io  [ebx + device.io_addr], reg_scb_ptr
495
        mov     eax, [ebx + device.rx_desc]
496
        invoke  GetPhysAddr
3545 hidnplayr 497
        out     dx, eax
498
 
499
        mov     ax, INT_MASK + RX_START
4581 hidnplayr 500
        set_io  [ebx + device.io_addr], reg_scb_cmd
3545 hidnplayr 501
        out     dx, ax
502
        call    cmd_wait
503
 
504
; Set-up TX
505
 
4581 hidnplayr 506
        set_io  [ebx + device.io_addr], reg_scb_ptr
3545 hidnplayr 507
        xor     eax, eax
508
        out     dx, eax
509
 
4581 hidnplayr 510
        set_io  [ebx + device.io_addr], reg_scb_cmd
3545 hidnplayr 511
        mov     ax, INT_MASK + CU_CMD_BASE
512
        out     dx, ax
513
        call    cmd_wait
514
 
515
;  --------------------
516
 
4581 hidnplayr 517
        mov     [ebx + device.confcmd.command], CmdConfigure + Cmdsuspend
518
        mov     [ebx + device.confcmd.status], 0
519
        lea     eax, [ebx + device.txfd.status]
520
        invoke  GetPhysAddr
521
        mov     [ebx + device.confcmd.link], eax
3545 hidnplayr 522
 
523
        mov     esi, confcmd_data
4581 hidnplayr 524
        lea     edi, [ebx + device.confcmd.data]
3545 hidnplayr 525
        mov     ecx, 22
526
        rep     movsb
527
 
4581 hidnplayr 528
        mov     byte[ebx + device.confcmd.data + 1], 0x88  ; fifo of 8 each
529
        mov     byte[ebx + device.confcmd.data + 4], 0
530
        mov     byte[ebx + device.confcmd.data + 5], 0x80
531
        mov     byte[ebx + device.confcmd.data + 15], 0x48
532
        mov     byte[ebx + device.confcmd.data + 19], 0x80
533
        mov     byte[ebx + device.confcmd.data + 21], 0x05
3545 hidnplayr 534
 
4581 hidnplayr 535
        mov     [ebx + device.txfd.command], CmdIASetup
536
        mov     [ebx + device.txfd.status], 0
537
        lea     eax, [ebx + device.confcmd.status]
538
        invoke  GetPhysAddr
539
        mov     [ebx + device.txfd.link], eax
3545 hidnplayr 540
 
541
;;; copy in our MAC
542
 
4581 hidnplayr 543
        lea     edi, [ebx + device.txfd.desc_addr]
544
        lea     esi, [ebx + device.mac]
3545 hidnplayr 545
        movsd
546
        movsw
547
 
4581 hidnplayr 548
        set_io  [ebx + device.io_addr], reg_scb_ptr
549
        lea     eax, [ebx + device.txfd.status]
550
        invoke  GetPhysAddr
3545 hidnplayr 551
        out     dx, eax
552
 
553
; Start CU & enable ints
554
 
4581 hidnplayr 555
        set_io  [ebx + device.io_addr], reg_scb_cmd
3545 hidnplayr 556
        mov     ax, CU_START
557
        out     dx, ax
558
        call    cmd_wait
559
 
560
;-----------------------
561
; build txfd structure (again!)
562
 
4581 hidnplayr 563
        lea     eax, [ebx + device.txfd.status]
564
        invoke  GetPhysAddr
565
        mov     [ebx + device.txfd.link], eax
566
        mov     [ebx + device.txfd.count], 0x02208000
567
        lea     eax, [ebx + device.txfd.buf_addr0]
568
        invoke  GetPhysAddr
569
        mov     [ebx + device.txfd.desc_addr], eax
3545 hidnplayr 570
 
571
; Indicate that we have successfully reset the card
572
 
3845 hidnplayr 573
        DEBUGF  1,"Reset complete\n"
3545 hidnplayr 574
 
4581 hidnplayr 575
        mov     [ebx + device.mtu], 1514
3545 hidnplayr 576
 
577
; Set link state to unknown
4581 hidnplayr 578
        mov     [ebx + device.state], ETH_LINK_UNKNOWN
3545 hidnplayr 579
 
580
        xor     eax, eax        ; indicate that we have successfully reset the card
581
        ret
582
 
583
 
584
align 4
585
create_ring:
586
 
587
        DEBUGF  1,"Creating ring\n"
588
 
589
;---------------------
590
; build rxfd structure
591
 
4581 hidnplayr 592
        invoke  KernelAlloc, 2000
593
        mov     [ebx + device.rx_desc], eax
3545 hidnplayr 594
        mov     esi, eax
4581 hidnplayr 595
        invoke  GetPhysAddr
3545 hidnplayr 596
        mov     [esi + rxfd.status], 0x0000
597
        mov     [esi + rxfd.command], 0x0000
598
        mov     [esi + rxfd.link], eax
599
        mov     [esi + rxfd.count], 0
600
        mov     [esi + rxfd.size], 1528
601
 
602
;-----------------------
603
; build txfd structure
604
 
4581 hidnplayr 605
        lea     eax, [ebx + device.txfd.status]
606
        invoke  GetPhysAddr
607
        mov     [ebx + device.txfd.link], eax
5194 hidnplayr 608
        mov     [ebx + device.txfd.count], 0x01208000
4581 hidnplayr 609
        lea     eax, [ebx + device.txfd.buf_addr0]
610
        invoke  GetPhysAddr
611
        mov     [ebx + device.txfd.desc_addr], eax
3545 hidnplayr 612
 
613
        ret
614
 
615
 
616
 
617
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
618
;;                                         ;;
619
;; Transmit                                ;;
620
;;                                         ;;
4581 hidnplayr 621
;; In: pointer to device structure in ebx  ;;
3545 hidnplayr 622
;;                                         ;;
623
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
624
 
4581 hidnplayr 625
proc transmit stdcall bufferptr, buffersize
3545 hidnplayr 626
 
4581 hidnplayr 627
        pushf
628
        cli
629
 
630
        DEBUGF  1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [buffersize]
631
        mov     eax, [bufferptr]
3545 hidnplayr 632
        DEBUGF  1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
633
        [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
634
        [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
635
        [eax+13]:2,[eax+12]:2
636
 
4581 hidnplayr 637
        cmp     [buffersize], 1514
638
        ja      .fail
639
        cmp     [buffersize], 60
640
        jb      .fail
3545 hidnplayr 641
 
642
        ;;; TODO: check if current descriptor is in use
643
        ; fill in buffer address and size
4581 hidnplayr 644
        mov     [ebx + device.last_tx_buffer], eax
645
        invoke  GetPhysAddr
646
        mov     [ebx + device.txfd.buf_addr0], eax
647
        mov     ecx, [buffersize]
648
        mov     [ebx + device.txfd.buf_size0], ecx
3545 hidnplayr 649
 
4581 hidnplayr 650
        mov     [ebx + device.txfd.status], 0
651
        mov     [ebx + device.txfd.command], Cmdsuspend + CmdTx + CmdTxFlex + 1 shl 15 ;;; EL bit
3545 hidnplayr 652
 ;       mov     [txfd.count], 0x02208000   ;;;;;;;;;;;
653
 
654
        ; Inform device of the new/updated transmit descriptor
4581 hidnplayr 655
        lea     eax, [ebx + device.txfd.status]
656
        invoke  GetPhysAddr
657
        set_io  [ebx + device.io_addr], 0
658
        set_io  [ebx + device.io_addr], reg_scb_ptr
3545 hidnplayr 659
        out     dx, eax
660
 
661
        ; Start the transmit
662
        mov     ax, CU_START
4581 hidnplayr 663
        set_io  [ebx + device.io_addr], reg_scb_cmd
3545 hidnplayr 664
        out     dx, ax
665
        call    cmd_wait
666
 
667
; Update stats
4581 hidnplayr 668
        inc     [ebx + device.packets_tx]
669
        mov     ecx, [buffersize]
670
        add     dword[ebx + device.bytes_tx], ecx
671
        adc     dword[ebx + device.bytes_tx + 4], 0
3545 hidnplayr 672
 
673
        DEBUGF  1,"Transmit OK\n"
4581 hidnplayr 674
        popf
3545 hidnplayr 675
        xor     eax, eax
4581 hidnplayr 676
        ret
3545 hidnplayr 677
 
4581 hidnplayr 678
  .fail:
679
        invoke  KernelFree, [bufferptr]
680
        popf
3545 hidnplayr 681
        or      eax, -1
4581 hidnplayr 682
        ret
3545 hidnplayr 683
 
4581 hidnplayr 684
endp
685
 
686
 
3545 hidnplayr 687
;;;;;;;;;;;;;;;;;;;;;;;
688
;;                   ;;
689
;; Interrupt handler ;;
690
;;                   ;;
691
;;;;;;;;;;;;;;;;;;;;;;;
692
 
693
align 4
694
int_handler:
695
 
696
        push    ebx esi edi
697
 
3845 hidnplayr 698
        DEBUGF  1,"INT\n"
3545 hidnplayr 699
 
700
; find pointer of device wich made IRQ occur
701
 
702
        mov     ecx, [devices]
703
        test    ecx, ecx
704
        jz      .nothing
705
        mov     esi, device_list
706
  .nextdevice:
707
        mov     ebx, [esi]
708
 
4581 hidnplayr 709
;        set_io  [ebx + device.io_addr], 0              ; reg_scb_status = 0
710
        set_io  [ebx + device.io_addr], reg_scb_status
3545 hidnplayr 711
        in      ax, dx
712
        out     dx, ax                              ; send it back to ACK
713
        test    ax, ax
714
        jnz     .got_it
715
  .continue:
716
        add     esi, 4
717
        dec     ecx
718
        jnz     .nextdevice
719
  .nothing:
720
        pop     edi esi ebx
721
        xor     eax, eax
722
 
723
        ret                                         ; If no device was found, abort (The irq was probably for a device, not registered to this driver)
724
 
725
  .got_it:
726
 
727
        DEBUGF  1,"Device: %x Status: %x\n", ebx, ax
728
 
729
        test    ax, 1 shl 14    ; did we receive a frame?
730
        jz      .no_rx
731
 
732
        push    ax
733
 
734
        DEBUGF  1,"Receiving\n"
735
 
736
        push    ebx
737
  .rx_loop:
738
        pop     ebx
739
 
4581 hidnplayr 740
        mov     esi, [ebx + device.rx_desc]
3545 hidnplayr 741
        cmp     [esi + rxfd.status], 0        ; we could also check bits C and OK (bit 15 and 13)
742
        je      .nodata
743
 
744
        DEBUGF  1,"rxfd status=0x%x\n", [esi + rxfd.status]:4
745
 
746
        movzx   ecx, [esi + rxfd.count]
747
        and     ecx, 0x3fff
748
 
749
        push    ebx
750
        push    .rx_loop
751
        push    ecx
752
        add     esi, rxfd.packet
753
        push    esi
754
 
755
; Update stats
4581 hidnplayr 756
        add     dword [ebx + device.bytes_rx], ecx
757
        adc     dword [ebx + device.bytes_rx + 4], 0
758
        inc     dword [ebx + device.packets_rx]
3545 hidnplayr 759
 
760
; allocate new descriptor
761
 
4581 hidnplayr 762
        invoke  KernelAlloc, 2000
763
        mov     [ebx + device.rx_desc], eax
3545 hidnplayr 764
        mov     esi, eax
4581 hidnplayr 765
        invoke  GetPhysAddr
3545 hidnplayr 766
        mov     [esi + rxfd.status], 0x0000
767
        mov     [esi + rxfd.command], 0xc000    ; End of list + Suspend
768
        mov     [esi + rxfd.link], eax
769
        mov     [esi + rxfd.count], 0
770
        mov     [esi + rxfd.size], 1528
771
 
772
; restart RX
773
 
4581 hidnplayr 774
        set_io  [ebx + device.io_addr], 0
775
        set_io  [ebx + device.io_addr], reg_scb_ptr
776
;        lea     eax, [ebx + device.rx_desc]
777
;        invoke  GetPhysAddr
3545 hidnplayr 778
        out     dx, eax
779
 
4581 hidnplayr 780
        set_io  [ebx + device.io_addr], reg_scb_cmd
3545 hidnplayr 781
        mov     ax, RX_START
782
        out     dx, ax
783
        call    cmd_wait
784
 
785
; And give packet to kernel
4581 hidnplayr 786
        jmp     [Eth_input]
3545 hidnplayr 787
 
788
  .nodata:
789
        DEBUGF  1, "no more data\n"
790
        pop     ax
791
 
792
  .no_rx:
793
 
794
; Cleanup after TX
4581 hidnplayr 795
        cmp     [ebx + device.txfd.status], 0
3545 hidnplayr 796
        je      .done
4581 hidnplayr 797
        cmp     [ebx + device.last_tx_buffer], 0
3545 hidnplayr 798
        je      .done
799
        push    ax
4581 hidnplayr 800
        DEBUGF  1, "Removing packet 0x%x from RAM!\n", [ebx + device.last_tx_buffer]
801
        invoke  KernelFree, [ebx + device.last_tx_buffer]
802
        mov     [ebx + device.last_tx_buffer], 0
3545 hidnplayr 803
        pop     ax
804
 
805
  .done:
806
        and     ax, 00111100b
807
        cmp     ax, 00001000b
808
        jne     .fail
809
 
810
        DEBUGF  1, "out of resources!\n"
811
; Restart the RX
812
 
813
; allocate new descriptor
814
 
4581 hidnplayr 815
        invoke  KernelAlloc, 2000
816
        mov     [ebx + device.rx_desc], eax
3545 hidnplayr 817
        mov     esi, eax
4581 hidnplayr 818
        invoke  GetPhysAddr
3545 hidnplayr 819
        mov     [esi + rxfd.status], 0x0000
820
        mov     [esi + rxfd.command], 0xc000    ; End of list + Suspend
821
        mov     [esi + rxfd.link], eax
822
        mov     [esi + rxfd.count], 0
823
        mov     [esi + rxfd.size], 1528
824
 
825
; restart RX
826
 
4581 hidnplayr 827
        set_io  [ebx + device.io_addr], 0
828
        set_io  [ebx + device.io_addr], reg_scb_ptr
829
;        lea     eax, [ebx + device.rx_desc]
830
;        invoke  GetPhysAddr
3545 hidnplayr 831
        out     dx, eax
832
 
4581 hidnplayr 833
        set_io  [ebx + device.io_addr], reg_scb_cmd
3545 hidnplayr 834
        mov     ax, RX_START
835
        out     dx, ax
836
        call    cmd_wait
837
 
838
  .fail:
839
        pop     edi esi ebx
840
        xor     eax, eax
841
        inc     eax
842
 
843
        ret
844
 
845
 
846
 
847
 
848
align 4
849
cmd_wait:
850
 
851
        in      al, dx
852
        test    al, al
853
        jnz     cmd_wait
854
 
855
        ret
856
 
857
 
858
 
859
 
860
 
861
 
862
align 4
863
ee_read:        ; esi = address to read
864
 
3845 hidnplayr 865
        DEBUGF  1,"Eeprom read from 0x%x\n", esi
3545 hidnplayr 866
 
4581 hidnplayr 867
        set_io  [ebx + device.io_addr], 0
868
        set_io  [ebx + device.io_addr], reg_eeprom
3545 hidnplayr 869
 
870
;-----------------------------------------------------
871
; Prepend start bit + read opcode to the address field
872
; and shift it to the very left bits of esi
873
 
874
        mov     cl, 29
4581 hidnplayr 875
        sub     cl, [ebx + device.ee_bus_width]
3545 hidnplayr 876
        shl     esi, cl
877
        or      esi, EE_READ shl 29
878
 
4581 hidnplayr 879
        movzx   ecx, [ebx + device.ee_bus_width]
3545 hidnplayr 880
        add     ecx, 3
881
 
882
        mov     al, EE_CS
883
        out     dx, al
5247 hidnplayr 884
        call    udelay
3545 hidnplayr 885
 
886
;-----------------------
887
; Write this to the chip
888
 
889
  .loop:
890
        mov     al, EE_CS + EE_SK
891
        shl     esi, 1
892
        jnc     @f
893
        or      al, EE_DI
894
       @@:
895
        out     dx, al
5247 hidnplayr 896
        call    udelay
3545 hidnplayr 897
 
898
        and     al, not EE_SK
899
        out     dx, al
5247 hidnplayr 900
        call    udelay
3545 hidnplayr 901
 
902
        loop    .loop
903
 
904
;------------------------------
905
; Now read the data from eeprom
906
 
907
        xor     esi, esi
908
        mov     ecx, 16
909
 
910
  .loop2:
911
        shl     esi, 1
912
        mov     al, EE_CS + EE_SK
913
        out     dx, al
5247 hidnplayr 914
        call    udelay
3545 hidnplayr 915
 
916
        in      al, dx
917
        test    al, EE_DO
918
        jz      @f
919
        inc     esi
920
       @@:
921
 
922
        mov     al, EE_CS
923
        out     dx, al
5247 hidnplayr 924
        call    udelay
3545 hidnplayr 925
 
926
        loop    .loop2
927
 
928
;-----------------------
929
; de-activate the eeprom
930
 
931
        xor     ax, ax
932
        out     dx, ax
933
 
934
 
3845 hidnplayr 935
        DEBUGF  1,"0x%x\n", esi:4
3545 hidnplayr 936
        ret
937
 
938
 
939
 
940
align 4
941
ee_write:       ; esi = address to write to, di = data
942
 
943
        DEBUGF  1,"Eeprom write 0x%x to 0x%x\n", di, esi
944
 
4581 hidnplayr 945
        set_io  [ebx + device.io_addr], 0
946
        set_io  [ebx + device.io_addr], reg_eeprom
3545 hidnplayr 947
 
948
;-----------------------------------------------------
949
; Prepend start bit + write opcode to the address field
950
; and shift it to the very left bits of esi
951
 
952
        mov     cl, 29
4581 hidnplayr 953
        sub     cl, [ebx + device.ee_bus_width]
3545 hidnplayr 954
        shl     esi, cl
955
        or      esi, EE_WRITE shl 29
956
 
4581 hidnplayr 957
        movzx   ecx, [ebx + device.ee_bus_width]
3545 hidnplayr 958
        add     ecx, 3
959
 
960
        mov     al, EE_CS       ; enable chip
961
        out     dx, al
962
 
963
;-----------------------
964
; Write this to the chip
965
 
966
  .loop:
967
        mov     al, EE_CS + EE_SK
968
        shl     esi, 1
969
        jnc     @f
970
        or      al, EE_DI
971
       @@:
972
        out     dx, al
5247 hidnplayr 973
        call    udelay
3545 hidnplayr 974
 
975
        and     al, not EE_SK
976
        out     dx, al
5247 hidnplayr 977
        call    udelay
3545 hidnplayr 978
 
979
        loop    .loop
980
 
981
;-----------------------------
982
; Now write the data to eeprom
983
 
984
        mov     ecx, 16
985
 
986
  .loop2:
987
        mov     al, EE_CS + EE_SK
988
        shl     di, 1
989
        jnc     @f
990
        or      al, EE_DI
991
       @@:
992
        out     dx, al
5247 hidnplayr 993
        call    udelay
3545 hidnplayr 994
 
995
        and     al, not EE_SK
996
        out     dx, al
5247 hidnplayr 997
        call    udelay
3545 hidnplayr 998
 
999
        loop    .loop2
1000
 
1001
;-----------------------
1002
; de-activate the eeprom
1003
 
1004
        xor     al, al
1005
        out     dx, al
1006
 
1007
 
1008
        ret
1009
 
1010
 
1011
 
1012
align 4
1013
ee_get_width:
1014
 
4581 hidnplayr 1015
        set_io  [ebx + device.io_addr], 0
1016
        set_io  [ebx + device.io_addr], reg_eeprom
3545 hidnplayr 1017
 
1018
        mov     al, EE_CS      ; activate eeprom
1019
        out     dx, al
5247 hidnplayr 1020
        call    udelay
3545 hidnplayr 1021
 
1022
        mov     si, EE_READ shl 13
1023
        xor     ecx, ecx
1024
  .loop:
1025
        mov     al, EE_CS + EE_SK
1026
        shl     si, 1
1027
        jnc     @f
1028
        or      al, EE_DI
1029
       @@:
1030
        out     dx, al
5247 hidnplayr 1031
        call    udelay
3545 hidnplayr 1032
 
1033
        and     al, not EE_SK
1034
        out     dx, al
5247 hidnplayr 1035
        call    udelay
3545 hidnplayr 1036
 
1037
        inc     ecx
1038
 
1039
        cmp     ecx, 15
1040
        jae     .give_up
1041
 
1042
        in      al, dx
1043
        test    al, EE_DO
1044
        jnz     .loop
1045
 
1046
        xor     al, al
1047
        out     dx, al          ; de-activate eeprom
1048
 
1049
        sub     cl, 3           ; dont count the opcode bits
4581 hidnplayr 1050
        mov     [ebx + device.ee_bus_width], cl
3845 hidnplayr 1051
        DEBUGF  1, "Eeprom width=%u bit\n", ecx
3545 hidnplayr 1052
 
3845 hidnplayr 1053
        ret
3545 hidnplayr 1054
 
3845 hidnplayr 1055
  .give_up:
1056
        DEBUGF  2, "Eeprom not found!\n"
3545 hidnplayr 1057
 
3845 hidnplayr 1058
        xor     al, al
1059
        out     dx, al          ; de-activate eeprom
3545 hidnplayr 1060
 
1061
        ret
1062
 
1063
 
5247 hidnplayr 1064
; Wait a minimum of 2µs
1065
udelay:
1066
        pusha
1067
        mov     esi, 1
1068
        invoke  Sleep
1069
        popa
3545 hidnplayr 1070
 
5247 hidnplayr 1071
        ret
1072
 
1073
 
1074
 
3545 hidnplayr 1075
; cx = phy addr
1076
; dx = phy reg addr
1077
 
1078
; ax = data
1079
 
1080
align 4
1081
mdio_read:
1082
 
1083
        DEBUGF  1,"MDIO read\n"
1084
 
1085
        shl     ecx, 21                 ; PHY addr
1086
        shl     edx, 16                 ; PHY reg addr
1087
 
1088
        mov     eax, ecx
1089
        or      eax, edx
1090
        or      eax, 10b shl 26         ; read opcode
1091
 
4581 hidnplayr 1092
        set_io  [ebx + device.io_addr], 0
1093
        set_io  [ebx + device.io_addr], reg_mdi_ctrl
3545 hidnplayr 1094
        out     dx, eax
1095
 
1096
  .wait:
5247 hidnplayr 1097
        call    udelay
3545 hidnplayr 1098
        in      eax, dx
1099
        test    eax, 1 shl 28           ; ready bit
1100
        jz      .wait
1101
 
1102
        ret
1103
 
1104
; ax = data
1105
; cx = phy addr
1106
; dx = phy reg addr
1107
 
1108
; ax = data
1109
 
1110
align 4
1111
mdio_write:
1112
 
1113
        DEBUGF  1,"MDIO write\n"
1114
 
1115
        and     eax, 0xffff
1116
 
1117
        shl     ecx, 21                 ; PHY addr
1118
        shl     edx, 16                 ; PHY reg addr
1119
 
1120
        or      eax, ecx
1121
        or      eax, edx
1122
        or      eax, 01b shl 26         ; write opcode
1123
 
4581 hidnplayr 1124
        set_io  [ebx + device.io_addr], 0
1125
        set_io  [ebx + device.io_addr], reg_mdi_ctrl
3545 hidnplayr 1126
        out     dx, eax
1127
 
1128
  .wait:
5247 hidnplayr 1129
        call    udelay
3545 hidnplayr 1130
        in      eax, dx
1131
        test    eax, 1 shl 28           ; ready bit
1132
        jz      .wait
1133
 
1134
        ret
1135
 
1136
read_mac:
1137
 
1138
        ret
1139
 
1140
 
1141
 
1142
align 4
1143
MAC_read_eeprom:
1144
 
1145
        mov     esi, 0
1146
        call    ee_read
4581 hidnplayr 1147
        mov     word[ebx + device.mac], si
3545 hidnplayr 1148
 
1149
        mov     esi, 1
1150
        call    ee_read
4581 hidnplayr 1151
        mov     word[ebx + device.mac+2], si
3545 hidnplayr 1152
 
1153
        mov     esi, 2
1154
        call    ee_read
4581 hidnplayr 1155
        mov     word[ebx + device.mac+4], si
3545 hidnplayr 1156
 
1157
 
1158
        ret
1159
 
1160
 
1161
align 4
1162
MAC_write:
1163
 
1164
;;;;
1165
 
1166
        ret
1167
 
1168
 
1169
 
1170
 
1171
; End of code
1172
 
1173
 
4581 hidnplayr 1174
data fixups
1175
end data
1176
 
1177
include '../peimport.inc'
1178
 
4629 hidnplayr 1179
my_service      db 'I8255X', 0                    ; max 16 chars include zero
3545 hidnplayr 1180
devicename      db 'Intel Etherexpress pro/100', 0
1181
 
1182
confcmd_data    db 22, 0x08, 0, 0, 0, 0x80, 0x32, 0x03, 1
1183
                db 0, 0x2e, 0, 0x60, 0, 0xf2, 0x48, 0, 0x40, 0xf2
1184
                db 0x80, 0x3f, 0x05                                     ; 22 bytes total
1185
 
1186
 
1187
device_id_list:
1188
 
1189
        dw 0x1029
1190
        dw 0x1030
1191
        dw 0x1031
1192
        dw 0x1032
1193
        dw 0x1033
1194
        dw 0x1034
1195
        dw 0x1038
1196
        dw 0x1039
1197
        dw 0x103A
1198
        dw 0x103B
1199
        dw 0x103C
1200
        dw 0x103D
1201
        dw 0x103E
1202
        dw 0x1050
1203
        dw 0x1051
1204
        dw 0x1052
1205
        dw 0x1053
1206
        dw 0x1054
1207
        dw 0x1055
1208
        dw 0x1056
1209
        dw 0x1057
1210
        dw 0x1059
1211
        dw 0x1064
1212
        dw 0x1065
1213
        dw 0x1066
1214
        dw 0x1067
1215
        dw 0x1068
1216
        dw 0x1069
1217
        dw 0x106A
1218
        dw 0x106B
1219
        dw 0x1091
1220
        dw 0x1092
1221
        dw 0x1093
1222
        dw 0x1094
1223
        dw 0x1095
1224
        dw 0x10fe
1225
        dw 0x1209
1226
        dw 0x1229
1227
        dw 0x2449
1228
        dw 0x2459
1229
        dw 0x245D
1230
        dw 0x27DC
1231
 
1232
DEVICE_IDs = ($ - device_id_list) / 2
1233
 
1234
include_debug_strings                           ; All data wich FDO uses will be included here
1235
 
4581 hidnplayr 1236
align 4
1237
devices         dd 0                              ; number of currently running devices
1238
device_list     rd MAX_DEVICES                    ; This list contains all pointers to device structures the driver is handling
3545 hidnplayr 1239