/* * (Try to) put the drive online. This is done the first time the * drive is opened, or if it har fallen offline. */ int rx_putonline(struct rx_softc *rx) { struct mscp *mp; struct mscp_softc *mi = device_private(device_parent(rx->ra_dev)); rx->ra_state = DK_CLOSED; mp = mscp_getcp(mi, MSCP_WAIT); mp->mscp_opcode = M_OP_ONLINE; mp->mscp_unit = rx->ra_hwunit; mp->mscp_cmdref = 1; *mp->mscp_addr |= MSCP_OWN | MSCP_INT; /* Poll away */ bus_space_read_2(mi->mi_iot, mi->mi_iph, 0); if (tsleep(&rx->ra_state, PRIBIO, "rxonline", 100*100)) rx->ra_state = DK_CLOSED; if (rx->ra_state == DK_CLOSED) return MSCP_FAILED; return MSCP_DONE; }
/* * (Try to) put the drive online. This is done the first time the * drive is opened, or if it has fallen offline. */ int mt_putonline(struct mt_softc *mt) { struct mscp *mp; struct mscp_softc *mi = device_private(device_parent(mt->mt_dev)); ((volatile struct mt_softc *) mt)->mt_state = MT_OFFLINE; mp = mscp_getcp(mi, MSCP_WAIT); mp->mscp_opcode = M_OP_ONLINE; mp->mscp_unit = mt->mt_hwunit; mp->mscp_cmdref = (long)&mt->mt_state; *mp->mscp_addr |= MSCP_OWN | MSCP_INT; /* Poll away */ bus_space_read_2(mi->mi_iot, mi->mi_iph, 0); if (tsleep(&mt->mt_state, PRIBIO, "mtonline", 240 * hz)) return MSCP_FAILED; if ((volatile int)mt->mt_state != MT_ONLINE) return MSCP_FAILED; return MSCP_DONE; }
/* * Send a command to the tape drive. Wait until the command is * finished before returning. * This routine must only be called when there are no data transfer * active on this device. Can we be sure of this? Or does the ctlr * queue up all command packets and take them in sequential order? * It sure would be nice if my manual stated this... /ragge */ int mtcmd(struct mt_softc *mt, int cmd, int count, int complete) { struct mscp *mp; struct mscp_softc *mi = device_private(device_parent(mt->mt_dev)); mp = mscp_getcp(mi, MSCP_WAIT); mt->mt_ioctlerr = 0; mp->mscp_unit = mt->mt_hwunit; mp->mscp_cmdref = -1; *mp->mscp_addr |= MSCP_OWN | MSCP_INT; switch (cmd) { case MTWEOF: mp->mscp_opcode = M_OP_WRITM; break; case MTBSF: mp->mscp_modifier = M_MD_REVERSE; case MTFSF: mp->mscp_opcode = M_OP_POS; mp->mscp_seq.seq_buffer = count; break; case MTBSR: mp->mscp_modifier = M_MD_REVERSE; case MTFSR: mp->mscp_opcode = M_OP_POS; mp->mscp_modifier |= M_MD_OBJCOUNT; mp->mscp_seq.seq_bytecount = count; break; case MTREW: mp->mscp_opcode = M_OP_POS; mp->mscp_modifier = M_MD_REWIND | M_MD_CLSEX; if (complete) mp->mscp_modifier |= M_MD_IMMEDIATE; mt->mt_serex = 0; break; case MTOFFL: mp->mscp_opcode = M_OP_AVAILABLE; mp->mscp_modifier = M_MD_UNLOAD | M_MD_CLSEX; mt->mt_serex = 0; break; case MTNOP: mp->mscp_opcode = M_OP_GETUNITST; break; case -1: /* Clear serious exception only */ mp->mscp_opcode = M_OP_POS; mp->mscp_modifier = M_MD_CLSEX; mt->mt_serex = 0; break; default: printf("Bad ioctl %x\n", cmd); mp->mscp_opcode = M_OP_POS; break; } bus_space_read_2(mi->mi_iot, mi->mi_iph, 0); tsleep(&mt->mt_inuse, PRIBIO, "mtioctl", 0); return mt->mt_ioctlerr; }