Initial import from FreeBSD RELENG_4:
[dragonfly.git] / sys / dev / disk / i386 / bs / bsfunc.c
1 /*      $NecBSD: bsfunc.c,v 1.2 1997/10/31 17:43:37 honda Exp $ */
2 /*      $NetBSD$        */
3 /* $FreeBSD: src/sys/i386/isa/bs/bsfunc.c,v 1.7.2.2 2001/07/26 02:32:18 nyan Exp $ */
4 /*
5  * [NetBSD for NEC PC98 series]
6  *  Copyright (c) 1994, 1995, 1996 NetBSD/pc98 porting staff.
7  *  All rights reserved.
8  * 
9  *  Redistribution and use in source and binary forms, with or without
10  *  modification, are permitted provided that the following conditions
11  *  are met:
12  *  1. Redistributions of source code must retain the above copyright
13  *     notice, this list of conditions and the following disclaimer.
14  *  2. Redistributions in binary form must reproduce the above copyright
15  *     notice, this list of conditions and the following disclaimer in the
16  *     documentation and/or other materials provided with the distribution.
17  *  3. The name of the author may not be used to endorse or promote products
18  *     derived from this software without specific prior written permission.
19  * 
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
24  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 /*
33  * Copyright (c) 1994, 1995, 1996 Naofumi HONDA.  All rights reserved.
34  */
35
36 #ifdef  __NetBSD__
37 #include <i386/Cbus/dev/bs/bsif.h>
38 #endif
39 #ifdef  __FreeBSD__
40 #include <i386/isa/bs/bsif.h>
41 #endif
42
43 #ifdef  BS_STATICS
44 struct bs_statics bs_statics[NTARGETS];
45 u_int bs_linkcmd_count[NTARGETS];
46 u_int bs_bounce_used[NTARGETS];
47 #endif  /* BS_STATICS */
48
49 #ifdef  BS_DEBUG
50 int bs_debug_flag = 0;
51 #endif  /* BS_DEBUG */
52
53 static void bs_print_syncmsg __P((struct targ_info *, char*));
54 static void bs_timeout_target __P((struct targ_info *));
55 static void bs_kill_msg __P((struct bsccb *cb));
56
57 static int bs_start_target __P((struct targ_info *));
58 static int bs_check_target __P((struct targ_info *));
59
60 /*************************************************************
61  * CCB
62  ************************************************************/
63 GENERIC_CCB_STATIC_ALLOC(bs, bsccb)
64 GENERIC_CCB(bs, bsccb, ccb_chain)
65
66 /*************************************************************
67  * TIMEOUT
68  ************************************************************/
69 static void
70 bs_timeout_target(ti)
71         struct targ_info *ti;
72 {
73         struct bs_softc *bsc = ti->ti_bsc;
74
75         ti->ti_error |= BSTIMEOUT;
76         bsc->sc_flags |= BSRESET;
77
78         if (ti->ti_herrcnt ++ >= HARDRETRIES)
79         {
80                 bs_printf(ti, "timeout", "async transfer!");
81                 ti->ti_syncmax.period = ti->ti_syncmax.offset = 0;
82         }
83 }
84
85 void
86 bstimeout(arg)
87         void *arg;
88 {
89         struct bs_softc *bsc = (struct bs_softc *) arg;
90         struct targ_info *ti;
91         struct bsccb *cb;
92         int s;
93
94         s = splcam();
95         bsc->sc_flags &= ~BSSTARTTIMEOUT;
96
97         /* check */
98         if ((ti = bsc->sc_nexus) && (cb = ti->ti_ctab.tqh_first))
99         {
100                 if ((cb->tc -= BS_TIMEOUT_CHECK_INTERVAL) < 0)
101                         bs_timeout_target(ti);
102         }
103         else for (ti = bsc->sc_titab.tqh_first; ti; ti = ti->ti_tchain.tqe_next)
104         {
105                 if (bsc->sc_dtgnum && ti->ti_phase < DISCONNECTED)
106                         continue;
107
108                 cb = ti->ti_ctab.tqh_first;
109                 if (cb && ((cb->tc -= BS_TIMEOUT_CHECK_INTERVAL) < 0))
110                         bs_timeout_target(ti);
111         }
112
113         /* try to recover */
114         if (bsc->sc_flags & BSRESET)
115         {
116                 bs_debug_print_all(bsc);
117                 bs_printf(ti, "timeout", "bus hang up");
118                 bs_reset_nexus(bsc);
119         }
120
121         bs_start_timeout(bsc);
122         splx(s);
123 }
124
125 /**************************************************
126  * MAKE CCB & MSG CCB
127  *************************************************/
128 static u_int8_t cmd_unit_ready[6];
129
130 struct bsccb *
131 bs_make_internal_ccb(ti, lun, cmd, cmdlen, data, datalen, flags, timeout)
132         struct targ_info *ti;
133         u_int lun;
134         u_int8_t *cmd;
135         u_int cmdlen;
136         u_int8_t *data;
137         u_int datalen;
138         u_int flags;
139         int timeout;
140 {
141         struct bsccb *cb;
142
143         if ((cb = bs_get_ccb()) == NULL)
144                 bs_panic(ti->ti_bsc, "can not get ccb mem");
145
146         cb->ccb = NULL;
147         cb->lun = lun;
148         cb->cmd = (cmd ? cmd : cmd_unit_ready);
149         cb->cmdlen = (cmd ? cmdlen : sizeof(cmd_unit_ready));
150         cb->data = data;
151         cb->datalen = (data ? datalen : 0);
152         cb->msgoutlen = 0;
153         cb->bsccb_flags = flags & BSCFLAGSMASK;
154         bs_targ_flags(ti, cb);
155         cb->rcnt = 0;
156         cb->tcmax = (timeout > BS_DEFAULT_TIMEOUT_SECOND ? timeout :
157                                 BS_DEFAULT_TIMEOUT_SECOND);
158
159         TAILQ_INSERT_HEAD(&ti->ti_ctab, cb, ccb_chain);
160
161         return cb;
162 }
163
164 struct bsccb *
165 bs_make_msg_ccb(ti, lun, cb, msg, timex)
166         struct targ_info *ti;
167         u_int lun;
168         struct bsccb *cb;
169         struct msgbase *msg;
170         u_int timex;
171 {
172         u_int flags;
173
174         flags = BSFORCEIOPOLL | msg->flag;
175         if (cb == NULL)
176                 cb = bs_make_internal_ccb(ti, lun, NULL, 0, NULL, 0,
177                                            flags, timex);
178         else
179                 cb->bsccb_flags |= flags & BSCFLAGSMASK;
180
181         cb->msgoutlen = msg->msglen;
182         bcopy(msg->msg, cb->msgout, msg->msglen);
183         return cb;
184 }
185
186 int
187 bs_send_msg(ti, lun, msg, timex)
188         struct targ_info *ti;
189         u_int lun;
190         struct msgbase *msg;
191         int timex;
192 {
193         struct bsccb *cb;
194
195         cb = bs_make_msg_ccb(ti, lun, NULL, msg, timex);
196         bscmdstart(ti, BSCMDSTART);
197         return bs_scsi_cmd_poll(ti, cb);
198 }
199
200 static void
201 bs_kill_msg(cb)
202         struct bsccb *cb;
203 {
204         cb->msgoutlen = 0;
205 }
206
207 /**************************************************
208  * MAKE SENSE CCB
209  **************************************************/
210 struct bsccb *
211 bs_request_sense(ti)
212         struct targ_info *ti;
213 {
214         struct bsccb *cb;
215
216         bzero(ti->scsi_cmd, sizeof(struct scsi_sense));
217         bzero(&ti->sense, sizeof(struct scsi_sense_data));
218         ti->scsi_cmd[0] = REQUEST_SENSE;
219         ti->scsi_cmd[1] = (ti->ti_lun << 5);
220         ti->scsi_cmd[4] = sizeof(struct scsi_sense_data);
221         cb = bs_make_internal_ccb(ti, ti->ti_lun, ti->scsi_cmd,
222                                      sizeof(struct scsi_sense),
223                                      (u_int8_t *) & ti->sense,
224                                      sizeof(struct scsi_sense_data),
225                                      BSFORCEIOPOLL,
226                                      BS_DEFAULT_TIMEOUT_SECOND);
227         cb->bsccb_flags |= BSSENSECCB;
228         return cb;
229 }
230
231 /**************************************************
232  * SYNC MSG
233  *************************************************/
234 /* sync neg */
235 int
236 bs_start_syncmsg(ti, cb, flag)
237         struct targ_info *ti;
238         struct bsccb *cb;
239         int flag;
240 {
241         struct syncdata *negp, *maxp;
242         struct msgbase msg;
243         u_int lun;
244
245         negp = &ti->ti_syncnow;
246         maxp = &ti->ti_syncmax;
247
248         ti->ti_state = BS_TARG_SYNCH;
249
250         if (flag == BS_SYNCMSG_REQUESTED)
251         {
252                 if (negp->offset > maxp->offset)
253                         negp->offset = maxp->offset;
254                 if (negp->offset != 0 && negp->period < maxp->period)
255                         negp->period = maxp->period;
256
257                 msg.flag = 0;
258                 lun = ti->ti_lun;
259                 if (cb == NULL)
260                         cb = ti->ti_ctab.tqh_first;
261         }
262         else if (ti->ti_cfgflags & BS_SCSI_SYNC)
263         {
264                 negp->offset = maxp->offset;
265                 negp->period = maxp->period;
266
267                 msg.flag = BSERROROK;
268                 lun = 0;
269         }
270         else
271         {
272                 ti->ti_state = BS_TARG_RDY;
273                 return COMPLETE;
274         }
275
276         BS_SETUP_SYNCSTATE(flag);
277         msg.msg[0] = MSG_EXTEND;
278         msg.msg[1] = MSG_EXTEND_SYNCHLEN;
279         msg.msg[2] = MSG_EXTEND_SYNCHCODE;
280         msg.msg[3] = negp->period;
281         msg.msg[4] = negp->offset;
282         msg.msglen = MSG_EXTEND_SYNCHLEN + 2;
283
284         bs_make_msg_ccb(ti, lun, cb, &msg, BS_SYNC_TIMEOUT);
285         return COMPLETE;
286 }
287
288 static void
289 bs_print_syncmsg(ti, s)
290         struct targ_info *ti;
291         char *s;
292 {
293         struct bs_softc *bsc = ti->ti_bsc;
294         struct syncdata *negp;
295         u_int speed;
296
297         negp = &ti->ti_syncnow;
298         speed = (negp->offset && negp->period) ?
299                 (2500 / ((u_int) negp->period)) : 0;
300
301         printf("%s(%d:%d): <%s> ", bsc->sc_dvname, ti->ti_id, ti->ti_lun, s);
302         printf("period 0x%x offset %d chip (0x%x)", negp->period, negp->offset,
303                 ti->ti_sync);
304         if (speed)
305                 printf(" %d.%d M/s", speed / 10, speed % 10);
306         printf("\n");
307 }
308
309 int
310 bs_analyze_syncmsg(ti, cb)
311         struct targ_info *ti;
312         struct bsccb *cb;
313 {
314         struct bs_softc *bsc = ti->ti_bsc;
315         u_int8_t ans = ti->ti_syncnow.state;
316         struct syncdata *negp, *maxp;
317         struct syncdata bdata;
318         char *s = NULL;
319         u_int8_t period;
320
321         negp = &ti->ti_syncnow;
322         bdata = *negp;
323         maxp = &ti->ti_syncmax;
324
325         switch(ans)
326         {
327         case BS_SYNCMSG_REJECT:
328                 period = 0;
329                 s = "msg reject";
330                 break;
331
332         case BS_SYNCMSG_ASSERT:
333                 period = 0;
334                 s = "no msg";
335                 break;
336
337         default:
338                 if (negp->offset != 0 && negp->period < maxp->period)
339                 {
340                         period = 0xff;
341                         s = "illegal(period)";
342                 }
343                 else if (negp->offset > maxp->offset)
344                 {
345                         period = 0xff;
346                         s = "illegal(offset)";
347                 }
348                 else
349                         period = negp->offset ? negp->period : 0;
350                 break;
351         }
352
353         if (s == NULL)
354         {
355                 bshw_adj_syncdata(negp);
356                 *maxp = *negp;
357
358                 if (ans == BS_SYNCMSG_REQUESTED)
359                         s = "requested";
360                 else
361                         s = negp->offset ? "synchronous" : "async";
362         }
363         else
364         {
365                 negp->offset = maxp->offset = 0;
366                 bshw_adj_syncdata(negp);
367                 bshw_adj_syncdata(maxp);
368         }
369
370         /* really setup hardware */
371         bshw_set_synchronous(bsc, ti);
372         if (cb == NULL || (period >= negp->period && period <= negp->period + 2))
373         {
374                 bs_print_syncmsg(ti, s);
375                 BS_SETUP_TARGSTATE(BS_TARG_RDY);
376                 BS_SETUP_SYNCSTATE(BS_SYNCMSG_NULL);
377                 if (cb)
378                         bs_kill_msg(cb);
379
380                 return 0;
381         }
382         else
383         {
384                 bs_printf(ti, "bs_analyze_syncmsg",
385                           "sync(period) mismatch, retry neg...");
386                 printf("expect(%d:0x%x) => reply(%d:0x%x)\n",
387                         bdata.offset, bdata.period, negp->offset, negp->period);
388
389                 bs_start_syncmsg(ti, cb, BS_SYNCMSG_ASSERT);
390                 return EINVAL;
391         }
392 }
393
394 /**************************************************
395  * ABORT AND RESET MSG
396  **************************************************/
397 /* send device reset msg and wait */
398 void
399 bs_reset_device(ti)
400         struct targ_info *ti;
401 {
402         struct msgbase msg;
403
404         msg.msglen = 1;
405         msg.msg[0] = MSG_RESET;
406         msg.flag = 0;
407
408         bs_send_msg(ti, 0, &msg, 0);
409
410         delay(ti->ti_bsc->sc_RSTdelay);
411         bs_check_target(ti);
412 }
413
414 /* send abort msg */
415 struct bsccb *
416 bs_force_abort(ti)
417         struct targ_info *ti;
418 {
419         struct bs_softc *bsc = ti->ti_bsc;
420         struct msgbase msg;
421         struct bsccb *cb = ti->ti_ctab.tqh_first;
422         u_int lun;
423
424         if (cb)
425         {
426                 lun = cb->lun;
427                 cb->rcnt++;
428         }
429         else
430                 lun = 0;
431
432         msg.msglen = 1;
433         msg.msg[0] = MSG_ABORT;
434         msg.flag = 0;
435
436         cb = bs_make_msg_ccb(ti, lun, NULL, &msg, 0);
437         bscmdstart(ti, BSCMDSTART);
438
439         if (bsc->sc_nexus == ti)
440                 BS_LOAD_SDP
441
442         return cb;
443 }
444
445 /**************************************************
446  * COMPLETE SCSI BUS RESET
447  *************************************************/
448 /*
449  * XXX:
450  * 1) reset scsi bus (ie. all target reseted).
451  * 2) chip reset.
452  * 3) check target status.
453  * 4) sync neg with all targets.
454  * 5) setup sync reg in host.
455  * 6) recover previous nexus.
456  */
457 void
458 bs_scsibus_start(bsc)
459         struct bs_softc *bsc;
460 {
461         struct targ_info *ti, *nextti = NULL;
462         int error = HASERROR;
463         u_int querm, bits, skip = 0;
464
465         querm = (bsc->sc_hstate == BSC_BOOTUP);
466         bsc->sc_hstate = BSC_TARG_CHECK;
467
468         /* target check */
469         do
470         {
471                 if (error != COMPLETE)
472                 {
473                         printf("%s: scsi bus reset and try to restart ...",
474                                bsc->sc_dvname);
475                         bshw_smitabort(bsc);
476                         bshw_dmaabort(bsc, NULL);
477                         bshw_chip_reset(bsc);
478                         bshw_bus_reset(bsc);
479                         bshw_chip_reset(bsc);
480                         printf(" done. scsi bus ready.\n");
481                         nextti = bsc->sc_titab.tqh_first;
482                         error = COMPLETE;
483                 }
484
485                 if ((ti = nextti) == NULL)
486                         break;
487                 nextti = ti->ti_tchain.tqe_next;
488
489                 bits = (1 << ti->ti_id);
490                 if (skip & bits)
491                         continue;
492
493                 if ((error = bs_check_target(ti)) != COMPLETE)
494                 {
495                         if (querm)
496                         {
497                                 TAILQ_REMOVE(&bsc->sc_titab, ti, ti_tchain);
498                                 bsc->sc_openf &= ~bits;
499                         }
500
501                         if (error == NOTARGET)
502                                 error = COMPLETE;
503
504                         skip |= bits;
505                 }
506         }
507         while (1);
508
509         /* ok now ready */
510         bsc->sc_hstate = BSC_RDY;
511
512         /* recover */
513         for (ti = bsc->sc_titab.tqh_first; ti; ti = ti->ti_tchain.tqe_next)
514         {
515                 ti->ti_ctab = ti->ti_bctab;
516                 TAILQ_INIT(&ti->ti_bctab);
517                 if (ti->ti_ctab.tqh_first)
518                         bscmdstart(ti, BSCMDSTART);
519         }
520 }
521
522 void
523 bs_reset_nexus(bsc)
524         struct bs_softc *bsc;
525 {
526         struct targ_info *ti;
527         struct bsccb *cb;
528
529         bsc->sc_flags &= ~(BSRESET | BSUNDERRESET);
530         if (bsc->sc_poll)
531         {
532                 bsc->sc_flags |= BSUNDERRESET;
533                 return;
534         }
535
536         /* host state clear */
537         BS_HOST_TERMINATE
538         BS_SETUP_MSGPHASE(FREE)
539         bsc->sc_dtgnum = 0;
540
541         /* target state clear */
542         for (ti = bsc->sc_titab.tqh_first; ti; ti = ti->ti_tchain.tqe_next)
543         {
544                 if (ti->ti_state == BS_TARG_SYNCH)
545                         bs_analyze_syncmsg(ti, NULL);
546                 if (ti->ti_state > BS_TARG_START)
547                         BS_SETUP_TARGSTATE(BS_TARG_START);
548
549                 BS_SETUP_PHASE(UNDEF)
550                 bs_hostque_delete(bsc, ti);
551                 if ((cb = ti->ti_ctab.tqh_first) != NULL)
552                 {
553                         if (bsc->sc_hstate == BSC_TARG_CHECK)
554                         {
555                                 ti->ti_error |= BSFATALIO;
556                                 bscmddone(ti);
557                         }
558                         else if (cb->rcnt >= bsc->sc_retry)
559                         {
560                                 ti->ti_error |= BSABNORMAL;
561                                 bscmddone(ti);
562                         }
563                         else if (ti->ti_error)
564                                 cb->rcnt++;
565                 }
566
567                 /* target state clear */
568                 BS_SETUP_PHASE(FREE)
569                 BS_SETUP_SYNCSTATE(BS_SYNCMSG_NULL);
570                 ti->ti_flags &= ~BSCFLAGSMASK;
571                 ti->ti_msgout = 0;
572 #ifdef  BS_DIAG
573                 ti->ti_flags &= ~BSNEXUS;
574 #endif  /* BS_DIAG */
575
576                 for ( ; cb; cb = cb->ccb_chain.tqe_next)
577                 {
578                         bs_kill_msg(cb);
579                         cb->bsccb_flags &= ~(BSITSDONE | BSCASTAT);
580                         cb->error = 0;
581                 }
582
583                 if (bsc->sc_hstate != BSC_TARG_CHECK &&
584                     ti->ti_bctab.tqh_first == NULL)
585                         ti->ti_bctab = ti->ti_ctab;
586
587                 TAILQ_INIT(&ti->ti_ctab);
588         }
589
590         if (bsc->sc_hstate != BSC_TARG_CHECK)
591                 bs_scsibus_start(bsc);
592 }
593
594 /**************************************************
595  * CHECK TARGETS AND START TARGETS
596  *************************************************/
597 static int
598 bs_start_target(ti)
599         struct targ_info *ti;
600 {
601         struct bsccb *cb;
602         struct scsi_start_stop_unit cmd;
603
604         bzero(&cmd, sizeof(struct scsi_start_stop_unit));
605         cmd.opcode = START_STOP;
606         cmd.how = SSS_START;
607         ti->ti_lun = 0;
608         cb = bs_make_internal_ccb(ti, 0, (u_int8_t *) &cmd,
609                                    sizeof(struct scsi_start_stop_unit),
610                                    NULL, 0, BSFORCEIOPOLL, BS_MOTOR_TIMEOUT);
611         bscmdstart(ti, BSCMDSTART);
612         return bs_scsi_cmd_poll(ti, cb);
613 }
614
615 /* test unit ready and check ATN msgout response */
616 static int
617 bs_check_target(ti)
618         struct targ_info *ti;
619 {
620         struct bs_softc *bsc = ti->ti_bsc;
621         struct scsi_inquiry scsi_cmd;
622         struct scsi_inquiry_data scsi_inquiry_data;
623         struct bsccb *cb;
624         int count, retry = bsc->sc_retry;
625         int s, error = COMPLETE;
626
627         ti->ti_lun = 0;
628         bsc->sc_retry = 2;
629         s = splcam();
630
631         /* inquiry */
632         bzero(&scsi_cmd, sizeof(scsi_cmd));
633         scsi_cmd.opcode = INQUIRY;
634         scsi_cmd.length = (u_int8_t) sizeof(struct scsi_inquiry_data);
635         cb = bs_make_internal_ccb(ti, 0,
636                                    (u_int8_t *) &scsi_cmd, sizeof(scsi_cmd),
637                                    (u_int8_t *) &scsi_inquiry_data,
638                                    sizeof(scsi_inquiry_data),
639                                    BSFORCEIOPOLL, BS_STARTUP_TIMEOUT);
640         bscmdstart(ti, BSCMDSTART);
641         error = bs_scsi_cmd_poll(ti, cb);
642         if (error != COMPLETE || (ti->ti_error & BSSELTIMEOUT))
643                 goto done;
644         ti->targ_type = scsi_inquiry_data.device;
645         ti->targ_support = scsi_inquiry_data.flags;
646
647         /* test unit ready twice */
648         for (count = 0; count < 2; count++)
649         {
650                 cb = bs_make_internal_ccb(ti, 0, NULL, 0, NULL, 0,
651                                          BSFORCEIOPOLL, BS_STARTUP_TIMEOUT);
652                 bscmdstart(ti, BSCMDSTART);
653                 error = bs_scsi_cmd_poll(ti, cb);
654                 if (error != COMPLETE || (ti->ti_error & BSSELTIMEOUT))
655                         goto done;
656         }
657
658         if (cb->bsccb_flags & BSCASTAT)
659                 bs_printf(ti, "check", "could not clear CA state");
660         ti->ti_error = 0;
661
662 done:
663         bsc->sc_retry = retry;
664
665         if (ti->ti_error & BSSELTIMEOUT)
666                 error = NOTARGET;
667
668         if (error == COMPLETE)
669                 error = bs_start_target(ti);
670
671         splx(s);
672         return error;
673 }
674
675 /**************************************************
676  * TARGET CONTROL
677  **************************************************/
678 struct targ_info *
679 bs_init_target_info(bsc, target)
680         struct bs_softc *bsc;
681         int target;
682 {
683         struct targ_info *ti;
684
685         ti = malloc(sizeof(struct targ_info), M_DEVBUF, M_NOWAIT);
686         if (ti == NULL)
687         {
688                 bs_printf(NULL, "bs_init_targ_info", "no target info memory");
689                 return ti;
690         }
691
692         bzero(ti, sizeof(*ti));
693
694         ti->ti_bsc = bsc;
695         ti->ti_id = target;
696         ti->sm_offset = 0;
697         ti->ti_cfgflags = BS_SCSI_NOPARITY | BS_SCSI_NOSAT;
698         ti->ti_mflags = ~(BSSAT | BSDISC | BSSMIT | BSLINK);
699         BS_SETUP_TARGSTATE(BS_TARG_CTRL);
700
701         TAILQ_INIT(&ti->ti_ctab);
702
703         bs_alloc_buf(ti);
704         if (ti->bounce_addr == NULL)
705         {
706                 free(ti, M_DEVBUF);
707                 return NULL;
708         }
709
710         TAILQ_INSERT_TAIL(&bsc->sc_titab, ti, ti_tchain);
711         bsc->sc_ti[target] = ti;
712         bsc->sc_openf |= (1 << target);
713
714         return ti;
715 }
716
717 void
718 bs_setup_ctrl(ti, quirks, flags)
719         struct targ_info *ti;
720         u_int quirks;
721         u_int flags;
722 {
723         struct bs_softc *bsc = ti->ti_bsc;
724         u_int offset, period, maxperiod;
725
726         if (ti->ti_state == BS_TARG_CTRL)
727         {
728                 ti->ti_cfgflags = BS_SCSI_POSITIVE;
729                 ti->ti_syncmax.offset = BSHW_MAX_OFFSET;
730                 BS_SETUP_TARGSTATE(BS_TARG_START);
731         }
732         else
733                 flags |= ti->ti_cfgflags & BS_SCSI_NEGATIVE;
734
735 #ifdef  BS_TARG_SAFEMODE
736         if (ti->targ_type != 0)
737         {
738                 flags &= ~(BS_SCSI_DISC | BS_SCSI_SYNC);
739                 flags |= BS_SCSI_NOPARITY;
740         }
741 #endif
742
743 #ifdef  SDEV_NODISC
744         if (quirks & SDEV_NODISC)
745                 flags &= ~BS_SCSI_DISC;
746 #endif
747 #ifdef  SDEV_NOPARITY
748         if (quirks & SDEV_NOPARITY)
749                 flags |= BS_SCSI_NOPARITY;
750 #endif
751 #ifdef  SDEV_NOCMDLNK
752         if (quirks & SDEV_NOCMDLNK)
753                 flags &= ~BS_SCSI_LINK;
754 #endif
755 #ifdef  SDEV_ASYNC
756         if (quirks & SDEV_ASYNC)
757                 flags &= ~BS_SCSI_SYNC;
758 #endif
759 #ifdef  SDEV_AUTOSAVE
760         if (quirks & SDEV_AUTOSAVE)
761                 flags |= BS_SCSI_SAVESP;
762 #endif
763 #ifdef  SD_Q_NO_SYNC
764         if (quirks & SD_Q_NO_SYNC)
765                 flags &= ~BS_SCSI_SYNC;
766 #endif
767
768         if ((flags & BS_SCSI_DISC) == 0 ||
769             (ti->targ_support & SID_Linked) == 0)
770                 flags &= ~BS_SCSI_LINK;
771
772         ti->sm_offset = (flags & BS_SCSI_NOSMIT) ?  0 : bsc->sm_offset;
773         if (ti->sm_offset == 0)
774                 flags |= BS_SCSI_NOSMIT;
775         else if (bsc->sc_cfgflags & BSC_SMITSAT_DISEN)
776                 flags |= BS_SCSI_NOSAT;
777
778         flags &= (ti->ti_cfgflags & BS_SCSI_POSITIVE) | (~BS_SCSI_POSITIVE);
779         ti->ti_cfgflags = flags;
780
781         /* calculate synch setup */
782         period = BS_SCSI_PERIOD(flags);
783         offset = (flags & BS_SCSI_SYNC) ? BS_SCSI_OFFSET(flags) : 0;
784
785         maxperiod = (bsc->sc_cspeed & IDR_FS_16_20) ? 100 : 50;
786         if (period > maxperiod)
787                 period = maxperiod;
788
789         if (period)
790                 period = 2500 / period;
791
792         if (ti->ti_syncmax.offset > offset)
793                 ti->ti_syncmax.offset = offset;
794         if (ti->ti_syncmax.period < period)
795                 ti->ti_syncmax.period = period;
796
797         bshw_adj_syncdata(&ti->ti_syncmax);
798
799         /* finally report our info */
800         printf("%s(%d:%d): {%d:0x%x:0x%x:%s} flags 0x%b\n",
801                 bsc->sc_dvname, ti->ti_id, ti->ti_lun,
802                (u_int) ti->targ_type,
803                (u_int) ti->targ_support,
804                (u_int) ti->bounce_size,
805                (flags & BS_SCSI_NOSMIT) ? "dma" : "pdma",
806                 flags, BS_SCSI_BITS);
807
808         /* internal representation */
809         ti->ti_mflags = ~0;
810         if ((ti->ti_cfgflags & BS_SCSI_DISC) == 0)
811                 ti->ti_mflags &= ~BSDISC;
812         if ((ti->ti_cfgflags & BS_SCSI_LINK) == 0)
813                 ti->ti_mflags &= ~BSLINK;
814         if (ti->ti_cfgflags & BS_SCSI_NOSAT)
815                 ti->ti_mflags &= ~BSSAT;
816         if (ti->ti_cfgflags & BS_SCSI_NOSMIT)
817                 ti->ti_mflags &= ~BSSMIT;
818 }
819
820 /**************************************************
821  * MISC
822  **************************************************/
823 void
824 bs_printf(ti, ph, c)
825         struct targ_info *ti;
826         char *ph;
827         char *c;
828 {
829
830         if (ti)
831                 printf("%s(%d:%d): <%s> %s\n",
832                        ti->ti_bsc->sc_dvname, ti->ti_id, ti->ti_lun, ph, c);
833         else
834                 printf("bs*(*:*): <%s> %s\n", ph, c);
835 }
836
837 void
838 bs_panic(bsc, c)
839         struct bs_softc *bsc;
840         u_char *c;
841 {
842
843         panic("%s %s\n", bsc->sc_dvname, c);
844 }
845
846 /**************************************************
847  * DEBUG FUNC
848  **************************************************/
849 #ifdef  BS_DEBUG_ROUTINE
850 u_int
851 bsr(addr)
852         u_int addr;
853 {
854
855         outb(0xcc0, addr);
856         return inb(0xcc2);
857 }
858
859 u_int
860 bsw(addr, data)
861         u_int addr;
862         int data;
863 {
864
865         outb(0xcc0, addr);
866         outb(0xcc2, data);
867         return 0;
868 }
869 #endif  /* BS_DEBUG_ROUTINE */
870
871 void
872 bs_debug_print_all(bsc)
873         struct bs_softc *bsc;
874 {
875         struct targ_info *ti;
876
877         for (ti = bsc->sc_titab.tqh_first; ti; ti = ti->ti_tchain.tqe_next)
878                 bs_debug_print(bsc, ti);
879 }
880
881 static u_char *phase[] =
882 {
883         "FREE", "HOSTQUE", "DISC", "COMPMSG", "ATN", "DISCMSG", "SELECT",
884         "SELECTED", "RESELECTED", "MSGIN", "MSGOUT", "STATIN", "CMDOUT",
885         "DATA", "SATSEL", "SATRESEL", "SATSDP", "SATCOMPSEQ", "UNDEF",
886 };
887
888 void
889 bs_debug_print(bsc, ti)
890         struct bs_softc *bsc;
891         struct targ_info *ti;
892 {
893         struct bsccb *cb;
894
895         /* host stat */
896         printf("%s <DEBUG INFO> nexus %lx bs %lx bus status %lx \n",
897                bsc->sc_dvname, (u_long) ti, (u_long) bsc->sc_nexus, (u_long) bsc->sc_busstat);
898
899         /* target stat */
900         if (ti)
901         {
902                 struct sc_p *sp = &bsc->sc_p;
903
904                 printf("%s(%d:%d) ph<%s> ", bsc->sc_dvname, ti->ti_id,
905                        ti->ti_lun, phase[(int) ti->ti_phase]);
906                 printf("msgptr %x msg[0] %x status %x tqh %lx fl %x\n",
907                        (u_int) (ti->ti_msginptr), (u_int) (ti->ti_msgin[0]),
908                        ti->ti_status, (u_long) (cb = ti->ti_ctab.tqh_first),
909                        ti->ti_flags);
910                 if (cb)
911                         printf("cmdlen %x cmdaddr %lx cmd[0] %x\n",
912                                cb->cmdlen, (u_long) cb->cmd, (int) cb->cmd[0]);
913                 printf("datalen %x dataaddr %lx seglen %x ",
914                        sp->datalen, (u_long) sp->data, sp->seglen);
915                 if (cb)
916                         printf("odatalen %x flags %x\n",
917                                 cb->datalen, cb->bsccb_flags);
918                 else
919                         printf("\n");
920                 printf("error flags %b\n", ti->ti_error, BSERRORBITS);
921         }
922 }