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