1 /*======================================================================
3 A PCMCIA ethernet driver for NS8390-based cards
5 This driver supports the D-Link DE-650 and Linksys EthernetCard
6 cards, the newer D-Link and Linksys combo cards, Accton EN2212
7 cards, the RPTI EP400, and the PreMax PE-200 in non-shared-memory
8 mode, and the IBM Credit Card Adapter, the NE4100, the Thomas
9 Conrad ethernet card, and the Kingston KNE-PCM/x in shared-memory
10 mode. It will also handle the Socket EA card in either mode.
12 Copyright (C) 1998 David A. Hinds -- dhinds@hyper.stanford.edu
14 pcnet_cs.c 1.94 1999/07/29 06:04:49
16 The network driver code is based on Donald Becker's NE2000 code:
18 Written 1992,1993 by Donald Becker.
19 Copyright 1993 United States Government as represented by the
20 Director, National Security Agency. This software may be used and
21 distributed according to the terms of the GNU Public License,
22 incorporated herein by reference.
23 Donald Becker may be reached at becker@cesdis1.gsfc.nasa.gov
25 Based also on Keith Moore's changes to Don Becker's code, for IBM
26 CCAE support. Drivers merged back together, and shared-memory
27 Socket EA support added, by Ken Raeburn, September 1995.
29 ======================================================================*/
31 #include <linux/module.h>
32 #include <linux/kernel.h>
33 #include <linux/sched.h>
34 #include <linux/ptrace.h>
35 #include <linux/malloc.h>
36 #include <linux/string.h>
37 #include <linux/timer.h>
38 #include <linux/delay.h>
40 #include <asm/system.h>
42 #include <linux/netdevice.h>
43 #include "../../drivers/net/8390.h"
45 #include <pcmcia/version.h>
46 #include <pcmcia/cs_types.h>
47 #include <pcmcia/cs.h>
48 #include <pcmcia/cistpl.h>
49 #include <pcmcia/ciscode.h>
50 #include <pcmcia/ds.h>
51 #include <pcmcia/cisreg.h>
53 #define PCNET_CMD 0x00
54 #define PCNET_DATAPORT 0x10 /* NatSemi-defined port window offset. */
55 #define PCNET_RESET 0x1f /* Issue a read to reset, a write to clear. */
56 #define PCNET_MISC 0x18 /* For IBM CCAE and Socket EA cards */
58 #define PCNET_START_PG 0x40 /* First page of TX buffer */
59 #define PCNET_STOP_PG 0x80 /* Last page +1 of RX ring */
61 /* Socket EA cards have a larger packet buffer */
62 #define SOCKET_START_PG 0x01
63 #define SOCKET_STOP_PG 0xff
65 #define PCNET_RDC_TIMEOUT 0x02 /* Max wait in jiffies for Tx RDC */
67 static char *if_names
[] = { "auto", "10baseT", "10base2"};
69 #define PCMCIA_DEBUG 6
71 static int pc_debug
= PCMCIA_DEBUG
;
72 MODULE_PARM(pc_debug
, "i");
73 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
74 static char *version
=
75 "pcnet_cs.c 1.94 1999/07/29 06:04:49 (David Hinds)";
77 #define DEBUG(n, args...)
80 /*====================================================================*/
82 /* Parameters that can be set with 'insmod' */
84 /* Bit map of interrupts to choose from */
85 static u_int irq_mask
= 0xdeb8;
86 static int irq_list
[4] = { -1 };
88 /* Transceiver type, for Socket EA and IBM CC cards. */
89 static int if_port
= 1;
91 /* Use 64K packet buffer, for Socket EA cards. */
92 static int use_big_buf
= 1;
94 /* Shared memory speed, in ns */
95 static int mem_speed
= 0;
97 /* Insert a pause in block_output after sending a packet */
98 static int delay_output
= 0;
100 /* Length of delay, in microseconds */
101 static int delay_time
= 4;
103 /* Use shared memory, if available? */
104 static int use_shmem
= -1;
106 /* Ugh! Let the user hardwire the hardware address for queer cards */
107 static int hw_addr
[6] = { 0, /* ... */ };
109 MODULE_PARM(irq_mask
, "i");
110 MODULE_PARM(irq_list
, "1-4i");
111 MODULE_PARM(if_port
, "i");
112 MODULE_PARM(use_big_buf
, "i");
113 MODULE_PARM(mem_speed
, "i");
114 MODULE_PARM(delay_output
, "i");
115 MODULE_PARM(delay_time
, "i");
116 MODULE_PARM(use_shmem
, "i");
117 MODULE_PARM(hw_addr
, "6i");
119 /*====================================================================*/
121 static void pcnet_config(dev_link_t
*link
);
122 static void pcnet_release(u_long arg
);
123 static int pcnet_event(event_t event
, int priority
,
124 event_callback_args_t
*args
);
126 static int pcnet_open(struct net_device
*dev
);
127 static int pcnet_close(struct net_device
*dev
);
129 static void pcnet_reset_8390(struct net_device
*dev
);
131 static int set_config(struct net_device
*dev
, struct ifmap
*map
);
133 static int setup_shmem_window(dev_link_t
*link
, int start_pg
,
134 int stop_pg
, int cm_offset
);
135 static int setup_dma_config(dev_link_t
*link
, int start_pg
,
138 static dev_info_t dev_info
= "pcnet_cs";
140 static dev_link_t
*pcnet_attach(void);
141 static void pcnet_detach(dev_link_t
*);
143 static dev_link_t
*dev_list
;
145 /*====================================================================*/
147 typedef struct hw_info_t
{
153 #define DELAY_OUTPUT 0x01
154 #define HAS_MISC_REG 0x02
155 #define USE_BIG_BUF 0x04
156 #define HAS_IBM_MISC 0x08
157 #define IS_DL10019A 0x10
158 #define USE_SHMEM 0x80 /* autodetected */
160 static hw_info_t hw_info
[] = {
161 { /* Accton EN2212 */ 0x0ff0, 0x00, 0x00, 0xe8, DELAY_OUTPUT
},
162 { /* Allied Telesis LA-PCM */ 0x0ff0, 0x00, 0x00, 0xf4, 0 },
163 { /* APEX MultiCard */ 0x03f4, 0x00, 0x20, 0xe5, 0 },
164 { /* ASANTE FriendlyNet */ 0x4910, 0x00, 0x00, 0x94,
165 DELAY_OUTPUT
| HAS_IBM_MISC
},
166 { /* Danpex EN-6200P2 */ 0x0110, 0x00, 0x40, 0xc7, 0 },
167 { /* DataTrek NetCard */ 0x0ff0, 0x00, 0x20, 0xe8, 0 },
168 { /* Dayna CommuniCard E */ 0x0110, 0x00, 0x80, 0x19, 0 },
169 { /* D-Link DE-650 */ 0x0040, 0x00, 0x80, 0xc8, 0 },
170 { /* EP-210 Ethernet */ 0x0110, 0x00, 0x40, 0x33, 0 },
171 { /* EP4000 Ethernet */ 0x01c0, 0x00, 0x00, 0xb4, 0 },
172 { /* Epson EEN10B */ 0x0ff0, 0x00, 0x00, 0x48,
173 HAS_MISC_REG
| HAS_IBM_MISC
},
174 { /* ELECOM Laneed LD-CDWA */ 0xb8, 0x08, 0x00, 0x42, 0 },
175 { /* Hypertec Ethernet */ 0x01c0, 0x00, 0x40, 0x4c, 0 },
176 { /* IBM CCAE */ 0x0ff0, 0x08, 0x00, 0x5a,
177 HAS_MISC_REG
| HAS_IBM_MISC
},
178 { /* IBM CCAE */ 0x0ff0, 0x00, 0x04, 0xac,
179 HAS_MISC_REG
| HAS_IBM_MISC
},
180 { /* IBM CCAE */ 0x0ff0, 0x00, 0x06, 0x29,
181 HAS_MISC_REG
| HAS_IBM_MISC
},
182 { /* IBM FME */ 0x0374, 0x08, 0x00, 0x5a,
183 HAS_MISC_REG
| HAS_IBM_MISC
},
184 { /* IBM FME */ 0x0374, 0x00, 0x04, 0xac,
185 HAS_MISC_REG
| HAS_IBM_MISC
},
186 { /* Kansai KLA-PCM/T */ 0x0ff0, 0x00, 0x60, 0x87,
187 HAS_MISC_REG
| HAS_IBM_MISC
},
188 { /* NSC DP83903 */ 0x0374, 0x00, 0xc0, 0xa8,
189 HAS_MISC_REG
| HAS_IBM_MISC
},
190 { /* NSC DP83903 */ 0x0374, 0x00, 0xa0, 0xb0,
191 HAS_MISC_REG
| HAS_IBM_MISC
},
192 { /* NSC DP83903 */ 0x0198, 0x00, 0x20, 0xe0,
193 HAS_MISC_REG
| HAS_IBM_MISC
},
194 { /* I-O DATA PCLA/T */ 0x0ff0, 0x00, 0xa0, 0xb0, 0 },
195 { /* Katron PE-520 */ 0x0110, 0x00, 0x40, 0xf6, 0 },
196 { /* Kingston KNE-PCM/x */ 0x0ff0, 0x00, 0xc0, 0xf0,
197 HAS_MISC_REG
| HAS_IBM_MISC
},
198 { /* Kingston KNE-PCM/x */ 0x0ff0, 0xe2, 0x0c, 0x0f,
199 HAS_MISC_REG
| HAS_IBM_MISC
},
200 { /* Kingston KNE-PC2 */ 0x0180, 0x00, 0xc0, 0xf0, 0 },
201 { /* Maxtech PCN2000 */ 0x5000, 0x00, 0x00, 0xe8, 0 },
202 { /* NDC Instant-Link */ 0x003a, 0x00, 0x80, 0xc6, 0 },
203 { /* NE2000 Compatible */ 0x0ff0, 0x00, 0xa0, 0x0c, 0 },
204 { /* Network General Sniffer */ 0x0ff0, 0x00, 0x00, 0x65,
205 HAS_MISC_REG
| HAS_IBM_MISC
},
206 { /* Panasonic VEL211 */ 0x0ff0, 0x00, 0x80, 0x45,
207 HAS_MISC_REG
| HAS_IBM_MISC
},
208 { /* PreMax PE-200 */ 0x07f0, 0x00, 0x20, 0xe0, 0 },
209 { /* RPTI EP400 */ 0x0110, 0x00, 0x40, 0x95, 0 },
210 { /* SCM Ethernet */ 0x0ff0, 0x00, 0x20, 0xcb, 0 },
211 { /* Socket EA */ 0x4000, 0x00, 0xc0, 0x1b,
212 DELAY_OUTPUT
| HAS_MISC_REG
| USE_BIG_BUF
},
213 { /* SuperSocket RE450T */ 0x0110, 0x00, 0xe0, 0x98, 0 },
214 { /* Volktek NPL-402CT */ 0x0060, 0x00, 0x40, 0x05, 0 }
217 #define NR_INFO (sizeof(hw_info)/sizeof(hw_info_t))
219 static hw_info_t default_info
=
220 { /* Unknown NE2000 Clone */ 0x00, 0x00, 0x00, 0x00, 0 };
221 static hw_info_t dl_fast_info
=
222 { /* D-Link EtherFast */ 0x00, 0x00, 0x00, 0x00, IS_DL10019A
};
224 typedef struct pcnet_dev_t
{
225 struct net_device dev
;
231 /*======================================================================
233 This bit of code is used to avoid unregistering network devices
234 at inappropriate times. 2.2 and later kernels are fairly picky
235 about when this can happen.
237 ======================================================================*/
239 static void flush_stale_links(void)
241 dev_link_t
*link
, *next
;
242 for (link
= dev_list
; link
; link
= next
) {
244 if (link
->state
& DEV_STALE_LINK
)
249 /*====================================================================*/
251 static void cs_error(client_handle_t handle
, int func
, int ret
)
253 error_info_t err
= { func
, ret
};
254 CardServices(ReportError
, handle
, &err
);
257 /*======================================================================
259 We never need to do anything when a pcnet device is "initialized"
260 by the net software, because we only register already-found cards.
262 ======================================================================*/
264 static int pcnet_init(struct net_device
*dev
)
269 /*======================================================================
271 pcnet_attach() creates an "instance" of the driver, allocating
272 local data structures for one device. The device is registered
275 ======================================================================*/
277 static dev_link_t
*pcnet_attach(void)
279 client_reg_t client_reg
;
282 struct net_device
*dev
;
285 DEBUG(0, "pcnet_attach()\n");
288 /* Create new ethernet device */
289 link
= kmalloc(sizeof(struct dev_link_t
), GFP_KERNEL
);
290 memset(link
, 0, sizeof(struct dev_link_t
));
291 link
->release
.function
= &pcnet_release
;
292 link
->release
.data
= (u_long
)link
;
293 link
->irq
.Attributes
= IRQ_TYPE_EXCLUSIVE
;
294 link
->irq
.IRQInfo1
= IRQ_INFO2_VALID
|IRQ_LEVEL_ID
;
295 if (irq_list
[0] == -1)
296 link
->irq
.IRQInfo2
= irq_mask
;
298 for (i
= 0; i
< 4; i
++)
299 link
->irq
.IRQInfo2
|= 1 << irq_list
[i
];
300 link
->conf
.Attributes
= CONF_ENABLE_IRQ
;
302 link
->conf
.IntType
= INT_MEMORY_AND_IO
;
304 info
= kmalloc(sizeof(struct pcnet_dev_t
), GFP_KERNEL
);
305 memset(info
, 0, sizeof(struct pcnet_dev_t
));
308 dev
->name
= info
->node
.dev_name
;
309 dev
->init
= &pcnet_init
;
310 dev
->open
= &pcnet_open
;
311 dev
->stop
= &pcnet_close
;
312 dev
->set_config
= &set_config
;
316 /* Register with Card Services */
317 link
->next
= dev_list
;
319 client_reg
.dev_info
= &dev_info
;
320 client_reg
.Attributes
= INFO_IO_CLIENT
| INFO_CARD_SHARE
;
321 client_reg
.EventMask
=
322 CS_EVENT_CARD_INSERTION
| CS_EVENT_CARD_REMOVAL
|
323 CS_EVENT_RESET_PHYSICAL
| CS_EVENT_CARD_RESET
|
324 CS_EVENT_PM_SUSPEND
| CS_EVENT_PM_RESUME
;
325 client_reg
.event_handler
= &pcnet_event
;
326 client_reg
.Version
= 0x0210;
327 client_reg
.event_callback_args
.client_data
= link
;
328 ret
= CardServices(RegisterClient
, &link
->handle
, &client_reg
);
329 if (ret
!= CS_SUCCESS
) {
330 cs_error(link
->handle
, RegisterClient
, ret
);
338 /*======================================================================
340 This deletes a driver "instance". The device is de-registered
341 with Card Services. If it has been released, all local data
342 structures are freed. Otherwise, the structures will be freed
343 when the device is released.
345 ======================================================================*/
347 static void pcnet_detach(dev_link_t
*link
)
352 DEBUG(0, "pcnet_detach(0x%p)\n", link
);
354 /* Locate device structure */
355 for (linkp
= &dev_list
; *linkp
; linkp
= &(*linkp
)->next
)
356 if (*linkp
== link
) break;
362 if (link
->state
& DEV_RELEASE_PENDING
) {
363 del_timer(&link
->release
);
364 link
->state
&= ~DEV_RELEASE_PENDING
;
366 restore_flags(flags
);
368 if (link
->state
& DEV_CONFIG
) {
369 pcnet_release((u_long
)link
);
370 if (link
->state
& DEV_STALE_CONFIG
) {
371 link
->state
|= DEV_STALE_LINK
;
377 CardServices(DeregisterClient
, link
->handle
);
379 /* Unlink device structure, free bits */
382 struct net_device
*dev
= link
->priv
;
383 if (link
->dev
!= NULL
)
384 unregister_netdev(dev
);
386 kfree_s(dev
->priv
, sizeof(struct ei_device
));
387 kfree_s(dev
, sizeof(struct pcnet_dev_t
));
389 kfree_s(link
, sizeof(struct dev_link_t
));
393 /*======================================================================
395 For the Linksys EtherFast 10/100 card
397 ======================================================================*/
399 static hw_info_t
*get_dl_fast(dev_link_t
*link
)
401 struct net_device
*dev
= link
->priv
;
405 for (sum
= 0, i
= 0x14; i
< 0x1c; i
++)
406 sum
+= inb_p(dev
->base_addr
+ i
);
409 for (i
= 0; i
< 6; i
++)
410 dev
->dev_addr
[i
] = inb_p(dev
->base_addr
+ 0x14 + i
);
411 return &dl_fast_info
;
414 /*======================================================================
416 This probes for a card's hardware address, for card types that
417 encode this information in their CIS.
419 ======================================================================*/
421 static hw_info_t
*get_hwinfo(dev_link_t
*link
)
423 struct net_device
*dev
= link
->priv
;
429 /* Allocate a small memory window */
430 req
.Attributes
= WIN_DATA_WIDTH_8
|WIN_MEMORY_TYPE_AM
|WIN_ENABLE
;
431 req
.Base
= 0; req
.Size
= 0;
433 link
->win
= (window_handle_t
)link
->handle
;
434 i
= CardServices(RequestWindow
, &link
->win
, &req
);
435 if (i
!= CS_SUCCESS
) {
436 cs_error(link
->handle
, RequestWindow
, i
);
440 virt
= ioremap(req
.Base
, req
.Size
);
442 for (i
= 0; i
< NR_INFO
; i
++) {
443 mem
.CardOffset
= hw_info
[i
].offset
& ~(req
.Size
-1);
444 CardServices(MapMemPage
, link
->win
, &mem
);
445 base
= &virt
[hw_info
[i
].offset
& (req
.Size
-1)];
446 if ((readb(base
+0) == hw_info
[i
].a0
) &&
447 (readb(base
+2) == hw_info
[i
].a1
) &&
448 (readb(base
+4) == hw_info
[i
].a2
))
452 for (j
= 0; j
< 6; j
++)
453 dev
->dev_addr
[j
] = readb(base
+ (j
<<1));
457 j
= CardServices(ReleaseWindow
, link
->win
);
459 cs_error(link
->handle
, ReleaseWindow
, j
);
460 return (i
< NR_INFO
) ? hw_info
+i
: NULL
;
463 /*======================================================================
465 This probes for a card's hardware address by reading the PROM.
466 It checks the address against a list of known types, then falls
467 back to a simple NE2000 clone signature check.
469 ======================================================================*/
471 static hw_info_t
*get_prom(dev_link_t
*link
)
473 struct net_device
*dev
= link
->priv
;
474 unsigned char prom
[32];
477 /* This is lifted straight from drivers/net/ne.c */
479 unsigned char value
, offset
;
481 {E8390_NODMA
+E8390_PAGE0
+E8390_STOP
, E8390_CMD
}, /* Select page 0*/
482 {0x48, EN0_DCFG
}, /* Set byte-wide (0x48) access. */
483 {0x00, EN0_RCNTLO
}, /* Clear the count regs. */
485 {0x00, EN0_IMR
}, /* Mask completion irq. */
487 {E8390_RXOFF
, EN0_RXCR
}, /* 0x20 Set to monitor */
488 {E8390_TXOFF
, EN0_TXCR
}, /* 0x02 and loopback mode. */
491 {0x00, EN0_RSARLO
}, /* DMA starting at 0x0000. */
493 {E8390_RREAD
+E8390_START
, E8390_CMD
},
496 ioaddr
= dev
->base_addr
;
498 pcnet_reset_8390(dev
);
501 for (i
= 0; i
< sizeof(program_seq
)/sizeof(program_seq
[0]); i
++)
502 outb_p(program_seq
[i
].value
, ioaddr
+ program_seq
[i
].offset
);
504 for (i
= 0; i
< 32; i
++)
505 prom
[i
] = inb(ioaddr
+ PCNET_DATAPORT
);
506 for (i
= 0; i
< NR_INFO
; i
++) {
507 if ((prom
[0] == hw_info
[i
].a0
) &&
508 (prom
[2] == hw_info
[i
].a1
) &&
509 (prom
[4] == hw_info
[i
].a2
))
512 if ((i
< NR_INFO
) || ((prom
[28] == 0x57) && (prom
[30] == 0x57))) {
513 for (j
= 0; j
< 6; j
++)
514 dev
->dev_addr
[j
] = prom
[j
<<1];
515 return (i
< NR_INFO
) ? hw_info
+i
: &default_info
;
520 /*======================================================================
522 This should be totally unnecessary... but when we can't figure
523 out the hardware address any other way, we'll let the user hard
524 wire it when the module is initialized.
526 ======================================================================*/
528 static hw_info_t
*get_hwired(dev_link_t
*link
)
530 struct net_device
*dev
= link
->priv
;
533 for (i
= 0; i
< 6; i
++)
534 if (hw_addr
[i
] != 0) break;
538 for (i
= 0; i
< 6; i
++)
539 dev
->dev_addr
[i
] = hw_addr
[i
];
541 return &default_info
;
544 /*======================================================================
546 pcnet_config() is scheduled to run after a CARD_INSERTION event
547 is received, to configure the PCMCIA socket, and to make the
548 ethernet device available to the system.
550 ======================================================================*/
552 #define CS_CHECK(fn, args...) \
553 while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failed
555 #define CFG_CHECK(fn, args...) \
556 if (CardServices(fn, args) != 0) goto next_entry
558 static int try_io_port(dev_link_t
*link
)
561 if (link
->io
.NumPorts1
== 32) {
562 link
->io
.Attributes1
= IO_DATA_PATH_WIDTH_AUTO
;
563 if (link
->io
.NumPorts2
> 0) {
564 /* for master/slave multifunction cards */
565 link
->io
.Attributes2
= IO_DATA_PATH_WIDTH_8
;
566 link
->irq
.Attributes
=
567 IRQ_TYPE_DYNAMIC_SHARING
|IRQ_FIRST_SHARED
;
570 /* This should be two 16-port windows */
571 link
->io
.Attributes1
= IO_DATA_PATH_WIDTH_8
;
572 link
->io
.Attributes2
= IO_DATA_PATH_WIDTH_16
;
574 if (link
->io
.BasePort1
== 0) {
575 for (j
= 0; j
< 0x400; j
+= 0x20) {
576 link
->io
.BasePort1
= j
^ 0x300;
577 link
->io
.BasePort2
= (j
^ 0x300) + 0x10;
578 ret
= CardServices(RequestIO
, link
->handle
, &link
->io
);
579 if (ret
== CS_SUCCESS
) return ret
;
583 return CardServices(RequestIO
, link
->handle
, &link
->io
);
587 static void pcnet_config(dev_link_t
*link
)
589 client_handle_t handle
;
593 struct net_device
*dev
;
594 int i
, last_ret
, last_fn
, start_pg
, stop_pg
, cm_offset
;
595 int manfid
= 0, prodid
= 0, has_shmem
= 0;
599 handle
= link
->handle
;
603 DEBUG(0, "pcnet_config(0x%p)\n", link
);
605 tuple
.Attributes
= 0;
606 tuple
.TupleData
= (cisdata_t
*)buf
;
607 tuple
.TupleDataMax
= sizeof(buf
);
608 tuple
.TupleOffset
= 0;
609 tuple
.DesiredTuple
= CISTPL_CONFIG
;
610 CS_CHECK(GetFirstTuple
, handle
, &tuple
);
611 CS_CHECK(GetTupleData
, handle
, &tuple
);
612 CS_CHECK(ParseTuple
, handle
, &tuple
, &parse
);
613 link
->conf
.ConfigBase
= parse
.config
.base
;
614 link
->conf
.Present
= parse
.config
.rmask
[0];
617 link
->state
|= DEV_CONFIG
;
619 tuple
.DesiredTuple
= CISTPL_MANFID
;
620 tuple
.Attributes
= TUPLE_RETURN_COMMON
;
621 if ((CardServices(GetFirstTuple
, handle
, &tuple
) == CS_SUCCESS
) &&
622 (CardServices(GetTupleData
, handle
, &tuple
) == CS_SUCCESS
)) {
623 manfid
= le16_to_cpu(buf
[0]);
624 prodid
= le16_to_cpu(buf
[1]);
627 tuple
.DesiredTuple
= CISTPL_CFTABLE_ENTRY
;
628 tuple
.Attributes
= 0;
629 CS_CHECK(GetFirstTuple
, handle
, &tuple
);
630 while (last_ret
== CS_SUCCESS
) {
631 cistpl_cftable_entry_t
*cfg
= &(parse
.cftable_entry
);
632 cistpl_io_t
*io
= &(parse
.cftable_entry
.io
);
634 CFG_CHECK(GetTupleData
, handle
, &tuple
);
635 CFG_CHECK(ParseTuple
, handle
, &tuple
, &parse
);
636 if ((cfg
->index
== 0) || (cfg
->io
.nwin
== 0))
639 link
->conf
.ConfigIndex
= cfg
->index
;
640 /* For multifunction cards, by convention, we configure the
641 network function with window 0, and serial with window 1 */
643 i
= (io
->win
[1].len
> io
->win
[0].len
);
644 link
->io
.BasePort2
= io
->win
[1-i
].base
;
645 link
->io
.NumPorts2
= io
->win
[1-i
].len
;
647 i
= link
->io
.NumPorts2
= 0;
649 has_shmem
= ((cfg
->mem
.nwin
== 1) &&
650 (cfg
->mem
.win
[0].len
>= 0x4000));
651 link
->io
.BasePort1
= io
->win
[i
].base
;
652 link
->io
.NumPorts1
= io
->win
[i
].len
;
653 if (link
->io
.NumPorts1
+ link
->io
.NumPorts2
>= 32) {
654 last_ret
= try_io_port(link
);
655 if (last_ret
== CS_SUCCESS
) break;
658 last_ret
= CardServices(GetNextTuple
, handle
, &tuple
);
660 if (last_ret
!= CS_SUCCESS
) {
661 cs_error(handle
, RequestIO
, last_ret
);
665 CS_CHECK(RequestIRQ
, handle
, &link
->irq
);
667 if (link
->io
.NumPorts2
== 8) {
668 link
->conf
.Attributes
|= CONF_ENABLE_SPKR
;
669 link
->conf
.Status
= CCSR_AUDIO_ENA
;
671 if ((manfid
== MANFID_IBM
) &&
672 (prodid
== PRODID_IBM_HOME_AND_AWAY
))
673 link
->conf
.ConfigIndex
|= 0x10;
675 CS_CHECK(RequestConfiguration
, handle
, &link
->conf
);
676 dev
->irq
= link
->irq
.AssignedIRQ
;
677 dev
->base_addr
= link
->io
.BasePort1
;
678 if ((if_port
== 1) || (if_port
== 2))
679 dev
->if_port
= if_port
;
681 printk(KERN_NOTICE
"pcnet_cs: invalid if_port requested\n");
683 if (register_netdev(dev
) != 0) {
684 printk(KERN_NOTICE
"pcnet_cs: register_netdev() failed\n");
688 hw_info
= get_hwinfo(link
);
690 hw_info
= get_prom(link
);
692 hw_info
= get_dl_fast(link
);
694 hw_info
= get_hwired(link
);
696 if (hw_info
== NULL
) {
697 printk(KERN_NOTICE
"pcnet_cs: unable to read hardware net address\n");
701 info
->flags
= hw_info
->flags
;
702 /* Check for user overrides */
703 info
->flags
|= (delay_output
) ? DELAY_OUTPUT
: 0;
704 if ((manfid
== MANFID_SOCKET
) && (prodid
== PRODID_SOCKET_LPE
))
705 info
->flags
&= ~USE_BIG_BUF
;
707 info
->flags
&= ~USE_BIG_BUF
;
709 if (info
->flags
& USE_BIG_BUF
) {
710 start_pg
= SOCKET_START_PG
;
711 stop_pg
= SOCKET_STOP_PG
;
714 start_pg
= PCNET_START_PG
;
715 stop_pg
= PCNET_STOP_PG
;
719 /* has_shmem is ignored if use_shmem != -1 */
720 if ((use_shmem
== 0) || (!has_shmem
&& (use_shmem
== -1)) ||
721 (setup_shmem_window(link
, start_pg
, stop_pg
, cm_offset
) != 0))
722 setup_dma_config(link
, start_pg
, stop_pg
);
724 ei_status
.name
= "NE2000";
725 ei_status
.word16
= 1;
726 ei_status
.reset_8390
= &pcnet_reset_8390
;
728 link
->dev
= &info
->node
;
729 link
->state
&= ~DEV_CONFIG_PENDING
;
731 printk(KERN_INFO
"%s: NE2000 Compatible: io %#3lx, irq %d,",
732 dev
->name
, dev
->base_addr
, dev
->irq
);
733 if (info
->flags
& USE_SHMEM
)
734 printk (" mem %#5lx,", dev
->mem_start
);
735 if (info
->flags
& HAS_MISC_REG
)
736 printk(" %s xcvr,", if_names
[dev
->if_port
]);
738 for (i
= 0; i
< 6; i
++)
739 printk("%02X%s", dev
->dev_addr
[i
], ((i
<5) ? ":" : "\n"));
743 unregister_netdev(dev
);
746 cs_error(link
->handle
, last_fn
, last_ret
);
748 pcnet_release((u_long
)link
);
752 /*======================================================================
754 After a card is removed, pcnet_release() will unregister the net
755 device, and release the PCMCIA configuration. If the device is
756 still open, this will be postponed until it is closed.
758 ======================================================================*/
760 static void pcnet_release(u_long arg
)
762 dev_link_t
*link
= (dev_link_t
*)arg
;
763 pcnet_dev_t
*info
= link
->priv
;
765 DEBUG(0, "pcnet_release(0x%p)\n", link
);
768 DEBUG(1, "pcnet_cs: release postponed, '%s' still open\n",
769 info
->node
.dev_name
);
770 link
->state
|= DEV_STALE_CONFIG
;
774 if (info
->flags
& USE_SHMEM
) {
776 CardServices(ReleaseWindow
, link
->win
);
778 CardServices(ReleaseConfiguration
, link
->handle
);
779 CardServices(ReleaseIO
, link
->handle
, &link
->io
);
780 CardServices(ReleaseIRQ
, link
->handle
, &link
->irq
);
782 link
->state
&= ~(DEV_CONFIG
| DEV_RELEASE_PENDING
);
784 } /* pcnet_release */
786 /*======================================================================
788 The card status event handler. Mostly, this schedules other
789 stuff to run after an event is received. A CARD_REMOVAL event
790 also sets some flags to discourage the net drivers from trying
791 to talk to the card any more.
793 ======================================================================*/
795 static int pcnet_event(event_t event
, int priority
,
796 event_callback_args_t
*args
)
798 dev_link_t
*link
= args
->client_data
;
799 pcnet_dev_t
*info
= link
->priv
;
801 DEBUG(2, "pcnet_event(0x%06x)\n", event
);
804 case CS_EVENT_CARD_REMOVAL
:
805 link
->state
&= ~DEV_PRESENT
;
806 if (link
->state
& DEV_CONFIG
) {
807 info
->dev
.tbusy
= 1; info
->dev
.start
= 0;
808 link
->release
.expires
= jiffies
+ HZ
/20;
809 link
->state
|= DEV_RELEASE_PENDING
;
810 add_timer(&link
->release
);
813 case CS_EVENT_CARD_INSERTION
:
814 link
->state
|= DEV_PRESENT
;
817 case CS_EVENT_PM_SUSPEND
:
818 link
->state
|= DEV_SUSPEND
;
819 /* Fall through... */
820 case CS_EVENT_RESET_PHYSICAL
:
821 if (link
->state
& DEV_CONFIG
) {
823 info
->dev
.tbusy
= 1; info
->dev
.start
= 0;
825 CardServices(ReleaseConfiguration
, link
->handle
);
828 case CS_EVENT_PM_RESUME
:
829 link
->state
&= ~DEV_SUSPEND
;
830 /* Fall through... */
831 case CS_EVENT_CARD_RESET
:
832 if (link
->state
& DEV_CONFIG
) {
833 CardServices(RequestConfiguration
, link
->handle
, &link
->conf
);
835 pcnet_reset_8390(&info
->dev
);
836 NS8390_init(&info
->dev
, 1);
837 info
->dev
.tbusy
= 0; info
->dev
.start
= 1;
845 /*====================================================================*/
847 static void set_misc_reg(struct net_device
*dev
)
849 int nic_base
= dev
->base_addr
;
850 pcnet_dev_t
*info
= (pcnet_dev_t
*)dev
;
853 if (info
->flags
& HAS_MISC_REG
) {
854 tmp
= inb_p(nic_base
+ PCNET_MISC
) & ~3;
855 if (dev
->if_port
== 2)
857 if (info
->flags
& USE_BIG_BUF
)
859 if (info
->flags
& HAS_IBM_MISC
)
861 outb_p(tmp
, nic_base
+ PCNET_MISC
);
865 /*====================================================================*/
867 static int pcnet_open(struct net_device
*dev
)
869 pcnet_dev_t
*info
= (pcnet_dev_t
*)dev
;
872 DEBUG(2, "pcnet_open('%s')\n", dev
->name
);
874 for (link
= dev_list
; link
; link
= link
->next
)
875 if (link
->priv
== dev
) break;
882 /* For D-Link EtherFast, wait for something(?) to happen */
883 if (info
->flags
& IS_DL10019A
) {
885 for (i
= 0; i
< 20; i
++) {
886 if ((inb(dev
->base_addr
+0x1c) & 0x01) == 0) break;
887 current
->state
= TASK_INTERRUPTIBLE
;
888 schedule_timeout(HZ
/10);
893 request_irq(dev
->irq
, ei_interrupt
, SA_SHIRQ
, dev_info
, dev
);
897 /*====================================================================*/
899 static int pcnet_close(struct net_device
*dev
)
903 DEBUG(2, "pcnet_close('%s')\n", dev
->name
);
905 for (link
= dev_list
; link
; link
= link
->next
)
906 if (link
->priv
== dev
) break;
909 free_irq(dev
->irq
, dev
);
911 link
->open
--; dev
->start
= 0;
912 if (link
->state
& DEV_STALE_CONFIG
) {
913 link
->release
.expires
= jiffies
+HZ
/20;
914 link
->state
|= DEV_RELEASE_PENDING
;
915 add_timer(&link
->release
);
923 /*======================================================================
925 Hard reset the card. This used to pause for the same period that
926 a 8390 reset command required, but that shouldn't be necessary.
928 ======================================================================*/
930 static void pcnet_reset_8390(struct net_device
*dev
)
932 int nic_base
= dev
->base_addr
;
935 ei_status
.txing
= ei_status
.dmaing
= 0;
937 outb(inb(nic_base
+ PCNET_RESET
), nic_base
+ PCNET_RESET
);
939 for (i
= 0; i
< 100; i
++) {
940 if ((inb_p(nic_base
+EN0_ISR
) & ENISR_RESET
) != 0)
944 outb_p(ENISR_RESET
, nic_base
+ EN0_ISR
); /* Ack intr. */
947 printk(KERN_ERR
"%s: pcnet_reset_8390() did not complete.\n",
951 } /* pcnet_reset_8390 */
953 /* ======================================================================= */
955 static int set_config(struct net_device
*dev
, struct ifmap
*map
)
957 pcnet_dev_t
*info
= (pcnet_dev_t
*)dev
;
958 if ((map
->port
!= (u_char
)(-1)) && (map
->port
!= dev
->if_port
)) {
959 if ((map
->port
!= 0) && !(info
->flags
& HAS_MISC_REG
)) {
960 printk(KERN_NOTICE
"%s: transceiver selection not "
961 "implemented\n", dev
->name
);
964 if ((map
->port
== 1) || (map
->port
== 2)) {
965 dev
->if_port
= map
->port
;
966 printk(KERN_INFO
"%s: switched to %s port\n",
967 dev
->name
, if_names
[dev
->if_port
]);
974 /* ======================================================================= */
976 static void dma_get_8390_hdr(struct net_device
*dev
,
977 struct e8390_pkt_hdr
*hdr
,
980 int nic_base
= dev
->base_addr
;
982 if (ei_status
.dmaing
) {
983 printk(KERN_NOTICE
"%s: DMAing conflict in dma_block_input."
984 "[DMAstat:%1x][irqlock:%1x][intr:%ld]\n",
985 dev
->name
, ei_status
.dmaing
, ei_status
.irqlock
,
986 (long)dev
->interrupt
);
990 ei_status
.dmaing
|= 0x01;
991 outb_p(E8390_NODMA
+E8390_PAGE0
+E8390_START
, nic_base
+ PCNET_CMD
);
992 outb_p(sizeof(struct e8390_pkt_hdr
), nic_base
+ EN0_RCNTLO
);
993 outb_p(0, nic_base
+ EN0_RCNTHI
);
994 outb_p(0, nic_base
+ EN0_RSARLO
); /* On page boundary */
995 outb_p(ring_page
, nic_base
+ EN0_RSARHI
);
996 outb_p(E8390_RREAD
+E8390_START
, nic_base
+ PCNET_CMD
);
998 insw(nic_base
+ PCNET_DATAPORT
, hdr
,
999 sizeof(struct e8390_pkt_hdr
)>>1);
1000 /* Fix for big endian systems */
1001 hdr
->count
= le16_to_cpu(hdr
->count
);
1003 outb_p(ENISR_RDC
, nic_base
+ EN0_ISR
); /* Ack intr. */
1004 ei_status
.dmaing
&= ~0x01;
1007 /* ======================================================================= */
1009 static void dma_block_input(struct net_device
*dev
, int count
,
1010 struct sk_buff
*skb
, int ring_offset
)
1012 int nic_base
= dev
->base_addr
;
1013 int xfer_count
= count
;
1014 char *buf
= skb
->data
;
1017 if ((ei_debug
> 4) && (count
!= 4))
1018 printk(KERN_DEBUG
"%s: [bi=%d]\n", dev
->name
, count
+4);
1020 if (ei_status
.dmaing
) {
1021 printk(KERN_NOTICE
"%s: DMAing conflict in dma_block_input."
1022 "[DMAstat:%1x][irqlock:%1x][intr:%ld]\n",
1023 dev
->name
, ei_status
.dmaing
, ei_status
.irqlock
,
1024 (long)dev
->interrupt
);
1027 ei_status
.dmaing
|= 0x01;
1028 outb_p(E8390_NODMA
+E8390_PAGE0
+E8390_START
, nic_base
+ PCNET_CMD
);
1029 outb_p(count
& 0xff, nic_base
+ EN0_RCNTLO
);
1030 outb_p(count
>> 8, nic_base
+ EN0_RCNTHI
);
1031 outb_p(ring_offset
& 0xff, nic_base
+ EN0_RSARLO
);
1032 outb_p(ring_offset
>> 8, nic_base
+ EN0_RSARHI
);
1033 outb_p(E8390_RREAD
+E8390_START
, nic_base
+ PCNET_CMD
);
1035 insw(nic_base
+ PCNET_DATAPORT
,buf
,count
>>1);
1037 buf
[count
-1] = inb(nic_base
+ PCNET_DATAPORT
), xfer_count
++;
1039 /* This was for the ALPHA version only, but enough people have
1040 encountering problems that it is still here. */
1042 if (ei_debug
> 4) { /* DMA termination address check... */
1043 int addr
, tries
= 20;
1045 /* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here
1046 -- it's broken for Rx on some cards! */
1047 int high
= inb_p(nic_base
+ EN0_RSARHI
);
1048 int low
= inb_p(nic_base
+ EN0_RSARLO
);
1049 addr
= (high
<< 8) + low
;
1050 if (((ring_offset
+ xfer_count
) & 0xff) == (addr
& 0xff))
1052 } while (--tries
> 0);
1054 printk(KERN_NOTICE
"%s: RX transfer address mismatch,"
1055 "%#4.4x (expected) vs. %#4.4x (actual).\n",
1056 dev
->name
, ring_offset
+ xfer_count
, addr
);
1059 outb_p(ENISR_RDC
, nic_base
+ EN0_ISR
); /* Ack intr. */
1060 ei_status
.dmaing
&= ~0x01;
1061 } /* dma_block_input */
1063 /*====================================================================*/
1065 static void dma_block_output(struct net_device
*dev
, int count
,
1066 const unsigned char *buf
,
1067 const int start_page
)
1069 int nic_base
= dev
->base_addr
;
1070 pcnet_dev_t
*info
= (pcnet_dev_t
*)dev
;
1078 printk(KERN_DEBUG
"%s: [bo=%d]\n", dev
->name
, count
);
1081 /* Round the count up for word writes. Do we need to do this?
1082 What effect will an odd byte count have on the 8390?
1083 I should check someday. */
1086 if (ei_status
.dmaing
) {
1087 printk(KERN_NOTICE
"%s: DMAing conflict in dma_block_output."
1088 "[DMAstat:%1x][irqlock:%1x][intr:%ld]\n",
1089 dev
->name
, ei_status
.dmaing
, ei_status
.irqlock
,
1090 (long)dev
->interrupt
);
1093 ei_status
.dmaing
|= 0x01;
1094 /* We should already be in page 0, but to be safe... */
1095 outb_p(E8390_PAGE0
+E8390_START
+E8390_NODMA
, nic_base
+PCNET_CMD
);
1101 outb_p(ENISR_RDC
, nic_base
+ EN0_ISR
);
1103 /* Now the normal output. */
1104 outb_p(count
& 0xff, nic_base
+ EN0_RCNTLO
);
1105 outb_p(count
>> 8, nic_base
+ EN0_RCNTHI
);
1106 outb_p(0x00, nic_base
+ EN0_RSARLO
);
1107 outb_p(start_page
, nic_base
+ EN0_RSARHI
);
1109 outb_p(E8390_RWRITE
+E8390_START
, nic_base
+ PCNET_CMD
);
1110 outsw(nic_base
+ PCNET_DATAPORT
, buf
, count
>>1);
1112 dma_start
= jiffies
;
1115 /* This was for the ALPHA version only, but enough people have
1116 encountering problems that it is still here. */
1117 if (ei_debug
> 4) { /* DMA termination address check... */
1118 int addr
, tries
= 20;
1120 int high
= inb_p(nic_base
+ EN0_RSARHI
);
1121 int low
= inb_p(nic_base
+ EN0_RSARLO
);
1122 addr
= (high
<< 8) + low
;
1123 if ((start_page
<< 8) + count
== addr
)
1125 } while (--tries
> 0);
1127 printk(KERN_NOTICE
"%s: Tx packet transfer address mismatch,"
1128 "%#4.4x (expected) vs. %#4.4x (actual).\n",
1129 dev
->name
, (start_page
<< 8) + count
, addr
);
1136 while ((inb_p(nic_base
+ EN0_ISR
) & ENISR_RDC
) == 0)
1137 if (jiffies
- dma_start
> PCNET_RDC_TIMEOUT
) {
1138 printk(KERN_NOTICE
"%s: timeout waiting for Tx RDC.\n",
1140 pcnet_reset_8390(dev
);
1141 NS8390_init(dev
, 1);
1145 outb_p(ENISR_RDC
, nic_base
+ EN0_ISR
); /* Ack intr. */
1146 if (info
->flags
& DELAY_OUTPUT
)
1147 udelay((long)delay_time
);
1148 ei_status
.dmaing
&= ~0x01;
1151 /*====================================================================*/
1153 static int setup_dma_config(dev_link_t
*link
, int start_pg
,
1156 struct net_device
*dev
= link
->priv
;
1158 ei_status
.tx_start_page
= start_pg
;
1159 ei_status
.rx_start_page
= start_pg
+ TX_PAGES
;
1160 ei_status
.stop_page
= stop_pg
;
1162 /* set up block i/o functions */
1163 ei_status
.get_8390_hdr
= &dma_get_8390_hdr
;
1164 ei_status
.block_input
= &dma_block_input
;
1165 ei_status
.block_output
= &dma_block_output
;
1170 /*====================================================================*/
1172 static void copyin(unsigned char *dest
, unsigned char *src
, int c
)
1174 unsigned short *d
= (unsigned short *) dest
;
1175 unsigned short *s
= (unsigned short *) src
;
1180 odd
= (c
& 01); c
>>= 1;
1183 do { *d
++ = readw(s
++); } while (--c
);
1185 /* get last byte by fetching a word and masking */
1187 *((unsigned char *)d
) = readw(s
) & 0xff;
1190 static void copyout(unsigned char *dest
, const unsigned char *src
, int c
)
1192 volatile unsigned short *d
= (unsigned short *) dest
;
1193 unsigned short *s
= (unsigned short *) src
;
1198 odd
= (c
& 01); c
>>= 1;
1201 do { writew(*s
++, d
++); } while (--c
);
1203 /* copy last byte doing a read-modify-write */
1205 writew((readw(d
) & 0xff00) | *(u_char
*)s
, d
);
1208 /*====================================================================*/
1210 static void shmem_get_8390_hdr(struct net_device
*dev
,
1211 struct e8390_pkt_hdr
*hdr
,
1214 void *xfer_start
= (void *)(dev
->rmem_start
+ (ring_page
<< 8)
1215 - (ei_status
.rx_start_page
<< 8));
1217 copyin((void *)hdr
, xfer_start
, sizeof(struct e8390_pkt_hdr
));
1218 /* Fix for big endian systems */
1219 hdr
->count
= le16_to_cpu(hdr
->count
);
1222 /*====================================================================*/
1224 static void shmem_block_input(struct net_device
*dev
, int count
,
1225 struct sk_buff
*skb
, int ring_offset
)
1227 void *xfer_start
= (void *)(dev
->rmem_start
+ ring_offset
1228 - (ei_status
.rx_start_page
<< 8));
1229 char *buf
= skb
->data
;
1231 if (xfer_start
+ count
> (void *)dev
->rmem_end
) {
1232 /* We must wrap the input move. */
1233 int semi_count
= (void*)dev
->rmem_end
- xfer_start
;
1234 copyin(buf
, xfer_start
, semi_count
);
1236 ring_offset
= ei_status
.rx_start_page
<< 8;
1237 xfer_start
= (void *)dev
->rmem_start
;
1238 count
-= semi_count
;
1240 copyin(buf
, xfer_start
, count
);
1243 /*====================================================================*/
1245 static void shmem_block_output(struct net_device
*dev
, int count
,
1246 const unsigned char *buf
,
1247 const int start_page
)
1249 void *shmem
= (void *)dev
->mem_start
+ (start_page
<< 8);
1250 shmem
-= ei_status
.tx_start_page
<< 8;
1253 printk(KERN_DEBUG
"[bo=%d @ %x]\n", count
, start_page
);
1255 copyout(shmem
, buf
, count
);
1258 /*====================================================================*/
1260 static int setup_shmem_window(dev_link_t
*link
, int start_pg
,
1261 int stop_pg
, int cm_offset
)
1263 struct net_device
*dev
= link
->priv
;
1264 pcnet_dev_t
*info
= link
->priv
;
1267 int i
, window_size
, offset
, last_ret
, last_fn
;
1269 window_size
= (stop_pg
- start_pg
) << 8;
1270 if (window_size
> 32 * 1024)
1271 window_size
= 32 * 1024;
1273 /* Make sure it's a power of two. */
1274 while ((window_size
& (window_size
- 1)) != 0)
1275 window_size
+= window_size
& ~(window_size
- 1);
1277 /* Allocate a memory window */
1278 req
.Attributes
= WIN_DATA_WIDTH_16
|WIN_MEMORY_TYPE_CM
|WIN_ENABLE
;
1279 req
.Attributes
|= WIN_USE_WAIT
;
1280 req
.Base
= 0; req
.Size
= window_size
;
1281 req
.AccessSpeed
= mem_speed
;
1282 link
->win
= (window_handle_t
)link
->handle
;
1283 CS_CHECK(RequestWindow
, &link
->win
, &req
);
1285 mem
.CardOffset
= (start_pg
<< 8) + cm_offset
;
1286 offset
= mem
.CardOffset
% window_size
;
1287 mem
.CardOffset
-= offset
;
1289 CS_CHECK(MapMemPage
, link
->win
, &mem
);
1291 /* Try scribbling on the buffer */
1292 info
->base
= ioremap(req
.Base
, window_size
);
1293 for (i
= 0; i
< (TX_PAGES
<<8); i
+= 2)
1294 writew((i
>>1), info
->base
+offset
+i
);
1296 for (i
= 0; i
< (TX_PAGES
<<8); i
+= 2)
1297 if (readw(info
->base
+offset
+i
) != (i
>>1)) break;
1298 pcnet_reset_8390(dev
);
1299 if (i
!= (TX_PAGES
<<8)) {
1300 iounmap(info
->base
);
1301 CardServices(ReleaseWindow
, link
->win
);
1302 info
->base
= NULL
; link
->win
= NULL
;
1306 dev
->mem_start
= (u_long
)info
->base
+ offset
;
1307 dev
->rmem_start
= dev
->mem_start
+ (TX_PAGES
<<8);
1308 dev
->mem_end
= dev
->rmem_end
= (u_long
)info
->base
+ req
.Size
;
1310 ei_status
.tx_start_page
= start_pg
;
1311 ei_status
.rx_start_page
= start_pg
+ TX_PAGES
;
1312 ei_status
.stop_page
= start_pg
+ ((req
.Size
- offset
) >> 8);
1314 /* set up block i/o functions */
1315 ei_status
.get_8390_hdr
= &shmem_get_8390_hdr
;
1316 ei_status
.block_input
= &shmem_block_input
;
1317 ei_status
.block_output
= &shmem_block_output
;
1319 info
->flags
|= USE_SHMEM
;
1323 cs_error(link
->handle
, last_fn
, last_ret
);
1328 /*====================================================================*/
1331 int init_module(void)
1333 int init_pcnet_cs(void)
1337 DEBUG(0, "%s\n", version
);
1338 CardServices(GetCardServicesInfo
, &serv
);
1339 if (serv
.Revision
!= CS_RELEASE_CODE
) {
1340 printk(KERN_NOTICE
"pcnet_cs: Card Services release "
1341 "does not match!\n");
1344 register_pcmcia_driver(&dev_info
, &pcnet_attach
, &pcnet_detach
);
1345 DEBUG(0, "pcnet driver registered\n" );
1349 //__initcall(init_pcnet_cs);
1352 void cleanup_module(void)
1354 DEBUG(0, "pcnet_cs: unloading\n");
1355 unregister_pcmcia_driver(&dev_info
);
1356 while (dev_list
!= NULL
)
1357 pcnet_detach(dev_list
);