xref: /openbsd/sys/dev/ic/aic79xx_openbsd.c (revision 274d7c50)
1 /*	$OpenBSD: aic79xx_openbsd.c,v 1.46 2017/12/12 12:33:36 krw Exp $	*/
2 
3 /*
4  * Copyright (c) 2004 Milos Urbanek, Kenneth R. Westerback & Marco Peereboom
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
20  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  */
29 
30 /*
31  * Bus independent OpenBSD shim for the aic79xx based Adaptec SCSI controllers
32  *
33  * Copyright (c) 1994-2002 Justin T. Gibbs.
34  * Copyright (c) 2001-2002 Adaptec Inc.
35  * All rights reserved.
36  *
37  * Redistribution and use in source and binary forms, with or without
38  * modification, are permitted provided that the following conditions
39  * are met:
40  * 1. Redistributions of source code must retain the above copyright
41  *    notice, this list of conditions, and the following disclaimer,
42  *    without modification.
43  * 2. The name of the author may not be used to endorse or promote products
44  *    derived from this software without specific prior written permission.
45  *
46  * Alternatively, this software may be distributed under the terms of the
47  * GNU Public License ("GPL").
48  *
49  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
50  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
53  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59  * SUCH DAMAGE.
60  *
61  */
62 
63 #include <dev/ic/aic79xx_openbsd.h>
64 #include <dev/ic/aic79xx_inline.h>
65 #include <dev/ic/aic79xx.h>
66 
67 #ifndef AHD_TMODE_ENABLE
68 #define AHD_TMODE_ENABLE 0
69 #endif
70 
71 /* XXX milos add ahd_ioctl */
72 void	ahd_action(struct scsi_xfer *);
73 void	ahd_execute_scb(void *, bus_dma_segment_t *, int);
74 int	ahd_poll(struct ahd_softc *, int);
75 void	ahd_setup_data(struct ahd_softc *, struct scsi_xfer *,
76 		    struct scb *);
77 
78 void	ahd_adapter_req_set_xfer_mode(struct ahd_softc *, struct scb *);
79 void    ahd_minphys(struct buf *, struct scsi_link *);
80 
81 struct cfdriver ahd_cd = {
82 	NULL, "ahd", DV_DULL
83 };
84 
85 static struct scsi_adapter ahd_switch =
86 {
87 	ahd_action,
88 	ahd_minphys,
89 	0,
90 	0,
91 };
92 
93 /*
94  * Attach all the sub-devices we can find
95  */
96 int
97 ahd_attach(struct ahd_softc *ahd)
98 {
99 	struct scsibus_attach_args saa;
100 	char   ahd_info[256];
101 	int	s;
102 
103 	ahd_controller_info(ahd, ahd_info, sizeof ahd_info);
104 	printf("%s\n", ahd_info);
105 	ahd_lock(ahd, &s);
106 
107 	/*
108 	 * fill in the prototype scsi_links.
109 	 */
110 	ahd->sc_channel.adapter_target = ahd->our_id;
111 	if (ahd->features & AHD_WIDE)
112 		ahd->sc_channel.adapter_buswidth = 16;
113 	ahd->sc_channel.adapter_softc = ahd;
114 	ahd->sc_channel.adapter = &ahd_switch;
115 	ahd->sc_channel.openings = 16; /* Must ALWAYS be < 256!! */
116 	ahd->sc_channel.pool = &ahd->sc_iopool;
117 
118 	if (bootverbose) {
119 		ahd_controller_info(ahd, ahd_info, sizeof ahd_info);
120 		printf("%s: %s\n", ahd->sc_dev.dv_xname, ahd_info);
121 	}
122 
123 	ahd_intr_enable(ahd, TRUE);
124 
125 	if (ahd->flags & AHD_RESET_BUS_A)
126 		ahd_reset_channel(ahd, 'A', TRUE);
127 
128 	bzero(&saa, sizeof(saa));
129 	saa.saa_sc_link = &ahd->sc_channel;
130 
131 	ahd->sc_child = config_found((void *)&ahd->sc_dev, &saa, scsiprint);
132 
133 	ahd_unlock(ahd, &s);
134 
135 	return (1);
136 
137 }
138 
139 /*
140  * Catch an interrupt from the adapter
141  */
142 int
143 ahd_platform_intr(void *arg)
144 {
145 	struct	ahd_softc *ahd;
146 
147 	/* XXX in ahc there is some bus_dmamap_sync(PREREAD|PREWRITE); */
148 
149 	ahd = (struct ahd_softc *)arg;
150 	return ahd_intr(ahd);
151 }
152 
153 /*
154  * We have an scb which has been processed by the
155  * adaptor, now we look to see how the operation
156  * went.
157  */
158 void
159 ahd_done(struct ahd_softc *ahd, struct scb *scb)
160 {
161 	struct scsi_xfer *xs = scb->xs;
162 
163 	/* XXX in ahc there is some bus_dmamap_sync(PREREAD|PREWRITE); */
164 
165 	TAILQ_REMOVE(&ahd->pending_scbs, scb, next);
166 
167 	timeout_del(&xs->stimeout);
168 
169 	if (xs->datalen) {
170 		int op;
171 
172 		if ((xs->flags & SCSI_DATA_IN) != 0)
173 			op = BUS_DMASYNC_POSTREAD;
174 		else
175 			op = BUS_DMASYNC_POSTWRITE;
176 		bus_dmamap_sync(ahd->parent_dmat, scb->dmamap, 0,
177 		    scb->dmamap->dm_mapsize, op);
178 		bus_dmamap_unload(ahd->parent_dmat, scb->dmamap);
179 	}
180 
181 	/* Translate the CAM status code to a SCSI error code. */
182 	switch (xs->error) {
183 	case CAM_SCSI_STATUS_ERROR:
184 	case CAM_REQ_INPROG:
185 	case CAM_REQ_CMP:
186 		switch (xs->status) {
187 		case SCSI_TASKSET_FULL:
188 		case SCSI_BUSY:
189 			xs->error = XS_BUSY;
190 			break;
191 		case SCSI_CHECK:
192 		case SCSI_TERMINATED:
193 			if ((scb->flags & SCB_SENSE) == 0) {
194 				/* CHECK on CHECK? */
195 				xs->error = XS_DRIVER_STUFFUP;
196 			} else
197 				xs->error = XS_NOERROR;
198 			break;
199 		default:
200 			xs->error = XS_NOERROR;
201 			break;
202 		}
203 		break;
204 	case CAM_BUSY:
205 	case CAM_REQUEUE_REQ:
206 		xs->error = XS_BUSY;
207 		break;
208 	case CAM_CMD_TIMEOUT:
209 		xs->error = XS_TIMEOUT;
210 		break;
211 	case CAM_BDR_SENT:
212 	case CAM_SCSI_BUS_RESET:
213 		xs->error = XS_RESET;
214 		break;
215 	case CAM_SEL_TIMEOUT:
216 		xs->error = XS_SELTIMEOUT;
217 		break;
218 	default:
219 		xs->error = XS_DRIVER_STUFFUP;
220 		break;
221 	}
222 
223 	if (xs->error != XS_NOERROR) {
224 		/* Don't clobber any existing error state */
225 	} else if ((scb->flags & SCB_SENSE) != 0) {
226 		/*
227 		 * We performed autosense retrieval.
228 		 *
229 		 * Zero any sense not transferred by the
230 		 * device.  The SCSI spec mandates that any
231 		 * untransferred data should be assumed to be
232 		 * zero.  Complete the 'bounce' of sense information
233 		 * through buffers accessible via bus-space by
234 		 * copying it into the clients csio.
235 		 */
236 		memset(&xs->sense, 0, sizeof(struct scsi_sense_data));
237 		memcpy(&xs->sense, ahd_get_sense_buf(ahd, scb),
238 		    sizeof(struct scsi_sense_data));
239 		xs->error = XS_SENSE;
240 	} else if ((scb->flags & SCB_PKT_SENSE) != 0) {
241 		struct scsi_status_iu_header *siu;
242 		u_int32_t len;
243 
244 		siu = (struct scsi_status_iu_header *)scb->sense_data;
245 		len = SIU_SENSE_LENGTH(siu);
246 		memset(&xs->sense, 0, sizeof(xs->sense));
247 		memcpy(&xs->sense, SIU_SENSE_DATA(siu),
248 		    ulmin(len, sizeof(xs->sense)));
249 		xs->error = XS_SENSE;
250 	}
251 
252 	scsi_done(xs);
253 }
254 
255 void
256 ahd_minphys(struct buf *bp, struct scsi_link *sl)
257 {
258 	/*
259 	 * Even though the card can transfer up to 16megs per command
260 	 * we are limited by the number of segments in the dma segment
261 	 * list that we can hold.  The worst case is that all pages are
262 	 * discontinuous physically, hence the "page per segment" limit
263 	 * enforced here.
264 	 */
265 	if (bp->b_bcount > ((AHD_NSEG - 1) * PAGE_SIZE)) {
266 		bp->b_bcount = ((AHD_NSEG - 1) * PAGE_SIZE);
267 	}
268 	minphys(bp);
269 }
270 
271 void
272 ahd_action(struct scsi_xfer *xs)
273 {
274 	struct	ahd_softc *ahd;
275 	struct scb *scb;
276 	struct hardware_scb *hscb;
277 	u_int	target_id;
278 	u_int	our_id;
279 	int	s;
280 	struct	ahd_initiator_tinfo *tinfo;
281 	struct	ahd_tmode_tstate *tstate;
282 	u_int16_t quirks;
283 
284 	SC_DEBUG(xs->sc_link, SDEV_DB3, ("ahd_action\n"));
285 	ahd = (struct ahd_softc *)xs->sc_link->adapter_softc;
286 
287 	target_id = xs->sc_link->target;
288 	our_id = SCSI_SCSI_ID(ahd, xs->sc_link);
289 
290 	ahd_lock(ahd, &s);
291 	if ((ahd->flags & AHD_INITIATORROLE) == 0) {
292 		xs->error = XS_DRIVER_STUFFUP;
293 		scsi_done(xs);
294 		ahd_unlock(ahd, &s);
295 		return;
296 	}
297 	/*
298 	 * get an scb to use.
299 	 */
300 	tinfo = ahd_fetch_transinfo(ahd, 'A', our_id, target_id, &tstate);
301 
302 	quirks = xs->sc_link->quirks;
303 
304 	ahd_unlock(ahd, &s);
305 
306 	scb = xs->io;
307 	hscb = scb->hscb;
308 	scb->flags = SCB_FLAG_NONE;
309 	scb->hscb->control = 0;
310 	ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = NULL;
311 
312 	SC_DEBUG(xs->sc_link, SDEV_DB3, ("start scb(%p)\n", scb));
313 
314 	scb->xs = xs;
315 	timeout_set(&xs->stimeout, ahd_timeout, scb);
316 
317 	/*
318 	 * Put all the arguments for the xfer in the scb
319 	 */
320 	hscb->control = 0;
321 	hscb->scsiid = BUILD_SCSIID(ahd, xs->sc_link, target_id, our_id);
322 	hscb->lun = xs->sc_link->lun;
323 	if (xs->xs_control & XS_CTL_RESET) {
324 		hscb->cdb_len = 0;
325 		scb->flags |= SCB_DEVICE_RESET;
326 		hscb->control |= MK_MESSAGE;
327 		hscb->task_management = SIU_TASKMGMT_LUN_RESET;
328 		ahd_execute_scb(scb, NULL, 0);
329 	} else {
330 		hscb->task_management = 0;
331 		ahd_setup_data(ahd, xs, scb);
332 	}
333 }
334 
335 void
336 ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments)
337 {
338 	struct	scb *scb;
339 	struct	scsi_xfer *xs;
340 	struct	ahd_softc *ahd;
341 	struct	ahd_initiator_tinfo *tinfo;
342 	struct	ahd_tmode_tstate *tstate;
343 	u_int	mask;
344 	int	s;
345 
346 	scb = (struct scb *)arg;
347 	xs = scb->xs;
348 	xs->error = CAM_REQ_INPROG;
349 	xs->status = 0;
350 	ahd = (struct ahd_softc *)xs->sc_link->adapter_softc;
351 
352 	if (nsegments != 0) {
353 		void *sg;
354 		int op;
355 		u_int i;
356 
357 		ahd_setup_data_scb(ahd, scb);
358 
359 		/* Copy the segments into our SG list */
360 		for (i = nsegments, sg = scb->sg_list; i > 0; i--) {
361 
362 			sg = ahd_sg_setup(ahd, scb, sg, dm_segs->ds_addr,
363 					  dm_segs->ds_len,
364 					  /*last*/i == 1);
365 			dm_segs++;
366 		}
367 
368 		if ((xs->flags & SCSI_DATA_IN) != 0)
369 			op = BUS_DMASYNC_PREREAD;
370 		else
371 			op = BUS_DMASYNC_PREWRITE;
372 
373 		bus_dmamap_sync(ahd->parent_dmat, scb->dmamap, 0,
374 				scb->dmamap->dm_mapsize, op);
375 
376 	}
377 
378 	ahd_lock(ahd, &s);
379 
380 	/*
381 	 * Last time we need to check if this SCB needs to
382 	 * be aborted.
383 	 */
384 	if (xs->flags & ITSDONE) {
385 		if (nsegments != 0)
386 			bus_dmamap_unload(ahd->parent_dmat,
387 					  scb->dmamap);
388 		ahd_unlock(ahd, &s);
389 		return;
390 	}
391 
392 	tinfo = ahd_fetch_transinfo(ahd, SCSIID_CHANNEL(ahd, scb->hscb->scsiid),
393 				    SCSIID_OUR_ID(scb->hscb->scsiid),
394 				    SCSIID_TARGET(ahd, scb->hscb->scsiid),
395 				    &tstate);
396 
397 	mask = SCB_GET_TARGET_MASK(ahd, scb);
398 
399 	if ((tstate->discenable & mask) != 0)
400 		scb->hscb->control |= DISCENB;
401 
402 	if ((tstate->tagenable & mask) != 0)
403 		scb->hscb->control |= TAG_ENB;
404 
405 	if ((tinfo->curr.ppr_options & MSG_EXT_PPR_PROT_IUS) != 0) {
406 		scb->flags |= SCB_PACKETIZED;
407 		if (scb->hscb->task_management != 0)
408 			scb->hscb->control &= ~MK_MESSAGE;
409 	}
410 
411 	if ((tstate->auto_negotiate & mask) != 0) {
412 		scb->flags |= SCB_AUTO_NEGOTIATE;
413 		scb->hscb->control |= MK_MESSAGE;
414 	}
415 
416 	/* XXX with ahc there was some bus_dmamap_sync(PREREAD|PREWRITE); */
417 
418 	TAILQ_INSERT_HEAD(&ahd->pending_scbs, scb, next);
419 
420 	if (!(xs->flags & SCSI_POLL))
421 		timeout_add_msec(&xs->stimeout, xs->timeout);
422 
423 	scb->flags |= SCB_ACTIVE;
424 
425 	if ((scb->flags & SCB_TARGET_IMMEDIATE) != 0) {
426 		/* Define a mapping from our tag to the SCB. */
427 		ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb;
428 		ahd_pause(ahd);
429 		ahd_set_scbptr(ahd, SCB_GET_TAG(scb));
430 		ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_TARG);
431 		ahd_unpause(ahd);
432 	} else {
433 		ahd_queue_scb(ahd, scb);
434 	}
435 
436 	if (!(xs->flags & SCSI_POLL)) {
437 		int target = xs->sc_link->target;
438 		int lun = SCB_GET_LUN(scb);
439 
440 		if (ahd->inited_target[target] == 0) {
441 			struct  ahd_devinfo devinfo;
442 
443 			ahd_adapter_req_set_xfer_mode(ahd, scb);
444 			ahd_compile_devinfo(&devinfo, ahd->our_id, target, lun,
445 			    'A', /*XXX milos*/ROLE_UNKNOWN);
446 			ahd_scb_devinfo(ahd, &devinfo, scb);
447 			ahd_update_neg_request(ahd, &devinfo, tstate, tinfo,
448 				AHD_NEG_IF_NON_ASYNC);
449 			ahd->inited_target[target] = 1;
450 		}
451 
452 		ahd_unlock(ahd, &s);
453 		return;
454 	}
455 
456 	/*
457 	 * If we can't use interrupts, poll for completion
458 	 */
459 	SC_DEBUG(xs->sc_link, SDEV_DB3, ("cmd_poll\n"));
460 
461 	do {
462 		if (ahd_poll(ahd, xs->timeout)) {
463 			if (!(xs->flags & SCSI_SILENT))
464 				printf("cmd fail\n");
465 			ahd_timeout(scb);
466 			break;
467 		}
468 	} while (!(xs->flags & ITSDONE));
469 
470 	ahd_unlock(ahd, &s);
471 }
472 
473 int
474 ahd_poll(struct ahd_softc *ahd, int wait)
475 {
476 	while (--wait) {
477 		DELAY(1000);
478 		if (ahd_inb(ahd, INTSTAT) & INT_PEND)
479 			break;
480 	}
481 
482 	if (wait == 0) {
483 		printf("%s: board is not responding\n", ahd_name(ahd));
484 		return (EIO);
485 	}
486 
487 	ahd_intr((void *)ahd);
488 	return (0);
489 }
490 
491 void
492 ahd_setup_data(struct ahd_softc *ahd, struct scsi_xfer *xs,
493 	       struct scb *scb)
494 {
495 	struct hardware_scb *hscb;
496 
497 	hscb = scb->hscb;
498 	xs->resid = xs->status = 0;
499 	xs->error = CAM_REQ_INPROG;
500 
501 	hscb->cdb_len = xs->cmdlen;
502 	if (hscb->cdb_len > MAX_CDB_LEN) {
503 		xs->error = XS_DRIVER_STUFFUP;
504 		scsi_done(xs);
505 		return;
506 	}
507 
508 	memcpy(hscb->shared_data.idata.cdb, xs->cmd, hscb->cdb_len);
509 
510 	/* Only use S/G if there is a transfer */
511 	if (xs->datalen) {
512 		int error;
513 
514 		error = bus_dmamap_load(ahd->parent_dmat,
515 					scb->dmamap, xs->data,
516 					xs->datalen, NULL,
517 					((xs->flags & SCSI_NOSLEEP) ?
518 					BUS_DMA_NOWAIT : BUS_DMA_WAITOK) |
519 					BUS_DMA_STREAMING |
520 					((xs->flags & XS_CTL_DATA_IN) ?
521 					BUS_DMA_READ : BUS_DMA_WRITE));
522 		if (error) {
523 #ifdef AHD_DEBUG
524 			printf("%s: in ahd_setup_data(): bus_dmamap_load() "
525 			    "= %d\n", ahd_name(ahd), error);
526 #endif
527 			xs->error = XS_DRIVER_STUFFUP;
528 			scsi_done(xs);
529 			return;
530 		}
531 		ahd_execute_scb(scb, scb->dmamap->dm_segs,
532 		    scb->dmamap->dm_nsegs);
533 	} else {
534 		ahd_execute_scb(scb, NULL, 0);
535 	}
536 }
537 
538 void
539 ahd_platform_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
540     ahd_queue_alg alg)
541 {
542 	struct ahd_tmode_tstate *tstate;
543 
544 	ahd_fetch_transinfo(ahd, devinfo->channel, devinfo->our_scsiid,
545 	    devinfo->target, &tstate);
546 
547 	if (alg != AHD_QUEUE_NONE)
548 		tstate->tagenable |= devinfo->target_mask;
549 	else
550 		tstate->tagenable &= ~devinfo->target_mask;
551 }
552 
553 int
554 ahd_softc_comp(struct ahd_softc *lahd, struct ahd_softc *rahd)
555 {
556 	/* We don't sort softcs under OpenBSD so report equal always */
557 	return (0);
558 }
559 
560 int
561 ahd_detach(struct device *self, int flags)
562 {
563 	int rv = 0;
564 
565 	struct ahd_softc *ahd = (struct ahd_softc*)self;
566 
567 	if (ahd->sc_child != NULL)
568 		rv = config_detach((void *)ahd->sc_child, flags);
569 
570 	ahd_free(ahd);
571 
572 	return rv;
573 }
574 
575 void
576 ahd_adapter_req_set_xfer_mode(struct ahd_softc *ahd, struct scb *scb)
577 {
578 	struct ahd_initiator_tinfo *tinfo;
579 	struct ahd_tmode_tstate *tstate;
580 	int target_id, our_id;
581 	struct ahd_devinfo devinfo;
582 	u_int16_t quirks;
583 	u_int width, ppr_options, period, offset;
584 	int s;
585 
586 	target_id = scb->xs->sc_link->target;
587 	our_id = SCSI_SCSI_ID(ahd, scb->xs->sc_link);
588 
589 	s = splbio();
590 
591 	quirks = scb->xs->sc_link->quirks;
592 	tinfo = ahd_fetch_transinfo(ahd, 'A', our_id, target_id, &tstate);
593 	ahd_compile_devinfo(&devinfo, our_id, target_id, 0, 'A',
594 	    ROLE_INITIATOR);
595 
596 	tstate->discenable |= (ahd->user_discenable & devinfo.target_mask);
597 
598 	if (quirks & SDEV_NOTAGS)
599 		tstate->tagenable &= ~devinfo.target_mask;
600 	else if (ahd->user_tagenable & devinfo.target_mask)
601 		tstate->tagenable |= devinfo.target_mask;
602 
603 	if (quirks & SDEV_NOWIDE)
604 		width = MSG_EXT_WDTR_BUS_8_BIT;
605 	else
606 		width = MSG_EXT_WDTR_BUS_16_BIT;
607 
608 	ahd_validate_width(ahd, NULL, &width, ROLE_UNKNOWN);
609 	if (width > tinfo->user.width)
610 		width = tinfo->user.width;
611 	ahd_set_width(ahd, &devinfo, width, AHD_TRANS_GOAL, FALSE);
612 
613 	if (quirks & SDEV_NOSYNC) {
614 		period = 0;
615 		offset = 0;
616 	} else {
617 		period = tinfo->user.period;
618 		offset = tinfo->user.offset;
619 	}
620 
621 	/* XXX Look at saved INQUIRY flags for PPR capabilities XXX */
622 	ppr_options = tinfo->user.ppr_options;
623 	/* XXX Other reasons to avoid ppr? XXX */
624 	if (width < MSG_EXT_WDTR_BUS_16_BIT)
625 		ppr_options = 0;
626 
627 	if ((tstate->discenable & devinfo.target_mask) == 0 ||
628 	    (tstate->tagenable & devinfo.target_mask) == 0)
629 		ppr_options &= ~MSG_EXT_PPR_PROT_IUS;
630 
631 	ahd_find_syncrate(ahd, &period, &ppr_options, AHD_SYNCRATE_MAX);
632 	ahd_validate_offset(ahd, NULL, period, &offset, width, ROLE_UNKNOWN);
633 
634 	if (offset == 0) {
635 		period = 0;
636 		ppr_options = 0;
637 	}
638 
639 	if (ppr_options != 0 && tinfo->user.transport_version >= 3) {
640 		tinfo->goal.transport_version = tinfo->user.transport_version;
641 		tinfo->curr.transport_version = tinfo->user.transport_version;
642 	}
643 
644 	ahd_set_syncrate(ahd, &devinfo, period, offset, ppr_options,
645 		AHD_TRANS_GOAL, FALSE);
646 
647 	splx(s);
648 }
649 
650 void
651 aic_timer_reset(aic_timer_t *timer, u_int msec, ahd_callback_t *func,
652     void *arg)
653 {
654 	uint64_t nticks;
655 
656 	nticks = msec;
657 	nticks *= hz;
658 	nticks /= 1000;
659 	callout_reset(timer, nticks, func, arg);
660 }
661 
662 void
663 aic_scb_timer_reset(struct scb *scb, u_int msec)
664 {
665 	uint64_t nticks;
666 
667 	nticks = msec;
668 	nticks *= hz;
669 	nticks /= 1000;
670 	if (!(scb->xs->xs_control & XS_CTL_POLL))
671 		callout_reset(&scb->xs->xs_callout, nticks, ahd_timeout, scb);
672 }
673 
674 void
675 ahd_flush_device_writes(struct ahd_softc *ahd)
676 {
677 	/* XXX Is this sufficient for all architectures??? */
678 	ahd_inb(ahd, INTSTAT);
679 }
680 
681 void
682 aic_platform_scb_free(struct ahd_softc *ahd, struct scb *scb)
683 {
684 	int s;
685 
686 	ahd_lock(ahd, &s);
687 
688 	if ((ahd->flags & AHD_RESOURCE_SHORTAGE) != 0) {
689 		ahd->flags &= ~AHD_RESOURCE_SHORTAGE;
690 	}
691 
692 	if (!cold) {
693 		/* we are no longer in autoconf */
694 		timeout_del(&scb->xs->stimeout);
695 	}
696 
697 	ahd_unlock(ahd, &s);
698 }
699 
700 void
701 ahd_print_path(struct ahd_softc *ahd, struct scb *scb)
702 {
703 	sc_print_addr(scb->xs->sc_link);
704 }
705 
706 void
707 ahd_platform_dump_card_state(struct ahd_softc *ahd)
708 {
709 	/* Nothing to do here for OpenBSD */
710 	printf("FEATURES = 0x%x, FLAGS = 0x%x, CHIP = 0x%x BUGS =0x%x\n",
711 		ahd->features, ahd->flags, ahd->chip, ahd->bugs);
712 }
713 
714