Sync with FreeBSD:
[dragonfly.git] / sys / dev / disk / aic / aic.c
blob2b91e04bed36e1318e6a1098b829b29f5907f0b8
1 /*-
2 * Copyright (c) 1999 Luoqi Chen.
3 * All rights reserved.
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.
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.
26 * $FreeBSD: src/sys/dev/aic/aic.c,v 1.8 2000/01/14 23:42:35 imp Exp $
27 * $DragonFly: src/sys/dev/disk/aic/aic.c,v 1.12 2008/01/05 07:27:09 pavalos Exp $
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/kernel.h>
33 #include <sys/bus.h>
34 #include <sys/thread2.h>
36 #include <bus/cam/cam.h>
37 #include <bus/cam/cam_ccb.h>
38 #include <bus/cam/cam_sim.h>
39 #include <bus/cam/cam_xpt_sim.h>
40 #include <bus/cam/cam_debug.h>
42 #include <bus/cam/scsi/scsi_message.h>
44 #include "aic6360reg.h"
45 #include "aicvar.h"
47 static void aic_action (struct cam_sim *sim, union ccb *ccb);
48 static void aic_execute_scb (void *arg, bus_dma_segment_t *dm_segs,
49 int nseg, int error);
50 static void aic_start (struct aic_softc *aic);
51 static void aic_select (struct aic_softc *aic);
52 static void aic_selected (struct aic_softc *aic);
53 static void aic_reselected (struct aic_softc *aic);
54 static void aic_reconnect (struct aic_softc *aic, int tag);
55 static void aic_cmd (struct aic_softc *aic);
56 static void aic_msgin (struct aic_softc *aic);
57 static void aic_handle_msgin (struct aic_softc *aic);
58 static void aic_msgout (struct aic_softc *aic);
59 static void aic_datain (struct aic_softc *aic);
60 static void aic_dataout (struct aic_softc *aic);
61 static void aic_done (struct aic_softc *aic, struct aic_scb *scb);
62 static void aic_poll (struct cam_sim *sim);
63 static void aic_timeout (void *arg);
64 static void aic_scsi_reset (struct aic_softc *aic);
65 static void aic_chip_reset (struct aic_softc *aic);
66 static void aic_reset (struct aic_softc *aic, int initiate_reset);
68 devclass_t aic_devclass;
70 static struct aic_scb *free_scbs;
72 static struct aic_scb *
73 aic_get_scb(struct aic_softc *aic)
75 struct aic_scb *scb;
77 crit_enter();
79 if ((scb = free_scbs) != NULL)
80 free_scbs = (struct aic_scb *)free_scbs->ccb;
82 crit_exit();
83 return (scb);
86 static void
87 aic_free_scb(struct aic_softc *aic, struct aic_scb *scb)
89 crit_enter();
91 if ((aic->flags & AIC_RESOURCE_SHORTAGE) != 0 &&
92 (scb->ccb->ccb_h.status & CAM_RELEASE_SIMQ) == 0) {
93 scb->ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
94 aic->flags &= ~AIC_RESOURCE_SHORTAGE;
96 scb->flags = 0;
97 scb->ccb = (union ccb *)free_scbs;
98 free_scbs = scb;
100 crit_exit();
103 static void
104 aic_action(struct cam_sim *sim, union ccb *ccb)
106 struct aic_softc *aic;
108 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("aic_action\n"));
110 aic = (struct aic_softc *)cam_sim_softc(sim);
112 switch (ccb->ccb_h.func_code) {
113 case XPT_SCSI_IO: /* Execute the requested I/O operation */
114 case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */
116 struct aic_scb *scb;
118 if ((scb = aic_get_scb(aic)) == NULL) {
119 crit_enter();
120 aic->flags |= AIC_RESOURCE_SHORTAGE;
121 crit_exit();
122 xpt_freeze_simq(aic->sim, /*count*/1);
123 ccb->ccb_h.status = CAM_REQUEUE_REQ;
124 xpt_done(ccb);
125 return;
128 scb->ccb = ccb;
129 ccb->ccb_h.ccb_scb_ptr = scb;
130 ccb->ccb_h.ccb_aic_ptr = aic;
132 scb->target = ccb->ccb_h.target_id;
133 scb->lun = ccb->ccb_h.target_lun;
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;
144 scb->cmd_ptr = ccb->csio.cdb_io.cdb_ptr;
145 } else {
146 scb->cmd_ptr = ccb->csio.cdb_io.cdb_bytes;
148 if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
149 if ((ccb->ccb_h.flags & CAM_SCATTER_VALID) ||
150 (ccb->ccb_h.flags & CAM_DATA_PHYS)) {
151 ccb->ccb_h.status = CAM_REQ_INVALID;
152 aic_free_scb(aic, scb);
153 xpt_done(ccb);
154 return;
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;
162 aic_execute_scb(scb, NULL, 0, 0);
163 } else {
164 scb->flags |= SCB_DEVICE_RESET;
165 aic_execute_scb(scb, NULL, 0, 0);
167 break;
169 case XPT_SET_TRAN_SETTINGS:
171 struct ccb_trans_settings *cts = cts = &ccb->cts;
172 struct aic_tinfo *ti = &aic->tinfo[ccb->ccb_h.target_id];
173 #ifdef CAM_NEW_TRAN_CODE
174 struct ccb_trans_settings_scsi *scsi =
175 &cts->proto_specific.scsi;
176 struct ccb_trans_settings_spi *spi =
177 &cts->xport_specific.spi;
179 crit_enter();
181 if ((spi->valid & CTS_SPI_VALID_DISC) != 0 &&
182 (aic->flags & AIC_DISC_ENABLE) != 0) {
183 if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) != 0)
184 ti->flags |= TINFO_DISC_ENB;
185 else
186 ti->flags &= ~TINFO_DISC_ENB;
189 if ((scsi->valid & CTS_SCSI_VALID_TQ) != 0) {
190 if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0)
191 ti->flags |= TINFO_TAG_ENB;
192 else
193 ti->flags &= ~TINFO_TAG_ENB;
196 if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
197 ti->goal.period = spi->sync_period;
199 if (ti->goal.period > aic->min_period) {
200 ti->goal.period = 0;
201 ti->goal.offset = 0;
202 } else if (ti->goal.period < aic->max_period)
203 ti->goal.period = aic->max_period;
206 if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0) {
207 ti->goal.offset = spi->sync_offset;
208 if (ti->goal.offset == 0)
209 ti->goal.period = 0;
210 else if (ti->goal.offset > AIC_SYNC_OFFSET)
211 ti->goal.offset = AIC_SYNC_OFFSET;
214 if ((ti->goal.period != ti->current.period)
215 || (ti->goal.offset != ti->current.offset))
216 ti->flags |= TINFO_SDTR_NEGO;
218 crit_exit();
219 #else
220 crit_enter();
221 if ((cts->valid & CCB_TRANS_DISC_VALID) != 0 &&
222 (aic->flags & AIC_DISC_ENABLE) != 0) {
223 if ((cts->flags & CCB_TRANS_DISC_ENB) != 0)
224 ti->flags |= TINFO_DISC_ENB;
225 else
226 ti->flags &= ~TINFO_DISC_ENB;
229 if ((cts->valid & CCB_TRANS_TQ_VALID) != 0) {
230 if ((cts->flags & CCB_TRANS_TAG_ENB) != 0)
231 ti->flags |= TINFO_TAG_ENB;
232 else
233 ti->flags &= ~TINFO_TAG_ENB;
236 if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) != 0) {
237 ti->goal.period = cts->sync_period;
238 if (ti->goal.period != ti->current.period)
239 ti->flags |= TINFO_SDTR_NEGO;
242 if ((cts->valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0) {
243 ti->goal.offset = cts->sync_offset;
244 if (ti->goal.offset != ti->current.offset)
245 ti->flags |= TINFO_SDTR_NEGO;
248 crit_exit();
249 #endif
250 ccb->ccb_h.status = CAM_REQ_CMP;
251 xpt_done(ccb);
252 break;
254 case XPT_GET_TRAN_SETTINGS:
256 struct ccb_trans_settings *cts = &ccb->cts;
257 struct aic_tinfo *ti = &aic->tinfo[ccb->ccb_h.target_id];
258 #ifdef CAM_NEW_TRAN_CODE
259 struct ccb_trans_settings_scsi *scsi =
260 &cts->proto_specific.scsi;
261 struct ccb_trans_settings_spi *spi =
262 &cts->xport_specific.spi;
264 cts->protocol = PROTO_SCSI;
265 cts->protocol_version = SCSI_REV_2;
266 cts->transport = XPORT_SPI;
267 cts->transport_version = 2;
268 scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
269 spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
271 crit_enter();
272 if ((ti->flags & TINFO_DISC_ENB) != 0)
273 spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
274 if ((ti->flags & TINFO_TAG_ENB) != 0)
275 scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
277 if (cts->type == CTS_TYPE_CURRENT_SETTINGS) {
278 spi->sync_period = ti->current.period;
279 spi->sync_offset = ti->current.offset;
280 } else {
281 spi->sync_period = ti->user.period;
282 spi->sync_offset = ti->user.offset;
284 crit_exit();
286 spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
287 spi->valid = CTS_SPI_VALID_SYNC_RATE
288 | CTS_SPI_VALID_SYNC_OFFSET
289 | CTS_SPI_VALID_BUS_WIDTH
290 | CTS_SPI_VALID_DISC;
291 scsi->valid = CTS_SCSI_VALID_TQ;
292 #else
293 crit_enter();
294 cts->flags &= ~(CCB_TRANS_DISC_ENB|CCB_TRANS_TAG_ENB);
295 if ((ti->flags & TINFO_DISC_ENB) != 0)
296 cts->flags |= CCB_TRANS_DISC_ENB;
297 if ((ti->flags & TINFO_TAG_ENB) != 0)
298 cts->flags |= CCB_TRANS_TAG_ENB;
300 if ((cts->flags & CCB_TRANS_CURRENT_SETTINGS) != 0) {
301 cts->sync_period = ti->current.period;
302 cts->sync_offset = ti->current.offset;
303 } else {
304 cts->sync_period = ti->user.period;
305 cts->sync_offset = ti->user.offset;
307 cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
309 crit_exit();
311 cts->valid = CCB_TRANS_SYNC_RATE_VALID
312 | CCB_TRANS_SYNC_OFFSET_VALID
313 | CCB_TRANS_BUS_WIDTH_VALID
314 | CCB_TRANS_DISC_VALID
315 | CCB_TRANS_TQ_VALID;
316 #endif
318 ccb->ccb_h.status = CAM_REQ_CMP;
319 xpt_done(ccb);
320 break;
322 case XPT_CALC_GEOMETRY:
324 cam_calc_geometry(&ccb->ccg, /*extended*/1);
325 xpt_done(ccb);
326 break;
328 case XPT_RESET_BUS: /* Reset the specified SCSI bus */
329 aic_reset(aic, /*initiate_reset*/TRUE);
330 ccb->ccb_h.status = CAM_REQ_CMP;
331 xpt_done(ccb);
332 break;
333 case XPT_PATH_INQ: /* Path routing inquiry */
335 struct ccb_pathinq *cpi = &ccb->cpi;
337 cpi->version_num = 1; /* XXX??? */
338 cpi->hba_inquiry = PI_SDTR_ABLE | PI_TAG_ABLE;
339 cpi->target_sprt = 0;
340 cpi->hba_misc = 0;
341 cpi->hba_eng_cnt = 0;
342 cpi->max_target = 7;
343 cpi->max_lun = 7;
344 cpi->initiator_id = aic->initiator;
345 cpi->bus_id = cam_sim_bus(sim);
346 cpi->base_transfer_speed = 3300;
347 strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
348 strncpy(cpi->hba_vid, "Adaptec", HBA_IDLEN);
349 strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
350 cpi->unit_number = cam_sim_unit(sim);
351 #ifdef CAM_NEW_TRAN_CODE
352 cpi->transport = XPORT_SPI;
353 cpi->transport_version = 2;
354 cpi->protocol = PROTO_SCSI;
355 cpi->protocol_version = SCSI_REV_2;
356 #endif
357 cpi->ccb_h.status = CAM_REQ_CMP;
358 xpt_done(ccb);
359 break;
361 default:
362 ccb->ccb_h.status = CAM_REQ_INVALID;
363 xpt_done(ccb);
364 break;
368 static void
369 aic_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
371 struct aic_scb *scb = (struct aic_scb *)arg;
372 union ccb *ccb = scb->ccb;
373 struct aic_softc *aic = (struct aic_softc *)ccb->ccb_h.ccb_aic_ptr;
375 crit_enter();
377 if (ccb->ccb_h.status != CAM_REQ_INPROG) {
378 crit_exit();
379 aic_free_scb(aic, scb);
380 xpt_done(ccb);
381 return;
384 scb->flags |= SCB_ACTIVE;
385 ccb->ccb_h.status |= CAM_SIM_QUEUED;
386 TAILQ_INSERT_TAIL(&aic->pending_ccbs, &ccb->ccb_h, sim_links.tqe);
388 callout_reset(&ccb->ccb_h.timeout_ch, (ccb->ccb_h.timeout * hz) / 1000,
389 aic_timeout, scb);
391 aic_start(aic);
392 crit_exit();
396 * Start another command if the controller is not busy.
398 static void
399 aic_start(struct aic_softc *aic)
401 struct ccb_hdr *ccb_h;
402 struct aic_tinfo *ti;
404 if (aic->state != AIC_IDLE)
405 return;
407 TAILQ_FOREACH(ccb_h, &aic->pending_ccbs, sim_links.tqe) {
408 ti = &aic->tinfo[ccb_h->target_id];
409 if ((ti->lubusy & (1 << ccb_h->target_lun)) == 0) {
410 TAILQ_REMOVE(&aic->pending_ccbs, ccb_h, sim_links.tqe);
411 aic->nexus = (struct aic_scb *)ccb_h->ccb_scb_ptr;
412 aic_select(aic);
413 return;
417 CAM_DEBUG_PRINT(CAM_DEBUG_TRACE, ("aic_start: idle\n"));
419 aic_outb(aic, SIMODE0, ENSELDI);
420 aic_outb(aic, SIMODE1, ENSCSIRST);
421 aic_outb(aic, SCSISEQ, ENRESELI);
425 * Start a selection.
427 static void
428 aic_select(struct aic_softc *aic)
430 struct aic_scb *scb = aic->nexus;
432 CAM_DEBUG(scb->ccb->ccb_h.path, CAM_DEBUG_TRACE,
433 ("aic_select - ccb %p\n", scb->ccb));
435 aic->state = AIC_SELECTING;
437 aic_outb(aic, DMACNTRL1, 0);
438 aic_outb(aic, SCSIID, aic->initiator << OID_S | scb->target);
439 aic_outb(aic, SXFRCTL1, STIMO_256ms | ENSTIMER |
440 (aic->flags & AIC_PARITY_ENABLE ? ENSPCHK : 0));
442 aic_outb(aic, SIMODE0, ENSELDI|ENSELDO);
443 aic_outb(aic, SIMODE1, ENSCSIRST|ENSELTIMO);
444 aic_outb(aic, SCSISEQ, ENRESELI|ENSELO|ENAUTOATNO);
448 * We have successfully selected a target, prepare for the information
449 * transfer phases.
451 static void
452 aic_selected(struct aic_softc *aic)
454 struct aic_scb *scb = aic->nexus;
455 union ccb *ccb = scb->ccb;
456 struct aic_tinfo *ti = &aic->tinfo[scb->target];
458 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
459 ("aic_selected - ccb %p\n", ccb));
461 aic->state = AIC_HASNEXUS;
463 if (scb->flags & SCB_DEVICE_RESET) {
464 aic->msg_buf[0] = MSG_BUS_DEV_RESET;
465 aic->msg_len = 1;
466 aic->msg_outq = AIC_MSG_MSGBUF;
467 } else {
468 aic->msg_outq = AIC_MSG_IDENTIFY;
469 if ((ti->flags & TINFO_TAG_ENB) != 0 &&
470 (ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) != 0)
471 aic->msg_outq |= AIC_MSG_TAG_Q;
472 else
473 ti->lubusy |= 1 << scb->lun;
474 if ((ti->flags & TINFO_SDTR_NEGO) != 0)
475 aic->msg_outq |= AIC_MSG_SDTR;
478 aic_outb(aic, CLRSINT0, CLRSELDO);
479 aic_outb(aic, CLRSINT1, CLRBUSFREE);
480 aic_outb(aic, SCSISEQ, ENAUTOATNP);
481 aic_outb(aic, SIMODE0, 0);
482 aic_outb(aic, SIMODE1, ENSCSIRST|ENBUSFREE|ENREQINIT);
483 aic_outb(aic, SCSIRATE, ti->scsirate);
487 * We are re-selected by a target, save the target id and wait for the
488 * target to further identify itself.
490 static void
491 aic_reselected(struct aic_softc *aic)
493 u_int8_t selid;
495 CAM_DEBUG_PRINT(CAM_DEBUG_TRACE, ("aic_reselected\n"));
498 * If we have started a selection, it must have lost out in
499 * the arbitration, put the command back to the pending queue.
501 if (aic->nexus) {
502 TAILQ_INSERT_HEAD(&aic->pending_ccbs,
503 &aic->nexus->ccb->ccb_h, sim_links.tqe);
504 aic->nexus = NULL;
507 selid = aic_inb(aic, SELID) & ~(1 << aic->initiator);
508 if (selid & (selid - 1)) {
509 /* this should never have happened */
510 kprintf("aic_reselected: invalid selid %x\n", selid);
511 aic_reset(aic, /*initiate_reset*/TRUE);
512 return;
515 aic->state = AIC_RESELECTED;
516 aic->target = ffs(selid) - 1;
517 aic->lun = -1;
519 aic_outb(aic, CLRSINT0, CLRSELDI);
520 aic_outb(aic, CLRSINT1, CLRBUSFREE);
521 aic_outb(aic, SIMODE0, 0);
522 aic_outb(aic, SIMODE1, ENSCSIRST|ENBUSFREE|ENREQINIT);
523 aic_outb(aic, SCSISEQ, ENAUTOATNP);
524 aic_outb(aic, SCSIRATE, aic->tinfo[aic->target].scsirate);
528 * Raise ATNO to signal the target that we have a message for it.
530 static __inline void
531 aic_sched_msgout(struct aic_softc *aic, u_int8_t msg)
533 if (msg) {
534 aic->msg_buf[0] = msg;
535 aic->msg_len = 1;
537 aic->msg_outq |= AIC_MSG_MSGBUF;
538 aic_outb(aic, SCSISIGO, aic_inb(aic, SCSISIGI) | ATNO);
542 * Wait for SPIORDY (SCSI PIO ready) flag, or a phase change.
544 static __inline int
545 aic_spiordy(struct aic_softc *aic)
547 while (!(aic_inb(aic, DMASTAT) & INTSTAT) &&
548 !(aic_inb(aic, SSTAT0) & SPIORDY))
550 return !(aic_inb(aic, DMASTAT) & INTSTAT);
554 * Reestablish a disconnected nexus.
556 static void
557 aic_reconnect(struct aic_softc *aic, int tag)
559 struct aic_scb *scb;
560 struct ccb_hdr *ccb_h;
562 CAM_DEBUG_PRINT(CAM_DEBUG_TRACE, ("aic_reconnect\n"));
564 /* Find the nexus */
565 scb = NULL;
566 TAILQ_FOREACH(ccb_h, &aic->nexus_ccbs, sim_links.tqe) {
567 scb = (struct aic_scb *)ccb_h->ccb_scb_ptr;
568 if (scb->target == aic->target && scb->lun == aic->lun &&
569 (tag == -1 || scb->tag == tag))
570 break;
573 /* ABORT if nothing is found */
574 if (!ccb_h) {
575 if (tag == -1)
576 aic_sched_msgout(aic, MSG_ABORT);
577 else
578 aic_sched_msgout(aic, MSG_ABORT_TAG);
579 xpt_async(AC_UNSOL_RESEL, aic->path, NULL);
580 return;
583 /* Reestablish the nexus */
584 TAILQ_REMOVE(&aic->nexus_ccbs, ccb_h, sim_links.tqe);
585 aic->nexus = scb;
586 scb->flags &= ~SCB_DISCONNECTED;
587 aic->state = AIC_HASNEXUS;
591 * Read messages.
593 static void
594 aic_msgin(struct aic_softc *aic)
596 int msglen;
598 CAM_DEBUG_PRINT(CAM_DEBUG_TRACE, ("aic_msgin\n"));
600 aic_outb(aic, SIMODE1, ENSCSIRST|ENPHASEMIS|ENBUSFREE);
601 aic_outb(aic, SXFRCTL0, CHEN|SPIOEN);
603 aic->flags &= ~AIC_DROP_MSGIN;
604 aic->msg_len = 0;
605 do {
607 * If a parity error is detected, drop the remaining
608 * bytes and inform the target so it could resend
609 * the messages.
611 if (aic_inb(aic, SSTAT1) & SCSIPERR) {
612 aic_outb(aic, CLRSINT1, CLRSCSIPERR);
613 aic->flags |= AIC_DROP_MSGIN;
614 aic_sched_msgout(aic, MSG_PARITY_ERROR);
616 if ((aic->flags & AIC_DROP_MSGIN)) {
617 aic_inb(aic, SCSIDAT);
618 continue;
620 /* read the message byte without ACKing on it */
621 aic->msg_buf[aic->msg_len++] = aic_inb(aic, SCSIBUS);
622 if (aic->msg_buf[0] == MSG_EXTENDED) {
623 if (aic->msg_len < 2) {
624 (void) aic_inb(aic, SCSIDAT);
625 continue;
627 switch (aic->msg_buf[2]) {
628 case MSG_EXT_SDTR:
629 msglen = MSG_EXT_SDTR_LEN;
630 break;
631 case MSG_EXT_WDTR:
632 msglen = MSG_EXT_WDTR_LEN;
633 break;
634 default:
635 msglen = 0;
636 break;
638 if (aic->msg_buf[1] != msglen) {
639 aic->flags |= AIC_DROP_MSGIN;
640 aic_sched_msgout(aic, MSG_MESSAGE_REJECT);
642 msglen += 2;
643 } else if (aic->msg_buf[0] >= 0x20 && aic->msg_buf[0] <= 0x2f)
644 msglen = 2;
645 else
646 msglen = 1;
648 * If we have a complete message, handle it before the final
649 * ACK (in case we decide to reject the message).
651 if (aic->msg_len == msglen) {
652 aic_handle_msgin(aic);
653 aic->msg_len = 0;
655 /* ACK on the message byte */
656 (void) aic_inb(aic, SCSIDAT);
657 } while (aic_spiordy(aic));
659 aic_outb(aic, SXFRCTL0, CHEN);
660 aic_outb(aic, SIMODE1, ENSCSIRST|ENBUSFREE|ENREQINIT);
664 * Handle a message.
666 static void
667 aic_handle_msgin(struct aic_softc *aic)
669 struct aic_scb *scb;
670 struct ccb_hdr *ccb_h;
671 struct aic_tinfo *ti;
672 struct ccb_trans_settings neg;
673 #ifdef CAM_NEW_TRAN_CODE
674 struct ccb_trans_settings_spi *spi = &neg.xport_specific.spi;
675 #endif
677 if (aic->state == AIC_RESELECTED) {
678 if (!MSG_ISIDENTIFY(aic->msg_buf[0])) {
679 aic_sched_msgout(aic, MSG_MESSAGE_REJECT);
680 return;
682 aic->lun = aic->msg_buf[0] & MSG_IDENTIFY_LUNMASK;
683 if (aic->tinfo[aic->target].lubusy & (1 << aic->lun))
684 aic_reconnect(aic, -1);
685 else
686 aic->state = AIC_RECONNECTING;
687 return;
690 if (aic->state == AIC_RECONNECTING) {
691 if (aic->msg_buf[0] != MSG_SIMPLE_Q_TAG) {
692 aic_sched_msgout(aic, MSG_MESSAGE_REJECT);
693 return;
695 aic_reconnect(aic, aic->msg_buf[1]);
696 return;
699 switch (aic->msg_buf[0]) {
700 case MSG_CMDCOMPLETE: {
701 struct ccb_scsiio *csio;
702 scb = aic->nexus;
703 ccb_h = &scb->ccb->ccb_h;
704 csio = &scb->ccb->csio;
705 if ((scb->flags & SCB_SENSE) != 0) {
706 /* auto REQUEST SENSE command */
707 scb->flags &= ~SCB_SENSE;
708 csio->sense_resid = scb->data_len;
709 if (scb->status == SCSI_STATUS_OK) {
710 ccb_h->status |=
711 CAM_SCSI_STATUS_ERROR|CAM_AUTOSNS_VALID;
712 /*scsi_sense_print(csio);*/
713 } else {
714 ccb_h->status |= CAM_AUTOSENSE_FAIL;
715 kprintf("ccb %p sense failed %x\n",
716 ccb_h, scb->status);
718 } else {
719 csio->scsi_status = scb->status;
720 csio->resid = scb->data_len;
721 if (scb->status == SCSI_STATUS_OK) {
722 /* everything goes well */
723 ccb_h->status |= CAM_REQ_CMP;
724 } else if ((ccb_h->flags & CAM_DIS_AUTOSENSE) == 0 &&
725 (csio->scsi_status == SCSI_STATUS_CHECK_COND ||
726 csio->scsi_status == SCSI_STATUS_CMD_TERMINATED)) {
727 /* try to retrieve sense information */
728 scb->flags |= SCB_SENSE;
729 aic->flags |= AIC_BUSFREE_OK;
730 return;
731 } else
732 ccb_h->status |= CAM_SCSI_STATUS_ERROR;
734 aic_done(aic, scb);
735 aic->flags |= AIC_BUSFREE_OK;
736 break;
738 case MSG_EXTENDED:
739 switch (aic->msg_buf[2]) {
740 case MSG_EXT_SDTR:
741 scb = aic->nexus;
742 ti = &aic->tinfo[scb->target];
743 if (ti->flags & TINFO_SDTR_SENT) {
744 ti->current.period = aic->msg_buf[3];
745 ti->current.offset = aic->msg_buf[4];
746 } else {
747 ti->current.period = aic->msg_buf[3] =
748 max(ti->goal.period, aic->msg_buf[3]);
749 ti->current.offset = aic->msg_buf[4] =
750 min(ti->goal.offset, aic->msg_buf[4]);
752 * The target initiated the negotiation,
753 * send back a response.
755 aic_sched_msgout(aic, 0);
757 ti->flags &= ~(TINFO_SDTR_SENT|TINFO_SDTR_NEGO);
758 ti->scsirate = ti->current.offset ? ti->current.offset |
759 ((ti->current.period * 4 + 49) / 50 - 2) << 4 : 0;
760 aic_outb(aic, SCSIRATE, ti->scsirate);
761 memset(&neg, 0, sizeof (neg));
762 #ifdef CAM_NEW_TRAN_CODE
763 neg.protocol = PROTO_SCSI;
764 neg.protocol_version = SCSI_REV_2;
765 neg.transport = XPORT_SPI;
766 neg.transport_version = 2;
767 spi->sync_period = ti->goal.period = ti->current.period;
768 spi->sync_offset = ti->goal.offset = ti->current.offset;
769 spi->valid = CTS_SPI_VALID_SYNC_RATE
770 | CTS_SPI_VALID_SYNC_OFFSET;
771 #else
772 neg.sync_period = ti->goal.period = ti->current.period;
773 neg.sync_offset = ti->goal.offset = ti->current.offset;
774 neg.valid = CCB_TRANS_SYNC_RATE_VALID
775 | CCB_TRANS_SYNC_OFFSET_VALID;
776 #endif
777 ccb_h = &scb->ccb->ccb_h;
778 xpt_setup_ccb(&neg.ccb_h, ccb_h->path, 1);
779 xpt_async(AC_TRANSFER_NEG, ccb_h->path, &neg);
780 break;
781 case MSG_EXT_WDTR:
782 default:
783 aic_sched_msgout(aic, MSG_MESSAGE_REJECT);
784 break;
786 break;
787 case MSG_DISCONNECT:
788 scb = aic->nexus;
789 ccb_h = &scb->ccb->ccb_h;
790 TAILQ_INSERT_TAIL(&aic->nexus_ccbs, ccb_h, sim_links.tqe);
791 scb->flags |= SCB_DISCONNECTED;
792 aic->flags |= AIC_BUSFREE_OK;
793 aic->nexus = NULL;
794 CAM_DEBUG(ccb_h->path, CAM_DEBUG_TRACE, ("disconnected\n"));
795 break;
796 case MSG_MESSAGE_REJECT:
797 switch (aic->msg_outq & -aic->msg_outq) {
798 case AIC_MSG_TAG_Q:
799 scb = aic->nexus;
800 ti = &aic->tinfo[scb->target];
801 ti->flags &= ~TINFO_TAG_ENB;
802 ti->lubusy |= 1 << scb->lun;
803 break;
804 case AIC_MSG_SDTR:
805 scb = aic->nexus;
806 ti = &aic->tinfo[scb->target];
807 ti->current.period = ti->goal.period = 0;
808 ti->current.offset = ti->goal.offset = 0;
809 ti->flags &= ~(TINFO_SDTR_SENT|TINFO_SDTR_NEGO);
810 ti->scsirate = 0;
811 aic_outb(aic, SCSIRATE, ti->scsirate);
812 memset(&neg, 0, sizeof (neg));
813 #ifdef CAM_NEW_TRAN_CODE
814 neg.protocol = PROTO_SCSI;
815 neg.protocol_version = SCSI_REV_2;
816 neg.transport = XPORT_SPI;
817 neg.transport_version = 2;
818 spi->sync_period = ti->current.period;
819 spi->sync_offset = ti->current.offset;
820 spi->valid = CTS_SPI_VALID_SYNC_RATE
821 | CTS_SPI_VALID_SYNC_OFFSET;
822 #else
823 neg.sync_period = ti->current.period;
824 neg.sync_offset = ti->current.offset;
825 neg.valid = CCB_TRANS_SYNC_RATE_VALID
826 | CCB_TRANS_SYNC_OFFSET_VALID;
827 #endif
828 ccb_h = &scb->ccb->ccb_h;
829 xpt_setup_ccb(&neg.ccb_h, ccb_h->path, 1);
830 xpt_async(AC_TRANSFER_NEG, ccb_h->path, &neg);
831 break;
832 default:
833 break;
835 break;
836 case MSG_SAVEDATAPOINTER:
837 break;
838 case MSG_RESTOREPOINTERS:
839 break;
840 case MSG_NOOP:
841 break;
842 default:
843 aic_sched_msgout(aic, MSG_MESSAGE_REJECT);
844 break;
849 * Send messages.
851 static void
852 aic_msgout(struct aic_softc *aic)
854 struct aic_scb *scb;
855 union ccb *ccb;
856 struct aic_tinfo *ti;
857 int msgidx = 0;
859 CAM_DEBUG_PRINT(CAM_DEBUG_TRACE, ("aic_msgout\n"));
861 aic_outb(aic, SIMODE1, ENSCSIRST|ENPHASEMIS|ENBUSFREE);
862 aic_outb(aic, SXFRCTL0, CHEN|SPIOEN);
865 * If the previous phase is also the message out phase,
866 * we need to retransmit all the messages, probably
867 * because the target has detected a parity error during
868 * the past transmission.
870 if (aic->prev_phase == PH_MSGOUT)
871 aic->msg_outq = aic->msg_sent;
873 do {
874 int q = aic->msg_outq;
875 if (msgidx > 0 && msgidx == aic->msg_len) {
876 /* complete message sent, start the next one */
877 q &= -q;
878 aic->msg_sent |= q;
879 aic->msg_outq ^= q;
880 q = aic->msg_outq;
881 msgidx = 0;
883 if (msgidx == 0) {
884 /* setup the message */
885 switch (q & -q) {
886 case AIC_MSG_IDENTIFY:
887 scb = aic->nexus;
888 ccb = scb->ccb;
889 ti = &aic->tinfo[scb->target];
890 aic->msg_buf[0] = MSG_IDENTIFY(scb->lun,
891 (ti->flags & TINFO_DISC_ENB) &&
892 !(ccb->ccb_h.flags & CAM_DIS_DISCONNECT));
893 aic->msg_len = 1;
894 break;
895 case AIC_MSG_TAG_Q:
896 scb = aic->nexus;
897 ccb = scb->ccb;
898 aic->msg_buf[0] = ccb->csio.tag_action;
899 aic->msg_buf[1] = scb->tag;
900 aic->msg_len = 2;
901 break;
902 case AIC_MSG_SDTR:
903 scb = aic->nexus;
904 ti = &aic->tinfo[scb->target];
905 aic->msg_buf[0] = MSG_EXTENDED;
906 aic->msg_buf[1] = MSG_EXT_SDTR_LEN;
907 aic->msg_buf[2] = MSG_EXT_SDTR;
908 aic->msg_buf[3] = ti->goal.period;
909 aic->msg_buf[4] = ti->goal.offset;
910 aic->msg_len = MSG_EXT_SDTR_LEN + 2;
911 ti->flags |= TINFO_SDTR_SENT;
912 break;
913 case AIC_MSG_MSGBUF:
914 /* a single message already in the buffer */
915 if (aic->msg_buf[0] == MSG_BUS_DEV_RESET ||
916 aic->msg_buf[0] == MSG_ABORT ||
917 aic->msg_buf[0] == MSG_ABORT_TAG)
918 aic->flags |= AIC_BUSFREE_OK;
919 break;
923 * If this is the last message byte of all messages,
924 * clear ATNO to signal transmission complete.
926 if ((q & (q - 1)) == 0 && msgidx == aic->msg_len - 1)
927 aic_outb(aic, CLRSINT1, CLRATNO);
928 /* transmit the message byte */
929 aic_outb(aic, SCSIDAT, aic->msg_buf[msgidx++]);
930 } while (aic_spiordy(aic));
932 aic_outb(aic, SXFRCTL0, CHEN);
933 aic_outb(aic, SIMODE1, ENSCSIRST|ENBUSFREE|ENREQINIT);
937 * Read data bytes.
939 static void
940 aic_datain(struct aic_softc *aic)
942 struct aic_scb *scb = aic->nexus;
943 u_int8_t dmastat, dmacntrl0;
944 int n;
946 CAM_DEBUG_PRINT(CAM_DEBUG_TRACE, ("aic_datain\n"));
948 aic_outb(aic, SIMODE1, ENSCSIRST|ENPHASEMIS|ENBUSFREE);
949 aic_outb(aic, SXFRCTL0, SCSIEN|DMAEN|CHEN);
951 dmacntrl0 = ENDMA;
952 if (aic->flags & AIC_DWIO_ENABLE)
953 dmacntrl0 |= DWORDPIO;
954 aic_outb(aic, DMACNTRL0, dmacntrl0);
956 while (scb->data_len > 0) {
957 for (;;) {
958 /* wait for the fifo to fill up or a phase change */
959 dmastat = aic_inb(aic, DMASTAT);
960 if (dmastat & (INTSTAT|DFIFOFULL))
961 break;
963 if (dmastat & DFIFOFULL) {
964 n = FIFOSIZE;
965 } else {
967 * No more data, wait for the remaining bytes in
968 * the scsi fifo to be transfer to the host fifo.
970 while (!(aic_inb(aic, SSTAT2) & SEMPTY))
972 n = aic_inb(aic, FIFOSTAT);
974 n = imin(scb->data_len, n);
975 if (aic->flags & AIC_DWIO_ENABLE) {
976 if (n >= 12) {
977 aic_insl(aic, DMADATALONG, scb->data_ptr, n>>2);
978 scb->data_ptr += n & ~3;
979 scb->data_len -= n & ~3;
980 n &= 3;
982 } else {
983 if (n >= 8) {
984 aic_insw(aic, DMADATA, scb->data_ptr, n >> 1);
985 scb->data_ptr += n & ~1;
986 scb->data_len -= n & ~1;
987 n &= 1;
990 if (n) {
991 aic_outb(aic, DMACNTRL0, ENDMA|B8MODE);
992 aic_insb(aic, DMADATA, scb->data_ptr, n);
993 scb->data_ptr += n;
994 scb->data_len -= n;
995 aic_outb(aic, DMACNTRL0, dmacntrl0);
998 if (dmastat & INTSTAT)
999 break;
1002 aic_outb(aic, SXFRCTL0, CHEN);
1003 aic_outb(aic, SIMODE1, ENSCSIRST|ENBUSFREE|ENREQINIT);
1007 * Send data bytes.
1009 static void
1010 aic_dataout(struct aic_softc *aic)
1012 struct aic_scb *scb = aic->nexus;
1013 u_int8_t dmastat, dmacntrl0, sstat2;
1014 int n;
1016 CAM_DEBUG_PRINT(CAM_DEBUG_TRACE, ("aic_dataout\n"));
1018 aic_outb(aic, SIMODE1, ENSCSIRST|ENPHASEMIS|ENBUSFREE);
1019 aic_outb(aic, SXFRCTL0, SCSIEN|DMAEN|CHEN);
1021 dmacntrl0 = ENDMA|WRITE;
1022 if (aic->flags & AIC_DWIO_ENABLE)
1023 dmacntrl0 |= DWORDPIO;
1024 aic_outb(aic, DMACNTRL0, dmacntrl0);
1026 while (scb->data_len > 0) {
1027 for (;;) {
1028 /* wait for the fifo to clear up or a phase change */
1029 dmastat = aic_inb(aic, DMASTAT);
1030 if (dmastat & (INTSTAT|DFIFOEMP))
1031 break;
1033 if (dmastat & INTSTAT)
1034 break;
1035 n = imin(scb->data_len, FIFOSIZE);
1036 if (aic->flags & AIC_DWIO_ENABLE) {
1037 if (n >= 12) {
1038 aic_outsl(aic, DMADATALONG, scb->data_ptr,n>>2);
1039 scb->data_ptr += n & ~3;
1040 scb->data_len -= n & ~3;
1041 n &= 3;
1043 } else {
1044 if (n >= 8) {
1045 aic_outsw(aic, DMADATA, scb->data_ptr, n >> 1);
1046 scb->data_ptr += n & ~1;
1047 scb->data_len -= n & ~1;
1048 n &= 1;
1051 if (n) {
1052 aic_outb(aic, DMACNTRL0, ENDMA|WRITE|B8MODE);
1053 aic_outsb(aic, DMADATA, scb->data_ptr, n);
1054 scb->data_ptr += n;
1055 scb->data_len -= n;
1056 aic_outb(aic, DMACNTRL0, dmacntrl0);
1060 for (;;) {
1061 /* wait until all bytes in the fifos are transmitted */
1062 dmastat = aic_inb(aic, DMASTAT);
1063 sstat2 = aic_inb(aic, SSTAT2);
1064 if ((dmastat & DFIFOEMP) && (sstat2 & SEMPTY))
1065 break;
1066 if (dmastat & INTSTAT) {
1067 /* adjust for untransmitted bytes */
1068 n = aic_inb(aic, FIFOSTAT) + (sstat2 & 0xf);
1069 scb->data_ptr -= n;
1070 scb->data_len += n;
1071 /* clear the fifo */
1072 aic_outb(aic, SXFRCTL0, CHEN|CLRCH);
1073 aic_outb(aic, DMACNTRL0, RSTFIFO);
1074 break;
1078 aic_outb(aic, SXFRCTL0, CHEN);
1079 aic_outb(aic, SIMODE1, ENSCSIRST|ENBUSFREE|ENREQINIT);
1083 * Send the scsi command.
1085 static void
1086 aic_cmd(struct aic_softc *aic)
1088 struct aic_scb *scb = aic->nexus;
1089 struct scsi_request_sense sense_cmd;
1091 CAM_DEBUG_PRINT(CAM_DEBUG_TRACE, ("aic_cmd\n"));
1093 if (scb->flags & SCB_SENSE) {
1094 /* autosense request */
1095 sense_cmd.opcode = REQUEST_SENSE;
1096 sense_cmd.byte2 = scb->lun << 5;
1097 sense_cmd.length = scb->ccb->csio.sense_len;
1098 sense_cmd.control = 0;
1099 sense_cmd.unused[0] = 0;
1100 sense_cmd.unused[1] = 0;
1101 scb->cmd_ptr = (u_int8_t *)&sense_cmd;
1102 scb->cmd_len = sizeof(sense_cmd);
1103 scb->data_ptr = (u_int8_t *)&scb->ccb->csio.sense_data;
1104 scb->data_len = scb->ccb->csio.sense_len;
1107 aic_outb(aic, SIMODE1, ENSCSIRST|ENPHASEMIS|ENBUSFREE);
1108 aic_outb(aic, DMACNTRL0, ENDMA|WRITE);
1109 aic_outb(aic, SXFRCTL0, SCSIEN|DMAEN|CHEN);
1110 aic_outsw(aic, DMADATA, (u_int16_t *)scb->cmd_ptr, scb->cmd_len >> 1);
1111 while ((aic_inb(aic, SSTAT2) & SEMPTY) == 0 &&
1112 (aic_inb(aic, DMASTAT) & INTSTAT) == 0)
1114 aic_outb(aic, SXFRCTL0, CHEN);
1115 aic_outb(aic, SIMODE1, ENSCSIRST|ENBUSFREE|ENREQINIT);
1119 * Finish off a command. The caller is responsible to remove the ccb
1120 * from any queue.
1122 static void
1123 aic_done(struct aic_softc *aic, struct aic_scb *scb)
1125 union ccb *ccb = scb->ccb;
1127 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
1128 ("aic_done - ccb %p status %x resid %d\n",
1129 ccb, ccb->ccb_h.status, ccb->csio.resid));
1131 callout_stop(&ccb->ccb_h.timeout_ch);
1133 if ((scb->flags & SCB_DEVICE_RESET) != 0 &&
1134 ccb->ccb_h.func_code != XPT_RESET_DEV) {
1135 struct cam_path *path;
1136 struct ccb_hdr *ccb_h;
1137 cam_status error;
1139 error = xpt_create_path(&path, /*periph*/NULL,
1140 cam_sim_path(aic->sim),
1141 scb->target,
1142 CAM_LUN_WILDCARD);
1144 if (error == CAM_REQ_CMP) {
1145 xpt_async(AC_SENT_BDR, path, NULL);
1146 xpt_free_path(path);
1149 ccb_h = TAILQ_FIRST(&aic->pending_ccbs);
1150 while (ccb_h != NULL) {
1151 struct aic_scb *pending_scb;
1153 pending_scb = (struct aic_scb *)ccb_h->ccb_scb_ptr;
1154 if (ccb_h->target_id == scb->target) {
1155 ccb_h->status |= CAM_BDR_SENT;
1156 ccb_h = TAILQ_NEXT(ccb_h, sim_links.tqe);
1157 TAILQ_REMOVE(&aic->pending_ccbs,
1158 &pending_scb->ccb->ccb_h, sim_links.tqe);
1159 aic_done(aic, pending_scb);
1160 } else {
1161 callout_reset(&ccb_h->timeout_ch,
1162 (ccb_h->timeout * hz) / 1000,
1163 aic_timeout, pending_scb);
1164 ccb_h = TAILQ_NEXT(ccb_h, sim_links.tqe);
1168 ccb_h = TAILQ_FIRST(&aic->nexus_ccbs);
1169 while (ccb_h != NULL) {
1170 struct aic_scb *nexus_scb;
1172 nexus_scb = (struct aic_scb *)ccb_h->ccb_scb_ptr;
1173 if (ccb_h->target_id == scb->target) {
1174 ccb_h->status |= CAM_BDR_SENT;
1175 ccb_h = TAILQ_NEXT(ccb_h, sim_links.tqe);
1176 TAILQ_REMOVE(&aic->nexus_ccbs,
1177 &nexus_scb->ccb->ccb_h, sim_links.tqe);
1178 aic_done(aic, nexus_scb);
1179 } else {
1180 callout_reset(&ccb_h->timeout_ch,
1181 (ccb_h->timeout * hz) / 1000,
1182 aic_timeout, nexus_scb);
1183 ccb_h = TAILQ_NEXT(ccb_h, sim_links.tqe);
1188 if (aic->nexus == scb || scb->flags & SCB_DISCONNECTED)
1189 aic->tinfo[scb->target].lubusy &= ~(1 << scb->lun);
1191 if (aic->nexus == scb) {
1192 aic->nexus = NULL;
1194 aic_free_scb(aic, scb);
1195 xpt_done(ccb);
1198 static void
1199 aic_poll(struct cam_sim *sim)
1201 aic_intr(cam_sim_softc(sim));
1204 static void
1205 aic_timeout(void *arg)
1207 struct aic_scb *scb = (struct aic_scb *)arg;
1208 union ccb *ccb = scb->ccb;
1209 struct aic_softc *aic = (struct aic_softc *)ccb->ccb_h.ccb_aic_ptr;
1211 xpt_print_path(ccb->ccb_h.path);
1212 kprintf("ccb %p - timed out", ccb);
1213 if (aic->nexus && aic->nexus != scb)
1214 kprintf(", nexus %p", aic->nexus->ccb);
1215 kprintf(", phase 0x%x, state %d\n", aic_inb(aic, SCSISIGI), aic->state);
1217 crit_enter();
1219 if ((scb->flags & SCB_ACTIVE) == 0) {
1220 crit_exit();
1221 xpt_print_path(ccb->ccb_h.path);
1222 kprintf("ccb %p - timed out already completed\n", ccb);
1223 return;
1226 if ((scb->flags & SCB_DEVICE_RESET) == 0 && aic->nexus == scb) {
1227 struct ccb_hdr *ccb_h = &scb->ccb->ccb_h;
1229 if ((ccb_h->status & CAM_RELEASE_SIMQ) == 0) {
1230 xpt_freeze_simq(aic->sim, /*count*/1);
1231 ccb_h->status |= CAM_RELEASE_SIMQ;
1234 TAILQ_FOREACH(ccb_h, &aic->pending_ccbs, sim_links.tqe)
1235 callout_stop(&ccb_h->timeout_ch);
1237 TAILQ_FOREACH(ccb_h, &aic->nexus_ccbs, sim_links.tqe)
1238 callout_stop(&ccb_h->timeout_ch);
1240 scb->flags |= SCB_DEVICE_RESET;
1241 callout_reset(&ccb->ccb_h.timeout_ch, 5 * hz, aic_timeout, scb);
1242 aic_sched_msgout(aic, MSG_BUS_DEV_RESET);
1243 } else {
1244 if (aic->nexus == scb) {
1245 ccb->ccb_h.status |= CAM_CMD_TIMEOUT;
1246 aic_done(aic, scb);
1248 aic_reset(aic, /*initiate_reset*/TRUE);
1251 crit_exit();
1254 void
1255 aic_intr(void *arg)
1257 struct aic_softc *aic = (struct aic_softc *)arg;
1258 u_int8_t sstat0, sstat1;
1259 union ccb *ccb;
1260 struct aic_scb *scb;
1262 if (!(aic_inb(aic, DMASTAT) & INTSTAT))
1263 return;
1265 aic_outb(aic, DMACNTRL0, 0);
1267 sstat0 = aic_inb(aic, SSTAT0);
1268 sstat1 = aic_inb(aic, SSTAT1);
1270 if ((sstat1 & SCSIRSTI) != 0) {
1271 /* a device-initiated bus reset */
1272 aic_outb(aic, CLRSINT1, CLRSCSIRSTI);
1273 aic_reset(aic, /*initiate_reset*/FALSE);
1274 return;
1277 if ((sstat1 & SCSIPERR) != 0) {
1278 aic_outb(aic, CLRSINT1, CLRSCSIPERR);
1279 aic_sched_msgout(aic, MSG_PARITY_ERROR);
1280 aic_outb(aic, DMACNTRL0, INTEN);
1281 return;
1284 if (aic_inb(aic, SSTAT4)) {
1285 aic_outb(aic, CLRSERR, CLRSYNCERR|CLRFWERR|CLRFRERR);
1286 aic_reset(aic, /*initiate_reset*/TRUE);
1287 return;
1290 if (aic->state <= AIC_SELECTING) {
1291 if ((sstat0 & SELDI) != 0) {
1292 aic_reselected(aic);
1293 aic_outb(aic, DMACNTRL0, INTEN);
1294 return;
1297 if ((sstat0 & SELDO) != 0) {
1298 aic_selected(aic);
1299 aic_outb(aic, DMACNTRL0, INTEN);
1300 return;
1303 if ((sstat1 & SELTO) != 0) {
1304 scb = aic->nexus;
1305 ccb = scb->ccb;
1306 ccb->ccb_h.status = CAM_SEL_TIMEOUT;
1307 aic_done(aic, scb);
1308 while ((sstat1 & BUSFREE) == 0)
1309 sstat1 = aic_inb(aic, SSTAT1);
1310 aic->flags |= AIC_BUSFREE_OK;
1314 if ((sstat1 & BUSFREE) != 0) {
1315 aic_outb(aic, SCSISEQ, 0);
1316 aic_outb(aic, CLRSINT0, sstat0);
1317 aic_outb(aic, CLRSINT1, sstat1);
1318 if ((scb = aic->nexus)) {
1319 if ((aic->flags & AIC_BUSFREE_OK) == 0) {
1320 ccb = scb->ccb;
1321 ccb->ccb_h.status = CAM_UNEXP_BUSFREE;
1322 aic_done(aic, scb);
1323 } else if (scb->flags & SCB_DEVICE_RESET) {
1324 ccb = scb->ccb;
1325 if (ccb->ccb_h.func_code == XPT_RESET_DEV) {
1326 xpt_async(AC_SENT_BDR,
1327 ccb->ccb_h.path, NULL);
1328 ccb->ccb_h.status |= CAM_REQ_CMP;
1329 } else
1330 ccb->ccb_h.status |= CAM_CMD_TIMEOUT;
1331 aic_done(aic, scb);
1332 } else if (scb->flags & SCB_SENSE) {
1333 /* autosense request */
1334 aic->flags &= ~AIC_BUSFREE_OK;
1335 aic->tinfo[scb->target].lubusy &=
1336 ~(1 << scb->lun);
1337 aic_select(aic);
1338 aic_outb(aic, DMACNTRL0, INTEN);
1339 return;
1342 aic->flags &= ~AIC_BUSFREE_OK;
1343 aic->state = AIC_IDLE;
1344 aic_start(aic);
1345 aic_outb(aic, DMACNTRL0, INTEN);
1346 return;
1349 if ((sstat1 & REQINIT) != 0) {
1350 u_int8_t phase = aic_inb(aic, SCSISIGI) & PH_MASK;
1351 aic_outb(aic, SCSISIGO, phase);
1352 aic_outb(aic, CLRSINT1, CLRPHASECHG);
1354 switch (phase) {
1355 case PH_MSGOUT:
1356 aic_msgout(aic);
1357 break;
1358 case PH_MSGIN:
1359 aic_msgin(aic);
1360 break;
1361 case PH_STAT:
1362 scb = aic->nexus;
1363 ccb = scb->ccb;
1364 aic_outb(aic, DMACNTRL0, 0);
1365 aic_outb(aic, SXFRCTL0, CHEN|SPIOEN);
1366 scb->status = aic_inb(aic, SCSIDAT);
1367 aic_outb(aic, SXFRCTL0, CHEN);
1368 break;
1369 case PH_CMD:
1370 aic_cmd(aic);
1371 break;
1372 case PH_DATAIN:
1373 aic_datain(aic);
1374 break;
1375 case PH_DATAOUT:
1376 aic_dataout(aic);
1377 break;
1379 aic->prev_phase = phase;
1380 aic_outb(aic, DMACNTRL0, INTEN);
1381 return;
1384 kprintf("aic_intr: unexpected intr sstat0 %x sstat1 %x\n",
1385 sstat0, sstat1);
1386 aic_outb(aic, DMACNTRL0, INTEN);
1390 * Reset ourselves.
1392 static void
1393 aic_chip_reset(struct aic_softc *aic)
1396 * Doc. recommends to clear these two registers before
1397 * operations commence
1399 aic_outb(aic, SCSITEST, 0);
1400 aic_outb(aic, TEST, 0);
1402 /* Reset SCSI-FIFO and abort any transfers */
1403 aic_outb(aic, SXFRCTL0, CHEN|CLRCH|CLRSTCNT);
1405 /* Reset HOST-FIFO */
1406 aic_outb(aic, DMACNTRL0, RSTFIFO);
1407 aic_outb(aic, DMACNTRL1, 0);
1409 /* Disable all selection features */
1410 aic_outb(aic, SCSISEQ, 0);
1411 aic_outb(aic, SXFRCTL1, 0);
1413 /* Disable interrupts */
1414 aic_outb(aic, SIMODE0, 0);
1415 aic_outb(aic, SIMODE1, 0);
1417 /* Clear interrupts */
1418 aic_outb(aic, CLRSINT0, 0x7f);
1419 aic_outb(aic, CLRSINT1, 0xef);
1421 /* Disable synchronous transfers */
1422 aic_outb(aic, SCSIRATE, 0);
1424 /* Haven't seen ant errors (yet) */
1425 aic_outb(aic, CLRSERR, 0x07);
1427 /* Set our SCSI-ID */
1428 aic_outb(aic, SCSIID, aic->initiator << OID_S);
1429 aic_outb(aic, BRSTCNTRL, EISA_BRST_TIM);
1433 * Reset the SCSI bus
1435 static void
1436 aic_scsi_reset(struct aic_softc *aic)
1438 aic_outb(aic, SCSISEQ, SCSIRSTO);
1439 DELAY(500);
1440 aic_outb(aic, SCSISEQ, 0);
1441 DELAY(50);
1445 * Reset. Abort all pending commands.
1447 static void
1448 aic_reset(struct aic_softc *aic, int initiate_reset)
1450 struct ccb_hdr *ccb_h;
1452 CAM_DEBUG_PRINT(CAM_DEBUG_TRACE, ("aic_reset\n"));
1454 if (initiate_reset)
1455 aic_scsi_reset(aic);
1456 aic_chip_reset(aic);
1458 xpt_async(AC_BUS_RESET, aic->path, NULL);
1460 while ((ccb_h = TAILQ_FIRST(&aic->pending_ccbs)) != NULL) {
1461 TAILQ_REMOVE(&aic->pending_ccbs, ccb_h, sim_links.tqe);
1462 ccb_h->status |= CAM_SCSI_BUS_RESET;
1463 aic_done(aic, (struct aic_scb *)ccb_h->ccb_scb_ptr);
1466 while ((ccb_h = TAILQ_FIRST(&aic->nexus_ccbs)) != NULL) {
1467 TAILQ_REMOVE(&aic->nexus_ccbs, ccb_h, sim_links.tqe);
1468 ccb_h->status |= CAM_SCSI_BUS_RESET;
1469 aic_done(aic, (struct aic_scb *)ccb_h->ccb_scb_ptr);
1472 if (aic->nexus) {
1473 ccb_h = &aic->nexus->ccb->ccb_h;
1474 ccb_h->status |= CAM_SCSI_BUS_RESET;
1475 aic_done(aic, aic->nexus);
1478 aic->state = AIC_IDLE;
1479 aic_outb(aic, DMACNTRL0, INTEN);
1482 static char *aic_chip_names[] = {
1483 "AIC6260", "AIC6360", "AIC6370", "GM82C700",
1486 static struct {
1487 int type;
1488 char *idstring;
1489 } aic_chip_ids[] = {
1490 { AIC6360, IDSTRING_AIC6360 },
1491 { AIC6370, IDSTRING_AIC6370 },
1492 { GM82C700, IDSTRING_GM82C700 },
1495 static void
1496 aic_init(struct aic_softc *aic)
1498 struct aic_scb *scb;
1499 struct aic_tinfo *ti;
1500 u_int8_t porta, portb;
1501 char chip_id[33];
1502 int i;
1504 TAILQ_INIT(&aic->pending_ccbs);
1505 TAILQ_INIT(&aic->nexus_ccbs);
1506 aic->nexus = NULL;
1507 aic->state = AIC_IDLE;
1508 aic->prev_phase = -1;
1509 aic->flags = 0;
1511 aic_chip_reset(aic);
1512 aic_scsi_reset(aic);
1514 /* determine the chip type from its ID string */
1515 aic->chip_type = AIC6260;
1516 aic_insb(aic, ID, chip_id, sizeof(chip_id) - 1);
1517 chip_id[sizeof(chip_id) - 1] = '\0';
1518 for (i = 0; i < sizeof(aic_chip_ids) / sizeof(aic_chip_ids[0]); i++) {
1519 if (!strcmp(chip_id, aic_chip_ids[i].idstring)) {
1520 aic->chip_type = aic_chip_ids[i].type;
1521 break;
1525 porta = aic_inb(aic, PORTA);
1526 portb = aic_inb(aic, PORTB);
1528 aic->initiator = PORTA_ID(porta);
1529 if (PORTA_PARITY(porta))
1530 aic->flags |= AIC_PARITY_ENABLE;
1531 if (PORTB_DISC(portb))
1532 aic->flags |= AIC_DISC_ENABLE;
1533 if (PORTB_DMA(portb))
1534 aic->flags |= AIC_DMA_ENABLE;
1537 * We can do fast SCSI (10MHz clock rate) if bit 4 of portb
1538 * is set and we've got a 6360. The 6260 can only do standard
1539 * 5MHz SCSI.
1541 if (aic->chip_type > AIC6260 || aic_inb(aic, REV)) {
1542 if (PORTB_FSYNC(portb))
1543 aic->flags |= AIC_FAST_ENABLE;
1544 aic->flags |= AIC_DWIO_ENABLE;
1547 if (aic->flags & AIC_FAST_ENABLE)
1548 aic->max_period = AIC_FAST_SYNC_PERIOD;
1549 else
1550 aic->max_period = AIC_SYNC_PERIOD;
1551 aic->min_period = AIC_MIN_SYNC_PERIOD;
1553 free_scbs = NULL;
1554 for (i = 255; i >= 0; i--) {
1555 scb = &aic->scbs[i];
1556 scb->tag = i;
1557 aic_free_scb(aic, scb);
1560 for (i = 0; i < 8; i++) {
1561 if (i == aic->initiator)
1562 continue;
1563 ti = &aic->tinfo[i];
1564 bzero(ti, sizeof(*ti));
1565 ti->flags = TINFO_TAG_ENB;
1566 if (aic->flags & AIC_DISC_ENABLE)
1567 ti->flags |= TINFO_DISC_ENB;
1568 ti->user.period = aic->max_period;
1569 ti->user.offset = AIC_SYNC_OFFSET;
1570 ti->scsirate = 0;
1573 aic_outb(aic, DMACNTRL0, INTEN);
1577 aic_probe(struct aic_softc *aic)
1579 int i;
1581 /* Remove aic6360 from possible powerdown mode */
1582 aic_outb(aic, DMACNTRL0, 0);
1584 #define STSIZE 16
1585 aic_outb(aic, DMACNTRL1, 0); /* Reset stack pointer */
1586 for (i = 0; i < STSIZE; i++)
1587 aic_outb(aic, STACK, i);
1589 /* See if we can pull out the same sequence */
1590 aic_outb(aic, DMACNTRL1, 0);
1591 for (i = 0; i < STSIZE && aic_inb(aic, STACK) == i; i++)
1593 if (i != STSIZE)
1594 return (ENXIO);
1595 #undef STSIZE
1596 return (0);
1600 aic_attach(struct aic_softc *aic)
1603 * Construct our SIM entry
1605 aic->sim = cam_sim_alloc(aic_action, aic_poll, "aic", aic,
1606 aic->unit, 2, 256, NULL);
1607 if (aic->sim == NULL)
1608 return (ENOMEM);
1610 if (xpt_bus_register(aic->sim, 0) != CAM_SUCCESS) {
1611 cam_sim_free(aic->sim);
1612 return (ENXIO);
1615 if (xpt_create_path(&aic->path, /*periph*/NULL,
1616 cam_sim_path(aic->sim), CAM_TARGET_WILDCARD,
1617 CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
1618 xpt_bus_deregister(cam_sim_path(aic->sim));
1619 cam_sim_free(aic->sim);
1620 return (ENXIO);
1623 aic_init(aic);
1625 kprintf("aic%d: %s", aic->unit, aic_chip_names[aic->chip_type]);
1626 if (aic->flags & AIC_DMA_ENABLE)
1627 kprintf(", dma");
1628 if (aic->flags & AIC_DISC_ENABLE)
1629 kprintf(", disconnection");
1630 if (aic->flags & AIC_PARITY_ENABLE)
1631 kprintf(", parity check");
1632 if (aic->flags & AIC_FAST_ENABLE)
1633 kprintf(", fast SCSI");
1634 kprintf("\n");
1635 return (0);
1639 aic_detach(struct aic_softc *aic)
1641 xpt_async(AC_LOST_DEVICE, aic->path, NULL);
1642 xpt_free_path(aic->path);
1643 xpt_bus_deregister(cam_sim_path(aic->sim));
1644 cam_sim_free(aic->sim);
1645 return (0);