Blame view

drivers/ide/ide-tape.c 54.9 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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
21
22
23
24
25
26
27
  #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:...
28
  #include <linux/jiffies.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29
  #include <linux/major.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
31
  #include <linux/errno.h>
  #include <linux/genhd.h>
6d703a81a   Alexey Dobriyan   ide: convert to -...
32
  #include <linux/seq_file.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33
34
35
  #include <linux/slab.h>
  #include <linux/pci.h>
  #include <linux/ide.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36
37
  #include <linux/completion.h>
  #include <linux/bitops.h>
cf8b8975c   Arjan van de Ven   [PATCH] sem2mutex...
38
  #include <linux/mutex.h>
90699ce2b   Borislav Petkov   ide-tape: use gen...
39
  #include <scsi/scsi.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
41
  
  #include <asm/byteorder.h>
c837cfa5b   Borislav Petkov   ide-tape: include...
42
43
  #include <linux/uaccess.h>
  #include <linux/io.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
44
  #include <asm/unaligned.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45
  #include <linux/mtio.h>
8004a8c97   Borislav Petkov   ide-tape: refacto...
46
  /* define to see debug info */
e972d7027   Borislav Petkov   ide-tape: convert...
47
  #undef IDETAPE_DEBUG_LOG
8004a8c97   Borislav Petkov   ide-tape: refacto...
48

e972d7027   Borislav Petkov   ide-tape: convert...
49
50
  #ifdef IDETAPE_DEBUG_LOG
  #define ide_debug_log(lvl, fmt, args...) __ide_debug_log(lvl, fmt, ## args)
8004a8c97   Borislav Petkov   ide-tape: refacto...
51
  #else
e972d7027   Borislav Petkov   ide-tape: convert...
52
  #define ide_debug_log(lvl, fmt, args...) do {} while (0)
8004a8c97   Borislav Petkov   ide-tape: refacto...
53
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
54
  /**************************** Tunable parameters *****************************/
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
55
  /*
3c98bf347   Borislav Petkov   ide-tape: cleanup...
56
57
   * 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
58
   *
3c98bf347   Borislav Petkov   ide-tape: cleanup...
59
   * Setting IDETAPE_MAX_PC_RETRIES to 0 will disable retries.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60
61
62
63
   */
  #define IDETAPE_MAX_PC_RETRIES		3
  
  /*
3c98bf347   Borislav Petkov   ide-tape: cleanup...
64
65
66
67
   * 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
68
   */
3c98bf347   Borislav Petkov   ide-tape: cleanup...
69
  #define IDETAPE_FIFO_THRESHOLD		2
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70
71
  
  /*
3c98bf347   Borislav Petkov   ide-tape: cleanup...
72
   * DSC polling parameters.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
73
   *
3c98bf347   Borislav Petkov   ide-tape: cleanup...
74
75
   * 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
76
   *
3c98bf347   Borislav Petkov   ide-tape: cleanup...
77
78
79
80
81
   * 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
82
   *
3c98bf347   Borislav Petkov   ide-tape: cleanup...
83
84
85
86
87
88
89
90
   * 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
91
   *
3c98bf347   Borislav Petkov   ide-tape: cleanup...
92
93
   * 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
94
   */
3c98bf347   Borislav Petkov   ide-tape: cleanup...
95
96
  
  /* DSC timings. */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
97
98
99
100
101
102
103
104
105
  #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 ...
106
107
108
109
110
111
  /* 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
112

03056b909   Borislav Petkov   ide-tape: move al...
113
114
115
116
117
118
119
120
121
122
123
124
125
  /* 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...
126
127
128
  /* 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
129
  /*
3c98bf347   Borislav Petkov   ide-tape: cleanup...
130
131
   * 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
132
133
   */
  typedef struct ide_tape_obj {
7f3c868ba   Bartlomiej Zolnierkiewicz   ide: remove ide_d...
134
135
136
  	ide_drive_t		*drive;
  	struct ide_driver	*driver;
  	struct gendisk		*disk;
8fed43684   Bartlomiej Zolnierkiewicz   ide: fix refcount...
137
  	struct device		dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
138

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
142
  	/*
3c98bf347   Borislav Petkov   ide-tape: cleanup...
143
  	 * DSC polling variables.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
144
  	 *
3c98bf347   Borislav Petkov   ide-tape: cleanup...
145
146
147
  	 * 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 ...
148
  	 * data transfer) request in the device request queue.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
149
  	 */
6f3848ac2   Borislav Petkov   ide-tape: fix han...
150
  	bool postponed_rq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
151
152
153
154
155
  	/* 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 ...
156
157
  	unsigned long best_dsc_rw_freq;
  	unsigned long dsc_poll_freq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
158
  	unsigned long dsc_timeout;
3c98bf347   Borislav Petkov   ide-tape: cleanup...
159
  	/* Read position information */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
160
161
  	u8 partition;
  	/* Current block */
54bb2074c   Borislav Petkov   ide-tape: struct ...
162
  	unsigned int first_frame;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
163

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

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
177
  	/* Copy of the tape's Capabilities and Mechanical Page */
b64220132   Borislav Petkov   ide-tape: remove ...
178
  	u8 caps[20];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
179
180
  
  	/*
3c98bf347   Borislav Petkov   ide-tape: cleanup...
181
  	 * Active data transfer request parameters.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
182
  	 *
3c98bf347   Borislav Petkov   ide-tape: cleanup...
183
184
185
  	 * 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
186
  	 */
83042b241   Borislav Petkov   ide-tape: remove ...
187

3c98bf347   Borislav Petkov   ide-tape: cleanup...
188
  	/* Data buffer size chosen based on the tape's recommendation */
f73850a30   Borislav Petkov   ide-tape: mv tape...
189
  	int buffer_size;
963da55c4   Tejun Heo   ide-tape: kill id...
190
191
192
193
194
195
  	/* 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...
196

3c98bf347   Borislav Petkov   ide-tape: cleanup...
197
  	/* Measures average tape speed */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
198
199
200
  	unsigned long avg_time;
  	int avg_size;
  	int avg_speed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
201
202
203
204
205
206
  	/* 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
207
  } idetape_tape_t;
2a48fc0ab   Arnd Bergmann   block: autoconver...
208
  static DEFINE_MUTEX(ide_tape_mutex);
cf8b8975c   Arjan van de Ven   [PATCH] sem2mutex...
209
  static DEFINE_MUTEX(idetape_ref_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
210

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

9d01e4cd7   Borislav Petkov   ide-tape: fix pro...
215
216
217
218
  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
219
220
  {
  	struct ide_tape_obj *tape = NULL;
cf8b8975c   Arjan van de Ven   [PATCH] sem2mutex...
221
  	mutex_lock(&idetape_ref_mutex);
9d01e4cd7   Borislav Petkov   ide-tape: fix pro...
222
223
224
225
226
  
  	if (cdev)
  		tape = idetape_devs[i];
  	else
  		tape = ide_drv_g(disk, ide_tape_obj);
08da591e1   Bartlomiej Zolnierkiewicz   ide: add ide_devi...
227
  	if (tape) {
d3e33ff59   Bartlomiej Zolnierkiewicz   ide: fix regressi...
228
  		if (ide_device_get(tape->drive))
08da591e1   Bartlomiej Zolnierkiewicz   ide: add ide_devi...
229
  			tape = NULL;
d3e33ff59   Bartlomiej Zolnierkiewicz   ide: fix regressi...
230
  		else
8fed43684   Bartlomiej Zolnierkiewicz   ide: fix refcount...
231
  			get_device(&tape->dev);
08da591e1   Bartlomiej Zolnierkiewicz   ide: add ide_devi...
232
  	}
9d01e4cd7   Borislav Petkov   ide-tape: fix pro...
233

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

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

e972d7027   Borislav Petkov   ide-tape: convert...
260
261
262
  	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
263

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

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

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

5985e6abb   Bartlomiej Zolnierkiewicz   ide-tape: merge c...
321
322
  	if (pc->c[0] == REQUEST_SENSE) {
  		if (uptodate)
ae3a8387b   Borislav Petkov   ide-atapi: use lo...
323
  			idetape_analyze_error(drive);
5985e6abb   Bartlomiej Zolnierkiewicz   ide-tape: merge c...
324
325
326
327
328
  		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...
329
  		unsigned int blocks =
82ed4db49   Christoph Hellwig   block: split scsi...
330
  			(blk_rq_bytes(rq) - scsi_req(rq)->resid_len) / tape->blk_size;
5985e6abb   Bartlomiej Zolnierkiewicz   ide-tape: merge c...
331
332
333
334
335
336
337
338
339
340
341
  
  		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...
342

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

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

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

54bb2074c   Borislav Petkov   ide-tape: struct ...
364
  	ide_stall_queue(drive, tape->dsc_poll_freq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
365
  }
74e63e74e   Bartlomiej Zolnierkiewicz   ide-tape: factor ...
366
367
368
369
370
371
372
373
374
  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...
375
  	ide_tape_stall_queue(drive);
74e63e74e   Bartlomiej Zolnierkiewicz   ide-tape: factor ...
376
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
377
  /*
3c98bf347   Borislav Petkov   ide-tape: cleanup...
378
   * Packet Command Interface
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
379
   *
2b9efba48   Bartlomiej Zolnierkiewicz   ide: add pointer ...
380
   * The current Packet Command is available in drive->pc, and will not change
3c98bf347   Borislav Petkov   ide-tape: cleanup...
381
382
   * 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
383
   *
3c98bf347   Borislav Petkov   ide-tape: cleanup...
384
   * The handling will be done in three stages:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
385
   *
b788ee9c6   Bartlomiej Zolnierkiewicz   ide: use do_rw_ta...
386
   * 1. ide_tape_issue_pc will send the packet command to the drive, and will set
aa5d2de7b   Bartlomiej Zolnierkiewicz   ide: make ide_pc_...
387
   * the interrupt handler to ide_pc_intr.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
388
   *
aa5d2de7b   Bartlomiej Zolnierkiewicz   ide: make ide_pc_...
389
   * 2. On each interrupt, ide_pc_intr will be called. This step will be
3c98bf347   Borislav Petkov   ide-tape: cleanup...
390
   * repeated until the device signals us that no more interrupts will be issued.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
391
   *
3c98bf347   Borislav Petkov   ide-tape: cleanup...
392
393
394
395
396
397
398
   * 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
399
   *
3c98bf347   Borislav Petkov   ide-tape: cleanup...
400
401
   * 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
402
   *
3c98bf347   Borislav Petkov   ide-tape: cleanup...
403
   * 4. When the packet command is finished, it will be checked for errors.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
404
   *
3c98bf347   Borislav Petkov   ide-tape: cleanup...
405
406
407
   * 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
408
   *
3c98bf347   Borislav Petkov   ide-tape: cleanup...
409
410
411
   * 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
412
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
413

b788ee9c6   Bartlomiej Zolnierkiewicz   ide: use do_rw_ta...
414
415
416
  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
417
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
418
  	idetape_tape_t *tape = drive->driver_data;
dfb7e621f   Borislav Petkov   ide-atapi: switch...
419
  	struct request *rq = drive->hwif->rq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
420

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

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
430
  		/*
3c98bf347   Borislav Petkov   ide-tape: cleanup...
431
432
433
  		 * 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
434
  		 */
346331f82   Borislav Petkov   ide-tape: remove ...
435
  		if (!(pc->flags & PC_FLAG_ABORT)) {
90699ce2b   Borislav Petkov   ide-tape: use gen...
436
  			if (!(pc->c[0] == TEST_UNIT_READY &&
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
437
438
439
440
441
442
443
444
445
446
447
  			      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...
448
  			pc->error = IDE_DRV_ERROR_GENERAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
449
  		}
b3071d190   Tejun Heo   ide-atapi,tape,fl...
450

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

49d8078ad   Borislav Petkov   ide-tape: fix IDE...
749
  	clear_bit(ilog2(IDE_AFLAG_FILEMARK), &drive->atapi_flags);
963da55c4   Tejun Heo   ide-tape: kill id...
750
751
752
753
  	tape->valid = 0;
  	if (tape->buf != NULL) {
  		kfree(tape->buf);
  		tape->buf = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
754
  	}
54abf37e4   Borislav Petkov   ide-tape: remove ...
755
  	tape->chrdev_dir = IDETAPE_DIR_NONE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
756
757
758
  }
  
  /*
3c98bf347   Borislav Petkov   ide-tape: cleanup...
759
760
761
762
   * 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
763
   */
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
764
765
  static int idetape_position_tape(ide_drive_t *drive, unsigned int block,
  		u8 partition, int skip)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
766
767
  {
  	idetape_tape_t *tape = drive->driver_data;
2ac07d920   Bartlomiej Zolnierkiewicz   ide: add ide_queu...
768
  	struct gendisk *disk = tape->disk;
55ce3a129   Borislav Petkov   ide-tape: fix REA...
769
  	int ret;
d236d74c0   Borislav Petkov   ide-tape: convert...
770
  	struct ide_atapi_pc pc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
771

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

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

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

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

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

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

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

88f1b941c   Tejun Heo   ide-tape: unify r...
901
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
  	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
939
940
  		}
  	}
5e69bd959   Borislav Petkov   ide-tape: remove ...
941

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

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

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

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

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

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

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

e972d7027   Borislav Petkov   ide-tape: convert...
1020
1021
  
  	ide_debug_log(IDE_DBG_FUNC, "mt_op: %d, mt_count: %d", mt_op, mt_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1022
1023
1024
  	if (mt_count == 0)
  		return 0;
  	if (MTBSF == mt_op || MTBSFM == mt_op) {
b64220132   Borislav Petkov   ide-tape: remove ...
1025
  		if (!sprev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1026
  			return -EIO;
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1027
  		mt_count = -mt_count;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1028
  	}
54abf37e4   Borislav Petkov   ide-tape: remove ...
1029
  	if (tape->chrdev_dir == IDETAPE_DIR_READ) {
963da55c4   Tejun Heo   ide-tape: kill id...
1030
  		tape->valid = 0;
49d8078ad   Borislav Petkov   ide-tape: fix IDE...
1031
1032
  		if (test_and_clear_bit(ilog2(IDE_AFLAG_FILEMARK),
  				       &drive->atapi_flags))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1033
  			++count;
ec0fdb01f   Borislav Petkov   ide-tape: mv idet...
1034
  		ide_tape_discard_merge_buffer(drive, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1035
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1036
  	switch (mt_op) {
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1037
1038
1039
1040
  	case MTFSF:
  	case MTBSF:
  		idetape_create_space_cmd(&pc, mt_count - count,
  					 IDETAPE_SPACE_OVER_FILEMARK);
b13345f39   Borislav Petkov   ide-atapi: add a ...
1041
  		return ide_queue_pc_tail(drive, disk, &pc, NULL, 0);
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
  	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
1057
1058
  	}
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1059
  /*
3c98bf347   Borislav Petkov   ide-tape: cleanup...
1060
   * Our character device read / write functions.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1061
   *
3c98bf347   Borislav Petkov   ide-tape: cleanup...
1062
1063
1064
   * 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
1065
   *
3c98bf347   Borislav Petkov   ide-tape: cleanup...
1066
1067
1068
1069
1070
1071
1072
   * 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
1073
   */
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1074
1075
  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
1076
  {
5aeddf907   Borislav Petkov   ide: unify conver...
1077
  	struct ide_tape_obj *tape = file->private_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1078
  	ide_drive_t *drive = tape->drive;
07bd9686c   Tejun Heo   ide-tape: simplif...
1079
  	size_t done = 0;
dcd963796   Daniel Walker   [PATCH] idetape g...
1080
  	ssize_t ret = 0;
07bd9686c   Tejun Heo   ide-tape: simplif...
1081
  	int rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1082

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

54abf37e4   Borislav Petkov   ide-tape: remove ...
1085
  	if (tape->chrdev_dir != IDETAPE_DIR_READ) {
49d8078ad   Borislav Petkov   ide-tape: fix IDE...
1086
  		if (test_bit(ilog2(IDE_AFLAG_DETECT_BS), &drive->atapi_flags))
54bb2074c   Borislav Petkov   ide-tape: struct ...
1087
1088
1089
  			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
1090
  	}
07bd9686c   Tejun Heo   ide-tape: simplif...
1091

88f1b941c   Tejun Heo   ide-tape: unify r...
1092
  	rc = idetape_init_rw(drive, IDETAPE_DIR_READ);
8d06bfadb   Borislav Petkov   ide-tape: shorten...
1093
  	if (rc < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1094
  		return rc;
07bd9686c   Tejun Heo   ide-tape: simplif...
1095
1096
1097
1098
1099
1100
1101
  
  	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...
1102
1103
  			if (test_bit(ilog2(IDE_AFLAG_FILEMARK),
  				     &drive->atapi_flags))
07bd9686c   Tejun Heo   ide-tape: simplif...
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
  				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...
1114
  			ret = -EFAULT;
07bd9686c   Tejun Heo   ide-tape: simplif...
1115
1116
1117
1118
  
  		tape->cur += todo;
  		tape->valid -= todo;
  		done += todo;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1119
  	}
07bd9686c   Tejun Heo   ide-tape: simplif...
1120

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

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

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1207
  	switch (mt_op) {
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1208
1209
1210
1211
1212
1213
1214
1215
1216
  	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
1217
  	}
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1218

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

54abf37e4   Borislav Petkov   ide-tape: remove ...
1326
  	if (tape->chrdev_dir == IDETAPE_DIR_WRITE) {
d9df937af   Borislav Petkov   ide-tape: mv idet...
1327
  		ide_tape_flush_merge_buffer(drive);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1328
1329
1330
  		idetape_flush_tape_buffers(drive);
  	}
  	if (cmd == MTIOCGET || cmd == MTIOCPOS) {
963da55c4   Tejun Heo   ide-tape: kill id...
1331
  		block_offset = tape->valid /
54bb2074c   Borislav Petkov   ide-tape: struct ...
1332
  			(tape->blk_size * tape->user_bs_factor);
55ce3a129   Borislav Petkov   ide-tape: fix REA...
1333
  		position = ide_tape_read_position(drive);
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1334
  		if (position < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1335
1336
1337
  			return -EIO;
  	}
  	switch (cmd) {
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
  	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);
  
  		if (copy_to_user(argp, &mtget, sizeof(struct mtget)))
  			return -EFAULT;
  		return 0;
  	case MTIOCPOS:
  		mtpos.mt_blkno = position / tape->user_bs_factor - block_offset;
  		if (copy_to_user(argp, &mtpos, sizeof(struct mtpos)))
  			return -EFAULT;
  		return 0;
  	default:
  		if (tape->chrdev_dir == IDETAPE_DIR_READ)
ec0fdb01f   Borislav Petkov   ide-tape: mv idet...
1363
  			ide_tape_discard_merge_buffer(drive, 1);
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1364
  		return idetape_blkdev_ioctl(drive, cmd, arg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1365
1366
  	}
  }
05227adff   Alan Cox   ide_tape: kill of...
1367
1368
1369
1370
  static long idetape_chrdev_ioctl(struct file *file,
  				unsigned int cmd, unsigned long arg)
  {
  	long ret;
2a48fc0ab   Arnd Bergmann   block: autoconver...
1371
  	mutex_lock(&ide_tape_mutex);
05227adff   Alan Cox   ide_tape: kill of...
1372
  	ret = do_idetape_chrdev_ioctl(file, cmd, arg);
2a48fc0ab   Arnd Bergmann   block: autoconver...
1373
  	mutex_unlock(&ide_tape_mutex);
05227adff   Alan Cox   ide_tape: kill of...
1374
1375
  	return ret;
  }
3cffb9ce4   Borislav Petkov   ide-tape: remove ...
1376
1377
1378
1379
1380
1381
1382
  /*
   * 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...
1383
  	struct ide_atapi_pc pc;
837272b4f   Borislav Petkov   ide-tape/ide_tape...
1384
  	u8 buf[12];
3cffb9ce4   Borislav Petkov   ide-tape: remove ...
1385
1386
  
  	idetape_create_mode_sense_cmd(&pc, IDETAPE_BLOCK_DESCRIPTOR);
837272b4f   Borislav Petkov   ide-tape/ide_tape...
1387
  	if (ide_queue_pc_tail(drive, tape->disk, &pc, buf, pc.req_xfer)) {
3cffb9ce4   Borislav Petkov   ide-tape: remove ...
1388
1389
  		printk(KERN_ERR "ide-tape: Can't get block descriptor
  ");
54bb2074c   Borislav Petkov   ide-tape: struct ...
1390
  		if (tape->blk_size == 0) {
3cffb9ce4   Borislav Petkov   ide-tape: remove ...
1391
1392
1393
  			printk(KERN_WARNING "ide-tape: Cannot deal with zero "
  					    "block size, assuming 32k
  ");
54bb2074c   Borislav Petkov   ide-tape: struct ...
1394
  			tape->blk_size = 32768;
3cffb9ce4   Borislav Petkov   ide-tape: remove ...
1395
1396
1397
  		}
  		return;
  	}
837272b4f   Borislav Petkov   ide-tape/ide_tape...
1398
1399
1400
1401
  	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...
1402
1403
1404
  
  	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 ...
1405
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1406

5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1407
  static int idetape_chrdev_open(struct inode *inode, struct file *filp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1408
1409
1410
1411
  {
  	unsigned int minor = iminor(inode), i = minor & ~0xc0;
  	ide_drive_t *drive;
  	idetape_tape_t *tape;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1412
  	int retval;
8004a8c97   Borislav Petkov   ide-tape: refacto...
1413
1414
  	if (i >= MAX_HWIFS * MAX_DRIVES)
  		return -ENXIO;
cbba2fa7b   Borislav Petkov   ide-tape: remove ...
1415
  	mutex_lock(&idetape_chrdev_mutex);
9d01e4cd7   Borislav Petkov   ide-tape: fix pro...
1416
  	tape = ide_tape_get(NULL, true, i);
04f4ac9d1   Jonathan Corbet   ide-tape: cdev lo...
1417
  	if (!tape) {
cbba2fa7b   Borislav Petkov   ide-tape: remove ...
1418
  		mutex_unlock(&idetape_chrdev_mutex);
8004a8c97   Borislav Petkov   ide-tape: refacto...
1419
  		return -ENXIO;
04f4ac9d1   Jonathan Corbet   ide-tape: cdev lo...
1420
  	}
8004a8c97   Borislav Petkov   ide-tape: refacto...
1421

e972d7027   Borislav Petkov   ide-tape: convert...
1422
1423
1424
1425
  	drive = tape->drive;
  	filp->private_data = tape;
  
  	ide_debug_log(IDE_DBG_FUNC, "enter");
8004a8c97   Borislav Petkov   ide-tape: refacto...
1426

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1427
1428
1429
1430
1431
1432
  	/*
  	 * 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
1433

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

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

54abf37e4   Borislav Petkov   ide-tape: remove ...
1508
  	if (tape->chrdev_dir == IDETAPE_DIR_WRITE)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1509
  		idetape_write_release(drive, minor);
54abf37e4   Borislav Petkov   ide-tape: remove ...
1510
  	if (tape->chrdev_dir == IDETAPE_DIR_READ) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1511
  		if (minor < 128)
ec0fdb01f   Borislav Petkov   ide-tape: mv idet...
1512
  			ide_tape_discard_merge_buffer(drive, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1513
  	}
f64eee7bb   Borislav Petkov   ide-tape: remove ...
1514

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

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1538
  	idetape_create_inquiry_cmd(&pc);
b13345f39   Borislav Petkov   ide-atapi: add a ...
1539
  	if (ide_queue_pc_tail(drive, tape->disk, &pc, pc_buf, pc.req_xfer)) {
6d29c8f0a   Borislav Petkov   ide-tape: remove ...
1540
1541
1542
  		printk(KERN_ERR "ide-tape: %s: can't get INQUIRY results
  ",
  				tape->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1543
1544
  		return;
  	}
b13345f39   Borislav Petkov   ide-atapi: add a ...
1545
1546
1547
  	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 ...
1548

801bd32e2   Borislav Petkov   ide-tape: fix ven...
1549
1550
1551
  	ide_fixstring(vendor_id, 8, 0);
  	ide_fixstring(product_id, 16, 0);
  	ide_fixstring(fw_rev, 4, 0);
41f81d545   Borislav Petkov   ide-tape: struct ...
1552

801bd32e2   Borislav Petkov   ide-tape: fix ven...
1553
1554
  	printk(KERN_INFO "ide-tape: %s <-> %s: %.8s %.16s rev %.4s
  ",
41f81d545   Borislav Petkov   ide-tape: struct ...
1555
  			drive->name, tape->name, vendor_id, product_id, fw_rev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1556
1557
1558
  }
  
  /*
b64220132   Borislav Petkov   ide-tape: remove ...
1559
1560
   * 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
1561
   */
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1562
  static void idetape_get_mode_sense_results(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1563
1564
  {
  	idetape_tape_t *tape = drive->driver_data;
d236d74c0   Borislav Petkov   ide-tape: convert...
1565
  	struct ide_atapi_pc pc;
b13345f39   Borislav Petkov   ide-atapi: add a ...
1566
  	u8 buf[24], *caps;
b64220132   Borislav Petkov   ide-tape: remove ...
1567
  	u8 speed, max_speed;
47314fa42   Borislav Petkov   ide-tape: remove ...
1568

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1569
  	idetape_create_mode_sense_cmd(&pc, IDETAPE_CAPABILITIES_PAGE);
b13345f39   Borislav Petkov   ide-atapi: add a ...
1570
  	if (ide_queue_pc_tail(drive, tape->disk, &pc, buf, pc.req_xfer)) {
b64220132   Borislav Petkov   ide-tape: remove ...
1571
1572
1573
  		printk(KERN_ERR "ide-tape: Can't get tape parameters - assuming"
  				" some default values
  ");
54bb2074c   Borislav Petkov   ide-tape: struct ...
1574
  		tape->blk_size = 512;
b64220132   Borislav Petkov   ide-tape: remove ...
1575
1576
1577
  		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
1578
1579
  		return;
  	}
b13345f39   Borislav Petkov   ide-atapi: add a ...
1580
  	caps = buf + 4 + buf[3];
b64220132   Borislav Petkov   ide-tape: remove ...
1581
1582
  
  	/* convert to host order and save for later use */
cd740ab0f   Harvey Harrison   ide: ide-tape.c s...
1583
1584
  	speed = be16_to_cpup((__be16 *)&caps[14]);
  	max_speed = be16_to_cpup((__be16 *)&caps[8]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1585

cd740ab0f   Harvey Harrison   ide: ide-tape.c s...
1586
1587
1588
1589
  	*(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
1590

b64220132   Borislav Petkov   ide-tape: remove ...
1591
1592
1593
1594
  	if (!speed) {
  		printk(KERN_INFO "ide-tape: %s: invalid tape speed "
  				"(assuming 650KB/sec)
  ", drive->name);
cd740ab0f   Harvey Harrison   ide: ide-tape.c s...
1595
  		*(u16 *)&caps[14] = 650;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1596
  	}
b64220132   Borislav Petkov   ide-tape: remove ...
1597
1598
1599
1600
  	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...
1601
  		*(u16 *)&caps[8] = 650;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1602
  	}
b64220132   Borislav Petkov   ide-tape: remove ...
1603
  	memcpy(&tape->caps, caps, 20);
0578042db   Bartlomiej Zolnierkiewicz   ide: add ide_set_...
1604
1605
1606
  
  	/* device lacks locking support according to capabilities page */
  	if ((caps[6] & 1) == 0)
42619d35c   Bartlomiej Zolnierkiewicz   ide: remove IDE_A...
1607
  		drive->dev_flags &= ~IDE_DFLAG_DOORLOCKING;
0578042db   Bartlomiej Zolnierkiewicz   ide: add ide_set_...
1608

b64220132   Borislav Petkov   ide-tape: remove ...
1609
  	if (caps[7] & 0x02)
54bb2074c   Borislav Petkov   ide-tape: struct ...
1610
  		tape->blk_size = 512;
b64220132   Borislav Petkov   ide-tape: remove ...
1611
  	else if (caps[7] & 0x04)
54bb2074c   Borislav Petkov   ide-tape: struct ...
1612
  		tape->blk_size = 1024;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1613
  }
7662d046d   Bartlomiej Zolnierkiewicz   ide: move IDE set...
1614
  #ifdef CONFIG_IDE_PROC_FS
8185d5aa9   Bartlomiej Zolnierkiewicz   ide: /proc/ide/hd...
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
  #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...
1629
  #define ide_tape_devset_rw_field(_name, _field) \
8185d5aa9   Bartlomiej Zolnierkiewicz   ide: /proc/ide/hd...
1630
1631
  ide_tape_devset_get(_name, _field) \
  ide_tape_devset_set(_name, _field) \
92f1f8fd8   Elias Oltmanns   ide: Remove ide_s...
1632
  IDE_DEVSET(_name, DS_SYNC, get_##_name, set_##_name)
8185d5aa9   Bartlomiej Zolnierkiewicz   ide: /proc/ide/hd...
1633

92f1f8fd8   Elias Oltmanns   ide: Remove ide_s...
1634
  #define ide_tape_devset_r_field(_name, _field) \
8185d5aa9   Bartlomiej Zolnierkiewicz   ide: /proc/ide/hd...
1635
  ide_tape_devset_get(_name, _field) \
92f1f8fd8   Elias Oltmanns   ide: Remove ide_s...
1636
  IDE_DEVSET(_name, 0, get_##_name, NULL)
8185d5aa9   Bartlomiej Zolnierkiewicz   ide: /proc/ide/hd...
1637
1638
1639
1640
1641
  
  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...
1642
  ide_devset_rw_flag(dsc_overlap, IDE_DFLAG_DSC_OVERLAP);
92f1f8fd8   Elias Oltmanns   ide: Remove ide_s...
1643

92f1f8fd8   Elias Oltmanns   ide: Remove ide_s...
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
  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...
1655
1656
1657
1658
  	__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: ...
1659
  	{ NULL },
8185d5aa9   Bartlomiej Zolnierkiewicz   ide: /proc/ide/hd...
1660
  };
7662d046d   Bartlomiej Zolnierkiewicz   ide: move IDE set...
1661
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1662
1663
  
  /*
3c98bf347   Borislav Petkov   ide-tape: cleanup...
1664
   * The function below is called to:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1665
   *
3c98bf347   Borislav Petkov   ide-tape: cleanup...
1666
1667
1668
1669
   * 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
1670
   *
3c98bf347   Borislav Petkov   ide-tape: cleanup...
1671
1672
   * 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
1673
   */
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1674
  static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1675
  {
83042b241   Borislav Petkov   ide-tape: remove ...
1676
  	unsigned long t;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1677
  	int speed;
b64220132   Borislav Petkov   ide-tape: remove ...
1678
  	u16 *ctl = (u16 *)&tape->caps[12];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1679

e972d7027   Borislav Petkov   ide-tape: convert...
1680
1681
1682
  	ide_debug_log(IDE_DBG_FUNC, "minor: %d", minor);
  
  	drive->pc_callback = ide_tape_callback;
776bb0270   Borislav Petkov   ide-tape: use dri...
1683

97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
1684
  	drive->dev_flags |= IDE_DFLAG_DSC_OVERLAP;
4166c1993   Bartlomiej Zolnierkiewicz   ide: add IDE_HFLA...
1685
1686
1687
1688
  	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...
1689
  		drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1690
  	}
97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
1691

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1692
  	/* Seagate Travan drives do not support DSC overlap. */
4dde4492d   Bartlomiej Zolnierkiewicz   ide: make drive->...
1693
  	if (strstr((char *)&drive->id[ATA_ID_PROD], "Seagate STT3401"))
97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
1694
  		drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1695
1696
1697
1698
  	tape->minor = minor;
  	tape->name[0] = 'h';
  	tape->name[1] = 't';
  	tape->name[2] = '0' + minor;
54abf37e4   Borislav Petkov   ide-tape: remove ...
1699
  	tape->chrdev_dir = IDETAPE_DIR_NONE;
4dde4492d   Bartlomiej Zolnierkiewicz   ide: make drive->...
1700

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1701
1702
  	idetape_get_inquiry_results(drive);
  	idetape_get_mode_sense_results(drive);
3cffb9ce4   Borislav Petkov   ide-tape: remove ...
1703
  	ide_tape_get_bsize_from_bdesc(drive);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1704
  	tape->user_bs_factor = 1;
f73850a30   Borislav Petkov   ide-tape: mv tape...
1705
1706
  	tape->buffer_size = *ctl * tape->blk_size;
  	while (tape->buffer_size > 0xffff) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1707
1708
  		printk(KERN_NOTICE "ide-tape: decreasing stage size
  ");
b64220132   Borislav Petkov   ide-tape: remove ...
1709
  		*ctl /= 2;
f73850a30   Borislav Petkov   ide-tape: mv tape...
1710
  		tape->buffer_size = *ctl * tape->blk_size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1711
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1712

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

f73850a30   Borislav Petkov   ide-tape: mv tape...
1716
  	t = (IDETAPE_FIFO_THRESHOLD * tape->buffer_size * HZ) / (speed * 1000);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1717
1718
  
  	/*
3c98bf347   Borislav Petkov   ide-tape: cleanup...
1719
1720
  	 * 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
1721
  	 */
a792bd5a4   Harvey Harrison   ide-tape: use cla...
1722
1723
  	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
1724
  	printk(KERN_INFO "ide-tape: %s <-> %s: %dKBps, %d*%dkB buffer, "
842159640   Nicholas Mc Guire   ide_tape: convert...
1725
1726
  		"%ums tDSC%s
  ",
b64220132   Borislav Petkov   ide-tape: remove ...
1727
  		drive->name, tape->name, *(u16 *)&tape->caps[14],
f73850a30   Borislav Petkov   ide-tape: mv tape...
1728
1729
  		(*(u16 *)&tape->caps[16] * 512) / tape->buffer_size,
  		tape->buffer_size / 1024,
842159640   Nicholas Mc Guire   ide_tape: convert...
1730
  		jiffies_to_msecs(tape->best_dsc_rw_freq),
97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
1731
  		(drive->dev_flags & IDE_DFLAG_USING_DMA) ? ", DMA" : "");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1732

1e874f448   Bartlomiej Zolnierkiewicz   ide: call ide_pro...
1733
  	ide_proc_register_driver(drive, tape->driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1734
  }
4031bbe4b   Russell King   [PATCH] Add ide_b...
1735
  static void ide_tape_remove(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1736
1737
  {
  	idetape_tape_t *tape = drive->driver_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1738

7662d046d   Bartlomiej Zolnierkiewicz   ide: move IDE set...
1739
  	ide_proc_unregister_driver(drive, tape->driver);
8fed43684   Bartlomiej Zolnierkiewicz   ide: fix refcount...
1740
  	device_del(&tape->dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1741
  	ide_unregister_region(tape->disk);
8fed43684   Bartlomiej Zolnierkiewicz   ide: fix refcount...
1742
1743
1744
  	mutex_lock(&idetape_ref_mutex);
  	put_device(&tape->dev);
  	mutex_unlock(&idetape_ref_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1745
  }
8fed43684   Bartlomiej Zolnierkiewicz   ide: fix refcount...
1746
  static void ide_tape_release(struct device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1747
  {
8fed43684   Bartlomiej Zolnierkiewicz   ide: fix refcount...
1748
  	struct ide_tape_obj *tape = to_ide_drv(dev, ide_tape_obj);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1749
1750
  	ide_drive_t *drive = tape->drive;
  	struct gendisk *g = tape->disk;
963da55c4   Tejun Heo   ide-tape: kill id...
1751
  	BUG_ON(tape->valid);
8604affde   Bartlomiej Zolnierkiewicz   [PATCH] convert I...
1752

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

6d703a81a   Alexey Dobriyan   ide: convert to -...
1769
1770
1771
1772
  	seq_printf(m, "%s
  ", tape->name);
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1773
  static ide_proc_entry_t idetape_proc[] = {
ec7d9c9ce   Christoph Hellwig   ide: replace ->pr...
1774
1775
  	{ "capacity",	S_IFREG|S_IRUGO,	ide_capacity_proc_show	},
  	{ "name",	S_IFREG|S_IRUGO,	idetape_name_proc_show	},
6d703a81a   Alexey Dobriyan   ide: convert to -...
1776
  	{}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1777
  };
79cb38039   Bartlomiej Zolnierkiewicz   ide: allow device...
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
  
  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
1788
  #endif
4031bbe4b   Russell King   [PATCH] Add ide_b...
1789
  static int ide_tape_probe(ide_drive_t *);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1790

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

5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1823
  	if (!tape)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1824
  		return -ENXIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1825
1826
  	return 0;
  }
db2a144be   Al Viro   block_device_oper...
1827
  static void idetape_release(struct gendisk *disk, fmode_t mode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1828
  {
5aeddf907   Borislav Petkov   ide: unify conver...
1829
  	struct ide_tape_obj *tape = ide_drv_g(disk, ide_tape_obj);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1830

2a48fc0ab   Arnd Bergmann   block: autoconver...
1831
  	mutex_lock(&ide_tape_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1832
  	ide_tape_put(tape);
2a48fc0ab   Arnd Bergmann   block: autoconver...
1833
  	mutex_unlock(&ide_tape_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1834
  }
a4600f813   Al Viro   [PATCH] switch id...
1835
  static int idetape_ioctl(struct block_device *bdev, fmode_t mode,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1836
1837
  			unsigned int cmd, unsigned long arg)
  {
5aeddf907   Borislav Petkov   ide: unify conver...
1838
  	struct ide_tape_obj *tape = ide_drv_g(bdev->bd_disk, ide_tape_obj);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1839
  	ide_drive_t *drive = tape->drive;
8a6cfeb6d   Arnd Bergmann   block: push down ...
1840
  	int err;
2a48fc0ab   Arnd Bergmann   block: autoconver...
1841
  	mutex_lock(&ide_tape_mutex);
8a6cfeb6d   Arnd Bergmann   block: push down ...
1842
  	err = generic_ide_ioctl(drive, bdev, cmd, arg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1843
1844
  	if (err == -EINVAL)
  		err = idetape_blkdev_ioctl(drive, cmd, arg);
2a48fc0ab   Arnd Bergmann   block: autoconver...
1845
  	mutex_unlock(&ide_tape_mutex);
8a6cfeb6d   Arnd Bergmann   block: push down ...
1846

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1847
1848
  	return err;
  }
83d5cde47   Alexey Dobriyan   const: make block...
1849
  static const struct block_device_operations idetape_block_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1850
  	.owner		= THIS_MODULE,
a4600f813   Al Viro   [PATCH] switch id...
1851
1852
  	.open		= idetape_open,
  	.release	= idetape_release,
8a6cfeb6d   Arnd Bergmann   block: push down ...
1853
  	.ioctl		= idetape_ioctl,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1854
  };
4031bbe4b   Russell King   [PATCH] Add ide_b...
1855
  static int ide_tape_probe(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1856
1857
1858
1859
  {
  	idetape_tape_t *tape;
  	struct gendisk *g;
  	int minor;
e972d7027   Borislav Petkov   ide-tape: convert...
1860
1861
1862
  	ide_debug_log(IDE_DBG_FUNC, "enter");
  
  	if (!strstr(DRV_NAME, drive->driver_req))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1863
  		goto failed;
2a924662b   Bartlomiej Zolnierkiewicz   ide: remove needl...
1864

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

97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
1868
1869
  	if ((drive->dev_flags & IDE_DFLAG_ID_READ) &&
  	    ide_check_atapi_device(drive, DRV_NAME) == 0) {
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1870
1871
1872
  		printk(KERN_ERR "ide-tape: %s: not supported by this version of"
  				" the driver
  ", drive->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1873
1874
  		goto failed;
  	}
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1875
  	tape = kzalloc(sizeof(idetape_tape_t), GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1876
  	if (tape == NULL) {
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1877
1878
1879
  		printk(KERN_ERR "ide-tape: %s: Can't allocate a tape struct
  ",
  				drive->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1880
1881
1882
1883
1884
1885
1886
1887
  		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...
1888
1889
  	tape->dev.parent = &drive->gendev;
  	tape->dev.release = ide_tape_release;
02aa2a376   Kees Cook   drivers: avoid fo...
1890
  	dev_set_name(&tape->dev, "%s", dev_name(&drive->gendev));
8fed43684   Bartlomiej Zolnierkiewicz   ide: fix refcount...
1891
1892
1893
  
  	if (device_register(&tape->dev))
  		goto out_free_disk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1894
1895
1896
1897
1898
1899
1900
1901
  
  	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...
1902
  	mutex_lock(&idetape_ref_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1903
1904
1905
  	for (minor = 0; idetape_devs[minor]; minor++)
  		;
  	idetape_devs[minor] = tape;
cf8b8975c   Arjan van de Ven   [PATCH] sem2mutex...
1906
  	mutex_unlock(&idetape_ref_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1907
1908
  
  	idetape_setup(drive, tape, minor);
3ee074bf4   Greg Kroah-Hartman   device create: id...
1909
1910
1911
1912
1913
  	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...
1914

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1915
1916
1917
1918
  	g->fops = &idetape_block_ops;
  	ide_register_region(g);
  
  	return 0;
8604affde   Bartlomiej Zolnierkiewicz   [PATCH] convert I...
1919

8fed43684   Bartlomiej Zolnierkiewicz   ide: fix refcount...
1920
1921
  out_free_disk:
  	put_disk(g);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1922
1923
1924
  out_free_tape:
  	kfree(tape);
  failed:
8604affde   Bartlomiej Zolnierkiewicz   [PATCH] convert I...
1925
  	return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1926
  }
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1927
  static void __exit idetape_exit(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1928
  {
8604affde   Bartlomiej Zolnierkiewicz   [PATCH] convert I...
1929
  	driver_unregister(&idetape_driver.gen_driver);
d5dee80ad   Will Dyson   [PATCH] add sysfs...
1930
  	class_destroy(idetape_sysfs_class);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1931
1932
  	unregister_chrdev(IDETAPE_MAJOR, "ht");
  }
17514e8a6   Bartlomiej Zolnierkiewicz   [PATCH] ide: add ...
1933
  static int __init idetape_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1934
  {
d5dee80ad   Will Dyson   [PATCH] add sysfs...
1935
1936
1937
1938
1939
1940
1941
1942
1943
  	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
1944
  	if (register_chrdev(IDETAPE_MAJOR, "ht", &idetape_fops)) {
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1945
1946
1947
  		printk(KERN_ERR "ide-tape: Failed to register chrdev"
  				" interface
  ");
d5dee80ad   Will Dyson   [PATCH] add sysfs...
1948
1949
  		error = -EBUSY;
  		goto out_free_class;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1950
  	}
d5dee80ad   Will Dyson   [PATCH] add sysfs...
1951
1952
1953
  
  	error = driver_register(&idetape_driver.gen_driver);
  	if (error)
79f18a063   Alexey Khoroshilov   ide-tape: fix mis...
1954
  		goto out_free_chrdev;
d5dee80ad   Will Dyson   [PATCH] add sysfs...
1955
1956
  
  	return 0;
79f18a063   Alexey Khoroshilov   ide-tape: fix mis...
1957
1958
  out_free_chrdev:
  	unregister_chrdev(IDETAPE_MAJOR, "ht");
d5dee80ad   Will Dyson   [PATCH] add sysfs...
1959
1960
1961
1962
  out_free_class:
  	class_destroy(idetape_sysfs_class);
  out:
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1963
  }
263756ec2   Kay Sievers   [PATCH] ide: MODA...
1964
  MODULE_ALIAS("ide:*m-tape*");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1965
1966
1967
  module_init(idetape_init);
  module_exit(idetape_exit);
  MODULE_ALIAS_CHARDEV_MAJOR(IDETAPE_MAJOR);
9c1457688   Borislav Petkov   ide-tape: collect...
1968
1969
  MODULE_DESCRIPTION("ATAPI Streaming TAPE Driver");
  MODULE_LICENSE("GPL");