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