1 /* ISDN4BSD code */
2 /*
3  *   Copyright (c) 1998 Martijn Plak. 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  *
9  *   1. Redistributions of source code must retain the above copyright
10  *      notice, this list of conditions and the following 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  *   3. Neither the name of the author nor the names of any co-contributors
15  *      may be used to endorse or promote products derived from this software
16  *      without specific prior written permission.
17  *   4. Altered versions must be plainly marked as such, and must not be
18  *      misrepresented as being the original software and/or documentation.
19  *
20  *   THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21  *   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  *   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  *   ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24  *   FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  *   OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  *   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  *   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  *   OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  *   SUCH DAMAGE.
31  *
32  *---------------------------------------------------------------------------
33  *
34  *	isdn4bsd layer1 driver for Dynalink IS64PH isdn TA
35  *	==================================================
36  *
37  *	$Id: isic_isapnp_dynalink.c,v 1.2 2003/05/14 19:55:07 tg Stab $
38  *
39  *      last edit-date: [Fri Jan  5 11:38:29 2001]
40  *
41  *	written by Martijn Plak (martijn@be3.com)
42  *
43  *	-mp 11 jun 1998 first try, code borrowed from Creatix driver
44  *	-mp 18 jun 1998 cleaned up code
45  *	-hm FreeBSD PnP
46  *	-mp 17 dec 1998 made it compile again
47  *
48  *---------------------------------------------------------------------------*/
49 
50 /*	NOTES:
51 
52 	This driver was written for the Dynalink IS64PH ISDN TA, based on two
53 	Siemens chips (HSCX 21525 and ISAC 2186). It is sold in the Netherlands.
54 
55 	model numbers found on (my) card:
56 		IS64PH, TAS100H-N, P/N:89590555, TA200S100045521
57 
58 	chips:
59 		Siemens PSB 21525N, HSCX TE V2.1
60 		Siemens PSB 2186N, ISAC-S TE V1.1
61 		95MS14, PNP
62 
63 	plug-and-play info:
64 		device id 	"ASU1688"
65 		vendor id 	0x88167506
66 		serial 		0x00000044
67 		i/o port	4 byte alignment, 4 bytes requested,
68 				10 bit i/o decoding, 0x100-0x3f8 (?)
69 		irq		3,4,5,9,10,11,12,15, high true, edge sensitive
70 
71 	At the moment I'm writing this Dynalink is replacing this card with
72 	one based on a single Siemens chip (IPAC). It will apparently be sold
73 	under the same model name.
74 
75 	This driver might also work for Asuscom cards.
76 */
77 
78 #include <sys/cdefs.h>
79 __KERNEL_RCSID(0, "$NetBSD: isic_isapnp_dynalink.c,v 1.4 2002/03/24 20:35:51 martin Exp $");
80 
81 #ifdef ISICPNP_DYNALINK
82 
83 /* HEADERS
84 */
85 
86 #include <sys/param.h>
87 #include <sys/kernel.h>
88 #include <sys/systm.h>
89 #include <sys/mbuf.h>
90 #include <sys/socket.h>
91 #include <net/if.h>
92 
93 #include <sys/timeout.h>
94 
95 #ifdef __FreeBSD__
96 #if __FreeBSD__ >= 3
97 #include <sys/ioccom.h>
98 #else
99 #include <sys/ioctl.h>
100 #endif
101 #include <machine/clock.h>
102 #include <i386/isa/isa_device.h>
103 #include <i386/isa/pnp.h>
104 #elif defined(__bsdi__)
105 #include <i386/isa/pnp.h>
106 #else
107 #include <machine/bus.h>
108 #include <sys/device.h>
109 #endif
110 
111 #ifdef __FreeBSD__
112 #include <machine/i4b_debug.h>
113 #include <machine/i4b_ioctl.h>
114 #else
115 #include <netisdn/i4b_debug.h>
116 #include <netisdn/i4b_ioctl.h>
117 #endif
118 
119 #include <netisdn/i4b_global.h>
120 #include <netisdn/i4b_l2.h>
121 #include <netisdn/i4b_l1l2.h>
122 #include <netisdn/i4b_mbuf.h>
123 
124 #include <dev/ic/isic_l1.h>
125 #include <dev/ic/isac.h>
126 #include <dev/ic/hscx.h>
127 
128 #if defined(__FreeBSD__) || defined(__bsdi__)
129 static void dynalink_read_fifo(void *buf, const void *base, size_t len);
130 static void dynalink_write_fifo(void *base, const void *buf, size_t len);
131 static void dynalink_write_reg(u_char *base, u_int offset, u_int v);
132 static u_char dynalink_read_reg(u_char *base, u_int offset);
133 #endif
134 
135 #ifdef __FreeBSD__
136 extern struct isa_driver isicdriver;
137 #endif
138 #ifdef __bsdi__
139 extern struct cfdriver isiccd;
140 #endif
141 
142 #if !defined(__FreeBSD__) && !defined(__bsdi__)
143 static void dynalink_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size);
144 static void dynalink_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size);
145 static void dynalink_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data);
146 static u_int8_t dynalink_read_reg(struct isic_softc *sc, int what, bus_size_t offs);
147 void isic_attach_Dyn(struct isic_softc *sc);
148 #endif
149 
150 /* io address mapping */
151 #define ISAC		0
152 #define HSCX		1
153 #define	ADDR		2
154 
155 /* ADDR bits */
156 #define ADDRMASK	0x7F
157 #define RESET		0x80
158 
159 /* HSCX register offsets */
160 #define HSCXA		0x00
161 #define HSCXB		0x40
162 
163 #if defined(__FreeBSD__) || defined(__bsdi__)
164 /* base address juggling */
165 #define HSCXB_HACK		0x400
166 #define IOBASE(addr)		(((int)addr)&0x3FC)
167 #define IOADDR(addr)		(((int)addr)&0x3FF)
168 #define IS_HSCXB_HACK(addr)	((((int)addr)&HSCXB_HACK)?HSCXB:HSCXA)
169 #endif
170 
171 #ifdef __FreeBSD__
172 /* ISIC probe and attach
173 */
174 
175 int
isic_probe_Dyn(struct isa_device * dev,unsigned int iobase2)176 isic_probe_Dyn(struct isa_device *dev, unsigned int iobase2)
177 {
178 
179 	struct isic_softc *sc = &l1_sc[dev->id_unit];
180 
181 	if(dev->id_unit >= ISIC_MAXUNIT)
182 	{
183 		printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Dynalink IS64PH.\n",
184 				dev->id_unit, dev->id_unit);
185 		return(0);
186 	}
187 	sc->sc_unit = dev->id_unit;
188 
189 	/* check IRQ validity */
190 
191 	switch(ffs(dev->id_irq) - 1)
192 	{
193 		case 3:
194 		case 4:
195 		case 5:
196 		case 9:
197 		case 10:
198 		case 11:
199 		case 12:
200 		case 15:
201 			break;
202 
203 		default:
204 			printf("isic%d: Error, invalid IRQ [%d] specified for Dynalink IS64PH.\n",
205 				dev->id_unit, ffs(dev->id_irq)-1);
206 			return(0);
207 			break;
208 	}
209 	sc->sc_irq = dev->id_irq;
210 
211 	/* check if memory addr specified */
212 
213 	if(dev->id_maddr)
214 	{
215 		printf("isic%d: Error, mem addr 0x%lx specified for Dynalink IS64PH.\n",
216 			dev->id_unit, (u_long)dev->id_maddr);
217 		return (0);
218 	}
219 	dev->id_msize = 0;
220 
221 	/* check if we got an iobase */
222 	if ( (dev->id_iobase < 0x100) ||
223 	     (dev->id_iobase > 0x3f8) ||
224 	     (dev->id_iobase & 3) )
225 	{
226 			printf("isic%d: Error, invalid iobase 0x%x specified for Dynalink!\n", dev->id_unit, dev->id_iobase);
227 			return(0);
228 	}
229 	sc->sc_port = dev->id_iobase;
230 
231 	/* setup access routines */
232 	sc->clearirq = NULL;
233 	sc->readreg = dynalink_read_reg;
234 	sc->writereg = dynalink_write_reg;
235 	sc->readfifo = dynalink_read_fifo;
236 	sc->writefifo = dynalink_write_fifo;
237 
238 	/* setup card type */
239 	sc->sc_cardtyp = CARD_TYPEP_DYNALINK;
240 
241 	/* setup IOM bus type */
242 	sc->sc_bustyp = BUS_TYPE_IOM2;
243 
244 	sc->sc_ipac = 0;
245 	sc->sc_bfifolen = HSCX_FIFO_LEN;
246 
247 	/* setup ISAC and HSCX base addr */
248 	ISAC_BASE = (caddr_t) sc->sc_port;
249 	HSCX_A_BASE = (caddr_t) sc->sc_port + 1;
250 	HSCX_B_BASE = (caddr_t) sc->sc_port + 1 + HSCXB_HACK;
251 
252 	/* Read HSCX A/B VSTR.  Expected value is 0x05 (V2.1). */
253 	if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) ||
254 	    ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
255 	{
256 		printf("isic%d: HSCX VSTR test failed for Dynalink\n",
257 			dev->id_unit);
258 		printf("isic%d: HSC0: VSTR: %#x\n",
259 			dev->id_unit, HSCX_READ(0, H_VSTR));
260 		printf("isic%d: HSC1: VSTR: %#x\n",
261 			dev->id_unit, HSCX_READ(1, H_VSTR));
262 		return (0);
263 	}
264 
265 	return (1);
266 }
267 
268 int
isic_attach_Dyn(struct isa_device * dev,unsigned int iobase2)269 isic_attach_Dyn(struct isa_device *dev, unsigned int iobase2)
270 {
271 	outb((dev->id_iobase)+ADDR, RESET);
272 	DELAY(SEC_DELAY / 10);
273 	outb((dev->id_iobase)+ADDR, 0);
274 	DELAY(SEC_DELAY / 10);
275 	return(1);
276 }
277 
278 #elif defined(__bsdi__)
279 
280 /* ISIC probe and attach
281 */
282 
283 static int
set_softc(struct isic_softc * sc,struct isa_attach_args * ia,int unit)284 set_softc(struct isic_softc *sc, struct isa_attach_args *ia, int unit)
285 {
286 	if (unit >= NISIC)
287 		return 0;
288 	sc->sc_unit = unit;
289 	switch(ffs(ia->ia_irq) - 1)
290 	{
291 		case 3:
292 		case 4:
293 		case 5:
294 		case 9:
295 		case 10:
296 		case 11:
297 		case 12:
298 		case 15:
299 			break;
300 
301 		default:
302 			printf("isic%d: Error, invalid IRQ [%d] specified for Dynalink IS64PH.\n",
303 				unit, ffs(ia->ia_irq)-1);
304 			return(0);
305 			break;
306 	}
307 	sc->sc_irq = ia->ia_irq;
308 
309 	/* check if memory addr specified */
310 
311 	if(ia->ia_maddr)
312 	{
313 		printf("isic%d: Error, mem addr 0x%lx specified for Dynalink IS64PH.\n",
314 			unit, (u_long)ia->ia_maddr);
315 		return (0);
316 	}
317 
318 	/* check if we got an iobase */
319 	if ( (ia->ia_iobase < 0x100) ||
320 	     (ia->ia_iobase > 0x3f8) ||
321 	     (ia->ia_iobase & 3) )
322 	{
323 			printf("isic%d: Error, invalid iobase 0x%x specified for Dynalink!\n", unit, ia->ia_iobase);
324 			return(0);
325 	}
326 	sc->sc_port = ia->ia_iobase;
327 
328 	/* setup access routines */
329 	sc->clearirq = NULL;
330 	sc->readreg = dynalink_read_reg;
331 	sc->writereg = dynalink_write_reg;
332 	sc->readfifo = dynalink_read_fifo;
333 	sc->writefifo = dynalink_write_fifo;
334 
335 	/* setup card type */
336 	sc->sc_cardtyp = CARD_TYPEP_DYNALINK;
337 
338 	/* setup IOM bus type */
339 	sc->sc_bustyp = BUS_TYPE_IOM2;
340 
341 	sc->sc_ipac = 0;
342 	sc->sc_bfifolen = HSCX_FIFO_LEN;
343 
344 	/* setup ISAC and HSCX base addr */
345 	ISAC_BASE = (caddr_t) sc->sc_port;
346 	HSCX_A_BASE = (caddr_t) sc->sc_port + 1;
347 	HSCX_B_BASE = (caddr_t) sc->sc_port + 1 + HSCXB_HACK;
348 	return 1;
349 }
350 
351 int
isapnp_match_dynalink(struct device * parent,struct cfdata * cf,struct isa_attach_args * ia)352 isapnp_match_dynalink(struct device *parent, struct cfdata *cf,
353 		struct isa_attach_args *ia)
354 {
355 	struct isic_softc dummysc, *sc = &dummysc;
356 	pnp_resource_t res;
357 	char *ids[] = {"ASU1688", NULL};
358 	bzero(&res, sizeof res);
359 	res.res_irq[0].irq_level = ia->ia_irq;
360 	res.res_port[0].prt_base = ia->ia_iobase;
361 	res.res_port[0].prt_length = 4;
362 
363 	if (!pnp_assigndev(ids, isiccd.cd_name, &res))
364 		return (0);
365 
366 	ia->ia_irq = res.res_irq[0].irq_level;
367 	ia->ia_iobase = res.res_port[0].prt_base;
368 	ia->ia_iosize = res.res_port[0].prt_length;
369 
370 	if (set_softc(sc, ia, cf->cf_unit) == 0)
371 		return 0;
372 
373 	/* Read HSCX A/B VSTR.  Expected value is 0x05 (V2.1). */
374 	if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) ||
375 	    ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
376 	{
377 		printf("isic%d: HSCX VSTR test failed for Dynalink\n",
378 			cf->cf_unit);
379 		printf("isic%d: HSC0: VSTR: %#x\n",
380 			cf->cf_unit, HSCX_READ(0, H_VSTR));
381 		printf("isic%d: HSC1: VSTR: %#x\n",
382 			cf->cf_unit, HSCX_READ(1, H_VSTR));
383 		return (0);
384 	}
385 
386 	cf->cf_flags = FLAG_DYNALINK;
387 	return (1);
388 }
389 
390 int
isic_attach_Dyn(struct device * parent,struct device * self,struct isa_attach_args * ia)391 isic_attach_Dyn(struct device *parent, struct device *self,
392 		struct isa_attach_args *ia)
393 {
394 	struct isic_softc *sc = (struct isic_softc *)self;
395 	int unit = sc->sc_dev.dv_unit;
396 
397 	/* Commit the probed attachment values */
398 	if (set_softc(sc, ia, unit) == 0)
399 		panic("isic_attach_Dyn: set_softc");
400 
401 	outb((ia->ia_iobase)+ADDR, RESET);
402 	DELAY(SEC_DELAY / 10);
403 	outb((ia->ia_iobase)+ADDR, 0);
404 	DELAY(SEC_DELAY / 10);
405 	return(1);
406 }
407 
408 #else
409 
isic_attach_Dyn(struct isic_softc * sc)410 void isic_attach_Dyn(struct isic_softc *sc)
411 {
412 	/* setup access routines */
413 	sc->clearirq = NULL;
414 	sc->readreg = dynalink_read_reg;
415 	sc->writereg = dynalink_write_reg;
416 	sc->readfifo = dynalink_read_fifo;
417 	sc->writefifo = dynalink_write_fifo;
418 
419 	/* setup card type */
420 	sc->sc_cardtyp = CARD_TYPEP_DYNALINK;
421 
422 	/* setup IOM bus type */
423 	sc->sc_bustyp = BUS_TYPE_IOM2;
424 
425 	sc->sc_ipac = 0;
426 	sc->sc_bfifolen = HSCX_FIFO_LEN;
427 
428 	/* Read HSCX A/B VSTR.  Expected value is 0x05 (V2.1). */
429 	if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) || ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
430 	{
431 		printf("%s: HSCX VSTR test failed for Dynalink PnP\n",
432 			sc->sc_dev.dv_xname);
433 		printf("%s: HSC0: VSTR: %#x\n",
434 			sc->sc_dev.dv_xname, HSCX_READ(0, H_VSTR));
435 		printf("%s: HSC1: VSTR: %#x\n",
436 			sc->sc_dev.dv_xname, HSCX_READ(1, H_VSTR));
437 		return;
438 	}
439 
440 	bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, ADDR, RESET);
441 	DELAY(SEC_DELAY / 10);
442 	bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, ADDR, 0);
443 	DELAY(SEC_DELAY / 10);
444 }
445 
446 #endif
447 
448 /*	LOW-LEVEL DEVICE ACCESS
449 
450 	NOTE:	The isdn4bsd code expects the two HSCX channels at different
451 	base addresses. I'm faking this, and remap them to the same address
452 	in the low-level routines. Search for HSCXB_HACK and IS_HSCXB_HACK.
453 
454 	REM: this is only true for the FreeBSD version of I4B!
455 */
456 
457 #if defined(__FreeBSD__) || defined(__bsdi__)
458 static void
dynalink_read_fifo(void * buf,const void * base,size_t len)459 dynalink_read_fifo(void *buf, const void *base, size_t len)
460 {
461 	outb(IOBASE(base)+ADDR, 0+IS_HSCXB_HACK(base));
462 	insb(IOADDR(base), (u_char *)buf, (u_int)len);
463 }
464 #else
465 static void
dynalink_read_fifo(struct isic_softc * sc,int what,void * buf,size_t size)466 dynalink_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
467 {
468 	bus_space_tag_t t = sc->sc_maps[0].t;
469 	bus_space_handle_t h = sc->sc_maps[0].h;
470 	switch (what) {
471 		case ISIC_WHAT_ISAC:
472 			bus_space_write_1(t, h, ADDR, 0);
473 			bus_space_read_multi_1(t, h, ISAC, buf, size);
474 			break;
475 		case ISIC_WHAT_HSCXA:
476 			bus_space_write_1(t, h, ADDR, HSCXA);
477 			bus_space_read_multi_1(t, h, HSCX, buf, size);
478 			break;
479 		case ISIC_WHAT_HSCXB:
480 			bus_space_write_1(t, h, ADDR, HSCXB);
481 			bus_space_read_multi_1(t, h, HSCX, buf, size);
482 			break;
483 	}
484 }
485 #endif
486 
487 #if defined(__FreeBSD__) || defined(__bsdi__)
488 static void
dynalink_write_fifo(void * base,const void * buf,size_t len)489 dynalink_write_fifo(void *base, const void *buf, size_t len)
490 {
491 	outb(IOBASE(base)+ADDR, 0+IS_HSCXB_HACK(base));
492 	outsb(IOADDR(base), (u_char *)buf, (u_int)len);
493 }
494 #else
dynalink_write_fifo(struct isic_softc * sc,int what,const void * buf,size_t size)495 static void dynalink_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size)
496 {
497 	bus_space_tag_t t = sc->sc_maps[0].t;
498 	bus_space_handle_t h = sc->sc_maps[0].h;
499 	switch (what) {
500 		case ISIC_WHAT_ISAC:
501 			bus_space_write_1(t, h, ADDR, 0);
502 			bus_space_write_multi_1(t, h, ISAC, (u_int8_t*)buf, size);
503 			break;
504 		case ISIC_WHAT_HSCXA:
505 			bus_space_write_1(t, h, ADDR, HSCXA);
506 			bus_space_write_multi_1(t, h, HSCX, (u_int8_t*)buf, size);
507 			break;
508 		case ISIC_WHAT_HSCXB:
509 			bus_space_write_1(t, h, ADDR, HSCXB);
510 			bus_space_write_multi_1(t, h, HSCX, (u_int8_t*)buf, size);
511 			break;
512 	}
513 }
514 #endif
515 
516 #if defined(__FreeBSD__) || defined(__bsdi__)
517 static void
dynalink_write_reg(u_char * base,u_int offset,u_int v)518 dynalink_write_reg(u_char *base, u_int offset, u_int v)
519 {
520 	outb(IOBASE(base)+ADDR, (offset+IS_HSCXB_HACK(base))&ADDRMASK);
521 	outb(IOADDR(base), (u_char)v);
522 }
523 #else
dynalink_write_reg(struct isic_softc * sc,int what,bus_size_t offs,u_int8_t data)524 static void dynalink_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
525 {
526 	bus_space_tag_t t = sc->sc_maps[0].t;
527 	bus_space_handle_t h = sc->sc_maps[0].h;
528 	switch (what) {
529 		case ISIC_WHAT_ISAC:
530 			bus_space_write_1(t, h, ADDR, offs);
531 			bus_space_write_1(t, h, ISAC, data);
532 			break;
533 		case ISIC_WHAT_HSCXA:
534 			bus_space_write_1(t, h, ADDR, HSCXA+offs);
535 			bus_space_write_1(t, h, HSCX, data);
536 			break;
537 		case ISIC_WHAT_HSCXB:
538 			bus_space_write_1(t, h, ADDR, HSCXB+offs);
539 			bus_space_write_1(t, h, HSCX, data);
540 			break;
541 	}
542 }
543 #endif
544 
545 #if defined(__FreeBSD__) || defined(__bsdi__)
546 static u_char
dynalink_read_reg(u_char * base,u_int offset)547 dynalink_read_reg(u_char *base, u_int offset)
548 {
549 	outb(IOBASE(base)+ADDR, (offset+IS_HSCXB_HACK(base))&ADDRMASK);
550 	return (inb(IOADDR(base)));
551 }
552 #else
dynalink_read_reg(struct isic_softc * sc,int what,bus_size_t offs)553 static u_int8_t dynalink_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
554 {
555 	bus_space_tag_t t = sc->sc_maps[0].t;
556 	bus_space_handle_t h = sc->sc_maps[0].h;
557 	switch (what) {
558 		case ISIC_WHAT_ISAC:
559 			bus_space_write_1(t, h, ADDR, offs);
560 			return bus_space_read_1(t, h, ISAC);
561 		case ISIC_WHAT_HSCXA:
562 			bus_space_write_1(t, h, ADDR, HSCXA+offs);
563 			return bus_space_read_1(t, h, HSCX);
564 		case ISIC_WHAT_HSCXB:
565 			bus_space_write_1(t, h, ADDR, HSCXB+offs);
566 			return bus_space_read_1(t, h, HSCX);
567 	}
568 	return 0;
569 }
570 #endif
571 
572 #endif /* ISICPNP_DYNALINK */
573