Subversion Repositories Kolibri OS

Rev

Rev 9232 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
3545 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
9232 hidnplayr 3
;; Copyright (C) KolibriOS team 2004-2021. 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
 
5560 hidnplayr 21
;TODO: use more RX buffers
3545 hidnplayr 22
 
4581 hidnplayr 23
format PE DLL native
24
entry START
3545 hidnplayr 25
 
4581 hidnplayr 26
        CURRENT_API             = 0x0200
27
        COMPATIBLE_API          = 0x0100
28
        API_VERSION             = (COMPATIBLE_API shl 16) + CURRENT_API
3545 hidnplayr 29
 
9232 hidnplayr 30
; configureable area
3545 hidnplayr 31
 
9232 hidnplayr 32
        MAX_DEVICES             = 16            ; Maximum number of devices this driver may handle
5525 hidnplayr 33
 
9232 hidnplayr 34
        TX_RING_SIZE            = 16            ; Number of packets in send ring buffer
35
        RX_RING_SIZE            = 1             ; Number of packets in receive ring buffer
36
 
37
        __DEBUG__               = 1             ; 1 = on, 0 = off
4582 hidnplayr 38
        __DEBUG_LEVEL__         = 2             ; 1 = verbose, 2 = errors only
3545 hidnplayr 39
 
9232 hidnplayr 40
; end configureable area
41
 
4581 hidnplayr 42
section '.flat' readable writable executable
43
 
44
include '../proc32.inc'
4467 hidnplayr 45
include '../struct.inc'
46
include '../macros.inc'
3545 hidnplayr 47
include '../fdo.inc'
5074 hidnplayr 48
include '../netdrv.inc'
3545 hidnplayr 49
 
9232 hidnplayr 50
if (bsr TX_RING_SIZE)>(bsf TX_RING_SIZE)
51
  display 'TX_RING_SIZE must be a power of two'
52
  err
53
end if
54
 
55
if (RX_RING_SIZE)<>(1)
56
  display 'RX_RING_SIZE must be 1'
57
  err
58
end if
59
 
6717 hidnplayr 60
; I/O registers
61
REG_SCB_STATUS          = 0
62
REG_SCB_CMD             = 2
63
REG_SCB_PTR             = 4
64
REG_PORT                = 8
65
REG_EEPROM              = 14
66
REG_MDI_CTRL            = 16
3545 hidnplayr 67
 
6717 hidnplayr 68
; Port commands
69
PORT_SOFT_RESET         = 0x0
70
PORT_SELF_TEST          = 0x1
71
PORT_SELECTIVE_RESET    = 0x2
72
PORT_DUMP               = 0x3
73
PORT_DUMP_WAKEUP        = 0x7
74
PORT_PTR_MASK           = 0xfffffff0
3545 hidnplayr 75
 
6717 hidnplayr 76
; Serial EEPROM
77
EE_SK                   = 1 shl 0       ; serial clock
78
EE_CS                   = 1 shl 1       ; chip select
79
EE_DI                   = 1 shl 2       ; data in
80
EE_DO                   = 1 shl 3       ; data out
9232 hidnplayr 81
EE_MASK                 = EE_SK or EE_CS or EE_DI or EE_DO
3545 hidnplayr 82
; opcodes, first bit is start bit and must be 1
6717 hidnplayr 83
EE_READ                 = 110b
84
EE_WRITE                = 101b
85
EE_ERASE                = 111b
3545 hidnplayr 86
 
87
; The SCB accepts the following controls for the Tx and Rx units:
6717 hidnplayr 88
CU_START                = 0x0010
89
CU_RESUME               = 0x0020
90
CU_STATSADDR            = 0x0040
91
CU_SHOWSTATS            = 0x0050        ; Dump statistics counters.
92
CU_CMD_BASE             = 0x0060        ; Base address to add CU commands.
93
CU_DUMPSTATS            = 0x0070        ; Dump then reset stats counters.
3545 hidnplayr 94
 
6717 hidnplayr 95
RX_START                = 0x0001
96
RX_RESUME               = 0x0002
97
RX_ABORT                = 0x0004
98
RX_ADDR_LOAD            = 0x0006
99
RX_RESUMENR             = 0x0007
100
INT_MASK                = 0x0100
101
DRVR_INT                = 0x0200        ; Driver generated interrupt
3545 hidnplayr 102
 
6717 hidnplayr 103
PHY_100a                = 0x000003E0
104
PHY_100c                = 0x035002A8
105
PHY_82555_tx            = 0x015002A8
106
PHY_nsc_tx              = 0x5C002000
107
PHY_82562_et            = 0x033002A8
108
PHY_82562_em            = 0x032002A8
109
PHY_82562_ek            = 0x031002A8
110
PHY_82562_eh            = 0x017002A8
111
PHY_82552_v             = 0xd061004d
112
PHY_unknown             = 0xFFFFFFFF
3545 hidnplayr 113
 
5562 hidnplayr 114
MAC_82557_D100_A        = 0
115
MAC_82557_D100_B        = 1
116
MAC_82557_D100_C        = 2
117
MAC_82558_D101_A4       = 4
118
MAC_82558_D101_B0       = 5
119
MAC_82559_D101M         = 8
120
MAC_82559_D101S         = 9
121
MAC_82550_D102          = 12
122
MAC_82550_D102_C        = 13
123
MAC_82551_E             = 14
124
MAC_82551_F             = 15
125
MAC_82551_10            = 16
126
MAC_unknown             = 0xFF
3545 hidnplayr 127
 
5562 hidnplayr 128
SCB_STATUS_RUS          = 111100b       ; RU Status
129
RU_STATUS_IDLE          = 0000b shl 2
130
RU_STATUS_SUSPENDED     = 0001b shl 2
131
RU_STATUS_NO_RESOURCES  = 0010b shl 2
132
RU_STATUS_READY         = 0100b shl 2
133
SCB_STATUS_FCP          = 1 shl 8       ; Flow Control Pause
134
SCB_STATUS_SWI          = 1 shl 10      ; Software Interrupt
135
SCB_STATUS_MDI          = 1 shl 11      ; MDI read/write complete
136
SCB_STATUS_RNR          = 1 shl 12      ; Receiver Not Ready
137
SCB_STATUS_CNA          = 1 shl 13      ; Command unit Not Active
138
SCB_STATUS_FR           = 1 shl 14      ; Frame received
139
SCB_STATUS_CX_TNO       = 1 shl 15      ; Command finished / Transmit Not Okay
3545 hidnplayr 140
 
4581 hidnplayr 141
struct  rxfd
142
 
143
        status          dw ?
144
        command         dw ?
145
        link            dd ?
146
        rx_buf_addr     dd ?
147
        count           dw ?
148
        size            dw ?
149
        packet          rb 1500
150
 
151
ends
152
 
5562 hidnplayr 153
RXFD_STATUS_RC          = 1 shl 0       ; Receive collision
154
RXFD_STATUS_IA          = 1 shl 1       ; IA mismatch
155
RXFD_STATUS_NA          = 1 shl 2       ; No address match
156
RXFD_STATUS_RE          = 1 shl 4       ; Receive Error
157
RXFD_STATUS_TL          = 1 shl 5       ; Type/length
158
RXFD_STATUS_FS          = 1 shl 7       ; Frame too short
159
RXFD_STATUS_DMA_FAIL    = 1 shl 8       ; DMA overrun failure
160
RXFD_STATUS_NR          = 1 shl 9       ; Out of buffer space; no resources
161
RXFD_STATUS_MISA        = 1 shl 10      ; Alignment error
162
RXFD_STATUS_CRC_ERR     = 1 shl 11      ; CRC error in aligned frame
163
RXFD_STATUS_OK          = 1 shl 13      ; Frame received and stored
164
RXFD_STATUS_C           = 1 shl 15      ; Completion of frame reception
165
 
166
RXFD_CMD_SF             = 1 shl 3
167
RXFD_CMD_H              = 1 shl 4       ; Header RFD
168
RXFD_CMD_SUSPEND        = 1 shl 14      ; Suspends RU after receiving the frame
169
RXFD_CMD_EL             = 1 shl 15      ; Last RFD in RFA
170
 
5525 hidnplayr 171
struct  txfd
4581 hidnplayr 172
 
5525 hidnplayr 173
        status          dw ?
174
        command         dw ?
175
        link            dd ?
176
        desc_addr       dd ?
177
        count           dd ?
4581 hidnplayr 178
 
5525 hidnplayr 179
        buf_addr        dd ?
180
        buf_size        dd ?
181
        virt_addr       dd ?
182
                        dd ?            ; alignment
4581 hidnplayr 183
 
5525 hidnplayr 184
ends
4581 hidnplayr 185
 
5562 hidnplayr 186
TXFD_CMD_IA             = 1 shl 0
187
TXFD_CMD_CFG            = 1 shl 1
188
TXFD_CMD_TX             = 1 shl 2
189
TXFD_CMD_TX_FLEX        = 1 shl 3
190
TXFD_CMD_SUSPEND        = 1 shl 14
191
 
4581 hidnplayr 192
struc   confcmd {
193
 
194
        .status         dw ?
195
        .command        dw ?
196
        .link           dd ?
197
        .data           rb 64
198
 
199
}
200
 
201
struc   lstats {
202
 
203
        .tx_good_frames         dd ?
204
        .tx_coll16_errs         dd ?
205
        .tx_late_colls          dd ?
206
        .tx_underruns           dd ?
207
        .tx_lost_carrier        dd ?
208
        .tx_deferred            dd ?
209
        .tx_one_colls           dd ?
210
        .tx_multi_colls         dd ?
211
        .tx_total_colls         dd ?
212
 
213
        .rx_good_frames         dd ?
214
        .rx_crc_errs            dd ?
215
        .rx_align_errs          dd ?
216
        .rx_resource_errs       dd ?
217
        .rx_overrun_errs        dd ?
218
        .rx_colls_errs          dd ?
219
        .rx_runt_errs           dd ?
220
 
221
}
222
 
223
struct  device          ETH_DEVICE
224
 
225
        io_addr         dd ?
226
        pci_bus         dd ?
227
        pci_dev         dd ?
228
        rx_desc         dd ?
5525 hidnplayr 229
        cur_tx          dd ?
230
        last_tx         dd ?
9243 hidnplayr 231
        link_timer      dd ?
4581 hidnplayr 232
        ee_bus_width    db ?
233
        irq_line        db ?
234
 
235
        rb 0x100 - ($ and 0xff) ; align 256
5525 hidnplayr 236
        tx_ring         rb TX_RING_SIZE*sizeof.txfd
4581 hidnplayr 237
 
238
        rb 0x100 - ($ and 0xff) ; align 256
239
        confcmd         confcmd
240
 
241
        rb 0x100 - ($ and 0xff) ; align 256
242
        lstats          lstats
243
 
244
ends
245
 
3545 hidnplayr 246
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
247
;;                        ;;
248
;; proc START             ;;
249
;;                        ;;
250
;; (standard driver proc) ;;
251
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
252
 
4581 hidnplayr 253
proc START c, state:dword
3545 hidnplayr 254
 
255
        cmp [state], 1
256
        jne .exit
257
 
258
  .entry:
259
 
3845 hidnplayr 260
        DEBUGF 1,"Loading driver\n"
4581 hidnplayr 261
        invoke  RegService, my_service, service_proc
3545 hidnplayr 262
        ret
263
 
264
  .fail:
265
  .exit:
266
        xor eax, eax
267
        ret
268
 
269
endp
270
 
271
 
272
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
273
;;                        ;;
274
;; proc SERVICE_PROC      ;;
275
;;                        ;;
276
;; (standard driver proc) ;;
277
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
278
 
279
align 4
280
proc service_proc stdcall, ioctl:dword
281
 
282
        mov     edx, [ioctl]
4470 hidnplayr 283
        mov     eax, [edx + IOCTL.io_code]
3545 hidnplayr 284
 
285
;------------------------------------------------------
286
 
287
        cmp     eax, 0 ;SRV_GETVERSION
288
        jne     @F
289
 
4470 hidnplayr 290
        cmp     [edx + IOCTL.out_size], 4
3545 hidnplayr 291
        jb      .fail
4470 hidnplayr 292
        mov     eax, [edx + IOCTL.output]
3545 hidnplayr 293
        mov     [eax], dword API_VERSION
294
 
295
        xor     eax, eax
296
        ret
297
 
298
;------------------------------------------------------
299
  @@:
300
        cmp     eax, 1 ;SRV_HOOK
301
        jne     .fail
302
 
4470 hidnplayr 303
        cmp     [edx + IOCTL.inp_size], 3               ; Data input must be at least 3 bytes
3545 hidnplayr 304
        jb      .fail
305
 
4470 hidnplayr 306
        mov     eax, [edx + IOCTL.input]
3545 hidnplayr 307
        cmp     byte [eax], 1                           ; 1 means device number and bus number (pci) are given
308
        jne     .fail                                   ; other types arent supported for this card yet
309
 
310
; check if the device is already listed
311
 
312
        mov     esi, device_list
313
        mov     ecx, [devices]
314
        test    ecx, ecx
315
        jz      .firstdevice
316
 
4470 hidnplayr 317
;        mov     eax, [edx + IOCTL.input]                ; get the pci bus and device numbers
3545 hidnplayr 318
        mov     ax , [eax+1]                            ;
319
  .nextdevice:
320
        mov     ebx, [esi]
4581 hidnplayr 321
        cmp     al, byte[ebx + device.pci_bus]
3545 hidnplayr 322
        jne     @f
4581 hidnplayr 323
        cmp     ah, byte[ebx + device.pci_dev]
3545 hidnplayr 324
        je      .find_devicenum                         ; Device is already loaded, let's find it's device number
325
       @@:
326
        add     esi, 4
327
        loop    .nextdevice
328
 
329
 
330
; This device doesnt have its own eth_device structure yet, lets create one
331
  .firstdevice:
332
        cmp     [devices], MAX_DEVICES                  ; First check if the driver can handle one more card
333
        jae     .fail
334
 
4581 hidnplayr 335
        allocate_and_clear ebx, sizeof.device, .fail      ; Allocate the buffer for device structure
3545 hidnplayr 336
 
337
; Fill in the direct call addresses into the struct
338
 
4581 hidnplayr 339
        mov     [ebx + device.reset], reset
340
        mov     [ebx + device.transmit], transmit
341
        mov     [ebx + device.unload], unload
6717 hidnplayr 342
        mov     [ebx + device.name], devicename
3545 hidnplayr 343
 
344
; save the pci bus and device numbers
345
 
4470 hidnplayr 346
        mov     eax, [edx + IOCTL.input]
3545 hidnplayr 347
        movzx   ecx, byte[eax+1]
4581 hidnplayr 348
        mov     [ebx + device.pci_bus], ecx
3545 hidnplayr 349
        movzx   ecx, byte[eax+2]
4581 hidnplayr 350
        mov     [ebx + device.pci_dev], ecx
3545 hidnplayr 351
 
352
; Now, it's time to find the base io addres of the PCI device
353
 
4581 hidnplayr 354
        stdcall PCI_find_io, [ebx + device.pci_bus], [ebx + device.pci_dev]
355
        mov     [ebx + device.io_addr], eax
3545 hidnplayr 356
 
357
; We've found the io address, find IRQ now
358
 
4581 hidnplayr 359
        invoke  PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.interrupt_line
360
        mov     [ebx + device.irq_line], al
3545 hidnplayr 361
 
6717 hidnplayr 362
        DEBUGF  1,"Hooking into device, devfn:%x, bus:%x, irq:%x, addr:%x\n",\
363
        [ebx + device.pci_dev]:2,[ebx + device.pci_bus]:2,[ebx + device.irq_line]:2,[ebx + device.io_addr]:4
3545 hidnplayr 364
 
365
; Ok, the eth_device structure is ready, let's probe the device
366
 
367
        mov     eax, [devices]                                          ; Add the device structure to our device list
368
        mov     [device_list+4*eax], ebx                                ; (IRQ handler uses this list to find device)
369
        inc     [devices]                                               ;
370
 
6717 hidnplayr 371
        call    probe                                                   ; this function will output in eax
372
        test    eax, eax
373
        jnz     .err                                                 ; If an error occured, exit
3545 hidnplayr 374
 
4581 hidnplayr 375
        mov     [ebx + device.type], NET_TYPE_ETH
376
        invoke  NetRegDev
3545 hidnplayr 377
 
378
        cmp     eax, -1
379
        je      .err
380
 
381
        ret
382
 
383
; If the device was already loaded, find the device number and return it in eax
384
 
385
  .find_devicenum:
386
        DEBUGF  2,"Trying to find device number of already registered device\n"
4581 hidnplayr 387
        invoke  NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
3545 hidnplayr 388
                                                                        ; into a device number in edi
389
        mov     eax, edi                                                ; Application wants it in eax instead
390
        DEBUGF  2,"Kernel says: %u\n", eax
391
        ret
392
 
393
; If an error occured, remove all allocated data and exit (returning -1 in eax)
394
  .err:
4581 hidnplayr 395
        invoke  KernelFree, ebx
3545 hidnplayr 396
 
397
  .fail:
398
        or      eax, -1
399
        ret
400
 
401
;------------------------------------------------------
402
endp
403
 
404
 
405
 
406
 
407
 
408
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
409
;;                                                                        ;;
410
;;        Actual Hardware dependent code starts here                      ;;
411
;;                                                                        ;;
412
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
413
 
414
 
415
unload:
9243 hidnplayr 416
 
417
        cmp     [ebx + device.link_timer], 0
418
        je      @f
419
        invoke  CancelTimerHS, [ebx + device.link_timer]
420
  @@:
421
 
3545 hidnplayr 422
        ; TODO: (in this particular order)
423
        ;
424
        ; - Stop the device
425
        ; - Detach int handler
426
        ; - Remove device from local list (device_list)
427
        ; - call unregister function in kernel
428
        ; - Remove all allocated structures and buffers the card used
429
 
5560 hidnplayr 430
        or      eax, -1
431
        ret
3545 hidnplayr 432
 
433
 
434
;-------------
435
;
436
; Probe
437
;
438
;-------------
439
 
440
align 4
441
probe:
442
 
3845 hidnplayr 443
        DEBUGF  1,"Probing\n"
3545 hidnplayr 444
 
4581 hidnplayr 445
; Make the device a bus master
446
        invoke  PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command
6717 hidnplayr 447
        or      al, PCI_CMD_MASTER or PCI_CMD_PIO
4581 hidnplayr 448
        invoke  PciWrite32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command, eax
3545 hidnplayr 449
 
450
;---------------------------
451
; First, identify the device
452
 
4581 hidnplayr 453
        invoke  PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header.vendor_id ; get device/vendor id
3545 hidnplayr 454
 
455
        DEBUGF  1,"Vendor_id=0x%x\n", ax
456
        cmp     ax, 0x8086
457
        jne     .notfound
458
        shr     eax, 16
459
 
460
        DEBUGF  1,"Device_id=0x%x\n", ax
461
        mov     ecx, DEVICE_IDs
462
        mov     edi, device_id_list
463
        repne   scasw
464
        jne     .notfound
465
        jmp     .found
466
 
467
  .notfound:
3845 hidnplayr 468
        DEBUGF  2,"Unsupported device!\n"
3545 hidnplayr 469
        or      eax, -1
470
        ret
471
 
472
  .found:
473
 
474
 
475
 
476
;----------
477
;
478
;  Reset
479
;
480
;----------
481
 
482
align 4
483
reset:
484
 
9243 hidnplayr 485
; Stop link check timer if it was already running
486
        cmp     [ebx + device.link_timer], 0
487
        je      @f
488
        invoke  CancelTimerHS, [ebx + device.link_timer]
489
  @@:
490
 
491
; attach int handler
4581 hidnplayr 492
        movzx   eax, [ebx + device.irq_line]
3545 hidnplayr 493
        DEBUGF  1,"Attaching int handler to irq %x\n", eax:1
4581 hidnplayr 494
        invoke  AttachIntHandler, eax, int_handler, ebx
3545 hidnplayr 495
        test    eax, eax
496
        jnz     @f
3845 hidnplayr 497
        DEBUGF  2,"Could not attach int handler!\n"
4581 hidnplayr 498
        or      eax, -1
499
        ret
3545 hidnplayr 500
  @@:
501
 
3845 hidnplayr 502
        DEBUGF  1,"Resetting\n"
3545 hidnplayr 503
 
6717 hidnplayr 504
;----------------
505
; Selective reset
3545 hidnplayr 506
 
4581 hidnplayr 507
        set_io  [ebx + device.io_addr], 0
6717 hidnplayr 508
        set_io  [ebx + device.io_addr], REG_EEPROM
509
        mov     eax, PORT_SELECTIVE_RESET
510
        out     dx, eax
511
 
6948 hidnplayr 512
        mov     esi, 10
6717 hidnplayr 513
        invoke  Sleep
514
 
515
;-----------
516
; Soft reset
517
 
5562 hidnplayr 518
        set_io  [ebx + device.io_addr], REG_PORT
6717 hidnplayr 519
        mov     eax, PORT_SOFT_RESET
3545 hidnplayr 520
        out     dx, eax
521
 
522
        mov     esi, 10
6717 hidnplayr 523
        invoke  Sleep
3545 hidnplayr 524
 
6717 hidnplayr 525
;-------------
526
; Read PHY IDs
527
 
528
        mov     cx, 1
529
        mov     dx, MII_PHYSID1
530
        call    mdio_read
531
        DEBUGF  1, "PHY ID1: 0x%x\n", ax
532
 
533
        mov     cx, 1
534
        mov     dx, MII_PHYSID2
535
        call    mdio_read
536
        DEBUGF  1, "PHY ID2: 0x%x\n", ax
537
 
538
;---------------------
539
; Read MAC from eeprom
540
 
541
        call    ee_get_width
542
        call    mac_read_eeprom
543
 
3545 hidnplayr 544
;---------------------------------
545
; Tell device where to store stats
546
 
4581 hidnplayr 547
        lea     eax, [ebx + device.lstats.tx_good_frames]      ; lstats
548
        invoke  GetPhysAddr
549
        set_io  [ebx + device.io_addr], 0
5562 hidnplayr 550
        set_io  [ebx + device.io_addr], REG_SCB_PTR
3545 hidnplayr 551
        out     dx, eax
552
 
5562 hidnplayr 553
        set_io  [ebx + device.io_addr], REG_SCB_CMD
5525 hidnplayr 554
        mov     ax, CU_STATSADDR or INT_MASK
3545 hidnplayr 555
        out     dx, ax
556
        call    cmd_wait
557
 
5525 hidnplayr 558
;------------------------
559
; setup RX base addr to 0
3545 hidnplayr 560
 
5562 hidnplayr 561
        set_io  [ebx + device.io_addr], REG_SCB_PTR
3545 hidnplayr 562
        xor     eax, eax
563
        out     dx, eax
564
 
5562 hidnplayr 565
        set_io  [ebx + device.io_addr], REG_SCB_CMD
5525 hidnplayr 566
        mov     ax, RX_ADDR_LOAD or INT_MASK
3545 hidnplayr 567
        out     dx, ax
568
        call    cmd_wait
569
 
570
;-----------------------------
571
; Create RX and TX descriptors
572
 
5525 hidnplayr 573
        call    init_rx_ring
5522 hidnplayr 574
        test    eax, eax
575
        jz      .error
3545 hidnplayr 576
 
5525 hidnplayr 577
        call    init_tx_ring
3545 hidnplayr 578
 
5525 hidnplayr 579
 
580
;---------
581
; Start RX
582
 
583
        DEBUGF  1, "Starting RX"
584
 
4581 hidnplayr 585
        set_io  [ebx + device.io_addr], 0
5562 hidnplayr 586
        set_io  [ebx + device.io_addr], REG_SCB_PTR
4581 hidnplayr 587
        mov     eax, [ebx + device.rx_desc]
588
        invoke  GetPhysAddr
5522 hidnplayr 589
        add     eax, NET_BUFF.data
3545 hidnplayr 590
        out     dx, eax
591
 
5562 hidnplayr 592
        set_io  [ebx + device.io_addr], REG_SCB_CMD
5525 hidnplayr 593
        mov     ax, RX_START or INT_MASK
3545 hidnplayr 594
        out     dx, ax
595
        call    cmd_wait
596
 
5525 hidnplayr 597
;----------
3545 hidnplayr 598
; Set-up TX
599
 
5562 hidnplayr 600
        set_io  [ebx + device.io_addr], REG_SCB_PTR
3545 hidnplayr 601
        xor     eax, eax
602
        out     dx, eax
603
 
5562 hidnplayr 604
        set_io  [ebx + device.io_addr], REG_SCB_CMD
5525 hidnplayr 605
        mov     ax, CU_CMD_BASE or INT_MASK
3545 hidnplayr 606
        out     dx, ax
607
        call    cmd_wait
608
 
5525 hidnplayr 609
;-------------------------
610
; Individual address setup
3545 hidnplayr 611
 
9232 hidnplayr 612
        mov     [ebx + device.confcmd.command], TXFD_CMD_IA or TXFD_CMD_SUSPEND
5525 hidnplayr 613
        mov     [ebx + device.confcmd.status], 0
614
        lea     eax, [ebx + device.tx_ring]
615
        invoke  GetPhysAddr
616
        mov     [ebx + device.confcmd.link], eax
617
        lea     edi, [ebx + device.confcmd.data]
618
        lea     esi, [ebx + device.mac]
619
        movsd
620
        movsw
621
 
5562 hidnplayr 622
        set_io  [ebx + device.io_addr], REG_SCB_PTR
5525 hidnplayr 623
        lea     eax, [ebx + device.confcmd.status]
624
        invoke  GetPhysAddr
625
        out     dx, eax
626
 
5562 hidnplayr 627
        set_io  [ebx + device.io_addr], REG_SCB_CMD
5525 hidnplayr 628
        mov     ax, CU_START or INT_MASK
629
        out     dx, ax
630
        call    cmd_wait
631
 
632
;-------------
633
; Configure CU
634
 
9232 hidnplayr 635
        mov     [ebx + device.confcmd.command], TXFD_CMD_CFG or TXFD_CMD_SUSPEND
4581 hidnplayr 636
        mov     [ebx + device.confcmd.status], 0
5525 hidnplayr 637
        lea     eax, [ebx + device.confcmd.status]
4581 hidnplayr 638
        invoke  GetPhysAddr
639
        mov     [ebx + device.confcmd.link], eax
3545 hidnplayr 640
 
641
        mov     esi, confcmd_data
4581 hidnplayr 642
        lea     edi, [ebx + device.confcmd.data]
3545 hidnplayr 643
        mov     ecx, 22
644
        rep     movsb
645
 
5562 hidnplayr 646
        set_io  [ebx + device.io_addr], REG_SCB_PTR
4581 hidnplayr 647
        lea     eax, [ebx + device.confcmd.status]
648
        invoke  GetPhysAddr
3545 hidnplayr 649
        out     dx, eax
650
 
5562 hidnplayr 651
        set_io  [ebx + device.io_addr], REG_SCB_CMD
5525 hidnplayr 652
        mov     ax, CU_START                            ; expect Interrupts from now on
3545 hidnplayr 653
        out     dx, ax
654
        call    cmd_wait
655
 
9243 hidnplayr 656
; Start media check timer
657
        mov     [ebx + device.state], ETH_LINK_DOWN
658
        invoke  TimerHS, 0, 50, check_media_mii, ebx
659
        mov     [ebx + device.link_timer], eax
660
 
4581 hidnplayr 661
        mov     [ebx + device.mtu], 1514
3545 hidnplayr 662
 
9243 hidnplayr 663
        DEBUGF  1,"Reset complete\n"
3545 hidnplayr 664
 
665
        xor     eax, eax        ; indicate that we have successfully reset the card
666
        ret
667
 
5522 hidnplayr 668
  .error:
669
        or      eax, -1
670
        ret
3545 hidnplayr 671
 
5522 hidnplayr 672
 
3545 hidnplayr 673
align 4
5525 hidnplayr 674
init_rx_ring:
3545 hidnplayr 675
 
676
        DEBUGF  1,"Creating ring\n"
677
 
678
;---------------------
679
; build rxfd structure
680
 
5522 hidnplayr 681
        invoke  NetAlloc, 2000
682
        test    eax, eax
683
        jz      .out_of_mem
4581 hidnplayr 684
        mov     [ebx + device.rx_desc], eax
3545 hidnplayr 685
        mov     esi, eax
4581 hidnplayr 686
        invoke  GetPhysAddr
5522 hidnplayr 687
        add     eax, NET_BUFF.data
5562 hidnplayr 688
        mov     [esi + sizeof.NET_BUFF + rxfd.status], 0
689
        mov     [esi + sizeof.NET_BUFF + rxfd.command], RXFD_CMD_EL or RXFD_CMD_SUSPEND
5522 hidnplayr 690
        mov     [esi + sizeof.NET_BUFF + rxfd.link], eax
691
        mov     [esi + sizeof.NET_BUFF + rxfd.count], 0
692
        mov     [esi + sizeof.NET_BUFF + rxfd.size], 1528
3545 hidnplayr 693
 
5525 hidnplayr 694
        ret
3545 hidnplayr 695
 
5525 hidnplayr 696
  .out_of_mem:
697
        ret
698
 
699
 
700
 
701
 
702
align 4
703
init_tx_ring:
704
 
705
        DEBUGF  1,"Creating TX ring\n"
706
 
707
        lea     esi, [ebx + device.tx_ring]
708
        mov     eax, esi
4581 hidnplayr 709
        invoke  GetPhysAddr
5525 hidnplayr 710
        mov     ecx, TX_RING_SIZE
711
  .next_desc:
712
        mov     [esi + txfd.status], 0
713
        mov     [esi + txfd.command], 0
714
        lea     edx, [eax + txfd.buf_addr]
715
        mov     [esi + txfd.desc_addr], edx
716
        add     eax, sizeof.txfd
717
        mov     [esi + txfd.link], eax
718
        mov     [esi + txfd.count], 0x01208000          ; One buffer, 0x20 bytes of transmit threshold, end of frame
719
        add     esi, sizeof.txfd
720
        dec     ecx
721
        jnz     .next_desc
722
 
723
        lea     eax, [ebx + device.tx_ring]
4581 hidnplayr 724
        invoke  GetPhysAddr
5525 hidnplayr 725
        mov     dword[ebx + device.tx_ring + sizeof.txfd*(TX_RING_SIZE-1) + txfd.link], eax
3545 hidnplayr 726
 
5525 hidnplayr 727
        mov     [ebx + device.cur_tx], 0
728
        mov     [ebx + device.last_tx], 0
5522 hidnplayr 729
 
3545 hidnplayr 730
        ret
731
 
732
 
733
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
734
;;                                         ;;
735
;; Transmit                                ;;
736
;;                                         ;;
4581 hidnplayr 737
;; In: pointer to device structure in ebx  ;;
9232 hidnplayr 738
;; Out: eax = 0 on success                 ;;
3545 hidnplayr 739
;;                                         ;;
740
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9232 hidnplayr 741
align 16
5522 hidnplayr 742
proc transmit stdcall bufferptr
3545 hidnplayr 743
 
9232 hidnplayr 744
        spin_lock_irqsave
4581 hidnplayr 745
 
5522 hidnplayr 746
        mov     esi, [bufferptr]
747
        DEBUGF  1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [esi + NET_BUFF.length]
748
        lea     eax, [esi + NET_BUFF.data]
3545 hidnplayr 749
        DEBUGF  1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
750
        [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
751
        [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
752
        [eax+13]:2,[eax+12]:2
753
 
5522 hidnplayr 754
        cmp     [esi + NET_BUFF.length], 1514
9232 hidnplayr 755
        ja      .error
5522 hidnplayr 756
        cmp     [esi + NET_BUFF.length], 60
9232 hidnplayr 757
        jb      .error
3545 hidnplayr 758
 
5525 hidnplayr 759
        ; Get current TX descriptor
760
        mov     edi, [ebx + device.cur_tx]
761
        mov     eax, sizeof.txfd
762
        mul     edi
763
        lea     edi, [ebx + device.tx_ring + eax]
764
 
765
        ; Check if current descriptor is free or still in use
766
        cmp     [edi + txfd.status], 0
9232 hidnplayr 767
        jne     .overrun
5525 hidnplayr 768
 
769
        ; Fill in status and command values
770
        mov     [edi + txfd.status], 0
9232 hidnplayr 771
        mov     [edi + txfd.command], TXFD_CMD_SUSPEND or TXFD_CMD_TX or TXFD_CMD_TX_FLEX
5525 hidnplayr 772
        mov     [edi + txfd.count], 0x01208000
773
 
774
        ; Fill in buffer address and size
775
        mov     [edi + txfd.virt_addr], esi
776
        mov     eax, esi
777
        add     eax, [esi + NET_BUFF.offset]
778
        push    edi
4581 hidnplayr 779
        invoke  GetPhysAddr
5525 hidnplayr 780
        pop     edi
781
        mov     [edi + txfd.buf_addr], eax
782
        mov     ecx, [esi + NET_BUFF.length]
783
        mov     [edi + txfd.buf_size], ecx
3545 hidnplayr 784
 
785
        ; Inform device of the new/updated transmit descriptor
5525 hidnplayr 786
        mov     eax, edi
4581 hidnplayr 787
        invoke  GetPhysAddr
788
        set_io  [ebx + device.io_addr], 0
5562 hidnplayr 789
        set_io  [ebx + device.io_addr], REG_SCB_PTR
3545 hidnplayr 790
        out     dx, eax
791
 
792
        ; Start the transmit
5562 hidnplayr 793
        set_io  [ebx + device.io_addr], REG_SCB_CMD
3545 hidnplayr 794
        mov     ax, CU_START
795
        out     dx, ax
796
 
5525 hidnplayr 797
        ; Update stats
4581 hidnplayr 798
        inc     [ebx + device.packets_tx]
799
        add     dword[ebx + device.bytes_tx], ecx
800
        adc     dword[ebx + device.bytes_tx + 4], 0
3545 hidnplayr 801
 
9232 hidnplayr 802
        inc     [ebx + device.cur_tx]
803
        and     [ebx + device.cur_tx], TX_RING_SIZE - 1
804
 
5525 hidnplayr 805
        ; Wait for command to complete
806
        call    cmd_wait
807
 
9232 hidnplayr 808
        spin_unlock_irqrestore
3545 hidnplayr 809
        xor     eax, eax
4581 hidnplayr 810
        ret
3545 hidnplayr 811
 
9232 hidnplayr 812
  .error:
813
        DEBUGF  2, "TX packet error\n"
814
        inc     [ebx + device.packets_tx_err]
5522 hidnplayr 815
        invoke  NetFree, [bufferptr]
9232 hidnplayr 816
 
817
        spin_unlock_irqrestore
3545 hidnplayr 818
        or      eax, -1
4581 hidnplayr 819
        ret
3545 hidnplayr 820
 
9232 hidnplayr 821
  .overrun:
822
        DEBUGF  2, "TX overrun\n"
823
        inc     [ebx + device.packets_tx_ovr]
824
        invoke  NetFree, [bufferptr]
825
 
826
        spin_unlock_irqrestore
827
        or      eax, -1
828
        ret
829
 
4581 hidnplayr 830
endp
831
 
832
 
3545 hidnplayr 833
;;;;;;;;;;;;;;;;;;;;;;;
834
;;                   ;;
835
;; Interrupt handler ;;
836
;;                   ;;
837
;;;;;;;;;;;;;;;;;;;;;;;
9232 hidnplayr 838
align 16
3545 hidnplayr 839
int_handler:
840
 
841
        push    ebx esi edi
842
 
9232 hidnplayr 843
        mov     ebx, [esp+4*4]
844
        DEBUGF  1,"INT for 0x%x\n", ebx
3545 hidnplayr 845
 
9232 hidnplayr 846
; TODO? if we are paranoid, we can check that the value from ebx is present in the current device_list
3545 hidnplayr 847
 
5562 hidnplayr 848
;        set_io  [ebx + device.io_addr], 0      ; REG_SCB_STATUS = 0
849
        set_io  [ebx + device.io_addr], REG_SCB_STATUS
3545 hidnplayr 850
        in      ax, dx
9232 hidnplayr 851
        test    ax, ax
852
        jz      .nothing
5562 hidnplayr 853
        out     dx, ax                          ; send it back to ACK
3545 hidnplayr 854
 
9232 hidnplayr 855
        DEBUGF  1,"Status: %x\n", ax
3545 hidnplayr 856
 
5562 hidnplayr 857
        test    ax, SCB_STATUS_FR               ; did we receive a frame?
3545 hidnplayr 858
        jz      .no_rx
859
 
860
        push    ax
861
 
862
        DEBUGF  1,"Receiving\n"
863
 
864
        push    ebx
865
  .rx_loop:
866
        pop     ebx
867
 
4581 hidnplayr 868
        mov     esi, [ebx + device.rx_desc]
5562 hidnplayr 869
        test    [esi + sizeof.NET_BUFF + rxfd.status], RXFD_STATUS_C            ; Completed?
870
        jz      .no_rx_
871
        test    [esi + sizeof.NET_BUFF + rxfd.status], RXFD_STATUS_OK           ; OK?
872
        jz      .not_ok
3545 hidnplayr 873
 
5522 hidnplayr 874
        DEBUGF  1,"rxfd status=0x%x\n", [esi + sizeof.NET_BUFF + rxfd.status]:4
3545 hidnplayr 875
 
5522 hidnplayr 876
        movzx   ecx, [esi + sizeof.NET_BUFF + rxfd.count]
3545 hidnplayr 877
        and     ecx, 0x3fff
878
 
879
        push    ebx
880
        push    .rx_loop
881
        push    esi
5522 hidnplayr 882
        mov     [esi + NET_BUFF.length], ecx
883
        mov     [esi + NET_BUFF.device], ebx
884
        mov     [esi + NET_BUFF.offset], NET_BUFF.data + rxfd.packet
3545 hidnplayr 885
 
886
; Update stats
4581 hidnplayr 887
        add     dword [ebx + device.bytes_rx], ecx
888
        adc     dword [ebx + device.bytes_rx + 4], 0
889
        inc     dword [ebx + device.packets_rx]
3545 hidnplayr 890
 
891
; allocate new descriptor
892
 
5522 hidnplayr 893
        invoke  NetAlloc, 2000
5561 hidnplayr 894
        test    eax, eax
895
        jz      .out_of_mem
4581 hidnplayr 896
        mov     [ebx + device.rx_desc], eax
3545 hidnplayr 897
        mov     esi, eax
4581 hidnplayr 898
        invoke  GetPhysAddr
5522 hidnplayr 899
        add     eax, NET_BUFF.data
5562 hidnplayr 900
        mov     [esi + sizeof.NET_BUFF + rxfd.status], 0
901
        mov     [esi + sizeof.NET_BUFF + rxfd.command], RXFD_CMD_EL or RXFD_CMD_SUSPEND
5522 hidnplayr 902
        mov     [esi + sizeof.NET_BUFF + rxfd.link], eax
903
        mov     [esi + sizeof.NET_BUFF + rxfd.count], 0
904
        mov     [esi + sizeof.NET_BUFF + rxfd.size], 1528
3545 hidnplayr 905
 
906
; restart RX
907
 
4581 hidnplayr 908
        set_io  [ebx + device.io_addr], 0
5562 hidnplayr 909
        set_io  [ebx + device.io_addr], REG_SCB_PTR
5560 hidnplayr 910
;        mov     eax, [ebx + device.rx_desc]
4581 hidnplayr 911
;        invoke  GetPhysAddr
5560 hidnplayr 912
;        add     eax, NET_BUFF.data
3545 hidnplayr 913
        out     dx, eax
914
 
5562 hidnplayr 915
        set_io  [ebx + device.io_addr], REG_SCB_CMD
3545 hidnplayr 916
        mov     ax, RX_START
917
        out     dx, ax
918
        call    cmd_wait
5561 hidnplayr 919
  .out_of_mem:
3545 hidnplayr 920
 
5562 hidnplayr 921
; Hand the frame over to the kernel
5522 hidnplayr 922
        jmp     [EthInput]
3545 hidnplayr 923
 
5562 hidnplayr 924
  .not_ok:
925
; Reset the FD
926
        mov     [esi + sizeof.NET_BUFF + rxfd.status], 0
927
        mov     [esi + sizeof.NET_BUFF + rxfd.command], RXFD_CMD_EL or RXFD_CMD_SUSPEND
928
        mov     [esi + sizeof.NET_BUFF + rxfd.count], 0
929
 
930
; Restart RX
931
        set_io  [ebx + device.io_addr], 0
932
        set_io  [ebx + device.io_addr], REG_SCB_PTR
933
        mov     eax, esi
934
        invoke  GetPhysAddr
935
        add     eax, NET_BUFF.data
936
        out     dx, eax
937
 
938
        set_io  [ebx + device.io_addr], REG_SCB_CMD
939
        mov     ax, RX_START
940
        out     dx, ax
941
        call    cmd_wait
942
 
943
        push    ebx
944
        jmp     .rx_loop
945
 
946
  .no_rx_:
3545 hidnplayr 947
        DEBUGF  1, "no more data\n"
948
        pop     ax
949
 
950
  .no_rx:
951
 
5562 hidnplayr 952
        test    ax, SCB_STATUS_CNA
5525 hidnplayr 953
        jz      .no_tx
954
        DEBUGF  1, "Command completed\n"
3545 hidnplayr 955
 
5525 hidnplayr 956
        push    eax
957
  .loop_tx:
958
        mov     edi, [ebx + device.last_tx]
959
        mov     eax, sizeof.txfd
960
        mul     eax
961
        lea     edi, [ebx + device.tx_ring + eax]
962
 
963
        cmp     [edi + txfd.status], 0
964
        je      .tx_done
965
 
966
        cmp     [edi + txfd.virt_addr], 0
967
        je      .tx_done
968
 
969
        DEBUGF  1,"Freeing buffer 0x%x\n", [edi + txfd.virt_addr]
970
 
971
        push    [edi + txfd.virt_addr]
972
        mov     [edi + txfd.virt_addr], 0
973
        invoke  NetFree
974
 
975
        inc     [ebx + device.last_tx]
976
        and     [ebx + device.last_tx], TX_RING_SIZE - 1
977
 
978
        jmp     .loop_tx
979
  .tx_done:
980
        pop     eax
981
  .no_tx:
982
 
5562 hidnplayr 983
        test    ax, RU_STATUS_NO_RESOURCES
9232 hidnplayr 984
        jz      .not_out_of_resources
3545 hidnplayr 985
 
5560 hidnplayr 986
        DEBUGF  2, "Out of resources!\n"
3545 hidnplayr 987
 
9232 hidnplayr 988
  .not_out_of_resources:
3545 hidnplayr 989
        pop     edi esi ebx
990
        xor     eax, eax
991
        inc     eax
992
 
993
        ret
994
 
9232 hidnplayr 995
  .nothing:
996
        pop     edi esi ebx
997
        xor     eax, eax
3545 hidnplayr 998
 
9232 hidnplayr 999
        ret
3545 hidnplayr 1000
 
1001
 
9243 hidnplayr 1002
 
1003
align 16
1004
proc check_media_mii stdcall dev:dword
1005
 
1006
        spin_lock_irqsave
1007
 
1008
        mov     ebx, [dev]
1009
 
1010
        mov     ecx, 1  ;;;
1011
        mov     edx, MII_BMSR
1012
        call    mdio_read
1013
 
1014
        mov     ecx, 1  ;;;
1015
        mov     edx, MII_BMSR
1016
        call    mdio_read
1017
 
1018
        mov     ecx, eax
1019
        and     eax, BMSR_LSTATUS
1020
        shr     eax, 2
1021
        cmp     eax, [ebx + device.state]
1022
        jne     .changed
1023
 
1024
        spin_unlock_irqrestore
1025
        ret
1026
 
1027
  .changed:
1028
        test    eax, eax
1029
        jz      .update
1030
 
1031
        test    ecx, BMSR_ANEGCOMPLETE
1032
        jz      .update
1033
 
1034
        mov     ecx, 1  ;;;
1035
        mov     edx, MII_ADVERTISE
1036
        call    mdio_read
1037
        mov     esi, eax
1038
 
1039
        mov     ecx, 1  ;;;
1040
        mov     edx, MII_LPA
1041
        call    mdio_read
1042
        and     eax, esi
1043
 
1044
        test    eax, LPA_100FULL
1045
        jz      @f
1046
        mov     eax, ETH_LINK_SPEED_100M or ETH_LINK_FULL_DUPLEX
1047
        jmp     .update
1048
  @@:
1049
 
1050
        test    eax, LPA_100HALF
1051
        jz      @f
1052
        mov     eax, ETH_LINK_SPEED_100M
1053
        jmp     .update
1054
  @@:
1055
 
1056
        test    eax, LPA_10FULL
1057
        jz      @f
1058
        mov     eax, ETH_LINK_SPEED_10M or ETH_LINK_FULL_DUPLEX
1059
        jmp     .update
1060
  @@:
1061
 
1062
        test    eax, LPA_10HALF
1063
        jz      @f
1064
        mov     eax, ETH_LINK_SPEED_10M
1065
        jmp     .update
1066
  @@:
1067
 
1068
        mov     eax, ETH_LINK_UNKNOWN
1069
 
1070
  .update:
1071
        mov     [ebx + device.state], eax
1072
        invoke  NetLinkChanged
1073
 
1074
 
1075
        spin_unlock_irqrestore
1076
        ret
1077
 
1078
 
1079
endp
1080
 
1081
 
3545 hidnplayr 1082
align 4
1083
cmd_wait:
1084
 
1085
        in      al, dx
1086
        test    al, al
1087
        jnz     cmd_wait
1088
 
1089
        ret
1090
 
1091
 
1092
 
1093
align 4
1094
ee_read:        ; esi = address to read
1095
 
3845 hidnplayr 1096
        DEBUGF  1,"Eeprom read from 0x%x\n", esi
3545 hidnplayr 1097
 
4581 hidnplayr 1098
        set_io  [ebx + device.io_addr], 0
5562 hidnplayr 1099
        set_io  [ebx + device.io_addr], REG_EEPROM
3545 hidnplayr 1100
 
1101
;-----------------------------------------------------
1102
; Prepend start bit + read opcode to the address field
1103
; and shift it to the very left bits of esi
1104
 
1105
        mov     cl, 29
4581 hidnplayr 1106
        sub     cl, [ebx + device.ee_bus_width]
3545 hidnplayr 1107
        shl     esi, cl
1108
        or      esi, EE_READ shl 29
1109
 
4581 hidnplayr 1110
        movzx   ecx, [ebx + device.ee_bus_width]
3545 hidnplayr 1111
        add     ecx, 3
1112
 
6717 hidnplayr 1113
        mov     ax, 0x4800 + EE_CS
1114
        out     dx, ax
5247 hidnplayr 1115
        call    udelay
3545 hidnplayr 1116
 
1117
;-----------------------
1118
; Write this to the chip
1119
 
1120
  .loop:
6717 hidnplayr 1121
        mov     al, EE_CS
3545 hidnplayr 1122
        shl     esi, 1
1123
        jnc     @f
1124
        or      al, EE_DI
1125
       @@:
1126
        out     dx, al
5247 hidnplayr 1127
        call    udelay
3545 hidnplayr 1128
 
6717 hidnplayr 1129
        or      al, EE_SK
3545 hidnplayr 1130
        out     dx, al
5247 hidnplayr 1131
        call    udelay
3545 hidnplayr 1132
 
1133
        loop    .loop
1134
 
1135
;------------------------------
1136
; Now read the data from eeprom
1137
 
1138
        xor     esi, esi
1139
        mov     ecx, 16
1140
 
1141
  .loop2:
1142
        shl     esi, 1
6717 hidnplayr 1143
        mov     al, EE_CS
3545 hidnplayr 1144
        out     dx, al
5247 hidnplayr 1145
        call    udelay
3545 hidnplayr 1146
 
6717 hidnplayr 1147
        or      al, EE_SK
1148
        out     dx, al
1149
        call    udelay
1150
 
3545 hidnplayr 1151
        in      al, dx
1152
        test    al, EE_DO
1153
        jz      @f
1154
        inc     esi
1155
       @@:
1156
 
1157
        loop    .loop2
1158
 
1159
;-----------------------
1160
; de-activate the eeprom
1161
 
6717 hidnplayr 1162
        xor     al, al
1163
        out     dx, al
3545 hidnplayr 1164
 
3845 hidnplayr 1165
        DEBUGF  1,"0x%x\n", esi:4
3545 hidnplayr 1166
        ret
1167
 
1168
 
1169
 
1170
align 4
1171
ee_write:       ; esi = address to write to, di = data
1172
 
1173
        DEBUGF  1,"Eeprom write 0x%x to 0x%x\n", di, esi
1174
 
4581 hidnplayr 1175
        set_io  [ebx + device.io_addr], 0
5562 hidnplayr 1176
        set_io  [ebx + device.io_addr], REG_EEPROM
3545 hidnplayr 1177
 
1178
;-----------------------------------------------------
1179
; Prepend start bit + write opcode to the address field
1180
; and shift it to the very left bits of esi
1181
 
1182
        mov     cl, 29
4581 hidnplayr 1183
        sub     cl, [ebx + device.ee_bus_width]
3545 hidnplayr 1184
        shl     esi, cl
1185
        or      esi, EE_WRITE shl 29
1186
 
4581 hidnplayr 1187
        movzx   ecx, [ebx + device.ee_bus_width]
3545 hidnplayr 1188
        add     ecx, 3
1189
 
6717 hidnplayr 1190
        mov     ax, 0x4800 + EE_CS       ; enable chip
1191
        out     dx, ax
3545 hidnplayr 1192
 
1193
;-----------------------
1194
; Write this to the chip
1195
 
1196
  .loop:
6717 hidnplayr 1197
        mov     al, EE_CS
3545 hidnplayr 1198
        shl     esi, 1
1199
        jnc     @f
1200
        or      al, EE_DI
1201
       @@:
1202
        out     dx, al
5247 hidnplayr 1203
        call    udelay
3545 hidnplayr 1204
 
6717 hidnplayr 1205
        or      al, EE_SK
3545 hidnplayr 1206
        out     dx, al
5247 hidnplayr 1207
        call    udelay
3545 hidnplayr 1208
 
1209
        loop    .loop
1210
 
1211
;-----------------------------
1212
; Now write the data to eeprom
1213
 
1214
        mov     ecx, 16
1215
 
1216
  .loop2:
6717 hidnplayr 1217
        mov     al, EE_CS
3545 hidnplayr 1218
        shl     di, 1
1219
        jnc     @f
1220
        or      al, EE_DI
1221
       @@:
1222
        out     dx, al
5247 hidnplayr 1223
        call    udelay
3545 hidnplayr 1224
 
6717 hidnplayr 1225
        or      al, EE_SK
3545 hidnplayr 1226
        out     dx, al
5247 hidnplayr 1227
        call    udelay
3545 hidnplayr 1228
 
1229
        loop    .loop2
1230
 
1231
;-----------------------
1232
; de-activate the eeprom
1233
 
1234
        xor     al, al
1235
        out     dx, al
1236
 
1237
 
1238
        ret
1239
 
1240
 
1241
 
1242
align 4
1243
ee_get_width:
1244
 
4581 hidnplayr 1245
        set_io  [ebx + device.io_addr], 0
5562 hidnplayr 1246
        set_io  [ebx + device.io_addr], REG_EEPROM
3545 hidnplayr 1247
 
6717 hidnplayr 1248
        mov     ax, 0x4800 + EE_CS      ; activate eeprom
1249
        out     dx, ax
5247 hidnplayr 1250
        call    udelay
3545 hidnplayr 1251
 
1252
        mov     si, EE_READ shl 13
1253
        xor     ecx, ecx
1254
  .loop:
6717 hidnplayr 1255
        mov     al, EE_CS
3545 hidnplayr 1256
        shl     si, 1
1257
        jnc     @f
1258
        or      al, EE_DI
1259
       @@:
6717 hidnplayr 1260
        out     dx, ax
5247 hidnplayr 1261
        call    udelay
3545 hidnplayr 1262
 
6717 hidnplayr 1263
        or      al, EE_SK
1264
        out     dx, ax
5247 hidnplayr 1265
        call    udelay
3545 hidnplayr 1266
 
1267
        inc     ecx
1268
 
1269
        cmp     ecx, 15
1270
        jae     .give_up
1271
 
1272
        in      al, dx
1273
        test    al, EE_DO
1274
        jnz     .loop
1275
 
1276
        xor     al, al
6717 hidnplayr 1277
        out     dx, al                  ; de-activate eeprom
3545 hidnplayr 1278
 
6717 hidnplayr 1279
        sub     cl, 3                   ; dont count the opcode bits
4581 hidnplayr 1280
        mov     [ebx + device.ee_bus_width], cl
3845 hidnplayr 1281
        DEBUGF  1, "Eeprom width=%u bit\n", ecx
3545 hidnplayr 1282
 
3845 hidnplayr 1283
        ret
3545 hidnplayr 1284
 
3845 hidnplayr 1285
  .give_up:
1286
        DEBUGF  2, "Eeprom not found!\n"
1287
        xor     al, al
6717 hidnplayr 1288
        out     dx, al                  ; de-activate eeprom
3545 hidnplayr 1289
 
1290
        ret
1291
 
1292
 
5247 hidnplayr 1293
; Wait a minimum of 2µs
1294
udelay:
1295
        pusha
1296
        mov     esi, 1
1297
        invoke  Sleep
1298
        popa
3545 hidnplayr 1299
 
5247 hidnplayr 1300
        ret
1301
 
1302
 
1303
 
3545 hidnplayr 1304
; cx = phy addr
1305
; dx = phy reg addr
1306
 
1307
; ax = data
1308
 
1309
align 4
1310
mdio_read:
1311
 
1312
        DEBUGF  1,"MDIO read\n"
1313
 
1314
        shl     ecx, 21                 ; PHY addr
6717 hidnplayr 1315
        mov     eax, ecx
3545 hidnplayr 1316
        shl     edx, 16                 ; PHY reg addr
1317
        or      eax, edx
1318
        or      eax, 10b shl 26         ; read opcode
1319
 
4581 hidnplayr 1320
        set_io  [ebx + device.io_addr], 0
5562 hidnplayr 1321
        set_io  [ebx + device.io_addr], REG_MDI_CTRL
3545 hidnplayr 1322
        out     dx, eax
1323
 
1324
  .wait:
5247 hidnplayr 1325
        call    udelay
3545 hidnplayr 1326
        in      eax, dx
1327
        test    eax, 1 shl 28           ; ready bit
1328
        jz      .wait
1329
 
1330
        ret
1331
 
6717 hidnplayr 1332
 
1333
 
3545 hidnplayr 1334
; ax = data
1335
; cx = phy addr
1336
; dx = phy reg addr
1337
 
1338
; ax = data
1339
 
1340
align 4
1341
mdio_write:
1342
 
1343
        DEBUGF  1,"MDIO write\n"
1344
 
1345
        and     eax, 0xffff
1346
 
1347
        shl     ecx, 21                 ; PHY addr
1348
        shl     edx, 16                 ; PHY reg addr
1349
 
1350
        or      eax, ecx
1351
        or      eax, edx
1352
        or      eax, 01b shl 26         ; write opcode
1353
 
4581 hidnplayr 1354
        set_io  [ebx + device.io_addr], 0
5562 hidnplayr 1355
        set_io  [ebx + device.io_addr], REG_MDI_CTRL
3545 hidnplayr 1356
        out     dx, eax
1357
 
1358
  .wait:
5247 hidnplayr 1359
        call    udelay
3545 hidnplayr 1360
        in      eax, dx
1361
        test    eax, 1 shl 28           ; ready bit
1362
        jz      .wait
1363
 
1364
        ret
1365
 
1366
 
1367
align 4
6717 hidnplayr 1368
mac_read_eeprom:
3545 hidnplayr 1369
 
1370
        mov     esi, 0
1371
        call    ee_read
4581 hidnplayr 1372
        mov     word[ebx + device.mac], si
3545 hidnplayr 1373
 
1374
        mov     esi, 1
1375
        call    ee_read
4581 hidnplayr 1376
        mov     word[ebx + device.mac+2], si
3545 hidnplayr 1377
 
1378
        mov     esi, 2
1379
        call    ee_read
4581 hidnplayr 1380
        mov     word[ebx + device.mac+4], si
3545 hidnplayr 1381
 
1382
 
1383
        ret
1384
 
1385
 
1386
; End of code
1387
 
1388
 
4581 hidnplayr 1389
data fixups
1390
end data
1391
 
1392
include '../peimport.inc'
1393
 
4629 hidnplayr 1394
my_service      db 'I8255X', 0                    ; max 16 chars include zero
3545 hidnplayr 1395
devicename      db 'Intel Etherexpress pro/100', 0
1396
 
1397
confcmd_data    db 22, 0x08, 0, 0, 0, 0x80, 0x32, 0x03, 1
1398
                db 0, 0x2e, 0, 0x60, 0, 0xf2, 0x48, 0, 0x40, 0xf2
1399
                db 0x80, 0x3f, 0x05                                     ; 22 bytes total
1400
 
1401
 
1402
device_id_list:
6717 hidnplayr 1403
dw 0x1029
1404
dw 0x1030
1405
dw 0x1031
1406
dw 0x1032
1407
dw 0x1033
1408
dw 0x1034
1409
dw 0x1038
1410
dw 0x1039
1411
dw 0x103A
1412
dw 0x103B
1413
dw 0x103C
1414
dw 0x103D
1415
dw 0x103E
1416
dw 0x1050
1417
dw 0x1051
1418
dw 0x1052
1419
dw 0x1053
1420
dw 0x1054
1421
dw 0x1055
1422
dw 0x1056
1423
dw 0x1057
1424
dw 0x1059
1425
dw 0x1064
1426
dw 0x1065
1427
dw 0x1066
1428
dw 0x1067
1429
dw 0x1068
1430
dw 0x1069
1431
dw 0x106A
1432
dw 0x106B
1433
dw 0x1091
1434
dw 0x1092
1435
dw 0x1093
1436
dw 0x1094
1437
dw 0x1095
1438
dw 0x10fe
1439
dw 0x1209
1440
dw 0x1229
1441
dw 0x2449
1442
dw 0x2459
1443
dw 0x245D
1444
dw 0x27DC
3545 hidnplayr 1445
 
1446
DEVICE_IDs = ($ - device_id_list) / 2
1447
 
1448
include_debug_strings                           ; All data wich FDO uses will be included here
1449
 
4581 hidnplayr 1450
align 4
1451
devices         dd 0                              ; number of currently running devices
1452
device_list     rd MAX_DEVICES                    ; This list contains all pointers to device structures the driver is handling
3545 hidnplayr 1453