Commit 3eb76c1ccde496c3c0bfda23d1c803e40b762ce6
Committed by
Bartlomiej Zolnierkiewicz
1 parent
041b62374c
Exists in
master
and in
4 other branches
ide-floppy: do not map dataless cmds to an sg
since it fails the virt_to_page() translation check with DEBUG_VIRTUAL enabled. Signed-off-by: Borislav Petkov <petkovbb@gmail.com> [bart: backport to Linus' tree] Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Showing 2 changed files with 16 additions and 2 deletions Inline Diff
drivers/ide/ide-atapi.c
1 | /* | 1 | /* |
2 | * ATAPI support. | 2 | * ATAPI support. |
3 | */ | 3 | */ |
4 | 4 | ||
5 | #include <linux/kernel.h> | 5 | #include <linux/kernel.h> |
6 | #include <linux/cdrom.h> | 6 | #include <linux/cdrom.h> |
7 | #include <linux/delay.h> | 7 | #include <linux/delay.h> |
8 | #include <linux/ide.h> | 8 | #include <linux/ide.h> |
9 | #include <scsi/scsi.h> | 9 | #include <scsi/scsi.h> |
10 | 10 | ||
11 | #ifdef DEBUG | 11 | #ifdef DEBUG |
12 | #define debug_log(fmt, args...) \ | 12 | #define debug_log(fmt, args...) \ |
13 | printk(KERN_INFO "ide: " fmt, ## args) | 13 | printk(KERN_INFO "ide: " fmt, ## args) |
14 | #else | 14 | #else |
15 | #define debug_log(fmt, args...) do {} while (0) | 15 | #define debug_log(fmt, args...) do {} while (0) |
16 | #endif | 16 | #endif |
17 | 17 | ||
18 | #define ATAPI_MIN_CDB_BYTES 12 | 18 | #define ATAPI_MIN_CDB_BYTES 12 |
19 | 19 | ||
20 | static inline int dev_is_idecd(ide_drive_t *drive) | 20 | static inline int dev_is_idecd(ide_drive_t *drive) |
21 | { | 21 | { |
22 | return drive->media == ide_cdrom || drive->media == ide_optical; | 22 | return drive->media == ide_cdrom || drive->media == ide_optical; |
23 | } | 23 | } |
24 | 24 | ||
25 | /* | 25 | /* |
26 | * Check whether we can support a device, | 26 | * Check whether we can support a device, |
27 | * based on the ATAPI IDENTIFY command results. | 27 | * based on the ATAPI IDENTIFY command results. |
28 | */ | 28 | */ |
29 | int ide_check_atapi_device(ide_drive_t *drive, const char *s) | 29 | int ide_check_atapi_device(ide_drive_t *drive, const char *s) |
30 | { | 30 | { |
31 | u16 *id = drive->id; | 31 | u16 *id = drive->id; |
32 | u8 gcw[2], protocol, device_type, removable, drq_type, packet_size; | 32 | u8 gcw[2], protocol, device_type, removable, drq_type, packet_size; |
33 | 33 | ||
34 | *((u16 *)&gcw) = id[ATA_ID_CONFIG]; | 34 | *((u16 *)&gcw) = id[ATA_ID_CONFIG]; |
35 | 35 | ||
36 | protocol = (gcw[1] & 0xC0) >> 6; | 36 | protocol = (gcw[1] & 0xC0) >> 6; |
37 | device_type = gcw[1] & 0x1F; | 37 | device_type = gcw[1] & 0x1F; |
38 | removable = (gcw[0] & 0x80) >> 7; | 38 | removable = (gcw[0] & 0x80) >> 7; |
39 | drq_type = (gcw[0] & 0x60) >> 5; | 39 | drq_type = (gcw[0] & 0x60) >> 5; |
40 | packet_size = gcw[0] & 0x03; | 40 | packet_size = gcw[0] & 0x03; |
41 | 41 | ||
42 | #ifdef CONFIG_PPC | 42 | #ifdef CONFIG_PPC |
43 | /* kludge for Apple PowerBook internal zip */ | 43 | /* kludge for Apple PowerBook internal zip */ |
44 | if (drive->media == ide_floppy && device_type == 5 && | 44 | if (drive->media == ide_floppy && device_type == 5 && |
45 | !strstr((char *)&id[ATA_ID_PROD], "CD-ROM") && | 45 | !strstr((char *)&id[ATA_ID_PROD], "CD-ROM") && |
46 | strstr((char *)&id[ATA_ID_PROD], "ZIP")) | 46 | strstr((char *)&id[ATA_ID_PROD], "ZIP")) |
47 | device_type = 0; | 47 | device_type = 0; |
48 | #endif | 48 | #endif |
49 | 49 | ||
50 | if (protocol != 2) | 50 | if (protocol != 2) |
51 | printk(KERN_ERR "%s: %s: protocol (0x%02x) is not ATAPI\n", | 51 | printk(KERN_ERR "%s: %s: protocol (0x%02x) is not ATAPI\n", |
52 | s, drive->name, protocol); | 52 | s, drive->name, protocol); |
53 | else if ((drive->media == ide_floppy && device_type != 0) || | 53 | else if ((drive->media == ide_floppy && device_type != 0) || |
54 | (drive->media == ide_tape && device_type != 1)) | 54 | (drive->media == ide_tape && device_type != 1)) |
55 | printk(KERN_ERR "%s: %s: invalid device type (0x%02x)\n", | 55 | printk(KERN_ERR "%s: %s: invalid device type (0x%02x)\n", |
56 | s, drive->name, device_type); | 56 | s, drive->name, device_type); |
57 | else if (removable == 0) | 57 | else if (removable == 0) |
58 | printk(KERN_ERR "%s: %s: the removable flag is not set\n", | 58 | printk(KERN_ERR "%s: %s: the removable flag is not set\n", |
59 | s, drive->name); | 59 | s, drive->name); |
60 | else if (drive->media == ide_floppy && drq_type == 3) | 60 | else if (drive->media == ide_floppy && drq_type == 3) |
61 | printk(KERN_ERR "%s: %s: sorry, DRQ type (0x%02x) not " | 61 | printk(KERN_ERR "%s: %s: sorry, DRQ type (0x%02x) not " |
62 | "supported\n", s, drive->name, drq_type); | 62 | "supported\n", s, drive->name, drq_type); |
63 | else if (packet_size != 0) | 63 | else if (packet_size != 0) |
64 | printk(KERN_ERR "%s: %s: packet size (0x%02x) is not 12 " | 64 | printk(KERN_ERR "%s: %s: packet size (0x%02x) is not 12 " |
65 | "bytes\n", s, drive->name, packet_size); | 65 | "bytes\n", s, drive->name, packet_size); |
66 | else | 66 | else |
67 | return 1; | 67 | return 1; |
68 | return 0; | 68 | return 0; |
69 | } | 69 | } |
70 | EXPORT_SYMBOL_GPL(ide_check_atapi_device); | 70 | EXPORT_SYMBOL_GPL(ide_check_atapi_device); |
71 | 71 | ||
72 | /* PIO data transfer routine using the scatter gather table. */ | 72 | /* PIO data transfer routine using the scatter gather table. */ |
73 | int ide_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, | 73 | int ide_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, |
74 | unsigned int bcount, int write) | 74 | unsigned int bcount, int write) |
75 | { | 75 | { |
76 | ide_hwif_t *hwif = drive->hwif; | 76 | ide_hwif_t *hwif = drive->hwif; |
77 | const struct ide_tp_ops *tp_ops = hwif->tp_ops; | 77 | const struct ide_tp_ops *tp_ops = hwif->tp_ops; |
78 | xfer_func_t *xf = write ? tp_ops->output_data : tp_ops->input_data; | 78 | xfer_func_t *xf = write ? tp_ops->output_data : tp_ops->input_data; |
79 | struct scatterlist *sg = pc->sg; | 79 | struct scatterlist *sg = pc->sg; |
80 | char *buf; | 80 | char *buf; |
81 | int count, done = 0; | 81 | int count, done = 0; |
82 | 82 | ||
83 | while (bcount) { | 83 | while (bcount) { |
84 | count = min(sg->length - pc->b_count, bcount); | 84 | count = min(sg->length - pc->b_count, bcount); |
85 | 85 | ||
86 | if (PageHighMem(sg_page(sg))) { | 86 | if (PageHighMem(sg_page(sg))) { |
87 | unsigned long flags; | 87 | unsigned long flags; |
88 | 88 | ||
89 | local_irq_save(flags); | 89 | local_irq_save(flags); |
90 | buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset; | 90 | buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset; |
91 | xf(drive, NULL, buf + pc->b_count, count); | 91 | xf(drive, NULL, buf + pc->b_count, count); |
92 | kunmap_atomic(buf - sg->offset, KM_IRQ0); | 92 | kunmap_atomic(buf - sg->offset, KM_IRQ0); |
93 | local_irq_restore(flags); | 93 | local_irq_restore(flags); |
94 | } else { | 94 | } else { |
95 | buf = sg_virt(sg); | 95 | buf = sg_virt(sg); |
96 | xf(drive, NULL, buf + pc->b_count, count); | 96 | xf(drive, NULL, buf + pc->b_count, count); |
97 | } | 97 | } |
98 | 98 | ||
99 | bcount -= count; | 99 | bcount -= count; |
100 | pc->b_count += count; | 100 | pc->b_count += count; |
101 | done += count; | 101 | done += count; |
102 | 102 | ||
103 | if (pc->b_count == sg->length) { | 103 | if (pc->b_count == sg->length) { |
104 | if (!--pc->sg_cnt) | 104 | if (!--pc->sg_cnt) |
105 | break; | 105 | break; |
106 | pc->sg = sg = sg_next(sg); | 106 | pc->sg = sg = sg_next(sg); |
107 | pc->b_count = 0; | 107 | pc->b_count = 0; |
108 | } | 108 | } |
109 | } | 109 | } |
110 | 110 | ||
111 | if (bcount) { | 111 | if (bcount) { |
112 | printk(KERN_ERR "%s: %d leftover bytes, %s\n", drive->name, | 112 | printk(KERN_ERR "%s: %d leftover bytes, %s\n", drive->name, |
113 | bcount, write ? "padding with zeros" | 113 | bcount, write ? "padding with zeros" |
114 | : "discarding data"); | 114 | : "discarding data"); |
115 | ide_pad_transfer(drive, write, bcount); | 115 | ide_pad_transfer(drive, write, bcount); |
116 | } | 116 | } |
117 | 117 | ||
118 | return done; | 118 | return done; |
119 | } | 119 | } |
120 | EXPORT_SYMBOL_GPL(ide_io_buffers); | 120 | EXPORT_SYMBOL_GPL(ide_io_buffers); |
121 | 121 | ||
122 | void ide_init_pc(struct ide_atapi_pc *pc) | 122 | void ide_init_pc(struct ide_atapi_pc *pc) |
123 | { | 123 | { |
124 | memset(pc, 0, sizeof(*pc)); | 124 | memset(pc, 0, sizeof(*pc)); |
125 | pc->buf = pc->pc_buf; | 125 | pc->buf = pc->pc_buf; |
126 | pc->buf_size = IDE_PC_BUFFER_SIZE; | 126 | pc->buf_size = IDE_PC_BUFFER_SIZE; |
127 | } | 127 | } |
128 | EXPORT_SYMBOL_GPL(ide_init_pc); | 128 | EXPORT_SYMBOL_GPL(ide_init_pc); |
129 | 129 | ||
130 | /* | 130 | /* |
131 | * Generate a new packet command request in front of the request queue, before | 131 | * Generate a new packet command request in front of the request queue, before |
132 | * the current request, so that it will be processed immediately, on the next | 132 | * the current request, so that it will be processed immediately, on the next |
133 | * pass through the driver. | 133 | * pass through the driver. |
134 | */ | 134 | */ |
135 | static void ide_queue_pc_head(ide_drive_t *drive, struct gendisk *disk, | 135 | static void ide_queue_pc_head(ide_drive_t *drive, struct gendisk *disk, |
136 | struct ide_atapi_pc *pc, struct request *rq) | 136 | struct ide_atapi_pc *pc, struct request *rq) |
137 | { | 137 | { |
138 | blk_rq_init(NULL, rq); | 138 | blk_rq_init(NULL, rq); |
139 | rq->cmd_type = REQ_TYPE_SPECIAL; | 139 | rq->cmd_type = REQ_TYPE_SPECIAL; |
140 | rq->cmd_flags |= REQ_PREEMPT; | 140 | rq->cmd_flags |= REQ_PREEMPT; |
141 | rq->buffer = (char *)pc; | 141 | rq->buffer = (char *)pc; |
142 | rq->rq_disk = disk; | 142 | rq->rq_disk = disk; |
143 | |||
144 | if (pc->req_xfer) { | ||
145 | rq->data = pc->buf; | ||
146 | rq->data_len = pc->req_xfer; | ||
147 | } | ||
148 | |||
143 | memcpy(rq->cmd, pc->c, 12); | 149 | memcpy(rq->cmd, pc->c, 12); |
144 | if (drive->media == ide_tape) | 150 | if (drive->media == ide_tape) |
145 | rq->cmd[13] = REQ_IDETAPE_PC1; | 151 | rq->cmd[13] = REQ_IDETAPE_PC1; |
146 | ide_do_drive_cmd(drive, rq); | 152 | ide_do_drive_cmd(drive, rq); |
147 | } | 153 | } |
148 | 154 | ||
149 | /* | 155 | /* |
150 | * Add a special packet command request to the tail of the request queue, | 156 | * Add a special packet command request to the tail of the request queue, |
151 | * and wait for it to be serviced. | 157 | * and wait for it to be serviced. |
152 | */ | 158 | */ |
153 | int ide_queue_pc_tail(ide_drive_t *drive, struct gendisk *disk, | 159 | int ide_queue_pc_tail(ide_drive_t *drive, struct gendisk *disk, |
154 | struct ide_atapi_pc *pc) | 160 | struct ide_atapi_pc *pc) |
155 | { | 161 | { |
156 | struct request *rq; | 162 | struct request *rq; |
157 | int error; | 163 | int error; |
158 | 164 | ||
159 | rq = blk_get_request(drive->queue, READ, __GFP_WAIT); | 165 | rq = blk_get_request(drive->queue, READ, __GFP_WAIT); |
160 | rq->cmd_type = REQ_TYPE_SPECIAL; | 166 | rq->cmd_type = REQ_TYPE_SPECIAL; |
161 | rq->buffer = (char *)pc; | 167 | rq->buffer = (char *)pc; |
168 | |||
169 | if (pc->req_xfer) { | ||
170 | rq->data = pc->buf; | ||
171 | rq->data_len = pc->req_xfer; | ||
172 | } | ||
173 | |||
162 | memcpy(rq->cmd, pc->c, 12); | 174 | memcpy(rq->cmd, pc->c, 12); |
163 | if (drive->media == ide_tape) | 175 | if (drive->media == ide_tape) |
164 | rq->cmd[13] = REQ_IDETAPE_PC1; | 176 | rq->cmd[13] = REQ_IDETAPE_PC1; |
165 | error = blk_execute_rq(drive->queue, disk, rq, 0); | 177 | error = blk_execute_rq(drive->queue, disk, rq, 0); |
166 | blk_put_request(rq); | 178 | blk_put_request(rq); |
167 | 179 | ||
168 | return error; | 180 | return error; |
169 | } | 181 | } |
170 | EXPORT_SYMBOL_GPL(ide_queue_pc_tail); | 182 | EXPORT_SYMBOL_GPL(ide_queue_pc_tail); |
171 | 183 | ||
172 | int ide_do_test_unit_ready(ide_drive_t *drive, struct gendisk *disk) | 184 | int ide_do_test_unit_ready(ide_drive_t *drive, struct gendisk *disk) |
173 | { | 185 | { |
174 | struct ide_atapi_pc pc; | 186 | struct ide_atapi_pc pc; |
175 | 187 | ||
176 | ide_init_pc(&pc); | 188 | ide_init_pc(&pc); |
177 | pc.c[0] = TEST_UNIT_READY; | 189 | pc.c[0] = TEST_UNIT_READY; |
178 | 190 | ||
179 | return ide_queue_pc_tail(drive, disk, &pc); | 191 | return ide_queue_pc_tail(drive, disk, &pc); |
180 | } | 192 | } |
181 | EXPORT_SYMBOL_GPL(ide_do_test_unit_ready); | 193 | EXPORT_SYMBOL_GPL(ide_do_test_unit_ready); |
182 | 194 | ||
183 | int ide_do_start_stop(ide_drive_t *drive, struct gendisk *disk, int start) | 195 | int ide_do_start_stop(ide_drive_t *drive, struct gendisk *disk, int start) |
184 | { | 196 | { |
185 | struct ide_atapi_pc pc; | 197 | struct ide_atapi_pc pc; |
186 | 198 | ||
187 | ide_init_pc(&pc); | 199 | ide_init_pc(&pc); |
188 | pc.c[0] = START_STOP; | 200 | pc.c[0] = START_STOP; |
189 | pc.c[4] = start; | 201 | pc.c[4] = start; |
190 | 202 | ||
191 | if (drive->media == ide_tape) | 203 | if (drive->media == ide_tape) |
192 | pc.flags |= PC_FLAG_WAIT_FOR_DSC; | 204 | pc.flags |= PC_FLAG_WAIT_FOR_DSC; |
193 | 205 | ||
194 | return ide_queue_pc_tail(drive, disk, &pc); | 206 | return ide_queue_pc_tail(drive, disk, &pc); |
195 | } | 207 | } |
196 | EXPORT_SYMBOL_GPL(ide_do_start_stop); | 208 | EXPORT_SYMBOL_GPL(ide_do_start_stop); |
197 | 209 | ||
198 | int ide_set_media_lock(ide_drive_t *drive, struct gendisk *disk, int on) | 210 | int ide_set_media_lock(ide_drive_t *drive, struct gendisk *disk, int on) |
199 | { | 211 | { |
200 | struct ide_atapi_pc pc; | 212 | struct ide_atapi_pc pc; |
201 | 213 | ||
202 | if ((drive->dev_flags & IDE_DFLAG_DOORLOCKING) == 0) | 214 | if ((drive->dev_flags & IDE_DFLAG_DOORLOCKING) == 0) |
203 | return 0; | 215 | return 0; |
204 | 216 | ||
205 | ide_init_pc(&pc); | 217 | ide_init_pc(&pc); |
206 | pc.c[0] = ALLOW_MEDIUM_REMOVAL; | 218 | pc.c[0] = ALLOW_MEDIUM_REMOVAL; |
207 | pc.c[4] = on; | 219 | pc.c[4] = on; |
208 | 220 | ||
209 | return ide_queue_pc_tail(drive, disk, &pc); | 221 | return ide_queue_pc_tail(drive, disk, &pc); |
210 | } | 222 | } |
211 | EXPORT_SYMBOL_GPL(ide_set_media_lock); | 223 | EXPORT_SYMBOL_GPL(ide_set_media_lock); |
212 | 224 | ||
213 | void ide_create_request_sense_cmd(ide_drive_t *drive, struct ide_atapi_pc *pc) | 225 | void ide_create_request_sense_cmd(ide_drive_t *drive, struct ide_atapi_pc *pc) |
214 | { | 226 | { |
215 | ide_init_pc(pc); | 227 | ide_init_pc(pc); |
216 | pc->c[0] = REQUEST_SENSE; | 228 | pc->c[0] = REQUEST_SENSE; |
217 | if (drive->media == ide_floppy) { | 229 | if (drive->media == ide_floppy) { |
218 | pc->c[4] = 255; | 230 | pc->c[4] = 255; |
219 | pc->req_xfer = 18; | 231 | pc->req_xfer = 18; |
220 | } else { | 232 | } else { |
221 | pc->c[4] = 20; | 233 | pc->c[4] = 20; |
222 | pc->req_xfer = 20; | 234 | pc->req_xfer = 20; |
223 | } | 235 | } |
224 | } | 236 | } |
225 | EXPORT_SYMBOL_GPL(ide_create_request_sense_cmd); | 237 | EXPORT_SYMBOL_GPL(ide_create_request_sense_cmd); |
226 | 238 | ||
227 | /* | 239 | /* |
228 | * Called when an error was detected during the last packet command. | 240 | * Called when an error was detected during the last packet command. |
229 | * We queue a request sense packet command in the head of the request list. | 241 | * We queue a request sense packet command in the head of the request list. |
230 | */ | 242 | */ |
231 | void ide_retry_pc(ide_drive_t *drive, struct gendisk *disk) | 243 | void ide_retry_pc(ide_drive_t *drive, struct gendisk *disk) |
232 | { | 244 | { |
233 | struct request *rq = &drive->request_sense_rq; | 245 | struct request *rq = &drive->request_sense_rq; |
234 | struct ide_atapi_pc *pc = &drive->request_sense_pc; | 246 | struct ide_atapi_pc *pc = &drive->request_sense_pc; |
235 | 247 | ||
236 | (void)ide_read_error(drive); | 248 | (void)ide_read_error(drive); |
237 | ide_create_request_sense_cmd(drive, pc); | 249 | ide_create_request_sense_cmd(drive, pc); |
238 | if (drive->media == ide_tape) | 250 | if (drive->media == ide_tape) |
239 | set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags); | 251 | set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags); |
240 | ide_queue_pc_head(drive, disk, pc, rq); | 252 | ide_queue_pc_head(drive, disk, pc, rq); |
241 | } | 253 | } |
242 | EXPORT_SYMBOL_GPL(ide_retry_pc); | 254 | EXPORT_SYMBOL_GPL(ide_retry_pc); |
243 | 255 | ||
244 | int ide_cd_expiry(ide_drive_t *drive) | 256 | int ide_cd_expiry(ide_drive_t *drive) |
245 | { | 257 | { |
246 | struct request *rq = drive->hwif->rq; | 258 | struct request *rq = drive->hwif->rq; |
247 | unsigned long wait = 0; | 259 | unsigned long wait = 0; |
248 | 260 | ||
249 | debug_log("%s: rq->cmd[0]: 0x%x\n", __func__, rq->cmd[0]); | 261 | debug_log("%s: rq->cmd[0]: 0x%x\n", __func__, rq->cmd[0]); |
250 | 262 | ||
251 | /* | 263 | /* |
252 | * Some commands are *slow* and normally take a long time to complete. | 264 | * Some commands are *slow* and normally take a long time to complete. |
253 | * Usually we can use the ATAPI "disconnect" to bypass this, but not all | 265 | * Usually we can use the ATAPI "disconnect" to bypass this, but not all |
254 | * commands/drives support that. Let ide_timer_expiry keep polling us | 266 | * commands/drives support that. Let ide_timer_expiry keep polling us |
255 | * for these. | 267 | * for these. |
256 | */ | 268 | */ |
257 | switch (rq->cmd[0]) { | 269 | switch (rq->cmd[0]) { |
258 | case GPCMD_BLANK: | 270 | case GPCMD_BLANK: |
259 | case GPCMD_FORMAT_UNIT: | 271 | case GPCMD_FORMAT_UNIT: |
260 | case GPCMD_RESERVE_RZONE_TRACK: | 272 | case GPCMD_RESERVE_RZONE_TRACK: |
261 | case GPCMD_CLOSE_TRACK: | 273 | case GPCMD_CLOSE_TRACK: |
262 | case GPCMD_FLUSH_CACHE: | 274 | case GPCMD_FLUSH_CACHE: |
263 | wait = ATAPI_WAIT_PC; | 275 | wait = ATAPI_WAIT_PC; |
264 | break; | 276 | break; |
265 | default: | 277 | default: |
266 | if (!(rq->cmd_flags & REQ_QUIET)) | 278 | if (!(rq->cmd_flags & REQ_QUIET)) |
267 | printk(KERN_INFO "cmd 0x%x timed out\n", | 279 | printk(KERN_INFO "cmd 0x%x timed out\n", |
268 | rq->cmd[0]); | 280 | rq->cmd[0]); |
269 | wait = 0; | 281 | wait = 0; |
270 | break; | 282 | break; |
271 | } | 283 | } |
272 | return wait; | 284 | return wait; |
273 | } | 285 | } |
274 | EXPORT_SYMBOL_GPL(ide_cd_expiry); | 286 | EXPORT_SYMBOL_GPL(ide_cd_expiry); |
275 | 287 | ||
276 | int ide_cd_get_xferlen(struct request *rq) | 288 | int ide_cd_get_xferlen(struct request *rq) |
277 | { | 289 | { |
278 | if (blk_fs_request(rq)) | 290 | if (blk_fs_request(rq)) |
279 | return 32768; | 291 | return 32768; |
280 | else if (blk_sense_request(rq) || blk_pc_request(rq) || | 292 | else if (blk_sense_request(rq) || blk_pc_request(rq) || |
281 | rq->cmd_type == REQ_TYPE_ATA_PC) | 293 | rq->cmd_type == REQ_TYPE_ATA_PC) |
282 | return rq->data_len; | 294 | return rq->data_len; |
283 | else | 295 | else |
284 | return 0; | 296 | return 0; |
285 | } | 297 | } |
286 | EXPORT_SYMBOL_GPL(ide_cd_get_xferlen); | 298 | EXPORT_SYMBOL_GPL(ide_cd_get_xferlen); |
287 | 299 | ||
288 | /* | 300 | /* |
289 | * This is the usual interrupt handler which will be called during a packet | 301 | * This is the usual interrupt handler which will be called during a packet |
290 | * command. We will transfer some of the data (as requested by the drive) | 302 | * command. We will transfer some of the data (as requested by the drive) |
291 | * and will re-point interrupt handler to us. | 303 | * and will re-point interrupt handler to us. |
292 | */ | 304 | */ |
293 | static ide_startstop_t ide_pc_intr(ide_drive_t *drive) | 305 | static ide_startstop_t ide_pc_intr(ide_drive_t *drive) |
294 | { | 306 | { |
295 | struct ide_atapi_pc *pc = drive->pc; | 307 | struct ide_atapi_pc *pc = drive->pc; |
296 | ide_hwif_t *hwif = drive->hwif; | 308 | ide_hwif_t *hwif = drive->hwif; |
297 | struct request *rq = hwif->rq; | 309 | struct request *rq = hwif->rq; |
298 | const struct ide_tp_ops *tp_ops = hwif->tp_ops; | 310 | const struct ide_tp_ops *tp_ops = hwif->tp_ops; |
299 | xfer_func_t *xferfunc; | 311 | xfer_func_t *xferfunc; |
300 | unsigned int timeout, temp; | 312 | unsigned int timeout, temp; |
301 | u16 bcount; | 313 | u16 bcount; |
302 | u8 stat, ireason, dsc = 0; | 314 | u8 stat, ireason, dsc = 0; |
303 | 315 | ||
304 | debug_log("Enter %s - interrupt handler\n", __func__); | 316 | debug_log("Enter %s - interrupt handler\n", __func__); |
305 | 317 | ||
306 | timeout = (drive->media == ide_floppy) ? WAIT_FLOPPY_CMD | 318 | timeout = (drive->media == ide_floppy) ? WAIT_FLOPPY_CMD |
307 | : WAIT_TAPE_CMD; | 319 | : WAIT_TAPE_CMD; |
308 | 320 | ||
309 | if (pc->flags & PC_FLAG_TIMEDOUT) { | 321 | if (pc->flags & PC_FLAG_TIMEDOUT) { |
310 | drive->pc_callback(drive, 0); | 322 | drive->pc_callback(drive, 0); |
311 | return ide_stopped; | 323 | return ide_stopped; |
312 | } | 324 | } |
313 | 325 | ||
314 | /* Clear the interrupt */ | 326 | /* Clear the interrupt */ |
315 | stat = tp_ops->read_status(hwif); | 327 | stat = tp_ops->read_status(hwif); |
316 | 328 | ||
317 | if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) { | 329 | if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) { |
318 | if (hwif->dma_ops->dma_end(drive) || | 330 | if (hwif->dma_ops->dma_end(drive) || |
319 | (drive->media == ide_tape && (stat & ATA_ERR))) { | 331 | (drive->media == ide_tape && (stat & ATA_ERR))) { |
320 | if (drive->media == ide_floppy) | 332 | if (drive->media == ide_floppy) |
321 | printk(KERN_ERR "%s: DMA %s error\n", | 333 | printk(KERN_ERR "%s: DMA %s error\n", |
322 | drive->name, rq_data_dir(pc->rq) | 334 | drive->name, rq_data_dir(pc->rq) |
323 | ? "write" : "read"); | 335 | ? "write" : "read"); |
324 | pc->flags |= PC_FLAG_DMA_ERROR; | 336 | pc->flags |= PC_FLAG_DMA_ERROR; |
325 | } else { | 337 | } else { |
326 | pc->xferred = pc->req_xfer; | 338 | pc->xferred = pc->req_xfer; |
327 | if (drive->pc_update_buffers) | 339 | if (drive->pc_update_buffers) |
328 | drive->pc_update_buffers(drive, pc); | 340 | drive->pc_update_buffers(drive, pc); |
329 | } | 341 | } |
330 | debug_log("%s: DMA finished\n", drive->name); | 342 | debug_log("%s: DMA finished\n", drive->name); |
331 | } | 343 | } |
332 | 344 | ||
333 | /* No more interrupts */ | 345 | /* No more interrupts */ |
334 | if ((stat & ATA_DRQ) == 0) { | 346 | if ((stat & ATA_DRQ) == 0) { |
335 | debug_log("Packet command completed, %d bytes transferred\n", | 347 | debug_log("Packet command completed, %d bytes transferred\n", |
336 | pc->xferred); | 348 | pc->xferred); |
337 | 349 | ||
338 | pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS; | 350 | pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS; |
339 | 351 | ||
340 | local_irq_enable_in_hardirq(); | 352 | local_irq_enable_in_hardirq(); |
341 | 353 | ||
342 | if (drive->media == ide_tape && | 354 | if (drive->media == ide_tape && |
343 | (stat & ATA_ERR) && rq->cmd[0] == REQUEST_SENSE) | 355 | (stat & ATA_ERR) && rq->cmd[0] == REQUEST_SENSE) |
344 | stat &= ~ATA_ERR; | 356 | stat &= ~ATA_ERR; |
345 | 357 | ||
346 | if ((stat & ATA_ERR) || (pc->flags & PC_FLAG_DMA_ERROR)) { | 358 | if ((stat & ATA_ERR) || (pc->flags & PC_FLAG_DMA_ERROR)) { |
347 | /* Error detected */ | 359 | /* Error detected */ |
348 | debug_log("%s: I/O error\n", drive->name); | 360 | debug_log("%s: I/O error\n", drive->name); |
349 | 361 | ||
350 | if (drive->media != ide_tape) | 362 | if (drive->media != ide_tape) |
351 | pc->rq->errors++; | 363 | pc->rq->errors++; |
352 | 364 | ||
353 | if (rq->cmd[0] == REQUEST_SENSE) { | 365 | if (rq->cmd[0] == REQUEST_SENSE) { |
354 | printk(KERN_ERR "%s: I/O error in request sense" | 366 | printk(KERN_ERR "%s: I/O error in request sense" |
355 | " command\n", drive->name); | 367 | " command\n", drive->name); |
356 | return ide_do_reset(drive); | 368 | return ide_do_reset(drive); |
357 | } | 369 | } |
358 | 370 | ||
359 | debug_log("[cmd %x]: check condition\n", rq->cmd[0]); | 371 | debug_log("[cmd %x]: check condition\n", rq->cmd[0]); |
360 | 372 | ||
361 | /* Retry operation */ | 373 | /* Retry operation */ |
362 | ide_retry_pc(drive, rq->rq_disk); | 374 | ide_retry_pc(drive, rq->rq_disk); |
363 | 375 | ||
364 | /* queued, but not started */ | 376 | /* queued, but not started */ |
365 | return ide_stopped; | 377 | return ide_stopped; |
366 | } | 378 | } |
367 | pc->error = 0; | 379 | pc->error = 0; |
368 | 380 | ||
369 | if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) && (stat & ATA_DSC) == 0) | 381 | if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) && (stat & ATA_DSC) == 0) |
370 | dsc = 1; | 382 | dsc = 1; |
371 | 383 | ||
372 | /* Command finished - Call the callback function */ | 384 | /* Command finished - Call the callback function */ |
373 | drive->pc_callback(drive, dsc); | 385 | drive->pc_callback(drive, dsc); |
374 | 386 | ||
375 | return ide_stopped; | 387 | return ide_stopped; |
376 | } | 388 | } |
377 | 389 | ||
378 | if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) { | 390 | if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) { |
379 | pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS; | 391 | pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS; |
380 | printk(KERN_ERR "%s: The device wants to issue more interrupts " | 392 | printk(KERN_ERR "%s: The device wants to issue more interrupts " |
381 | "in DMA mode\n", drive->name); | 393 | "in DMA mode\n", drive->name); |
382 | ide_dma_off(drive); | 394 | ide_dma_off(drive); |
383 | return ide_do_reset(drive); | 395 | return ide_do_reset(drive); |
384 | } | 396 | } |
385 | 397 | ||
386 | /* Get the number of bytes to transfer on this interrupt. */ | 398 | /* Get the number of bytes to transfer on this interrupt. */ |
387 | ide_read_bcount_and_ireason(drive, &bcount, &ireason); | 399 | ide_read_bcount_and_ireason(drive, &bcount, &ireason); |
388 | 400 | ||
389 | if (ireason & ATAPI_COD) { | 401 | if (ireason & ATAPI_COD) { |
390 | printk(KERN_ERR "%s: CoD != 0 in %s\n", drive->name, __func__); | 402 | printk(KERN_ERR "%s: CoD != 0 in %s\n", drive->name, __func__); |
391 | return ide_do_reset(drive); | 403 | return ide_do_reset(drive); |
392 | } | 404 | } |
393 | 405 | ||
394 | if (((ireason & ATAPI_IO) == ATAPI_IO) == | 406 | if (((ireason & ATAPI_IO) == ATAPI_IO) == |
395 | !!(pc->flags & PC_FLAG_WRITING)) { | 407 | !!(pc->flags & PC_FLAG_WRITING)) { |
396 | /* Hopefully, we will never get here */ | 408 | /* Hopefully, we will never get here */ |
397 | printk(KERN_ERR "%s: We wanted to %s, but the device wants us " | 409 | printk(KERN_ERR "%s: We wanted to %s, but the device wants us " |
398 | "to %s!\n", drive->name, | 410 | "to %s!\n", drive->name, |
399 | (ireason & ATAPI_IO) ? "Write" : "Read", | 411 | (ireason & ATAPI_IO) ? "Write" : "Read", |
400 | (ireason & ATAPI_IO) ? "Read" : "Write"); | 412 | (ireason & ATAPI_IO) ? "Read" : "Write"); |
401 | return ide_do_reset(drive); | 413 | return ide_do_reset(drive); |
402 | } | 414 | } |
403 | 415 | ||
404 | if (!(pc->flags & PC_FLAG_WRITING)) { | 416 | if (!(pc->flags & PC_FLAG_WRITING)) { |
405 | /* Reading - Check that we have enough space */ | 417 | /* Reading - Check that we have enough space */ |
406 | temp = pc->xferred + bcount; | 418 | temp = pc->xferred + bcount; |
407 | if (temp > pc->req_xfer) { | 419 | if (temp > pc->req_xfer) { |
408 | if (temp > pc->buf_size) { | 420 | if (temp > pc->buf_size) { |
409 | printk(KERN_ERR "%s: The device wants to send " | 421 | printk(KERN_ERR "%s: The device wants to send " |
410 | "us more data than expected - " | 422 | "us more data than expected - " |
411 | "discarding data\n", | 423 | "discarding data\n", |
412 | drive->name); | 424 | drive->name); |
413 | 425 | ||
414 | ide_pad_transfer(drive, 0, bcount); | 426 | ide_pad_transfer(drive, 0, bcount); |
415 | goto next_irq; | 427 | goto next_irq; |
416 | } | 428 | } |
417 | debug_log("The device wants to send us more data than " | 429 | debug_log("The device wants to send us more data than " |
418 | "expected - allowing transfer\n"); | 430 | "expected - allowing transfer\n"); |
419 | } | 431 | } |
420 | xferfunc = tp_ops->input_data; | 432 | xferfunc = tp_ops->input_data; |
421 | } else | 433 | } else |
422 | xferfunc = tp_ops->output_data; | 434 | xferfunc = tp_ops->output_data; |
423 | 435 | ||
424 | if ((drive->media == ide_floppy && !pc->buf) || | 436 | if ((drive->media == ide_floppy && !pc->buf) || |
425 | (drive->media == ide_tape && pc->bh)) { | 437 | (drive->media == ide_tape && pc->bh)) { |
426 | int done = drive->pc_io_buffers(drive, pc, bcount, | 438 | int done = drive->pc_io_buffers(drive, pc, bcount, |
427 | !!(pc->flags & PC_FLAG_WRITING)); | 439 | !!(pc->flags & PC_FLAG_WRITING)); |
428 | 440 | ||
429 | /* FIXME: don't do partial completions */ | 441 | /* FIXME: don't do partial completions */ |
430 | if (drive->media == ide_floppy) | 442 | if (drive->media == ide_floppy) |
431 | ide_end_request(drive, 1, done >> 9); | 443 | ide_end_request(drive, 1, done >> 9); |
432 | } else | 444 | } else |
433 | xferfunc(drive, NULL, pc->cur_pos, bcount); | 445 | xferfunc(drive, NULL, pc->cur_pos, bcount); |
434 | 446 | ||
435 | /* Update the current position */ | 447 | /* Update the current position */ |
436 | pc->xferred += bcount; | 448 | pc->xferred += bcount; |
437 | pc->cur_pos += bcount; | 449 | pc->cur_pos += bcount; |
438 | 450 | ||
439 | debug_log("[cmd %x] transferred %d bytes on that intr.\n", | 451 | debug_log("[cmd %x] transferred %d bytes on that intr.\n", |
440 | rq->cmd[0], bcount); | 452 | rq->cmd[0], bcount); |
441 | next_irq: | 453 | next_irq: |
442 | /* And set the interrupt handler again */ | 454 | /* And set the interrupt handler again */ |
443 | ide_set_handler(drive, ide_pc_intr, timeout, NULL); | 455 | ide_set_handler(drive, ide_pc_intr, timeout, NULL); |
444 | return ide_started; | 456 | return ide_started; |
445 | } | 457 | } |
446 | 458 | ||
447 | static u8 ide_read_ireason(ide_drive_t *drive) | 459 | static u8 ide_read_ireason(ide_drive_t *drive) |
448 | { | 460 | { |
449 | ide_task_t task; | 461 | ide_task_t task; |
450 | 462 | ||
451 | memset(&task, 0, sizeof(task)); | 463 | memset(&task, 0, sizeof(task)); |
452 | task.tf_flags = IDE_TFLAG_IN_NSECT; | 464 | task.tf_flags = IDE_TFLAG_IN_NSECT; |
453 | 465 | ||
454 | drive->hwif->tp_ops->tf_read(drive, &task); | 466 | drive->hwif->tp_ops->tf_read(drive, &task); |
455 | 467 | ||
456 | return task.tf.nsect & 3; | 468 | return task.tf.nsect & 3; |
457 | } | 469 | } |
458 | 470 | ||
459 | static u8 ide_wait_ireason(ide_drive_t *drive, u8 ireason) | 471 | static u8 ide_wait_ireason(ide_drive_t *drive, u8 ireason) |
460 | { | 472 | { |
461 | int retries = 100; | 473 | int retries = 100; |
462 | 474 | ||
463 | while (retries-- && ((ireason & ATAPI_COD) == 0 || | 475 | while (retries-- && ((ireason & ATAPI_COD) == 0 || |
464 | (ireason & ATAPI_IO))) { | 476 | (ireason & ATAPI_IO))) { |
465 | printk(KERN_ERR "%s: (IO,CoD != (0,1) while issuing " | 477 | printk(KERN_ERR "%s: (IO,CoD != (0,1) while issuing " |
466 | "a packet command, retrying\n", drive->name); | 478 | "a packet command, retrying\n", drive->name); |
467 | udelay(100); | 479 | udelay(100); |
468 | ireason = ide_read_ireason(drive); | 480 | ireason = ide_read_ireason(drive); |
469 | if (retries == 0) { | 481 | if (retries == 0) { |
470 | printk(KERN_ERR "%s: (IO,CoD != (0,1) while issuing " | 482 | printk(KERN_ERR "%s: (IO,CoD != (0,1) while issuing " |
471 | "a packet command, ignoring\n", | 483 | "a packet command, ignoring\n", |
472 | drive->name); | 484 | drive->name); |
473 | ireason |= ATAPI_COD; | 485 | ireason |= ATAPI_COD; |
474 | ireason &= ~ATAPI_IO; | 486 | ireason &= ~ATAPI_IO; |
475 | } | 487 | } |
476 | } | 488 | } |
477 | 489 | ||
478 | return ireason; | 490 | return ireason; |
479 | } | 491 | } |
480 | 492 | ||
481 | static int ide_delayed_transfer_pc(ide_drive_t *drive) | 493 | static int ide_delayed_transfer_pc(ide_drive_t *drive) |
482 | { | 494 | { |
483 | /* Send the actual packet */ | 495 | /* Send the actual packet */ |
484 | drive->hwif->tp_ops->output_data(drive, NULL, drive->pc->c, 12); | 496 | drive->hwif->tp_ops->output_data(drive, NULL, drive->pc->c, 12); |
485 | 497 | ||
486 | /* Timeout for the packet command */ | 498 | /* Timeout for the packet command */ |
487 | return WAIT_FLOPPY_CMD; | 499 | return WAIT_FLOPPY_CMD; |
488 | } | 500 | } |
489 | 501 | ||
490 | static ide_startstop_t ide_transfer_pc(ide_drive_t *drive) | 502 | static ide_startstop_t ide_transfer_pc(ide_drive_t *drive) |
491 | { | 503 | { |
492 | struct ide_atapi_pc *uninitialized_var(pc); | 504 | struct ide_atapi_pc *uninitialized_var(pc); |
493 | ide_hwif_t *hwif = drive->hwif; | 505 | ide_hwif_t *hwif = drive->hwif; |
494 | struct request *rq = hwif->rq; | 506 | struct request *rq = hwif->rq; |
495 | ide_expiry_t *expiry; | 507 | ide_expiry_t *expiry; |
496 | unsigned int timeout; | 508 | unsigned int timeout; |
497 | int cmd_len; | 509 | int cmd_len; |
498 | ide_startstop_t startstop; | 510 | ide_startstop_t startstop; |
499 | u8 ireason; | 511 | u8 ireason; |
500 | 512 | ||
501 | if (ide_wait_stat(&startstop, drive, ATA_DRQ, ATA_BUSY, WAIT_READY)) { | 513 | if (ide_wait_stat(&startstop, drive, ATA_DRQ, ATA_BUSY, WAIT_READY)) { |
502 | printk(KERN_ERR "%s: Strange, packet command initiated yet " | 514 | printk(KERN_ERR "%s: Strange, packet command initiated yet " |
503 | "DRQ isn't asserted\n", drive->name); | 515 | "DRQ isn't asserted\n", drive->name); |
504 | return startstop; | 516 | return startstop; |
505 | } | 517 | } |
506 | 518 | ||
507 | if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) { | 519 | if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) { |
508 | if (drive->dma) | 520 | if (drive->dma) |
509 | drive->waiting_for_dma = 1; | 521 | drive->waiting_for_dma = 1; |
510 | } | 522 | } |
511 | 523 | ||
512 | if (dev_is_idecd(drive)) { | 524 | if (dev_is_idecd(drive)) { |
513 | /* ATAPI commands get padded out to 12 bytes minimum */ | 525 | /* ATAPI commands get padded out to 12 bytes minimum */ |
514 | cmd_len = COMMAND_SIZE(rq->cmd[0]); | 526 | cmd_len = COMMAND_SIZE(rq->cmd[0]); |
515 | if (cmd_len < ATAPI_MIN_CDB_BYTES) | 527 | if (cmd_len < ATAPI_MIN_CDB_BYTES) |
516 | cmd_len = ATAPI_MIN_CDB_BYTES; | 528 | cmd_len = ATAPI_MIN_CDB_BYTES; |
517 | 529 | ||
518 | timeout = rq->timeout; | 530 | timeout = rq->timeout; |
519 | expiry = ide_cd_expiry; | 531 | expiry = ide_cd_expiry; |
520 | } else { | 532 | } else { |
521 | pc = drive->pc; | 533 | pc = drive->pc; |
522 | 534 | ||
523 | cmd_len = ATAPI_MIN_CDB_BYTES; | 535 | cmd_len = ATAPI_MIN_CDB_BYTES; |
524 | 536 | ||
525 | /* | 537 | /* |
526 | * If necessary schedule the packet transfer to occur 'timeout' | 538 | * If necessary schedule the packet transfer to occur 'timeout' |
527 | * miliseconds later in ide_delayed_transfer_pc() after the | 539 | * miliseconds later in ide_delayed_transfer_pc() after the |
528 | * device says it's ready for a packet. | 540 | * device says it's ready for a packet. |
529 | */ | 541 | */ |
530 | if (drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) { | 542 | if (drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) { |
531 | timeout = drive->pc_delay; | 543 | timeout = drive->pc_delay; |
532 | expiry = &ide_delayed_transfer_pc; | 544 | expiry = &ide_delayed_transfer_pc; |
533 | } else { | 545 | } else { |
534 | timeout = (drive->media == ide_floppy) ? WAIT_FLOPPY_CMD | 546 | timeout = (drive->media == ide_floppy) ? WAIT_FLOPPY_CMD |
535 | : WAIT_TAPE_CMD; | 547 | : WAIT_TAPE_CMD; |
536 | expiry = NULL; | 548 | expiry = NULL; |
537 | } | 549 | } |
538 | 550 | ||
539 | ireason = ide_read_ireason(drive); | 551 | ireason = ide_read_ireason(drive); |
540 | if (drive->media == ide_tape) | 552 | if (drive->media == ide_tape) |
541 | ireason = ide_wait_ireason(drive, ireason); | 553 | ireason = ide_wait_ireason(drive, ireason); |
542 | 554 | ||
543 | if ((ireason & ATAPI_COD) == 0 || (ireason & ATAPI_IO)) { | 555 | if ((ireason & ATAPI_COD) == 0 || (ireason & ATAPI_IO)) { |
544 | printk(KERN_ERR "%s: (IO,CoD) != (0,1) while issuing " | 556 | printk(KERN_ERR "%s: (IO,CoD) != (0,1) while issuing " |
545 | "a packet command\n", drive->name); | 557 | "a packet command\n", drive->name); |
546 | 558 | ||
547 | return ide_do_reset(drive); | 559 | return ide_do_reset(drive); |
548 | } | 560 | } |
549 | } | 561 | } |
550 | 562 | ||
551 | /* Set the interrupt routine */ | 563 | /* Set the interrupt routine */ |
552 | ide_set_handler(drive, | 564 | ide_set_handler(drive, |
553 | (dev_is_idecd(drive) ? drive->irq_handler | 565 | (dev_is_idecd(drive) ? drive->irq_handler |
554 | : ide_pc_intr), | 566 | : ide_pc_intr), |
555 | timeout, expiry); | 567 | timeout, expiry); |
556 | 568 | ||
557 | /* Begin DMA, if necessary */ | 569 | /* Begin DMA, if necessary */ |
558 | if (dev_is_idecd(drive)) { | 570 | if (dev_is_idecd(drive)) { |
559 | if (drive->dma) | 571 | if (drive->dma) |
560 | hwif->dma_ops->dma_start(drive); | 572 | hwif->dma_ops->dma_start(drive); |
561 | } else { | 573 | } else { |
562 | if (pc->flags & PC_FLAG_DMA_OK) { | 574 | if (pc->flags & PC_FLAG_DMA_OK) { |
563 | pc->flags |= PC_FLAG_DMA_IN_PROGRESS; | 575 | pc->flags |= PC_FLAG_DMA_IN_PROGRESS; |
564 | hwif->dma_ops->dma_start(drive); | 576 | hwif->dma_ops->dma_start(drive); |
565 | } | 577 | } |
566 | } | 578 | } |
567 | 579 | ||
568 | /* Send the actual packet */ | 580 | /* Send the actual packet */ |
569 | if ((drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) == 0) | 581 | if ((drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) == 0) |
570 | hwif->tp_ops->output_data(drive, NULL, rq->cmd, cmd_len); | 582 | hwif->tp_ops->output_data(drive, NULL, rq->cmd, cmd_len); |
571 | 583 | ||
572 | return ide_started; | 584 | return ide_started; |
573 | } | 585 | } |
574 | 586 | ||
575 | ide_startstop_t ide_issue_pc(ide_drive_t *drive) | 587 | ide_startstop_t ide_issue_pc(ide_drive_t *drive) |
576 | { | 588 | { |
577 | struct ide_atapi_pc *pc; | 589 | struct ide_atapi_pc *pc; |
578 | ide_hwif_t *hwif = drive->hwif; | 590 | ide_hwif_t *hwif = drive->hwif; |
579 | ide_expiry_t *expiry = NULL; | 591 | ide_expiry_t *expiry = NULL; |
580 | unsigned int timeout; | 592 | unsigned int timeout; |
581 | u32 tf_flags; | 593 | u32 tf_flags; |
582 | u16 bcount; | 594 | u16 bcount; |
583 | 595 | ||
584 | if (dev_is_idecd(drive)) { | 596 | if (dev_is_idecd(drive)) { |
585 | tf_flags = IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL; | 597 | tf_flags = IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL; |
586 | bcount = ide_cd_get_xferlen(hwif->rq); | 598 | bcount = ide_cd_get_xferlen(hwif->rq); |
587 | expiry = ide_cd_expiry; | 599 | expiry = ide_cd_expiry; |
588 | timeout = ATAPI_WAIT_PC; | 600 | timeout = ATAPI_WAIT_PC; |
589 | 601 | ||
590 | if (drive->dma) | 602 | if (drive->dma) |
591 | drive->dma = !hwif->dma_ops->dma_setup(drive); | 603 | drive->dma = !hwif->dma_ops->dma_setup(drive); |
592 | } else { | 604 | } else { |
593 | pc = drive->pc; | 605 | pc = drive->pc; |
594 | 606 | ||
595 | /* We haven't transferred any data yet */ | 607 | /* We haven't transferred any data yet */ |
596 | pc->xferred = 0; | 608 | pc->xferred = 0; |
597 | pc->cur_pos = pc->buf; | 609 | pc->cur_pos = pc->buf; |
598 | 610 | ||
599 | tf_flags = IDE_TFLAG_OUT_DEVICE; | 611 | tf_flags = IDE_TFLAG_OUT_DEVICE; |
600 | bcount = ((drive->media == ide_tape) ? | 612 | bcount = ((drive->media == ide_tape) ? |
601 | pc->req_xfer : | 613 | pc->req_xfer : |
602 | min(pc->req_xfer, 63 * 1024)); | 614 | min(pc->req_xfer, 63 * 1024)); |
603 | 615 | ||
604 | if (pc->flags & PC_FLAG_DMA_ERROR) { | 616 | if (pc->flags & PC_FLAG_DMA_ERROR) { |
605 | pc->flags &= ~PC_FLAG_DMA_ERROR; | 617 | pc->flags &= ~PC_FLAG_DMA_ERROR; |
606 | ide_dma_off(drive); | 618 | ide_dma_off(drive); |
607 | } | 619 | } |
608 | 620 | ||
609 | if ((pc->flags & PC_FLAG_DMA_OK) && | 621 | if ((pc->flags & PC_FLAG_DMA_OK) && |
610 | (drive->dev_flags & IDE_DFLAG_USING_DMA)) | 622 | (drive->dev_flags & IDE_DFLAG_USING_DMA)) |
611 | drive->dma = !hwif->dma_ops->dma_setup(drive); | 623 | drive->dma = !hwif->dma_ops->dma_setup(drive); |
612 | 624 | ||
613 | if (!drive->dma) | 625 | if (!drive->dma) |
614 | pc->flags &= ~PC_FLAG_DMA_OK; | 626 | pc->flags &= ~PC_FLAG_DMA_OK; |
615 | 627 | ||
616 | timeout = (drive->media == ide_floppy) ? WAIT_FLOPPY_CMD | 628 | timeout = (drive->media == ide_floppy) ? WAIT_FLOPPY_CMD |
617 | : WAIT_TAPE_CMD; | 629 | : WAIT_TAPE_CMD; |
618 | } | 630 | } |
619 | 631 | ||
620 | ide_pktcmd_tf_load(drive, tf_flags, bcount, drive->dma); | 632 | ide_pktcmd_tf_load(drive, tf_flags, bcount, drive->dma); |
621 | 633 | ||
622 | /* Issue the packet command */ | 634 | /* Issue the packet command */ |
623 | if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) { | 635 | if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) { |
624 | if (drive->dma) | 636 | if (drive->dma) |
625 | drive->waiting_for_dma = 0; | 637 | drive->waiting_for_dma = 0; |
626 | ide_execute_command(drive, ATA_CMD_PACKET, ide_transfer_pc, | 638 | ide_execute_command(drive, ATA_CMD_PACKET, ide_transfer_pc, |
627 | timeout, expiry); | 639 | timeout, expiry); |
628 | return ide_started; | 640 | return ide_started; |
629 | } else { | 641 | } else { |
630 | ide_execute_pkt_cmd(drive); | 642 | ide_execute_pkt_cmd(drive); |
631 | return ide_transfer_pc(drive); | 643 | return ide_transfer_pc(drive); |
632 | } | 644 | } |
633 | } | 645 | } |
634 | EXPORT_SYMBOL_GPL(ide_issue_pc); | 646 | EXPORT_SYMBOL_GPL(ide_issue_pc); |
635 | 647 |
drivers/ide/ide-floppy.c
1 | /* | 1 | /* |
2 | * IDE ATAPI floppy driver. | 2 | * IDE ATAPI floppy driver. |
3 | * | 3 | * |
4 | * Copyright (C) 1996-1999 Gadi Oxman <gadio@netvision.net.il> | 4 | * Copyright (C) 1996-1999 Gadi Oxman <gadio@netvision.net.il> |
5 | * Copyright (C) 2000-2002 Paul Bristow <paul@paulbristow.net> | 5 | * Copyright (C) 2000-2002 Paul Bristow <paul@paulbristow.net> |
6 | * Copyright (C) 2005 Bartlomiej Zolnierkiewicz | 6 | * Copyright (C) 2005 Bartlomiej Zolnierkiewicz |
7 | * | 7 | * |
8 | * This driver supports the following IDE floppy drives: | 8 | * This driver supports the following IDE floppy drives: |
9 | * | 9 | * |
10 | * LS-120/240 SuperDisk | 10 | * LS-120/240 SuperDisk |
11 | * Iomega Zip 100/250 | 11 | * Iomega Zip 100/250 |
12 | * Iomega PC Card Clik!/PocketZip | 12 | * Iomega PC Card Clik!/PocketZip |
13 | * | 13 | * |
14 | * For a historical changelog see | 14 | * For a historical changelog see |
15 | * Documentation/ide/ChangeLog.ide-floppy.1996-2002 | 15 | * Documentation/ide/ChangeLog.ide-floppy.1996-2002 |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/types.h> | 18 | #include <linux/types.h> |
19 | #include <linux/string.h> | 19 | #include <linux/string.h> |
20 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
21 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
22 | #include <linux/timer.h> | 22 | #include <linux/timer.h> |
23 | #include <linux/mm.h> | 23 | #include <linux/mm.h> |
24 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
25 | #include <linux/major.h> | 25 | #include <linux/major.h> |
26 | #include <linux/errno.h> | 26 | #include <linux/errno.h> |
27 | #include <linux/genhd.h> | 27 | #include <linux/genhd.h> |
28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
29 | #include <linux/cdrom.h> | 29 | #include <linux/cdrom.h> |
30 | #include <linux/ide.h> | 30 | #include <linux/ide.h> |
31 | #include <linux/hdreg.h> | 31 | #include <linux/hdreg.h> |
32 | #include <linux/bitops.h> | 32 | #include <linux/bitops.h> |
33 | #include <linux/mutex.h> | 33 | #include <linux/mutex.h> |
34 | #include <linux/scatterlist.h> | 34 | #include <linux/scatterlist.h> |
35 | 35 | ||
36 | #include <scsi/scsi_ioctl.h> | 36 | #include <scsi/scsi_ioctl.h> |
37 | 37 | ||
38 | #include <asm/byteorder.h> | 38 | #include <asm/byteorder.h> |
39 | #include <linux/irq.h> | 39 | #include <linux/irq.h> |
40 | #include <linux/uaccess.h> | 40 | #include <linux/uaccess.h> |
41 | #include <linux/io.h> | 41 | #include <linux/io.h> |
42 | #include <asm/unaligned.h> | 42 | #include <asm/unaligned.h> |
43 | 43 | ||
44 | #include "ide-floppy.h" | 44 | #include "ide-floppy.h" |
45 | 45 | ||
46 | /* | 46 | /* |
47 | * After each failed packet command we issue a request sense command and retry | 47 | * After each failed packet command we issue a request sense command and retry |
48 | * the packet command IDEFLOPPY_MAX_PC_RETRIES times. | 48 | * the packet command IDEFLOPPY_MAX_PC_RETRIES times. |
49 | */ | 49 | */ |
50 | #define IDEFLOPPY_MAX_PC_RETRIES 3 | 50 | #define IDEFLOPPY_MAX_PC_RETRIES 3 |
51 | 51 | ||
52 | /* format capacities descriptor codes */ | 52 | /* format capacities descriptor codes */ |
53 | #define CAPACITY_INVALID 0x00 | 53 | #define CAPACITY_INVALID 0x00 |
54 | #define CAPACITY_UNFORMATTED 0x01 | 54 | #define CAPACITY_UNFORMATTED 0x01 |
55 | #define CAPACITY_CURRENT 0x02 | 55 | #define CAPACITY_CURRENT 0x02 |
56 | #define CAPACITY_NO_CARTRIDGE 0x03 | 56 | #define CAPACITY_NO_CARTRIDGE 0x03 |
57 | 57 | ||
58 | /* | 58 | /* |
59 | * The following delay solves a problem with ATAPI Zip 100 drive where BSY bit | 59 | * The following delay solves a problem with ATAPI Zip 100 drive where BSY bit |
60 | * was apparently being deasserted before the unit was ready to receive data. | 60 | * was apparently being deasserted before the unit was ready to receive data. |
61 | */ | 61 | */ |
62 | #define IDEFLOPPY_PC_DELAY (HZ/20) /* default delay for ZIP 100 (50ms) */ | 62 | #define IDEFLOPPY_PC_DELAY (HZ/20) /* default delay for ZIP 100 (50ms) */ |
63 | 63 | ||
64 | /* Error code returned in rq->errors to the higher part of the driver. */ | 64 | /* Error code returned in rq->errors to the higher part of the driver. */ |
65 | #define IDEFLOPPY_ERROR_GENERAL 101 | 65 | #define IDEFLOPPY_ERROR_GENERAL 101 |
66 | 66 | ||
67 | /* | 67 | /* |
68 | * Used to finish servicing a request. For read/write requests, we will call | 68 | * Used to finish servicing a request. For read/write requests, we will call |
69 | * ide_end_request to pass to the next buffer. | 69 | * ide_end_request to pass to the next buffer. |
70 | */ | 70 | */ |
71 | static int ide_floppy_end_request(ide_drive_t *drive, int uptodate, int nsecs) | 71 | static int ide_floppy_end_request(ide_drive_t *drive, int uptodate, int nsecs) |
72 | { | 72 | { |
73 | struct ide_disk_obj *floppy = drive->driver_data; | 73 | struct ide_disk_obj *floppy = drive->driver_data; |
74 | struct request *rq = drive->hwif->rq; | 74 | struct request *rq = drive->hwif->rq; |
75 | int error; | 75 | int error; |
76 | 76 | ||
77 | ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__); | 77 | ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__); |
78 | 78 | ||
79 | switch (uptodate) { | 79 | switch (uptodate) { |
80 | case 0: | 80 | case 0: |
81 | error = IDEFLOPPY_ERROR_GENERAL; | 81 | error = IDEFLOPPY_ERROR_GENERAL; |
82 | break; | 82 | break; |
83 | 83 | ||
84 | case 1: | 84 | case 1: |
85 | error = 0; | 85 | error = 0; |
86 | break; | 86 | break; |
87 | 87 | ||
88 | default: | 88 | default: |
89 | error = uptodate; | 89 | error = uptodate; |
90 | } | 90 | } |
91 | 91 | ||
92 | if (error) | 92 | if (error) |
93 | floppy->failed_pc = NULL; | 93 | floppy->failed_pc = NULL; |
94 | /* Why does this happen? */ | 94 | /* Why does this happen? */ |
95 | if (!rq) | 95 | if (!rq) |
96 | return 0; | 96 | return 0; |
97 | if (!blk_special_request(rq)) { | 97 | if (!blk_special_request(rq)) { |
98 | /* our real local end request function */ | 98 | /* our real local end request function */ |
99 | ide_end_request(drive, uptodate, nsecs); | 99 | ide_end_request(drive, uptodate, nsecs); |
100 | return 0; | 100 | return 0; |
101 | } | 101 | } |
102 | rq->errors = error; | 102 | rq->errors = error; |
103 | /* fixme: need to move this local also */ | 103 | /* fixme: need to move this local also */ |
104 | ide_end_drive_cmd(drive, 0, 0); | 104 | ide_end_drive_cmd(drive, 0, 0); |
105 | return 0; | 105 | return 0; |
106 | } | 106 | } |
107 | 107 | ||
108 | static void idefloppy_update_buffers(ide_drive_t *drive, | 108 | static void idefloppy_update_buffers(ide_drive_t *drive, |
109 | struct ide_atapi_pc *pc) | 109 | struct ide_atapi_pc *pc) |
110 | { | 110 | { |
111 | struct request *rq = pc->rq; | 111 | struct request *rq = pc->rq; |
112 | struct bio *bio = rq->bio; | 112 | struct bio *bio = rq->bio; |
113 | 113 | ||
114 | while ((bio = rq->bio) != NULL) | 114 | while ((bio = rq->bio) != NULL) |
115 | ide_floppy_end_request(drive, 1, 0); | 115 | ide_floppy_end_request(drive, 1, 0); |
116 | } | 116 | } |
117 | 117 | ||
118 | static void ide_floppy_callback(ide_drive_t *drive, int dsc) | 118 | static void ide_floppy_callback(ide_drive_t *drive, int dsc) |
119 | { | 119 | { |
120 | struct ide_disk_obj *floppy = drive->driver_data; | 120 | struct ide_disk_obj *floppy = drive->driver_data; |
121 | struct ide_atapi_pc *pc = drive->pc; | 121 | struct ide_atapi_pc *pc = drive->pc; |
122 | int uptodate = pc->error ? 0 : 1; | 122 | int uptodate = pc->error ? 0 : 1; |
123 | 123 | ||
124 | ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__); | 124 | ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__); |
125 | 125 | ||
126 | if (floppy->failed_pc == pc) | 126 | if (floppy->failed_pc == pc) |
127 | floppy->failed_pc = NULL; | 127 | floppy->failed_pc = NULL; |
128 | 128 | ||
129 | if (pc->c[0] == GPCMD_READ_10 || pc->c[0] == GPCMD_WRITE_10 || | 129 | if (pc->c[0] == GPCMD_READ_10 || pc->c[0] == GPCMD_WRITE_10 || |
130 | (pc->rq && blk_pc_request(pc->rq))) | 130 | (pc->rq && blk_pc_request(pc->rq))) |
131 | uptodate = 1; /* FIXME */ | 131 | uptodate = 1; /* FIXME */ |
132 | else if (pc->c[0] == GPCMD_REQUEST_SENSE) { | 132 | else if (pc->c[0] == GPCMD_REQUEST_SENSE) { |
133 | u8 *buf = pc->buf; | 133 | u8 *buf = pc->buf; |
134 | 134 | ||
135 | if (!pc->error) { | 135 | if (!pc->error) { |
136 | floppy->sense_key = buf[2] & 0x0F; | 136 | floppy->sense_key = buf[2] & 0x0F; |
137 | floppy->asc = buf[12]; | 137 | floppy->asc = buf[12]; |
138 | floppy->ascq = buf[13]; | 138 | floppy->ascq = buf[13]; |
139 | floppy->progress_indication = buf[15] & 0x80 ? | 139 | floppy->progress_indication = buf[15] & 0x80 ? |
140 | (u16)get_unaligned((u16 *)&buf[16]) : 0x10000; | 140 | (u16)get_unaligned((u16 *)&buf[16]) : 0x10000; |
141 | 141 | ||
142 | if (floppy->failed_pc) | 142 | if (floppy->failed_pc) |
143 | ide_debug_log(IDE_DBG_PC, "pc = %x, ", | 143 | ide_debug_log(IDE_DBG_PC, "pc = %x, ", |
144 | floppy->failed_pc->c[0]); | 144 | floppy->failed_pc->c[0]); |
145 | 145 | ||
146 | ide_debug_log(IDE_DBG_SENSE, "sense key = %x, asc = %x," | 146 | ide_debug_log(IDE_DBG_SENSE, "sense key = %x, asc = %x," |
147 | "ascq = %x\n", floppy->sense_key, | 147 | "ascq = %x\n", floppy->sense_key, |
148 | floppy->asc, floppy->ascq); | 148 | floppy->asc, floppy->ascq); |
149 | } else | 149 | } else |
150 | printk(KERN_ERR PFX "Error in REQUEST SENSE itself - " | 150 | printk(KERN_ERR PFX "Error in REQUEST SENSE itself - " |
151 | "Aborting request!\n"); | 151 | "Aborting request!\n"); |
152 | } | 152 | } |
153 | 153 | ||
154 | ide_floppy_end_request(drive, uptodate, 0); | 154 | ide_floppy_end_request(drive, uptodate, 0); |
155 | } | 155 | } |
156 | 156 | ||
157 | static void ide_floppy_report_error(struct ide_disk_obj *floppy, | 157 | static void ide_floppy_report_error(struct ide_disk_obj *floppy, |
158 | struct ide_atapi_pc *pc) | 158 | struct ide_atapi_pc *pc) |
159 | { | 159 | { |
160 | /* supress error messages resulting from Medium not present */ | 160 | /* supress error messages resulting from Medium not present */ |
161 | if (floppy->sense_key == 0x02 && | 161 | if (floppy->sense_key == 0x02 && |
162 | floppy->asc == 0x3a && | 162 | floppy->asc == 0x3a && |
163 | floppy->ascq == 0x00) | 163 | floppy->ascq == 0x00) |
164 | return; | 164 | return; |
165 | 165 | ||
166 | printk(KERN_ERR PFX "%s: I/O error, pc = %2x, key = %2x, " | 166 | printk(KERN_ERR PFX "%s: I/O error, pc = %2x, key = %2x, " |
167 | "asc = %2x, ascq = %2x\n", | 167 | "asc = %2x, ascq = %2x\n", |
168 | floppy->drive->name, pc->c[0], floppy->sense_key, | 168 | floppy->drive->name, pc->c[0], floppy->sense_key, |
169 | floppy->asc, floppy->ascq); | 169 | floppy->asc, floppy->ascq); |
170 | 170 | ||
171 | } | 171 | } |
172 | 172 | ||
173 | static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive, | 173 | static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive, |
174 | struct ide_atapi_pc *pc) | 174 | struct ide_atapi_pc *pc) |
175 | { | 175 | { |
176 | struct ide_disk_obj *floppy = drive->driver_data; | 176 | struct ide_disk_obj *floppy = drive->driver_data; |
177 | 177 | ||
178 | if (floppy->failed_pc == NULL && | 178 | if (floppy->failed_pc == NULL && |
179 | pc->c[0] != GPCMD_REQUEST_SENSE) | 179 | pc->c[0] != GPCMD_REQUEST_SENSE) |
180 | floppy->failed_pc = pc; | 180 | floppy->failed_pc = pc; |
181 | 181 | ||
182 | /* Set the current packet command */ | 182 | /* Set the current packet command */ |
183 | drive->pc = pc; | 183 | drive->pc = pc; |
184 | 184 | ||
185 | if (pc->retries > IDEFLOPPY_MAX_PC_RETRIES) { | 185 | if (pc->retries > IDEFLOPPY_MAX_PC_RETRIES) { |
186 | if (!(pc->flags & PC_FLAG_SUPPRESS_ERROR)) | 186 | if (!(pc->flags & PC_FLAG_SUPPRESS_ERROR)) |
187 | ide_floppy_report_error(floppy, pc); | 187 | ide_floppy_report_error(floppy, pc); |
188 | /* Giving up */ | 188 | /* Giving up */ |
189 | pc->error = IDEFLOPPY_ERROR_GENERAL; | 189 | pc->error = IDEFLOPPY_ERROR_GENERAL; |
190 | 190 | ||
191 | floppy->failed_pc = NULL; | 191 | floppy->failed_pc = NULL; |
192 | drive->pc_callback(drive, 0); | 192 | drive->pc_callback(drive, 0); |
193 | return ide_stopped; | 193 | return ide_stopped; |
194 | } | 194 | } |
195 | 195 | ||
196 | ide_debug_log(IDE_DBG_FUNC, "%s: Retry #%d\n", __func__, pc->retries); | 196 | ide_debug_log(IDE_DBG_FUNC, "%s: Retry #%d\n", __func__, pc->retries); |
197 | 197 | ||
198 | pc->retries++; | 198 | pc->retries++; |
199 | 199 | ||
200 | return ide_issue_pc(drive); | 200 | return ide_issue_pc(drive); |
201 | } | 201 | } |
202 | 202 | ||
203 | void ide_floppy_create_read_capacity_cmd(struct ide_atapi_pc *pc) | 203 | void ide_floppy_create_read_capacity_cmd(struct ide_atapi_pc *pc) |
204 | { | 204 | { |
205 | ide_init_pc(pc); | 205 | ide_init_pc(pc); |
206 | pc->c[0] = GPCMD_READ_FORMAT_CAPACITIES; | 206 | pc->c[0] = GPCMD_READ_FORMAT_CAPACITIES; |
207 | pc->c[7] = 255; | 207 | pc->c[7] = 255; |
208 | pc->c[8] = 255; | 208 | pc->c[8] = 255; |
209 | pc->req_xfer = 255; | 209 | pc->req_xfer = 255; |
210 | } | 210 | } |
211 | 211 | ||
212 | /* A mode sense command is used to "sense" floppy parameters. */ | 212 | /* A mode sense command is used to "sense" floppy parameters. */ |
213 | void ide_floppy_create_mode_sense_cmd(struct ide_atapi_pc *pc, u8 page_code) | 213 | void ide_floppy_create_mode_sense_cmd(struct ide_atapi_pc *pc, u8 page_code) |
214 | { | 214 | { |
215 | u16 length = 8; /* sizeof(Mode Parameter Header) = 8 Bytes */ | 215 | u16 length = 8; /* sizeof(Mode Parameter Header) = 8 Bytes */ |
216 | 216 | ||
217 | ide_init_pc(pc); | 217 | ide_init_pc(pc); |
218 | pc->c[0] = GPCMD_MODE_SENSE_10; | 218 | pc->c[0] = GPCMD_MODE_SENSE_10; |
219 | pc->c[1] = 0; | 219 | pc->c[1] = 0; |
220 | pc->c[2] = page_code; | 220 | pc->c[2] = page_code; |
221 | 221 | ||
222 | switch (page_code) { | 222 | switch (page_code) { |
223 | case IDEFLOPPY_CAPABILITIES_PAGE: | 223 | case IDEFLOPPY_CAPABILITIES_PAGE: |
224 | length += 12; | 224 | length += 12; |
225 | break; | 225 | break; |
226 | case IDEFLOPPY_FLEXIBLE_DISK_PAGE: | 226 | case IDEFLOPPY_FLEXIBLE_DISK_PAGE: |
227 | length += 32; | 227 | length += 32; |
228 | break; | 228 | break; |
229 | default: | 229 | default: |
230 | printk(KERN_ERR PFX "unsupported page code in %s\n", __func__); | 230 | printk(KERN_ERR PFX "unsupported page code in %s\n", __func__); |
231 | } | 231 | } |
232 | put_unaligned(cpu_to_be16(length), (u16 *) &pc->c[7]); | 232 | put_unaligned(cpu_to_be16(length), (u16 *) &pc->c[7]); |
233 | pc->req_xfer = length; | 233 | pc->req_xfer = length; |
234 | } | 234 | } |
235 | 235 | ||
236 | static void idefloppy_create_rw_cmd(ide_drive_t *drive, | 236 | static void idefloppy_create_rw_cmd(ide_drive_t *drive, |
237 | struct ide_atapi_pc *pc, struct request *rq, | 237 | struct ide_atapi_pc *pc, struct request *rq, |
238 | unsigned long sector) | 238 | unsigned long sector) |
239 | { | 239 | { |
240 | struct ide_disk_obj *floppy = drive->driver_data; | 240 | struct ide_disk_obj *floppy = drive->driver_data; |
241 | int block = sector / floppy->bs_factor; | 241 | int block = sector / floppy->bs_factor; |
242 | int blocks = rq->nr_sectors / floppy->bs_factor; | 242 | int blocks = rq->nr_sectors / floppy->bs_factor; |
243 | int cmd = rq_data_dir(rq); | 243 | int cmd = rq_data_dir(rq); |
244 | 244 | ||
245 | ide_debug_log(IDE_DBG_FUNC, "%s: block: %d, blocks: %d\n", __func__, | 245 | ide_debug_log(IDE_DBG_FUNC, "%s: block: %d, blocks: %d\n", __func__, |
246 | block, blocks); | 246 | block, blocks); |
247 | 247 | ||
248 | ide_init_pc(pc); | 248 | ide_init_pc(pc); |
249 | pc->c[0] = cmd == READ ? GPCMD_READ_10 : GPCMD_WRITE_10; | 249 | pc->c[0] = cmd == READ ? GPCMD_READ_10 : GPCMD_WRITE_10; |
250 | put_unaligned(cpu_to_be16(blocks), (unsigned short *)&pc->c[7]); | 250 | put_unaligned(cpu_to_be16(blocks), (unsigned short *)&pc->c[7]); |
251 | put_unaligned(cpu_to_be32(block), (unsigned int *) &pc->c[2]); | 251 | put_unaligned(cpu_to_be32(block), (unsigned int *) &pc->c[2]); |
252 | 252 | ||
253 | memcpy(rq->cmd, pc->c, 12); | 253 | memcpy(rq->cmd, pc->c, 12); |
254 | 254 | ||
255 | pc->rq = rq; | 255 | pc->rq = rq; |
256 | pc->b_count = 0; | 256 | pc->b_count = 0; |
257 | if (rq->cmd_flags & REQ_RW) | 257 | if (rq->cmd_flags & REQ_RW) |
258 | pc->flags |= PC_FLAG_WRITING; | 258 | pc->flags |= PC_FLAG_WRITING; |
259 | pc->buf = NULL; | 259 | pc->buf = NULL; |
260 | pc->req_xfer = pc->buf_size = blocks * floppy->block_size; | 260 | pc->req_xfer = pc->buf_size = blocks * floppy->block_size; |
261 | pc->flags |= PC_FLAG_DMA_OK; | 261 | pc->flags |= PC_FLAG_DMA_OK; |
262 | } | 262 | } |
263 | 263 | ||
264 | static void idefloppy_blockpc_cmd(struct ide_disk_obj *floppy, | 264 | static void idefloppy_blockpc_cmd(struct ide_disk_obj *floppy, |
265 | struct ide_atapi_pc *pc, struct request *rq) | 265 | struct ide_atapi_pc *pc, struct request *rq) |
266 | { | 266 | { |
267 | ide_init_pc(pc); | 267 | ide_init_pc(pc); |
268 | memcpy(pc->c, rq->cmd, sizeof(pc->c)); | 268 | memcpy(pc->c, rq->cmd, sizeof(pc->c)); |
269 | pc->rq = rq; | 269 | pc->rq = rq; |
270 | pc->b_count = 0; | 270 | pc->b_count = 0; |
271 | if (rq->data_len && rq_data_dir(rq) == WRITE) | 271 | if (rq->data_len && rq_data_dir(rq) == WRITE) |
272 | pc->flags |= PC_FLAG_WRITING; | 272 | pc->flags |= PC_FLAG_WRITING; |
273 | pc->buf = rq->data; | 273 | pc->buf = rq->data; |
274 | if (rq->bio) | 274 | if (rq->bio) |
275 | pc->flags |= PC_FLAG_DMA_OK; | 275 | pc->flags |= PC_FLAG_DMA_OK; |
276 | /* | 276 | /* |
277 | * possibly problematic, doesn't look like ide-floppy correctly | 277 | * possibly problematic, doesn't look like ide-floppy correctly |
278 | * handled scattered requests if dma fails... | 278 | * handled scattered requests if dma fails... |
279 | */ | 279 | */ |
280 | pc->req_xfer = pc->buf_size = rq->data_len; | 280 | pc->req_xfer = pc->buf_size = rq->data_len; |
281 | } | 281 | } |
282 | 282 | ||
283 | static ide_startstop_t ide_floppy_do_request(ide_drive_t *drive, | 283 | static ide_startstop_t ide_floppy_do_request(ide_drive_t *drive, |
284 | struct request *rq, sector_t block) | 284 | struct request *rq, sector_t block) |
285 | { | 285 | { |
286 | struct ide_disk_obj *floppy = drive->driver_data; | 286 | struct ide_disk_obj *floppy = drive->driver_data; |
287 | ide_hwif_t *hwif = drive->hwif; | 287 | ide_hwif_t *hwif = drive->hwif; |
288 | struct ide_atapi_pc *pc; | 288 | struct ide_atapi_pc *pc; |
289 | 289 | ||
290 | ide_debug_log(IDE_DBG_FUNC, "%s: dev: %s, cmd: 0x%x, cmd_type: %x, " | 290 | ide_debug_log(IDE_DBG_FUNC, "%s: dev: %s, cmd: 0x%x, cmd_type: %x, " |
291 | "errors: %d\n", | 291 | "errors: %d\n", |
292 | __func__, rq->rq_disk ? rq->rq_disk->disk_name : "?", | 292 | __func__, rq->rq_disk ? rq->rq_disk->disk_name : "?", |
293 | rq->cmd[0], rq->cmd_type, rq->errors); | 293 | rq->cmd[0], rq->cmd_type, rq->errors); |
294 | 294 | ||
295 | ide_debug_log(IDE_DBG_FUNC, "%s: sector: %ld, nr_sectors: %ld, " | 295 | ide_debug_log(IDE_DBG_FUNC, "%s: sector: %ld, nr_sectors: %ld, " |
296 | "current_nr_sectors: %d\n", | 296 | "current_nr_sectors: %d\n", |
297 | __func__, (long)rq->sector, rq->nr_sectors, | 297 | __func__, (long)rq->sector, rq->nr_sectors, |
298 | rq->current_nr_sectors); | 298 | rq->current_nr_sectors); |
299 | 299 | ||
300 | if (rq->errors >= ERROR_MAX) { | 300 | if (rq->errors >= ERROR_MAX) { |
301 | if (floppy->failed_pc) | 301 | if (floppy->failed_pc) |
302 | ide_floppy_report_error(floppy, floppy->failed_pc); | 302 | ide_floppy_report_error(floppy, floppy->failed_pc); |
303 | else | 303 | else |
304 | printk(KERN_ERR PFX "%s: I/O error\n", drive->name); | 304 | printk(KERN_ERR PFX "%s: I/O error\n", drive->name); |
305 | 305 | ||
306 | ide_floppy_end_request(drive, 0, 0); | 306 | ide_floppy_end_request(drive, 0, 0); |
307 | return ide_stopped; | 307 | return ide_stopped; |
308 | } | 308 | } |
309 | if (blk_fs_request(rq)) { | 309 | if (blk_fs_request(rq)) { |
310 | if (((long)rq->sector % floppy->bs_factor) || | 310 | if (((long)rq->sector % floppy->bs_factor) || |
311 | (rq->nr_sectors % floppy->bs_factor)) { | 311 | (rq->nr_sectors % floppy->bs_factor)) { |
312 | printk(KERN_ERR PFX "%s: unsupported r/w rq size\n", | 312 | printk(KERN_ERR PFX "%s: unsupported r/w rq size\n", |
313 | drive->name); | 313 | drive->name); |
314 | ide_floppy_end_request(drive, 0, 0); | 314 | ide_floppy_end_request(drive, 0, 0); |
315 | return ide_stopped; | 315 | return ide_stopped; |
316 | } | 316 | } |
317 | pc = &floppy->queued_pc; | 317 | pc = &floppy->queued_pc; |
318 | idefloppy_create_rw_cmd(drive, pc, rq, (unsigned long)block); | 318 | idefloppy_create_rw_cmd(drive, pc, rq, (unsigned long)block); |
319 | } else if (blk_special_request(rq)) { | 319 | } else if (blk_special_request(rq)) { |
320 | pc = (struct ide_atapi_pc *) rq->buffer; | 320 | pc = (struct ide_atapi_pc *) rq->buffer; |
321 | } else if (blk_pc_request(rq)) { | 321 | } else if (blk_pc_request(rq)) { |
322 | pc = &floppy->queued_pc; | 322 | pc = &floppy->queued_pc; |
323 | idefloppy_blockpc_cmd(floppy, pc, rq); | 323 | idefloppy_blockpc_cmd(floppy, pc, rq); |
324 | } else { | 324 | } else { |
325 | blk_dump_rq_flags(rq, PFX "unsupported command in queue"); | 325 | blk_dump_rq_flags(rq, PFX "unsupported command in queue"); |
326 | ide_floppy_end_request(drive, 0, 0); | 326 | ide_floppy_end_request(drive, 0, 0); |
327 | return ide_stopped; | 327 | return ide_stopped; |
328 | } | 328 | } |
329 | 329 | ||
330 | ide_init_sg_cmd(drive, rq); | 330 | if (blk_fs_request(rq) || pc->req_xfer) { |
331 | ide_map_sg(drive, rq); | 331 | ide_init_sg_cmd(drive, rq); |
332 | ide_map_sg(drive, rq); | ||
333 | } | ||
332 | 334 | ||
333 | pc->sg = hwif->sg_table; | 335 | pc->sg = hwif->sg_table; |
334 | pc->sg_cnt = hwif->sg_nents; | 336 | pc->sg_cnt = hwif->sg_nents; |
335 | 337 | ||
336 | pc->rq = rq; | 338 | pc->rq = rq; |
337 | 339 | ||
338 | return idefloppy_issue_pc(drive, pc); | 340 | return idefloppy_issue_pc(drive, pc); |
339 | } | 341 | } |
340 | 342 | ||
341 | /* | 343 | /* |
342 | * Look at the flexible disk page parameters. We ignore the CHS capacity | 344 | * Look at the flexible disk page parameters. We ignore the CHS capacity |
343 | * parameters and use the LBA parameters instead. | 345 | * parameters and use the LBA parameters instead. |
344 | */ | 346 | */ |
345 | static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive, | 347 | static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive, |
346 | struct ide_atapi_pc *pc) | 348 | struct ide_atapi_pc *pc) |
347 | { | 349 | { |
348 | struct ide_disk_obj *floppy = drive->driver_data; | 350 | struct ide_disk_obj *floppy = drive->driver_data; |
349 | struct gendisk *disk = floppy->disk; | 351 | struct gendisk *disk = floppy->disk; |
350 | u8 *page; | 352 | u8 *page; |
351 | int capacity, lba_capacity; | 353 | int capacity, lba_capacity; |
352 | u16 transfer_rate, sector_size, cyls, rpm; | 354 | u16 transfer_rate, sector_size, cyls, rpm; |
353 | u8 heads, sectors; | 355 | u8 heads, sectors; |
354 | 356 | ||
355 | ide_floppy_create_mode_sense_cmd(pc, IDEFLOPPY_FLEXIBLE_DISK_PAGE); | 357 | ide_floppy_create_mode_sense_cmd(pc, IDEFLOPPY_FLEXIBLE_DISK_PAGE); |
356 | 358 | ||
357 | if (ide_queue_pc_tail(drive, disk, pc)) { | 359 | if (ide_queue_pc_tail(drive, disk, pc)) { |
358 | printk(KERN_ERR PFX "Can't get flexible disk page params\n"); | 360 | printk(KERN_ERR PFX "Can't get flexible disk page params\n"); |
359 | return 1; | 361 | return 1; |
360 | } | 362 | } |
361 | 363 | ||
362 | if (pc->buf[3] & 0x80) | 364 | if (pc->buf[3] & 0x80) |
363 | drive->dev_flags |= IDE_DFLAG_WP; | 365 | drive->dev_flags |= IDE_DFLAG_WP; |
364 | else | 366 | else |
365 | drive->dev_flags &= ~IDE_DFLAG_WP; | 367 | drive->dev_flags &= ~IDE_DFLAG_WP; |
366 | 368 | ||
367 | set_disk_ro(disk, !!(drive->dev_flags & IDE_DFLAG_WP)); | 369 | set_disk_ro(disk, !!(drive->dev_flags & IDE_DFLAG_WP)); |
368 | 370 | ||
369 | page = &pc->buf[8]; | 371 | page = &pc->buf[8]; |
370 | 372 | ||
371 | transfer_rate = be16_to_cpup((__be16 *)&pc->buf[8 + 2]); | 373 | transfer_rate = be16_to_cpup((__be16 *)&pc->buf[8 + 2]); |
372 | sector_size = be16_to_cpup((__be16 *)&pc->buf[8 + 6]); | 374 | sector_size = be16_to_cpup((__be16 *)&pc->buf[8 + 6]); |
373 | cyls = be16_to_cpup((__be16 *)&pc->buf[8 + 8]); | 375 | cyls = be16_to_cpup((__be16 *)&pc->buf[8 + 8]); |
374 | rpm = be16_to_cpup((__be16 *)&pc->buf[8 + 28]); | 376 | rpm = be16_to_cpup((__be16 *)&pc->buf[8 + 28]); |
375 | heads = pc->buf[8 + 4]; | 377 | heads = pc->buf[8 + 4]; |
376 | sectors = pc->buf[8 + 5]; | 378 | sectors = pc->buf[8 + 5]; |
377 | 379 | ||
378 | capacity = cyls * heads * sectors * sector_size; | 380 | capacity = cyls * heads * sectors * sector_size; |
379 | 381 | ||
380 | if (memcmp(page, &floppy->flexible_disk_page, 32)) | 382 | if (memcmp(page, &floppy->flexible_disk_page, 32)) |
381 | printk(KERN_INFO PFX "%s: %dkB, %d/%d/%d CHS, %d kBps, " | 383 | printk(KERN_INFO PFX "%s: %dkB, %d/%d/%d CHS, %d kBps, " |
382 | "%d sector size, %d rpm\n", | 384 | "%d sector size, %d rpm\n", |
383 | drive->name, capacity / 1024, cyls, heads, | 385 | drive->name, capacity / 1024, cyls, heads, |
384 | sectors, transfer_rate / 8, sector_size, rpm); | 386 | sectors, transfer_rate / 8, sector_size, rpm); |
385 | 387 | ||
386 | memcpy(&floppy->flexible_disk_page, page, 32); | 388 | memcpy(&floppy->flexible_disk_page, page, 32); |
387 | drive->bios_cyl = cyls; | 389 | drive->bios_cyl = cyls; |
388 | drive->bios_head = heads; | 390 | drive->bios_head = heads; |
389 | drive->bios_sect = sectors; | 391 | drive->bios_sect = sectors; |
390 | lba_capacity = floppy->blocks * floppy->block_size; | 392 | lba_capacity = floppy->blocks * floppy->block_size; |
391 | 393 | ||
392 | if (capacity < lba_capacity) { | 394 | if (capacity < lba_capacity) { |
393 | printk(KERN_NOTICE PFX "%s: The disk reports a capacity of %d " | 395 | printk(KERN_NOTICE PFX "%s: The disk reports a capacity of %d " |
394 | "bytes, but the drive only handles %d\n", | 396 | "bytes, but the drive only handles %d\n", |
395 | drive->name, lba_capacity, capacity); | 397 | drive->name, lba_capacity, capacity); |
396 | floppy->blocks = floppy->block_size ? | 398 | floppy->blocks = floppy->block_size ? |
397 | capacity / floppy->block_size : 0; | 399 | capacity / floppy->block_size : 0; |
398 | drive->capacity64 = floppy->blocks * floppy->bs_factor; | 400 | drive->capacity64 = floppy->blocks * floppy->bs_factor; |
399 | } | 401 | } |
400 | 402 | ||
401 | return 0; | 403 | return 0; |
402 | } | 404 | } |
403 | 405 | ||
404 | /* | 406 | /* |
405 | * Determine if a media is present in the floppy drive, and if so, its LBA | 407 | * Determine if a media is present in the floppy drive, and if so, its LBA |
406 | * capacity. | 408 | * capacity. |
407 | */ | 409 | */ |
408 | static int ide_floppy_get_capacity(ide_drive_t *drive) | 410 | static int ide_floppy_get_capacity(ide_drive_t *drive) |
409 | { | 411 | { |
410 | struct ide_disk_obj *floppy = drive->driver_data; | 412 | struct ide_disk_obj *floppy = drive->driver_data; |
411 | struct gendisk *disk = floppy->disk; | 413 | struct gendisk *disk = floppy->disk; |
412 | struct ide_atapi_pc pc; | 414 | struct ide_atapi_pc pc; |
413 | u8 *cap_desc; | 415 | u8 *cap_desc; |
414 | u8 header_len, desc_cnt; | 416 | u8 header_len, desc_cnt; |
415 | int i, rc = 1, blocks, length; | 417 | int i, rc = 1, blocks, length; |
416 | 418 | ||
417 | drive->bios_cyl = 0; | 419 | drive->bios_cyl = 0; |
418 | drive->bios_head = drive->bios_sect = 0; | 420 | drive->bios_head = drive->bios_sect = 0; |
419 | floppy->blocks = 0; | 421 | floppy->blocks = 0; |
420 | floppy->bs_factor = 1; | 422 | floppy->bs_factor = 1; |
421 | drive->capacity64 = 0; | 423 | drive->capacity64 = 0; |
422 | 424 | ||
423 | ide_floppy_create_read_capacity_cmd(&pc); | 425 | ide_floppy_create_read_capacity_cmd(&pc); |
424 | if (ide_queue_pc_tail(drive, disk, &pc)) { | 426 | if (ide_queue_pc_tail(drive, disk, &pc)) { |
425 | printk(KERN_ERR PFX "Can't get floppy parameters\n"); | 427 | printk(KERN_ERR PFX "Can't get floppy parameters\n"); |
426 | return 1; | 428 | return 1; |
427 | } | 429 | } |
428 | header_len = pc.buf[3]; | 430 | header_len = pc.buf[3]; |
429 | cap_desc = &pc.buf[4]; | 431 | cap_desc = &pc.buf[4]; |
430 | desc_cnt = header_len / 8; /* capacity descriptor of 8 bytes */ | 432 | desc_cnt = header_len / 8; /* capacity descriptor of 8 bytes */ |
431 | 433 | ||
432 | for (i = 0; i < desc_cnt; i++) { | 434 | for (i = 0; i < desc_cnt; i++) { |
433 | unsigned int desc_start = 4 + i*8; | 435 | unsigned int desc_start = 4 + i*8; |
434 | 436 | ||
435 | blocks = be32_to_cpup((__be32 *)&pc.buf[desc_start]); | 437 | blocks = be32_to_cpup((__be32 *)&pc.buf[desc_start]); |
436 | length = be16_to_cpup((__be16 *)&pc.buf[desc_start + 6]); | 438 | length = be16_to_cpup((__be16 *)&pc.buf[desc_start + 6]); |
437 | 439 | ||
438 | ide_debug_log(IDE_DBG_PROBE, "Descriptor %d: %dkB, %d blocks, " | 440 | ide_debug_log(IDE_DBG_PROBE, "Descriptor %d: %dkB, %d blocks, " |
439 | "%d sector size\n", | 441 | "%d sector size\n", |
440 | i, blocks * length / 1024, blocks, length); | 442 | i, blocks * length / 1024, blocks, length); |
441 | 443 | ||
442 | if (i) | 444 | if (i) |
443 | continue; | 445 | continue; |
444 | /* | 446 | /* |
445 | * the code below is valid only for the 1st descriptor, ie i=0 | 447 | * the code below is valid only for the 1st descriptor, ie i=0 |
446 | */ | 448 | */ |
447 | 449 | ||
448 | switch (pc.buf[desc_start + 4] & 0x03) { | 450 | switch (pc.buf[desc_start + 4] & 0x03) { |
449 | /* Clik! drive returns this instead of CAPACITY_CURRENT */ | 451 | /* Clik! drive returns this instead of CAPACITY_CURRENT */ |
450 | case CAPACITY_UNFORMATTED: | 452 | case CAPACITY_UNFORMATTED: |
451 | if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE)) | 453 | if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE)) |
452 | /* | 454 | /* |
453 | * If it is not a clik drive, break out | 455 | * If it is not a clik drive, break out |
454 | * (maintains previous driver behaviour) | 456 | * (maintains previous driver behaviour) |
455 | */ | 457 | */ |
456 | break; | 458 | break; |
457 | case CAPACITY_CURRENT: | 459 | case CAPACITY_CURRENT: |
458 | /* Normal Zip/LS-120 disks */ | 460 | /* Normal Zip/LS-120 disks */ |
459 | if (memcmp(cap_desc, &floppy->cap_desc, 8)) | 461 | if (memcmp(cap_desc, &floppy->cap_desc, 8)) |
460 | printk(KERN_INFO PFX "%s: %dkB, %d blocks, %d " | 462 | printk(KERN_INFO PFX "%s: %dkB, %d blocks, %d " |
461 | "sector size\n", | 463 | "sector size\n", |
462 | drive->name, blocks * length / 1024, | 464 | drive->name, blocks * length / 1024, |
463 | blocks, length); | 465 | blocks, length); |
464 | memcpy(&floppy->cap_desc, cap_desc, 8); | 466 | memcpy(&floppy->cap_desc, cap_desc, 8); |
465 | 467 | ||
466 | if (!length || length % 512) { | 468 | if (!length || length % 512) { |
467 | printk(KERN_NOTICE PFX "%s: %d bytes block size" | 469 | printk(KERN_NOTICE PFX "%s: %d bytes block size" |
468 | " not supported\n", drive->name, length); | 470 | " not supported\n", drive->name, length); |
469 | } else { | 471 | } else { |
470 | floppy->blocks = blocks; | 472 | floppy->blocks = blocks; |
471 | floppy->block_size = length; | 473 | floppy->block_size = length; |
472 | floppy->bs_factor = length / 512; | 474 | floppy->bs_factor = length / 512; |
473 | if (floppy->bs_factor != 1) | 475 | if (floppy->bs_factor != 1) |
474 | printk(KERN_NOTICE PFX "%s: Warning: " | 476 | printk(KERN_NOTICE PFX "%s: Warning: " |
475 | "non 512 bytes block size not " | 477 | "non 512 bytes block size not " |
476 | "fully supported\n", | 478 | "fully supported\n", |
477 | drive->name); | 479 | drive->name); |
478 | drive->capacity64 = | 480 | drive->capacity64 = |
479 | floppy->blocks * floppy->bs_factor; | 481 | floppy->blocks * floppy->bs_factor; |
480 | rc = 0; | 482 | rc = 0; |
481 | } | 483 | } |
482 | break; | 484 | break; |
483 | case CAPACITY_NO_CARTRIDGE: | 485 | case CAPACITY_NO_CARTRIDGE: |
484 | /* | 486 | /* |
485 | * This is a KERN_ERR so it appears on screen | 487 | * This is a KERN_ERR so it appears on screen |
486 | * for the user to see | 488 | * for the user to see |
487 | */ | 489 | */ |
488 | printk(KERN_ERR PFX "%s: No disk in drive\n", | 490 | printk(KERN_ERR PFX "%s: No disk in drive\n", |
489 | drive->name); | 491 | drive->name); |
490 | break; | 492 | break; |
491 | case CAPACITY_INVALID: | 493 | case CAPACITY_INVALID: |
492 | printk(KERN_ERR PFX "%s: Invalid capacity for disk " | 494 | printk(KERN_ERR PFX "%s: Invalid capacity for disk " |
493 | "in drive\n", drive->name); | 495 | "in drive\n", drive->name); |
494 | break; | 496 | break; |
495 | } | 497 | } |
496 | ide_debug_log(IDE_DBG_PROBE, "Descriptor 0 Code: %d\n", | 498 | ide_debug_log(IDE_DBG_PROBE, "Descriptor 0 Code: %d\n", |
497 | pc.buf[desc_start + 4] & 0x03); | 499 | pc.buf[desc_start + 4] & 0x03); |
498 | } | 500 | } |
499 | 501 | ||
500 | /* Clik! disk does not support get_flexible_disk_page */ | 502 | /* Clik! disk does not support get_flexible_disk_page */ |
501 | if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE)) | 503 | if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE)) |
502 | (void) ide_floppy_get_flexible_disk_page(drive, &pc); | 504 | (void) ide_floppy_get_flexible_disk_page(drive, &pc); |
503 | 505 | ||
504 | return rc; | 506 | return rc; |
505 | } | 507 | } |
506 | 508 | ||
507 | static void ide_floppy_setup(ide_drive_t *drive) | 509 | static void ide_floppy_setup(ide_drive_t *drive) |
508 | { | 510 | { |
509 | struct ide_disk_obj *floppy = drive->driver_data; | 511 | struct ide_disk_obj *floppy = drive->driver_data; |
510 | u16 *id = drive->id; | 512 | u16 *id = drive->id; |
511 | 513 | ||
512 | drive->pc_callback = ide_floppy_callback; | 514 | drive->pc_callback = ide_floppy_callback; |
513 | drive->pc_update_buffers = idefloppy_update_buffers; | 515 | drive->pc_update_buffers = idefloppy_update_buffers; |
514 | drive->pc_io_buffers = ide_io_buffers; | 516 | drive->pc_io_buffers = ide_io_buffers; |
515 | 517 | ||
516 | /* | 518 | /* |
517 | * We used to check revisions here. At this point however I'm giving up. | 519 | * We used to check revisions here. At this point however I'm giving up. |
518 | * Just assume they are all broken, its easier. | 520 | * Just assume they are all broken, its easier. |
519 | * | 521 | * |
520 | * The actual reason for the workarounds was likely a driver bug after | 522 | * The actual reason for the workarounds was likely a driver bug after |
521 | * all rather than a firmware bug, and the workaround below used to hide | 523 | * all rather than a firmware bug, and the workaround below used to hide |
522 | * it. It should be fixed as of version 1.9, but to be on the safe side | 524 | * it. It should be fixed as of version 1.9, but to be on the safe side |
523 | * we'll leave the limitation below for the 2.2.x tree. | 525 | * we'll leave the limitation below for the 2.2.x tree. |
524 | */ | 526 | */ |
525 | if (!strncmp((char *)&id[ATA_ID_PROD], "IOMEGA ZIP 100 ATAPI", 20)) { | 527 | if (!strncmp((char *)&id[ATA_ID_PROD], "IOMEGA ZIP 100 ATAPI", 20)) { |
526 | drive->atapi_flags |= IDE_AFLAG_ZIP_DRIVE; | 528 | drive->atapi_flags |= IDE_AFLAG_ZIP_DRIVE; |
527 | /* This value will be visible in the /proc/ide/hdx/settings */ | 529 | /* This value will be visible in the /proc/ide/hdx/settings */ |
528 | drive->pc_delay = IDEFLOPPY_PC_DELAY; | 530 | drive->pc_delay = IDEFLOPPY_PC_DELAY; |
529 | blk_queue_max_sectors(drive->queue, 64); | 531 | blk_queue_max_sectors(drive->queue, 64); |
530 | } | 532 | } |
531 | 533 | ||
532 | /* | 534 | /* |
533 | * Guess what? The IOMEGA Clik! drive also needs the above fix. It makes | 535 | * Guess what? The IOMEGA Clik! drive also needs the above fix. It makes |
534 | * nasty clicking noises without it, so please don't remove this. | 536 | * nasty clicking noises without it, so please don't remove this. |
535 | */ | 537 | */ |
536 | if (strncmp((char *)&id[ATA_ID_PROD], "IOMEGA Clik!", 11) == 0) { | 538 | if (strncmp((char *)&id[ATA_ID_PROD], "IOMEGA Clik!", 11) == 0) { |
537 | blk_queue_max_sectors(drive->queue, 64); | 539 | blk_queue_max_sectors(drive->queue, 64); |
538 | drive->atapi_flags |= IDE_AFLAG_CLIK_DRIVE; | 540 | drive->atapi_flags |= IDE_AFLAG_CLIK_DRIVE; |
539 | /* IOMEGA Clik! drives do not support lock/unlock commands */ | 541 | /* IOMEGA Clik! drives do not support lock/unlock commands */ |
540 | drive->dev_flags &= ~IDE_DFLAG_DOORLOCKING; | 542 | drive->dev_flags &= ~IDE_DFLAG_DOORLOCKING; |
541 | } | 543 | } |
542 | 544 | ||
543 | (void) ide_floppy_get_capacity(drive); | 545 | (void) ide_floppy_get_capacity(drive); |
544 | 546 | ||
545 | ide_proc_register_driver(drive, floppy->driver); | 547 | ide_proc_register_driver(drive, floppy->driver); |
546 | 548 | ||
547 | drive->dev_flags |= IDE_DFLAG_ATTACH; | 549 | drive->dev_flags |= IDE_DFLAG_ATTACH; |
548 | } | 550 | } |
549 | 551 | ||
550 | static void ide_floppy_flush(ide_drive_t *drive) | 552 | static void ide_floppy_flush(ide_drive_t *drive) |
551 | { | 553 | { |
552 | } | 554 | } |
553 | 555 | ||
554 | static int ide_floppy_init_media(ide_drive_t *drive, struct gendisk *disk) | 556 | static int ide_floppy_init_media(ide_drive_t *drive, struct gendisk *disk) |
555 | { | 557 | { |
556 | int ret = 0; | 558 | int ret = 0; |
557 | 559 | ||
558 | if (ide_do_test_unit_ready(drive, disk)) | 560 | if (ide_do_test_unit_ready(drive, disk)) |
559 | ide_do_start_stop(drive, disk, 1); | 561 | ide_do_start_stop(drive, disk, 1); |
560 | 562 | ||
561 | ret = ide_floppy_get_capacity(drive); | 563 | ret = ide_floppy_get_capacity(drive); |
562 | 564 | ||
563 | set_capacity(disk, ide_gd_capacity(drive)); | 565 | set_capacity(disk, ide_gd_capacity(drive)); |
564 | 566 | ||
565 | return ret; | 567 | return ret; |
566 | } | 568 | } |
567 | 569 | ||
568 | const struct ide_disk_ops ide_atapi_disk_ops = { | 570 | const struct ide_disk_ops ide_atapi_disk_ops = { |
569 | .check = ide_check_atapi_device, | 571 | .check = ide_check_atapi_device, |
570 | .get_capacity = ide_floppy_get_capacity, | 572 | .get_capacity = ide_floppy_get_capacity, |
571 | .setup = ide_floppy_setup, | 573 | .setup = ide_floppy_setup, |
572 | .flush = ide_floppy_flush, | 574 | .flush = ide_floppy_flush, |
573 | .init_media = ide_floppy_init_media, | 575 | .init_media = ide_floppy_init_media, |
574 | .set_doorlock = ide_set_media_lock, | 576 | .set_doorlock = ide_set_media_lock, |
575 | .do_request = ide_floppy_do_request, | 577 | .do_request = ide_floppy_do_request, |
576 | .end_request = ide_floppy_end_request, | 578 | .end_request = ide_floppy_end_request, |
577 | .ioctl = ide_floppy_ioctl, | 579 | .ioctl = ide_floppy_ioctl, |
578 | }; | 580 | }; |
579 | 581 |