428 lines
11 KiB
C
428 lines
11 KiB
C
/*****************************************************************************
|
||
*
|
||
* COPYRIGHT 1993 - COLORADO MEMORY SYSTEMS, INC.
|
||
* ALL RIGHTS RESERVED.
|
||
*
|
||
******************************************************************************
|
||
*
|
||
* FILE: \SE\DRIVER\DEVICE\JUMBO\SRC\0X1102A.C
|
||
*
|
||
* FUNCTION: cqd_HighSpeedSeek
|
||
*
|
||
* PURPOSE: Execute a High Speed Seek. There are two methods of doing
|
||
* this now. First, if the Skip commands are not implemented,
|
||
* the high speed seek is accomplished by calculating the
|
||
* approximate amount of time needed at high speed to reach the
|
||
* target position and allowing the tape drive to go at 90 ips
|
||
* for that amount of time. If the Skip commands are implemented,
|
||
* the high speed seek is merely the proper command with
|
||
* a calculated offset.
|
||
*
|
||
* The Seeking is done by using either the Skip_N_Segments command
|
||
* or by using the time seeking algorithm provided by cqd_WaitSeek.
|
||
* The Skip_N_Segments commands are not reliable in all versions of
|
||
* the firmware. Only in versions for JUMBO_B and greater are the
|
||
* commands available at all and only in versions of 65 and greater
|
||
* are the Skip_N_Segment commands reliable for skipping past the
|
||
* DC erased gap.
|
||
*
|
||
* HISTORY:
|
||
* $Log: J:\se.vcs\driver\q117cd\src\0x1102a.c $
|
||
*
|
||
* Rev 1.13 15 May 1995 10:47:28 GaryKiwi
|
||
* Phoenix merge from CBW95s
|
||
*
|
||
* Rev 1.12.1.0 11 Apr 1995 18:04:06 garykiwi
|
||
* PHOENIX pass #1
|
||
*
|
||
* Rev 1.13 30 Jan 1995 14:25:08 BOBLEHMA
|
||
* Changed device_descriptor.version to cqd_context->firmware_version.
|
||
*
|
||
* Rev 1.12 14 Apr 1994 11:50:40 KEVINKES
|
||
* Changed seek slop back to previous rev and added rev seek slop if
|
||
* the drive is a Jumbo B.
|
||
*
|
||
* Rev 1.11 12 Apr 1994 14:49:52 KEVINKES
|
||
* Changed eot seek slop to 5% and rev seek slop to double the fwd seek slop.
|
||
*
|
||
* Rev 1.10 09 Mar 1994 09:48:08 KEVINKES
|
||
* Modified the setting of the reverse seek slop to be 1 if
|
||
* the firmware is greater than or equal to fw 88.
|
||
*
|
||
* Rev 1.9 17 Feb 1994 11:42:42 KEVINKES
|
||
* Added an extra parameter to WaitCC.
|
||
*
|
||
* Rev 1.8 01 Feb 1994 12:30:38 KEVINKES
|
||
* Added seek debug code.
|
||
*
|
||
* Rev 1.7 27 Jan 1994 15:58:42 KEVINKES
|
||
* Added debug code.
|
||
*
|
||
* Rev 1.6 18 Jan 1994 16:21:10 KEVINKES
|
||
* Updated debug code.
|
||
*
|
||
* Rev 1.5 14 Jan 1994 10:26:26 KEVINKES
|
||
* Modified EOT, BOT reverse seeking to only add 1 for cms drives
|
||
* with FW greater than 110.
|
||
*
|
||
* Rev 1.4 11 Jan 1994 14:39:22 KEVINKES
|
||
* Removed magic numbers.
|
||
*
|
||
* Rev 1.3 23 Nov 1993 18:49:48 KEVINKES
|
||
* Modified CHECKED_DUMP calls for debugging over the serial port.
|
||
*
|
||
* Rev 1.2 08 Nov 1993 14:04:28 KEVINKES
|
||
* Removed all bit-field structures, removed all enumerated types, changed
|
||
* all defines to uppercase, and removed all signed data types wherever
|
||
* possible.
|
||
*
|
||
* Rev 1.1 25 Oct 1993 14:38:46 KEVINKES
|
||
* Changed kdi_wt2ticks to kdi_wt004ms.
|
||
*
|
||
* Rev 1.0 18 Oct 1993 17:18:44 KEVINKES
|
||
* Initial Revision.
|
||
*
|
||
*****************************************************************************/
|
||
#define FCT_ID 0x1102a
|
||
#include "include\public\adi_api.h"
|
||
#include "include\public\frb_api.h"
|
||
#include "include\public\vendor.h"
|
||
#include "include\private\kdi_pub.h"
|
||
#include "include\private\cqd_pub.h"
|
||
#include "q117cd\include\cqd_defs.h"
|
||
#include "q117cd\include\cqd_strc.h"
|
||
#include "q117cd\include\cqd_hdr.h"
|
||
/*endinclude*/
|
||
|
||
dStatus cqd_HighSpeedSeek
|
||
(
|
||
/* INPUT PARAMETERS: */
|
||
|
||
CqdContextPtr cqd_context
|
||
|
||
/* UPDATE PARAMETERS: */
|
||
|
||
/* OUTPUT PARAMETERS: */
|
||
|
||
)
|
||
/* COMMENTS: *****************************************************************
|
||
*
|
||
* DEFINITIONS: *************************************************************/
|
||
{
|
||
|
||
/* DATA: ********************************************************************/
|
||
|
||
dStatus status=DONT_PANIC; /* dStatus or error condition.*/
|
||
dSDWord seek_offset=0l;
|
||
dUWord i;
|
||
dUByte seek_dir;
|
||
dUByte skip_n_segs;
|
||
dUWord skip;
|
||
|
||
/* CODE: ********************************************************************/
|
||
|
||
/* Determine the logical direction that the tape needs to be moved */
|
||
|
||
seek_offset = (dSDWord)((cqd_context->rd_wr_op.d_segment - 1l) -
|
||
cqd_context->operation_status.current_segment);
|
||
|
||
|
||
if (seek_offset >= 0l) {
|
||
|
||
seek_dir = FWD;
|
||
DBG_ADD_ENTRY(QIC117DBGSEEK, cqd_context, DBG_SEEK_FWD);
|
||
|
||
} else {
|
||
|
||
seek_dir = REV;
|
||
seek_offset = 0l - seek_offset;
|
||
DBG_ADD_ENTRY(QIC117DBGSEEK, cqd_context, DBG_SEEK_REV);
|
||
|
||
}
|
||
|
||
DBG_ADD_ENTRY(QIC117DBGSEEK, cqd_context, seek_offset);
|
||
|
||
if (seek_dir == REV || seek_offset > STOP_LEN) {
|
||
|
||
if ((status = cqd_StopTape(cqd_context)) != DONT_PANIC) {
|
||
|
||
return status;
|
||
|
||
}
|
||
|
||
if (seek_dir == FWD) {
|
||
|
||
if (cqd_context->drive_parms.seek_mode == SEEK_TIMED) {
|
||
|
||
seek_offset -= SEEK_SLOP;
|
||
|
||
} else {
|
||
|
||
seek_offset -= 1l;
|
||
|
||
}
|
||
|
||
} else {
|
||
|
||
/* seek direction is reverse */
|
||
|
||
if (cqd_context->rd_wr_op.bot ||
|
||
cqd_context->rd_wr_op.eot) {
|
||
|
||
if ((cqd_context->device_descriptor.vendor == VENDOR_CMS) &&
|
||
(cqd_context->firmware_version >= FIRM_VERSION_88)) {
|
||
|
||
seek_offset += 1l;
|
||
|
||
} else {
|
||
|
||
seek_offset += (cqd_context->tape_cfg.seg_tape_track * 45l)/1000l;
|
||
|
||
}
|
||
|
||
} else {
|
||
|
||
if ((cqd_context->drive_parms.seek_mode == SEEK_TIMED) ||
|
||
((cqd_context->device_descriptor.vendor == VENDOR_CMS) &&
|
||
(cqd_context->firmware_version >= FIRM_VERSION_60) &&
|
||
(cqd_context->firmware_version < FIRM_VERSION_80))) {
|
||
|
||
seek_offset += SEEK_SLOP;
|
||
|
||
} else {
|
||
|
||
seek_offset += 1l;
|
||
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
DBG_ADD_ENTRY(QIC117DBGSEEK, cqd_context, seek_offset);
|
||
|
||
switch (cqd_context->drive_parms.seek_mode) {
|
||
|
||
case SEEK_SKIP:
|
||
|
||
/* Determine the offset to be used for the Skip_N_Segment commands */
|
||
|
||
DBG_ADD_ENTRY(QIC117DBGSEEK, cqd_context, DBG_SEEK_PHASE);
|
||
DBG_ADD_ENTRY(QIC117DBGSEEK, cqd_context, 2);
|
||
|
||
if (seek_dir == FWD) {
|
||
|
||
skip_n_segs = FW_CMD_SKIP_N_FWD;
|
||
|
||
} else {
|
||
|
||
skip_n_segs = FW_CMD_SKIP_N_REV;
|
||
|
||
}
|
||
|
||
/* Skip the first bytes worth of segments */
|
||
|
||
if ((status = cqd_SendByte(
|
||
cqd_context,
|
||
skip_n_segs)) != DONT_PANIC) {
|
||
|
||
return status;
|
||
|
||
}
|
||
|
||
kdi_Sleep(cqd_context->kdi_context, INTERVAL_CMD, dFALSE);
|
||
|
||
if ((status = cqd_SendByte(
|
||
cqd_context,
|
||
(dUByte)((seek_offset & NIBBLE_MASK) + CMD_OFFSET))) != DONT_PANIC) {
|
||
|
||
return status;
|
||
|
||
}
|
||
|
||
kdi_Sleep(cqd_context->kdi_context, INTERVAL_CMD, dFALSE);
|
||
|
||
seek_offset >>= NIBBLE_SHIFT;
|
||
|
||
if ((status = cqd_SendByte(
|
||
cqd_context,
|
||
(dUByte)((seek_offset & NIBBLE_MASK) + CMD_OFFSET))) != DONT_PANIC) {
|
||
|
||
return status;
|
||
|
||
}
|
||
|
||
kdi_Sleep(cqd_context->kdi_context, INTERVAL_CMD, dFALSE);
|
||
|
||
if ((status = cqd_WaitCommandComplete(
|
||
cqd_context,
|
||
cqd_context->floppy_tape_parms.time_out[PHYSICAL],
|
||
dTRUE)) != DONT_PANIC) {
|
||
|
||
return status;
|
||
|
||
}
|
||
|
||
seek_offset >>= NIBBLE_SHIFT;
|
||
|
||
for (;seek_offset != 0; --seek_offset) {
|
||
|
||
/* Skip the second bytes worth of segments */
|
||
|
||
for (i=0; i<2; ++i) {
|
||
if (i) {
|
||
|
||
skip = 1;
|
||
|
||
} else {
|
||
|
||
skip = MAX_SKIP;
|
||
|
||
}
|
||
|
||
if ((status = cqd_SendByte(
|
||
cqd_context,
|
||
skip_n_segs)) != DONT_PANIC) {
|
||
|
||
return status;
|
||
|
||
}
|
||
|
||
kdi_Sleep(cqd_context->kdi_context, INTERVAL_CMD, dFALSE);
|
||
|
||
if ((status = cqd_SendByte(
|
||
cqd_context,
|
||
(dUByte)((skip & NIBBLE_MASK) + CMD_OFFSET))) != DONT_PANIC) {
|
||
|
||
return status;
|
||
|
||
}
|
||
|
||
kdi_Sleep(cqd_context->kdi_context, INTERVAL_CMD, dFALSE);
|
||
|
||
if ((status = cqd_SendByte(
|
||
cqd_context,
|
||
(dUByte)((skip >> NIBBLE_SHIFT) + CMD_OFFSET))) != DONT_PANIC) {
|
||
|
||
return status;
|
||
|
||
}
|
||
|
||
kdi_Sleep(cqd_context->kdi_context, INTERVAL_CMD, dFALSE);
|
||
|
||
if ((status = cqd_WaitCommandComplete(
|
||
cqd_context,
|
||
cqd_context->floppy_tape_parms.time_out[PHYSICAL],
|
||
dTRUE)) != DONT_PANIC) {
|
||
|
||
return status;
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
break;
|
||
|
||
case SEEK_SKIP_EXTENDED:
|
||
|
||
DBG_ADD_ENTRY(QIC117DBGSEEK, cqd_context, DBG_SEEK_PHASE);
|
||
DBG_ADD_ENTRY(QIC117DBGSEEK, cqd_context, 3);
|
||
|
||
if (seek_dir == FWD) {
|
||
|
||
if ((status = cqd_SendByte(
|
||
cqd_context,
|
||
FW_CMD_SKIP_N_FWD_EXT)) != DONT_PANIC) {
|
||
|
||
return status;
|
||
|
||
}
|
||
|
||
} else {
|
||
|
||
if ((status = cqd_SendByte(
|
||
cqd_context,
|
||
FW_CMD_SKIP_N_REV_EXT)) != DONT_PANIC) {
|
||
|
||
return status;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
|
||
|
||
kdi_Sleep(cqd_context->kdi_context, INTERVAL_CMD, dFALSE);
|
||
|
||
for (i = 0; i < MAX_SEEK_NIBBLES; i++) {
|
||
|
||
if ((status = cqd_SendByte(
|
||
cqd_context,
|
||
(dUByte)((seek_offset & NIBBLE_MASK) + CMD_OFFSET))) != DONT_PANIC) {
|
||
|
||
return status;
|
||
|
||
}
|
||
|
||
kdi_Sleep(cqd_context->kdi_context, INTERVAL_CMD, dFALSE);
|
||
|
||
seek_offset >>= NIBBLE_SHIFT;
|
||
|
||
}
|
||
|
||
if ((status = cqd_WaitCommandComplete(
|
||
cqd_context,
|
||
cqd_context->floppy_tape_parms.time_out[PHYSICAL],
|
||
dTRUE)) != DONT_PANIC) {
|
||
|
||
return status;
|
||
|
||
}
|
||
|
||
break;
|
||
|
||
default: /* SEEK_TIMED */
|
||
|
||
/* Skip segments commands are not available */
|
||
|
||
DBG_ADD_ENTRY(QIC117DBGSEEK, cqd_context, DBG_SEEK_PHASE);
|
||
DBG_ADD_ENTRY(QIC117DBGSEEK, cqd_context, 4);
|
||
|
||
if (((seek_dir == FWD) &&
|
||
((cqd_context->operation_status.current_track & 1) == 0)) ||
|
||
((seek_dir == REV) &&
|
||
((cqd_context->operation_status.current_track & 1) == 1))) {
|
||
|
||
if ((status = cqd_SendByte(cqd_context, FW_CMD_PHYSICAL_FWD)) !=
|
||
DONT_PANIC) {
|
||
|
||
return status;
|
||
|
||
}
|
||
|
||
} else {
|
||
|
||
if ((status = cqd_SendByte(cqd_context, FW_CMD_PHYSICAL_REV)) !=
|
||
DONT_PANIC) {
|
||
|
||
return status;
|
||
|
||
}
|
||
}
|
||
|
||
if ((status = cqd_WaitSeek(cqd_context, seek_offset)) != DONT_PANIC) {
|
||
|
||
return status;
|
||
|
||
}
|
||
|
||
if ((status = cqd_StopTape(cqd_context)) != DONT_PANIC) {
|
||
|
||
return status;
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
return status;
|
||
}
|