Make CAM_NEW_TRAN_CODE default.
[dragonfly.git] / sys / dev / disk / aic / aic.c
bloba02e7b5de894938642c872d16fcdaf3af28f7de3
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.13 2008/02/10 00:01:02 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 struct ccb_trans_settings_scsi *scsi =
174 &cts->proto_specific.scsi;
175 struct ccb_trans_settings_spi *spi =
176 &cts->xport_specific.spi;
178 crit_enter();
180 if ((spi->valid & CTS_SPI_VALID_DISC) != 0 &&
181 (aic->flags & AIC_DISC_ENABLE) != 0) {
182 if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) != 0)
183 ti->flags |= TINFO_DISC_ENB;
184 else
185 ti->flags &= ~TINFO_DISC_ENB;
188 if ((scsi->valid & CTS_SCSI_VALID_TQ) != 0) {
189 if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0)
190 ti->flags |= TINFO_TAG_ENB;
191 else
192 ti->flags &= ~TINFO_TAG_ENB;
195 if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
196 ti->goal.period = spi->sync_period;
198 if (ti->goal.period > aic->min_period) {
199 ti->goal.period = 0;
200 ti->goal.offset = 0;
201 } else if (ti->goal.period < aic->max_period)
202 ti->goal.period = aic->max_period;
205 if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0) {
206 ti->goal.offset = spi->sync_offset;
207 if (ti->goal.offset == 0)
208 ti->goal.period = 0;
209 else if (ti->goal.offset > AIC_SYNC_OFFSET)
210 ti->goal.offset = AIC_SYNC_OFFSET;
213 if ((ti->goal.period != ti->current.period)
214 || (ti->goal.offset != ti->current.offset))
215 ti->flags |= TINFO_SDTR_NEGO;
217 crit_exit();
218 ccb->ccb_h.status = CAM_REQ_CMP;
219 xpt_done(ccb);
220 break;
222 case XPT_GET_TRAN_SETTINGS:
224 struct ccb_trans_settings *cts = &ccb->cts;
225 struct aic_tinfo *ti = &aic->tinfo[ccb->ccb_h.target_id];
226 struct ccb_trans_settings_scsi *scsi =
227 &cts->proto_specific.scsi;
228 struct ccb_trans_settings_spi *spi =
229 &cts->xport_specific.spi;
231 cts->protocol = PROTO_SCSI;
232 cts->protocol_version = SCSI_REV_2;
233 cts->transport = XPORT_SPI;
234 cts->transport_version = 2;
235 scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
236 spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
238 crit_enter();
239 if ((ti->flags & TINFO_DISC_ENB) != 0)
240 spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
241 if ((ti->flags & TINFO_TAG_ENB) != 0)
242 scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
244 if (cts->type == CTS_TYPE_CURRENT_SETTINGS) {
245 spi->sync_period = ti->current.period;
246 spi->sync_offset = ti->current.offset;
247 } else {
248 spi->sync_period = ti->user.period;
249 spi->sync_offset = ti->user.offset;
251 crit_exit();
253 spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
254 spi->valid = CTS_SPI_VALID_SYNC_RATE
255 | CTS_SPI_VALID_SYNC_OFFSET
256 | CTS_SPI_VALID_BUS_WIDTH
257 | CTS_SPI_VALID_DISC;
258 scsi->valid = CTS_SCSI_VALID_TQ;
260 ccb->ccb_h.status = CAM_REQ_CMP;
261 xpt_done(ccb);
262 break;
264 case XPT_CALC_GEOMETRY:
266 cam_calc_geometry(&ccb->ccg, /*extended*/1);
267 xpt_done(ccb);
268 break;
270 case XPT_RESET_BUS: /* Reset the specified SCSI bus */
271 aic_reset(aic, /*initiate_reset*/TRUE);
272 ccb->ccb_h.status = CAM_REQ_CMP;
273 xpt_done(ccb);
274 break;
275 case XPT_PATH_INQ: /* Path routing inquiry */
277 struct ccb_pathinq *cpi = &ccb->cpi;
279 cpi->version_num = 1; /* XXX??? */
280 cpi->hba_inquiry = PI_SDTR_ABLE | PI_TAG_ABLE;
281 cpi->target_sprt = 0;
282 cpi->hba_misc = 0;
283 cpi->hba_eng_cnt = 0;
284 cpi->max_target = 7;
285 cpi->max_lun = 7;
286 cpi->initiator_id = aic->initiator;
287 cpi->bus_id = cam_sim_bus(sim);
288 cpi->base_transfer_speed = 3300;
289 strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
290 strncpy(cpi->hba_vid, "Adaptec", HBA_IDLEN);
291 strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
292 cpi->unit_number = cam_sim_unit(sim);
293 cpi->transport = XPORT_SPI;
294 cpi->transport_version = 2;
295 cpi->protocol = PROTO_SCSI;
296 cpi->protocol_version = SCSI_REV_2;
297 cpi->ccb_h.status = CAM_REQ_CMP;
298 xpt_done(ccb);
299 break;
301 default:
302 ccb->ccb_h.status = CAM_REQ_INVALID;
303 xpt_done(ccb);
304 break;
308 static void
309 aic_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
311 struct aic_scb *scb = (struct aic_scb *)arg;
312 union ccb *ccb = scb->ccb;
313 struct aic_softc *aic = (struct aic_softc *)ccb->ccb_h.ccb_aic_ptr;
315 crit_enter();
317 if (ccb->ccb_h.status != CAM_REQ_INPROG) {
318 crit_exit();
319 aic_free_scb(aic, scb);
320 xpt_done(ccb);
321 return;
324 scb->flags |= SCB_ACTIVE;
325 ccb->ccb_h.status |= CAM_SIM_QUEUED;
326 TAILQ_INSERT_TAIL(&aic->pending_ccbs, &ccb->ccb_h, sim_links.tqe);
328 callout_reset(&ccb->ccb_h.timeout_ch, (ccb->ccb_h.timeout * hz) / 1000,
329 aic_timeout, scb);
331 aic_start(aic);
332 crit_exit();
336 * Start another command if the controller is not busy.
338 static void
339 aic_start(struct aic_softc *aic)
341 struct ccb_hdr *ccb_h;
342 struct aic_tinfo *ti;
344 if (aic->state != AIC_IDLE)
345 return;
347 TAILQ_FOREACH(ccb_h, &aic->pending_ccbs, sim_links.tqe) {
348 ti = &aic->tinfo[ccb_h->target_id];
349 if ((ti->lubusy & (1 << ccb_h->target_lun)) == 0) {
350 TAILQ_REMOVE(&aic->pending_ccbs, ccb_h, sim_links.tqe);
351 aic->nexus = (struct aic_scb *)ccb_h->ccb_scb_ptr;
352 aic_select(aic);
353 return;
357 CAM_DEBUG_PRINT(CAM_DEBUG_TRACE, ("aic_start: idle\n"));
359 aic_outb(aic, SIMODE0, ENSELDI);
360 aic_outb(aic, SIMODE1, ENSCSIRST);
361 aic_outb(aic, SCSISEQ, ENRESELI);
365 * Start a selection.
367 static void
368 aic_select(struct aic_softc *aic)
370 struct aic_scb *scb = aic->nexus;
372 CAM_DEBUG(scb->ccb->ccb_h.path, CAM_DEBUG_TRACE,
373 ("aic_select - ccb %p\n", scb->ccb));
375 aic->state = AIC_SELECTING;
377 aic_outb(aic, DMACNTRL1, 0);
378 aic_outb(aic, SCSIID, aic->initiator << OID_S | scb->target);
379 aic_outb(aic, SXFRCTL1, STIMO_256ms | ENSTIMER |
380 (aic->flags & AIC_PARITY_ENABLE ? ENSPCHK : 0));
382 aic_outb(aic, SIMODE0, ENSELDI|ENSELDO);
383 aic_outb(aic, SIMODE1, ENSCSIRST|ENSELTIMO);
384 aic_outb(aic, SCSISEQ, ENRESELI|ENSELO|ENAUTOATNO);
388 * We have successfully selected a target, prepare for the information
389 * transfer phases.
391 static void
392 aic_selected(struct aic_softc *aic)
394 struct aic_scb *scb = aic->nexus;
395 union ccb *ccb = scb->ccb;
396 struct aic_tinfo *ti = &aic->tinfo[scb->target];
398 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
399 ("aic_selected - ccb %p\n", ccb));
401 aic->state = AIC_HASNEXUS;
403 if (scb->flags & SCB_DEVICE_RESET) {
404 aic->msg_buf[0] = MSG_BUS_DEV_RESET;
405 aic->msg_len = 1;
406 aic->msg_outq = AIC_MSG_MSGBUF;
407 } else {
408 aic->msg_outq = AIC_MSG_IDENTIFY;
409 if ((ti->flags & TINFO_TAG_ENB) != 0 &&
410 (ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) != 0)
411 aic->msg_outq |= AIC_MSG_TAG_Q;
412 else
413 ti->lubusy |= 1 << scb->lun;
414 if ((ti->flags & TINFO_SDTR_NEGO) != 0)
415 aic->msg_outq |= AIC_MSG_SDTR;
418 aic_outb(aic, CLRSINT0, CLRSELDO);
419 aic_outb(aic, CLRSINT1, CLRBUSFREE);
420 aic_outb(aic, SCSISEQ, ENAUTOATNP);
421 aic_outb(aic, SIMODE0, 0);
422 aic_outb(aic, SIMODE1, ENSCSIRST|ENBUSFREE|ENREQINIT);
423 aic_outb(aic, SCSIRATE, ti->scsirate);
427 * We are re-selected by a target, save the target id and wait for the
428 * target to further identify itself.
430 static void
431 aic_reselected(struct aic_softc *aic)
433 u_int8_t selid;
435 CAM_DEBUG_PRINT(CAM_DEBUG_TRACE, ("aic_reselected\n"));
438 * If we have started a selection, it must have lost out in
439 * the arbitration, put the command back to the pending queue.
441 if (aic->nexus) {
442 TAILQ_INSERT_HEAD(&aic->pending_ccbs,
443 &aic->nexus->ccb->ccb_h, sim_links.tqe);
444 aic->nexus = NULL;
447 selid = aic_inb(aic, SELID) & ~(1 << aic->initiator);
448 if (selid & (selid - 1)) {
449 /* this should never have happened */
450 kprintf("aic_reselected: invalid selid %x\n", selid);
451 aic_reset(aic, /*initiate_reset*/TRUE);
452 return;
455 aic->state = AIC_RESELECTED;
456 aic->target = ffs(selid) - 1;
457 aic->lun = -1;
459 aic_outb(aic, CLRSINT0, CLRSELDI);
460 aic_outb(aic, CLRSINT1, CLRBUSFREE);
461 aic_outb(aic, SIMODE0, 0);
462 aic_outb(aic, SIMODE1, ENSCSIRST|ENBUSFREE|ENREQINIT);
463 aic_outb(aic, SCSISEQ, ENAUTOATNP);
464 aic_outb(aic, SCSIRATE, aic->tinfo[aic->target].scsirate);
468 * Raise ATNO to signal the target that we have a message for it.
470 static __inline void
471 aic_sched_msgout(struct aic_softc *aic, u_int8_t msg)
473 if (msg) {
474 aic->msg_buf[0] = msg;
475 aic->msg_len = 1;
477 aic->msg_outq |= AIC_MSG_MSGBUF;
478 aic_outb(aic, SCSISIGO, aic_inb(aic, SCSISIGI) | ATNO);
482 * Wait for SPIORDY (SCSI PIO ready) flag, or a phase change.
484 static __inline int
485 aic_spiordy(struct aic_softc *aic)
487 while (!(aic_inb(aic, DMASTAT) & INTSTAT) &&
488 !(aic_inb(aic, SSTAT0) & SPIORDY))
490 return !(aic_inb(aic, DMASTAT) & INTSTAT);
494 * Reestablish a disconnected nexus.
496 static void
497 aic_reconnect(struct aic_softc *aic, int tag)
499 struct aic_scb *scb;
500 struct ccb_hdr *ccb_h;
502 CAM_DEBUG_PRINT(CAM_DEBUG_TRACE, ("aic_reconnect\n"));
504 /* Find the nexus */
505 scb = NULL;
506 TAILQ_FOREACH(ccb_h, &aic->nexus_ccbs, sim_links.tqe) {
507 scb = (struct aic_scb *)ccb_h->ccb_scb_ptr;
508 if (scb->target == aic->target && scb->lun == aic->lun &&
509 (tag == -1 || scb->tag == tag))
510 break;
513 /* ABORT if nothing is found */
514 if (!ccb_h) {
515 if (tag == -1)
516 aic_sched_msgout(aic, MSG_ABORT);
517 else
518 aic_sched_msgout(aic, MSG_ABORT_TAG);
519 xpt_async(AC_UNSOL_RESEL, aic->path, NULL);
520 return;
523 /* Reestablish the nexus */
524 TAILQ_REMOVE(&aic->nexus_ccbs, ccb_h, sim_links.tqe);
525 aic->nexus = scb;
526 scb->flags &= ~SCB_DISCONNECTED;
527 aic->state = AIC_HASNEXUS;
531 * Read messages.
533 static void
534 aic_msgin(struct aic_softc *aic)
536 int msglen;
538 CAM_DEBUG_PRINT(CAM_DEBUG_TRACE, ("aic_msgin\n"));
540 aic_outb(aic, SIMODE1, ENSCSIRST|ENPHASEMIS|ENBUSFREE);
541 aic_outb(aic, SXFRCTL0, CHEN|SPIOEN);
543 aic->flags &= ~AIC_DROP_MSGIN;
544 aic->msg_len = 0;
545 do {
547 * If a parity error is detected, drop the remaining
548 * bytes and inform the target so it could resend
549 * the messages.
551 if (aic_inb(aic, SSTAT1) & SCSIPERR) {
552 aic_outb(aic, CLRSINT1, CLRSCSIPERR);
553 aic->flags |= AIC_DROP_MSGIN;
554 aic_sched_msgout(aic, MSG_PARITY_ERROR);
556 if ((aic->flags & AIC_DROP_MSGIN)) {
557 aic_inb(aic, SCSIDAT);
558 continue;
560 /* read the message byte without ACKing on it */
561 aic->msg_buf[aic->msg_len++] = aic_inb(aic, SCSIBUS);
562 if (aic->msg_buf[0] == MSG_EXTENDED) {
563 if (aic->msg_len < 2) {
564 (void) aic_inb(aic, SCSIDAT);
565 continue;
567 switch (aic->msg_buf[2]) {
568 case MSG_EXT_SDTR:
569 msglen = MSG_EXT_SDTR_LEN;
570 break;
571 case MSG_EXT_WDTR:
572 msglen = MSG_EXT_WDTR_LEN;
573 break;
574 default:
575 msglen = 0;
576 break;
578 if (aic->msg_buf[1] != msglen) {
579 aic->flags |= AIC_DROP_MSGIN;
580 aic_sched_msgout(aic, MSG_MESSAGE_REJECT);
582 msglen += 2;
583 } else if (aic->msg_buf[0] >= 0x20 && aic->msg_buf[0] <= 0x2f)
584 msglen = 2;
585 else
586 msglen = 1;
588 * If we have a complete message, handle it before the final
589 * ACK (in case we decide to reject the message).
591 if (aic->msg_len == msglen) {
592 aic_handle_msgin(aic);
593 aic->msg_len = 0;
595 /* ACK on the message byte */
596 (void) aic_inb(aic, SCSIDAT);
597 } while (aic_spiordy(aic));
599 aic_outb(aic, SXFRCTL0, CHEN);
600 aic_outb(aic, SIMODE1, ENSCSIRST|ENBUSFREE|ENREQINIT);
604 * Handle a message.
606 static void
607 aic_handle_msgin(struct aic_softc *aic)
609 struct aic_scb *scb;
610 struct ccb_hdr *ccb_h;
611 struct aic_tinfo *ti;
612 struct ccb_trans_settings neg;
613 struct ccb_trans_settings_spi *spi = &neg.xport_specific.spi;
615 if (aic->state == AIC_RESELECTED) {
616 if (!MSG_ISIDENTIFY(aic->msg_buf[0])) {
617 aic_sched_msgout(aic, MSG_MESSAGE_REJECT);
618 return;
620 aic->lun = aic->msg_buf[0] & MSG_IDENTIFY_LUNMASK;
621 if (aic->tinfo[aic->target].lubusy & (1 << aic->lun))
622 aic_reconnect(aic, -1);
623 else
624 aic->state = AIC_RECONNECTING;
625 return;
628 if (aic->state == AIC_RECONNECTING) {
629 if (aic->msg_buf[0] != MSG_SIMPLE_Q_TAG) {
630 aic_sched_msgout(aic, MSG_MESSAGE_REJECT);
631 return;
633 aic_reconnect(aic, aic->msg_buf[1]);
634 return;
637 switch (aic->msg_buf[0]) {
638 case MSG_CMDCOMPLETE: {
639 struct ccb_scsiio *csio;
640 scb = aic->nexus;
641 ccb_h = &scb->ccb->ccb_h;
642 csio = &scb->ccb->csio;
643 if ((scb->flags & SCB_SENSE) != 0) {
644 /* auto REQUEST SENSE command */
645 scb->flags &= ~SCB_SENSE;
646 csio->sense_resid = scb->data_len;
647 if (scb->status == SCSI_STATUS_OK) {
648 ccb_h->status |=
649 CAM_SCSI_STATUS_ERROR|CAM_AUTOSNS_VALID;
650 /*scsi_sense_print(csio);*/
651 } else {
652 ccb_h->status |= CAM_AUTOSENSE_FAIL;
653 kprintf("ccb %p sense failed %x\n",
654 ccb_h, scb->status);
656 } else {
657 csio->scsi_status = scb->status;
658 csio->resid = scb->data_len;
659 if (scb->status == SCSI_STATUS_OK) {
660 /* everything goes well */
661 ccb_h->status |= CAM_REQ_CMP;
662 } else if ((ccb_h->flags & CAM_DIS_AUTOSENSE) == 0 &&
663 (csio->scsi_status == SCSI_STATUS_CHECK_COND ||
664 csio->scsi_status == SCSI_STATUS_CMD_TERMINATED)) {
665 /* try to retrieve sense information */
666 scb->flags |= SCB_SENSE;
667 aic->flags |= AIC_BUSFREE_OK;
668 return;
669 } else
670 ccb_h->status |= CAM_SCSI_STATUS_ERROR;
672 aic_done(aic, scb);
673 aic->flags |= AIC_BUSFREE_OK;
674 break;
676 case MSG_EXTENDED:
677 switch (aic->msg_buf[2]) {
678 case MSG_EXT_SDTR:
679 scb = aic->nexus;
680 ti = &aic->tinfo[scb->target];
681 if (ti->flags & TINFO_SDTR_SENT) {
682 ti->current.period = aic->msg_buf[3];
683 ti->current.offset = aic->msg_buf[4];
684 } else {
685 ti->current.period = aic->msg_buf[3] =
686 max(ti->goal.period, aic->msg_buf[3]);
687 ti->current.offset = aic->msg_buf[4] =
688 min(ti->goal.offset, aic->msg_buf[4]);
690 * The target initiated the negotiation,
691 * send back a response.
693 aic_sched_msgout(aic, 0);
695 ti->flags &= ~(TINFO_SDTR_SENT|TINFO_SDTR_NEGO);
696 ti->scsirate = ti->current.offset ? ti->current.offset |
697 ((ti->current.period * 4 + 49) / 50 - 2) << 4 : 0;
698 aic_outb(aic, SCSIRATE, ti->scsirate);
699 memset(&neg, 0, sizeof (neg));
700 neg.protocol = PROTO_SCSI;
701 neg.protocol_version = SCSI_REV_2;
702 neg.transport = XPORT_SPI;
703 neg.transport_version = 2;
704 spi->sync_period = ti->goal.period = ti->current.period;
705 spi->sync_offset = ti->goal.offset = ti->current.offset;
706 spi->valid = CTS_SPI_VALID_SYNC_RATE
707 | CTS_SPI_VALID_SYNC_OFFSET;
708 ccb_h = &scb->ccb->ccb_h;
709 xpt_setup_ccb(&neg.ccb_h, ccb_h->path, 1);
710 xpt_async(AC_TRANSFER_NEG, ccb_h->path, &neg);
711 break;
712 case MSG_EXT_WDTR:
713 default:
714 aic_sched_msgout(aic, MSG_MESSAGE_REJECT);
715 break;
717 break;
718 case MSG_DISCONNECT:
719 scb = aic->nexus;
720 ccb_h = &scb->ccb->ccb_h;
721 TAILQ_INSERT_TAIL(&aic->nexus_ccbs, ccb_h, sim_links.tqe);
722 scb->flags |= SCB_DISCONNECTED;
723 aic->flags |= AIC_BUSFREE_OK;
724 aic->nexus = NULL;
725 CAM_DEBUG(ccb_h->path, CAM_DEBUG_TRACE, ("disconnected\n"));
726 break;
727 case MSG_MESSAGE_REJECT:
728 switch (aic->msg_outq & -aic->msg_outq) {
729 case AIC_MSG_TAG_Q:
730 scb = aic->nexus;
731 ti = &aic->tinfo[scb->target];
732 ti->flags &= ~TINFO_TAG_ENB;
733 ti->lubusy |= 1 << scb->lun;
734 break;
735 case AIC_MSG_SDTR:
736 scb = aic->nexus;
737 ti = &aic->tinfo[scb->target];
738 ti->current.period = ti->goal.period = 0;
739 ti->current.offset = ti->goal.offset = 0;
740 ti->flags &= ~(TINFO_SDTR_SENT|TINFO_SDTR_NEGO);
741 ti->scsirate = 0;
742 aic_outb(aic, SCSIRATE, ti->scsirate);
743 memset(&neg, 0, sizeof (neg));
744 neg.protocol = PROTO_SCSI;
745 neg.protocol_version = SCSI_REV_2;
746 neg.transport = XPORT_SPI;
747 neg.transport_version = 2;
748 spi->sync_period = ti->current.period;
749 spi->sync_offset = ti->current.offset;
750 spi->valid = CTS_SPI_VALID_SYNC_RATE
751 | CTS_SPI_VALID_SYNC_OFFSET;
752 ccb_h = &scb->ccb->ccb_h;
753 xpt_setup_ccb(&neg.ccb_h, ccb_h->path, 1);
754 xpt_async(AC_TRANSFER_NEG, ccb_h->path, &neg);
755 break;
756 default:
757 break;
759 break;
760 case MSG_SAVEDATAPOINTER:
761 break;
762 case MSG_RESTOREPOINTERS:
763 break;
764 case MSG_NOOP:
765 break;
766 default:
767 aic_sched_msgout(aic, MSG_MESSAGE_REJECT);
768 break;
773 * Send messages.
775 static void
776 aic_msgout(struct aic_softc *aic)
778 struct aic_scb *scb;
779 union ccb *ccb;
780 struct aic_tinfo *ti;
781 int msgidx = 0;
783 CAM_DEBUG_PRINT(CAM_DEBUG_TRACE, ("aic_msgout\n"));
785 aic_outb(aic, SIMODE1, ENSCSIRST|ENPHASEMIS|ENBUSFREE);
786 aic_outb(aic, SXFRCTL0, CHEN|SPIOEN);
789 * If the previous phase is also the message out phase,
790 * we need to retransmit all the messages, probably
791 * because the target has detected a parity error during
792 * the past transmission.
794 if (aic->prev_phase == PH_MSGOUT)
795 aic->msg_outq = aic->msg_sent;
797 do {
798 int q = aic->msg_outq;
799 if (msgidx > 0 && msgidx == aic->msg_len) {
800 /* complete message sent, start the next one */
801 q &= -q;
802 aic->msg_sent |= q;
803 aic->msg_outq ^= q;
804 q = aic->msg_outq;
805 msgidx = 0;
807 if (msgidx == 0) {
808 /* setup the message */
809 switch (q & -q) {
810 case AIC_MSG_IDENTIFY:
811 scb = aic->nexus;
812 ccb = scb->ccb;
813 ti = &aic->tinfo[scb->target];
814 aic->msg_buf[0] = MSG_IDENTIFY(scb->lun,
815 (ti->flags & TINFO_DISC_ENB) &&
816 !(ccb->ccb_h.flags & CAM_DIS_DISCONNECT));
817 aic->msg_len = 1;
818 break;
819 case AIC_MSG_TAG_Q:
820 scb = aic->nexus;
821 ccb = scb->ccb;
822 aic->msg_buf[0] = ccb->csio.tag_action;
823 aic->msg_buf[1] = scb->tag;
824 aic->msg_len = 2;
825 break;
826 case AIC_MSG_SDTR:
827 scb = aic->nexus;
828 ti = &aic->tinfo[scb->target];
829 aic->msg_buf[0] = MSG_EXTENDED;
830 aic->msg_buf[1] = MSG_EXT_SDTR_LEN;
831 aic->msg_buf[2] = MSG_EXT_SDTR;
832 aic->msg_buf[3] = ti->goal.period;
833 aic->msg_buf[4] = ti->goal.offset;
834 aic->msg_len = MSG_EXT_SDTR_LEN + 2;
835 ti->flags |= TINFO_SDTR_SENT;
836 break;
837 case AIC_MSG_MSGBUF:
838 /* a single message already in the buffer */
839 if (aic->msg_buf[0] == MSG_BUS_DEV_RESET ||
840 aic->msg_buf[0] == MSG_ABORT ||
841 aic->msg_buf[0] == MSG_ABORT_TAG)
842 aic->flags |= AIC_BUSFREE_OK;
843 break;
847 * If this is the last message byte of all messages,
848 * clear ATNO to signal transmission complete.
850 if ((q & (q - 1)) == 0 && msgidx == aic->msg_len - 1)
851 aic_outb(aic, CLRSINT1, CLRATNO);
852 /* transmit the message byte */
853 aic_outb(aic, SCSIDAT, aic->msg_buf[msgidx++]);
854 } while (aic_spiordy(aic));
856 aic_outb(aic, SXFRCTL0, CHEN);
857 aic_outb(aic, SIMODE1, ENSCSIRST|ENBUSFREE|ENREQINIT);
861 * Read data bytes.
863 static void
864 aic_datain(struct aic_softc *aic)
866 struct aic_scb *scb = aic->nexus;
867 u_int8_t dmastat, dmacntrl0;
868 int n;
870 CAM_DEBUG_PRINT(CAM_DEBUG_TRACE, ("aic_datain\n"));
872 aic_outb(aic, SIMODE1, ENSCSIRST|ENPHASEMIS|ENBUSFREE);
873 aic_outb(aic, SXFRCTL0, SCSIEN|DMAEN|CHEN);
875 dmacntrl0 = ENDMA;
876 if (aic->flags & AIC_DWIO_ENABLE)
877 dmacntrl0 |= DWORDPIO;
878 aic_outb(aic, DMACNTRL0, dmacntrl0);
880 while (scb->data_len > 0) {
881 for (;;) {
882 /* wait for the fifo to fill up or a phase change */
883 dmastat = aic_inb(aic, DMASTAT);
884 if (dmastat & (INTSTAT|DFIFOFULL))
885 break;
887 if (dmastat & DFIFOFULL) {
888 n = FIFOSIZE;
889 } else {
891 * No more data, wait for the remaining bytes in
892 * the scsi fifo to be transfer to the host fifo.
894 while (!(aic_inb(aic, SSTAT2) & SEMPTY))
896 n = aic_inb(aic, FIFOSTAT);
898 n = imin(scb->data_len, n);
899 if (aic->flags & AIC_DWIO_ENABLE) {
900 if (n >= 12) {
901 aic_insl(aic, DMADATALONG, scb->data_ptr, n>>2);
902 scb->data_ptr += n & ~3;
903 scb->data_len -= n & ~3;
904 n &= 3;
906 } else {
907 if (n >= 8) {
908 aic_insw(aic, DMADATA, scb->data_ptr, n >> 1);
909 scb->data_ptr += n & ~1;
910 scb->data_len -= n & ~1;
911 n &= 1;
914 if (n) {
915 aic_outb(aic, DMACNTRL0, ENDMA|B8MODE);
916 aic_insb(aic, DMADATA, scb->data_ptr, n);
917 scb->data_ptr += n;
918 scb->data_len -= n;
919 aic_outb(aic, DMACNTRL0, dmacntrl0);
922 if (dmastat & INTSTAT)
923 break;
926 aic_outb(aic, SXFRCTL0, CHEN);
927 aic_outb(aic, SIMODE1, ENSCSIRST|ENBUSFREE|ENREQINIT);
931 * Send data bytes.
933 static void
934 aic_dataout(struct aic_softc *aic)
936 struct aic_scb *scb = aic->nexus;
937 u_int8_t dmastat, dmacntrl0, sstat2;
938 int n;
940 CAM_DEBUG_PRINT(CAM_DEBUG_TRACE, ("aic_dataout\n"));
942 aic_outb(aic, SIMODE1, ENSCSIRST|ENPHASEMIS|ENBUSFREE);
943 aic_outb(aic, SXFRCTL0, SCSIEN|DMAEN|CHEN);
945 dmacntrl0 = ENDMA|WRITE;
946 if (aic->flags & AIC_DWIO_ENABLE)
947 dmacntrl0 |= DWORDPIO;
948 aic_outb(aic, DMACNTRL0, dmacntrl0);
950 while (scb->data_len > 0) {
951 for (;;) {
952 /* wait for the fifo to clear up or a phase change */
953 dmastat = aic_inb(aic, DMASTAT);
954 if (dmastat & (INTSTAT|DFIFOEMP))
955 break;
957 if (dmastat & INTSTAT)
958 break;
959 n = imin(scb->data_len, FIFOSIZE);
960 if (aic->flags & AIC_DWIO_ENABLE) {
961 if (n >= 12) {
962 aic_outsl(aic, DMADATALONG, scb->data_ptr,n>>2);
963 scb->data_ptr += n & ~3;
964 scb->data_len -= n & ~3;
965 n &= 3;
967 } else {
968 if (n >= 8) {
969 aic_outsw(aic, DMADATA, scb->data_ptr, n >> 1);
970 scb->data_ptr += n & ~1;
971 scb->data_len -= n & ~1;
972 n &= 1;
975 if (n) {
976 aic_outb(aic, DMACNTRL0, ENDMA|WRITE|B8MODE);
977 aic_outsb(aic, DMADATA, scb->data_ptr, n);
978 scb->data_ptr += n;
979 scb->data_len -= n;
980 aic_outb(aic, DMACNTRL0, dmacntrl0);
984 for (;;) {
985 /* wait until all bytes in the fifos are transmitted */
986 dmastat = aic_inb(aic, DMASTAT);
987 sstat2 = aic_inb(aic, SSTAT2);
988 if ((dmastat & DFIFOEMP) && (sstat2 & SEMPTY))
989 break;
990 if (dmastat & INTSTAT) {
991 /* adjust for untransmitted bytes */
992 n = aic_inb(aic, FIFOSTAT) + (sstat2 & 0xf);
993 scb->data_ptr -= n;
994 scb->data_len += n;
995 /* clear the fifo */
996 aic_outb(aic, SXFRCTL0, CHEN|CLRCH);
997 aic_outb(aic, DMACNTRL0, RSTFIFO);
998 break;
1002 aic_outb(aic, SXFRCTL0, CHEN);
1003 aic_outb(aic, SIMODE1, ENSCSIRST|ENBUSFREE|ENREQINIT);
1007 * Send the scsi command.
1009 static void
1010 aic_cmd(struct aic_softc *aic)
1012 struct aic_scb *scb = aic->nexus;
1013 struct scsi_request_sense sense_cmd;
1015 CAM_DEBUG_PRINT(CAM_DEBUG_TRACE, ("aic_cmd\n"));
1017 if (scb->flags & SCB_SENSE) {
1018 /* autosense request */
1019 sense_cmd.opcode = REQUEST_SENSE;
1020 sense_cmd.byte2 = scb->lun << 5;
1021 sense_cmd.length = scb->ccb->csio.sense_len;
1022 sense_cmd.control = 0;
1023 sense_cmd.unused[0] = 0;
1024 sense_cmd.unused[1] = 0;
1025 scb->cmd_ptr = (u_int8_t *)&sense_cmd;
1026 scb->cmd_len = sizeof(sense_cmd);
1027 scb->data_ptr = (u_int8_t *)&scb->ccb->csio.sense_data;
1028 scb->data_len = scb->ccb->csio.sense_len;
1031 aic_outb(aic, SIMODE1, ENSCSIRST|ENPHASEMIS|ENBUSFREE);
1032 aic_outb(aic, DMACNTRL0, ENDMA|WRITE);
1033 aic_outb(aic, SXFRCTL0, SCSIEN|DMAEN|CHEN);
1034 aic_outsw(aic, DMADATA, (u_int16_t *)scb->cmd_ptr, scb->cmd_len >> 1);
1035 while ((aic_inb(aic, SSTAT2) & SEMPTY) == 0 &&
1036 (aic_inb(aic, DMASTAT) & INTSTAT) == 0)
1038 aic_outb(aic, SXFRCTL0, CHEN);
1039 aic_outb(aic, SIMODE1, ENSCSIRST|ENBUSFREE|ENREQINIT);
1043 * Finish off a command. The caller is responsible to remove the ccb
1044 * from any queue.
1046 static void
1047 aic_done(struct aic_softc *aic, struct aic_scb *scb)
1049 union ccb *ccb = scb->ccb;
1051 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
1052 ("aic_done - ccb %p status %x resid %d\n",
1053 ccb, ccb->ccb_h.status, ccb->csio.resid));
1055 callout_stop(&ccb->ccb_h.timeout_ch);
1057 if ((scb->flags & SCB_DEVICE_RESET) != 0 &&
1058 ccb->ccb_h.func_code != XPT_RESET_DEV) {
1059 struct cam_path *path;
1060 struct ccb_hdr *ccb_h;
1061 cam_status error;
1063 error = xpt_create_path(&path, /*periph*/NULL,
1064 cam_sim_path(aic->sim),
1065 scb->target,
1066 CAM_LUN_WILDCARD);
1068 if (error == CAM_REQ_CMP) {
1069 xpt_async(AC_SENT_BDR, path, NULL);
1070 xpt_free_path(path);
1073 ccb_h = TAILQ_FIRST(&aic->pending_ccbs);
1074 while (ccb_h != NULL) {
1075 struct aic_scb *pending_scb;
1077 pending_scb = (struct aic_scb *)ccb_h->ccb_scb_ptr;
1078 if (ccb_h->target_id == scb->target) {
1079 ccb_h->status |= CAM_BDR_SENT;
1080 ccb_h = TAILQ_NEXT(ccb_h, sim_links.tqe);
1081 TAILQ_REMOVE(&aic->pending_ccbs,
1082 &pending_scb->ccb->ccb_h, sim_links.tqe);
1083 aic_done(aic, pending_scb);
1084 } else {
1085 callout_reset(&ccb_h->timeout_ch,
1086 (ccb_h->timeout * hz) / 1000,
1087 aic_timeout, pending_scb);
1088 ccb_h = TAILQ_NEXT(ccb_h, sim_links.tqe);
1092 ccb_h = TAILQ_FIRST(&aic->nexus_ccbs);
1093 while (ccb_h != NULL) {
1094 struct aic_scb *nexus_scb;
1096 nexus_scb = (struct aic_scb *)ccb_h->ccb_scb_ptr;
1097 if (ccb_h->target_id == scb->target) {
1098 ccb_h->status |= CAM_BDR_SENT;
1099 ccb_h = TAILQ_NEXT(ccb_h, sim_links.tqe);
1100 TAILQ_REMOVE(&aic->nexus_ccbs,
1101 &nexus_scb->ccb->ccb_h, sim_links.tqe);
1102 aic_done(aic, nexus_scb);
1103 } else {
1104 callout_reset(&ccb_h->timeout_ch,
1105 (ccb_h->timeout * hz) / 1000,
1106 aic_timeout, nexus_scb);
1107 ccb_h = TAILQ_NEXT(ccb_h, sim_links.tqe);
1112 if (aic->nexus == scb || scb->flags & SCB_DISCONNECTED)
1113 aic->tinfo[scb->target].lubusy &= ~(1 << scb->lun);
1115 if (aic->nexus == scb) {
1116 aic->nexus = NULL;
1118 aic_free_scb(aic, scb);
1119 xpt_done(ccb);
1122 static void
1123 aic_poll(struct cam_sim *sim)
1125 aic_intr(cam_sim_softc(sim));
1128 static void
1129 aic_timeout(void *arg)
1131 struct aic_scb *scb = (struct aic_scb *)arg;
1132 union ccb *ccb = scb->ccb;
1133 struct aic_softc *aic = (struct aic_softc *)ccb->ccb_h.ccb_aic_ptr;
1135 xpt_print_path(ccb->ccb_h.path);
1136 kprintf("ccb %p - timed out", ccb);
1137 if (aic->nexus && aic->nexus != scb)
1138 kprintf(", nexus %p", aic->nexus->ccb);
1139 kprintf(", phase 0x%x, state %d\n", aic_inb(aic, SCSISIGI), aic->state);
1141 crit_enter();
1143 if ((scb->flags & SCB_ACTIVE) == 0) {
1144 crit_exit();
1145 xpt_print_path(ccb->ccb_h.path);
1146 kprintf("ccb %p - timed out already completed\n", ccb);
1147 return;
1150 if ((scb->flags & SCB_DEVICE_RESET) == 0 && aic->nexus == scb) {
1151 struct ccb_hdr *ccb_h = &scb->ccb->ccb_h;
1153 if ((ccb_h->status & CAM_RELEASE_SIMQ) == 0) {
1154 xpt_freeze_simq(aic->sim, /*count*/1);
1155 ccb_h->status |= CAM_RELEASE_SIMQ;
1158 TAILQ_FOREACH(ccb_h, &aic->pending_ccbs, sim_links.tqe)
1159 callout_stop(&ccb_h->timeout_ch);
1161 TAILQ_FOREACH(ccb_h, &aic->nexus_ccbs, sim_links.tqe)
1162 callout_stop(&ccb_h->timeout_ch);
1164 scb->flags |= SCB_DEVICE_RESET;
1165 callout_reset(&ccb->ccb_h.timeout_ch, 5 * hz, aic_timeout, scb);
1166 aic_sched_msgout(aic, MSG_BUS_DEV_RESET);
1167 } else {
1168 if (aic->nexus == scb) {
1169 ccb->ccb_h.status |= CAM_CMD_TIMEOUT;
1170 aic_done(aic, scb);
1172 aic_reset(aic, /*initiate_reset*/TRUE);
1175 crit_exit();
1178 void
1179 aic_intr(void *arg)
1181 struct aic_softc *aic = (struct aic_softc *)arg;
1182 u_int8_t sstat0, sstat1;
1183 union ccb *ccb;
1184 struct aic_scb *scb;
1186 if (!(aic_inb(aic, DMASTAT) & INTSTAT))
1187 return;
1189 aic_outb(aic, DMACNTRL0, 0);
1191 sstat0 = aic_inb(aic, SSTAT0);
1192 sstat1 = aic_inb(aic, SSTAT1);
1194 if ((sstat1 & SCSIRSTI) != 0) {
1195 /* a device-initiated bus reset */
1196 aic_outb(aic, CLRSINT1, CLRSCSIRSTI);
1197 aic_reset(aic, /*initiate_reset*/FALSE);
1198 return;
1201 if ((sstat1 & SCSIPERR) != 0) {
1202 aic_outb(aic, CLRSINT1, CLRSCSIPERR);
1203 aic_sched_msgout(aic, MSG_PARITY_ERROR);
1204 aic_outb(aic, DMACNTRL0, INTEN);
1205 return;
1208 if (aic_inb(aic, SSTAT4)) {
1209 aic_outb(aic, CLRSERR, CLRSYNCERR|CLRFWERR|CLRFRERR);
1210 aic_reset(aic, /*initiate_reset*/TRUE);
1211 return;
1214 if (aic->state <= AIC_SELECTING) {
1215 if ((sstat0 & SELDI) != 0) {
1216 aic_reselected(aic);
1217 aic_outb(aic, DMACNTRL0, INTEN);
1218 return;
1221 if ((sstat0 & SELDO) != 0) {
1222 aic_selected(aic);
1223 aic_outb(aic, DMACNTRL0, INTEN);
1224 return;
1227 if ((sstat1 & SELTO) != 0) {
1228 scb = aic->nexus;
1229 ccb = scb->ccb;
1230 ccb->ccb_h.status = CAM_SEL_TIMEOUT;
1231 aic_done(aic, scb);
1232 while ((sstat1 & BUSFREE) == 0)
1233 sstat1 = aic_inb(aic, SSTAT1);
1234 aic->flags |= AIC_BUSFREE_OK;
1238 if ((sstat1 & BUSFREE) != 0) {
1239 aic_outb(aic, SCSISEQ, 0);
1240 aic_outb(aic, CLRSINT0, sstat0);
1241 aic_outb(aic, CLRSINT1, sstat1);
1242 if ((scb = aic->nexus)) {
1243 if ((aic->flags & AIC_BUSFREE_OK) == 0) {
1244 ccb = scb->ccb;
1245 ccb->ccb_h.status = CAM_UNEXP_BUSFREE;
1246 aic_done(aic, scb);
1247 } else if (scb->flags & SCB_DEVICE_RESET) {
1248 ccb = scb->ccb;
1249 if (ccb->ccb_h.func_code == XPT_RESET_DEV) {
1250 xpt_async(AC_SENT_BDR,
1251 ccb->ccb_h.path, NULL);
1252 ccb->ccb_h.status |= CAM_REQ_CMP;
1253 } else
1254 ccb->ccb_h.status |= CAM_CMD_TIMEOUT;
1255 aic_done(aic, scb);
1256 } else if (scb->flags & SCB_SENSE) {
1257 /* autosense request */
1258 aic->flags &= ~AIC_BUSFREE_OK;
1259 aic->tinfo[scb->target].lubusy &=
1260 ~(1 << scb->lun);
1261 aic_select(aic);
1262 aic_outb(aic, DMACNTRL0, INTEN);
1263 return;
1266 aic->flags &= ~AIC_BUSFREE_OK;
1267 aic->state = AIC_IDLE;
1268 aic_start(aic);
1269 aic_outb(aic, DMACNTRL0, INTEN);
1270 return;
1273 if ((sstat1 & REQINIT) != 0) {
1274 u_int8_t phase = aic_inb(aic, SCSISIGI) & PH_MASK;
1275 aic_outb(aic, SCSISIGO, phase);
1276 aic_outb(aic, CLRSINT1, CLRPHASECHG);
1278 switch (phase) {
1279 case PH_MSGOUT:
1280 aic_msgout(aic);
1281 break;
1282 case PH_MSGIN:
1283 aic_msgin(aic);
1284 break;
1285 case PH_STAT:
1286 scb = aic->nexus;
1287 ccb = scb->ccb;
1288 aic_outb(aic, DMACNTRL0, 0);
1289 aic_outb(aic, SXFRCTL0, CHEN|SPIOEN);
1290 scb->status = aic_inb(aic, SCSIDAT);
1291 aic_outb(aic, SXFRCTL0, CHEN);
1292 break;
1293 case PH_CMD:
1294 aic_cmd(aic);
1295 break;
1296 case PH_DATAIN:
1297 aic_datain(aic);
1298 break;
1299 case PH_DATAOUT:
1300 aic_dataout(aic);
1301 break;
1303 aic->prev_phase = phase;
1304 aic_outb(aic, DMACNTRL0, INTEN);
1305 return;
1308 kprintf("aic_intr: unexpected intr sstat0 %x sstat1 %x\n",
1309 sstat0, sstat1);
1310 aic_outb(aic, DMACNTRL0, INTEN);
1314 * Reset ourselves.
1316 static void
1317 aic_chip_reset(struct aic_softc *aic)
1320 * Doc. recommends to clear these two registers before
1321 * operations commence
1323 aic_outb(aic, SCSITEST, 0);
1324 aic_outb(aic, TEST, 0);
1326 /* Reset SCSI-FIFO and abort any transfers */
1327 aic_outb(aic, SXFRCTL0, CHEN|CLRCH|CLRSTCNT);
1329 /* Reset HOST-FIFO */
1330 aic_outb(aic, DMACNTRL0, RSTFIFO);
1331 aic_outb(aic, DMACNTRL1, 0);
1333 /* Disable all selection features */
1334 aic_outb(aic, SCSISEQ, 0);
1335 aic_outb(aic, SXFRCTL1, 0);
1337 /* Disable interrupts */
1338 aic_outb(aic, SIMODE0, 0);
1339 aic_outb(aic, SIMODE1, 0);
1341 /* Clear interrupts */
1342 aic_outb(aic, CLRSINT0, 0x7f);
1343 aic_outb(aic, CLRSINT1, 0xef);
1345 /* Disable synchronous transfers */
1346 aic_outb(aic, SCSIRATE, 0);
1348 /* Haven't seen ant errors (yet) */
1349 aic_outb(aic, CLRSERR, 0x07);
1351 /* Set our SCSI-ID */
1352 aic_outb(aic, SCSIID, aic->initiator << OID_S);
1353 aic_outb(aic, BRSTCNTRL, EISA_BRST_TIM);
1357 * Reset the SCSI bus
1359 static void
1360 aic_scsi_reset(struct aic_softc *aic)
1362 aic_outb(aic, SCSISEQ, SCSIRSTO);
1363 DELAY(500);
1364 aic_outb(aic, SCSISEQ, 0);
1365 DELAY(50);
1369 * Reset. Abort all pending commands.
1371 static void
1372 aic_reset(struct aic_softc *aic, int initiate_reset)
1374 struct ccb_hdr *ccb_h;
1376 CAM_DEBUG_PRINT(CAM_DEBUG_TRACE, ("aic_reset\n"));
1378 if (initiate_reset)
1379 aic_scsi_reset(aic);
1380 aic_chip_reset(aic);
1382 xpt_async(AC_BUS_RESET, aic->path, NULL);
1384 while ((ccb_h = TAILQ_FIRST(&aic->pending_ccbs)) != NULL) {
1385 TAILQ_REMOVE(&aic->pending_ccbs, ccb_h, sim_links.tqe);
1386 ccb_h->status |= CAM_SCSI_BUS_RESET;
1387 aic_done(aic, (struct aic_scb *)ccb_h->ccb_scb_ptr);
1390 while ((ccb_h = TAILQ_FIRST(&aic->nexus_ccbs)) != NULL) {
1391 TAILQ_REMOVE(&aic->nexus_ccbs, ccb_h, sim_links.tqe);
1392 ccb_h->status |= CAM_SCSI_BUS_RESET;
1393 aic_done(aic, (struct aic_scb *)ccb_h->ccb_scb_ptr);
1396 if (aic->nexus) {
1397 ccb_h = &aic->nexus->ccb->ccb_h;
1398 ccb_h->status |= CAM_SCSI_BUS_RESET;
1399 aic_done(aic, aic->nexus);
1402 aic->state = AIC_IDLE;
1403 aic_outb(aic, DMACNTRL0, INTEN);
1406 static char *aic_chip_names[] = {
1407 "AIC6260", "AIC6360", "AIC6370", "GM82C700",
1410 static struct {
1411 int type;
1412 char *idstring;
1413 } aic_chip_ids[] = {
1414 { AIC6360, IDSTRING_AIC6360 },
1415 { AIC6370, IDSTRING_AIC6370 },
1416 { GM82C700, IDSTRING_GM82C700 },
1419 static void
1420 aic_init(struct aic_softc *aic)
1422 struct aic_scb *scb;
1423 struct aic_tinfo *ti;
1424 u_int8_t porta, portb;
1425 char chip_id[33];
1426 int i;
1428 TAILQ_INIT(&aic->pending_ccbs);
1429 TAILQ_INIT(&aic->nexus_ccbs);
1430 aic->nexus = NULL;
1431 aic->state = AIC_IDLE;
1432 aic->prev_phase = -1;
1433 aic->flags = 0;
1435 aic_chip_reset(aic);
1436 aic_scsi_reset(aic);
1438 /* determine the chip type from its ID string */
1439 aic->chip_type = AIC6260;
1440 aic_insb(aic, ID, chip_id, sizeof(chip_id) - 1);
1441 chip_id[sizeof(chip_id) - 1] = '\0';
1442 for (i = 0; i < sizeof(aic_chip_ids) / sizeof(aic_chip_ids[0]); i++) {
1443 if (!strcmp(chip_id, aic_chip_ids[i].idstring)) {
1444 aic->chip_type = aic_chip_ids[i].type;
1445 break;
1449 porta = aic_inb(aic, PORTA);
1450 portb = aic_inb(aic, PORTB);
1452 aic->initiator = PORTA_ID(porta);
1453 if (PORTA_PARITY(porta))
1454 aic->flags |= AIC_PARITY_ENABLE;
1455 if (PORTB_DISC(portb))
1456 aic->flags |= AIC_DISC_ENABLE;
1457 if (PORTB_DMA(portb))
1458 aic->flags |= AIC_DMA_ENABLE;
1461 * We can do fast SCSI (10MHz clock rate) if bit 4 of portb
1462 * is set and we've got a 6360. The 6260 can only do standard
1463 * 5MHz SCSI.
1465 if (aic->chip_type > AIC6260 || aic_inb(aic, REV)) {
1466 if (PORTB_FSYNC(portb))
1467 aic->flags |= AIC_FAST_ENABLE;
1468 aic->flags |= AIC_DWIO_ENABLE;
1471 if (aic->flags & AIC_FAST_ENABLE)
1472 aic->max_period = AIC_FAST_SYNC_PERIOD;
1473 else
1474 aic->max_period = AIC_SYNC_PERIOD;
1475 aic->min_period = AIC_MIN_SYNC_PERIOD;
1477 free_scbs = NULL;
1478 for (i = 255; i >= 0; i--) {
1479 scb = &aic->scbs[i];
1480 scb->tag = i;
1481 aic_free_scb(aic, scb);
1484 for (i = 0; i < 8; i++) {
1485 if (i == aic->initiator)
1486 continue;
1487 ti = &aic->tinfo[i];
1488 bzero(ti, sizeof(*ti));
1489 ti->flags = TINFO_TAG_ENB;
1490 if (aic->flags & AIC_DISC_ENABLE)
1491 ti->flags |= TINFO_DISC_ENB;
1492 ti->user.period = aic->max_period;
1493 ti->user.offset = AIC_SYNC_OFFSET;
1494 ti->scsirate = 0;
1497 aic_outb(aic, DMACNTRL0, INTEN);
1501 aic_probe(struct aic_softc *aic)
1503 int i;
1505 /* Remove aic6360 from possible powerdown mode */
1506 aic_outb(aic, DMACNTRL0, 0);
1508 #define STSIZE 16
1509 aic_outb(aic, DMACNTRL1, 0); /* Reset stack pointer */
1510 for (i = 0; i < STSIZE; i++)
1511 aic_outb(aic, STACK, i);
1513 /* See if we can pull out the same sequence */
1514 aic_outb(aic, DMACNTRL1, 0);
1515 for (i = 0; i < STSIZE && aic_inb(aic, STACK) == i; i++)
1517 if (i != STSIZE)
1518 return (ENXIO);
1519 #undef STSIZE
1520 return (0);
1524 aic_attach(struct aic_softc *aic)
1527 * Construct our SIM entry
1529 aic->sim = cam_sim_alloc(aic_action, aic_poll, "aic", aic,
1530 aic->unit, 2, 256, NULL);
1531 if (aic->sim == NULL)
1532 return (ENOMEM);
1534 if (xpt_bus_register(aic->sim, 0) != CAM_SUCCESS) {
1535 cam_sim_free(aic->sim);
1536 return (ENXIO);
1539 if (xpt_create_path(&aic->path, /*periph*/NULL,
1540 cam_sim_path(aic->sim), CAM_TARGET_WILDCARD,
1541 CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
1542 xpt_bus_deregister(cam_sim_path(aic->sim));
1543 cam_sim_free(aic->sim);
1544 return (ENXIO);
1547 aic_init(aic);
1549 kprintf("aic%d: %s", aic->unit, aic_chip_names[aic->chip_type]);
1550 if (aic->flags & AIC_DMA_ENABLE)
1551 kprintf(", dma");
1552 if (aic->flags & AIC_DISC_ENABLE)
1553 kprintf(", disconnection");
1554 if (aic->flags & AIC_PARITY_ENABLE)
1555 kprintf(", parity check");
1556 if (aic->flags & AIC_FAST_ENABLE)
1557 kprintf(", fast SCSI");
1558 kprintf("\n");
1559 return (0);
1563 aic_detach(struct aic_softc *aic)
1565 xpt_async(AC_LOST_DEVICE, aic->path, NULL);
1566 xpt_free_path(aic->path);
1567 xpt_bus_deregister(cam_sim_path(aic->sim));
1568 cam_sim_free(aic->sim);
1569 return (0);