|
|
1.1 root 1: /*++
2:
3: Copyright (c) 1993 - Colorado Memory Systems, Inc.
4: All Rights Reserved
5:
6: Module Name:
7:
8: send.c
9:
10: Abstract:
11:
12: Sends a QIC117 command to the drive.
13:
14: Revision History:
15:
16:
17:
18:
19: --*/
20:
21: //
22: // include files
23: //
24:
25: #include <ntddk.h> // various NT definitions
26: #include <ntdddisk.h> // disk device driver I/O control codes
27: #include <ntiologc.h>
28: #include "common.h"
29: #include "drvtask.h" // this driver's data declarations
30: #include "mt1defs.h" // this driver's data declarations
31: #include "mt1strc.h" // this driver's data declarations
32: #include "q117data.h" // this driver's data declarations
33:
34:
35: STATUS
36: Q117iSendByte(
37: IN PTAPE_EXTENSION TapeExtension,
38: IN FIRMWARE_CMD Command
39: )
40:
41: /*++
42:
43: Routine Description:
44:
45: Transmit a command to the tape drive using step pulses generated by
46: the FDC.
47:
48: Using the Present Cylinder Number (pcn) of the FDC calculate a New
49: Cylinder Number (ncn) that will make the FDC generate the number of
50: step pulses corresponding to the command byte.
51:
52: Execute a Seek with the FDC.
53:
54: Sense Interrupt Status of the FDC and make sure that the pcn concurs
55: with the ncn, which indicates that the correct number of step pulses
56: were issued.
57:
58: Arguments:
59:
60: TapeExtension -
61:
62: Command -
63:
64: Return Value:
65:
66:
67:
68: --*/
69:
70: {
71: STATUS retval = NoErr;
72: SHORT statLength;
73: struct seek_cmd seek;
74: struct fdc_result result;
75: #if DBG
76: BOOLEAN save;
77:
78: // Lockout commands used to receive the status
79: save = TapeExtension->DbgLockout;
80: TapeExtension->DbgLockout = TRUE;
81: #endif
82:
83: if (TapeExtension->QControllerData->AbortRequested) {
84:
85: return(DAbort);
86:
87: }
88:
89: if (Command >= 128) {
90:
91: return(InvalCmd);
92:
93: }
94:
95: if (TapeExtension->QControllerData->FDC_Pcn < 128) {
96:
97: seek.NCN = TapeExtension->QControllerData->FDC_Pcn + Command;
98:
99: } else {
100:
101: seek.NCN = TapeExtension->QControllerData->FDC_Pcn - Command;
102:
103: }
104:
105: seek.cmd = 0x0f;
106: seek.drive = (UCHAR)TapeExtension->DriveParms.DriveSelect;
107: (VOID) Q117iResetInterruptEvent(TapeExtension);
108:
109: if ((retval = Q117iProgramFDC(
110: TapeExtension,
111: (CHAR *)&seek,
112: sizeof(seek),
113: FALSE)) != NoErr) {
114:
115: return(retval);
116:
117: }
118:
119: if (TapeExtension->QControllerData->StartFormatMode) {
120:
121: TapeExtension->FmtOp.NCN = seek.NCN;
122:
123: if (TapeExtension->XferRate.XferRate == SLOW) {
124:
125: CheckedDump(QIC117INFO,( "Q117i: FmtOp L_SLOW timeout %ld (decimal)\n",
126: TapeExtension->TapeParms.TimeOut[L_SLOW]));
127: retval = Q117iSleep(TapeExtension, TapeExtension->TapeParms.TimeOut[L_SLOW], TRUE);
128:
129: } else {
130:
131: CheckedDump(QIC117INFO,( "Q117i: FmtOp L_FAST timeout %ld (decimal)\n",
132: TapeExtension->TapeParms.TimeOut[L_FAST]));
133: retval = Q117iSleep(TapeExtension, TapeExtension->TapeParms.TimeOut[L_FAST], TRUE);
134:
135: }
136:
137: if ((retval == TimeOut) && (TapeExtension->FmtOp.retval == NoErr)) {
138:
139: TapeExtension->QControllerData->StartFormatMode = FALSE;
140: TapeExtension->QControllerData->EndFormatMode = FALSE;
141: IoFlushAdapterBuffers(
142: TapeExtension->QControllerData->AdapterObject,
143: TapeExtension->FmtOp.MdlAddress,
144: TapeExtension->QControllerData->MapRegisterBase,
145: (PVOID)( (ULONG) MmGetMdlVirtualAddress(TapeExtension->FmtOp.MdlAddress )
146: + TapeExtension->RdWrOp.BytesTransferredSoFar ),
147: TapeExtension->RdWrOp.TotalBytesOfTransfer,
148: DMA_READ );
149:
150: }
151:
152: if (retval == NoErr) {
153:
154: retval = TapeExtension->FmtOp.retval;
155:
156: }
157:
158: TapeExtension->QControllerData->StartFormatMode = FALSE;
159:
160: } else {
161:
162: Q117iSleep(TapeExtension, mt_wt001s, TRUE);
163:
164: // For some unknown reason, we occasionally miss an interrupt.
165: // Despite the timeout, we still press on as if we received the interrupt.
166: // Therefore, we go ahead and perform the sense interrupt status. If
167: // status register 0 is bad, then we assume that we truly did miss the
168: // interrupt. Otherwise, we go on as if nothing happened.
169: //
170:
171: if ((retval = Q117iReadFDC(TapeExtension, (CHAR *)&result, &statLength))
172: != NoErr) {
173:
174: return(retval);
175:
176: } else {
177:
178: //
179: // If the sense interrupt status is O.K., then proceed as if
180: // nothing happened. If, however, there is an error returned by
181: // status register 0, then return a NECFLT.
182: //
183:
184: if (! (result.ST0 & ST0_IC)) {
185:
186: //
187: // If we timed out, then we did the sense interrupt status
188: // without clearing the interrupt from the interrupt controller.
189: // Since the FDC did not indicate an error, we assume that we
190: // missed the interrupt and send the EOI. Only needed for an
191: // 82072.
192: //
193:
194: if (TapeExtension->QControllerData->InterfaceType != MicroChannel) {
195:
196: if (result.ST0 !=
197: (UCHAR)(TapeExtension->DriveParms.DriveSelect | ST0_SE)) {
198:
199: return(NECFlt);
200:
201: }
202: }
203:
204: if (seek.NCN != result.PCN) {
205:
206: return(CmdFlt);
207:
208: }
209:
210: TapeExtension->QControllerData->FDC_Pcn = result.PCN;
211:
212: } else {
213:
214: return(NECFlt);
215:
216: }
217: }
218: #if DBG
219: TapeExtension->DbgLockout = save;
220: DbgAddEntry(0x1234567b);
221: DbgAddEntry((UCHAR)Command);
222: #endif
223:
224: }
225:
226: return(retval);
227: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.