1 /* $NecBSD: bsfunc.c,v 1.2 1997/10/31 17:43:37 honda Exp $ */
3 /* $FreeBSD: src/sys/i386/isa/bs/bsfunc.c,v 1.7.2.2 2001/07/26 02:32:18 nyan Exp $ */
4 /* $DragonFly: src/sys/dev/disk/i386/bs/Attic/bsfunc.c,v 1.7 2004/08/02 13:22:32 joerg Exp $ */
6 * [NetBSD for NEC PC98 series]
7 * Copyright (c) 1994, 1995, 1996 NetBSD/pc98 porting staff.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
34 * Copyright (c) 1994, 1995, 1996 Naofumi HONDA. All rights reserved.
38 #include <i386/Cbus/dev/bs/bsif.h>
40 #if defined(__DragonFly__) || defined(__FreeBSD__)
45 struct bs_statics bs_statics[NTARGETS];
46 u_int bs_linkcmd_count[NTARGETS];
47 u_int bs_bounce_used[NTARGETS];
48 #endif /* BS_STATICS */
51 int bs_debug_flag = 0;
54 static void bs_print_syncmsg (struct targ_info *, char*);
55 static void bs_timeout_target (struct targ_info *);
56 static void bs_kill_msg (struct bsccb *cb);
58 static int bs_start_target (struct targ_info *);
59 static int bs_check_target (struct targ_info *);
61 /*************************************************************
63 ************************************************************/
64 GENERIC_CCB_STATIC_ALLOC(bs, bsccb)
65 GENERIC_CCB(bs, bsccb, ccb_chain)
67 /*************************************************************
69 ************************************************************/
74 struct bs_softc *bsc = ti->ti_bsc;
76 ti->ti_error |= BSTIMEOUT;
77 bsc->sc_flags |= BSRESET;
79 if (ti->ti_herrcnt ++ >= HARDRETRIES)
81 bs_printf(ti, "timeout", "async transfer!");
82 ti->ti_syncmax.period = ti->ti_syncmax.offset = 0;
90 struct bs_softc *bsc = (struct bs_softc *) arg;
96 bsc->sc_flags &= ~BSSTARTTIMEOUT;
99 if ((ti = bsc->sc_nexus) && (cb = TAILQ_FIRST(&ti->ti_ctab)))
101 if ((cb->tc -= BS_TIMEOUT_CHECK_INTERVAL) < 0)
102 bs_timeout_target(ti);
105 TAILQ_FOREACH(ti, &bsc->sc_titab, ti_tichain) {
106 if (bsc->sc_dtgnum && ti->ti_phase < DISCONNECTED)
109 cb = TAILQ_FIRST(&ti->ti_ctab);
110 if (cb && ((cb->tc -= BS_TIMEOUT_CHECK_INTERVAL) < 0))
111 bs_timeout_target(ti);
116 if (bsc->sc_flags & BSRESET)
118 bs_debug_print_all(bsc);
119 bs_printf(ti, "timeout", "bus hang up");
123 bs_start_timeout(bsc);
127 /**************************************************
129 *************************************************/
130 static u_int8_t cmd_unit_ready[6];
133 bs_make_internal_ccb(ti, lun, cmd, cmdlen, data, datalen, flags, timeout)
134 struct targ_info *ti;
145 if ((cb = bs_get_ccb()) == NULL)
146 bs_panic(ti->ti_bsc, "can not get ccb mem");
150 cb->cmd = (cmd ? cmd : cmd_unit_ready);
151 cb->cmdlen = (cmd ? cmdlen : sizeof(cmd_unit_ready));
153 cb->datalen = (data ? datalen : 0);
155 cb->bsccb_flags = flags & BSCFLAGSMASK;
156 bs_targ_flags(ti, cb);
158 cb->tcmax = (timeout > BS_DEFAULT_TIMEOUT_SECOND ? timeout :
159 BS_DEFAULT_TIMEOUT_SECOND);
161 TAILQ_INSERT_HEAD(&ti->ti_ctab, cb, ccb_chain);
167 bs_make_msg_ccb(ti, lun, cb, msg, timex)
168 struct targ_info *ti;
176 flags = BSFORCEIOPOLL | msg->flag;
178 cb = bs_make_internal_ccb(ti, lun, NULL, 0, NULL, 0,
181 cb->bsccb_flags |= flags & BSCFLAGSMASK;
183 cb->msgoutlen = msg->msglen;
184 bcopy(msg->msg, cb->msgout, msg->msglen);
189 bs_send_msg(ti, lun, msg, timex)
190 struct targ_info *ti;
197 cb = bs_make_msg_ccb(ti, lun, NULL, msg, timex);
198 bscmdstart(ti, BSCMDSTART);
199 return bs_scsi_cmd_poll(ti, cb);
209 /**************************************************
211 **************************************************/
214 struct targ_info *ti;
218 bzero(ti->scsi_cmd, sizeof(struct scsi_sense));
219 bzero(&ti->sense, sizeof(struct scsi_sense_data));
220 ti->scsi_cmd[0] = REQUEST_SENSE;
221 ti->scsi_cmd[1] = (ti->ti_lun << 5);
222 ti->scsi_cmd[4] = sizeof(struct scsi_sense_data);
223 cb = bs_make_internal_ccb(ti, ti->ti_lun, ti->scsi_cmd,
224 sizeof(struct scsi_sense),
225 (u_int8_t *) & ti->sense,
226 sizeof(struct scsi_sense_data),
228 BS_DEFAULT_TIMEOUT_SECOND);
229 cb->bsccb_flags |= BSSENSECCB;
233 /**************************************************
235 *************************************************/
238 bs_start_syncmsg(ti, cb, flag)
239 struct targ_info *ti;
243 struct syncdata *negp, *maxp;
247 negp = &ti->ti_syncnow;
248 maxp = &ti->ti_syncmax;
250 ti->ti_state = BS_TARG_SYNCH;
252 if (flag == BS_SYNCMSG_REQUESTED)
254 if (negp->offset > maxp->offset)
255 negp->offset = maxp->offset;
256 if (negp->offset != 0 && negp->period < maxp->period)
257 negp->period = maxp->period;
262 cb = TAILQ_FIRST(&ti->ti_ctab);
264 else if (ti->ti_cfgflags & BS_SCSI_SYNC)
266 negp->offset = maxp->offset;
267 negp->period = maxp->period;
269 msg.flag = BSERROROK;
274 ti->ti_state = BS_TARG_RDY;
278 BS_SETUP_SYNCSTATE(flag);
279 msg.msg[0] = MSG_EXTEND;
280 msg.msg[1] = MSG_EXTEND_SYNCHLEN;
281 msg.msg[2] = MSG_EXTEND_SYNCHCODE;
282 msg.msg[3] = negp->period;
283 msg.msg[4] = negp->offset;
284 msg.msglen = MSG_EXTEND_SYNCHLEN + 2;
286 bs_make_msg_ccb(ti, lun, cb, &msg, BS_SYNC_TIMEOUT);
291 bs_print_syncmsg(ti, s)
292 struct targ_info *ti;
295 struct bs_softc *bsc = ti->ti_bsc;
296 struct syncdata *negp;
299 negp = &ti->ti_syncnow;
300 speed = (negp->offset && negp->period) ?
301 (2500 / ((u_int) negp->period)) : 0;
303 printf("%s(%d:%d): <%s> ", bsc->sc_dvname, ti->ti_id, ti->ti_lun, s);
304 printf("period 0x%x offset %d chip (0x%x)", negp->period, negp->offset,
307 printf(" %d.%d M/s", speed / 10, speed % 10);
312 bs_analyze_syncmsg(ti, cb)
313 struct targ_info *ti;
316 struct bs_softc *bsc = ti->ti_bsc;
317 u_int8_t ans = ti->ti_syncnow.state;
318 struct syncdata *negp, *maxp;
319 struct syncdata bdata;
323 negp = &ti->ti_syncnow;
325 maxp = &ti->ti_syncmax;
329 case BS_SYNCMSG_REJECT:
334 case BS_SYNCMSG_ASSERT:
340 if (negp->offset != 0 && negp->period < maxp->period)
343 s = "illegal(period)";
345 else if (negp->offset > maxp->offset)
348 s = "illegal(offset)";
351 period = negp->offset ? negp->period : 0;
357 bshw_adj_syncdata(negp);
360 if (ans == BS_SYNCMSG_REQUESTED)
363 s = negp->offset ? "synchronous" : "async";
367 negp->offset = maxp->offset = 0;
368 bshw_adj_syncdata(negp);
369 bshw_adj_syncdata(maxp);
372 /* really setup hardware */
373 bshw_set_synchronous(bsc, ti);
374 if (cb == NULL || (period >= negp->period && period <= negp->period + 2))
376 bs_print_syncmsg(ti, s);
377 BS_SETUP_TARGSTATE(BS_TARG_RDY);
378 BS_SETUP_SYNCSTATE(BS_SYNCMSG_NULL);
386 bs_printf(ti, "bs_analyze_syncmsg",
387 "sync(period) mismatch, retry neg...");
388 printf("expect(%d:0x%x) => reply(%d:0x%x)\n",
389 bdata.offset, bdata.period, negp->offset, negp->period);
391 bs_start_syncmsg(ti, cb, BS_SYNCMSG_ASSERT);
396 /**************************************************
397 * ABORT AND RESET MSG
398 **************************************************/
399 /* send device reset msg and wait */
402 struct targ_info *ti;
407 msg.msg[0] = MSG_RESET;
410 bs_send_msg(ti, 0, &msg, 0);
412 delay(ti->ti_bsc->sc_RSTdelay);
419 struct targ_info *ti;
421 struct bs_softc *bsc = ti->ti_bsc;
423 struct bsccb *cb = TAILQ_FIRST(&ti->ti_ctab);
435 msg.msg[0] = MSG_ABORT;
438 cb = bs_make_msg_ccb(ti, lun, NULL, &msg, 0);
439 bscmdstart(ti, BSCMDSTART);
441 if (bsc->sc_nexus == ti)
447 /**************************************************
448 * COMPLETE SCSI BUS RESET
449 *************************************************/
452 * 1) reset scsi bus (ie. all target reseted).
454 * 3) check target status.
455 * 4) sync neg with all targets.
456 * 5) setup sync reg in host.
457 * 6) recover previous nexus.
460 bs_scsibus_start(bsc)
461 struct bs_softc *bsc;
463 struct targ_info *ti, *nextti = NULL;
464 int error = HASERROR;
465 u_int querm, bits, skip = 0;
467 querm = (bsc->sc_hstate == BSC_BOOTUP);
468 bsc->sc_hstate = BSC_TARG_CHECK;
473 if (error != COMPLETE)
475 printf("%s: scsi bus reset and try to restart ...",
478 bshw_dmaabort(bsc, NULL);
479 bshw_chip_reset(bsc);
481 bshw_chip_reset(bsc);
482 printf(" done. scsi bus ready.\n");
483 nextti = TAILQ_FIRST(&bsc->sc_titab);
487 if ((ti = nextti) == NULL)
489 nextti = TAILQ_NEXT(ti, ti_tchain);
491 bits = (1 << ti->ti_id);
495 if ((error = bs_check_target(ti)) != COMPLETE)
499 TAILQ_REMOVE(&bsc->sc_titab, ti, ti_tchain);
500 bsc->sc_openf &= ~bits;
503 if (error == NOTARGET)
512 bsc->sc_hstate = BSC_RDY;
515 TAILQ_FOREACH(ti, &bsc->sc_titab; ti_tchain) {
516 ti->ti_ctab = ti->ti_bctab;
517 TAILQ_INIT(&ti->ti_bctab);
518 if (!TAILQ_EMPTY(&ti->ti_ctab))
519 bscmdstart(ti, BSCMDSTART);
525 struct bs_softc *bsc;
527 struct targ_info *ti;
530 bsc->sc_flags &= ~(BSRESET | BSUNDERRESET);
533 bsc->sc_flags |= BSUNDERRESET;
537 /* host state clear */
539 BS_SETUP_MSGPHASE(FREE)
542 /* target state clear */
543 TAILQ_FOREACH(ti, &bsc->sc_titab, ti_tchain) {
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);
549 BS_SETUP_PHASE(UNDEF)
550 bs_hostque_delete(bsc, ti);
551 if (!TAILQ_EMPTY(&ti->ti_ctab))
553 cb = TAILQ_FIRST(&ti->ti_ctab);
554 if (bsc->sc_hstate == BSC_TARG_CHECK)
556 ti->ti_error |= BSFATALIO;
559 else if (cb->rcnt >= bsc->sc_retry)
561 ti->ti_error |= BSABNORMAL;
564 else if (ti->ti_error)
568 /* target state clear */
570 BS_SETUP_SYNCSTATE(BS_SYNCMSG_NULL);
571 ti->ti_flags &= ~BSCFLAGSMASK;
574 ti->ti_flags &= ~BSNEXUS;
577 TAILQ_FOREACH(cb, &ti->ti_ctab, ccb_chain) {
579 cb->bsccb_flags &= ~(BSITSDONE | BSCASTAT);
583 if (bsc->sc_hstate != BSC_TARG_CHECK &&
584 TAILQ_EMPTY(&ti->ti_bctab))
585 ti->ti_bctab = ti->ti_ctab;
587 TAILQ_INIT(&ti->ti_ctab);
590 if (bsc->sc_hstate != BSC_TARG_CHECK)
591 bs_scsibus_start(bsc);
594 /**************************************************
595 * CHECK TARGETS AND START TARGETS
596 *************************************************/
599 struct targ_info *ti;
602 struct scsi_start_stop_unit cmd;
604 bzero(&cmd, sizeof(struct scsi_start_stop_unit));
605 cmd.opcode = START_STOP;
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);
615 /* test unit ready and check ATN msgout response */
618 struct targ_info *ti;
620 struct bs_softc *bsc = ti->ti_bsc;
621 struct scsi_inquiry scsi_cmd;
622 struct scsi_inquiry_data scsi_inquiry_data;
624 int count, retry = bsc->sc_retry;
625 int s, error = COMPLETE;
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))
644 ti->targ_type = scsi_inquiry_data.device;
645 ti->targ_support = scsi_inquiry_data.flags;
647 /* test unit ready twice */
648 for (count = 0; count < 2; count++)
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))
658 if (cb->bsccb_flags & BSCASTAT)
659 bs_printf(ti, "check", "could not clear CA state");
663 bsc->sc_retry = retry;
665 if (ti->ti_error & BSSELTIMEOUT)
668 if (error == COMPLETE)
669 error = bs_start_target(ti);
675 /**************************************************
677 **************************************************/
679 bs_init_target_info(bsc, target)
680 struct bs_softc *bsc;
683 struct targ_info *ti;
685 ti = malloc(sizeof(struct targ_info), M_DEVBUF, M_WAITOK | M_ZERO);
689 ti->ti_cfgflags = BS_SCSI_NOPARITY | BS_SCSI_NOSAT;
690 ti->ti_mflags = ~(BSSAT | BSDISC | BSSMIT | BSLINK);
691 BS_SETUP_TARGSTATE(BS_TARG_CTRL);
693 TAILQ_INIT(&ti->ti_ctab);
696 if (ti->bounce_addr == NULL)
702 TAILQ_INSERT_TAIL(&bsc->sc_titab, ti, ti_tchain);
703 bsc->sc_ti[target] = ti;
704 bsc->sc_openf |= (1 << target);
710 bs_setup_ctrl(ti, quirks, flags)
711 struct targ_info *ti;
715 struct bs_softc *bsc = ti->ti_bsc;
716 u_int offset, period, maxperiod;
718 if (ti->ti_state == BS_TARG_CTRL)
720 ti->ti_cfgflags = BS_SCSI_POSITIVE;
721 ti->ti_syncmax.offset = BSHW_MAX_OFFSET;
722 BS_SETUP_TARGSTATE(BS_TARG_START);
725 flags |= ti->ti_cfgflags & BS_SCSI_NEGATIVE;
727 #ifdef BS_TARG_SAFEMODE
728 if (ti->targ_type != 0)
730 flags &= ~(BS_SCSI_DISC | BS_SCSI_SYNC);
731 flags |= BS_SCSI_NOPARITY;
736 if (quirks & SDEV_NODISC)
737 flags &= ~BS_SCSI_DISC;
740 if (quirks & SDEV_NOPARITY)
741 flags |= BS_SCSI_NOPARITY;
744 if (quirks & SDEV_NOCMDLNK)
745 flags &= ~BS_SCSI_LINK;
748 if (quirks & SDEV_ASYNC)
749 flags &= ~BS_SCSI_SYNC;
752 if (quirks & SDEV_AUTOSAVE)
753 flags |= BS_SCSI_SAVESP;
756 if (quirks & SD_Q_NO_SYNC)
757 flags &= ~BS_SCSI_SYNC;
760 if ((flags & BS_SCSI_DISC) == 0 ||
761 (ti->targ_support & SID_Linked) == 0)
762 flags &= ~BS_SCSI_LINK;
764 ti->sm_offset = (flags & BS_SCSI_NOSMIT) ? 0 : bsc->sm_offset;
765 if (ti->sm_offset == 0)
766 flags |= BS_SCSI_NOSMIT;
767 else if (bsc->sc_cfgflags & BSC_SMITSAT_DISEN)
768 flags |= BS_SCSI_NOSAT;
770 flags &= (ti->ti_cfgflags & BS_SCSI_POSITIVE) | (~BS_SCSI_POSITIVE);
771 ti->ti_cfgflags = flags;
773 /* calculate synch setup */
774 period = BS_SCSI_PERIOD(flags);
775 offset = (flags & BS_SCSI_SYNC) ? BS_SCSI_OFFSET(flags) : 0;
777 maxperiod = (bsc->sc_cspeed & IDR_FS_16_20) ? 100 : 50;
778 if (period > maxperiod)
782 period = 2500 / period;
784 if (ti->ti_syncmax.offset > offset)
785 ti->ti_syncmax.offset = offset;
786 if (ti->ti_syncmax.period < period)
787 ti->ti_syncmax.period = period;
789 bshw_adj_syncdata(&ti->ti_syncmax);
791 /* finally report our info */
792 printf("%s(%d:%d): {%d:0x%x:0x%x:%s} flags 0x%b\n",
793 bsc->sc_dvname, ti->ti_id, ti->ti_lun,
794 (u_int) ti->targ_type,
795 (u_int) ti->targ_support,
796 (u_int) ti->bounce_size,
797 (flags & BS_SCSI_NOSMIT) ? "dma" : "pdma",
798 flags, BS_SCSI_BITS);
800 /* internal representation */
802 if ((ti->ti_cfgflags & BS_SCSI_DISC) == 0)
803 ti->ti_mflags &= ~BSDISC;
804 if ((ti->ti_cfgflags & BS_SCSI_LINK) == 0)
805 ti->ti_mflags &= ~BSLINK;
806 if (ti->ti_cfgflags & BS_SCSI_NOSAT)
807 ti->ti_mflags &= ~BSSAT;
808 if (ti->ti_cfgflags & BS_SCSI_NOSMIT)
809 ti->ti_mflags &= ~BSSMIT;
812 /**************************************************
814 **************************************************/
817 struct targ_info *ti;
823 printf("%s(%d:%d): <%s> %s\n",
824 ti->ti_bsc->sc_dvname, ti->ti_id, ti->ti_lun, ph, c);
826 printf("bs*(*:*): <%s> %s\n", ph, c);
831 struct bs_softc *bsc;
835 panic("%s %s\n", bsc->sc_dvname, c);
838 /**************************************************
840 **************************************************/
841 #ifdef BS_DEBUG_ROUTINE
861 #endif /* BS_DEBUG_ROUTINE */
864 bs_debug_print_all(bsc)
865 struct bs_softc *bsc;
867 struct targ_info *ti;
869 TAILQ_FOREACH(ti, &bsc->sc_titab.tqh_first, ti_tchain)
870 bs_debug_print(bsc, ti);
873 static u_char *phase[] =
875 "FREE", "HOSTQUE", "DISC", "COMPMSG", "ATN", "DISCMSG", "SELECT",
876 "SELECTED", "RESELECTED", "MSGIN", "MSGOUT", "STATIN", "CMDOUT",
877 "DATA", "SATSEL", "SATRESEL", "SATSDP", "SATCOMPSEQ", "UNDEF",
881 bs_debug_print(bsc, ti)
882 struct bs_softc *bsc;
883 struct targ_info *ti;
888 printf("%s <DEBUG INFO> nexus %lx bs %lx bus status %lx \n",
889 bsc->sc_dvname, (u_long) ti, (u_long) bsc->sc_nexus, (u_long) bsc->sc_busstat);
894 struct sc_p *sp = &bsc->sc_p;
896 printf("%s(%d:%d) ph<%s> ", bsc->sc_dvname, ti->ti_id,
897 ti->ti_lun, phase[(int) ti->ti_phase]);
898 printf("msgptr %x msg[0] %x status %x tqh %lx fl %x\n",
899 (u_int) (ti->ti_msginptr), (u_int) (ti->ti_msgin[0]),
900 ti->ti_status, (u_long) (cb = TAILQ_FIRST(&ti->ti_ctab)),
903 printf("cmdlen %x cmdaddr %lx cmd[0] %x\n",
904 cb->cmdlen, (u_long) cb->cmd, (int) cb->cmd[0]);
905 printf("datalen %x dataaddr %lx seglen %x ",
906 sp->datalen, (u_long) sp->data, sp->seglen);
908 printf("odatalen %x flags %x\n",
909 cb->datalen, cb->bsccb_flags);
912 printf("error flags %b\n", ti->ti_error, BSERRORBITS);