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