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