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