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