Subversion Repositories Kolibri OS

Rev

Rev 5617 | Rev 8898 | 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
4532 hidnplayr 1019
        ja      .fail
5522 hidnplayr 1020
        cmp     [esi + NET_BUFF.length], 60
4532 hidnplayr 1021
        jb      .fail
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
4532 hidnplayr 1030
        jnz     .fail
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
 
1061
  .finish:
4532 hidnplayr 1062
        popf
3545 hidnplayr 1063
        xor     eax, eax
4532 hidnplayr 1064
        ret
3545 hidnplayr 1065
 
4532 hidnplayr 1066
  .fail:
1067
        DEBUGF  2, "Send failed\n"
5522 hidnplayr 1068
        invoke  NetFree, [bufferptr]
4532 hidnplayr 1069
        popf
3545 hidnplayr 1070
        or      eax, -1
4532 hidnplayr 1071
        ret
3545 hidnplayr 1072
 
4532 hidnplayr 1073
endp
3545 hidnplayr 1074
 
1075
 
1076
;;;;;;;;;;;;;;;;;;;;;;;
1077
;;                   ;;
1078
;; Interrupt handler ;;
1079
;;                   ;;
1080
;;;;;;;;;;;;;;;;;;;;;;;
1081
 
1082
align 4
1083
int_handler:
1084
 
1085
        push    ebx esi edi
1086
 
3855 hidnplayr 1087
        DEBUGF  1,"INT\n"
3545 hidnplayr 1088
 
1089
; find pointer of device wich made IRQ occur
1090
 
1091
        mov     ecx, [devices]
1092
        test    ecx, ecx
1093
        jz      .nothing
1094
        mov     esi, device_list
1095
  .nextdevice:
1096
        mov     ebx, [esi]
4532 hidnplayr 1097
        mov     edx, [ebx + device.io_addr]
3545 hidnplayr 1098
        push    ecx
1099
        xor     ecx, ecx                        ; CSR0
4532 hidnplayr 1100
        call    [ebx + device.read_csr]         ; get IRQ reason
1101
        call    [ebx + device.write_csr]        ; write it back to ACK
3545 hidnplayr 1102
        pop     ecx
5617 hidnplayr 1103
        test    ax, CSR_RINT or CSR_TINT
3545 hidnplayr 1104
        jnz     .got_it
1105
  .continue:
1106
        add     esi, 4
1107
        dec     ecx
1108
        jnz     .nextdevice
1109
  .nothing:
1110
        pop     edi esi ebx
1111
        xor     eax, eax
1112
 
1113
        ret
1114
 
1115
  .got_it:
5065 hidnplayr 1116
        DEBUGF  1,"Device: %x status: %x\n", ebx, eax:4
3545 hidnplayr 1117
 
1118
        push    ax
1119
        test    ax, CSR_RINT
1120
        jz      .not_receive
1121
 
1122
        push    ebx
1123
  .rx_loop:
1124
        pop     ebx
8897 hidnplayr 1125
        mov     eax, [ebx + device.cur_rx]
3545 hidnplayr 1126
        shl     eax, 4
4532 hidnplayr 1127
        lea     edi, [ebx + device.rx_ring]
3545 hidnplayr 1128
        add     edi, eax                        ; edi now points to current rx ring entry
1129
 
1130
        mov     ax, [edi + descriptor.status]
1131
        DEBUGF  1,"RX packet status: %x\n", eax:4
1132
 
1133
        test    ax, RXSTAT_OWN                  ; If this bit is set, the controller OWN's the packet, if not, we do
1134
        jnz     .not_receive
1135
 
1136
        test    ax, RXSTAT_ENP
1137
        jz      .not_receive
1138
 
1139
        test    ax, RXSTAT_STP
1140
        jz      .not_receive
1141
 
1142
        movzx   ecx, [edi + descriptor.msg_length]      ; get packet length in ecx
4532 hidnplayr 1143
        sub     ecx, 4                                  ; We dont need the CRC
1144
        DEBUGF  1,"Got %u bytes\n", ecx
3545 hidnplayr 1145
 
1146
; Set pointers for ETH_input
1147
        push    ebx
1148
 
1149
        push    .rx_loop                                ; return address
5522 hidnplayr 1150
        mov     eax, [edi + descriptor.virtual]
1151
        push    eax                                     ; packet address
1152
        mov     [eax + NET_BUFF.length], ecx
1153
        mov     [eax + NET_BUFF.device], ebx
1154
        mov     [eax + NET_BUFF.offset], NET_BUFF.data
3545 hidnplayr 1155
 
1156
; Update stats
4532 hidnplayr 1157
        add     dword[ebx + device.bytes_rx], ecx
1158
        adc     dword[ebx + device.bytes_rx + 4], 0
1159
        inc     [ebx + device.packets_rx]
3545 hidnplayr 1160
 
1161
; now allocate a new buffer
5522 hidnplayr 1162
        invoke  NetAlloc, PKT_BUF_SZ+NET_BUFF.data      ; Allocate a buffer for the next packet
1163
        test    eax, eax
1164
        jz      .out_of_mem
3545 hidnplayr 1165
        mov     [edi + descriptor.virtual], eax         ; set virtual address
4532 hidnplayr 1166
        invoke  GetPhysAddr
5522 hidnplayr 1167
        add     eax, NET_BUFF.data
4532 hidnplayr 1168
        mov     [edi + descriptor.base], eax            ; and physical address
3545 hidnplayr 1169
        mov     [edi + descriptor.status], RXSTAT_OWN   ; give it back to PCnet controller
1170
 
4532 hidnplayr 1171
        inc     [ebx + device.cur_rx]                   ; set next receive descriptor
1172
        and     [ebx + device.cur_rx], RX_RING_SIZE - 1
3545 hidnplayr 1173
 
5522 hidnplayr 1174
        jmp     [EthInput]
3545 hidnplayr 1175
 
5522 hidnplayr 1176
  .out_of_mem:
1177
        DEBUGF  2,"Out of memory!\n"
1178
 
1179
        inc     [ebx + device.cur_rx]                   ; set next receive descriptor
1180
        and     [ebx + device.cur_rx], RX_RING_SIZE - 1
1181
 
1182
        jmp     [EthInput]
1183
 
3545 hidnplayr 1184
  .not_receive:
1185
        pop     ax
1186
 
1187
        test    ax, CSR_TINT
1188
        jz      .not_transmit
1189
 
1190
  .tx_loop:
4532 hidnplayr 1191
        lea     edi, [ebx + device.tx_ring]
8897 hidnplayr 1192
        mov     eax, [ebx + device.last_tx]
3545 hidnplayr 1193
        shl     eax, 4
1194
        add     edi, eax
1195
 
1196
        test    [edi + descriptor.status], TXCTL_OWN
1197
        jnz     .not_transmit
1198
 
1199
        mov     eax, [edi + descriptor.virtual]
1200
        test    eax, eax
1201
        jz      .not_transmit
1202
 
1203
        mov     [edi + descriptor.virtual], 0
1204
 
1205
        DEBUGF  1,"Removing packet %x from memory\n", eax
1206
 
5522 hidnplayr 1207
        invoke  NetFree, eax
3545 hidnplayr 1208
 
4532 hidnplayr 1209
        inc     [ebx + device.last_tx]
1210
        and     [ebx + device.last_tx], TX_RING_SIZE - 1
3545 hidnplayr 1211
        jmp     .tx_loop
1212
 
1213
  .not_transmit:
1214
        pop     edi esi ebx
1215
        xor     eax, eax
1216
        inc     eax
1217
 
1218
        ret
1219
 
1220
 
1221
 
1222
 
1223
;;;;;;;;;;;;;;;;;;;;;;;
1224
;;                   ;;
1225
;; Write MAC address ;;
1226
;;                   ;;
1227
;;;;;;;;;;;;;;;;;;;;;;;
1228
 
1229
align 4
1230
write_mac:      ; in: mac pushed onto stack (as 3 words)
1231
 
4532 hidnplayr 1232
        DEBUGF  1,"Writing MAC: %x-%x-%x-%x-%x-%x\n",\
1233
        [esp+0]:2,[esp+1]:2,[esp+2]:2,[esp+3]:2,[esp+4]:2,[esp+5]:2
3545 hidnplayr 1234
 
4532 hidnplayr 1235
        mov     edx, [ebx + device.io_addr]
3545 hidnplayr 1236
        add     dx, 2
1237
        xor     eax, eax
1238
 
1239
        mov     ecx, CSR_PAR0
1240
       @@:
1241
        pop     ax
4532 hidnplayr 1242
        call    [ebx + device.write_csr]
3545 hidnplayr 1243
        inc     ecx
1244
        cmp     ecx, CSR_PAR2
1245
        jb      @r
1246
 
1247
; Notice this procedure does not ret, but continues to read_mac instead.
1248
 
1249
;;;;;;;;;;;;;;;;;;;;;;
1250
;;                  ;;
1251
;; Read MAC address ;;
1252
;;                  ;;
1253
;;;;;;;;;;;;;;;;;;;;;;
1254
align 4
1255
read_mac:
4532 hidnplayr 1256
        DEBUGF  1,"Reading MAC\n"
3545 hidnplayr 1257
 
4532 hidnplayr 1258
        mov     edx, [ebx + device.io_addr]
1259
        lea     edi, [ebx + device.mac]
3545 hidnplayr 1260
        in      ax, dx
4532 hidnplayr 1261
        stosw
3545 hidnplayr 1262
 
4532 hidnplayr 1263
        inc     dx
1264
        inc     dx
1265
        in      ax, dx
1266
        stosw
3545 hidnplayr 1267
 
4532 hidnplayr 1268
        inc     dx
1269
        inc     dx
1270
        in      ax, dx
3545 hidnplayr 1271
        stosw
1272
 
4532 hidnplayr 1273
        DEBUGF  1,"MAC = %x-%x-%x-%x-%x-%x\n",\
1274
        [ebx + device.mac+0]:2,[ebx + device.mac+1]:2,[ebx + device.mac+2]:2,\
1275
        [ebx + device.mac+3]:2,[ebx + device.mac+4]:2,[ebx + device.mac+5]:2
1276
 
3545 hidnplayr 1277
        ret
1278
 
1279
align 4
1280
switch_to_wio:
1281
 
1282
        DEBUGF  1,"Switching to 16-bit mode\n"
1283
 
4532 hidnplayr 1284
        mov     [ebx + device.read_csr], wio_read_csr
1285
        mov     [ebx + device.write_csr], wio_write_csr
1286
        mov     [ebx + device.read_bcr], wio_read_bcr
1287
        mov     [ebx + device.write_bcr], wio_write_bcr
1288
        mov     [ebx + device.read_rap], wio_read_rap
1289
        mov     [ebx + device.write_rap], wio_write_rap
1290
        mov     [ebx + device.sw_reset], wio_reset
3545 hidnplayr 1291
 
1292
        ret
1293
 
1294
align 4
1295
switch_to_dwio:
1296
 
1297
        DEBUGF  1,"Switching to 32-bit mode\n"
1298
 
4532 hidnplayr 1299
        mov     [ebx + device.read_csr], dwio_read_csr
1300
        mov     [ebx + device.write_csr], dwio_write_csr
1301
        mov     [ebx + device.read_bcr], dwio_read_bcr
1302
        mov     [ebx + device.write_bcr], dwio_write_bcr
1303
        mov     [ebx + device.read_rap], dwio_read_rap
1304
        mov     [ebx + device.write_rap], dwio_write_rap
1305
        mov     [ebx + device.sw_reset], dwio_reset
3545 hidnplayr 1306
 
1307
        ret
1308
 
1309
 
1310
; ecx - index
1311
; return:
1312
; eax - data
1313
align 4
1314
wio_read_csr:
1315
 
1316
        add     edx, WIO_RAP
1317
        mov     ax, cx
1318
        out     dx, ax
1319
        add     edx, WIO_RDP - WIO_RAP
1320
        in      ax, dx
1321
        and     eax, 0xffff
1322
        sub     edx, WIO_RDP
1323
 
1324
        ret
1325
 
1326
 
1327
; eax - data
1328
; ecx - index
1329
align 4
1330
wio_write_csr:
1331
 
1332
        add     edx, WIO_RAP
1333
        xchg    eax, ecx
1334
        out     dx, ax
1335
        xchg    eax, ecx
1336
        add     edx, WIO_RDP - WIO_RAP
1337
        out     dx, ax
1338
        sub     edx, WIO_RDP
1339
 
1340
        ret
1341
 
1342
 
1343
; ecx - index
1344
; return:
1345
; eax - data
1346
align 4
1347
wio_read_bcr:
1348
 
1349
        add     edx, WIO_RAP
1350
        mov     ax, cx
1351
        out     dx, ax
1352
        add     edx, WIO_BDP - WIO_RAP
1353
        in      ax, dx
1354
        and     eax, 0xffff
1355
        sub     edx, WIO_BDP
1356
 
1357
        ret
1358
 
1359
 
1360
; eax - data
1361
; ecx - index
1362
align 4
1363
wio_write_bcr:
1364
 
1365
        add     edx, WIO_RAP
1366
        xchg    eax, ecx
1367
        out     dx, ax
1368
        xchg    eax, ecx
1369
        add     edx, WIO_BDP - WIO_RAP
1370
        out     dx, ax
1371
        sub     edx, WIO_BDP
1372
 
1373
        ret
1374
 
1375
align 4
1376
wio_read_rap:
1377
 
1378
        add     edx, WIO_RAP
1379
        in      ax, dx
1380
        and     eax, 0xffff
1381
        sub     edx, WIO_RAP
1382
 
1383
        ret
1384
 
1385
; eax - val
1386
align 4
1387
wio_write_rap:
1388
 
1389
        add     edx, WIO_RAP
1390
        out     dx, ax
1391
        sub     edx, WIO_RAP
1392
 
1393
        ret
1394
 
1395
align 4
1396
wio_reset:
1397
 
1398
        push    eax
1399
        add     edx, WIO_RESET
1400
        in      ax, dx
1401
        pop     eax
1402
        sub     edx, WIO_RESET
1403
 
1404
        ret
1405
 
1406
 
1407
 
1408
; ecx - index
1409
; return:
1410
; eax - data
1411
align 4
1412
dwio_read_csr:
1413
 
1414
        add     edx, DWIO_RAP
1415
        mov     eax, ecx
1416
        out     dx, eax
1417
        add     edx, DWIO_RDP - DWIO_RAP
1418
        in      eax, dx
1419
        and     eax, 0xffff
1420
        sub     edx, DWIO_RDP
1421
 
1422
        ret
1423
 
1424
 
1425
; ecx - index
1426
; eax - data
1427
align 4
1428
dwio_write_csr:
1429
 
1430
        add     edx, DWIO_RAP
1431
        xchg    eax, ecx
1432
        out     dx, eax
1433
        add     edx, DWIO_RDP - DWIO_RAP
1434
        xchg    eax, ecx
1435
        out     dx, eax
1436
        sub     edx, DWIO_RDP
1437
 
1438
        ret
1439
 
1440
; ecx - index
1441
; return:
1442
; eax - data
1443
align 4
1444
dwio_read_bcr:
1445
 
1446
        add     edx, DWIO_RAP
1447
        mov     eax, ecx
1448
        out     dx, eax
1449
        add     edx, DWIO_BDP - DWIO_RAP
1450
        in      eax, dx
1451
        and     eax, 0xffff
1452
        sub     edx, DWIO_BDP
1453
 
1454
        ret
1455
 
1456
 
1457
; ecx - index
1458
; eax - data
1459
align 4
1460
dwio_write_bcr:
1461
 
1462
        add     edx, DWIO_RAP
1463
        xchg    eax, ecx
1464
        out     dx, eax
1465
        add     edx, DWIO_BDP - DWIO_RAP
1466
        xchg    eax, ecx
1467
        out     dx, eax
1468
        sub     edx, DWIO_BDP
1469
 
1470
        ret
1471
 
1472
align 4
1473
dwio_read_rap:
1474
 
1475
        add     edx, DWIO_RAP
1476
        in      eax, dx
1477
        and     eax, 0xffff
1478
        sub     edx, DWIO_RAP
1479
 
1480
        ret
1481
 
1482
 
1483
; eax - val
1484
align 4
1485
dwio_write_rap:
1486
 
1487
        add     edx, DWIO_RAP
1488
        out     dx, eax
1489
        sub     edx, DWIO_RAP
1490
 
1491
        ret
1492
 
1493
align 4
1494
dwio_reset:
1495
 
1496
        push    eax
1497
        add     edx, DWIO_RESET
1498
        in      eax, dx
1499
        pop     eax
1500
        sub     edx, DWIO_RESET
1501
 
1502
        ret
1503
 
1504
 
1505
align 4
1506
mdio_read:
1507
 
1508
        and     ecx, 0x1f
4532 hidnplayr 1509
        mov     ax, [ebx + device.phy]
3545 hidnplayr 1510
        and     ax, 0x1f
1511
        shl     ax, 5
1512
        or      ax, cx
1513
 
1514
        mov     ecx, BCR_MIIADDR
4532 hidnplayr 1515
        call    [ebx + device.write_bcr]
3545 hidnplayr 1516
 
1517
        mov     ecx, BCR_MIIDATA
4532 hidnplayr 1518
        call    [ebx + device.read_bcr]
3545 hidnplayr 1519
 
1520
        ret
1521
 
1522
 
1523
align 4
1524
mdio_write:
1525
 
1526
        push    eax
1527
        and     ecx, 0x1f
4532 hidnplayr 1528
        mov     ax, [ebx + device.phy]
3545 hidnplayr 1529
        and     ax, 0x1f
1530
        shl     ax, 5
1531
        or      ax, cx
1532
 
1533
        mov     ecx, BCR_MIIADDR
4532 hidnplayr 1534
        call    [ebx + device.write_bcr]
3545 hidnplayr 1535
 
1536
        pop     eax
1537
        mov     ecx, BCR_MIIDATA
4532 hidnplayr 1538
        call    [ebx + device.write_bcr]
3545 hidnplayr 1539
 
1540
        ret
1541
 
1542
 
1543
align 4
1544
check_media:
1545
 
1546
        DEBUGF  1, "check_media\n"
1547
 
4532 hidnplayr 1548
        test    [ebx + device.mii], 1
3855 hidnplayr 1549
        jnz     mii_link_ok
3545 hidnplayr 1550
 
1551
        mov     ecx, BCR_LED0
4532 hidnplayr 1552
        call    [ebx + device.read_bcr]
3545 hidnplayr 1553
        cmp     eax, 0xc0
1554
 
5004 hidnplayr 1555
        DEBUGF  2, "link status=0x%x\n", ax
3545 hidnplayr 1556
 
1557
        ret
1558
 
1559
 
1560
 
1561
; End of code
1562
 
1563
 
4532 hidnplayr 1564
data fixups
1565
end data
3545 hidnplayr 1566
 
4532 hidnplayr 1567
include '../peimport.inc'
1568
 
4629 hidnplayr 1569
my_service    db 'PCNET32',0            ; max 16 chars include zero
4532 hidnplayr 1570
 
3545 hidnplayr 1571
device_l2     db "PCnet/PCI 79C970",0
1572
device_l4     db "PCnet/PCI II 79C970A",0
1573
device_l5     db "PCnet/FAST 79C971",0
1574
device_l6     db "PCnet/FAST+ 79C972",0
1575
device_l7     db "PCnet/FAST III 79C973",0
1576
device_l8     db "PCnet/Home 79C978",0
1577
device_l9     db "PCnet/FAST III 79C975",0
1578
 
1579
options_mapping:
1580
dd PORT_ASEL                            ; 0 Auto-select
1581
dd PORT_AUI                             ; 1 BNC/AUI
1582
dd PORT_AUI                             ; 2 AUI/BNC
1583
dd PORT_ASEL                            ; 3 not supported
1584
dd PORT_10BT or PORT_FD                 ; 4 10baseT-FD
1585
dd PORT_ASEL                            ; 5 not supported
1586
dd PORT_ASEL                            ; 6 not supported
1587
dd PORT_ASEL                            ; 7 not supported
1588
dd PORT_ASEL                            ; 8 not supported
1589
dd PORT_MII                             ; 9 MII 10baseT
1590
dd PORT_MII or PORT_FD                  ; 10 MII 10baseT-FD
1591
dd PORT_MII                             ; 11 MII (autosel)
1592
dd PORT_10BT                            ; 12 10BaseT
1593
dd PORT_MII or PORT_100                 ; 13 MII 100BaseTx
1594
dd PORT_MII or PORT_100 or PORT_FD      ; 14 MII 100BaseTx-FD
1595
dd PORT_ASEL                            ; 15 not supported
1596
 
1597
include_debug_strings                                   ; All data wich FDO uses will be included here
1598
 
1599
 
4532 hidnplayr 1600
align 4
1601
devices     dd 0
3545 hidnplayr 1602
device_list rd MAX_DEVICES                              ; This list contains all pointers to device structures the driver is handling