1 /*
2 * Copyright (c) 1998,1999,2000
3 * Traakan, Inc., Los Altos, CA
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice unmodified, this list of conditions, and the following
11 * disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 /*
30 * Project: NDMJOB
31 * Ident: $Id: $
32 *
33 * Description:
34 *
35 */
36
37
38 #include "ndmagents.h"
39
40
41 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT
42
43
44 int
ndmca_op_robot_remedy(struct ndm_session * sess)45 ndmca_op_robot_remedy (struct ndm_session *sess)
46 {
47 struct ndm_job_param * job = &sess->control_acb->job;
48 int rc;
49
50 if (!job->have_robot)
51 return 0;
52
53 rc = ndmca_connect_robot_agent (sess);
54 if (rc) return rc; /* already tattled */
55
56 rc = ndmca_robot_prep_target (sess);
57 if (rc) return rc; /* already tattled */
58
59 rc = ndmca_robot_check_ready (sess);
60 if (rc) { /* already tattled */
61 ndmalogf (sess, 0, 0, "Robot is not ready, trying to remedy");
62 rc = ndmca_robot_remedy_ready (sess);
63 if (rc) {
64 ndmalogf (sess, 0, 0, "Robot remedy failed");
65 return -1;
66 }
67 }
68
69 return 0;
70 }
71
72 int
ndmca_op_robot_startup(struct ndm_session * sess,int verify_media_flag)73 ndmca_op_robot_startup (struct ndm_session *sess, int verify_media_flag)
74 {
75 struct ndm_job_param * job = &sess->control_acb->job;
76 int rc;
77
78 if (!job->have_robot)
79 return 0;
80
81 if (!sess->control_acb->smc_cb) {
82 sess->control_acb->smc_cb = NDMOS_API_MALLOC (sizeof(struct smc_ctrl_block));
83 NDMOS_MACRO_ZEROFILL (sess->control_acb->smc_cb);
84 }
85 rc = ndmca_connect_robot_agent (sess);
86 if (rc) return rc; /* already tattled */
87
88 rc = ndmca_robot_prep_target (sess);
89 if (rc) return rc; /* already tattled */
90
91 rc = ndmca_robot_check_ready (sess);
92 if (rc) { /* already tattled */
93 if (!job->auto_remedy) {
94 ndmalogf (sess, 0, 0, "Robot is not ready, failing");
95 return -1;
96 }
97 ndmalogf (sess, 0, 0, "Robot is not ready, trying to remedy");
98 rc = ndmca_robot_remedy_ready (sess);
99 if (rc) {
100 ndmalogf (sess, 0, 0, "Robot remedy failed");
101 return -1;
102 }
103 }
104
105 if (verify_media_flag) {
106 rc = ndmca_media_verify (sess);
107 if (rc) return rc; /* already tattled */
108 }
109
110 return 0;
111 }
112
113 /*
114 * ndmca_op_rewind_tape() and ndmca_op_eject_tape() really
115 * belong somewhere else. Here because they are close
116 * to the other "tape handling" operations.
117 */
118
119 int
ndmca_op_rewind_tape(struct ndm_session * sess)120 ndmca_op_rewind_tape (struct ndm_session *sess)
121 {
122 return ndmca_op_mtio (sess, NDMP9_MTIO_REW);
123 }
124
125 int
ndmca_op_eject_tape(struct ndm_session * sess)126 ndmca_op_eject_tape (struct ndm_session *sess)
127 {
128 return ndmca_op_mtio (sess, NDMP9_MTIO_OFF);
129 }
130
131
132 int
ndmca_op_mtio(struct ndm_session * sess,ndmp9_tape_mtio_op mtio_op)133 ndmca_op_mtio (struct ndm_session *sess, ndmp9_tape_mtio_op mtio_op)
134 {
135 struct ndm_control_agent *ca = sess->control_acb;
136 int rc;
137
138 ca->tape_mode = NDMP9_TAPE_READ_MODE;
139 ca->is_label_op = 1;
140
141 rc = ndmca_connect_tape_agent (sess);
142 if (rc) {
143 ndmconn_destruct (sess->plumb.tape);
144 return rc; /* already tattled */
145 }
146
147 rc = ndmca_media_open_tape (sess);
148 if (rc) return rc; /* already tattled */
149
150 if (mtio_op == NDMP9_MTIO_OFF) {
151 /* best-effort rewind */
152 ndmca_media_mtio_tape (sess, NDMP9_MTIO_REW, 1, 0);
153 }
154
155 rc = ndmca_media_mtio_tape (sess, mtio_op, 1, 0);
156 if (rc) {
157 /* best-effort close */
158 ndmca_media_close_tape (sess);
159 return rc; /* already tattled */
160 }
161
162 rc = ndmca_media_close_tape (sess);
163 if (rc) return rc; /* already tattled */
164
165 return 0;
166 }
167
168 int
ndmca_op_move_tape(struct ndm_session * sess)169 ndmca_op_move_tape (struct ndm_session *sess)
170 {
171 struct ndm_control_agent *ca = sess->control_acb;
172 struct ndm_job_param * job = &ca->job;
173 int src_addr = job->from_addr;
174 int dst_addr = job->to_addr;
175 int rc;
176
177 /* repeat audits */
178 if (!job->to_addr_given || !job->from_addr_given) {
179 ndmalogf (sess, 0, 0, "Missing to/from addr");
180 return -1;
181 }
182
183 rc = ndmca_robot_startup (sess);
184 if (rc) return rc; /* already tattled -- NOT */
185
186 rc = ndmca_robot_obtain_info (sess);
187 if (rc) return rc; /* already tattled -- NOT */
188
189 rc = ndmca_robot_move (sess, src_addr, dst_addr);
190 if (rc) return rc; /* already tattled */
191
192 return 0;
193 }
194
195 int
ndmca_op_import_tape(struct ndm_session * sess)196 ndmca_op_import_tape (struct ndm_session *sess)
197 {
198 struct ndm_control_agent *ca = sess->control_acb;
199 struct ndm_job_param * job = &ca->job;
200 struct smc_ctrl_block * smc = ca->smc_cb;
201 int src_addr;
202 int dst_addr = job->to_addr;
203 int rc;
204
205 /* repeat audits */
206 if (!job->to_addr_given) {
207 ndmalogf (sess, 0, 0, "Missing to-addr");
208 return -1;
209 }
210
211 rc = ndmca_robot_startup (sess);
212 if (rc) return rc; /* already tattled -- NOT */
213
214 rc = ndmca_robot_obtain_info (sess);
215 if (rc) return rc; /* already tattled -- NOT */
216
217 if (smc->elem_aa.iee_count < 1) {
218 ndmalogf (sess, 0, 0, "robot has no import/export; try move");
219 return -1;
220 }
221 src_addr = smc->elem_aa.iee_addr;
222
223 rc = ndmca_robot_move (sess, src_addr, dst_addr);
224 if (rc) return rc; /* already tattled */
225
226 return 0;
227 }
228
229 int
ndmca_op_export_tape(struct ndm_session * sess)230 ndmca_op_export_tape (struct ndm_session *sess)
231 {
232 struct ndm_control_agent *ca = sess->control_acb;
233 struct ndm_job_param * job = &ca->job;
234 struct smc_ctrl_block * smc = ca->smc_cb;
235 int src_addr = job->from_addr;
236 int dst_addr;
237 int rc;
238
239 /* repeat audits */
240 if (!job->from_addr_given) {
241 ndmalogf (sess, 0, 0, "Missing from-addr");
242 return -1;
243 }
244
245 rc = ndmca_robot_startup (sess);
246 if (rc) return rc; /* already tattled -- NOT */
247
248 rc = ndmca_robot_obtain_info (sess);
249 if (rc) return rc; /* already tattled -- NOT */
250
251 if (smc->elem_aa.iee_count < 1) {
252 ndmalogf (sess, 0, 0, "robot has no import/export; try move");
253 return -1;
254 }
255 dst_addr = smc->elem_aa.iee_addr;
256
257 rc = ndmca_robot_move (sess, src_addr, dst_addr);
258 if (rc) return rc; /* already tattled */
259
260 return 0;
261 }
262
263 int
ndmca_op_load_tape(struct ndm_session * sess)264 ndmca_op_load_tape (struct ndm_session *sess)
265 {
266 struct ndm_control_agent *ca = sess->control_acb;
267 struct ndm_job_param * job = &ca->job;
268 struct smc_ctrl_block * smc = ca->smc_cb;
269 int src_addr = job->from_addr;
270 int dst_addr;
271 int rc;
272
273 /* repeat audits */
274 if (!job->from_addr_given) {
275 ndmalogf (sess, 0, 0, "Missing from-addr");
276 return -1;
277 }
278
279 rc = ndmca_robot_startup (sess);
280 if (rc) return rc; /* already tattled -- NOT */
281
282 rc = ndmca_robot_obtain_info (sess);
283 if (rc) return rc; /* already tattled -- NOT */
284
285 if (job->drive_addr_given) {
286 dst_addr = job->drive_addr;
287 } else if (smc->elem_aa.dte_count > 0) {
288 dst_addr = smc->elem_aa.dte_addr;
289 } else {
290 ndmalogf (sess, 0, 0, "robot has no tape drives? try move");
291 return -1;
292 }
293
294 /*
295 * Calculation for dst_addr repeated in ndmca_robot_load().
296 * We just did it to be sure it would succeed
297 */
298
299 rc = ndmca_robot_load (sess, src_addr);
300 if (rc) return rc; /* already tattled */
301
302 return 0;
303 }
304
305 int
ndmca_op_unload_tape(struct ndm_session * sess)306 ndmca_op_unload_tape (struct ndm_session *sess)
307 {
308 struct ndm_control_agent *ca = sess->control_acb;
309 struct ndm_job_param * job = &ca->job;
310 struct smc_ctrl_block * smc = ca->smc_cb;
311 int src_addr = job->from_addr;
312 int dst_addr;
313 int rc;
314
315 /* repeat audits */
316 rc = ndmca_robot_startup (sess);
317 if (rc) return rc; /* already tattled -- NOT */
318
319 rc = ndmca_robot_obtain_info (sess);
320 if (rc) return rc; /* already tattled -- NOT */
321
322 if (job->drive_addr_given) {
323 src_addr = job->drive_addr;
324 } else if (smc->elem_aa.dte_count > 0) {
325 src_addr = smc->elem_aa.dte_addr;
326 } else {
327 ndmalogf (sess, 0, 0, "robot has no tape drives? try move");
328 return -1;
329 }
330
331 /*
332 * Calculation for src_addr repeated in ndmca_robot_unload().
333 * We just did it to be sure it would succeed
334 */
335
336 if (job->tape_device) {
337 /* best effort */
338 rc = ndmca_op_mtio (sess, job->use_eject
339 ? NDMP9_MTIO_OFF : NDMP9_MTIO_REW);
340 if (rc) return rc; /* already tattled -- NOT */
341 }
342
343 if (job->to_addr_given) {
344 dst_addr = job->to_addr;
345 } else {
346 struct smc_element_descriptor * edp;
347 struct smc_element_descriptor * edp2;
348 char prefix[60];
349
350 /*
351 * Try to automatically determine where to
352 * put the tape, if there is one in the drive.
353 * This is pretty much a rip-off of remedy_robot().
354 * The difference is here we believe the user
355 * that something should happen. Otherwise,
356 * the user would have used REMEDY_ROBOT.
357 */
358
359 edp = ndmca_robot_find_element (sess, src_addr);
360 if (!edp) {
361 ndmalogf (sess, 0, 1,
362 "no such slot @%d, trying unload anyway",
363 src_addr);
364 dst_addr = 0; /* g'luck! */
365 goto unload_anyway;
366 }
367
368 if (!edp->Full) {
369 ndmalogf (sess, 0, 1,
370 "drive @%d empty, trying unload anyway",
371 src_addr);
372 dst_addr = 0; /* g'luck! */
373 goto unload_anyway;
374 }
375
376 snprintf (prefix, sizeof(prefix), "drive @%d full", edp->element_address);
377
378 if (!edp->SValid) {
379 ndmalogf (sess, 0, 1,
380 "%s, no SValid info, you must specify to-addr",
381 prefix);
382 return -1;
383 }
384
385 dst_addr = edp->src_se_addr;
386
387 sprintf (NDMOS_API_STREND(prefix), ", src @%d",
388 edp->src_se_addr);
389
390 edp2 = ndmca_robot_find_element (sess, dst_addr);
391 if (!edp2) {
392 ndmalogf (sess, 0, 1,
393 "%s, no such addr, trying unload anyway",
394 prefix);
395 goto unload_anyway;
396 }
397
398 if (edp2->element_type_code != SMC_ELEM_TYPE_SE) {
399 ndmalogf (sess, 0, 1,
400 "%s, not slot, trying unload anyway", prefix);
401 goto unload_anyway;
402 }
403
404 if (edp2->Full) {
405 ndmalogf (sess, 0, 1,
406 "%s, slot Full, trying unload anyway", prefix);
407 goto unload_anyway;
408 }
409 }
410
411
412 unload_anyway:
413 rc = ndmca_robot_unload (sess, dst_addr);
414 if (rc) return rc; /* already tattled */
415
416 return 0;
417 }
418
419 int
ndmca_op_init_elem_status(struct ndm_session * sess)420 ndmca_op_init_elem_status (struct ndm_session *sess)
421 {
422 int rc;
423
424 /* repeat audits */
425 rc = ndmca_robot_startup (sess);
426 if (rc) return rc; /* already tattled -- NOT */
427
428 /* best-effort */
429 rc = ndmca_robot_obtain_info (sess);
430
431 rc = ndmca_robot_init_elem_status (sess);
432 if (rc) return rc; /* already tattled */
433
434 rc = ndmca_robot_query (sess);
435 if (rc) return rc; /* already tattled -- WAY WAY tattled */
436
437 return 0;
438 }
439
440 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */
441