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 	rc = ndmca_connect_robot_agent (sess);
82 	if (rc) return rc;	/* already tattled */
83 
84 	rc = ndmca_robot_prep_target (sess);
85 	if (rc) return rc;	/* already tattled */
86 
87 	rc = ndmca_robot_check_ready (sess);
88 	if (rc) {	/* already tattled */
89 		if (!job->auto_remedy) {
90 			ndmalogf (sess, 0, 0, "Robot is not ready, failing");
91 			return -1;
92 		}
93 		ndmalogf (sess, 0, 0, "Robot is not ready, trying to remedy");
94 		rc = ndmca_robot_remedy_ready (sess);
95 		if (rc) {
96 			ndmalogf (sess, 0, 0, "Robot remedy failed");
97 			return -1;
98 		}
99 	}
100 
101 	if (verify_media_flag) {
102 		rc = ndmca_media_verify (sess);
103 		if (rc) return rc;	/* already tattled */
104 	}
105 
106 	return 0;
107 }
108 
109 /*
110  * ndmca_op_rewind_tape() and ndmca_op_eject_tape() really
111  * belong somewhere else. Here because they are close
112  * to the other "tape handling" operations.
113  */
114 
115 int
ndmca_op_rewind_tape(struct ndm_session * sess)116 ndmca_op_rewind_tape (struct ndm_session *sess)
117 {
118 	return ndmca_op_mtio (sess, NDMP9_MTIO_REW);
119 }
120 
121 int
ndmca_op_eject_tape(struct ndm_session * sess)122 ndmca_op_eject_tape (struct ndm_session *sess)
123 {
124 	return ndmca_op_mtio (sess, NDMP9_MTIO_OFF);
125 }
126 
127 
128 int
ndmca_op_mtio(struct ndm_session * sess,ndmp9_tape_mtio_op mtio_op)129 ndmca_op_mtio (struct ndm_session *sess, ndmp9_tape_mtio_op mtio_op)
130 {
131 	struct ndm_control_agent *ca = &sess->control_acb;
132 	int			rc;
133 
134 	ca->tape_mode = NDMP9_TAPE_READ_MODE;
135 	ca->is_label_op = 1;
136 
137 	rc = ndmca_connect_tape_agent (sess);
138 	if (rc) {
139 		ndmconn_destruct (sess->plumb.tape);
140 		return rc;	/* already tattled */
141 	}
142 
143 	rc = ndmca_media_open_tape (sess);
144 	if (rc) return rc;	/* already tattled */
145 
146 	if (mtio_op == NDMP9_MTIO_OFF) {
147 		/* best-effort rewind */
148 		ndmca_media_mtio_tape (sess, NDMP9_MTIO_REW, 1, 0);
149 	}
150 
151 	rc = ndmca_media_mtio_tape (sess, mtio_op, 1, 0);
152 	if (rc) {
153 		/* best-effort close */
154 		ndmca_media_close_tape (sess);
155 		return rc;	/* already tattled */
156 	}
157 
158 	rc = ndmca_media_close_tape (sess);
159 	if (rc) return rc;	/* already tattled */
160 
161 	return 0;
162 }
163 
164 int
ndmca_op_move_tape(struct ndm_session * sess)165 ndmca_op_move_tape (struct ndm_session *sess)
166 {
167 	struct ndm_control_agent *ca = &sess->control_acb;
168 	struct ndm_job_param *	job = &ca->job;
169 	int			src_addr = job->from_addr;
170 	int			dst_addr = job->to_addr;
171 	int			rc;
172 
173 	/* repeat audits */
174 	if (!job->to_addr_given || !job->from_addr_given) {
175 		ndmalogf (sess, 0, 0, "Missing to/from addr");
176 		return -1;
177 	}
178 
179 	rc = ndmca_robot_startup (sess);
180 	if (rc) return rc;	/* already tattled -- NOT */
181 
182 	rc = ndmca_robot_obtain_info (sess);
183 	if (rc) return rc;	/* already tattled -- NOT */
184 
185 	rc = ndmca_robot_move (sess, src_addr, dst_addr);
186 	if (rc) return rc;	/* already tattled */
187 
188 	return 0;
189 }
190 
191 int
ndmca_op_import_tape(struct ndm_session * sess)192 ndmca_op_import_tape (struct ndm_session *sess)
193 {
194 	struct ndm_control_agent *ca = &sess->control_acb;
195 	struct ndm_job_param *	job = &ca->job;
196 	struct smc_ctrl_block *	smc = &ca->smc_cb;
197 	int			src_addr;
198 	int			dst_addr = job->to_addr;
199 	int			rc;
200 
201 	/* repeat audits */
202 	if (!job->to_addr_given) {
203 		ndmalogf (sess, 0, 0, "Missing to-addr");
204 		return -1;
205 	}
206 
207 	rc = ndmca_robot_startup (sess);
208 	if (rc) return rc;	/* already tattled -- NOT */
209 
210 	rc = ndmca_robot_obtain_info (sess);
211 	if (rc) return rc;	/* already tattled -- NOT */
212 
213 	if (smc->elem_aa.iee_count < 1) {
214 		ndmalogf (sess, 0, 0, "robot has no import/export; try move");
215 		return -1;
216 	}
217 	src_addr = smc->elem_aa.iee_addr;
218 
219 	rc = ndmca_robot_move (sess, src_addr, dst_addr);
220 	if (rc) return rc;	/* already tattled */
221 
222 	return 0;
223 }
224 
225 int
ndmca_op_export_tape(struct ndm_session * sess)226 ndmca_op_export_tape (struct ndm_session *sess)
227 {
228 	struct ndm_control_agent *ca = &sess->control_acb;
229 	struct ndm_job_param *	job = &ca->job;
230 	struct smc_ctrl_block *	smc = &ca->smc_cb;
231 	int			src_addr = job->from_addr;
232 	int			dst_addr;
233 	int			rc;
234 
235 	/* repeat audits */
236 	if (!job->from_addr_given) {
237 		ndmalogf (sess, 0, 0, "Missing from-addr");
238 		return -1;
239 	}
240 
241 	rc = ndmca_robot_startup (sess);
242 	if (rc) return rc;	/* already tattled -- NOT */
243 
244 	rc = ndmca_robot_obtain_info (sess);
245 	if (rc) return rc;	/* already tattled -- NOT */
246 
247 	if (smc->elem_aa.iee_count < 1) {
248 		ndmalogf (sess, 0, 0, "robot has no import/export; try move");
249 		return -1;
250 	}
251 	dst_addr = smc->elem_aa.iee_addr;
252 
253 	rc = ndmca_robot_move (sess, src_addr, dst_addr);
254 	if (rc) return rc;	/* already tattled */
255 
256 	return 0;
257 }
258 
259 int
ndmca_op_load_tape(struct ndm_session * sess)260 ndmca_op_load_tape (struct ndm_session *sess)
261 {
262 	struct ndm_control_agent *ca = &sess->control_acb;
263 	struct ndm_job_param *	job = &ca->job;
264 	struct smc_ctrl_block *	smc = &ca->smc_cb;
265 	int			src_addr = job->from_addr;
266 	int			dst_addr;
267 	int			rc;
268 
269 	/* repeat audits */
270 	if (!job->from_addr_given) {
271 		ndmalogf (sess, 0, 0, "Missing from-addr");
272 		return -1;
273 	}
274 
275 	rc = ndmca_robot_startup (sess);
276 	if (rc) return rc;	/* already tattled -- NOT */
277 
278 	rc = ndmca_robot_obtain_info (sess);
279 	if (rc) return rc;	/* already tattled -- NOT */
280 
281 	if (job->drive_addr_given) {
282 		dst_addr = job->drive_addr;
283 	} else if (smc->elem_aa.dte_count > 0) {
284 		dst_addr = smc->elem_aa.dte_addr;
285 	} else {
286 		ndmalogf (sess, 0, 0, "robot has no tape drives? try move");
287 		return -1;
288 	}
289 
290 	/*
291 	 * Calculation for dst_addr repeated in ndmca_robot_load().
292 	 * We just did it to be sure it would succeed
293 	 */
294 
295 	rc = ndmca_robot_load (sess, src_addr);
296 	if (rc) return rc;	/* already tattled */
297 
298 	return 0;
299 }
300 
301 int
ndmca_op_unload_tape(struct ndm_session * sess)302 ndmca_op_unload_tape (struct ndm_session *sess)
303 {
304 	struct ndm_control_agent *ca = &sess->control_acb;
305 	struct ndm_job_param *	job = &ca->job;
306 	struct smc_ctrl_block *	smc = &ca->smc_cb;
307 	int			src_addr = job->from_addr;
308 	int			dst_addr;
309 	int			rc;
310 
311 	/* repeat audits */
312 	rc = ndmca_robot_startup (sess);
313 	if (rc) return rc;	/* already tattled -- NOT */
314 
315 	rc = ndmca_robot_obtain_info (sess);
316 	if (rc) return rc;	/* already tattled -- NOT */
317 
318 	if (job->drive_addr_given) {
319 		src_addr = job->drive_addr;
320 	} else if (smc->elem_aa.dte_count > 0) {
321 		src_addr = smc->elem_aa.dte_addr;
322 	} else {
323 		ndmalogf (sess, 0, 0, "robot has no tape drives? try move");
324 		return -1;
325 	}
326 
327 	/*
328 	 * Calculation for src_addr repeated in ndmca_robot_unload().
329 	 * We just did it to be sure it would succeed
330 	 */
331 
332 	if (job->tape_device) {
333 		/* best effort */
334 		rc = ndmca_op_mtio (sess, job->use_eject
335 					    ? NDMP9_MTIO_OFF : NDMP9_MTIO_REW);
336 	}
337 
338 	if (job->to_addr_given) {
339 		dst_addr = job->to_addr;
340 	} else {
341 		struct smc_element_descriptor *	edp;
342 		struct smc_element_descriptor *	edp2;
343 		char				prefix[60];
344 
345 		/*
346 		 * Try to automatically determine where to
347 		 * put the tape, if there is one in the drive.
348 		 * This is pretty much a rip-off of remedy_robot().
349 		 * The difference is here we believe the user
350 		 * that something should happen. Otherwise,
351 		 * the user would have used REMEDY_ROBOT.
352 		 */
353 
354 		edp = ndmca_robot_find_element (sess, src_addr);
355 		if (!edp) {
356 			ndmalogf (sess, 0, 1,
357 				"no such slot @%d, trying unload anyway",
358 				src_addr);
359 			dst_addr = 0;		/* g'luck! */
360 			goto unload_anyway;
361 		}
362 
363 		if (!edp->Full) {
364 			ndmalogf (sess, 0, 1,
365 				"drive @%d empty, trying unload anyway",
366 				src_addr);
367 			dst_addr = 0;		/* g'luck! */
368 			goto unload_anyway;
369 		}
370 
371 		sprintf (prefix, "drive @%d full", edp->element_address);
372 
373 		if (!edp->SValid) {
374 			ndmalogf (sess, 0, 1,
375 				"%s, no SValid info, you must specify to-addr",
376 				prefix);
377 			return -1;
378 		}
379 
380 		dst_addr = edp->src_se_addr;
381 
382 		sprintf (NDMOS_API_STREND(prefix), ", src @%d",
383 							edp->src_se_addr);
384 
385 		edp2 = ndmca_robot_find_element (sess, dst_addr);
386 		if (!edp2) {
387 			ndmalogf (sess, 0, 1,
388 				"%s, no such addr, trying unload anyway",
389 				prefix);
390 			goto unload_anyway;
391 		}
392 
393 		if (edp2->element_type_code != SMC_ELEM_TYPE_SE) {
394 			ndmalogf (sess, 0, 1,
395 				"%s, not slot, trying unload anyway", prefix);
396 			goto unload_anyway;
397 		}
398 
399 		if (edp2->Full) {
400 			ndmalogf (sess, 0, 1,
401 				"%s, slot Full, trying unload anyway", prefix);
402 			goto unload_anyway;
403 		}
404 	}
405 
406 
407   unload_anyway:
408 	rc = ndmca_robot_unload (sess, dst_addr);
409 	if (rc) return rc;	/* already tattled */
410 
411 	return 0;
412 }
413 
414 int
ndmca_op_init_elem_status(struct ndm_session * sess)415 ndmca_op_init_elem_status (struct ndm_session *sess)
416 {
417 	int			rc;
418 
419 	/* repeat audits */
420 	rc = ndmca_robot_startup (sess);
421 	if (rc) return rc;	/* already tattled -- NOT */
422 
423 	/* best-effort */
424 	rc = ndmca_robot_obtain_info (sess);
425 
426 	rc = ndmca_robot_init_elem_status (sess);
427 	if (rc) return rc;	/* already tattled */
428 
429 	rc = ndmca_robot_query (sess);
430 	if (rc) return rc;	/* already tattled -- WAY WAY tattled */
431 
432 	return 0;
433 }
434 
435 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */
436