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