/* * The assign command sometimes blocks if the device is assigned * to another host (actually this shouldn't happen but it does). * So we set up a timeout for this call.
*/
timer_setup(&request->timer, tape_std_assign_timeout, 0);
mod_timer(&request->timer, jiffies + msecs_to_jiffies(2000));
/* * TAPE390_DISPLAY: Show a string on the tape display.
*/ int
tape_std_display(struct tape_device *device, struct display_struct *disp)
{ struct tape_request *request; int rc;
/* * MTLOAD: Loads the tape. * The default implementation just wait until the tape medium state changes * to MS_LOADED.
*/ int
tape_std_mtload(struct tape_device *device, int count)
{ return wait_event_interruptible(device->state_change_wq,
(device->medium_state == MS_LOADED));
}
/* * MTSETBLK: Set block size.
*/ int
tape_std_mtsetblk(struct tape_device *device, int count)
{ struct idal_buffer *new;
DBF_LH(6, "tape_std_mtsetblk(%d)\n", count); if (count <= 0) { /* * Just set block_size to 0. tapechar_read/tapechar_write * will realloc the idal buffer if a bigger one than the * current is needed.
*/
device->char_data.block_size = 0; return 0;
} if (device->char_data.idal_buf != NULL &&
device->char_data.idal_buf->size == count) /* We already have a idal buffer of that size. */ return 0;
/* Allocate a new idal buffer. */ new = idal_buffer_alloc(count, 0); if (IS_ERR(new)) return -ENOMEM; if (device->char_data.idal_buf != NULL)
idal_buffer_free(device->char_data.idal_buf);
device->char_data.idal_buf = new;
device->char_data.block_size = count;
DBF_LH(6, "new blocksize is %d\n", device->char_data.block_size);
return 0;
}
/* * MTRESET: Set block size to 0.
*/ int
tape_std_mtreset(struct tape_device *device, int count)
{
DBF_EVENT(6, "TCHAR:devreset:\n");
device->char_data.block_size = 0; return 0;
}
/* * MTFSF: Forward space over 'count' file marks. The tape is positioned * at the EOT (End of Tape) side of the file mark.
*/ int
tape_std_mtfsf(struct tape_device *device, int mt_count)
{ struct tape_request *request; struct ccw1 *ccw;
/* execute it */ return tape_do_io_free(device, request);
}
/* * MTFSR: Forward space over 'count' tape blocks (blocksize is set * via MTSETBLK.
*/ int
tape_std_mtfsr(struct tape_device *device, int mt_count)
{ struct tape_request *request; struct ccw1 *ccw; int rc;
/* execute it */
rc = tape_do_io(device, request); if (rc == 0 && request->rescnt > 0) {
DBF_LH(3, "FSR over tapemark\n");
rc = 1;
}
tape_free_request(request);
return rc;
}
/* * MTBSR: Backward space over 'count' tape blocks. * (blocksize is set via MTSETBLK.
*/ int
tape_std_mtbsr(struct tape_device *device, int mt_count)
{ struct tape_request *request; struct ccw1 *ccw; int rc;
/* execute it */
rc = tape_do_io(device, request); if (rc == 0 && request->rescnt > 0) {
DBF_LH(3, "BSR over tapemark\n");
rc = 1;
}
tape_free_request(request);
return rc;
}
/* * MTWEOF: Write 'count' file marks at the current position.
*/ int
tape_std_mtweof(struct tape_device *device, int mt_count)
{ struct tape_request *request; struct ccw1 *ccw;
/* execute it */ return tape_do_io_free(device, request);
}
/* * MTBSFM: Backward space over 'count' file marks. * The tape is positioned at the BOT (Begin Of Tape) side of the * last skipped file mark.
*/ int
tape_std_mtbsfm(struct tape_device *device, int mt_count)
{ struct tape_request *request; struct ccw1 *ccw;
/* execute it */ return tape_do_io_free(device, request);
}
/* * MTBSF: Backward space over 'count' file marks. The tape is positioned at * the EOT (End of Tape) side of the last skipped file mark.
*/ int
tape_std_mtbsf(struct tape_device *device, int mt_count)
{ struct tape_request *request; struct ccw1 *ccw; int rc;
/* * MTFSFM: Forward space over 'count' file marks. * The tape is positioned at the BOT (Begin Of Tape) side * of the last skipped file mark.
*/ int
tape_std_mtfsfm(struct tape_device *device, int mt_count)
{ struct tape_request *request; struct ccw1 *ccw; int rc;
/* execute it */ return tape_do_io_free(device, request);
}
/* * MTOFFL: Rewind the tape and put the drive off-line. * Implement 'rewind unload'
*/ int
tape_std_mtoffl(struct tape_device *device, int mt_count)
{ struct tape_request *request;
/* * MTEOM: positions at the end of the portion of the tape already used * for recordind data. MTEOM positions after the last file mark, ready for * appending another file.
*/ int
tape_std_mteom(struct tape_device *device, int mt_count)
{ int rc;
/* * Seek from the beginning of tape (rewind).
*/ if ((rc = tape_mtop(device, MTREW, 1)) < 0) return rc;
/* * The logical end of volume is given by two sewuential tapemarks. * Look for this by skipping to the next file (over one tapemark) * and then test for another one (fsr returns 1 if a tapemark was * encountered).
*/ do { if ((rc = tape_mtop(device, MTFSF, 1)) < 0) return rc; if ((rc = tape_mtop(device, MTFSR, 1)) < 0) return rc;
} while (rc == 0);
return tape_mtop(device, MTBSR, 1);
}
/* * MTRETEN: Retension the tape, i.e. forward space to end of tape and rewind.
*/ int
tape_std_mtreten(struct tape_device *device, int mt_count)
{ struct tape_request *request;
/* execute it */ return tape_do_io_free(device, request);
}
/* * MTUNLOAD: Rewind the tape and unload it.
*/ int
tape_std_mtunload(struct tape_device *device, int mt_count)
{ return tape_mtop(device, MTOFFL, mt_count);
}
/* * MTCOMPRESSION: used to enable compression. * Sets the IDRC on/off.
*/ int
tape_std_mtcompression(struct tape_device *device, int mt_count)
{ struct tape_request *request;
/* * We have to alloc 4 ccws in order to be able to transform request * into a read backward request in error case.
*/
request = tape_alloc_request(4, 0); if (IS_ERR(request)) {
DBF_EXCEPTION(6, "xrbl fail"); return request;
}
request->op = TO_RFO;
tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte);
tape_ccw_end_idal(request->cpaddr + 1, READ_FORWARD,
device->char_data.idal_buf);
DBF_EVENT(6, "xrbl ccwg\n"); return request;
}
/* * Read Block backward transformation function.
*/ void
tape_std_read_backward(struct tape_device *device, struct tape_request *request)
{ /* * We have allocated 4 ccws in tape_std_read, so we can now * transform the request to a read backward, followed by a * forward space block.
*/
request->op = TO_RBA;
tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte);
tape_ccw_cc_idal(request->cpaddr + 1, READ_BACKWARD,
device->char_data.idal_buf);
tape_ccw_cc(request->cpaddr + 2, FORSPACEBLOCK, 0, NULL);
tape_ccw_end(request->cpaddr + 3, NOP, 0, NULL);
DBF_EVENT(6, "xrop ccwg");}
/* * This routine is called by frontend after an ENOSP on write
*/ void
tape_std_process_eov(struct tape_device *device)
{ /* * End of volume: We have to backspace the last written record, then * we TRY to write a tapemark and then backspace over the written TM
*/ if (tape_mtop(device, MTBSR, 1) == 0 &&
tape_mtop(device, MTWEOF, 1) == 0) {
tape_mtop(device, MTBSR, 1);
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.