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