Blame view

drivers/ide/ide-tape.c 55.1 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)
077e6dba2   Borislav Petkov   ide-atapi: switch...
266
  		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) &&
077e6dba2   Borislav Petkov   ide-atapi: switch...
300
  		    (blk_rq_bytes(rq) - 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
330
  		unsigned int blocks =
  			(blk_rq_bytes(rq) - 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
  	}
313afea7f   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
348
  	rq->errors = err;
03a2faaea   Bartlomiej Zolnierkiewicz   ide: return reque...
349
  	return uptodate;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
350
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
351
  /*
3c98bf347   Borislav Petkov   ide-tape: cleanup...
352
   * Postpone the current request so that ide.c will be able to service requests
b65fac32c   Bartlomiej Zolnierkiewicz   ide: merge ide_hw...
353
   * from another device on the same port while we are polling for DSC.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
354
   */
6f3848ac2   Borislav Petkov   ide-tape: fix han...
355
  static void ide_tape_stall_queue(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
356
357
  {
  	idetape_tape_t *tape = drive->driver_data;
e972d7027   Borislav Petkov   ide-tape: convert...
358
  	ide_debug_log(IDE_DBG_FUNC, "cmd: 0x%x, dsc_poll_freq: %lu",
6f3848ac2   Borislav Petkov   ide-tape: fix han...
359
  		      drive->hwif->rq->cmd[0], tape->dsc_poll_freq);
8004a8c97   Borislav Petkov   ide-tape: refacto...
360

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

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

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

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

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

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

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

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

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

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

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

963da55c4   Tejun Heo   ide-tape: kill id...
528
  	if (opcode == READ_6)
cd2abbfec   Borislav Petkov   ide-tape: unify i...
529
  		pc->c[0] = READ_6;
963da55c4   Tejun Heo   ide-tape: kill id...
530
  	else if (opcode == WRITE_6) {
cd2abbfec   Borislav Petkov   ide-tape: unify i...
531
532
  		pc->c[0] = WRITE_6;
  		pc->flags |= PC_FLAG_WRITING;
cd2abbfec   Borislav Petkov   ide-tape: unify i...
533
  	}
0014c75be   Borislav Petkov   ide-tape: pass pa...
534
535
  
  	memcpy(rq->cmd, pc->c, 12);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
536
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
537
538
539
  static ide_startstop_t idetape_do_request(ide_drive_t *drive,
  					  struct request *rq, sector_t block)
  {
b73c7ee25   Bartlomiej Zolnierkiewicz   ide: add ->read_s...
540
  	ide_hwif_t *hwif = drive->hwif;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
541
  	idetape_tape_t *tape = drive->driver_data;
d236d74c0   Borislav Petkov   ide-tape: convert...
542
  	struct ide_atapi_pc *pc = NULL;
b788ee9c6   Bartlomiej Zolnierkiewicz   ide: use do_rw_ta...
543
  	struct ide_cmd cmd;
22c525b97   Bartlomiej Zolnierkiewicz   ide: remove ata_s...
544
  	u8 stat;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
545

e972d7027   Borislav Petkov   ide-tape: convert...
546
547
548
  	ide_debug_log(IDE_DBG_RQ, "cmd: 0x%x, sector: %llu, nr_sectors: %u",
  		      rq->cmd[0], (unsigned long long)blk_rq_pos(rq),
  		      blk_rq_sectors(rq));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
549

33659ebba   Christoph Hellwig   block: remove wra...
550
551
  	BUG_ON(!(rq->cmd_type == REQ_TYPE_SPECIAL ||
  		 rq->cmd_type == REQ_TYPE_SENSE));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
552

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

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

97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
565
566
  	if ((drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) == 0 &&
  	    (rq->cmd[13] & REQ_IDETAPE_PC2) == 0)
626542ca2   Borislav Petkov   ide-tape: change ...
567
  		drive->atapi_flags |= IDE_AFLAG_IGNORE_DSC;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
568

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

83dd57351   Borislav Petkov   ide-tape: make ro...
600
  	if (rq->cmd[13] & REQ_IDETAPE_READ) {
2e8a6f89d   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
601
  		pc = &tape->queued_pc;
0014c75be   Borislav Petkov   ide-tape: pass pa...
602
  		ide_tape_create_rw_cmd(tape, pc, rq, READ_6);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
603
604
  		goto out;
  	}
83dd57351   Borislav Petkov   ide-tape: make ro...
605
  	if (rq->cmd[13] & REQ_IDETAPE_WRITE) {
2e8a6f89d   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
606
  		pc = &tape->queued_pc;
0014c75be   Borislav Petkov   ide-tape: pass pa...
607
  		ide_tape_create_rw_cmd(tape, pc, rq, WRITE_6);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
608
609
  		goto out;
  	}
83dd57351   Borislav Petkov   ide-tape: make ro...
610
  	if (rq->cmd[13] & REQ_IDETAPE_PC1) {
c267cc1c4   Tejun Heo   ide-atapi: don't ...
611
  		pc = (struct ide_atapi_pc *)rq->special;
83dd57351   Borislav Petkov   ide-tape: make ro...
612
613
  		rq->cmd[13] &= ~(REQ_IDETAPE_PC1);
  		rq->cmd[13] |= REQ_IDETAPE_PC2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
614
615
  		goto out;
  	}
83dd57351   Borislav Petkov   ide-tape: make ro...
616
  	if (rq->cmd[13] & REQ_IDETAPE_PC2) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
617
618
619
620
  		idetape_media_access_finished(drive);
  		return ide_stopped;
  	}
  	BUG();
28c7214bd   Bartlomiej Zolnierkiewicz   ide: add PC_FLAG_...
621

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

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

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

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

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

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

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

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

64ea1b4ab   FUJITA Tomonori   ide-tape: convert...
814
815
  	rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
  	rq->cmd_type = REQ_TYPE_SPECIAL;
83dd57351   Borislav Petkov   ide-tape: make ro...
816
  	rq->cmd[13] = cmd;
64ea1b4ab   FUJITA Tomonori   ide-tape: convert...
817
  	rq->rq_disk = tape->disk;
c9059598e   Linus Torvalds   Merge branch 'for...
818
  	rq->__sector = tape->first_frame;
21d9c5d22   Tejun Heo   ide-tape: use sta...
819
820
  
  	if (size) {
963da55c4   Tejun Heo   ide-tape: kill id...
821
  		ret = blk_rq_map_kern(drive->queue, rq, tape->buf, size,
21d9c5d22   Tejun Heo   ide-tape: use sta...
822
823
824
825
  				      __GFP_WAIT);
  		if (ret)
  			goto out_put;
  	}
64ea1b4ab   FUJITA Tomonori   ide-tape: convert...
826
  	blk_execute_rq(drive->queue, tape->disk, rq, 0);
963da55c4   Tejun Heo   ide-tape: kill id...
827
  	/* calculate the number of transferred bytes and update buffer state */
c3a4d78c5   Tejun Heo   block: add rq->re...
828
  	size -= rq->resid_len;
963da55c4   Tejun Heo   ide-tape: kill id...
829
  	tape->cur = tape->buf;
21d9c5d22   Tejun Heo   ide-tape: use sta...
830
  	if (cmd == REQ_IDETAPE_READ)
963da55c4   Tejun Heo   ide-tape: kill id...
831
832
833
  		tape->valid = size;
  	else
  		tape->valid = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
834

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

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

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

88f1b941c   Tejun Heo   ide-tape: unify r...
898
899
900
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
  	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
936
937
  		}
  	}
5e69bd959   Borislav Petkov   ide-tape: remove ...
938

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

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

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

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

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

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

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

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

e972d7027   Borislav Petkov   ide-tape: convert...
1080
  	ide_debug_log(IDE_DBG_FUNC, "count %Zd", count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1081

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

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

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

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

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

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

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

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

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

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1424
1425
1426
1427
1428
1429
  	/*
  	 * 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
1430

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

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

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

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

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

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

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

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

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

cd740ab0f   Harvey Harrison   ide: ide-tape.c s...
1583
1584
1585
1586
  	*(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
1587

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

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

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

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

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

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

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

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

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

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

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

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

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

6d703a81a   Alexey Dobriyan   ide: convert to -...
1768
1769
1770
1771
1772
1773
1774
1775
  	seq_printf(m, "%s
  ", tape->name);
  	return 0;
  }
  
  static int idetape_name_proc_open(struct inode *inode, struct file *file)
  {
  	return single_open(file, idetape_name_proc_show, PDE(inode)->data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1776
  }
6d703a81a   Alexey Dobriyan   ide: convert to -...
1777
1778
1779
1780
1781
1782
1783
  static const struct file_operations idetape_name_proc_fops = {
  	.owner		= THIS_MODULE,
  	.open		= idetape_name_proc_open,
  	.read		= seq_read,
  	.llseek		= seq_lseek,
  	.release	= single_release,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1784
  static ide_proc_entry_t idetape_proc[] = {
6d703a81a   Alexey Dobriyan   ide: convert to -...
1785
1786
1787
  	{ "capacity",	S_IFREG|S_IRUGO,	&ide_capacity_proc_fops	},
  	{ "name",	S_IFREG|S_IRUGO,	&idetape_name_proc_fops	},
  	{}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1788
  };
79cb38039   Bartlomiej Zolnierkiewicz   ide: allow device...
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
  
  static ide_proc_entry_t *ide_tape_proc_entries(ide_drive_t *drive)
  {
  	return idetape_proc;
  }
  
  static const struct ide_proc_devset *ide_tape_proc_devsets(ide_drive_t *drive)
  {
  	return idetape_settings;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1799
  #endif
4031bbe4b   Russell King   [PATCH] Add ide_b...
1800
  static int ide_tape_probe(ide_drive_t *);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1801

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

5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1834
  	if (!tape)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1835
  		return -ENXIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1836
1837
  	return 0;
  }
a4600f813   Al Viro   [PATCH] switch id...
1838
  static int idetape_release(struct gendisk *disk, fmode_t mode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1839
  {
5aeddf907   Borislav Petkov   ide: unify conver...
1840
  	struct ide_tape_obj *tape = ide_drv_g(disk, ide_tape_obj);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1841

2a48fc0ab   Arnd Bergmann   block: autoconver...
1842
  	mutex_lock(&ide_tape_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1843
  	ide_tape_put(tape);
2a48fc0ab   Arnd Bergmann   block: autoconver...
1844
  	mutex_unlock(&ide_tape_mutex);
6e9624b8c   Arnd Bergmann   block: push down ...
1845

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1860
1861
  	return err;
  }
83d5cde47   Alexey Dobriyan   const: make block...
1862
  static const struct block_device_operations idetape_block_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1863
  	.owner		= THIS_MODULE,
a4600f813   Al Viro   [PATCH] switch id...
1864
1865
  	.open		= idetape_open,
  	.release	= idetape_release,
8a6cfeb6d   Arnd Bergmann   block: push down ...
1866
  	.ioctl		= idetape_ioctl,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1867
  };
4031bbe4b   Russell King   [PATCH] Add ide_b...
1868
  static int ide_tape_probe(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1869
1870
1871
1872
  {
  	idetape_tape_t *tape;
  	struct gendisk *g;
  	int minor;
e972d7027   Borislav Petkov   ide-tape: convert...
1873
1874
1875
  	ide_debug_log(IDE_DBG_FUNC, "enter");
  
  	if (!strstr(DRV_NAME, drive->driver_req))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1876
  		goto failed;
2a924662b   Bartlomiej Zolnierkiewicz   ide: remove needl...
1877

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

97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
1881
1882
  	if ((drive->dev_flags & IDE_DFLAG_ID_READ) &&
  	    ide_check_atapi_device(drive, DRV_NAME) == 0) {
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1883
1884
1885
  		printk(KERN_ERR "ide-tape: %s: not supported by this version of"
  				" the driver
  ", drive->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1886
1887
  		goto failed;
  	}
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1888
  	tape = kzalloc(sizeof(idetape_tape_t), GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1889
  	if (tape == NULL) {
5a04cfa91   Borislav Petkov   ide-tape: cleanup...
1890
1891
1892
  		printk(KERN_ERR "ide-tape: %s: Can't allocate a tape struct
  ",
  				drive->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1893
1894
1895
1896
1897
1898
1899
1900
  		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...
1901
1902
1903
1904
1905
1906
  	tape->dev.parent = &drive->gendev;
  	tape->dev.release = ide_tape_release;
  	dev_set_name(&tape->dev, dev_name(&drive->gendev));
  
  	if (device_register(&tape->dev))
  		goto out_free_disk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1907
1908
1909
1910
1911
1912
1913
1914
  
  	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...
1915
  	mutex_lock(&idetape_ref_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1916
1917
1918
  	for (minor = 0; idetape_devs[minor]; minor++)
  		;
  	idetape_devs[minor] = tape;
cf8b8975c   Arjan van de Ven   [PATCH] sem2mutex...
1919
  	mutex_unlock(&idetape_ref_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1920
1921
  
  	idetape_setup(drive, tape, minor);
3ee074bf4   Greg Kroah-Hartman   device create: id...
1922
1923
1924
1925
1926
  	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...
1927

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1928
1929
1930
1931
  	g->fops = &idetape_block_ops;
  	ide_register_region(g);
  
  	return 0;
8604affde   Bartlomiej Zolnierkiewicz   [PATCH] convert I...
1932

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