Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
3545 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                  ;;
8897 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
;;  AMD PCnet driver for KolibriOS                                  ;;
7
;;                                                                  ;;
8
;;  By hidnplayr & clevermouse                                      ;;
9
;;                                                                  ;;
10
;;  Based on the PCnet32 driver for MenuetOS, by Jarek Pelczar      ;;
11
;;                                                                  ;;
12
;;          GNU GENERAL PUBLIC LICENSE                              ;;
13
;;             Version 2, June 1991                                 ;;
14
;;                                                                  ;;
15
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
16
 
4532 hidnplayr 17
format PE DLL native
18
entry START
3545 hidnplayr 19
 
4532 hidnplayr 20
        CURRENT_API             = 0x0200
21
        COMPATIBLE_API          = 0x0100
22
        API_VERSION             = (COMPATIBLE_API shl 16) + CURRENT_API
3545 hidnplayr 23
 
8897 hidnplayr 24
; configureable area
4532 hidnplayr 25
 
8897 hidnplayr 26
        MAX_DEVICES             = 16    ; Maximum number of devices this driver may handle
3545 hidnplayr 27
 
8897 hidnplayr 28
        __DEBUG__               = 1     ; 1 = on, 0 = off
29
        __DEBUG_LEVEL__         = 2     ; 1 = verbose, 2 = errors only
3545 hidnplayr 30
 
8897 hidnplayr 31
        TX_RING_SIZE            = 32    ; Number of packets in send ring buffer
32
        RX_RING_SIZE            = 32    ; Number of packets in receive ring buffer
33
 
34
; end configureable area
35
 
4532 hidnplayr 36
section '.flat' readable writable executable
37
 
4467 hidnplayr 38
include '../struct.inc'
39
include '../macros.inc'
3545 hidnplayr 40
include '../proc32.inc'
41
include '../fdo.inc'
5074 hidnplayr 42
include '../netdrv.inc'
3545 hidnplayr 43
 
8897 hidnplayr 44
if (bsr TX_RING_SIZE)>(bsf TX_RING_SIZE)
45
  display 'TX_RING_SIZE must be a power of two'
46
  err
47
end if
3545 hidnplayr 48
 
8897 hidnplayr 49
if (bsr RX_RING_SIZE)>(bsf RX_RING_SIZE)
50
  display 'RX_RING_SIZE must be a power of two'
51
  err
52
end if
53
 
3545 hidnplayr 54
        PORT_AUI                = 0x00
55
        PORT_10BT               = 0x01
56
        PORT_GPSI               = 0x02
57
        PORT_MII                = 0x03
58
        PORT_PORTSEL            = 0x03
59
        PORT_ASEL               = 0x04
60
        PORT_100                = 0x40
61
        PORT_FD                 = 0x80
62
 
63
        DMA_MASK                = 0xffffffff
64
 
8897 hidnplayr 65
        TX_RING_LEN_BITS        = ((bsf TX_RING_SIZE) shl 12)
66
        RX_RING_LEN_BITS        = ((bsf RX_RING_SIZE) shl 4)
3545 hidnplayr 67
 
68
        PKT_BUF_SZ              = 1544
69
 
70
        WIO_RDP                 = 0x10
71
        WIO_RAP                 = 0x12
72
        WIO_RESET               = 0x14
73
        WIO_BDP                 = 0x16
74
 
75
        DWIO_RDP                = 0x10
76
        DWIO_RAP                = 0x14
77
        DWIO_RESET              = 0x18
78
        DWIO_BDP                = 0x1C
79
 
80
; CSR registers
81
 
82
        CSR_CSR                 = 0x00
83
        CSR_IAB0                = 0x01
84
        CSR_IAB1                = 0x02
85
        CSR_IMR                 = 0x03
86
        CSR_TFEAT               = 0x04
87
        CSR_EXTCTL1             = 0x05
88
        CSR_DTBLLEN             = 0x06
89
        CSR_EXTCTL2             = 0x07
90
        CSR_MAR0                = 0x08
91
        CSR_MAR1                = 0x09
92
        CSR_MAR2                = 0x0A
93
        CSR_MAR3                = 0x0B
94
        CSR_PAR0                = 0x0C
95
        CSR_PAR1                = 0x0D
96
        CSR_PAR2                = 0x0E
97
        CSR_MODE                = 0x0F
98
        CSR_RXADDR0             = 0x18
99
        CSR_RXADDR1             = 0x19
100
        CSR_TXADDR0             = 0x1E
101
        CSR_TXADDR1             = 0x1F
102
        CSR_TXPOLL              = 0x2F
103
        CSR_RXPOLL              = 0x31
104
        CSR_RXRINGLEN           = 0x4C
105
        CSR_TXRINGLEN           = 0x4E
106
        CSR_DMACTL              = 0x50
107
        CSR_BUSTIMER            = 0x52
108
        CSR_MEMERRTIMEO         = 0x64
109
        CSR_ONNOWMISC           = 0x74
110
        CSR_ADVFEAT             = 0x7A
111
        CSR_MACCFG              = 0x7D
112
        CSR_CHIPID0             = 0x58
113
        CSR_CHIPID1             = 0x59
114
 
115
; Control and Status Register (CSR0)
116
 
5004 hidnplayr 117
        CSR_INIT                = 0x0001 ;1 shl 0
118
        CSR_START               = 0x0002 ;1 shl 1
119
        CSR_STOP                = 0x0004 ;1 shl 2
120
        CSR_TX                  = 0x0008 ;1 shl 3
121
        CSR_TXON                = 0x0010 ;1 shl 4
122
        CSR_RXON                = 0x0020 ;1 shl 5
123
        CSR_INTEN               = 0x0040 ;1 shl 6
124
        CSR_INTR                = 0x0080 ;1 shl 7
125
        CSR_IDONE               = 0x0100 ;1 shl 8
126
        CSR_TINT                = 0x0200 ;1 shl 9
127
        CSR_RINT                = 0x0400 ;1 shl 10
128
        CSR_MERR                = 0x0800 ;1 shl 11
129
        CSR_MISS                = 0x1000 ;1 shl 12
130
        CSR_CERR                = 0x2000 ;1 shl 13
3545 hidnplayr 131
 
132
; Interrupt masks and deferral control (CSR3)
133
 
134
        IMR_BSWAP               = 0x0004
135
        IMR_ENMBA               = 0x0008  ; enable modified backoff alg
136
        IMR_DXMT2PD             = 0x0010
137
        IMR_LAPPEN              = 0x0020  ; lookahead packet processing enb
138
        IMR_DXSUFLO             = 0x0040  ; disable TX stop on underflow
139
        IMR_IDONE               = 0x0100
140
        IMR_TINT                = 0x0200
141
        IMR_RINT                = 0x0400
142
        IMR_MERR                = 0x0800
143
        IMR_MISS                = 0x1000
144
 
5004 hidnplayr 145
        ; Masked interrupts will be disabled.
146
        IMR                     = 0 ;IMR_IDONE ;or IMR_TINT or IMR_RINT or IMR_MERR or IMR_MISS
3545 hidnplayr 147
 
148
; Test and features control (CSR4)
149
 
150
        TFEAT_TXSTRTMASK        = 0x0004
151
        TFEAT_TXSTRT            = 0x0008
152
        TFEAT_RXCCOFLOWM        = 0x0010  ; Rx collision counter oflow
153
        TFEAT_RXCCOFLOW         = 0x0020
154
        TFEAT_UINT              = 0x0040
155
        TFEAT_UINTREQ           = 0x0080
156
        TFEAT_MISSOFLOWM        = 0x0100
157
        TFEAT_MISSOFLOW         = 0x0200
158
        TFEAT_STRIP_FCS         = 0x0400
159
        TFEAT_PAD_TX            = 0x0800
160
        TFEAT_TXDPOLL           = 0x1000
161
        TFEAT_DMAPLUS           = 0x4000
162
 
163
; Extended control and interrupt 1 (CSR5)
164
 
165
        EXTCTL1_SPND            = 0x0001  ; suspend
166
        EXTCTL1_MPMODE          = 0x0002  ; magic packet mode
167
        EXTCTL1_MPENB           = 0x0004  ; magic packet enable
168
        EXTCTL1_MPINTEN         = 0x0008  ; magic packet interrupt enable
169
        EXTCTL1_MPINT           = 0x0010  ; magic packet interrupt
170
        EXTCTL1_MPPLBA          = 0x0020  ; magic packet phys. logical bcast
171
        EXTCTL1_EXDEFEN         = 0x0040  ; excessive deferral interrupt enb.
172
        EXTCTL1_EXDEF           = 0x0080  ; excessive deferral interrupt
173
        EXTCTL1_SINTEN          = 0x0400  ; system interrupt enable
174
        EXTCTL1_SINT            = 0x0800  ; system interrupt
175
        EXTCTL1_LTINTEN         = 0x4000  ; last TX interrupt enb
176
        EXTCTL1_TXOKINTD        = 0x8000  ; TX OK interrupt disable
177
 
178
; RX/TX descriptor len (CSR6)
179
 
180
        DTBLLEN_RLEN            = 0x0F00
181
        DTBLLEN_TLEN            = 0xF000
182
 
183
; Extended control and interrupt 2 (CSR7)
184
 
185
        EXTCTL2_MIIPDTINTE      = 0x0001
186
        EXTCTL2_MIIPDTINT       = 0x0002
187
        EXTCTL2_MCCIINTE        = 0x0004
188
        EXTCTL2_MCCIINT         = 0x0008
189
        EXTCTL2_MCCINTE         = 0x0010
190
        EXTCTL2_MCCINT          = 0x0020
191
        EXTCTL2_MAPINTE         = 0x0040
192
        EXTCTL2_MAPINT          = 0x0080
193
        EXTCTL2_MREINTE         = 0x0100
194
        EXTCTL2_MREINT          = 0x0200
195
        EXTCTL2_STINTE          = 0x0400
196
        EXTCTL2_STINT           = 0x0800
197
        EXTCTL2_RXDPOLL         = 0x1000
198
        EXTCTL2_RDMD            = 0x2000
199
        EXTCTL2_RXFRTG          = 0x4000
200
        EXTCTL2_FASTSPNDE       = 0x8000
201
 
202
; Mode (CSR15)
203
 
204
        MODE_RXD                = 0x0001  ; RX disable
205
        MODE_TXD                = 0x0002  ; TX disable
206
        MODE_LOOP               = 0x0004  ; loopback enable
207
        MODE_TXCRCD             = 0x0008
208
        MODE_FORCECOLL          = 0x0010
209
        MODE_RETRYD             = 0x0020
210
        MODE_INTLOOP            = 0x0040
211
        MODE_PORTSEL            = 0x0180
212
        MODE_RXVPAD             = 0x2000
213
        MODE_RXNOBROAD          = 0x4000
214
        MODE_PROMISC            = 0x8000
215
 
216
; BCR (Bus Control Registers)
217
 
218
        BCR_MMRA                = 0x00    ; Master Mode Read Active
219
        BCR_MMW                 = 0x01    ; Master Mode Write Active
220
        BCR_MISCCFG             = 0x02
221
        BCR_LED0                = 0x04
222
        BCR_LED1                = 0x05
223
        BCR_LED2                = 0x06
224
        BCR_LED3                = 0x07
225
        BCR_DUPLEX              = 0x09
226
        BCR_BUSCTL              = 0x12
227
        BCR_EECTL               = 0x13
228
        BCR_SSTYLE              = 0x14
229
        BCR_PCILAT              = 0x16
230
        BCR_PCISUBVENID         = 0x17
231
        BCR_PCISUBSYSID         = 0x18
232
        BCR_SRAMSIZE            = 0x19
233
        BCR_SRAMBOUND           = 0x1A
234
        BCR_SRAMCTL             = 0x1B
235
        BCR_MIICTL              = 0x20
236
        BCR_MIIADDR             = 0x21
237
        BCR_MIIDATA             = 0x22
238
        BCR_PCIVENID            = 0x23
239
        BCR_PCIPCAP             = 0x24
240
        BCR_DATA0               = 0x25
241
        BCR_DATA1               = 0x26
242
        BCR_DATA2               = 0x27
243
        BCR_DATA3               = 0x28
244
        BCR_DATA4               = 0x29
245
        BCR_DATA5               = 0x2A
246
        BCR_DATA6               = 0x2B
247
        BCR_DATA7               = 0x2C
248
        BCR_ONNOWPAT0           = 0x2D
249
        BCR_ONNOWPAT1           = 0x2E
250
        BCR_ONNOWPAT2           = 0x2F
251
        BCR_PHYSEL              = 0x31
252
 
253
; RX status register
254
 
255
        RXSTAT_BPE              = 0x0080        ; bus parity error
256
        RXSTAT_ENP              = 0x0100        ; end of packet
257
        RXSTAT_STP              = 0x0200        ; start of packet
258
        RXSTAT_BUFF             = 0x0400        ; buffer error
259
        RXSTAT_CRC              = 0x0800        ; CRC error
260
        RXSTAT_OFLOW            = 0x1000        ; rx overrun
261
        RXSTAT_FRAM             = 0x2000        ; framing error
262
        RXSTAT_ERR              = 0x4000        ; error summary
263
        RXSTAT_OWN              = 0x8000
264
 
265
; TX status register
266
 
267
        TXSTAT_TRC              = 0x0000000F    ; transmit retries
268
        TXSTAT_RTRY             = 0x04000000    ; retry
269
        TXSTAT_LCAR             = 0x08000000    ; lost carrier
270
        TXSTAT_LCOL             = 0x10000000    ; late collision
271
        TXSTAT_EXDEF            = 0x20000000    ; excessive deferrals
272
        TXSTAT_UFLOW            = 0x40000000    ; transmit underrun
273
        TXSTAT_BUFF             = 0x80000000    ; buffer error
274
 
275
        TXCTL_OWN               = 0x8000
276
        TXCTL_ERR               = 0x4000        ; error summary
277
        TXCTL_ADD_FCS           = 0x2000        ; add FCS to pkt
278
        TXCTL_MORE_LTINT        = 0x1000
279
        TXCTL_ONE               = 0x0800
280
        TXCTL_DEF               = 0x0400
281
        TXCTL_STP               = 0x0200
282
        TXCTL_ENP               = 0x0100
283
        TXCTL_BPE               = 0x0080
284
 
285
        TXCTL_MBO               = 0x0000F000
286
        TXCTL_BUFSZ             = 0x00000FFF
287
 
288
        MAX_PHYS                = 32
289
 
290
 
8897 hidnplayr 291
; Pcnet configuration structure
292
struct  pcnet_init_block
3545 hidnplayr 293
 
4532 hidnplayr 294
        mode            dw ?
295
        tlen_rlen       dw ?
296
        phys_addr       dp ?
297
        reserved        dw ?
298
        filter          dq ?
299
        rx_ring_phys    dd ?
300
        tx_ring_phys    dd ?
8897 hidnplayr 301
ends
3545 hidnplayr 302
 
8897 hidnplayr 303
 
304
struct  device          ETH_DEVICE
305
 
4532 hidnplayr 306
        rb 0x100-($ and 0xff)   ; align 256
8897 hidnplayr 307
        init_block      pcnet_init_block
3545 hidnplayr 308
 
8897 hidnplayr 309
        rb 0x100-($ and 0xff)   ; align 256
4532 hidnplayr 310
        rx_ring         rb RX_RING_SIZE * sizeof.descriptor
3545 hidnplayr 311
 
4532 hidnplayr 312
        rb 0x100-($ and 0xff)   ; align 256
313
        tx_ring         rb TX_RING_SIZE * sizeof.descriptor
3545 hidnplayr 314
 
8897 hidnplayr 315
        cur_rx          dd ?
316
        cur_tx          dd ?
317
        last_tx         dd ?
318
 
4532 hidnplayr 319
        options         dd ?
320
        full_duplex     db ?
321
        chip_version    dw ?
322
        mii             db ?
323
        ltint           db ?
324
        dxsuflo         db ?
325
        fset            db ?
326
        fdx             db ?
3545 hidnplayr 327
 
4532 hidnplayr 328
        io_addr         dd ?
329
        irq_line        db ?
330
        pci_bus         dd ?
331
        pci_dev         dd ?
3545 hidnplayr 332
 
4532 hidnplayr 333
        phy             dw ?
3545 hidnplayr 334
 
8897 hidnplayr 335
        rb 0x100-($ and 0xff)   ; align 256
336
 
4532 hidnplayr 337
        read_csr        dd ?
338
        write_csr       dd ?
339
        read_bcr        dd ?
340
        write_bcr       dd ?
341
        read_rap        dd ?
342
        write_rap       dd ?
343
        sw_reset        dd ?
3545 hidnplayr 344
 
4532 hidnplayr 345
ends
3545 hidnplayr 346
 
4532 hidnplayr 347
struct  descriptor
3545 hidnplayr 348
 
4532 hidnplayr 349
        base            dd ?
350
        length          dw ?
351
        status          dw ?
352
        msg_length      dw ?
353
        misc            dw ?
354
        virtual         dd ?
3545 hidnplayr 355
 
4532 hidnplayr 356
ends
3545 hidnplayr 357
 
358
 
359
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
360
;;                        ;;
361
;; proc START             ;;
362
;;                        ;;
363
;; (standard driver proc) ;;
364
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
365
 
4532 hidnplayr 366
proc START c, reason:dword, cmdline:dword
3545 hidnplayr 367
 
4532 hidnplayr 368
        cmp     [reason], DRV_ENTRY
369
        jne     .fail
3545 hidnplayr 370
 
4532 hidnplayr 371
        DEBUGF  2,"Loading driver\n"
372
        invoke  RegService, my_service, service_proc
3545 hidnplayr 373
        ret
374
 
375
  .fail:
376
        xor eax, eax
377
        ret
378
 
379
endp
380
 
381
 
382
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
383
;;                        ;;
384
;; proc SERVICE_PROC      ;;
385
;;                        ;;
386
;; (standard driver proc) ;;
387
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
388
 
389
align 4
390
proc service_proc stdcall, ioctl:dword
391
 
392
        mov     edx, [ioctl]
4470 hidnplayr 393
        mov     eax, [edx + IOCTL.io_code]
3545 hidnplayr 394
 
395
;------------------------------------------------------
396
 
397
        cmp     eax, 0 ;SRV_GETVERSION
398
        jne     @F
399
 
4470 hidnplayr 400
        cmp     [edx + IOCTL.out_size], 4
3545 hidnplayr 401
        jb      .fail
4470 hidnplayr 402
        mov     eax, [edx + IOCTL.output]
3545 hidnplayr 403
        mov     [eax], dword API_VERSION
404
 
405
        xor     eax, eax
406
        ret
407
 
408
;------------------------------------------------------
409
  @@:
410
        cmp     eax, 1 ;SRV_HOOK
411
        jne     .fail
412
 
4532 hidnplayr 413
        cmp     [edx + IOCTL.inp_size], 3               ; Data input must be at least 3 bytes
3545 hidnplayr 414
        jb      .fail
415
 
4470 hidnplayr 416
        mov     eax, [edx + IOCTL.input]
4532 hidnplayr 417
        cmp     byte[eax], 1                            ; 1 means device number and bus number (pci) are given
3545 hidnplayr 418
        jne     .fail                                   ; other types arent supported for this card yet
419
 
420
; check if the device is already listed
421
 
422
        mov     ecx, [devices]
423
        test    ecx, ecx
424
        jz      .firstdevice
425
 
426
        mov     esi, device_list
4470 hidnplayr 427
;        mov     eax, [edx + IOCTL.input]                ; get the pci bus and device numbers
428
        mov     ax, [eax+1]                             ;
3545 hidnplayr 429
  .nextdevice:
430
        mov     ebx, [esi]
4532 hidnplayr 431
        cmp     al, byte[ebx + device.pci_bus]
3545 hidnplayr 432
        jne     @f
4532 hidnplayr 433
        cmp     ah, byte[ebx + device.pci_dev]
3545 hidnplayr 434
        je      .find_devicenum                         ; Device is already loaded, let's find it's device number
435
       @@:
436
        add     esi, 4
437
        loop    .nextdevice
438
 
439
; This device doesnt have its own eth_device structure yet, lets create one
440
 
441
  .firstdevice:
442
        cmp     [devices], MAX_DEVICES                  ; First check if the driver can handle one more card
443
        jae     .fail
444
 
4532 hidnplayr 445
        allocate_and_clear ebx, sizeof.device, .fail
3545 hidnplayr 446
 
447
; Fill in the direct call addresses into the struct
448
 
4532 hidnplayr 449
        mov     [ebx + device.reset], reset
450
        mov     [ebx + device.transmit], transmit
451
        mov     [ebx + device.unload], unload
452
        mov     [ebx + device.name], my_service
3545 hidnplayr 453
 
454
; save the pci bus and device numbers
455
 
4470 hidnplayr 456
        mov     eax, [edx + IOCTL.input]
3545 hidnplayr 457
        movzx   ecx, byte[eax+1]
4532 hidnplayr 458
        mov     [ebx + device.pci_bus], ecx
3545 hidnplayr 459
        movzx   ecx, byte[eax+2]
4532 hidnplayr 460
        mov     [ebx + device.pci_dev], ecx
3545 hidnplayr 461
 
462
; Now, it's time to find the base io addres of the PCI device
463
 
4532 hidnplayr 464
        stdcall PCI_find_io, [ebx + device.pci_bus], [ebx + device.pci_dev]
465
        mov     [ebx + device.io_addr], eax
3545 hidnplayr 466
 
467
; We've found the io address, find IRQ now
468
 
4532 hidnplayr 469
        invoke  PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.interrupt_line
470
        mov     [ebx + device.irq_line], al
3545 hidnplayr 471
 
472
        DEBUGF  1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
4532 hidnplayr 473
        [ebx + device.pci_dev]:1,[ebx + device.pci_bus]:1,[ebx + device.irq_line]:1,[ebx + device.io_addr]:4
3545 hidnplayr 474
 
475
; Ok, the eth_device structure is ready, let's probe the device
476
; Because initialization fires IRQ, IRQ handler must be aware of this device
477
        mov     eax, [devices]                                          ; Add the device structure to our device list
478
        mov     [device_list+4*eax], ebx                                ; (IRQ handler uses this list to find device)
479
        inc     [devices]                                               ;
480
 
481
        call    probe                                                   ; this function will output in eax
482
        test    eax, eax
483
        jnz     .destroy                                                ; If an error occured, exit
484
 
4532 hidnplayr 485
        mov     [ebx + device.type], NET_TYPE_ETH
486
        invoke  NetRegDev
3545 hidnplayr 487
        cmp     eax, -1
488
        je      .destroy
489
 
490
        ret
491
 
492
; If the device was already loaded, find the device number and return it in eax
493
 
494
  .find_devicenum:
495
        DEBUGF  1,"Trying to find device number of already registered device\n"
4532 hidnplayr 496
        invoke  NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
3545 hidnplayr 497
                                                                        ; into a device number in edi
498
        mov     eax, edi                                                ; Application wants it in eax instead
499
        DEBUGF  1,"Kernel says: %u\n", eax
500
        ret
501
 
502
; If an error occured, remove all allocated data and exit (returning -1 in eax)
503
 
504
  .destroy:
505
        ; todo: reset device into virgin state
5522 hidnplayr 506
        add     eax, NET_BUFF.data
3545 hidnplayr 507
        dec     [devices]
508
  .err:
3855 hidnplayr 509
        DEBUGF  2,"Error, removing all data !\n"
4532 hidnplayr 510
        invoke  KernelFree, ebx
3545 hidnplayr 511
 
512
  .fail:
513
        or      eax, -1
514
        ret
515
 
516
;------------------------------------------------------
517
endp
518
 
519
 
520
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
521
;;                                                                        ;;
522
;;        Actual Hardware dependent code starts here                      ;;
523
;;                                                                        ;;
524
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
525
 
526
align 4
527
unload:
528
        ; TODO: (in this particular order)
529
        ;
530
        ; - Stop the device
531
        ; - Detach int handler
4532 hidnplayr 532
        ; - Remove device from local list (device_list)
3545 hidnplayr 533
        ; - call unregister function in kernel
534
        ; - Remove all allocated structures and buffers the card used
535
 
5522 hidnplayr 536
        or      eax, -1
537
        ret
3545 hidnplayr 538
 
539
 
540
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
541
;;
542
;;  probe: enables the device (if it really is a PCnet device)
543
;;
544
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
545
 
546
align 4
547
probe:
548
 
4532 hidnplayr 549
        mov     edx, [ebx + device.io_addr]
3545 hidnplayr 550
 
551
        call    wio_reset
552
 
553
        xor     ecx, ecx
554
        call    wio_read_csr
555
        cmp     eax, 4
556
        jne     .try_dwio
557
 
558
        ; Try Word I/O
559
        mov     ax, 88
560
        add     edx, WIO_RAP
561
        out     dx, ax
562
        nop
563
        nop
564
        in      ax, dx
565
        sub     edx, WIO_RAP
566
        cmp     ax, 88
567
        jne     .try_dwio
568
 
569
        call    switch_to_wio
570
 
571
        jmp     .L1
572
 
573
  .try_dwio:
574
        call    dwio_reset
575
 
576
        xor     ecx, ecx
577
        call    dwio_read_csr
578
        cmp     eax, 4
579
        jne     .no_dev
580
 
581
        ; Try Dword I/O
582
        add     edx, DWIO_RAP
583
        mov     eax, 88
584
        out     dx, eax
585
        nop
586
        nop
587
        in      eax, dx
588
        sub     edx, DWIO_RAP
589
        and     eax, 0xffff
590
        cmp     eax, 88
591
        jne     .no_dev
592
 
593
        call    switch_to_dwio
594
 
595
        jmp     .L1
596
 
597
  .no_dev:
4532 hidnplayr 598
        DEBUGF  2,"device not found!\n"
3545 hidnplayr 599
        mov     eax, 1
600
        ret
601
 
602
  .L1:
603
        mov     ecx, CSR_CHIPID0
4532 hidnplayr 604
        call    [ebx + device.read_csr]
3545 hidnplayr 605
 
606
        mov     esi, eax
607
        shr     esi, 12
608
 
609
        and     ax, 0xfff
610
        cmp     ax, 3
611
        jne     .no_dev
612
 
613
        mov     ecx, CSR_CHIPID1
4532 hidnplayr 614
        call    [ebx + device.read_csr]
3545 hidnplayr 615
        shl     eax, 4
616
        or      eax, esi
4532 hidnplayr 617
        mov     [ebx + device.chip_version], ax
3545 hidnplayr 618
 
4532 hidnplayr 619
        mov     [ebx + device.fdx], 0
620
        mov     [ebx + device.mii], 0
621
        mov     [ebx + device.fset], 0
622
        mov     [ebx + device.dxsuflo], 0
623
        mov     [ebx + device.ltint], 0
3545 hidnplayr 624
 
625
        cmp     ax, 0x2420
626
        je      .L2
627
        cmp     ax, 0x2430
628
        je      .L2
629
 
4532 hidnplayr 630
        mov     [ebx + device.fdx], 1
3545 hidnplayr 631
 
632
        cmp     ax, 0x2621
633
        je      .L4
634
        cmp     ax, 0x2623
635
        je      .L5
636
        cmp     ax, 0x2624
637
        je      .L6
638
        cmp     ax, 0x2625
639
        je      .L7
640
        cmp     ax, 0x2626
641
        je      .L8
642
        cmp     ax, 0x2627
643
        je      .L9
644
 
5065 hidnplayr 645
        DEBUGF  2,"Invalid chip rev\n"
3545 hidnplayr 646
        jmp     .no_dev
647
  .L2:
4532 hidnplayr 648
        mov     [ebx + device.name], device_l2
3545 hidnplayr 649
        jmp     .L10
650
  .L4:
4532 hidnplayr 651
        mov     [ebx + device.name], device_l4
652
;        mov     [ebx + device.fdx], 1
3545 hidnplayr 653
        jmp     .L10
654
  .L5:
4532 hidnplayr 655
        mov     [ebx + device.name], device_l5
656
;        mov     [ebx + device.fdx], 1
657
        mov     [ebx + device.mii], 1
658
        mov     [ebx + device.fset], 1
659
        mov     [ebx + device.ltint], 1
3545 hidnplayr 660
        jmp     .L10
661
  .L6:
4532 hidnplayr 662
        mov     [ebx + device.name], device_l6
663
;        mov     [ebx + device.fdx], 1
664
        mov     [ebx + device.mii], 1
665
        mov     [ebx + device.fset], 1
3545 hidnplayr 666
        jmp     .L10
667
  .L7:
4532 hidnplayr 668
        mov     [ebx + device.name], device_l7
669
;        mov     [ebx + device.fdx], 1
670
        mov     [ebx + device.mii], 1
3545 hidnplayr 671
        jmp     .L10
672
  .L8:
4532 hidnplayr 673
        mov     [ebx + device.name], device_l8
674
;        mov     [ebx + device.fdx], 1
3545 hidnplayr 675
        mov     ecx, CSR_RXPOLL
4532 hidnplayr 676
        call    dword [ebx + device.read_bcr]
677
        call    dword [ebx + device.write_bcr]
3545 hidnplayr 678
        jmp     .L10
679
  .L9:
4532 hidnplayr 680
        mov     [ebx + device.name], device_l9
681
;        mov     [ebx + device.fdx], 1
682
        mov     [ebx + device.mii], 1
3545 hidnplayr 683
  .L10:
4532 hidnplayr 684
        DEBUGF  1,"device name: %s\n", [ebx + device.name]
3545 hidnplayr 685
 
4532 hidnplayr 686
        cmp     [ebx + device.fset], 1
3545 hidnplayr 687
        jne     .L11
688
        mov     ecx, BCR_BUSCTL
4532 hidnplayr 689
        call    [ebx + device.read_bcr]
3545 hidnplayr 690
        or      eax, 0x800
4532 hidnplayr 691
        call    [ebx + device.write_bcr]
3545 hidnplayr 692
 
693
        mov     ecx, CSR_DMACTL
5617 hidnplayr 694
;        call    [ebx + device.read_csr]
3545 hidnplayr 695
        mov     eax, 0xc00
4532 hidnplayr 696
        call    [ebx + device.write_csr]
3545 hidnplayr 697
 
4532 hidnplayr 698
        mov     [ebx + device.dxsuflo],1
699
        mov     [ebx + device.ltint],1
3545 hidnplayr 700
  .L11:
701
 
4532 hidnplayr 702
; Make the device a bus master
703
        invoke  PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command
704
        or      al, PCI_CMD_MASTER
705
        invoke  PciWrite32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command, eax
3545 hidnplayr 706
 
4532 hidnplayr 707
        mov     [ebx + device.options], PORT_ASEL
8897 hidnplayr 708
        mov     [ebx + device.init_block.mode], MODE_RXD + MODE_TXD     ; disable receive and transmit
709
        mov     [ebx + device.init_block.tlen_rlen], (TX_RING_LEN_BITS or RX_RING_LEN_BITS)
3545 hidnplayr 710
 
8897 hidnplayr 711
        mov     dword[ebx + device.init_block.filter], 0
712
        mov     dword[ebx + device.init_block.filter+4], 0
3545 hidnplayr 713
 
714
align 4
715
reset:
716
 
717
; attach int handler
718
 
4532 hidnplayr 719
        movzx   eax, [ebx + device.irq_line]
3545 hidnplayr 720
        DEBUGF  1,"Attaching int handler to irq %x\n", eax:1
4532 hidnplayr 721
        invoke  AttachIntHandler, eax, int_handler, ebx
3545 hidnplayr 722
        test    eax, eax
723
        jnz     @f
3855 hidnplayr 724
        DEBUGF  2,"Could not attach int handler!\n"
4532 hidnplayr 725
        or      eax, -1
726
        ret
3545 hidnplayr 727
  @@:
728
 
4532 hidnplayr 729
        mov     edx, [ebx + device.io_addr]
730
        call    [ebx + device.sw_reset]
3545 hidnplayr 731
 
732
        ; Switch pcnet32 to 32bit mode
733
        mov     ecx, BCR_SSTYLE
734
        mov     eax, 2
4532 hidnplayr 735
        call    [ebx + device.write_bcr]
3545 hidnplayr 736
 
737
        ; set/reset autoselect bit
738
        mov     ecx, BCR_MISCCFG
4532 hidnplayr 739
        call    [ebx + device.read_bcr]
3545 hidnplayr 740
        and     eax, not 2
4532 hidnplayr 741
        test    [ebx + device.options], PORT_ASEL
3545 hidnplayr 742
        jz      @f
743
        or      eax, 2
744
  @@:
4532 hidnplayr 745
        call    [ebx + device.write_bcr]
3545 hidnplayr 746
 
747
        ; Handle full duplex setting
4532 hidnplayr 748
        cmp     byte [ebx + device.full_duplex], 0
3545 hidnplayr 749
        je      .duplex_ok
750
        mov     ecx, BCR_DUPLEX
4532 hidnplayr 751
        call    [ebx + device.read_bcr]
3545 hidnplayr 752
        and     eax, not 3
4532 hidnplayr 753
        test    [ebx + device.options], PORT_FD
3545 hidnplayr 754
        jz      @f
755
        or      eax, 1
4532 hidnplayr 756
        cmp     [ebx + device.options], PORT_FD or PORT_AUI
3545 hidnplayr 757
        jne     .set_duplex
758
        or      eax, 2
759
        jmp     .set_duplex
760
  @@:
4532 hidnplayr 761
        test    [ebx + device.options], PORT_ASEL
3545 hidnplayr 762
        jz      .set_duplex
4532 hidnplayr 763
        cmp     [ebx + device.chip_version], 0x2627
3545 hidnplayr 764
        jne     .set_duplex
765
        or      eax, 3
766
  .set_duplex:
767
        mov     ecx, BCR_DUPLEX
4532 hidnplayr 768
        call    [ebx + device.write_bcr]
3545 hidnplayr 769
  .duplex_ok:
770
 
771
        ; set/reset GPSI bit in test register
772
        mov     ecx, 124
4532 hidnplayr 773
        call    [ebx + device.read_csr]
774
        mov     ecx, [ebx + device.options]
3545 hidnplayr 775
        and     ecx, PORT_PORTSEL
776
        cmp     ecx, PORT_GPSI
777
        jne     @f
778
        or      eax, 0x10
779
  @@:
4532 hidnplayr 780
        call    [ebx + device.write_csr]
781
        cmp     [ebx + device.mii], 0
3545 hidnplayr 782
        je      .L6
4532 hidnplayr 783
        test    [ebx + device.options], PORT_ASEL
3545 hidnplayr 784
        jnz     .L6
785
        mov     ecx, BCR_MIICTL
4532 hidnplayr 786
        call    [ebx + device.read_bcr]
3545 hidnplayr 787
        and     eax, not 0x38
4532 hidnplayr 788
        test    [ebx + device.options], PORT_FD
3545 hidnplayr 789
        jz      @f
790
        or      eax, 0x10
791
  @@:
4532 hidnplayr 792
        test    [ebx + device.options], PORT_100
3545 hidnplayr 793
        jz      @f
794
        or      eax, 0x08
795
  @@:
4532 hidnplayr 796
        call    [ebx + device.write_bcr]
3545 hidnplayr 797
        jmp     .L9
798
  .L6:
4532 hidnplayr 799
        test    [ebx + device.options], PORT_ASEL
3545 hidnplayr 800
        jz      .L9
801
        mov     ecx, BCR_MIICTL
3855 hidnplayr 802
        DEBUGF  1,"ASEL, enable auto-negotiation\n"
4532 hidnplayr 803
        call    [ebx + device.read_bcr]
3545 hidnplayr 804
        and     eax, not 0x98
805
        or      eax, 0x20
4532 hidnplayr 806
        call    [ebx + device.write_bcr]
3545 hidnplayr 807
  .L9:
4532 hidnplayr 808
        cmp     [ebx + device.ltint], 0
3545 hidnplayr 809
        je      @f
810
        mov     ecx, 5
4532 hidnplayr 811
        call    [ebx + device.read_csr]
3545 hidnplayr 812
        or      eax, (1 shl 14)
4532 hidnplayr 813
        call    [ebx + device.write_csr]
3545 hidnplayr 814
  @@:
4532 hidnplayr 815
        mov     eax, [ebx + device.options]
3545 hidnplayr 816
        and     eax, PORT_PORTSEL
817
        shl     eax, 7
8897 hidnplayr 818
        mov     [ebx + device.init_block.mode], ax
819
        mov     dword [ebx + device.init_block.filter], -1
820
        mov     dword [ebx + device.init_block.filter+4], -1
3545 hidnplayr 821
 
822
 
823
 
824
;-----------------------------
825
 
4532 hidnplayr 826
        test    [ebx + device.mii], 1
3545 hidnplayr 827
        jz      .no_mii
828
 
4532 hidnplayr 829
        mov     [ebx + device.phy], 0
3545 hidnplayr 830
 
831
  .mii_loop:
832
        mov     ecx, MII_PHYSID1
833
        call    mdio_read
834
        cmp     ax, 0xffff
835
        je      .next
836
 
837
        DEBUGF  1, "0x%x\n", ax
838
 
839
        mov     ecx, MII_PHYSID2
840
        call    mdio_read
841
        cmp     ax, 0xffff
842
        je      .next
843
 
844
        DEBUGF  1, "0x%x\n", ax
845
 
846
        jmp     .got_phy
847
 
4532 hidnplayr 848
        cmp     [ebx + device.phy], 31
3545 hidnplayr 849
        jne     .next
4532 hidnplayr 850
        mov     ax, [ebx + device.chip_version]
3545 hidnplayr 851
        inc     ax
852
        and     ax, 0xfffe
853
        cmp     ax, 0x2624              ; 79c971 & 79c972 have phantom phy at id 31
854
        je      .got_phy
855
 
856
  .next:
4532 hidnplayr 857
        inc     [ebx + device.phy]
858
        cmp     [ebx + device.phy], MAX_PHYS
3545 hidnplayr 859
        jb      .mii_loop
860
 
3855 hidnplayr 861
        DEBUGF  2, "No PHY found!\n"
3545 hidnplayr 862
        or      eax, -1
863
        ret
864
 
865
  .got_phy:
4532 hidnplayr 866
        DEBUGF  1, "Found PHY at 0x%x\n", [ebx + device.phy]:4
3545 hidnplayr 867
 
868
  .no_mii:
869
 
870
;-----------------------------------------------
871
 
872
        call    read_mac
873
 
4532 hidnplayr 874
        lea     esi, [ebx + device.mac]
8897 hidnplayr 875
        lea     edi, [ebx + device.init_block.phys_addr]
3545 hidnplayr 876
        movsd
877
        movsw
878
 
879
        call    init_ring
5522 hidnplayr 880
        test    eax, eax
881
        jnz     .fail
3545 hidnplayr 882
 
8897 hidnplayr 883
        mov     edx, [ebx + device.io_addr]     ; init ring destroys edx
3545 hidnplayr 884
 
8897 hidnplayr 885
        lea     eax, [ebx + device.init_block]
4532 hidnplayr 886
        invoke  GetPhysAddr
3545 hidnplayr 887
        push    eax
888
        and     eax, 0xffff
8897 hidnplayr 889
        mov     ecx, CSR_IAB0
4532 hidnplayr 890
        call    [ebx + device.write_csr]
3545 hidnplayr 891
        pop     eax
892
        shr     eax, 16
8897 hidnplayr 893
        mov     ecx, CSR_IAB1
4532 hidnplayr 894
        call    [ebx + device.write_csr]
3545 hidnplayr 895
 
8897 hidnplayr 896
        mov     ecx, CSR_TFEAT
897
        mov     eax, 0x0915                     ; Auto TX PAD ?
4532 hidnplayr 898
        call    [ebx + device.write_csr]
3545 hidnplayr 899
 
900
; Set the interrupt mask
901
        mov     ecx, CSR_IMR
902
        mov     eax, IMR
4532 hidnplayr 903
        call    [ebx + device.write_csr]
3545 hidnplayr 904
 
905
; Initialise the device
906
        xor     ecx, ecx
907
        mov     eax, CSR_INIT
4532 hidnplayr 908
        call    [ebx + device.write_csr]
3545 hidnplayr 909
 
910
        mov     esi, 100
911
;        xor     ecx, ecx
912
  @@:
4532 hidnplayr 913
        call    [ebx + device.read_csr]
3545 hidnplayr 914
        test    ax, CSR_IDONE
915
        jnz     @f
916
 
917
        dec     esi
918
        jnz     @r
3855 hidnplayr 919
        DEBUGF  2,"Initialize timeout!\n"
3545 hidnplayr 920
  @@:
921
 
922
; Start the device and enable interrupts
923
        xor     ecx, ecx
924
        mov     eax, CSR_START + CSR_INTEN
4532 hidnplayr 925
        call    [ebx + device.write_csr]
3545 hidnplayr 926
 
927
; Set the mtu, kernel will be able to send now
4532 hidnplayr 928
        mov     [ebx + device.mtu], 1514
3545 hidnplayr 929
 
930
; get link status
4580 hidnplayr 931
        mov     [ebx + device.state], ETH_LINK_UNKNOWN
3545 hidnplayr 932
 
933
        call    check_media
934
 
3855 hidnplayr 935
        DEBUGF  1,"reset complete\n"
3545 hidnplayr 936
        xor     eax, eax
5522 hidnplayr 937
  .fail:
3545 hidnplayr 938
        ret
939
 
940
 
941
align 4
942
init_ring:
943
 
3855 hidnplayr 944
        DEBUGF  1,"init ring\n"
3545 hidnplayr 945
 
4532 hidnplayr 946
        lea     edi, [ebx + device.rx_ring]
3545 hidnplayr 947
        mov     eax, edi
4532 hidnplayr 948
        invoke  GetPhysAddr
8897 hidnplayr 949
        mov     [ebx + device.init_block.rx_ring_phys], eax
3545 hidnplayr 950
        mov     ecx, RX_RING_SIZE
951
  .rx_init:
952
        push    ecx
5522 hidnplayr 953
        invoke  NetAlloc, PKT_BUF_SZ+NET_BUFF.data
3545 hidnplayr 954
        pop     ecx
5522 hidnplayr 955
        test    eax, eax
956
        jz      .out_of_mem
3545 hidnplayr 957
        mov     [edi + descriptor.virtual], eax
4532 hidnplayr 958
        invoke  GetPhysAddr
5522 hidnplayr 959
        add     eax, NET_BUFF.data
3545 hidnplayr 960
        mov     [edi + descriptor.base], eax
961
        mov     [edi + descriptor.length], - PKT_BUF_SZ
8897 hidnplayr 962
        mov     dword[edi + descriptor.msg_length], 0    ; also clears misc field
3545 hidnplayr 963
        mov     [edi + descriptor.status], RXSTAT_OWN
4532 hidnplayr 964
        add     edi, sizeof.descriptor
3545 hidnplayr 965
        dec     ecx
966
        jnz     .rx_init
967
 
4532 hidnplayr 968
        lea     edi, [ebx + device.tx_ring]
3545 hidnplayr 969
        mov     eax, edi
4532 hidnplayr 970
        invoke  GetPhysAddr
8897 hidnplayr 971
        mov     [ebx + device.init_block.tx_ring_phys], eax
3545 hidnplayr 972
        mov     ecx, TX_RING_SIZE
973
  .tx_init:
974
        mov     [edi + descriptor.status], 0
4532 hidnplayr 975
        add     edi, sizeof.descriptor
3545 hidnplayr 976
        dec     ecx
977
        jnz     .tx_init
978
 
8897 hidnplayr 979
        mov     [ebx + device.init_block.tlen_rlen], (TX_RING_LEN_BITS or RX_RING_LEN_BITS)
3545 hidnplayr 980
 
4532 hidnplayr 981
        mov     [ebx + device.cur_tx], 0
982
        mov     [ebx + device.last_tx], 0
983
        mov     [ebx + device.cur_rx], 0
3545 hidnplayr 984
 
5522 hidnplayr 985
        xor     eax, eax
3545 hidnplayr 986
        ret
987
 
5522 hidnplayr 988
  .out_of_mem:
989
        DEBUGF  2,"Out of memory!\n"
3545 hidnplayr 990
 
5522 hidnplayr 991
        or      eax, -1
992
        ret
3545 hidnplayr 993
 
994
 
5522 hidnplayr 995
 
996
 
3545 hidnplayr 997
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
998
;;                                         ;;
999
;; Transmit                                ;;
1000
;;                                         ;;
4532 hidnplayr 1001
;; In: pointer to device structure in ebx  ;;
3545 hidnplayr 1002
;;                                         ;;
1003
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1004
 
5522 hidnplayr 1005
proc transmit stdcall bufferptr
4532 hidnplayr 1006
 
1007
        pushf
1008
        cli
1009
 
5522 hidnplayr 1010
        mov     esi, [bufferptr]
1011
        DEBUGF  1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [esi + NET_BUFF.length]
1012
        lea     eax, [esi + NET_BUFF.data]
3545 hidnplayr 1013
        DEBUGF  1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
1014
        [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
1015
        [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
1016
        [eax+13]:2,[eax+12]:2
1017
 
5522 hidnplayr 1018
        cmp     [esi + NET_BUFF.length], 1514
8898 hidnplayr 1019
        ja      .error
5522 hidnplayr 1020
        cmp     [esi + NET_BUFF.length], 60
8898 hidnplayr 1021
        jb      .error
3545 hidnplayr 1022
 
1023
; check descriptor
4532 hidnplayr 1024
        lea     edi, [ebx + device.tx_ring]
8897 hidnplayr 1025
        mov     ecx, [ebx + device.cur_tx]
5522 hidnplayr 1026
        shl     ecx, 4
1027
        add     edi, ecx
3545 hidnplayr 1028
 
1029
        test    [edi + descriptor.status], TXCTL_OWN
8898 hidnplayr 1030
        jnz     .overrun
3545 hidnplayr 1031
; descriptor is free, use it
5522 hidnplayr 1032
        mov     [edi + descriptor.virtual], esi
1033
        mov     eax, esi
1034
        add     eax, [eax + NET_BUFF.offset]
4532 hidnplayr 1035
        invoke  GetPhysAddr
3545 hidnplayr 1036
        mov     [edi + descriptor.base], eax
1037
; set length
5522 hidnplayr 1038
        mov     eax, [esi + NET_BUFF.length]
3545 hidnplayr 1039
        neg     eax
1040
        mov     [edi + descriptor.length], ax
1041
; put to transfer queue
1042
        mov     [edi + descriptor.status], TXCTL_OWN + TXCTL_STP + TXCTL_ENP
1043
 
1044
; trigger an immediate send
4532 hidnplayr 1045
        mov     edx, [ebx + device.io_addr]
3545 hidnplayr 1046
        xor     ecx, ecx                        ; CSR0
4532 hidnplayr 1047
        call    [ebx + device.read_csr]
3545 hidnplayr 1048
        or      eax, CSR_TX
4532 hidnplayr 1049
        call    [ebx + device.write_csr]
3545 hidnplayr 1050
 
8897 hidnplayr 1051
; get next descriptor
4532 hidnplayr 1052
        inc     [ebx + device.cur_tx]
1053
        and     [ebx + device.cur_tx], TX_RING_SIZE - 1
3545 hidnplayr 1054
 
1055
; Update stats
4532 hidnplayr 1056
        inc     [ebx + device.packets_tx]
5522 hidnplayr 1057
        mov     eax, [esi + NET_BUFF.length]
4532 hidnplayr 1058
        add     dword[ebx + device.bytes_tx], eax
1059
        adc     dword[ebx + device.bytes_tx + 4], 0
3545 hidnplayr 1060
 
4532 hidnplayr 1061
        popf
3545 hidnplayr 1062
        xor     eax, eax
4532 hidnplayr 1063
        ret
3545 hidnplayr 1064
 
8898 hidnplayr 1065
  .error:
1066
        DEBUGF  2, "TX packet error\n"
1067
        inc     [ebx + device.packets_tx_err]
5522 hidnplayr 1068
        invoke  NetFree, [bufferptr]
8898 hidnplayr 1069
 
4532 hidnplayr 1070
        popf
3545 hidnplayr 1071
        or      eax, -1
4532 hidnplayr 1072
        ret
3545 hidnplayr 1073
 
8898 hidnplayr 1074
  .overrun:
1075
        DEBUGF  2, "TX overrun\n"
1076
        inc     [ebx + device.packets_tx_ovr]
1077
        invoke  NetFree, [bufferptr]
1078
 
1079
        popf
1080
        or      eax, -1
1081
        ret
1082
 
4532 hidnplayr 1083
endp
3545 hidnplayr 1084
 
1085
 
1086
;;;;;;;;;;;;;;;;;;;;;;;
1087
;;                   ;;
1088
;; Interrupt handler ;;
1089
;;                   ;;
1090
;;;;;;;;;;;;;;;;;;;;;;;
1091
 
1092
align 4
1093
int_handler:
1094
 
1095
        push    ebx esi edi
1096
 
3855 hidnplayr 1097
        DEBUGF  1,"INT\n"
3545 hidnplayr 1098
 
1099
; find pointer of device wich made IRQ occur
1100
 
1101
        mov     ecx, [devices]
1102
        test    ecx, ecx
1103
        jz      .nothing
1104
        mov     esi, device_list
1105
  .nextdevice:
1106
        mov     ebx, [esi]
4532 hidnplayr 1107
        mov     edx, [ebx + device.io_addr]
3545 hidnplayr 1108
        push    ecx
1109
        xor     ecx, ecx                        ; CSR0
4532 hidnplayr 1110
        call    [ebx + device.read_csr]         ; get IRQ reason
1111
        call    [ebx + device.write_csr]        ; write it back to ACK
3545 hidnplayr 1112
        pop     ecx
5617 hidnplayr 1113
        test    ax, CSR_RINT or CSR_TINT
3545 hidnplayr 1114
        jnz     .got_it
1115
  .continue:
1116
        add     esi, 4
1117
        dec     ecx
1118
        jnz     .nextdevice
1119
  .nothing:
1120
        pop     edi esi ebx
1121
        xor     eax, eax
1122
 
1123
        ret
1124
 
1125
  .got_it:
5065 hidnplayr 1126
        DEBUGF  1,"Device: %x status: %x\n", ebx, eax:4
3545 hidnplayr 1127
 
1128
        push    ax
1129
        test    ax, CSR_RINT
1130
        jz      .not_receive
1131
 
1132
        push    ebx
1133
  .rx_loop:
1134
        pop     ebx
8898 hidnplayr 1135
        push    ebx
8897 hidnplayr 1136
        mov     eax, [ebx + device.cur_rx]
3545 hidnplayr 1137
        shl     eax, 4
4532 hidnplayr 1138
        lea     edi, [ebx + device.rx_ring]
3545 hidnplayr 1139
        add     edi, eax                        ; edi now points to current rx ring entry
1140
 
1141
        mov     ax, [edi + descriptor.status]
1142
        DEBUGF  1,"RX packet status: %x\n", eax:4
1143
 
1144
        test    ax, RXSTAT_OWN                  ; If this bit is set, the controller OWN's the packet, if not, we do
8898 hidnplayr 1145
        jnz     .rx_done
1146
; Both Start of packet and End of packet bits should be set, we dont support multi frame packets
3545 hidnplayr 1147
        test    ax, RXSTAT_ENP
8898 hidnplayr 1148
        jz      .rx_drop
3545 hidnplayr 1149
        test    ax, RXSTAT_STP
8898 hidnplayr 1150
        jz      .rx_drop
3545 hidnplayr 1151
 
1152
        movzx   ecx, [edi + descriptor.msg_length]      ; get packet length in ecx
4532 hidnplayr 1153
        sub     ecx, 4                                  ; We dont need the CRC
1154
        DEBUGF  1,"Got %u bytes\n", ecx
3545 hidnplayr 1155
 
1156
; Set pointers for ETH_input
1157
        push    .rx_loop                                ; return address
5522 hidnplayr 1158
        mov     eax, [edi + descriptor.virtual]
1159
        push    eax                                     ; packet address
1160
        mov     [eax + NET_BUFF.length], ecx
1161
        mov     [eax + NET_BUFF.device], ebx
1162
        mov     [eax + NET_BUFF.offset], NET_BUFF.data
3545 hidnplayr 1163
 
1164
; Update stats
4532 hidnplayr 1165
        add     dword[ebx + device.bytes_rx], ecx
1166
        adc     dword[ebx + device.bytes_rx + 4], 0
1167
        inc     [ebx + device.packets_rx]
3545 hidnplayr 1168
 
1169
; now allocate a new buffer
5522 hidnplayr 1170
        invoke  NetAlloc, PKT_BUF_SZ+NET_BUFF.data      ; Allocate a buffer for the next packet
1171
        test    eax, eax
8898 hidnplayr 1172
        jz      .rx_overrun
3545 hidnplayr 1173
        mov     [edi + descriptor.virtual], eax         ; set virtual address
4532 hidnplayr 1174
        invoke  GetPhysAddr
5522 hidnplayr 1175
        add     eax, NET_BUFF.data
4532 hidnplayr 1176
        mov     [edi + descriptor.base], eax            ; and physical address
3545 hidnplayr 1177
        mov     [edi + descriptor.status], RXSTAT_OWN   ; give it back to PCnet controller
1178
 
4532 hidnplayr 1179
        inc     [ebx + device.cur_rx]                   ; set next receive descriptor
1180
        and     [ebx + device.cur_rx], RX_RING_SIZE - 1
3545 hidnplayr 1181
 
5522 hidnplayr 1182
        jmp     [EthInput]
3545 hidnplayr 1183
 
8898 hidnplayr 1184
  .rx_overrun:
1185
        add     esp, 4+4
1186
        DEBUGF  2,"RX FIFO overrun\n"
1187
        inc     [ebx + device.packets_rx_ovr]
1188
        jmp     .rx_next
5522 hidnplayr 1189
 
8898 hidnplayr 1190
  .rx_drop:
1191
        DEBUGF  2,"Dropping incoming packet\n"
1192
        inc     [ebx + device.packets_rx_drop]
1193
 
1194
  .rx_next:
1195
        mov     [edi + descriptor.status], RXSTAT_OWN   ; give it back to PCnet controller
1196
 
5522 hidnplayr 1197
        inc     [ebx + device.cur_rx]                   ; set next receive descriptor
1198
        and     [ebx + device.cur_rx], RX_RING_SIZE - 1
8898 hidnplayr 1199
        jmp     .rx_loop
5522 hidnplayr 1200
 
8898 hidnplayr 1201
  .rx_done:
1202
        pop     ebx
5522 hidnplayr 1203
 
3545 hidnplayr 1204
  .not_receive:
1205
        pop     ax
1206
 
1207
        test    ax, CSR_TINT
1208
        jz      .not_transmit
1209
 
1210
  .tx_loop:
4532 hidnplayr 1211
        lea     edi, [ebx + device.tx_ring]
8897 hidnplayr 1212
        mov     eax, [ebx + device.last_tx]
3545 hidnplayr 1213
        shl     eax, 4
1214
        add     edi, eax
1215
 
1216
        test    [edi + descriptor.status], TXCTL_OWN
1217
        jnz     .not_transmit
1218
 
1219
        mov     eax, [edi + descriptor.virtual]
1220
        test    eax, eax
1221
        jz      .not_transmit
1222
 
1223
        mov     [edi + descriptor.virtual], 0
1224
 
1225
        DEBUGF  1,"Removing packet %x from memory\n", eax
1226
 
5522 hidnplayr 1227
        invoke  NetFree, eax
3545 hidnplayr 1228
 
4532 hidnplayr 1229
        inc     [ebx + device.last_tx]
1230
        and     [ebx + device.last_tx], TX_RING_SIZE - 1
3545 hidnplayr 1231
        jmp     .tx_loop
1232
 
1233
  .not_transmit:
1234
        pop     edi esi ebx
1235
        xor     eax, eax
1236
        inc     eax
1237
 
1238
        ret
1239
 
1240
 
1241
 
1242
 
1243
;;;;;;;;;;;;;;;;;;;;;;;
1244
;;                   ;;
1245
;; Write MAC address ;;
1246
;;                   ;;
1247
;;;;;;;;;;;;;;;;;;;;;;;
1248
 
1249
align 4
1250
write_mac:      ; in: mac pushed onto stack (as 3 words)
1251
 
4532 hidnplayr 1252
        DEBUGF  1,"Writing MAC: %x-%x-%x-%x-%x-%x\n",\
1253
        [esp+0]:2,[esp+1]:2,[esp+2]:2,[esp+3]:2,[esp+4]:2,[esp+5]:2
3545 hidnplayr 1254
 
4532 hidnplayr 1255
        mov     edx, [ebx + device.io_addr]
3545 hidnplayr 1256
        add     dx, 2
1257
        xor     eax, eax
1258
 
1259
        mov     ecx, CSR_PAR0
1260
       @@:
1261
        pop     ax
4532 hidnplayr 1262
        call    [ebx + device.write_csr]
3545 hidnplayr 1263
        inc     ecx
1264
        cmp     ecx, CSR_PAR2
1265
        jb      @r
1266
 
1267
; Notice this procedure does not ret, but continues to read_mac instead.
1268
 
1269
;;;;;;;;;;;;;;;;;;;;;;
1270
;;                  ;;
1271
;; Read MAC address ;;
1272
;;                  ;;
1273
;;;;;;;;;;;;;;;;;;;;;;
1274
align 4
1275
read_mac:
4532 hidnplayr 1276
        DEBUGF  1,"Reading MAC\n"
3545 hidnplayr 1277
 
4532 hidnplayr 1278
        mov     edx, [ebx + device.io_addr]
1279
        lea     edi, [ebx + device.mac]
3545 hidnplayr 1280
        in      ax, dx
4532 hidnplayr 1281
        stosw
3545 hidnplayr 1282
 
4532 hidnplayr 1283
        inc     dx
1284
        inc     dx
1285
        in      ax, dx
1286
        stosw
3545 hidnplayr 1287
 
4532 hidnplayr 1288
        inc     dx
1289
        inc     dx
1290
        in      ax, dx
3545 hidnplayr 1291
        stosw
1292
 
4532 hidnplayr 1293
        DEBUGF  1,"MAC = %x-%x-%x-%x-%x-%x\n",\
1294
        [ebx + device.mac+0]:2,[ebx + device.mac+1]:2,[ebx + device.mac+2]:2,\
1295
        [ebx + device.mac+3]:2,[ebx + device.mac+4]:2,[ebx + device.mac+5]:2
1296
 
3545 hidnplayr 1297
        ret
1298
 
1299
align 4
1300
switch_to_wio:
1301
 
1302
        DEBUGF  1,"Switching to 16-bit mode\n"
1303
 
4532 hidnplayr 1304
        mov     [ebx + device.read_csr], wio_read_csr
1305
        mov     [ebx + device.write_csr], wio_write_csr
1306
        mov     [ebx + device.read_bcr], wio_read_bcr
1307
        mov     [ebx + device.write_bcr], wio_write_bcr
1308
        mov     [ebx + device.read_rap], wio_read_rap
1309
        mov     [ebx + device.write_rap], wio_write_rap
1310
        mov     [ebx + device.sw_reset], wio_reset
3545 hidnplayr 1311
 
1312
        ret
1313
 
1314
align 4
1315
switch_to_dwio:
1316
 
1317
        DEBUGF  1,"Switching to 32-bit mode\n"
1318
 
4532 hidnplayr 1319
        mov     [ebx + device.read_csr], dwio_read_csr
1320
        mov     [ebx + device.write_csr], dwio_write_csr
1321
        mov     [ebx + device.read_bcr], dwio_read_bcr
1322
        mov     [ebx + device.write_bcr], dwio_write_bcr
1323
        mov     [ebx + device.read_rap], dwio_read_rap
1324
        mov     [ebx + device.write_rap], dwio_write_rap
1325
        mov     [ebx + device.sw_reset], dwio_reset
3545 hidnplayr 1326
 
1327
        ret
1328
 
1329
 
1330
; ecx - index
1331
; return:
1332
; eax - data
1333
align 4
1334
wio_read_csr:
1335
 
1336
        add     edx, WIO_RAP
1337
        mov     ax, cx
1338
        out     dx, ax
1339
        add     edx, WIO_RDP - WIO_RAP
1340
        in      ax, dx
1341
        and     eax, 0xffff
1342
        sub     edx, WIO_RDP
1343
 
1344
        ret
1345
 
1346
 
1347
; eax - data
1348
; ecx - index
1349
align 4
1350
wio_write_csr:
1351
 
1352
        add     edx, WIO_RAP
1353
        xchg    eax, ecx
1354
        out     dx, ax
1355
        xchg    eax, ecx
1356
        add     edx, WIO_RDP - WIO_RAP
1357
        out     dx, ax
1358
        sub     edx, WIO_RDP
1359
 
1360
        ret
1361
 
1362
 
1363
; ecx - index
1364
; return:
1365
; eax - data
1366
align 4
1367
wio_read_bcr:
1368
 
1369
        add     edx, WIO_RAP
1370
        mov     ax, cx
1371
        out     dx, ax
1372
        add     edx, WIO_BDP - WIO_RAP
1373
        in      ax, dx
1374
        and     eax, 0xffff
1375
        sub     edx, WIO_BDP
1376
 
1377
        ret
1378
 
1379
 
1380
; eax - data
1381
; ecx - index
1382
align 4
1383
wio_write_bcr:
1384
 
1385
        add     edx, WIO_RAP
1386
        xchg    eax, ecx
1387
        out     dx, ax
1388
        xchg    eax, ecx
1389
        add     edx, WIO_BDP - WIO_RAP
1390
        out     dx, ax
1391
        sub     edx, WIO_BDP
1392
 
1393
        ret
1394
 
1395
align 4
1396
wio_read_rap:
1397
 
1398
        add     edx, WIO_RAP
1399
        in      ax, dx
1400
        and     eax, 0xffff
1401
        sub     edx, WIO_RAP
1402
 
1403
        ret
1404
 
1405
; eax - val
1406
align 4
1407
wio_write_rap:
1408
 
1409
        add     edx, WIO_RAP
1410
        out     dx, ax
1411
        sub     edx, WIO_RAP
1412
 
1413
        ret
1414
 
1415
align 4
1416
wio_reset:
1417
 
1418
        push    eax
1419
        add     edx, WIO_RESET
1420
        in      ax, dx
1421
        pop     eax
1422
        sub     edx, WIO_RESET
1423
 
1424
        ret
1425
 
1426
 
1427
 
1428
; ecx - index
1429
; return:
1430
; eax - data
1431
align 4
1432
dwio_read_csr:
1433
 
1434
        add     edx, DWIO_RAP
1435
        mov     eax, ecx
1436
        out     dx, eax
1437
        add     edx, DWIO_RDP - DWIO_RAP
1438
        in      eax, dx
1439
        and     eax, 0xffff
1440
        sub     edx, DWIO_RDP
1441
 
1442
        ret
1443
 
1444
 
1445
; ecx - index
1446
; eax - data
1447
align 4
1448
dwio_write_csr:
1449
 
1450
        add     edx, DWIO_RAP
1451
        xchg    eax, ecx
1452
        out     dx, eax
1453
        add     edx, DWIO_RDP - DWIO_RAP
1454
        xchg    eax, ecx
1455
        out     dx, eax
1456
        sub     edx, DWIO_RDP
1457
 
1458
        ret
1459
 
1460
; ecx - index
1461
; return:
1462
; eax - data
1463
align 4
1464
dwio_read_bcr:
1465
 
1466
        add     edx, DWIO_RAP
1467
        mov     eax, ecx
1468
        out     dx, eax
1469
        add     edx, DWIO_BDP - DWIO_RAP
1470
        in      eax, dx
1471
        and     eax, 0xffff
1472
        sub     edx, DWIO_BDP
1473
 
1474
        ret
1475
 
1476
 
1477
; ecx - index
1478
; eax - data
1479
align 4
1480
dwio_write_bcr:
1481
 
1482
        add     edx, DWIO_RAP
1483
        xchg    eax, ecx
1484
        out     dx, eax
1485
        add     edx, DWIO_BDP - DWIO_RAP
1486
        xchg    eax, ecx
1487
        out     dx, eax
1488
        sub     edx, DWIO_BDP
1489
 
1490
        ret
1491
 
1492
align 4
1493
dwio_read_rap:
1494
 
1495
        add     edx, DWIO_RAP
1496
        in      eax, dx
1497
        and     eax, 0xffff
1498
        sub     edx, DWIO_RAP
1499
 
1500
        ret
1501
 
1502
 
1503
; eax - val
1504
align 4
1505
dwio_write_rap:
1506
 
1507
        add     edx, DWIO_RAP
1508
        out     dx, eax
1509
        sub     edx, DWIO_RAP
1510
 
1511
        ret
1512
 
1513
align 4
1514
dwio_reset:
1515
 
1516
        push    eax
1517
        add     edx, DWIO_RESET
1518
        in      eax, dx
1519
        pop     eax
1520
        sub     edx, DWIO_RESET
1521
 
1522
        ret
1523
 
1524
 
1525
align 4
1526
mdio_read:
1527
 
1528
        and     ecx, 0x1f
4532 hidnplayr 1529
        mov     ax, [ebx + device.phy]
3545 hidnplayr 1530
        and     ax, 0x1f
1531
        shl     ax, 5
1532
        or      ax, cx
1533
 
1534
        mov     ecx, BCR_MIIADDR
4532 hidnplayr 1535
        call    [ebx + device.write_bcr]
3545 hidnplayr 1536
 
1537
        mov     ecx, BCR_MIIDATA
4532 hidnplayr 1538
        call    [ebx + device.read_bcr]
3545 hidnplayr 1539
 
1540
        ret
1541
 
1542
 
1543
align 4
1544
mdio_write:
1545
 
1546
        push    eax
1547
        and     ecx, 0x1f
4532 hidnplayr 1548
        mov     ax, [ebx + device.phy]
3545 hidnplayr 1549
        and     ax, 0x1f
1550
        shl     ax, 5
1551
        or      ax, cx
1552
 
1553
        mov     ecx, BCR_MIIADDR
4532 hidnplayr 1554
        call    [ebx + device.write_bcr]
3545 hidnplayr 1555
 
1556
        pop     eax
1557
        mov     ecx, BCR_MIIDATA
4532 hidnplayr 1558
        call    [ebx + device.write_bcr]
3545 hidnplayr 1559
 
1560
        ret
1561
 
1562
 
1563
align 4
1564
check_media:
1565
 
1566
        DEBUGF  1, "check_media\n"
1567
 
4532 hidnplayr 1568
        test    [ebx + device.mii], 1
3855 hidnplayr 1569
        jnz     mii_link_ok
3545 hidnplayr 1570
 
1571
        mov     ecx, BCR_LED0
4532 hidnplayr 1572
        call    [ebx + device.read_bcr]
3545 hidnplayr 1573
        cmp     eax, 0xc0
1574
 
5004 hidnplayr 1575
        DEBUGF  2, "link status=0x%x\n", ax
3545 hidnplayr 1576
 
1577
        ret
1578
 
1579
 
1580
 
1581
; End of code
1582
 
1583
 
4532 hidnplayr 1584
data fixups
1585
end data
3545 hidnplayr 1586
 
4532 hidnplayr 1587
include '../peimport.inc'
1588
 
4629 hidnplayr 1589
my_service    db 'PCNET32',0            ; max 16 chars include zero
4532 hidnplayr 1590
 
3545 hidnplayr 1591
device_l2     db "PCnet/PCI 79C970",0
1592
device_l4     db "PCnet/PCI II 79C970A",0
1593
device_l5     db "PCnet/FAST 79C971",0
1594
device_l6     db "PCnet/FAST+ 79C972",0
1595
device_l7     db "PCnet/FAST III 79C973",0
1596
device_l8     db "PCnet/Home 79C978",0
1597
device_l9     db "PCnet/FAST III 79C975",0
1598
 
1599
options_mapping:
1600
dd PORT_ASEL                            ; 0 Auto-select
1601
dd PORT_AUI                             ; 1 BNC/AUI
1602
dd PORT_AUI                             ; 2 AUI/BNC
1603
dd PORT_ASEL                            ; 3 not supported
1604
dd PORT_10BT or PORT_FD                 ; 4 10baseT-FD
1605
dd PORT_ASEL                            ; 5 not supported
1606
dd PORT_ASEL                            ; 6 not supported
1607
dd PORT_ASEL                            ; 7 not supported
1608
dd PORT_ASEL                            ; 8 not supported
1609
dd PORT_MII                             ; 9 MII 10baseT
1610
dd PORT_MII or PORT_FD                  ; 10 MII 10baseT-FD
1611
dd PORT_MII                             ; 11 MII (autosel)
1612
dd PORT_10BT                            ; 12 10BaseT
1613
dd PORT_MII or PORT_100                 ; 13 MII 100BaseTx
1614
dd PORT_MII or PORT_100 or PORT_FD      ; 14 MII 100BaseTx-FD
1615
dd PORT_ASEL                            ; 15 not supported
1616
 
1617
include_debug_strings                                   ; All data wich FDO uses will be included here
1618
 
1619
 
4532 hidnplayr 1620
align 4
1621
devices     dd 0
3545 hidnplayr 1622
device_list rd MAX_DEVICES                              ; This list contains all pointers to device structures the driver is handling