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