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