Subversion Repositories Kolibri OS

Rev

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