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