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