aic.c revision 315813
1/*-
2 * Copyright (c) 1999 Luoqi Chen.
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, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: stable/10/sys/dev/aic/aic.c 315813 2017-03-23 06:41:13Z mav $");
29
30#include <sys/param.h>
31#include <sys/conf.h>
32#include <sys/systm.h>
33#include <sys/kernel.h>
34#include <sys/lock.h>
35#include <sys/mutex.h>
36#include <sys/malloc.h>
37#include <sys/bus.h>
38
39#include <machine/bus.h>
40#include <sys/rman.h>
41
42#include <cam/cam.h>
43#include <cam/cam_ccb.h>
44#include <cam/cam_sim.h>
45#include <cam/cam_xpt_sim.h>
46#include <cam/cam_debug.h>
47
48#include <cam/scsi/scsi_message.h>
49
50#include <dev/aic/aic6360reg.h>
51#include <dev/aic/aicvar.h>
52
53static void aic_action(struct cam_sim *sim, union ccb *ccb);
54static void aic_execute_scb(void *arg, bus_dma_segment_t *dm_segs,
55				int nseg, int error);
56static void aic_intr_locked(struct aic_softc *aic);
57static void aic_start(struct aic_softc *aic);
58static void aic_select(struct aic_softc *aic);
59static void aic_selected(struct aic_softc *aic);
60static void aic_reselected(struct aic_softc *aic);
61static void aic_reconnect(struct aic_softc *aic, int tag);
62static void aic_cmd(struct aic_softc *aic);
63static void aic_msgin(struct aic_softc *aic);
64static void aic_handle_msgin(struct aic_softc *aic);
65static void aic_msgout(struct aic_softc *aic);
66static void aic_datain(struct aic_softc *aic);
67static void aic_dataout(struct aic_softc *aic);
68static void aic_done(struct aic_softc *aic, struct aic_scb *scb);
69static void aic_poll(struct cam_sim *sim);
70static void aic_timeout(void *arg);
71static void aic_scsi_reset(struct aic_softc *aic);
72static void aic_chip_reset(struct aic_softc *aic);
73static void aic_reset(struct aic_softc *aic, int initiate_reset);
74
75devclass_t aic_devclass;
76
77static struct aic_scb *
78aic_get_scb(struct aic_softc *aic)
79{
80	struct aic_scb *scb;
81
82	if (!dumping)
83		mtx_assert(&aic->lock, MA_OWNED);
84	if ((scb = SLIST_FIRST(&aic->free_scbs)) != NULL)
85		SLIST_REMOVE_HEAD(&aic->free_scbs, link);
86	return (scb);
87}
88
89static void
90aic_free_scb(struct aic_softc *aic, struct aic_scb *scb)
91{
92
93	if (!dumping)
94		mtx_assert(&aic->lock, MA_OWNED);
95	if ((aic->flags & AIC_RESOURCE_SHORTAGE) != 0 &&
96	    (scb->ccb->ccb_h.status & CAM_RELEASE_SIMQ) == 0) {
97		scb->ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
98		aic->flags &= ~AIC_RESOURCE_SHORTAGE;
99	}
100	scb->flags = 0;
101	SLIST_INSERT_HEAD(&aic->free_scbs, scb, link);
102}
103
104static void
105aic_action(struct cam_sim *sim, union ccb *ccb)
106{
107	struct aic_softc *aic;
108
109	CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("aic_action\n"));
110
111	aic = (struct aic_softc *)cam_sim_softc(sim);
112	mtx_assert(&aic->lock, MA_OWNED);
113
114	switch (ccb->ccb_h.func_code) {
115	case XPT_SCSI_IO:	/* Execute the requested I/O operation */
116	case XPT_RESET_DEV:	/* Bus Device Reset the specified SCSI device */
117        {
118		struct aic_scb *scb;
119
120		if ((scb = aic_get_scb(aic)) == NULL) {
121			aic->flags |= AIC_RESOURCE_SHORTAGE;
122			xpt_freeze_simq(aic->sim, /*count*/1);
123			ccb->ccb_h.status = CAM_REQUEUE_REQ;
124			xpt_done(ccb);
125			return;
126		}
127
128		scb->ccb = ccb;
129		ccb->ccb_h.ccb_scb_ptr = scb;
130		ccb->ccb_h.ccb_aic_ptr = aic;
131
132		scb->target = ccb->ccb_h.target_id;
133		scb->lun = ccb->ccb_h.target_lun;
134
135		if (ccb->ccb_h.func_code == XPT_SCSI_IO) {
136			scb->cmd_len = ccb->csio.cdb_len;
137			if (ccb->ccb_h.flags & CAM_CDB_POINTER) {
138				if (ccb->ccb_h.flags & CAM_CDB_PHYS) {
139					ccb->ccb_h.status = CAM_REQ_INVALID;
140					aic_free_scb(aic, scb);
141					xpt_done(ccb);
142					return;
143				}
144				scb->cmd_ptr = ccb->csio.cdb_io.cdb_ptr;
145			} else {
146				scb->cmd_ptr = ccb->csio.cdb_io.cdb_bytes;
147			}
148			if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
149				if ((ccb->ccb_h.flags & CAM_DATA_MASK) !=
150				    CAM_DATA_VADDR) {
151					ccb->ccb_h.status = CAM_REQ_INVALID;
152					aic_free_scb(aic, scb);
153					xpt_done(ccb);
154					return;
155				}
156				scb->data_ptr = ccb->csio.data_ptr;
157				scb->data_len = ccb->csio.dxfer_len;
158			} else {
159				scb->data_ptr = NULL;
160				scb->data_len = 0;
161			}
162			aic_execute_scb(scb, NULL, 0, 0);
163		} else {
164			scb->flags |= SCB_DEVICE_RESET;
165			aic_execute_scb(scb, NULL, 0, 0);
166		}
167		break;
168	}
169	case XPT_SET_TRAN_SETTINGS:
170	{
171		struct ccb_trans_settings *cts = &ccb->cts;
172		struct aic_tinfo *ti = &aic->tinfo[ccb->ccb_h.target_id];
173		struct ccb_trans_settings_scsi *scsi =
174		    &cts->proto_specific.scsi;
175		struct ccb_trans_settings_spi *spi =
176		    &cts->xport_specific.spi;
177
178		if ((spi->valid & CTS_SPI_VALID_DISC) != 0 &&
179		    (aic->flags & AIC_DISC_ENABLE) != 0) {
180			if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) != 0)
181				ti->flags |= TINFO_DISC_ENB;
182			else
183				ti->flags &= ~TINFO_DISC_ENB;
184		}
185
186		if ((scsi->valid & CTS_SCSI_VALID_TQ) != 0) {
187			if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0)
188				ti->flags |= TINFO_TAG_ENB;
189			else
190				ti->flags &= ~TINFO_TAG_ENB;
191		}
192
193		if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
194			ti->goal.period = spi->sync_period;
195
196			if (ti->goal.period > aic->min_period) {
197				ti->goal.period = 0;
198				ti->goal.offset = 0;
199			} else if (ti->goal.period < aic->max_period)
200				ti->goal.period = aic->max_period;
201		}
202
203		if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0) {
204			ti->goal.offset = spi->sync_offset;
205			if (ti->goal.offset == 0)
206				ti->goal.period = 0;
207			else if (ti->goal.offset > AIC_SYNC_OFFSET)
208				ti->goal.offset = AIC_SYNC_OFFSET;
209		}
210
211		if ((ti->goal.period != ti->current.period)
212		 || (ti->goal.offset != ti->current.offset))
213			ti->flags |= TINFO_SDTR_NEGO;
214
215		ccb->ccb_h.status = CAM_REQ_CMP;
216		xpt_done(ccb);
217		break;
218	}
219	case XPT_GET_TRAN_SETTINGS:
220	{
221		struct ccb_trans_settings *cts = &ccb->cts;
222		struct aic_tinfo *ti = &aic->tinfo[ccb->ccb_h.target_id];
223		struct ccb_trans_settings_scsi *scsi =
224		    &cts->proto_specific.scsi;
225		struct ccb_trans_settings_spi *spi =
226		    &cts->xport_specific.spi;
227
228		cts->protocol = PROTO_SCSI;
229		cts->protocol_version = SCSI_REV_2;
230		cts->transport = XPORT_SPI;
231		cts->transport_version = 2;
232		scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
233		spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
234
235		if ((ti->flags & TINFO_DISC_ENB) != 0)
236			spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
237		if ((ti->flags & TINFO_TAG_ENB) != 0)
238			scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
239
240		if (cts->type == CTS_TYPE_CURRENT_SETTINGS) {
241			spi->sync_period = ti->current.period;
242			spi->sync_offset = ti->current.offset;
243		} else {
244			spi->sync_period = ti->user.period;
245			spi->sync_offset = ti->user.offset;
246		}
247
248		spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
249		spi->valid = CTS_SPI_VALID_SYNC_RATE
250			   | CTS_SPI_VALID_SYNC_OFFSET
251			   | CTS_SPI_VALID_BUS_WIDTH
252			   | CTS_SPI_VALID_DISC;
253		scsi->valid = CTS_SCSI_VALID_TQ;
254
255		ccb->ccb_h.status = CAM_REQ_CMP;
256		xpt_done(ccb);
257		break;
258	}
259	case XPT_CALC_GEOMETRY:
260	{
261		cam_calc_geometry(&ccb->ccg, /*extended*/1);
262		xpt_done(ccb);
263		break;
264	}
265	case XPT_RESET_BUS:		/* Reset the specified SCSI bus */
266		aic_reset(aic, /*initiate_reset*/TRUE);
267		ccb->ccb_h.status = CAM_REQ_CMP;
268		xpt_done(ccb);
269		break;
270        case XPT_PATH_INQ:              /* Path routing inquiry */
271        {
272                struct ccb_pathinq *cpi = &ccb->cpi;
273
274                cpi->version_num = 1; /* XXX??? */
275                cpi->hba_inquiry = PI_SDTR_ABLE | PI_TAG_ABLE;
276                cpi->target_sprt = 0;
277                cpi->hba_misc = 0;
278                cpi->hba_eng_cnt = 0;
279                cpi->max_target = 7;
280                cpi->max_lun = 7;
281                cpi->initiator_id = aic->initiator;
282                cpi->bus_id = cam_sim_bus(sim);
283		cpi->base_transfer_speed = 3300;
284                strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
285                strlcpy(cpi->hba_vid, "Adaptec", HBA_IDLEN);
286                strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
287                cpi->unit_number = cam_sim_unit(sim);
288                cpi->transport = XPORT_SPI;
289                cpi->transport_version = 2;
290                cpi->protocol = PROTO_SCSI;
291                cpi->protocol_version = SCSI_REV_2;
292                cpi->ccb_h.status = CAM_REQ_CMP;
293                xpt_done(ccb);
294                break;
295        }
296	default:
297                ccb->ccb_h.status = CAM_REQ_INVALID;
298                xpt_done(ccb);
299                break;
300	}
301}
302
303static void
304aic_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
305{
306	struct aic_scb *scb = (struct aic_scb *)arg;
307	union ccb *ccb = scb->ccb;
308	struct aic_softc *aic = (struct aic_softc *)ccb->ccb_h.ccb_aic_ptr;
309
310	if (!dumping)
311		mtx_assert(&aic->lock, MA_OWNED);
312	if (ccb->ccb_h.status != CAM_REQ_INPROG) {
313		aic_free_scb(aic, scb);
314		xpt_done(ccb);
315		return;
316	}
317
318	scb->flags |= SCB_ACTIVE;
319	ccb->ccb_h.status |= CAM_SIM_QUEUED;
320	TAILQ_INSERT_TAIL(&aic->pending_ccbs, &ccb->ccb_h, sim_links.tqe);
321
322	callout_reset_sbt(&scb->timer, SBT_1MS * ccb->ccb_h.timeout, 0,
323	    aic_timeout, scb, 0);
324
325	aic_start(aic);
326}
327
328/*
329 * Start another command if the controller is not busy.
330 */
331static void
332aic_start(struct aic_softc *aic)
333{
334	struct ccb_hdr *ccb_h;
335	struct aic_tinfo *ti;
336
337	if (aic->state != AIC_IDLE)
338		return;
339
340	TAILQ_FOREACH(ccb_h, &aic->pending_ccbs, sim_links.tqe) {
341		ti = &aic->tinfo[ccb_h->target_id];
342		if ((ti->lubusy & (1 << ccb_h->target_lun)) == 0) {
343			TAILQ_REMOVE(&aic->pending_ccbs, ccb_h, sim_links.tqe);
344			aic->nexus = (struct aic_scb *)ccb_h->ccb_scb_ptr;
345			aic_select(aic);
346			return;
347		}
348	}
349
350	CAM_DEBUG_PRINT(CAM_DEBUG_TRACE, ("aic_start: idle\n"));
351
352	aic_outb(aic, SIMODE0, ENSELDI);
353	aic_outb(aic, SIMODE1, ENSCSIRST);
354	aic_outb(aic, SCSISEQ, ENRESELI);
355}
356
357/*
358 * Start a selection.
359 */
360static void
361aic_select(struct aic_softc *aic)
362{
363	struct aic_scb *scb = aic->nexus;
364
365	CAM_DEBUG(scb->ccb->ccb_h.path, CAM_DEBUG_TRACE,
366		  ("aic_select - ccb %p\n", scb->ccb));
367
368	aic->state = AIC_SELECTING;
369
370	aic_outb(aic, DMACNTRL1, 0);
371	aic_outb(aic, SCSIID, aic->initiator << OID_S | scb->target);
372	aic_outb(aic, SXFRCTL1, STIMO_256ms | ENSTIMER |
373	    (aic->flags & AIC_PARITY_ENABLE ? ENSPCHK : 0));
374
375	aic_outb(aic, SIMODE0, ENSELDI|ENSELDO);
376	aic_outb(aic, SIMODE1, ENSCSIRST|ENSELTIMO);
377	aic_outb(aic, SCSISEQ, ENRESELI|ENSELO|ENAUTOATNO);
378}
379
380/*
381 * We have successfully selected a target, prepare for the information
382 * transfer phases.
383 */
384static void
385aic_selected(struct aic_softc *aic)
386{
387	struct aic_scb *scb = aic->nexus;
388	union ccb *ccb = scb->ccb;
389	struct aic_tinfo *ti = &aic->tinfo[scb->target];
390
391	CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
392		  ("aic_selected - ccb %p\n", ccb));
393
394	aic->state = AIC_HASNEXUS;
395
396	if (scb->flags & SCB_DEVICE_RESET) {
397		aic->msg_buf[0] = MSG_BUS_DEV_RESET;
398		aic->msg_len = 1;
399		aic->msg_outq = AIC_MSG_MSGBUF;
400	} else {
401		aic->msg_outq = AIC_MSG_IDENTIFY;
402		if ((ti->flags & TINFO_TAG_ENB) != 0 &&
403		    (ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) != 0)
404			aic->msg_outq |= AIC_MSG_TAG_Q;
405		else
406			ti->lubusy |= 1 << scb->lun;
407		if ((ti->flags & TINFO_SDTR_NEGO) != 0)
408			aic->msg_outq |= AIC_MSG_SDTR;
409	}
410
411	aic_outb(aic, CLRSINT0, CLRSELDO);
412	aic_outb(aic, CLRSINT1, CLRBUSFREE);
413	aic_outb(aic, SCSISEQ, ENAUTOATNP);
414	aic_outb(aic, SIMODE0, 0);
415	aic_outb(aic, SIMODE1, ENSCSIRST|ENBUSFREE|ENREQINIT);
416	aic_outb(aic, SCSIRATE, ti->scsirate);
417}
418
419/*
420 * We are re-selected by a target, save the target id and wait for the
421 * target to further identify itself.
422 */
423static void
424aic_reselected(struct aic_softc *aic)
425{
426	u_int8_t selid;
427
428	CAM_DEBUG_PRINT(CAM_DEBUG_TRACE, ("aic_reselected\n"));
429
430	/*
431	 * If we have started a selection, it must have lost out in
432	 * the arbitration, put the command back to the pending queue.
433	 */
434	if (aic->nexus) {
435		TAILQ_INSERT_HEAD(&aic->pending_ccbs,
436		    &aic->nexus->ccb->ccb_h, sim_links.tqe);
437		aic->nexus = NULL;
438	}
439
440	selid = aic_inb(aic, SELID) & ~(1 << aic->initiator);
441	if (selid & (selid - 1)) {
442		/* this should never have happened */
443		printf("aic_reselected: invalid selid %x\n", selid);
444		aic_reset(aic, /*initiate_reset*/TRUE);
445		return;
446	}
447
448	aic->state = AIC_RESELECTED;
449	aic->target = ffs(selid) - 1;
450	aic->lun = -1;
451
452	aic_outb(aic, CLRSINT0, CLRSELDI);
453	aic_outb(aic, CLRSINT1, CLRBUSFREE);
454	aic_outb(aic, SIMODE0, 0);
455	aic_outb(aic, SIMODE1, ENSCSIRST|ENBUSFREE|ENREQINIT);
456	aic_outb(aic, SCSISEQ, ENAUTOATNP);
457	aic_outb(aic, SCSIRATE, aic->tinfo[aic->target].scsirate);
458}
459
460/*
461 * Raise ATNO to signal the target that we have a message for it.
462 */
463static __inline void
464aic_sched_msgout(struct aic_softc *aic, u_int8_t msg)
465{
466	if (msg) {
467		aic->msg_buf[0] = msg;
468		aic->msg_len = 1;
469	}
470	aic->msg_outq |= AIC_MSG_MSGBUF;
471	aic_outb(aic, SCSISIGO, aic_inb(aic, SCSISIGI) | ATNO);
472}
473
474/*
475 * Wait for SPIORDY (SCSI PIO ready) flag, or a phase change.
476 */
477static __inline int
478aic_spiordy(struct aic_softc *aic)
479{
480	while (!(aic_inb(aic, DMASTAT) & INTSTAT) &&
481	    !(aic_inb(aic, SSTAT0) & SPIORDY))
482		;
483	return !(aic_inb(aic, DMASTAT) & INTSTAT);
484}
485
486/*
487 * Reestablish a disconnected nexus.
488 */
489static void
490aic_reconnect(struct aic_softc *aic, int tag)
491{
492	struct aic_scb *scb;
493	struct ccb_hdr *ccb_h;
494
495	CAM_DEBUG_PRINT(CAM_DEBUG_TRACE, ("aic_reconnect\n"));
496
497	/* Find the nexus */
498	scb = NULL;
499	TAILQ_FOREACH(ccb_h, &aic->nexus_ccbs, sim_links.tqe) {
500		scb = (struct aic_scb *)ccb_h->ccb_scb_ptr;
501		if (scb->target == aic->target && scb->lun == aic->lun &&
502		    (tag == -1 || scb->tag == tag))
503			break;
504	}
505
506	/* ABORT if nothing is found */
507	if (!ccb_h) {
508		if (tag == -1)
509			aic_sched_msgout(aic, MSG_ABORT);
510		else
511			aic_sched_msgout(aic, MSG_ABORT_TAG);
512		xpt_async(AC_UNSOL_RESEL, aic->path, NULL);
513		return;
514	}
515
516	/* Reestablish the nexus */
517	TAILQ_REMOVE(&aic->nexus_ccbs, ccb_h, sim_links.tqe);
518	aic->nexus = scb;
519	scb->flags &= ~SCB_DISCONNECTED;
520	aic->state = AIC_HASNEXUS;
521}
522
523/*
524 * Read messages.
525 */
526static void
527aic_msgin(struct aic_softc *aic)
528{
529	int msglen;
530
531	CAM_DEBUG_PRINT(CAM_DEBUG_TRACE, ("aic_msgin\n"));
532
533	aic_outb(aic, SIMODE1, ENSCSIRST|ENPHASEMIS|ENBUSFREE);
534	aic_outb(aic, SXFRCTL0, CHEN|SPIOEN);
535
536	aic->flags &= ~AIC_DROP_MSGIN;
537	aic->msg_len = 0;
538	do {
539		/*
540		 * If a parity error is detected, drop the remaining
541		 * bytes and inform the target so it could resend
542		 * the messages.
543		 */
544		if (aic_inb(aic, SSTAT1) & SCSIPERR) {
545			aic_outb(aic, CLRSINT1, CLRSCSIPERR);
546			aic->flags |= AIC_DROP_MSGIN;
547			aic_sched_msgout(aic, MSG_PARITY_ERROR);
548		}
549		if ((aic->flags & AIC_DROP_MSGIN)) {
550			aic_inb(aic, SCSIDAT);
551			continue;
552		}
553		/* read the message byte without ACKing on it */
554		aic->msg_buf[aic->msg_len++] = aic_inb(aic, SCSIBUS);
555		if (aic->msg_buf[0] == MSG_EXTENDED) {
556			if (aic->msg_len < 2) {
557				(void) aic_inb(aic, SCSIDAT);
558				continue;
559			}
560			switch (aic->msg_buf[2]) {
561			case MSG_EXT_SDTR:
562				msglen = MSG_EXT_SDTR_LEN;
563				break;
564			case MSG_EXT_WDTR:
565				msglen = MSG_EXT_WDTR_LEN;
566				break;
567			default:
568				msglen = 0;
569				break;
570			}
571			if (aic->msg_buf[1] != msglen) {
572				aic->flags |= AIC_DROP_MSGIN;
573				aic_sched_msgout(aic, MSG_MESSAGE_REJECT);
574			}
575			msglen += 2;
576		} else if (aic->msg_buf[0] >= 0x20 && aic->msg_buf[0] <= 0x2f)
577			msglen = 2;
578		else
579			msglen = 1;
580		/*
581		 * If we have a complete message, handle it before the final
582		 * ACK (in case we decide to reject the message).
583		 */
584		if (aic->msg_len == msglen) {
585			aic_handle_msgin(aic);
586			aic->msg_len = 0;
587		}
588		/* ACK on the message byte */
589		(void) aic_inb(aic, SCSIDAT);
590	} while (aic_spiordy(aic));
591
592	aic_outb(aic, SXFRCTL0, CHEN);
593	aic_outb(aic, SIMODE1, ENSCSIRST|ENBUSFREE|ENREQINIT);
594}
595
596/*
597 * Handle a message.
598 */
599static void
600aic_handle_msgin(struct aic_softc *aic)
601{
602	struct aic_scb *scb;
603	struct ccb_hdr *ccb_h;
604	struct aic_tinfo *ti;
605	struct ccb_trans_settings neg;
606	struct ccb_trans_settings_spi *spi = &neg.xport_specific.spi;
607
608	if (aic->state == AIC_RESELECTED) {
609		if (!MSG_ISIDENTIFY(aic->msg_buf[0])) {
610			aic_sched_msgout(aic, MSG_MESSAGE_REJECT);
611			return;
612		}
613		aic->lun = aic->msg_buf[0] & MSG_IDENTIFY_LUNMASK;
614		if (aic->tinfo[aic->target].lubusy & (1 << aic->lun))
615			aic_reconnect(aic, -1);
616		else
617			aic->state = AIC_RECONNECTING;
618		return;
619	}
620
621	if (aic->state == AIC_RECONNECTING) {
622		if (aic->msg_buf[0] != MSG_SIMPLE_Q_TAG) {
623			aic_sched_msgout(aic, MSG_MESSAGE_REJECT);
624			return;
625		}
626		aic_reconnect(aic, aic->msg_buf[1]);
627		return;
628	}
629
630	switch (aic->msg_buf[0]) {
631	case MSG_CMDCOMPLETE: {
632		struct ccb_scsiio *csio;
633		scb = aic->nexus;
634		ccb_h = &scb->ccb->ccb_h;
635		csio = &scb->ccb->csio;
636		if ((scb->flags & SCB_SENSE) != 0) {
637			/* auto REQUEST SENSE command */
638			scb->flags &= ~SCB_SENSE;
639			csio->sense_resid = scb->data_len;
640			if (scb->status == SCSI_STATUS_OK) {
641				ccb_h->status |=
642				    CAM_SCSI_STATUS_ERROR|CAM_AUTOSNS_VALID;
643				/*scsi_sense_print(csio);*/
644			} else {
645				ccb_h->status |= CAM_AUTOSENSE_FAIL;
646				printf("ccb %p sense failed %x\n",
647				    ccb_h, scb->status);
648			}
649		} else {
650			csio->scsi_status = scb->status;
651			csio->resid = scb->data_len;
652			if (scb->status == SCSI_STATUS_OK) {
653				/* everything goes well */
654				ccb_h->status |= CAM_REQ_CMP;
655			} else if ((ccb_h->flags & CAM_DIS_AUTOSENSE) == 0 &&
656			    (csio->scsi_status == SCSI_STATUS_CHECK_COND ||
657			     csio->scsi_status == SCSI_STATUS_CMD_TERMINATED)) {
658				/* try to retrieve sense information */
659				scb->flags |= SCB_SENSE;
660				aic->flags |= AIC_BUSFREE_OK;
661				return;
662			} else
663				ccb_h->status |= CAM_SCSI_STATUS_ERROR;
664		}
665		aic_done(aic, scb);
666		aic->flags |= AIC_BUSFREE_OK;
667		break;
668	}
669	case MSG_EXTENDED:
670		switch (aic->msg_buf[2]) {
671		case MSG_EXT_SDTR:
672			scb = aic->nexus;
673			ti = &aic->tinfo[scb->target];
674			if (ti->flags & TINFO_SDTR_SENT) {
675				ti->current.period = aic->msg_buf[3];
676				ti->current.offset = aic->msg_buf[4];
677			} else {
678				ti->current.period = aic->msg_buf[3] =
679					max(ti->goal.period, aic->msg_buf[3]);
680				ti->current.offset = aic->msg_buf[4] =
681					min(ti->goal.offset, aic->msg_buf[4]);
682				/*
683				 * The target initiated the negotiation,
684				 * send back a response.
685				 */
686				aic_sched_msgout(aic, 0);
687			}
688			ti->flags &= ~(TINFO_SDTR_SENT|TINFO_SDTR_NEGO);
689			ti->scsirate = ti->current.offset ? ti->current.offset |
690			    ((ti->current.period * 4 + 49) / 50 - 2) << 4 : 0;
691			aic_outb(aic, SCSIRATE, ti->scsirate);
692			memset(&neg, 0, sizeof (neg));
693			neg.protocol = PROTO_SCSI;
694			neg.protocol_version = SCSI_REV_2;
695			neg.transport = XPORT_SPI;
696			neg.transport_version = 2;
697			spi->sync_period = ti->goal.period = ti->current.period;
698			spi->sync_offset = ti->goal.offset = ti->current.offset;
699			spi->valid = CTS_SPI_VALID_SYNC_RATE
700				  | CTS_SPI_VALID_SYNC_OFFSET;
701			ccb_h = &scb->ccb->ccb_h;
702			xpt_setup_ccb(&neg.ccb_h, ccb_h->path, 1);
703			xpt_async(AC_TRANSFER_NEG, ccb_h->path, &neg);
704			break;
705		case MSG_EXT_WDTR:
706		default:
707			aic_sched_msgout(aic, MSG_MESSAGE_REJECT);
708			break;
709		}
710		break;
711	case MSG_DISCONNECT:
712		scb = aic->nexus;
713		ccb_h = &scb->ccb->ccb_h;
714		TAILQ_INSERT_TAIL(&aic->nexus_ccbs, ccb_h, sim_links.tqe);
715		scb->flags |= SCB_DISCONNECTED;
716		aic->flags |= AIC_BUSFREE_OK;
717		aic->nexus = NULL;
718		CAM_DEBUG(ccb_h->path, CAM_DEBUG_TRACE, ("disconnected\n"));
719		break;
720	case MSG_MESSAGE_REJECT:
721		switch (aic->msg_outq & -aic->msg_outq) {
722		case AIC_MSG_TAG_Q:
723			scb = aic->nexus;
724			ti = &aic->tinfo[scb->target];
725			ti->flags &= ~TINFO_TAG_ENB;
726			ti->lubusy |= 1 << scb->lun;
727			break;
728		case AIC_MSG_SDTR:
729			scb = aic->nexus;
730			ti = &aic->tinfo[scb->target];
731			ti->current.period = ti->goal.period = 0;
732			ti->current.offset = ti->goal.offset = 0;
733			ti->flags &= ~(TINFO_SDTR_SENT|TINFO_SDTR_NEGO);
734			ti->scsirate = 0;
735			aic_outb(aic, SCSIRATE, ti->scsirate);
736			memset(&neg, 0, sizeof (neg));
737			neg.protocol = PROTO_SCSI;
738			neg.protocol_version = SCSI_REV_2;
739			neg.transport = XPORT_SPI;
740			neg.transport_version = 2;
741			spi->sync_period = ti->current.period;
742			spi->sync_offset = ti->current.offset;
743			spi->valid = CTS_SPI_VALID_SYNC_RATE
744				  | CTS_SPI_VALID_SYNC_OFFSET;
745			ccb_h = &scb->ccb->ccb_h;
746			xpt_setup_ccb(&neg.ccb_h, ccb_h->path, 1);
747			xpt_async(AC_TRANSFER_NEG, ccb_h->path, &neg);
748			break;
749		default:
750			break;
751		}
752		break;
753	case MSG_SAVEDATAPOINTER:
754		break;
755	case MSG_RESTOREPOINTERS:
756		break;
757	case MSG_NOOP:
758		break;
759	default:
760		aic_sched_msgout(aic, MSG_MESSAGE_REJECT);
761		break;
762	}
763}
764
765/*
766 * Send messages.
767 */
768static void
769aic_msgout(struct aic_softc *aic)
770{
771	struct aic_scb *scb;
772	union ccb *ccb;
773	struct aic_tinfo *ti;
774	int msgidx = 0;
775
776	CAM_DEBUG_PRINT(CAM_DEBUG_TRACE, ("aic_msgout\n"));
777
778	aic_outb(aic, SIMODE1, ENSCSIRST|ENPHASEMIS|ENBUSFREE);
779	aic_outb(aic, SXFRCTL0, CHEN|SPIOEN);
780
781	/*
782	 * If the previous phase is also the message out phase,
783	 * we need to retransmit all the messages, probably
784	 * because the target has detected a parity error during
785	 * the past transmission.
786	 */
787	if (aic->prev_phase == PH_MSGOUT)
788		aic->msg_outq = aic->msg_sent;
789
790	do {
791		int q = aic->msg_outq;
792		if (msgidx > 0 && msgidx == aic->msg_len) {
793			/* complete message sent, start the next one */
794			q &= -q;
795			aic->msg_sent |= q;
796			aic->msg_outq ^= q;
797			q = aic->msg_outq;
798			msgidx = 0;
799		}
800		if (msgidx == 0) {
801			/* setup the message */
802			switch (q & -q) {
803			case AIC_MSG_IDENTIFY:
804				scb = aic->nexus;
805				ccb = scb->ccb;
806				ti = &aic->tinfo[scb->target];
807				aic->msg_buf[0] = MSG_IDENTIFY(scb->lun,
808				    (ti->flags & TINFO_DISC_ENB) &&
809				    !(ccb->ccb_h.flags & CAM_DIS_DISCONNECT));
810				aic->msg_len = 1;
811				break;
812			case AIC_MSG_TAG_Q:
813				scb = aic->nexus;
814				ccb = scb->ccb;
815				aic->msg_buf[0] = ccb->csio.tag_action;
816				aic->msg_buf[1] = scb->tag;
817				aic->msg_len = 2;
818				break;
819			case AIC_MSG_SDTR:
820				scb = aic->nexus;
821				ti = &aic->tinfo[scb->target];
822				aic->msg_buf[0] = MSG_EXTENDED;
823				aic->msg_buf[1] = MSG_EXT_SDTR_LEN;
824				aic->msg_buf[2] = MSG_EXT_SDTR;
825				aic->msg_buf[3] = ti->goal.period;
826				aic->msg_buf[4] = ti->goal.offset;
827				aic->msg_len = MSG_EXT_SDTR_LEN + 2;
828				ti->flags |= TINFO_SDTR_SENT;
829				break;
830			case AIC_MSG_MSGBUF:
831				/* a single message already in the buffer */
832				if (aic->msg_buf[0] == MSG_BUS_DEV_RESET ||
833				    aic->msg_buf[0] == MSG_ABORT ||
834				    aic->msg_buf[0] == MSG_ABORT_TAG)
835					aic->flags |= AIC_BUSFREE_OK;
836				break;
837			}
838		}
839		/*
840		 * If this is the last message byte of all messages,
841		 * clear ATNO to signal transmission complete.
842		 */
843		if ((q & (q - 1)) == 0 && msgidx == aic->msg_len - 1)
844			aic_outb(aic, CLRSINT1, CLRATNO);
845		/* transmit the message byte */
846		aic_outb(aic, SCSIDAT, aic->msg_buf[msgidx++]);
847	} while (aic_spiordy(aic));
848
849	aic_outb(aic, SXFRCTL0, CHEN);
850	aic_outb(aic, SIMODE1, ENSCSIRST|ENBUSFREE|ENREQINIT);
851}
852
853/*
854 * Read data bytes.
855 */
856static void
857aic_datain(struct aic_softc *aic)
858{
859	struct aic_scb *scb = aic->nexus;
860	u_int8_t dmastat, dmacntrl0;
861	int n;
862
863	CAM_DEBUG_PRINT(CAM_DEBUG_TRACE, ("aic_datain\n"));
864
865	aic_outb(aic, SIMODE1, ENSCSIRST|ENPHASEMIS|ENBUSFREE);
866	aic_outb(aic, SXFRCTL0, SCSIEN|DMAEN|CHEN);
867
868	dmacntrl0 = ENDMA;
869	if (aic->flags & AIC_DWIO_ENABLE)
870		dmacntrl0 |= DWORDPIO;
871	aic_outb(aic, DMACNTRL0, dmacntrl0);
872
873	while (scb->data_len > 0) {
874		for (;;) {
875			/* wait for the fifo to fill up or a phase change */
876			dmastat = aic_inb(aic, DMASTAT);
877			if (dmastat & (INTSTAT|DFIFOFULL))
878				break;
879		}
880		if (dmastat & DFIFOFULL) {
881			n = FIFOSIZE;
882		} else {
883			/*
884			 * No more data, wait for the remaining bytes in
885			 * the scsi fifo to be transfer to the host fifo.
886			 */
887			while (!(aic_inb(aic, SSTAT2) & SEMPTY))
888				;
889			n = aic_inb(aic, FIFOSTAT);
890		}
891		n = imin(scb->data_len, n);
892		if (aic->flags & AIC_DWIO_ENABLE) {
893			if (n >= 12) {
894				aic_insl(aic, DMADATALONG, scb->data_ptr, n>>2);
895				scb->data_ptr += n & ~3;
896				scb->data_len -= n & ~3;
897				n &= 3;
898			}
899		} else {
900			if (n >= 8) {
901				aic_insw(aic, DMADATA, scb->data_ptr, n >> 1);
902				scb->data_ptr += n & ~1;
903				scb->data_len -= n & ~1;
904				n &= 1;
905			}
906		}
907		if (n) {
908			aic_outb(aic, DMACNTRL0, ENDMA|B8MODE);
909			aic_insb(aic, DMADATA, scb->data_ptr, n);
910			scb->data_ptr += n;
911			scb->data_len -= n;
912			aic_outb(aic, DMACNTRL0, dmacntrl0);
913		}
914
915		if (dmastat & INTSTAT)
916			break;
917	}
918
919	aic_outb(aic, SXFRCTL0, CHEN);
920	aic_outb(aic, SIMODE1, ENSCSIRST|ENBUSFREE|ENREQINIT);
921}
922
923/*
924 * Send data bytes.
925 */
926static void
927aic_dataout(struct aic_softc *aic)
928{
929	struct aic_scb *scb = aic->nexus;
930	u_int8_t dmastat, dmacntrl0, sstat2;
931	int n;
932
933	CAM_DEBUG_PRINT(CAM_DEBUG_TRACE, ("aic_dataout\n"));
934
935	aic_outb(aic, SIMODE1, ENSCSIRST|ENPHASEMIS|ENBUSFREE);
936	aic_outb(aic, SXFRCTL0, SCSIEN|DMAEN|CHEN);
937
938	dmacntrl0 = ENDMA|WRITE;
939	if (aic->flags & AIC_DWIO_ENABLE)
940		dmacntrl0 |= DWORDPIO;
941	aic_outb(aic, DMACNTRL0, dmacntrl0);
942
943	while (scb->data_len > 0) {
944		for (;;) {
945			/* wait for the fifo to clear up or a phase change */
946			dmastat = aic_inb(aic, DMASTAT);
947			if (dmastat & (INTSTAT|DFIFOEMP))
948				break;
949		}
950		if (dmastat & INTSTAT)
951			break;
952		n = imin(scb->data_len, FIFOSIZE);
953		if (aic->flags & AIC_DWIO_ENABLE) {
954			if (n >= 12) {
955				aic_outsl(aic, DMADATALONG, scb->data_ptr,n>>2);
956				scb->data_ptr += n & ~3;
957				scb->data_len -= n & ~3;
958				n &= 3;
959			}
960		} else {
961			if (n >= 8) {
962				aic_outsw(aic, DMADATA, scb->data_ptr, n >> 1);
963				scb->data_ptr += n & ~1;
964				scb->data_len -= n & ~1;
965				n &= 1;
966			}
967		}
968		if (n) {
969			aic_outb(aic, DMACNTRL0, ENDMA|WRITE|B8MODE);
970			aic_outsb(aic, DMADATA, scb->data_ptr, n);
971			scb->data_ptr += n;
972			scb->data_len -= n;
973			aic_outb(aic, DMACNTRL0, dmacntrl0);
974		}
975	}
976
977	for (;;) {
978		/* wait until all bytes in the fifos are transmitted */
979		dmastat = aic_inb(aic, DMASTAT);
980		sstat2 = aic_inb(aic, SSTAT2);
981		if ((dmastat & DFIFOEMP) && (sstat2 & SEMPTY))
982			break;
983		if (dmastat & INTSTAT) {
984			/* adjust for untransmitted bytes */
985			n = aic_inb(aic, FIFOSTAT) + (sstat2 & 0xf);
986			scb->data_ptr -= n;
987			scb->data_len += n;
988			/* clear the fifo */
989			aic_outb(aic, SXFRCTL0, CHEN|CLRCH);
990			aic_outb(aic, DMACNTRL0, RSTFIFO);
991			break;
992		}
993	}
994
995	aic_outb(aic, SXFRCTL0, CHEN);
996	aic_outb(aic, SIMODE1, ENSCSIRST|ENBUSFREE|ENREQINIT);
997}
998
999/*
1000 * Send the scsi command.
1001 */
1002static void
1003aic_cmd(struct aic_softc *aic)
1004{
1005	struct aic_scb *scb = aic->nexus;
1006	struct scsi_request_sense sense_cmd;
1007
1008	CAM_DEBUG_PRINT(CAM_DEBUG_TRACE, ("aic_cmd\n"));
1009
1010	if (scb->flags & SCB_SENSE) {
1011		/* autosense request */
1012		sense_cmd.opcode = REQUEST_SENSE;
1013		sense_cmd.byte2 = scb->lun << 5;
1014		sense_cmd.length = scb->ccb->csio.sense_len;
1015		sense_cmd.control = 0;
1016		sense_cmd.unused[0] = 0;
1017		sense_cmd.unused[1] = 0;
1018		scb->cmd_ptr = (u_int8_t *)&sense_cmd;
1019		scb->cmd_len = sizeof(sense_cmd);
1020		scb->data_ptr = (u_int8_t *)&scb->ccb->csio.sense_data;
1021		scb->data_len = scb->ccb->csio.sense_len;
1022	}
1023
1024	aic_outb(aic, SIMODE1, ENSCSIRST|ENPHASEMIS|ENBUSFREE);
1025	aic_outb(aic, DMACNTRL0, ENDMA|WRITE);
1026	aic_outb(aic, SXFRCTL0, SCSIEN|DMAEN|CHEN);
1027	aic_outsw(aic, DMADATA, (u_int16_t *)scb->cmd_ptr, scb->cmd_len >> 1);
1028	while ((aic_inb(aic, SSTAT2) & SEMPTY) == 0 &&
1029	    (aic_inb(aic, DMASTAT) & INTSTAT) == 0)
1030		;
1031	aic_outb(aic, SXFRCTL0, CHEN);
1032	aic_outb(aic, SIMODE1, ENSCSIRST|ENBUSFREE|ENREQINIT);
1033}
1034
1035/*
1036 * Finish off a command. The caller is responsible to remove the ccb
1037 * from any queue.
1038 */
1039static void
1040aic_done(struct aic_softc *aic, struct aic_scb *scb)
1041{
1042	union ccb *ccb = scb->ccb;
1043
1044	CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
1045		  ("aic_done - ccb %p status %x resid %d\n",
1046		   ccb, ccb->ccb_h.status, ccb->csio.resid));
1047
1048	callout_stop(&scb->timer);
1049
1050	if ((scb->flags & SCB_DEVICE_RESET) != 0 &&
1051	    ccb->ccb_h.func_code != XPT_RESET_DEV) {
1052		struct cam_path *path;
1053		struct ccb_hdr *ccb_h;
1054		cam_status error;
1055
1056		error = xpt_create_path(&path, /*periph*/NULL,
1057					cam_sim_path(aic->sim),
1058					scb->target,
1059					CAM_LUN_WILDCARD);
1060
1061		if (error == CAM_REQ_CMP) {
1062			xpt_async(AC_SENT_BDR, path, NULL);
1063			xpt_free_path(path);
1064		}
1065
1066		ccb_h = TAILQ_FIRST(&aic->pending_ccbs);
1067		while (ccb_h != NULL) {
1068			struct aic_scb *pending_scb;
1069
1070			pending_scb = (struct aic_scb *)ccb_h->ccb_scb_ptr;
1071			if (ccb_h->target_id == scb->target) {
1072				ccb_h->status |= CAM_BDR_SENT;
1073				ccb_h = TAILQ_NEXT(ccb_h, sim_links.tqe);
1074				TAILQ_REMOVE(&aic->pending_ccbs,
1075				    &pending_scb->ccb->ccb_h, sim_links.tqe);
1076				aic_done(aic, pending_scb);
1077			} else {
1078				callout_reset_sbt(&pending_scb->timer,
1079				    SBT_1MS * ccb_h->timeout, 0, aic_timeout,
1080				    pending_scb, 0);
1081				ccb_h = TAILQ_NEXT(ccb_h, sim_links.tqe);
1082			}
1083		}
1084
1085		ccb_h = TAILQ_FIRST(&aic->nexus_ccbs);
1086		while (ccb_h != NULL) {
1087			struct aic_scb *nexus_scb;
1088
1089			nexus_scb = (struct aic_scb *)ccb_h->ccb_scb_ptr;
1090			if (ccb_h->target_id == scb->target) {
1091				ccb_h->status |= CAM_BDR_SENT;
1092				ccb_h = TAILQ_NEXT(ccb_h, sim_links.tqe);
1093				TAILQ_REMOVE(&aic->nexus_ccbs,
1094				    &nexus_scb->ccb->ccb_h, sim_links.tqe);
1095				aic_done(aic, nexus_scb);
1096			} else {
1097				callout_reset_sbt(&nexus_scb->timer,
1098				    SBT_1MS * ccb_h->timeout, 0, aic_timeout,
1099				    nexus_scb, 0);
1100				ccb_h = TAILQ_NEXT(ccb_h, sim_links.tqe);
1101			}
1102		}
1103	}
1104
1105	if (aic->nexus == scb || scb->flags & SCB_DISCONNECTED)
1106		aic->tinfo[scb->target].lubusy &= ~(1 << scb->lun);
1107
1108	if (aic->nexus == scb) {
1109		aic->nexus = NULL;
1110	}
1111	aic_free_scb(aic, scb);
1112	xpt_done(ccb);
1113}
1114
1115static void
1116aic_poll(struct cam_sim *sim)
1117{
1118	aic_intr_locked(cam_sim_softc(sim));
1119}
1120
1121static void
1122aic_timeout(void *arg)
1123{
1124	struct aic_scb *scb = (struct aic_scb *)arg;
1125	union ccb *ccb = scb->ccb;
1126	struct aic_softc *aic = (struct aic_softc *)ccb->ccb_h.ccb_aic_ptr;
1127
1128	mtx_assert(&aic->lock, MA_OWNED);
1129	xpt_print_path(ccb->ccb_h.path);
1130	printf("ccb %p - timed out", ccb);
1131	if (aic->nexus && aic->nexus != scb)
1132		printf(", nexus %p", aic->nexus->ccb);
1133	printf(", phase 0x%x, state %d\n", aic_inb(aic, SCSISIGI), aic->state);
1134
1135	if ((scb->flags & SCB_ACTIVE) == 0) {
1136		xpt_print_path(ccb->ccb_h.path);
1137		printf("ccb %p - timed out already completed\n", ccb);
1138		return;
1139	}
1140
1141	if ((scb->flags & SCB_DEVICE_RESET) == 0 && aic->nexus == scb) {
1142		struct ccb_hdr *ccb_h = &scb->ccb->ccb_h;
1143		struct aic_scb *pending_scb;
1144
1145		if ((ccb_h->status & CAM_RELEASE_SIMQ) == 0) {
1146			xpt_freeze_simq(aic->sim, /*count*/1);
1147			ccb_h->status |= CAM_RELEASE_SIMQ;
1148		}
1149
1150		TAILQ_FOREACH(ccb_h, &aic->pending_ccbs, sim_links.tqe) {
1151			pending_scb = ccb_h->ccb_scb_ptr;
1152			callout_stop(&pending_scb->timer);
1153		}
1154
1155		TAILQ_FOREACH(ccb_h, &aic->nexus_ccbs, sim_links.tqe) {
1156			pending_scb = ccb_h->ccb_scb_ptr;
1157			callout_stop(&pending_scb->timer);
1158		}
1159
1160		scb->flags |= SCB_DEVICE_RESET;
1161		callout_reset(&scb->timer, 5 * hz, aic_timeout, scb);
1162		aic_sched_msgout(aic, MSG_BUS_DEV_RESET);
1163	} else {
1164		if (aic->nexus == scb) {
1165			ccb->ccb_h.status |= CAM_CMD_TIMEOUT;
1166			aic_done(aic, scb);
1167		}
1168		aic_reset(aic, /*initiate_reset*/TRUE);
1169	}
1170}
1171
1172void
1173aic_intr(void *arg)
1174{
1175	struct aic_softc *aic = (struct aic_softc *)arg;
1176
1177	mtx_lock(&aic->lock);
1178	aic_intr_locked(aic);
1179	mtx_unlock(&aic->lock);
1180}
1181
1182void
1183aic_intr_locked(struct aic_softc *aic)
1184{
1185	u_int8_t sstat0, sstat1;
1186	union ccb *ccb;
1187	struct aic_scb *scb;
1188
1189	if (!(aic_inb(aic, DMASTAT) & INTSTAT))
1190		return;
1191
1192	aic_outb(aic, DMACNTRL0, 0);
1193
1194	sstat0 = aic_inb(aic, SSTAT0);
1195	sstat1 = aic_inb(aic, SSTAT1);
1196
1197	if ((sstat1 & SCSIRSTI) != 0) {
1198		/* a device-initiated bus reset */
1199		aic_outb(aic, CLRSINT1, CLRSCSIRSTI);
1200		aic_reset(aic, /*initiate_reset*/FALSE);
1201		return;
1202	}
1203
1204	if ((sstat1 & SCSIPERR) != 0) {
1205		aic_outb(aic, CLRSINT1, CLRSCSIPERR);
1206		aic_sched_msgout(aic, MSG_PARITY_ERROR);
1207		aic_outb(aic, DMACNTRL0, INTEN);
1208		return;
1209	}
1210
1211	if (aic_inb(aic, SSTAT4)) {
1212		aic_outb(aic, CLRSERR, CLRSYNCERR|CLRFWERR|CLRFRERR);
1213		aic_reset(aic, /*initiate_reset*/TRUE);
1214		return;
1215	}
1216
1217	if (aic->state <= AIC_SELECTING) {
1218		if ((sstat0 & SELDI) != 0) {
1219			aic_reselected(aic);
1220			aic_outb(aic, DMACNTRL0, INTEN);
1221			return;
1222		}
1223
1224		if ((sstat0 & SELDO) != 0) {
1225			aic_selected(aic);
1226			aic_outb(aic, DMACNTRL0, INTEN);
1227			return;
1228		}
1229
1230		if ((sstat1 & SELTO) != 0) {
1231			scb = aic->nexus;
1232			ccb = scb->ccb;
1233			ccb->ccb_h.status = CAM_SEL_TIMEOUT;
1234			aic_done(aic, scb);
1235			while ((sstat1 & BUSFREE) == 0)
1236				sstat1 = aic_inb(aic, SSTAT1);
1237			aic->flags |= AIC_BUSFREE_OK;
1238		}
1239	}
1240
1241	if ((sstat1 & BUSFREE) != 0) {
1242		aic_outb(aic, SCSISEQ, 0);
1243		aic_outb(aic, CLRSINT0, sstat0);
1244		aic_outb(aic, CLRSINT1, sstat1);
1245		if ((scb = aic->nexus)) {
1246			if ((aic->flags & AIC_BUSFREE_OK) == 0) {
1247				ccb = scb->ccb;
1248				ccb->ccb_h.status = CAM_UNEXP_BUSFREE;
1249				aic_done(aic, scb);
1250			} else if (scb->flags & SCB_DEVICE_RESET) {
1251				ccb = scb->ccb;
1252				if (ccb->ccb_h.func_code == XPT_RESET_DEV) {
1253					xpt_async(AC_SENT_BDR,
1254					    ccb->ccb_h.path, NULL);
1255					ccb->ccb_h.status |= CAM_REQ_CMP;
1256				} else
1257					ccb->ccb_h.status |= CAM_CMD_TIMEOUT;
1258				aic_done(aic, scb);
1259			} else if (scb->flags & SCB_SENSE) {
1260				/* autosense request */
1261				aic->flags &= ~AIC_BUSFREE_OK;
1262				aic->tinfo[scb->target].lubusy &=
1263				    ~(1 << scb->lun);
1264				aic_select(aic);
1265				aic_outb(aic, DMACNTRL0, INTEN);
1266				return;
1267			}
1268		}
1269		aic->flags &= ~AIC_BUSFREE_OK;
1270		aic->state = AIC_IDLE;
1271		aic_start(aic);
1272		aic_outb(aic, DMACNTRL0, INTEN);
1273		return;
1274	}
1275
1276	if ((sstat1 & REQINIT) != 0) {
1277		u_int8_t phase = aic_inb(aic, SCSISIGI) & PH_MASK;
1278		aic_outb(aic, SCSISIGO, phase);
1279		aic_outb(aic, CLRSINT1, CLRPHASECHG);
1280
1281		switch (phase) {
1282		case PH_MSGOUT:
1283			aic_msgout(aic);
1284			break;
1285		case PH_MSGIN:
1286			aic_msgin(aic);
1287			break;
1288		case PH_STAT:
1289			scb = aic->nexus;
1290			ccb = scb->ccb;
1291			aic_outb(aic, DMACNTRL0, 0);
1292			aic_outb(aic, SXFRCTL0, CHEN|SPIOEN);
1293			scb->status = aic_inb(aic, SCSIDAT);
1294			aic_outb(aic, SXFRCTL0, CHEN);
1295			break;
1296		case PH_CMD:
1297			aic_cmd(aic);
1298			break;
1299		case PH_DATAIN:
1300			aic_datain(aic);
1301			break;
1302		case PH_DATAOUT:
1303			aic_dataout(aic);
1304			break;
1305		}
1306		aic->prev_phase = phase;
1307		aic_outb(aic, DMACNTRL0, INTEN);
1308		return;
1309	}
1310
1311	printf("aic_intr: unexpected intr sstat0 %x sstat1 %x\n",
1312		sstat0, sstat1);
1313	aic_outb(aic, DMACNTRL0, INTEN);
1314}
1315
1316/*
1317 * Reset ourselves.
1318 */
1319static void
1320aic_chip_reset(struct aic_softc *aic)
1321{
1322	/*
1323	 * Doc. recommends to clear these two registers before
1324	 * operations commence
1325	 */
1326	aic_outb(aic, SCSITEST, 0);
1327	aic_outb(aic, TEST, 0);
1328
1329	/* Reset SCSI-FIFO and abort any transfers */
1330	aic_outb(aic, SXFRCTL0, CHEN|CLRCH|CLRSTCNT);
1331
1332	/* Reset HOST-FIFO */
1333	aic_outb(aic, DMACNTRL0, RSTFIFO);
1334	aic_outb(aic, DMACNTRL1, 0);
1335
1336	/* Disable all selection features */
1337	aic_outb(aic, SCSISEQ, 0);
1338	aic_outb(aic, SXFRCTL1, 0);
1339
1340	/* Disable interrupts */
1341	aic_outb(aic, SIMODE0, 0);
1342	aic_outb(aic, SIMODE1, 0);
1343
1344	/* Clear interrupts */
1345	aic_outb(aic, CLRSINT0, 0x7f);
1346	aic_outb(aic, CLRSINT1, 0xef);
1347
1348	/* Disable synchronous transfers */
1349	aic_outb(aic, SCSIRATE, 0);
1350
1351	/* Haven't seen ant errors (yet) */
1352	aic_outb(aic, CLRSERR, 0x07);
1353
1354	/* Set our SCSI-ID */
1355	aic_outb(aic, SCSIID, aic->initiator << OID_S);
1356	aic_outb(aic, BRSTCNTRL, EISA_BRST_TIM);
1357}
1358
1359/*
1360 * Reset the SCSI bus
1361 */
1362static void
1363aic_scsi_reset(struct aic_softc *aic)
1364{
1365	aic_outb(aic, SCSISEQ, SCSIRSTO);
1366	DELAY(500);
1367	aic_outb(aic, SCSISEQ, 0);
1368	DELAY(50);
1369}
1370
1371/*
1372 * Reset. Abort all pending commands.
1373 */
1374static void
1375aic_reset(struct aic_softc *aic, int initiate_reset)
1376{
1377	struct ccb_hdr *ccb_h;
1378
1379	CAM_DEBUG_PRINT(CAM_DEBUG_TRACE, ("aic_reset\n"));
1380
1381	if (initiate_reset)
1382		aic_scsi_reset(aic);
1383	aic_chip_reset(aic);
1384
1385	xpt_async(AC_BUS_RESET, aic->path, NULL);
1386
1387	while ((ccb_h = TAILQ_FIRST(&aic->pending_ccbs)) != NULL) {
1388		TAILQ_REMOVE(&aic->pending_ccbs, ccb_h, sim_links.tqe);
1389		ccb_h->status |= CAM_SCSI_BUS_RESET;
1390		aic_done(aic, (struct aic_scb *)ccb_h->ccb_scb_ptr);
1391	}
1392
1393	while ((ccb_h = TAILQ_FIRST(&aic->nexus_ccbs)) != NULL) {
1394		TAILQ_REMOVE(&aic->nexus_ccbs, ccb_h, sim_links.tqe);
1395		ccb_h->status |= CAM_SCSI_BUS_RESET;
1396		aic_done(aic, (struct aic_scb *)ccb_h->ccb_scb_ptr);
1397	}
1398
1399	if (aic->nexus) {
1400		ccb_h = &aic->nexus->ccb->ccb_h;
1401		ccb_h->status |= CAM_SCSI_BUS_RESET;
1402		aic_done(aic, aic->nexus);
1403	}
1404
1405	aic->state = AIC_IDLE;
1406	aic_outb(aic, DMACNTRL0, INTEN);
1407}
1408
1409static char *aic_chip_names[] = {
1410	"AIC6260", "AIC6360", "AIC6370", "GM82C700",
1411};
1412
1413static struct {
1414    	int type;
1415	char *idstring;
1416} aic_chip_ids[] = {
1417    	{ AIC6360, IDSTRING_AIC6360 },
1418	{ AIC6370, IDSTRING_AIC6370 },
1419	{ GM82C700, IDSTRING_GM82C700 },
1420};
1421
1422static void
1423aic_init(struct aic_softc *aic)
1424{
1425	struct aic_scb *scb;
1426	struct aic_tinfo *ti;
1427	u_int8_t porta, portb;
1428	char chip_id[33];
1429	int i;
1430
1431	TAILQ_INIT(&aic->pending_ccbs);
1432	TAILQ_INIT(&aic->nexus_ccbs);
1433	SLIST_INIT(&aic->free_scbs);
1434	aic->nexus = NULL;
1435	aic->state = AIC_IDLE;
1436	aic->prev_phase = -1;
1437	aic->flags = 0;
1438
1439	aic_chip_reset(aic);
1440	aic_scsi_reset(aic);
1441
1442	/* determine the chip type from its ID string */
1443	aic->chip_type = AIC6260;
1444	aic_insb(aic, ID, chip_id, sizeof(chip_id) - 1);
1445	chip_id[sizeof(chip_id) - 1] = '\0';
1446	for (i = 0; i < sizeof(aic_chip_ids) / sizeof(aic_chip_ids[0]); i++) {
1447		if (!strcmp(chip_id, aic_chip_ids[i].idstring)) {
1448			aic->chip_type = aic_chip_ids[i].type;
1449			break;
1450		}
1451	}
1452
1453	porta = aic_inb(aic, PORTA);
1454	portb = aic_inb(aic, PORTB);
1455
1456	aic->initiator = PORTA_ID(porta);
1457	if (PORTA_PARITY(porta))
1458		aic->flags |= AIC_PARITY_ENABLE;
1459	if (PORTB_DISC(portb))
1460		aic->flags |= AIC_DISC_ENABLE;
1461	if (PORTB_DMA(portb))
1462		aic->flags |= AIC_DMA_ENABLE;
1463
1464	/*
1465	 * We can do fast SCSI (10MHz clock rate) if bit 4 of portb
1466	 * is set and we've got a 6360.  The 6260 can only do standard
1467	 * 5MHz SCSI.
1468	 */
1469	if (aic->chip_type > AIC6260 || aic_inb(aic, REV)) {
1470		if (PORTB_FSYNC(portb))
1471			aic->flags |= AIC_FAST_ENABLE;
1472		aic->flags |= AIC_DWIO_ENABLE;
1473	}
1474
1475	if (aic->flags & AIC_FAST_ENABLE)
1476		aic->max_period = AIC_FAST_SYNC_PERIOD;
1477    	else
1478		aic->max_period = AIC_SYNC_PERIOD;
1479	aic->min_period = AIC_MIN_SYNC_PERIOD;
1480
1481	for (i = 255; i >= 0; i--) {
1482		scb = &aic->scbs[i];
1483		scb->tag = i;
1484		callout_init_mtx(&scb->timer, &aic->lock, 0);
1485		aic_free_scb(aic, scb);
1486	}
1487
1488	for (i = 0; i < 8; i++) {
1489		if (i == aic->initiator)
1490			continue;
1491		ti = &aic->tinfo[i];
1492		bzero(ti, sizeof(*ti));
1493		ti->flags = TINFO_TAG_ENB;
1494		if (aic->flags & AIC_DISC_ENABLE)
1495			ti->flags |= TINFO_DISC_ENB;
1496		ti->user.period = aic->max_period;
1497		ti->user.offset = AIC_SYNC_OFFSET;
1498		ti->scsirate = 0;
1499	}
1500
1501	aic_outb(aic, DMACNTRL0, INTEN);
1502}
1503
1504int
1505aic_probe(struct aic_softc *aic)
1506{
1507	int i;
1508
1509	/* Remove aic6360 from possible powerdown mode */
1510	aic_outb(aic, DMACNTRL0, 0);
1511
1512#define	STSIZE	16
1513	aic_outb(aic, DMACNTRL1, 0);	/* Reset stack pointer */
1514	for (i = 0; i < STSIZE; i++)
1515		aic_outb(aic, STACK, i);
1516
1517	/* See if we can pull out the same sequence */
1518	aic_outb(aic, DMACNTRL1, 0);
1519	for (i = 0; i < STSIZE && aic_inb(aic, STACK) == i; i++)
1520		;
1521	if (i != STSIZE)
1522		return (ENXIO);
1523#undef	STSIZE
1524	return (0);
1525}
1526
1527int
1528aic_attach(struct aic_softc *aic)
1529{
1530	struct cam_devq *devq;
1531
1532	/*
1533	 * Create the device queue for our SIM.
1534	 */
1535	devq = cam_simq_alloc(256);
1536	if (devq == NULL)
1537		return (ENOMEM);
1538
1539	/*
1540	 * Construct our SIM entry
1541	 */
1542	aic->sim = cam_sim_alloc(aic_action, aic_poll, "aic", aic,
1543	    device_get_unit(aic->dev), &aic->lock, 2, 256, devq);
1544	if (aic->sim == NULL) {
1545		cam_simq_free(devq);
1546		return (ENOMEM);
1547	}
1548
1549	mtx_lock(&aic->lock);
1550	if (xpt_bus_register(aic->sim, aic->dev, 0) != CAM_SUCCESS) {
1551		cam_sim_free(aic->sim, /*free_devq*/TRUE);
1552		mtx_unlock(&aic->lock);
1553		return (ENXIO);
1554	}
1555
1556	if (xpt_create_path(&aic->path, /*periph*/NULL,
1557			    cam_sim_path(aic->sim), CAM_TARGET_WILDCARD,
1558			    CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
1559		xpt_bus_deregister(cam_sim_path(aic->sim));
1560		cam_sim_free(aic->sim, /*free_devq*/TRUE);
1561		mtx_unlock(&aic->lock);
1562		return (ENXIO);
1563	}
1564
1565	aic_init(aic);
1566
1567	device_printf(aic->dev, "%s", aic_chip_names[aic->chip_type]);
1568	if (aic->flags & AIC_DMA_ENABLE)
1569		printf(", dma");
1570	if (aic->flags & AIC_DISC_ENABLE)
1571		printf(", disconnection");
1572	if (aic->flags & AIC_PARITY_ENABLE)
1573		printf(", parity check");
1574	if (aic->flags & AIC_FAST_ENABLE)
1575		printf(", fast SCSI");
1576	printf("\n");
1577	mtx_unlock(&aic->lock);
1578	return (0);
1579}
1580
1581int
1582aic_detach(struct aic_softc *aic)
1583{
1584	struct aic_scb *scb;
1585	int i;
1586
1587	mtx_lock(&aic->lock);
1588	xpt_async(AC_LOST_DEVICE, aic->path, NULL);
1589	xpt_free_path(aic->path);
1590	xpt_bus_deregister(cam_sim_path(aic->sim));
1591	cam_sim_free(aic->sim, /*free_devq*/TRUE);
1592	mtx_unlock(&aic->lock);
1593	for (i = 255; i >= 0; i--) {
1594		scb = &aic->scbs[i];
1595		callout_drain(&scb->timer);
1596	}
1597	return (0);
1598}
1599