1/*	$NetBSD: aic79xx_osm.c,v 1.30 2010/01/08 20:02:39 dyoung Exp $	*/
2
3/*
4 * Bus independent NetBSD shim for the aic7xxx based adaptec SCSI controllers
5 *
6 * Copyright (c) 1994-2002 Justin T. Gibbs.
7 * Copyright (c) 2001-2002 Adaptec Inc.
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions, and the following disclaimer,
15 *    without modification.
16 * 2. The name of the author may not be used to endorse or promote products
17 *    derived from this software without specific prior written permission.
18 *
19 * Alternatively, this software may be distributed under the terms of the
20 * GNU Public License ("GPL").
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
26 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 * //depot/aic7xxx/freebsd/dev/aic7xxx/aic79xx_osm.c#26 $
35 *
36 * $FreeBSD: src/sys/dev/aic7xxx/aic79xx_osm.c,v 1.11 2003/05/04 00:20:07 gibbs Exp $
37 */
38/*
39 * Ported from FreeBSD by Pascal Renauld, Network Storage Solutions, Inc.
40 * - April 2003
41 */
42
43#include <sys/cdefs.h>
44__KERNEL_RCSID(0, "$NetBSD: aic79xx_osm.c,v 1.30 2010/01/08 20:02:39 dyoung Exp $");
45
46#include <dev/ic/aic79xx_osm.h>
47#include <dev/ic/aic79xx_inline.h>
48
49#ifndef AHD_TMODE_ENABLE
50#define AHD_TMODE_ENABLE 0
51#endif
52
53static int	ahd_ioctl(struct scsipi_channel *channel, u_long cmd,
54			  void *addr, int flag, struct proc *p);
55static void	ahd_action(struct scsipi_channel *chan,
56			   scsipi_adapter_req_t req, void *arg);
57static void	ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs,
58				int nsegments);
59static int	ahd_poll(struct ahd_softc *ahd, int wait);
60static void	ahd_setup_data(struct ahd_softc *ahd, struct scsipi_xfer *xs,
61			       struct scb *scb);
62
63#if NOT_YET
64static void	ahd_set_recoveryscb(struct ahd_softc *ahd, struct scb *scb);
65#endif
66
67static bool	ahd_pmf_suspend(device_t, const pmf_qual_t *);
68static bool	ahd_pmf_resume(device_t, const pmf_qual_t *);
69static bool	ahd_pmf_shutdown(device_t, int);
70
71/*
72 * Attach all the sub-devices we can find
73 */
74int
75ahd_attach(struct ahd_softc *ahd)
76{
77	int	s;
78	char	ahd_info[256];
79
80	ahd_controller_info(ahd, ahd_info, sizeof(ahd_info));
81	printf("%s: %s\n", ahd_name(ahd), ahd_info);
82
83	ahd_lock(ahd, &s);
84
85	ahd->sc_adapter.adapt_dev = ahd->sc_dev;
86	ahd->sc_adapter.adapt_nchannels = 1;
87
88	ahd->sc_adapter.adapt_openings = ahd->scb_data.numscbs - 1;
89	ahd->sc_adapter.adapt_max_periph = 32;
90
91	ahd->sc_adapter.adapt_ioctl = ahd_ioctl;
92	ahd->sc_adapter.adapt_minphys = ahd_minphys;
93	ahd->sc_adapter.adapt_request = ahd_action;
94
95	ahd->sc_channel.chan_adapter = &ahd->sc_adapter;
96	ahd->sc_channel.chan_bustype = &scsi_bustype;
97	ahd->sc_channel.chan_channel = 0;
98	ahd->sc_channel.chan_ntargets = AHD_NUM_TARGETS;
99	ahd->sc_channel.chan_nluns = 8 /*AHD_NUM_LUNS*/;
100	ahd->sc_channel.chan_id = ahd->our_id;
101	ahd->sc_channel.chan_flags |= SCSIPI_CHAN_CANGROW;
102
103	ahd->sc_child = config_found(ahd->sc_dev, &ahd->sc_channel, scsiprint);
104
105	ahd_intr_enable(ahd, TRUE);
106
107	if (ahd->flags & AHD_RESET_BUS_A)
108		ahd_reset_channel(ahd, 'A', TRUE);
109
110	if (!pmf_device_register1(ahd->sc_dev,
111	    ahd_pmf_suspend, ahd_pmf_resume, ahd_pmf_shutdown))
112		aprint_error_dev(ahd->sc_dev,
113		    "couldn't establish power handler\n");
114
115	ahd_unlock(ahd, &s);
116
117	return (1);
118}
119
120static bool
121ahd_pmf_suspend(device_t dev, const pmf_qual_t *qual)
122{
123	struct ahd_softc *sc = device_private(dev);
124#if 0
125	return (ahd_suspend(sc) == 0);
126#else
127	ahd_shutdown(sc);
128	return true;
129#endif
130}
131
132static bool
133ahd_pmf_resume(device_t dev, const pmf_qual_t *qual)
134{
135#if 0
136	struct ahd_softc *sc = device_private(dev);
137
138	return (ahd_resume(sc) == 0);
139#else
140	return true;
141#endif
142}
143
144static bool
145ahd_pmf_shutdown(device_t dev, int howto)
146{
147	struct ahd_softc *sc = device_private(dev);
148
149	/* Disable all interrupt sources by resetting the controller */
150	ahd_shutdown(sc);
151
152	return true;
153}
154
155static int
156ahd_ioctl(struct scsipi_channel *channel, u_long cmd,
157	  void *addr, int flag, struct proc *p)
158{
159	struct ahd_softc *ahd;
160	int s, ret = ENOTTY;
161
162	ahd = device_private(channel->chan_adapter->adapt_dev);
163
164	switch (cmd) {
165	case SCBUSIORESET:
166		s = splbio();
167		ahd_reset_channel(ahd, channel->chan_channel == 1 ? 'B' : 'A', TRUE);
168		splx(s);
169		ret = 0;
170		break;
171	default:
172		break;
173	}
174
175	return ret;
176}
177
178/*
179 * Catch an interrupt from the adapter
180 */
181void
182ahd_platform_intr(void *arg)
183{
184	struct	ahd_softc *ahd;
185
186	ahd = arg;
187
188	printf("%s; ahd_platform_intr\n", ahd_name(ahd));
189
190	ahd_intr(ahd);
191}
192
193/*
194 * We have an scb which has been processed by the
195 * adaptor, now we look to see how the operation * went.
196 */
197void
198ahd_done(struct ahd_softc *ahd, struct scb *scb)
199{
200	struct scsipi_xfer	*xs;
201	struct scsipi_periph	*periph;
202	int			s;
203
204	LIST_REMOVE(scb, pending_links);
205
206	xs = scb->xs;
207	periph = xs->xs_periph;
208
209	callout_stop(&scb->xs->xs_callout);
210
211	if (xs->datalen) {
212		int op;
213
214		if (xs->xs_control & XS_CTL_DATA_IN)
215			op = BUS_DMASYNC_POSTREAD;
216		else
217			op = BUS_DMASYNC_POSTWRITE;
218
219		bus_dmamap_sync(ahd->parent_dmat, scb->dmamap, 0,
220				scb->dmamap->dm_mapsize, op);
221		bus_dmamap_unload(ahd->parent_dmat, scb->dmamap);
222	}
223
224	/*
225	 * If the recovery SCB completes, we have to be
226	 * out of our timeout.
227	 */
228	if ((scb->flags & SCB_RECOVERY_SCB) != 0) {
229		struct	scb *list_scb;
230
231		/*
232		 * We were able to complete the command successfully,
233		 * so reinstate the timeouts for all other pending
234		 * commands.
235		 */
236		LIST_FOREACH(list_scb, &ahd->pending_scbs, pending_links) {
237			struct scsipi_xfer	*txs = list_scb->xs;
238
239			if (!(txs->xs_control & XS_CTL_POLL)) {
240				callout_reset(&txs->xs_callout,
241				    (txs->timeout > 1000000) ?
242				    (txs->timeout / 1000) * hz :
243				    (txs->timeout * hz) / 1000,
244				    ahd_timeout, list_scb);
245			}
246		}
247
248		if (ahd_get_transaction_status(scb) != XS_NOERROR)
249			ahd_set_transaction_status(scb, XS_TIMEOUT);
250		scsipi_printaddr(xs->xs_periph);
251		printf("%s: no longer in timeout, status = %x\n",
252		       ahd_name(ahd), xs->status);
253	}
254
255	if (xs->error != XS_NOERROR) {
256		/* Don't clobber any existing error state */
257	} else if ((xs->status == SCSI_STATUS_BUSY) ||
258		   (xs->status == SCSI_STATUS_QUEUE_FULL)) {
259		ahd_set_transaction_status(scb, XS_BUSY);
260		printf("%s: drive (ID %d, LUN %d) queue full (SCB 0x%x)\n",
261		       ahd_name(ahd), SCB_GET_TARGET(ahd,scb), SCB_GET_LUN(scb), SCB_GET_TAG(scb));
262	} else if ((scb->flags & SCB_SENSE) != 0) {
263		/*
264		 * We performed autosense retrieval.
265		 *
266		 * zero the sense data before having
267		 * the drive fill it.  The SCSI spec mandates
268		 * that any untransferred data should be
269		 * assumed to be zero.  Complete the 'bounce'
270		 * of sense information through buffers accessible
271		 * via bus-space by copying it into the clients
272		 * csio.
273		 */
274		memset(&xs->sense.scsi_sense, 0, sizeof(xs->sense.scsi_sense));
275		memcpy(&xs->sense.scsi_sense, ahd_get_sense_buf(ahd, scb),
276		       sizeof(struct scsi_sense_data));
277
278		ahd_set_transaction_status(scb, XS_SENSE);
279	} else if ((scb->flags & SCB_PKT_SENSE) != 0) {
280		struct scsi_status_iu_header *siu;
281		u_int sense_len;
282#ifdef AHD_DEBUG
283		int i;
284#endif
285		/*
286		 * Copy only the sense data into the provided buffer.
287		 */
288		siu = (struct scsi_status_iu_header *)scb->sense_data;
289		sense_len = MIN(scsi_4btoul(siu->sense_length),
290				sizeof(xs->sense.scsi_sense));
291		memset(&xs->sense.scsi_sense, 0, sizeof(xs->sense.scsi_sense));
292		memcpy(&xs->sense.scsi_sense,
293		       scb->sense_data + SIU_SENSE_OFFSET(siu), sense_len);
294#ifdef AHD_DEBUG
295		printf("Copied %d bytes of sense data offset %d:", sense_len,
296		       SIU_SENSE_OFFSET(siu));
297		for (i = 0; i < sense_len; i++)
298			printf(" 0x%x", ((uint8_t *)&xs->sense.scsi_sense)[i]);
299		printf("\n");
300#endif
301		ahd_set_transaction_status(scb, XS_SENSE);
302	}
303
304	if (scb->flags & SCB_FREEZE_QUEUE) {
305		scsipi_periph_thaw(periph, 1);
306		scb->flags &= ~SCB_FREEZE_QUEUE;
307	}
308
309	if (scb->flags & SCB_REQUEUE)
310		ahd_set_transaction_status(scb, XS_REQUEUE);
311
312	ahd_lock(ahd, &s);
313	ahd_free_scb(ahd, scb);
314	ahd_unlock(ahd, &s);
315
316	scsipi_done(xs);
317}
318
319static void
320ahd_action(struct scsipi_channel *chan, scsipi_adapter_req_t req, void *arg)
321{
322	struct ahd_softc *ahd;
323	struct ahd_initiator_tinfo *tinfo;
324	struct ahd_tmode_tstate *tstate;
325
326	ahd = device_private(chan->chan_adapter->adapt_dev);
327
328	switch(req) {
329
330	case ADAPTER_REQ_RUN_XFER:
331	  {
332		struct scsipi_xfer *xs;
333		struct scsipi_periph *periph;
334		struct scb *scb;
335		struct hardware_scb *hscb;
336		u_int target_id;
337		u_int our_id;
338		u_int col_idx;
339		char channel;
340		int s;
341
342		xs = arg;
343		periph = xs->xs_periph;
344
345		SC_DEBUG(periph, SCSIPI_DB3, ("ahd_action\n"));
346
347		target_id = periph->periph_target;
348		our_id = ahd->our_id;
349		channel = (chan->chan_channel == 1) ? 'B' : 'A';
350
351		/*
352		 * get an scb to use.
353		 */
354		ahd_lock(ahd, &s);
355		tinfo = ahd_fetch_transinfo(ahd, channel, our_id,
356					    target_id, &tstate);
357
358		if (xs->xs_tag_type != 0 ||
359		    (tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0)
360			col_idx = AHD_NEVER_COL_IDX;
361		else
362			col_idx = AHD_BUILD_COL_IDX(target_id,
363			    periph->periph_lun);
364
365		if ((scb = ahd_get_scb(ahd, col_idx)) == NULL) {
366			xs->error = XS_RESOURCE_SHORTAGE;
367			ahd_unlock(ahd, &s);
368			scsipi_done(xs);
369			return;
370		}
371		ahd_unlock(ahd, &s);
372
373		hscb = scb->hscb;
374
375		SC_DEBUG(periph, SCSIPI_DB3, ("start scb(%p)\n", scb));
376		scb->xs = xs;
377
378		/*
379		 * Put all the arguments for the xfer in the scb
380		 */
381		hscb->control = 0;
382		hscb->scsiid = BUILD_SCSIID(ahd, sim, target_id, our_id);
383		hscb->lun = periph->periph_lun;
384		if (xs->xs_control & XS_CTL_RESET) {
385			hscb->cdb_len = 0;
386			scb->flags |= SCB_DEVICE_RESET;
387			hscb->control |= MK_MESSAGE;
388			hscb->task_management = SIU_TASKMGMT_LUN_RESET;
389			ahd_execute_scb(scb, NULL, 0);
390		} else {
391			hscb->task_management = 0;
392		}
393
394		ahd_setup_data(ahd, xs, scb);
395		break;
396	  }
397
398	case ADAPTER_REQ_GROW_RESOURCES:
399#ifdef AHC_DEBUG
400		printf("%s: ADAPTER_REQ_GROW_RESOURCES\n", ahd_name(ahd));
401#endif
402		chan->chan_adapter->adapt_openings += ahd_alloc_scbs(ahd);
403		if (ahd->scb_data.numscbs >= AHD_SCB_MAX_ALLOC)
404			chan->chan_flags &= ~SCSIPI_CHAN_CANGROW;
405		break;
406
407	case ADAPTER_REQ_SET_XFER_MODE:
408	    {
409		struct scsipi_xfer_mode *xm = arg;
410		struct ahd_devinfo devinfo;
411		int target_id, our_id, first;
412		u_int width;
413		int s;
414		char channel;
415		u_int ppr_options = 0, period, offset;
416		uint16_t old_autoneg;
417
418		target_id = xm->xm_target;
419		our_id = chan->chan_id;
420		channel = 'A';
421		s = splbio();
422		tinfo = ahd_fetch_transinfo(ahd, channel, our_id, target_id,
423		    &tstate);
424		ahd_compile_devinfo(&devinfo, our_id, target_id,
425		    0, channel, ROLE_INITIATOR);
426
427		old_autoneg = tstate->auto_negotiate;
428
429		/*
430		 * XXX since the period and offset are not provided here,
431		 * fake things by forcing a renegotiation using the user
432		 * settings if this is called for the first time (i.e.
433		 * during probe). Also, cap various values at the user
434		 * values, assuming that the user set it up that way.
435		 */
436		if (ahd->inited_target[target_id] == 0) {
437			period = tinfo->user.period;
438			offset = tinfo->user.offset;
439			ppr_options = tinfo->user.ppr_options;
440			width = tinfo->user.width;
441			tstate->tagenable |=
442			    (ahd->user_tagenable & devinfo.target_mask);
443			tstate->discenable |=
444			    (ahd->user_discenable & devinfo.target_mask);
445			ahd->inited_target[target_id] = 1;
446			first = 1;
447		} else
448			first = 0;
449
450		if (xm->xm_mode & (PERIPH_CAP_WIDE16 | PERIPH_CAP_DT))
451			width = MSG_EXT_WDTR_BUS_16_BIT;
452		else
453			width = MSG_EXT_WDTR_BUS_8_BIT;
454
455		ahd_validate_width(ahd, NULL, &width, ROLE_UNKNOWN);
456		if (width > tinfo->user.width)
457			width = tinfo->user.width;
458		ahd_set_width(ahd, &devinfo, width, AHD_TRANS_GOAL, FALSE);
459
460		if (!(xm->xm_mode & (PERIPH_CAP_SYNC | PERIPH_CAP_DT))) {
461			period = 0;
462			offset = 0;
463			ppr_options = 0;
464		}
465
466		if ((xm->xm_mode & PERIPH_CAP_DT) &&
467		    (tinfo->user.ppr_options & MSG_EXT_PPR_DT_REQ))
468			ppr_options |= MSG_EXT_PPR_DT_REQ;
469		else
470			ppr_options &= ~MSG_EXT_PPR_DT_REQ;
471
472		if ((tstate->discenable & devinfo.target_mask) == 0 ||
473		    (tstate->tagenable & devinfo.target_mask) == 0)
474			ppr_options &= ~MSG_EXT_PPR_IU_REQ;
475
476		if ((xm->xm_mode & PERIPH_CAP_TQING) &&
477		    (ahd->user_tagenable & devinfo.target_mask))
478			tstate->tagenable |= devinfo.target_mask;
479		else
480			tstate->tagenable &= ~devinfo.target_mask;
481
482		ahd_find_syncrate(ahd, &period, &ppr_options, AHD_SYNCRATE_MAX);
483		ahd_validate_offset(ahd, NULL, period, &offset,
484		    MSG_EXT_WDTR_BUS_8_BIT, ROLE_UNKNOWN);
485		if (offset == 0) {
486			period = 0;
487			ppr_options = 0;
488		}
489		if (ppr_options != 0
490		    && tinfo->user.transport_version >= 3) {
491			tinfo->goal.transport_version =
492			    tinfo->user.transport_version;
493			tinfo->curr.transport_version =
494			    tinfo->user.transport_version;
495		}
496
497		ahd_set_syncrate(ahd, &devinfo, period, offset,
498		    ppr_options, AHD_TRANS_GOAL, FALSE);
499
500		/*
501		 * If this is the first request, and no negotiation is
502		 * needed, just confirm the state to the scsipi layer,
503		 * so that it can print a message.
504		 */
505		if (old_autoneg == tstate->auto_negotiate && first) {
506			xm->xm_mode = 0;
507			xm->xm_period = tinfo->curr.period;
508			xm->xm_offset = tinfo->curr.offset;
509			if (tinfo->curr.width == MSG_EXT_WDTR_BUS_16_BIT)
510				xm->xm_mode |= PERIPH_CAP_WIDE16;
511			if (tinfo->curr.period)
512				xm->xm_mode |= PERIPH_CAP_SYNC;
513			if (tstate->tagenable & devinfo.target_mask)
514				xm->xm_mode |= PERIPH_CAP_TQING;
515			if (tinfo->curr.ppr_options & MSG_EXT_PPR_DT_REQ)
516				xm->xm_mode |= PERIPH_CAP_DT;
517			scsipi_async_event(chan, ASYNC_EVENT_XFER_MODE, xm);
518		}
519		splx(s);
520	    }
521	}
522
523	return;
524}
525
526static void
527ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments)
528{
529	struct scb *scb;
530	struct scsipi_xfer *xs;
531	struct ahd_softc *ahd;
532	struct ahd_initiator_tinfo *tinfo;
533	struct ahd_tmode_tstate *tstate;
534	u_int  mask;
535	int    s;
536
537	scb = arg;
538	xs = scb->xs;
539	xs->error = 0;
540	xs->status = 0;
541	xs->xs_status = 0;
542	ahd = device_private(
543	    xs->xs_periph->periph_channel->chan_adapter->adapt_dev);
544
545	scb->sg_count = 0;
546	if (nsegments != 0) {
547		void *sg;
548		int op;
549		u_int i;
550
551		ahd_setup_data_scb(ahd, scb);
552
553		/* Copy the segments into our SG list */
554		for (i = nsegments, sg = scb->sg_list; i > 0; i--) {
555
556			sg = ahd_sg_setup(ahd, scb, sg, dm_segs->ds_addr,
557					  dm_segs->ds_len,
558					  /*last*/i == 1);
559			dm_segs++;
560		}
561
562		if (xs->xs_control & XS_CTL_DATA_IN)
563			op = BUS_DMASYNC_PREREAD;
564		else
565			op = BUS_DMASYNC_PREWRITE;
566
567		bus_dmamap_sync(ahd->parent_dmat, scb->dmamap, 0,
568				scb->dmamap->dm_mapsize, op);
569	}
570
571	ahd_lock(ahd, &s);
572
573	/*
574	 * Last time we need to check if this SCB needs to
575	 * be aborted.
576	 */
577	if (ahd_get_scsi_status(scb) == XS_STS_DONE) {
578		if (nsegments != 0)
579			bus_dmamap_unload(ahd->parent_dmat,
580					  scb->dmamap);
581		ahd_free_scb(ahd, scb);
582		ahd_unlock(ahd, &s);
583		return;
584	}
585
586	tinfo = ahd_fetch_transinfo(ahd, SCSIID_CHANNEL(ahd, scb->hscb->scsiid),
587				    SCSIID_OUR_ID(scb->hscb->scsiid),
588				    SCSIID_TARGET(ahd, scb->hscb->scsiid),
589				    &tstate);
590
591	mask = SCB_GET_TARGET_MASK(ahd, scb);
592
593	if ((tstate->discenable & mask) != 0)
594		scb->hscb->control |= DISCENB;
595
596	if ((tstate->tagenable & mask) != 0)
597		scb->hscb->control |= xs->xs_tag_type|TAG_ENB;
598
599	if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU) != 0) {
600		scb->flags |= SCB_PACKETIZED;
601		if (scb->hscb->task_management != 0)
602			scb->hscb->control &= ~MK_MESSAGE;
603	}
604
605#if 0	/* This looks like it makes sense at first, but it can loop */
606	if ((xs->xs_control & XS_CTL_DISCOVERY) &&
607	    (tinfo->goal.width != 0
608	     || tinfo->goal.period != 0
609	     || tinfo->goal.ppr_options != 0)) {
610		scb->flags |= SCB_NEGOTIATE;
611		scb->hscb->control |= MK_MESSAGE;
612	} else
613#endif
614	if ((tstate->auto_negotiate & mask) != 0) {
615		scb->flags |= SCB_AUTO_NEGOTIATE;
616		scb->hscb->control |= MK_MESSAGE;
617	}
618
619	LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links);
620
621	scb->flags |= SCB_ACTIVE;
622
623	if (!(xs->xs_control & XS_CTL_POLL)) {
624		callout_reset(&scb->xs->xs_callout, xs->timeout > 1000000 ?
625			      (xs->timeout / 1000) * hz : (xs->timeout * hz) / 1000,
626			      ahd_timeout, scb);
627	}
628
629	if ((scb->flags & SCB_TARGET_IMMEDIATE) != 0) {
630		/* Define a mapping from our tag to the SCB. */
631		ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb;
632		ahd_pause(ahd);
633		ahd_set_scbptr(ahd, SCB_GET_TAG(scb));
634		ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_TARG);
635		ahd_unpause(ahd);
636	} else {
637		ahd_queue_scb(ahd, scb);
638	}
639
640	if (!(xs->xs_control & XS_CTL_POLL)) {
641		ahd_unlock(ahd, &s);
642		return;
643	}
644	/*
645	 * If we can't use interrupts, poll for completion
646	 */
647	SC_DEBUG(xs->xs_periph, SCSIPI_DB3, ("cmd_poll\n"));
648	do {
649		if (ahd_poll(ahd, xs->timeout)) {
650			if (!(xs->xs_control & XS_CTL_SILENT))
651				printf("cmd fail\n");
652			ahd_timeout(scb);
653			break;
654		}
655	} while (!(xs->xs_status & XS_STS_DONE));
656
657	ahd_unlock(ahd, &s);
658}
659
660static int
661ahd_poll(struct ahd_softc *ahd, int wait)
662{
663
664	while (--wait) {
665		DELAY(1000);
666		if (ahd_inb(ahd, INTSTAT) & INT_PEND)
667			break;
668	}
669
670	if (wait == 0) {
671		printf("%s: board is not responding\n", ahd_name(ahd));
672		return (EIO);
673	}
674
675	ahd_intr(ahd);
676	return (0);
677}
678
679
680static void
681ahd_setup_data(struct ahd_softc *ahd, struct scsipi_xfer *xs,
682	       struct scb *scb)
683{
684	struct hardware_scb *hscb;
685
686	hscb = scb->hscb;
687	xs->resid = xs->status = 0;
688
689	hscb->cdb_len = xs->cmdlen;
690	if (hscb->cdb_len > MAX_CDB_LEN) {
691		int s;
692		/*
693		 * Should CAM start to support CDB sizes
694		 * greater than 16 bytes, we could use
695		 * the sense buffer to store the CDB.
696		 */
697		ahd_set_transaction_status(scb,
698					   XS_DRIVER_STUFFUP);
699
700		ahd_lock(ahd, &s);
701		ahd_free_scb(ahd, scb);
702		ahd_unlock(ahd, &s);
703		scsipi_done(xs);
704	}
705	memcpy(hscb->shared_data.idata.cdb, xs->cmd, hscb->cdb_len);
706
707	/* Only use S/G if there is a transfer */
708	if (xs->datalen) {
709		int error;
710
711		error = bus_dmamap_load(ahd->parent_dmat,
712					scb->dmamap, xs->data,
713					xs->datalen, NULL,
714					((xs->xs_control & XS_CTL_NOSLEEP) ?
715					 BUS_DMA_NOWAIT : BUS_DMA_WAITOK) |
716					BUS_DMA_STREAMING |
717					((xs->xs_control & XS_CTL_DATA_IN) ?
718					 BUS_DMA_READ : BUS_DMA_WRITE));
719		if (error) {
720#ifdef AHD_DEBUG
721			printf("%s: in ahd_setup_data(): bus_dmamap_load() "
722			       "= %d\n",
723			       ahd_name(ahd), error);
724#endif
725			xs->error = XS_RESOURCE_SHORTAGE;
726			scsipi_done(xs);
727			return;
728		}
729		ahd_execute_scb(scb,
730				scb->dmamap->dm_segs,
731				scb->dmamap->dm_nsegs);
732	} else {
733		ahd_execute_scb(scb, NULL, 0);
734	}
735}
736
737void
738ahd_timeout(void *arg)
739{
740	struct	scb	  *scb;
741	struct	ahd_softc *ahd;
742	ahd_mode_state	   saved_modes;
743	int		   s;
744
745	scb = arg;
746	ahd = scb->ahd_softc;
747
748	printf("%s: ahd_timeout\n", ahd_name(ahd));
749
750	ahd_lock(ahd, &s);
751
752	ahd_pause_and_flushwork(ahd);
753	saved_modes = ahd_save_modes(ahd);
754#if 0
755	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
756	ahd_outb(ahd, SCSISIGO, ACKO);
757	printf("set ACK\n");
758	ahd_outb(ahd, SCSISIGO, 0);
759	printf("clearing Ack\n");
760	ahd_restore_modes(ahd, saved_modes);
761#endif
762	if ((scb->flags & SCB_ACTIVE) == 0) {
763		/* Previous timeout took care of me already */
764		printf("%s: Timedout SCB already complete. "
765		       "Interrupts may not be functioning.\n", ahd_name(ahd));
766		ahd_unpause(ahd);
767		ahd_unlock(ahd, &s);
768		return;
769	}
770
771	ahd_print_path(ahd, scb);
772	printf("SCB 0x%x - timed out\n", SCB_GET_TAG(scb));
773	ahd_dump_card_state(ahd);
774	ahd_reset_channel(ahd, SIM_CHANNEL(ahd, sim),
775			  /*initiate reset*/TRUE);
776	ahd_unlock(ahd, &s);
777	return;
778}
779
780int
781ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg)
782{
783	ahd->platform_data = malloc(sizeof(struct ahd_platform_data), M_DEVBUF,
784				    M_NOWAIT /*| M_ZERO*/);
785	if (ahd->platform_data == NULL)
786		return (ENOMEM);
787
788	memset(ahd->platform_data, 0, sizeof(struct ahd_platform_data));
789
790	return (0);
791}
792
793void
794ahd_platform_free(struct ahd_softc *ahd)
795{
796	free(ahd->platform_data, M_DEVBUF);
797}
798
799int
800ahd_softc_comp(struct ahd_softc *lahd, struct ahd_softc *rahd)
801{
802	/* We don't sort softcs under NetBSD so report equal always */
803	return (0);
804}
805
806int
807ahd_detach(struct ahd_softc *ahd, int flags)
808{
809	int rv = 0;
810
811	if (ahd->sc_child != NULL)
812		rv = config_detach(ahd->sc_child, flags);
813
814	pmf_device_deregister(ahd->sc_dev);
815
816	ahd_free(ahd);
817
818	return rv;
819}
820
821void
822ahd_platform_set_tags(struct ahd_softc *ahd,
823		      struct ahd_devinfo *devinfo, ahd_queue_alg alg)
824{
825	struct ahd_tmode_tstate *tstate;
826
827	ahd_fetch_transinfo(ahd, devinfo->channel, devinfo->our_scsiid,
828			    devinfo->target, &tstate);
829
830	if (alg != AHD_QUEUE_NONE)
831		tstate->tagenable |= devinfo->target_mask;
832	else
833		tstate->tagenable &= ~devinfo->target_mask;
834}
835
836void
837ahd_send_async(struct ahd_softc *ahd, char channel, u_int target, u_int lun,
838	       ac_code code, void *opt_arg)
839{
840	struct ahd_tmode_tstate *tstate;
841	struct ahd_initiator_tinfo *tinfo;
842	struct ahd_devinfo devinfo;
843	struct scsipi_channel *chan;
844	struct scsipi_xfer_mode xm;
845
846#ifdef DIAGNOSTIC
847	if (channel != 'A')
848		panic("ahd_send_async: not channel A");
849#endif
850	chan = &ahd->sc_channel;
851	switch (code) {
852	case AC_TRANSFER_NEG:
853		tinfo = ahd_fetch_transinfo(ahd, channel, ahd->our_id, target,
854			    &tstate);
855		ahd_compile_devinfo(&devinfo, ahd->our_id, target, lun,
856		    channel, ROLE_UNKNOWN);
857		/*
858		 * Don't bother if negotiating. XXX?
859		 */
860		if (tinfo->curr.period != tinfo->goal.period
861		    || tinfo->curr.width != tinfo->goal.width
862		    || tinfo->curr.offset != tinfo->goal.offset
863		    || tinfo->curr.ppr_options != tinfo->goal.ppr_options)
864			break;
865		xm.xm_target = target;
866		xm.xm_mode = 0;
867		xm.xm_period = tinfo->curr.period;
868		xm.xm_offset = tinfo->curr.offset;
869		if (tinfo->goal.ppr_options & MSG_EXT_PPR_DT_REQ)
870			xm.xm_mode |= PERIPH_CAP_DT;
871		if (tinfo->curr.width == MSG_EXT_WDTR_BUS_16_BIT)
872			xm.xm_mode |= PERIPH_CAP_WIDE16;
873		if (tinfo->curr.period)
874			xm.xm_mode |= PERIPH_CAP_SYNC;
875		if (tstate->tagenable & devinfo.target_mask)
876			xm.xm_mode |= PERIPH_CAP_TQING;
877		scsipi_async_event(chan, ASYNC_EVENT_XFER_MODE, &xm);
878		break;
879	case AC_BUS_RESET:
880		scsipi_async_event(chan, ASYNC_EVENT_RESET, NULL);
881	case AC_SENT_BDR:
882	default:
883		break;
884	}
885}
886