Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
1196 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                  ;;
3155 hidnplayr 3
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved.     ;;
1196 hidnplayr 4
;; Distributed under terms of the GNU General Public License        ;;
5
;;                                                                  ;;
1564 hidnplayr 6
;;  PCnet driver for KolibriOS                                      ;;
1519 hidnplayr 7
;;                                                                  ;;
1564 hidnplayr 8
;;  By hidnplayr & clevermouse                                      ;;
9
;;                                                                  ;;
1519 hidnplayr 10
;;  Based on the PCnet32 driver for MenuetOS, by Jarek Pelczar      ;;
11
;;                                                                  ;;
1196 hidnplayr 12
;;          GNU GENERAL PUBLIC LICENSE                              ;;
13
;;             Version 2, June 1991                                 ;;
14
;;                                                                  ;;
15
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
16
 
17
format MS COFF
18
 
2852 hidnplayr 19
        API_VERSION             =   0x01000100
1196 hidnplayr 20
 
2852 hidnplayr 21
        DEBUG                   =   1
22
        __DEBUG__               =   1
23
        __DEBUG_LEVEL__         =   1
1196 hidnplayr 24
 
2852 hidnplayr 25
        MAX_DEVICES =   4
26
        MAX_ETH_FRAME_SIZE =   1514
1196 hidnplayr 27
 
28
include 'proc32.inc'
29
include 'imports.inc'
30
include 'fdo.inc'
1492 hidnplayr 31
include 'netdrv.inc'
1196 hidnplayr 32
 
1564 hidnplayr 33
 
1196 hidnplayr 34
public START
35
public service_proc
36
public version
37
 
38
 
1492 hidnplayr 39
virtual at ebx
1196 hidnplayr 40
 
2387 hidnplayr 41
        device:
1196 hidnplayr 42
 
2387 hidnplayr 43
        ETH_DEVICE
1492 hidnplayr 44
 
1564 hidnplayr 45
; device specific
1196 hidnplayr 46
 
1564 hidnplayr 47
      .private:
2387 hidnplayr 48
      .mode_            dw ?
49
      .tlen_rlen        dw ?
50
      .phys_addr        dp ?
51
      .reserved         dw ?
52
      .filter           dq ?
53
      .rx_ring_phys     dd ?
54
      .tx_ring_phys     dd ?
1196 hidnplayr 55
 
2387 hidnplayr 56
      .cur_rx           db ?
57
      .cur_tx           db ?
58
      .dirty_rx         dd ?
59
      .dirty_tx         dd ?
60
      .tx_full          db ?
61
      .options          dd ?
62
      .full_duplex      db ?
63
      .chip_version     dd ?
64
      .mii              db ?
65
      .ltint            db ?
66
      .dxsuflo          db ?
67
      .fset             db ?
68
      .fdx              db ?
1492 hidnplayr 69
 
2387 hidnplayr 70
      .rx_buffer        dd ?
71
      .tx_buffer        dd ?
1492 hidnplayr 72
 
2387 hidnplayr 73
      .io_addr          dd ?
74
      .irq_line         db ?
75
      .pci_bus          db ?
76
      .pci_dev          db ?
1541 hidnplayr 77
 
78
 
2387 hidnplayr 79
      .access_read_csr          dd ?
80
      .access_write_csr         dd ?
81
      .access_read_bcr          dd ?
82
      .access_write_bcr         dd ?
83
      .access_read_rap          dd ?
84
      .access_write_rap         dd ?
85
      .access_reset             dd ?
1196 hidnplayr 86
 
2387 hidnplayr 87
      device_size       = $ - device
1196 hidnplayr 88
 
89
end virtual
90
 
1564 hidnplayr 91
struc buf_head {
2387 hidnplayr 92
        .base           dd ?
93
        .length         dw ?
94
        .status         dw ?
95
        .msg_length     dw ?
96
        .misc           dw ?
97
        .reserved       dd ?
1196 hidnplayr 98
 
2387 hidnplayr 99
        .size:
1196 hidnplayr 100
}
101
 
102
virtual at 0
1564 hidnplayr 103
 buf_head buf_head
1196 hidnplayr 104
end virtual
105
 
2852 hidnplayr 106
        PCNET_PORT_AUI                =   0x00
107
        PCNET_PORT_10BT               =   0x01
108
        PCNET_PORT_GPSI               =   0x02
109
        PCNET_PORT_MII                =   0x03
110
        PCNET_PORT_PORTSEL            =   0x03
111
        PCNET_PORT_ASEL               =   0x04
112
        PCNET_PORT_100                =   0x40
113
        PCNET_PORT_FD                 =   0x80
1196 hidnplayr 114
 
2852 hidnplayr 115
        PCNET_DMA_MASK                =   0xffffffff
1196 hidnplayr 116
 
2852 hidnplayr 117
        PCNET_LOG_TX_BUFFERS          =   2
118
        PCNET_LOG_RX_BUFFERS          =   2
1196 hidnplayr 119
 
2852 hidnplayr 120
        PCNET_TX_RING_SIZE            =   4
121
        PCNET_TX_RING_MOD_MASK        =   (PCNET_TX_RING_SIZE-1)
122
        PCNET_TX_RING_LEN_BITS        =   (PCNET_LOG_TX_BUFFERS shl 12)
1196 hidnplayr 123
 
2852 hidnplayr 124
        PCNET_RX_RING_SIZE            =   4
125
        PCNET_RX_RING_MOD_MASK        =   (PCNET_RX_RING_SIZE-1)
126
        PCNET_RX_RING_LEN_BITS        =   (PCNET_LOG_RX_BUFFERS shl 4)
1196 hidnplayr 127
 
2852 hidnplayr 128
        PCNET_PKT_BUF_SZ              =   1544
129
        PCNET_PKT_BUF_SZ_NEG          =   0xf9f8
1196 hidnplayr 130
 
2852 hidnplayr 131
        PCNET_WIO_RDP                 =   0x10
132
        PCNET_WIO_RAP                 =   0x12
133
        PCNET_WIO_RESET               =   0x14
134
        PCNET_WIO_BDP                 =   0x16
135
        PCNET_DWIO_RDP                =   0x10
136
        PCNET_DWIO_RAP                =   0x14
137
        PCNET_DWIO_RESET              =   0x18
138
        PCNET_DWIO_BDP                =   0x1C
139
        PCNET_TOTAL_SIZE              =   0x20
1564 hidnplayr 140
 
1196 hidnplayr 141
; CSR registers
142
 
2852 hidnplayr 143
        PCNET_CSR_CSR                 =   0x00
144
        PCNET_CSR_IAB0                =   0x01
145
        PCNET_CSR_IAB1                =   0x02
146
        PCNET_CSR_IMR                 =   0x03
147
        PCNET_CSR_TFEAT               =   0x04
148
        PCNET_CSR_EXTCTL1             =   0x05
149
        PCNET_CSR_DTBLLEN             =   0x06
150
        PCNET_CSR_EXTCTL2             =   0x07
151
        PCNET_CSR_MAR0                =   0x08
152
        PCNET_CSR_MAR1                =   0x09
153
        PCNET_CSR_MAR2                =   0x0A
154
        PCNET_CSR_MAR3                =   0x0B
155
        PCNET_CSR_PAR0                =   0x0C
156
        PCNET_CSR_PAR1                =   0x0D
157
        PCNET_CSR_PAR2                =   0x0E
158
        PCNET_CSR_MODE                =   0x0F
159
        PCNET_CSR_RXADDR0             =   0x18
160
        PCNET_CSR_RXADDR1             =   0x19
161
        PCNET_CSR_TXADDR0             =   0x1E
162
        PCNET_CSR_TXADDR1             =   0x1F
163
        PCNET_CSR_TXPOLL              =   0x2F
164
        PCNET_CSR_RXPOLL              =   0x31
165
        PCNET_CSR_RXRINGLEN           =   0x4C
166
        PCNET_CSR_TXRINGLEN           =   0x4E
167
        PCNET_CSR_DMACTL              =   0x50
168
        PCNET_CSR_BUSTIMER            =   0x52
169
        PCNET_CSR_MEMERRTIMEO         =   0x64
170
        PCNET_CSR_ONNOWMISC           =   0x74
171
        PCNET_CSR_ADVFEAT             =   0x7A
172
        PCNET_CSR_MACCFG              =   0x7D
173
        PCNET_CSR_CHIPID0             =   0x58
174
        PCNET_CSR_CHIPID1             =   0x59
1196 hidnplayr 175
 
176
; Control and Status Register (CSR0)
177
 
2852 hidnplayr 178
        PCNET_CSR_INIT                =   1 shl 0
179
        PCNET_CSR_START               =   1 shl 1
180
        PCNET_CSR_STOP                =   1 shl 2
181
        PCNET_CSR_TX                  =   1 shl 3
182
        PCNET_CSR_TXON                =   1 shl 4
183
        PCNET_CSR_RXON                =   1 shl 5
184
        PCNET_CSR_INTEN               =   1 shl 6
185
        PCNET_CSR_INTR                =   1 shl 7
186
        PCNET_CSR_IDONE               =   1 shl 8
187
        PCNET_CSR_TINT                =   1 shl 9
188
        PCNET_CSR_RINT                =   1 shl 10
189
        PCNET_CSR_MERR                =   1 shl 11
190
        PCNET_CSR_MISS                =   1 shl 12
191
        PCNET_CSR_CERR                =   1 shl 13
1196 hidnplayr 192
 
193
; Interrupt masks and deferral control (CSR3)
194
 
2852 hidnplayr 195
        PCNET_IMR_BSWAP               =   0x0004
196
        PCNET_IMR_ENMBA               =   0x0008  ; enable modified backoff alg
197
        PCNET_IMR_DXMT2PD             =   0x0010
198
        PCNET_IMR_LAPPEN              =   0x0020  ; lookahead packet processing enb
199
        PCNET_IMR_DXSUFLO             =   0x0040  ; disable TX stop on underflow
200
        PCNET_IMR_IDONE               =   0x0100
201
        PCNET_IMR_TINT                =   0x0200
202
        PCNET_IMR_RINT                =   0x0400
203
        PCNET_IMR_MERR                =   0x0800
204
        PCNET_IMR_MISS                =   0x1000
1196 hidnplayr 205
 
2852 hidnplayr 206
        PCNET_IMR                     =   PCNET_IMR_TINT+PCNET_IMR_RINT+PCNET_IMR_IDONE+PCNET_IMR_MERR+PCNET_IMR_MISS
1196 hidnplayr 207
 
208
; Test and features control (CSR4)
209
 
2852 hidnplayr 210
        PCNET_TFEAT_TXSTRTMASK        =   0x0004
211
        PCNET_TFEAT_TXSTRT            =   0x0008
212
        PCNET_TFEAT_RXCCOFLOWM        =   0x0010  ; Rx collision counter oflow
213
        PCNET_TFEAT_RXCCOFLOW         =   0x0020
214
        PCNET_TFEAT_UINT              =   0x0040
215
        PCNET_TFEAT_UINTREQ           =   0x0080
216
        PCNET_TFEAT_MISSOFLOWM        =   0x0100
217
        PCNET_TFEAT_MISSOFLOW         =   0x0200
218
        PCNET_TFEAT_STRIP_FCS         =   0x0400
219
        PCNET_TFEAT_PAD_TX            =   0x0800
220
        PCNET_TFEAT_TXDPOLL           =   0x1000
221
        PCNET_TFEAT_DMAPLUS           =   0x4000
1196 hidnplayr 222
 
223
; Extended control and interrupt 1 (CSR5)
224
 
2852 hidnplayr 225
        PCNET_EXTCTL1_SPND            =   0x0001  ; suspend
226
        PCNET_EXTCTL1_MPMODE          =   0x0002  ; magic packet mode
227
        PCNET_EXTCTL1_MPENB           =   0x0004  ; magic packet enable
228
        PCNET_EXTCTL1_MPINTEN         =   0x0008  ; magic packet interrupt enable
229
        PCNET_EXTCTL1_MPINT           =   0x0010  ; magic packet interrupt
230
        PCNET_EXTCTL1_MPPLBA          =   0x0020  ; magic packet phys. logical bcast
231
        PCNET_EXTCTL1_EXDEFEN         =   0x0040  ; excessive deferral interrupt enb.
232
        PCNET_EXTCTL1_EXDEF           =   0x0080  ; excessive deferral interrupt
233
        PCNET_EXTCTL1_SINTEN          =   0x0400  ; system interrupt enable
234
        PCNET_EXTCTL1_SINT            =   0x0800  ; system interrupt
235
        PCNET_EXTCTL1_LTINTEN         =   0x4000  ; last TX interrupt enb
236
        PCNET_EXTCTL1_TXOKINTD        =   0x8000  ; TX OK interrupt disable
1196 hidnplayr 237
 
238
; RX/TX descriptor len (CSR6)
239
 
2852 hidnplayr 240
        PCNET_DTBLLEN_RLEN            =   0x0F00
241
        PCNET_DTBLLEN_TLEN            =   0xF000
1196 hidnplayr 242
 
243
; Extended control and interrupt 2 (CSR7)
244
 
2852 hidnplayr 245
        PCNET_EXTCTL2_MIIPDTINTE      =   0x0001
246
        PCNET_EXTCTL2_MIIPDTINT       =   0x0002
247
        PCNET_EXTCTL2_MCCIINTE        =   0x0004
248
        PCNET_EXTCTL2_MCCIINT         =   0x0008
249
        PCNET_EXTCTL2_MCCINTE         =   0x0010
250
        PCNET_EXTCTL2_MCCINT          =   0x0020
251
        PCNET_EXTCTL2_MAPINTE         =   0x0040
252
        PCNET_EXTCTL2_MAPINT          =   0x0080
253
        PCNET_EXTCTL2_MREINTE         =   0x0100
254
        PCNET_EXTCTL2_MREINT          =   0x0200
255
        PCNET_EXTCTL2_STINTE          =   0x0400
256
        PCNET_EXTCTL2_STINT           =   0x0800
257
        PCNET_EXTCTL2_RXDPOLL         =   0x1000
258
        PCNET_EXTCTL2_RDMD            =   0x2000
259
        PCNET_EXTCTL2_RXFRTG          =   0x4000
260
        PCNET_EXTCTL2_FASTSPNDE       =   0x8000
1196 hidnplayr 261
 
262
; Mode (CSR15)
263
 
2852 hidnplayr 264
        PCNET_MODE_RXD                =   0x0001  ; RX disable
265
        PCNET_MODE_TXD                =   0x0002  ; TX disable
266
        PCNET_MODE_LOOP               =   0x0004  ; loopback enable
267
        PCNET_MODE_TXCRCD             =   0x0008
268
        PCNET_MODE_FORCECOLL          =   0x0010
269
        PCNET_MODE_RETRYD             =   0x0020
270
        PCNET_MODE_INTLOOP            =   0x0040
271
        PCNET_MODE_PORTSEL            =   0x0180
272
        PCNET_MODE_RXVPAD             =   0x2000
273
        PCNET_MODE_RXNOBROAD          =   0x4000
274
        PCNET_MODE_PROMISC            =   0x8000
1196 hidnplayr 275
 
276
; BCR (Bus Control Registers)
277
 
2852 hidnplayr 278
        PCNET_BCR_MMRA                =   0x00    ; Master Mode Read Active
279
        PCNET_BCR_MMW                 =   0x01    ; Master Mode Write Active
280
        PCNET_BCR_MISCCFG             =   0x02
281
        PCNET_BCR_LED0                =   0x04
282
        PCNET_BCR_LED1                =   0x05
283
        PCNET_BCR_LED2                =   0x06
284
        PCNET_BCR_LED3                =   0x07
285
        PCNET_BCR_DUPLEX              =   0x09
286
        PCNET_BCR_BUSCTL              =   0x12
287
        PCNET_BCR_EECTL               =   0x13
288
        PCNET_BCR_SSTYLE              =   0x14
289
        PCNET_BCR_PCILAT              =   0x16
290
        PCNET_BCR_PCISUBVENID         =   0x17
291
        PCNET_BCR_PCISUBSYSID         =   0x18
292
        PCNET_BCR_SRAMSIZE            =   0x19
293
        PCNET_BCR_SRAMBOUND           =   0x1A
294
        PCNET_BCR_SRAMCTL             =   0x1B
295
        PCNET_BCR_MIICTL              =   0x20
296
        PCNET_BCR_MIIADDR             =   0x21
297
        PCNET_BCR_MIIDATA             =   0x22
298
        PCNET_BCR_PCIVENID            =   0x23
299
        PCNET_BCR_PCIPCAP             =   0x24
300
        PCNET_BCR_DATA0               =   0x25
301
        PCNET_BCR_DATA1               =   0x26
302
        PCNET_BCR_DATA2               =   0x27
303
        PCNET_BCR_DATA3               =   0x28
304
        PCNET_BCR_DATA4               =   0x29
305
        PCNET_BCR_DATA5               =   0x2A
306
        PCNET_BCR_DATA6               =   0x2B
307
        PCNET_BCR_DATA7               =   0x2C
308
        PCNET_BCR_ONNOWPAT0           =   0x2D
309
        PCNET_BCR_ONNOWPAT1           =   0x2E
310
        PCNET_BCR_ONNOWPAT2           =   0x2F
311
        PCNET_BCR_PHYSEL              =   0x31
1196 hidnplayr 312
 
313
; RX status register
314
 
2852 hidnplayr 315
        PCNET_RXSTAT_BPE              =   0x0080  ; bus parity error
316
        PCNET_RXSTAT_ENP              =   0x0100  ; end of packet
317
        PCNET_RXSTAT_STP              =   0x0200  ; start of packet
318
        PCNET_RXSTAT_BUFF             =   0x0400  ; buffer error
319
        PCNET_RXSTAT_CRC              =   0x0800  ; CRC error
320
        PCNET_RXSTAT_OFLOW            =   0x1000  ; rx overrun
321
        PCNET_RXSTAT_FRAM             =   0x2000  ; framing error
322
        PCNET_RXSTAT_ERR              =   0x4000  ; error summary
323
        PCNET_RXSTAT_OWN              =   0x8000
1196 hidnplayr 324
 
325
; TX status register
326
 
2852 hidnplayr 327
        PCNET_TXSTAT_TRC              =   0x0000000F      ; transmit retries
328
        PCNET_TXSTAT_RTRY             =   0x04000000      ; retry
329
        PCNET_TXSTAT_LCAR             =   0x08000000      ; lost carrier
330
        PCNET_TXSTAT_LCOL             =   0x10000000      ; late collision
331
        PCNET_TXSTAT_EXDEF            =   0x20000000      ; excessive deferrals
332
        PCNET_TXSTAT_UFLOW            =   0x40000000      ; transmit underrun
333
        PCNET_TXSTAT_BUFF             =   0x80000000      ; buffer error
1196 hidnplayr 334
 
2852 hidnplayr 335
        PCNET_TXCTL_OWN               =   0x80000000
336
        PCNET_TXCTL_ERR               =   0x40000000      ; error summary
337
        PCNET_TXCTL_ADD_FCS           =   0x20000000      ; add FCS to pkt
338
        PCNET_TXCTL_MORE_LTINT        =   0x10000000
339
        PCNET_TXCTL_ONE               =   0x08000000
340
        PCNET_TXCTL_DEF               =   0x04000000
341
        PCNET_TXCTL_STP               =   0x02000000
342
        PCNET_TXCTL_ENP               =   0x01000000
343
        PCNET_TXCTL_BPE               =   0x00800000
344
        PCNET_TXCTL_MBO               =   0x0000F000
345
        PCNET_TXCTL_BUFSZ             =   0x00000FFF
1196 hidnplayr 346
 
347
 
348
 
1564 hidnplayr 349
 
1196 hidnplayr 350
section '.flat' code readable align 16
351
 
352
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
353
;;                        ;;
354
;; proc START             ;;
355
;;                        ;;
356
;; (standard driver proc) ;;
357
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
358
 
359
proc START stdcall, state:dword
360
 
2387 hidnplayr 361
        cmp [state], 1
362
        jne .exit
1196 hidnplayr 363
 
364
  .entry:
365
 
3155 hidnplayr 366
        DEBUGF 1,"Loading %s driver\n", my_service
2387 hidnplayr 367
        stdcall RegService, my_service, service_proc
368
        ret
1196 hidnplayr 369
 
370
  .fail:
371
  .exit:
2387 hidnplayr 372
        xor eax, eax
373
        ret
1196 hidnplayr 374
 
375
endp
376
 
377
 
378
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
379
;;                        ;;
380
;; proc SERVICE_PROC      ;;
381
;;                        ;;
382
;; (standard driver proc) ;;
383
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
384
 
385
align 4
386
proc service_proc stdcall, ioctl:dword
387
 
2387 hidnplayr 388
        mov     edx, [ioctl]
389
        mov     eax, [IOCTL.io_code]
1196 hidnplayr 390
 
391
;------------------------------------------------------
392
 
2387 hidnplayr 393
        cmp     eax, 0 ;SRV_GETVERSION
394
        jne     @F
1196 hidnplayr 395
 
2387 hidnplayr 396
        cmp     [IOCTL.out_size], 4
3155 hidnplayr 397
        jb      .fail
2387 hidnplayr 398
        mov     eax, [IOCTL.output]
399
        mov     [eax], dword API_VERSION
1196 hidnplayr 400
 
2387 hidnplayr 401
        xor     eax, eax
402
        ret
1196 hidnplayr 403
 
404
;------------------------------------------------------
405
  @@:
2387 hidnplayr 406
        cmp     eax, 1 ;SRV_HOOK
407
        jne     .fail
1196 hidnplayr 408
 
2387 hidnplayr 409
        cmp     [IOCTL.inp_size], 3               ; Data input must be at least 3 bytes
3155 hidnplayr 410
        jb      .fail
1196 hidnplayr 411
 
2387 hidnplayr 412
        mov     eax, [IOCTL.input]
413
        cmp     byte [eax], 1                           ; 1 means device number and bus number (pci) are given
414
        jne     .fail                                   ; other types arent supported for this card yet
1196 hidnplayr 415
 
416
; check if the device is already listed
417
 
2387 hidnplayr 418
        mov     ecx, [devices]
419
        test    ecx, ecx
420
        jz      .firstdevice
1492 hidnplayr 421
 
2387 hidnplayr 422
        mov     esi, device_list
1492 hidnplayr 423
;        mov     eax, [IOCTL.input]                      ; get the pci bus and device numbers
2387 hidnplayr 424
        mov     ax , [eax+1]                            ;
1196 hidnplayr 425
  .nextdevice:
2387 hidnplayr 426
        mov     ebx, [esi]
427
        cmp     ax , word [device.pci_bus]              ; compare with pci and device num in device list (notice the usage of word instead of byte)
428
        je      .find_devicenum                         ; Device is already loaded, let's find it's device number
429
        add     esi, 4
430
        loop    .nextdevice
1196 hidnplayr 431
 
432
; This device doesnt have its own eth_device structure yet, lets create one
433
 
434
  .firstdevice:
2387 hidnplayr 435
        cmp     [devices], MAX_DEVICES                  ; First check if the driver can handle one more card
3155 hidnplayr 436
        jae     .fail
1196 hidnplayr 437
 
2387 hidnplayr 438
        allocate_and_clear ebx, device_size, .fail
1196 hidnplayr 439
 
440
; Fill in the direct call addresses into the struct
441
 
2387 hidnplayr 442
        mov     [device.reset], reset
443
        mov     [device.transmit], transmit
444
        mov     [device.get_MAC], read_mac
445
        mov     [device.set_MAC], write_mac
446
        mov     [device.unload], unload
447
        mov     [device.name], my_service
1196 hidnplayr 448
 
449
; save the pci bus and device numbers
450
 
2387 hidnplayr 451
        mov     eax, [IOCTL.input]
452
        mov     cl , [eax+1]
453
        mov     [device.pci_bus], cl
454
        mov     cl , [eax+2]
455
        mov     [device.pci_dev], cl
1196 hidnplayr 456
 
457
; Now, it's time to find the base io addres of the PCI device
458
 
2387 hidnplayr 459
        find_io [device.pci_bus], [device.pci_dev], [device.io_addr]
1196 hidnplayr 460
 
461
; We've found the io address, find IRQ now
462
 
2387 hidnplayr 463
        find_irq [device.pci_bus], [device.pci_dev], [device.irq_line]
1196 hidnplayr 464
 
2387 hidnplayr 465
        DEBUGF  1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
466
        [device.pci_dev]:1,[device.pci_bus]:1,[device.irq_line]:1,[device.io_addr]:4
1196 hidnplayr 467
 
2387 hidnplayr 468
        allocate_and_clear [device.tx_buffer], PCNET_RX_RING_SIZE * (PCNET_PKT_BUF_SZ + buf_head.size), .err
469
        allocate_and_clear [device.rx_buffer], PCNET_TX_RING_SIZE * (PCNET_PKT_BUF_SZ + buf_head.size), .err
1196 hidnplayr 470
 
471
; Ok, the eth_device structure is ready, let's probe the device
1201 clevermous 472
; Because initialization fires IRQ, IRQ handler must be aware of this device
2387 hidnplayr 473
        mov     eax, [devices]                                        ; Add the device structure to our device list
474
        mov     [device_list+4*eax], ebx                                 ; (IRQ handler uses this list to find device)
475
        inc     [devices]                                             ;
1196 hidnplayr 476
 
2387 hidnplayr 477
        call    probe                                                   ; this function will output in eax
478
        test    eax, eax
479
        jnz     .destroy                                                        ; If an error occured, exit
1196 hidnplayr 480
 
2387 hidnplayr 481
        mov     [device.type], NET_TYPE_ETH
482
        call    NetRegDev
483
        cmp     eax, -1
484
        je      .destroy
1196 hidnplayr 485
 
2387 hidnplayr 486
        ret
1196 hidnplayr 487
 
488
; If the device was already loaded, find the device number and return it in eax
489
 
490
  .find_devicenum:
2387 hidnplayr 491
        DEBUGF  1,"Trying to find device number of already registered device\n"
492
        call    NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
493
                                                                        ; into a device number in edi
494
        mov     eax, edi                                                ; Application wants it in eax instead
495
        DEBUGF  1,"Kernel says: %u\n", eax
496
        ret
1196 hidnplayr 497
 
498
; If an error occured, remove all allocated data and exit (returning -1 in eax)
499
 
500
  .destroy:
2387 hidnplayr 501
        ; todo: reset device into virgin state
1564 hidnplayr 502
 
2387 hidnplayr 503
        dec     [devices]
1196 hidnplayr 504
  .err:
2387 hidnplayr 505
        DEBUGF  1,"Error, removing all data !\n"
506
        stdcall KernelFree, [device.rx_buffer]
507
        stdcall KernelFree, [device.tx_buffer]
508
        stdcall KernelFree, ebx
1196 hidnplayr 509
 
510
  .fail:
2387 hidnplayr 511
        or      eax, -1
512
        ret
1196 hidnplayr 513
 
514
;------------------------------------------------------
515
endp
516
 
517
 
518
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
519
;;                                                                        ;;
520
;;        Actual Hardware dependent code starts here                      ;;
521
;;                                                                        ;;
522
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
523
 
524
align 4
525
unload:
2387 hidnplayr 526
        ; TODO: (in this particular order)
527
        ;
528
        ; - Stop the device
529
        ; - Detach int handler
530
        ; - Remove device from local list (RTL8139_LIST)
531
        ; - call unregister function in kernel
532
        ; - Remove all allocated structures and buffers the card used
1196 hidnplayr 533
 
2387 hidnplayr 534
        or      eax,-1
1196 hidnplayr 535
 
536
ret
537
 
538
 
539
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
540
;;
541
;;  probe: enables the device (if it really is a PCnet device)
542
;;
543
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
544
 
545
align 4
546
probe:
2387 hidnplayr 547
        mov     edx, [device.io_addr]
1196 hidnplayr 548
 
2387 hidnplayr 549
        call    wio_reset
1196 hidnplayr 550
 
2387 hidnplayr 551
        xor     ecx, ecx
552
        call    wio_read_csr
553
        cmp     eax, 4
554
        jne     .try_dwio
1196 hidnplayr 555
 
2387 hidnplayr 556
        ; Try Word I/O
557
        mov     ax , 88
558
        add     edx, PCNET_WIO_RAP
559
        out     dx , ax
560
        nop
561
        nop
562
        in      ax , dx
563
        sub     edx, PCNET_WIO_RAP
564
        cmp     ax , 88
565
        jne     .try_dwio
1196 hidnplayr 566
 
2387 hidnplayr 567
        call    switch_to_wio
1196 hidnplayr 568
 
2387 hidnplayr 569
        jmp     .L1
1196 hidnplayr 570
 
571
  .try_dwio:
2387 hidnplayr 572
        call    dwio_reset
1196 hidnplayr 573
 
2387 hidnplayr 574
        xor     ecx, ecx
575
        call    dwio_read_csr
576
        cmp     eax, 4
577
        jne     .no_dev
1196 hidnplayr 578
 
2387 hidnplayr 579
        ; Try Dword I/O
580
        add     edx, PCNET_DWIO_RAP
581
        mov     eax, 88
582
        out     dx , eax
583
        nop
584
        nop
585
        in      eax, dx
586
        sub     edx, PCNET_DWIO_RAP
587
        and     eax, 0xffff
588
        cmp     eax, 88
589
        jne     .no_dev
1196 hidnplayr 590
 
2387 hidnplayr 591
        call    switch_to_dwio
1196 hidnplayr 592
 
2387 hidnplayr 593
        jmp     .L1
1196 hidnplayr 594
 
595
  .no_dev:
2387 hidnplayr 596
        DEBUGF 1,"PCnet device not found!\n"
597
        mov     eax, 1
598
        ret
1564 hidnplayr 599
  .L1:
1541 hidnplayr 600
 
2387 hidnplayr 601
        mov     ecx, PCNET_CSR_CHIPID0
602
        call    [device.access_read_csr]
603
        mov     esi, eax
1196 hidnplayr 604
 
2387 hidnplayr 605
        mov     ecx, PCNET_CSR_CHIPID1
606
        call    [device.access_read_csr]
607
        shl     eax, 16
608
        or      eax, esi
1196 hidnplayr 609
 
2387 hidnplayr 610
        mov     ecx, eax
611
        and     ecx, 0xfff
612
        cmp     ecx, 3
613
        jne     .no_dev
1196 hidnplayr 614
 
2387 hidnplayr 615
        shr     eax, 12
616
        and     eax, 0xffff
617
        mov     [device.chip_version], eax
1196 hidnplayr 618
 
2387 hidnplayr 619
        DEBUGF 1,"chip version ok\n"
620
        mov     [device.fdx], 0
621
        mov     [device.mii], 0
622
        mov     [device.fset], 0
623
        mov     [device.dxsuflo], 0
624
        mov     [device.ltint], 0
1196 hidnplayr 625
 
2387 hidnplayr 626
        cmp     eax, 0x2420
627
        je      .L2
628
        cmp     eax, 0x2430
629
        je      .L2
1196 hidnplayr 630
 
2387 hidnplayr 631
        mov     [device.fdx], 1
1196 hidnplayr 632
 
2387 hidnplayr 633
        cmp     eax, 0x2621
634
        je      .L4
635
        cmp     eax, 0x2623
636
        je      .L5
637
        cmp     eax, 0x2624
638
        je      .L6
639
        cmp     eax, 0x2625
640
        je      .L7
641
        cmp     eax, 0x2626
642
        je      .L8
643
        cmp     eax, 0x2627
644
        je      .L9
1196 hidnplayr 645
 
2387 hidnplayr 646
        DEBUGF 1,"Invalid chip rev\n"
647
        jmp     .no_dev
1196 hidnplayr 648
  .L2:
2387 hidnplayr 649
        mov     [device.name], device_l2
650
        jmp     .L10
1196 hidnplayr 651
  .L4:
2387 hidnplayr 652
        mov     [device.name], device_l4
1492 hidnplayr 653
;        mov     [device.fdx], 1
2387 hidnplayr 654
        jmp     .L10
1196 hidnplayr 655
  .L5:
2387 hidnplayr 656
        mov     [device.name], device_l5
1492 hidnplayr 657
;        mov     [device.fdx], 1
2387 hidnplayr 658
        mov     [device.mii], 1
659
        mov     [device.fset], 1
660
        mov     [device.ltint], 1
661
        jmp     .L10
1196 hidnplayr 662
  .L6:
2387 hidnplayr 663
        mov     [device.name], device_l6
1492 hidnplayr 664
;        mov     [device.fdx], 1
2387 hidnplayr 665
        mov     [device.mii], 1
666
        mov     [device.fset], 1
667
        jmp     .L10
1196 hidnplayr 668
  .L7:
2387 hidnplayr 669
        mov     [device.name], device_l7
1492 hidnplayr 670
;        mov     [device.fdx], 1
2387 hidnplayr 671
        mov     [device.mii], 1
672
        jmp     .L10
1196 hidnplayr 673
  .L8:
2387 hidnplayr 674
        mov     [device.name], device_l8
1492 hidnplayr 675
;        mov     [device.fdx], 1
2387 hidnplayr 676
        mov     ecx, PCNET_CSR_RXPOLL
677
        call    dword [device.access_read_bcr]
678
        call    dword [device.access_write_bcr]
679
        jmp     .L10
1196 hidnplayr 680
  .L9:
2387 hidnplayr 681
        mov     [device.name], device_l9
1492 hidnplayr 682
;        mov     [device.fdx], 1
2387 hidnplayr 683
        mov     [device.mii], 1
1196 hidnplayr 684
  .L10:
2387 hidnplayr 685
        DEBUGF 1,"device name: %s\n",[device.name]
1196 hidnplayr 686
 
2387 hidnplayr 687
        cmp     [device.fset], 1
688
        jne     .L11
689
        mov     ecx, PCNET_BCR_BUSCTL
690
        call    [device.access_read_bcr]
691
        or      eax, 0x800
692
        call    [device.access_write_bcr]
1196 hidnplayr 693
 
2387 hidnplayr 694
        mov     ecx, PCNET_CSR_DMACTL
695
        call    [device.access_read_csr]
1564 hidnplayr 696
;        and     eax, 0xc00
697
;        or      eax, 0xc00
2387 hidnplayr 698
        mov     eax, 0xc00
699
        call    [device.access_write_csr]
1196 hidnplayr 700
 
2387 hidnplayr 701
        mov     [device.dxsuflo],1
702
        mov     [device.ltint],1
1196 hidnplayr 703
  .L11:
704
 
2387 hidnplayr 705
        make_bus_master [device.pci_bus], [device.pci_dev]
1564 hidnplayr 706
 
2387 hidnplayr 707
        mov     eax, PCNET_PORT_ASEL
708
        mov     [device.options], eax
709
        mov     [device.mode_], word 0x0003
710
        mov     [device.tlen_rlen], word (PCNET_TX_RING_LEN_BITS or PCNET_RX_RING_LEN_BITS)
1196 hidnplayr 711
 
2387 hidnplayr 712
        mov     dword [device.filter], 0
713
        mov     dword [device.filter+4], 0
1196 hidnplayr 714
 
2387 hidnplayr 715
        mov     eax, PCNET_IMR
716
        mov     ecx, PCNET_CSR_IMR                      ; Write interrupt mask
717
        call    [device.access_write_csr]
1196 hidnplayr 718
 
1492 hidnplayr 719
align 4
1196 hidnplayr 720
reset:
721
 
722
; attach int handler
723
 
2387 hidnplayr 724
        movzx   eax, [device.irq_line]
725
        DEBUGF  1,"Attaching int handler to irq %x\n",eax:1
726
        stdcall AttachIntHandler, eax, int_handler, dword 0
727
        test    eax, eax
728
        jnz     @f
729
        DEBUGF  1,"\nCould not attach int handler!\n"
1196 hidnplayr 730
;        or      eax, -1
731
;        ret
732
  @@:
733
 
2387 hidnplayr 734
        mov     edx, [device.io_addr]
735
        call    [device.access_reset]
1492 hidnplayr 736
 
2387 hidnplayr 737
        ; Switch pcnet32 to 32bit mode
738
        mov     ecx, PCNET_BCR_SSTYLE
739
        mov     eax, 2
740
        call    [device.access_write_bcr]
1492 hidnplayr 741
 
2387 hidnplayr 742
        ; set/reset autoselect bit
743
        mov     ecx, PCNET_BCR_MISCCFG
744
        call    [device.access_read_bcr]
745
        and     eax,not 2
746
        test    [device.options], PCNET_PORT_ASEL
747
        jz      .L1
748
        or      eax, 2
1196 hidnplayr 749
  .L1:
2387 hidnplayr 750
        call    [device.access_write_bcr]
1196 hidnplayr 751
 
752
 
2387 hidnplayr 753
        ; Handle full duplex setting
754
        cmp     byte [device.full_duplex], 0
755
        je      .L2
756
        mov     ecx, PCNET_BCR_DUPLEX
757
        call    [device.access_read_bcr]
758
        and     eax, not 3
759
        test    [device.options], PCNET_PORT_FD
760
        jz      .L3
761
        or      eax, 1
762
        cmp     [device.options], PCNET_PORT_FD or PCNET_PORT_AUI
763
        jne     .L4
764
        or      eax, 2
765
        jmp     .L4
1196 hidnplayr 766
  .L3:
2387 hidnplayr 767
        test    [device.options], PCNET_PORT_ASEL
768
        jz      .L4
769
        cmp     [device.chip_version], 0x2627
770
        jne     .L4
771
        or      eax, 3
1196 hidnplayr 772
  .L4:
2387 hidnplayr 773
        mov     ecx, PCNET_BCR_DUPLEX
774
        call    [device.access_write_bcr]
1196 hidnplayr 775
  .L2:
776
 
777
 
2387 hidnplayr 778
        ; set/reset GPSI bit in test register
779
        mov     ecx, 124
780
        call    [device.access_read_csr]
781
        mov     ecx, [device.options]
782
        and     ecx, PCNET_PORT_PORTSEL
783
        cmp     ecx, PCNET_PORT_GPSI
784
        jne     .L5
785
        or      eax, 0x10
1196 hidnplayr 786
  .L5:
2387 hidnplayr 787
        call    [device.access_write_csr]
788
        cmp     [device.mii], 0
789
        je      .L6
790
        test    [device.options], PCNET_PORT_ASEL
791
        jnz     .L6
792
        mov     ecx, PCNET_BCR_MIICTL
793
        call    [device.access_read_bcr]
794
        and     eax,not 0x38
795
        test    [device.options], PCNET_PORT_FD
796
        jz      .L7
797
        or      eax, 0x10
1196 hidnplayr 798
  .L7:
2387 hidnplayr 799
        test    [device.options], PCNET_PORT_100
800
        jz      .L8
801
        or      eax, 0x08
1196 hidnplayr 802
  .L8:
2387 hidnplayr 803
        call    [device.access_write_bcr]
804
        jmp     .L9
1196 hidnplayr 805
.L6:
2387 hidnplayr 806
        test    [device.options], PCNET_PORT_ASEL
807
        jz      .L9
808
        mov     ecx, PCNET_BCR_MIICTL
809
        DEBUGF 1,"ASEL, enable auto-negotiation\n"
810
        call    [device.access_read_bcr]
811
        and     eax, not 0x98
812
        or      eax, 0x20
813
        call    [device.access_write_bcr]
1196 hidnplayr 814
.L9:
2387 hidnplayr 815
        cmp     [device.ltint],0
816
        je      .L10
817
        mov     ecx,5
818
        call    [device.access_read_csr]
819
        or      eax,(1 shl 14)
820
        call    [device.access_write_csr]
1196 hidnplayr 821
.L10:
2387 hidnplayr 822
        mov     eax,[device.options]
823
        and     eax,PCNET_PORT_PORTSEL
824
        shl     eax,7
825
        mov     [device.mode_],ax
826
        mov     dword [device.filter], -1
827
        mov     dword [device.filter+4], -1
1196 hidnplayr 828
 
2387 hidnplayr 829
        call    read_mac
1196 hidnplayr 830
 
2387 hidnplayr 831
        lea     esi, [device.mac]
832
        lea     edi, [device.phys_addr]
833
        movsd
834
        movsw
1201 clevermous 835
 
2387 hidnplayr 836
        call    init_ring
1564 hidnplayr 837
 
2387 hidnplayr 838
        lea     eax, [device.private]
839
        GetRealAddr
1564 hidnplayr 840
 
2387 hidnplayr 841
        push    eax
842
        and     eax, 0xffff
843
        mov     ecx, 1
844
        call    [device.access_write_csr]
845
        pop     eax
846
        shr     eax,16
847
        mov     ecx,2
848
        call    [device.access_write_csr]
1196 hidnplayr 849
 
2387 hidnplayr 850
        mov     ecx,4
851
        mov     eax,0x0915
852
        call    [device.access_write_csr]
1196 hidnplayr 853
 
2387 hidnplayr 854
        mov     ecx,0
855
        mov     eax,1
856
        call    [device.access_write_csr]
1196 hidnplayr 857
 
2387 hidnplayr 858
        mov     [device.tx_full],0
859
        mov     [device.cur_rx],0
860
        mov     [device.cur_tx],0
861
        mov     [device.dirty_rx],0
862
        mov     [device.dirty_tx],0
1196 hidnplayr 863
 
2387 hidnplayr 864
        mov     ecx,100
1196 hidnplayr 865
.L11:
2387 hidnplayr 866
        push    ecx
867
        xor     ecx,ecx
868
        call    [device.access_read_csr]
869
        pop     ecx
870
        test    ax,0x100
871
        jnz     .L12
872
        loop    .L11
1196 hidnplayr 873
.L12:
874
 
2387 hidnplayr 875
        DEBUGF 1,"hardware reset\n"
876
        xor     ecx, ecx
877
        mov     eax, 0x0002
878
        call    [device.access_write_csr]
1196 hidnplayr 879
 
2387 hidnplayr 880
        xor     ecx, ecx
881
        call    [device.access_read_csr]
1196 hidnplayr 882
 
2387 hidnplayr 883
        xor     ecx, ecx
884
        mov     eax, PCNET_CSR_INTEN or PCNET_CSR_START
885
        call    [device.access_write_csr]
1196 hidnplayr 886
 
1564 hidnplayr 887
; Set the mtu, kernel will be able to send now
2387 hidnplayr 888
        mov     [device.mtu], 1514
1564 hidnplayr 889
 
2387 hidnplayr 890
        DEBUGF 1,"PCNET reset complete\n"
891
        xor     eax, eax
892
        ret
1492 hidnplayr 893
 
1519 hidnplayr 894
 
1564 hidnplayr 895
align 4
896
init_ring:
897
 
2387 hidnplayr 898
        mov     ecx, PCNET_RX_RING_SIZE
899
        mov     edi, [device.rx_buffer]
900
        mov     eax, edi
901
        GetRealAddr
902
        mov     [device.rx_ring_phys], eax
903
        add     eax, PCNET_RX_RING_SIZE * buf_head.size
1564 hidnplayr 904
  .rx_init:
2387 hidnplayr 905
        mov     [edi + buf_head.base], eax
906
        mov     [edi + buf_head.length], PCNET_PKT_BUF_SZ_NEG
907
        mov     [edi + buf_head.status], 0x8000
908
        and     dword [edi + buf_head.msg_length], 0
909
        and     dword [edi + buf_head.reserved], 0
910
        add     eax, PCNET_PKT_BUF_SZ
911
        add     edi, buf_head.size
912
        loop    .rx_init
1564 hidnplayr 913
 
2387 hidnplayr 914
        mov     ecx, PCNET_TX_RING_SIZE
915
        mov     edi, [device.tx_buffer]
916
        mov     eax, edi
917
        GetRealAddr
918
        mov     [device.tx_ring_phys], eax
919
        add     eax, PCNET_TX_RING_SIZE * buf_head.size
1564 hidnplayr 920
  .tx_init:
2387 hidnplayr 921
        mov     [edi + buf_head.base], eax
922
        and     dword [edi + buf_head.length], 0
923
        and     dword [edi + buf_head.msg_length], 0
924
        and     dword [edi + buf_head.reserved], 0
925
        add     eax, PCNET_PKT_BUF_SZ
926
        add     edi, buf_head.size
927
        loop    .tx_init
1564 hidnplayr 928
 
2387 hidnplayr 929
        mov     [device.tlen_rlen], (PCNET_TX_RING_LEN_BITS or PCNET_RX_RING_LEN_BITS)
1564 hidnplayr 930
 
2387 hidnplayr 931
        ret
1196 hidnplayr 932
 
933
 
934
 
935
 
936
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
937
;;                                         ;;
938
;; Transmit                                ;;
939
;;                                         ;;
1263 clevermous 940
;; In: buffer pointer in [esp+4]           ;;
1254 hidnplayr 941
;;     size of buffer in [esp+8]           ;;
1196 hidnplayr 942
;;     pointer to device structure in ebx  ;;
943
;;                                         ;;
944
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
945
 
946
align 4
947
transmit:
2387 hidnplayr 948
        DEBUGF  1,"Transmitting packet, buffer:%x, size:%u\n",[esp+4],[esp+8]
949
        mov     eax, [esp+4]
950
        DEBUGF  1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
951
        [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
952
        [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
953
        [eax+13]:2,[eax+12]:2
1196 hidnplayr 954
 
2387 hidnplayr 955
        cmp     dword [esp+8], 1514
3155 hidnplayr 956
        ja      .nospace                        ; packet is too long
2387 hidnplayr 957
        cmp     dword [esp+8], 60
3155 hidnplayr 958
        jb      .nospace                        ; packet is too short
1196 hidnplayr 959
 
960
; check descriptor
2387 hidnplayr 961
        movzx   eax, [device.cur_tx]
962
        imul    edi, eax, PCNET_PKT_BUF_SZ
963
        shl     eax, 4
964
        add     eax, [device.tx_buffer]
965
        add     edi, [device.tx_buffer]
966
        add     edi, PCNET_TX_RING_SIZE * buf_head.size
1541 hidnplayr 967
 
2387 hidnplayr 968
        test    byte [eax + buf_head.status + 1], 80h
969
        jnz     .nospace
1201 clevermous 970
; descriptor is free, copy data
2387 hidnplayr 971
        mov     esi, [esp+4]
972
        mov     ecx, [esp+8]
973
        mov     edx, ecx
974
        shr     ecx, 2
975
        and     edx, 3
976
        rep     movsd
977
        mov     ecx, edx
978
        rep     movsb
1201 clevermous 979
; set length
2387 hidnplayr 980
        mov     ecx, [esp+8]
981
        neg     ecx
982
        mov     [eax + buf_head.length], cx
1201 clevermous 983
; put to transfer queue
2387 hidnplayr 984
        mov     [eax + buf_head.status], 0x8300
1196 hidnplayr 985
 
986
; trigger an immediate send
3197 hidnplayr 987
        mov     edx, [device.io_addr]
2387 hidnplayr 988
        xor     ecx, ecx         ; CSR0
989
        call    [device.access_read_csr]
990
        or      eax, PCNET_CSR_TX
991
        call    [device.access_write_csr]
1196 hidnplayr 992
 
993
; get next descriptor 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, ...
2387 hidnplayr 994
        inc     [device.cur_tx]
995
        and     [device.cur_tx], 3
996
        DEBUGF  2," - Packet Sent! "
1196 hidnplayr 997
 
2863 hidnplayr 998
; Update stats
999
        inc     [device.packets_tx]
1000
        mov     eax, [esp+8]
1001
        add     dword [device.bytes_tx], eax
1002
        adc     dword [device.bytes_tx + 4], 0
1003
 
1196 hidnplayr 1004
.finish:
2387 hidnplayr 1005
        DEBUGF  2," - Done!\n"
1006
        stdcall KernelFree, [esp+4]
1007
        xor     eax, eax
1008
        ret     8
1196 hidnplayr 1009
 
1201 clevermous 1010
.nospace:
2387 hidnplayr 1011
        DEBUGF  1, 'ERROR: no free transmit descriptors\n'
1012
        stdcall KernelFree, [esp+4]
1013
        or      eax, -1
1014
        ret     8
1196 hidnplayr 1015
 
1016
 
1017
 
1018
;;;;;;;;;;;;;;;;;;;;;;;
1019
;;                   ;;
1020
;; Interrupt handler ;;
1021
;;                   ;;
1022
;;;;;;;;;;;;;;;;;;;;;;;
1023
 
1024
align 4
1025
int_handler:
1026
 
2935 hidnplayr 1027
        DEBUGF  1,"\n%s int\n", my_service
1196 hidnplayr 1028
 
1029
; find pointer of device wich made IRQ occur
1030
 
2387 hidnplayr 1031
        mov     ecx, [devices]
1032
        test    ecx, ecx
2935 hidnplayr 1033
        jz      .nothing
1034
        mov     esi, device_list
1196 hidnplayr 1035
  .nextdevice:
2935 hidnplayr 1036
        mov     ebx, [esi]
1037
 
2387 hidnplayr 1038
        mov     edx, [device.io_addr]     ; get IRQ reason
1039
        push    ecx
1040
        xor     ecx, ecx ; CSR0
1041
        call    [device.access_read_csr]
1042
        pop     ecx
2935 hidnplayr 1043
        test    al, al
2387 hidnplayr 1044
        js      .got_it
2935 hidnplayr 1045
  .continue:
2387 hidnplayr 1046
        add     esi, 4
2935 hidnplayr 1047
        dec     ecx
1048
        jnz     .nextdevice
1049
  .nothing:
2387 hidnplayr 1050
        ret                                         ; If no device was found, abort (The irq was probably for a device, not registered to this driver
1196 hidnplayr 1051
 
1052
  .got_it:
2935 hidnplayr 1053
 
1054
        DEBUGF  1,"Device: %x Status: %x ", ebx, eax:2
1055
 
1196 hidnplayr 1056
;-------------------------------------------------------
1201 clevermous 1057
; Possible reasons:
1058
; initialization done - ignore
1059
; transmit done - ignore
1060
; packet received - handle
1061
; Clear ALL IRQ reasons.
1062
; N.B. One who wants to handle more than one reason must be ready
1063
; to two or more reasons in one IRQ.
2387 hidnplayr 1064
        xor     ecx, ecx
1065
        call    [device.access_write_csr]
1196 hidnplayr 1066
; Received packet ok?
1067
 
2387 hidnplayr 1068
        test    ax, PCNET_CSR_RINT
1069
        jz      @f
1196 hidnplayr 1070
 
2401 hidnplayr 1071
        push    ebx
1564 hidnplayr 1072
.receiver_test_loop:
2401 hidnplayr 1073
        pop     ebx
2387 hidnplayr 1074
        movzx   eax, [device.cur_rx]
1564 hidnplayr 1075
;        and     eax, PCNET_RX_RING_MOD_MASK
2387 hidnplayr 1076
        mov     edi, eax
1196 hidnplayr 1077
 
2387 hidnplayr 1078
        imul    esi, eax, PCNET_PKT_BUF_SZ      ;
1079
        add     esi, [device.rx_buffer]         ; esi now points to rx buffer
1080
        add     esi, PCNET_RX_RING_SIZE * buf_head.size
1196 hidnplayr 1081
 
2387 hidnplayr 1082
        shl     edi, 4                          ; desc * 16 (16 is size of one ring entry)
1083
        add     edi, [device.rx_buffer]     ; edi now points to current rx ring entry
1196 hidnplayr 1084
 
2387 hidnplayr 1085
        mov     cx , [edi + buf_head.status]
1196 hidnplayr 1086
 
2387 hidnplayr 1087
        test    cx , PCNET_RXSTAT_OWN           ; If this bit is set, the controller OWN's the packet, if not, we do
1088
        jnz     .abort
1196 hidnplayr 1089
 
2387 hidnplayr 1090
        test    cx , PCNET_RXSTAT_ENP
1091
        jz      .abort
1196 hidnplayr 1092
 
2387 hidnplayr 1093
        test    cx , PCNET_RXSTAT_STP
1094
        jz      .abort
1196 hidnplayr 1095
 
2387 hidnplayr 1096
        movzx   ecx, [edi + buf_head.msg_length]        ; get packet length in ecx
1097
        sub     ecx, 4                          ;
1196 hidnplayr 1098
 
2387 hidnplayr 1099
        push    ecx
1100
        stdcall KernelAlloc, ecx                ; Allocate a buffer to put packet into
1101
        pop     ecx
1102
        test    eax, eax                        ; Test if we allocated succesfully
1103
        jz      .abort                          ;
1196 hidnplayr 1104
 
2863 hidnplayr 1105
; Update stats
1106
        add     dword [device.bytes_rx], ecx
1107
        adc     dword [device.bytes_rx + 4], 0
1108
        inc     dword [device.packets_rx]
1109
 
2401 hidnplayr 1110
        push    ebx
2387 hidnplayr 1111
        push    .receiver_test_loop             ;
1112
        push    ecx                             ; for eth_receiver
1113
        push    eax                             ;
1196 hidnplayr 1114
 
2387 hidnplayr 1115
        xchg    edi, eax
1116
        push    ecx
1117
        shr     ecx, 2
1118
        cld
1119
        rep     movsd
1120
        pop     ecx
1121
        and     ecx, 3
1122
        rep     movsb
1196 hidnplayr 1123
 
1564 hidnplayr 1124
;       mov     word [eax + buf_head.length], PCNET_PKT_BUF_SZ_NEG
2387 hidnplayr 1125
        mov     word [eax + buf_head.status], PCNET_RXSTAT_OWN      ; Set OWN bit back to 1 (controller may write to tx-buffer again now)
1196 hidnplayr 1126
 
2387 hidnplayr 1127
        inc     [device.cur_rx]           ; update descriptor
1128
        and     [device.cur_rx], 3        ;
1196 hidnplayr 1129
 
2981 hidnplayr 1130
        jmp     Eth_input
1196 hidnplayr 1131
 
1132
  .abort:
1133
 
1541 hidnplayr 1134
  @@:
1135
 
2387 hidnplayr 1136
        ret
1196 hidnplayr 1137
 
1138
 
1139
 
1140
 
1141
;;;;;;;;;;;;;;;;;;;;;;;
1142
;;                   ;;
1143
;; Write MAC address ;;
1144
;;                   ;;
1145
;;;;;;;;;;;;;;;;;;;;;;;
1146
 
1147
align 4
2387 hidnplayr 1148
write_mac:      ; in: mac pushed onto stack (as 3 words)
1196 hidnplayr 1149
 
2387 hidnplayr 1150
        DEBUGF  1,"Writing MAC: %x-%x-%x-%x-%x-%x",[esp+0]:2,[esp+1]:2,[esp+2]:2,[esp+3]:2,[esp+4]:2,[esp+5]:2
1196 hidnplayr 1151
 
2387 hidnplayr 1152
        mov     edx, [device.io_addr]
1153
        add     dx, 2
1154
        xor     eax, eax
1564 hidnplayr 1155
 
2387 hidnplayr 1156
        mov     ecx, PCNET_CSR_PAR0
1196 hidnplayr 1157
       @@:
2387 hidnplayr 1158
        pop     ax
1159
        call    [device.access_write_csr]
1160
        DEBUGF  1,"."
1161
        inc     ecx
1162
        cmp     ecx, PCNET_CSR_PAR2
3155 hidnplayr 1163
        jb      @r
1196 hidnplayr 1164
 
2387 hidnplayr 1165
        DEBUGF  1,"\n"
1196 hidnplayr 1166
 
1167
; Notice this procedure does not ret, but continues to read_mac instead.
1168
 
1169
;;;;;;;;;;;;;;;;;;;;;;
1170
;;                  ;;
1171
;; Read MAC address ;;
1172
;;                  ;;
1173
;;;;;;;;;;;;;;;;;;;;;;
1564 hidnplayr 1174
align 4
1492 hidnplayr 1175
read_mac:
2387 hidnplayr 1176
        DEBUGF  1,"Reading MAC"
1196 hidnplayr 1177
 
2387 hidnplayr 1178
        mov     edx, [device.io_addr]
1179
        add     dx, 6
1196 hidnplayr 1180
       @@:
2387 hidnplayr 1181
        dec     dx
1182
        dec     dx
1183
        in      ax, dx
1184
        push    ax
1185
        DEBUGF  1,"."
1186
        cmp     edx, [device.io_addr]
3155 hidnplayr 1187
        ja      @r
1196 hidnplayr 1188
 
2387 hidnplayr 1189
        DEBUGF  1," %x-%x-%x-%x-%x-%x\n",[esp+0]:2,[esp+1]:2,[esp+2]:2,[esp+3]:2,[esp+4]:2,[esp+5]:2
1196 hidnplayr 1190
 
2387 hidnplayr 1191
        lea     edi, [device.mac]
1192
        pop     ax
1193
        stosw
1194
        pop     ax
1195
        stosw
1196
        pop     ax
1197
        stosw
1196 hidnplayr 1198
 
2387 hidnplayr 1199
        ret
1196 hidnplayr 1200
 
1564 hidnplayr 1201
align 4
1196 hidnplayr 1202
switch_to_wio:
1203
 
2387 hidnplayr 1204
        DEBUGF  1,"Switching to 16-bit mode\n"
1564 hidnplayr 1205
 
2387 hidnplayr 1206
        mov     [device.access_read_csr], wio_read_csr
1207
        mov     [device.access_write_csr], wio_write_csr
1208
        mov     [device.access_read_bcr], wio_read_bcr
1209
        mov     [device.access_write_bcr], wio_write_bcr
1210
        mov     [device.access_read_rap], wio_read_rap
1211
        mov     [device.access_write_rap], wio_write_rap
1212
        mov     [device.access_reset], wio_reset
1196 hidnplayr 1213
 
2387 hidnplayr 1214
        ret
1196 hidnplayr 1215
 
1564 hidnplayr 1216
align 4
1196 hidnplayr 1217
switch_to_dwio:
1218
 
2387 hidnplayr 1219
        DEBUGF  1,"Switching to 32-bit mode\n"
1564 hidnplayr 1220
 
2387 hidnplayr 1221
        mov     [device.access_read_csr], dwio_read_csr
1222
        mov     [device.access_write_csr], dwio_write_csr
1223
        mov     [device.access_read_bcr], dwio_read_bcr
1224
        mov     [device.access_write_bcr], dwio_write_bcr
1225
        mov     [device.access_read_rap], dwio_read_rap
1226
        mov     [device.access_write_rap], dwio_write_rap
1227
        mov     [device.access_reset], dwio_reset
1196 hidnplayr 1228
 
2387 hidnplayr 1229
        ret
1196 hidnplayr 1230
 
1231
 
1232
; ecx - index
1233
; return:
1234
; eax - data
1564 hidnplayr 1235
align 4
1196 hidnplayr 1236
wio_read_csr:
1237
 
2387 hidnplayr 1238
        add     edx, PCNET_WIO_RAP
1239
        mov     ax , cx
1240
        out     dx , ax
1241
        add     edx, PCNET_WIO_RDP - PCNET_WIO_RAP
1242
        in      ax , dx
1243
        and     eax, 0xffff
1244
        sub     edx, PCNET_WIO_RDP
1196 hidnplayr 1245
 
2387 hidnplayr 1246
        ret
1196 hidnplayr 1247
 
1248
 
1249
; eax - data
1250
; ecx - index
1564 hidnplayr 1251
align 4
1196 hidnplayr 1252
wio_write_csr:
1253
 
2387 hidnplayr 1254
        add     edx, PCNET_WIO_RAP
1255
        xchg    eax, ecx
1256
        out     dx , ax
1257
        xchg    eax, ecx
1258
        add     edx, PCNET_WIO_RDP - PCNET_WIO_RAP
1259
        out     dx , ax
1260
        sub     edx, PCNET_WIO_RDP
1196 hidnplayr 1261
 
2387 hidnplayr 1262
        ret
1196 hidnplayr 1263
 
1264
 
1265
; ecx - index
1266
; return:
1267
; eax - data
1564 hidnplayr 1268
align 4
1196 hidnplayr 1269
wio_read_bcr:
1270
 
2387 hidnplayr 1271
        add     edx, PCNET_WIO_RAP
1272
        mov     ax , cx
1273
        out     dx , ax
1274
        add     edx, PCNET_WIO_BDP - PCNET_WIO_RAP
1275
        in      ax , dx
1276
        and     eax, 0xffff
1277
        sub     edx, PCNET_WIO_BDP
1196 hidnplayr 1278
 
2387 hidnplayr 1279
        ret
1196 hidnplayr 1280
 
1281
 
1282
; eax - data
1283
; ecx - index
1564 hidnplayr 1284
align 4
1196 hidnplayr 1285
wio_write_bcr:
1286
 
2387 hidnplayr 1287
        add     edx, PCNET_WIO_RAP
1288
        xchg    eax, ecx
1289
        out     dx , ax
1290
        xchg    eax, ecx
1291
        add     edx, PCNET_WIO_BDP - PCNET_WIO_RAP
1292
        out     dx , ax
1293
        sub     edx, PCNET_WIO_BDP
1196 hidnplayr 1294
 
2387 hidnplayr 1295
        ret
1196 hidnplayr 1296
 
1564 hidnplayr 1297
align 4
1196 hidnplayr 1298
wio_read_rap:
1299
 
2387 hidnplayr 1300
        add     edx, PCNET_WIO_RAP
1301
        in      ax , dx
1302
        and     eax, 0xffff
1303
        sub     edx, PCNET_WIO_RAP
1196 hidnplayr 1304
 
2387 hidnplayr 1305
        ret
1196 hidnplayr 1306
 
1307
; eax - val
1564 hidnplayr 1308
align 4
1196 hidnplayr 1309
wio_write_rap:
1310
 
2387 hidnplayr 1311
        add     edx, PCNET_WIO_RAP
1312
        out     dx , ax
1313
        sub     edx, PCNET_WIO_RAP
1196 hidnplayr 1314
 
2387 hidnplayr 1315
        ret
1196 hidnplayr 1316
 
1564 hidnplayr 1317
align 4
1196 hidnplayr 1318
wio_reset:
1319
 
2387 hidnplayr 1320
        push    eax
1321
        add     edx, PCNET_WIO_RESET
1322
        in      ax , dx
1323
        pop     eax
1324
        sub     edx, PCNET_WIO_RESET
1196 hidnplayr 1325
 
2387 hidnplayr 1326
        ret
1196 hidnplayr 1327
 
1328
 
1564 hidnplayr 1329
 
1196 hidnplayr 1330
; ecx - index
1331
; return:
1332
; eax - data
1564 hidnplayr 1333
align 4
1196 hidnplayr 1334
dwio_read_csr:
1335
 
2387 hidnplayr 1336
        add     edx, PCNET_DWIO_RAP
1337
        mov     eax, ecx
1338
        out     dx , eax
1339
        add     edx, PCNET_DWIO_RDP - PCNET_DWIO_RAP
1340
        in      eax, dx
1341
        and     eax, 0xffff
1342
        sub     edx, PCNET_DWIO_RDP
1196 hidnplayr 1343
 
2387 hidnplayr 1344
        ret
1196 hidnplayr 1345
 
1346
 
1347
; ecx - index
1348
; eax - data
1564 hidnplayr 1349
align 4
1196 hidnplayr 1350
dwio_write_csr:
1351
 
2387 hidnplayr 1352
        add     edx, PCNET_DWIO_RAP
1353
        xchg    eax, ecx
1354
        out     dx , eax
1355
        add     edx, PCNET_DWIO_RDP - PCNET_DWIO_RAP
1356
        xchg    eax, ecx
1357
        out     dx , eax
1358
        sub     edx, PCNET_DWIO_RDP
1196 hidnplayr 1359
 
2387 hidnplayr 1360
        ret
1196 hidnplayr 1361
 
1362
; ecx - index
1363
; return:
1364
; eax - data
1564 hidnplayr 1365
align 4
1196 hidnplayr 1366
dwio_read_bcr:
1367
 
2387 hidnplayr 1368
        add     edx, PCNET_DWIO_RAP
1369
        mov     eax, ecx
1370
        out     dx , eax
1371
        add     edx, PCNET_DWIO_BDP - PCNET_DWIO_RAP
1372
        in      eax, dx
1373
        and     eax, 0xffff
1374
        sub     edx, PCNET_DWIO_BDP
1196 hidnplayr 1375
 
2387 hidnplayr 1376
        ret
1196 hidnplayr 1377
 
1378
 
1379
; ecx - index
1380
; eax - data
1564 hidnplayr 1381
align 4
1196 hidnplayr 1382
dwio_write_bcr:
1383
 
2387 hidnplayr 1384
        add     edx, PCNET_DWIO_RAP
1385
        xchg    eax, ecx
1386
        out     dx , eax
1387
        add     edx, PCNET_DWIO_BDP - PCNET_DWIO_RAP
1388
        xchg    eax, ecx
1389
        out     dx , eax
1390
        sub     edx, PCNET_DWIO_BDP
1196 hidnplayr 1391
 
2387 hidnplayr 1392
        ret
1196 hidnplayr 1393
 
1564 hidnplayr 1394
align 4
1196 hidnplayr 1395
dwio_read_rap:
1396
 
2387 hidnplayr 1397
        add     edx, PCNET_DWIO_RAP
1398
        in      eax, dx
1399
        and     eax, 0xffff
1400
        sub     edx, PCNET_DWIO_RAP
1196 hidnplayr 1401
 
2387 hidnplayr 1402
        ret
1196 hidnplayr 1403
 
1404
 
1405
; eax - val
1564 hidnplayr 1406
align 4
1196 hidnplayr 1407
dwio_write_rap:
1408
 
2387 hidnplayr 1409
        add     edx, PCNET_DWIO_RAP
1410
        out     dx , eax
1411
        sub     edx, PCNET_DWIO_RAP
1196 hidnplayr 1412
 
2387 hidnplayr 1413
        ret
1196 hidnplayr 1414
 
1564 hidnplayr 1415
align 4
1196 hidnplayr 1416
dwio_reset:
1417
 
2387 hidnplayr 1418
        push    eax
1419
        add     edx, PCNET_DWIO_RESET
1420
        in      eax, dx
1421
        pop     eax
1422
        sub     edx, PCNET_DWIO_RESET
1196 hidnplayr 1423
 
2387 hidnplayr 1424
        ret
1196 hidnplayr 1425
 
1426
 
1427
 
1428
; End of code
1429
 
2387 hidnplayr 1430
align 4                                       ; Place all initialised data here
1196 hidnplayr 1431
 
1564 hidnplayr 1432
devices     dd 0
1433
version       dd (5 shl 16) or (API_VERSION and 0xFFFF)
2387 hidnplayr 1434
my_service    db 'PCnet',0                    ; max 16 chars include zero
1564 hidnplayr 1435
 
1196 hidnplayr 1436
device_l2     db "PCnet/PCI 79C970",0
1437
device_l4     db "PCnet/PCI II 79C970A",0
1438
device_l5     db "PCnet/FAST 79C971",0
1439
device_l6     db "PCnet/FAST+ 79C972",0
1440
device_l7     db "PCnet/FAST III 79C973",0
1441
device_l8     db "PCnet/Home 79C978",0
1442
device_l9     db "PCnet/FAST III 79C975",0
1443
 
1444
options_mapping:
2387 hidnplayr 1445
dd PCNET_PORT_ASEL                                      ;  0 Auto-select
1446
dd PCNET_PORT_AUI                                       ;  1 BNC/AUI
1447
dd PCNET_PORT_AUI                                       ;  2 AUI/BNC
1448
dd PCNET_PORT_ASEL                                      ;  3 not supported
1449
dd PCNET_PORT_10BT or PCNET_PORT_FD                     ;  4 10baseT-FD
1450
dd PCNET_PORT_ASEL                                      ;  5 not supported
1451
dd PCNET_PORT_ASEL                                      ;  6 not supported
1452
dd PCNET_PORT_ASEL                                      ;  7 not supported
1453
dd PCNET_PORT_ASEL                                      ;  8 not supported
1454
dd PCNET_PORT_MII                                       ;  9 MII 10baseT
1455
dd PCNET_PORT_MII or PCNET_PORT_FD                      ; 10 MII 10baseT-FD
1456
dd PCNET_PORT_MII                                       ; 11 MII (autosel)
1457
dd PCNET_PORT_10BT                                      ; 12 10BaseT
1458
dd PCNET_PORT_MII or PCNET_PORT_100                     ; 13 MII 100BaseTx
1459
dd PCNET_PORT_MII or PCNET_PORT_100 or PCNET_PORT_FD    ; 14 MII 100BaseTx-FD
1460
dd PCNET_PORT_ASEL                                      ; 15 not supported
1196 hidnplayr 1461
 
2387 hidnplayr 1462
include_debug_strings                                   ; All data wich FDO uses will be included here
1196 hidnplayr 1463
 
2387 hidnplayr 1464
section '.data' data readable writable align 16         ; place all uninitialized data place here
1196 hidnplayr 1465
 
2387 hidnplayr 1466
device_list rd MAX_DEVICES                                 ; This list contains all pointers to device structures the driver is handling