xref: /freebsd-12.1/sys/dev/cs/if_cs.c (revision 578d29dd)
1 /*
2  * Copyright (c) 1997,1998 Maxim Bolotin and Oleg Sharoiko.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice unmodified, this list of conditions, and the following
10  *    disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  */
28 
29 /*
30  * $FreeBSD$
31  *
32  * Device driver for Crystal Semiconductor CS8920 based ethernet
33  *   adapters. By Maxim Bolotin and Oleg Sharoiko, 27-April-1997
34  */
35 
36 /* #define	 CS_DEBUG */
37 #include "cs.h"
38 #include "bpf.h"
39 
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/malloc.h>
43 #include <sys/sockio.h>
44 #include <sys/kernel.h>
45 #include <sys/mbuf.h>
46 #include <sys/socket.h>
47 #include <sys/sysctl.h>
48 #include <sys/syslog.h>
49 
50 #include <net/if.h>
51 #include <net/if_arp.h>
52 #include <net/if_media.h>
53 #include <net/ethernet.h>
54 
55 #if NBPF > 0
56 #include <net/bpf.h>
57 #endif
58 
59 #include <machine/clock.h>
60 
61 #include <i386/isa/isa_device.h>
62 #include <i386/isa/if_csreg.h>
63 
64 /* #include "pnp.h" */
65 #define NPNP 0
66 
67 #if NPNP > 0
68 #include <i386/isa/pnp.h>
69 #endif
70 
71 #ifdef  CS_USE_64K_DMA
72 #define CS_DMA_BUFFER_SIZE 65536
73 #else
74 #define CS_DMA_BUFFER_SIZE 16384
75 #endif
76 
77 /*
78  * cs_softc: per line info and status
79  */
80 static struct cs_softc {
81 
82         /* Ethernet common code */
83         struct arpcom arpcom;
84 
85         /* Configuration words from EEPROM */
86         int auto_neg_cnf;               /* AutoNegotitation configuration */
87 	int adapter_cnf;                /* Adapter configuration */
88         int isa_config;                 /* ISA configuration */
89         int chip_type;			/* Type of chip */
90 
91         struct ifmedia media;		/* Media information */
92 
93         int nic_addr; 			/* Base IO address of card */
94 	int send_cmd;
95         int line_ctl;                   /* */
96         int send_underrun;
97         void *recv_ring;
98 
99         unsigned char *buffer;
100         int buf_len;
101 
102 } cs_softc[NCS];
103 
104 #if NPNP > 0
105 static u_long	cs_unit = NCS;
106 #endif
107 
108 static int	cs_recv_delay = 570;
109 SYSCTL_INT(_machdep, OID_AUTO, cs_recv_delay, CTLFLAG_RW, &cs_recv_delay, 0, "");
110 
111 static int	cs_attach		__P((struct cs_softc *, int, int));
112 static int	cs_attach_isa		__P((struct isa_device *));
113 static void	cs_init			__P((void *));
114 static ointhand2_t	csintr;
115 static int	cs_ioctl		__P((struct ifnet *, u_long, caddr_t));
116 static int	cs_probe		__P((struct isa_device *));
117 static int	cs_cs89x0_probe		__P((struct cs_softc *,
118 					 u_int *, int *, int, int, int));
119 static void	cs_start		__P((struct ifnet *));
120 static void	cs_stop			__P((struct cs_softc *));
121 static void	cs_reset		__P((struct cs_softc *));
122 static void	cs_watchdog		__P((struct ifnet *));
123 
124 static int	cs_mediachange	__P((struct ifnet *));
125 static void	cs_mediastatus	__P((struct ifnet *, struct ifmediareq *));
126 static int      cs_mediaset	__P((struct cs_softc *, int));
127 
128 static void	cs_write_mbufs(struct cs_softc*, struct mbuf*);
129 static void	cs_xmit_buf(struct cs_softc*);
130 static int	cs_get_packet(struct cs_softc*);
131 static void	cs_setmode(struct cs_softc*);
132 
133 static int	get_eeprom_data(struct cs_softc *sc, int, int, int *);
134 static int	get_eeprom_cksum(int, int, int *);
135 static int	wait_eeprom_ready( struct cs_softc *);
136 static void	control_dc_dc( struct cs_softc *, int );
137 static int	send_test_pkt( struct cs_softc * );
138 static int	enable_tp(struct cs_softc *);
139 static int	enable_aui(struct cs_softc *);
140 static int	enable_bnc(struct cs_softc *);
141 static int      cs_duplex_auto(struct cs_softc *);
142 
143 struct isa_driver csdriver = {
144 	cs_probe,
145 	cs_attach_isa,
146 	CS_NAME,
147 	0
148 };
149 
150 static int
151 get_eeprom_data( struct cs_softc *sc, int off, int len, int *buffer)
152 {
153 	int i;
154 
155 #ifdef CS_DEBUG
156 	printf(CS_NAME":EEPROM data from %x for %x:\n", off,len);
157 #endif
158 
159 	for (i=0;i<len;i++) {
160 		if (wait_eeprom_ready(sc) < 0) return -1;
161 		/* Send command to EEPROM to read */
162 		cs_writereg(sc->nic_addr, PP_EECMD, (off+i)|EEPROM_READ_CMD );
163 		if (wait_eeprom_ready(sc)<0)
164 			return -1;
165 		buffer[i] = cs_readreg (sc->nic_addr, PP_EEData);
166 
167 #ifdef CS_DEBUG
168 		printf("%02x %02x ",(unsigned char)buffer[i],
169 					(unsigned char)buffer[i+1]);
170 #endif
171 	}
172 
173 #ifdef CS_DEBUG
174 	printf("\n");
175 #endif
176 
177 	return 0;
178 }
179 
180 static int
181 get_eeprom_cksum(int off, int len, int *buffer)
182 {
183 	int i,cksum=0;
184 
185 	for (i=0;i<len;i++)
186 		cksum+=buffer[i];
187 	cksum &= 0xffff;
188 	if (cksum==0)
189 		return 0;
190 	return -1;
191 }
192 
193 static int
194 wait_eeprom_ready(struct cs_softc *sc)
195 {
196 	DELAY ( 30000 );	/* XXX should we do some checks here ? */
197 	return 0;
198 }
199 
200 static void
201 control_dc_dc(struct cs_softc *sc, int on_not_off)
202 {
203 	unsigned int self_control = HCB1_ENBL;
204 
205 	if (((sc->adapter_cnf & A_CNF_DC_DC_POLARITY)!=0) ^ on_not_off)
206 		self_control |= HCB1;
207 	else
208 		self_control &= ~HCB1;
209 	cs_writereg( sc->nic_addr, PP_SelfCTL, self_control );
210 
211 	DELAY( 500000 );
212 }
213 
214 
215 static int
216 cs_duplex_auto(struct cs_softc *sc)
217 {
218         int i, error=0, unit=sc->arpcom.ac_if.if_unit;
219 
220         cs_writereg(sc->nic_addr, PP_AutoNegCTL,
221                     RE_NEG_NOW | ALLOW_FDX | AUTO_NEG_ENABLE );
222         for (i=0; cs_readreg(sc->nic_addr,PP_AutoNegST)&AUTO_NEG_BUSY; i++) {
223                 if (i > 40000) {
224                         printf(CS_NAME"%1d: full/half duplex "
225                                "auto negotiation timeout\n", unit);
226 			error = ETIMEDOUT;
227                         break;
228                 }
229                 DELAY(1000);
230         }
231         DELAY( 1000000 );
232 	return error;
233 }
234 
235 static int
236 enable_tp(struct cs_softc *sc)
237 {
238 	int unit = sc->arpcom.ac_if.if_unit;
239 
240 	cs_writereg(sc->nic_addr, PP_LineCTL, sc->line_ctl & ~AUI_ONLY);
241 	control_dc_dc(sc, 0);
242 	DELAY( 150000 );
243 
244 	if ((cs_readreg(sc->nic_addr, PP_LineST) & LINK_OK)==0) {
245 		printf(CS_NAME"%1d: failed to enable TP\n", unit);
246                 return EINVAL;
247 	}
248 
249 	return 0;
250 }
251 
252 /*
253  * XXX This was rewritten from Linux driver without any tests.
254  */
255 static int
256 send_test_pkt(struct cs_softc *sc)
257 {
258 	char test_packet[] = { 0,0,0,0,0,0, 0,0,0,0,0,0,
259 				0, 46,  /* A 46 in network order */
260 				0, 0,   /* DSAP=0 & SSAP=0 fields */
261 				0xf3, 0 /* Control (Test Req + P bit set) */ };
262 	int i;
263 	u_char ether_address_backup[ETHER_ADDR_LEN];
264 
265 	for (i = 0; i < ETHER_ADDR_LEN; i++) {
266 		ether_address_backup[i] = sc->arpcom.ac_enaddr[i];
267 	}
268 
269 	cs_writereg(sc->nic_addr, PP_LineCTL,
270 		cs_readreg(sc->nic_addr, PP_LineCTL) | SERIAL_TX_ON );
271 	bcopy(test_packet,
272 			sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
273 	bcopy(test_packet+ETHER_ADDR_LEN,
274 			sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
275 	outw(sc->nic_addr + TX_CMD_PORT, sc->send_cmd);
276 	outw(sc->nic_addr + TX_LEN_PORT, sizeof(test_packet));
277 
278 	/* Wait for chip to allocate memory */
279 	DELAY(50000);
280 	if (!(cs_readreg(sc->nic_addr, PP_BusST) & READY_FOR_TX_NOW)) {
281 		for (i = 0; i < ETHER_ADDR_LEN; i++) {
282 			sc->arpcom.ac_enaddr[i] = ether_address_backup[i];
283 		}
284 		return 0;
285 	}
286 
287 	outsw(sc->nic_addr + TX_FRAME_PORT, test_packet, sizeof(test_packet));
288 
289 	DELAY(30000);
290 
291 	if ((cs_readreg(sc->nic_addr,PP_TxEvent) & TX_SEND_OK_BITS) == TX_OK) {
292 		for (i = 0; i < ETHER_ADDR_LEN; i++) {
293 			sc->arpcom.ac_enaddr[i] = ether_address_backup[i];
294 		}
295 		return 1;
296 	}
297 	for (i = 0; i < ETHER_ADDR_LEN; i++) {
298 		sc->arpcom.ac_enaddr[i] = ether_address_backup[i];
299 	}
300 	return 0;
301 }
302 
303 /*
304  * XXX This was rewritten from Linux driver without any tests.
305  */
306 static int
307 enable_aui(struct cs_softc *sc)
308 {
309 	int unit = sc->arpcom.ac_if.if_unit;
310 
311 	control_dc_dc(sc, 0);
312 	cs_writereg(sc->nic_addr, PP_LineCTL,
313 		(sc->line_ctl & ~AUTO_AUI_10BASET) | AUI_ONLY);
314 
315 	if (!send_test_pkt(sc)) {
316 		printf(CS_NAME"%1d failed to enable AUI\n", unit);
317 		return EINVAL;
318         }
319         return 0;
320 }
321 
322 /*
323  * XXX This was rewritten from Linux driver without any tests.
324  */
325 static int
326 enable_bnc(struct cs_softc *sc)
327 {
328 	int unit = sc->arpcom.ac_if.if_unit;
329 
330 	control_dc_dc(sc, 1);
331 	cs_writereg(sc->nic_addr, PP_LineCTL,
332 		(sc->line_ctl & ~AUTO_AUI_10BASET) | AUI_ONLY);
333 
334 	if (!send_test_pkt(sc)) {
335 		printf(CS_NAME"%1d failed to enable BNC\n", unit);
336 		return EINVAL;
337         }
338         return 0;
339 }
340 
341 static int
342 cs_cs89x0_probe(struct cs_softc *sc, u_int *dev_irq,
343 			int *dev_drq, int iobase, int unit, int flags)
344 {
345 	unsigned rev_type = 0;
346 	int i, irq=0;
347 	int eeprom_buff[CHKSUM_LEN];
348 	int chip_type, pp_isaint, pp_isadma;
349 	char chip_revision;
350 
351 	if ((inw(iobase+ADD_PORT) & ADD_MASK) != ADD_SIG) {
352 		/* Chip not detected. Let's try to reset it */
353 		if (bootverbose)
354 			printf(CS_NAME"%1d: trying to reset the chip.\n", unit);
355 		outw(iobase+ADD_PORT, PP_SelfCTL);
356 		i = inw(iobase+DATA_PORT);
357 		outw(iobase+ADD_PORT, PP_SelfCTL);
358 		outw(iobase+DATA_PORT, i | POWER_ON_RESET);
359 		if ((inw(iobase+ADD_PORT) & ADD_MASK) != ADD_SIG)
360 			return 0;
361 	}
362 
363 	outw(iobase+ADD_PORT, PP_ChipID);
364 	if (inw(iobase+DATA_PORT) != CHIP_EISA_ID_SIG)
365 		return 0;
366 
367 	rev_type = cs_readreg(iobase, PRODUCT_ID_ADD);
368 	chip_type = rev_type & ~REVISON_BITS;
369 	chip_revision = ((rev_type & REVISON_BITS) >> 8) + 'A';
370 
371 	sc->nic_addr = iobase;
372 	sc->chip_type = chip_type;
373 	if(chip_type==CS8900) {
374 		pp_isaint = PP_CS8900_ISAINT;
375 		pp_isadma = PP_CS8900_ISADMA;
376 		sc->send_cmd = TX_CS8900_AFTER_ALL;
377 	} else {
378 		pp_isaint = PP_CS8920_ISAINT;
379 		pp_isadma = PP_CS8920_ISADMA;
380 		sc->send_cmd = TX_CS8920_AFTER_ALL;
381 	}
382 
383         /*
384          * Clear some fields so that fail of EEPROM will left them clean
385          */
386         sc->auto_neg_cnf = 0;
387         sc->adapter_cnf  = 0;
388         sc->isa_config   = 0;
389 
390 	/*
391 	 * EEPROM
392 	 */
393 	if((cs_readreg(iobase, PP_SelfST) & EEPROM_PRESENT) == 0) {
394 		printf(CS_NAME"%1d: No EEPROM, assuming defaults.\n",
395 			unit);
396 	} else {
397 		if (get_eeprom_data(sc,START_EEPROM_DATA,CHKSUM_LEN, eeprom_buff)<0) {
398 			 printf(CS_NAME"%1d: EEPROM read failed, "
399 				"assuming defaults..\n", unit);
400 		} else {
401 			if (get_eeprom_cksum(START_EEPROM_DATA,CHKSUM_LEN, eeprom_buff)<0) {
402 				printf( CS_NAME"%1d: EEPROM cheksum bad, "
403 					"assuming defaults..\n", unit );
404 			} else {
405                                 sc->auto_neg_cnf =
406                                         eeprom_buff[AUTO_NEG_CNF_OFFSET/2];
407                                 sc->adapter_cnf =
408                                         eeprom_buff[ADAPTER_CNF_OFFSET/2];
409                                 sc->isa_config =
410                                         eeprom_buff[ISA_CNF_OFFSET/2];
411 
412                                 for (i=0; i<ETHER_ADDR_LEN/2; i++) {
413                                         sc->arpcom.ac_enaddr[i*2]=
414                                                 eeprom_buff[i];
415                                         sc->arpcom.ac_enaddr[i*2+1]=
416                                                 eeprom_buff[i] >> 8;
417                                 }
418 
419                                 /*
420                                  * If no interrupt specified (or "?"),
421                                  * use what the board tells us.
422                                  */
423                                 if (*dev_irq <= 0) {
424                                         irq = sc->isa_config & INT_NO_MASK;
425                                         if (chip_type==CS8900) {
426 						switch(irq) {
427                                                 case 0: irq=10; break;
428                                                 case 1: irq=11; break;
429                                                 case 2: irq=12; break;
430                                                 case 3: irq=5;  break;
431                                                 default: printf(CS_NAME"%1d: invalid irq in EEPROM.\n",unit);
432 						}
433 						if (irq!=0)
434 							*dev_irq=(u_short)(1<<irq);
435 					} else {
436 						if (irq!=0 && irq<=CS8920_NO_INTS)
437 							*dev_irq=(u_short)(1<<irq);
438 					}
439                                 }
440 			}
441                 }
442         }
443 
444         if ((irq=ffs(*dev_irq))) {
445                 irq--;
446                 if (chip_type == CS8900) {
447 			switch(irq) {
448                         case  5: irq = 3; break;
449                         case 10: irq = 0; break;
450                         case 11: irq = 1; break;
451                         case 12: irq = 2; break;
452                         default: printf(CS_NAME"%1d: invalid irq\n", unit);
453                                 return 0;
454 			}
455                 } else {
456                         if (irq > CS8920_NO_INTS) {
457                                 printf(CS_NAME"%1d: invalid irq\n", unit);
458                                 return 0;
459                         }
460                 }
461                 cs_writereg(iobase, pp_isaint, irq);
462 	} else {
463 	       	printf(CS_NAME"%1d: invalid irq\n", unit);
464                 return 0;
465         }
466 
467         /*
468          * Temporary disabled
469          *
470         if (drq>0)
471 		cs_writereg(iobase, pp_isadma, drq);
472 	else {
473 		printf( CS_NAME"%1d: incorrect drq\n", unit );
474 		return 0;
475 	}
476         */
477 
478 	if (bootverbose)
479 		 printf(CS_NAME"%1d: model CS89%c0%s rev %c\n"
480 			CS_NAME"%1d: media%s%s%s\n"
481 			CS_NAME"%1d: irq %d drq %d\n",
482 			unit,
483 			chip_type==CS8900 ? '0' : '2',
484 			chip_type==CS8920M ? "M" : "",
485 			chip_revision,
486 			unit,
487 			(sc->adapter_cnf & A_CNF_10B_T) ? " TP"  : "",
488 			(sc->adapter_cnf & A_CNF_AUI)   ? " AUI" : "",
489 			(sc->adapter_cnf & A_CNF_10B_2) ? " BNC" : "",
490 			unit, (int)*dev_irq, (int)*dev_drq);
491 
492         if ((sc->adapter_cnf & A_CNF_EXTND_10B_2) &&
493             (sc->adapter_cnf & A_CNF_LOW_RX_SQUELCH))
494                 sc->line_ctl = LOW_RX_SQUELCH;
495         else
496                 sc->line_ctl = 0;
497 
498 
499 	return PP_ISAIOB;
500 }
501 
502 /*
503  * Determine if the device is present
504  *
505  *   on entry:
506  * 	a pointer to an isa_device struct
507  *   on exit:
508  *	NULL if device not found
509  *	or # of i/o addresses used (if found)
510  */
511 static int
512 cs_probe(struct isa_device *dev)
513 {
514 	int nports;
515 
516 	struct cs_softc *sc=&cs_softc[dev->id_unit];
517 
518 	nports=cs_cs89x0_probe(sc, &(dev->id_irq), &(dev->id_drq),
519 			(dev->id_iobase), (dev->id_unit), (dev->id_flags));
520 
521 	if (nports)
522 		return (nports);
523 
524 	return (0);
525 }
526 
527 /*
528  * Install the interface into kernel networking data structures
529  */
530 static int
531 cs_attach(struct cs_softc *sc, int unit, int flags)
532 {
533         int media=0;
534 /*	struct cs_softc *sc = &cs_softc[dev->id_unit]; */
535 	struct ifnet *ifp = &(sc->arpcom.ac_if);
536 
537 	if (!ifp->if_name) {
538 		ifp->if_softc=sc;
539 		ifp->if_unit=unit;
540 		ifp->if_name=csdriver.name;
541 		ifp->if_output=ether_output;
542 		ifp->if_start=cs_start;
543 		ifp->if_ioctl=cs_ioctl;
544 		ifp->if_watchdog=cs_watchdog;
545 		ifp->if_init=cs_init;
546 		ifp->if_snd.ifq_maxlen= IFQ_MAXLEN;
547 		/*
548                  *  MIB DATA
549                  */
550                 /*
551 		ifp->if_linkmib=&sc->mibdata;
552 		ifp->if_linkmiblen=sizeof sc->mibdata;
553                 */
554 
555 		ifp->if_flags=(IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST );
556 
557 		/*
558 		 * this code still in progress (DMA support)
559 		 *
560 
561 		sc->recv_ring=malloc(CS_DMA_BUFFER_SIZE<<1, M_DEVBUF, M_NOWAIT);
562 		if (sc->recv_ring == NULL) {
563 			log(LOG_ERR,CS_NAME
564 			"%d: Couldn't allocate memory for NIC\n", unit);
565 			return(0);
566 		}
567 		if ((sc->recv_ring-(sc->recv_ring & 0x1FFFF))
568 		    < (128*1024-CS_DMA_BUFFER_SIZE))
569 		    sc->recv_ring+=16*1024;
570 
571 		*/
572 
573 		sc->buffer=malloc(ETHER_MAX_LEN-ETHER_CRC_LEN,M_DEVBUF,M_NOWAIT);
574 		if (sc->buffer == NULL) {
575                         printf(CS_NAME"%d: Couldn't allocate memory for NIC\n",
576                                unit);
577                         return(0);
578 		}
579 
580 		/*
581 		 * Initialize the media structures.
582 		 */
583 		ifmedia_init(&sc->media, 0, cs_mediachange, cs_mediastatus);
584 
585 		if (sc->adapter_cnf & A_CNF_10B_T) {
586 			ifmedia_add(&sc->media, IFM_ETHER|IFM_10_T, 0, NULL);
587 			if (sc->chip_type != CS8900) {
588 				ifmedia_add(&sc->media,
589 					IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL);
590 				ifmedia_add(&sc->media,
591 					IFM_ETHER|IFM_10_T|IFM_HDX, 0, NULL);
592 			}
593 		}
594 
595 		if (sc->adapter_cnf & A_CNF_10B_2)
596 			ifmedia_add(&sc->media, IFM_ETHER|IFM_10_2, 0, NULL);
597 
598 		if (sc->adapter_cnf & A_CNF_AUI)
599 			ifmedia_add(&sc->media, IFM_ETHER|IFM_10_5, 0, NULL);
600 
601                 if (sc->adapter_cnf & A_CNF_MEDIA)
602                         ifmedia_add(&sc->media, IFM_ETHER|IFM_AUTO, 0, NULL);
603 
604                 /* Set default media from EEPROM */
605                 switch (sc->adapter_cnf & A_CNF_MEDIA_TYPE) {
606                 case A_CNF_MEDIA_AUTO:  media = IFM_ETHER|IFM_AUTO; break;
607                 case A_CNF_MEDIA_10B_T: media = IFM_ETHER|IFM_10_T; break;
608                 case A_CNF_MEDIA_10B_2: media = IFM_ETHER|IFM_10_2; break;
609                 case A_CNF_MEDIA_AUI:   media = IFM_ETHER|IFM_10_5; break;
610                 default: printf(CS_NAME"%d: adapter has no media\n", unit);
611                 }
612                 ifmedia_set(&sc->media, media);
613 		cs_mediaset(sc, media);
614 
615 		if_attach(ifp);
616 		cs_stop( sc );
617 		ether_ifattach(ifp);
618 	}
619 
620 	if (bootverbose)
621 		printf(CS_NAME"%d: ethernet address %6D\n",
622 		       ifp->if_unit, sc->arpcom.ac_enaddr, ":");
623 
624 #if NBPF > 0
625 	bpfattach(ifp, DLT_EN10MB, sizeof (struct ether_header));
626 #endif
627 	return 1;
628 }
629 
630 static int
631 cs_attach_isa(struct isa_device *dev)
632 {
633         int unit=dev->id_unit;
634         struct cs_softc *sc=&cs_softc[unit];
635         int flags=dev->id_flags;
636 
637 	dev->id_ointr = csintr;
638         return cs_attach(sc, unit, flags);
639 }
640 
641 /*
642  * Initialize the board
643  */
644 static void
645 cs_init(void *xsc)
646 {
647 	struct cs_softc *sc=(struct cs_softc *)xsc;
648 	struct ifnet *ifp = &sc->arpcom.ac_if;
649 	int i, s, rx_cfg;
650 
651 	/* address not known */
652 	if (TAILQ_EMPTY(&ifp->if_addrhead)) /* unlikely? XXX */
653 		return;
654 
655 	/*
656 	 * reset whatchdog timer
657 	 */
658 	ifp->if_timer=0;
659 	sc->buf_len = 0;
660 
661 	s=splimp();
662 
663 	/*
664 	 * Hardware initialization of cs
665 	 */
666 
667 	/* Enable receiver and transmitter */
668 	cs_writereg(sc->nic_addr, PP_LineCTL,
669 		cs_readreg( sc->nic_addr, PP_LineCTL ) |
670 		SERIAL_RX_ON | SERIAL_TX_ON);
671 
672 	/* Configure the receiver mode */
673 	cs_setmode(sc);
674 
675 	/*
676 	 * This defines what type of frames will cause interrupts
677 	 * Bad frames should generate interrupts so that the driver
678 	 * could track statistics of discarded packets
679 	 */
680         rx_cfg = RX_OK_ENBL | RX_CRC_ERROR_ENBL | RX_RUNT_ENBL |
681 		 RX_EXTRA_DATA_ENBL;
682 	if (sc->isa_config & STREAM_TRANSFER)
683 		rx_cfg |= RX_STREAM_ENBL;
684 	cs_writereg(sc->nic_addr, PP_RxCFG, rx_cfg);
685 
686 	cs_writereg(sc->nic_addr, PP_TxCFG, TX_LOST_CRS_ENBL |
687 		    TX_SQE_ERROR_ENBL | TX_OK_ENBL | TX_LATE_COL_ENBL |
688 		    TX_JBR_ENBL | TX_ANY_COL_ENBL | TX_16_COL_ENBL);
689 
690 	cs_writereg(sc->nic_addr, PP_BufCFG, READY_FOR_TX_ENBL |
691 		    RX_MISS_COUNT_OVRFLOW_ENBL | TX_COL_COUNT_OVRFLOW_ENBL |
692 		    TX_UNDERRUN_ENBL /*| RX_DMA_ENBL*/);
693 
694         /* Write MAC address into IA filter */
695         for (i=0; i<ETHER_ADDR_LEN/2; i++)
696                 cs_writereg(sc->nic_addr, PP_IA+i*2,
697                             sc->arpcom.ac_enaddr[i*2] |
698                             (sc->arpcom.ac_enaddr[i*2+1] << 8) );
699 
700 	/*
701 	 * Now enable everything
702 	 */
703 /*
704 #ifdef	CS_USE_64K_DMA
705 	cs_writereg(sc->nic_addr, PP_BusCTL, ENABLE_IRQ | RX_DMA_SIZE_64K);
706         #else
707 
708         cs_writereg(sc->nic_addr, PP_BusCTL, ENABLE_IRQ);
709 #endif
710 */
711 	cs_writereg(sc->nic_addr, PP_BusCTL, ENABLE_IRQ);
712 
713 	/*
714 	 * Set running and clear output active flags
715 	 */
716 	sc->arpcom.ac_if.if_flags |= IFF_RUNNING;
717 	sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
718 
719 	/*
720 	 * Start sending process
721 	 */
722 	cs_start(ifp);
723 
724 	(void) splx(s);
725 }
726 
727 /*
728  * Get the packet from the board and send it to the upper layer
729  * via ether_input().
730  */
731 static int
732 cs_get_packet(struct cs_softc *sc)
733 {
734 	struct ifnet *ifp = &(sc->arpcom.ac_if);
735 	int iobase = sc->nic_addr, status, length;
736 	struct ether_header *eh;
737 	struct mbuf *m;
738 
739 #ifdef CS_DEBUG
740 	int i;
741 #endif
742 
743 	status = inw(iobase + RX_FRAME_PORT);
744 	length = inw(iobase + RX_FRAME_PORT);
745 
746 #ifdef CS_DEBUG
747 	printf(CS_NAME"%1d: rcvd: stat %x, len %d\n",
748 		ifp->if_unit, status, length);
749 #endif
750 
751 	if (!(status & RX_OK)) {
752 #ifdef CS_DEBUG
753 		printf(CS_NAME"%1d: bad pkt stat %x\n", ifp->if_unit, status);
754 #endif
755 		ifp->if_ierrors++;
756 		return -1;
757 	}
758 
759 	MGETHDR(m, M_DONTWAIT, MT_DATA);
760 	if (m==NULL)
761 		return -1;
762 
763 	if (length > MHLEN) {
764 		MCLGET(m, M_DONTWAIT);
765 		if (!(m->m_flags & M_EXT)) {
766 			m_freem(m);
767 			return -1;
768 		}
769 	}
770 
771 	/* Initialize packet's header info */
772 	m->m_pkthdr.rcvif = ifp;
773 	m->m_pkthdr.len = length;
774 	m->m_len = length;
775 
776 	/* Get the data */
777 	insw(iobase + RX_FRAME_PORT, m->m_data, (length+1)>>1);
778 
779 	eh = mtod(m, struct ether_header *);
780 
781 #if NBPF > 0
782 	if (ifp->if_bpf)
783 		bpf_mtap(ifp, m);
784 #endif
785 
786 #ifdef CS_DEBUG
787 	for (i=0;i<length;i++)
788 	     printf(" %02x",(unsigned char)*((char *)(m->m_data+i)));
789 	printf( "\n" );
790 #endif
791 
792 	if (status & (RX_IA | RX_BROADCAST) ||
793 	    (ifp->if_flags & IFF_MULTICAST && status & RX_HASHED)) {
794 		m->m_pkthdr.len -= sizeof(struct ether_header);
795 		m->m_len -= sizeof(struct ether_header);
796 		m->m_data += sizeof(struct ether_header);
797 
798 		/* Feed the packet to the upper layer */
799 		ether_input(ifp, eh, m);
800 
801 		ifp->if_ipackets++;
802 
803 		if (length==ETHER_MAX_LEN-ETHER_CRC_LEN)
804                         DELAY( cs_recv_delay );
805 	} else {
806 		m_freem(m);
807 	}
808 
809 	return 0;
810 }
811 
812 /*
813  * Software calls interrupt handler
814  */
815 static void
816 csintr_sc(struct cs_softc *sc, int unit)
817 {
818 	struct ifnet *ifp = &(sc->arpcom.ac_if);
819 	int status;
820 
821 #ifdef CS_DEBUG
822 	printf(CS_NAME"%1d: Interrupt.\n", unit);
823 #endif
824 
825 	while ((status=cs_readword(sc->nic_addr, ISQ_PORT))) {
826 
827 #ifdef CS_DEBUG
828 		printf( CS_NAME"%1d:from ISQ: %04x\n", unit, status );
829 #endif
830 
831 		switch (status & ISQ_EVENT_MASK) {
832                 case ISQ_RECEIVER_EVENT:
833                         cs_get_packet(sc);
834                         break;
835 
836                 case ISQ_TRANSMITTER_EVENT:
837                         if (status & TX_OK)
838                                 ifp->if_opackets++;
839                         else
840                                 ifp->if_oerrors++;
841                         ifp->if_flags &= ~IFF_OACTIVE;
842                         ifp->if_timer = 0;
843                         break;
844 
845                 case ISQ_BUFFER_EVENT:
846                         if (status & READY_FOR_TX) {
847                                 ifp->if_flags &= ~IFF_OACTIVE;
848                                 ifp->if_timer = 0;
849                         }
850 
851                         if (status & TX_UNDERRUN) {
852                                 ifp->if_flags &= ~IFF_OACTIVE;
853                                 ifp->if_timer = 0;
854                                 ifp->if_oerrors++;
855                         }
856                         break;
857 
858                 case ISQ_RX_MISS_EVENT:
859                         ifp->if_ierrors+=(status>>6);
860                         break;
861 
862                 case ISQ_TX_COL_EVENT:
863                         ifp->if_collisions+=(status>>6);
864                         break;
865                 }
866         }
867 
868         if (!(ifp->if_flags & IFF_OACTIVE)) {
869                 cs_start(ifp);
870         }
871 }
872 
873 /*
874  * Handle interrupts
875  */
876 static void
877 csintr(int unit)
878 {
879 	struct cs_softc *sc = &cs_softc[unit];
880 
881 	csintr_sc(sc, unit);
882 }
883 
884 /*
885  * Save the data in buffer
886  */
887 
888 static void
889 cs_write_mbufs( struct cs_softc *sc, struct mbuf *m )
890 {
891 	int len;
892 	struct mbuf *mp;
893 	unsigned char *data, *buf;
894 
895 	for (mp=m, buf=sc->buffer, sc->buf_len=0; mp != NULL; mp=mp->m_next) {
896 		len = mp->m_len;
897 
898 		/*
899 		 * Ignore empty parts
900 		 */
901 		if (!len)
902 		continue;
903 
904 		/*
905 		 * Find actual data address
906 		 */
907 		data = mtod(mp, caddr_t);
908 
909 		bcopy((caddr_t) data, (caddr_t) buf, len);
910 		buf += len;
911 		sc->buf_len += len;
912 	}
913 }
914 
915 
916 static void
917 cs_xmit_buf( struct cs_softc *sc )
918 {
919 	outsw(sc->nic_addr+TX_FRAME_PORT, sc->buffer, (sc->buf_len+1)>>1);
920 	sc->buf_len = 0;
921 }
922 
923 static void
924 cs_start(struct ifnet *ifp)
925 {
926 	int s, length;
927 	struct mbuf *m, *mp;
928 	struct cs_softc *sc = ifp->if_softc;
929 
930 	s = splimp();
931 
932 	for (;;) {
933 		if (sc->buf_len)
934 			length = sc->buf_len;
935 		else {
936 			IF_DEQUEUE( &ifp->if_snd, m );
937 
938 			if (m==NULL) {
939 				(void) splx(s);
940 				return;
941 			}
942 
943 			for (length=0, mp=m; mp != NULL; mp=mp->m_next)
944 				length += mp->m_len;
945 
946 			/* Skip zero-length packets */
947 			if (length == 0) {
948 				m_freem(m);
949 				continue;
950 			}
951 
952 			cs_write_mbufs(sc, m);
953 
954 #if NBPF > 0
955 			if (ifp->if_bpf) {
956 				bpf_mtap(ifp, m);
957 			}
958 #endif
959 
960 			m_freem(m);
961 		}
962 
963 		/*
964 		 * Issue a SEND command
965 		 */
966 		outw(sc->nic_addr+TX_CMD_PORT, sc->send_cmd);
967 		outw(sc->nic_addr+TX_LEN_PORT, length );
968 
969 		/*
970 		 * If there's no free space in the buffer then leave
971 		 * this packet for the next time: indicate output active
972 		 * and return.
973 		 */
974 		if (!(cs_readreg(sc->nic_addr, PP_BusST) & READY_FOR_TX_NOW)) {
975 			ifp->if_timer = sc->buf_len;
976 			(void) splx(s);
977 			ifp->if_flags |= IFF_OACTIVE;
978 			return;
979 		}
980 
981                	cs_xmit_buf(sc);
982 
983 		/*
984 		 * Set the watchdog timer in case we never hear
985 		 * from board again. (I don't know about correct
986 		 * value for this timeout)
987 		 */
988 		ifp->if_timer = length;
989 
990 		(void) splx(s);
991 		ifp->if_flags |= IFF_OACTIVE;
992 		return;
993 	}
994 }
995 
996 /*
997  * Stop everything on the interface
998  */
999 static void
1000 cs_stop(struct cs_softc *sc)
1001 {
1002 	int s = splimp();
1003 
1004 	cs_writereg(sc->nic_addr, PP_RxCFG, 0);
1005 	cs_writereg(sc->nic_addr, PP_TxCFG, 0);
1006 	cs_writereg(sc->nic_addr, PP_BufCFG, 0);
1007 	cs_writereg(sc->nic_addr, PP_BusCTL, 0);
1008 
1009 	sc->arpcom.ac_if.if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
1010 	sc->arpcom.ac_if.if_timer = 0;
1011 
1012 	(void) splx(s);
1013 }
1014 
1015 /*
1016  * Reset the interface
1017  */
1018 static void
1019 cs_reset(struct cs_softc *sc)
1020 {
1021 	cs_stop(sc);
1022 	cs_init(sc);
1023 }
1024 
1025 static void
1026 cs_setmode(struct cs_softc *sc)
1027 {
1028 	struct ifnet *ifp = &(sc->arpcom.ac_if);
1029 	int rx_ctl;
1030 
1031 	/* Stop the receiver while changing filters */
1032 	cs_writereg(sc->nic_addr, PP_LineCTL,
1033 			cs_readreg(sc->nic_addr, PP_LineCTL) & ~SERIAL_RX_ON);
1034 
1035 	if (ifp->if_flags & IFF_PROMISC) {
1036 		/* Turn on promiscuous mode. */
1037 		rx_ctl = RX_OK_ACCEPT | RX_PROM_ACCEPT;
1038 	} else {
1039 		if (ifp->if_flags & IFF_MULTICAST) {
1040 			/* Allow receiving frames with multicast addresses */
1041 			rx_ctl = RX_IA_ACCEPT | RX_BROADCAST_ACCEPT |
1042 				 RX_OK_ACCEPT | RX_MULTCAST_ACCEPT;
1043 			/*
1044 			 * Here the reconfiguration of chip's multicast
1045 			 * filters should be done but I've no idea about
1046 			 * hash transformation in this chip. If you can
1047 			 * add this code or describe me the transformation
1048 			 * I'd be very glad.
1049 			 */
1050 		} else {
1051 			/*
1052 			 * Receive only good frames addressed for us and
1053 			 * good broadcasts.
1054 			 */
1055 			rx_ctl = RX_IA_ACCEPT | RX_BROADCAST_ACCEPT |
1056 				 RX_OK_ACCEPT;
1057 		}
1058 	}
1059 
1060 	/* Set up the filter */
1061 	cs_writereg(sc->nic_addr, PP_RxCTL, RX_DEF_ACCEPT | rx_ctl);
1062 
1063 	/* Turn on receiver */
1064 	cs_writereg(sc->nic_addr, PP_LineCTL,
1065 			cs_readreg(sc->nic_addr, PP_LineCTL) | SERIAL_RX_ON);
1066 }
1067 
1068 static int
1069 cs_ioctl(register struct ifnet *ifp, u_long command, caddr_t data)
1070 {
1071 	struct cs_softc *sc=ifp->if_softc;
1072 	struct ifreq *ifr = (struct ifreq *)data;
1073 	int s,error=0;
1074 
1075 #ifdef CS_DEBUG
1076 	printf(CS_NAME"%d: ioctl(%x)\n",sc->arpcom.ac_if.if_unit,command);
1077 #endif
1078 
1079 	s=splimp();
1080 
1081 	switch (command) {
1082 	case SIOCSIFADDR:
1083 	case SIOCGIFADDR:
1084 	case SIOCSIFMTU:
1085 		ether_ioctl(ifp, command, data);
1086 		break;
1087 
1088 	case SIOCSIFFLAGS:
1089 		/*
1090 		 * Switch interface state between "running" and
1091 		 * "stopped", reflecting the UP flag.
1092                  */
1093                 if (sc->arpcom.ac_if.if_flags & IFF_UP) {
1094                         if ((sc->arpcom.ac_if.if_flags & IFF_RUNNING)==0) {
1095                                 cs_init(sc);
1096                         }
1097                 } else {
1098                         if ((sc->arpcom.ac_if.if_flags & IFF_RUNNING)!=0) {
1099                                 cs_stop(sc);
1100                         }
1101 		}
1102 		/*
1103 		 * Promiscuous and/or multicast flags may have changed,
1104 		 * so reprogram the multicast filter and/or receive mode.
1105 		 *
1106 		 * See note about multicasts in cs_setmode
1107 		 */
1108 		cs_setmode(sc);
1109 		break;
1110 
1111 	case SIOCADDMULTI:
1112 	case SIOCDELMULTI:
1113 	    /*
1114 	     * Multicast list has changed; set the hardware filter
1115 	     * accordingly.
1116 	     *
1117 	     * See note about multicasts in cs_setmode
1118 	     */
1119 	    cs_setmode(sc);
1120 	    error = 0;
1121 	    break;
1122 
1123         case SIOCSIFMEDIA:
1124         case SIOCGIFMEDIA:
1125                 error = ifmedia_ioctl(ifp, ifr, &sc->media, command);
1126                 break;
1127 
1128         default:
1129 		error = EINVAL;
1130         }
1131 
1132 	(void) splx(s);
1133 	return error;
1134 }
1135 
1136 /*
1137  * Device timeout/watchdog routine. Entered if the device neglects to
1138  * generate an interrupt after a transmit has been started on it.
1139  */
1140 static void
1141 cs_watchdog(struct ifnet *ifp)
1142 {
1143 	struct cs_softc *sc = &cs_softc[ifp->if_unit];
1144 
1145 	ifp->if_oerrors++;
1146 	log(LOG_ERR, CS_NAME"%d: device timeout\n", ifp->if_unit);
1147 
1148 	/* Reset the interface */
1149 	if (ifp->if_flags & IFF_UP)
1150 		cs_reset(sc);
1151 	else
1152 		cs_stop(sc);
1153 }
1154 
1155 static int
1156 cs_mediachange(struct ifnet *ifp)
1157 {
1158 	struct cs_softc *sc = ifp->if_softc;
1159 	struct ifmedia *ifm = &sc->media;
1160 
1161 	if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
1162 		return EINVAL;
1163 
1164 	return cs_mediaset(sc, ifm->ifm_media);
1165 }
1166 
1167 static void
1168 cs_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr)
1169 {
1170 	int line_status;
1171 	struct cs_softc *sc = ifp->if_softc;
1172 
1173 	ifmr->ifm_active = IFM_ETHER;
1174 	line_status = cs_readreg(sc->nic_addr, PP_LineST);
1175 	if (line_status & TENBASET_ON) {
1176 		ifmr->ifm_active |= IFM_10_T;
1177 		if (sc->chip_type != CS8900) {
1178 			if (cs_readreg(sc->nic_addr, PP_AutoNegST) & FDX_ACTIVE)
1179 				ifmr->ifm_active |= IFM_FDX;
1180 			if (cs_readreg(sc->nic_addr, PP_AutoNegST) & HDX_ACTIVE)
1181 				ifmr->ifm_active |= IFM_HDX;
1182 		}
1183 		ifmr->ifm_status = IFM_AVALID;
1184 		if (line_status & LINK_OK)
1185 			ifmr->ifm_status |= IFM_ACTIVE;
1186 	} else {
1187 		if (line_status & AUI_ON) {
1188 			cs_writereg(sc->nic_addr, PP_SelfCTL,
1189 				    cs_readreg(sc->nic_addr, PP_SelfCTL) |
1190 				    HCB1_ENBL);
1191 			if (((sc->adapter_cnf & A_CNF_DC_DC_POLARITY)!=0)^
1192 			    (cs_readreg(sc->nic_addr, PP_SelfCTL)&HCB1))
1193 				ifmr->ifm_active |= IFM_10_2;
1194 			else
1195 				ifmr->ifm_active |= IFM_10_5;
1196 		}
1197 	}
1198 }
1199 
1200 static int
1201 cs_mediaset(struct cs_softc *sc, int media)
1202 {
1203         int error;
1204 
1205 	/* Stop the receiver & transmitter */
1206 	cs_writereg(sc->nic_addr, PP_LineCTL,
1207                     cs_readreg(sc->nic_addr, PP_LineCTL) &
1208 		    ~(SERIAL_RX_ON | SERIAL_TX_ON));
1209 
1210 #ifdef CS_DEBUG
1211 	printf(CS_NAME"%d: cs_setmedia(%x)\n",sc->arpcom.ac_if.if_unit,media);
1212 #endif
1213 
1214 	switch (IFM_SUBTYPE(media)) {
1215 	default:
1216 	case IFM_AUTO:
1217 		if ((error=enable_tp(sc))==0)
1218 			error = cs_duplex_auto(sc);
1219 		else if ((error=enable_bnc(sc)) != 0)
1220 			error = enable_aui(sc);
1221 		break;
1222 	case IFM_10_T:
1223 		if ((error=enable_tp(sc)) != 0)
1224 			break;
1225 		if (media & IFM_FDX)
1226 			cs_duplex_full(sc);
1227 		else if (media & IFM_HDX)
1228 			cs_duplex_half(sc);
1229 		else
1230 			error = cs_duplex_auto(sc);
1231 		break;
1232 	case IFM_10_2:
1233 		error = enable_bnc(sc);
1234 		break;
1235 	case IFM_10_5:
1236 		error = enable_aui(sc);
1237 		break;
1238 	}
1239 
1240 	/*
1241 	 * Turn the transmitter & receiver back on
1242 	 */
1243 	cs_writereg(sc->nic_addr, PP_LineCTL,
1244 		    cs_readreg( sc->nic_addr, PP_LineCTL ) |
1245 		    SERIAL_RX_ON | SERIAL_TX_ON);
1246 
1247 	return error;
1248 }
1249 
1250 
1251 #if NPNP > 0
1252 
1253 static struct cspnp_ids {
1254 	u_long	vend_id;
1255 	char 	*id_str;
1256 } cspnp_ids[]= {
1257 	{ 0x4060630e, "CSC6040" },
1258 	{ 0x10104d24, "IBM EtherJet" },
1259 	{ 0 }
1260 };
1261 
1262 static char *cs_pnp_probe(u_long, u_long);
1263 static void cs_pnp_attach(u_long, u_long, char *, struct isa_device *);
1264 
1265 struct pnp_device cs_pnp = {
1266 	"CS8920 based PnP Ethernet",
1267 	cs_pnp_probe,
1268 	cs_pnp_attach,
1269 	&cs_unit,
1270 	&net_imask	/* imask */
1271 };
1272 
1273 DATA_SET (pnpdevice_set, cs_pnp);
1274 
1275 struct csintr_list {
1276 	struct cs_softc *sc;
1277 	int unit;
1278 	struct csintr_list *next;
1279 };
1280 
1281 static struct csintr_list *csintr_head;
1282 
1283 static void csintr_pnp_add(struct cs_softc *sc, int unit);
1284 static void csintr_pnp(int unit);
1285 
1286 static void
1287 csintr_pnp_add(struct cs_softc *sc, int unit)
1288 {
1289     struct csintr_list *intr;
1290 
1291     if (!sc) return;
1292 
1293     intr = malloc (sizeof (*intr), M_DEVBUF, M_WAITOK);
1294     if (!intr) return;
1295 
1296     intr->sc = sc;
1297     intr->unit = unit;
1298     intr->next = csintr_head;
1299     csintr_head = intr;
1300 }
1301 
1302 /*
1303  * Interrupt handler for PNP installed card
1304  * We have to find the number of the card.
1305  */
1306 static void
1307 csintr_pnp(int unit)
1308 {
1309     struct csintr_list *intr;
1310 
1311     for (intr=csintr_head; intr; intr=intr->next) {
1312 	    if (intr->unit == unit)
1313 		csintr_sc(intr->sc, unit);
1314 		break;
1315 	}
1316 }
1317 
1318 static char *
1319 cs_pnp_probe(u_long csn, u_long vend_id)
1320 {
1321     struct cspnp_ids *ids;
1322     char	     *s=NULL;
1323 
1324     for(ids = cspnp_ids; ids->vend_id != 0; ids++) {
1325 	if (vend_id == ids->vend_id) {
1326 	    s = ids->id_str;
1327 	    break;
1328 	}
1329     }
1330 
1331     if (s) {
1332 	struct pnp_cinfo d;
1333 	int ldn = 0;
1334 
1335 	read_pnp_parms(&d, ldn);
1336 	if (d.enable == 0) {
1337 	    printf("This is a %s, but LDN %d is disabled\n", s, ldn);
1338 	    return NULL ;
1339 	}
1340 	return s;
1341     }
1342 
1343     return NULL ;
1344 }
1345 
1346 static void
1347 cs_pnp_attach(u_long csn, u_long vend_id, char *name,
1348 	struct isa_device *dev)
1349 {
1350 
1351     struct pnp_cinfo d;
1352     int	ldn = 0;
1353     int iobase, unit, flags;
1354     u_int irq;
1355     int drq;
1356     struct cs_softc *sc = malloc(sizeof *sc, M_DEVBUF, M_NOWAIT);
1357 
1358     if (read_pnp_parms ( &d , ldn ) == 0 ) {
1359 	printf("failed to read pnp parms\n");
1360 	return;
1361     }
1362 
1363     write_pnp_parms( &d, ldn );
1364     enable_pnp_card();
1365 
1366     iobase = dev->id_iobase = d.port[0];
1367     irq = dev->id_irq = (1 << d.irq[0] );
1368     drq = dev->id_drq = d.drq[0];
1369     dev->id_maddr = 0;
1370     dev->id_ointr = csintr_pnp;
1371     flags = dev->id_flags = 0;
1372     unit = dev->id_unit;
1373 
1374     if (dev->id_driver == NULL) {
1375 	dev->id_driver = &csdriver;
1376 	dev->id_id = isa_compat_nextid();
1377     }
1378 
1379     if (!sc) return;
1380 
1381     bzero(sc, sizeof *sc);
1382     if (cs_cs89x0_probe(sc, &irq, &drq, iobase, unit, flags) == 0
1383 	|| cs_attach(sc, unit, flags) == 0) {
1384 	    free(sc, M_DEVBUF);
1385     } else {
1386 	if ((irq != dev->id_irq)
1387 	    || (drq != dev->id_drq)
1388 	    || (iobase != dev->id_iobase)
1389 	    || (unit != dev->id_unit)
1390 	    || (flags != dev->id_flags)
1391 		) {
1392 		printf("failed to pnp card parametars\n");
1393 	}
1394     }
1395     csintr_pnp_add(sc, dev->id_unit);
1396 }
1397 #endif /* NPNP */
1398