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