Subversion Repositories Kolibri OS

Rev

Rev 5363 | Rev 5525 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
3545 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
5363 yogev_ezra 3
;; Copyright (C) KolibriOS team 2004-2015. 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
 
4581 hidnplayr 22
format PE DLL native
23
entry START
3545 hidnplayr 24
 
4581 hidnplayr 25
        CURRENT_API             = 0x0200
26
        COMPATIBLE_API          = 0x0100
27
        API_VERSION             = (COMPATIBLE_API shl 16) + CURRENT_API
3545 hidnplayr 28
 
29
        MAX_DEVICES             = 16
30
 
31
        DEBUG                   = 1
32
        __DEBUG__               = 1
4582 hidnplayr 33
        __DEBUG_LEVEL__         = 2             ; 1 = verbose, 2 = errors only
3545 hidnplayr 34
 
4581 hidnplayr 35
section '.flat' readable writable executable
36
 
37
include '../proc32.inc'
4467 hidnplayr 38
include '../struct.inc'
39
include '../macros.inc'
3545 hidnplayr 40
include '../fdo.inc'
5074 hidnplayr 41
include '../netdrv.inc'
3545 hidnplayr 42
 
43
; Serial EEPROM
44
 
45
EE_SK           = 1 shl 0      ; serial clock
46
EE_CS           = 1 shl 1      ; chip select
47
EE_DI           = 1 shl 2      ; data in
48
EE_DO           = 1 shl 3      ; data out
49
EE_MASK         = EE_SK + EE_CS + EE_DI + EE_DO
50
 
51
; opcodes, first bit is start bit and must be 1
52
EE_READ         = 110b
53
EE_WRITE        = 101b
54
EE_ERASE        = 111b
55
 
56
; The SCB accepts the following controls for the Tx and Rx units:
57
 
58
CU_START        = 0x0010
59
CU_RESUME       = 0x0020
60
CU_STATSADDR    = 0x0040
61
CU_SHOWSTATS    = 0x0050        ; Dump statistics counters.
62
CU_CMD_BASE     = 0x0060        ; Base address to add CU commands.
63
CU_DUMPSTATS    = 0x0070        ; Dump then reset stats counters.
64
 
65
RX_START        = 0x0001
66
RX_RESUME       = 0x0002
67
RX_ABORT        = 0x0004
68
RX_ADDR_LOAD    = 0x0006
69
RX_RESUMENR     = 0x0007
70
INT_MASK        = 0x0100
71
DRVR_INT        = 0x0200        ; Driver generated interrupt
72
 
73
CmdIASetup      = 0x0001
74
CmdConfigure    = 0x0002
75
CmdTx           = 0x0004
76
CmdTxFlex       = 0x0008
77
Cmdsuspend      = 0x4000
78
 
5522 hidnplayr 79
CmdRxFlex       = 0x0008
80
 
3545 hidnplayr 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
5522 hidnplayr 490
        test    eax, eax
491
        jz      .error
3545 hidnplayr 492
 
493
; RX start
494
 
4581 hidnplayr 495
        set_io  [ebx + device.io_addr], 0
496
        set_io  [ebx + device.io_addr], reg_scb_ptr
497
        mov     eax, [ebx + device.rx_desc]
498
        invoke  GetPhysAddr
5522 hidnplayr 499
        add     eax, NET_BUFF.data
3545 hidnplayr 500
        out     dx, eax
501
 
502
        mov     ax, INT_MASK + RX_START
4581 hidnplayr 503
        set_io  [ebx + device.io_addr], reg_scb_cmd
3545 hidnplayr 504
        out     dx, ax
505
        call    cmd_wait
506
 
507
; Set-up TX
508
 
4581 hidnplayr 509
        set_io  [ebx + device.io_addr], reg_scb_ptr
3545 hidnplayr 510
        xor     eax, eax
511
        out     dx, eax
512
 
4581 hidnplayr 513
        set_io  [ebx + device.io_addr], reg_scb_cmd
3545 hidnplayr 514
        mov     ax, INT_MASK + CU_CMD_BASE
515
        out     dx, ax
516
        call    cmd_wait
517
 
518
;  --------------------
519
 
4581 hidnplayr 520
        mov     [ebx + device.confcmd.command], CmdConfigure + Cmdsuspend
521
        mov     [ebx + device.confcmd.status], 0
522
        lea     eax, [ebx + device.txfd.status]
523
        invoke  GetPhysAddr
524
        mov     [ebx + device.confcmd.link], eax
3545 hidnplayr 525
 
526
        mov     esi, confcmd_data
4581 hidnplayr 527
        lea     edi, [ebx + device.confcmd.data]
3545 hidnplayr 528
        mov     ecx, 22
529
        rep     movsb
530
 
4581 hidnplayr 531
        mov     byte[ebx + device.confcmd.data + 1], 0x88  ; fifo of 8 each
532
        mov     byte[ebx + device.confcmd.data + 4], 0
533
        mov     byte[ebx + device.confcmd.data + 5], 0x80
534
        mov     byte[ebx + device.confcmd.data + 15], 0x48
535
        mov     byte[ebx + device.confcmd.data + 19], 0x80
536
        mov     byte[ebx + device.confcmd.data + 21], 0x05
3545 hidnplayr 537
 
4581 hidnplayr 538
        mov     [ebx + device.txfd.command], CmdIASetup
539
        mov     [ebx + device.txfd.status], 0
540
        lea     eax, [ebx + device.confcmd.status]
541
        invoke  GetPhysAddr
542
        mov     [ebx + device.txfd.link], eax
3545 hidnplayr 543
 
544
;;; copy in our MAC
545
 
4581 hidnplayr 546
        lea     edi, [ebx + device.txfd.desc_addr]
547
        lea     esi, [ebx + device.mac]
3545 hidnplayr 548
        movsd
549
        movsw
550
 
4581 hidnplayr 551
        set_io  [ebx + device.io_addr], reg_scb_ptr
552
        lea     eax, [ebx + device.txfd.status]
553
        invoke  GetPhysAddr
3545 hidnplayr 554
        out     dx, eax
555
 
556
; Start CU & enable ints
557
 
4581 hidnplayr 558
        set_io  [ebx + device.io_addr], reg_scb_cmd
3545 hidnplayr 559
        mov     ax, CU_START
560
        out     dx, ax
561
        call    cmd_wait
562
 
563
;-----------------------
564
; build txfd structure (again!)
565
 
4581 hidnplayr 566
        lea     eax, [ebx + device.txfd.status]
567
        invoke  GetPhysAddr
568
        mov     [ebx + device.txfd.link], eax
569
        mov     [ebx + device.txfd.count], 0x02208000
570
        lea     eax, [ebx + device.txfd.buf_addr0]
571
        invoke  GetPhysAddr
572
        mov     [ebx + device.txfd.desc_addr], eax
3545 hidnplayr 573
 
574
; Indicate that we have successfully reset the card
575
 
3845 hidnplayr 576
        DEBUGF  1,"Reset complete\n"
3545 hidnplayr 577
 
4581 hidnplayr 578
        mov     [ebx + device.mtu], 1514
3545 hidnplayr 579
 
580
; Set link state to unknown
4581 hidnplayr 581
        mov     [ebx + device.state], ETH_LINK_UNKNOWN
3545 hidnplayr 582
 
583
        xor     eax, eax        ; indicate that we have successfully reset the card
584
        ret
585
 
5522 hidnplayr 586
  .error:
587
        or      eax, -1
588
        ret
3545 hidnplayr 589
 
5522 hidnplayr 590
 
3545 hidnplayr 591
align 4
592
create_ring:
593
 
594
        DEBUGF  1,"Creating ring\n"
595
 
596
;---------------------
597
; build rxfd structure
598
 
5522 hidnplayr 599
        invoke  NetAlloc, 2000
600
        test    eax, eax
601
        jz      .out_of_mem
4581 hidnplayr 602
        mov     [ebx + device.rx_desc], eax
3545 hidnplayr 603
        mov     esi, eax
4581 hidnplayr 604
        invoke  GetPhysAddr
5522 hidnplayr 605
        add     eax, NET_BUFF.data
606
        mov     [esi + sizeof.NET_BUFF + rxfd.status], 0x0000
607
        mov     [esi + sizeof.NET_BUFF + rxfd.command], 0x0000
608
        mov     [esi + sizeof.NET_BUFF + rxfd.link], eax
609
        mov     [esi + sizeof.NET_BUFF + rxfd.count], 0
610
        mov     [esi + sizeof.NET_BUFF + rxfd.size], 1528
3545 hidnplayr 611
 
612
;-----------------------
613
; build txfd structure
614
 
4581 hidnplayr 615
        lea     eax, [ebx + device.txfd.status]
616
        invoke  GetPhysAddr
617
        mov     [ebx + device.txfd.link], eax
5194 hidnplayr 618
        mov     [ebx + device.txfd.count], 0x01208000
4581 hidnplayr 619
        lea     eax, [ebx + device.txfd.buf_addr0]
620
        invoke  GetPhysAddr
621
        mov     [ebx + device.txfd.desc_addr], eax
3545 hidnplayr 622
 
5522 hidnplayr 623
  .out_of_mem:
624
 
3545 hidnplayr 625
        ret
626
 
627
 
628
 
629
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
630
;;                                         ;;
631
;; Transmit                                ;;
632
;;                                         ;;
4581 hidnplayr 633
;; In: pointer to device structure in ebx  ;;
3545 hidnplayr 634
;;                                         ;;
635
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
636
 
5522 hidnplayr 637
proc transmit stdcall bufferptr
3545 hidnplayr 638
 
4581 hidnplayr 639
        pushf
640
        cli
641
 
5522 hidnplayr 642
        mov     esi, [bufferptr]
643
        DEBUGF  1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [esi + NET_BUFF.length]
644
        lea     eax, [esi + NET_BUFF.data]
3545 hidnplayr 645
        DEBUGF  1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
646
        [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
647
        [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
648
        [eax+13]:2,[eax+12]:2
649
 
5522 hidnplayr 650
        cmp     [esi + NET_BUFF.length], 1514
4581 hidnplayr 651
        ja      .fail
5522 hidnplayr 652
        cmp     [esi + NET_BUFF.length], 60
4581 hidnplayr 653
        jb      .fail
3545 hidnplayr 654
 
655
        ;;; TODO: check if current descriptor is in use
656
        ; fill in buffer address and size
5522 hidnplayr 657
        mov     eax, [bufferptr]
4581 hidnplayr 658
        mov     [ebx + device.last_tx_buffer], eax
5522 hidnplayr 659
        add     eax, [eax + NET_BUFF.offset]
4581 hidnplayr 660
        invoke  GetPhysAddr
661
        mov     [ebx + device.txfd.buf_addr0], eax
5522 hidnplayr 662
        mov     ecx, [bufferptr]
663
        mov     ecx, [ecx + NET_BUFF.length]
4581 hidnplayr 664
        mov     [ebx + device.txfd.buf_size0], ecx
3545 hidnplayr 665
 
4581 hidnplayr 666
        mov     [ebx + device.txfd.status], 0
5522 hidnplayr 667
        mov     [ebx + device.txfd.command], Cmdsuspend + CmdTx + CmdTxFlex ;+ 1 shl 15 ;;; EL bit
3545 hidnplayr 668
 ;       mov     [txfd.count], 0x02208000   ;;;;;;;;;;;
669
 
670
        ; Inform device of the new/updated transmit descriptor
4581 hidnplayr 671
        lea     eax, [ebx + device.txfd.status]
672
        invoke  GetPhysAddr
673
        set_io  [ebx + device.io_addr], 0
674
        set_io  [ebx + device.io_addr], reg_scb_ptr
3545 hidnplayr 675
        out     dx, eax
676
 
677
        ; Start the transmit
678
        mov     ax, CU_START
4581 hidnplayr 679
        set_io  [ebx + device.io_addr], reg_scb_cmd
3545 hidnplayr 680
        out     dx, ax
681
        call    cmd_wait
682
 
683
; Update stats
4581 hidnplayr 684
        inc     [ebx + device.packets_tx]
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:
5522 hidnplayr 694
        invoke  NetFree, [bufferptr]
4581 hidnplayr 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]
5522 hidnplayr 756
        cmp     [esi + sizeof.NET_BUFF + rxfd.status], 0        ; we could also check bits C and OK (bit 15 and 13)
3545 hidnplayr 757
        je      .nodata
758
 
5522 hidnplayr 759
        DEBUGF  1,"rxfd status=0x%x\n", [esi + sizeof.NET_BUFF + rxfd.status]:4
3545 hidnplayr 760
 
5522 hidnplayr 761
        movzx   ecx, [esi + sizeof.NET_BUFF + rxfd.count]
3545 hidnplayr 762
        and     ecx, 0x3fff
763
 
764
        push    ebx
765
        push    .rx_loop
766
        push    esi
5522 hidnplayr 767
        mov     [esi + NET_BUFF.length], ecx
768
        mov     [esi + NET_BUFF.device], ebx
769
        mov     [esi + NET_BUFF.offset], NET_BUFF.data + rxfd.packet
3545 hidnplayr 770
 
771
; Update stats
4581 hidnplayr 772
        add     dword [ebx + device.bytes_rx], ecx
773
        adc     dword [ebx + device.bytes_rx + 4], 0
774
        inc     dword [ebx + device.packets_rx]
3545 hidnplayr 775
 
776
; allocate new descriptor
777
 
5522 hidnplayr 778
        invoke  NetAlloc, 2000
4581 hidnplayr 779
        mov     [ebx + device.rx_desc], eax
3545 hidnplayr 780
        mov     esi, eax
4581 hidnplayr 781
        invoke  GetPhysAddr
5522 hidnplayr 782
        add     eax, NET_BUFF.data
783
        mov     [esi + sizeof.NET_BUFF + rxfd.status], 0x0000
784
        mov     [esi + sizeof.NET_BUFF + rxfd.command], 0xc000    ; End of list + Suspend
785
        mov     [esi + sizeof.NET_BUFF + rxfd.link], eax
786
        mov     [esi + sizeof.NET_BUFF + rxfd.count], 0
787
        mov     [esi + sizeof.NET_BUFF + rxfd.size], 1528
3545 hidnplayr 788
 
789
; restart RX
790
 
4581 hidnplayr 791
        set_io  [ebx + device.io_addr], 0
792
        set_io  [ebx + device.io_addr], reg_scb_ptr
793
;        lea     eax, [ebx + device.rx_desc]
794
;        invoke  GetPhysAddr
3545 hidnplayr 795
        out     dx, eax
796
 
4581 hidnplayr 797
        set_io  [ebx + device.io_addr], reg_scb_cmd
3545 hidnplayr 798
        mov     ax, RX_START
799
        out     dx, ax
800
        call    cmd_wait
801
 
802
; And give packet to kernel
5522 hidnplayr 803
        jmp     [EthInput]
3545 hidnplayr 804
 
805
  .nodata:
806
        DEBUGF  1, "no more data\n"
807
        pop     ax
808
 
809
  .no_rx:
810
 
811
; Cleanup after TX
4581 hidnplayr 812
        cmp     [ebx + device.txfd.status], 0
3545 hidnplayr 813
        je      .done
4581 hidnplayr 814
        cmp     [ebx + device.last_tx_buffer], 0
3545 hidnplayr 815
        je      .done
816
        push    ax
4581 hidnplayr 817
        DEBUGF  1, "Removing packet 0x%x from RAM!\n", [ebx + device.last_tx_buffer]
818
        invoke  KernelFree, [ebx + device.last_tx_buffer]
819
        mov     [ebx + device.last_tx_buffer], 0
3545 hidnplayr 820
        pop     ax
821
 
822
  .done:
823
        and     ax, 00111100b
824
        cmp     ax, 00001000b
825
        jne     .fail
826
 
827
        DEBUGF  1, "out of resources!\n"
828
; Restart the RX
829
 
830
; allocate new descriptor
831
 
4581 hidnplayr 832
        invoke  KernelAlloc, 2000
833
        mov     [ebx + device.rx_desc], eax
3545 hidnplayr 834
        mov     esi, eax
4581 hidnplayr 835
        invoke  GetPhysAddr
3545 hidnplayr 836
        mov     [esi + rxfd.status], 0x0000
837
        mov     [esi + rxfd.command], 0xc000    ; End of list + Suspend
838
        mov     [esi + rxfd.link], eax
839
        mov     [esi + rxfd.count], 0
840
        mov     [esi + rxfd.size], 1528
841
 
842
; restart RX
843
 
4581 hidnplayr 844
        set_io  [ebx + device.io_addr], 0
845
        set_io  [ebx + device.io_addr], reg_scb_ptr
846
;        lea     eax, [ebx + device.rx_desc]
847
;        invoke  GetPhysAddr
3545 hidnplayr 848
        out     dx, eax
849
 
4581 hidnplayr 850
        set_io  [ebx + device.io_addr], reg_scb_cmd
3545 hidnplayr 851
        mov     ax, RX_START
852
        out     dx, ax
853
        call    cmd_wait
854
 
855
  .fail:
856
        pop     edi esi ebx
857
        xor     eax, eax
858
        inc     eax
859
 
860
        ret
861
 
862
 
863
 
864
 
865
align 4
866
cmd_wait:
867
 
868
        in      al, dx
869
        test    al, al
870
        jnz     cmd_wait
871
 
872
        ret
873
 
874
 
875
 
876
 
877
 
878
 
879
align 4
880
ee_read:        ; esi = address to read
881
 
3845 hidnplayr 882
        DEBUGF  1,"Eeprom read from 0x%x\n", esi
3545 hidnplayr 883
 
4581 hidnplayr 884
        set_io  [ebx + device.io_addr], 0
885
        set_io  [ebx + device.io_addr], reg_eeprom
3545 hidnplayr 886
 
887
;-----------------------------------------------------
888
; Prepend start bit + read opcode to the address field
889
; and shift it to the very left bits of esi
890
 
891
        mov     cl, 29
4581 hidnplayr 892
        sub     cl, [ebx + device.ee_bus_width]
3545 hidnplayr 893
        shl     esi, cl
894
        or      esi, EE_READ shl 29
895
 
4581 hidnplayr 896
        movzx   ecx, [ebx + device.ee_bus_width]
3545 hidnplayr 897
        add     ecx, 3
898
 
899
        mov     al, EE_CS
900
        out     dx, al
5247 hidnplayr 901
        call    udelay
3545 hidnplayr 902
 
903
;-----------------------
904
; Write this to the chip
905
 
906
  .loop:
907
        mov     al, EE_CS + EE_SK
908
        shl     esi, 1
909
        jnc     @f
910
        or      al, EE_DI
911
       @@:
912
        out     dx, al
5247 hidnplayr 913
        call    udelay
3545 hidnplayr 914
 
915
        and     al, not EE_SK
916
        out     dx, al
5247 hidnplayr 917
        call    udelay
3545 hidnplayr 918
 
919
        loop    .loop
920
 
921
;------------------------------
922
; Now read the data from eeprom
923
 
924
        xor     esi, esi
925
        mov     ecx, 16
926
 
927
  .loop2:
928
        shl     esi, 1
929
        mov     al, EE_CS + EE_SK
930
        out     dx, al
5247 hidnplayr 931
        call    udelay
3545 hidnplayr 932
 
933
        in      al, dx
934
        test    al, EE_DO
935
        jz      @f
936
        inc     esi
937
       @@:
938
 
939
        mov     al, EE_CS
940
        out     dx, al
5247 hidnplayr 941
        call    udelay
3545 hidnplayr 942
 
943
        loop    .loop2
944
 
945
;-----------------------
946
; de-activate the eeprom
947
 
948
        xor     ax, ax
949
        out     dx, ax
950
 
951
 
3845 hidnplayr 952
        DEBUGF  1,"0x%x\n", esi:4
3545 hidnplayr 953
        ret
954
 
955
 
956
 
957
align 4
958
ee_write:       ; esi = address to write to, di = data
959
 
960
        DEBUGF  1,"Eeprom write 0x%x to 0x%x\n", di, esi
961
 
4581 hidnplayr 962
        set_io  [ebx + device.io_addr], 0
963
        set_io  [ebx + device.io_addr], reg_eeprom
3545 hidnplayr 964
 
965
;-----------------------------------------------------
966
; Prepend start bit + write opcode to the address field
967
; and shift it to the very left bits of esi
968
 
969
        mov     cl, 29
4581 hidnplayr 970
        sub     cl, [ebx + device.ee_bus_width]
3545 hidnplayr 971
        shl     esi, cl
972
        or      esi, EE_WRITE shl 29
973
 
4581 hidnplayr 974
        movzx   ecx, [ebx + device.ee_bus_width]
3545 hidnplayr 975
        add     ecx, 3
976
 
977
        mov     al, EE_CS       ; enable chip
978
        out     dx, al
979
 
980
;-----------------------
981
; Write this to the chip
982
 
983
  .loop:
984
        mov     al, EE_CS + EE_SK
985
        shl     esi, 1
986
        jnc     @f
987
        or      al, EE_DI
988
       @@:
989
        out     dx, al
5247 hidnplayr 990
        call    udelay
3545 hidnplayr 991
 
992
        and     al, not EE_SK
993
        out     dx, al
5247 hidnplayr 994
        call    udelay
3545 hidnplayr 995
 
996
        loop    .loop
997
 
998
;-----------------------------
999
; Now write the data to eeprom
1000
 
1001
        mov     ecx, 16
1002
 
1003
  .loop2:
1004
        mov     al, EE_CS + EE_SK
1005
        shl     di, 1
1006
        jnc     @f
1007
        or      al, EE_DI
1008
       @@:
1009
        out     dx, al
5247 hidnplayr 1010
        call    udelay
3545 hidnplayr 1011
 
1012
        and     al, not EE_SK
1013
        out     dx, al
5247 hidnplayr 1014
        call    udelay
3545 hidnplayr 1015
 
1016
        loop    .loop2
1017
 
1018
;-----------------------
1019
; de-activate the eeprom
1020
 
1021
        xor     al, al
1022
        out     dx, al
1023
 
1024
 
1025
        ret
1026
 
1027
 
1028
 
1029
align 4
1030
ee_get_width:
1031
 
4581 hidnplayr 1032
        set_io  [ebx + device.io_addr], 0
1033
        set_io  [ebx + device.io_addr], reg_eeprom
3545 hidnplayr 1034
 
1035
        mov     al, EE_CS      ; activate eeprom
1036
        out     dx, al
5247 hidnplayr 1037
        call    udelay
3545 hidnplayr 1038
 
1039
        mov     si, EE_READ shl 13
1040
        xor     ecx, ecx
1041
  .loop:
1042
        mov     al, EE_CS + EE_SK
1043
        shl     si, 1
1044
        jnc     @f
1045
        or      al, EE_DI
1046
       @@:
1047
        out     dx, al
5247 hidnplayr 1048
        call    udelay
3545 hidnplayr 1049
 
1050
        and     al, not EE_SK
1051
        out     dx, al
5247 hidnplayr 1052
        call    udelay
3545 hidnplayr 1053
 
1054
        inc     ecx
1055
 
1056
        cmp     ecx, 15
1057
        jae     .give_up
1058
 
1059
        in      al, dx
1060
        test    al, EE_DO
1061
        jnz     .loop
1062
 
1063
        xor     al, al
1064
        out     dx, al          ; de-activate eeprom
1065
 
1066
        sub     cl, 3           ; dont count the opcode bits
4581 hidnplayr 1067
        mov     [ebx + device.ee_bus_width], cl
3845 hidnplayr 1068
        DEBUGF  1, "Eeprom width=%u bit\n", ecx
3545 hidnplayr 1069
 
3845 hidnplayr 1070
        ret
3545 hidnplayr 1071
 
3845 hidnplayr 1072
  .give_up:
1073
        DEBUGF  2, "Eeprom not found!\n"
3545 hidnplayr 1074
 
3845 hidnplayr 1075
        xor     al, al
1076
        out     dx, al          ; de-activate eeprom
3545 hidnplayr 1077
 
1078
        ret
1079
 
1080
 
5247 hidnplayr 1081
; Wait a minimum of 2µs
1082
udelay:
1083
        pusha
1084
        mov     esi, 1
1085
        invoke  Sleep
1086
        popa
3545 hidnplayr 1087
 
5247 hidnplayr 1088
        ret
1089
 
1090
 
1091
 
3545 hidnplayr 1092
; cx = phy addr
1093
; dx = phy reg addr
1094
 
1095
; ax = data
1096
 
1097
align 4
1098
mdio_read:
1099
 
1100
        DEBUGF  1,"MDIO read\n"
1101
 
1102
        shl     ecx, 21                 ; PHY addr
1103
        shl     edx, 16                 ; PHY reg addr
1104
 
1105
        mov     eax, ecx
1106
        or      eax, edx
1107
        or      eax, 10b shl 26         ; read opcode
1108
 
4581 hidnplayr 1109
        set_io  [ebx + device.io_addr], 0
1110
        set_io  [ebx + device.io_addr], reg_mdi_ctrl
3545 hidnplayr 1111
        out     dx, eax
1112
 
1113
  .wait:
5247 hidnplayr 1114
        call    udelay
3545 hidnplayr 1115
        in      eax, dx
1116
        test    eax, 1 shl 28           ; ready bit
1117
        jz      .wait
1118
 
1119
        ret
1120
 
1121
; ax = data
1122
; cx = phy addr
1123
; dx = phy reg addr
1124
 
1125
; ax = data
1126
 
1127
align 4
1128
mdio_write:
1129
 
1130
        DEBUGF  1,"MDIO write\n"
1131
 
1132
        and     eax, 0xffff
1133
 
1134
        shl     ecx, 21                 ; PHY addr
1135
        shl     edx, 16                 ; PHY reg addr
1136
 
1137
        or      eax, ecx
1138
        or      eax, edx
1139
        or      eax, 01b shl 26         ; write opcode
1140
 
4581 hidnplayr 1141
        set_io  [ebx + device.io_addr], 0
1142
        set_io  [ebx + device.io_addr], reg_mdi_ctrl
3545 hidnplayr 1143
        out     dx, eax
1144
 
1145
  .wait:
5247 hidnplayr 1146
        call    udelay
3545 hidnplayr 1147
        in      eax, dx
1148
        test    eax, 1 shl 28           ; ready bit
1149
        jz      .wait
1150
 
1151
        ret
1152
 
1153
read_mac:
1154
 
1155
        ret
1156
 
1157
 
1158
 
1159
align 4
1160
MAC_read_eeprom:
1161
 
1162
        mov     esi, 0
1163
        call    ee_read
4581 hidnplayr 1164
        mov     word[ebx + device.mac], si
3545 hidnplayr 1165
 
1166
        mov     esi, 1
1167
        call    ee_read
4581 hidnplayr 1168
        mov     word[ebx + device.mac+2], si
3545 hidnplayr 1169
 
1170
        mov     esi, 2
1171
        call    ee_read
4581 hidnplayr 1172
        mov     word[ebx + device.mac+4], si
3545 hidnplayr 1173
 
1174
 
1175
        ret
1176
 
1177
 
1178
align 4
1179
MAC_write:
1180
 
1181
;;;;
1182
 
1183
        ret
1184
 
1185
 
1186
 
1187
 
1188
; End of code
1189
 
1190
 
4581 hidnplayr 1191
data fixups
1192
end data
1193
 
1194
include '../peimport.inc'
1195
 
4629 hidnplayr 1196
my_service      db 'I8255X', 0                    ; max 16 chars include zero
3545 hidnplayr 1197
devicename      db 'Intel Etherexpress pro/100', 0
1198
 
1199
confcmd_data    db 22, 0x08, 0, 0, 0, 0x80, 0x32, 0x03, 1
1200
                db 0, 0x2e, 0, 0x60, 0, 0xf2, 0x48, 0, 0x40, 0xf2
1201
                db 0x80, 0x3f, 0x05                                     ; 22 bytes total
1202
 
1203
 
1204
device_id_list:
1205
 
1206
        dw 0x1029
1207
        dw 0x1030
1208
        dw 0x1031
1209
        dw 0x1032
1210
        dw 0x1033
1211
        dw 0x1034
1212
        dw 0x1038
1213
        dw 0x1039
1214
        dw 0x103A
1215
        dw 0x103B
1216
        dw 0x103C
1217
        dw 0x103D
1218
        dw 0x103E
1219
        dw 0x1050
1220
        dw 0x1051
1221
        dw 0x1052
1222
        dw 0x1053
1223
        dw 0x1054
1224
        dw 0x1055
1225
        dw 0x1056
1226
        dw 0x1057
1227
        dw 0x1059
1228
        dw 0x1064
1229
        dw 0x1065
1230
        dw 0x1066
1231
        dw 0x1067
1232
        dw 0x1068
1233
        dw 0x1069
1234
        dw 0x106A
1235
        dw 0x106B
1236
        dw 0x1091
1237
        dw 0x1092
1238
        dw 0x1093
1239
        dw 0x1094
1240
        dw 0x1095
1241
        dw 0x10fe
1242
        dw 0x1209
1243
        dw 0x1229
1244
        dw 0x2449
1245
        dw 0x2459
1246
        dw 0x245D
1247
        dw 0x27DC
1248
 
1249
DEVICE_IDs = ($ - device_id_list) / 2
1250
 
1251
include_debug_strings                           ; All data wich FDO uses will be included here
1252
 
4581 hidnplayr 1253
align 4
1254
devices         dd 0                              ; number of currently running devices
1255
device_list     rd MAX_DEVICES                    ; This list contains all pointers to device structures the driver is handling
3545 hidnplayr 1256