Blame view

drivers/ide/ide-tape.c 55.6 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
5ce78af4b   Borislav Petkov   ide-tape: move hi...
2
3
   * IDE ATAPI streaming tape driver.
   *
59bca8cc9   Bartlomiej Zolnierkiewicz   ide: update/add m...
4
5
   * Copyright (C) 1995-1999  Gadi Oxman <gadio@netvision.net.il>
   * Copyright (C) 2003-2005  Bartlomiej Zolnierkiewicz
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
7
8
9
10
11
12
   * This driver was constructed as a student project in the software laboratory
   * of the faculty of electrical engineering in the Technion - Israel's
   * Institute Of Technology, with the guide of Avner Lottem and Dr. Ilana David.
   *
   * It is hereby placed under the terms of the GNU general public license.
   * (See linux/COPYING).
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
13
   *
5ce78af4b   Borislav Petkov   ide-tape: move hi...
14
15
   * For a historical changelog see
   * Documentation/ide/ChangeLog.ide-tape.1995-2002
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
16
   */
51509eec3   Bartlomiej Zolnierkiewicz   ide: add ide_chec...
17
  #define DRV_NAME "ide-tape"
dfe799364   Borislav Petkov   ide-tape: bump mi...
18
  #define IDETAPE_VERSION "1.20"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19

1207045da   Arnd Bergmann   compat_ioctl: mov...
20
  #include <linux/compat.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
21
22
23
24
25
26
27
28
  #include <linux/module.h>
  #include <linux/types.h>
  #include <linux/string.h>
  #include <linux/kernel.h>
  #include <linux/delay.h>
  #include <linux/timer.h>
  #include <linux/mm.h>
  #include <linux/interrupt.h>
9bae1ff3e   Marcelo Feitoza Parisi   [PATCH] ide-tape:...
29
  #include <linux/jiffies.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
  #include <linux/major.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31
32
  #include <linux/errno.h>
  #include <linux/genhd.h>
6d703a81a   Alexey Dobriyan   ide: convert to -...
33
  #include <linux/seq_file.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
35
36
  #include <linux/slab.h>
  #include <linux/pci.h>
  #include <linux/ide.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37
38
  #include <linux/completion.h>
  #include <linux/bitops.h>
cf8b8975c   Arjan van de Ven   [PATCH] sem2mutex...
39
  #include <linux/mutex.h>
90699ce2b   Borislav Petkov   ide-tape: use gen...
40
  #include <scsi/scsi.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
42
  
  #include <asm/byteorder.h>
c837cfa5b   Borislav Petkov   ide-tape: include...
43
44
  #include <linux/uaccess.h>
  #include <linux/io.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45
  #include <asm/unaligned.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
  #include <linux/mtio.h>
8004a8c97   Borislav Petkov   ide-tape: refacto...
47
  /* define to see debug info */
e972d7027   Borislav Petkov   ide-tape: convert...
48
  #undef IDETAPE_DEBUG_LOG
8004a8c97   Borislav Petkov   ide-tape: refacto...
49

e972d7027   Borislav Petkov   ide-tape: convert...
50
51
  #ifdef IDETAPE_DEBUG_LOG
  #define ide_debug_log(lvl, fmt, args...) __ide_debug_log(lvl, fmt, ## args)
8004a8c97   Borislav Petkov   ide-tape: refacto...
52
  #else
e972d7027   Borislav Petkov   ide-tape: convert...
53
  #define ide_debug_log(lvl, fmt, args...) do {} while (0)
8004a8c97   Borislav Petkov   ide-tape: refacto...
54
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
55
  /**************************** Tunable parameters *****************************/
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
  /*
3c98bf347   Borislav Petkov   ide-tape: cleanup...
57
58
   * After each failed packet command we issue a request sense command and retry
   * the packet command IDETAPE_MAX_PC_RETRIES times.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
59
   *
3c98bf347   Borislav Petkov   ide-tape: cleanup...
60
   * Setting IDETAPE_MAX_PC_RETRIES to 0 will disable retries.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
61
62
63
64
   */
  #define IDETAPE_MAX_PC_RETRIES		3
  
  /*
3c98bf347   Borislav Petkov   ide-tape: cleanup...
65
66
67
68
   * The following parameter is used to select the point in the internal tape fifo
   * in which we will start to refill the buffer. Decreasing the following
   * parameter will improve the system's latency and interactive response, while
   * using a high value might improve system throughput.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69
   */
3c98bf347   Borislav Petkov   ide-tape: cleanup...
70
  #define IDETAPE_FIFO_THRESHOLD		2
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
71
72
  
  /*
3c98bf347   Borislav Petkov   ide-tape: cleanup...
73
   * DSC polling parameters.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
74
   *
3c98bf347   Borislav Petkov   ide-tape: cleanup...
75
76
   * Polling for DSC (a single bit in the status register) is a very important
   * function in ide-tape. There are two cases in which we poll for DSC:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
77
   *
3c98bf347   Borislav Petkov   ide-tape: cleanup...
78
79
80
81
82
   * 1. Before a read/write packet command, to ensure that we can transfer data
   * from/to the tape's data buffers, without causing an actual media access.
   * In case the tape is not ready yet, we take out our request from the device
   * request queue, so that ide.c could service requests from the other device
   * on the same interface in the meantime.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
83
   *
3c98bf347   Borislav Petkov   ide-tape: cleanup...
84
85
86
87
88
89
90
91
   * 2. After the successful initialization of a "media access packet command",
   * which is a command that can take a long time to complete (the interval can
   * range from several seconds to even an hour). Again, we postpone our request
   * in the middle to free the bus for the other device. The polling frequency
   * here should be lower than the read/write frequency since those media access
   * commands are slow. We start from a "fast" frequency - IDETAPE_DSC_MA_FAST
   * (1 second), and if we don't receive DSC after IDETAPE_DSC_MA_THRESHOLD
   * (5 min), we switch it to a lower frequency - IDETAPE_DSC_MA_SLOW (1 min).
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
92
   *
3c98bf347   Borislav Petkov   ide-tape: cleanup...
93
94
   * We also set a timeout for the timer, in case something goes wrong. The
   * timeout should be longer then the maximum execution time of a tape operation.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
95
   */
3c98bf347   Borislav Petkov   ide-tape: cleanup...
96
97
  
  /* DSC timings. */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98
99
100
101
102
103
104
105
106
  #define IDETAPE_DSC_RW_MIN		5*HZ/100	/* 50 msec */
  #define IDETAPE_DSC_RW_MAX		40*HZ/100	/* 400 msec */
  #define IDETAPE_DSC_RW_TIMEOUT		2*60*HZ		/* 2 minutes */
  #define IDETAPE_DSC_MA_FAST		2*HZ		/* 2 seconds */
  #define IDETAPE_DSC_MA_THRESHOLD	5*60*HZ		/* 5 minutes */
  #define IDETAPE_DSC_MA_SLOW		30*HZ		/* 30 seconds */
  #define IDETAPE_DSC_MA_TIMEOUT		2*60*60*HZ	/* 2 hours */
  
  /*************************** End of tunable parameters ***********************/
54abf37e4   Borislav Petkov   ide-tape: remove ...
107
108
109
110
111
112
  /* tape directions */
  enum {
  	IDETAPE_DIR_NONE  = (1 << 0),
  	IDETAPE_DIR_READ  = (1 << 1),
  	IDETAPE_DIR_WRITE = (1 << 2),
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
113

03056b909   Borislav Petkov   ide-tape: move al...
114
115
116
117
118
119
120
121
122
123
124
125
126
  /* Tape door status */
  #define DOOR_UNLOCKED			0
  #define DOOR_LOCKED			1
  #define DOOR_EXPLICITLY_LOCKED		2
  
  /* Some defines for the SPACE command */
  #define IDETAPE_SPACE_OVER_FILEMARK	1
  #define IDETAPE_SPACE_TO_EOD		3
  
  /* Some defines for the LOAD UNLOAD command */
  #define IDETAPE_LU_LOAD_MASK		1
  #define IDETAPE_LU_RETENSION_MASK	2
  #define IDETAPE_LU_EOT_MASK		4
03056b909   Borislav Petkov   ide-tape: move al...
127
128
129
  /* Structures related to the SELECT SENSE / MODE SENSE packet commands. */
  #define IDETAPE_BLOCK_DESCRIPTOR	0
  #define IDETAPE_CAPABILITIES_PAGE	0x2a
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
130
  /*
3c98bf347   Borislav Petkov   ide-tape: cleanup...
131
132
   * Most of our global data which we need to save even as we leave the driver due
   * to an interrupt or a timer event is stored in the struct defined below.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
133
134
   */
  typedef struct ide_tape_obj {
7f3c868ba   Bartlomiej Zolnierkiewicz   ide: remove ide_d...
135
136
137
  	ide_drive_t		*drive;
  	struct ide_driver	*driver;
  	struct gendisk		*disk;
8fed43684   Bartlomiej Zolnierkiewicz   ide: fix refcount...
138
  	struct device		dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139

2e8a6f89d   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
140
141
  	/* used by REQ_IDETAPE_{READ,WRITE} requests */
  	struct ide_atapi_pc queued_pc;
394a4c210   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
142

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
143
  	/*
3c98bf347   Borislav Petkov   ide-tape: cleanup...
144
  	 * DSC polling variables.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
145
  	 *
3c98bf347   Borislav Petkov   ide-tape: cleanup...
146
147
148
  	 * While polling for DSC we use postponed_rq to postpone the current
  	 * request so that ide.c will be able to service pending requests on the
  	 * other device. Note that at most we will have only one DSC (usually
5bd50dc6a   Borislav Petkov   ide-tape: remove ...
149
  	 * data transfer) request in the device request queue.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
150
  	 */
6f3848ac2   Borislav Petkov   ide-tape: fix han...
151
  	bool postponed_rq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
152
153
154
155
156
  	/* The time in which we started polling for DSC */
  	unsigned long dsc_polling_start;
  	/* Timer used to poll for dsc */
  	struct timer_list dsc_timer;
  	/* Read/Write dsc polling frequency */
54bb2074c   Borislav Petkov   ide-tape: struct ...
157
158
  	unsigned long best_dsc_rw_freq;
  	unsigned long dsc_poll_freq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
159
  	unsigned long dsc_timeout;
3c98bf347   Borislav Petkov   ide-tape: cleanup...
160
  	/* Read position information */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
161
162
  	u8 partition;
  	/* Current block */
54bb2074c   Borislav Petkov   ide-tape: struct ...
163
  	unsigned int first_frame;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164

3c98bf347   Borislav Petkov   ide-tape: cleanup...
165
  	/* Last error information */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
166
  	u8 sense_key, asc, ascq;
3c98bf347   Borislav Petkov   ide-tape: cleanup...
167
  	/* Character device operation */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
168
169
170
171
  	unsigned int minor;
  	/* device name */
  	char name[4];
  	/* Current character device data transfer direction */
54abf37e4   Borislav Petkov   ide-tape: remove ...
172
  	u8 chrdev_dir;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
173

54bb2074c   Borislav Petkov   ide-tape: struct ...
174
175
  	/* tape block size, usually 512 or 1024 bytes */
  	unsigned short blk_size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
176
  	int user_bs_factor;
b64220132   Borislav Petkov   ide-tape: remove ...
177

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
178
  	/* Copy of the tape's Capabilities and Mechanical Page */
b64220132   Borislav Petkov   ide-tape: remove ...
179
  	u8 caps[20];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
180
181
  
  	/*
3c98bf347   Borislav Petkov   ide-tape: cleanup...
182
  	 * Active data transfer request parameters.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183
  	 *
3c98bf347   Borislav Petkov   ide-tape: cleanup...
184
185
186
  	 * At most, there is only one ide-tape originated data transfer request
  	 * in the device request queue. This allows ide.c to easily service
  	 * requests from the other device when we postpone our active request.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
187
  	 */
83042b241   Borislav Petkov   ide-tape: remove ...
188

3c98bf347   Borislav Petkov   ide-tape: cleanup...
189
  	/* Data buffer size chosen based on the tape's recommendation */
f73850a30   Borislav Petkov   ide-tape: mv tape...
190
  	int buffer_size;
963da55c4   Tejun Heo   ide-tape: kill id...
191
192
193
194
195
196
  	/* Staging buffer of buffer_size bytes */
  	void *buf;
  	/* The read/write cursor */
  	void *cur;
  	/* The number of valid bytes in buf */
  	size_t valid;
3c98bf347   Borislav Petkov   ide-tape: cleanup...
197

3c98bf347   Borislav Petkov   ide-tape: cleanup...
198
  	/* Measures average tape speed */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
199
200
201
  	unsigned long avg_time;
  	int avg_size;
  	int avg_speed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
202
203
204
205
206
207
  	/* the door is currently locked */
  	int door_locked;
  	/* the tape hardware is write protected */
  	char drv_write_prot;
  	/* the tape is write protected (hardware or opened as read-only) */
  	char write_prot;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
208
  } idetape_tape_t;
2a48fc0ab   Arnd Bergmann   block: autoconver...
209
  static DEFINE_MUTEX(ide_tape_mutex);
cf8b8975c   Arjan van de Ven   [PATCH] sem2mutex...
210
  static DEFINE_MUTEX(idetape_ref_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
211

cbba2fa7b   Borislav Petkov   ide-tape: remove ...
212
  static DEFINE_MUTEX(idetape_chrdev_mutex);
d5dee80ad   Will Dyson   [PATCH] add sysfs...
213
  static struct class *idetape_sysfs_class;
8fed43684   Bartlomiej Zolnierkiewicz   ide: fix refcount...
214
  static void ide_tape_release(struct device *);
08da591e1   Bartlomiej Zolnierkiewicz   ide: add ide_devi...
215

9d01e4cd7   Borislav Petkov   ide-tape: fix pro...
216
217
218
219
  static struct ide_tape_obj *idetape_devs[MAX_HWIFS * MAX_DRIVES];
  
  static struct ide_tape_obj *ide_tape_get(struct gendisk *disk, bool cdev,
  					 unsigned int i)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
220
221
  {
  	struct ide_tape_obj *tape = NULL;
cf8b8975c   Arjan van de Ven   [PATCH] sem2mutex...
222
  	mutex_lock(&idetape_ref_mutex);
9d01e4cd7   Borislav Petkov   ide-tape: fix pro...
223
224
225
226
227
  
  	if (cdev)
  		tape = idetape_devs[i];
  	else
  		tape = ide_drv_g(disk, ide_tape_obj);
08da591e1   Bartlomiej Zolnierkiewicz   ide: add ide_devi...
228
  	if (tape) {
d3e33ff59   Bartlomiej Zolnierkiewicz   ide: fix regressi...
229
  		if (ide_device_get(tape->drive))
08da591e1   Bartlomiej Zolnierkiewicz   ide: add ide_devi...
230
  			tape = NULL;
d3e33ff59   Bartlomiej Zolnierkiewicz   ide: fix regressi...
231
  		else
8fed43684   Bartlomiej Zolnierkiewicz   ide: fix refcount...
232
  			get_device(&tape->dev);
08da591e1   Bartlomiej Zolnierkiewicz   ide: add ide_devi...
233
  	}
9d01e4cd7   Borislav Petkov   ide-tape: fix pro...
234

cf8b8975c   Arjan van de Ven   [PATCH] sem2mutex...
235
  	mutex_unlock(&idetape_ref_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
236
237
  	return tape;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
238
239
  static void ide_tape_put(struct ide_tape_obj *tape)
  {
d3e33ff59   Bartlomiej Zolnierkiewicz   ide: fix regressi...
240
  	ide_drive_t *drive = tape->drive;
cf8b8975c   Arjan van de Ven   [PATCH] sem2mutex...
241
  	mutex_lock(&idetape_ref_mutex);
8fed43684   Bartlomiej Zolnierkiewicz   ide: fix refcount...
242
  	put_device(&tape->dev);
d3e33ff59   Bartlomiej Zolnierkiewicz   ide: fix regressi...
243
  	ide_device_put(drive);
cf8b8975c   Arjan van de Ven   [PATCH] sem2mutex...
244
  	mutex_unlock(&idetape_ref_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
245
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
246
  /*
1b5db434f   Borislav Petkov   ide-tape: remove ...
247
248
   * called on each failed packet command retry to analyze the request sense. We
   * currently do not utilize this information.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
249
   */
ae3a8387b   Borislav Petkov   ide-atapi: use lo...
250
  static void idetape_analyze_error(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
251
252
  {
  	idetape_tape_t *tape = drive->driver_data;
5e2040fd0   Bartlomiej Zolnierkiewicz   ide: move ->faile...
253
  	struct ide_atapi_pc *pc = drive->failed_pc;
dfb7e621f   Borislav Petkov   ide-atapi: switch...
254
  	struct request *rq = drive->hwif->rq;
ae3a8387b   Borislav Petkov   ide-atapi: use lo...
255
  	u8 *sense = bio_data(rq->bio);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
256

1b5db434f   Borislav Petkov   ide-tape: remove ...
257
258
259
  	tape->sense_key = sense[2] & 0xF;
  	tape->asc       = sense[12];
  	tape->ascq      = sense[13];
8004a8c97   Borislav Petkov   ide-tape: refacto...
260

e972d7027   Borislav Petkov   ide-tape: convert...
261
262
263
  	ide_debug_log(IDE_DBG_FUNC,
  		      "cmd: 0x%x, sense key = %x, asc = %x, ascq = %x",
  		      rq->cmd[0], tape->sense_key, tape->asc, tape->ascq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
264

077e6dba2   Borislav Petkov   ide-atapi: switch...
265
  	/* correct remaining bytes to transfer */
21d9c5d22   Tejun Heo   ide-tape: use sta...
266
  	if (pc->flags & PC_FLAG_DMA_ERROR)
82ed4db49   Christoph Hellwig   block: split scsi...
267
  		scsi_req(rq)->resid_len = tape->blk_size * get_unaligned_be32(&sense[3]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
268
269
270
271
272
273
  
  	/*
  	 * If error was the result of a zero-length read or write command,
  	 * with sense key=5, asc=0x22, ascq=0, let it slide.  Some drives
  	 * (i.e. Seagate STT3401A Travan) don't support 0-length read/writes.
  	 */
90699ce2b   Borislav Petkov   ide-tape: use gen...
274
  	if ((pc->c[0] == READ_6 || pc->c[0] == WRITE_6)
1b5db434f   Borislav Petkov   ide-tape: remove ...
275
276
277
  	    /* length == 0 */
  	    && pc->c[4] == 0 && pc->c[3] == 0 && pc->c[2] == 0) {
  		if (tape->sense_key == 5) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
278
279
280
  			/* don't report an error, everything's ok */
  			pc->error = 0;
  			/* don't retry read/write */
346331f82   Borislav Petkov   ide-tape: remove ...
281
  			pc->flags |= PC_FLAG_ABORT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
282
283
  		}
  	}
90699ce2b   Borislav Petkov   ide-tape: use gen...
284
  	if (pc->c[0] == READ_6 && (sense[2] & 0x80)) {
c152cc1a9   Bartlomiej Zolnierkiewicz   ide: use ->end_re...
285
  		pc->error = IDE_DRV_ERROR_FILEMARK;
346331f82   Borislav Petkov   ide-tape: remove ...
286
  		pc->flags |= PC_FLAG_ABORT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
287
  	}
90699ce2b   Borislav Petkov   ide-tape: use gen...
288
  	if (pc->c[0] == WRITE_6) {
1b5db434f   Borislav Petkov   ide-tape: remove ...
289
290
  		if ((sense[2] & 0x40) || (tape->sense_key == 0xd
  		     && tape->asc == 0x0 && tape->ascq == 0x2)) {
c152cc1a9   Bartlomiej Zolnierkiewicz   ide: use ->end_re...
291
  			pc->error = IDE_DRV_ERROR_EOD;
346331f82   Borislav Petkov   ide-tape: remove ...
292
  			pc->flags |= PC_FLAG_ABORT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
293
294
  		}
  	}
90699ce2b   Borislav Petkov   ide-tape: use gen...
295
  	if (pc->c[0] == READ_6 || pc->c[0] == WRITE_6) {
1b5db434f   Borislav Petkov   ide-tape: remove ...
296
  		if (tape->sense_key == 8) {
c152cc1a9   Bartlomiej Zolnierkiewicz   ide: use ->end_re...
297
  			pc->error = IDE_DRV_ERROR_EOD;
346331f82   Borislav Petkov   ide-tape: remove ...
298
  			pc->flags |= PC_FLAG_ABORT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
299
  		}
346331f82   Borislav Petkov   ide-tape: remove ...
300
  		if (!(pc->flags & PC_FLAG_ABORT) &&
82ed4db49   Christoph Hellwig   block: split scsi...
301
  		    (blk_rq_bytes(rq) - scsi_req(rq)->resid_len))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
302
303
304
  			pc->retries = IDETAPE_MAX_PC_RETRIES + 1;
  	}
  }
b14c72127   Bartlomiej Zolnierkiewicz   ide: drop dsc_han...
305
  static void ide_tape_handle_dsc(ide_drive_t *);
03a2faaea   Bartlomiej Zolnierkiewicz   ide: return reque...
306
  static int ide_tape_callback(ide_drive_t *drive, int dsc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
307
308
  {
  	idetape_tape_t *tape = drive->driver_data;
2b9efba48   Bartlomiej Zolnierkiewicz   ide: add pointer ...
309
  	struct ide_atapi_pc *pc = drive->pc;
313afea7f   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
310
  	struct request *rq = drive->hwif->rq;
5985e6abb   Bartlomiej Zolnierkiewicz   ide-tape: merge c...
311
  	int uptodate = pc->error ? 0 : 1;
313afea7f   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
312
  	int err = uptodate ? 0 : IDE_DRV_ERROR_GENERAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
313

e972d7027   Borislav Petkov   ide-tape: convert...
314
315
  	ide_debug_log(IDE_DBG_FUNC, "cmd: 0x%x, dsc: %d, err: %d", rq->cmd[0],
  		      dsc, err);
8004a8c97   Borislav Petkov   ide-tape: refacto...
316

b14c72127   Bartlomiej Zolnierkiewicz   ide: drop dsc_han...
317
318
  	if (dsc)
  		ide_tape_handle_dsc(drive);
5e2040fd0   Bartlomiej Zolnierkiewicz   ide: move ->faile...
319
320
  	if (drive->failed_pc == pc)
  		drive->failed_pc = NULL;
dd2e9a032   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
321

5985e6abb   Bartlomiej Zolnierkiewicz   ide-tape: merge c...
322
323
  	if (pc->c[0] == REQUEST_SENSE) {
  		if (uptodate)
ae3a8387b   Borislav Petkov   ide-atapi: use lo...
324
  			idetape_analyze_error(drive);
5985e6abb   Bartlomiej Zolnierkiewicz   ide-tape: merge c...
325
326
327
328
329
  		else
  			printk(KERN_ERR "ide-tape: Error in REQUEST SENSE "
  					"itself - Aborting request!
  ");
  	} else if (pc->c[0] == READ_6 || pc->c[0] == WRITE_6) {
077e6dba2   Borislav Petkov   ide-atapi: switch...
330
  		unsigned int blocks =
82ed4db49   Christoph Hellwig   block: split scsi...
331
  			(blk_rq_bytes(rq) - scsi_req(rq)->resid_len) / tape->blk_size;
5985e6abb   Bartlomiej Zolnierkiewicz   ide-tape: merge c...
332
333
334
335
336
337
338
339
340
341
342
  
  		tape->avg_size += blocks * tape->blk_size;
  
  		if (time_after_eq(jiffies, tape->avg_time + HZ)) {
  			tape->avg_speed = tape->avg_size * HZ /
  				(jiffies - tape->avg_time) / 1024;
  			tape->avg_size = 0;
  			tape->avg_time = jiffies;
  		}
  
  		tape->first_frame += blocks;
5985e6abb   Bartlomiej Zolnierkiewicz   ide-tape: merge c...
343

313afea7f   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
344
345
346
347
  		if (pc->error) {
  			uptodate = 0;
  			err = pc->error;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
348
  	}
17d5363b8   Christoph Hellwig   scsi: introduce a...
349
  	scsi_req(rq)->result = err;
313afea7f   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
350

03a2faaea   Bartlomiej Zolnierkiewicz   ide: return reque...
351
  	return uptodate;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
352
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
353
  /*
3c98bf347   Borislav Petkov   ide-tape: cleanup...
354
   * Postpone the current request so that ide.c will be able to service requests
b65fac32c   Bartlomiej Zolnierkiewicz   ide: merge ide_hw...
355
   * from another device on the same port while we are polling for DSC.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
356
   */
6f3848ac2   Borislav Petkov   ide-tape: fix han...
357
  static void ide_tape_stall_queue(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
358
359
  {
  	idetape_tape_t *tape = drive->driver_data;
e972d7027   Borislav Petkov   ide-tape: convert...
360
  	ide_debug_log(IDE_DBG_FUNC, "cmd: 0x%x, dsc_poll_freq: %lu",
6f3848ac2   Borislav Petkov   ide-tape: fix han...
361
  		      drive->hwif->rq->cmd[0], tape->dsc_poll_freq);
8004a8c97   Borislav Petkov   ide-tape: refacto...
362

6f3848ac2   Borislav Petkov   ide-tape: fix han...
363
  	tape->postponed_rq = true;
b65fac32c   Bartlomiej Zolnierkiewicz   ide: merge ide_hw...
364

54bb2074c   Borislav Petkov   ide-tape: struct ...
365
  	ide_stall_queue(drive, tape->dsc_poll_freq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
366
  }
74e63e74e   Bartlomiej Zolnierkiewicz   ide-tape: factor ...
367
368
369
370
371
372
373
374
375
  static void ide_tape_handle_dsc(ide_drive_t *drive)
  {
  	idetape_tape_t *tape = drive->driver_data;
  
  	/* Media access command */
  	tape->dsc_polling_start = jiffies;
  	tape->dsc_poll_freq = IDETAPE_DSC_MA_FAST;
  	tape->dsc_timeout = jiffies + IDETAPE_DSC_MA_TIMEOUT;
  	/* Allow ide.c to handle other requests */
6f3848ac2   Borislav Petkov   ide-tape: fix han...
376
  	ide_tape_stall_queue(drive);
74e63e74e   Bartlomiej Zolnierkiewicz   ide-tape: factor ...
377
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
378
  /*
3c98bf347   Borislav Petkov   ide-tape: cleanup...
379
   * Packet Command Interface
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
380
   *
2b9efba48   Bartlomiej Zolnierkiewicz   ide: add pointer ...
381
   * The current Packet Command is available in drive->pc, and will not change
3c98bf347   Borislav Petkov   ide-tape: cleanup...
382
383
   * until we finish handling it. Each packet command is associated with a
   * callback function that will be called when the command is finished.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
384
   *
3c98bf347   Borislav Petkov   ide-tape: cleanup...
385
   * The handling will be done in three stages:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
386
   *
b788ee9c6   Bartlomiej Zolnierkiewicz   ide: use do_rw_ta...
387
   * 1. ide_tape_issue_pc will send the packet command to the drive, and will set
aa5d2de7b   Bartlomiej Zolnierkiewicz   ide: make ide_pc_...
388
   * the interrupt handler to ide_pc_intr.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
389
   *
aa5d2de7b   Bartlomiej Zolnierkiewicz   ide: make ide_pc_...
390
   * 2. On each interrupt, ide_pc_intr will be called. This step will be
3c98bf347   Borislav Petkov   ide-tape: cleanup...
391
   * repeated until the device signals us that no more interrupts will be issued.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
392
   *
3c98bf347   Borislav Petkov   ide-tape: cleanup...
393
394
395
396
397
398
399
   * 3. ATAPI Tape media access commands have immediate status with a delayed
   * process. In case of a successful initiation of a media access packet command,
   * the DSC bit will be set when the actual execution of the command is finished.
   * Since the tape drive will not issue an interrupt, we have to poll for this
   * event. In this case, we define the request as "low priority request" by
   * setting rq_status to IDETAPE_RQ_POSTPONED, set a timer to poll for DSC and
   * exit the driver.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
400
   *
3c98bf347   Borislav Petkov   ide-tape: cleanup...
401
402
   * ide.c will then give higher priority to requests which originate from the
   * other device, until will change rq_status to RQ_ACTIVE.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
403
   *
3c98bf347   Borislav Petkov   ide-tape: cleanup...
404
   * 4. When the packet command is finished, it will be checked for errors.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
405
   *
3c98bf347   Borislav Petkov   ide-tape: cleanup...
406
407
408
   * 5. In case an error was found, we queue a request sense packet command in
   * front of the request queue and retry the operation up to
   * IDETAPE_MAX_PC_RETRIES times.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
409
   *
3c98bf347   Borislav Petkov   ide-tape: cleanup...
410
411
412
   * 6. In case no error was found, or we decided to give up and not to retry
   * again, the callback function will be called and then we will handle the next
   * request.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
413
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
414

b788ee9c6   Bartlomiej Zolnierkiewicz   ide: use do_rw_ta...
415
416
417
  static ide_startstop_t ide_tape_issue_pc(ide_drive_t *drive,
  					 struct ide_cmd *cmd,
  					 struct ide_atapi_pc *pc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
418
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
419
  	idetape_tape_t *tape = drive->driver_data;
dfb7e621f   Borislav Petkov   ide-atapi: switch...
420
  	struct request *rq = drive->hwif->rq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
421

5e2040fd0   Bartlomiej Zolnierkiewicz   ide: move ->faile...
422
423
  	if (drive->failed_pc == NULL && pc->c[0] != REQUEST_SENSE)
  		drive->failed_pc = pc;
2b9efba48   Bartlomiej Zolnierkiewicz   ide: add pointer ...
424

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
425
  	/* Set the current packet command */
2b9efba48   Bartlomiej Zolnierkiewicz   ide: add pointer ...
426
  	drive->pc = pc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
427
428
  
  	if (pc->retries > IDETAPE_MAX_PC_RETRIES ||
346331f82   Borislav Petkov   ide-tape: remove ...
429
  		(pc->flags & PC_FLAG_ABORT)) {
b3071d190   Tejun Heo   ide-atapi,tape,fl...
430

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
431
  		/*
3c98bf347   Borislav Petkov   ide-tape: cleanup...
432
433
434
  		 * We will "abort" retrying a packet command in case legitimate
  		 * error code was received (crossing a filemark, or end of the
  		 * media, for example).
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
435
  		 */
346331f82   Borislav Petkov   ide-tape: remove ...
436
  		if (!(pc->flags & PC_FLAG_ABORT)) {
90699ce2b   Borislav Petkov   ide-tape: use gen...
437
  			if (!(pc->c[0] == TEST_UNIT_READY &&
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
438
439
440
441
442
443
444
445
446
447
448
  			      tape->sense_key == 2 && tape->asc == 4 &&
  			     (tape->ascq == 1 || tape->ascq == 8))) {
  				printk(KERN_ERR "ide-tape: %s: I/O error, "
  						"pc = %2x, key = %2x, "
  						"asc = %2x, ascq = %2x
  ",
  						tape->name, pc->c[0],
  						tape->sense_key, tape->asc,
  						tape->ascq);
  			}
  			/* Giving up */
c152cc1a9   Bartlomiej Zolnierkiewicz   ide: use ->end_re...
449
  			pc->error = IDE_DRV_ERROR_GENERAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
450
  		}
b3071d190   Tejun Heo   ide-atapi,tape,fl...
451

5e2040fd0   Bartlomiej Zolnierkiewicz   ide: move ->faile...
452
  		drive->failed_pc = NULL;
b14c72127   Bartlomiej Zolnierkiewicz   ide: drop dsc_han...
453
  		drive->pc_callback(drive, 0);
2a842acab   Christoph Hellwig   block: introduce ...
454
  		ide_complete_rq(drive, BLK_STS_IOERR, blk_rq_bytes(rq));
92f5daff2   Bartlomiej Zolnierkiewicz   ide-tape: make pc...
455
  		return ide_stopped;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
456
  	}
e972d7027   Borislav Petkov   ide-tape: convert...
457
458
  	ide_debug_log(IDE_DBG_SENSE, "retry #%d, cmd: 0x%02x", pc->retries,
  		      pc->c[0]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
459
460
  
  	pc->retries++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
461

b788ee9c6   Bartlomiej Zolnierkiewicz   ide: use do_rw_ta...
462
  	return ide_issue_pc(drive, cmd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
463
  }
3c98bf347   Borislav Petkov   ide-tape: cleanup...
464
  /* A mode sense command is used to "sense" tape parameters. */
d236d74c0   Borislav Petkov   ide-tape: convert...
465
  static void idetape_create_mode_sense_cmd(struct ide_atapi_pc *pc, u8 page_code)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
466
  {
7bf7420a3   Bartlomiej Zolnierkiewicz   ide: add ide_init...
467
  	ide_init_pc(pc);
90699ce2b   Borislav Petkov   ide-tape: use gen...
468
  	pc->c[0] = MODE_SENSE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
469
  	if (page_code != IDETAPE_BLOCK_DESCRIPTOR)
3c98bf347   Borislav Petkov   ide-tape: cleanup...
470
471
  		/* DBD = 1 - Don't return block descriptors */
  		pc->c[1] = 8;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
472
473
474
475
476
477
478
479
480
  	pc->c[2] = page_code;
  	/*
  	 * Changed pc->c[3] to 0 (255 will at best return unused info).
  	 *
  	 * For SCSI this byte is defined as subpage instead of high byte
  	 * of length and some IDE drives seem to interpret it this way
  	 * and return an error when 255 is used.
  	 */
  	pc->c[3] = 0;
3c98bf347   Borislav Petkov   ide-tape: cleanup...
481
482
  	/* We will just discard data in that case */
  	pc->c[4] = 255;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
483
  	if (page_code == IDETAPE_BLOCK_DESCRIPTOR)
d236d74c0   Borislav Petkov   ide-tape: convert...
484
  		pc->req_xfer = 12;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
485
  	else if (page_code == IDETAPE_CAPABILITIES_PAGE)
d236d74c0   Borislav Petkov   ide-tape: convert...
486
  		pc->req_xfer = 24;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
487
  	else
d236d74c0   Borislav Petkov   ide-tape: convert...
488
  		pc->req_xfer = 50;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
489
  }
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
490
  static ide_startstop_t idetape_media_access_finished(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
491
  {
b73c7ee25   Bartlomiej Zolnierkiewicz   ide: add ->read_s...
492
  	ide_hwif_t *hwif = drive->hwif;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
493
  	idetape_tape_t *tape = drive->driver_data;
2b9efba48   Bartlomiej Zolnierkiewicz   ide: add pointer ...
494
  	struct ide_atapi_pc *pc = drive->pc;
22c525b97   Bartlomiej Zolnierkiewicz   ide: remove ata_s...
495
  	u8 stat;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
496

374e042c3   Bartlomiej Zolnierkiewicz   ide: add struct i...
497
  	stat = hwif->tp_ops->read_status(hwif);
c47137a99   Bartlomiej Zolnierkiewicz   ide: add ide_read...
498

3a7d24841   Bartlomiej Zolnierkiewicz   ide: use ATA_* de...
499
500
  	if (stat & ATA_DSC) {
  		if (stat & ATA_ERR) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
501
  			/* Error detected */
90699ce2b   Borislav Petkov   ide-tape: use gen...
502
  			if (pc->c[0] != TEST_UNIT_READY)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
503
504
505
  				printk(KERN_ERR "ide-tape: %s: I/O error, ",
  						tape->name);
  			/* Retry operation */
6b544fcc8   Borislav Petkov   ide-atapi: conver...
506
  			ide_retry_pc(drive);
258ec4113   Bartlomiej Zolnierkiewicz   ide-tape: make id...
507
  			return ide_stopped;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
508
509
  		}
  		pc->error = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
510
  	} else {
c152cc1a9   Bartlomiej Zolnierkiewicz   ide: use ->end_re...
511
  		pc->error = IDE_DRV_ERROR_GENERAL;
5e2040fd0   Bartlomiej Zolnierkiewicz   ide: move ->faile...
512
  		drive->failed_pc = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
513
  	}
b14c72127   Bartlomiej Zolnierkiewicz   ide: drop dsc_han...
514
  	drive->pc_callback(drive, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
515
516
  	return ide_stopped;
  }
cd2abbfec   Borislav Petkov   ide-tape: unify i...
517
  static void ide_tape_create_rw_cmd(idetape_tape_t *tape,
0014c75be   Borislav Petkov   ide-tape: pass pa...
518
519
  				   struct ide_atapi_pc *pc, struct request *rq,
  				   u8 opcode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
520
  {
10c0b3437   Borislav Petkov   ide-tape: fix pot...
521
  	unsigned int length = blk_rq_sectors(rq) / (tape->blk_size >> 9);
0014c75be   Borislav Petkov   ide-tape: pass pa...
522

7bf7420a3   Bartlomiej Zolnierkiewicz   ide: add ide_init...
523
  	ide_init_pc(pc);
860ff5ecb   Borislav Petkov   ide-tape: use gen...
524
  	put_unaligned(cpu_to_be32(length), (unsigned int *) &pc->c[1]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
525
  	pc->c[1] = 1;
19f52a784   Borislav Petkov   ide-atapi: remove...
526
527
  
  	if (blk_rq_bytes(rq) == tape->buffer_size)
5e3310958   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
528
  		pc->flags |= PC_FLAG_DMA_OK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
529

963da55c4   Tejun Heo   ide-tape: kill id...
530
  	if (opcode == READ_6)
cd2abbfec   Borislav Petkov   ide-tape: unify i...
531
  		pc->c[0] = READ_6;
963da55c4   Tejun Heo   ide-tape: kill id...
532
  	else if (opcode == WRITE_6) {
cd2abbfec   Borislav Petkov   ide-tape: unify i...
533
534
  		pc->c[0] = WRITE_6;
  		pc->flags |= PC_FLAG_WRITING;
cd2abbfec   Borislav Petkov   ide-tape: unify i...
535
  	}
0014c75be   Borislav Petkov   ide-tape: pass pa...
536

82ed4db49   Christoph Hellwig   block: split scsi...
537
  	memcpy(scsi_req(rq)->cmd, pc->c, 12);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
538
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
539
540
541
  static ide_startstop_t idetape_do_request(ide_drive_t *drive,
  					  struct request *rq, sector_t block)
  {
b73c7ee25   Bartlomiej Zolnierkiewicz   ide: add ->read_s...
542
  	ide_hwif_t *hwif = drive->hwif;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
543
  	idetape_tape_t *tape = drive->driver_data;
d236d74c0   Borislav Petkov   ide-tape: convert...
544
  	struct ide_atapi_pc *pc = NULL;
b788ee9c6   Bartlomiej Zolnierkiewicz   ide: use do_rw_ta...
545
  	struct ide_cmd cmd;
82ed4db49   Christoph Hellwig   block: split scsi...
546
  	struct scsi_request *req = scsi_req(rq);
22c525b97   Bartlomiej Zolnierkiewicz   ide: remove ata_s...
547
  	u8 stat;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
548

e972d7027   Borislav Petkov   ide-tape: convert...
549
  	ide_debug_log(IDE_DBG_RQ, "cmd: 0x%x, sector: %llu, nr_sectors: %u",
82ed4db49   Christoph Hellwig   block: split scsi...
550
  		      req->cmd[0], (unsigned long long)blk_rq_pos(rq),
e972d7027   Borislav Petkov   ide-tape: convert...
551
  		      blk_rq_sectors(rq));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
552

aebf526b5   Christoph Hellwig   block: fold cmd_t...
553
  	BUG_ON(!blk_rq_is_private(rq));
2f5a8e80f   Christoph Hellwig   ide: don't abuse ...
554
555
  	BUG_ON(ide_req(rq)->type != ATA_PRIV_MISC &&
  	       ide_req(rq)->type != ATA_PRIV_SENSE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
556

3c98bf347   Borislav Petkov   ide-tape: cleanup...
557
  	/* Retry a failed packet command */
5e2040fd0   Bartlomiej Zolnierkiewicz   ide: move ->faile...
558
559
  	if (drive->failed_pc && drive->pc->c[0] == REQUEST_SENSE) {
  		pc = drive->failed_pc;
28c7214bd   Bartlomiej Zolnierkiewicz   ide: add PC_FLAG_...
560
561
  		goto out;
  	}
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
562

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
563
564
565
566
  	/*
  	 * If the tape is still busy, postpone our request and service
  	 * the other device meanwhile.
  	 */
374e042c3   Bartlomiej Zolnierkiewicz   ide: add struct i...
567
  	stat = hwif->tp_ops->read_status(hwif);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
568

97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
569
  	if ((drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) == 0 &&
82ed4db49   Christoph Hellwig   block: split scsi...
570
  	    (req->cmd[13] & REQ_IDETAPE_PC2) == 0)
626542ca2   Borislav Petkov   ide-tape: change ...
571
  		drive->atapi_flags |= IDE_AFLAG_IGNORE_DSC;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
572

97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
573
  	if (drive->dev_flags & IDE_DFLAG_POST_RESET) {
626542ca2   Borislav Petkov   ide-tape: change ...
574
  		drive->atapi_flags |= IDE_AFLAG_IGNORE_DSC;
97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
575
  		drive->dev_flags &= ~IDE_DFLAG_POST_RESET;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
576
  	}
626542ca2   Borislav Petkov   ide-tape: change ...
577
578
  	if (!(drive->atapi_flags & IDE_AFLAG_IGNORE_DSC) &&
  	    !(stat & ATA_DSC)) {
6f3848ac2   Borislav Petkov   ide-tape: fix han...
579
  		if (!tape->postponed_rq) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
580
  			tape->dsc_polling_start = jiffies;
54bb2074c   Borislav Petkov   ide-tape: struct ...
581
  			tape->dsc_poll_freq = tape->best_dsc_rw_freq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
582
583
584
585
586
  			tape->dsc_timeout = jiffies + IDETAPE_DSC_RW_TIMEOUT;
  		} else if (time_after(jiffies, tape->dsc_timeout)) {
  			printk(KERN_ERR "ide-tape: %s: DSC timeout
  ",
  				tape->name);
82ed4db49   Christoph Hellwig   block: split scsi...
587
  			if (req->cmd[13] & REQ_IDETAPE_PC2) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
588
589
590
591
592
  				idetape_media_access_finished(drive);
  				return ide_stopped;
  			} else {
  				return ide_do_reset(drive);
  			}
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
593
594
595
  		} else if (time_after(jiffies,
  					tape->dsc_polling_start +
  					IDETAPE_DSC_MA_THRESHOLD))
54bb2074c   Borislav Petkov   ide-tape: struct ...
596
  			tape->dsc_poll_freq = IDETAPE_DSC_MA_SLOW;
6f3848ac2   Borislav Petkov   ide-tape: fix han...
597
  		ide_tape_stall_queue(drive);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
598
  		return ide_stopped;
6f3848ac2   Borislav Petkov   ide-tape: fix han...
599
  	} else {
626542ca2   Borislav Petkov   ide-tape: change ...
600
  		drive->atapi_flags &= ~IDE_AFLAG_IGNORE_DSC;
6f3848ac2   Borislav Petkov   ide-tape: fix han...
601
602
  		tape->postponed_rq = false;
  	}
626542ca2   Borislav Petkov   ide-tape: change ...
603

82ed4db49   Christoph Hellwig   block: split scsi...
604
  	if (req->cmd[13] & REQ_IDETAPE_READ) {
2e8a6f89d   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
605
  		pc = &tape->queued_pc;
0014c75be   Borislav Petkov   ide-tape: pass pa...
606
  		ide_tape_create_rw_cmd(tape, pc, rq, READ_6);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
607
608
  		goto out;
  	}
82ed4db49   Christoph Hellwig   block: split scsi...
609
  	if (req->cmd[13] & REQ_IDETAPE_WRITE) {
2e8a6f89d   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
610
  		pc = &tape->queued_pc;
0014c75be   Borislav Petkov   ide-tape: pass pa...
611
  		ide_tape_create_rw_cmd(tape, pc, rq, WRITE_6);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
612
613
  		goto out;
  	}
82ed4db49   Christoph Hellwig   block: split scsi...
614
  	if (req->cmd[13] & REQ_IDETAPE_PC1) {
22ce0a7cc   Christoph Hellwig   ide: don't use re...
615
  		pc = (struct ide_atapi_pc *)ide_req(rq)->special;
82ed4db49   Christoph Hellwig   block: split scsi...
616
617
  		req->cmd[13] &= ~(REQ_IDETAPE_PC1);
  		req->cmd[13] |= REQ_IDETAPE_PC2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
618
619
  		goto out;
  	}
82ed4db49   Christoph Hellwig   block: split scsi...
620
  	if (req->cmd[13] & REQ_IDETAPE_PC2) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
621
622
623
624
  		idetape_media_access_finished(drive);
  		return ide_stopped;
  	}
  	BUG();
28c7214bd   Bartlomiej Zolnierkiewicz   ide: add PC_FLAG_...
625

f2e3ab52a   Borislav Petkov   ide-tape: convert...
626
  out:
6b544fcc8   Borislav Petkov   ide-atapi: conver...
627
628
  	/* prepare sense request for this command */
  	ide_prep_sense(drive, rq);
b788ee9c6   Bartlomiej Zolnierkiewicz   ide: use do_rw_ta...
629
630
631
632
633
634
  	memset(&cmd, 0, sizeof(cmd));
  
  	if (rq_data_dir(rq))
  		cmd.tf_flags |= IDE_TFLAG_WRITE;
  
  	cmd.rq = rq;
dfb7e621f   Borislav Petkov   ide-atapi: switch...
635
  	ide_init_sg_cmd(&cmd, blk_rq_bytes(rq));
5c4be5724   Tejun Heo   ide-cd,atapi: use...
636
  	ide_map_sg(drive, &cmd);
b788ee9c6   Bartlomiej Zolnierkiewicz   ide: use do_rw_ta...
637
  	return ide_tape_issue_pc(drive, &cmd, pc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
638
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
639
  /*
3c98bf347   Borislav Petkov   ide-tape: cleanup...
640
641
   * Write a filemark if write_filemark=1. Flush the device buffers without
   * writing a filemark otherwise.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
642
   */
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
643
  static void idetape_create_write_filemark_cmd(ide_drive_t *drive,
d236d74c0   Borislav Petkov   ide-tape: convert...
644
  		struct ide_atapi_pc *pc, int write_filemark)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
645
  {
7bf7420a3   Bartlomiej Zolnierkiewicz   ide: add ide_init...
646
  	ide_init_pc(pc);
90699ce2b   Borislav Petkov   ide-tape: use gen...
647
  	pc->c[0] = WRITE_FILEMARKS;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
648
  	pc->c[4] = write_filemark;
346331f82   Borislav Petkov   ide-tape: remove ...
649
  	pc->flags |= PC_FLAG_WAIT_FOR_DSC;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
650
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
651
652
653
  static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout)
  {
  	idetape_tape_t *tape = drive->driver_data;
2ac07d920   Bartlomiej Zolnierkiewicz   ide: add ide_queu...
654
  	struct gendisk *disk = tape->disk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
655
  	int load_attempted = 0;
3c98bf347   Borislav Petkov   ide-tape: cleanup...
656
  	/* Wait for the tape to become ready */
49d8078ad   Borislav Petkov   ide-tape: fix IDE...
657
  	set_bit(ilog2(IDE_AFLAG_MEDIUM_PRESENT), &drive->atapi_flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
658
659
  	timeout += jiffies;
  	while (time_before(jiffies, timeout)) {
de699ad59   Bartlomiej Zolnierkiewicz   ide: add ide_do_t...
660
  		if (ide_do_test_unit_ready(drive, disk) == 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
661
662
  			return 0;
  		if ((tape->sense_key == 2 && tape->asc == 4 && tape->ascq == 2)
3c98bf347   Borislav Petkov   ide-tape: cleanup...
663
664
  		    || (tape->asc == 0x3A)) {
  			/* no media */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
665
666
  			if (load_attempted)
  				return -ENOMEDIUM;
0c8a6c7ae   Bartlomiej Zolnierkiewicz   ide: add ide_do_s...
667
  			ide_do_start_stop(drive, disk, IDETAPE_LU_LOAD_MASK);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
668
669
670
671
672
  			load_attempted = 1;
  		/* not about to be ready */
  		} else if (!(tape->sense_key == 2 && tape->asc == 4 &&
  			     (tape->ascq == 1 || tape->ascq == 8)))
  			return -EIO;
80ce45fd9   Nishanth Aravamudan   [PATCH] janitor: ...
673
  		msleep(100);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
674
675
676
  	}
  	return -EIO;
  }
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
677
  static int idetape_flush_tape_buffers(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
678
  {
2ac07d920   Bartlomiej Zolnierkiewicz   ide: add ide_queu...
679
  	struct ide_tape_obj *tape = drive->driver_data;
d236d74c0   Borislav Petkov   ide-tape: convert...
680
  	struct ide_atapi_pc pc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
681
682
683
  	int rc;
  
  	idetape_create_write_filemark_cmd(drive, &pc, 0);
b13345f39   Borislav Petkov   ide-atapi: add a ...
684
  	rc = ide_queue_pc_tail(drive, tape->disk, &pc, NULL, 0);
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
685
  	if (rc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
686
687
688
689
  		return rc;
  	idetape_wait_ready(drive, 60 * 5 * HZ);
  	return 0;
  }
55ce3a129   Borislav Petkov   ide-tape: fix REA...
690
  static int ide_tape_read_position(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
691
692
  {
  	idetape_tape_t *tape = drive->driver_data;
d236d74c0   Borislav Petkov   ide-tape: convert...
693
  	struct ide_atapi_pc pc;
55ce3a129   Borislav Petkov   ide-tape: fix REA...
694
  	u8 buf[20];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
695

e972d7027   Borislav Petkov   ide-tape: convert...
696
  	ide_debug_log(IDE_DBG_FUNC, "enter");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
697

55ce3a129   Borislav Petkov   ide-tape: fix REA...
698
699
700
701
702
703
  	/* prep cmd */
  	ide_init_pc(&pc);
  	pc.c[0] = READ_POSITION;
  	pc.req_xfer = 20;
  
  	if (ide_queue_pc_tail(drive, tape->disk, &pc, buf, pc.req_xfer))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
704
  		return -1;
55ce3a129   Borislav Petkov   ide-tape: fix REA...
705
706
  
  	if (!pc.error) {
e972d7027   Borislav Petkov   ide-tape: convert...
707
  		ide_debug_log(IDE_DBG_FUNC, "BOP - %s",
55ce3a129   Borislav Petkov   ide-tape: fix REA...
708
  				(buf[0] & 0x80) ? "Yes" : "No");
e972d7027   Borislav Petkov   ide-tape: convert...
709
  		ide_debug_log(IDE_DBG_FUNC, "EOP - %s",
55ce3a129   Borislav Petkov   ide-tape: fix REA...
710
711
712
713
714
715
  				(buf[0] & 0x40) ? "Yes" : "No");
  
  		if (buf[0] & 0x4) {
  			printk(KERN_INFO "ide-tape: Block location is unknown"
  					 "to the tape
  ");
8dcce4081   Bartlomiej Zolnierkiewicz   Merge branch 'bp-...
716
717
  			clear_bit(ilog2(IDE_AFLAG_ADDRESS_VALID),
  				  &drive->atapi_flags);
55ce3a129   Borislav Petkov   ide-tape: fix REA...
718
719
  			return -1;
  		} else {
e972d7027   Borislav Petkov   ide-tape: convert...
720
721
  			ide_debug_log(IDE_DBG_FUNC, "Block Location: %u",
  				      be32_to_cpup((__be32 *)&buf[4]));
55ce3a129   Borislav Petkov   ide-tape: fix REA...
722
723
724
  
  			tape->partition = buf[1];
  			tape->first_frame = be32_to_cpup((__be32 *)&buf[4]);
8dcce4081   Bartlomiej Zolnierkiewicz   Merge branch 'bp-...
725
726
  			set_bit(ilog2(IDE_AFLAG_ADDRESS_VALID),
  				&drive->atapi_flags);
55ce3a129   Borislav Petkov   ide-tape: fix REA...
727
728
729
730
  		}
  	}
  
  	return tape->first_frame;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
731
  }
d236d74c0   Borislav Petkov   ide-tape: convert...
732
733
  static void idetape_create_locate_cmd(ide_drive_t *drive,
  		struct ide_atapi_pc *pc,
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
734
  		unsigned int block, u8 partition, int skip)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
735
  {
7bf7420a3   Bartlomiej Zolnierkiewicz   ide: add ide_init...
736
  	ide_init_pc(pc);
90699ce2b   Borislav Petkov   ide-tape: use gen...
737
  	pc->c[0] = POSITION_TO_ELEMENT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
738
  	pc->c[1] = 2;
860ff5ecb   Borislav Petkov   ide-tape: use gen...
739
  	put_unaligned(cpu_to_be32(block), (unsigned int *) &pc->c[3]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
740
  	pc->c[8] = partition;
346331f82   Borislav Petkov   ide-tape: remove ...
741
  	pc->flags |= PC_FLAG_WAIT_FOR_DSC;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
742
  }
ec0fdb01f   Borislav Petkov   ide-tape: mv idet...
743
  static void __ide_tape_discard_merge_buffer(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
744
745
  {
  	idetape_tape_t *tape = drive->driver_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
746

54abf37e4   Borislav Petkov   ide-tape: remove ...
747
  	if (tape->chrdev_dir != IDETAPE_DIR_READ)
9798630a7   Borislav Petkov   ide-tape: make __...
748
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
749

49d8078ad   Borislav Petkov   ide-tape: fix IDE...
750
  	clear_bit(ilog2(IDE_AFLAG_FILEMARK), &drive->atapi_flags);
963da55c4   Tejun Heo   ide-tape: kill id...
751
752
753
754
  	tape->valid = 0;
  	if (tape->buf != NULL) {
  		kfree(tape->buf);
  		tape->buf = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
755
  	}
54abf37e4   Borislav Petkov   ide-tape: remove ...
756
  	tape->chrdev_dir = IDETAPE_DIR_NONE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
757
758
759
  }
  
  /*
3c98bf347   Borislav Petkov   ide-tape: cleanup...
760
761
762
763
   * Position the tape to the requested block using the LOCATE packet command.
   * A READ POSITION command is then issued to check where we are positioned. Like
   * all higher level operations, we queue the commands at the tail of the request
   * queue and wait for their completion.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
764
   */
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
765
766
  static int idetape_position_tape(ide_drive_t *drive, unsigned int block,
  		u8 partition, int skip)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
767
768
  {
  	idetape_tape_t *tape = drive->driver_data;
2ac07d920   Bartlomiej Zolnierkiewicz   ide: add ide_queu...
769
  	struct gendisk *disk = tape->disk;
55ce3a129   Borislav Petkov   ide-tape: fix REA...
770
  	int ret;
d236d74c0   Borislav Petkov   ide-tape: convert...
771
  	struct ide_atapi_pc pc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
772

54abf37e4   Borislav Petkov   ide-tape: remove ...
773
  	if (tape->chrdev_dir == IDETAPE_DIR_READ)
ec0fdb01f   Borislav Petkov   ide-tape: mv idet...
774
  		__ide_tape_discard_merge_buffer(drive);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
775
776
  	idetape_wait_ready(drive, 60 * 5 * HZ);
  	idetape_create_locate_cmd(drive, &pc, block, partition, skip);
55ce3a129   Borislav Petkov   ide-tape: fix REA...
777
778
779
  	ret = ide_queue_pc_tail(drive, disk, &pc, NULL, 0);
  	if (ret)
  		return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
780

55ce3a129   Borislav Petkov   ide-tape: fix REA...
781
782
783
784
  	ret = ide_tape_read_position(drive);
  	if (ret < 0)
  		return ret;
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
785
  }
ec0fdb01f   Borislav Petkov   ide-tape: mv idet...
786
  static void ide_tape_discard_merge_buffer(ide_drive_t *drive,
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
787
  					  int restore_position)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
788
789
  {
  	idetape_tape_t *tape = drive->driver_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
790
  	int seek, position;
ec0fdb01f   Borislav Petkov   ide-tape: mv idet...
791
  	__ide_tape_discard_merge_buffer(drive);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
792
  	if (restore_position) {
55ce3a129   Borislav Petkov   ide-tape: fix REA...
793
  		position = ide_tape_read_position(drive);
9798630a7   Borislav Petkov   ide-tape: make __...
794
  		seek = position > 0 ? position : 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
795
  		if (idetape_position_tape(drive, seek, 0, 0)) {
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
796
  			printk(KERN_INFO "ide-tape: %s: position_tape failed in"
ec0fdb01f   Borislav Petkov   ide-tape: mv idet...
797
798
  					 " %s
  ", tape->name, __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
799
800
801
802
803
804
  			return;
  		}
  	}
  }
  
  /*
3c98bf347   Borislav Petkov   ide-tape: cleanup...
805
806
   * Generate a read/write request for the block device interface and wait for it
   * to be serviced.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
807
   */
6bb11dd14   Tejun Heo   ide-tape: use byt...
808
  static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int size)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
809
810
  {
  	idetape_tape_t *tape = drive->driver_data;
64ea1b4ab   FUJITA Tomonori   ide-tape: convert...
811
  	struct request *rq;
21d9c5d22   Tejun Heo   ide-tape: use sta...
812
  	int ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
813

e972d7027   Borislav Petkov   ide-tape: convert...
814
  	ide_debug_log(IDE_DBG_FUNC, "cmd: 0x%x, size: %d", cmd, size);
21d9c5d22   Tejun Heo   ide-tape: use sta...
815
  	BUG_ON(cmd != REQ_IDETAPE_READ && cmd != REQ_IDETAPE_WRITE);
6bb11dd14   Tejun Heo   ide-tape: use byt...
816
  	BUG_ON(size < 0 || size % tape->blk_size);
8004a8c97   Borislav Petkov   ide-tape: refacto...
817

ff005a066   Christoph Hellwig   block: sanitize b...
818
  	rq = blk_get_request(drive->queue, REQ_OP_DRV_IN, 0);
2f5a8e80f   Christoph Hellwig   ide: don't abuse ...
819
  	ide_req(rq)->type = ATA_PRIV_MISC;
82ed4db49   Christoph Hellwig   block: split scsi...
820
  	scsi_req(rq)->cmd[13] = cmd;
64ea1b4ab   FUJITA Tomonori   ide-tape: convert...
821
  	rq->rq_disk = tape->disk;
c9059598e   Linus Torvalds   Merge branch 'for...
822
  	rq->__sector = tape->first_frame;
21d9c5d22   Tejun Heo   ide-tape: use sta...
823
824
  
  	if (size) {
963da55c4   Tejun Heo   ide-tape: kill id...
825
  		ret = blk_rq_map_kern(drive->queue, rq, tape->buf, size,
0eb0b63c1   Christoph Hellwig   block: consistent...
826
  				      GFP_NOIO);
21d9c5d22   Tejun Heo   ide-tape: use sta...
827
828
829
  		if (ret)
  			goto out_put;
  	}
64ea1b4ab   FUJITA Tomonori   ide-tape: convert...
830
  	blk_execute_rq(drive->queue, tape->disk, rq, 0);
963da55c4   Tejun Heo   ide-tape: kill id...
831
  	/* calculate the number of transferred bytes and update buffer state */
82ed4db49   Christoph Hellwig   block: split scsi...
832
  	size -= scsi_req(rq)->resid_len;
963da55c4   Tejun Heo   ide-tape: kill id...
833
  	tape->cur = tape->buf;
21d9c5d22   Tejun Heo   ide-tape: use sta...
834
  	if (cmd == REQ_IDETAPE_READ)
963da55c4   Tejun Heo   ide-tape: kill id...
835
836
837
  		tape->valid = size;
  	else
  		tape->valid = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
838

21d9c5d22   Tejun Heo   ide-tape: use sta...
839
  	ret = size;
17d5363b8   Christoph Hellwig   scsi: introduce a...
840
  	if (scsi_req(rq)->result == IDE_DRV_ERROR_GENERAL)
21d9c5d22   Tejun Heo   ide-tape: use sta...
841
  		ret = -EIO;
21d9c5d22   Tejun Heo   ide-tape: use sta...
842
843
  out_put:
  	blk_put_request(rq);
64ea1b4ab   FUJITA Tomonori   ide-tape: convert...
844
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
845
  }
d236d74c0   Borislav Petkov   ide-tape: convert...
846
  static void idetape_create_inquiry_cmd(struct ide_atapi_pc *pc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
847
  {
7bf7420a3   Bartlomiej Zolnierkiewicz   ide: add ide_init...
848
  	ide_init_pc(pc);
90699ce2b   Borislav Petkov   ide-tape: use gen...
849
  	pc->c[0] = INQUIRY;
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
850
  	pc->c[4] = 254;
d236d74c0   Borislav Petkov   ide-tape: convert...
851
  	pc->req_xfer = 254;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
852
  }
d236d74c0   Borislav Petkov   ide-tape: convert...
853
854
  static void idetape_create_rewind_cmd(ide_drive_t *drive,
  		struct ide_atapi_pc *pc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
855
  {
7bf7420a3   Bartlomiej Zolnierkiewicz   ide: add ide_init...
856
  	ide_init_pc(pc);
90699ce2b   Borislav Petkov   ide-tape: use gen...
857
  	pc->c[0] = REZERO_UNIT;
346331f82   Borislav Petkov   ide-tape: remove ...
858
  	pc->flags |= PC_FLAG_WAIT_FOR_DSC;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
859
  }
d236d74c0   Borislav Petkov   ide-tape: convert...
860
  static void idetape_create_erase_cmd(struct ide_atapi_pc *pc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
861
  {
7bf7420a3   Bartlomiej Zolnierkiewicz   ide: add ide_init...
862
  	ide_init_pc(pc);
90699ce2b   Borislav Petkov   ide-tape: use gen...
863
  	pc->c[0] = ERASE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
864
  	pc->c[1] = 1;
346331f82   Borislav Petkov   ide-tape: remove ...
865
  	pc->flags |= PC_FLAG_WAIT_FOR_DSC;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
866
  }
d236d74c0   Borislav Petkov   ide-tape: convert...
867
  static void idetape_create_space_cmd(struct ide_atapi_pc *pc, int count, u8 cmd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
868
  {
7bf7420a3   Bartlomiej Zolnierkiewicz   ide: add ide_init...
869
  	ide_init_pc(pc);
90699ce2b   Borislav Petkov   ide-tape: use gen...
870
  	pc->c[0] = SPACE;
860ff5ecb   Borislav Petkov   ide-tape: use gen...
871
  	put_unaligned(cpu_to_be32(count), (unsigned int *) &pc->c[1]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
872
  	pc->c[1] = cmd;
346331f82   Borislav Petkov   ide-tape: remove ...
873
  	pc->flags |= PC_FLAG_WAIT_FOR_DSC;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
874
  }
d9df937af   Borislav Petkov   ide-tape: mv idet...
875
  static void ide_tape_flush_merge_buffer(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
876
877
  {
  	idetape_tape_t *tape = drive->driver_data;
55a5d291f   Borislav Petkov   ide-tape: remove ...
878

54abf37e4   Borislav Petkov   ide-tape: remove ...
879
  	if (tape->chrdev_dir != IDETAPE_DIR_WRITE) {
077e3bdb9   Borislav Petkov   ide-tape: remove ...
880
  		printk(KERN_ERR "ide-tape: bug: Trying to empty merge buffer"
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
881
882
  				" but we are not writing.
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
883
884
  		return;
  	}
963da55c4   Tejun Heo   ide-tape: kill id...
885
  	if (tape->buf) {
6bb11dd14   Tejun Heo   ide-tape: use byt...
886
887
888
  		size_t aligned = roundup(tape->valid, tape->blk_size);
  
  		memset(tape->cur, 0, aligned - tape->valid);
07bd9686c   Tejun Heo   ide-tape: simplif...
889
  		idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, aligned);
963da55c4   Tejun Heo   ide-tape: kill id...
890
891
  		kfree(tape->buf);
  		tape->buf = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
892
  	}
54abf37e4   Borislav Petkov   ide-tape: remove ...
893
  	tape->chrdev_dir = IDETAPE_DIR_NONE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
894
  }
88f1b941c   Tejun Heo   ide-tape: unify r...
895
  static int idetape_init_rw(ide_drive_t *drive, int dir)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
896
897
  {
  	idetape_tape_t *tape = drive->driver_data;
88f1b941c   Tejun Heo   ide-tape: unify r...
898
  	int rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
899

88f1b941c   Tejun Heo   ide-tape: unify r...
900
  	BUG_ON(dir != IDETAPE_DIR_READ && dir != IDETAPE_DIR_WRITE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
901

88f1b941c   Tejun Heo   ide-tape: unify r...
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
  	if (tape->chrdev_dir == dir)
  		return 0;
  
  	if (tape->chrdev_dir == IDETAPE_DIR_READ)
  		ide_tape_discard_merge_buffer(drive, 1);
  	else if (tape->chrdev_dir == IDETAPE_DIR_WRITE) {
  		ide_tape_flush_merge_buffer(drive);
  		idetape_flush_tape_buffers(drive);
  	}
  
  	if (tape->buf || tape->valid) {
  		printk(KERN_ERR "ide-tape: valid should be 0 now
  ");
  		tape->valid = 0;
  	}
  
  	tape->buf = kmalloc(tape->buffer_size, GFP_KERNEL);
  	if (!tape->buf)
  		return -ENOMEM;
  	tape->chrdev_dir = dir;
  	tape->cur = tape->buf;
  
  	/*
  	 * Issue a 0 rw command to ensure that DSC handshake is
  	 * switched from completion mode to buffer available mode.  No
  	 * point in issuing this if DSC overlap isn't supported, some
  	 * drives (Seagate STT3401A) will return an error.
  	 */
  	if (drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) {
  		int cmd = dir == IDETAPE_DIR_READ ? REQ_IDETAPE_READ
  						  : REQ_IDETAPE_WRITE;
  
  		rc = idetape_queue_rw_tail(drive, cmd, 0);
  		if (rc < 0) {
  			kfree(tape->buf);
  			tape->buf = NULL;
  			tape->chrdev_dir = IDETAPE_DIR_NONE;
  			return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
940
941
  		}
  	}
5e69bd959   Borislav Petkov   ide-tape: remove ...
942

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
943
944
  	return 0;
  }
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
945
  static void idetape_pad_zeros(ide_drive_t *drive, int bcount)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
946
947
  {
  	idetape_tape_t *tape = drive->driver_data;
963da55c4   Tejun Heo   ide-tape: kill id...
948
949
  
  	memset(tape->buf, 0, tape->buffer_size);
3c98bf347   Borislav Petkov   ide-tape: cleanup...
950

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
951
  	while (bcount) {
963da55c4   Tejun Heo   ide-tape: kill id...
952
  		unsigned int count = min(tape->buffer_size, bcount);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
953

6bb11dd14   Tejun Heo   ide-tape: use byt...
954
  		idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
955
  		bcount -= count;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
956
957
  	}
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
958
  /*
3c98bf347   Borislav Petkov   ide-tape: cleanup...
959
960
961
   * Rewinds the tape to the Beginning Of the current Partition (BOP). We
   * currently support only one partition.
   */
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
962
  static int idetape_rewind_tape(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
963
  {
2ac07d920   Bartlomiej Zolnierkiewicz   ide: add ide_queu...
964
965
  	struct ide_tape_obj *tape = drive->driver_data;
  	struct gendisk *disk = tape->disk;
d236d74c0   Borislav Petkov   ide-tape: convert...
966
  	struct ide_atapi_pc pc;
55ce3a129   Borislav Petkov   ide-tape: fix REA...
967
  	int ret;
8004a8c97   Borislav Petkov   ide-tape: refacto...
968

e972d7027   Borislav Petkov   ide-tape: convert...
969
  	ide_debug_log(IDE_DBG_FUNC, "enter");
8004a8c97   Borislav Petkov   ide-tape: refacto...
970

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
971
  	idetape_create_rewind_cmd(drive, &pc);
55ce3a129   Borislav Petkov   ide-tape: fix REA...
972
973
974
  	ret = ide_queue_pc_tail(drive, disk, &pc, NULL, 0);
  	if (ret)
  		return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
975

55ce3a129   Borislav Petkov   ide-tape: fix REA...
976
977
978
  	ret = ide_tape_read_position(drive);
  	if (ret < 0)
  		return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
979
980
  	return 0;
  }
3c98bf347   Borislav Petkov   ide-tape: cleanup...
981
  /* mtio.h compatible commands should be issued to the chrdev interface. */
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
982
983
  static int idetape_blkdev_ioctl(ide_drive_t *drive, unsigned int cmd,
  				unsigned long arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
984
985
  {
  	idetape_tape_t *tape = drive->driver_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
986
  	void __user *argp = (void __user *)arg;
d59823fa4   Borislav Petkov   ide-tape: remove ...
987
988
989
990
991
  	struct idetape_config {
  		int dsc_rw_frequency;
  		int dsc_media_access_frequency;
  		int nr_stages;
  	} config;
e972d7027   Borislav Petkov   ide-tape: convert...
992
  	ide_debug_log(IDE_DBG_FUNC, "cmd: 0x%04x", cmd);
8004a8c97   Borislav Petkov   ide-tape: refacto...
993

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
994
  	switch (cmd) {
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
995
996
997
998
  	case 0x0340:
  		if (copy_from_user(&config, argp, sizeof(config)))
  			return -EFAULT;
  		tape->best_dsc_rw_freq = config.dsc_rw_frequency;
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
999
1000
  		break;
  	case 0x0350:
2fc2111c2   Michael Buesch   ide-tape: Don't l...
1001
  		memset(&config, 0, sizeof(config));
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1002
  		config.dsc_rw_frequency = (int) tape->best_dsc_rw_freq;
83042b241   Borislav Petkov   ide-tape: remove ...
1003
  		config.nr_stages = 1;
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1004
1005
1006
1007
1008
  		if (copy_to_user(argp, &config, sizeof(config)))
  			return -EFAULT;
  		break;
  	default:
  		return -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1009
1010
1011
  	}
  	return 0;
  }
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1012
1013
  static int idetape_space_over_filemarks(ide_drive_t *drive, short mt_op,
  					int mt_count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1014
1015
  {
  	idetape_tape_t *tape = drive->driver_data;
2ac07d920   Bartlomiej Zolnierkiewicz   ide: add ide_queu...
1016
  	struct gendisk *disk = tape->disk;
d236d74c0   Borislav Petkov   ide-tape: convert...
1017
  	struct ide_atapi_pc pc;
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1018
  	int retval, count = 0;
b64220132   Borislav Petkov   ide-tape: remove ...
1019
  	int sprev = !!(tape->caps[4] & 0x20);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1020

e972d7027   Borislav Petkov   ide-tape: convert...
1021
1022
  
  	ide_debug_log(IDE_DBG_FUNC, "mt_op: %d, mt_count: %d", mt_op, mt_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1023
1024
1025
  	if (mt_count == 0)
  		return 0;
  	if (MTBSF == mt_op || MTBSFM == mt_op) {
b64220132   Borislav Petkov   ide-tape: remove ...
1026
  		if (!sprev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1027
  			return -EIO;
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1028
  		mt_count = -mt_count;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1029
  	}
54abf37e4   Borislav Petkov   ide-tape: remove ...
1030
  	if (tape->chrdev_dir == IDETAPE_DIR_READ) {
963da55c4   Tejun Heo   ide-tape: kill id...
1031
  		tape->valid = 0;
49d8078ad   Borislav Petkov   ide-tape: fix IDE...
1032
1033
  		if (test_and_clear_bit(ilog2(IDE_AFLAG_FILEMARK),
  				       &drive->atapi_flags))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1034
  			++count;
ec0fdb01f   Borislav Petkov   ide-tape: mv idet...
1035
  		ide_tape_discard_merge_buffer(drive, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1036
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1037
  	switch (mt_op) {
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1038
1039
1040
1041
  	case MTFSF:
  	case MTBSF:
  		idetape_create_space_cmd(&pc, mt_count - count,
  					 IDETAPE_SPACE_OVER_FILEMARK);
b13345f39   Borislav Petkov   ide-atapi: add a ...
1042
  		return ide_queue_pc_tail(drive, disk, &pc, NULL, 0);
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
  	case MTFSFM:
  	case MTBSFM:
  		if (!sprev)
  			return -EIO;
  		retval = idetape_space_over_filemarks(drive, MTFSF,
  						      mt_count - count);
  		if (retval)
  			return retval;
  		count = (MTBSFM == mt_op ? 1 : -1);
  		return idetape_space_over_filemarks(drive, MTFSF, count);
  	default:
  		printk(KERN_ERR "ide-tape: MTIO operation %d not supported
  ",
  				mt_op);
  		return -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1058
1059
  	}
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1060
  /*
3c98bf347   Borislav Petkov   ide-tape: cleanup...
1061
   * Our character device read / write functions.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1062
   *
3c98bf347   Borislav Petkov   ide-tape: cleanup...
1063
1064
1065
   * The tape is optimized to maximize throughput when it is transferring an
   * integral number of the "continuous transfer limit", which is a parameter of
   * the specific tape (26kB on my particular tape, 32kB for Onstream).
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1066
   *
3c98bf347   Borislav Petkov   ide-tape: cleanup...
1067
1068
1069
1070
1071
1072
1073
   * As of version 1.3 of the driver, the character device provides an abstract
   * continuous view of the media - any mix of block sizes (even 1 byte) on the
   * same backup/restore procedure is supported. The driver will internally
   * convert the requests to the recommended transfer unit, so that an unmatch
   * between the user's block size to the recommended size will only result in a
   * (slightly) increased driver overhead, but will no longer hit performance.
   * This is not applicable to Onstream.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1074
   */
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1075
1076
  static ssize_t idetape_chrdev_read(struct file *file, char __user *buf,
  				   size_t count, loff_t *ppos)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1077
  {
5aeddf907   Borislav Petkov   ide: unify conver...
1078
  	struct ide_tape_obj *tape = file->private_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1079
  	ide_drive_t *drive = tape->drive;
07bd9686c   Tejun Heo   ide-tape: simplif...
1080
  	size_t done = 0;
dcd963796   Daniel Walker   [PATCH] idetape g...
1081
  	ssize_t ret = 0;
07bd9686c   Tejun Heo   ide-tape: simplif...
1082
  	int rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1083

5b5e0928f   Alexey Dobriyan   lib/vsprintf.c: r...
1084
  	ide_debug_log(IDE_DBG_FUNC, "count %zd", count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1085

54abf37e4   Borislav Petkov   ide-tape: remove ...
1086
  	if (tape->chrdev_dir != IDETAPE_DIR_READ) {
49d8078ad   Borislav Petkov   ide-tape: fix IDE...
1087
  		if (test_bit(ilog2(IDE_AFLAG_DETECT_BS), &drive->atapi_flags))
54bb2074c   Borislav Petkov   ide-tape: struct ...
1088
1089
1090
  			if (count > tape->blk_size &&
  			    (count % tape->blk_size) == 0)
  				tape->user_bs_factor = count / tape->blk_size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1091
  	}
07bd9686c   Tejun Heo   ide-tape: simplif...
1092

88f1b941c   Tejun Heo   ide-tape: unify r...
1093
  	rc = idetape_init_rw(drive, IDETAPE_DIR_READ);
8d06bfadb   Borislav Petkov   ide-tape: shorten...
1094
  	if (rc < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1095
  		return rc;
07bd9686c   Tejun Heo   ide-tape: simplif...
1096
1097
1098
1099
1100
1101
1102
  
  	while (done < count) {
  		size_t todo;
  
  		/* refill if staging buffer is empty */
  		if (!tape->valid) {
  			/* If we are at a filemark, nothing more to read */
49d8078ad   Borislav Petkov   ide-tape: fix IDE...
1103
1104
  			if (test_bit(ilog2(IDE_AFLAG_FILEMARK),
  				     &drive->atapi_flags))
07bd9686c   Tejun Heo   ide-tape: simplif...
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
  				break;
  			/* read */
  			if (idetape_queue_rw_tail(drive, REQ_IDETAPE_READ,
  						  tape->buffer_size) <= 0)
  				break;
  		}
  
  		/* copy out */
  		todo = min_t(size_t, count - done, tape->valid);
  		if (copy_to_user(buf + done, tape->cur, todo))
dcd963796   Daniel Walker   [PATCH] idetape g...
1115
  			ret = -EFAULT;
07bd9686c   Tejun Heo   ide-tape: simplif...
1116
1117
1118
1119
  
  		tape->cur += todo;
  		tape->valid -= todo;
  		done += todo;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1120
  	}
07bd9686c   Tejun Heo   ide-tape: simplif...
1121

49d8078ad   Borislav Petkov   ide-tape: fix IDE...
1122
  	if (!done && test_bit(ilog2(IDE_AFLAG_FILEMARK), &drive->atapi_flags)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1123
1124
1125
  		idetape_space_over_filemarks(drive, MTFSF, 1);
  		return 0;
  	}
dcd963796   Daniel Walker   [PATCH] idetape g...
1126

07bd9686c   Tejun Heo   ide-tape: simplif...
1127
  	return ret ? ret : done;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1128
  }
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1129
  static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1130
1131
  				     size_t count, loff_t *ppos)
  {
5aeddf907   Borislav Petkov   ide: unify conver...
1132
  	struct ide_tape_obj *tape = file->private_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1133
  	ide_drive_t *drive = tape->drive;
07bd9686c   Tejun Heo   ide-tape: simplif...
1134
  	size_t done = 0;
dcd963796   Daniel Walker   [PATCH] idetape g...
1135
  	ssize_t ret = 0;
88f1b941c   Tejun Heo   ide-tape: unify r...
1136
  	int rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1137
1138
1139
1140
  
  	/* The drive is write protected. */
  	if (tape->write_prot)
  		return -EACCES;
5b5e0928f   Alexey Dobriyan   lib/vsprintf.c: r...
1141
  	ide_debug_log(IDE_DBG_FUNC, "count %zd", count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1142
1143
  
  	/* Initialize write operation */
88f1b941c   Tejun Heo   ide-tape: unify r...
1144
1145
1146
  	rc = idetape_init_rw(drive, IDETAPE_DIR_WRITE);
  	if (rc < 0)
  		return rc;
07bd9686c   Tejun Heo   ide-tape: simplif...
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
  
  	while (done < count) {
  		size_t todo;
  
  		/* flush if staging buffer is full */
  		if (tape->valid == tape->buffer_size &&
  		    idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE,
  					  tape->buffer_size) <= 0)
  			return rc;
  
  		/* copy in */
  		todo = min_t(size_t, count - done,
  			     tape->buffer_size - tape->valid);
  		if (copy_from_user(tape->cur, buf + done, todo))
dcd963796   Daniel Walker   [PATCH] idetape g...
1161
  			ret = -EFAULT;
07bd9686c   Tejun Heo   ide-tape: simplif...
1162
1163
1164
1165
  
  		tape->cur += todo;
  		tape->valid += todo;
  		done += todo;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1166
  	}
07bd9686c   Tejun Heo   ide-tape: simplif...
1167
1168
  
  	return ret ? ret : done;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1169
  }
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1170
  static int idetape_write_filemark(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1171
  {
2ac07d920   Bartlomiej Zolnierkiewicz   ide: add ide_queu...
1172
  	struct ide_tape_obj *tape = drive->driver_data;
d236d74c0   Borislav Petkov   ide-tape: convert...
1173
  	struct ide_atapi_pc pc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1174
1175
1176
  
  	/* Write a filemark */
  	idetape_create_write_filemark_cmd(drive, &pc, 1);
b13345f39   Borislav Petkov   ide-atapi: add a ...
1177
  	if (ide_queue_pc_tail(drive, tape->disk, &pc, NULL, 0)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1178
1179
1180
1181
1182
1183
1184
1185
  		printk(KERN_ERR "ide-tape: Couldn't write a filemark
  ");
  		return -EIO;
  	}
  	return 0;
  }
  
  /*
d99c9da21   Borislav Petkov   ide-tape: remove ...
1186
1187
   * Called from idetape_chrdev_ioctl when the general mtio MTIOCTOP ioctl is
   * requested.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1188
   *
d99c9da21   Borislav Petkov   ide-tape: remove ...
1189
1190
   * Note: MTBSF and MTBSFM are not supported when the tape doesn't support
   * spacing over filemarks in the reverse direction. In this case, MTFSFM is also
5bd50dc6a   Borislav Petkov   ide-tape: remove ...
1191
   * usually not supported.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1192
   *
d99c9da21   Borislav Petkov   ide-tape: remove ...
1193
   * The following commands are currently not supported:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1194
   *
d99c9da21   Borislav Petkov   ide-tape: remove ...
1195
1196
   * MTFSS, MTBSS, MTWSM, MTSETDENSITY, MTSETDRVBUFFER, MT_ST_BOOLEANS,
   * MT_ST_WRITE_THRESHOLD.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1197
   */
d99c9da21   Borislav Petkov   ide-tape: remove ...
1198
  static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1199
1200
  {
  	idetape_tape_t *tape = drive->driver_data;
2ac07d920   Bartlomiej Zolnierkiewicz   ide: add ide_queu...
1201
  	struct gendisk *disk = tape->disk;
d236d74c0   Borislav Petkov   ide-tape: convert...
1202
  	struct ide_atapi_pc pc;
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1203
  	int i, retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1204

e972d7027   Borislav Petkov   ide-tape: convert...
1205
1206
  	ide_debug_log(IDE_DBG_FUNC, "MTIOCTOP ioctl: mt_op: %d, mt_count: %d",
  		      mt_op, mt_count);
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1207

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1208
  	switch (mt_op) {
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1209
1210
1211
1212
1213
1214
1215
1216
1217
  	case MTFSF:
  	case MTFSFM:
  	case MTBSF:
  	case MTBSFM:
  		if (!mt_count)
  			return 0;
  		return idetape_space_over_filemarks(drive, mt_op, mt_count);
  	default:
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1218
  	}
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1219

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1220
  	switch (mt_op) {
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1221
1222
1223
  	case MTWEOF:
  		if (tape->write_prot)
  			return -EACCES;
ec0fdb01f   Borislav Petkov   ide-tape: mv idet...
1224
  		ide_tape_discard_merge_buffer(drive, 1);
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1225
1226
1227
1228
1229
1230
1231
  		for (i = 0; i < mt_count; i++) {
  			retval = idetape_write_filemark(drive);
  			if (retval)
  				return retval;
  		}
  		return 0;
  	case MTREW:
ec0fdb01f   Borislav Petkov   ide-tape: mv idet...
1232
  		ide_tape_discard_merge_buffer(drive, 0);
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1233
1234
1235
1236
  		if (idetape_rewind_tape(drive))
  			return -EIO;
  		return 0;
  	case MTLOAD:
ec0fdb01f   Borislav Petkov   ide-tape: mv idet...
1237
  		ide_tape_discard_merge_buffer(drive, 0);
0c8a6c7ae   Bartlomiej Zolnierkiewicz   ide: add ide_do_s...
1238
  		return ide_do_start_stop(drive, disk, IDETAPE_LU_LOAD_MASK);
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1239
1240
1241
1242
1243
1244
1245
  	case MTUNLOAD:
  	case MTOFFL:
  		/*
  		 * If door is locked, attempt to unlock before
  		 * attempting to eject.
  		 */
  		if (tape->door_locked) {
0578042db   Bartlomiej Zolnierkiewicz   ide: add ide_set_...
1246
  			if (!ide_set_media_lock(drive, disk, 0))
385a4b878   Bartlomiej Zolnierkiewicz   ide-tape: add ide...
1247
  				tape->door_locked = DOOR_UNLOCKED;
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1248
  		}
ec0fdb01f   Borislav Petkov   ide-tape: mv idet...
1249
  		ide_tape_discard_merge_buffer(drive, 0);
0c8a6c7ae   Bartlomiej Zolnierkiewicz   ide: add ide_do_s...
1250
  		retval = ide_do_start_stop(drive, disk, !IDETAPE_LU_LOAD_MASK);
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1251
  		if (!retval)
49d8078ad   Borislav Petkov   ide-tape: fix IDE...
1252
1253
  			clear_bit(ilog2(IDE_AFLAG_MEDIUM_PRESENT),
  				  &drive->atapi_flags);
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1254
1255
  		return retval;
  	case MTNOP:
ec0fdb01f   Borislav Petkov   ide-tape: mv idet...
1256
  		ide_tape_discard_merge_buffer(drive, 0);
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1257
1258
  		return idetape_flush_tape_buffers(drive);
  	case MTRETEN:
ec0fdb01f   Borislav Petkov   ide-tape: mv idet...
1259
  		ide_tape_discard_merge_buffer(drive, 0);
0c8a6c7ae   Bartlomiej Zolnierkiewicz   ide: add ide_do_s...
1260
  		return ide_do_start_stop(drive, disk,
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1261
  			IDETAPE_LU_RETENSION_MASK | IDETAPE_LU_LOAD_MASK);
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1262
1263
  	case MTEOM:
  		idetape_create_space_cmd(&pc, 0, IDETAPE_SPACE_TO_EOD);
b13345f39   Borislav Petkov   ide-atapi: add a ...
1264
  		return ide_queue_pc_tail(drive, disk, &pc, NULL, 0);
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1265
1266
1267
  	case MTERASE:
  		(void)idetape_rewind_tape(drive);
  		idetape_create_erase_cmd(&pc);
b13345f39   Borislav Petkov   ide-atapi: add a ...
1268
  		return ide_queue_pc_tail(drive, disk, &pc, NULL, 0);
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1269
1270
1271
1272
  	case MTSETBLK:
  		if (mt_count) {
  			if (mt_count < tape->blk_size ||
  			    mt_count % tape->blk_size)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1273
  				return -EIO;
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1274
  			tape->user_bs_factor = mt_count / tape->blk_size;
49d8078ad   Borislav Petkov   ide-tape: fix IDE...
1275
1276
  			clear_bit(ilog2(IDE_AFLAG_DETECT_BS),
  				  &drive->atapi_flags);
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1277
  		} else
49d8078ad   Borislav Petkov   ide-tape: fix IDE...
1278
1279
  			set_bit(ilog2(IDE_AFLAG_DETECT_BS),
  				&drive->atapi_flags);
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1280
1281
  		return 0;
  	case MTSEEK:
ec0fdb01f   Borislav Petkov   ide-tape: mv idet...
1282
  		ide_tape_discard_merge_buffer(drive, 0);
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1283
1284
1285
  		return idetape_position_tape(drive,
  			mt_count * tape->user_bs_factor, tape->partition, 0);
  	case MTSETPART:
ec0fdb01f   Borislav Petkov   ide-tape: mv idet...
1286
  		ide_tape_discard_merge_buffer(drive, 0);
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1287
1288
1289
1290
  		return idetape_position_tape(drive, 0, mt_count, 0);
  	case MTFSR:
  	case MTBSR:
  	case MTLOCK:
0578042db   Bartlomiej Zolnierkiewicz   ide: add ide_set_...
1291
  		retval = ide_set_media_lock(drive, disk, 1);
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1292
  		if (retval)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1293
  			return retval;
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1294
1295
1296
  		tape->door_locked = DOOR_EXPLICITLY_LOCKED;
  		return 0;
  	case MTUNLOCK:
0578042db   Bartlomiej Zolnierkiewicz   ide: add ide_set_...
1297
  		retval = ide_set_media_lock(drive, disk, 0);
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1298
1299
1300
1301
1302
1303
1304
1305
1306
  		if (retval)
  			return retval;
  		tape->door_locked = DOOR_UNLOCKED;
  		return 0;
  	default:
  		printk(KERN_ERR "ide-tape: MTIO operation %d not supported
  ",
  				mt_op);
  		return -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1307
1308
1309
1310
  	}
  }
  
  /*
d99c9da21   Borislav Petkov   ide-tape: remove ...
1311
1312
1313
   * Our character device ioctls. General mtio.h magnetic io commands are
   * supported here, and not in the corresponding block interface. Our own
   * ide-tape ioctls are supported on both interfaces.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1314
   */
05227adff   Alan Cox   ide_tape: kill of...
1315
  static long do_idetape_chrdev_ioctl(struct file *file,
d99c9da21   Borislav Petkov   ide-tape: remove ...
1316
  				unsigned int cmd, unsigned long arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1317
  {
5aeddf907   Borislav Petkov   ide: unify conver...
1318
  	struct ide_tape_obj *tape = file->private_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1319
1320
1321
1322
  	ide_drive_t *drive = tape->drive;
  	struct mtop mtop;
  	struct mtget mtget;
  	struct mtpos mtpos;
54bb2074c   Borislav Petkov   ide-tape: struct ...
1323
  	int block_offset = 0, position = tape->first_frame;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1324
  	void __user *argp = (void __user *)arg;
e972d7027   Borislav Petkov   ide-tape: convert...
1325
  	ide_debug_log(IDE_DBG_FUNC, "cmd: 0x%x", cmd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1326

54abf37e4   Borislav Petkov   ide-tape: remove ...
1327
  	if (tape->chrdev_dir == IDETAPE_DIR_WRITE) {
d9df937af   Borislav Petkov   ide-tape: mv idet...
1328
  		ide_tape_flush_merge_buffer(drive);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1329
1330
1331
  		idetape_flush_tape_buffers(drive);
  	}
  	if (cmd == MTIOCGET || cmd == MTIOCPOS) {
963da55c4   Tejun Heo   ide-tape: kill id...
1332
  		block_offset = tape->valid /
54bb2074c   Borislav Petkov   ide-tape: struct ...
1333
  			(tape->blk_size * tape->user_bs_factor);
55ce3a129   Borislav Petkov   ide-tape: fix REA...
1334
  		position = ide_tape_read_position(drive);
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1335
  		if (position < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1336
1337
1338
  			return -EIO;
  	}
  	switch (cmd) {
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
  	case MTIOCTOP:
  		if (copy_from_user(&mtop, argp, sizeof(struct mtop)))
  			return -EFAULT;
  		return idetape_mtioctop(drive, mtop.mt_op, mtop.mt_count);
  	case MTIOCGET:
  		memset(&mtget, 0, sizeof(struct mtget));
  		mtget.mt_type = MT_ISSCSI2;
  		mtget.mt_blkno = position / tape->user_bs_factor - block_offset;
  		mtget.mt_dsreg =
  			((tape->blk_size * tape->user_bs_factor)
  			 << MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK;
  
  		if (tape->drv_write_prot)
  			mtget.mt_gstat |= GMT_WR_PROT(0xffffffff);
1207045da   Arnd Bergmann   compat_ioctl: mov...
1353
  		return put_user_mtget(argp, &mtget);
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1354
1355
  	case MTIOCPOS:
  		mtpos.mt_blkno = position / tape->user_bs_factor - block_offset;
1207045da   Arnd Bergmann   compat_ioctl: mov...
1356
  		return put_user_mtpos(argp, &mtpos);
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1357
1358
  	default:
  		if (tape->chrdev_dir == IDETAPE_DIR_READ)
ec0fdb01f   Borislav Petkov   ide-tape: mv idet...
1359
  			ide_tape_discard_merge_buffer(drive, 1);
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1360
  		return idetape_blkdev_ioctl(drive, cmd, arg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1361
1362
  	}
  }
05227adff   Alan Cox   ide_tape: kill of...
1363
1364
1365
1366
  static long idetape_chrdev_ioctl(struct file *file,
  				unsigned int cmd, unsigned long arg)
  {
  	long ret;
2a48fc0ab   Arnd Bergmann   block: autoconver...
1367
  	mutex_lock(&ide_tape_mutex);
05227adff   Alan Cox   ide_tape: kill of...
1368
  	ret = do_idetape_chrdev_ioctl(file, cmd, arg);
2a48fc0ab   Arnd Bergmann   block: autoconver...
1369
  	mutex_unlock(&ide_tape_mutex);
05227adff   Alan Cox   ide_tape: kill of...
1370
1371
  	return ret;
  }
1207045da   Arnd Bergmann   compat_ioctl: mov...
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
  static long idetape_chrdev_compat_ioctl(struct file *file,
  				unsigned int cmd, unsigned long arg)
  {
  	long ret;
  
  	if (cmd == MTIOCPOS32)
  		cmd = MTIOCPOS;
  	else if (cmd == MTIOCGET32)
  		cmd = MTIOCGET;
  
  	mutex_lock(&ide_tape_mutex);
  	ret = do_idetape_chrdev_ioctl(file, cmd, arg);
  	mutex_unlock(&ide_tape_mutex);
  	return ret;
  }
3cffb9ce4   Borislav Petkov   ide-tape: remove ...
1387
1388
1389
1390
1391
1392
1393
  /*
   * Do a mode sense page 0 with block descriptor and if it succeeds set the tape
   * block size with the reported value.
   */
  static void ide_tape_get_bsize_from_bdesc(ide_drive_t *drive)
  {
  	idetape_tape_t *tape = drive->driver_data;
d236d74c0   Borislav Petkov   ide-tape: convert...
1394
  	struct ide_atapi_pc pc;
837272b4f   Borislav Petkov   ide-tape/ide_tape...
1395
  	u8 buf[12];
3cffb9ce4   Borislav Petkov   ide-tape: remove ...
1396
1397
  
  	idetape_create_mode_sense_cmd(&pc, IDETAPE_BLOCK_DESCRIPTOR);
837272b4f   Borislav Petkov   ide-tape/ide_tape...
1398
  	if (ide_queue_pc_tail(drive, tape->disk, &pc, buf, pc.req_xfer)) {
3cffb9ce4   Borislav Petkov   ide-tape: remove ...
1399
1400
  		printk(KERN_ERR "ide-tape: Can't get block descriptor
  ");
54bb2074c   Borislav Petkov   ide-tape: struct ...
1401
  		if (tape->blk_size == 0) {
3cffb9ce4   Borislav Petkov   ide-tape: remove ...
1402
1403
1404
  			printk(KERN_WARNING "ide-tape: Cannot deal with zero "
  					    "block size, assuming 32k
  ");
54bb2074c   Borislav Petkov   ide-tape: struct ...
1405
  			tape->blk_size = 32768;
3cffb9ce4   Borislav Petkov   ide-tape: remove ...
1406
1407
1408
  		}
  		return;
  	}
837272b4f   Borislav Petkov   ide-tape/ide_tape...
1409
1410
1411
1412
  	tape->blk_size = (buf[4 + 5] << 16) +
  				(buf[4 + 6] << 8)  +
  				 buf[4 + 7];
  	tape->drv_write_prot = (buf[2] & 0x80) >> 7;
e972d7027   Borislav Petkov   ide-tape: convert...
1413
1414
1415
  
  	ide_debug_log(IDE_DBG_FUNC, "blk_size: %d, write_prot: %d",
  		      tape->blk_size, tape->drv_write_prot);
3cffb9ce4   Borislav Petkov   ide-tape: remove ...
1416
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1417

5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1418
  static int idetape_chrdev_open(struct inode *inode, struct file *filp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1419
1420
1421
1422
  {
  	unsigned int minor = iminor(inode), i = minor & ~0xc0;
  	ide_drive_t *drive;
  	idetape_tape_t *tape;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1423
  	int retval;
8004a8c97   Borislav Petkov   ide-tape: refacto...
1424
1425
  	if (i >= MAX_HWIFS * MAX_DRIVES)
  		return -ENXIO;
cbba2fa7b   Borislav Petkov   ide-tape: remove ...
1426
  	mutex_lock(&idetape_chrdev_mutex);
9d01e4cd7   Borislav Petkov   ide-tape: fix pro...
1427
  	tape = ide_tape_get(NULL, true, i);
04f4ac9d1   Jonathan Corbet   ide-tape: cdev lo...
1428
  	if (!tape) {
cbba2fa7b   Borislav Petkov   ide-tape: remove ...
1429
  		mutex_unlock(&idetape_chrdev_mutex);
8004a8c97   Borislav Petkov   ide-tape: refacto...
1430
  		return -ENXIO;
04f4ac9d1   Jonathan Corbet   ide-tape: cdev lo...
1431
  	}
8004a8c97   Borislav Petkov   ide-tape: refacto...
1432

e972d7027   Borislav Petkov   ide-tape: convert...
1433
1434
1435
1436
  	drive = tape->drive;
  	filp->private_data = tape;
  
  	ide_debug_log(IDE_DBG_FUNC, "enter");
8004a8c97   Borislav Petkov   ide-tape: refacto...
1437

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1438
1439
1440
1441
1442
1443
  	/*
  	 * We really want to do nonseekable_open(inode, filp); here, but some
  	 * versions of tar incorrectly call lseek on tapes and bail out if that
  	 * fails.  So we disallow pread() and pwrite(), but permit lseeks.
  	 */
  	filp->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1444

49d8078ad   Borislav Petkov   ide-tape: fix IDE...
1445
  	if (test_and_set_bit(ilog2(IDE_AFLAG_BUSY), &drive->atapi_flags)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1446
1447
1448
1449
1450
1451
  		retval = -EBUSY;
  		goto out_put_tape;
  	}
  
  	retval = idetape_wait_ready(drive, 60 * HZ);
  	if (retval) {
49d8078ad   Borislav Petkov   ide-tape: fix IDE...
1452
  		clear_bit(ilog2(IDE_AFLAG_BUSY), &drive->atapi_flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1453
1454
1455
1456
  		printk(KERN_ERR "ide-tape: %s: drive not ready
  ", tape->name);
  		goto out_put_tape;
  	}
79ca743f6   Borislav Petkov   ide-tape: fix bui...
1457
  	ide_tape_read_position(drive);
49d8078ad   Borislav Petkov   ide-tape: fix IDE...
1458
  	if (!test_bit(ilog2(IDE_AFLAG_ADDRESS_VALID), &drive->atapi_flags))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1459
  		(void)idetape_rewind_tape(drive);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1460
  	/* Read block size and write protect status from drive. */
3cffb9ce4   Borislav Petkov   ide-tape: remove ...
1461
  	ide_tape_get_bsize_from_bdesc(drive);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
  
  	/* Set write protect flag if device is opened as read-only. */
  	if ((filp->f_flags & O_ACCMODE) == O_RDONLY)
  		tape->write_prot = 1;
  	else
  		tape->write_prot = tape->drv_write_prot;
  
  	/* Make sure drive isn't write protected if user wants to write. */
  	if (tape->write_prot) {
  		if ((filp->f_flags & O_ACCMODE) == O_WRONLY ||
  		    (filp->f_flags & O_ACCMODE) == O_RDWR) {
49d8078ad   Borislav Petkov   ide-tape: fix IDE...
1473
  			clear_bit(ilog2(IDE_AFLAG_BUSY), &drive->atapi_flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1474
1475
1476
1477
  			retval = -EROFS;
  			goto out_put_tape;
  		}
  	}
3c98bf347   Borislav Petkov   ide-tape: cleanup...
1478
  	/* Lock the tape drive door so user can't eject. */
54abf37e4   Borislav Petkov   ide-tape: remove ...
1479
  	if (tape->chrdev_dir == IDETAPE_DIR_NONE) {
0578042db   Bartlomiej Zolnierkiewicz   ide: add ide_set_...
1480
  		if (!ide_set_media_lock(drive, tape->disk, 1)) {
385a4b878   Bartlomiej Zolnierkiewicz   ide-tape: add ide...
1481
1482
  			if (tape->door_locked != DOOR_EXPLICITLY_LOCKED)
  				tape->door_locked = DOOR_LOCKED;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1483
1484
  		}
  	}
cbba2fa7b   Borislav Petkov   ide-tape: remove ...
1485
  	mutex_unlock(&idetape_chrdev_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1486
1487
1488
1489
  	return 0;
  
  out_put_tape:
  	ide_tape_put(tape);
cbba2fa7b   Borislav Petkov   ide-tape: remove ...
1490
1491
  
  	mutex_unlock(&idetape_chrdev_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1492
1493
  	return retval;
  }
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1494
  static void idetape_write_release(ide_drive_t *drive, unsigned int minor)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1495
1496
  {
  	idetape_tape_t *tape = drive->driver_data;
d9df937af   Borislav Petkov   ide-tape: mv idet...
1497
  	ide_tape_flush_merge_buffer(drive);
963da55c4   Tejun Heo   ide-tape: kill id...
1498
1499
  	tape->buf = kmalloc(tape->buffer_size, GFP_KERNEL);
  	if (tape->buf != NULL) {
54bb2074c   Borislav Petkov   ide-tape: struct ...
1500
1501
  		idetape_pad_zeros(drive, tape->blk_size *
  				(tape->user_bs_factor - 1));
963da55c4   Tejun Heo   ide-tape: kill id...
1502
1503
  		kfree(tape->buf);
  		tape->buf = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1504
1505
1506
1507
1508
  	}
  	idetape_write_filemark(drive);
  	idetape_flush_tape_buffers(drive);
  	idetape_flush_tape_buffers(drive);
  }
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1509
  static int idetape_chrdev_release(struct inode *inode, struct file *filp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1510
  {
5aeddf907   Borislav Petkov   ide: unify conver...
1511
  	struct ide_tape_obj *tape = filp->private_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1512
  	ide_drive_t *drive = tape->drive;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1513
  	unsigned int minor = iminor(inode);
cbba2fa7b   Borislav Petkov   ide-tape: remove ...
1514
  	mutex_lock(&idetape_chrdev_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1515
  	tape = drive->driver_data;
8004a8c97   Borislav Petkov   ide-tape: refacto...
1516

e972d7027   Borislav Petkov   ide-tape: convert...
1517
  	ide_debug_log(IDE_DBG_FUNC, "enter");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1518

54abf37e4   Borislav Petkov   ide-tape: remove ...
1519
  	if (tape->chrdev_dir == IDETAPE_DIR_WRITE)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1520
  		idetape_write_release(drive, minor);
54abf37e4   Borislav Petkov   ide-tape: remove ...
1521
  	if (tape->chrdev_dir == IDETAPE_DIR_READ) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1522
  		if (minor < 128)
ec0fdb01f   Borislav Petkov   ide-tape: mv idet...
1523
  			ide_tape_discard_merge_buffer(drive, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1524
  	}
f64eee7bb   Borislav Petkov   ide-tape: remove ...
1525

49d8078ad   Borislav Petkov   ide-tape: fix IDE...
1526
1527
  	if (minor < 128 && test_bit(ilog2(IDE_AFLAG_MEDIUM_PRESENT),
  				    &drive->atapi_flags))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1528
  		(void) idetape_rewind_tape(drive);
49d8078ad   Borislav Petkov   ide-tape: fix IDE...
1529

54abf37e4   Borislav Petkov   ide-tape: remove ...
1530
  	if (tape->chrdev_dir == IDETAPE_DIR_NONE) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1531
  		if (tape->door_locked == DOOR_LOCKED) {
0578042db   Bartlomiej Zolnierkiewicz   ide: add ide_set_...
1532
  			if (!ide_set_media_lock(drive, tape->disk, 0))
385a4b878   Bartlomiej Zolnierkiewicz   ide-tape: add ide...
1533
  				tape->door_locked = DOOR_UNLOCKED;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1534
1535
  		}
  	}
49d8078ad   Borislav Petkov   ide-tape: fix IDE...
1536
  	clear_bit(ilog2(IDE_AFLAG_BUSY), &drive->atapi_flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1537
  	ide_tape_put(tape);
cbba2fa7b   Borislav Petkov   ide-tape: remove ...
1538
1539
  
  	mutex_unlock(&idetape_chrdev_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1540
1541
  	return 0;
  }
6d29c8f0a   Borislav Petkov   ide-tape: remove ...
1542
  static void idetape_get_inquiry_results(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1543
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1544
  	idetape_tape_t *tape = drive->driver_data;
d236d74c0   Borislav Petkov   ide-tape: convert...
1545
  	struct ide_atapi_pc pc;
41fa9f863   Bartlomiej Zolnierkiewicz   ide: decrease siz...
1546
  	u8 pc_buf[256];
801bd32e2   Borislav Petkov   ide-tape: fix ven...
1547
  	char fw_rev[4], vendor_id[8], product_id[16];
6d29c8f0a   Borislav Petkov   ide-tape: remove ...
1548

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1549
  	idetape_create_inquiry_cmd(&pc);
b13345f39   Borislav Petkov   ide-atapi: add a ...
1550
  	if (ide_queue_pc_tail(drive, tape->disk, &pc, pc_buf, pc.req_xfer)) {
6d29c8f0a   Borislav Petkov   ide-tape: remove ...
1551
1552
1553
  		printk(KERN_ERR "ide-tape: %s: can't get INQUIRY results
  ",
  				tape->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1554
1555
  		return;
  	}
b13345f39   Borislav Petkov   ide-atapi: add a ...
1556
1557
1558
  	memcpy(vendor_id, &pc_buf[8], 8);
  	memcpy(product_id, &pc_buf[16], 16);
  	memcpy(fw_rev, &pc_buf[32], 4);
41f81d545   Borislav Petkov   ide-tape: struct ...
1559

801bd32e2   Borislav Petkov   ide-tape: fix ven...
1560
1561
1562
  	ide_fixstring(vendor_id, 8, 0);
  	ide_fixstring(product_id, 16, 0);
  	ide_fixstring(fw_rev, 4, 0);
41f81d545   Borislav Petkov   ide-tape: struct ...
1563

801bd32e2   Borislav Petkov   ide-tape: fix ven...
1564
1565
  	printk(KERN_INFO "ide-tape: %s <-> %s: %.8s %.16s rev %.4s
  ",
41f81d545   Borislav Petkov   ide-tape: struct ...
1566
  			drive->name, tape->name, vendor_id, product_id, fw_rev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1567
1568
1569
  }
  
  /*
b64220132   Borislav Petkov   ide-tape: remove ...
1570
1571
   * Ask the tape about its various parameters. In particular, we will adjust our
   * data transfer buffer	size to the recommended value as returned by the tape.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1572
   */
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1573
  static void idetape_get_mode_sense_results(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1574
1575
  {
  	idetape_tape_t *tape = drive->driver_data;
d236d74c0   Borislav Petkov   ide-tape: convert...
1576
  	struct ide_atapi_pc pc;
b13345f39   Borislav Petkov   ide-atapi: add a ...
1577
  	u8 buf[24], *caps;
b64220132   Borislav Petkov   ide-tape: remove ...
1578
  	u8 speed, max_speed;
47314fa42   Borislav Petkov   ide-tape: remove ...
1579

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1580
  	idetape_create_mode_sense_cmd(&pc, IDETAPE_CAPABILITIES_PAGE);
b13345f39   Borislav Petkov   ide-atapi: add a ...
1581
  	if (ide_queue_pc_tail(drive, tape->disk, &pc, buf, pc.req_xfer)) {
b64220132   Borislav Petkov   ide-tape: remove ...
1582
1583
1584
  		printk(KERN_ERR "ide-tape: Can't get tape parameters - assuming"
  				" some default values
  ");
54bb2074c   Borislav Petkov   ide-tape: struct ...
1585
  		tape->blk_size = 512;
b64220132   Borislav Petkov   ide-tape: remove ...
1586
1587
1588
  		put_unaligned(52,   (u16 *)&tape->caps[12]);
  		put_unaligned(540,  (u16 *)&tape->caps[14]);
  		put_unaligned(6*52, (u16 *)&tape->caps[16]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1589
1590
  		return;
  	}
b13345f39   Borislav Petkov   ide-atapi: add a ...
1591
  	caps = buf + 4 + buf[3];
b64220132   Borislav Petkov   ide-tape: remove ...
1592
1593
  
  	/* convert to host order and save for later use */
cd740ab0f   Harvey Harrison   ide: ide-tape.c s...
1594
1595
  	speed = be16_to_cpup((__be16 *)&caps[14]);
  	max_speed = be16_to_cpup((__be16 *)&caps[8]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1596

cd740ab0f   Harvey Harrison   ide: ide-tape.c s...
1597
1598
1599
1600
  	*(u16 *)&caps[8] = max_speed;
  	*(u16 *)&caps[12] = be16_to_cpup((__be16 *)&caps[12]);
  	*(u16 *)&caps[14] = speed;
  	*(u16 *)&caps[16] = be16_to_cpup((__be16 *)&caps[16]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1601

b64220132   Borislav Petkov   ide-tape: remove ...
1602
1603
1604
1605
  	if (!speed) {
  		printk(KERN_INFO "ide-tape: %s: invalid tape speed "
  				"(assuming 650KB/sec)
  ", drive->name);
cd740ab0f   Harvey Harrison   ide: ide-tape.c s...
1606
  		*(u16 *)&caps[14] = 650;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1607
  	}
b64220132   Borislav Petkov   ide-tape: remove ...
1608
1609
1610
1611
  	if (!max_speed) {
  		printk(KERN_INFO "ide-tape: %s: invalid max_speed "
  				"(assuming 650KB/sec)
  ", drive->name);
cd740ab0f   Harvey Harrison   ide: ide-tape.c s...
1612
  		*(u16 *)&caps[8] = 650;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1613
  	}
b64220132   Borislav Petkov   ide-tape: remove ...
1614
  	memcpy(&tape->caps, caps, 20);
0578042db   Bartlomiej Zolnierkiewicz   ide: add ide_set_...
1615
1616
1617
  
  	/* device lacks locking support according to capabilities page */
  	if ((caps[6] & 1) == 0)
42619d35c   Bartlomiej Zolnierkiewicz   ide: remove IDE_A...
1618
  		drive->dev_flags &= ~IDE_DFLAG_DOORLOCKING;
0578042db   Bartlomiej Zolnierkiewicz   ide: add ide_set_...
1619

b64220132   Borislav Petkov   ide-tape: remove ...
1620
  	if (caps[7] & 0x02)
54bb2074c   Borislav Petkov   ide-tape: struct ...
1621
  		tape->blk_size = 512;
b64220132   Borislav Petkov   ide-tape: remove ...
1622
  	else if (caps[7] & 0x04)
54bb2074c   Borislav Petkov   ide-tape: struct ...
1623
  		tape->blk_size = 1024;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1624
  }
7662d046d   Bartlomiej Zolnierkiewicz   ide: move IDE set...
1625
  #ifdef CONFIG_IDE_PROC_FS
8185d5aa9   Bartlomiej Zolnierkiewicz   ide: /proc/ide/hd...
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
  #define ide_tape_devset_get(name, field) \
  static int get_##name(ide_drive_t *drive) \
  { \
  	idetape_tape_t *tape = drive->driver_data; \
  	return tape->field; \
  }
  
  #define ide_tape_devset_set(name, field) \
  static int set_##name(ide_drive_t *drive, int arg) \
  { \
  	idetape_tape_t *tape = drive->driver_data; \
  	tape->field = arg; \
  	return 0; \
  }
92f1f8fd8   Elias Oltmanns   ide: Remove ide_s...
1640
  #define ide_tape_devset_rw_field(_name, _field) \
8185d5aa9   Bartlomiej Zolnierkiewicz   ide: /proc/ide/hd...
1641
1642
  ide_tape_devset_get(_name, _field) \
  ide_tape_devset_set(_name, _field) \
92f1f8fd8   Elias Oltmanns   ide: Remove ide_s...
1643
  IDE_DEVSET(_name, DS_SYNC, get_##_name, set_##_name)
8185d5aa9   Bartlomiej Zolnierkiewicz   ide: /proc/ide/hd...
1644

92f1f8fd8   Elias Oltmanns   ide: Remove ide_s...
1645
  #define ide_tape_devset_r_field(_name, _field) \
8185d5aa9   Bartlomiej Zolnierkiewicz   ide: /proc/ide/hd...
1646
  ide_tape_devset_get(_name, _field) \
92f1f8fd8   Elias Oltmanns   ide: Remove ide_s...
1647
  IDE_DEVSET(_name, 0, get_##_name, NULL)
8185d5aa9   Bartlomiej Zolnierkiewicz   ide: /proc/ide/hd...
1648
1649
1650
1651
1652
  
  static int mulf_tdsc(ide_drive_t *drive)	{ return 1000; }
  static int divf_tdsc(ide_drive_t *drive)	{ return   HZ; }
  static int divf_buffer(ide_drive_t *drive)	{ return    2; }
  static int divf_buffer_size(ide_drive_t *drive)	{ return 1024; }
97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
1653
  ide_devset_rw_flag(dsc_overlap, IDE_DFLAG_DSC_OVERLAP);
92f1f8fd8   Elias Oltmanns   ide: Remove ide_s...
1654

92f1f8fd8   Elias Oltmanns   ide: Remove ide_s...
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
  ide_tape_devset_rw_field(tdsc, best_dsc_rw_freq);
  
  ide_tape_devset_r_field(avg_speed, avg_speed);
  ide_tape_devset_r_field(speed, caps[14]);
  ide_tape_devset_r_field(buffer, caps[16]);
  ide_tape_devset_r_field(buffer_size, buffer_size);
  
  static const struct ide_proc_devset idetape_settings[] = {
  	__IDE_PROC_DEVSET(avg_speed,	0, 0xffff, NULL, NULL),
  	__IDE_PROC_DEVSET(buffer,	0, 0xffff, NULL, divf_buffer),
  	__IDE_PROC_DEVSET(buffer_size,	0, 0xffff, NULL, divf_buffer_size),
92f1f8fd8   Elias Oltmanns   ide: Remove ide_s...
1666
1667
1668
1669
  	__IDE_PROC_DEVSET(dsc_overlap,	0,      1, NULL, NULL),
  	__IDE_PROC_DEVSET(speed,	0, 0xffff, NULL, NULL),
  	__IDE_PROC_DEVSET(tdsc,		IDETAPE_DSC_RW_MIN, IDETAPE_DSC_RW_MAX,
  					mulf_tdsc, divf_tdsc),
71bfc7a7c   Hannes Eder   ide: NULL noise: ...
1670
  	{ NULL },
8185d5aa9   Bartlomiej Zolnierkiewicz   ide: /proc/ide/hd...
1671
  };
7662d046d   Bartlomiej Zolnierkiewicz   ide: move IDE set...
1672
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1673
1674
  
  /*
3c98bf347   Borislav Petkov   ide-tape: cleanup...
1675
   * The function below is called to:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1676
   *
3c98bf347   Borislav Petkov   ide-tape: cleanup...
1677
1678
1679
1680
   * 1. Initialize our various state variables.
   * 2. Ask the tape for its capabilities.
   * 3. Allocate a buffer which will be used for data transfer. The buffer size
   * is chosen based on the recommendation which we received in step 2.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1681
   *
3c98bf347   Borislav Petkov   ide-tape: cleanup...
1682
1683
   * Note that at this point ide.c already assigned us an irq, so that we can
   * queue requests here and wait for their completion.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1684
   */
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1685
  static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1686
  {
83042b241   Borislav Petkov   ide-tape: remove ...
1687
  	unsigned long t;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1688
  	int speed;
b64220132   Borislav Petkov   ide-tape: remove ...
1689
  	u16 *ctl = (u16 *)&tape->caps[12];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1690

e972d7027   Borislav Petkov   ide-tape: convert...
1691
1692
1693
  	ide_debug_log(IDE_DBG_FUNC, "minor: %d", minor);
  
  	drive->pc_callback = ide_tape_callback;
776bb0270   Borislav Petkov   ide-tape: use dri...
1694

97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
1695
  	drive->dev_flags |= IDE_DFLAG_DSC_OVERLAP;
4166c1993   Bartlomiej Zolnierkiewicz   ide: add IDE_HFLA...
1696
1697
1698
1699
  	if (drive->hwif->host_flags & IDE_HFLAG_NO_DSC) {
  		printk(KERN_INFO "ide-tape: %s: disabling DSC overlap
  ",
  				 tape->name);
97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
1700
  		drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1701
  	}
97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
1702

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1703
  	/* Seagate Travan drives do not support DSC overlap. */
4dde4492d   Bartlomiej Zolnierkiewicz   ide: make drive->...
1704
  	if (strstr((char *)&drive->id[ATA_ID_PROD], "Seagate STT3401"))
97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
1705
  		drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1706
1707
1708
1709
  	tape->minor = minor;
  	tape->name[0] = 'h';
  	tape->name[1] = 't';
  	tape->name[2] = '0' + minor;
54abf37e4   Borislav Petkov   ide-tape: remove ...
1710
  	tape->chrdev_dir = IDETAPE_DIR_NONE;
4dde4492d   Bartlomiej Zolnierkiewicz   ide: make drive->...
1711

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1712
1713
  	idetape_get_inquiry_results(drive);
  	idetape_get_mode_sense_results(drive);
3cffb9ce4   Borislav Petkov   ide-tape: remove ...
1714
  	ide_tape_get_bsize_from_bdesc(drive);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1715
  	tape->user_bs_factor = 1;
f73850a30   Borislav Petkov   ide-tape: mv tape...
1716
1717
  	tape->buffer_size = *ctl * tape->blk_size;
  	while (tape->buffer_size > 0xffff) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1718
1719
  		printk(KERN_NOTICE "ide-tape: decreasing stage size
  ");
b64220132   Borislav Petkov   ide-tape: remove ...
1720
  		*ctl /= 2;
f73850a30   Borislav Petkov   ide-tape: mv tape...
1721
  		tape->buffer_size = *ctl * tape->blk_size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1722
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1723

83042b241   Borislav Petkov   ide-tape: remove ...
1724
  	/* select the "best" DSC read/write polling freq */
b64220132   Borislav Petkov   ide-tape: remove ...
1725
  	speed = max(*(u16 *)&tape->caps[14], *(u16 *)&tape->caps[8]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1726

f73850a30   Borislav Petkov   ide-tape: mv tape...
1727
  	t = (IDETAPE_FIFO_THRESHOLD * tape->buffer_size * HZ) / (speed * 1000);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1728
1729
  
  	/*
3c98bf347   Borislav Petkov   ide-tape: cleanup...
1730
1731
  	 * Ensure that the number we got makes sense; limit it within
  	 * IDETAPE_DSC_RW_MIN and IDETAPE_DSC_RW_MAX.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1732
  	 */
a792bd5a4   Harvey Harrison   ide-tape: use cla...
1733
1734
  	tape->best_dsc_rw_freq = clamp_t(unsigned long, t, IDETAPE_DSC_RW_MIN,
  					 IDETAPE_DSC_RW_MAX);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1735
  	printk(KERN_INFO "ide-tape: %s <-> %s: %dKBps, %d*%dkB buffer, "
842159640   Nicholas Mc Guire   ide_tape: convert...
1736
1737
  		"%ums tDSC%s
  ",
b64220132   Borislav Petkov   ide-tape: remove ...
1738
  		drive->name, tape->name, *(u16 *)&tape->caps[14],
f73850a30   Borislav Petkov   ide-tape: mv tape...
1739
1740
  		(*(u16 *)&tape->caps[16] * 512) / tape->buffer_size,
  		tape->buffer_size / 1024,
842159640   Nicholas Mc Guire   ide_tape: convert...
1741
  		jiffies_to_msecs(tape->best_dsc_rw_freq),
97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
1742
  		(drive->dev_flags & IDE_DFLAG_USING_DMA) ? ", DMA" : "");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1743

1e874f448   Bartlomiej Zolnierkiewicz   ide: call ide_pro...
1744
  	ide_proc_register_driver(drive, tape->driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1745
  }
4031bbe4b   Russell King   [PATCH] Add ide_b...
1746
  static void ide_tape_remove(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1747
1748
  {
  	idetape_tape_t *tape = drive->driver_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1749

7662d046d   Bartlomiej Zolnierkiewicz   ide: move IDE set...
1750
  	ide_proc_unregister_driver(drive, tape->driver);
8fed43684   Bartlomiej Zolnierkiewicz   ide: fix refcount...
1751
  	device_del(&tape->dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1752
  	ide_unregister_region(tape->disk);
8fed43684   Bartlomiej Zolnierkiewicz   ide: fix refcount...
1753
1754
1755
  	mutex_lock(&idetape_ref_mutex);
  	put_device(&tape->dev);
  	mutex_unlock(&idetape_ref_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1756
  }
8fed43684   Bartlomiej Zolnierkiewicz   ide: fix refcount...
1757
  static void ide_tape_release(struct device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1758
  {
8fed43684   Bartlomiej Zolnierkiewicz   ide: fix refcount...
1759
  	struct ide_tape_obj *tape = to_ide_drv(dev, ide_tape_obj);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1760
1761
  	ide_drive_t *drive = tape->drive;
  	struct gendisk *g = tape->disk;
963da55c4   Tejun Heo   ide-tape: kill id...
1762
  	BUG_ON(tape->valid);
8604affde   Bartlomiej Zolnierkiewicz   [PATCH] convert I...
1763

97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
1764
  	drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1765
  	drive->driver_data = NULL;
dbc1272ed   Tony Jones   IDE: Convert from...
1766
  	device_destroy(idetape_sysfs_class, MKDEV(IDETAPE_MAJOR, tape->minor));
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1767
1768
  	device_destroy(idetape_sysfs_class,
  			MKDEV(IDETAPE_MAJOR, tape->minor + 128));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1769
1770
1771
1772
1773
  	idetape_devs[tape->minor] = NULL;
  	g->private_data = NULL;
  	put_disk(g);
  	kfree(tape);
  }
ecfd80e4a   Bartlomiej Zolnierkiewicz   ide: make /proc/i...
1774
  #ifdef CONFIG_IDE_PROC_FS
6d703a81a   Alexey Dobriyan   ide: convert to -...
1775
  static int idetape_name_proc_show(struct seq_file *m, void *v)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1776
  {
6d703a81a   Alexey Dobriyan   ide: convert to -...
1777
  	ide_drive_t	*drive = (ide_drive_t *) m->private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1778
  	idetape_tape_t	*tape = drive->driver_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1779

6d703a81a   Alexey Dobriyan   ide: convert to -...
1780
1781
1782
1783
  	seq_printf(m, "%s
  ", tape->name);
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1784
  static ide_proc_entry_t idetape_proc[] = {
ec7d9c9ce   Christoph Hellwig   ide: replace ->pr...
1785
1786
  	{ "capacity",	S_IFREG|S_IRUGO,	ide_capacity_proc_show	},
  	{ "name",	S_IFREG|S_IRUGO,	idetape_name_proc_show	},
6d703a81a   Alexey Dobriyan   ide: convert to -...
1787
  	{}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1788
  };
79cb38039   Bartlomiej Zolnierkiewicz   ide: allow device...
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
  
  static ide_proc_entry_t *ide_tape_proc_entries(ide_drive_t *drive)
  {
  	return idetape_proc;
  }
  
  static const struct ide_proc_devset *ide_tape_proc_devsets(ide_drive_t *drive)
  {
  	return idetape_settings;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1799
  #endif
4031bbe4b   Russell King   [PATCH] Add ide_b...
1800
  static int ide_tape_probe(ide_drive_t *);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1801

7f3c868ba   Bartlomiej Zolnierkiewicz   ide: remove ide_d...
1802
  static struct ide_driver idetape_driver = {
8604affde   Bartlomiej Zolnierkiewicz   [PATCH] convert I...
1803
  	.gen_driver = {
4ef3b8f4a   Laurent Riffard   [PATCH] ide: remo...
1804
  		.owner		= THIS_MODULE,
8604affde   Bartlomiej Zolnierkiewicz   [PATCH] convert I...
1805
1806
  		.name		= "ide-tape",
  		.bus		= &ide_bus_type,
8604affde   Bartlomiej Zolnierkiewicz   [PATCH] convert I...
1807
  	},
4031bbe4b   Russell King   [PATCH] Add ide_b...
1808
1809
  	.probe			= ide_tape_probe,
  	.remove			= ide_tape_remove,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1810
  	.version		= IDETAPE_VERSION,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1811
  	.do_request		= idetape_do_request,
7662d046d   Bartlomiej Zolnierkiewicz   ide: move IDE set...
1812
  #ifdef CONFIG_IDE_PROC_FS
79cb38039   Bartlomiej Zolnierkiewicz   ide: allow device...
1813
1814
  	.proc_entries		= ide_tape_proc_entries,
  	.proc_devsets		= ide_tape_proc_devsets,
7662d046d   Bartlomiej Zolnierkiewicz   ide: move IDE set...
1815
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1816
  };
3c98bf347   Borislav Petkov   ide-tape: cleanup...
1817
  /* Our character device supporting functions, passed to register_chrdev. */
2b8693c06   Arjan van de Ven   [PATCH] mark stru...
1818
  static const struct file_operations idetape_fops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1819
1820
1821
  	.owner		= THIS_MODULE,
  	.read		= idetape_chrdev_read,
  	.write		= idetape_chrdev_write,
05227adff   Alan Cox   ide_tape: kill of...
1822
  	.unlocked_ioctl	= idetape_chrdev_ioctl,
1207045da   Arnd Bergmann   compat_ioctl: mov...
1823
1824
  	.compat_ioctl	= IS_ENABLED(CONFIG_COMPAT) ?
  			  idetape_chrdev_compat_ioctl : NULL,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1825
1826
  	.open		= idetape_chrdev_open,
  	.release	= idetape_chrdev_release,
6038f373a   Arnd Bergmann   llseek: automatic...
1827
  	.llseek		= noop_llseek,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1828
  };
a4600f813   Al Viro   [PATCH] switch id...
1829
  static int idetape_open(struct block_device *bdev, fmode_t mode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1830
  {
6e9624b8c   Arnd Bergmann   block: push down ...
1831
  	struct ide_tape_obj *tape;
2a48fc0ab   Arnd Bergmann   block: autoconver...
1832
  	mutex_lock(&ide_tape_mutex);
6e9624b8c   Arnd Bergmann   block: push down ...
1833
  	tape = ide_tape_get(bdev->bd_disk, false, 0);
2a48fc0ab   Arnd Bergmann   block: autoconver...
1834
  	mutex_unlock(&ide_tape_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1835

5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1836
  	if (!tape)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1837
  		return -ENXIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1838
1839
  	return 0;
  }
db2a144be   Al Viro   block_device_oper...
1840
  static void idetape_release(struct gendisk *disk, fmode_t mode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1841
  {
5aeddf907   Borislav Petkov   ide: unify conver...
1842
  	struct ide_tape_obj *tape = ide_drv_g(disk, ide_tape_obj);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1843

2a48fc0ab   Arnd Bergmann   block: autoconver...
1844
  	mutex_lock(&ide_tape_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1845
  	ide_tape_put(tape);
2a48fc0ab   Arnd Bergmann   block: autoconver...
1846
  	mutex_unlock(&ide_tape_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1847
  }
a4600f813   Al Viro   [PATCH] switch id...
1848
  static int idetape_ioctl(struct block_device *bdev, fmode_t mode,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1849
1850
  			unsigned int cmd, unsigned long arg)
  {
5aeddf907   Borislav Petkov   ide: unify conver...
1851
  	struct ide_tape_obj *tape = ide_drv_g(bdev->bd_disk, ide_tape_obj);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1852
  	ide_drive_t *drive = tape->drive;
8a6cfeb6d   Arnd Bergmann   block: push down ...
1853
  	int err;
2a48fc0ab   Arnd Bergmann   block: autoconver...
1854
  	mutex_lock(&ide_tape_mutex);
8a6cfeb6d   Arnd Bergmann   block: push down ...
1855
  	err = generic_ide_ioctl(drive, bdev, cmd, arg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1856
1857
  	if (err == -EINVAL)
  		err = idetape_blkdev_ioctl(drive, cmd, arg);
2a48fc0ab   Arnd Bergmann   block: autoconver...
1858
  	mutex_unlock(&ide_tape_mutex);
8a6cfeb6d   Arnd Bergmann   block: push down ...
1859

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1860
1861
  	return err;
  }
1df23c6fe   Arnd Bergmann   compat_ioctl: mov...
1862
1863
1864
1865
1866
1867
1868
1869
  static int idetape_compat_ioctl(struct block_device *bdev, fmode_t mode,
  				unsigned int cmd, unsigned long arg)
  {
          if (cmd == 0x0340 || cmd == 0x350)
  		arg = (unsigned long)compat_ptr(arg);
  
  	return idetape_ioctl(bdev, mode, cmd, arg);
  }
83d5cde47   Alexey Dobriyan   const: make block...
1870
  static const struct block_device_operations idetape_block_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1871
  	.owner		= THIS_MODULE,
a4600f813   Al Viro   [PATCH] switch id...
1872
1873
  	.open		= idetape_open,
  	.release	= idetape_release,
8a6cfeb6d   Arnd Bergmann   block: push down ...
1874
  	.ioctl		= idetape_ioctl,
1df23c6fe   Arnd Bergmann   compat_ioctl: mov...
1875
1876
  	.compat_ioctl	= IS_ENABLED(CONFIG_COMPAT) ?
  				idetape_compat_ioctl : NULL,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1877
  };
4031bbe4b   Russell King   [PATCH] Add ide_b...
1878
  static int ide_tape_probe(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1879
1880
1881
1882
  {
  	idetape_tape_t *tape;
  	struct gendisk *g;
  	int minor;
e972d7027   Borislav Petkov   ide-tape: convert...
1883
1884
1885
  	ide_debug_log(IDE_DBG_FUNC, "enter");
  
  	if (!strstr(DRV_NAME, drive->driver_req))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1886
  		goto failed;
2a924662b   Bartlomiej Zolnierkiewicz   ide: remove needl...
1887

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1888
1889
  	if (drive->media != ide_tape)
  		goto failed;
2a924662b   Bartlomiej Zolnierkiewicz   ide: remove needl...
1890

97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
1891
1892
  	if ((drive->dev_flags & IDE_DFLAG_ID_READ) &&
  	    ide_check_atapi_device(drive, DRV_NAME) == 0) {
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1893
1894
1895
  		printk(KERN_ERR "ide-tape: %s: not supported by this version of"
  				" the driver
  ", drive->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1896
1897
  		goto failed;
  	}
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1898
  	tape = kzalloc(sizeof(idetape_tape_t), GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1899
  	if (tape == NULL) {
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1900
1901
1902
  		printk(KERN_ERR "ide-tape: %s: Can't allocate a tape struct
  ",
  				drive->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1903
1904
1905
1906
1907
1908
1909
1910
  		goto failed;
  	}
  
  	g = alloc_disk(1 << PARTN_BITS);
  	if (!g)
  		goto out_free_tape;
  
  	ide_init_disk(g, drive);
8fed43684   Bartlomiej Zolnierkiewicz   ide: fix refcount...
1911
1912
  	tape->dev.parent = &drive->gendev;
  	tape->dev.release = ide_tape_release;
02aa2a376   Kees Cook   drivers: avoid fo...
1913
  	dev_set_name(&tape->dev, "%s", dev_name(&drive->gendev));
8fed43684   Bartlomiej Zolnierkiewicz   ide: fix refcount...
1914
1915
1916
  
  	if (device_register(&tape->dev))
  		goto out_free_disk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1917
1918
1919
1920
1921
1922
1923
1924
  
  	tape->drive = drive;
  	tape->driver = &idetape_driver;
  	tape->disk = g;
  
  	g->private_data = &tape->driver;
  
  	drive->driver_data = tape;
cf8b8975c   Arjan van de Ven   [PATCH] sem2mutex...
1925
  	mutex_lock(&idetape_ref_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1926
1927
1928
  	for (minor = 0; idetape_devs[minor]; minor++)
  		;
  	idetape_devs[minor] = tape;
cf8b8975c   Arjan van de Ven   [PATCH] sem2mutex...
1929
  	mutex_unlock(&idetape_ref_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1930
1931
  
  	idetape_setup(drive, tape, minor);
3ee074bf4   Greg Kroah-Hartman   device create: id...
1932
1933
1934
1935
1936
  	device_create(idetape_sysfs_class, &drive->gendev,
  		      MKDEV(IDETAPE_MAJOR, minor), NULL, "%s", tape->name);
  	device_create(idetape_sysfs_class, &drive->gendev,
  		      MKDEV(IDETAPE_MAJOR, minor + 128), NULL,
  		      "n%s", tape->name);
d5dee80ad   Will Dyson   [PATCH] add sysfs...
1937

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1938
1939
1940
1941
  	g->fops = &idetape_block_ops;
  	ide_register_region(g);
  
  	return 0;
8604affde   Bartlomiej Zolnierkiewicz   [PATCH] convert I...
1942

8fed43684   Bartlomiej Zolnierkiewicz   ide: fix refcount...
1943
1944
  out_free_disk:
  	put_disk(g);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1945
1946
1947
  out_free_tape:
  	kfree(tape);
  failed:
8604affde   Bartlomiej Zolnierkiewicz   [PATCH] convert I...
1948
  	return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1949
  }
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1950
  static void __exit idetape_exit(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1951
  {
8604affde   Bartlomiej Zolnierkiewicz   [PATCH] convert I...
1952
  	driver_unregister(&idetape_driver.gen_driver);
d5dee80ad   Will Dyson   [PATCH] add sysfs...
1953
  	class_destroy(idetape_sysfs_class);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1954
1955
  	unregister_chrdev(IDETAPE_MAJOR, "ht");
  }
17514e8a6   Bartlomiej Zolnierkiewicz   [PATCH] ide: add ...
1956
  static int __init idetape_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1957
  {
d5dee80ad   Will Dyson   [PATCH] add sysfs...
1958
1959
1960
1961
1962
1963
1964
1965
1966
  	int error = 1;
  	idetape_sysfs_class = class_create(THIS_MODULE, "ide_tape");
  	if (IS_ERR(idetape_sysfs_class)) {
  		idetape_sysfs_class = NULL;
  		printk(KERN_ERR "Unable to create sysfs class for ide tapes
  ");
  		error = -EBUSY;
  		goto out;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1967
  	if (register_chrdev(IDETAPE_MAJOR, "ht", &idetape_fops)) {
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1968
1969
1970
  		printk(KERN_ERR "ide-tape: Failed to register chrdev"
  				" interface
  ");
d5dee80ad   Will Dyson   [PATCH] add sysfs...
1971
1972
  		error = -EBUSY;
  		goto out_free_class;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1973
  	}
d5dee80ad   Will Dyson   [PATCH] add sysfs...
1974
1975
1976
  
  	error = driver_register(&idetape_driver.gen_driver);
  	if (error)
79f18a063   Alexey Khoroshilov   ide-tape: fix mis...
1977
  		goto out_free_chrdev;
d5dee80ad   Will Dyson   [PATCH] add sysfs...
1978
1979
  
  	return 0;
79f18a063   Alexey Khoroshilov   ide-tape: fix mis...
1980
1981
  out_free_chrdev:
  	unregister_chrdev(IDETAPE_MAJOR, "ht");
d5dee80ad   Will Dyson   [PATCH] add sysfs...
1982
1983
1984
1985
  out_free_class:
  	class_destroy(idetape_sysfs_class);
  out:
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1986
  }
263756ec2   Kay Sievers   [PATCH] ide: MODA...
1987
  MODULE_ALIAS("ide:*m-tape*");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1988
1989
1990
  module_init(idetape_init);
  module_exit(idetape_exit);
  MODULE_ALIAS_CHARDEV_MAJOR(IDETAPE_MAJOR);
9c1457688   Borislav Petkov   ide-tape: collect...
1991
1992
  MODULE_DESCRIPTION("ATAPI Streaming TAPE Driver");
  MODULE_LICENSE("GPL");