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