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