Blame view

drivers/ide/ide-floppy.c 26.6 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
d3f208488   Borislav Petkov   ide-floppy: clean...
2
3
   * IDE ATAPI floppy driver.
   *
59bca8cc9   Bartlomiej Zolnierkiewicz   ide: update/add m...
4
5
6
   * Copyright (C) 1996-1999  Gadi Oxman <gadio@netvision.net.il>
   * Copyright (C) 2000-2002  Paul Bristow <paul@paulbristow.net>
   * Copyright (C) 2005       Bartlomiej Zolnierkiewicz
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
7
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
8
9
10
11
12
13
   * This driver supports the following IDE floppy drives:
   *
   * LS-120/240 SuperDisk
   * Iomega Zip 100/250
   * Iomega PC Card Clik!/PocketZip
   *
d3f208488   Borislav Petkov   ide-floppy: clean...
14
15
   * For a historical changelog see
   * Documentation/ide/ChangeLog.ide-floppy.1996-2002
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
16
   */
51509eec3   Bartlomiej Zolnierkiewicz   ide: add ide_chec...
17
  #define DRV_NAME "ide-floppy"
fc6c5bc7c   Borislav Petkov   ide-floppy: bump ...
18
  #define IDEFLOPPY_VERSION "1.00"
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
28
29
30
31
32
33
  #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>
  #include <linux/major.h>
  #include <linux/errno.h>
  #include <linux/genhd.h>
  #include <linux/slab.h>
  #include <linux/cdrom.h>
  #include <linux/ide.h>
3ceca727f   Bartlomiej Zolnierkiewicz   ide: include <lin...
34
  #include <linux/hdreg.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35
  #include <linux/bitops.h>
cf8b8975c   Arjan van de Ven   [PATCH] sem2mutex...
36
  #include <linux/mutex.h>
b98b3409a   Borislav Petkov   ide-floppy: use s...
37
  #include <linux/scatterlist.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38

89636af25   Bartlomiej Zolnierkiewicz   ide: add support ...
39
  #include <scsi/scsi_ioctl.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
  #include <asm/byteorder.h>
7e8b163b2   Borislav Petkov   ide-floppy: inclu...
41
42
43
  #include <linux/irq.h>
  #include <linux/uaccess.h>
  #include <linux/io.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
44
  #include <asm/unaligned.h>
0127854d7   Bartlomiej Zolnierkiewicz   ide-floppy: move ...
45
  #include "ide-floppy.h"
f373bd820   Borislav Petkov   ide-floppy: remov...
46
  /* define to see debug info */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
47
  #define IDEFLOPPY_DEBUG_LOG		0
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48
49
  
  /* #define IDEFLOPPY_DEBUG(fmt, args...) printk(KERN_INFO fmt, ## args) */
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
50
  #define IDEFLOPPY_DEBUG(fmt, args...)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
52
  
  #if IDEFLOPPY_DEBUG_LOG
bcc77d9cc   Borislav Petkov   ide-floppy: clean...
53
54
  #define debug_log(fmt, args...) \
  	printk(KERN_INFO "ide-floppy: " fmt, ## args)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
55
  #else
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
56
  #define debug_log(fmt, args...) do {} while (0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
57
  #endif
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
58
  /* Some drives require a longer irq timeout. */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
59
60
61
  #define IDEFLOPPY_WAIT_CMD		(5 * WAIT_CMD)
  
  /*
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
62
63
   * After each failed packet command we issue a request sense command and retry
   * the packet command IDEFLOPPY_MAX_PC_RETRIES times.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64
65
   */
  #define IDEFLOPPY_MAX_PC_RETRIES	3
194ec0c07   Borislav Petkov   ide-floppy: remov...
66
  /* format capacities descriptor codes */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
67
68
69
70
  #define CAPACITY_INVALID	0x00
  #define CAPACITY_UNFORMATTED	0x01
  #define CAPACITY_CURRENT	0x02
  #define CAPACITY_NO_CARTRIDGE	0x03
c40d3d38a   Bartlomiej Zolnierkiewicz   [PATCH] ide-flopp...
71
  #define IDEFLOPPY_TICKS_DELAY	HZ/20	/* default delay for ZIP 100 (50ms) */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72

0571c7a4f   Borislav Petkov   ide-floppy: fix m...
73
  /* Error code returned in rq->errors to the higher part of the driver. */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
74
  #define	IDEFLOPPY_ERROR_GENERAL		101
cf8b8975c   Arjan van de Ven   [PATCH] sem2mutex...
75
  static DEFINE_MUTEX(idefloppy_ref_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
76
77
78
79
80
  
  #define to_ide_floppy(obj) container_of(obj, struct ide_floppy_obj, kref)
  
  #define ide_floppy_g(disk) \
  	container_of((disk)->private_data, struct ide_floppy_obj, driver)
08da591e1   Bartlomiej Zolnierkiewicz   ide: add ide_devi...
81
  static void idefloppy_cleanup_obj(struct kref *);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
82
83
84
  static struct ide_floppy_obj *ide_floppy_get(struct gendisk *disk)
  {
  	struct ide_floppy_obj *floppy = NULL;
cf8b8975c   Arjan van de Ven   [PATCH] sem2mutex...
85
  	mutex_lock(&idefloppy_ref_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86
  	floppy = ide_floppy_g(disk);
08da591e1   Bartlomiej Zolnierkiewicz   ide: add ide_devi...
87
  	if (floppy) {
d3e33ff59   Bartlomiej Zolnierkiewicz   ide: fix regressi...
88
  		if (ide_device_get(floppy->drive))
08da591e1   Bartlomiej Zolnierkiewicz   ide: add ide_devi...
89
  			floppy = NULL;
d3e33ff59   Bartlomiej Zolnierkiewicz   ide: fix regressi...
90
91
  		else
  			kref_get(&floppy->kref);
08da591e1   Bartlomiej Zolnierkiewicz   ide: add ide_devi...
92
  	}
cf8b8975c   Arjan van de Ven   [PATCH] sem2mutex...
93
  	mutex_unlock(&idefloppy_ref_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
94
95
  	return floppy;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
96
97
  static void ide_floppy_put(struct ide_floppy_obj *floppy)
  {
d3e33ff59   Bartlomiej Zolnierkiewicz   ide: fix regressi...
98
  	ide_drive_t *drive = floppy->drive;
cf8b8975c   Arjan van de Ven   [PATCH] sem2mutex...
99
  	mutex_lock(&idefloppy_ref_mutex);
9a24b63db   Borislav Petkov   ide-floppy: disam...
100
  	kref_put(&floppy->kref, idefloppy_cleanup_obj);
d3e33ff59   Bartlomiej Zolnierkiewicz   ide: fix regressi...
101
  	ide_device_put(drive);
cf8b8975c   Arjan van de Ven   [PATCH] sem2mutex...
102
  	mutex_unlock(&idefloppy_ref_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
103
104
105
  }
  
  /*
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
106
107
   * Used to finish servicing a request. For read/write requests, we will call
   * ide_end_request to pass to the next buffer.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
108
   */
c2b2b2936   Borislav Petkov   ide-floppy: renam...
109
  static int idefloppy_end_request(ide_drive_t *drive, int uptodate, int nsecs)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
110
111
112
113
  {
  	idefloppy_floppy_t *floppy = drive->driver_data;
  	struct request *rq = HWGROUP(drive)->rq;
  	int error;
bcc77d9cc   Borislav Petkov   ide-floppy: clean...
114
115
  	debug_log("Reached %s
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
116
117
  
  	switch (uptodate) {
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
118
119
120
  	case 0: error = IDEFLOPPY_ERROR_GENERAL; break;
  	case 1: error = 0; break;
  	default: error = uptodate;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121
122
123
124
125
126
  	}
  	if (error)
  		floppy->failed_pc = NULL;
  	/* Why does this happen? */
  	if (!rq)
  		return 0;
4aff5e233   Jens Axboe   [PATCH] Split str...
127
  	if (!blk_special_request(rq)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
128
129
130
131
132
133
134
135
136
  		/* our real local end request function */
  		ide_end_request(drive, uptodate, nsecs);
  		return 0;
  	}
  	rq->errors = error;
  	/* fixme: need to move this local also */
  	ide_end_drive_cmd(drive, 0, 0);
  	return 0;
  }
8e5551239   Borislav Petkov   ide-floppy: conve...
137
138
  static void idefloppy_update_buffers(ide_drive_t *drive,
  				struct ide_atapi_pc *pc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139
140
141
142
143
  {
  	struct request *rq = pc->rq;
  	struct bio *bio = rq->bio;
  
  	while ((bio = rq->bio) != NULL)
c2b2b2936   Borislav Petkov   ide-floppy: renam...
144
  		idefloppy_end_request(drive, 1, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
145
  }
81f493823   Borislav Petkov   ide-floppy: merge...
146
  static void ide_floppy_callback(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
147
148
  {
  	idefloppy_floppy_t *floppy = drive->driver_data;
81f493823   Borislav Petkov   ide-floppy: merge...
149
150
  	struct ide_atapi_pc *pc = floppy->pc;
  	int uptodate = pc->error ? 0 : 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
151

bcc77d9cc   Borislav Petkov   ide-floppy: clean...
152
153
  	debug_log("Reached %s
  ", __func__);
dd2e9a032   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
154
155
  	if (floppy->failed_pc == pc)
  		floppy->failed_pc = NULL;
81f493823   Borislav Petkov   ide-floppy: merge...
156
157
158
159
160
  	if (pc->c[0] == GPCMD_READ_10 || pc->c[0] == GPCMD_WRITE_10 ||
  	    (pc->rq && blk_pc_request(pc->rq)))
  		uptodate = 1; /* FIXME */
  	else if (pc->c[0] == GPCMD_REQUEST_SENSE) {
  		u8 *buf = floppy->pc->buf;
a6ff2d3b0   Borislav Petkov   ide-floppy: remov...
161

81f493823   Borislav Petkov   ide-floppy: merge...
162
163
164
165
166
167
  		if (!pc->error) {
  			floppy->sense_key = buf[2] & 0x0F;
  			floppy->asc = buf[12];
  			floppy->ascq = buf[13];
  			floppy->progress_indication = buf[15] & 0x80 ?
  				(u16)get_unaligned((u16 *)&buf[16]) : 0x10000;
a6ff2d3b0   Borislav Petkov   ide-floppy: remov...
168

81f493823   Borislav Petkov   ide-floppy: merge...
169
170
  			if (floppy->failed_pc)
  				debug_log("pc = %x, ", floppy->failed_pc->c[0]);
bcc77d9cc   Borislav Petkov   ide-floppy: clean...
171

81f493823   Borislav Petkov   ide-floppy: merge...
172
173
174
175
176
177
178
179
  			debug_log("sense key = %x, asc = %x, ascq = %x
  ",
  				  floppy->sense_key, floppy->asc, floppy->ascq);
  		} else
  			printk(KERN_ERR "Error in REQUEST SENSE itself - "
  					"Aborting request!
  ");
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
180

81f493823   Borislav Petkov   ide-floppy: merge...
181
  	idefloppy_end_request(drive, uptodate, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
182
  }
0127854d7   Bartlomiej Zolnierkiewicz   ide-floppy: move ...
183
  void ide_floppy_create_request_sense_cmd(struct ide_atapi_pc *pc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
184
  {
7bf7420a3   Bartlomiej Zolnierkiewicz   ide: add ide_init...
185
  	ide_init_pc(pc);
30d670993   Borislav Petkov   ide-floppy: conve...
186
  	pc->c[0] = GPCMD_REQUEST_SENSE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
187
  	pc->c[4] = 255;
8e5551239   Borislav Petkov   ide-floppy: conve...
188
  	pc->req_xfer = 18;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
189
190
191
  }
  
  /*
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
192
193
   * Called when an error was detected during the last packet command. We queue a
   * request sense packet command in the head of the request list.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
194
   */
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
195
  static void idefloppy_retry_pc(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
196
  {
394a4c210   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
197
198
  	struct ide_floppy_obj *floppy = drive->driver_data;
  	struct request *rq = &floppy->request_sense_rq;
2e8a6f89d   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
199
  	struct ide_atapi_pc *pc = &floppy->request_sense_pc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
200

64a57fe43   Bartlomiej Zolnierkiewicz   ide: add ide_read...
201
  	(void)ide_read_error(drive);
0127854d7   Bartlomiej Zolnierkiewicz   ide-floppy: move ...
202
  	ide_floppy_create_request_sense_cmd(pc);
7645c1514   Bartlomiej Zolnierkiewicz   ide: add ide_queu...
203
  	ide_queue_pc_head(drive, floppy->disk, pc, rq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
204
  }
0eea6458c   Borislav Petkov   ide-floppy: use a...
205
  /* The usual interrupt handler called during a packet command. */
52d3ccf76   Paolo Ciarrocchi   IDE: Coding Style...
206
  static ide_startstop_t idefloppy_pc_intr(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
207
208
  {
  	idefloppy_floppy_t *floppy = drive->driver_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
209

646c0cb6c   Bartlomiej Zolnierkiewicz   ide: add ide_pc_i...
210
211
  	return ide_pc_intr(drive, floppy->pc, idefloppy_pc_intr,
  			   IDEFLOPPY_WAIT_CMD, NULL, idefloppy_update_buffers,
acaa0f5f6   Bartlomiej Zolnierkiewicz   ide: add ide_io_b...
212
  			   idefloppy_retry_pc, NULL, ide_io_buffers);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
213
214
215
  }
  
  /*
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
216
217
218
219
   * What we have here is a classic case of a top half / bottom half interrupt
   * service routine. In interrupt mode, the device sends an interrupt to signal
   * that it is ready to receive a packet. However, we need to delay about 2-3
   * ticks before issuing the packet or we gets in trouble.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
220
   */
cbbc4e818   Borislav Petkov   ide-floppy: fix u...
221
  static int idefloppy_transfer_pc(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
222
223
224
225
  {
  	idefloppy_floppy_t *floppy = drive->driver_data;
  
  	/* Send the actual packet */
374e042c3   Bartlomiej Zolnierkiewicz   ide: add struct i...
226
  	drive->hwif->tp_ops->output_data(drive, NULL, floppy->pc->c, 12);
9567b349f   Bartlomiej Zolnierkiewicz   ide: merge ->atap...
227

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
228
229
230
  	/* Timeout for the packet command */
  	return IDEFLOPPY_WAIT_CMD;
  }
cbbc4e818   Borislav Petkov   ide-floppy: fix u...
231
232
233
234
235
236
237
  
  /*
   * Called as an interrupt (or directly). When the device says it's ready for a
   * packet, we schedule the packet transfer to occur about 2-3 ticks later in
   * transfer_pc.
   */
  static ide_startstop_t idefloppy_start_pc_transfer(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
238
239
  {
  	idefloppy_floppy_t *floppy = drive->driver_data;
6ffb66410   Bartlomiej Zolnierkiewicz   ide-floppy: start...
240
  	struct ide_atapi_pc *pc = floppy->pc;
0b2eea4c5   Bartlomiej Zolnierkiewicz   ide-floppy: merge...
241
242
  	ide_expiry_t *expiry;
  	unsigned int timeout;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243

0571c7a4f   Borislav Petkov   ide-floppy: fix m...
244
  	/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
245
246
247
248
249
250
251
  	 * The following delay solves a problem with ATAPI Zip 100 drives
  	 * where the Busy flag was apparently being deasserted before the
  	 * unit was ready to receive data. This was happening on a
  	 * 1200 MHz Athlon system. 10/26/01 25msec is too short,
  	 * 40 and 50msec work well. idefloppy_pc_intr will not be actually
  	 * used until after the packet is moved in about 50 msec.
  	 */
ea68d270f   Borislav Petkov   ide-floppy: conve...
252
  	if (drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) {
0b2eea4c5   Bartlomiej Zolnierkiewicz   ide-floppy: merge...
253
  		timeout = floppy->ticks;
cbbc4e818   Borislav Petkov   ide-floppy: fix u...
254
  		expiry = &idefloppy_transfer_pc;
0b2eea4c5   Bartlomiej Zolnierkiewicz   ide-floppy: merge...
255
256
257
258
  	} else {
  		timeout = IDEFLOPPY_WAIT_CMD;
  		expiry = NULL;
  	}
594c16d8d   Bartlomiej Zolnierkiewicz   ide: add ide_tran...
259
  	return ide_transfer_pc(drive, pc, idefloppy_pc_intr, timeout, expiry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
260
  }
d652c1380   Borislav Petkov   ide-floppy: mv id...
261
  static void ide_floppy_report_error(idefloppy_floppy_t *floppy,
8e5551239   Borislav Petkov   ide-floppy: conve...
262
  				    struct ide_atapi_pc *pc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
263
  {
d652c1380   Borislav Petkov   ide-floppy: mv id...
264
  	/* supress error messages resulting from Medium not present */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
265
266
267
  	if (floppy->sense_key == 0x02 &&
  	    floppy->asc       == 0x3a &&
  	    floppy->ascq      == 0x00)
d652c1380   Borislav Petkov   ide-floppy: mv id...
268
269
270
271
272
273
274
  		return;
  
  	printk(KERN_ERR "ide-floppy: %s: I/O error, pc = %2x, key = %2x, "
  			"asc = %2x, ascq = %2x
  ",
  			floppy->drive->name, pc->c[0], floppy->sense_key,
  			floppy->asc, floppy->ascq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
275
  }
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
276
  static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive,
8e5551239   Borislav Petkov   ide-floppy: conve...
277
  		struct ide_atapi_pc *pc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
278
279
  {
  	idefloppy_floppy_t *floppy = drive->driver_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
280

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
281
  	if (floppy->failed_pc == NULL &&
30d670993   Borislav Petkov   ide-floppy: conve...
282
  	    pc->c[0] != GPCMD_REQUEST_SENSE)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
283
284
285
  		floppy->failed_pc = pc;
  	/* Set the current packet command */
  	floppy->pc = pc;
757ced898   Borislav Petkov   ide-floppy: remov...
286
  	if (pc->retries > IDEFLOPPY_MAX_PC_RETRIES) {
6e5fa7b88   Borislav Petkov   ide-floppy: remov...
287
  		if (!(pc->flags & PC_FLAG_SUPPRESS_ERROR))
757ced898   Borislav Petkov   ide-floppy: remov...
288
289
290
  			ide_floppy_report_error(floppy, pc);
  		/* Giving up */
  		pc->error = IDEFLOPPY_ERROR_GENERAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
291
  		floppy->failed_pc = NULL;
2207fa5af   Borislav Petkov   ide-floppy: use d...
292
  		drive->pc_callback(drive);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
293
294
  		return ide_stopped;
  	}
bcc77d9cc   Borislav Petkov   ide-floppy: clean...
295
296
  	debug_log("Retry number - %d
  ", pc->retries);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
297
298
  
  	pc->retries++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
299

cbbc4e818   Borislav Petkov   ide-floppy: fix u...
300
  	return ide_issue_pc(drive, pc, idefloppy_start_pc_transfer,
6bf1641ca   Bartlomiej Zolnierkiewicz   ide: add ide_issu...
301
  			    IDEFLOPPY_WAIT_CMD, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
302
  }
0127854d7   Bartlomiej Zolnierkiewicz   ide-floppy: move ...
303
  void ide_floppy_create_read_capacity_cmd(struct ide_atapi_pc *pc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
304
  {
7bf7420a3   Bartlomiej Zolnierkiewicz   ide: add ide_init...
305
  	ide_init_pc(pc);
30d670993   Borislav Petkov   ide-floppy: conve...
306
  	pc->c[0] = GPCMD_READ_FORMAT_CAPACITIES;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
307
308
  	pc->c[7] = 255;
  	pc->c[8] = 255;
8e5551239   Borislav Petkov   ide-floppy: conve...
309
  	pc->req_xfer = 255;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
310
  }
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
311
  /* A mode sense command is used to "sense" floppy parameters. */
0127854d7   Bartlomiej Zolnierkiewicz   ide-floppy: move ...
312
  void ide_floppy_create_mode_sense_cmd(struct ide_atapi_pc *pc, u8 page_code)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
313
  {
24a5d7033   Borislav Petkov   ide-floppy: remov...
314
  	u16 length = 8; /* sizeof(Mode Parameter Header) = 8 Bytes */
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
315

7bf7420a3   Bartlomiej Zolnierkiewicz   ide: add ide_init...
316
  	ide_init_pc(pc);
30d670993   Borislav Petkov   ide-floppy: conve...
317
  	pc->c[0] = GPCMD_MODE_SENSE_10;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
318
  	pc->c[1] = 0;
4de4b9e14   Bartlomiej Zolnierkiewicz   ide-floppy: remov...
319
  	pc->c[2] = page_code;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
320
321
  
  	switch (page_code) {
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
322
323
324
325
326
327
328
329
  	case IDEFLOPPY_CAPABILITIES_PAGE:
  		length += 12;
  		break;
  	case IDEFLOPPY_FLEXIBLE_DISK_PAGE:
  		length += 32;
  		break;
  	default:
  		printk(KERN_ERR "ide-floppy: unsupported page code "
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
330
331
332
  				"in create_mode_sense_cmd
  ");
  	}
8f6224308   Borislav Petkov   ide-floppy: repla...
333
  	put_unaligned(cpu_to_be16(length), (u16 *) &pc->c[7]);
8e5551239   Borislav Petkov   ide-floppy: conve...
334
  	pc->req_xfer = length;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
335
  }
8e5551239   Borislav Petkov   ide-floppy: conve...
336
  static void idefloppy_create_start_stop_cmd(struct ide_atapi_pc *pc, int start)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
337
  {
7bf7420a3   Bartlomiej Zolnierkiewicz   ide: add ide_init...
338
  	ide_init_pc(pc);
30d670993   Borislav Petkov   ide-floppy: conve...
339
  	pc->c[0] = GPCMD_START_STOP_UNIT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
340
341
  	pc->c[4] = start;
  }
ae7e8ddc3   Borislav Petkov   ide-floppy: remov...
342
  static void idefloppy_create_rw_cmd(idefloppy_floppy_t *floppy,
8e5551239   Borislav Petkov   ide-floppy: conve...
343
  				    struct ide_atapi_pc *pc, struct request *rq,
ae7e8ddc3   Borislav Petkov   ide-floppy: remov...
344
  				    unsigned long sector)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
345
346
347
348
  {
  	int block = sector / floppy->bs_factor;
  	int blocks = rq->nr_sectors / floppy->bs_factor;
  	int cmd = rq_data_dir(rq);
ae7e8ddc3   Borislav Petkov   ide-floppy: remov...
349
350
  	debug_log("create_rw10_cmd: block == %d, blocks == %d
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
351
  		block, blocks);
7bf7420a3   Bartlomiej Zolnierkiewicz   ide: add ide_init...
352
  	ide_init_pc(pc);
ae7e8ddc3   Borislav Petkov   ide-floppy: remov...
353
354
  	pc->c[0] = cmd == READ ? GPCMD_READ_10 : GPCMD_WRITE_10;
  	put_unaligned(cpu_to_be16(blocks), (unsigned short *)&pc->c[7]);
8f6224308   Borislav Petkov   ide-floppy: repla...
355
  	put_unaligned(cpu_to_be32(block), (unsigned int *) &pc->c[2]);
ae7e8ddc3   Borislav Petkov   ide-floppy: remov...
356

20cd93be6   Borislav Petkov   ide-floppy: pass ...
357
  	memcpy(rq->cmd, pc->c, 12);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
358
  	pc->rq = rq;
b98b3409a   Borislav Petkov   ide-floppy: use s...
359
  	pc->b_count = 0;
4aff5e233   Jens Axboe   [PATCH] Split str...
360
  	if (rq->cmd_flags & REQ_RW)
6e5fa7b88   Borislav Petkov   ide-floppy: remov...
361
  		pc->flags |= PC_FLAG_WRITING;
8e5551239   Borislav Petkov   ide-floppy: conve...
362
363
  	pc->buf = NULL;
  	pc->req_xfer = pc->buf_size = blocks * floppy->block_size;
5e3310958   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
364
  	pc->flags |= PC_FLAG_DMA_OK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
365
  }
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
366
  static void idefloppy_blockpc_cmd(idefloppy_floppy_t *floppy,
8e5551239   Borislav Petkov   ide-floppy: conve...
367
  		struct ide_atapi_pc *pc, struct request *rq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
368
  {
7bf7420a3   Bartlomiej Zolnierkiewicz   ide: add ide_init...
369
  	ide_init_pc(pc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
370
  	memcpy(pc->c, rq->cmd, sizeof(pc->c));
3d6392cfb   Jens Axboe   bsg: support for ...
371
  	pc->rq = rq;
b98b3409a   Borislav Petkov   ide-floppy: use s...
372
  	pc->b_count = 0;
3d6392cfb   Jens Axboe   bsg: support for ...
373
  	if (rq->data_len && rq_data_dir(rq) == WRITE)
6e5fa7b88   Borislav Petkov   ide-floppy: remov...
374
  		pc->flags |= PC_FLAG_WRITING;
8e5551239   Borislav Petkov   ide-floppy: conve...
375
  	pc->buf = rq->data;
3d6392cfb   Jens Axboe   bsg: support for ...
376
  	if (rq->bio)
5e3310958   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
377
  		pc->flags |= PC_FLAG_DMA_OK;
3d6392cfb   Jens Axboe   bsg: support for ...
378
379
380
381
  	/*
  	 * possibly problematic, doesn't look like ide-floppy correctly
  	 * handled scattered requests if dma fails...
  	 */
8e5551239   Borislav Petkov   ide-floppy: conve...
382
  	pc->req_xfer = pc->buf_size = rq->data_len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
383
  }
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
384
385
  static ide_startstop_t idefloppy_do_request(ide_drive_t *drive,
  		struct request *rq, sector_t block_s)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
386
387
  {
  	idefloppy_floppy_t *floppy = drive->driver_data;
b98b3409a   Borislav Petkov   ide-floppy: use s...
388
  	ide_hwif_t *hwif = drive->hwif;
8e5551239   Borislav Petkov   ide-floppy: conve...
389
  	struct ide_atapi_pc *pc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
390
  	unsigned long block = (unsigned long)block_s;
b98b3409a   Borislav Petkov   ide-floppy: use s...
391
392
393
394
395
396
397
398
399
  	debug_log("%s: dev: %s, cmd: 0x%x, cmd_type: %x, errors: %d
  ",
  		  __func__, rq->rq_disk ? rq->rq_disk->disk_name : "?",
  		  rq->cmd[0], rq->cmd_type, rq->errors);
  
  	debug_log("%s: sector: %ld, nr_sectors: %ld, current_nr_sectors: %d
  ",
  		  __func__, (long)rq->sector, rq->nr_sectors,
  		  rq->current_nr_sectors);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
400
401
  
  	if (rq->errors >= ERROR_MAX) {
d652c1380   Borislav Petkov   ide-floppy: mv id...
402
403
  		if (floppy->failed_pc)
  			ide_floppy_report_error(floppy, floppy->failed_pc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
404
405
406
407
  		else
  			printk(KERN_ERR "ide-floppy: %s: I/O error
  ",
  				drive->name);
c2b2b2936   Borislav Petkov   ide-floppy: renam...
408
  		idefloppy_end_request(drive, 0, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
409
410
  		return ide_stopped;
  	}
4aff5e233   Jens Axboe   [PATCH] Split str...
411
  	if (blk_fs_request(rq)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
412
413
  		if (((long)rq->sector % floppy->bs_factor) ||
  		    (rq->nr_sectors % floppy->bs_factor)) {
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
414
415
416
  			printk(KERN_ERR "%s: unsupported r/w request size
  ",
  					drive->name);
c2b2b2936   Borislav Petkov   ide-floppy: renam...
417
  			idefloppy_end_request(drive, 0, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
418
419
  			return ide_stopped;
  		}
2e8a6f89d   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
420
  		pc = &floppy->queued_pc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
421
  		idefloppy_create_rw_cmd(floppy, pc, rq, block);
4aff5e233   Jens Axboe   [PATCH] Split str...
422
  	} else if (blk_special_request(rq)) {
8e5551239   Borislav Petkov   ide-floppy: conve...
423
  		pc = (struct ide_atapi_pc *) rq->buffer;
4aff5e233   Jens Axboe   [PATCH] Split str...
424
  	} else if (blk_pc_request(rq)) {
2e8a6f89d   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
425
  		pc = &floppy->queued_pc;
3d6392cfb   Jens Axboe   bsg: support for ...
426
  		idefloppy_blockpc_cmd(floppy, pc, rq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
427
428
429
  	} else {
  		blk_dump_rq_flags(rq,
  			"ide-floppy: unsupported command in queue");
c2b2b2936   Borislav Petkov   ide-floppy: renam...
430
  		idefloppy_end_request(drive, 0, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
431
432
  		return ide_stopped;
  	}
b98b3409a   Borislav Petkov   ide-floppy: use s...
433
434
435
436
437
  	ide_init_sg_cmd(drive, rq);
  	ide_map_sg(drive, rq);
  
  	pc->sg = hwif->sg_table;
  	pc->sg_cnt = hwif->sg_nents;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
438
  	pc->rq = rq;
5d41893c0   Bartlomiej Zolnierkiewicz   ide: add PC_FLAG_...
439

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
440
441
442
443
  	return idefloppy_issue_pc(drive, pc);
  }
  
  /*
8e81bbba7   Borislav Petkov   ide-floppy: remov...
444
445
   * Look at the flexible disk page parameters. We ignore the CHS capacity
   * parameters and use the LBA parameters instead.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
446
   */
8e81bbba7   Borislav Petkov   ide-floppy: remov...
447
  static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
448
449
  {
  	idefloppy_floppy_t *floppy = drive->driver_data;
2ac07d920   Bartlomiej Zolnierkiewicz   ide: add ide_queu...
450
  	struct gendisk *disk = floppy->disk;
8e5551239   Borislav Petkov   ide-floppy: conve...
451
  	struct ide_atapi_pc pc;
8e81bbba7   Borislav Petkov   ide-floppy: remov...
452
  	u8 *page;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
453
  	int capacity, lba_capacity;
8e81bbba7   Borislav Petkov   ide-floppy: remov...
454
455
  	u16 transfer_rate, sector_size, cyls, rpm;
  	u8 heads, sectors;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
456

0127854d7   Bartlomiej Zolnierkiewicz   ide-floppy: move ...
457
  	ide_floppy_create_mode_sense_cmd(&pc, IDEFLOPPY_FLEXIBLE_DISK_PAGE);
8e81bbba7   Borislav Petkov   ide-floppy: remov...
458

2ac07d920   Bartlomiej Zolnierkiewicz   ide: add ide_queu...
459
  	if (ide_queue_pc_tail(drive, disk, &pc)) {
8e81bbba7   Borislav Petkov   ide-floppy: remov...
460
461
462
  		printk(KERN_ERR "ide-floppy: Can't get flexible disk page"
  				" parameters
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
463
464
  		return 1;
  	}
49cac39e7   Bartlomiej Zolnierkiewicz   ide-floppy: ->{sr...
465
466
467
468
469
470
471
  
  	if (pc.buf[3] & 0x80)
  		drive->atapi_flags |= IDE_AFLAG_WP;
  	else
  		drive->atapi_flags &= ~IDE_AFLAG_WP;
  
  	set_disk_ro(disk, !!(drive->atapi_flags & IDE_AFLAG_WP));
8e5551239   Borislav Petkov   ide-floppy: conve...
472
  	page = &pc.buf[8];
8e81bbba7   Borislav Petkov   ide-floppy: remov...
473

85ae98a3d   Harvey Harrison   ide: endian annot...
474
475
476
477
  	transfer_rate = be16_to_cpup((__be16 *)&pc.buf[8 + 2]);
  	sector_size   = be16_to_cpup((__be16 *)&pc.buf[8 + 6]);
  	cyls          = be16_to_cpup((__be16 *)&pc.buf[8 + 8]);
  	rpm           = be16_to_cpup((__be16 *)&pc.buf[8 + 28]);
8e5551239   Borislav Petkov   ide-floppy: conve...
478
479
  	heads         = pc.buf[8 + 4];
  	sectors       = pc.buf[8 + 5];
8e81bbba7   Borislav Petkov   ide-floppy: remov...
480
481
482
483
  
  	capacity = cyls * heads * sectors * sector_size;
  
  	if (memcmp(page, &floppy->flexible_disk_page, 32))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
484
485
486
  		printk(KERN_INFO "%s: %dkB, %d/%d/%d CHS, %d kBps, "
  				"%d sector size, %d rpm
  ",
8e81bbba7   Borislav Petkov   ide-floppy: remov...
487
488
489
490
491
492
493
  				drive->name, capacity / 1024, cyls, heads,
  				sectors, transfer_rate / 8, sector_size, rpm);
  
  	memcpy(&floppy->flexible_disk_page, page, 32);
  	drive->bios_cyl = cyls;
  	drive->bios_head = heads;
  	drive->bios_sect = sectors;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
494
  	lba_capacity = floppy->blocks * floppy->block_size;
8e81bbba7   Borislav Petkov   ide-floppy: remov...
495

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
496
497
498
499
500
  	if (capacity < lba_capacity) {
  		printk(KERN_NOTICE "%s: The disk reports a capacity of %d "
  			"bytes, but the drive only handles %d
  ",
  			drive->name, lba_capacity, capacity);
8e81bbba7   Borislav Petkov   ide-floppy: remov...
501
502
  		floppy->blocks = floppy->block_size ?
  			capacity / floppy->block_size : 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
503
504
505
  	}
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
506
  /*
194ec0c07   Borislav Petkov   ide-floppy: remov...
507
508
   * Determine if a media is present in the floppy drive, and if so, its LBA
   * capacity.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
509
   */
194ec0c07   Borislav Petkov   ide-floppy: remov...
510
  static int ide_floppy_get_capacity(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
511
512
  {
  	idefloppy_floppy_t *floppy = drive->driver_data;
2ac07d920   Bartlomiej Zolnierkiewicz   ide: add ide_queu...
513
  	struct gendisk *disk = floppy->disk;
8e5551239   Borislav Petkov   ide-floppy: conve...
514
  	struct ide_atapi_pc pc;
194ec0c07   Borislav Petkov   ide-floppy: remov...
515
516
517
  	u8 *cap_desc;
  	u8 header_len, desc_cnt;
  	int i, rc = 1, blocks, length;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
518
519
  	drive->bios_cyl = 0;
  	drive->bios_head = drive->bios_sect = 0;
fdb77da4c   Alan Cox   ide-floppy: Fix u...
520
521
  	floppy->blocks = 0;
  	floppy->bs_factor = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
522
  	set_capacity(floppy->disk, 0);
0127854d7   Bartlomiej Zolnierkiewicz   ide-floppy: move ...
523
  	ide_floppy_create_read_capacity_cmd(&pc);
2ac07d920   Bartlomiej Zolnierkiewicz   ide: add ide_queu...
524
  	if (ide_queue_pc_tail(drive, disk, &pc)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
525
526
527
528
  		printk(KERN_ERR "ide-floppy: Can't get floppy parameters
  ");
  		return 1;
  	}
8e5551239   Borislav Petkov   ide-floppy: conve...
529
530
  	header_len = pc.buf[3];
  	cap_desc = &pc.buf[4];
194ec0c07   Borislav Petkov   ide-floppy: remov...
531
532
533
534
  	desc_cnt = header_len / 8; /* capacity descriptor of 8 bytes */
  
  	for (i = 0; i < desc_cnt; i++) {
  		unsigned int desc_start = 4 + i*8;
85ae98a3d   Harvey Harrison   ide: endian annot...
535
536
  		blocks = be32_to_cpup((__be32 *)&pc.buf[desc_start]);
  		length = be16_to_cpup((__be16 *)&pc.buf[desc_start + 6]);
194ec0c07   Borislav Petkov   ide-floppy: remov...
537
538
539
540
  
  		debug_log("Descriptor %d: %dkB, %d blocks, %d sector size
  ",
  				i, blocks * length / 1024, blocks, length);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
541

194ec0c07   Borislav Petkov   ide-floppy: remov...
542
543
544
545
546
  		if (i)
  			continue;
  		/*
  		 * the code below is valid only for the 1st descriptor, ie i=0
  		 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
547

8e5551239   Borislav Petkov   ide-floppy: conve...
548
  		switch (pc.buf[desc_start + 4] & 0x03) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
549
550
  		/* Clik! drive returns this instead of CAPACITY_CURRENT */
  		case CAPACITY_UNFORMATTED:
ea68d270f   Borislav Petkov   ide-floppy: conve...
551
  			if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE))
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
552
  				/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
553
554
555
556
557
558
  				 * If it is not a clik drive, break out
  				 * (maintains previous driver behaviour)
  				 */
  				break;
  		case CAPACITY_CURRENT:
  			/* Normal Zip/LS-120 disks */
194ec0c07   Borislav Petkov   ide-floppy: remov...
559
  			if (memcmp(cap_desc, &floppy->cap_desc, 8))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
560
561
562
563
  				printk(KERN_INFO "%s: %dkB, %d blocks, %d "
  					"sector size
  ", drive->name,
  					blocks * length / 1024, blocks, length);
194ec0c07   Borislav Petkov   ide-floppy: remov...
564
  			memcpy(&floppy->cap_desc, cap_desc, 8);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
565
566
567
568
569
  			if (!length || length % 512) {
  				printk(KERN_NOTICE "%s: %d bytes block size "
  					"not supported
  ", drive->name, length);
  			} else {
194ec0c07   Borislav Petkov   ide-floppy: remov...
570
571
572
573
574
  				floppy->blocks = blocks;
  				floppy->block_size = length;
  				floppy->bs_factor = length / 512;
  				if (floppy->bs_factor != 1)
  					printk(KERN_NOTICE "%s: warning: non "
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
575
576
577
578
  						"512 bytes block size not "
  						"fully supported
  ",
  						drive->name);
194ec0c07   Borislav Petkov   ide-floppy: remov...
579
  				rc = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
  			}
  			break;
  		case CAPACITY_NO_CARTRIDGE:
  			/*
  			 * This is a KERN_ERR so it appears on screen
  			 * for the user to see
  			 */
  			printk(KERN_ERR "%s: No disk in drive
  ", drive->name);
  			break;
  		case CAPACITY_INVALID:
  			printk(KERN_ERR "%s: Invalid capacity for disk "
  				"in drive
  ", drive->name);
  			break;
  		}
194ec0c07   Borislav Petkov   ide-floppy: remov...
596
597
  		debug_log("Descriptor 0 Code: %d
  ",
8e5551239   Borislav Petkov   ide-floppy: conve...
598
  			  pc.buf[desc_start + 4] & 0x03);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
599
600
601
  	}
  
  	/* Clik! disk does not support get_flexible_disk_page */
ea68d270f   Borislav Petkov   ide-floppy: conve...
602
  	if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE))
8e81bbba7   Borislav Petkov   ide-floppy: remov...
603
  		(void) ide_floppy_get_flexible_disk_page(drive);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
604

2ac07d920   Bartlomiej Zolnierkiewicz   ide: add ide_queu...
605
  	set_capacity(disk, floppy->blocks * floppy->bs_factor);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
606
607
  	return rc;
  }
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
608
  static sector_t idefloppy_capacity(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
609
610
611
612
613
614
  {
  	idefloppy_floppy_t *floppy = drive->driver_data;
  	unsigned long capacity = floppy->blocks * floppy->bs_factor;
  
  	return capacity;
  }
7662d046d   Bartlomiej Zolnierkiewicz   ide: move IDE set...
615
  #ifdef CONFIG_IDE_PROC_FS
8185d5aa9   Bartlomiej Zolnierkiewicz   ide: /proc/ide/hd...
616
617
618
619
620
  ide_devset_rw(bios_cyl,  0, 1023, bios_cyl);
  ide_devset_rw(bios_head, 0,  255, bios_head);
  ide_devset_rw(bios_sect, 0,   63, bios_sect);
  
  static int get_ticks(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
621
622
  {
  	idefloppy_floppy_t *floppy = drive->driver_data;
8185d5aa9   Bartlomiej Zolnierkiewicz   ide: /proc/ide/hd...
623
624
  	return floppy->ticks;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
625

8185d5aa9   Bartlomiej Zolnierkiewicz   ide: /proc/ide/hd...
626
627
628
629
630
  static int set_ticks(ide_drive_t *drive, int arg)
  {
  	idefloppy_floppy_t *floppy = drive->driver_data;
  	floppy->ticks = arg;
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
631
  }
8185d5aa9   Bartlomiej Zolnierkiewicz   ide: /proc/ide/hd...
632
633
634
635
636
637
638
639
640
641
  
  IDE_DEVSET(ticks, S_RW, 0, 255, get_ticks, set_ticks);
  
  static const struct ide_devset *idefloppy_settings[] = {
  	&ide_devset_bios_cyl,
  	&ide_devset_bios_head,
  	&ide_devset_bios_sect,
  	&ide_devset_ticks,
  	NULL
  };
7662d046d   Bartlomiej Zolnierkiewicz   ide: move IDE set...
642
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
643

0571c7a4f   Borislav Petkov   ide-floppy: fix m...
644
  static void idefloppy_setup(ide_drive_t *drive, idefloppy_floppy_t *floppy)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
645
  {
4dde4492d   Bartlomiej Zolnierkiewicz   ide: make drive->...
646
  	u16 *id = drive->id;
3ad6776cc   Borislav Petkov   ide-floppy: remov...
647
  	u8 gcw[2];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
648

4dde4492d   Bartlomiej Zolnierkiewicz   ide: make drive->...
649
  	*((u16 *)&gcw) = id[ATA_ID_CONFIG];
2e8a6f89d   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
650

2207fa5af   Borislav Petkov   ide-floppy: use d...
651
  	drive->pc_callback = ide_floppy_callback;
3ad6776cc   Borislav Petkov   ide-floppy: remov...
652
653
  
  	if (((gcw[0] & 0x60) >> 5) == 1)
ea68d270f   Borislav Petkov   ide-floppy: conve...
654
  		drive->atapi_flags |= IDE_AFLAG_DRQ_INTERRUPT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
655
  	/*
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
656
657
  	 * We used to check revisions here. At this point however I'm giving up.
  	 * Just assume they are all broken, its easier.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
658
  	 *
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
659
660
661
662
  	 * The actual reason for the workarounds was likely a driver bug after
  	 * all rather than a firmware bug, and the workaround below used to hide
  	 * it. It should be fixed as of version 1.9, but to be on the safe side
  	 * we'll leave the limitation below for the 2.2.x tree.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
663
  	 */
4dde4492d   Bartlomiej Zolnierkiewicz   ide: make drive->...
664
  	if (!strncmp((char *)&id[ATA_ID_PROD], "IOMEGA ZIP 100 ATAPI", 20)) {
ea68d270f   Borislav Petkov   ide-floppy: conve...
665
  		drive->atapi_flags |= IDE_AFLAG_ZIP_DRIVE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
666
667
668
669
670
671
  		/* This value will be visible in the /proc/ide/hdx/settings */
  		floppy->ticks = IDEFLOPPY_TICKS_DELAY;
  		blk_queue_max_sectors(drive->queue, 64);
  	}
  
  	/*
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
672
673
674
  	 * Guess what? The IOMEGA Clik! drive also needs the above fix. It makes
  	 * nasty clicking noises without it, so please don't remove this.
  	 */
4dde4492d   Bartlomiej Zolnierkiewicz   ide: make drive->...
675
  	if (strncmp((char *)&id[ATA_ID_PROD], "IOMEGA Clik!", 11) == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
676
  		blk_queue_max_sectors(drive->queue, 64);
ea68d270f   Borislav Petkov   ide-floppy: conve...
677
  		drive->atapi_flags |= IDE_AFLAG_CLIK_DRIVE;
0578042db   Bartlomiej Zolnierkiewicz   ide: add ide_set_...
678
679
  		/* IOMEGA Clik! drives do not support lock/unlock commands */
  		drive->atapi_flags |= IDE_AFLAG_NO_DOORLOCK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
680
  	}
194ec0c07   Borislav Petkov   ide-floppy: remov...
681
  	(void) ide_floppy_get_capacity(drive);
1e874f448   Bartlomiej Zolnierkiewicz   ide: call ide_pro...
682
683
  
  	ide_proc_register_driver(drive, floppy->driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
684
  }
4031bbe4b   Russell King   [PATCH] Add ide_b...
685
  static void ide_floppy_remove(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
686
687
688
  {
  	idefloppy_floppy_t *floppy = drive->driver_data;
  	struct gendisk *g = floppy->disk;
7662d046d   Bartlomiej Zolnierkiewicz   ide: move IDE set...
689
  	ide_proc_unregister_driver(drive, floppy->driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
690
691
692
693
  
  	del_gendisk(g);
  
  	ide_floppy_put(floppy);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
694
  }
9a24b63db   Borislav Petkov   ide-floppy: disam...
695
  static void idefloppy_cleanup_obj(struct kref *kref)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
696
697
698
699
700
701
702
703
704
705
  {
  	struct ide_floppy_obj *floppy = to_ide_floppy(kref);
  	ide_drive_t *drive = floppy->drive;
  	struct gendisk *g = floppy->disk;
  
  	drive->driver_data = NULL;
  	g->private_data = NULL;
  	put_disk(g);
  	kfree(floppy);
  }
ecfd80e4a   Bartlomiej Zolnierkiewicz   ide: make /proc/i...
706
  #ifdef CONFIG_IDE_PROC_FS
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
707
708
  static int proc_idefloppy_read_capacity(char *page, char **start, off_t off,
  		int count, int *eof, void *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
709
710
711
  {
  	ide_drive_t*drive = (ide_drive_t *)data;
  	int len;
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
712
713
714
  	len = sprintf(page, "%llu
  ", (long long)idefloppy_capacity(drive));
  	PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
715
716
717
  }
  
  static ide_proc_entry_t idefloppy_proc[] = {
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
718
719
  	{ "capacity",	S_IFREG|S_IRUGO, proc_idefloppy_read_capacity,	NULL },
  	{ "geometry",	S_IFREG|S_IRUGO, proc_ide_read_geometry,	NULL },
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
720
721
  	{ NULL, 0, NULL, NULL }
  };
ecfd80e4a   Bartlomiej Zolnierkiewicz   ide: make /proc/i...
722
  #endif	/* CONFIG_IDE_PROC_FS */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
723

4031bbe4b   Russell King   [PATCH] Add ide_b...
724
  static int ide_floppy_probe(ide_drive_t *);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
725

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
726
  static ide_driver_t idefloppy_driver = {
8604affde   Bartlomiej Zolnierkiewicz   [PATCH] convert I...
727
  	.gen_driver = {
4ef3b8f4a   Laurent Riffard   [PATCH] ide: remo...
728
  		.owner		= THIS_MODULE,
8604affde   Bartlomiej Zolnierkiewicz   [PATCH] convert I...
729
730
  		.name		= "ide-floppy",
  		.bus		= &ide_bus_type,
8604affde   Bartlomiej Zolnierkiewicz   [PATCH] convert I...
731
  	},
4031bbe4b   Russell King   [PATCH] Add ide_b...
732
733
  	.probe			= ide_floppy_probe,
  	.remove			= ide_floppy_remove,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
734
735
  	.version		= IDEFLOPPY_VERSION,
  	.media			= ide_floppy,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
736
  	.do_request		= idefloppy_do_request,
c2b2b2936   Borislav Petkov   ide-floppy: renam...
737
  	.end_request		= idefloppy_end_request,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
738
  	.error			= __ide_error,
7662d046d   Bartlomiej Zolnierkiewicz   ide: move IDE set...
739
  #ifdef CONFIG_IDE_PROC_FS
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
740
  	.proc			= idefloppy_proc,
8185d5aa9   Bartlomiej Zolnierkiewicz   ide: /proc/ide/hd...
741
  	.settings		= idefloppy_settings,
7662d046d   Bartlomiej Zolnierkiewicz   ide: move IDE set...
742
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
743
744
745
746
747
748
749
  };
  
  static int idefloppy_open(struct inode *inode, struct file *filp)
  {
  	struct gendisk *disk = inode->i_bdev->bd_disk;
  	struct ide_floppy_obj *floppy;
  	ide_drive_t *drive;
8e5551239   Borislav Petkov   ide-floppy: conve...
750
  	struct ide_atapi_pc pc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
751
  	int ret = 0;
bcc77d9cc   Borislav Petkov   ide-floppy: clean...
752
753
  	debug_log("Reached %s
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
754

0571c7a4f   Borislav Petkov   ide-floppy: fix m...
755
756
  	floppy = ide_floppy_get(disk);
  	if (!floppy)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
757
758
759
  		return -ENXIO;
  
  	drive = floppy->drive;
c94964a45   Bartlomiej Zolnierkiewicz   ide: remove ide_d...
760
  	floppy->openers++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
761

c94964a45   Bartlomiej Zolnierkiewicz   ide: remove ide_d...
762
  	if (floppy->openers == 1) {
ea68d270f   Borislav Petkov   ide-floppy: conve...
763
  		drive->atapi_flags &= ~IDE_AFLAG_FORMAT_IN_PROGRESS;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
764
  		/* Just in case */
7bf7420a3   Bartlomiej Zolnierkiewicz   ide: add ide_init...
765
  		ide_init_pc(&pc);
c96a7df8d   Borislav Petkov   ide-floppy: fold ...
766
  		pc.c[0] = GPCMD_TEST_UNIT_READY;
2ac07d920   Bartlomiej Zolnierkiewicz   ide: add ide_queu...
767
  		if (ide_queue_pc_tail(drive, disk, &pc)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
768
  			idefloppy_create_start_stop_cmd(&pc, 1);
2ac07d920   Bartlomiej Zolnierkiewicz   ide: add ide_queu...
769
  			(void)ide_queue_pc_tail(drive, disk, &pc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
770
  		}
194ec0c07   Borislav Petkov   ide-floppy: remov...
771
  		if (ide_floppy_get_capacity(drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
772
773
  		   && (filp->f_flags & O_NDELAY) == 0
  		    /*
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
774
775
776
777
  		     * Allow O_NDELAY to open a drive without a disk, or with an
  		     * unreadable disk, so that we can get the format capacity
  		     * of the drive or begin the format - Sam
  		     */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
778
  		    ) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
779
780
781
  			ret = -EIO;
  			goto out_put_floppy;
  		}
49cac39e7   Bartlomiej Zolnierkiewicz   ide-floppy: ->{sr...
782
  		if ((drive->atapi_flags & IDE_AFLAG_WP) && (filp->f_mode & 2)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
783
784
785
  			ret = -EROFS;
  			goto out_put_floppy;
  		}
e996fc8ae   Bartlomiej Zolnierkiewicz   ide-floppy: add i...
786

ea68d270f   Borislav Petkov   ide-floppy: conve...
787
  		drive->atapi_flags |= IDE_AFLAG_MEDIA_CHANGED;
0578042db   Bartlomiej Zolnierkiewicz   ide: add ide_set_...
788
  		ide_set_media_lock(drive, disk, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
789
  		check_disk_change(inode->i_bdev);
ea68d270f   Borislav Petkov   ide-floppy: conve...
790
  	} else if (drive->atapi_flags & IDE_AFLAG_FORMAT_IN_PROGRESS) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
791
792
793
794
795
796
  		ret = -EBUSY;
  		goto out_put_floppy;
  	}
  	return 0;
  
  out_put_floppy:
c94964a45   Bartlomiej Zolnierkiewicz   ide: remove ide_d...
797
  	floppy->openers--;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
798
799
800
801
802
803
804
805
806
  	ide_floppy_put(floppy);
  	return ret;
  }
  
  static int idefloppy_release(struct inode *inode, struct file *filp)
  {
  	struct gendisk *disk = inode->i_bdev->bd_disk;
  	struct ide_floppy_obj *floppy = ide_floppy_g(disk);
  	ide_drive_t *drive = floppy->drive;
bcc77d9cc   Borislav Petkov   ide-floppy: clean...
807
808
809
  
  	debug_log("Reached %s
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
810

c94964a45   Bartlomiej Zolnierkiewicz   ide: remove ide_d...
811
  	if (floppy->openers == 1) {
0578042db   Bartlomiej Zolnierkiewicz   ide: add ide_set_...
812
  		ide_set_media_lock(drive, disk, 0);
ea68d270f   Borislav Petkov   ide-floppy: conve...
813
  		drive->atapi_flags &= ~IDE_AFLAG_FORMAT_IN_PROGRESS;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
814
  	}
c94964a45   Bartlomiej Zolnierkiewicz   ide: remove ide_d...
815
816
  
  	floppy->openers--;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
817
818
819
820
821
  
  	ide_floppy_put(floppy);
  
  	return 0;
  }
a885c8c43   Christoph Hellwig   [PATCH] Add block...
822
823
824
825
826
827
828
829
830
831
  static int idefloppy_getgeo(struct block_device *bdev, struct hd_geometry *geo)
  {
  	struct ide_floppy_obj *floppy = ide_floppy_g(bdev->bd_disk);
  	ide_drive_t *drive = floppy->drive;
  
  	geo->heads = drive->bios_head;
  	geo->sectors = drive->bios_sect;
  	geo->cylinders = (u16)drive->bios_cyl; /* truncate */
  	return 0;
  }
ea68d270f   Borislav Petkov   ide-floppy: conve...
832
833
  static int ide_floppy_lockdoor(ide_drive_t *drive, struct ide_atapi_pc *pc,
  			       unsigned long arg, unsigned int cmd)
20bf7bdad   Borislav Petkov   ide-floppy: facto...
834
  {
ea68d270f   Borislav Petkov   ide-floppy: conve...
835
  	idefloppy_floppy_t *floppy = drive->driver_data;
0578042db   Bartlomiej Zolnierkiewicz   ide: add ide_set_...
836
  	struct gendisk *disk = floppy->disk;
e996fc8ae   Bartlomiej Zolnierkiewicz   ide-floppy: add i...
837
  	int prevent = (arg && cmd != CDROMEJECT) ? 1 : 0;
ea68d270f   Borislav Petkov   ide-floppy: conve...
838

20bf7bdad   Borislav Petkov   ide-floppy: facto...
839
840
  	if (floppy->openers > 1)
  		return -EBUSY;
0578042db   Bartlomiej Zolnierkiewicz   ide: add ide_set_...
841
  	ide_set_media_lock(drive, disk, prevent);
20bf7bdad   Borislav Petkov   ide-floppy: facto...
842
843
844
  
  	if (cmd == CDROMEJECT) {
  		idefloppy_create_start_stop_cmd(pc, 2);
0578042db   Bartlomiej Zolnierkiewicz   ide: add ide_set_...
845
  		(void)ide_queue_pc_tail(drive, disk, pc);
20bf7bdad   Borislav Petkov   ide-floppy: facto...
846
847
848
849
  	}
  
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
850
851
852
853
854
855
  static int idefloppy_ioctl(struct inode *inode, struct file *file,
  			unsigned int cmd, unsigned long arg)
  {
  	struct block_device *bdev = inode->i_bdev;
  	struct ide_floppy_obj *floppy = ide_floppy_g(bdev->bd_disk);
  	ide_drive_t *drive = floppy->drive;
8e5551239   Borislav Petkov   ide-floppy: conve...
856
  	struct ide_atapi_pc pc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
857
  	void __user *argp = (void __user *)arg;
07203f647   Ondrej Zary   [PATCH] ide-flopp...
858
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
859

d56c99e26   Bartlomiej Zolnierkiewicz   ide-floppy: add i...
860
  	if (cmd == CDROMEJECT || cmd == CDROM_LOCKDOOR)
ea68d270f   Borislav Petkov   ide-floppy: conve...
861
  		return ide_floppy_lockdoor(drive, &pc, arg, cmd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
862

d56c99e26   Bartlomiej Zolnierkiewicz   ide-floppy: add i...
863
864
865
  	err = ide_floppy_format_ioctl(drive, file, cmd, argp);
  	if (err != -ENOTTY)
  		return err;
89636af25   Bartlomiej Zolnierkiewicz   ide: add support ...
866
867
868
869
870
871
872
873
  
  	/*
  	 * skip SCSI_IOCTL_SEND_COMMAND (deprecated)
  	 * and CDROM_SEND_PACKET (legacy) ioctls
  	 */
  	if (cmd != CDROM_SEND_PACKET && cmd != SCSI_IOCTL_SEND_COMMAND)
  		err = scsi_cmd_ioctl(file, bdev->bd_disk->queue,
  					bdev->bd_disk, cmd, argp);
89636af25   Bartlomiej Zolnierkiewicz   ide: add support ...
874
875
876
877
878
  
  	if (err == -ENOTTY)
  		err = generic_ide_ioctl(drive, file, bdev, cmd, arg);
  
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
879
880
881
882
883
884
  }
  
  static int idefloppy_media_changed(struct gendisk *disk)
  {
  	struct ide_floppy_obj *floppy = ide_floppy_g(disk);
  	ide_drive_t *drive = floppy->drive;
6e5fa7b88   Borislav Petkov   ide-floppy: remov...
885
  	int ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
886
887
888
889
890
891
  
  	/* do not scan partitions twice if this is a removable device */
  	if (drive->attach) {
  		drive->attach = 0;
  		return 0;
  	}
ea68d270f   Borislav Petkov   ide-floppy: conve...
892
893
  	ret = !!(drive->atapi_flags & IDE_AFLAG_MEDIA_CHANGED);
  	drive->atapi_flags &= ~IDE_AFLAG_MEDIA_CHANGED;
6e5fa7b88   Borislav Petkov   ide-floppy: remov...
894
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
895
896
897
898
899
900
901
902
903
904
  }
  
  static int idefloppy_revalidate_disk(struct gendisk *disk)
  {
  	struct ide_floppy_obj *floppy = ide_floppy_g(disk);
  	set_capacity(disk, idefloppy_capacity(floppy->drive));
  	return 0;
  }
  
  static struct block_device_operations idefloppy_ops = {
52d3ccf76   Paolo Ciarrocchi   IDE: Coding Style...
905
906
907
908
909
910
911
  	.owner			= THIS_MODULE,
  	.open			= idefloppy_open,
  	.release		= idefloppy_release,
  	.ioctl			= idefloppy_ioctl,
  	.getgeo			= idefloppy_getgeo,
  	.media_changed		= idefloppy_media_changed,
  	.revalidate_disk	= idefloppy_revalidate_disk
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
912
  };
4031bbe4b   Russell King   [PATCH] Add ide_b...
913
  static int ide_floppy_probe(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
914
915
916
917
918
919
  {
  	idefloppy_floppy_t *floppy;
  	struct gendisk *g;
  
  	if (!strstr("ide-floppy", drive->driver_req))
  		goto failed;
2a924662b   Bartlomiej Zolnierkiewicz   ide: remove needl...
920

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
921
922
  	if (drive->media != ide_floppy)
  		goto failed;
2a924662b   Bartlomiej Zolnierkiewicz   ide: remove needl...
923

51509eec3   Bartlomiej Zolnierkiewicz   ide: add ide_chec...
924
  	if (!ide_check_atapi_device(drive, DRV_NAME)) {
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
925
926
927
  		printk(KERN_ERR "ide-floppy: %s: not supported by this version"
  				" of ide-floppy
  ", drive->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
928
929
  		goto failed;
  	}
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
930
931
932
933
934
  	floppy = kzalloc(sizeof(idefloppy_floppy_t), GFP_KERNEL);
  	if (!floppy) {
  		printk(KERN_ERR "ide-floppy: %s: Can't allocate a floppy"
  				" structure
  ", drive->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
935
936
937
938
939
940
941
942
  		goto failed;
  	}
  
  	g = alloc_disk(1 << PARTN_BITS);
  	if (!g)
  		goto out_free_floppy;
  
  	ide_init_disk(g, drive);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
943
944
945
946
947
948
949
950
951
  	kref_init(&floppy->kref);
  
  	floppy->drive = drive;
  	floppy->driver = &idefloppy_driver;
  	floppy->disk = g;
  
  	g->private_data = &floppy->driver;
  
  	drive->driver_data = floppy;
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
952
  	idefloppy_setup(drive, floppy);
8604affde   Bartlomiej Zolnierkiewicz   [PATCH] convert I...
953

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
954
955
  	g->minors = 1 << PARTN_BITS;
  	g->driverfs_dev = &drive->gendev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
956
957
958
959
960
  	g->flags = drive->removable ? GENHD_FL_REMOVABLE : 0;
  	g->fops = &idefloppy_ops;
  	drive->attach = 1;
  	add_disk(g);
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
961
962
963
  out_free_floppy:
  	kfree(floppy);
  failed:
8604affde   Bartlomiej Zolnierkiewicz   [PATCH] convert I...
964
  	return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
965
  }
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
966
  static void __exit idefloppy_exit(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
967
  {
8604affde   Bartlomiej Zolnierkiewicz   [PATCH] convert I...
968
  	driver_unregister(&idefloppy_driver.gen_driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
969
  }
17514e8a6   Bartlomiej Zolnierkiewicz   [PATCH] ide: add ...
970
  static int __init idefloppy_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
971
972
973
  {
  	printk("ide-floppy driver " IDEFLOPPY_VERSION "
  ");
8604affde   Bartlomiej Zolnierkiewicz   [PATCH] convert I...
974
  	return driver_register(&idefloppy_driver.gen_driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
975
  }
263756ec2   Kay Sievers   [PATCH] ide: MODA...
976
  MODULE_ALIAS("ide:*m-floppy*");
0127854d7   Bartlomiej Zolnierkiewicz   ide-floppy: move ...
977
  MODULE_ALIAS("ide-floppy");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
978
979
980
  module_init(idefloppy_init);
  module_exit(idefloppy_exit);
  MODULE_LICENSE("GPL");
0571c7a4f   Borislav Petkov   ide-floppy: fix m...
981
  MODULE_DESCRIPTION("ATAPI FLOPPY Driver");