1 /*
2 SCSI Tape Driver for Linux version 1.1 and newer. See the accompanying
3 file README.st for more information.
4
5 History:
6
7 OnStream SCSI Tape support (osst) cloned from st.c by
8 Willem Riede (osst@riede.org) Feb 2000
9 Fixes ... Kurt Garloff <garloff@suse.de> Mar 2000
10
11 Rewritten from Dwayne Forsyth's SCSI tape driver by Kai Makisara.
12 Contribution and ideas from several people including (in alphabetical
13 order) Klaus Ehrenfried, Wolfgang Denk, Steve Hirsch, Andreas Koppenh"ofer,
14 Michael Leodolter, Eyal Lebedinsky, J"org Weule, and Eric Youngdale.
15
16 Copyright 1992 - 2000 Kai Makisara
17 email Kai.Makisara@metla.fi
18
19 $Header: /cvsroot/osst/Driver/osst.c,v 1.67.2.1 2003/06/28 00:21:28 riede Exp $
20
21 Microscopic alterations - Rik Ling, 2000/12/21
22 Last modified: Wed Feb 2 22:04:05 2000 by makisara@kai.makisara.local
23 Some small formal changes - aeb, 950809
24 */
25
26 static const char * cvsid = "$Id: osst.c,v 1.67.2.2 2003/12/14 14:28:46 wriede Exp $";
27 const char * osst_version = "0.9.14";
28
29 /* The "failure to reconnect" firmware bug */
30 #define OSST_FW_NEED_POLL_MIN 10601 /*(107A)*/
31 #define OSST_FW_NEED_POLL_MAX 10704 /*(108D)*/
32 #define OSST_FW_NEED_POLL(x,d) ((x) >= OSST_FW_NEED_POLL_MIN && (x) <= OSST_FW_NEED_POLL_MAX && d->host->this_id != 7)
33
34 #include <linux/module.h>
35
36 #include <linux/fs.h>
37 #include <linux/kernel.h>
38 #include <linux/sched.h>
39 #include <linux/proc_fs.h>
40 #include <linux/mm.h>
41 #include <linux/init.h>
42 #include <linux/string.h>
43 #include <linux/errno.h>
44 #include <linux/mtio.h>
45 #include <linux/ioctl.h>
46 #include <linux/fcntl.h>
47 #include <linux/spinlock.h>
48 #include <linux/vmalloc.h>
49 #include <linux/version.h>
50 #include <asm/uaccess.h>
51 #include <asm/dma.h>
52 #include <asm/system.h>
53
54 /* The driver prints some debugging information on the console if DEBUG
55 is defined and non-zero. */
56 #define DEBUG 0
57
58 /* The message level for the debug messages is currently set to KERN_NOTICE
59 so that people can easily see the messages. Later when the debugging messages
60 in the drivers are more widely classified, this may be changed to KERN_DEBUG. */
61 #define OSST_DEB_MSG KERN_NOTICE
62
63 #define MAJOR_NR OSST_MAJOR
64 #include <linux/blk.h>
65
66 #include "scsi.h"
67 #include "hosts.h"
68 #include <scsi/scsi_ioctl.h>
69
70 #define ST_KILOBYTE 1024
71
72 #include "st.h"
73 #include "osst.h"
74 #include "osst_options.h"
75 #include "osst_detect.h"
76
77 #include "constants.h"
78
79 static int max_dev = 0;
80 static int write_threshold_kbs = 0;
81 static int max_sg_segs = 0;
82
83 #ifdef MODULE
84 MODULE_AUTHOR("Willem Riede");
85 MODULE_DESCRIPTION("OnStream SCSI Tape Driver");
86 MODULE_LICENSE("GPL");
87
88 MODULE_PARM(max_dev, "i");
89 MODULE_PARM(write_threshold_kbs, "i");
90 MODULE_PARM(max_sg_segs, "i");
91 #else
92 static struct osst_dev_parm {
93 char *name;
94 int *val;
95 } parms[] __initdata = {
96 { "max_dev", &max_dev },
97 { "write_threshold_kbs", &write_threshold_kbs },
98 { "max_sg_segs", &max_sg_segs }
99 };
100 #endif
101
102 /* Some default definitions have been moved to osst_options.h */
103 #define OSST_BUFFER_SIZE (OSST_BUFFER_BLOCKS * ST_KILOBYTE)
104 #define OSST_WRITE_THRESHOLD (OSST_WRITE_THRESHOLD_BLOCKS * ST_KILOBYTE)
105
106 /* The buffer size should fit into the 24 bits for length in the
107 6-byte SCSI read and write commands. */
108 #if OSST_BUFFER_SIZE >= (2 << 24 - 1)
109 #error "Buffer size should not exceed (2 << 24 - 1) bytes!"
110 #endif
111
112 #if DEBUG
113 static int debugging = 1;
114 /* uncomment define below to test error recovery */
115 // #define OSST_INJECT_ERRORS 1
116 #endif
117
118 #define MAX_RETRIES 2
119 #define MAX_READ_RETRIES 0
120 #define MAX_WRITE_RETRIES 0
121 #define MAX_READY_RETRIES 0
122 #define NO_TAPE NOT_READY
123
124 #define OSST_WAIT_POSITION_COMPLETE (HZ > 200 ? HZ / 200 : 1)
125 #define OSST_WAIT_WRITE_COMPLETE (HZ / 12)
126 #define OSST_WAIT_LONG_WRITE_COMPLETE (HZ / 2)
127
128 #define OSST_TIMEOUT (200 * HZ)
129 #define OSST_LONG_TIMEOUT (1800 * HZ)
130
131 #define TAPE_NR(x) (MINOR(x) & ~(128 | ST_MODE_MASK))
132 #define TAPE_MODE(x) ((MINOR(x) & ST_MODE_MASK) >> ST_MODE_SHIFT)
133
134 /* Internal ioctl to set both density (uppermost 8 bits) and blocksize (lower
135 24 bits) */
136 #define SET_DENS_AND_BLK 0x10001
137
138 static int osst_nbr_buffers;
139 static int osst_buffer_size = OSST_BUFFER_SIZE;
140 static int osst_write_threshold = OSST_WRITE_THRESHOLD;
141 static int osst_max_buffers = OSST_MAX_BUFFERS;
142 static int osst_max_sg_segs = OSST_MAX_SG;
143 static int osst_max_dev = OSST_MAX_TAPES;
144
145 static OS_Scsi_Tape **os_scsi_tapes = NULL;
146 static OSST_buffer **osst_buffers = NULL;
147
148 static int modes_defined = FALSE;
149
150 static OSST_buffer *new_tape_buffer(int, int);
151 static int enlarge_buffer(OSST_buffer *, int, int);
152 static void normalize_buffer(OSST_buffer *);
153 static int append_to_buffer(const char *, OSST_buffer *, int);
154 static int from_buffer(OSST_buffer *, char *, int);
155 static int osst_zero_buffer_tail(OSST_buffer *);
156 static int osst_copy_to_buffer(OSST_buffer *, unsigned char *);
157 static int osst_copy_from_buffer(OSST_buffer *, unsigned char *);
158
159 static int osst_init(void);
160 static int osst_attach(Scsi_Device *);
161 static int osst_detect(Scsi_Device *);
162 static void osst_detach(Scsi_Device *);
163
164 struct Scsi_Device_Template osst_template =
165 {
166 name: "OnStream tape",
167 tag: "osst",
168 scsi_type: TYPE_TAPE,
169 major: OSST_MAJOR,
170 detect: osst_detect,
171 init: osst_init,
172 attach: osst_attach,
173 detach: osst_detach
174 };
175
176 static int osst_int_ioctl(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, unsigned int cmd_in,unsigned long arg);
177
178 static int osst_set_frame_position(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, int frame, int skip);
179
180 static int osst_get_frame_position(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt);
181
182 static int osst_flush_write_buffer(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt);
183
184 static int osst_write_error_recovery(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int pending);
185
186
187 /* Routines that handle the interaction with mid-layer SCSI routines */
188
189 /* Convert the result to success code */
osst_chk_result(OS_Scsi_Tape * STp,Scsi_Request * SRpnt)190 static int osst_chk_result(OS_Scsi_Tape * STp, Scsi_Request * SRpnt)
191 {
192 int dev = TAPE_NR(STp->devt);
193 int result = SRpnt->sr_result;
194 unsigned char * sense = SRpnt->sr_sense_buffer, scode;
195 #if DEBUG
196 const char *stp;
197 #endif
198
199 if (!result) {
200 sense[0] = 0; /* We don't have sense data if this byte is zero */
201 return 0;
202 }
203 if (driver_byte(result) & DRIVER_SENSE)
204 scode = sense[2] & 0x0f;
205 else {
206 sense[0] = 0; /* We don't have sense data if this byte is zero */
207 scode = 0;
208 }
209
210 #if DEBUG
211 if (debugging) {
212 printk(OSST_DEB_MSG "osst%d:D: Error: %x, cmd: %x %x %x %x %x %x Len: %d\n",
213 dev, result,
214 SRpnt->sr_cmnd[0], SRpnt->sr_cmnd[1], SRpnt->sr_cmnd[2],
215 SRpnt->sr_cmnd[3], SRpnt->sr_cmnd[4], SRpnt->sr_cmnd[5],
216 SRpnt->sr_bufflen);
217 if (driver_byte(result) & DRIVER_SENSE)
218 print_req_sense("osst", SRpnt);
219 }
220 else
221 #endif
222 if (!(driver_byte(result) & DRIVER_SENSE) ||
223 ((sense[0] & 0x70) == 0x70 &&
224 scode != NO_SENSE &&
225 scode != RECOVERED_ERROR &&
226 /* scode != UNIT_ATTENTION && */
227 scode != BLANK_CHECK &&
228 scode != VOLUME_OVERFLOW &&
229 SRpnt->sr_cmnd[0] != MODE_SENSE &&
230 SRpnt->sr_cmnd[0] != TEST_UNIT_READY)) { /* Abnormal conditions for tape */
231 if (driver_byte(result) & DRIVER_SENSE) {
232 printk(KERN_WARNING "osst%d:W: Command with sense data: ", dev);
233 print_req_sense("osst:", SRpnt);
234 }
235 else {
236 static int notyetprinted = 1;
237
238 printk(KERN_WARNING
239 "osst%d:W: Warning %x (sugg. bt 0x%x, driver bt 0x%x, host bt 0x%x).\n",
240 dev, result, suggestion(result), driver_byte(result) & DRIVER_MASK,
241 host_byte(result));
242 if (notyetprinted) {
243 notyetprinted = 0;
244 printk(KERN_INFO
245 "osst%d:I: This warning may be caused by your scsi controller,\n", dev);
246 printk(KERN_INFO
247 "osst%d:I: it has been reported with some Buslogic cards.\n", dev);
248 }
249 }
250 }
251 if ((sense[0] & 0x70) == 0x70 &&
252 scode == RECOVERED_ERROR) {
253 STp->recover_count++;
254 STp->recover_erreg++;
255 #if DEBUG
256 if (debugging) {
257 if (SRpnt->sr_cmnd[0] == READ_6)
258 stp = "read";
259 else if (SRpnt->sr_cmnd[0] == WRITE_6)
260 stp = "write";
261 else
262 stp = "ioctl";
263 printk(OSST_DEB_MSG "osst%d:D: Recovered %s error (%d).\n", dev, stp,
264 os_scsi_tapes[dev]->recover_count);
265 }
266 #endif
267 if ((sense[2] & 0xe0) == 0)
268 return 0;
269 }
270 return (-EIO);
271 }
272
273
274 /* Wakeup from interrupt */
osst_sleep_done(Scsi_Cmnd * SCpnt)275 static void osst_sleep_done (Scsi_Cmnd * SCpnt)
276 {
277 unsigned int dev = TAPE_NR(SCpnt->request.rq_dev);
278 OS_Scsi_Tape * STp;
279
280 if (os_scsi_tapes && (STp = os_scsi_tapes[dev])) {
281 if ((STp->buffer)->writing &&
282 (SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
283 (SCpnt->sense_buffer[2] & 0x40)) {
284 /* EOM at write-behind, has all been written? */
285 if ((SCpnt->sense_buffer[2] & 0x0f) == VOLUME_OVERFLOW)
286 (STp->buffer)->midlevel_result = SCpnt->result; /* Error */
287 else
288 (STp->buffer)->midlevel_result = INT_MAX; /* OK */
289 }
290 else
291 (STp->buffer)->midlevel_result = SCpnt->result;
292 SCpnt->request.rq_status = RQ_SCSI_DONE;
293 (STp->buffer)->last_SRpnt = SCpnt->sc_request;
294
295 #if DEBUG
296 STp->write_pending = 0;
297 #endif
298 complete(SCpnt->request.waiting);
299 }
300 #if DEBUG
301 else if (debugging)
302 printk(OSST_DEB_MSG "osst?:D: Illegal interrupt device %x\n", dev);
303 #endif
304 }
305
306
307 /* Do the scsi command. Waits until command performed if do_wait is true.
308 Otherwise osst_write_behind_check() is used to check that the command
309 has finished. */
osst_do_scsi(Scsi_Request * SRpnt,OS_Scsi_Tape * STp,unsigned char * cmd,int bytes,int direction,int timeout,int retries,int do_wait)310 static Scsi_Request * osst_do_scsi(Scsi_Request *SRpnt, OS_Scsi_Tape *STp,
311 unsigned char *cmd, int bytes, int direction, int timeout, int retries, int do_wait)
312 {
313 unsigned char *bp;
314 #ifdef OSST_INJECT_ERRORS
315 static int inject = 0;
316 static int repeat = 0;
317 #endif
318 if (SRpnt == NULL) {
319 if ((SRpnt = scsi_allocate_request(STp->device)) == NULL) {
320 printk(KERN_ERR "osst%d:E: Can't get SCSI request.\n", TAPE_NR(STp->devt));
321 if (signal_pending(current))
322 (STp->buffer)->syscall_result = (-EINTR);
323 else
324 (STp->buffer)->syscall_result = (-EBUSY);
325 return NULL;
326 }
327 }
328
329 if (SRpnt->sr_device->scsi_level <= SCSI_2)
330 cmd[1] |= (SRpnt->sr_device->lun << 5) & 0xe0;
331 init_completion(&STp->wait);
332 SRpnt->sr_use_sg = (bytes > (STp->buffer)->sg[0].length) ?
333 (STp->buffer)->use_sg : 0;
334 if (SRpnt->sr_use_sg) {
335 bp = (char *)&(STp->buffer->sg[0]);
336 if (STp->buffer->sg_segs < SRpnt->sr_use_sg)
337 SRpnt->sr_use_sg = STp->buffer->sg_segs;
338 }
339 else
340 bp = (STp->buffer)->b_data;
341 SRpnt->sr_data_direction = direction;
342 SRpnt->sr_cmd_len = 0;
343 SRpnt->sr_request.waiting = &(STp->wait);
344 SRpnt->sr_request.rq_status = RQ_SCSI_BUSY;
345 SRpnt->sr_request.rq_dev = STp->devt;
346
347 scsi_do_req(SRpnt, (void *)cmd, bp, bytes, osst_sleep_done, timeout, retries);
348
349 if (do_wait) {
350 wait_for_completion(SRpnt->sr_request.waiting);
351 SRpnt->sr_request.waiting = NULL;
352 STp->buffer->syscall_result = osst_chk_result(STp, SRpnt);
353 #ifdef OSST_INJECT_ERRORS
354 if (STp->buffer->syscall_result == 0 &&
355 cmd[0] == READ_6 &&
356 cmd[4] &&
357 ( (++ inject % 83) == 29 ||
358 (STp->first_frame_position == 240
359 /* or STp->read_error_frame to fail again on the block calculated above */ &&
360 ++repeat < 3))) {
361 printk(OSST_DEB_MSG "osst%d:D: Injecting read error\n", TAPE_NR(STp->devt));
362 STp->buffer->last_result_fatal = 1;
363 }
364 #endif
365 }
366 return SRpnt;
367 }
368
369
370 /* Handle the write-behind checking (downs the semaphore) */
osst_write_behind_check(OS_Scsi_Tape * STp)371 static void osst_write_behind_check(OS_Scsi_Tape *STp)
372 {
373 OSST_buffer * STbuffer;
374
375 STbuffer = STp->buffer;
376
377 #if DEBUG
378 if (STp->write_pending)
379 STp->nbr_waits++;
380 else
381 STp->nbr_finished++;
382 #endif
383 wait_for_completion(&(STp->wait));
384 (STp->buffer)->last_SRpnt->sr_request.waiting = NULL;
385
386 STp->buffer->syscall_result = osst_chk_result(STp, STp->buffer->last_SRpnt);
387
388 if ((STp->buffer)->syscall_result)
389 (STp->buffer)->syscall_result =
390 osst_write_error_recovery(STp, &((STp->buffer)->last_SRpnt), 1);
391 else
392 STp->first_frame_position++;
393
394 scsi_release_request((STp->buffer)->last_SRpnt);
395
396 if (STbuffer->writing < STbuffer->buffer_bytes)
397 printk(KERN_WARNING "osst:A: write_behind_check: something left in buffer!\n");
398
399 STbuffer->buffer_bytes -= STbuffer->writing;
400 STbuffer->writing = 0;
401
402 return;
403 }
404
405
406
407 /* Onstream specific Routines */
408 /*
409 * Initialize the OnStream AUX
410 */
osst_init_aux(OS_Scsi_Tape * STp,int frame_type,int frame_seq_number,int logical_blk_num,int blk_sz,int blk_cnt)411 static void osst_init_aux(OS_Scsi_Tape * STp, int frame_type, int frame_seq_number,
412 int logical_blk_num, int blk_sz, int blk_cnt)
413 {
414 os_aux_t *aux = STp->buffer->aux;
415 os_partition_t *par = &aux->partition;
416 os_dat_t *dat = &aux->dat;
417
418 if (STp->raw) return;
419
420 memset(aux, 0, sizeof(*aux));
421 aux->format_id = htonl(0);
422 memcpy(aux->application_sig, "LIN4", 4);
423 aux->hdwr = htonl(0);
424 aux->frame_type = frame_type;
425
426 switch (frame_type) {
427 case OS_FRAME_TYPE_HEADER:
428 aux->update_frame_cntr = htonl(STp->update_frame_cntr);
429 par->partition_num = OS_CONFIG_PARTITION;
430 par->par_desc_ver = OS_PARTITION_VERSION;
431 par->wrt_pass_cntr = htons(0xffff);
432 /* 0-4 = reserved, 5-9 = header, 2990-2994 = header, 2995-2999 = reserved */
433 par->first_frame_ppos = htonl(0);
434 par->last_frame_ppos = htonl(0xbb7);
435 aux->frame_seq_num = htonl(0);
436 aux->logical_blk_num_high = htonl(0);
437 aux->logical_blk_num = htonl(0);
438 aux->next_mark_ppos = htonl(STp->first_mark_ppos);
439 break;
440 case OS_FRAME_TYPE_DATA:
441 case OS_FRAME_TYPE_MARKER:
442 dat->dat_sz = 8;
443 dat->reserved1 = 0;
444 dat->entry_cnt = 1;
445 dat->reserved3 = 0;
446 dat->dat_list[0].blk_sz = htonl(blk_sz);
447 dat->dat_list[0].blk_cnt = htons(blk_cnt);
448 dat->dat_list[0].flags = frame_type==OS_FRAME_TYPE_MARKER?
449 OS_DAT_FLAGS_MARK:OS_DAT_FLAGS_DATA;
450 dat->dat_list[0].reserved = 0;
451 case OS_FRAME_TYPE_EOD:
452 aux->update_frame_cntr = htonl(0);
453 par->partition_num = OS_DATA_PARTITION;
454 par->par_desc_ver = OS_PARTITION_VERSION;
455 par->wrt_pass_cntr = htons(STp->wrt_pass_cntr);
456 par->first_frame_ppos = htonl(STp->first_data_ppos);
457 par->last_frame_ppos = htonl(STp->capacity);
458 aux->frame_seq_num = htonl(frame_seq_number);
459 aux->logical_blk_num_high = htonl(0);
460 aux->logical_blk_num = htonl(logical_blk_num);
461 break;
462 default: ; /* probably FILL */
463 }
464 aux->filemark_cnt = ntohl(STp->filemark_cnt);
465 aux->phys_fm = ntohl(0xffffffff);
466 aux->last_mark_ppos = ntohl(STp->last_mark_ppos);
467 aux->last_mark_lbn = ntohl(STp->last_mark_lbn);
468 }
469
470 /*
471 * Verify that we have the correct tape frame
472 */
osst_verify_frame(OS_Scsi_Tape * STp,int frame_seq_number,int quiet)473 static int osst_verify_frame(OS_Scsi_Tape * STp, int frame_seq_number, int quiet)
474 {
475 os_aux_t * aux = STp->buffer->aux;
476 os_partition_t * par = &(aux->partition);
477 ST_partstat * STps = &(STp->ps[STp->partition]);
478 int dev = TAPE_NR(STp->devt);
479 int blk_cnt, blk_sz, i;
480
481 if (STp->raw) {
482 if (STp->buffer->syscall_result) {
483 for (i=0; i < STp->buffer->sg_segs; i++)
484 memset(STp->buffer->sg[i].address, 0, STp->buffer->sg[i].length);
485 strcpy(STp->buffer->b_data, "READ ERROR ON FRAME");
486 } else
487 STp->buffer->buffer_bytes = OS_FRAME_SIZE;
488 return 1;
489 }
490 if (STp->buffer->syscall_result) {
491 #if DEBUG
492 printk(OSST_DEB_MSG "osst%d:D: Skipping frame, read error\n", dev);
493 #endif
494 return 0;
495 }
496 if (ntohl(aux->format_id) != 0) {
497 #if DEBUG
498 printk(OSST_DEB_MSG "osst%d:D: Skipping frame, format_id %u\n", dev, ntohl(aux->format_id));
499 #endif
500 goto err_out;
501 }
502 if (memcmp(aux->application_sig, STp->application_sig, 4) != 0 &&
503 (memcmp(aux->application_sig, "LIN3", 4) != 0 || STp->linux_media_version != 4)) {
504 #if DEBUG
505 printk(OSST_DEB_MSG "osst%d:D: Skipping frame, incorrect application signature\n", dev);
506 #endif
507 goto err_out;
508 }
509 if (par->partition_num != OS_DATA_PARTITION) {
510 if (!STp->linux_media || STp->linux_media_version != 2) {
511 #if DEBUG
512 printk(OSST_DEB_MSG "osst%d:D: Skipping frame, partition num %d\n",
513 dev, par->partition_num);
514 #endif
515 goto err_out;
516 }
517 }
518 if (par->par_desc_ver != OS_PARTITION_VERSION) {
519 #if DEBUG
520 printk(OSST_DEB_MSG "osst%d:D: Skipping frame, partition version %d\n", dev, par->par_desc_ver);
521 #endif
522 goto err_out;
523 }
524 if (ntohs(par->wrt_pass_cntr) != STp->wrt_pass_cntr) {
525 #if DEBUG
526 printk(OSST_DEB_MSG "osst%d:D: Skipping frame, wrt_pass_cntr %d (expected %d)\n",
527 dev, ntohs(par->wrt_pass_cntr), STp->wrt_pass_cntr);
528 #endif
529 goto err_out;
530 }
531 if (aux->frame_type != OS_FRAME_TYPE_DATA &&
532 aux->frame_type != OS_FRAME_TYPE_EOD &&
533 aux->frame_type != OS_FRAME_TYPE_MARKER) {
534 if (!quiet)
535 #if DEBUG
536 printk(OSST_DEB_MSG "osst%d:D: Skipping frame, frame type %x\n", dev, aux->frame_type);
537 #endif
538 goto err_out;
539 }
540 if (aux->frame_type == OS_FRAME_TYPE_EOD &&
541 STp->first_frame_position < STp->eod_frame_ppos) {
542 printk(KERN_INFO "osst%d:I: Skipping premature EOD frame %d\n", dev,
543 STp->first_frame_position);
544 goto err_out;
545 }
546 if (frame_seq_number != -1 && ntohl(aux->frame_seq_num) != frame_seq_number) {
547 if (!quiet)
548 #if DEBUG
549 printk(OSST_DEB_MSG "osst%d:D: Skipping frame, sequence number %u (expected %d)\n",
550 dev, ntohl(aux->frame_seq_num), frame_seq_number);
551 #endif
552 goto err_out;
553 }
554 if (aux->frame_type == OS_FRAME_TYPE_MARKER) {
555 STps->eof = ST_FM_HIT;
556
557 i = ntohl(aux->filemark_cnt);
558 if (STp->header_cache != NULL && i < OS_FM_TAB_MAX && (i > STp->filemark_cnt ||
559 STp->first_frame_position - 1 != ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[i]))) {
560 #if DEBUG
561 printk(OSST_DEB_MSG "osst%d:D: %s filemark %d at frame pos %d\n", dev,
562 STp->header_cache->dat_fm_tab.fm_tab_ent[i] == 0?"Learned":"Corrected",
563 i, STp->first_frame_position - 1);
564 #endif
565 STp->header_cache->dat_fm_tab.fm_tab_ent[i] = htonl(STp->first_frame_position - 1);
566 if (i >= STp->filemark_cnt)
567 STp->filemark_cnt = i+1;
568 }
569 }
570 if (aux->frame_type == OS_FRAME_TYPE_EOD) {
571 STps->eof = ST_EOD_1;
572 STp->frame_in_buffer = 1;
573 }
574 if (aux->frame_type == OS_FRAME_TYPE_DATA) {
575 blk_cnt = ntohs(aux->dat.dat_list[0].blk_cnt);
576 blk_sz = ntohl(aux->dat.dat_list[0].blk_sz);
577 STp->buffer->buffer_bytes = blk_cnt * blk_sz;
578 STp->buffer->read_pointer = 0;
579 STp->frame_in_buffer = 1;
580
581 /* See what block size was used to write file */
582 if (STp->block_size != blk_sz && blk_sz > 0) {
583 printk(KERN_INFO
584 "osst%d:I: File was written with block size %d%c, currently %d%c, adjusted to match.\n",
585 dev, blk_sz<1024?blk_sz:blk_sz/1024,blk_sz<1024?'b':'k',
586 STp->block_size<1024?STp->block_size:STp->block_size/1024,
587 STp->block_size<1024?'b':'k');
588 STp->block_size = blk_sz;
589 STp->buffer->buffer_blocks = OS_DATA_SIZE / blk_sz;
590 }
591 STps->eof = ST_NOEOF;
592 }
593 STp->frame_seq_number = ntohl(aux->frame_seq_num);
594 STp->logical_blk_num = ntohl(aux->logical_blk_num);
595 return 1;
596
597 err_out:
598 if (STp->read_error_frame == 0)
599 STp->read_error_frame = STp->first_frame_position - 1;
600 return 0;
601 }
602
603 /*
604 * Wait for the unit to become Ready
605 */
osst_wait_ready(OS_Scsi_Tape * STp,Scsi_Request ** aSRpnt,unsigned timeout,int initial_delay)606 static int osst_wait_ready(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned timeout, int initial_delay)
607 {
608 unsigned char cmd[MAX_COMMAND_SIZE];
609 Scsi_Request * SRpnt;
610 long startwait = jiffies;
611 #if DEBUG
612 int dbg = debugging;
613 int dev = TAPE_NR(STp->devt);
614
615 printk(OSST_DEB_MSG "osst%d:D: Reached onstream wait ready\n", dev);
616 #endif
617
618 if (initial_delay > 0) {
619 set_current_state(TASK_INTERRUPTIBLE);
620 schedule_timeout(initial_delay);
621 }
622
623 memset(cmd, 0, MAX_COMMAND_SIZE);
624 cmd[0] = TEST_UNIT_READY;
625
626 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READY_RETRIES, TRUE);
627 *aSRpnt = SRpnt;
628 if (!SRpnt) return (-EBUSY);
629
630 while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) &&
631 (( SRpnt->sr_sense_buffer[2] == 2 && SRpnt->sr_sense_buffer[12] == 4 &&
632 (SRpnt->sr_sense_buffer[13] == 1 || SRpnt->sr_sense_buffer[13] == 8) ) ||
633 ( SRpnt->sr_sense_buffer[2] == 6 && SRpnt->sr_sense_buffer[12] == 0x28 &&
634 SRpnt->sr_sense_buffer[13] == 0 ) )) {
635 #if DEBUG
636 if (debugging) {
637 printk(OSST_DEB_MSG "osst%d:D: Sleeping in onstream wait ready\n", dev);
638 printk(OSST_DEB_MSG "osst%d:D: Turning off debugging for a while\n", dev);
639 debugging = 0;
640 }
641 #endif
642 set_current_state(TASK_INTERRUPTIBLE);
643 schedule_timeout(HZ / 10);
644
645 memset(cmd, 0, MAX_COMMAND_SIZE);
646 cmd[0] = TEST_UNIT_READY;
647
648 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READY_RETRIES, TRUE);
649 }
650 *aSRpnt = SRpnt;
651 #if DEBUG
652 debugging = dbg;
653 #endif
654 if ( STp->buffer->syscall_result &&
655 osst_write_error_recovery(STp, aSRpnt, 0) ) {
656 #if DEBUG
657 printk(OSST_DEB_MSG "osst%d:D: Abnormal exit from onstream wait ready\n", dev);
658 printk(OSST_DEB_MSG "osst%d:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", dev,
659 STp->buffer->syscall_result, SRpnt->sr_sense_buffer[0], SRpnt->sr_sense_buffer[2],
660 SRpnt->sr_sense_buffer[12], SRpnt->sr_sense_buffer[13]);
661 #endif
662 return (-EIO);
663 }
664 #if DEBUG
665 printk(OSST_DEB_MSG "osst%d:D: Normal exit from onstream wait ready\n", dev);
666 #endif
667 return 0;
668 }
669
670 /*
671 * Wait for a tape to be inserted in the unit
672 */
osst_wait_for_medium(OS_Scsi_Tape * STp,Scsi_Request ** aSRpnt,unsigned timeout)673 static int osst_wait_for_medium(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned timeout)
674 {
675 unsigned char cmd[MAX_COMMAND_SIZE];
676 Scsi_Request * SRpnt;
677 long startwait = jiffies;
678 #if DEBUG
679 int dbg = debugging;
680 int dev = TAPE_NR(STp->devt);
681
682 printk(OSST_DEB_MSG "osst%d:D: Reached onstream wait for medium\n", dev);
683 #endif
684
685 memset(cmd, 0, MAX_COMMAND_SIZE);
686 cmd[0] = TEST_UNIT_READY;
687
688 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READY_RETRIES, TRUE);
689 *aSRpnt = SRpnt;
690 if (!SRpnt) return (-EBUSY);
691
692 while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) &&
693 SRpnt->sr_sense_buffer[2] == 2 && SRpnt->sr_sense_buffer[12] == 0x3a &&
694 SRpnt->sr_sense_buffer[13] == 0 ) {
695 #if DEBUG
696 if (debugging) {
697 printk(OSST_DEB_MSG "osst%d:D: Sleeping in onstream wait medium\n", dev);
698 printk(OSST_DEB_MSG "osst%d:D: Turning off debugging for a while\n", dev);
699 debugging = 0;
700 }
701 #endif
702 set_current_state(TASK_INTERRUPTIBLE);
703 schedule_timeout(HZ / 10);
704
705 memset(cmd, 0, MAX_COMMAND_SIZE);
706 cmd[0] = TEST_UNIT_READY;
707
708 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READY_RETRIES, TRUE);
709 }
710 *aSRpnt = SRpnt;
711 #if DEBUG
712 debugging = dbg;
713 #endif
714 if ( STp->buffer->syscall_result && SRpnt->sr_sense_buffer[2] != 2 &&
715 SRpnt->sr_sense_buffer[12] != 4 && SRpnt->sr_sense_buffer[13] == 1) {
716 #if DEBUG
717 printk(OSST_DEB_MSG "osst%d:D: Abnormal exit from onstream wait medium\n", dev);
718 printk(OSST_DEB_MSG "osst%d:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", dev,
719 STp->buffer->syscall_result, SRpnt->sr_sense_buffer[0], SRpnt->sr_sense_buffer[2],
720 SRpnt->sr_sense_buffer[12], SRpnt->sr_sense_buffer[13]);
721 #endif
722 return 0;
723 }
724 #if DEBUG
725 printk(OSST_DEB_MSG "osst%d:D: Normal exit from onstream wait medium\n", dev);
726 #endif
727 return 1;
728 }
729
osst_position_tape_and_confirm(OS_Scsi_Tape * STp,Scsi_Request ** aSRpnt,int frame)730 static int osst_position_tape_and_confirm(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int frame)
731 {
732 int retval;
733
734 osst_wait_ready(STp, aSRpnt, 15 * 60, 0); /* TODO - can this catch a write error? */
735 retval = osst_set_frame_position(STp, aSRpnt, frame, 0);
736 if (retval) return (retval);
737 osst_wait_ready(STp, aSRpnt, 15 * 60, OSST_WAIT_POSITION_COMPLETE);
738 return (osst_get_frame_position(STp, aSRpnt));
739 }
740
741 /*
742 * Wait for write(s) to complete
743 */
osst_flush_drive_buffer(OS_Scsi_Tape * STp,Scsi_Request ** aSRpnt)744 static int osst_flush_drive_buffer(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
745 {
746 unsigned char cmd[MAX_COMMAND_SIZE];
747 Scsi_Request * SRpnt;
748
749 int result = 0;
750 int delay = OSST_WAIT_WRITE_COMPLETE;
751 #if DEBUG
752 int dev = TAPE_NR(STp->devt);
753
754 printk(OSST_DEB_MSG "osst%d:D: Reached onstream flush drive buffer (write filemark)\n", dev);
755 #endif
756
757 memset(cmd, 0, MAX_COMMAND_SIZE);
758 cmd[0] = WRITE_FILEMARKS;
759 cmd[1] = 1;
760
761 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_WRITE_RETRIES, TRUE);
762 *aSRpnt = SRpnt;
763 if (!SRpnt) return (-EBUSY);
764 if (STp->buffer->syscall_result) {
765 if ((SRpnt->sr_sense_buffer[2] & 0x0f) == 2 && SRpnt->sr_sense_buffer[12] == 4) {
766 if (SRpnt->sr_sense_buffer[13] == 8) {
767 delay = OSST_WAIT_LONG_WRITE_COMPLETE;
768 }
769 } else
770 result = osst_write_error_recovery(STp, aSRpnt, 0);
771 }
772 result |= osst_wait_ready(STp, aSRpnt, 5 * 60, delay);
773 STp->ps[STp->partition].rw = OS_WRITING_COMPLETE;
774
775 return (result);
776 }
777
778 #define OSST_POLL_PER_SEC 10
osst_wait_frame(OS_Scsi_Tape * STp,Scsi_Request ** aSRpnt,int curr,int minlast,int to)779 static int osst_wait_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int curr, int minlast, int to)
780 {
781 long startwait = jiffies;
782 int dev = TAPE_NR(STp->devt);
783 #if DEBUG
784 char notyetprinted = 1;
785 #endif
786 if (minlast >= 0 && STp->ps[STp->partition].rw != ST_READING)
787 printk(KERN_ERR "osst%i:A: Waiting for frame without having initialized read!\n", dev);
788
789 while (time_before (jiffies, startwait + to*HZ))
790 {
791 int result;
792 result = osst_get_frame_position (STp, aSRpnt);
793 if (result == -EIO)
794 if ((result = osst_write_error_recovery(STp, aSRpnt, 0)) == 0)
795 return 0; /* successful recovery leaves drive ready for frame */
796 if (result < 0) break;
797 if (STp->first_frame_position == curr &&
798 ((minlast < 0 &&
799 (signed)STp->last_frame_position > (signed)curr + minlast) ||
800 (minlast >= 0 && STp->cur_frames > minlast)
801 ) && result >= 0)
802 {
803 #if DEBUG
804 if (debugging || jiffies - startwait >= 2*HZ/OSST_POLL_PER_SEC)
805 printk (OSST_DEB_MSG
806 "osst%d:D: Succ wait f fr %i (>%i): %i-%i %i (%i): %3li.%li s\n",
807 dev, curr, curr+minlast, STp->first_frame_position,
808 STp->last_frame_position, STp->cur_frames,
809 result, (jiffies-startwait)/HZ,
810 (((jiffies-startwait)%HZ)*10)/HZ);
811 #endif
812 return 0;
813 }
814 #if DEBUG
815 if (jiffies - startwait >= 2*HZ/OSST_POLL_PER_SEC && notyetprinted)
816 {
817 printk (OSST_DEB_MSG "osst%d:D: Wait for frame %i (>%i): %i-%i %i (%i)\n",
818 dev, curr, curr+minlast, STp->first_frame_position,
819 STp->last_frame_position, STp->cur_frames, result);
820 notyetprinted--;
821 }
822 #endif
823 set_current_state(TASK_INTERRUPTIBLE);
824 schedule_timeout (HZ / OSST_POLL_PER_SEC);
825 }
826 #if DEBUG
827 printk (OSST_DEB_MSG "osst%d:D: Fail wait f fr %i (>%i): %i-%i %i: %3li.%li s\n",
828 dev, curr, curr+minlast, STp->first_frame_position,
829 STp->last_frame_position, STp->cur_frames,
830 (jiffies-startwait)/HZ, (((jiffies-startwait)%HZ)*10)/HZ);
831 #endif
832 return -EBUSY;
833 }
834
835 /*
836 * Read the next OnStream tape frame at the current location
837 */
osst_read_frame(OS_Scsi_Tape * STp,Scsi_Request ** aSRpnt,int timeout)838 static int osst_read_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int timeout)
839 {
840 unsigned char cmd[MAX_COMMAND_SIZE];
841 Scsi_Request * SRpnt;
842 int retval = 0;
843 #if DEBUG
844 os_aux_t * aux = STp->buffer->aux;
845 int dev = TAPE_NR(STp->devt);
846 #endif
847
848 /* TODO: Error handling */
849 if (STp->poll)
850 retval = osst_wait_frame (STp, aSRpnt, STp->first_frame_position, 0, timeout);
851
852 memset(cmd, 0, MAX_COMMAND_SIZE);
853 cmd[0] = READ_6;
854 cmd[1] = 1;
855 cmd[4] = 1;
856
857 #if DEBUG
858 if (debugging)
859 printk(OSST_DEB_MSG "osst%d:D: Reading frame from OnStream tape\n", dev);
860 #endif
861 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_READ,
862 STp->timeout, MAX_READ_RETRIES, TRUE);
863 *aSRpnt = SRpnt;
864 if (!SRpnt)
865 return (-EBUSY);
866
867 if ((STp->buffer)->syscall_result) {
868 retval = 1;
869 if (STp->read_error_frame == 0) {
870 STp->read_error_frame = STp->first_frame_position;
871 #if DEBUG
872 printk(OSST_DEB_MSG "osst%d:D: Recording read error at %d\n", dev, STp->read_error_frame);
873 #endif
874 }
875 #if DEBUG
876 if (debugging)
877 printk(OSST_DEB_MSG "osst%d:D: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",
878 dev,
879 SRpnt->sr_sense_buffer[0], SRpnt->sr_sense_buffer[1],
880 SRpnt->sr_sense_buffer[2], SRpnt->sr_sense_buffer[3],
881 SRpnt->sr_sense_buffer[4], SRpnt->sr_sense_buffer[5],
882 SRpnt->sr_sense_buffer[6], SRpnt->sr_sense_buffer[7]);
883 #endif
884 }
885 else
886 STp->first_frame_position++;
887 #if DEBUG
888 if (debugging) {
889 printk(OSST_DEB_MSG
890 "osst%d:D: AUX: %c%c%c%c UpdFrCt#%d Wpass#%d %s FrSeq#%d LogBlk#%d Qty=%d Sz=%d\n", dev,
891 aux->application_sig[0], aux->application_sig[1],
892 aux->application_sig[2], aux->application_sig[3],
893 ntohl(aux->update_frame_cntr), ntohs(aux->partition.wrt_pass_cntr),
894 aux->frame_type==1?"EOD":aux->frame_type==2?"MARK":
895 aux->frame_type==8?"HEADR":aux->frame_type==0x80?"DATA":"FILL",
896 ntohl(aux->frame_seq_num), ntohl(aux->logical_blk_num),
897 ntohs(aux->dat.dat_list[0].blk_cnt), ntohl(aux->dat.dat_list[0].blk_sz) );
898 if (aux->frame_type==2)
899 printk(OSST_DEB_MSG "osst%d:D: mark_cnt=%d, last_mark_ppos=%d, last_mark_lbn=%d\n", dev,
900 ntohl(aux->filemark_cnt), ntohl(aux->last_mark_ppos), ntohl(aux->last_mark_lbn));
901 printk(OSST_DEB_MSG "osst%d:D: Exit read frame from OnStream tape with code %d\n", dev, retval);
902 }
903 #endif
904 return (retval);
905 }
906
osst_initiate_read(OS_Scsi_Tape * STp,Scsi_Request ** aSRpnt)907 static int osst_initiate_read(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
908 {
909 ST_partstat * STps = &(STp->ps[STp->partition]);
910 Scsi_Request * SRpnt ;
911 unsigned char cmd[MAX_COMMAND_SIZE];
912 int retval = 0;
913 #if DEBUG
914 int dev = TAPE_NR(STp->devt);
915 #endif
916
917 if (STps->rw != ST_READING) { /* Initialize read operation */
918 if (STps->rw == ST_WRITING || STp->dirty) {
919 STp->write_type = OS_WRITE_DATA;
920 osst_flush_write_buffer(STp, aSRpnt);
921 osst_flush_drive_buffer(STp, aSRpnt);
922 }
923 STps->rw = ST_READING;
924 STp->frame_in_buffer = 0;
925
926 /*
927 * Issue a read 0 command to get the OnStream drive
928 * read frames into its buffer.
929 */
930 memset(cmd, 0, MAX_COMMAND_SIZE);
931 cmd[0] = READ_6;
932 cmd[1] = 1;
933
934 #if DEBUG
935 printk(OSST_DEB_MSG "osst%d:D: Start Read Ahead on OnStream tape\n", dev);
936 #endif
937 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READ_RETRIES, TRUE);
938 *aSRpnt = SRpnt;
939 retval = STp->buffer->syscall_result;
940 }
941
942 return retval;
943 }
944
osst_get_logical_frame(OS_Scsi_Tape * STp,Scsi_Request ** aSRpnt,int frame_seq_number,int quiet)945 static int osst_get_logical_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int frame_seq_number, int quiet)
946 {
947 ST_partstat * STps = &(STp->ps[STp->partition]);
948 int dev = TAPE_NR(STp->devt);
949 int cnt = 0,
950 bad = 0,
951 past = 0,
952 x,
953 position;
954
955 /*
956 * If we want just any frame (-1) and there is a frame in the buffer, return it
957 */
958 if (frame_seq_number == -1 && STp->frame_in_buffer) {
959 #if DEBUG
960 printk(OSST_DEB_MSG "osst%d:D: Frame %d still in buffer\n", dev, STp->frame_seq_number);
961 #endif
962 return (STps->eof);
963 }
964 /*
965 * Search and wait for the next logical tape frame
966 */
967 while (1) {
968 if (cnt++ > 400) {
969 printk(KERN_ERR "osst%d:E: Couldn't find logical frame %d, aborting\n",
970 dev, frame_seq_number);
971 if (STp->read_error_frame) {
972 osst_set_frame_position(STp, aSRpnt, STp->read_error_frame, 0);
973 #if DEBUG
974 printk(OSST_DEB_MSG "osst%d:D: Repositioning tape to bad frame %d\n",
975 dev, STp->read_error_frame);
976 #endif
977 STp->read_error_frame = 0;
978 }
979 return (-EIO);
980 }
981 #if DEBUG
982 if (debugging)
983 printk(OSST_DEB_MSG "osst%d:D: Looking for frame %d, attempt %d\n",
984 dev, frame_seq_number, cnt);
985 #endif
986 if ( osst_initiate_read(STp, aSRpnt)
987 || ( (!STp->frame_in_buffer) && osst_read_frame(STp, aSRpnt, 30) ) ) {
988 if (STp->raw)
989 return (-EIO);
990 position = osst_get_frame_position(STp, aSRpnt);
991 if (position >= 0xbae && position < 0xbb8)
992 position = 0xbb8;
993 else if (position > STp->eod_frame_ppos || ++bad == 10) {
994 position = STp->read_error_frame - 1;
995 }
996 else {
997 position += 39;
998 cnt += 20;
999 }
1000 #if DEBUG
1001 printk(OSST_DEB_MSG "osst%d:D: Bad frame detected, positioning tape to block %d\n",
1002 dev, position);
1003 #endif
1004 osst_set_frame_position(STp, aSRpnt, position, 0);
1005 continue;
1006 }
1007 if (osst_verify_frame(STp, frame_seq_number, quiet))
1008 break;
1009 if (osst_verify_frame(STp, -1, quiet)) {
1010 x = ntohl(STp->buffer->aux->frame_seq_num);
1011 if (STp->fast_open) {
1012 printk(KERN_WARNING
1013 "osst%d:W: Found logical frame %d instead of %d after fast open\n",
1014 dev, x, frame_seq_number);
1015 STp->header_ok = 0;
1016 STp->read_error_frame = 0;
1017 return (-EIO);
1018 }
1019 if (x > frame_seq_number) {
1020 if (++past > 3) {
1021 /* positioning backwards did not bring us to the desired frame */
1022 position = STp->read_error_frame - 1;
1023 }
1024 else {
1025 position = osst_get_frame_position(STp, aSRpnt)
1026 + frame_seq_number - x - 1;
1027
1028 if (STp->first_frame_position >= 3000 && position < 3000)
1029 position -= 10;
1030 }
1031 #if DEBUG
1032 printk(OSST_DEB_MSG
1033 "osst%d:D: Found logical frame %d while looking for %d: back up %d\n",
1034 dev, x, frame_seq_number,
1035 STp->first_frame_position - position);
1036 #endif
1037 osst_set_frame_position(STp, aSRpnt, position, 0);
1038 cnt += 10;
1039 }
1040 else
1041 past = 0;
1042 }
1043 if (osst_get_frame_position(STp, aSRpnt) == 0xbaf) {
1044 #if DEBUG
1045 printk(OSST_DEB_MSG "osst%d:D: Skipping config partition\n", dev);
1046 #endif
1047 osst_set_frame_position(STp, aSRpnt, 0xbb8, 0);
1048 cnt--;
1049 }
1050 STp->frame_in_buffer = 0;
1051 }
1052 if (cnt > 1) {
1053 STp->recover_count++;
1054 STp->recover_erreg++;
1055 printk(KERN_WARNING "osst%d:I: Don't worry, Read error at position %d recovered\n",
1056 dev, STp->read_error_frame);
1057 }
1058 STp->read_count++;
1059
1060 #if DEBUG
1061 if (debugging || STps->eof)
1062 printk(OSST_DEB_MSG
1063 "osst%d:D: Exit get logical frame (%d=>%d) from OnStream tape with code %d\n",
1064 dev, frame_seq_number, STp->frame_seq_number, STps->eof);
1065 #endif
1066 STp->fast_open = FALSE;
1067 STp->read_error_frame = 0;
1068 return (STps->eof);
1069 }
1070
osst_seek_logical_blk(OS_Scsi_Tape * STp,Scsi_Request ** aSRpnt,int logical_blk_num)1071 static int osst_seek_logical_blk(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int logical_blk_num)
1072 {
1073 ST_partstat * STps = &(STp->ps[STp->partition]);
1074 int dev = TAPE_NR(STp->devt);
1075 int retries = 0;
1076 int frame_seq_estimate, ppos_estimate, move;
1077
1078 if (logical_blk_num < 0) logical_blk_num = 0;
1079 #if DEBUG
1080 printk(OSST_DEB_MSG "osst%d:D: Seeking logical block %d (now at %d, size %d%c)\n",
1081 dev, logical_blk_num, STp->logical_blk_num,
1082 STp->block_size<1024?STp->block_size:STp->block_size/1024,
1083 STp->block_size<1024?'b':'k');
1084 #endif
1085 /* Do we know where we are? */
1086 if (STps->drv_block >= 0) {
1087 move = logical_blk_num - STp->logical_blk_num;
1088 if (move < 0) move -= (OS_DATA_SIZE / STp->block_size) - 1;
1089 move /= (OS_DATA_SIZE / STp->block_size);
1090 frame_seq_estimate = STp->frame_seq_number + move;
1091 } else
1092 frame_seq_estimate = logical_blk_num * STp->block_size / OS_DATA_SIZE;
1093
1094 if (frame_seq_estimate < 2980) ppos_estimate = frame_seq_estimate + 10;
1095 else ppos_estimate = frame_seq_estimate + 20;
1096 while (++retries < 10) {
1097 if (ppos_estimate > STp->eod_frame_ppos-2) {
1098 frame_seq_estimate += STp->eod_frame_ppos - 2 - ppos_estimate;
1099 ppos_estimate = STp->eod_frame_ppos - 2;
1100 }
1101 if (frame_seq_estimate < 0) {
1102 frame_seq_estimate = 0;
1103 ppos_estimate = 10;
1104 }
1105 osst_set_frame_position(STp, aSRpnt, ppos_estimate, 0);
1106 if (osst_get_logical_frame(STp, aSRpnt, frame_seq_estimate, 1) >= 0) {
1107 /* we've located the estimated frame, now does it have our block? */
1108 if (logical_blk_num < STp->logical_blk_num ||
1109 logical_blk_num >= STp->logical_blk_num + ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt)) {
1110 if (STps->eof == ST_FM_HIT)
1111 move = logical_blk_num < STp->logical_blk_num? -2 : 1;
1112 else {
1113 move = logical_blk_num - STp->logical_blk_num;
1114 if (move < 0) move -= (OS_DATA_SIZE / STp->block_size) - 1;
1115 move /= (OS_DATA_SIZE / STp->block_size);
1116 }
1117 if (!move) move = logical_blk_num > STp->logical_blk_num ? 1 : -1;
1118 #if DEBUG
1119 printk(OSST_DEB_MSG
1120 "osst%d:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d) move %d\n",
1121 dev, retries, ppos_estimate, STp->frame_seq_number, frame_seq_estimate,
1122 STp->logical_blk_num, logical_blk_num, move);
1123 #endif
1124 frame_seq_estimate += move;
1125 ppos_estimate += move;
1126 continue;
1127 } else {
1128 STp->buffer->read_pointer = (logical_blk_num - STp->logical_blk_num) * STp->block_size;
1129 STp->buffer->buffer_bytes -= STp->buffer->read_pointer;
1130 STp->logical_blk_num = logical_blk_num;
1131 #if DEBUG
1132 printk(OSST_DEB_MSG
1133 "osst%d:D: Seek success at ppos %d fsq %d in_buf %d, bytes %d, ptr %d*%d\n",
1134 dev, ppos_estimate, STp->frame_seq_number, STp->frame_in_buffer,
1135 STp->buffer->buffer_bytes, STp->buffer->read_pointer / STp->block_size,
1136 STp->block_size);
1137 #endif
1138 STps->drv_file = ntohl(STp->buffer->aux->filemark_cnt);
1139 if (STps->eof == ST_FM_HIT) {
1140 STps->drv_file++;
1141 STps->drv_block = 0;
1142 } else {
1143 STps->drv_block = ntohl(STp->buffer->aux->last_mark_lbn)?
1144 STp->logical_blk_num -
1145 (STps->drv_file ? ntohl(STp->buffer->aux->last_mark_lbn) + 1 : 0):
1146 -1;
1147 }
1148 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_NOEOF;
1149 return 0;
1150 }
1151 }
1152 if (osst_get_logical_frame(STp, aSRpnt, -1, 1) < 0)
1153 goto error;
1154 /* we are not yet at the estimated frame, adjust our estimate of its physical position */
1155 #if DEBUG
1156 printk(OSST_DEB_MSG "osst%d:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d)\n",
1157 dev, retries, ppos_estimate, STp->frame_seq_number, frame_seq_estimate,
1158 STp->logical_blk_num, logical_blk_num);
1159 #endif
1160 if (frame_seq_estimate != STp->frame_seq_number)
1161 ppos_estimate += frame_seq_estimate - STp->frame_seq_number;
1162 else
1163 break;
1164 }
1165 error:
1166 printk(KERN_ERR "osst%d:E: Couldn't seek to logical block %d (at %d), %d retries\n",
1167 dev, logical_blk_num, STp->logical_blk_num, retries);
1168 return (-EIO);
1169 }
1170
1171 /* The values below are based on the OnStream frame payload size of 32K == 2**15,
1172 * that is, OSST_FRAME_SHIFT + OSST_SECTOR_SHIFT must be 15. With a minimum block
1173 * size of 512 bytes, we need to be able to resolve 32K/512 == 64 == 2**6 positions
1174 * inside each frame. Finaly, OSST_SECTOR_MASK == 2**OSST_FRAME_SHIFT - 1.
1175 */
1176 #define OSST_FRAME_SHIFT 6
1177 #define OSST_SECTOR_SHIFT 9
1178 #define OSST_SECTOR_MASK 0x03F
1179
osst_get_sector(OS_Scsi_Tape * STp,Scsi_Request ** aSRpnt)1180 static int osst_get_sector(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
1181 {
1182 int sector;
1183 #if DEBUG
1184 int dev = TAPE_NR(STp->devt);
1185
1186 printk(OSST_DEB_MSG
1187 "osst%d:D: Positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, %cptr %d, eof %d\n",
1188 dev, STp->first_frame_position, STp->frame_seq_number, STp->logical_blk_num,
1189 STp->ps[STp->partition].drv_file, STp->ps[STp->partition].drv_block,
1190 STp->ps[STp->partition].rw == ST_WRITING?'w':'r',
1191 STp->ps[STp->partition].rw == ST_WRITING?STp->buffer->buffer_bytes:
1192 STp->buffer->read_pointer, STp->ps[STp->partition].eof);
1193 #endif
1194 /* do we know where we are inside a file? */
1195 if (STp->ps[STp->partition].drv_block >= 0) {
1196 sector = (STp->frame_in_buffer ? STp->first_frame_position-1 :
1197 STp->first_frame_position) << OSST_FRAME_SHIFT;
1198 if (STp->ps[STp->partition].rw == ST_WRITING)
1199 sector |= (STp->buffer->buffer_bytes >> OSST_SECTOR_SHIFT) & OSST_SECTOR_MASK;
1200 else
1201 sector |= (STp->buffer->read_pointer >> OSST_SECTOR_SHIFT) & OSST_SECTOR_MASK;
1202 } else {
1203 sector = osst_get_frame_position(STp, aSRpnt);
1204 if (sector > 0)
1205 sector <<= OSST_FRAME_SHIFT;
1206 }
1207 return sector;
1208 }
1209
osst_seek_sector(OS_Scsi_Tape * STp,Scsi_Request ** aSRpnt,int sector)1210 static int osst_seek_sector(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int sector)
1211 {
1212 ST_partstat * STps = &(STp->ps[STp->partition]);
1213 int frame = sector >> OSST_FRAME_SHIFT,
1214 offset = (sector & OSST_SECTOR_MASK) << OSST_SECTOR_SHIFT,
1215 r;
1216 #if DEBUG
1217 int dev = TAPE_NR(STp->devt);
1218
1219 printk(OSST_DEB_MSG "osst%d:D: Seeking sector %d in frame %d at offset %d\n",
1220 dev, sector, frame, offset);
1221 #endif
1222 if (frame < 0 || frame >= STp->capacity) return (-ENXIO);
1223
1224 if (frame <= STp->first_data_ppos) {
1225 STp->frame_seq_number = STp->logical_blk_num = STps->drv_file = STps->drv_block = 0;
1226 return (osst_set_frame_position(STp, aSRpnt, frame, 0));
1227 }
1228 r = osst_set_frame_position(STp, aSRpnt, offset?frame:frame-1, 0);
1229 if (r < 0) return r;
1230
1231 r = osst_get_logical_frame(STp, aSRpnt, -1, 1);
1232 if (r < 0) return r;
1233
1234 if (osst_get_frame_position(STp, aSRpnt) != (offset?frame+1:frame)) return (-EIO);
1235
1236 if (offset) {
1237 STp->logical_blk_num += offset / STp->block_size;
1238 STp->buffer->read_pointer = offset;
1239 STp->buffer->buffer_bytes -= offset;
1240 } else {
1241 STp->frame_seq_number++;
1242 STp->frame_in_buffer = 0;
1243 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1244 STp->buffer->buffer_bytes = STp->buffer->read_pointer = 0;
1245 }
1246 STps->drv_file = ntohl(STp->buffer->aux->filemark_cnt);
1247 if (STps->eof == ST_FM_HIT) {
1248 STps->drv_file++;
1249 STps->drv_block = 0;
1250 } else {
1251 STps->drv_block = ntohl(STp->buffer->aux->last_mark_lbn)?
1252 STp->logical_blk_num -
1253 (STps->drv_file ? ntohl(STp->buffer->aux->last_mark_lbn) + 1 : 0):
1254 -1;
1255 }
1256 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_NOEOF;
1257 #if DEBUG
1258 printk(OSST_DEB_MSG
1259 "osst%d:D: Now positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, rptr %d, eof %d\n",
1260 dev, STp->first_frame_position, STp->frame_seq_number, STp->logical_blk_num,
1261 STps->drv_file, STps->drv_block, STp->buffer->read_pointer, STps->eof);
1262 #endif
1263 return 0;
1264 }
1265
1266 /*
1267 * Read back the drive's internal buffer contents, as a part
1268 * of the write error recovery mechanism for old OnStream
1269 * firmware revisions.
1270 * Precondition for this function to work: all frames in the
1271 * drive's buffer must be of one type (DATA, MARK or EOD)!
1272 */
osst_read_back_buffer_and_rewrite(OS_Scsi_Tape * STp,Scsi_Request ** aSRpnt,unsigned int frame,unsigned int skip,int pending)1273 static int osst_read_back_buffer_and_rewrite(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,
1274 unsigned int frame, unsigned int skip, int pending)
1275 {
1276 Scsi_Request * SRpnt = * aSRpnt;
1277 unsigned char * buffer, * p;
1278 unsigned char cmd[MAX_COMMAND_SIZE];
1279 int flag, new_frame, i;
1280 int nframes = STp->cur_frames;
1281 int blks_per_frame = ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1282 int frame_seq_number = ntohl(STp->buffer->aux->frame_seq_num)
1283 - (nframes + pending - 1);
1284 int logical_blk_num = ntohl(STp->buffer->aux->logical_blk_num)
1285 - (nframes + pending - 1) * blks_per_frame;
1286 int dev = TAPE_NR(STp->devt);
1287 long startwait = jiffies;
1288 #if DEBUG
1289 int dbg = debugging;
1290 #endif
1291
1292 if ((buffer = (unsigned char *)vmalloc((nframes + 1) * OS_DATA_SIZE)) == NULL)
1293 return (-EIO);
1294
1295 printk(KERN_INFO "osst%d:I: Reading back %d frames from drive buffer%s\n",
1296 dev, nframes, pending?" and one that was pending":"");
1297
1298 osst_copy_from_buffer(STp->buffer, (p = &buffer[nframes * OS_DATA_SIZE]));
1299 #if DEBUG
1300 if (pending && debugging)
1301 printk(OSST_DEB_MSG "osst%d:D: Pending frame %d (lblk %d), data %02x %02x %02x %02x\n",
1302 dev, frame_seq_number + nframes,
1303 logical_blk_num + nframes * blks_per_frame,
1304 p[0], p[1], p[2], p[3]);
1305 #endif
1306 for (i = 0, p = buffer; i < nframes; i++, p += OS_DATA_SIZE) {
1307
1308 memset(cmd, 0, MAX_COMMAND_SIZE);
1309 cmd[0] = 0x3C; /* Buffer Read */
1310 cmd[1] = 6; /* Retrieve Faulty Block */
1311 cmd[7] = 32768 >> 8;
1312 cmd[8] = 32768 & 0xff;
1313
1314 SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_READ,
1315 STp->timeout, MAX_READ_RETRIES, TRUE);
1316
1317 if ((STp->buffer)->syscall_result || !SRpnt) {
1318 printk(KERN_ERR "osst%d:E: Failed to read frame back from OnStream buffer\n", dev);
1319 vfree((void *)buffer);
1320 *aSRpnt = SRpnt;
1321 return (-EIO);
1322 }
1323 osst_copy_from_buffer(STp->buffer, p);
1324 #if DEBUG
1325 if (debugging)
1326 printk(OSST_DEB_MSG "osst%d:D: Read back logical frame %d, data %02x %02x %02x %02x\n",
1327 dev, frame_seq_number + i, p[0], p[1], p[2], p[3]);
1328 #endif
1329 }
1330 *aSRpnt = SRpnt;
1331 osst_get_frame_position(STp, aSRpnt);
1332
1333 #if DEBUG
1334 printk(OSST_DEB_MSG "osst%d:D: Frames left in buffer: %d\n", dev, STp->cur_frames);
1335 #endif
1336 /* Write synchronously so we can be sure we're OK again and don't have to recover recursively */
1337 /* In the header we don't actually re-write the frames that fail, just the ones after them */
1338
1339 for (flag=1, new_frame=frame, p=buffer, i=0; i < nframes + pending; ) {
1340
1341 if (flag) {
1342 if (STp->write_type == OS_WRITE_HEADER) {
1343 i += skip;
1344 p += skip * OS_DATA_SIZE;
1345 }
1346 else if (new_frame < 2990 && new_frame+skip+nframes+pending >= 2990)
1347 new_frame = 3000-i;
1348 else
1349 new_frame += skip;
1350 #if DEBUG
1351 printk(OSST_DEB_MSG "osst%d:D: Position to frame %d, write fseq %d\n",
1352 dev, new_frame+i, frame_seq_number+i);
1353 #endif
1354 osst_set_frame_position(STp, aSRpnt, new_frame + i, 0);
1355 osst_wait_ready(STp, aSRpnt, 60, OSST_WAIT_POSITION_COMPLETE);
1356 osst_get_frame_position(STp, aSRpnt);
1357 SRpnt = * aSRpnt;
1358
1359 if (new_frame > frame + 1000) {
1360 printk(KERN_ERR "osst%d:E: Failed to find writable tape media\n", dev);
1361 vfree((void *)buffer);
1362 return (-EIO);
1363 }
1364 flag = 0;
1365 if ( i >= nframes + pending ) break;
1366 }
1367 osst_copy_to_buffer(STp->buffer, p);
1368 /*
1369 * IMPORTANT: for error recovery to work, _never_ queue frames with mixed frame type!
1370 */
1371 osst_init_aux(STp, STp->buffer->aux->frame_type, frame_seq_number+i,
1372 logical_blk_num + i*blks_per_frame,
1373 ntohl(STp->buffer->aux->dat.dat_list[0].blk_sz), blks_per_frame);
1374 memset(cmd, 0, MAX_COMMAND_SIZE);
1375 cmd[0] = WRITE_6;
1376 cmd[1] = 1;
1377 cmd[4] = 1;
1378
1379 #if DEBUG
1380 if (debugging)
1381 printk(OSST_DEB_MSG
1382 "osst%d:D: About to write frame %d, seq %d, lbn %d, data %02x %02x %02x %02x\n",
1383 dev, new_frame+i, frame_seq_number+i, logical_blk_num + i*blks_per_frame,
1384 p[0], p[1], p[2], p[3]);
1385 #endif
1386 SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_WRITE,
1387 STp->timeout, MAX_WRITE_RETRIES, TRUE);
1388
1389 if (STp->buffer->syscall_result)
1390 flag = 1;
1391 else {
1392 p += OS_DATA_SIZE; i++;
1393
1394 /* if we just sent the last frame, wait till all successfully written */
1395 if ( i == nframes + pending ) {
1396 #if DEBUG
1397 printk(OSST_DEB_MSG "osst%d:D: Check re-write successful\n", dev);
1398 #endif
1399 memset(cmd, 0, MAX_COMMAND_SIZE);
1400 cmd[0] = WRITE_FILEMARKS;
1401 cmd[1] = 1;
1402 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE,
1403 STp->timeout, MAX_WRITE_RETRIES, TRUE);
1404 #if DEBUG
1405 if (debugging) {
1406 printk(OSST_DEB_MSG "osst%d:D: Sleeping in re-write wait ready\n", dev);
1407 printk(OSST_DEB_MSG "osst%d:D: Turning off debugging for a while\n", dev);
1408 debugging = 0;
1409 }
1410 #endif
1411 flag = STp->buffer->syscall_result;
1412 while ( !flag && time_before(jiffies, startwait + 60*HZ) ) {
1413
1414 memset(cmd, 0, MAX_COMMAND_SIZE);
1415 cmd[0] = TEST_UNIT_READY;
1416
1417 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout,
1418 MAX_READY_RETRIES, TRUE);
1419
1420 if (SRpnt->sr_sense_buffer[2] == 2 && SRpnt->sr_sense_buffer[12] == 4 &&
1421 (SRpnt->sr_sense_buffer[13] == 1 || SRpnt->sr_sense_buffer[13] == 8)) {
1422 /* in the process of becoming ready */
1423 set_current_state(TASK_INTERRUPTIBLE);
1424 schedule_timeout(HZ / 10);
1425 continue;
1426 }
1427 if (STp->buffer->syscall_result)
1428 flag = 1;
1429 break;
1430 }
1431 #if DEBUG
1432 debugging = dbg;
1433 printk(OSST_DEB_MSG "osst%d:D: Wait re-write finished\n", dev);
1434 #endif
1435 }
1436 }
1437 *aSRpnt = SRpnt;
1438 if (flag) {
1439 if ((SRpnt->sr_sense_buffer[ 2] & 0x0f) == 13 &&
1440 SRpnt->sr_sense_buffer[12] == 0 &&
1441 SRpnt->sr_sense_buffer[13] == 2) {
1442 printk(KERN_ERR "osst%d:E: Volume overflow in write error recovery\n", dev);
1443 vfree((void *)buffer);
1444 return (-EIO); /* hit end of tape = fail */
1445 }
1446 i = ((SRpnt->sr_sense_buffer[3] << 24) |
1447 (SRpnt->sr_sense_buffer[4] << 16) |
1448 (SRpnt->sr_sense_buffer[5] << 8) |
1449 SRpnt->sr_sense_buffer[6] ) - new_frame;
1450 p = &buffer[i * OS_DATA_SIZE];
1451 #if DEBUG
1452 printk(OSST_DEB_MSG "osst%d:D: Additional write error at %d\n", dev, new_frame+i);
1453 #endif
1454 osst_get_frame_position(STp, aSRpnt);
1455 #if DEBUG
1456 printk(OSST_DEB_MSG "osst%d:D: reported frame positions: host = %d, tape = %d\n",
1457 dev, STp->first_frame_position, STp->last_frame_position);
1458 #endif
1459 }
1460 }
1461 if (!pending)
1462 osst_copy_to_buffer(STp->buffer, p); /* so buffer content == at entry in all cases */
1463 vfree((void *)buffer);
1464 return 0;
1465 }
1466
osst_reposition_and_retry(OS_Scsi_Tape * STp,Scsi_Request ** aSRpnt,unsigned int frame,unsigned int skip,int pending)1467 static int osst_reposition_and_retry(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,
1468 unsigned int frame, unsigned int skip, int pending)
1469 {
1470 unsigned char cmd[MAX_COMMAND_SIZE];
1471 Scsi_Request * SRpnt;
1472 int dev = TAPE_NR(STp->devt);
1473 int expected = 0;
1474 int attempts = 1000 / skip;
1475 int flag = 1;
1476 long startwait = jiffies;
1477 #if DEBUG
1478 int dbg = debugging;
1479 #endif
1480
1481 while (attempts && time_before(jiffies, startwait + 60*HZ)) {
1482 if (flag) {
1483 #if DEBUG
1484 debugging = dbg;
1485 #endif
1486 if (frame < 2990 && frame+skip+STp->cur_frames+pending >= 2990)
1487 frame = 3000-skip;
1488 expected = frame+skip+STp->cur_frames+pending;
1489 #if DEBUG
1490 printk(OSST_DEB_MSG "osst%d:D: Position to fppos %d, re-write from fseq %d\n",
1491 dev, frame+skip, STp->frame_seq_number-STp->cur_frames-pending);
1492 #endif
1493 osst_set_frame_position(STp, aSRpnt, frame + skip, 1);
1494 flag = 0;
1495 attempts--;
1496 set_current_state(TASK_INTERRUPTIBLE);
1497 schedule_timeout(HZ / 10);
1498 }
1499 if (osst_get_frame_position(STp, aSRpnt) < 0) { /* additional write error */
1500 #if DEBUG
1501 printk(OSST_DEB_MSG "osst%d:D: Addl error, host %d, tape %d, buffer %d\n",
1502 dev, STp->first_frame_position,
1503 STp->last_frame_position, STp->cur_frames);
1504 #endif
1505 frame = STp->last_frame_position;
1506 flag = 1;
1507 continue;
1508 }
1509 if (pending && STp->cur_frames < 50) {
1510
1511 memset(cmd, 0, MAX_COMMAND_SIZE);
1512 cmd[0] = WRITE_6;
1513 cmd[1] = 1;
1514 cmd[4] = 1;
1515 #if DEBUG
1516 printk(OSST_DEB_MSG "osst%d:D: About to write pending fseq %d at fppos %d\n",
1517 dev, STp->frame_seq_number-1, STp->first_frame_position);
1518 #endif
1519 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_WRITE,
1520 STp->timeout, MAX_WRITE_RETRIES, TRUE);
1521 *aSRpnt = SRpnt;
1522
1523 if (STp->buffer->syscall_result) { /* additional write error */
1524 if ((SRpnt->sr_sense_buffer[ 2] & 0x0f) == 13 &&
1525 SRpnt->sr_sense_buffer[12] == 0 &&
1526 SRpnt->sr_sense_buffer[13] == 2) {
1527 printk(KERN_ERR
1528 "osst%d:E: Volume overflow in write error recovery\n",
1529 dev);
1530 break; /* hit end of tape = fail */
1531 }
1532 flag = 1;
1533 }
1534 else
1535 pending = 0;
1536
1537 continue;
1538 }
1539 if (STp->cur_frames == 0) {
1540 #if DEBUG
1541 debugging = dbg;
1542 printk(OSST_DEB_MSG "osst%d:D: Wait re-write finished\n", dev);
1543 #endif
1544 if (STp->first_frame_position != expected) {
1545 printk(KERN_ERR "osst%d:A: Actual position %d - expected %d\n",
1546 dev, STp->first_frame_position, expected);
1547 return (-EIO);
1548 }
1549 return 0;
1550 }
1551 #if DEBUG
1552 if (debugging) {
1553 printk(OSST_DEB_MSG "osst%d:D: Sleeping in re-write wait ready\n", dev);
1554 printk(OSST_DEB_MSG "osst%d:D: Turning off debugging for a while\n", dev);
1555 debugging = 0;
1556 }
1557 #endif
1558 set_current_state(TASK_INTERRUPTIBLE);
1559 schedule_timeout(HZ / 10);
1560 }
1561 printk(KERN_ERR "osst%d:E: Failed to find valid tape media\n", dev);
1562 #if DEBUG
1563 debugging = dbg;
1564 #endif
1565 return (-EIO);
1566 }
1567
1568 /*
1569 * Error recovery algorithm for the OnStream tape.
1570 */
1571
osst_write_error_recovery(OS_Scsi_Tape * STp,Scsi_Request ** aSRpnt,int pending)1572 static int osst_write_error_recovery(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int pending)
1573 {
1574 Scsi_Request * SRpnt = * aSRpnt;
1575 ST_partstat * STps = & STp->ps[STp->partition];
1576 int dev = TAPE_NR(STp->devt);
1577 int retval = 0;
1578 int rw_state;
1579 unsigned int frame, skip;
1580
1581 rw_state = STps->rw;
1582
1583 if ((SRpnt->sr_sense_buffer[ 2] & 0x0f) != 3
1584 || SRpnt->sr_sense_buffer[12] != 12
1585 || SRpnt->sr_sense_buffer[13] != 0) {
1586 #if DEBUG
1587 printk(OSST_DEB_MSG "osst%d:D: Write error recovery cannot handle %02x:%02x:%02x\n", dev,
1588 SRpnt->sr_sense_buffer[2], SRpnt->sr_sense_buffer[12], SRpnt->sr_sense_buffer[13]);
1589 #endif
1590 return (-EIO);
1591 }
1592 frame = (SRpnt->sr_sense_buffer[3] << 24) |
1593 (SRpnt->sr_sense_buffer[4] << 16) |
1594 (SRpnt->sr_sense_buffer[5] << 8) |
1595 SRpnt->sr_sense_buffer[6];
1596 skip = SRpnt->sr_sense_buffer[9];
1597
1598 #if DEBUG
1599 printk(OSST_DEB_MSG "osst%d:D: Detected physical bad frame at %u, advised to skip %d\n", dev, frame, skip);
1600 #endif
1601 osst_get_frame_position(STp, aSRpnt);
1602 #if DEBUG
1603 printk(OSST_DEB_MSG "osst%d:D: reported frame positions: host = %d, tape = %d\n",
1604 dev, STp->first_frame_position, STp->last_frame_position);
1605 #endif
1606 switch (STp->write_type) {
1607 case OS_WRITE_DATA:
1608 case OS_WRITE_EOD:
1609 case OS_WRITE_NEW_MARK:
1610 printk(KERN_WARNING
1611 "osst%d:I: Relocating %d buffered logical frames from position %u to %u\n",
1612 dev, STp->cur_frames, frame, (frame + skip > 3000 && frame < 3000)?3000:frame + skip);
1613 if (STp->os_fw_rev >= 10600)
1614 retval = osst_reposition_and_retry(STp, aSRpnt, frame, skip, pending);
1615 else
1616 retval = osst_read_back_buffer_and_rewrite(STp, aSRpnt, frame, skip, pending);
1617 printk(KERN_WARNING "osst%d:%s: %sWrite error%srecovered\n", dev,
1618 retval?"E" :"I",
1619 retval?"" :"Don't worry, ",
1620 retval?" not ":" ");
1621 break;
1622 case OS_WRITE_LAST_MARK:
1623 printk(KERN_ERR "osst%d:E: Bad frame in update last marker, fatal\n", dev);
1624 osst_set_frame_position(STp, aSRpnt, frame + STp->cur_frames + pending, 0);
1625 retval = -EIO;
1626 break;
1627 case OS_WRITE_HEADER:
1628 printk(KERN_WARNING "osst%d:I: Bad frame in header partition, skipped\n", dev);
1629 retval = osst_read_back_buffer_and_rewrite(STp, aSRpnt, frame, 1, pending);
1630 break;
1631 default:
1632 printk(KERN_INFO "osst%d:I: Bad frame in filler, ignored\n", dev);
1633 osst_set_frame_position(STp, aSRpnt, frame + STp->cur_frames + pending, 0);
1634 }
1635 osst_get_frame_position(STp, aSRpnt);
1636 #if DEBUG
1637 printk(OSST_DEB_MSG "osst%d:D: Positioning complete, cur_frames %d, pos %d, tape pos %d\n",
1638 dev, STp->cur_frames, STp->first_frame_position, STp->last_frame_position);
1639 printk(OSST_DEB_MSG "osst%d:D: next logical frame to write: %d\n", dev, STp->logical_blk_num);
1640 #endif
1641 if (retval == 0) {
1642 STp->recover_count++;
1643 STp->recover_erreg++;
1644 }
1645 STps->rw = rw_state;
1646 return retval;
1647 }
1648
osst_space_over_filemarks_backward(OS_Scsi_Tape * STp,Scsi_Request ** aSRpnt,int mt_op,int mt_count)1649 static int osst_space_over_filemarks_backward(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,
1650 int mt_op, int mt_count)
1651 {
1652 int dev = TAPE_NR(STp->devt);
1653 int cnt;
1654 int last_mark_ppos = -1;
1655
1656 #if DEBUG
1657 printk(OSST_DEB_MSG "osst%d:D: Reached space_over_filemarks_backwards %d %d\n", dev, mt_op, mt_count);
1658 #endif
1659 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1660 #if DEBUG
1661 printk(OSST_DEB_MSG "osst%d:D: Couldn't get logical blk num in space_filemarks_bwd\n", dev);
1662 #endif
1663 return -EIO;
1664 }
1665 if (STp->linux_media_version >= 4) {
1666 /*
1667 * direct lookup in header filemark list
1668 */
1669 cnt = ntohl(STp->buffer->aux->filemark_cnt);
1670 if (STp->header_ok &&
1671 STp->header_cache != NULL &&
1672 (cnt - mt_count) >= 0 &&
1673 (cnt - mt_count) < OS_FM_TAB_MAX &&
1674 (cnt - mt_count) < STp->filemark_cnt &&
1675 STp->header_cache->dat_fm_tab.fm_tab_ent[cnt-1] == STp->buffer->aux->last_mark_ppos)
1676
1677 last_mark_ppos = ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[cnt - mt_count]);
1678 #if DEBUG
1679 if (STp->header_cache == NULL || (cnt - mt_count) < 0 || (cnt - mt_count) >= OS_FM_TAB_MAX)
1680 printk(OSST_DEB_MSG "osst%d:D: Filemark lookup fail due to %s\n", dev,
1681 STp->header_cache == NULL?"lack of header cache":"count out of range");
1682 else
1683 printk(OSST_DEB_MSG "osst%d:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
1684 dev, cnt,
1685 ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
1686 (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt-1] ==
1687 STp->buffer->aux->last_mark_ppos))?"match":"error",
1688 mt_count, last_mark_ppos);
1689 #endif
1690 if (last_mark_ppos > 10 && last_mark_ppos < STp->eod_frame_ppos) {
1691 osst_position_tape_and_confirm(STp, aSRpnt, last_mark_ppos);
1692 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1693 #if DEBUG
1694 printk(OSST_DEB_MSG
1695 "osst%d:D: Couldn't get logical blk num in space_filemarks\n", dev);
1696 #endif
1697 return (-EIO);
1698 }
1699 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1700 printk(KERN_WARNING "osst%d:W: Expected to find marker at ppos %d, not found\n",
1701 dev, last_mark_ppos);
1702 return (-EIO);
1703 }
1704 goto found;
1705 }
1706 #if DEBUG
1707 printk(OSST_DEB_MSG "osst%d:D: Reverting to scan filemark backwards\n", dev);
1708 #endif
1709 }
1710 cnt = 0;
1711 while (cnt != mt_count) {
1712 last_mark_ppos = ntohl(STp->buffer->aux->last_mark_ppos);
1713 if (last_mark_ppos == -1)
1714 return (-EIO);
1715 #if DEBUG
1716 printk(OSST_DEB_MSG "osst%d:D: Positioning to last mark at %d\n", dev, last_mark_ppos);
1717 #endif
1718 osst_position_tape_and_confirm(STp, aSRpnt, last_mark_ppos);
1719 cnt++;
1720 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1721 #if DEBUG
1722 printk(OSST_DEB_MSG "osst%d:D: Couldn't get logical blk num in space_filemarks\n", dev);
1723 #endif
1724 return (-EIO);
1725 }
1726 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1727 printk(KERN_WARNING "osst%d:W: Expected to find marker at ppos %d, not found\n",
1728 dev, last_mark_ppos);
1729 return (-EIO);
1730 }
1731 }
1732 found:
1733 if (mt_op == MTBSFM) {
1734 STp->frame_seq_number++;
1735 STp->frame_in_buffer = 0;
1736 STp->buffer->buffer_bytes = 0;
1737 STp->buffer->read_pointer = 0;
1738 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1739 }
1740 return 0;
1741 }
1742
1743 /*
1744 * ADRL 1.1 compatible "slow" space filemarks fwd version
1745 *
1746 * Just scans for the filemark sequentially.
1747 */
osst_space_over_filemarks_forward_slow(OS_Scsi_Tape * STp,Scsi_Request ** aSRpnt,int mt_op,int mt_count)1748 static int osst_space_over_filemarks_forward_slow(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,
1749 int mt_op, int mt_count)
1750 {
1751 int cnt = 0;
1752 #if DEBUG
1753 int dev = TAPE_NR(STp->devt);
1754
1755 printk(OSST_DEB_MSG "osst%d:D: Reached space_over_filemarks_forward_slow %d %d\n", dev, mt_op, mt_count);
1756 #endif
1757 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1758 #if DEBUG
1759 printk(OSST_DEB_MSG "osst%d:D: Couldn't get logical blk num in space_filemarks_fwd\n", dev);
1760 #endif
1761 return (-EIO);
1762 }
1763 while (1) {
1764 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1765 #if DEBUG
1766 printk(OSST_DEB_MSG "osst%d:D: Couldn't get logical blk num in space_filemarks\n", dev);
1767 #endif
1768 return (-EIO);
1769 }
1770 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER)
1771 cnt++;
1772 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_EOD) {
1773 #if DEBUG
1774 printk(OSST_DEB_MSG "osst%d:D: space_fwd: EOD reached\n", dev);
1775 #endif
1776 if (STp->first_frame_position > STp->eod_frame_ppos+1) {
1777 #if DEBUG
1778 printk(OSST_DEB_MSG "osst%d:D: EOD position corrected (%d=>%d)\n",
1779 dev, STp->eod_frame_ppos, STp->first_frame_position-1);
1780 #endif
1781 STp->eod_frame_ppos = STp->first_frame_position-1;
1782 }
1783 return (-EIO);
1784 }
1785 if (cnt == mt_count)
1786 break;
1787 STp->frame_in_buffer = 0;
1788 }
1789 if (mt_op == MTFSF) {
1790 STp->frame_seq_number++;
1791 STp->frame_in_buffer = 0;
1792 STp->buffer->buffer_bytes = 0;
1793 STp->buffer->read_pointer = 0;
1794 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1795 }
1796 return 0;
1797 }
1798
1799 /*
1800 * Fast linux specific version of OnStream FSF
1801 */
osst_space_over_filemarks_forward_fast(OS_Scsi_Tape * STp,Scsi_Request ** aSRpnt,int mt_op,int mt_count)1802 static int osst_space_over_filemarks_forward_fast(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,
1803 int mt_op, int mt_count)
1804 {
1805 int dev = TAPE_NR(STp->devt);
1806 int cnt = 0,
1807 next_mark_ppos = -1;
1808
1809 #if DEBUG
1810 printk(OSST_DEB_MSG "osst%d:D: Reached space_over_filemarks_forward_fast %d %d\n", dev, mt_op, mt_count);
1811 #endif
1812 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1813 #if DEBUG
1814 printk(OSST_DEB_MSG "osst%d:D: Couldn't get logical blk num in space_filemarks_fwd\n", dev);
1815 #endif
1816 return (-EIO);
1817 }
1818
1819 if (STp->linux_media_version >= 4) {
1820 /*
1821 * direct lookup in header filemark list
1822 */
1823 cnt = ntohl(STp->buffer->aux->filemark_cnt) - 1;
1824 if (STp->header_ok &&
1825 STp->header_cache != NULL &&
1826 (cnt + mt_count) < OS_FM_TAB_MAX &&
1827 (cnt + mt_count) < STp->filemark_cnt &&
1828 ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
1829 (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt] == STp->buffer->aux->last_mark_ppos)))
1830
1831 next_mark_ppos = ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[cnt + mt_count]);
1832 #if DEBUG
1833 if (STp->header_cache == NULL || (cnt + mt_count) >= OS_FM_TAB_MAX)
1834 printk(OSST_DEB_MSG "osst%d:D: Filemark lookup fail due to %s\n", dev,
1835 STp->header_cache == NULL?"lack of header cache":"count out of range");
1836 else
1837 printk(OSST_DEB_MSG "osst%d:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
1838 dev, cnt,
1839 ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
1840 (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt] ==
1841 STp->buffer->aux->last_mark_ppos))?"match":"error",
1842 mt_count, next_mark_ppos);
1843 #endif
1844 if (next_mark_ppos <= 10 || next_mark_ppos > STp->eod_frame_ppos) {
1845 #if DEBUG
1846 printk(OSST_DEB_MSG "osst%d:D: Reverting to slow filemark space\n", dev);
1847 #endif
1848 return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count);
1849 } else {
1850 osst_position_tape_and_confirm(STp, aSRpnt, next_mark_ppos);
1851 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1852 #if DEBUG
1853 printk(OSST_DEB_MSG "osst%d:D: Couldn't get logical blk num in space_filemarks\n",
1854 dev);
1855 #endif
1856 return (-EIO);
1857 }
1858 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1859 printk(KERN_WARNING "osst%d:W: Expected to find marker at ppos %d, not found\n",
1860 dev, next_mark_ppos);
1861 return (-EIO);
1862 }
1863 if (ntohl(STp->buffer->aux->filemark_cnt) != cnt + mt_count) {
1864 printk(KERN_WARNING "osst%d:W: Expected to find marker %d at ppos %d, not %d\n",
1865 dev, cnt+mt_count, next_mark_ppos,
1866 ntohl(STp->buffer->aux->filemark_cnt));
1867 return (-EIO);
1868 }
1869 }
1870 } else {
1871 /*
1872 * Find nearest (usually previous) marker, then jump from marker to marker
1873 */
1874 while (1) {
1875 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER)
1876 break;
1877 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_EOD) {
1878 #if DEBUG
1879 printk(OSST_DEB_MSG "osst%d:D: space_fwd: EOD reached\n", dev);
1880 #endif
1881 return (-EIO);
1882 }
1883 if (ntohl(STp->buffer->aux->filemark_cnt) == 0) {
1884 if (STp->first_mark_ppos == -1) {
1885 #if DEBUG
1886 printk(OSST_DEB_MSG "osst%d:D: Reverting to slow filemark space\n", dev);
1887 #endif
1888 return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count);
1889 }
1890 osst_position_tape_and_confirm(STp, aSRpnt, STp->first_mark_ppos);
1891 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1892 #if DEBUG
1893 printk(OSST_DEB_MSG
1894 "osst%d:D: Couldn't get logical blk num in space_filemarks_fwd_fast\n",
1895 dev);
1896 #endif
1897 return (-EIO);
1898 }
1899 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1900 printk(KERN_WARNING "osst%d:W: Expected to find filemark at %d\n",
1901 dev, STp->first_mark_ppos);
1902 return (-EIO);
1903 }
1904 } else {
1905 if (osst_space_over_filemarks_backward(STp, aSRpnt, MTBSF, 1) < 0)
1906 return (-EIO);
1907 mt_count++;
1908 }
1909 }
1910 cnt++;
1911 while (cnt != mt_count) {
1912 next_mark_ppos = ntohl(STp->buffer->aux->next_mark_ppos);
1913 if (!next_mark_ppos || next_mark_ppos > STp->eod_frame_ppos) {
1914 #if DEBUG
1915 printk(OSST_DEB_MSG "osst%d:D: Reverting to slow filemark space\n", dev);
1916 #endif
1917 return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count - cnt);
1918 }
1919 #if DEBUG
1920 else printk(OSST_DEB_MSG "osst%d:D: Positioning to next mark at %d\n", dev, next_mark_ppos);
1921 #endif
1922 osst_position_tape_and_confirm(STp, aSRpnt, next_mark_ppos);
1923 cnt++;
1924 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1925 #if DEBUG
1926 printk(OSST_DEB_MSG "osst%d:D: Couldn't get logical blk num in space_filemarks\n",
1927 dev);
1928 #endif
1929 return (-EIO);
1930 }
1931 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1932 printk(KERN_WARNING "osst%d:W: Expected to find marker at ppos %d, not found\n",
1933 dev, next_mark_ppos);
1934 return (-EIO);
1935 }
1936 }
1937 }
1938 if (mt_op == MTFSF) {
1939 STp->frame_seq_number++;
1940 STp->frame_in_buffer = 0;
1941 STp->buffer->buffer_bytes = 0;
1942 STp->buffer->read_pointer = 0;
1943 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1944 }
1945 return 0;
1946 }
1947
1948 /*
1949 * In debug mode, we want to see as many errors as possible
1950 * to test the error recovery mechanism.
1951 */
1952 #if DEBUG
osst_set_retries(OS_Scsi_Tape * STp,Scsi_Request ** aSRpnt,int retries)1953 static void osst_set_retries(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int retries)
1954 {
1955 unsigned char cmd[MAX_COMMAND_SIZE];
1956 Scsi_Request * SRpnt = * aSRpnt;
1957 int dev = TAPE_NR(STp->devt);
1958
1959 memset(cmd, 0, MAX_COMMAND_SIZE);
1960 cmd[0] = MODE_SELECT;
1961 cmd[1] = 0x10;
1962 cmd[4] = NUMBER_RETRIES_PAGE_LENGTH + MODE_HEADER_LENGTH;
1963
1964 (STp->buffer)->b_data[0] = cmd[4] - 1;
1965 (STp->buffer)->b_data[1] = 0; /* Medium Type - ignoring */
1966 (STp->buffer)->b_data[2] = 0; /* Reserved */
1967 (STp->buffer)->b_data[3] = 0; /* Block Descriptor Length */
1968 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = NUMBER_RETRIES_PAGE | (1 << 7);
1969 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 2;
1970 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 4;
1971 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = retries;
1972
1973 if (debugging)
1974 printk(OSST_DEB_MSG "osst%d:D: Setting number of retries on OnStream tape to %d\n", dev, retries);
1975
1976 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_WRITE, STp->timeout, 0, TRUE);
1977 *aSRpnt = SRpnt;
1978
1979 if ((STp->buffer)->syscall_result)
1980 printk (KERN_ERR "osst%d:D: Couldn't set retries to %d\n", dev, retries);
1981 }
1982 #endif
1983
1984
osst_write_filemark(OS_Scsi_Tape * STp,Scsi_Request ** aSRpnt)1985 static int osst_write_filemark(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
1986 {
1987 int result;
1988 int this_mark_ppos = STp->first_frame_position;
1989 int this_mark_lbn = STp->logical_blk_num;
1990 #if DEBUG
1991 int dev = TAPE_NR(STp->devt);
1992 #endif
1993
1994 if (STp->raw) return 0;
1995
1996 STp->write_type = OS_WRITE_NEW_MARK;
1997 #if DEBUG
1998 printk(OSST_DEB_MSG "osst%d:D: Writing Filemark %i at fppos %d (fseq %d, lblk %d)\n",
1999 dev, STp->filemark_cnt, this_mark_ppos, STp->frame_seq_number, this_mark_lbn);
2000 #endif
2001 STp->dirty = 1;
2002 result = osst_flush_write_buffer(STp, aSRpnt);
2003 result |= osst_flush_drive_buffer(STp, aSRpnt);
2004 STp->last_mark_ppos = this_mark_ppos;
2005 STp->last_mark_lbn = this_mark_lbn;
2006 if (STp->header_cache != NULL && STp->filemark_cnt < OS_FM_TAB_MAX)
2007 STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt] = htonl(this_mark_ppos);
2008 if (STp->filemark_cnt++ == 0)
2009 STp->first_mark_ppos = this_mark_ppos;
2010 return result;
2011 }
2012
osst_write_eod(OS_Scsi_Tape * STp,Scsi_Request ** aSRpnt)2013 static int osst_write_eod(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
2014 {
2015 int result;
2016 #if DEBUG
2017 int dev = TAPE_NR(STp->devt);
2018 #endif
2019
2020 if (STp->raw) return 0;
2021
2022 STp->write_type = OS_WRITE_EOD;
2023 STp->eod_frame_ppos = STp->first_frame_position;
2024 #if DEBUG
2025 printk(OSST_DEB_MSG "osst%d:D: Writing EOD at fppos %d (fseq %d, lblk %d)\n", dev,
2026 STp->eod_frame_ppos, STp->frame_seq_number, STp->logical_blk_num);
2027 #endif
2028 STp->dirty = 1;
2029
2030 result = osst_flush_write_buffer(STp, aSRpnt);
2031 result |= osst_flush_drive_buffer(STp, aSRpnt);
2032 STp->eod_frame_lfa = --(STp->frame_seq_number);
2033 return result;
2034 }
2035
osst_write_filler(OS_Scsi_Tape * STp,Scsi_Request ** aSRpnt,int where,int count)2036 static int osst_write_filler(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int where, int count)
2037 {
2038 int dev = TAPE_NR(STp->devt);
2039
2040 #if DEBUG
2041 printk(OSST_DEB_MSG "osst%d:D: Reached onstream write filler group %d\n", dev, where);
2042 #endif
2043 osst_wait_ready(STp, aSRpnt, 60 * 5, 0);
2044 osst_set_frame_position(STp, aSRpnt, where, 0);
2045 STp->write_type = OS_WRITE_FILLER;
2046 while (count--) {
2047 memcpy(STp->buffer->b_data, "Filler", 6);
2048 STp->buffer->buffer_bytes = 6;
2049 STp->dirty = 1;
2050 if (osst_flush_write_buffer(STp, aSRpnt)) {
2051 printk(KERN_INFO "osst%i:I: Couldn't write filler frame\n", dev);
2052 return (-EIO);
2053 }
2054 }
2055 #if DEBUG
2056 printk(OSST_DEB_MSG "osst%d:D: Exiting onstream write filler group\n", dev);
2057 #endif
2058 return osst_flush_drive_buffer(STp, aSRpnt);
2059 }
2060
__osst_write_header(OS_Scsi_Tape * STp,Scsi_Request ** aSRpnt,int where,int count)2061 static int __osst_write_header(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int where, int count)
2062 {
2063 int dev = TAPE_NR(STp->devt);
2064 int result;
2065
2066 #if DEBUG
2067 printk(OSST_DEB_MSG "osst%d:D: Reached onstream write header group %d\n", dev, where);
2068 #endif
2069 osst_wait_ready(STp, aSRpnt, 60 * 5, 0);
2070 osst_set_frame_position(STp, aSRpnt, where, 0);
2071 STp->write_type = OS_WRITE_HEADER;
2072 while (count--) {
2073 osst_copy_to_buffer(STp->buffer, (unsigned char *)STp->header_cache);
2074 STp->buffer->buffer_bytes = sizeof(os_header_t);
2075 STp->dirty = 1;
2076 if (osst_flush_write_buffer(STp, aSRpnt)) {
2077 printk(KERN_INFO "osst%i:I: Couldn't write header frame\n", dev);
2078 return (-EIO);
2079 }
2080 }
2081 result = osst_flush_drive_buffer(STp, aSRpnt);
2082 #if DEBUG
2083 printk(OSST_DEB_MSG "osst%d:D: Write onstream header group %s\n", dev, result?"failed":"done");
2084 #endif
2085 return result;
2086 }
2087
osst_write_header(OS_Scsi_Tape * STp,Scsi_Request ** aSRpnt,int locate_eod)2088 static int osst_write_header(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int locate_eod)
2089 {
2090 os_header_t * header;
2091 int result;
2092 int dev = TAPE_NR(STp->devt);
2093
2094 #if DEBUG
2095 printk(OSST_DEB_MSG "osst%d:D: Writing tape header\n", dev);
2096 #endif
2097 if (STp->raw) return 0;
2098
2099 if (STp->header_cache == NULL) {
2100 if ((STp->header_cache = (os_header_t *)vmalloc(sizeof(os_header_t))) == NULL) {
2101 printk(KERN_ERR "osst%i:E: Failed to allocate header cache\n", dev);
2102 return (-ENOMEM);
2103 }
2104 memset(STp->header_cache, 0, sizeof(os_header_t));
2105 #if DEBUG
2106 printk(OSST_DEB_MSG "osst%d:D: Allocated and cleared memory for header cache\n", dev);
2107 #endif
2108 }
2109 if (STp->header_ok) STp->update_frame_cntr++;
2110 else STp->update_frame_cntr = 0;
2111
2112 header = STp->header_cache;
2113 strcpy(header->ident_str, "ADR_SEQ");
2114 header->major_rev = 1;
2115 header->minor_rev = 4;
2116 header->ext_trk_tb_off = htons(17192);
2117 header->pt_par_num = 1;
2118 header->partition[0].partition_num = OS_DATA_PARTITION;
2119 header->partition[0].par_desc_ver = OS_PARTITION_VERSION;
2120 header->partition[0].wrt_pass_cntr = htons(STp->wrt_pass_cntr);
2121 header->partition[0].first_frame_ppos = htonl(STp->first_data_ppos);
2122 header->partition[0].last_frame_ppos = htonl(STp->capacity);
2123 header->partition[0].eod_frame_ppos = htonl(STp->eod_frame_ppos);
2124 header->cfg_col_width = htonl(20);
2125 header->dat_col_width = htonl(1500);
2126 header->qfa_col_width = htonl(0);
2127 header->ext_track_tb.nr_stream_part = 1;
2128 header->ext_track_tb.et_ent_sz = 32;
2129 header->ext_track_tb.dat_ext_trk_ey.et_part_num = 0;
2130 header->ext_track_tb.dat_ext_trk_ey.fmt = 1;
2131 header->ext_track_tb.dat_ext_trk_ey.fm_tab_off = htons(17736);
2132 header->ext_track_tb.dat_ext_trk_ey.last_hlb_hi = 0;
2133 header->ext_track_tb.dat_ext_trk_ey.last_hlb = htonl(STp->eod_frame_lfa);
2134 header->ext_track_tb.dat_ext_trk_ey.last_pp = htonl(STp->eod_frame_ppos);
2135 header->dat_fm_tab.fm_part_num = 0;
2136 header->dat_fm_tab.fm_tab_ent_sz = 4;
2137 header->dat_fm_tab.fm_tab_ent_cnt = htons(STp->filemark_cnt<OS_FM_TAB_MAX?
2138 STp->filemark_cnt:OS_FM_TAB_MAX);
2139
2140 result = __osst_write_header(STp, aSRpnt, 0xbae, 5);
2141 if (STp->update_frame_cntr == 0)
2142 osst_write_filler(STp, aSRpnt, 0xbb3, 5);
2143 result &= __osst_write_header(STp, aSRpnt, 5, 5);
2144
2145 if (locate_eod) {
2146 #if DEBUG
2147 printk(OSST_DEB_MSG "osst%d:D: Locating back to eod frame addr %d\n", dev, STp->eod_frame_ppos);
2148 #endif
2149 osst_set_frame_position(STp, aSRpnt, STp->eod_frame_ppos, 0);
2150 }
2151 if (result)
2152 printk(KERN_ERR "osst%i:E: Write header failed\n", dev);
2153 else {
2154 memcpy(STp->application_sig, "LIN4", 4);
2155 STp->linux_media = 1;
2156 STp->linux_media_version = 4;
2157 STp->header_ok = 1;
2158 }
2159 return result;
2160 }
2161
osst_reset_header(OS_Scsi_Tape * STp,Scsi_Request ** aSRpnt)2162 static int osst_reset_header(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
2163 {
2164 if (STp->header_cache != NULL)
2165 memset(STp->header_cache, 0, sizeof(os_header_t));
2166
2167 STp->logical_blk_num = STp->frame_seq_number = 0;
2168 STp->frame_in_buffer = 0;
2169 STp->eod_frame_ppos = STp->first_data_ppos = 0x0000000A;
2170 STp->filemark_cnt = 0;
2171 STp->first_mark_ppos = STp->last_mark_ppos = STp->last_mark_lbn = -1;
2172 return osst_write_header(STp, aSRpnt, 1);
2173 }
2174
__osst_analyze_headers(OS_Scsi_Tape * STp,Scsi_Request ** aSRpnt,int ppos)2175 static int __osst_analyze_headers(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int ppos)
2176 {
2177 int dev = TAPE_NR(STp->devt);
2178 os_header_t * header;
2179 os_aux_t * aux;
2180 char id_string[8];
2181 int linux_media_version,
2182 update_frame_cntr;
2183
2184 if (STp->raw)
2185 return 1;
2186
2187 if (ppos == 5 || ppos == 0xbae || STp->buffer->syscall_result) {
2188 if (osst_set_frame_position(STp, aSRpnt, ppos, 0))
2189 printk(KERN_WARNING "osst%i:W: Couldn't position tape\n", dev);
2190 osst_wait_ready(STp, aSRpnt, 60 * 15, 0);
2191 if (osst_initiate_read(STp, aSRpnt)) {
2192 printk(KERN_WARNING "osst%i:W: Couldn't initiate read\n", dev);
2193 return 0;
2194 }
2195 }
2196 if (osst_read_frame(STp, aSRpnt, 180)) {
2197 #if DEBUG
2198 printk(OSST_DEB_MSG "osst%d:D: Couldn't read header frame\n", dev);
2199 #endif
2200 return 0;
2201 }
2202 header = (os_header_t *) STp->buffer->b_data; /* warning: only first segment addressable */
2203 aux = STp->buffer->aux;
2204 if (aux->frame_type != OS_FRAME_TYPE_HEADER) {
2205 #if DEBUG
2206 printk(OSST_DEB_MSG "osst%d:D: Skipping non-header frame (%d)\n", dev, ppos);
2207 #endif
2208 return 0;
2209 }
2210 if (ntohl(aux->frame_seq_num) != 0 ||
2211 ntohl(aux->logical_blk_num) != 0 ||
2212 aux->partition.partition_num != OS_CONFIG_PARTITION ||
2213 ntohl(aux->partition.first_frame_ppos) != 0 ||
2214 ntohl(aux->partition.last_frame_ppos) != 0xbb7 ) {
2215 #if DEBUG
2216 printk(OSST_DEB_MSG "osst%d:D: Invalid header frame (%d,%d,%d,%d,%d)\n", dev,
2217 ntohl(aux->frame_seq_num), ntohl(aux->logical_blk_num),
2218 aux->partition.partition_num, ntohl(aux->partition.first_frame_ppos),
2219 ntohl(aux->partition.last_frame_ppos));
2220 #endif
2221 return 0;
2222 }
2223 if (strncmp(header->ident_str, "ADR_SEQ", 7) != 0 &&
2224 strncmp(header->ident_str, "ADR-SEQ", 7) != 0) {
2225 strncpy(id_string, header->ident_str, 7);
2226 id_string[7] = 0;
2227 #if DEBUG
2228 printk(OSST_DEB_MSG "osst%d:D: Invalid header identification string %s\n", dev, id_string);
2229 #endif
2230 return 0;
2231 }
2232 update_frame_cntr = ntohl(aux->update_frame_cntr);
2233 if (update_frame_cntr < STp->update_frame_cntr) {
2234 #if DEBUG
2235 printk(OSST_DEB_MSG "osst%d:D: Skipping frame %d with update_frame_counter %d<%d\n",
2236 dev, ppos, update_frame_cntr, STp->update_frame_cntr);
2237 #endif
2238 return 0;
2239 }
2240 if (header->major_rev != 1 || header->minor_rev != 4 ) {
2241 #if DEBUG
2242 printk(OSST_DEB_MSG "osst%d:D: %s revision %d.%d detected (1.4 supported)\n",
2243 dev, (header->major_rev != 1 || header->minor_rev < 2 ||
2244 header->minor_rev > 4 )? "Invalid" : "Warning:",
2245 header->major_rev, header->minor_rev);
2246 #endif
2247 if (header->major_rev != 1 || header->minor_rev < 2 || header->minor_rev > 4)
2248 return 0;
2249 }
2250 #if DEBUG
2251 if (header->pt_par_num != 1)
2252 printk(KERN_INFO "osst%i:W: %d partitions defined, only one supported\n",
2253 dev, header->pt_par_num);
2254 #endif
2255 memcpy(id_string, aux->application_sig, 4);
2256 id_string[4] = 0;
2257 if (memcmp(id_string, "LIN", 3) == 0) {
2258 STp->linux_media = 1;
2259 linux_media_version = id_string[3] - '0';
2260 if (linux_media_version != 4)
2261 printk(KERN_INFO "osst%i:I: Linux media version %d detected (current 4)\n",
2262 dev, linux_media_version);
2263 } else {
2264 printk(KERN_WARNING "osst%i:W: Non Linux media detected (%s)\n", dev, id_string);
2265 return 0;
2266 }
2267 if (linux_media_version < STp->linux_media_version) {
2268 #if DEBUG
2269 printk(OSST_DEB_MSG "osst%d:D: Skipping frame %d with linux_media_version %d\n",
2270 dev, ppos, linux_media_version);
2271 #endif
2272 return 0;
2273 }
2274 if (linux_media_version > STp->linux_media_version) {
2275 #if DEBUG
2276 printk(OSST_DEB_MSG "osst%d:D: Frame %d sets linux_media_version to %d\n",
2277 dev, ppos, linux_media_version);
2278 #endif
2279 memcpy(STp->application_sig, id_string, 5);
2280 STp->linux_media_version = linux_media_version;
2281 STp->update_frame_cntr = -1;
2282 }
2283 if (update_frame_cntr > STp->update_frame_cntr) {
2284 #if DEBUG
2285 printk(OSST_DEB_MSG "osst%d:D: Frame %d sets update_frame_counter to %d\n",
2286 dev, ppos, update_frame_cntr);
2287 #endif
2288 if (STp->header_cache == NULL) {
2289 if ((STp->header_cache = (os_header_t *)vmalloc(sizeof(os_header_t))) == NULL) {
2290 printk(KERN_ERR "osst%i:E: Failed to allocate header cache\n", dev);
2291 return 0;
2292 }
2293 #if DEBUG
2294 printk(OSST_DEB_MSG "osst%d:D: Allocated memory for header cache\n", dev);
2295 #endif
2296 }
2297 osst_copy_from_buffer(STp->buffer, (unsigned char *)STp->header_cache);
2298 header = STp->header_cache; /* further accesses from cached (full) copy */
2299
2300 STp->wrt_pass_cntr = ntohs(header->partition[0].wrt_pass_cntr);
2301 STp->first_data_ppos = ntohl(header->partition[0].first_frame_ppos);
2302 STp->eod_frame_ppos = ntohl(header->partition[0].eod_frame_ppos);
2303 STp->eod_frame_lfa = ntohl(header->ext_track_tb.dat_ext_trk_ey.last_hlb);
2304 STp->filemark_cnt = ntohl(aux->filemark_cnt);
2305 STp->first_mark_ppos = ntohl(aux->next_mark_ppos);
2306 STp->last_mark_ppos = ntohl(aux->last_mark_ppos);
2307 STp->last_mark_lbn = ntohl(aux->last_mark_lbn);
2308 STp->update_frame_cntr = update_frame_cntr;
2309 #if DEBUG
2310 printk(OSST_DEB_MSG "osst%d:D: Detected write pass %d, update frame counter %d, filemark counter %d\n",
2311 dev, STp->wrt_pass_cntr, STp->update_frame_cntr, STp->filemark_cnt);
2312 printk(OSST_DEB_MSG "osst%d:D: first data frame on tape = %d, last = %d, eod frame = %d\n", dev,
2313 STp->first_data_ppos,
2314 ntohl(header->partition[0].last_frame_ppos),
2315 ntohl(header->partition[0].eod_frame_ppos));
2316 printk(OSST_DEB_MSG "osst%d:D: first mark on tape = %d, last = %d, eod frame = %d\n",
2317 dev, STp->first_mark_ppos, STp->last_mark_ppos, STp->eod_frame_ppos);
2318 #endif
2319 if (header->minor_rev < 4 && STp->linux_media_version == 4) {
2320 #if DEBUG
2321 printk(OSST_DEB_MSG "osst%i:D: Moving filemark list to ADR 1.4 location\n", dev);
2322 #endif
2323 memcpy((void *)header->dat_fm_tab.fm_tab_ent,
2324 (void *)header->old_filemark_list, sizeof(header->dat_fm_tab.fm_tab_ent));
2325 memset((void *)header->old_filemark_list, 0, sizeof(header->old_filemark_list));
2326 }
2327 if (header->minor_rev == 4 &&
2328 (header->ext_trk_tb_off != htons(17192) ||
2329 header->partition[0].partition_num != OS_DATA_PARTITION ||
2330 header->partition[0].par_desc_ver != OS_PARTITION_VERSION ||
2331 header->partition[0].last_frame_ppos != htonl(STp->capacity) ||
2332 header->cfg_col_width != htonl(20) ||
2333 header->dat_col_width != htonl(1500) ||
2334 header->qfa_col_width != htonl(0) ||
2335 header->ext_track_tb.nr_stream_part != 1 ||
2336 header->ext_track_tb.et_ent_sz != 32 ||
2337 header->ext_track_tb.dat_ext_trk_ey.et_part_num != OS_DATA_PARTITION ||
2338 header->ext_track_tb.dat_ext_trk_ey.fmt != 1 ||
2339 header->ext_track_tb.dat_ext_trk_ey.fm_tab_off != htons(17736) ||
2340 header->ext_track_tb.dat_ext_trk_ey.last_hlb_hi != 0 ||
2341 header->ext_track_tb.dat_ext_trk_ey.last_pp != htonl(STp->eod_frame_ppos) ||
2342 header->dat_fm_tab.fm_part_num != OS_DATA_PARTITION ||
2343 header->dat_fm_tab.fm_tab_ent_sz != 4 ||
2344 header->dat_fm_tab.fm_tab_ent_cnt !=
2345 htons(STp->filemark_cnt<OS_FM_TAB_MAX?STp->filemark_cnt:OS_FM_TAB_MAX)))
2346 printk(KERN_WARNING "osst%i:W: Failed consistency check ADR 1.4 format\n", dev);
2347
2348 }
2349
2350 return 1;
2351 }
2352
osst_analyze_headers(OS_Scsi_Tape * STp,Scsi_Request ** aSRpnt)2353 static int osst_analyze_headers(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
2354 {
2355 int position, ppos;
2356 int first, last;
2357 int valid = 0;
2358 int dev = TAPE_NR(STp->devt);
2359
2360 position = osst_get_frame_position(STp, aSRpnt);
2361
2362 if (STp->raw) {
2363 STp->header_ok = STp->linux_media = 1;
2364 STp->linux_media_version = 0;
2365 return 1;
2366 }
2367 STp->header_ok = STp->linux_media = STp->linux_media_version = 0;
2368 STp->wrt_pass_cntr = STp->update_frame_cntr = -1;
2369 STp->eod_frame_ppos = STp->first_data_ppos = -1;
2370 STp->first_mark_ppos = STp->last_mark_ppos = STp->last_mark_lbn = -1;
2371 #if DEBUG
2372 printk(OSST_DEB_MSG "osst%d:D: Reading header\n", dev);
2373 #endif
2374
2375 /* optimization for speed - if we are positioned at ppos 10, read second group first */
2376 /* TODO try the ADR 1.1 locations for the second group if we have no valid one yet... */
2377
2378 first = position==10?0xbae: 5;
2379 last = position==10?0xbb3:10;
2380
2381 for (ppos = first; ppos < last; ppos++)
2382 if (__osst_analyze_headers(STp, aSRpnt, ppos))
2383 valid = 1;
2384
2385 first = position==10? 5:0xbae;
2386 last = position==10?10:0xbb3;
2387
2388 for (ppos = first; ppos < last; ppos++)
2389 if (__osst_analyze_headers(STp, aSRpnt, ppos))
2390 valid = 1;
2391
2392 if (!valid) {
2393 printk(KERN_ERR "osst%i:E: Failed to find valid ADRL header, new media?\n", dev);
2394 STp->eod_frame_ppos = STp->first_data_ppos = 0;
2395 osst_set_frame_position(STp, aSRpnt, 10, 0);
2396 return 0;
2397 }
2398 if (position <= STp->first_data_ppos) {
2399 position = STp->first_data_ppos;
2400 STp->ps[0].drv_file = STp->ps[0].drv_block = STp->frame_seq_number = STp->logical_blk_num = 0;
2401 }
2402 osst_set_frame_position(STp, aSRpnt, position, 0);
2403 STp->header_ok = 1;
2404
2405 return 1;
2406 }
2407
osst_verify_position(OS_Scsi_Tape * STp,Scsi_Request ** aSRpnt)2408 static int osst_verify_position(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
2409 {
2410 int write_pass = STp->wrt_pass_cntr;
2411 int frame_position = STp->first_frame_position;
2412 int frame_seq_numbr = STp->frame_seq_number;
2413 int logical_blk_num = STp->logical_blk_num;
2414 int halfway_frame = STp->frame_in_buffer;
2415 int read_pointer = STp->buffer->read_pointer;
2416 int prev_mark_ppos = -1;
2417 int actual_mark_ppos, i, n;
2418 #if DEBUG
2419 int dev = TAPE_NR(STp->devt);
2420
2421 printk(OSST_DEB_MSG "osst%d:D: Verify that the tape is really the one we think before writing\n", dev);
2422 #endif
2423 if (frame_position <= STp->first_data_ppos) {
2424 /* check header match */
2425 if (!osst_analyze_headers(STp, aSRpnt) ||
2426 (write_pass != STp->wrt_pass_cntr)) {
2427 #if DEBUG
2428 printk(OSST_DEB_MSG "osst%d:D: Couldn't match header in verify_position\n", dev);
2429 #endif
2430 return (-EIO);
2431 }
2432 } else {
2433 /* find preceding data frame of current write pass */
2434 osst_set_frame_position(STp, aSRpnt, frame_position - 1, 0);
2435 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2436 #if DEBUG
2437 printk(OSST_DEB_MSG "osst%d:D: Couldn't get logical blk num in verify_position\n", dev);
2438 #endif
2439 return (-EIO);
2440 }
2441 }
2442 if (STp->linux_media_version >= 4) {
2443 for (i=0; i<STp->filemark_cnt; i++)
2444 if ((n=ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[i])) < frame_position)
2445 prev_mark_ppos = n;
2446 } else
2447 prev_mark_ppos = frame_position - 1; /* usually - we don't really know */
2448 actual_mark_ppos = STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER ?
2449 frame_position - 1 : ntohl(STp->buffer->aux->last_mark_ppos);
2450 if (frame_position != STp->first_frame_position ||
2451 frame_seq_numbr != STp->frame_seq_number + (halfway_frame?0:1) ||
2452 prev_mark_ppos != actual_mark_ppos ) {
2453 #if DEBUG
2454 printk(OSST_DEB_MSG "osst%d:D: Block mismatch: fppos %d-%d, fseq %d-%d, mark %d-%d\n", dev,
2455 STp->first_frame_position, frame_position,
2456 STp->frame_seq_number + (halfway_frame?0:1),
2457 frame_seq_numbr, actual_mark_ppos, prev_mark_ppos);
2458 #endif
2459 return (-EIO);
2460 }
2461 if (halfway_frame) {
2462 /* prepare buffer for append and rewrite on top of original */
2463 osst_set_frame_position(STp, aSRpnt, frame_position - 1, 0);
2464 STp->buffer->buffer_bytes = read_pointer;
2465 STp->ps[STp->partition].rw = ST_WRITING;
2466 STp->dirty = 1;
2467 }
2468 STp->frame_in_buffer = halfway_frame;
2469 STp->frame_seq_number = frame_seq_numbr;
2470 STp->logical_blk_num = logical_blk_num;
2471 return 0;
2472 }
2473
2474 /* Acc. to OnStream, the vers. numbering is the following:
2475 * X.XX for released versions (X=digit),
2476 * XXXY for unreleased versions (Y=letter)
2477 * Ordering 1.05 < 106A < 106B < ... < 106a < ... < 1.06
2478 * This fn makes monoton numbers out of this scheme ...
2479 */
osst_parse_firmware_rev(const char * str)2480 static unsigned int osst_parse_firmware_rev (const char * str)
2481 {
2482 if (str[1] == '.') {
2483 return (str[0]-'0')*10000
2484 +(str[2]-'0')*1000
2485 +(str[3]-'0')*100;
2486 } else {
2487 return (str[0]-'0')*10000
2488 +(str[1]-'0')*1000
2489 +(str[2]-'0')*100 - 100
2490 +(str[3]-'@');
2491 }
2492 }
2493
2494 /*
2495 * Configure the OnStream SCII tape drive for default operation
2496 */
osst_configure_onstream(OS_Scsi_Tape * STp,Scsi_Request ** aSRpnt)2497 static int osst_configure_onstream(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt)
2498 {
2499 unsigned char cmd[MAX_COMMAND_SIZE];
2500 int dev = TAPE_NR(STp->devt);
2501 Scsi_Request * SRpnt = * aSRpnt;
2502 osst_mode_parameter_header_t * header;
2503 osst_block_size_page_t * bs;
2504 osst_capabilities_page_t * cp;
2505 osst_tape_paramtr_page_t * prm;
2506 int drive_buffer_size;
2507
2508 if (STp->ready != ST_READY) {
2509 #if DEBUG
2510 printk(OSST_DEB_MSG "osst%d:D: Not Ready\n", dev);
2511 #endif
2512 return (-EIO);
2513 }
2514
2515 if (STp->os_fw_rev < 10600) {
2516 printk(KERN_INFO "osst%i:I: Old OnStream firmware revision detected (%s),\n", dev, STp->device->rev);
2517 printk(KERN_INFO "osst%d:I: an upgrade to version 1.06 or above is recommended\n", dev);
2518 }
2519
2520 /*
2521 * Configure 32.5KB (data+aux) frame size.
2522 * Get the current frame size from the block size mode page
2523 */
2524 memset(cmd, 0, MAX_COMMAND_SIZE);
2525 cmd[0] = MODE_SENSE;
2526 cmd[1] = 8;
2527 cmd[2] = BLOCK_SIZE_PAGE;
2528 cmd[4] = BLOCK_SIZE_PAGE_LENGTH + MODE_HEADER_LENGTH;
2529
2530 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_READ, STp->timeout, 0, TRUE);
2531 if (SRpnt == NULL) {
2532 #if DEBUG
2533 printk(OSST_DEB_MSG "osst :D: Busy\n");
2534 #endif
2535 return (-EBUSY);
2536 }
2537 *aSRpnt = SRpnt;
2538 if ((STp->buffer)->syscall_result != 0) {
2539 printk (KERN_ERR "osst%i:E: Can't get tape block size mode page\n", dev);
2540 return (-EIO);
2541 }
2542
2543 header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2544 bs = (osst_block_size_page_t *) ((STp->buffer)->b_data + sizeof(osst_mode_parameter_header_t) + header->bdl);
2545
2546 #if DEBUG
2547 printk(OSST_DEB_MSG "osst%d:D: 32KB play back: %s\n", dev, bs->play32 ? "Yes" : "No");
2548 printk(OSST_DEB_MSG "osst%d:D: 32.5KB play back: %s\n", dev, bs->play32_5 ? "Yes" : "No");
2549 printk(OSST_DEB_MSG "osst%d:D: 32KB record: %s\n", dev, bs->record32 ? "Yes" : "No");
2550 printk(OSST_DEB_MSG "osst%d:D: 32.5KB record: %s\n", dev, bs->record32_5 ? "Yes" : "No");
2551 #endif
2552
2553 /*
2554 * Configure default auto columns mode, 32.5KB transfer mode
2555 */
2556 bs->one = 1;
2557 bs->play32 = 0;
2558 bs->play32_5 = 1;
2559 bs->record32 = 0;
2560 bs->record32_5 = 1;
2561
2562 memset(cmd, 0, MAX_COMMAND_SIZE);
2563 cmd[0] = MODE_SELECT;
2564 cmd[1] = 0x10;
2565 cmd[4] = BLOCK_SIZE_PAGE_LENGTH + MODE_HEADER_LENGTH;
2566
2567 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_WRITE, STp->timeout, 0, TRUE);
2568 *aSRpnt = SRpnt;
2569 if ((STp->buffer)->syscall_result != 0) {
2570 printk (KERN_ERR "osst%i:E: Couldn't set tape block size mode page\n", dev);
2571 return (-EIO);
2572 }
2573
2574 #if DEBUG
2575 printk(KERN_INFO "osst%d:D: Drive Block Size changed to 32.5K\n", dev);
2576 /*
2577 * In debug mode, we want to see as many errors as possible
2578 * to test the error recovery mechanism.
2579 */
2580 osst_set_retries(STp, aSRpnt, 0);
2581 SRpnt = * aSRpnt;
2582 #endif
2583
2584 /*
2585 * Set vendor name to 'LIN4' for "Linux support version 4".
2586 */
2587
2588 memset(cmd, 0, MAX_COMMAND_SIZE);
2589 cmd[0] = MODE_SELECT;
2590 cmd[1] = 0x10;
2591 cmd[4] = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH;
2592
2593 header->mode_data_length = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH - 1;
2594 header->medium_type = 0; /* Medium Type - ignoring */
2595 header->dsp = 0; /* Reserved */
2596 header->bdl = 0; /* Block Descriptor Length */
2597
2598 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = VENDOR_IDENT_PAGE | (1 << 7);
2599 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 6;
2600 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 'L';
2601 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = 'I';
2602 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 4] = 'N';
2603 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 5] = '4';
2604 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 6] = 0;
2605 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 7] = 0;
2606
2607 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_WRITE, STp->timeout, 0, TRUE);
2608 *aSRpnt = SRpnt;
2609
2610 if ((STp->buffer)->syscall_result != 0) {
2611 printk (KERN_ERR "osst%i:E: Couldn't set vendor name to %s\n", dev,
2612 (char *) ((STp->buffer)->b_data + MODE_HEADER_LENGTH + 2));
2613 return (-EIO);
2614 }
2615
2616 memset(cmd, 0, MAX_COMMAND_SIZE);
2617 cmd[0] = MODE_SENSE;
2618 cmd[1] = 8;
2619 cmd[2] = CAPABILITIES_PAGE;
2620 cmd[4] = CAPABILITIES_PAGE_LENGTH + MODE_HEADER_LENGTH;
2621
2622 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_READ, STp->timeout, 0, TRUE);
2623 *aSRpnt = SRpnt;
2624
2625 if ((STp->buffer)->syscall_result != 0) {
2626 printk (KERN_ERR "osst%i:E: Can't get capabilities page\n", dev);
2627 return (-EIO);
2628 }
2629
2630 header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2631 cp = (osst_capabilities_page_t *) ((STp->buffer)->b_data +
2632 sizeof(osst_mode_parameter_header_t) + header->bdl);
2633
2634 drive_buffer_size = ntohs(cp->buffer_size) / 2;
2635
2636 memset(cmd, 0, MAX_COMMAND_SIZE);
2637 cmd[0] = MODE_SENSE;
2638 cmd[1] = 8;
2639 cmd[2] = TAPE_PARAMTR_PAGE;
2640 cmd[4] = TAPE_PARAMTR_PAGE_LENGTH + MODE_HEADER_LENGTH;
2641
2642 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_READ, STp->timeout, 0, TRUE);
2643 *aSRpnt = SRpnt;
2644
2645 if ((STp->buffer)->syscall_result != 0) {
2646 printk (KERN_ERR "osst%i:E: Can't get tape parameter page\n", dev);
2647 return (-EIO);
2648 }
2649
2650 header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2651 prm = (osst_tape_paramtr_page_t *) ((STp->buffer)->b_data +
2652 sizeof(osst_mode_parameter_header_t) + header->bdl);
2653
2654 STp->density = prm->density;
2655 STp->capacity = ntohs(prm->segtrk) * ntohs(prm->trks);
2656 #if DEBUG
2657 printk(OSST_DEB_MSG "osst%d:D: Density %d, tape length: %dMB, drive buffer size: %dKB\n",
2658 dev, STp->density, STp->capacity / 32, drive_buffer_size);
2659 #endif
2660
2661 return 0;
2662
2663 }
2664
2665
2666 /* Step over EOF if it has been inadvertently crossed (ioctl not used because
2667 it messes up the block number). */
cross_eof(OS_Scsi_Tape * STp,Scsi_Request ** aSRpnt,int forward)2668 static int cross_eof(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, int forward)
2669 {
2670 int result;
2671 int dev = TAPE_NR(STp->devt);
2672
2673 #if DEBUG
2674 if (debugging)
2675 printk(OSST_DEB_MSG "osst%d:D: Stepping over filemark %s.\n",
2676 dev, forward ? "forward" : "backward");
2677 #endif
2678
2679 if (forward) {
2680 /* assumes that the filemark is already read by the drive, so this is low cost */
2681 result = osst_space_over_filemarks_forward_slow(STp, aSRpnt, MTFSF, 1);
2682 }
2683 else
2684 /* assumes this is only called if we just read the filemark! */
2685 result = osst_seek_logical_blk(STp, aSRpnt, STp->logical_blk_num - 1);
2686
2687 if (result < 0)
2688 printk(KERN_WARNING "osst%d:W: Stepping over filemark %s failed.\n",
2689 dev, forward ? "forward" : "backward");
2690
2691 return result;
2692 }
2693
2694
2695 /* Get the tape position. */
2696
osst_get_frame_position(OS_Scsi_Tape * STp,Scsi_Request ** aSRpnt)2697 static int osst_get_frame_position(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt)
2698 {
2699 unsigned char scmd[MAX_COMMAND_SIZE];
2700 Scsi_Request * SRpnt;
2701 int result = 0;
2702
2703 /* KG: We want to be able to use it for checking Write Buffer availability
2704 * and thus don't want to risk to overwrite anything. Exchange buffers ... */
2705 char mybuf[24];
2706 char * olddata = STp->buffer->b_data;
2707 int oldsize = STp->buffer->buffer_size;
2708 int dev = TAPE_NR(STp->devt);
2709
2710 if (STp->ready != ST_READY) return (-EIO);
2711
2712 memset (scmd, 0, MAX_COMMAND_SIZE);
2713 scmd[0] = READ_POSITION;
2714
2715 STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
2716 SRpnt = osst_do_scsi(*aSRpnt, STp, scmd, 20, SCSI_DATA_READ,
2717 STp->timeout, MAX_RETRIES, TRUE);
2718 if (!SRpnt) {
2719 STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
2720 return (-EBUSY);
2721 }
2722 *aSRpnt = SRpnt;
2723
2724 if (STp->buffer->syscall_result)
2725 result = ((SRpnt->sr_sense_buffer[2] & 0x0f) == 3) ? -EIO : -EINVAL;
2726
2727 if (result == -EINVAL)
2728 printk(KERN_ERR "osst%d:E: Can't read tape position.\n", dev);
2729 else {
2730
2731 if (result == -EIO) { /* re-read position */
2732 unsigned char mysense[16];
2733 memcpy (mysense, SRpnt->sr_sense_buffer, 16);
2734 memset (scmd, 0, MAX_COMMAND_SIZE);
2735 scmd[0] = READ_POSITION;
2736 STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
2737 SRpnt = osst_do_scsi(SRpnt, STp, scmd, 20, SCSI_DATA_READ,
2738 STp->timeout, MAX_RETRIES, TRUE);
2739 if (!STp->buffer->syscall_result)
2740 memcpy (SRpnt->sr_sense_buffer, mysense, 16);
2741 }
2742 STp->first_frame_position = ((STp->buffer)->b_data[4] << 24)
2743 + ((STp->buffer)->b_data[5] << 16)
2744 + ((STp->buffer)->b_data[6] << 8)
2745 + (STp->buffer)->b_data[7];
2746 STp->last_frame_position = ((STp->buffer)->b_data[ 8] << 24)
2747 + ((STp->buffer)->b_data[ 9] << 16)
2748 + ((STp->buffer)->b_data[10] << 8)
2749 + (STp->buffer)->b_data[11];
2750 STp->cur_frames = (STp->buffer)->b_data[15];
2751 #if DEBUG
2752 if (debugging) {
2753 printk(OSST_DEB_MSG "osst%d:D: Drive Positions: host %d, tape %d%s, buffer %d\n", dev,
2754 STp->first_frame_position, STp->last_frame_position,
2755 ((STp->buffer)->b_data[0]&0x80)?" (BOP)":
2756 ((STp->buffer)->b_data[0]&0x40)?" (EOP)":"",
2757 STp->cur_frames);
2758 }
2759 #endif
2760 if (STp->cur_frames == 0 && STp->first_frame_position != STp->last_frame_position) {
2761 #if DEBUG
2762 printk(KERN_WARNING "osst%d:D: Correcting read position %d, %d, %d\n", dev,
2763 STp->first_frame_position, STp->last_frame_position, STp->cur_frames);
2764 #endif
2765 STp->first_frame_position = STp->last_frame_position;
2766 }
2767 }
2768 STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
2769
2770 return (result == 0 ? STp->first_frame_position : result);
2771 }
2772
2773
2774 /* Set the tape block */
osst_set_frame_position(OS_Scsi_Tape * STp,Scsi_Request ** aSRpnt,int ppos,int skip)2775 static int osst_set_frame_position(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, int ppos, int skip)
2776 {
2777 unsigned char scmd[MAX_COMMAND_SIZE];
2778 Scsi_Request * SRpnt;
2779 ST_partstat * STps;
2780 int result = 0;
2781 int pp = (ppos == 3000 && !skip)? 0 : ppos;
2782 int dev = TAPE_NR(STp->devt);
2783
2784 if (STp->ready != ST_READY) return (-EIO);
2785
2786 STps = &(STp->ps[STp->partition]);
2787
2788 if (ppos < 0 || ppos > STp->capacity) {
2789 printk(KERN_WARNING "osst%d:W: Reposition request %d out of range\n", dev, ppos);
2790 pp = ppos = ppos < 0 ? 0 : (STp->capacity - 1);
2791 result = (-EINVAL);
2792 }
2793
2794 do {
2795 #if DEBUG
2796 if (debugging)
2797 printk(OSST_DEB_MSG "osst%d:D: Setting ppos to %d.\n", dev, pp);
2798 #endif
2799 memset (scmd, 0, MAX_COMMAND_SIZE);
2800 scmd[0] = SEEK_10;
2801 scmd[1] = 1;
2802 scmd[3] = (pp >> 24);
2803 scmd[4] = (pp >> 16);
2804 scmd[5] = (pp >> 8);
2805 scmd[6] = pp;
2806 if (skip)
2807 scmd[9] = 0x80;
2808
2809 SRpnt = osst_do_scsi(*aSRpnt, STp, scmd, 0, SCSI_DATA_NONE, STp->long_timeout,
2810 MAX_RETRIES, TRUE);
2811 if (!SRpnt)
2812 return (-EBUSY);
2813 *aSRpnt = SRpnt;
2814
2815 if ((STp->buffer)->syscall_result != 0) {
2816 #if DEBUG
2817 printk(OSST_DEB_MSG "osst%d:D: SEEK command from %d to %d failed.\n",
2818 dev, STp->first_frame_position, pp);
2819 #endif
2820 result = (-EIO);
2821 }
2822 if (pp != ppos)
2823 osst_wait_ready(STp, aSRpnt, 5 * 60, OSST_WAIT_POSITION_COMPLETE);
2824 } while ((pp != ppos) && (pp = ppos));
2825 STp->first_frame_position = STp->last_frame_position = ppos;
2826 STps->eof = ST_NOEOF;
2827 STps->at_sm = 0;
2828 STps->rw = ST_IDLE;
2829 STp->frame_in_buffer = 0;
2830 return result;
2831 }
2832
osst_write_trailer(OS_Scsi_Tape * STp,Scsi_Request ** aSRpnt,int leave_at_EOT)2833 static int osst_write_trailer(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, int leave_at_EOT)
2834 {
2835 ST_partstat * STps = &(STp->ps[STp->partition]);
2836 int result = 0;
2837
2838 if (STp->write_type != OS_WRITE_NEW_MARK) {
2839 /* true unless the user wrote the filemark for us */
2840 result = osst_flush_drive_buffer(STp, aSRpnt);
2841 if (result < 0) goto out;
2842 result = osst_write_filemark(STp, aSRpnt);
2843 if (result < 0) goto out;
2844
2845 if (STps->drv_file >= 0)
2846 STps->drv_file++ ;
2847 STps->drv_block = 0;
2848 }
2849 result = osst_write_eod(STp, aSRpnt);
2850 osst_write_header(STp, aSRpnt, leave_at_EOT);
2851
2852 STps->eof = ST_FM;
2853 out:
2854 return result;
2855 }
2856
2857 /* osst versions of st functions - augmented and stripped to suit OnStream only */
2858
2859 /* Flush the write buffer (never need to write if variable blocksize). */
osst_flush_write_buffer(OS_Scsi_Tape * STp,Scsi_Request ** aSRpnt)2860 static int osst_flush_write_buffer(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt)
2861 {
2862 int offset, transfer, blks = 0;
2863 int result = 0;
2864 unsigned char cmd[MAX_COMMAND_SIZE];
2865 Scsi_Request * SRpnt = *aSRpnt;
2866 ST_partstat * STps;
2867 int dev = TAPE_NR(STp->devt);
2868
2869 if ((STp->buffer)->writing) {
2870 if (SRpnt == (STp->buffer)->last_SRpnt)
2871 #if DEBUG
2872 { printk(OSST_DEB_MSG
2873 "osst%d:D: aSRpnt points to Scsi_Request that write_behind_check will release -- cleared\n", dev);
2874 #endif
2875 *aSRpnt = SRpnt = NULL;
2876 #if DEBUG
2877 } else if (SRpnt)
2878 printk(OSST_DEB_MSG
2879 "osst%d:D: aSRpnt does not point to Scsi_Request that write_behind_check will release -- strange\n", dev);
2880 #endif
2881 osst_write_behind_check(STp);
2882 if ((STp->buffer)->syscall_result) {
2883 #if DEBUG
2884 if (debugging)
2885 printk(OSST_DEB_MSG "osst%d:D: Async write error (flush) %x.\n",
2886 dev, (STp->buffer)->midlevel_result);
2887 #endif
2888 if ((STp->buffer)->midlevel_result == INT_MAX)
2889 return (-ENOSPC);
2890 return (-EIO);
2891 }
2892 }
2893
2894 result = 0;
2895 if (STp->dirty == 1) {
2896
2897 STp->write_count++;
2898 STps = &(STp->ps[STp->partition]);
2899 STps->rw = ST_WRITING;
2900 offset = STp->buffer->buffer_bytes;
2901 blks = (offset + STp->block_size - 1) / STp->block_size;
2902 transfer = OS_FRAME_SIZE;
2903
2904 if (offset < OS_DATA_SIZE)
2905 osst_zero_buffer_tail(STp->buffer);
2906
2907 /* TODO: Error handling! */
2908 if (STp->poll)
2909 result = osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -50, 120);
2910
2911 memset(cmd, 0, MAX_COMMAND_SIZE);
2912 cmd[0] = WRITE_6;
2913 cmd[1] = 1;
2914 cmd[4] = 1;
2915
2916 switch (STp->write_type) {
2917 case OS_WRITE_DATA:
2918 #if DEBUG
2919 if (debugging)
2920 printk(OSST_DEB_MSG "osst%d:D: Writing %d blocks to frame %d, lblks %d-%d\n",
2921 dev, blks, STp->frame_seq_number,
2922 STp->logical_blk_num - blks, STp->logical_blk_num - 1);
2923 #endif
2924 osst_init_aux(STp, OS_FRAME_TYPE_DATA, STp->frame_seq_number++,
2925 STp->logical_blk_num - blks, STp->block_size, blks);
2926 break;
2927 case OS_WRITE_EOD:
2928 osst_init_aux(STp, OS_FRAME_TYPE_EOD, STp->frame_seq_number++,
2929 STp->logical_blk_num, 0, 0);
2930 break;
2931 case OS_WRITE_NEW_MARK:
2932 osst_init_aux(STp, OS_FRAME_TYPE_MARKER, STp->frame_seq_number++,
2933 STp->logical_blk_num++, 0, blks=1);
2934 break;
2935 case OS_WRITE_HEADER:
2936 osst_init_aux(STp, OS_FRAME_TYPE_HEADER, 0, 0, 0, blks=0);
2937 break;
2938 default: /* probably FILLER */
2939 osst_init_aux(STp, OS_FRAME_TYPE_FILL, 0, 0, 0, 0);
2940 }
2941 #if DEBUG
2942 if (debugging)
2943 printk(OSST_DEB_MSG "osst%d:D: Flushing %d bytes, Transfering %d bytes in %d lblocks.\n",
2944 dev, offset, transfer, blks);
2945 #endif
2946
2947 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, transfer, SCSI_DATA_WRITE,
2948 STp->timeout, MAX_WRITE_RETRIES, TRUE);
2949 *aSRpnt = SRpnt;
2950 if (!SRpnt)
2951 return (-EBUSY);
2952
2953 if ((STp->buffer)->syscall_result != 0) {
2954 #if DEBUG
2955 printk(OSST_DEB_MSG
2956 "osst%d:D: write sense [0]=0x%02x [2]=%02x [12]=%02x [13]=%02x\n",
2957 dev, SRpnt->sr_sense_buffer[0], SRpnt->sr_sense_buffer[2],
2958 SRpnt->sr_sense_buffer[12], SRpnt->sr_sense_buffer[13]);
2959 #endif
2960 if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
2961 (SRpnt->sr_sense_buffer[2] & 0x40) && /* FIXME - SC-30 drive doesn't assert EOM bit */
2962 (SRpnt->sr_sense_buffer[2] & 0x0f) == NO_SENSE) {
2963 STp->dirty = 0;
2964 (STp->buffer)->buffer_bytes = 0;
2965 result = (-ENOSPC);
2966 }
2967 else {
2968 if (osst_write_error_recovery(STp, aSRpnt, 1)) {
2969 printk(KERN_ERR "osst%d:E: Error on flush write.\n", dev);
2970 result = (-EIO);
2971 }
2972 }
2973 STps->drv_block = (-1); /* FIXME - even if write recovery succeeds? */
2974 }
2975 else {
2976 STp->first_frame_position++;
2977 STp->dirty = 0;
2978 (STp->buffer)->buffer_bytes = 0;
2979 }
2980 }
2981 #if DEBUG
2982 printk(OSST_DEB_MSG "osst%d:D: Exit flush write buffer with code %d\n", dev, result);
2983 #endif
2984 return result;
2985 }
2986
2987
2988 /* Flush the tape buffer. The tape will be positioned correctly unless
2989 seek_next is true. */
osst_flush_buffer(OS_Scsi_Tape * STp,Scsi_Request ** aSRpnt,int seek_next)2990 static int osst_flush_buffer(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int seek_next)
2991 {
2992 ST_partstat * STps;
2993 int backspace = 0, result = 0;
2994 #if DEBUG
2995 int dev = TAPE_NR(STp->devt);
2996 #endif
2997
2998 /*
2999 * If there was a bus reset, block further access
3000 * to this device.
3001 */
3002 if( STp->device->was_reset )
3003 return (-EIO);
3004
3005 if (STp->ready != ST_READY)
3006 return 0;
3007
3008 STps = &(STp->ps[STp->partition]);
3009 if (STps->rw == ST_WRITING || STp->dirty) { /* Writing */
3010 STp->write_type = OS_WRITE_DATA;
3011 return osst_flush_write_buffer(STp, aSRpnt);
3012 }
3013 if (STp->block_size == 0)
3014 return 0;
3015
3016 #if DEBUG
3017 printk(OSST_DEB_MSG "osst%d:D: Reached flush (read) buffer\n", dev);
3018 #endif
3019
3020 if (!STp->can_bsr) {
3021 backspace = ((STp->buffer)->buffer_bytes + (STp->buffer)->read_pointer) / STp->block_size -
3022 ((STp->buffer)->read_pointer + STp->block_size - 1 ) / STp->block_size ;
3023 (STp->buffer)->buffer_bytes = 0;
3024 (STp->buffer)->read_pointer = 0;
3025 STp->frame_in_buffer = 0; /* FIXME is this relevant w. OSST? */
3026 }
3027
3028 if (!seek_next) {
3029 if (STps->eof == ST_FM_HIT) {
3030 result = cross_eof(STp, aSRpnt, FALSE); /* Back over the EOF hit */
3031 if (!result)
3032 STps->eof = ST_NOEOF;
3033 else {
3034 if (STps->drv_file >= 0)
3035 STps->drv_file++;
3036 STps->drv_block = 0;
3037 }
3038 }
3039 if (!result && backspace > 0) /* TODO -- design and run a test case for this */
3040 result = osst_seek_logical_blk(STp, aSRpnt, STp->logical_blk_num - backspace);
3041 }
3042 else if (STps->eof == ST_FM_HIT) {
3043 if (STps->drv_file >= 0)
3044 STps->drv_file++;
3045 STps->drv_block = 0;
3046 STps->eof = ST_NOEOF;
3047 }
3048
3049 return result;
3050 }
3051
osst_write_frame(OS_Scsi_Tape * STp,Scsi_Request ** aSRpnt,int synchronous)3052 static int osst_write_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int synchronous)
3053 {
3054 unsigned char cmd[MAX_COMMAND_SIZE];
3055 Scsi_Request * SRpnt;
3056 int blks;
3057 #if DEBUG
3058 int dev = TAPE_NR(STp->devt);
3059 #endif
3060
3061 if ((!STp-> raw) && (STp->first_frame_position == 0xbae)) { /* _must_ preserve buffer! */
3062 #if DEBUG
3063 printk(OSST_DEB_MSG "osst%d:D: Reaching config partition.\n", dev);
3064 #endif
3065 if (osst_flush_drive_buffer(STp, aSRpnt) < 0) {
3066 return (-EIO);
3067 }
3068 /* error recovery may have bumped us past the header partition */
3069 if (osst_get_frame_position(STp, aSRpnt) < 0xbb8) {
3070 #if DEBUG
3071 printk(OSST_DEB_MSG "osst%d:D: Skipping over config partition.\n", dev);
3072 #endif
3073 osst_position_tape_and_confirm(STp, aSRpnt, 0xbb8);
3074 }
3075 }
3076
3077 if (STp->poll)
3078 osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -50, 60);
3079 /* TODO: Check for an error ! */
3080
3081 // osst_build_stats(STp, &SRpnt);
3082
3083 STp->ps[STp->partition].rw = ST_WRITING;
3084 STp->write_type = OS_WRITE_DATA;
3085
3086 memset(cmd, 0, MAX_COMMAND_SIZE);
3087 cmd[0] = WRITE_6;
3088 cmd[1] = 1;
3089 cmd[4] = 1; /* one frame at a time... */
3090 blks = STp->buffer->buffer_bytes / STp->block_size;
3091 #if DEBUG
3092 if (debugging)
3093 printk(OSST_DEB_MSG "osst%d:D: Writing %d blocks to frame %d, lblks %d-%d\n", dev, blks,
3094 STp->frame_seq_number, STp->logical_blk_num - blks, STp->logical_blk_num - 1);
3095 #endif
3096 osst_init_aux(STp, OS_FRAME_TYPE_DATA, STp->frame_seq_number++,
3097 STp->logical_blk_num - blks, STp->block_size, blks);
3098
3099 #if DEBUG
3100 if (!synchronous)
3101 STp->write_pending = 1;
3102 #endif
3103 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_WRITE, STp->timeout,
3104 MAX_WRITE_RETRIES, synchronous);
3105 if (!SRpnt)
3106 return (-EBUSY);
3107 *aSRpnt = SRpnt;
3108
3109 if (synchronous) {
3110 if (STp->buffer->syscall_result != 0) {
3111 #if DEBUG
3112 if (debugging)
3113 printk(OSST_DEB_MSG "osst%d:D: Error on write:\n", dev);
3114 #endif
3115 if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
3116 (SRpnt->sr_sense_buffer[2] & 0x40)) {
3117 if ((SRpnt->sr_sense_buffer[2] & 0x0f) == VOLUME_OVERFLOW)
3118 return (-ENOSPC);
3119 }
3120 else {
3121 if (osst_write_error_recovery(STp, aSRpnt, 1))
3122 return (-EIO);
3123 }
3124 }
3125 else
3126 STp->first_frame_position++;
3127 }
3128
3129 STp->write_count++;
3130
3131 return 0;
3132 }
3133
3134
3135 /* Entry points to osst */
3136
3137 /* Write command */
osst_write(struct file * filp,const char * buf,size_t count,loff_t * ppos)3138 static ssize_t osst_write(struct file * filp, const char * buf, size_t count, loff_t *ppos)
3139 {
3140 struct inode *inode = filp->f_dentry->d_inode;
3141 ssize_t total, retval = 0;
3142 ssize_t i, do_count, blks, transfer;
3143 int write_threshold;
3144 int doing_write = 0;
3145 const char *b_point;
3146 Scsi_Request * SRpnt = NULL;
3147 OS_Scsi_Tape * STp;
3148 ST_mode * STm;
3149 ST_partstat * STps;
3150 int dev = TAPE_NR(inode->i_rdev);
3151 loff_t pos = *ppos;
3152
3153 STp = os_scsi_tapes[dev];
3154
3155 if (down_interruptible(&STp->lock))
3156 return (-ERESTARTSYS);
3157
3158 /*
3159 * If we are in the middle of error recovery, don't let anyone
3160 * else try and use this device. Also, if error recovery fails, it
3161 * may try and take the device offline, in which case all further
3162 * access to the device is prohibited.
3163 */
3164 if( !scsi_block_when_processing_errors(STp->device) ) {
3165 retval = (-ENXIO);
3166 goto out;
3167 }
3168
3169 if (ppos != &filp->f_pos) {
3170 /* "A request was outside the capabilities of the device." */
3171 retval = (-ENXIO);
3172 goto out;
3173 }
3174
3175 if (STp->ready != ST_READY) {
3176 if (STp->ready == ST_NO_TAPE)
3177 retval = (-ENOMEDIUM);
3178 else
3179 retval = (-EIO);
3180 goto out;
3181 }
3182 STm = &(STp->modes[STp->current_mode]);
3183 if (!STm->defined) {
3184 retval = (-ENXIO);
3185 goto out;
3186 }
3187 if (count == 0)
3188 goto out;
3189
3190 /*
3191 * If there was a bus reset, block further access
3192 * to this device.
3193 */
3194 if (STp->device->was_reset) {
3195 retval = (-EIO);
3196 goto out;
3197 }
3198
3199 #if DEBUG
3200 if (!STp->in_use) {
3201 printk(OSST_DEB_MSG "osst%d:D: Incorrect device.\n", dev);
3202 retval = (-EIO);
3203 goto out;
3204 }
3205 #endif
3206
3207 if (STp->write_prot) {
3208 retval = (-EACCES);
3209 goto out;
3210 }
3211
3212 /* Write must be integral number of blocks */
3213 if (STp->block_size != 0 && (count % STp->block_size) != 0) {
3214 printk(KERN_ERR "osst%d:E: Write (%ld bytes) not multiple of tape block size (%d%c).\n",
3215 dev, (unsigned long)count, STp->block_size<1024?
3216 STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k');
3217 retval = (-EINVAL);
3218 goto out;
3219 }
3220
3221 if (STp->first_frame_position >= STp->capacity - OSST_EOM_RESERVE) {
3222 printk(KERN_ERR "osst%d:E: Write truncated at EOM early warning (frame %d).\n",
3223 dev, STp->first_frame_position);
3224 retval = (-ENOSPC);
3225 goto out;
3226 }
3227
3228 STps = &(STp->ps[STp->partition]);
3229
3230 if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED &&
3231 !osst_int_ioctl(STp, &SRpnt, MTLOCK, 0))
3232 STp->door_locked = ST_LOCKED_AUTO;
3233
3234
3235 if (STps->rw == ST_READING) {
3236 #if DEBUG
3237 printk(OSST_DEB_MSG "osst%d:D: Switching from read to write at file %d, block %d\n", dev,
3238 STps->drv_file, STps->drv_block);
3239 #endif
3240 retval = osst_flush_buffer(STp, &SRpnt, 0);
3241 if (retval)
3242 goto out;
3243 STps->rw = ST_IDLE;
3244 }
3245 if (STps->rw != ST_WRITING) {
3246 /* Are we totally rewriting this tape? */
3247 if (!STp->header_ok ||
3248 (STp->first_frame_position == STp->first_data_ppos && STps->drv_block < 0) ||
3249 (STps->drv_file == 0 && STps->drv_block == 0)) {
3250 STp->wrt_pass_cntr++;
3251 #if DEBUG
3252 printk(OSST_DEB_MSG "osst%d:D: Allocating next write pass counter: %d\n",
3253 dev, STp->wrt_pass_cntr);
3254 #endif
3255 osst_reset_header(STp, &SRpnt);
3256 STps->drv_file = STps->drv_block = 0;
3257 }
3258 /* Do we know where we'll be writing on the tape? */
3259 else {
3260 if ((STp->fast_open && osst_verify_position(STp, &SRpnt)) ||
3261 STps->drv_file < 0 || STps->drv_block < 0) {
3262 if (STp->first_frame_position == STp->eod_frame_ppos) { /* at EOD */
3263 STps->drv_file = STp->filemark_cnt;
3264 STps->drv_block = 0;
3265 }
3266 else {
3267 /* We have no idea where the tape is positioned - give up */
3268 #if DEBUG
3269 printk(OSST_DEB_MSG
3270 "osst%d:D: Cannot write at indeterminate position.\n", dev);
3271 #endif
3272 retval = (-EIO);
3273 goto out;
3274 }
3275 }
3276 if ((STps->drv_file + STps->drv_block) > 0 && STps->drv_file < STp->filemark_cnt) {
3277 STp->filemark_cnt = STps->drv_file;
3278 STp->last_mark_ppos =
3279 ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt-1]);
3280 printk(KERN_WARNING
3281 "osst%d:W: Overwriting file %d with old write pass counter %d\n",
3282 dev, STps->drv_file, STp->wrt_pass_cntr);
3283 printk(KERN_WARNING
3284 "osst%d:W: may lead to stale data being accepted on reading back!\n",
3285 dev);
3286 #if DEBUG
3287 printk(OSST_DEB_MSG
3288 "osst%d:D: resetting filemark count to %d and last mark ppos,lbn to %d,%d\n",
3289 dev, STp->filemark_cnt, STp->last_mark_ppos, STp->last_mark_lbn);
3290 #endif
3291 }
3292 }
3293 STp->fast_open = FALSE;
3294 }
3295 if (!STp->header_ok) {
3296 #if DEBUG
3297 printk(OSST_DEB_MSG "osst%d:D: Write cannot proceed without valid headers\n", dev);
3298 #endif
3299 retval = (-EIO);
3300 goto out;
3301 }
3302
3303 if ((STp->buffer)->writing) {
3304 if (SRpnt) printk(KERN_ERR "osst%d:A: Not supposed to have SRpnt at line %d\n", dev, __LINE__);
3305 osst_write_behind_check(STp);
3306 if ((STp->buffer)->syscall_result) {
3307 #if DEBUG
3308 if (debugging)
3309 printk(OSST_DEB_MSG "osst%d:D: Async write error (write) %x.\n", dev,
3310 (STp->buffer)->midlevel_result);
3311 #endif
3312 if ((STp->buffer)->midlevel_result == INT_MAX)
3313 STps->eof = ST_EOM_OK;
3314 else
3315 STps->eof = ST_EOM_ERROR;
3316 }
3317 }
3318 if (STps->eof == ST_EOM_OK) {
3319 retval = (-ENOSPC);
3320 goto out;
3321 }
3322 else if (STps->eof == ST_EOM_ERROR) {
3323 retval = (-EIO);
3324 goto out;
3325 }
3326
3327 /* Check the buffer readability in cases where copy_user might catch
3328 the problems after some tape movement. */
3329 if ((copy_from_user(&i, buf, 1) != 0 ||
3330 copy_from_user(&i, buf + count - 1, 1) != 0)) {
3331 retval = (-EFAULT);
3332 goto out;
3333 }
3334
3335 if (!STm->do_buffer_writes) {
3336 write_threshold = 1;
3337 }
3338 else
3339 write_threshold = (STp->buffer)->buffer_blocks * STp->block_size;
3340 if (!STm->do_async_writes)
3341 write_threshold--;
3342
3343 total = count;
3344 #if DEBUG
3345 if (debugging)
3346 printk(OSST_DEB_MSG "osst%d:D: Writing %d bytes to file %d block %d lblk %d fseq %d fppos %d\n",
3347 dev, count, STps->drv_file, STps->drv_block,
3348 STp->logical_blk_num, STp->frame_seq_number, STp->first_frame_position);
3349 #endif
3350 b_point = buf;
3351 while ((STp->buffer)->buffer_bytes + count > write_threshold)
3352 {
3353 doing_write = 1;
3354 do_count = (STp->buffer)->buffer_blocks * STp->block_size -
3355 (STp->buffer)->buffer_bytes;
3356 if (do_count > count)
3357 do_count = count;
3358
3359 i = append_to_buffer(b_point, STp->buffer, do_count);
3360 if (i) {
3361 retval = i;
3362 goto out;
3363 }
3364
3365 blks = do_count / STp->block_size;
3366 STp->logical_blk_num += blks; /* logical_blk_num is incremented as data is moved from user */
3367
3368 i = osst_write_frame(STp, &SRpnt, TRUE);
3369
3370 if (i == (-ENOSPC)) {
3371 transfer = STp->buffer->writing; /* FIXME -- check this logic */
3372 if (transfer <= do_count) {
3373 pos += do_count - transfer;
3374 count -= do_count - transfer;
3375 if (STps->drv_block >= 0) {
3376 STps->drv_block += (do_count - transfer) / STp->block_size;
3377 }
3378 STps->eof = ST_EOM_OK;
3379 retval = (-ENOSPC); /* EOM within current request */
3380 #if DEBUG
3381 if (debugging)
3382 printk(OSST_DEB_MSG "osst%d:D: EOM with %d bytes unwritten.\n",
3383 dev, transfer);
3384 #endif
3385 }
3386 else {
3387 STps->eof = ST_EOM_ERROR;
3388 STps->drv_block = (-1); /* Too cautious? */
3389 retval = (-EIO); /* EOM for old data */
3390 #if DEBUG
3391 if (debugging)
3392 printk(OSST_DEB_MSG "osst%d:D: EOM with lost data.\n", dev);
3393 #endif
3394 }
3395 }
3396 else
3397 retval = i;
3398
3399 if (retval < 0) {
3400 if (SRpnt != NULL) {
3401 scsi_release_request(SRpnt);
3402 SRpnt = NULL;
3403 }
3404 STp->buffer->buffer_bytes = 0;
3405 STp->dirty = 0;
3406 if (count < total)
3407 retval = total - count;
3408 goto out;
3409 }
3410
3411 pos += do_count;
3412 b_point += do_count;
3413 count -= do_count;
3414 if (STps->drv_block >= 0) {
3415 STps->drv_block += blks;
3416 }
3417 STp->buffer->buffer_bytes = 0;
3418 STp->dirty = 0;
3419 } /* end while write threshold exceeded */
3420
3421 if (count != 0) {
3422 STp->dirty = 1;
3423 i = append_to_buffer(b_point, STp->buffer, count);
3424 if (i) {
3425 retval = i;
3426 goto out;
3427 }
3428 blks = count / STp->block_size;
3429 STp->logical_blk_num += blks;
3430 if (STps->drv_block >= 0) {
3431 STps->drv_block += blks;
3432 }
3433 pos += count;
3434 count = 0;
3435 }
3436
3437 if (doing_write && (STp->buffer)->syscall_result != 0) {
3438 retval = (STp->buffer)->syscall_result;
3439 goto out;
3440 }
3441
3442 if (STm->do_async_writes && ((STp->buffer)->buffer_bytes >= STp->write_threshold)) {
3443 /* Schedule an asynchronous write */
3444 (STp->buffer)->writing = ((STp->buffer)->buffer_bytes /
3445 STp->block_size) * STp->block_size;
3446 STp->dirty = !((STp->buffer)->writing ==
3447 (STp->buffer)->buffer_bytes);
3448
3449 i = osst_write_frame(STp, &SRpnt, FALSE);
3450 if (i < 0) {
3451 retval = (-EIO);
3452 goto out;
3453 }
3454 SRpnt = NULL; /* Prevent releasing this request! */
3455 }
3456 STps->at_sm &= (total == 0);
3457 if (total > 0)
3458 STps->eof = ST_NOEOF;
3459
3460 retval = total;
3461
3462 out:
3463 *ppos = pos;
3464 if (SRpnt != NULL) scsi_release_request(SRpnt);
3465
3466 up(&STp->lock);
3467
3468 return retval;
3469 }
3470
3471
3472 /* Read command */
osst_read(struct file * filp,char * buf,size_t count,loff_t * ppos)3473 static ssize_t osst_read(struct file * filp, char * buf, size_t count, loff_t *ppos)
3474 {
3475 struct inode * inode = filp->f_dentry->d_inode;
3476 ssize_t total, retval = 0;
3477 ssize_t i, transfer;
3478 int special;
3479 OS_Scsi_Tape * STp;
3480 ST_mode * STm;
3481 ST_partstat * STps;
3482 Scsi_Request *SRpnt = NULL;
3483 int dev = TAPE_NR(inode->i_rdev);
3484 loff_t pos = *ppos;
3485
3486 STp = os_scsi_tapes[dev];
3487
3488 if (down_interruptible(&STp->lock))
3489 return (-ERESTARTSYS);
3490
3491 /*
3492 * If we are in the middle of error recovery, don't let anyone
3493 * else try and use this device. Also, if error recovery fails, it
3494 * may try and take the device offline, in which case all further
3495 * access to the device is prohibited.
3496 */
3497 if( !scsi_block_when_processing_errors(STp->device) ) {
3498 retval = (-ENXIO);
3499 goto out;
3500 }
3501
3502 if (ppos != &filp->f_pos) {
3503 /* "A request was outside the capabilities of the device." */
3504 retval = (-ENXIO);
3505 goto out;
3506 }
3507
3508 if (STp->ready != ST_READY) {
3509 if (STp->ready == ST_NO_TAPE)
3510 retval = (-ENOMEDIUM);
3511 else
3512 retval = (-EIO);
3513 goto out;
3514 }
3515 STm = &(STp->modes[STp->current_mode]);
3516 if (!STm->defined) {
3517 retval = (-ENXIO);
3518 goto out;
3519 }
3520 #if DEBUG
3521 if (!STp->in_use) {
3522 printk(OSST_DEB_MSG "osst%d:D: Incorrect device.\n", dev);
3523 retval = (-EIO);
3524 goto out;
3525 }
3526 #endif
3527 /* Must have initialized medium */
3528 if (!STp->header_ok) {
3529 retval = (-EIO);
3530 goto out;
3531 }
3532
3533 if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED &&
3534 !osst_int_ioctl(STp, &SRpnt, MTLOCK, 0))
3535 STp->door_locked = ST_LOCKED_AUTO;
3536
3537 STps = &(STp->ps[STp->partition]);
3538 if (STps->rw == ST_WRITING) {
3539 retval = osst_flush_buffer(STp, &SRpnt, 0);
3540 if (retval)
3541 goto out;
3542 STps->rw = ST_IDLE;
3543 /* FIXME -- this may leave the tape without EOD and up2date headers */
3544 }
3545
3546 if ((count % STp->block_size) != 0) {
3547 printk(KERN_WARNING
3548 "osst%d:W: Read (%Zd bytes) not multiple of tape block size (%d%c).\n", dev, count,
3549 STp->block_size<1024?STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k');
3550 }
3551
3552 #if DEBUG
3553 if (debugging && STps->eof != ST_NOEOF)
3554 printk(OSST_DEB_MSG "osst%d:D: EOF/EOM flag up (%d). Bytes %d\n", dev,
3555 STps->eof, (STp->buffer)->buffer_bytes);
3556 #endif
3557 if ((STp->buffer)->buffer_bytes == 0 &&
3558 STps->eof >= ST_EOD_1) {
3559 if (STps->eof < ST_EOD) {
3560 STps->eof += 1;
3561 retval = 0;
3562 goto out;
3563 }
3564 retval = (-EIO); /* EOM or Blank Check */
3565 goto out;
3566 }
3567
3568 /* Check the buffer writability before any tape movement. Don't alter
3569 buffer data. */
3570 if (copy_from_user(&i, buf, 1) != 0 ||
3571 copy_to_user (buf, &i, 1) != 0 ||
3572 copy_from_user(&i, buf + count - 1, 1) != 0 ||
3573 copy_to_user (buf + count - 1, &i, 1) != 0) {
3574 retval = (-EFAULT);
3575 goto out;
3576 }
3577
3578 /* Loop until enough data in buffer or a special condition found */
3579 for (total = 0, special = 0; total < count - STp->block_size + 1 && !special; ) {
3580
3581 /* Get new data if the buffer is empty */
3582 if ((STp->buffer)->buffer_bytes == 0) {
3583 if (STps->eof == ST_FM_HIT)
3584 break;
3585 special = osst_get_logical_frame(STp, &SRpnt, STp->frame_seq_number, 0);
3586 if (special < 0) { /* No need to continue read */
3587 STp->frame_in_buffer = 0;
3588 retval = special;
3589 goto out;
3590 }
3591 }
3592
3593 /* Move the data from driver buffer to user buffer */
3594 if ((STp->buffer)->buffer_bytes > 0) {
3595 #if DEBUG
3596 if (debugging && STps->eof != ST_NOEOF)
3597 printk(OSST_DEB_MSG "osst%d:D: EOF up (%d). Left %d, needed %d.\n", dev,
3598 STps->eof, (STp->buffer)->buffer_bytes, count - total);
3599 #endif
3600 /* force multiple of block size, note block_size may have been adjusted */
3601 transfer = (((STp->buffer)->buffer_bytes < count - total ?
3602 (STp->buffer)->buffer_bytes : count - total)/
3603 STp->block_size) * STp->block_size;
3604
3605 if (transfer == 0) {
3606 printk(KERN_WARNING
3607 "osst%d:W: Nothing can be transfered, requested %d, tape block size (%d%c).\n",
3608 dev, count, STp->block_size < 1024?
3609 STp->block_size:STp->block_size/1024,
3610 STp->block_size<1024?'b':'k');
3611 break;
3612 }
3613 i = from_buffer(STp->buffer, buf, transfer);
3614 if (i) {
3615 retval = i;
3616 goto out;
3617 }
3618 STp->logical_blk_num += transfer / STp->block_size;
3619 STps->drv_block += transfer / STp->block_size;
3620 pos += transfer;
3621 buf += transfer;
3622 total += transfer;
3623 }
3624
3625 if ((STp->buffer)->buffer_bytes == 0) {
3626 #if DEBUG
3627 if (debugging)
3628 printk(OSST_DEB_MSG "osst%d:D: Finished with frame %d\n",
3629 dev, STp->frame_seq_number);
3630 #endif
3631 STp->frame_in_buffer = 0;
3632 STp->frame_seq_number++; /* frame to look for next time */
3633 }
3634 } /* for (total = 0, special = 0; total < count && !special; ) */
3635
3636 /* Change the eof state if no data from tape or buffer */
3637 if (total == 0) {
3638 if (STps->eof == ST_FM_HIT) {
3639 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD_2:ST_FM;
3640 STps->drv_block = 0;
3641 if (STps->drv_file >= 0)
3642 STps->drv_file++;
3643 }
3644 else if (STps->eof == ST_EOD_1) {
3645 STps->eof = ST_EOD_2;
3646 if (STps->drv_block > 0 && STps->drv_file >= 0)
3647 STps->drv_file++;
3648 STps->drv_block = 0;
3649 }
3650 else if (STps->eof == ST_EOD_2)
3651 STps->eof = ST_EOD;
3652 }
3653 else if (STps->eof == ST_FM)
3654 STps->eof = ST_NOEOF;
3655
3656 retval = total;
3657
3658 out:
3659 *ppos = pos;
3660 if (SRpnt != NULL) scsi_release_request(SRpnt);
3661
3662 up(&STp->lock);
3663
3664 return retval;
3665 }
3666
3667
3668 /* Set the driver options */
osst_log_options(OS_Scsi_Tape * STp,ST_mode * STm,int dev)3669 static void osst_log_options(OS_Scsi_Tape *STp, ST_mode *STm, int dev)
3670 {
3671 printk(KERN_INFO
3672 "osst%d:I: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n",
3673 dev, STp->current_mode, STm->do_buffer_writes, STm->do_async_writes,
3674 STm->do_read_ahead);
3675 printk(KERN_INFO
3676 "osst%d:I: can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n",
3677 dev, STp->can_bsr, STp->two_fm, STp->fast_mteom, STp->do_auto_lock);
3678 printk(KERN_INFO
3679 "osst%d:I: defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n",
3680 dev, STm->defaults_for_writes, STp->omit_blklims, STp->can_partitions,
3681 STp->scsi2_logical);
3682 printk(KERN_INFO
3683 "osst%d:I: sysv: %d\n", dev, STm->sysv);
3684 #if DEBUG
3685 printk(KERN_INFO
3686 "osst%d:D: debugging: %d\n",
3687 dev, debugging);
3688 #endif
3689 }
3690
3691
osst_set_options(OS_Scsi_Tape * STp,long options)3692 static int osst_set_options(OS_Scsi_Tape *STp, long options)
3693 {
3694 int value;
3695 long code;
3696 ST_mode *STm;
3697 int dev = TAPE_NR(STp->devt);
3698
3699 STm = &(STp->modes[STp->current_mode]);
3700 if (!STm->defined) {
3701 memcpy(STm, &(STp->modes[0]), sizeof(ST_mode));
3702 modes_defined = TRUE;
3703 #if DEBUG
3704 if (debugging)
3705 printk(OSST_DEB_MSG "osst%d:D: Initialized mode %d definition from mode 0\n",
3706 dev, STp->current_mode);
3707 #endif
3708 }
3709
3710 code = options & MT_ST_OPTIONS;
3711 if (code == MT_ST_BOOLEANS) {
3712 STm->do_buffer_writes = (options & MT_ST_BUFFER_WRITES) != 0;
3713 STm->do_async_writes = (options & MT_ST_ASYNC_WRITES) != 0;
3714 STm->defaults_for_writes = (options & MT_ST_DEF_WRITES) != 0;
3715 STm->do_read_ahead = (options & MT_ST_READ_AHEAD) != 0;
3716 STp->two_fm = (options & MT_ST_TWO_FM) != 0;
3717 STp->fast_mteom = (options & MT_ST_FAST_MTEOM) != 0;
3718 STp->do_auto_lock = (options & MT_ST_AUTO_LOCK) != 0;
3719 STp->can_bsr = (options & MT_ST_CAN_BSR) != 0;
3720 STp->omit_blklims = (options & MT_ST_NO_BLKLIMS) != 0;
3721 if ((STp->device)->scsi_level >= SCSI_2)
3722 STp->can_partitions = (options & MT_ST_CAN_PARTITIONS) != 0;
3723 STp->scsi2_logical = (options & MT_ST_SCSI2LOGICAL) != 0;
3724 STm->sysv = (options & MT_ST_SYSV) != 0;
3725 #if DEBUG
3726 debugging = (options & MT_ST_DEBUGGING) != 0;
3727 #endif
3728 osst_log_options(STp, STm, dev);
3729 }
3730 else if (code == MT_ST_SETBOOLEANS || code == MT_ST_CLEARBOOLEANS) {
3731 value = (code == MT_ST_SETBOOLEANS);
3732 if ((options & MT_ST_BUFFER_WRITES) != 0)
3733 STm->do_buffer_writes = value;
3734 if ((options & MT_ST_ASYNC_WRITES) != 0)
3735 STm->do_async_writes = value;
3736 if ((options & MT_ST_DEF_WRITES) != 0)
3737 STm->defaults_for_writes = value;
3738 if ((options & MT_ST_READ_AHEAD) != 0)
3739 STm->do_read_ahead = value;
3740 if ((options & MT_ST_TWO_FM) != 0)
3741 STp->two_fm = value;
3742 if ((options & MT_ST_FAST_MTEOM) != 0)
3743 STp->fast_mteom = value;
3744 if ((options & MT_ST_AUTO_LOCK) != 0)
3745 STp->do_auto_lock = value;
3746 if ((options & MT_ST_CAN_BSR) != 0)
3747 STp->can_bsr = value;
3748 if ((options & MT_ST_NO_BLKLIMS) != 0)
3749 STp->omit_blklims = value;
3750 if ((STp->device)->scsi_level >= SCSI_2 &&
3751 (options & MT_ST_CAN_PARTITIONS) != 0)
3752 STp->can_partitions = value;
3753 if ((options & MT_ST_SCSI2LOGICAL) != 0)
3754 STp->scsi2_logical = value;
3755 if ((options & MT_ST_SYSV) != 0)
3756 STm->sysv = value;
3757 #if DEBUG
3758 if ((options & MT_ST_DEBUGGING) != 0)
3759 debugging = value;
3760 #endif
3761 osst_log_options(STp, STm, dev);
3762 }
3763 else if (code == MT_ST_WRITE_THRESHOLD) {
3764 value = (options & ~MT_ST_OPTIONS) * ST_KILOBYTE;
3765 if (value < 1 || value > osst_buffer_size) {
3766 printk(KERN_WARNING "osst%d:W: Write threshold %d too small or too large.\n",
3767 dev, value);
3768 return (-EIO);
3769 }
3770 STp->write_threshold = value;
3771 printk(KERN_INFO "osst%d:I: Write threshold set to %d bytes.\n",
3772 dev, value);
3773 }
3774 else if (code == MT_ST_DEF_BLKSIZE) {
3775 value = (options & ~MT_ST_OPTIONS);
3776 if (value == ~MT_ST_OPTIONS) {
3777 STm->default_blksize = (-1);
3778 printk(KERN_INFO "osst%d:I: Default block size disabled.\n", dev);
3779 }
3780 else {
3781 if (value < 512 || value > OS_DATA_SIZE || OS_DATA_SIZE % value) {
3782 printk(KERN_WARNING "osst%d:W: Default block size cannot be set to %d.\n",
3783 dev, value);
3784 return (-EINVAL);
3785 }
3786 STm->default_blksize = value;
3787 printk(KERN_INFO "osst%d:I: Default block size set to %d bytes.\n",
3788 dev, STm->default_blksize);
3789 }
3790 }
3791 else if (code == MT_ST_TIMEOUTS) {
3792 value = (options & ~MT_ST_OPTIONS);
3793 if ((value & MT_ST_SET_LONG_TIMEOUT) != 0) {
3794 STp->long_timeout = (value & ~MT_ST_SET_LONG_TIMEOUT) * HZ;
3795 printk(KERN_INFO "osst%d:I: Long timeout set to %d seconds.\n", dev,
3796 (value & ~MT_ST_SET_LONG_TIMEOUT));
3797 }
3798 else {
3799 STp->timeout = value * HZ;
3800 printk(KERN_INFO "osst%d:I: Normal timeout set to %d seconds.\n", dev, value);
3801 }
3802 }
3803 else if (code == MT_ST_DEF_OPTIONS) {
3804 code = (options & ~MT_ST_CLEAR_DEFAULT);
3805 value = (options & MT_ST_CLEAR_DEFAULT);
3806 if (code == MT_ST_DEF_DENSITY) {
3807 if (value == MT_ST_CLEAR_DEFAULT) {
3808 STm->default_density = (-1);
3809 printk(KERN_INFO "osst%d:I: Density default disabled.\n", dev);
3810 }
3811 else {
3812 STm->default_density = value & 0xff;
3813 printk(KERN_INFO "osst%d:I: Density default set to %x\n",
3814 dev, STm->default_density);
3815 }
3816 }
3817 else if (code == MT_ST_DEF_DRVBUFFER) {
3818 if (value == MT_ST_CLEAR_DEFAULT) {
3819 STp->default_drvbuffer = 0xff;
3820 printk(KERN_INFO "osst%d:I: Drive buffer default disabled.\n", dev);
3821 }
3822 else {
3823 STp->default_drvbuffer = value & 7;
3824 printk(KERN_INFO "osst%d:I: Drive buffer default set to %x\n",
3825 dev, STp->default_drvbuffer);
3826 }
3827 }
3828 else if (code == MT_ST_DEF_COMPRESSION) {
3829 if (value == MT_ST_CLEAR_DEFAULT) {
3830 STm->default_compression = ST_DONT_TOUCH;
3831 printk(KERN_INFO "osst%d:I: Compression default disabled.\n", dev);
3832 }
3833 else {
3834 STm->default_compression = (value & 1 ? ST_YES : ST_NO);
3835 printk(KERN_INFO "osst%d:I: Compression default set to %x\n",
3836 dev, (value & 1));
3837 }
3838 }
3839 }
3840 else
3841 return (-EIO);
3842
3843 return 0;
3844 }
3845
3846
3847 /* Internal ioctl function */
osst_int_ioctl(OS_Scsi_Tape * STp,Scsi_Request ** aSRpnt,unsigned int cmd_in,unsigned long arg)3848 static int osst_int_ioctl(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned int cmd_in, unsigned long arg)
3849 {
3850 int timeout;
3851 long ltmp;
3852 int i, ioctl_result;
3853 int chg_eof = TRUE;
3854 unsigned char cmd[MAX_COMMAND_SIZE];
3855 Scsi_Request * SRpnt = * aSRpnt;
3856 ST_partstat * STps;
3857 int fileno, blkno, at_sm, frame_seq_numbr, logical_blk_num;
3858 int datalen = 0, direction = SCSI_DATA_NONE;
3859 int dev = TAPE_NR(STp->devt);
3860
3861 if (STp->ready != ST_READY && cmd_in != MTLOAD) {
3862 if (STp->ready == ST_NO_TAPE)
3863 return (-ENOMEDIUM);
3864 else
3865 return (-EIO);
3866 }
3867 timeout = STp->long_timeout;
3868 STps = &(STp->ps[STp->partition]);
3869 fileno = STps->drv_file;
3870 blkno = STps->drv_block;
3871 at_sm = STps->at_sm;
3872 frame_seq_numbr = STp->frame_seq_number;
3873 logical_blk_num = STp->logical_blk_num;
3874
3875 memset(cmd, 0, MAX_COMMAND_SIZE);
3876 switch (cmd_in) {
3877 case MTFSFM:
3878 chg_eof = FALSE; /* Changed from the FSF after this */
3879 case MTFSF:
3880 if (STp->raw)
3881 return (-EIO);
3882 if (STp->linux_media)
3883 ioctl_result = osst_space_over_filemarks_forward_fast(STp, &SRpnt, cmd_in, arg);
3884 else
3885 ioctl_result = osst_space_over_filemarks_forward_slow(STp, &SRpnt, cmd_in, arg);
3886 if (fileno >= 0)
3887 fileno += arg;
3888 blkno = 0;
3889 at_sm &= (arg == 0);
3890 goto os_bypass;
3891
3892 case MTBSF:
3893 chg_eof = FALSE; /* Changed from the FSF after this */
3894 case MTBSFM:
3895 if (STp->raw)
3896 return (-EIO);
3897 ioctl_result = osst_space_over_filemarks_backward(STp, &SRpnt, cmd_in, arg);
3898 if (fileno >= 0)
3899 fileno -= arg;
3900 blkno = (-1); /* We can't know the block number */
3901 at_sm &= (arg == 0);
3902 goto os_bypass;
3903
3904 case MTFSR:
3905 case MTBSR:
3906 #if DEBUG
3907 if (debugging)
3908 printk(OSST_DEB_MSG "osst%d:D: Skipping %lu blocks %s from logical block %d\n",
3909 dev, arg, cmd_in==MTFSR?"forward":"backward", logical_blk_num);
3910 #endif
3911 if (cmd_in == MTFSR) {
3912 logical_blk_num += arg;
3913 if (blkno >= 0) blkno += arg;
3914 }
3915 else {
3916 logical_blk_num -= arg;
3917 if (blkno >= 0) blkno -= arg;
3918 }
3919 ioctl_result = osst_seek_logical_blk(STp, &SRpnt, logical_blk_num);
3920 fileno = STps->drv_file;
3921 blkno = STps->drv_block;
3922 at_sm &= (arg == 0);
3923 goto os_bypass;
3924
3925 case MTFSS:
3926 cmd[0] = SPACE;
3927 cmd[1] = 0x04; /* Space Setmarks */ /* FIXME -- OS can't do this? */
3928 cmd[2] = (arg >> 16);
3929 cmd[3] = (arg >> 8);
3930 cmd[4] = arg;
3931 #if DEBUG
3932 if (debugging)
3933 printk(OSST_DEB_MSG "osst%d:D: Spacing tape forward %d setmarks.\n", dev,
3934 cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
3935 #endif
3936 if (arg != 0) {
3937 blkno = fileno = (-1);
3938 at_sm = 1;
3939 }
3940 break;
3941 case MTBSS:
3942 cmd[0] = SPACE;
3943 cmd[1] = 0x04; /* Space Setmarks */ /* FIXME -- OS can't do this? */
3944 ltmp = (-arg);
3945 cmd[2] = (ltmp >> 16);
3946 cmd[3] = (ltmp >> 8);
3947 cmd[4] = ltmp;
3948 #if DEBUG
3949 if (debugging) {
3950 if (cmd[2] & 0x80)
3951 ltmp = 0xff000000;
3952 ltmp = ltmp | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
3953 printk(OSST_DEB_MSG "osst%d:D: Spacing tape backward %ld setmarks.\n",
3954 dev, (-ltmp));
3955 }
3956 #endif
3957 if (arg != 0) {
3958 blkno = fileno = (-1);
3959 at_sm = 1;
3960 }
3961 break;
3962 case MTWEOF:
3963 if ((STps->rw == ST_WRITING || STp->dirty) && !(STp->device)->was_reset) {
3964 STp->write_type = OS_WRITE_DATA;
3965 ioctl_result = osst_flush_write_buffer(STp, &SRpnt);
3966 } else
3967 ioctl_result = 0;
3968 #if DEBUG
3969 if (debugging)
3970 printk(OSST_DEB_MSG "osst%d:D: Writing %ld filemark(s).\n", dev, arg);
3971 #endif
3972 for (i=0; i<arg; i++)
3973 ioctl_result |= osst_write_filemark(STp, &SRpnt);
3974 if (fileno >= 0) fileno += arg;
3975 if (blkno >= 0) blkno = 0;
3976 goto os_bypass;
3977
3978 case MTWSM:
3979 if (STp->write_prot)
3980 return (-EACCES);
3981 if (!STp->raw)
3982 return 0;
3983 cmd[0] = WRITE_FILEMARKS; /* FIXME -- need OS version */
3984 if (cmd_in == MTWSM)
3985 cmd[1] = 2;
3986 cmd[2] = (arg >> 16);
3987 cmd[3] = (arg >> 8);
3988 cmd[4] = arg;
3989 timeout = STp->timeout;
3990 #if DEBUG
3991 if (debugging)
3992 printk(OSST_DEB_MSG "osst%d:D: Writing %d setmark(s).\n", dev,
3993 cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
3994 #endif
3995 if (fileno >= 0)
3996 fileno += arg;
3997 blkno = 0;
3998 at_sm = (cmd_in == MTWSM);
3999 break;
4000 case MTOFFL:
4001 case MTLOAD:
4002 case MTUNLOAD:
4003 case MTRETEN:
4004 cmd[0] = START_STOP;
4005 cmd[1] = 1; /* Don't wait for completion */
4006 if (cmd_in == MTLOAD) {
4007 if (STp->ready == ST_NO_TAPE)
4008 cmd[4] = 4; /* open tray */
4009 else
4010 cmd[4] = 1; /* load */
4011 }
4012 if (cmd_in == MTRETEN)
4013 cmd[4] = 3; /* retension then mount */
4014 if (cmd_in == MTOFFL)
4015 cmd[4] = 4; /* rewind then eject */
4016 timeout = STp->timeout;
4017 #if DEBUG
4018 if (debugging) {
4019 switch (cmd_in) {
4020 case MTUNLOAD:
4021 printk(OSST_DEB_MSG "osst%d:D: Unloading tape.\n", dev);
4022 break;
4023 case MTLOAD:
4024 printk(OSST_DEB_MSG "osst%d:D: Loading tape.\n", dev);
4025 break;
4026 case MTRETEN:
4027 printk(OSST_DEB_MSG "osst%d:D: Retensioning tape.\n", dev);
4028 break;
4029 case MTOFFL:
4030 printk(OSST_DEB_MSG "osst%d:D: Ejecting tape.\n", dev);
4031 break;
4032 }
4033 }
4034 #endif
4035 fileno = blkno = at_sm = frame_seq_numbr = logical_blk_num = 0 ;
4036 break;
4037 case MTNOP:
4038 #if DEBUG
4039 if (debugging)
4040 printk(OSST_DEB_MSG "osst%d:D: No-op on tape.\n", dev);
4041 #endif
4042 return 0; /* Should do something ? */
4043 break;
4044 case MTEOM:
4045 #if DEBUG
4046 if (debugging)
4047 printk(OSST_DEB_MSG "osst%d:D: Spacing to end of recorded medium.\n", dev);
4048 #endif
4049 if ((osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos) < 0) ||
4050 (osst_get_logical_frame(STp, &SRpnt, -1, 0) < 0)) {
4051 ioctl_result = -EIO;
4052 goto os_bypass;
4053 }
4054 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_EOD) {
4055 #if DEBUG
4056 printk(OSST_DEB_MSG "osst%d:D: No EOD frame found where expected.\n", dev);
4057 #endif
4058 ioctl_result = -EIO;
4059 goto os_bypass;
4060 }
4061 ioctl_result = osst_set_frame_position(STp, &SRpnt, STp->eod_frame_ppos, 0);
4062 fileno = STp->filemark_cnt;
4063 blkno = at_sm = 0;
4064 goto os_bypass;
4065
4066 case MTERASE:
4067 if (STp->write_prot)
4068 return (-EACCES);
4069 ioctl_result = osst_reset_header(STp, &SRpnt);
4070 i = osst_write_eod(STp, &SRpnt);
4071 if (i < ioctl_result) ioctl_result = i;
4072 i = osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos);
4073 if (i < ioctl_result) ioctl_result = i;
4074 fileno = blkno = at_sm = 0 ;
4075 goto os_bypass;
4076
4077 case MTREW:
4078 cmd[0] = REZERO_UNIT; /* rewind */
4079 cmd[1] = 1;
4080 #if DEBUG
4081 if (debugging)
4082 printk(OSST_DEB_MSG "osst%d:D: Rewinding tape, Immed=%d.\n", dev, cmd[1]);
4083 #endif
4084 fileno = blkno = at_sm = frame_seq_numbr = logical_blk_num = 0 ;
4085 break;
4086
4087 case MTLOCK:
4088 chg_eof = FALSE;
4089 cmd[0] = ALLOW_MEDIUM_REMOVAL;
4090 cmd[4] = SCSI_REMOVAL_PREVENT;
4091 #if DEBUG
4092 if (debugging)
4093 printk(OSST_DEB_MSG "osst%d:D: Locking drive door.\n", dev);
4094 #endif
4095 break;
4096
4097 case MTUNLOCK:
4098 chg_eof = FALSE;
4099 cmd[0] = ALLOW_MEDIUM_REMOVAL;
4100 cmd[4] = SCSI_REMOVAL_ALLOW;
4101 #if DEBUG
4102 if (debugging)
4103 printk(OSST_DEB_MSG "osst%d:D: Unlocking drive door.\n", dev);
4104 #endif
4105 break;
4106
4107 case MTSETBLK: /* Set block length */
4108 if ((STps->drv_block == 0 ) &&
4109 !STp->dirty &&
4110 ((STp->buffer)->buffer_bytes == 0) &&
4111 ((arg & MT_ST_BLKSIZE_MASK) >= 512 ) &&
4112 ((arg & MT_ST_BLKSIZE_MASK) <= OS_DATA_SIZE) &&
4113 !(OS_DATA_SIZE % (arg & MT_ST_BLKSIZE_MASK)) ) {
4114 /*
4115 * Only allowed to change the block size if you opened the
4116 * device at the beginning of a file before writing anything.
4117 * Note, that when reading, changing block_size is futile,
4118 * as the size used when writing overrides it.
4119 */
4120 STp->block_size = (arg & MT_ST_BLKSIZE_MASK);
4121 printk(KERN_INFO "osst%d:I: Block size set to %d bytes.\n",
4122 dev, STp->block_size);
4123 return 0;
4124 }
4125 case MTSETDENSITY: /* Set tape density */
4126 case MTSETDRVBUFFER: /* Set drive buffering */
4127 case SET_DENS_AND_BLK: /* Set density and block size */
4128 chg_eof = FALSE;
4129 if (STp->dirty || (STp->buffer)->buffer_bytes != 0)
4130 return (-EIO); /* Not allowed if data in buffer */
4131 if ((cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) &&
4132 (arg & MT_ST_BLKSIZE_MASK) != 0 &&
4133 (arg & MT_ST_BLKSIZE_MASK) != STp->block_size ) {
4134 printk(KERN_WARNING "osst%d:W: Illegal to set block size to %d%s.\n",
4135 dev, (int)(arg & MT_ST_BLKSIZE_MASK),
4136 (OS_DATA_SIZE % (arg & MT_ST_BLKSIZE_MASK))?"":" now");
4137 return (-EINVAL);
4138 }
4139 return 0; /* FIXME silently ignore if block size didn't change */
4140
4141 default:
4142 return (-ENOSYS);
4143 }
4144
4145 SRpnt = osst_do_scsi(SRpnt, STp, cmd, datalen, direction, timeout, MAX_RETRIES, TRUE);
4146
4147 ioctl_result = (STp->buffer)->syscall_result;
4148
4149 if (!SRpnt) {
4150 #if DEBUG
4151 printk(OSST_DEB_MSG "osst%d:D: Couldn't exec scsi cmd for IOCTL\n", dev);
4152 #endif
4153 return ioctl_result;
4154 }
4155
4156 if (!ioctl_result) { /* SCSI command successful */
4157 STp->frame_seq_number = frame_seq_numbr;
4158 STp->logical_blk_num = logical_blk_num;
4159 }
4160
4161 os_bypass:
4162 #if DEBUG
4163 if (debugging)
4164 printk(OSST_DEB_MSG "osst%d:D: IOCTL (%d) Result=%d\n", dev, cmd_in, ioctl_result);
4165 #endif
4166
4167 if (!ioctl_result) { /* success */
4168
4169 if (cmd_in == MTFSFM) {
4170 fileno--;
4171 blkno--;
4172 }
4173 if (cmd_in == MTBSFM) {
4174 fileno++;
4175 blkno++;
4176 }
4177 STps->drv_block = blkno;
4178 STps->drv_file = fileno;
4179 STps->at_sm = at_sm;
4180
4181 if (cmd_in == MTLOCK)
4182 STp->door_locked = ST_LOCKED_EXPLICIT;
4183 else if (cmd_in == MTUNLOCK)
4184 STp->door_locked = ST_UNLOCKED;
4185
4186 if (cmd_in == MTEOM)
4187 STps->eof = ST_EOD;
4188 else if ((cmd_in == MTFSFM || cmd_in == MTBSF) && STps->eof == ST_FM_HIT) {
4189 ioctl_result = osst_seek_logical_blk(STp, &SRpnt, STp->logical_blk_num-1);
4190 STps->drv_block++;
4191 STp->logical_blk_num++;
4192 STp->frame_seq_number++;
4193 STp->frame_in_buffer = 0;
4194 STp->buffer->read_pointer = 0;
4195 }
4196 else if (cmd_in == MTFSF)
4197 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_FM;
4198 else if (chg_eof)
4199 STps->eof = ST_NOEOF;
4200
4201 if (cmd_in == MTOFFL || cmd_in == MTUNLOAD)
4202 STp->rew_at_close = 0;
4203 else if (cmd_in == MTLOAD) {
4204 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4205 STp->ps[i].rw = ST_IDLE;
4206 STp->ps[i].last_block_valid = FALSE;/* FIXME - where else is this field maintained? */
4207 }
4208 STp->partition = 0;
4209 }
4210
4211 if (cmd_in == MTREW) {
4212 ioctl_result = osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos);
4213 if (ioctl_result > 0)
4214 ioctl_result = 0;
4215 }
4216
4217 } else if (cmd_in == MTBSF || cmd_in == MTBSFM ) {
4218 if (osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos) < 0)
4219 STps->drv_file = STps->drv_block = -1;
4220 else
4221 STps->drv_file = STps->drv_block = 0;
4222 STps->eof = ST_NOEOF;
4223 } else if (cmd_in == MTFSF || cmd_in == MTFSFM) {
4224 if (osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos) < 0)
4225 STps->drv_file = STps->drv_block = -1;
4226 else {
4227 STps->drv_file = STp->filemark_cnt;
4228 STps->drv_block = 0;
4229 }
4230 STps->eof = ST_EOD;
4231 } else if (cmd_in == MTBSR || cmd_in == MTFSR || cmd_in == MTWEOF || cmd_in == MTEOM) {
4232 STps->drv_file = STps->drv_block = (-1);
4233 STps->eof = ST_NOEOF;
4234 STp->header_ok = 0;
4235 } else if (cmd_in == MTERASE) {
4236 STp->header_ok = 0;
4237 } else if (SRpnt) { /* SCSI command was not completely successful. */
4238 if (SRpnt->sr_sense_buffer[2] & 0x40) {
4239 STps->eof = ST_EOM_OK;
4240 STps->drv_block = 0;
4241 }
4242 if (chg_eof)
4243 STps->eof = ST_NOEOF;
4244
4245 if ((SRpnt->sr_sense_buffer[2] & 0x0f) == BLANK_CHECK)
4246 STps->eof = ST_EOD;
4247
4248 if (cmd_in == MTLOCK)
4249 STp->door_locked = ST_LOCK_FAILS;
4250
4251 if (cmd_in == MTLOAD && osst_wait_for_medium(STp, &SRpnt, 60))
4252 ioctl_result = osst_wait_ready(STp, &SRpnt, 5 * 60, OSST_WAIT_POSITION_COMPLETE);
4253 }
4254 *aSRpnt = SRpnt;
4255
4256 #if DEBUG
4257 printk(OSST_DEB_MSG "osst%d:D: Ioctl %s, ppos %d fseq %d lblk %d bytes %d file %d blk %d\n", dev,
4258 ioctl_result?"fail":"success", STp->first_frame_position, STp->frame_seq_number,
4259 STp->logical_blk_num, STp->buffer->buffer_bytes, STps->drv_file, STps->drv_block);
4260 #endif
4261 return ioctl_result;
4262 }
4263
4264
4265 /* Open the device */
os_scsi_tape_open(struct inode * inode,struct file * filp)4266 static int os_scsi_tape_open(struct inode * inode, struct file * filp)
4267 {
4268 unsigned short flags;
4269 int i, b_size, need_dma_buffer, new_session = FALSE, retval = 0;
4270 unsigned char cmd[MAX_COMMAND_SIZE];
4271 Scsi_Request * SRpnt;
4272 OS_Scsi_Tape * STp;
4273 ST_mode * STm;
4274 ST_partstat * STps;
4275 int dev = TAPE_NR(inode->i_rdev);
4276 int mode = TAPE_MODE(inode->i_rdev);
4277
4278 if (dev >= osst_template.dev_max || (STp = os_scsi_tapes[dev]) == NULL || !STp->device)
4279 return (-ENXIO);
4280
4281 if( !scsi_block_when_processing_errors(STp->device) ) {
4282 return -ENXIO;
4283 }
4284
4285 if (STp->in_use) {
4286 #if DEBUG
4287 printk(OSST_DEB_MSG "osst%d:D: Device already in use.\n", dev);
4288 #endif
4289 return (-EBUSY);
4290 }
4291 STp->in_use = 1;
4292 STp->rew_at_close = (MINOR(inode->i_rdev) & 0x80) == 0;
4293
4294 if (STp->device->host->hostt->module)
4295 __MOD_INC_USE_COUNT(STp->device->host->hostt->module);
4296 if (osst_template.module)
4297 __MOD_INC_USE_COUNT(osst_template.module);
4298 STp->device->access_count++;
4299
4300 if (mode != STp->current_mode) {
4301 #if DEBUG
4302 if (debugging)
4303 printk(OSST_DEB_MSG "osst%d:D: Mode change from %d to %d.\n",
4304 dev, STp->current_mode, mode);
4305 #endif
4306 new_session = TRUE;
4307 STp->current_mode = mode;
4308 }
4309 STm = &(STp->modes[STp->current_mode]);
4310
4311 flags = filp->f_flags;
4312 STp->write_prot = ((flags & O_ACCMODE) == O_RDONLY);
4313
4314 STp->raw = (MINOR(inode->i_rdev) & 0x40) != 0;
4315 if (STp->raw)
4316 STp->header_ok = 0;
4317
4318 /* Allocate a buffer for this user */
4319 need_dma_buffer = STp->restr_dma;
4320 for (i=0; i < osst_nbr_buffers; i++)
4321 if (!osst_buffers[i]->in_use &&
4322 (!need_dma_buffer || osst_buffers[i]->dma))
4323 break;
4324 if (i >= osst_nbr_buffers) {
4325 STp->buffer = new_tape_buffer(FALSE, need_dma_buffer);
4326 if (STp->buffer == NULL) {
4327 printk(KERN_WARNING "osst%d:W: Can't allocate tape buffer.\n", dev);
4328 retval = (-EBUSY);
4329 goto err_out;
4330 }
4331 }
4332 else
4333 STp->buffer = osst_buffers[i];
4334 (STp->buffer)->in_use = 1;
4335 (STp->buffer)->writing = 0;
4336 (STp->buffer)->syscall_result = 0;
4337 (STp->buffer)->use_sg = STp->device->host->sg_tablesize;
4338
4339 /* Compute the usable buffer size for this SCSI adapter */
4340 if (!(STp->buffer)->use_sg)
4341 (STp->buffer)->buffer_size = (STp->buffer)->sg[0].length;
4342 else {
4343 for (i=0, (STp->buffer)->buffer_size = 0; i < (STp->buffer)->use_sg &&
4344 i < (STp->buffer)->sg_segs; i++)
4345 (STp->buffer)->buffer_size += (STp->buffer)->sg[i].length;
4346 }
4347
4348 STp->dirty = 0;
4349 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4350 STps = &(STp->ps[i]);
4351 STps->rw = ST_IDLE;
4352 }
4353 STp->ready = ST_READY;
4354 #if DEBUG
4355 STp->nbr_waits = STp->nbr_finished = 0;
4356 #endif
4357
4358 memset (cmd, 0, MAX_COMMAND_SIZE);
4359 cmd[0] = TEST_UNIT_READY;
4360
4361 SRpnt = osst_do_scsi(NULL, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READY_RETRIES, TRUE);
4362 if (!SRpnt) {
4363 retval = (STp->buffer)->syscall_result;
4364 goto err_out;
4365 }
4366 if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
4367 (SRpnt->sr_sense_buffer[2] & 0x0f) == NOT_READY &&
4368 SRpnt->sr_sense_buffer[12] == 4 ) {
4369 #if DEBUG
4370 printk(OSST_DEB_MSG "osst%d:D: Unit not ready, cause %x\n", dev, SRpnt->sr_sense_buffer[13]);
4371 #endif
4372 if (SRpnt->sr_sense_buffer[13] == 2) { /* initialize command required (LOAD) */
4373 memset (cmd, 0, MAX_COMMAND_SIZE);
4374 cmd[0] = START_STOP;
4375 cmd[1] = 1;
4376 cmd[4] = 1;
4377 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE,
4378 STp->timeout, MAX_READY_RETRIES, TRUE);
4379 }
4380 osst_wait_ready(STp, &SRpnt, (SRpnt->sr_sense_buffer[13]==1?15:3) * 60, 0);
4381 }
4382 if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
4383 (SRpnt->sr_sense_buffer[2] & 0x0f) == UNIT_ATTENTION) { /* New media? */
4384 #if DEBUG
4385 printk(OSST_DEB_MSG "osst%d:D: Unit wants attention\n", dev);
4386 #endif
4387 STp->header_ok = 0;
4388
4389 for (i=0; i < 10; i++) {
4390
4391 memset (cmd, 0, MAX_COMMAND_SIZE);
4392 cmd[0] = TEST_UNIT_READY;
4393
4394 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE,
4395 STp->timeout, MAX_READY_RETRIES, TRUE);
4396 if ((SRpnt->sr_sense_buffer[0] & 0x70) != 0x70 ||
4397 (SRpnt->sr_sense_buffer[2] & 0x0f) != UNIT_ATTENTION)
4398 break;
4399 }
4400
4401 STp->device->was_reset = 0;
4402 STp->partition = STp->new_partition = 0;
4403 if (STp->can_partitions)
4404 STp->nbr_partitions = 1; /* This guess will be updated later if necessary */
4405 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4406 STps = &(STp->ps[i]);
4407 STps->rw = ST_IDLE; /* FIXME - seems to be redundant... */
4408 STps->eof = ST_NOEOF;
4409 STps->at_sm = 0;
4410 STps->last_block_valid = FALSE;
4411 STps->drv_block = 0;
4412 STps->drv_file = 0 ;
4413 }
4414 new_session = TRUE;
4415 STp->recover_count = 0;
4416 }
4417 /*
4418 * if we have valid headers from before, and the drive/tape seem untouched,
4419 * open without reconfiguring and re-reading the headers
4420 */
4421 if (!STp->buffer->syscall_result && STp->header_ok &&
4422 !SRpnt->sr_result && SRpnt->sr_sense_buffer[0] == 0) {
4423
4424 memset(cmd, 0, MAX_COMMAND_SIZE);
4425 cmd[0] = MODE_SENSE;
4426 cmd[1] = 8;
4427 cmd[2] = VENDOR_IDENT_PAGE;
4428 cmd[4] = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH;
4429
4430 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_READ, STp->timeout, 0, TRUE);
4431
4432 if (STp->buffer->syscall_result ||
4433 STp->buffer->b_data[MODE_HEADER_LENGTH + 2] != 'L' ||
4434 STp->buffer->b_data[MODE_HEADER_LENGTH + 3] != 'I' ||
4435 STp->buffer->b_data[MODE_HEADER_LENGTH + 4] != 'N' ||
4436 STp->buffer->b_data[MODE_HEADER_LENGTH + 5] != '4' ) {
4437 #if DEBUG
4438 printk(OSST_DEB_MSG "osst%d:D: Signature was changed to %c%c%c%c\n", dev,
4439 STp->buffer->b_data[MODE_HEADER_LENGTH + 2],
4440 STp->buffer->b_data[MODE_HEADER_LENGTH + 3],
4441 STp->buffer->b_data[MODE_HEADER_LENGTH + 4],
4442 STp->buffer->b_data[MODE_HEADER_LENGTH + 5]);
4443 #endif
4444 STp->header_ok = 0;
4445 }
4446 i = STp->first_frame_position;
4447 if (STp->header_ok && i == osst_get_frame_position(STp, &SRpnt)) {
4448 if (STp->door_locked == ST_UNLOCKED) {
4449 if (osst_int_ioctl(STp, &SRpnt, MTLOCK, 0))
4450 printk(KERN_INFO "osst%d:I: Can't lock drive door\n", dev);
4451 else
4452 STp->door_locked = ST_LOCKED_AUTO;
4453 }
4454 if (!STp->frame_in_buffer) {
4455 STp->block_size = (STm->default_blksize > 0) ?
4456 STm->default_blksize : OS_DATA_SIZE;
4457 STp->buffer->buffer_bytes = STp->buffer->read_pointer = 0;
4458 }
4459 STp->buffer->buffer_blocks = OS_DATA_SIZE / STp->block_size;
4460 STp->fast_open = TRUE;
4461 scsi_release_request(SRpnt);
4462 return 0;
4463 }
4464 #if DEBUG
4465 if (i != STp->first_frame_position)
4466 printk(OSST_DEB_MSG "osst%d:D: Tape position changed from %d to %d\n",
4467 dev, i, STp->first_frame_position);
4468 #endif
4469 STp->header_ok = 0;
4470 }
4471 STp->fast_open = FALSE;
4472
4473 if ((STp->buffer)->syscall_result != 0 && /* in all error conditions except no medium */
4474 (SRpnt->sr_sense_buffer[2] != 2 || SRpnt->sr_sense_buffer[12] != 0x3A) ) {
4475
4476 memset(cmd, 0, MAX_COMMAND_SIZE);
4477 cmd[0] = MODE_SELECT;
4478 cmd[1] = 0x10;
4479 cmd[4] = 4 + MODE_HEADER_LENGTH;
4480
4481 (STp->buffer)->b_data[0] = cmd[4] - 1;
4482 (STp->buffer)->b_data[1] = 0; /* Medium Type - ignoring */
4483 (STp->buffer)->b_data[2] = 0; /* Reserved */
4484 (STp->buffer)->b_data[3] = 0; /* Block Descriptor Length */
4485 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = 0x3f;
4486 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 1;
4487 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 2;
4488 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = 3;
4489
4490 #if DEBUG
4491 printk(OSST_DEB_MSG "osst%d:D: Applying soft reset\n", dev);
4492 #endif
4493 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_WRITE, STp->timeout, 0, TRUE);
4494
4495 STp->header_ok = 0;
4496
4497 for (i=0; i < 10; i++) {
4498
4499 memset (cmd, 0, MAX_COMMAND_SIZE);
4500 cmd[0] = TEST_UNIT_READY;
4501
4502 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE,
4503 STp->timeout, MAX_READY_RETRIES, TRUE);
4504 if ((SRpnt->sr_sense_buffer[0] & 0x70) != 0x70 ||
4505 (SRpnt->sr_sense_buffer[2] & 0x0f) == NOT_READY)
4506 break;
4507
4508 if ((SRpnt->sr_sense_buffer[2] & 0x0f) == UNIT_ATTENTION) {
4509 STp->device->was_reset = 0;
4510 STp->partition = STp->new_partition = 0;
4511 if (STp->can_partitions)
4512 STp->nbr_partitions = 1; /* This guess will be updated later if necessary */
4513 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4514 STps = &(STp->ps[i]);
4515 STps->rw = ST_IDLE;
4516 STps->eof = ST_NOEOF;
4517 STps->at_sm = 0;
4518 STps->last_block_valid = FALSE;
4519 STps->drv_block = 0;
4520 STps->drv_file = 0 ;
4521 }
4522 new_session = TRUE;
4523 }
4524 }
4525 }
4526
4527 if (osst_wait_ready(STp, &SRpnt, 15 * 60, 0)) /* FIXME - not allowed with NOBLOCK */
4528 printk(KERN_INFO "osst%i:I: Device did not become Ready in open\n",dev);
4529
4530 if ((STp->buffer)->syscall_result != 0) {
4531 if ((STp->device)->scsi_level >= SCSI_2 &&
4532 (SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
4533 (SRpnt->sr_sense_buffer[2] & 0x0f) == NOT_READY &&
4534 SRpnt->sr_sense_buffer[12] == 0x3a) { /* Check ASC */
4535 STp->ready = ST_NO_TAPE;
4536 } else
4537 STp->ready = ST_NOT_READY;
4538 scsi_release_request(SRpnt);
4539 SRpnt = NULL;
4540 STp->density = 0; /* Clear the erroneous "residue" */
4541 STp->write_prot = 0;
4542 STp->block_size = 0;
4543 STp->ps[0].drv_file = STp->ps[0].drv_block = (-1);
4544 STp->partition = STp->new_partition = 0;
4545 STp->door_locked = ST_UNLOCKED;
4546 return 0;
4547 }
4548
4549 osst_configure_onstream(STp, &SRpnt);
4550
4551 /* STp->drv_write_prot = ((STp->buffer)->b_data[2] & 0x80) != 0; FIXME */
4552
4553 if (OS_FRAME_SIZE > (STp->buffer)->buffer_size &&
4554 !enlarge_buffer(STp->buffer, OS_FRAME_SIZE, STp->restr_dma)) {
4555 printk(KERN_NOTICE "osst%d:A: Framesize %d too large for buffer.\n", dev,
4556 OS_FRAME_SIZE);
4557 retval = (-EIO);
4558 goto err_out;
4559 }
4560
4561 if ((STp->buffer)->buffer_size >= OS_FRAME_SIZE) {
4562 for (i = 0, b_size = 0;
4563 i < STp->buffer->sg_segs && (b_size + STp->buffer->sg[i].length) <= OS_DATA_SIZE;
4564 b_size += STp->buffer->sg[i++].length);
4565 STp->buffer->aux = (os_aux_t *) (STp->buffer->sg[i].address + OS_DATA_SIZE - b_size);
4566 #if DEBUG
4567 printk(OSST_DEB_MSG "osst%d:D: b_data points to %p in segment 0 at %p\n", dev,
4568 STp->buffer->b_data, STp->buffer->sg[0].address);
4569 printk(OSST_DEB_MSG "osst%d:D: AUX points to %p in segment %d at %p\n", dev,
4570 STp->buffer->aux, i, STp->buffer->sg[i].address);
4571 #endif
4572 } else
4573 STp->buffer->aux = NULL; /* this had better never happen! */
4574
4575 STp->block_size = STp->raw ? OS_FRAME_SIZE : (
4576 (STm->default_blksize > 0) ? STm->default_blksize : OS_DATA_SIZE);
4577 STp->buffer->buffer_blocks = STp->raw ? 1 : OS_DATA_SIZE / STp->block_size;
4578 STp->buffer->buffer_bytes =
4579 STp->buffer->read_pointer =
4580 STp->frame_in_buffer = 0;
4581
4582 #if DEBUG
4583 if (debugging)
4584 printk(OSST_DEB_MSG "osst%d:D: Block size: %d, frame size: %d, buffer size: %d (%d blocks).\n",
4585 dev, STp->block_size, OS_FRAME_SIZE, (STp->buffer)->buffer_size,
4586 (STp->buffer)->buffer_blocks);
4587 #endif
4588
4589 if (STp->drv_write_prot) {
4590 STp->write_prot = 1;
4591 #if DEBUG
4592 if (debugging)
4593 printk(OSST_DEB_MSG "osst%d:D: Write protected\n", dev);
4594 #endif
4595 if ((flags & O_ACCMODE) == O_WRONLY || (flags & O_ACCMODE) == O_RDWR) {
4596 retval = (-EROFS);
4597 goto err_out;
4598 }
4599 }
4600
4601 if (new_session) { /* Change the drive parameters for the new mode */
4602 #if DEBUG
4603 if (debugging)
4604 printk(OSST_DEB_MSG "osst%d:D: New Session\n", dev);
4605 #endif
4606 STp->density_changed = STp->blksize_changed = FALSE;
4607 STp->compression_changed = FALSE;
4608 }
4609
4610 /*
4611 * properly position the tape and check the ADR headers
4612 */
4613 if (STp->door_locked == ST_UNLOCKED) {
4614 if (osst_int_ioctl(STp, &SRpnt, MTLOCK, 0))
4615 printk(KERN_INFO "osst%d:I: Can't lock drive door\n", dev);
4616 else
4617 STp->door_locked = ST_LOCKED_AUTO;
4618 }
4619
4620 osst_analyze_headers(STp, &SRpnt);
4621
4622 scsi_release_request(SRpnt);
4623 SRpnt = NULL;
4624
4625 return 0;
4626
4627 err_out:
4628 if (SRpnt != NULL)
4629 scsi_release_request(SRpnt);
4630 if (STp->buffer != NULL) {
4631 STp->buffer->in_use = 0;
4632 STp->buffer = NULL;
4633 }
4634 STp->in_use = 0;
4635 STp->header_ok = 0;
4636 STp->device->access_count--;
4637
4638 if (STp->device->host->hostt->module)
4639 __MOD_DEC_USE_COUNT(STp->device->host->hostt->module);
4640 if (osst_template.module)
4641 __MOD_DEC_USE_COUNT(osst_template.module);
4642
4643 return retval;
4644 }
4645
4646
4647 /* Flush the tape buffer before close */
os_scsi_tape_flush(struct file * filp)4648 static int os_scsi_tape_flush(struct file * filp)
4649 {
4650 int result = 0, result2;
4651 OS_Scsi_Tape * STp;
4652 ST_mode * STm;
4653 ST_partstat * STps;
4654 Scsi_Request *SRpnt = NULL;
4655
4656 struct inode *inode = filp->f_dentry->d_inode;
4657 kdev_t devt = inode->i_rdev;
4658 int dev;
4659
4660 if (file_count(filp) > 1)
4661 return 0;
4662
4663 dev = TAPE_NR(devt);
4664 STp = os_scsi_tapes[dev];
4665 STm = &(STp->modes[STp->current_mode]);
4666 STps = &(STp->ps[STp->partition]);
4667
4668 if ((STps->rw == ST_WRITING || STp->dirty) && !(STp->device)->was_reset) {
4669 STp->write_type = OS_WRITE_DATA;
4670 result = osst_flush_write_buffer(STp, &SRpnt);
4671 if (result != 0 && result != (-ENOSPC))
4672 goto out;
4673 }
4674 if ( STps->rw >= ST_WRITING && !(STp->device)->was_reset) {
4675
4676 #if DEBUG
4677 if (debugging) {
4678 printk(OSST_DEB_MSG "osst%d:D: File length %ld bytes.\n",
4679 dev, (long)(filp->f_pos));
4680 printk(OSST_DEB_MSG "osst%d:D: Async write waits %d, finished %d.\n",
4681 dev, STp->nbr_waits, STp->nbr_finished);
4682 }
4683 #endif
4684 result = osst_write_trailer(STp, &SRpnt, !(STp->rew_at_close));
4685 #if DEBUG
4686 if (debugging)
4687 printk(OSST_DEB_MSG "osst%d:D: Buffer flushed, %d EOF(s) written\n",
4688 dev, 1+STp->two_fm);
4689 #endif
4690 }
4691 else if (!STp->rew_at_close) {
4692 STps = &(STp->ps[STp->partition]);
4693 if (!STm->sysv || STps->rw != ST_READING) {
4694 if (STp->can_bsr)
4695 result = osst_flush_buffer(STp, &SRpnt, 0); /* this is the default path */
4696 else if (STps->eof == ST_FM_HIT) {
4697 result = cross_eof(STp, &SRpnt, FALSE);
4698 if (result) {
4699 if (STps->drv_file >= 0)
4700 STps->drv_file++;
4701 STps->drv_block = 0;
4702 STps->eof = ST_FM;
4703 }
4704 else
4705 STps->eof = ST_NOEOF;
4706 }
4707 }
4708 else if ((STps->eof == ST_NOEOF &&
4709 !(result = cross_eof(STp, &SRpnt, TRUE))) ||
4710 STps->eof == ST_FM_HIT) {
4711 if (STps->drv_file >= 0)
4712 STps->drv_file++;
4713 STps->drv_block = 0;
4714 STps->eof = ST_FM;
4715 }
4716 }
4717
4718 out:
4719 if (STp->rew_at_close) {
4720 result2 = osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos);
4721 STps->drv_file = STps->drv_block = STp->frame_seq_number = STp->logical_blk_num = 0;
4722 if (result == 0 && result2 < 0)
4723 result = result2;
4724 }
4725 if (SRpnt) scsi_release_request(SRpnt);
4726
4727 if (STp->recover_count) {
4728 printk(KERN_INFO "osst%d:I: %d recovered errors in", dev, STp->recover_count);
4729 if (STp->write_count)
4730 printk(" %d frames written", STp->write_count);
4731 if (STp->read_count)
4732 printk(" %d frames read", STp->read_count);
4733 printk("\n");
4734 STp->recover_count = 0;
4735 }
4736 STp->write_count = 0;
4737 STp->read_count = 0;
4738
4739 return result;
4740 }
4741
4742
4743 /* Close the device and release it */
os_scsi_tape_close(struct inode * inode,struct file * filp)4744 static int os_scsi_tape_close(struct inode * inode, struct file * filp)
4745 {
4746 int result = 0;
4747 OS_Scsi_Tape * STp;
4748 Scsi_Request * SRpnt = NULL;
4749
4750 kdev_t devt = inode->i_rdev;
4751 int dev;
4752
4753 dev = TAPE_NR(devt);
4754 STp = os_scsi_tapes[dev];
4755
4756 if (STp->door_locked == ST_LOCKED_AUTO)
4757 osst_int_ioctl(STp, &SRpnt, MTUNLOCK, 0);
4758 if (SRpnt) scsi_release_request(SRpnt);
4759
4760 if (STp->buffer != NULL)
4761 STp->buffer->in_use = 0;
4762
4763 if (STp->raw)
4764 STp->header_ok = 0;
4765
4766 STp->in_use = 0;
4767 STp->device->access_count--;
4768
4769 if (STp->device->host->hostt->module)
4770 __MOD_DEC_USE_COUNT(STp->device->host->hostt->module);
4771 if(osst_template.module)
4772 __MOD_DEC_USE_COUNT(osst_template.module);
4773
4774 return result;
4775 }
4776
4777
4778 /* The ioctl command */
osst_ioctl(struct inode * inode,struct file * file,unsigned int cmd_in,unsigned long arg)4779 static int osst_ioctl(struct inode * inode,struct file * file,
4780 unsigned int cmd_in, unsigned long arg)
4781 {
4782 int i, cmd_nr, cmd_type, retval = 0;
4783 unsigned int blk;
4784 OS_Scsi_Tape *STp;
4785 ST_mode *STm;
4786 ST_partstat *STps;
4787 Scsi_Request *SRpnt = NULL;
4788 int dev = TAPE_NR(inode->i_rdev);
4789
4790 STp = os_scsi_tapes[dev];
4791
4792 if (down_interruptible(&STp->lock))
4793 return -ERESTARTSYS;
4794
4795 #if DEBUG
4796 if (debugging && !STp->in_use) {
4797 printk(OSST_DEB_MSG "osst%d:D: Incorrect device.\n", dev);
4798 retval = (-EIO);
4799 goto out;
4800 }
4801 #endif
4802 STm = &(STp->modes[STp->current_mode]);
4803 STps = &(STp->ps[STp->partition]);
4804
4805 /*
4806 * If we are in the middle of error recovery, don't let anyone
4807 * else try and use this device. Also, if error recovery fails, it
4808 * may try and take the device offline, in which case all further
4809 * access to the device is prohibited.
4810 */
4811 if( !scsi_block_when_processing_errors(STp->device) ) {
4812 retval = (-ENXIO);
4813 goto out;
4814 }
4815
4816 cmd_type = _IOC_TYPE(cmd_in);
4817 cmd_nr = _IOC_NR(cmd_in);
4818 #if DEBUG
4819 printk(OSST_DEB_MSG "osst%d:D: Ioctl %d,%d in %s mode\n", dev,
4820 cmd_type, cmd_nr, STp->raw?"raw":"normal");
4821 #endif
4822 if (cmd_type == _IOC_TYPE(MTIOCTOP) && cmd_nr == _IOC_NR(MTIOCTOP)) {
4823 struct mtop mtc;
4824 int auto_weof = 0;
4825
4826 if (_IOC_SIZE(cmd_in) != sizeof(mtc)) {
4827 retval = (-EINVAL);
4828 goto out;
4829 }
4830
4831 i = copy_from_user((char *) &mtc, (char *)arg, sizeof(struct mtop));
4832 if (i) {
4833 retval = (-EFAULT);
4834 goto out;
4835 }
4836
4837 if (mtc.mt_op == MTSETDRVBUFFER && !capable(CAP_SYS_ADMIN)) {
4838 printk(KERN_WARNING "osst%d:W: MTSETDRVBUFFER only allowed for root.\n", dev);
4839 retval = (-EPERM);
4840 goto out;
4841 }
4842
4843 if (!STm->defined && (mtc.mt_op != MTSETDRVBUFFER && (mtc.mt_count & MT_ST_OPTIONS) == 0)) {
4844 retval = (-ENXIO);
4845 goto out;
4846 }
4847
4848 if (!(STp->device)->was_reset) {
4849
4850 if (STps->eof == ST_FM_HIT) {
4851 if (mtc.mt_op == MTFSF || mtc.mt_op == MTFSFM|| mtc.mt_op == MTEOM) {
4852 mtc.mt_count -= 1;
4853 if (STps->drv_file >= 0)
4854 STps->drv_file += 1;
4855 }
4856 else if (mtc.mt_op == MTBSF || mtc.mt_op == MTBSFM) {
4857 mtc.mt_count += 1;
4858 if (STps->drv_file >= 0)
4859 STps->drv_file += 1;
4860 }
4861 }
4862
4863 if (mtc.mt_op == MTSEEK) {
4864 /* Old position must be restored if partition will be changed */
4865 i = !STp->can_partitions || (STp->new_partition != STp->partition);
4866 }
4867 else {
4868 i = mtc.mt_op == MTREW || mtc.mt_op == MTOFFL ||
4869 mtc.mt_op == MTRETEN || mtc.mt_op == MTEOM ||
4870 mtc.mt_op == MTLOCK || mtc.mt_op == MTLOAD ||
4871 mtc.mt_op == MTCOMPRESSION;
4872 }
4873 i = osst_flush_buffer(STp, &SRpnt, i);
4874 if (i < 0) {
4875 retval = i;
4876 goto out;
4877 }
4878 }
4879 else {
4880 /*
4881 * If there was a bus reset, block further access
4882 * to this device. If the user wants to rewind the tape,
4883 * then reset the flag and allow access again.
4884 */
4885 if(mtc.mt_op != MTREW &&
4886 mtc.mt_op != MTOFFL &&
4887 mtc.mt_op != MTRETEN &&
4888 mtc.mt_op != MTERASE &&
4889 mtc.mt_op != MTSEEK &&
4890 mtc.mt_op != MTEOM) {
4891 retval = (-EIO);
4892 goto out;
4893 }
4894 STp->device->was_reset = 0;
4895 if (STp->door_locked != ST_UNLOCKED &&
4896 STp->door_locked != ST_LOCK_FAILS) {
4897 if (osst_int_ioctl(STp, &SRpnt, MTLOCK, 0)) {
4898 printk(KERN_NOTICE "osst%d:I: Could not relock door after bus reset.\n",
4899 dev);
4900 STp->door_locked = ST_UNLOCKED;
4901 }
4902 }
4903 }
4904
4905 if (mtc.mt_op != MTCOMPRESSION && mtc.mt_op != MTLOCK &&
4906 mtc.mt_op != MTNOP && mtc.mt_op != MTSETBLK &&
4907 mtc.mt_op != MTSETDENSITY && mtc.mt_op != MTSETDRVBUFFER &&
4908 mtc.mt_op != MTMKPART && mtc.mt_op != MTSETPART &&
4909 mtc.mt_op != MTWEOF && mtc.mt_op != MTWSM ) {
4910
4911 /*
4912 * The user tells us to move to another position on the tape.
4913 * If we were appending to the tape content, that would leave
4914 * the tape without proper end, in that case write EOD and
4915 * update the header to reflect its position.
4916 */
4917 #if DEBUG
4918 printk(KERN_WARNING "osst%d:D: auto_weod %s at ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n",dev,
4919 STps->rw >= ST_WRITING ? "write" : STps->rw == ST_READING ? "read" : "idle",
4920 STp->first_frame_position, STp->eod_frame_ppos, STp->frame_seq_number,
4921 STp->logical_blk_num, STps->drv_file, STps->drv_block );
4922 #endif
4923 if (STps->rw >= ST_WRITING && STp->first_frame_position >= STp->eod_frame_ppos) {
4924 auto_weof = ((STp->write_type != OS_WRITE_NEW_MARK) &&
4925 !(mtc.mt_op == MTREW || mtc.mt_op == MTOFFL));
4926 i = osst_write_trailer(STp, &SRpnt,
4927 !(mtc.mt_op == MTREW || mtc.mt_op == MTOFFL));
4928 #if DEBUG
4929 printk(KERN_WARNING "osst%d:D: post trailer xeof=%d,ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n",
4930 dev, auto_weof, STp->first_frame_position, STp->eod_frame_ppos,
4931 STp->frame_seq_number, STp->logical_blk_num, STps->drv_file, STps->drv_block );
4932 #endif
4933 if (i < 0) {
4934 retval = i;
4935 goto out;
4936 }
4937 }
4938 STps->rw = ST_IDLE;
4939 }
4940
4941 if (mtc.mt_op == MTOFFL && STp->door_locked != ST_UNLOCKED)
4942 osst_int_ioctl(STp, &SRpnt, MTUNLOCK, 0); /* Ignore result! */
4943
4944 if (mtc.mt_op == MTSETDRVBUFFER &&
4945 (mtc.mt_count & MT_ST_OPTIONS) != 0) {
4946 retval = osst_set_options(STp, mtc.mt_count);
4947 goto out;
4948 }
4949
4950 if (mtc.mt_op == MTSETPART) {
4951 if (mtc.mt_count >= STp->nbr_partitions)
4952 retval = -EINVAL;
4953 else {
4954 STp->new_partition = mtc.mt_count;
4955 retval = 0;
4956 }
4957 goto out;
4958 }
4959
4960 if (mtc.mt_op == MTMKPART) {
4961 if (!STp->can_partitions) {
4962 retval = (-EINVAL);
4963 goto out;
4964 }
4965 if ((i = osst_int_ioctl(STp, &SRpnt, MTREW, 0)) < 0 /*||
4966 (i = partition_tape(inode, mtc.mt_count)) < 0*/) {
4967 retval = i;
4968 goto out;
4969 }
4970 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4971 STp->ps[i].rw = ST_IDLE;
4972 STp->ps[i].at_sm = 0;
4973 STp->ps[i].last_block_valid = FALSE;
4974 }
4975 STp->partition = STp->new_partition = 0;
4976 STp->nbr_partitions = 1; /* Bad guess ?-) */
4977 STps->drv_block = STps->drv_file = 0;
4978 retval = 0;
4979 goto out;
4980 }
4981
4982 if (mtc.mt_op == MTSEEK) {
4983 if (STp->raw)
4984 i = osst_set_frame_position(STp, &SRpnt, mtc.mt_count, 0);
4985 else
4986 i = osst_seek_sector(STp, &SRpnt, mtc.mt_count);
4987 if (!STp->can_partitions)
4988 STp->ps[0].rw = ST_IDLE;
4989 retval = i;
4990 goto out;
4991 }
4992
4993 if (auto_weof)
4994 cross_eof(STp, &SRpnt, FALSE);
4995
4996 if (mtc.mt_op == MTCOMPRESSION)
4997 retval = -EINVAL; /* OnStream drives don't have compression hardware */
4998 else
4999 /* MTBSF MTBSFM MTBSR MTBSS MTEOM MTERASE MTFSF MTFSFB MTFSR MTFSS MTLOAD
5000 * MTLOCK MTOFFL MTRESET MTRETEN MTREW MTUNLOAD MTUNLOCK MTWEOF MTWSM */
5001 retval = osst_int_ioctl(STp, &SRpnt, mtc.mt_op, mtc.mt_count);
5002 goto out;
5003 }
5004
5005 if (!STm->defined) {
5006 retval = (-ENXIO);
5007 goto out;
5008 }
5009
5010 if ((i = osst_flush_buffer(STp, &SRpnt, FALSE)) < 0) {
5011 retval = i;
5012 goto out;
5013 }
5014
5015 if (cmd_type == _IOC_TYPE(MTIOCGET) && cmd_nr == _IOC_NR(MTIOCGET)) {
5016 struct mtget mt_status;
5017
5018 if (_IOC_SIZE(cmd_in) != sizeof(struct mtget)) {
5019 retval = (-EINVAL);
5020 goto out;
5021 }
5022
5023 mt_status.mt_type = MT_ISONSTREAM_SC;
5024 mt_status.mt_erreg = STp->recover_erreg << MT_ST_SOFTERR_SHIFT;
5025 mt_status.mt_dsreg =
5026 ((STp->block_size << MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK) |
5027 ((STp->density << MT_ST_DENSITY_SHIFT) & MT_ST_DENSITY_MASK);
5028 mt_status.mt_blkno = STps->drv_block;
5029 mt_status.mt_fileno = STps->drv_file;
5030 if (STp->block_size != 0) {
5031 if (STps->rw == ST_WRITING)
5032 mt_status.mt_blkno += (STp->buffer)->buffer_bytes / STp->block_size;
5033 else if (STps->rw == ST_READING)
5034 mt_status.mt_blkno -= ((STp->buffer)->buffer_bytes +
5035 STp->block_size - 1) / STp->block_size;
5036 }
5037
5038 mt_status.mt_gstat = 0;
5039 if (STp->drv_write_prot)
5040 mt_status.mt_gstat |= GMT_WR_PROT(0xffffffff);
5041 if (mt_status.mt_blkno == 0) {
5042 if (mt_status.mt_fileno == 0)
5043 mt_status.mt_gstat |= GMT_BOT(0xffffffff);
5044 else
5045 mt_status.mt_gstat |= GMT_EOF(0xffffffff);
5046 }
5047 mt_status.mt_resid = STp->partition;
5048 if (STps->eof == ST_EOM_OK || STps->eof == ST_EOM_ERROR)
5049 mt_status.mt_gstat |= GMT_EOT(0xffffffff);
5050 else if (STps->eof >= ST_EOM_OK)
5051 mt_status.mt_gstat |= GMT_EOD(0xffffffff);
5052 if (STp->density == 1)
5053 mt_status.mt_gstat |= GMT_D_800(0xffffffff);
5054 else if (STp->density == 2)
5055 mt_status.mt_gstat |= GMT_D_1600(0xffffffff);
5056 else if (STp->density == 3)
5057 mt_status.mt_gstat |= GMT_D_6250(0xffffffff);
5058 if (STp->ready == ST_READY)
5059 mt_status.mt_gstat |= GMT_ONLINE(0xffffffff);
5060 if (STp->ready == ST_NO_TAPE)
5061 mt_status.mt_gstat |= GMT_DR_OPEN(0xffffffff);
5062 if (STps->at_sm)
5063 mt_status.mt_gstat |= GMT_SM(0xffffffff);
5064 if (STm->do_async_writes || (STm->do_buffer_writes && STp->block_size != 0) ||
5065 STp->drv_buffer != 0)
5066 mt_status.mt_gstat |= GMT_IM_REP_EN(0xffffffff);
5067
5068 i = copy_to_user((char *)arg, (char *)&mt_status,
5069 sizeof(struct mtget));
5070 if (i) {
5071 retval = (-EFAULT);
5072 goto out;
5073 }
5074
5075 STp->recover_erreg = 0; /* Clear after read */
5076 retval = 0;
5077 goto out;
5078 } /* End of MTIOCGET */
5079
5080 if (cmd_type == _IOC_TYPE(MTIOCPOS) && cmd_nr == _IOC_NR(MTIOCPOS)) {
5081 struct mtpos mt_pos;
5082
5083 if (_IOC_SIZE(cmd_in) != sizeof(struct mtpos)) {
5084 retval = (-EINVAL);
5085 goto out;
5086 }
5087 if (STp->raw)
5088 blk = osst_get_frame_position(STp, &SRpnt);
5089 else
5090 blk = osst_get_sector(STp, &SRpnt);
5091 if (blk < 0) {
5092 retval = blk;
5093 goto out;
5094 }
5095 mt_pos.mt_blkno = blk;
5096 i = copy_to_user((char *)arg, (char *) (&mt_pos), sizeof(struct mtpos));
5097 if (i)
5098 retval = -EFAULT;
5099 goto out;
5100 }
5101 if (SRpnt) scsi_release_request(SRpnt);
5102
5103 up(&STp->lock);
5104
5105 return scsi_ioctl(STp->device, cmd_in, (void *) arg);
5106
5107 out:
5108 if (SRpnt) scsi_release_request(SRpnt);
5109
5110 up(&STp->lock);
5111
5112 return retval;
5113 }
5114
5115
5116 /* Memory handling routines */
5117
5118 /* Try to allocate a new tape buffer */
new_tape_buffer(int from_initialization,int need_dma)5119 static OSST_buffer * new_tape_buffer( int from_initialization, int need_dma )
5120 {
5121 int i, priority, b_size, order, got = 0, segs = 0;
5122 OSST_buffer *tb;
5123
5124 if (osst_nbr_buffers >= osst_template.dev_max)
5125 return NULL; /* Should never happen */
5126
5127 if (from_initialization)
5128 priority = GFP_ATOMIC;
5129 else
5130 priority = GFP_KERNEL;
5131
5132 i = sizeof(OSST_buffer) + (osst_max_sg_segs - 1) * sizeof(struct scatterlist);
5133 tb = (OSST_buffer *)kmalloc(i, priority);
5134 if (tb) {
5135 // tb->this_size = i;
5136 if (need_dma)
5137 priority |= GFP_DMA;
5138
5139 /* Try to allocate the first segment up to OSST_FIRST_ORDER and the
5140 others big enough to reach the goal */
5141 for (b_size = PAGE_SIZE, order = 0;
5142 b_size < osst_buffer_size && order < OSST_FIRST_ORDER;
5143 b_size *= 2, order++ );
5144
5145 for ( ; b_size >= PAGE_SIZE; order--, b_size /= 2) {
5146 tb->sg[0].address =
5147 (unsigned char *)__get_free_pages(priority, order);
5148 if (tb->sg[0].address != NULL) {
5149 tb->sg[0].page = NULL;
5150 tb->sg[0].length = b_size;
5151 break;
5152 }
5153 }
5154 if (tb->sg[segs].address == NULL) {
5155 kfree(tb);
5156 tb = NULL;
5157 }
5158 else { /* Got something, continue */
5159
5160 for (b_size = PAGE_SIZE, order = 0;
5161 osst_buffer_size > tb->sg[0].length + (OSST_FIRST_SG - 1) * b_size;
5162 b_size *= 2, order++ );
5163
5164 for (segs=1, got=tb->sg[0].length;
5165 got < osst_buffer_size && segs < OSST_FIRST_SG; ) {
5166 tb->sg[segs].address =
5167 (unsigned char *)__get_free_pages(priority, order);
5168 if (tb->sg[segs].address == NULL) {
5169 if (osst_buffer_size - got <=
5170 (OSST_FIRST_SG - segs) * b_size / 2) {
5171 b_size /= 2; /* Large enough for the rest of the buffers */
5172 order--;
5173 continue;
5174 }
5175 tb->sg_segs = segs;
5176 tb->orig_sg_segs = 0;
5177 #if DEBUG
5178 tb->buffer_size = got;
5179 #endif
5180 normalize_buffer(tb);
5181 kfree(tb);
5182 tb = NULL;
5183 break;
5184 }
5185 tb->sg[segs].page = NULL;
5186 tb->sg[segs].length = b_size;
5187 got += b_size;
5188 segs++;
5189 }
5190 }
5191 }
5192 if (!tb) {
5193 printk(KERN_NOTICE "osst :I: Can't allocate new tape buffer (nbr %d).\n",
5194 osst_nbr_buffers);
5195 return NULL;
5196 }
5197 tb->sg_segs = tb->orig_sg_segs = segs;
5198 tb->b_data = tb->sg[0].address;
5199
5200 #if DEBUG
5201 if (debugging) {
5202 printk(OSST_DEB_MSG
5203 "osst :D: Allocated tape buffer %d (%d bytes, %d segments, dma: %d, a: %p).\n",
5204 osst_nbr_buffers, got, tb->sg_segs, need_dma, tb->b_data);
5205 printk(OSST_DEB_MSG
5206 "osst :D: segment sizes: first %d, last %d bytes.\n",
5207 tb->sg[0].length, tb->sg[segs-1].length);
5208 }
5209 #endif
5210 tb->in_use = 0;
5211 tb->dma = need_dma;
5212 tb->buffer_size = got;
5213 tb->writing = 0;
5214 osst_buffers[osst_nbr_buffers++] = tb;
5215
5216 return tb;
5217 }
5218
5219
5220 /* Try to allocate a temporary enlarged tape buffer */
enlarge_buffer(OSST_buffer * STbuffer,int new_size,int need_dma)5221 static int enlarge_buffer(OSST_buffer *STbuffer, int new_size, int need_dma)
5222 {
5223 int segs, nbr, max_segs, b_size, priority, order, got;
5224
5225 normalize_buffer(STbuffer);
5226
5227 max_segs = STbuffer->use_sg;
5228 if (max_segs > osst_max_sg_segs)
5229 max_segs = osst_max_sg_segs;
5230 nbr = max_segs - STbuffer->sg_segs;
5231 if (nbr <= 0)
5232 return FALSE;
5233
5234 priority = GFP_KERNEL;
5235 if (need_dma)
5236 priority |= GFP_DMA;
5237 for (b_size = PAGE_SIZE, order = 0;
5238 b_size * nbr < new_size - STbuffer->buffer_size;
5239 b_size *= 2, order++);
5240
5241 for (segs=STbuffer->sg_segs, got=STbuffer->buffer_size;
5242 segs < max_segs && got < new_size; ) {
5243 STbuffer->sg[segs].address =
5244 (unsigned char *)__get_free_pages(priority,
5245 (new_size - got <= PAGE_SIZE) ? 0 : order);
5246 if (STbuffer->sg[segs].address == NULL) {
5247 if (new_size - got <= (max_segs - segs) * b_size / 2 && order) {
5248 b_size /= 2; /* Large enough for the rest of the buffers */
5249 order--;
5250 continue;
5251 }
5252 printk(KERN_WARNING "osst :W: Failed to enlarge buffer to %d bytes.\n",
5253 new_size);
5254 #if DEBUG
5255 STbuffer->buffer_size = got;
5256 #endif
5257 normalize_buffer(STbuffer);
5258 return FALSE;
5259 }
5260 STbuffer->sg[segs].page = NULL;
5261 STbuffer->sg[segs].length = (new_size - got <= PAGE_SIZE / 2) ? (new_size - got) : b_size;
5262 STbuffer->sg_segs += 1;
5263 got += STbuffer->sg[segs].length;
5264 STbuffer->buffer_size = got;
5265 segs++;
5266 }
5267 #if DEBUG
5268 if (debugging) {
5269 for (nbr=0; osst_buffers[nbr] != STbuffer && nbr < osst_nbr_buffers; nbr++);
5270 printk(OSST_DEB_MSG
5271 "osst :D: Expanded tape buffer %d (%d bytes, %d->%d segments, dma: %d, a: %p).\n",
5272 nbr, got, STbuffer->orig_sg_segs, STbuffer->sg_segs, need_dma, STbuffer->b_data);
5273 printk(OSST_DEB_MSG
5274 "osst :D: segment sizes: first %d, last %d bytes.\n",
5275 STbuffer->sg[0].length, STbuffer->sg[segs-1].length);
5276 }
5277 #endif
5278
5279 return TRUE;
5280 }
5281
5282
5283 /* Release the extra buffer */
normalize_buffer(OSST_buffer * STbuffer)5284 static void normalize_buffer(OSST_buffer *STbuffer)
5285 {
5286 int i, order, b_size;
5287
5288 for (i=STbuffer->orig_sg_segs; i < STbuffer->sg_segs; i++) {
5289
5290 for (b_size = PAGE_SIZE, order = 0;
5291 b_size < STbuffer->sg[i].length;
5292 b_size *= 2, order++);
5293
5294 free_pages((unsigned long)STbuffer->sg[i].address, order);
5295 STbuffer->buffer_size -= STbuffer->sg[i].length;
5296 }
5297 #if DEBUG
5298 if (debugging && STbuffer->orig_sg_segs < STbuffer->sg_segs)
5299 printk(OSST_DEB_MSG "osst :D: Buffer at %p normalized to %d bytes (segs %d).\n",
5300 STbuffer->b_data, STbuffer->buffer_size, STbuffer->sg_segs);
5301 #endif
5302 STbuffer->sg_segs = STbuffer->orig_sg_segs;
5303 }
5304
5305
5306 /* Move data from the user buffer to the tape buffer. Returns zero (success) or
5307 negative error code. */
append_to_buffer(const char * ubp,OSST_buffer * st_bp,int do_count)5308 static int append_to_buffer(const char *ubp, OSST_buffer *st_bp, int do_count)
5309 {
5310 int i, cnt, res, offset;
5311
5312 for (i=0, offset=st_bp->buffer_bytes;
5313 i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5314 offset -= st_bp->sg[i].length;
5315 if (i == st_bp->sg_segs) { /* Should never happen */
5316 printk(KERN_WARNING "osst :A: Append_to_buffer offset overflow.\n");
5317 return (-EIO);
5318 }
5319 for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
5320 cnt = st_bp->sg[i].length - offset < do_count ?
5321 st_bp->sg[i].length - offset : do_count;
5322 res = copy_from_user(st_bp->sg[i].address + offset, ubp, cnt);
5323 if (res)
5324 return (-EFAULT);
5325 do_count -= cnt;
5326 st_bp->buffer_bytes += cnt;
5327 ubp += cnt;
5328 offset = 0;
5329 }
5330 if (do_count) { /* Should never happen */
5331 printk(KERN_WARNING "osst :A: Append_to_buffer overflow (left %d).\n",
5332 do_count);
5333 return (-EIO);
5334 }
5335 return 0;
5336 }
5337
5338
5339 /* Move data from the tape buffer to the user buffer. Returns zero (success) or
5340 negative error code. */
from_buffer(OSST_buffer * st_bp,char * ubp,int do_count)5341 static int from_buffer(OSST_buffer *st_bp, char *ubp, int do_count)
5342 {
5343 int i, cnt, res, offset;
5344
5345 for (i=0, offset=st_bp->read_pointer;
5346 i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5347 offset -= st_bp->sg[i].length;
5348 if (i == st_bp->sg_segs) { /* Should never happen */
5349 printk(KERN_WARNING "osst :A: From_buffer offset overflow.\n");
5350 return (-EIO);
5351 }
5352 for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
5353 cnt = st_bp->sg[i].length - offset < do_count ?
5354 st_bp->sg[i].length - offset : do_count;
5355 res = copy_to_user(ubp, st_bp->sg[i].address + offset, cnt);
5356 if (res)
5357 return (-EFAULT);
5358 do_count -= cnt;
5359 st_bp->buffer_bytes -= cnt;
5360 st_bp->read_pointer += cnt;
5361 ubp += cnt;
5362 offset = 0;
5363 }
5364 if (do_count) { /* Should never happen */
5365 printk(KERN_WARNING "osst :A: From_buffer overflow (left %d).\n", do_count);
5366 return (-EIO);
5367 }
5368 return 0;
5369 }
5370
5371 /* Sets the tail of the buffer after fill point to zero.
5372 Returns zero (success) or negative error code. */
osst_zero_buffer_tail(OSST_buffer * st_bp)5373 static int osst_zero_buffer_tail(OSST_buffer *st_bp)
5374 {
5375 int i, offset, do_count, cnt;
5376
5377 for (i = 0, offset = st_bp->buffer_bytes;
5378 i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5379 offset -= st_bp->sg[i].length;
5380 if (i == st_bp->sg_segs) { /* Should never happen */
5381 printk(KERN_WARNING "osst :A: Zero_buffer offset overflow.\n");
5382 return (-EIO);
5383 }
5384 for (do_count = OS_DATA_SIZE - st_bp->buffer_bytes;
5385 i < st_bp->sg_segs && do_count > 0; i++) {
5386 cnt = st_bp->sg[i].length - offset < do_count ?
5387 st_bp->sg[i].length - offset : do_count ;
5388 memset(st_bp->sg[i].address + offset, 0, cnt);
5389 do_count -= cnt;
5390 offset = 0;
5391 }
5392 if (do_count) { /* Should never happen */
5393 printk(KERN_WARNING "osst :A: Zero_buffer overflow (left %d).\n", do_count);
5394 return (-EIO);
5395 }
5396 return 0;
5397 }
5398
5399 /* Copy a osst 32K chunk of memory into the buffer.
5400 Returns zero (success) or negative error code. */
osst_copy_to_buffer(OSST_buffer * st_bp,unsigned char * ptr)5401 static int osst_copy_to_buffer(OSST_buffer *st_bp, unsigned char *ptr)
5402 {
5403 int i, cnt, do_count = OS_DATA_SIZE;
5404
5405 for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) {
5406 cnt = st_bp->sg[i].length < do_count ?
5407 st_bp->sg[i].length : do_count ;
5408 memcpy(st_bp->sg[i].address, ptr, cnt);
5409 do_count -= cnt;
5410 ptr += cnt;
5411 }
5412 if (do_count || i != st_bp->sg_segs-1) { /* Should never happen */
5413 printk(KERN_WARNING "osst :A: Copy_to_buffer overflow (left %d at sg %d).\n",
5414 do_count, i);
5415 return (-EIO);
5416 }
5417 return 0;
5418 }
5419
5420 /* Copy a osst 32K chunk of memory from the buffer.
5421 Returns zero (success) or negative error code. */
osst_copy_from_buffer(OSST_buffer * st_bp,unsigned char * ptr)5422 static int osst_copy_from_buffer(OSST_buffer *st_bp, unsigned char *ptr)
5423 {
5424 int i, cnt, do_count = OS_DATA_SIZE;
5425
5426 for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) {
5427 cnt = st_bp->sg[i].length < do_count ?
5428 st_bp->sg[i].length : do_count ;
5429 memcpy(ptr, st_bp->sg[i].address, cnt);
5430 do_count -= cnt;
5431 ptr += cnt;
5432 }
5433 if (do_count || i != st_bp->sg_segs-1) { /* Should never happen */
5434 printk(KERN_WARNING "osst :A: Copy_from_buffer overflow (left %d at sg %d).\n",
5435 do_count, i);
5436 return (-EIO);
5437 }
5438 return 0;
5439 }
5440
5441
5442 /* Module housekeeping */
5443
validate_options(void)5444 static void validate_options (void)
5445 {
5446 if (max_dev > 0)
5447 osst_max_dev = osst_max_buffers = max_dev;
5448 if (write_threshold_kbs > 0)
5449 osst_write_threshold = write_threshold_kbs * ST_KILOBYTE;
5450 if (osst_write_threshold > osst_buffer_size)
5451 osst_write_threshold = osst_buffer_size;
5452 if (max_sg_segs >= OSST_FIRST_SG)
5453 osst_max_sg_segs = max_sg_segs;
5454 #if DEBUG
5455 printk(OSST_DEB_MSG "osst :D: bufsize %d, wrt %d, max devices %d, s/g segs %d.\n",
5456 osst_buffer_size, osst_write_threshold, osst_max_buffers, osst_max_sg_segs);
5457 #endif
5458 }
5459
5460 #ifndef MODULE
5461 /* Set the boot options. Syntax: osst=xxx,yyy,zzz
5462 * where xxx is maximum nr of devices to attach,
5463 * yyy is write threshold in 1024 byte blocks
5464 * and zzz the maximum nr of s/g segments to handle.
5465 */
osst_setup(char * str)5466 static int __init osst_setup (char *str)
5467 {
5468 int i, ints[5];
5469 char *stp;
5470
5471 stp = get_options(str, ARRAY_SIZE(ints), ints);
5472
5473 if (ints[0] > 0) {
5474 for (i = 0; i < ints[0] && i < ARRAY_SIZE(parms); i++)
5475 *parms[i].val = ints[i + 1];
5476 } else {
5477 while (stp != NULL) {
5478 for (i = 0; i < ARRAY_SIZE(parms); i++) {
5479 int len = strlen(parms[i].name);
5480 if (!strncmp(stp, parms[i].name, len) &&
5481 (*(stp + len) == ':' || *(stp + len) == '=')) {
5482 *parms[i].val =
5483 simple_strtoul(stp + len + 1, NULL, 0);
5484 break;
5485 }
5486 }
5487 if (i >= sizeof(parms) / sizeof(struct osst_dev_parm))
5488 printk(KERN_INFO "osst :I: Illegal parameter in '%s'\n",
5489 stp);
5490 stp = strchr(stp, ',');
5491 if (stp)
5492 stp++;
5493 }
5494 }
5495
5496 return 1;
5497 }
5498
5499 __setup("osst=", osst_setup);
5500
5501 #endif
5502
5503
5504 static struct file_operations osst_fops = {
5505 read: osst_read,
5506 write: osst_write,
5507 ioctl: osst_ioctl,
5508 open: os_scsi_tape_open,
5509 flush: os_scsi_tape_flush,
5510 release: os_scsi_tape_close,
5511 };
5512
osst_supports(Scsi_Device * SDp)5513 static int osst_supports(Scsi_Device * SDp)
5514 {
5515 struct osst_support_data {
5516 char *vendor;
5517 char *model;
5518 char *rev;
5519 char *driver_hint; /* Name of the correct driver, NULL if unknown */
5520 };
5521
5522 static struct osst_support_data support_list[] = {
5523 /* {"XXX", "Yy-", "", NULL}, example */
5524 SIGS_FROM_OSST,
5525 {NULL, }};
5526
5527 struct osst_support_data *rp;
5528
5529 /* We are willing to drive OnStream SC-x0 as well as the
5530 * * IDE, ParPort, FireWire, USB variants, if accessible by
5531 * * emulation layer (ide-scsi, usb-storage, ...) */
5532
5533 for (rp=&(support_list[0]); rp->vendor != NULL; rp++)
5534 if (!strncmp(rp->vendor, SDp->vendor, strlen(rp->vendor)) &&
5535 !strncmp(rp->model, SDp->model, strlen(rp->model)) &&
5536 !strncmp(rp->rev, SDp->rev, strlen(rp->rev)))
5537 return 1;
5538 return 0;
5539 }
5540
5541 /*
5542 * /proc support for accessing ADR header information
5543 */
5544 static struct proc_dir_entry * osst_proc_dir = NULL;
5545 static char osst_proc_dirname[] = "osst";
5546
osst_proc_read(char * page,char ** start,off_t off,int count,int * eof,void * data)5547 static int osst_proc_read(char *page, char **start, off_t off, int count, int *eof, void *data)
5548 {
5549 int l = 0;
5550 OS_Scsi_Tape * STp = (OS_Scsi_Tape *) data;
5551
5552 if (!osst_proc_dir) return 0;
5553
5554 if (STp->header_ok && STp->linux_media)
5555 l = sprintf(page, "%d.%d LIN%d %8d %8d %8d \n",
5556 STp->header_cache->major_rev,
5557 STp->header_cache->minor_rev,
5558 STp->linux_media_version,
5559 STp->first_data_ppos,
5560 STp->eod_frame_ppos,
5561 STp->filemark_cnt );
5562 return l;
5563 }
5564
osst_proc_init(void)5565 static void osst_proc_init(void)
5566 {
5567 if (!proc_scsi) return;
5568
5569 osst_proc_dir = proc_mkdir(osst_proc_dirname, proc_scsi);
5570 osst_proc_dir->owner = THIS_MODULE;
5571 }
5572
osst_proc_create(OS_Scsi_Tape * STp,int dev)5573 static void osst_proc_create(OS_Scsi_Tape * STp, int dev)
5574 {
5575 char s[16];
5576 struct proc_dir_entry * p_entry;
5577
5578 if (!osst_proc_dir) return;
5579
5580 sprintf(s, "osst%d", dev);
5581 p_entry = create_proc_read_entry(s, 0444, osst_proc_dir, osst_proc_read, (void *) STp);
5582 p_entry->owner = THIS_MODULE;
5583 }
5584
osst_proc_destroy(int dev)5585 static void osst_proc_destroy(int dev)
5586 {
5587 char s[16];
5588
5589 if (!osst_proc_dir) return;
5590
5591 sprintf(s, "osst%d", dev);
5592 remove_proc_entry(s, osst_proc_dir);
5593 }
5594
osst_proc_cleanup(void)5595 static void osst_proc_cleanup(void)
5596 {
5597 if ((! proc_scsi) || (!osst_proc_dir)) return;
5598
5599 remove_proc_entry(osst_proc_dirname, proc_scsi);
5600 osst_proc_dir = NULL;
5601 }
5602
5603 /*
5604 * osst startup / cleanup code
5605 */
5606
osst_attach(Scsi_Device * SDp)5607 static int osst_attach(Scsi_Device * SDp)
5608 {
5609 OS_Scsi_Tape * tpnt;
5610 ST_mode * STm;
5611 ST_partstat * STps;
5612 int i, dev;
5613 #ifdef CONFIG_DEVFS_FS
5614 int mode;
5615 #endif
5616
5617 if (SDp->type != TYPE_TAPE || !osst_supports(SDp))
5618 return 1;
5619
5620 if (osst_template.nr_dev >= osst_template.dev_max) {
5621 SDp->attached--;
5622 return 1;
5623 }
5624
5625 /* find a free minor number */
5626 for (i=0; os_scsi_tapes[i] && i<osst_template.dev_max; i++);
5627 if(i >= osst_template.dev_max) panic ("Scsi_devices corrupt (osst)");
5628
5629 /* allocate a OS_Scsi_Tape for this device */
5630 tpnt = (OS_Scsi_Tape *)kmalloc(sizeof(OS_Scsi_Tape), GFP_ATOMIC);
5631 if (tpnt == NULL) {
5632 SDp->attached--;
5633 printk(KERN_WARNING "osst :W: Can't allocate device descriptor.\n");
5634 return 1;
5635 }
5636 memset(tpnt, 0, sizeof(OS_Scsi_Tape));
5637 os_scsi_tapes[i] = tpnt;
5638 dev = i;
5639 tpnt->capacity = 0xfffff;
5640
5641 /* allocate a buffer for this device */
5642 if (!new_tape_buffer(TRUE, TRUE))
5643 printk(KERN_ERR "osst :W: Unable to allocate a tape buffer.\n");
5644
5645 #ifdef CONFIG_DEVFS_FS
5646 for (mode = 0; mode < ST_NBR_MODES; ++mode) {
5647 char name[8];
5648 static char *formats[ST_NBR_MODES] ={"", "l", "m", "a"};
5649
5650 /* Rewind entry */
5651 sprintf (name, "mt%s", formats[mode]);
5652 tpnt->de_r[mode] =
5653 devfs_register (SDp->de, name, DEVFS_FL_DEFAULT,
5654 MAJOR_NR, i + (mode << 5),
5655 S_IFCHR | S_IRUGO | S_IWUGO,
5656 &osst_fops, NULL);
5657 /* No-rewind entry */
5658 sprintf (name, "mt%sn", formats[mode]);
5659 tpnt->de_n[mode] =
5660 devfs_register (SDp->de, name, DEVFS_FL_DEFAULT,
5661 MAJOR_NR, i + (mode << 5) + 128,
5662 S_IFCHR | S_IRUGO | S_IWUGO,
5663 &osst_fops, NULL);
5664 }
5665 devfs_register_tape (tpnt->de_r[0]);
5666 #endif
5667
5668 tpnt->device = SDp;
5669 tpnt->devt = MKDEV(MAJOR_NR, i);
5670 tpnt->dirty = 0;
5671 tpnt->in_use = 0;
5672 tpnt->drv_buffer = 1; /* Try buffering if no mode sense */
5673 tpnt->restr_dma = (SDp->host)->unchecked_isa_dma;
5674 tpnt->density = 0;
5675 tpnt->do_auto_lock = OSST_AUTO_LOCK;
5676 tpnt->can_bsr = OSST_IN_FILE_POS;
5677 tpnt->can_partitions = 0;
5678 tpnt->two_fm = OSST_TWO_FM;
5679 tpnt->fast_mteom = OSST_FAST_MTEOM;
5680 tpnt->scsi2_logical = OSST_SCSI2LOGICAL; /* FIXME */
5681 tpnt->write_threshold = osst_write_threshold;
5682 tpnt->default_drvbuffer = 0xff; /* No forced buffering */
5683 tpnt->partition = 0;
5684 tpnt->new_partition = 0;
5685 tpnt->nbr_partitions = 0;
5686 tpnt->min_block = 512;
5687 tpnt->max_block = OS_DATA_SIZE;
5688 tpnt->timeout = OSST_TIMEOUT;
5689 tpnt->long_timeout = OSST_LONG_TIMEOUT;
5690
5691 /* Recognize OnStream tapes */
5692 /* We don't need to test for OnStream, as this has been done in detect () */
5693 tpnt->os_fw_rev = osst_parse_firmware_rev (SDp->rev);
5694 tpnt->omit_blklims = 1;
5695
5696 tpnt->poll = (strncmp(SDp->model, "DI-", 3) == 0) ||
5697 (strncmp(SDp->model, "FW-", 3) == 0) || OSST_FW_NEED_POLL(tpnt->os_fw_rev,SDp);
5698 tpnt->frame_in_buffer = 0;
5699 tpnt->header_ok = 0;
5700 tpnt->linux_media = 0;
5701 tpnt->header_cache = NULL;
5702
5703 for (i=0; i < ST_NBR_MODES; i++) {
5704 STm = &(tpnt->modes[i]);
5705 STm->defined = FALSE;
5706 STm->sysv = OSST_SYSV;
5707 STm->defaults_for_writes = 0;
5708 STm->do_async_writes = OSST_ASYNC_WRITES;
5709 STm->do_buffer_writes = OSST_BUFFER_WRITES;
5710 STm->do_read_ahead = OSST_READ_AHEAD;
5711 STm->default_compression = ST_DONT_TOUCH;
5712 STm->default_blksize = 512;
5713 STm->default_density = (-1); /* No forced density */
5714 }
5715
5716 for (i=0; i < ST_NBR_PARTITIONS; i++) {
5717 STps = &(tpnt->ps[i]);
5718 STps->rw = ST_IDLE;
5719 STps->eof = ST_NOEOF;
5720 STps->at_sm = 0;
5721 STps->last_block_valid = FALSE;
5722 STps->drv_block = (-1);
5723 STps->drv_file = (-1);
5724 }
5725
5726 tpnt->current_mode = 0;
5727 tpnt->modes[0].defined = TRUE;
5728 tpnt->modes[2].defined = TRUE;
5729 tpnt->density_changed = tpnt->compression_changed = tpnt->blksize_changed = FALSE;
5730 init_MUTEX(&tpnt->lock);
5731
5732 osst_template.nr_dev++;
5733
5734 osst_proc_create(tpnt, dev);
5735
5736 printk(KERN_INFO
5737 "osst :I: Attached OnStream %.5s tape at scsi%d, channel %d, id %d, lun %d as osst%d\n",
5738 SDp->model, SDp->host->host_no, SDp->channel, SDp->id, SDp->lun, dev);
5739
5740 return 0;
5741 };
5742
osst_detect(Scsi_Device * SDp)5743 static int osst_detect(Scsi_Device * SDp)
5744 {
5745 if (SDp->type != TYPE_TAPE) return 0;
5746 if ( ! osst_supports(SDp) ) return 0;
5747
5748 osst_template.dev_noticed++;
5749 return 1;
5750 }
5751
5752 static int osst_registered = 0;
5753
5754 /* Driver initialization (not __initfunc because may be called later) */
osst_init()5755 static int osst_init()
5756 {
5757 int i;
5758
5759 if (osst_template.dev_noticed == 0) return 0;
5760
5761 if(!osst_registered) {
5762 #ifdef CONFIG_DEVFS_FS
5763 if (devfs_register_chrdev(MAJOR_NR,"osst",&osst_fops)) {
5764 #else
5765 if (register_chrdev(MAJOR_NR,"osst",&osst_fops)) {
5766 #endif
5767 printk(KERN_ERR "osst :W: Unable to get major %d for OnStream tapes\n",MAJOR_NR);
5768 return 1;
5769 }
5770 osst_registered++;
5771 }
5772
5773 if (os_scsi_tapes) return 0;
5774 osst_template.dev_max = osst_max_dev;
5775 if (osst_template.dev_max > 128 / ST_NBR_MODES)
5776 printk(KERN_INFO "osst :I: Only %d tapes accessible.\n", 128 / ST_NBR_MODES);
5777 os_scsi_tapes =
5778 (OS_Scsi_Tape **)kmalloc(osst_template.dev_max * sizeof(OS_Scsi_Tape *),
5779 GFP_ATOMIC);
5780 if (os_scsi_tapes == NULL) {
5781 printk(KERN_ERR "osst :W: Unable to allocate array for OnStream SCSI tapes.\n");
5782 #ifdef CONFIG_DEVFS_FS
5783 devfs_unregister_chrdev(MAJOR_NR, "osst");
5784 #else
5785 unregister_chrdev(MAJOR_NR, "osst");
5786 #endif
5787 return 1;
5788 }
5789
5790 for (i=0; i < osst_template.dev_max; ++i) os_scsi_tapes[i] = NULL;
5791
5792 /* Allocate the buffer pointers */
5793 osst_buffers =
5794 (OSST_buffer **)kmalloc(osst_template.dev_max * sizeof(OSST_buffer *),
5795 GFP_ATOMIC);
5796 if (osst_buffers == NULL) {
5797 printk(KERN_ERR "osst :W: Unable to allocate tape buffer pointers.\n");
5798 #ifdef CONFIG_DEVFS_FS
5799 devfs_unregister_chrdev(MAJOR_NR, "osst");
5800 #else
5801 unregister_chrdev(MAJOR_NR, "osst");
5802 #endif
5803 kfree(os_scsi_tapes);
5804 return 1;
5805 }
5806 osst_nbr_buffers = 0;
5807
5808 printk(KERN_INFO "osst :I: Tape driver with OnStream support version %s\nosst :I: %s\n", osst_version, cvsid);
5809
5810 #if DEBUG
5811 printk(OSST_DEB_MSG "osst :D: Buffer size %d bytes, write threshold %d bytes.\n",
5812 osst_buffer_size, osst_write_threshold);
5813 #endif
5814 osst_proc_init();
5815 return 0;
5816 }
5817
5818
5819 static void osst_detach(Scsi_Device * SDp)
5820 {
5821 OS_Scsi_Tape * tpnt;
5822 int i;
5823 #ifdef CONFIG_DEVFS_FS
5824 int mode;
5825 #endif
5826 for(i=0; i<osst_template.dev_max; i++) {
5827 tpnt = os_scsi_tapes[i];
5828 if(tpnt != NULL && tpnt->device == SDp) {
5829 osst_proc_destroy(i);
5830 tpnt->device = NULL;
5831 #ifdef CONFIG_DEVFS_FS
5832 for (mode = 0; mode < ST_NBR_MODES; ++mode) {
5833 devfs_unregister (tpnt->de_r[mode]);
5834 tpnt->de_r[mode] = NULL;
5835 devfs_unregister (tpnt->de_n[mode]);
5836 tpnt->de_n[mode] = NULL;
5837 }
5838 #endif
5839 if (tpnt->header_cache != NULL) {
5840 vfree(tpnt->header_cache);
5841 }
5842 kfree(tpnt);
5843 os_scsi_tapes[i] = NULL;
5844 SDp->attached--;
5845 osst_template.nr_dev--;
5846 osst_template.dev_noticed--;
5847 return;
5848 }
5849 }
5850 }
5851
5852 static int __init init_osst(void)
5853 {
5854 validate_options();
5855 osst_template.module = THIS_MODULE;
5856 return scsi_register_module(MODULE_SCSI_DEV, &osst_template);
5857 }
5858
5859 static void __exit exit_osst (void)
5860 {
5861 int i;
5862
5863 scsi_unregister_module(MODULE_SCSI_DEV, &osst_template);
5864 #ifdef CONFIG_DEVFS_FS
5865 devfs_unregister_chrdev(MAJOR_NR, "osst");
5866 #else
5867 unregister_chrdev(MAJOR_NR, "osst");
5868 #endif
5869 osst_registered--;
5870
5871 osst_proc_cleanup();
5872
5873 if(os_scsi_tapes != NULL) {
5874 kfree(os_scsi_tapes);
5875 }
5876 if (osst_buffers != NULL) {
5877 for (i=0; i < osst_nbr_buffers; i++)
5878 if (osst_buffers[i] != NULL) {
5879 osst_buffers[i]->orig_sg_segs = 0;
5880 normalize_buffer(osst_buffers[i]);
5881 kfree(osst_buffers[i]);
5882 }
5883 kfree(osst_buffers);
5884 }
5885 osst_template.dev_max = 0;
5886 printk(KERN_INFO "osst :I: Unloaded.\n");
5887 }
5888
5889 module_init(init_osst);
5890 module_exit(exit_osst);
5891