diff options
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/Kconfig | 10 | ||||
-rw-r--r-- | drivers/block/Makefile | 1 | ||||
-rw-r--r-- | drivers/block/aoe/aoenet.c | 2 | ||||
-rw-r--r-- | drivers/block/cciss.c | 274 | ||||
-rw-r--r-- | drivers/block/cciss_scsi.c | 12 | ||||
-rw-r--r-- | drivers/block/cryptoloop.c | 1 | ||||
-rw-r--r-- | drivers/block/floppy.c | 5 | ||||
-rw-r--r-- | drivers/block/loop.c | 26 | ||||
-rw-r--r-- | drivers/block/nbd.c | 12 | ||||
-rw-r--r-- | drivers/block/pktcdvd.c | 21 | ||||
-rw-r--r-- | drivers/block/ps2esdi.c | 1079 | ||||
-rw-r--r-- | drivers/block/sx8.c | 6 | ||||
-rw-r--r-- | drivers/block/ub.c | 38 | ||||
-rw-r--r-- | drivers/block/viodasd.c | 5 | ||||
-rw-r--r-- | drivers/block/virtio_blk.c | 1 | ||||
-rw-r--r-- | drivers/block/xen-blkfront.c | 18 |
16 files changed, 278 insertions, 1233 deletions
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index b6d230b3209f..0d1d2133d9bc 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig | |||
@@ -44,16 +44,6 @@ config MAC_FLOPPY | |||
44 | If you have a SWIM-3 (Super Woz Integrated Machine 3; from Apple) | 44 | If you have a SWIM-3 (Super Woz Integrated Machine 3; from Apple) |
45 | floppy controller, say Y here. Most commonly found in PowerMacs. | 45 | floppy controller, say Y here. Most commonly found in PowerMacs. |
46 | 46 | ||
47 | config BLK_DEV_PS2 | ||
48 | tristate "PS/2 ESDI hard disk support" | ||
49 | depends on MCA && MCA_LEGACY && BROKEN | ||
50 | help | ||
51 | Say Y here if you have a PS/2 machine with a MCA bus and an ESDI | ||
52 | hard disk. | ||
53 | |||
54 | To compile this driver as a module, choose M here: the | ||
55 | module will be called ps2esdi. | ||
56 | |||
57 | config AMIGA_Z2RAM | 47 | config AMIGA_Z2RAM |
58 | tristate "Amiga Zorro II ramdisk support" | 48 | tristate "Amiga Zorro II ramdisk support" |
59 | depends on ZORRO | 49 | depends on ZORRO |
diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 01c972415cb2..5e584306be99 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile | |||
@@ -13,7 +13,6 @@ obj-$(CONFIG_ATARI_FLOPPY) += ataflop.o | |||
13 | obj-$(CONFIG_AMIGA_Z2RAM) += z2ram.o | 13 | obj-$(CONFIG_AMIGA_Z2RAM) += z2ram.o |
14 | obj-$(CONFIG_BLK_DEV_RAM) += brd.o | 14 | obj-$(CONFIG_BLK_DEV_RAM) += brd.o |
15 | obj-$(CONFIG_BLK_DEV_LOOP) += loop.o | 15 | obj-$(CONFIG_BLK_DEV_LOOP) += loop.o |
16 | obj-$(CONFIG_BLK_DEV_PS2) += ps2esdi.o | ||
17 | obj-$(CONFIG_BLK_DEV_XD) += xd.o | 16 | obj-$(CONFIG_BLK_DEV_XD) += xd.o |
18 | obj-$(CONFIG_BLK_CPQ_DA) += cpqarray.o | 17 | obj-$(CONFIG_BLK_CPQ_DA) += cpqarray.o |
19 | obj-$(CONFIG_BLK_CPQ_CISS_DA) += cciss.o | 18 | obj-$(CONFIG_BLK_CPQ_CISS_DA) += cciss.o |
diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c index 8460ef736d56..18d243c73eee 100644 --- a/drivers/block/aoe/aoenet.c +++ b/drivers/block/aoe/aoenet.c | |||
@@ -115,7 +115,7 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, | |||
115 | struct aoe_hdr *h; | 115 | struct aoe_hdr *h; |
116 | u32 n; | 116 | u32 n; |
117 | 117 | ||
118 | if (ifp->nd_net != &init_net) | 118 | if (dev_net(ifp) != &init_net) |
119 | goto exit; | 119 | goto exit; |
120 | 120 | ||
121 | skb = skb_share_check(skb, GFP_ATOMIC); | 121 | skb = skb_share_check(skb, GFP_ATOMIC); |
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 9715be3f2487..cf6083a1f928 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/blkpg.h> | 33 | #include <linux/blkpg.h> |
34 | #include <linux/timer.h> | 34 | #include <linux/timer.h> |
35 | #include <linux/proc_fs.h> | 35 | #include <linux/proc_fs.h> |
36 | #include <linux/seq_file.h> | ||
36 | #include <linux/init.h> | 37 | #include <linux/init.h> |
37 | #include <linux/hdreg.h> | 38 | #include <linux/hdreg.h> |
38 | #include <linux/spinlock.h> | 39 | #include <linux/spinlock.h> |
@@ -49,6 +50,7 @@ | |||
49 | #include <scsi/sg.h> | 50 | #include <scsi/sg.h> |
50 | #include <scsi/scsi_ioctl.h> | 51 | #include <scsi/scsi_ioctl.h> |
51 | #include <linux/cdrom.h> | 52 | #include <linux/cdrom.h> |
53 | #include <linux/scatterlist.h> | ||
52 | 54 | ||
53 | #define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin)) | 55 | #define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin)) |
54 | #define DRIVER_NAME "HP CISS Driver (v 3.6.14)" | 56 | #define DRIVER_NAME "HP CISS Driver (v 3.6.14)" |
@@ -131,7 +133,6 @@ static struct board_type products[] = { | |||
131 | /*define how many times we will try a command because of bus resets */ | 133 | /*define how many times we will try a command because of bus resets */ |
132 | #define MAX_CMD_RETRIES 3 | 134 | #define MAX_CMD_RETRIES 3 |
133 | 135 | ||
134 | #define READ_AHEAD 1024 | ||
135 | #define MAX_CTLR 32 | 136 | #define MAX_CTLR 32 |
136 | 137 | ||
137 | /* Originally cciss driver only supports 8 major numbers */ | 138 | /* Originally cciss driver only supports 8 major numbers */ |
@@ -174,8 +175,6 @@ static int sendcmd_withirq(__u8 cmd, int ctlr, void *buff, size_t size, | |||
174 | static void fail_all_cmds(unsigned long ctlr); | 175 | static void fail_all_cmds(unsigned long ctlr); |
175 | 176 | ||
176 | #ifdef CONFIG_PROC_FS | 177 | #ifdef CONFIG_PROC_FS |
177 | static int cciss_proc_get_info(char *buffer, char **start, off_t offset, | ||
178 | int length, int *eof, void *data); | ||
179 | static void cciss_procinit(int i); | 178 | static void cciss_procinit(int i); |
180 | #else | 179 | #else |
181 | static void cciss_procinit(int i) | 180 | static void cciss_procinit(int i) |
@@ -240,24 +239,46 @@ static inline CommandList_struct *removeQ(CommandList_struct **Qptr, | |||
240 | */ | 239 | */ |
241 | #define ENG_GIG 1000000000 | 240 | #define ENG_GIG 1000000000 |
242 | #define ENG_GIG_FACTOR (ENG_GIG/512) | 241 | #define ENG_GIG_FACTOR (ENG_GIG/512) |
242 | #define ENGAGE_SCSI "engage scsi" | ||
243 | static const char *raid_label[] = { "0", "4", "1(1+0)", "5", "5+1", "ADG", | 243 | static const char *raid_label[] = { "0", "4", "1(1+0)", "5", "5+1", "ADG", |
244 | "UNKNOWN" | 244 | "UNKNOWN" |
245 | }; | 245 | }; |
246 | 246 | ||
247 | static struct proc_dir_entry *proc_cciss; | 247 | static struct proc_dir_entry *proc_cciss; |
248 | 248 | ||
249 | static int cciss_proc_get_info(char *buffer, char **start, off_t offset, | 249 | static void cciss_seq_show_header(struct seq_file *seq) |
250 | int length, int *eof, void *data) | ||
251 | { | 250 | { |
252 | off_t pos = 0; | 251 | ctlr_info_t *h = seq->private; |
253 | off_t len = 0; | 252 | |
254 | int size, i, ctlr; | 253 | seq_printf(seq, "%s: HP %s Controller\n" |
255 | ctlr_info_t *h = (ctlr_info_t *) data; | 254 | "Board ID: 0x%08lx\n" |
256 | drive_info_struct *drv; | 255 | "Firmware Version: %c%c%c%c\n" |
257 | unsigned long flags; | 256 | "IRQ: %d\n" |
258 | sector_t vol_sz, vol_sz_frac; | 257 | "Logical drives: %d\n" |
258 | "Current Q depth: %d\n" | ||
259 | "Current # commands on controller: %d\n" | ||
260 | "Max Q depth since init: %d\n" | ||
261 | "Max # commands on controller since init: %d\n" | ||
262 | "Max SG entries since init: %d\n", | ||
263 | h->devname, | ||
264 | h->product_name, | ||
265 | (unsigned long)h->board_id, | ||
266 | h->firm_ver[0], h->firm_ver[1], h->firm_ver[2], | ||
267 | h->firm_ver[3], (unsigned int)h->intr[SIMPLE_MODE_INT], | ||
268 | h->num_luns, | ||
269 | h->Qdepth, h->commands_outstanding, | ||
270 | h->maxQsinceinit, h->max_outstanding, h->maxSG); | ||
259 | 271 | ||
260 | ctlr = h->ctlr; | 272 | #ifdef CONFIG_CISS_SCSI_TAPE |
273 | cciss_seq_tape_report(seq, h->ctlr); | ||
274 | #endif /* CONFIG_CISS_SCSI_TAPE */ | ||
275 | } | ||
276 | |||
277 | static void *cciss_seq_start(struct seq_file *seq, loff_t *pos) | ||
278 | { | ||
279 | ctlr_info_t *h = seq->private; | ||
280 | unsigned ctlr = h->ctlr; | ||
281 | unsigned long flags; | ||
261 | 282 | ||
262 | /* prevent displaying bogus info during configuration | 283 | /* prevent displaying bogus info during configuration |
263 | * or deconfiguration of a logical volume | 284 | * or deconfiguration of a logical volume |
@@ -265,115 +286,155 @@ static int cciss_proc_get_info(char *buffer, char **start, off_t offset, | |||
265 | spin_lock_irqsave(CCISS_LOCK(ctlr), flags); | 286 | spin_lock_irqsave(CCISS_LOCK(ctlr), flags); |
266 | if (h->busy_configuring) { | 287 | if (h->busy_configuring) { |
267 | spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); | 288 | spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); |
268 | return -EBUSY; | 289 | return ERR_PTR(-EBUSY); |
269 | } | 290 | } |
270 | h->busy_configuring = 1; | 291 | h->busy_configuring = 1; |
271 | spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); | 292 | spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); |
272 | 293 | ||
273 | size = sprintf(buffer, "%s: HP %s Controller\n" | 294 | if (*pos == 0) |
274 | "Board ID: 0x%08lx\n" | 295 | cciss_seq_show_header(seq); |
275 | "Firmware Version: %c%c%c%c\n" | ||
276 | "IRQ: %d\n" | ||
277 | "Logical drives: %d\n" | ||
278 | "Max sectors: %d\n" | ||
279 | "Current Q depth: %d\n" | ||
280 | "Current # commands on controller: %d\n" | ||
281 | "Max Q depth since init: %d\n" | ||
282 | "Max # commands on controller since init: %d\n" | ||
283 | "Max SG entries since init: %d\n\n", | ||
284 | h->devname, | ||
285 | h->product_name, | ||
286 | (unsigned long)h->board_id, | ||
287 | h->firm_ver[0], h->firm_ver[1], h->firm_ver[2], | ||
288 | h->firm_ver[3], (unsigned int)h->intr[SIMPLE_MODE_INT], | ||
289 | h->num_luns, | ||
290 | h->cciss_max_sectors, | ||
291 | h->Qdepth, h->commands_outstanding, | ||
292 | h->maxQsinceinit, h->max_outstanding, h->maxSG); | ||
293 | |||
294 | pos += size; | ||
295 | len += size; | ||
296 | cciss_proc_tape_report(ctlr, buffer, &pos, &len); | ||
297 | for (i = 0; i <= h->highest_lun; i++) { | ||
298 | |||
299 | drv = &h->drv[i]; | ||
300 | if (drv->heads == 0) | ||
301 | continue; | ||
302 | 296 | ||
303 | vol_sz = drv->nr_blocks; | 297 | return pos; |
304 | vol_sz_frac = sector_div(vol_sz, ENG_GIG_FACTOR); | 298 | } |
305 | vol_sz_frac *= 100; | 299 | |
306 | sector_div(vol_sz_frac, ENG_GIG_FACTOR); | 300 | static int cciss_seq_show(struct seq_file *seq, void *v) |
301 | { | ||
302 | sector_t vol_sz, vol_sz_frac; | ||
303 | ctlr_info_t *h = seq->private; | ||
304 | unsigned ctlr = h->ctlr; | ||
305 | loff_t *pos = v; | ||
306 | drive_info_struct *drv = &h->drv[*pos]; | ||
307 | |||
308 | if (*pos > h->highest_lun) | ||
309 | return 0; | ||
310 | |||
311 | if (drv->heads == 0) | ||
312 | return 0; | ||
313 | |||
314 | vol_sz = drv->nr_blocks; | ||
315 | vol_sz_frac = sector_div(vol_sz, ENG_GIG_FACTOR); | ||
316 | vol_sz_frac *= 100; | ||
317 | sector_div(vol_sz_frac, ENG_GIG_FACTOR); | ||
318 | |||
319 | if (drv->raid_level > 5) | ||
320 | drv->raid_level = RAID_UNKNOWN; | ||
321 | seq_printf(seq, "cciss/c%dd%d:" | ||
322 | "\t%4u.%02uGB\tRAID %s\n", | ||
323 | ctlr, (int) *pos, (int)vol_sz, (int)vol_sz_frac, | ||
324 | raid_label[drv->raid_level]); | ||
325 | return 0; | ||
326 | } | ||
327 | |||
328 | static void *cciss_seq_next(struct seq_file *seq, void *v, loff_t *pos) | ||
329 | { | ||
330 | ctlr_info_t *h = seq->private; | ||
331 | |||
332 | if (*pos > h->highest_lun) | ||
333 | return NULL; | ||
334 | *pos += 1; | ||
335 | |||
336 | return pos; | ||
337 | } | ||
338 | |||
339 | static void cciss_seq_stop(struct seq_file *seq, void *v) | ||
340 | { | ||
341 | ctlr_info_t *h = seq->private; | ||
342 | |||
343 | /* Only reset h->busy_configuring if we succeeded in setting | ||
344 | * it during cciss_seq_start. */ | ||
345 | if (v == ERR_PTR(-EBUSY)) | ||
346 | return; | ||
307 | 347 | ||
308 | if (drv->raid_level > 5) | ||
309 | drv->raid_level = RAID_UNKNOWN; | ||
310 | size = sprintf(buffer + len, "cciss/c%dd%d:" | ||
311 | "\t%4u.%02uGB\tRAID %s\n", | ||
312 | ctlr, i, (int)vol_sz, (int)vol_sz_frac, | ||
313 | raid_label[drv->raid_level]); | ||
314 | pos += size; | ||
315 | len += size; | ||
316 | } | ||
317 | |||
318 | *eof = 1; | ||
319 | *start = buffer + offset; | ||
320 | len -= offset; | ||
321 | if (len > length) | ||
322 | len = length; | ||
323 | h->busy_configuring = 0; | 348 | h->busy_configuring = 0; |
324 | return len; | ||
325 | } | 349 | } |
326 | 350 | ||
327 | static int | 351 | static struct seq_operations cciss_seq_ops = { |
328 | cciss_proc_write(struct file *file, const char __user *buffer, | 352 | .start = cciss_seq_start, |
329 | unsigned long count, void *data) | 353 | .show = cciss_seq_show, |
354 | .next = cciss_seq_next, | ||
355 | .stop = cciss_seq_stop, | ||
356 | }; | ||
357 | |||
358 | static int cciss_seq_open(struct inode *inode, struct file *file) | ||
330 | { | 359 | { |
331 | unsigned char cmd[80]; | 360 | int ret = seq_open(file, &cciss_seq_ops); |
332 | int len; | 361 | struct seq_file *seq = file->private_data; |
333 | #ifdef CONFIG_CISS_SCSI_TAPE | 362 | |
334 | ctlr_info_t *h = (ctlr_info_t *) data; | 363 | if (!ret) |
335 | int rc; | 364 | seq->private = PDE(inode)->data; |
365 | |||
366 | return ret; | ||
367 | } | ||
368 | |||
369 | static ssize_t | ||
370 | cciss_proc_write(struct file *file, const char __user *buf, | ||
371 | size_t length, loff_t *ppos) | ||
372 | { | ||
373 | int err; | ||
374 | char *buffer; | ||
375 | |||
376 | #ifndef CONFIG_CISS_SCSI_TAPE | ||
377 | return -EINVAL; | ||
336 | #endif | 378 | #endif |
337 | 379 | ||
338 | if (count > sizeof(cmd) - 1) | 380 | if (!buf || length > PAGE_SIZE - 1) |
339 | return -EINVAL; | 381 | return -EINVAL; |
340 | if (copy_from_user(cmd, buffer, count)) | 382 | |
341 | return -EFAULT; | 383 | buffer = (char *)__get_free_page(GFP_KERNEL); |
342 | cmd[count] = '\0'; | 384 | if (!buffer) |
343 | len = strlen(cmd); // above 3 lines ensure safety | 385 | return -ENOMEM; |
344 | if (len && cmd[len - 1] == '\n') | 386 | |
345 | cmd[--len] = '\0'; | 387 | err = -EFAULT; |
346 | # ifdef CONFIG_CISS_SCSI_TAPE | 388 | if (copy_from_user(buffer, buf, length)) |
347 | if (strcmp("engage scsi", cmd) == 0) { | 389 | goto out; |
390 | buffer[length] = '\0'; | ||
391 | |||
392 | #ifdef CONFIG_CISS_SCSI_TAPE | ||
393 | if (strncmp(ENGAGE_SCSI, buffer, sizeof ENGAGE_SCSI - 1) == 0) { | ||
394 | struct seq_file *seq = file->private_data; | ||
395 | ctlr_info_t *h = seq->private; | ||
396 | int rc; | ||
397 | |||
348 | rc = cciss_engage_scsi(h->ctlr); | 398 | rc = cciss_engage_scsi(h->ctlr); |
349 | if (rc != 0) | 399 | if (rc != 0) |
350 | return -rc; | 400 | err = -rc; |
351 | return count; | 401 | else |
352 | } | 402 | err = length; |
403 | } else | ||
404 | #endif /* CONFIG_CISS_SCSI_TAPE */ | ||
405 | err = -EINVAL; | ||
353 | /* might be nice to have "disengage" too, but it's not | 406 | /* might be nice to have "disengage" too, but it's not |
354 | safely possible. (only 1 module use count, lock issues.) */ | 407 | safely possible. (only 1 module use count, lock issues.) */ |
355 | # endif | 408 | |
356 | return -EINVAL; | 409 | out: |
410 | free_page((unsigned long)buffer); | ||
411 | return err; | ||
357 | } | 412 | } |
358 | 413 | ||
359 | /* | 414 | static struct file_operations cciss_proc_fops = { |
360 | * Get us a file in /proc/cciss that says something about each controller. | 415 | .owner = THIS_MODULE, |
361 | * Create /proc/cciss if it doesn't exist yet. | 416 | .open = cciss_seq_open, |
362 | */ | 417 | .read = seq_read, |
418 | .llseek = seq_lseek, | ||
419 | .release = seq_release, | ||
420 | .write = cciss_proc_write, | ||
421 | }; | ||
422 | |||
363 | static void __devinit cciss_procinit(int i) | 423 | static void __devinit cciss_procinit(int i) |
364 | { | 424 | { |
365 | struct proc_dir_entry *pde; | 425 | struct proc_dir_entry *pde; |
366 | 426 | ||
367 | if (proc_cciss == NULL) { | 427 | if (proc_cciss == NULL) |
368 | proc_cciss = proc_mkdir("cciss", proc_root_driver); | 428 | proc_cciss = proc_mkdir("cciss", proc_root_driver); |
369 | if (!proc_cciss) | 429 | if (!proc_cciss) |
370 | return; | 430 | return; |
371 | } | 431 | pde = proc_create(hba[i]->devname, S_IWUSR | S_IRUSR | S_IRGRP | |
432 | S_IROTH, proc_cciss, | ||
433 | &cciss_proc_fops); | ||
434 | if (!pde) | ||
435 | return; | ||
372 | 436 | ||
373 | pde = create_proc_read_entry(hba[i]->devname, | 437 | pde->data = hba[i]; |
374 | S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH, | ||
375 | proc_cciss, cciss_proc_get_info, hba[i]); | ||
376 | pde->write_proc = cciss_proc_write; | ||
377 | } | 438 | } |
378 | #endif /* CONFIG_PROC_FS */ | 439 | #endif /* CONFIG_PROC_FS */ |
379 | 440 | ||
@@ -1288,6 +1349,10 @@ static void cciss_update_drive_info(int ctlr, int drv_index) | |||
1288 | spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); | 1349 | spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); |
1289 | h->drv[drv_index].busy_configuring = 1; | 1350 | h->drv[drv_index].busy_configuring = 1; |
1290 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); | 1351 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); |
1352 | |||
1353 | /* deregister_disk sets h->drv[drv_index].queue = NULL */ | ||
1354 | /* which keeps the interrupt handler from starting */ | ||
1355 | /* the queue. */ | ||
1291 | ret = deregister_disk(h->gendisk[drv_index], | 1356 | ret = deregister_disk(h->gendisk[drv_index], |
1292 | &h->drv[drv_index], 0); | 1357 | &h->drv[drv_index], 0); |
1293 | h->drv[drv_index].busy_configuring = 0; | 1358 | h->drv[drv_index].busy_configuring = 0; |
@@ -1341,7 +1406,6 @@ geo_inq: | |||
1341 | disk->private_data = &h->drv[drv_index]; | 1406 | disk->private_data = &h->drv[drv_index]; |
1342 | 1407 | ||
1343 | /* Set up queue information */ | 1408 | /* Set up queue information */ |
1344 | disk->queue->backing_dev_info.ra_pages = READ_AHEAD; | ||
1345 | blk_queue_bounce_limit(disk->queue, hba[ctlr]->pdev->dma_mask); | 1409 | blk_queue_bounce_limit(disk->queue, hba[ctlr]->pdev->dma_mask); |
1346 | 1410 | ||
1347 | /* This is a hardware imposed limit. */ | 1411 | /* This is a hardware imposed limit. */ |
@@ -1359,6 +1423,10 @@ geo_inq: | |||
1359 | blk_queue_hardsect_size(disk->queue, | 1423 | blk_queue_hardsect_size(disk->queue, |
1360 | hba[ctlr]->drv[drv_index].block_size); | 1424 | hba[ctlr]->drv[drv_index].block_size); |
1361 | 1425 | ||
1426 | /* Make sure all queue data is written out before */ | ||
1427 | /* setting h->drv[drv_index].queue, as setting this */ | ||
1428 | /* allows the interrupt handler to start the queue */ | ||
1429 | wmb(); | ||
1362 | h->drv[drv_index].queue = disk->queue; | 1430 | h->drv[drv_index].queue = disk->queue; |
1363 | add_disk(disk); | 1431 | add_disk(disk); |
1364 | } | 1432 | } |
@@ -3434,7 +3502,6 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, | |||
3434 | } | 3502 | } |
3435 | drv->queue = q; | 3503 | drv->queue = q; |
3436 | 3504 | ||
3437 | q->backing_dev_info.ra_pages = READ_AHEAD; | ||
3438 | blk_queue_bounce_limit(q, hba[i]->pdev->dma_mask); | 3505 | blk_queue_bounce_limit(q, hba[i]->pdev->dma_mask); |
3439 | 3506 | ||
3440 | /* This is a hardware imposed limit. */ | 3507 | /* This is a hardware imposed limit. */ |
@@ -3461,10 +3528,17 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, | |||
3461 | continue; | 3528 | continue; |
3462 | blk_queue_hardsect_size(q, drv->block_size); | 3529 | blk_queue_hardsect_size(q, drv->block_size); |
3463 | set_capacity(disk, drv->nr_blocks); | 3530 | set_capacity(disk, drv->nr_blocks); |
3464 | add_disk(disk); | ||
3465 | j++; | 3531 | j++; |
3466 | } while (j <= hba[i]->highest_lun); | 3532 | } while (j <= hba[i]->highest_lun); |
3467 | 3533 | ||
3534 | /* Make sure all queue data is written out before */ | ||
3535 | /* interrupt handler, triggered by add_disk, */ | ||
3536 | /* is allowed to start them. */ | ||
3537 | wmb(); | ||
3538 | |||
3539 | for (j = 0; j <= hba[i]->highest_lun; j++) | ||
3540 | add_disk(hba[i]->gendisk[j]); | ||
3541 | |||
3468 | return 1; | 3542 | return 1; |
3469 | 3543 | ||
3470 | clean4: | 3544 | clean4: |
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index 55178e9973a0..e4bf9a11ca0d 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c | |||
@@ -1349,9 +1349,9 @@ cciss_unregister_scsi(int ctlr) | |||
1349 | /* set scsi_host to NULL so our detect routine will | 1349 | /* set scsi_host to NULL so our detect routine will |
1350 | find us on register */ | 1350 | find us on register */ |
1351 | sa->scsi_host = NULL; | 1351 | sa->scsi_host = NULL; |
1352 | spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); | ||
1352 | scsi_cmd_stack_free(ctlr); | 1353 | scsi_cmd_stack_free(ctlr); |
1353 | kfree(sa); | 1354 | kfree(sa); |
1354 | spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); | ||
1355 | } | 1355 | } |
1356 | 1356 | ||
1357 | static int | 1357 | static int |
@@ -1404,21 +1404,18 @@ cciss_engage_scsi(int ctlr) | |||
1404 | } | 1404 | } |
1405 | 1405 | ||
1406 | static void | 1406 | static void |
1407 | cciss_proc_tape_report(int ctlr, unsigned char *buffer, off_t *pos, off_t *len) | 1407 | cciss_seq_tape_report(struct seq_file *seq, int ctlr) |
1408 | { | 1408 | { |
1409 | unsigned long flags; | 1409 | unsigned long flags; |
1410 | int size; | ||
1411 | |||
1412 | *pos = *pos -1; *len = *len - 1; // cut off the last trailing newline | ||
1413 | 1410 | ||
1414 | CPQ_TAPE_LOCK(ctlr, flags); | 1411 | CPQ_TAPE_LOCK(ctlr, flags); |
1415 | size = sprintf(buffer + *len, | 1412 | seq_printf(seq, |
1416 | "Sequential access devices: %d\n\n", | 1413 | "Sequential access devices: %d\n\n", |
1417 | ccissscsi[ctlr].ndevices); | 1414 | ccissscsi[ctlr].ndevices); |
1418 | CPQ_TAPE_UNLOCK(ctlr, flags); | 1415 | CPQ_TAPE_UNLOCK(ctlr, flags); |
1419 | *pos += size; *len += size; | ||
1420 | } | 1416 | } |
1421 | 1417 | ||
1418 | |||
1422 | /* Need at least one of these error handlers to keep ../scsi/hosts.c from | 1419 | /* Need at least one of these error handlers to keep ../scsi/hosts.c from |
1423 | * complaining. Doing a host- or bus-reset can't do anything good here. | 1420 | * complaining. Doing a host- or bus-reset can't do anything good here. |
1424 | * Despite what it might say in scsi_error.c, there may well be commands | 1421 | * Despite what it might say in scsi_error.c, there may well be commands |
@@ -1498,6 +1495,5 @@ static int cciss_eh_abort_handler(struct scsi_cmnd *scsicmd) | |||
1498 | #define cciss_scsi_setup(cntl_num) | 1495 | #define cciss_scsi_setup(cntl_num) |
1499 | #define cciss_unregister_scsi(ctlr) | 1496 | #define cciss_unregister_scsi(ctlr) |
1500 | #define cciss_register_scsi(ctlr) | 1497 | #define cciss_register_scsi(ctlr) |
1501 | #define cciss_proc_tape_report(ctlr, buffer, pos, len) | ||
1502 | 1498 | ||
1503 | #endif /* CONFIG_CISS_SCSI_TAPE */ | 1499 | #endif /* CONFIG_CISS_SCSI_TAPE */ |
diff --git a/drivers/block/cryptoloop.c b/drivers/block/cryptoloop.c index 241167878edf..8b6bb764b0a3 100644 --- a/drivers/block/cryptoloop.c +++ b/drivers/block/cryptoloop.c | |||
@@ -27,7 +27,6 @@ | |||
27 | #include <linux/blkdev.h> | 27 | #include <linux/blkdev.h> |
28 | #include <linux/loop.h> | 28 | #include <linux/loop.h> |
29 | #include <linux/scatterlist.h> | 29 | #include <linux/scatterlist.h> |
30 | #include <asm/semaphore.h> | ||
31 | #include <asm/uaccess.h> | 30 | #include <asm/uaccess.h> |
32 | 31 | ||
33 | MODULE_LICENSE("GPL"); | 32 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 32c79a55511b..7652e87d60c5 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c | |||
@@ -217,7 +217,6 @@ static int use_virtual_dma; | |||
217 | */ | 217 | */ |
218 | 218 | ||
219 | static DEFINE_SPINLOCK(floppy_lock); | 219 | static DEFINE_SPINLOCK(floppy_lock); |
220 | static struct completion device_release; | ||
221 | 220 | ||
222 | static unsigned short virtual_dma_port = 0x3f0; | 221 | static unsigned short virtual_dma_port = 0x3f0; |
223 | irqreturn_t floppy_interrupt(int irq, void *dev_id); | 222 | irqreturn_t floppy_interrupt(int irq, void *dev_id); |
@@ -4144,7 +4143,6 @@ DEVICE_ATTR(cmos,S_IRUGO,floppy_cmos_show,NULL); | |||
4144 | 4143 | ||
4145 | static void floppy_device_release(struct device *dev) | 4144 | static void floppy_device_release(struct device *dev) |
4146 | { | 4145 | { |
4147 | complete(&device_release); | ||
4148 | } | 4146 | } |
4149 | 4147 | ||
4150 | static struct platform_device floppy_device[N_DRIVE]; | 4148 | static struct platform_device floppy_device[N_DRIVE]; |
@@ -4539,7 +4537,6 @@ void cleanup_module(void) | |||
4539 | { | 4537 | { |
4540 | int drive; | 4538 | int drive; |
4541 | 4539 | ||
4542 | init_completion(&device_release); | ||
4543 | blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256); | 4540 | blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256); |
4544 | unregister_blkdev(FLOPPY_MAJOR, "fd"); | 4541 | unregister_blkdev(FLOPPY_MAJOR, "fd"); |
4545 | 4542 | ||
@@ -4564,8 +4561,6 @@ void cleanup_module(void) | |||
4564 | 4561 | ||
4565 | /* eject disk, if any */ | 4562 | /* eject disk, if any */ |
4566 | fd_eject(0); | 4563 | fd_eject(0); |
4567 | |||
4568 | wait_for_completion(&device_release); | ||
4569 | } | 4564 | } |
4570 | 4565 | ||
4571 | module_param(floppy, charp, 0); | 4566 | module_param(floppy, charp, 0); |
diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 91ebb007416c..f7f163557aa0 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c | |||
@@ -82,6 +82,9 @@ | |||
82 | static LIST_HEAD(loop_devices); | 82 | static LIST_HEAD(loop_devices); |
83 | static DEFINE_MUTEX(loop_devices_mutex); | 83 | static DEFINE_MUTEX(loop_devices_mutex); |
84 | 84 | ||
85 | static int max_part; | ||
86 | static int part_shift; | ||
87 | |||
85 | /* | 88 | /* |
86 | * Transfer functions | 89 | * Transfer functions |
87 | */ | 90 | */ |
@@ -692,6 +695,8 @@ static int loop_change_fd(struct loop_device *lo, struct file *lo_file, | |||
692 | goto out_putf; | 695 | goto out_putf; |
693 | 696 | ||
694 | fput(old_file); | 697 | fput(old_file); |
698 | if (max_part > 0) | ||
699 | ioctl_by_bdev(bdev, BLKRRPART, 0); | ||
695 | return 0; | 700 | return 0; |
696 | 701 | ||
697 | out_putf: | 702 | out_putf: |
@@ -819,6 +824,8 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file, | |||
819 | } | 824 | } |
820 | lo->lo_state = Lo_bound; | 825 | lo->lo_state = Lo_bound; |
821 | wake_up_process(lo->lo_thread); | 826 | wake_up_process(lo->lo_thread); |
827 | if (max_part > 0) | ||
828 | ioctl_by_bdev(bdev, BLKRRPART, 0); | ||
822 | return 0; | 829 | return 0; |
823 | 830 | ||
824 | out_clr: | 831 | out_clr: |
@@ -919,6 +926,8 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev) | |||
919 | fput(filp); | 926 | fput(filp); |
920 | /* This is safe: open() is still holding a reference. */ | 927 | /* This is safe: open() is still holding a reference. */ |
921 | module_put(THIS_MODULE); | 928 | module_put(THIS_MODULE); |
929 | if (max_part > 0) | ||
930 | ioctl_by_bdev(bdev, BLKRRPART, 0); | ||
922 | return 0; | 931 | return 0; |
923 | } | 932 | } |
924 | 933 | ||
@@ -1360,6 +1369,8 @@ static struct block_device_operations lo_fops = { | |||
1360 | static int max_loop; | 1369 | static int max_loop; |
1361 | module_param(max_loop, int, 0); | 1370 | module_param(max_loop, int, 0); |
1362 | MODULE_PARM_DESC(max_loop, "Maximum number of loop devices"); | 1371 | MODULE_PARM_DESC(max_loop, "Maximum number of loop devices"); |
1372 | module_param(max_part, int, 0); | ||
1373 | MODULE_PARM_DESC(max_part, "Maximum number of partitions per loop device"); | ||
1363 | MODULE_LICENSE("GPL"); | 1374 | MODULE_LICENSE("GPL"); |
1364 | MODULE_ALIAS_BLOCKDEV_MAJOR(LOOP_MAJOR); | 1375 | MODULE_ALIAS_BLOCKDEV_MAJOR(LOOP_MAJOR); |
1365 | 1376 | ||
@@ -1412,7 +1423,7 @@ static struct loop_device *loop_alloc(int i) | |||
1412 | if (!lo->lo_queue) | 1423 | if (!lo->lo_queue) |
1413 | goto out_free_dev; | 1424 | goto out_free_dev; |
1414 | 1425 | ||
1415 | disk = lo->lo_disk = alloc_disk(1); | 1426 | disk = lo->lo_disk = alloc_disk(1 << part_shift); |
1416 | if (!disk) | 1427 | if (!disk) |
1417 | goto out_free_queue; | 1428 | goto out_free_queue; |
1418 | 1429 | ||
@@ -1422,7 +1433,7 @@ static struct loop_device *loop_alloc(int i) | |||
1422 | init_waitqueue_head(&lo->lo_event); | 1433 | init_waitqueue_head(&lo->lo_event); |
1423 | spin_lock_init(&lo->lo_lock); | 1434 | spin_lock_init(&lo->lo_lock); |
1424 | disk->major = LOOP_MAJOR; | 1435 | disk->major = LOOP_MAJOR; |
1425 | disk->first_minor = i; | 1436 | disk->first_minor = i << part_shift; |
1426 | disk->fops = &lo_fops; | 1437 | disk->fops = &lo_fops; |
1427 | disk->private_data = lo; | 1438 | disk->private_data = lo; |
1428 | disk->queue = lo->lo_queue; | 1439 | disk->queue = lo->lo_queue; |
@@ -1502,7 +1513,12 @@ static int __init loop_init(void) | |||
1502 | * themselves and have kernel automatically instantiate actual | 1513 | * themselves and have kernel automatically instantiate actual |
1503 | * device on-demand. | 1514 | * device on-demand. |
1504 | */ | 1515 | */ |
1505 | if (max_loop > 1UL << MINORBITS) | 1516 | |
1517 | part_shift = 0; | ||
1518 | if (max_part > 0) | ||
1519 | part_shift = fls(max_part); | ||
1520 | |||
1521 | if (max_loop > 1UL << (MINORBITS - part_shift)) | ||
1506 | return -EINVAL; | 1522 | return -EINVAL; |
1507 | 1523 | ||
1508 | if (max_loop) { | 1524 | if (max_loop) { |
@@ -1510,7 +1526,7 @@ static int __init loop_init(void) | |||
1510 | range = max_loop; | 1526 | range = max_loop; |
1511 | } else { | 1527 | } else { |
1512 | nr = 8; | 1528 | nr = 8; |
1513 | range = 1UL << MINORBITS; | 1529 | range = 1UL << (MINORBITS - part_shift); |
1514 | } | 1530 | } |
1515 | 1531 | ||
1516 | if (register_blkdev(LOOP_MAJOR, "loop")) | 1532 | if (register_blkdev(LOOP_MAJOR, "loop")) |
@@ -1549,7 +1565,7 @@ static void __exit loop_exit(void) | |||
1549 | unsigned long range; | 1565 | unsigned long range; |
1550 | struct loop_device *lo, *next; | 1566 | struct loop_device *lo, *next; |
1551 | 1567 | ||
1552 | range = max_loop ? max_loop : 1UL << MINORBITS; | 1568 | range = max_loop ? max_loop : 1UL << (MINORBITS - part_shift); |
1553 | 1569 | ||
1554 | list_for_each_entry_safe(lo, next, &loop_devices, lo_list) | 1570 | list_for_each_entry_safe(lo, next, &loop_devices, lo_list) |
1555 | loop_del_one(lo); | 1571 | loop_del_one(lo); |
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 018753c59b8e..60cc54368b66 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c | |||
@@ -153,6 +153,12 @@ static int sock_xmit(struct nbd_device *lo, int send, void *buf, int size, | |||
153 | struct kvec iov; | 153 | struct kvec iov; |
154 | sigset_t blocked, oldset; | 154 | sigset_t blocked, oldset; |
155 | 155 | ||
156 | if (unlikely(!sock)) { | ||
157 | printk(KERN_ERR "%s: Attempted %s on closed socket in sock_xmit\n", | ||
158 | lo->disk->disk_name, (send ? "send" : "recv")); | ||
159 | return -EINVAL; | ||
160 | } | ||
161 | |||
156 | /* Allow interception of SIGKILL only | 162 | /* Allow interception of SIGKILL only |
157 | * Don't allow other signals to interrupt the transmission */ | 163 | * Don't allow other signals to interrupt the transmission */ |
158 | siginitsetinv(&blocked, sigmask(SIGKILL)); | 164 | siginitsetinv(&blocked, sigmask(SIGKILL)); |
@@ -655,6 +661,7 @@ static int __init nbd_init(void) | |||
655 | 661 | ||
656 | for (i = 0; i < nbds_max; i++) { | 662 | for (i = 0; i < nbds_max; i++) { |
657 | struct gendisk *disk = alloc_disk(1); | 663 | struct gendisk *disk = alloc_disk(1); |
664 | elevator_t *old_e; | ||
658 | if (!disk) | 665 | if (!disk) |
659 | goto out; | 666 | goto out; |
660 | nbd_dev[i].disk = disk; | 667 | nbd_dev[i].disk = disk; |
@@ -668,6 +675,11 @@ static int __init nbd_init(void) | |||
668 | put_disk(disk); | 675 | put_disk(disk); |
669 | goto out; | 676 | goto out; |
670 | } | 677 | } |
678 | old_e = disk->queue->elevator; | ||
679 | if (elevator_init(disk->queue, "deadline") == 0 || | ||
680 | elevator_init(disk->queue, "noop") == 0) { | ||
681 | elevator_exit(old_e); | ||
682 | } | ||
671 | } | 683 | } |
672 | 684 | ||
673 | if (register_blkdev(NBD_MAJOR, "nbd")) { | 685 | if (register_blkdev(NBD_MAJOR, "nbd")) { |
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 674cd66dcaba..18feb1c7c33b 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c | |||
@@ -849,7 +849,8 @@ static int pkt_flush_cache(struct pktcdvd_device *pd) | |||
849 | /* | 849 | /* |
850 | * speed is given as the normal factor, e.g. 4 for 4x | 850 | * speed is given as the normal factor, e.g. 4 for 4x |
851 | */ | 851 | */ |
852 | static int pkt_set_speed(struct pktcdvd_device *pd, unsigned write_speed, unsigned read_speed) | 852 | static noinline_for_stack int pkt_set_speed(struct pktcdvd_device *pd, |
853 | unsigned write_speed, unsigned read_speed) | ||
853 | { | 854 | { |
854 | struct packet_command cgc; | 855 | struct packet_command cgc; |
855 | struct request_sense sense; | 856 | struct request_sense sense; |
@@ -1776,7 +1777,8 @@ static int pkt_get_track_info(struct pktcdvd_device *pd, __u16 track, __u8 type, | |||
1776 | return pkt_generic_packet(pd, &cgc); | 1777 | return pkt_generic_packet(pd, &cgc); |
1777 | } | 1778 | } |
1778 | 1779 | ||
1779 | static int pkt_get_last_written(struct pktcdvd_device *pd, long *last_written) | 1780 | static noinline_for_stack int pkt_get_last_written(struct pktcdvd_device *pd, |
1781 | long *last_written) | ||
1780 | { | 1782 | { |
1781 | disc_information di; | 1783 | disc_information di; |
1782 | track_information ti; | 1784 | track_information ti; |
@@ -1813,7 +1815,7 @@ static int pkt_get_last_written(struct pktcdvd_device *pd, long *last_written) | |||
1813 | /* | 1815 | /* |
1814 | * write mode select package based on pd->settings | 1816 | * write mode select package based on pd->settings |
1815 | */ | 1817 | */ |
1816 | static int pkt_set_write_settings(struct pktcdvd_device *pd) | 1818 | static noinline_for_stack int pkt_set_write_settings(struct pktcdvd_device *pd) |
1817 | { | 1819 | { |
1818 | struct packet_command cgc; | 1820 | struct packet_command cgc; |
1819 | struct request_sense sense; | 1821 | struct request_sense sense; |
@@ -1972,7 +1974,7 @@ static int pkt_writable_disc(struct pktcdvd_device *pd, disc_information *di) | |||
1972 | return 1; | 1974 | return 1; |
1973 | } | 1975 | } |
1974 | 1976 | ||
1975 | static int pkt_probe_settings(struct pktcdvd_device *pd) | 1977 | static noinline_for_stack int pkt_probe_settings(struct pktcdvd_device *pd) |
1976 | { | 1978 | { |
1977 | struct packet_command cgc; | 1979 | struct packet_command cgc; |
1978 | unsigned char buf[12]; | 1980 | unsigned char buf[12]; |
@@ -2071,7 +2073,8 @@ static int pkt_probe_settings(struct pktcdvd_device *pd) | |||
2071 | /* | 2073 | /* |
2072 | * enable/disable write caching on drive | 2074 | * enable/disable write caching on drive |
2073 | */ | 2075 | */ |
2074 | static int pkt_write_caching(struct pktcdvd_device *pd, int set) | 2076 | static noinline_for_stack int pkt_write_caching(struct pktcdvd_device *pd, |
2077 | int set) | ||
2075 | { | 2078 | { |
2076 | struct packet_command cgc; | 2079 | struct packet_command cgc; |
2077 | struct request_sense sense; | 2080 | struct request_sense sense; |
@@ -2116,7 +2119,8 @@ static int pkt_lock_door(struct pktcdvd_device *pd, int lockflag) | |||
2116 | /* | 2119 | /* |
2117 | * Returns drive maximum write speed | 2120 | * Returns drive maximum write speed |
2118 | */ | 2121 | */ |
2119 | static int pkt_get_max_speed(struct pktcdvd_device *pd, unsigned *write_speed) | 2122 | static noinline_for_stack int pkt_get_max_speed(struct pktcdvd_device *pd, |
2123 | unsigned *write_speed) | ||
2120 | { | 2124 | { |
2121 | struct packet_command cgc; | 2125 | struct packet_command cgc; |
2122 | struct request_sense sense; | 2126 | struct request_sense sense; |
@@ -2177,7 +2181,8 @@ static char us_clv_to_speed[16] = { | |||
2177 | /* | 2181 | /* |
2178 | * reads the maximum media speed from ATIP | 2182 | * reads the maximum media speed from ATIP |
2179 | */ | 2183 | */ |
2180 | static int pkt_media_speed(struct pktcdvd_device *pd, unsigned *speed) | 2184 | static noinline_for_stack int pkt_media_speed(struct pktcdvd_device *pd, |
2185 | unsigned *speed) | ||
2181 | { | 2186 | { |
2182 | struct packet_command cgc; | 2187 | struct packet_command cgc; |
2183 | struct request_sense sense; | 2188 | struct request_sense sense; |
@@ -2249,7 +2254,7 @@ static int pkt_media_speed(struct pktcdvd_device *pd, unsigned *speed) | |||
2249 | } | 2254 | } |
2250 | } | 2255 | } |
2251 | 2256 | ||
2252 | static int pkt_perform_opc(struct pktcdvd_device *pd) | 2257 | static noinline_for_stack int pkt_perform_opc(struct pktcdvd_device *pd) |
2253 | { | 2258 | { |
2254 | struct packet_command cgc; | 2259 | struct packet_command cgc; |
2255 | struct request_sense sense; | 2260 | struct request_sense sense; |
diff --git a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c deleted file mode 100644 index 3c796e236253..000000000000 --- a/drivers/block/ps2esdi.c +++ /dev/null | |||
@@ -1,1079 +0,0 @@ | |||
1 | /* ps2esdi driver based on assembler code by Arindam Banerji, | ||
2 | written by Peter De Schrijver */ | ||
3 | /* Reassuring note to IBM : This driver was NOT developed by vice-versa | ||
4 | engineering the PS/2's BIOS */ | ||
5 | /* Dedicated to Wannes, Tofke, Ykke, Godot, Killroy and all those | ||
6 | other lovely fish out there... */ | ||
7 | /* This code was written during the long and boring WINA | ||
8 | elections 1994 */ | ||
9 | /* Thanks to Arindam Banerij for giving me the source of his driver */ | ||
10 | /* This code may be freely distributed and modified in any way, | ||
11 | as long as these notes remain intact */ | ||
12 | |||
13 | /* Revised: 05/07/94 by Arindam Banerji (axb@cse.nd.edu) */ | ||
14 | /* Revised: 09/08/94 by Peter De Schrijver (stud11@cc4.kuleuven.ac.be) | ||
15 | Thanks to Arindam Banerij for sending me the docs of the adapter */ | ||
16 | |||
17 | /* BA Modified for ThinkPad 720 by Boris Ashkinazi */ | ||
18 | /* (bash@vnet.ibm.com) 08/08/95 */ | ||
19 | |||
20 | /* Modified further for ThinkPad-720C by Uri Blumenthal */ | ||
21 | /* (uri@watson.ibm.com) Sep 11, 1995 */ | ||
22 | |||
23 | /* TODO : | ||
24 | + Timeouts | ||
25 | + Get disk parameters | ||
26 | + DMA above 16MB | ||
27 | + reset after read/write error | ||
28 | */ | ||
29 | |||
30 | #define DEVICE_NAME "PS/2 ESDI" | ||
31 | |||
32 | #include <linux/major.h> | ||
33 | #include <linux/errno.h> | ||
34 | #include <linux/wait.h> | ||
35 | #include <linux/interrupt.h> | ||
36 | #include <linux/fs.h> | ||
37 | #include <linux/kernel.h> | ||
38 | #include <linux/genhd.h> | ||
39 | #include <linux/ps2esdi.h> | ||
40 | #include <linux/blkdev.h> | ||
41 | #include <linux/mca-legacy.h> | ||
42 | #include <linux/init.h> | ||
43 | #include <linux/ioport.h> | ||
44 | #include <linux/module.h> | ||
45 | #include <linux/hdreg.h> | ||
46 | |||
47 | #include <asm/system.h> | ||
48 | #include <asm/io.h> | ||
49 | #include <asm/dma.h> | ||
50 | #include <asm/mca_dma.h> | ||
51 | #include <asm/uaccess.h> | ||
52 | |||
53 | #define PS2ESDI_IRQ 14 | ||
54 | #define MAX_HD 2 | ||
55 | #define MAX_RETRIES 5 | ||
56 | #define MAX_16BIT 65536 | ||
57 | #define ESDI_TIMEOUT 0xf000 | ||
58 | #define ESDI_STAT_TIMEOUT 4 | ||
59 | |||
60 | #define TYPE_0_CMD_BLK_LENGTH 2 | ||
61 | #define TYPE_1_CMD_BLK_LENGTH 4 | ||
62 | |||
63 | static void reset_ctrl(void); | ||
64 | |||
65 | static int ps2esdi_geninit(void); | ||
66 | |||
67 | static void do_ps2esdi_request(struct request_queue * q); | ||
68 | |||
69 | static void ps2esdi_readwrite(int cmd, struct request *req); | ||
70 | |||
71 | static void ps2esdi_fill_cmd_block(u_short * cmd_blk, u_short cmd, | ||
72 | u_short cyl, u_short head, u_short sector, u_short length, u_char drive); | ||
73 | |||
74 | static int ps2esdi_out_cmd_blk(u_short * cmd_blk); | ||
75 | |||
76 | static void ps2esdi_prep_dma(char *buffer, u_short length, u_char dma_xmode); | ||
77 | |||
78 | static irqreturn_t ps2esdi_interrupt_handler(int irq, void *dev_id); | ||
79 | static void (*current_int_handler) (u_int) = NULL; | ||
80 | static void ps2esdi_normal_interrupt_handler(u_int); | ||
81 | static void ps2esdi_initial_reset_int_handler(u_int); | ||
82 | static void ps2esdi_geometry_int_handler(u_int); | ||
83 | static int ps2esdi_getgeo(struct block_device *bdev, struct hd_geometry *geo); | ||
84 | |||
85 | static int ps2esdi_read_status_words(int num_words, int max_words, u_short * buffer); | ||
86 | |||
87 | static void dump_cmd_complete_status(u_int int_ret_code); | ||
88 | |||
89 | static void ps2esdi_get_device_cfg(void); | ||
90 | |||
91 | static void ps2esdi_reset_timer(unsigned long unused); | ||
92 | |||
93 | static u_int dma_arb_level; /* DMA arbitration level */ | ||
94 | |||
95 | static DECLARE_WAIT_QUEUE_HEAD(ps2esdi_int); | ||
96 | |||
97 | static int no_int_yet; | ||
98 | static int ps2esdi_drives; | ||
99 | static u_short io_base; | ||
100 | static DEFINE_TIMER(esdi_timer, ps2esdi_reset_timer, 0, 0); | ||
101 | static int reset_status; | ||
102 | static int ps2esdi_slot = -1; | ||
103 | static int tp720esdi = 0; /* Is it Integrated ESDI of ThinkPad-720? */ | ||
104 | static int intg_esdi = 0; /* If integrated adapter */ | ||
105 | struct ps2esdi_i_struct { | ||
106 | unsigned int head, sect, cyl, wpcom, lzone, ctl; | ||
107 | }; | ||
108 | static DEFINE_SPINLOCK(ps2esdi_lock); | ||
109 | static struct request_queue *ps2esdi_queue; | ||
110 | static struct request *current_req; | ||
111 | |||
112 | #if 0 | ||
113 | #if 0 /* try both - I don't know which one is better... UB */ | ||
114 | static struct ps2esdi_i_struct ps2esdi_info[MAX_HD] = | ||
115 | { | ||
116 | {4, 48, 1553, 0, 0, 0}, | ||
117 | {0, 0, 0, 0, 0, 0}}; | ||
118 | #else | ||
119 | static struct ps2esdi_i_struct ps2esdi_info[MAX_HD] = | ||
120 | { | ||
121 | {64, 32, 161, 0, 0, 0}, | ||
122 | {0, 0, 0, 0, 0, 0}}; | ||
123 | #endif | ||
124 | #endif | ||
125 | static struct ps2esdi_i_struct ps2esdi_info[MAX_HD] = | ||
126 | { | ||
127 | {0, 0, 0, 0, 0, 0}, | ||
128 | {0, 0, 0, 0, 0, 0}}; | ||
129 | |||
130 | static struct block_device_operations ps2esdi_fops = | ||
131 | { | ||
132 | .owner = THIS_MODULE, | ||
133 | .getgeo = ps2esdi_getgeo, | ||
134 | }; | ||
135 | |||
136 | static struct gendisk *ps2esdi_gendisk[2]; | ||
137 | |||
138 | /* initialization routine called by ll_rw_blk.c */ | ||
139 | static int __init ps2esdi_init(void) | ||
140 | { | ||
141 | |||
142 | int error = 0; | ||
143 | |||
144 | /* register the device - pass the name and major number */ | ||
145 | if (register_blkdev(PS2ESDI_MAJOR, "ed")) | ||
146 | return -EBUSY; | ||
147 | |||
148 | /* set up some global information - indicating device specific info */ | ||
149 | ps2esdi_queue = blk_init_queue(do_ps2esdi_request, &ps2esdi_lock); | ||
150 | if (!ps2esdi_queue) { | ||
151 | unregister_blkdev(PS2ESDI_MAJOR, "ed"); | ||
152 | return -ENOMEM; | ||
153 | } | ||
154 | |||
155 | /* some minor housekeeping - setup the global gendisk structure */ | ||
156 | error = ps2esdi_geninit(); | ||
157 | if (error) { | ||
158 | printk(KERN_WARNING "PS2ESDI: error initialising" | ||
159 | " device, releasing resources\n"); | ||
160 | unregister_blkdev(PS2ESDI_MAJOR, "ed"); | ||
161 | blk_cleanup_queue(ps2esdi_queue); | ||
162 | return error; | ||
163 | } | ||
164 | return 0; | ||
165 | } /* ps2esdi_init */ | ||
166 | |||
167 | #ifndef MODULE | ||
168 | |||
169 | module_init(ps2esdi_init); | ||
170 | |||
171 | #else | ||
172 | |||
173 | static int cyl[MAX_HD] = {-1,-1}; | ||
174 | static int head[MAX_HD] = {-1, -1}; | ||
175 | static int sect[MAX_HD] = {-1, -1}; | ||
176 | |||
177 | module_param(tp720esdi, bool, 0); | ||
178 | module_param_array(cyl, int, NULL, 0); | ||
179 | module_param_array(head, int, NULL, 0); | ||
180 | module_param_array(sect, int, NULL, 0); | ||
181 | MODULE_LICENSE("GPL"); | ||
182 | |||
183 | int init_module(void) { | ||
184 | int drive; | ||
185 | |||
186 | for(drive = 0; drive < MAX_HD; drive++) { | ||
187 | struct ps2esdi_i_struct *info = &ps2esdi_info[drive]; | ||
188 | |||
189 | if (cyl[drive] != -1) { | ||
190 | info->cyl = info->lzone = cyl[drive]; | ||
191 | info->wpcom = 0; | ||
192 | } | ||
193 | if (head[drive] != -1) { | ||
194 | info->head = head[drive]; | ||
195 | info->ctl = (head[drive] > 8 ? 8 : 0); | ||
196 | } | ||
197 | if (sect[drive] != -1) info->sect = sect[drive]; | ||
198 | } | ||
199 | return ps2esdi_init(); | ||
200 | } | ||
201 | |||
202 | void | ||
203 | cleanup_module(void) { | ||
204 | int i; | ||
205 | if(ps2esdi_slot) { | ||
206 | mca_mark_as_unused(ps2esdi_slot); | ||
207 | mca_set_adapter_procfn(ps2esdi_slot, NULL, NULL); | ||
208 | } | ||
209 | release_region(io_base, 4); | ||
210 | free_dma(dma_arb_level); | ||
211 | free_irq(PS2ESDI_IRQ, &ps2esdi_gendisk); | ||
212 | unregister_blkdev(PS2ESDI_MAJOR, "ed"); | ||
213 | blk_cleanup_queue(ps2esdi_queue); | ||
214 | for (i = 0; i < ps2esdi_drives; i++) { | ||
215 | del_gendisk(ps2esdi_gendisk[i]); | ||
216 | put_disk(ps2esdi_gendisk[i]); | ||
217 | } | ||
218 | } | ||
219 | #endif /* MODULE */ | ||
220 | |||
221 | /* handles boot time command line parameters */ | ||
222 | void __init tp720_setup(char *str, int *ints) | ||
223 | { | ||
224 | /* no params, just sets the tp720esdi flag if it exists */ | ||
225 | |||
226 | printk("%s: TP 720 ESDI flag set\n", DEVICE_NAME); | ||
227 | tp720esdi = 1; | ||
228 | } | ||
229 | |||
230 | void __init ed_setup(char *str, int *ints) | ||
231 | { | ||
232 | int hdind = 0; | ||
233 | |||
234 | /* handles 3 parameters only - corresponding to | ||
235 | 1. Number of cylinders | ||
236 | 2. Number of heads | ||
237 | 3. Sectors/track | ||
238 | */ | ||
239 | |||
240 | if (ints[0] != 3) | ||
241 | return; | ||
242 | |||
243 | /* print out the information - seen at boot time */ | ||
244 | printk("%s: ints[0]=%d ints[1]=%d ints[2]=%d ints[3]=%d\n", | ||
245 | DEVICE_NAME, ints[0], ints[1], ints[2], ints[3]); | ||
246 | |||
247 | /* set the index into device specific information table */ | ||
248 | if (ps2esdi_info[0].head != 0) | ||
249 | hdind = 1; | ||
250 | |||
251 | /* set up all the device information */ | ||
252 | ps2esdi_info[hdind].head = ints[2]; | ||
253 | ps2esdi_info[hdind].sect = ints[3]; | ||
254 | ps2esdi_info[hdind].cyl = ints[1]; | ||
255 | ps2esdi_info[hdind].wpcom = 0; | ||
256 | ps2esdi_info[hdind].lzone = ints[1]; | ||
257 | ps2esdi_info[hdind].ctl = (ints[2] > 8 ? 8 : 0); | ||
258 | #if 0 /* this may be needed for PS2/Mod.80, but it hurts ThinkPad! */ | ||
259 | ps2esdi_drives = hdind + 1; /* increment index for the next time */ | ||
260 | #endif | ||
261 | } /* ed_setup */ | ||
262 | |||
263 | static int ps2esdi_getinfo(char *buf, int slot, void *d) | ||
264 | { | ||
265 | int len = 0; | ||
266 | |||
267 | len += sprintf(buf + len, "DMA Arbitration Level: %d\n", | ||
268 | dma_arb_level); | ||
269 | len += sprintf(buf + len, "IO Port: %x\n", io_base); | ||
270 | len += sprintf(buf + len, "IRQ: 14\n"); | ||
271 | len += sprintf(buf + len, "Drives: %d\n", ps2esdi_drives); | ||
272 | |||
273 | return len; | ||
274 | } | ||
275 | |||
276 | /* ps2 esdi specific initialization - called thru the gendisk chain */ | ||
277 | static int __init ps2esdi_geninit(void) | ||
278 | { | ||
279 | /* | ||
280 | The first part contains the initialization code | ||
281 | for the ESDI disk subsystem. All we really do | ||
282 | is search for the POS registers of the controller | ||
283 | to do some simple setup operations. First, we | ||
284 | must ensure that the controller is installed, | ||
285 | enabled, and configured as PRIMARY. Then we must | ||
286 | determine the DMA arbitration level being used by | ||
287 | the controller so we can handle data transfer | ||
288 | operations properly. If all of this works, then | ||
289 | we will set the INIT_FLAG to a non-zero value. | ||
290 | */ | ||
291 | |||
292 | int slot = 0, i, reset_start, reset_end; | ||
293 | u_char status; | ||
294 | unsigned short adapterID; | ||
295 | int error = 0; | ||
296 | |||
297 | if ((slot = mca_find_adapter(INTG_ESDI_ID, 0)) != MCA_NOTFOUND) { | ||
298 | adapterID = INTG_ESDI_ID; | ||
299 | printk("%s: integrated ESDI adapter found in slot %d\n", | ||
300 | DEVICE_NAME, slot+1); | ||
301 | #ifndef MODULE | ||
302 | mca_set_adapter_name(slot, "PS/2 Integrated ESDI"); | ||
303 | #endif | ||
304 | } else if ((slot = mca_find_adapter(NRML_ESDI_ID, 0)) != -1) { | ||
305 | adapterID = NRML_ESDI_ID; | ||
306 | printk("%s: normal ESDI adapter found in slot %d\n", | ||
307 | DEVICE_NAME, slot+1); | ||
308 | mca_set_adapter_name(slot, "PS/2 ESDI"); | ||
309 | } else { | ||
310 | return -ENODEV; | ||
311 | } | ||
312 | |||
313 | ps2esdi_slot = slot; | ||
314 | mca_mark_as_used(slot); | ||
315 | mca_set_adapter_procfn(slot, (MCA_ProcFn) ps2esdi_getinfo, NULL); | ||
316 | |||
317 | /* Found the slot - read the POS register 2 to get the necessary | ||
318 | configuration and status information. POS register 2 has the | ||
319 | following information : | ||
320 | Bit Function | ||
321 | 7 reserved = 0 | ||
322 | 6 arbitration method | ||
323 | 0 - fairness enabled | ||
324 | 1 - fairness disabled, linear priority assignment | ||
325 | 5-2 arbitration level | ||
326 | 1 alternate address | ||
327 | 1 alternate address | ||
328 | 0 - use addresses 0x3510 - 0x3517 | ||
329 | 0 adapter enable | ||
330 | */ | ||
331 | |||
332 | status = mca_read_stored_pos(slot, 2); | ||
333 | /* is it enabled ? */ | ||
334 | if (!(status & STATUS_ENABLED)) { | ||
335 | printk("%s: ESDI adapter disabled\n", DEVICE_NAME); | ||
336 | error = -ENODEV; | ||
337 | goto err_out1; | ||
338 | } | ||
339 | /* try to grab IRQ, and try to grab a slow IRQ if it fails, so we can | ||
340 | share with the SCSI driver */ | ||
341 | if (request_irq(PS2ESDI_IRQ, ps2esdi_interrupt_handler, | ||
342 | IRQF_DISABLED | IRQF_SHARED, "PS/2 ESDI", &ps2esdi_gendisk) | ||
343 | && request_irq(PS2ESDI_IRQ, ps2esdi_interrupt_handler, | ||
344 | IRQF_SHARED, "PS/2 ESDI", &ps2esdi_gendisk) | ||
345 | ) { | ||
346 | printk("%s: Unable to get IRQ %d\n", DEVICE_NAME, PS2ESDI_IRQ); | ||
347 | error = -EBUSY; | ||
348 | goto err_out1; | ||
349 | } | ||
350 | if (status & STATUS_ALTERNATE) | ||
351 | io_base = ALT_IO_BASE; | ||
352 | else | ||
353 | io_base = PRIMARY_IO_BASE; | ||
354 | |||
355 | if (!request_region(io_base, 4, "ed")) { | ||
356 | printk(KERN_WARNING"Unable to request region 0x%x\n", io_base); | ||
357 | error = -EBUSY; | ||
358 | goto err_out2; | ||
359 | } | ||
360 | /* get the dma arbitration level */ | ||
361 | dma_arb_level = (status >> 2) & 0xf; | ||
362 | |||
363 | /* BA */ | ||
364 | printk("%s: DMA arbitration level : %d\n", | ||
365 | DEVICE_NAME, dma_arb_level); | ||
366 | |||
367 | LITE_ON; | ||
368 | current_int_handler = ps2esdi_initial_reset_int_handler; | ||
369 | reset_ctrl(); | ||
370 | reset_status = 0; | ||
371 | reset_start = jiffies; | ||
372 | while (!reset_status) { | ||
373 | init_timer(&esdi_timer); | ||
374 | esdi_timer.expires = jiffies + HZ; | ||
375 | esdi_timer.data = 0; | ||
376 | add_timer(&esdi_timer); | ||
377 | sleep_on(&ps2esdi_int); | ||
378 | } | ||
379 | reset_end = jiffies; | ||
380 | LITE_OFF; | ||
381 | printk("%s: reset interrupt after %d jiffies, %u.%02u secs\n", | ||
382 | DEVICE_NAME, reset_end - reset_start, (reset_end - reset_start) / HZ, | ||
383 | (reset_end - reset_start) % HZ); | ||
384 | |||
385 | |||
386 | /* Integrated ESDI Disk and Controller has only one drive! */ | ||
387 | if (adapterID == INTG_ESDI_ID) {/* if not "normal" PS2 ESDI adapter */ | ||
388 | ps2esdi_drives = 1; /* then we have only one physical disk! */ intg_esdi = 1; | ||
389 | } | ||
390 | |||
391 | |||
392 | |||
393 | /* finally this part sets up some global data structures etc. */ | ||
394 | |||
395 | ps2esdi_get_device_cfg(); | ||
396 | |||
397 | /* some annoyance in the above routine returns TWO drives? | ||
398 | Is something else happining in the background? | ||
399 | Regaurdless we fix the # of drives again. AJK */ | ||
400 | /* Integrated ESDI Disk and Controller has only one drive! */ | ||
401 | if (adapterID == INTG_ESDI_ID) /* if not "normal" PS2 ESDI adapter */ | ||
402 | ps2esdi_drives = 1; /* Not three or two, ONE DAMNIT! */ | ||
403 | |||
404 | current_int_handler = ps2esdi_normal_interrupt_handler; | ||
405 | |||
406 | if (request_dma(dma_arb_level, "ed") !=0) { | ||
407 | printk(KERN_WARNING "PS2ESDI: Can't request dma-channel %d\n" | ||
408 | ,(int) dma_arb_level); | ||
409 | error = -EBUSY; | ||
410 | goto err_out3; | ||
411 | } | ||
412 | blk_queue_max_sectors(ps2esdi_queue, 128); | ||
413 | |||
414 | error = -ENOMEM; | ||
415 | for (i = 0; i < ps2esdi_drives; i++) { | ||
416 | struct gendisk *disk = alloc_disk(64); | ||
417 | if (!disk) | ||
418 | goto err_out4; | ||
419 | disk->major = PS2ESDI_MAJOR; | ||
420 | disk->first_minor = i<<6; | ||
421 | sprintf(disk->disk_name, "ed%c", 'a'+i); | ||
422 | disk->fops = &ps2esdi_fops; | ||
423 | ps2esdi_gendisk[i] = disk; | ||
424 | } | ||
425 | |||
426 | for (i = 0; i < ps2esdi_drives; i++) { | ||
427 | struct gendisk *disk = ps2esdi_gendisk[i]; | ||
428 | set_capacity(disk, ps2esdi_info[i].head * ps2esdi_info[i].sect * | ||
429 | ps2esdi_info[i].cyl); | ||
430 | disk->queue = ps2esdi_queue; | ||
431 | disk->private_data = &ps2esdi_info[i]; | ||
432 | add_disk(disk); | ||
433 | } | ||
434 | return 0; | ||
435 | err_out4: | ||
436 | while (i--) | ||
437 | put_disk(ps2esdi_gendisk[i]); | ||
438 | err_out3: | ||
439 | release_region(io_base, 4); | ||
440 | err_out2: | ||
441 | free_irq(PS2ESDI_IRQ, &ps2esdi_gendisk); | ||
442 | err_out1: | ||
443 | if(ps2esdi_slot) { | ||
444 | mca_mark_as_unused(ps2esdi_slot); | ||
445 | mca_set_adapter_procfn(ps2esdi_slot, NULL, NULL); | ||
446 | } | ||
447 | return error; | ||
448 | } | ||
449 | |||
450 | static void __init ps2esdi_get_device_cfg(void) | ||
451 | { | ||
452 | u_short cmd_blk[TYPE_0_CMD_BLK_LENGTH]; | ||
453 | |||
454 | /*BA */ printk("%s: Drive 0\n", DEVICE_NAME); | ||
455 | current_int_handler = ps2esdi_geometry_int_handler; | ||
456 | cmd_blk[0] = CMD_GET_DEV_CONFIG | 0x600; | ||
457 | cmd_blk[1] = 0; | ||
458 | no_int_yet = TRUE; | ||
459 | ps2esdi_out_cmd_blk(cmd_blk); | ||
460 | if (no_int_yet) | ||
461 | sleep_on(&ps2esdi_int); | ||
462 | |||
463 | if (ps2esdi_drives > 1) { | ||
464 | printk("%s: Drive 1\n", DEVICE_NAME); /*BA */ | ||
465 | cmd_blk[0] = CMD_GET_DEV_CONFIG | (1 << 5) | 0x600; | ||
466 | cmd_blk[1] = 0; | ||
467 | no_int_yet = TRUE; | ||
468 | ps2esdi_out_cmd_blk(cmd_blk); | ||
469 | if (no_int_yet) | ||
470 | sleep_on(&ps2esdi_int); | ||
471 | } /* if second physical drive is present */ | ||
472 | return; | ||
473 | } | ||
474 | |||
475 | /* strategy routine that handles most of the IO requests */ | ||
476 | static void do_ps2esdi_request(struct request_queue * q) | ||
477 | { | ||
478 | struct request *req; | ||
479 | /* since, this routine is called with interrupts cleared - they | ||
480 | must be before it finishes */ | ||
481 | |||
482 | req = elv_next_request(q); | ||
483 | if (!req) | ||
484 | return; | ||
485 | |||
486 | #if 0 | ||
487 | printk("%s:got request. device : %s command : %d sector : %ld count : %ld, buffer: %p\n", | ||
488 | DEVICE_NAME, | ||
489 | req->rq_disk->disk_name, | ||
490 | req->cmd, req->sector, | ||
491 | req->current_nr_sectors, req->buffer); | ||
492 | #endif | ||
493 | |||
494 | /* check for above 16Mb dmas */ | ||
495 | if (isa_virt_to_bus(req->buffer + req->current_nr_sectors * 512) > 16 * MB) { | ||
496 | printk("%s: DMA above 16MB not supported\n", DEVICE_NAME); | ||
497 | end_request(req, FAIL); | ||
498 | return; | ||
499 | } | ||
500 | |||
501 | if (req->sector+req->current_nr_sectors > get_capacity(req->rq_disk)) { | ||
502 | printk("Grrr. error. ps2esdi_drives: %d, %llu %llu\n", | ||
503 | ps2esdi_drives, req->sector, | ||
504 | (unsigned long long)get_capacity(req->rq_disk)); | ||
505 | end_request(req, FAIL); | ||
506 | return; | ||
507 | } | ||
508 | |||
509 | switch (rq_data_dir(req)) { | ||
510 | case READ: | ||
511 | ps2esdi_readwrite(READ, req); | ||
512 | break; | ||
513 | case WRITE: | ||
514 | ps2esdi_readwrite(WRITE, req); | ||
515 | break; | ||
516 | default: | ||
517 | printk("%s: Unknown command\n", req->rq_disk->disk_name); | ||
518 | end_request(req, FAIL); | ||
519 | break; | ||
520 | } /* handle different commands */ | ||
521 | } /* main strategy routine */ | ||
522 | |||
523 | /* resets the ESDI adapter */ | ||
524 | static void reset_ctrl(void) | ||
525 | { | ||
526 | |||
527 | u_long expire; | ||
528 | u_short status; | ||
529 | |||
530 | /* enable interrupts on the controller */ | ||
531 | status = inb(ESDI_INTRPT); | ||
532 | outb((status & 0xe0) | ATT_EOI, ESDI_ATTN); /* to be sure we don't have | ||
533 | any interrupt pending... */ | ||
534 | outb_p(CTRL_ENABLE_INTR, ESDI_CONTROL); | ||
535 | |||
536 | /* read the ESDI status port - if the controller is not busy, | ||
537 | simply do a soft reset (fast) - otherwise we'll have to do a | ||
538 | hard (slow) reset. */ | ||
539 | if (!(inb_p(ESDI_STATUS) & STATUS_BUSY)) { | ||
540 | /*BA */ printk("%s: soft reset...\n", DEVICE_NAME); | ||
541 | outb_p(CTRL_SOFT_RESET, ESDI_ATTN); | ||
542 | } | ||
543 | /* soft reset */ | ||
544 | else { | ||
545 | /*BA */ | ||
546 | printk("%s: hard reset...\n", DEVICE_NAME); | ||
547 | outb_p(CTRL_HARD_RESET, ESDI_CONTROL); | ||
548 | expire = jiffies + 2*HZ; | ||
549 | while (time_before(jiffies, expire)); | ||
550 | outb_p(1, ESDI_CONTROL); | ||
551 | } /* hard reset */ | ||
552 | |||
553 | |||
554 | } /* reset the controller */ | ||
555 | |||
556 | /* called by the strategy routine to handle read and write requests */ | ||
557 | static void ps2esdi_readwrite(int cmd, struct request *req) | ||
558 | { | ||
559 | struct ps2esdi_i_struct *p = req->rq_disk->private_data; | ||
560 | unsigned block = req->sector; | ||
561 | unsigned count = req->current_nr_sectors; | ||
562 | int drive = p - ps2esdi_info; | ||
563 | u_short track, head, cylinder, sector; | ||
564 | u_short cmd_blk[TYPE_1_CMD_BLK_LENGTH]; | ||
565 | |||
566 | /* do some relevant arithmatic */ | ||
567 | track = block / p->sect; | ||
568 | head = track % p->head; | ||
569 | cylinder = track / p->head; | ||
570 | sector = block % p->sect; | ||
571 | |||
572 | #if 0 | ||
573 | printk("%s: cyl=%d head=%d sect=%d\n", DEVICE_NAME, cylinder, head, sector); | ||
574 | #endif | ||
575 | /* call the routine that actually fills out a command block */ | ||
576 | ps2esdi_fill_cmd_block | ||
577 | (cmd_blk, | ||
578 | (cmd == READ) ? CMD_READ : CMD_WRITE, | ||
579 | cylinder, head, sector, count, drive); | ||
580 | |||
581 | /* send the command block to the controller */ | ||
582 | current_req = req; | ||
583 | spin_unlock_irq(&ps2esdi_lock); | ||
584 | if (ps2esdi_out_cmd_blk(cmd_blk)) { | ||
585 | spin_lock_irq(&ps2esdi_lock); | ||
586 | printk("%s: Controller failed\n", DEVICE_NAME); | ||
587 | if ((++req->errors) >= MAX_RETRIES) | ||
588 | end_request(req, FAIL); | ||
589 | } | ||
590 | /* check for failure to put out the command block */ | ||
591 | else { | ||
592 | spin_lock_irq(&ps2esdi_lock); | ||
593 | #if 0 | ||
594 | printk("%s: waiting for xfer\n", DEVICE_NAME); | ||
595 | #endif | ||
596 | /* turn disk lights on */ | ||
597 | LITE_ON; | ||
598 | } | ||
599 | |||
600 | } /* ps2esdi_readwrite */ | ||
601 | |||
602 | /* fill out the command block */ | ||
603 | static void ps2esdi_fill_cmd_block(u_short * cmd_blk, u_short cmd, | ||
604 | u_short cyl, u_short head, u_short sector, u_short length, u_char drive) | ||
605 | { | ||
606 | |||
607 | cmd_blk[0] = (drive << 5) | cmd; | ||
608 | cmd_blk[1] = length; | ||
609 | cmd_blk[2] = ((cyl & 0x1f) << 11) | (head << 5) | sector; | ||
610 | cmd_blk[3] = (cyl & 0x3E0) >> 5; | ||
611 | |||
612 | } /* fill out the command block */ | ||
613 | |||
614 | /* write a command block to the controller */ | ||
615 | static int ps2esdi_out_cmd_blk(u_short * cmd_blk) | ||
616 | { | ||
617 | |||
618 | int i; | ||
619 | unsigned long jif; | ||
620 | u_char status; | ||
621 | |||
622 | /* enable interrupts */ | ||
623 | outb(CTRL_ENABLE_INTR, ESDI_CONTROL); | ||
624 | |||
625 | /* do not write to the controller, if it is busy */ | ||
626 | for (jif = jiffies + ESDI_STAT_TIMEOUT; | ||
627 | time_after(jif, jiffies) && | ||
628 | (inb(ESDI_STATUS) & STATUS_BUSY); ) | ||
629 | ; | ||
630 | |||
631 | #if 0 | ||
632 | printk("%s: i(1)=%ld\n", DEVICE_NAME, jif); | ||
633 | #endif | ||
634 | |||
635 | /* if device is still busy - then just time out */ | ||
636 | if (inb(ESDI_STATUS) & STATUS_BUSY) { | ||
637 | printk("%s: ps2esdi_out_cmd timed out (1)\n", DEVICE_NAME); | ||
638 | return ERROR; | ||
639 | } /* timeout ??? */ | ||
640 | /* Set up the attention register in the controller */ | ||
641 | outb(((*cmd_blk) & 0xE0) | 1, ESDI_ATTN); | ||
642 | |||
643 | #if 0 | ||
644 | printk("%s: sending %d words to controller\n", DEVICE_NAME, (((*cmd_blk) >> 14) + 1) << 1); | ||
645 | #endif | ||
646 | |||
647 | /* one by one send each word out */ | ||
648 | for (i = (((*cmd_blk) >> 14) + 1) << 1; i; i--) { | ||
649 | status = inb(ESDI_STATUS); | ||
650 | for (jif = jiffies + ESDI_STAT_TIMEOUT; | ||
651 | time_after(jif, jiffies) && (status & STATUS_BUSY) && | ||
652 | (status & STATUS_CMD_INF); status = inb(ESDI_STATUS)); | ||
653 | if ((status & (STATUS_BUSY | STATUS_CMD_INF)) == STATUS_BUSY) { | ||
654 | #if 0 | ||
655 | printk("%s: sending %04X\n", DEVICE_NAME, *cmd_blk); | ||
656 | #endif | ||
657 | outw(*cmd_blk++, ESDI_CMD_INT); | ||
658 | } else { | ||
659 | printk("%s: ps2esdi_out_cmd timed out while sending command (status=%02X)\n", | ||
660 | DEVICE_NAME, status); | ||
661 | return ERROR; | ||
662 | } | ||
663 | } /* send all words out */ | ||
664 | return OK; | ||
665 | } /* send out the commands */ | ||
666 | |||
667 | |||
668 | /* prepare for dma - do all the necessary setup */ | ||
669 | static void ps2esdi_prep_dma(char *buffer, u_short length, u_char dma_xmode) | ||
670 | { | ||
671 | unsigned long flags = claim_dma_lock(); | ||
672 | |||
673 | mca_disable_dma(dma_arb_level); | ||
674 | |||
675 | mca_set_dma_addr(dma_arb_level, isa_virt_to_bus(buffer)); | ||
676 | |||
677 | mca_set_dma_count(dma_arb_level, length * 512 / 2); | ||
678 | |||
679 | mca_set_dma_mode(dma_arb_level, dma_xmode); | ||
680 | |||
681 | mca_enable_dma(dma_arb_level); | ||
682 | |||
683 | release_dma_lock(flags); | ||
684 | |||
685 | } /* prepare for dma */ | ||
686 | |||
687 | |||
688 | |||
689 | static irqreturn_t ps2esdi_interrupt_handler(int irq, void *dev_id) | ||
690 | { | ||
691 | u_int int_ret_code; | ||
692 | |||
693 | if (inb(ESDI_STATUS) & STATUS_INTR) { | ||
694 | int_ret_code = inb(ESDI_INTRPT); | ||
695 | if (current_int_handler) { | ||
696 | /* Disable adapter interrupts till processing is finished */ | ||
697 | outb(CTRL_DISABLE_INTR, ESDI_CONTROL); | ||
698 | current_int_handler(int_ret_code); | ||
699 | } else | ||
700 | printk("%s: help ! No interrupt handler.\n", DEVICE_NAME); | ||
701 | } else { | ||
702 | return IRQ_NONE; | ||
703 | } | ||
704 | return IRQ_HANDLED; | ||
705 | } | ||
706 | |||
707 | static void ps2esdi_initial_reset_int_handler(u_int int_ret_code) | ||
708 | { | ||
709 | |||
710 | switch (int_ret_code & 0xf) { | ||
711 | case INT_RESET: | ||
712 | /*BA */ | ||
713 | printk("%s: initial reset completed.\n", DEVICE_NAME); | ||
714 | outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); | ||
715 | wake_up(&ps2esdi_int); | ||
716 | break; | ||
717 | case INT_ATTN_ERROR: | ||
718 | printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME, | ||
719 | int_ret_code); | ||
720 | printk("%s: status: %02x\n", DEVICE_NAME, inb(ESDI_STATUS)); | ||
721 | break; | ||
722 | default: | ||
723 | printk("%s: initial reset handler received interrupt: %02X\n", | ||
724 | DEVICE_NAME, int_ret_code); | ||
725 | outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); | ||
726 | break; | ||
727 | } | ||
728 | outb(CTRL_ENABLE_INTR, ESDI_CONTROL); | ||
729 | } | ||
730 | |||
731 | |||
732 | static void ps2esdi_geometry_int_handler(u_int int_ret_code) | ||
733 | { | ||
734 | u_int status, drive_num; | ||
735 | unsigned long rba; | ||
736 | int i; | ||
737 | |||
738 | drive_num = int_ret_code >> 5; | ||
739 | switch (int_ret_code & 0xf) { | ||
740 | case INT_CMD_COMPLETE: | ||
741 | for (i = ESDI_TIMEOUT; i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--); | ||
742 | if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) { | ||
743 | printk("%s: timeout reading status word\n", DEVICE_NAME); | ||
744 | outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); | ||
745 | break; | ||
746 | } | ||
747 | status = inw(ESDI_STT_INT); | ||
748 | if ((status & 0x1F) == CMD_GET_DEV_CONFIG) { | ||
749 | #define REPLY_WORDS 5 /* we already read word 0 */ | ||
750 | u_short reply[REPLY_WORDS]; | ||
751 | |||
752 | if (ps2esdi_read_status_words((status >> 8) - 1, REPLY_WORDS, reply)) { | ||
753 | /*BA */ | ||
754 | printk("%s: Device Configuration Status for drive %u\n", | ||
755 | DEVICE_NAME, drive_num); | ||
756 | |||
757 | printk("%s: Spares/cyls: %u", DEVICE_NAME, reply[0] >> 8); | ||
758 | |||
759 | printk | ||
760 | ("Config bits: %s%s%s%s%s\n", | ||
761 | (reply[0] & CONFIG_IS) ? "Invalid Secondary, " : "", | ||
762 | ((reply[0] & CONFIG_ZD) && !(reply[0] & CONFIG_IS)) | ||
763 | ? "Zero Defect, " : "Defects Present, ", | ||
764 | (reply[0] & CONFIG_SF) ? "Skewed Format, " : "", | ||
765 | (reply[0] & CONFIG_FR) ? "Removable, " : "Non-Removable, ", | ||
766 | (reply[0] & CONFIG_RT) ? "No Retries" : "Retries"); | ||
767 | |||
768 | rba = reply[1] | ((unsigned long) reply[2] << 16); | ||
769 | printk("%s: Number of RBA's: %lu\n", DEVICE_NAME, rba); | ||
770 | |||
771 | printk("%s: Physical number of cylinders: %u, Sectors/Track: %u, Heads: %u\n", | ||
772 | DEVICE_NAME, reply[3], reply[4] >> 8, reply[4] & 0xff); | ||
773 | |||
774 | if (!ps2esdi_info[drive_num].head) { | ||
775 | ps2esdi_info[drive_num].head = 64; | ||
776 | ps2esdi_info[drive_num].sect = 32; | ||
777 | ps2esdi_info[drive_num].cyl = rba / (64 * 32); | ||
778 | ps2esdi_info[drive_num].wpcom = 0; | ||
779 | ps2esdi_info[drive_num].lzone = ps2esdi_info[drive_num].cyl; | ||
780 | ps2esdi_info[drive_num].ctl = 8; | ||
781 | if (tp720esdi) { /* store the retrieved parameters */ | ||
782 | ps2esdi_info[0].head = reply[4] & 0Xff; | ||
783 | ps2esdi_info[0].sect = reply[4] >> 8; | ||
784 | ps2esdi_info[0].cyl = reply[3]; | ||
785 | ps2esdi_info[0].wpcom = 0; | ||
786 | ps2esdi_info[0].lzone = reply[3]; | ||
787 | } else { | ||
788 | if (!intg_esdi) | ||
789 | ps2esdi_drives++; | ||
790 | } | ||
791 | } | ||
792 | #ifdef OBSOLETE | ||
793 | if (!ps2esdi_info[drive_num].head) { | ||
794 | ps2esdi_info[drive_num].head = reply[4] & 0Xff; | ||
795 | ps2esdi_info[drive_num].sect = reply[4] >> 8; | ||
796 | ps2esdi_info[drive_num].cyl = reply[3]; | ||
797 | ps2esdi_info[drive_num].wpcom = 0; | ||
798 | ps2esdi_info[drive_num].lzone = reply[3]; | ||
799 | if (tp720esdi) { /* store the retrieved parameters */ | ||
800 | ps2esdi_info[0].head = reply[4] & 0Xff; | ||
801 | ps2esdi_info[0].sect = reply[4] >> 8; | ||
802 | ps2esdi_info[0].cyl = reply[3]; | ||
803 | ps2esdi_info[0].wpcom = 0; | ||
804 | ps2esdi_info[0].lzone = reply[3]; | ||
805 | } else { | ||
806 | ps2esdi_drives++; | ||
807 | } | ||
808 | } | ||
809 | #endif | ||
810 | |||
811 | } else | ||
812 | printk("%s: failed while getting device config\n", DEVICE_NAME); | ||
813 | #undef REPLY_WORDS | ||
814 | } else | ||
815 | printk("%s: command %02X unknown by geometry handler\n", | ||
816 | DEVICE_NAME, status & 0x1f); | ||
817 | |||
818 | outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); | ||
819 | break; | ||
820 | |||
821 | case INT_ATTN_ERROR: | ||
822 | printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME, | ||
823 | int_ret_code); | ||
824 | printk("%s: Device not available\n", DEVICE_NAME); | ||
825 | break; | ||
826 | case INT_CMD_ECC: | ||
827 | case INT_CMD_RETRY: | ||
828 | case INT_CMD_ECC_RETRY: | ||
829 | case INT_CMD_WARNING: | ||
830 | case INT_CMD_ABORT: | ||
831 | case INT_CMD_FAILED: | ||
832 | case INT_DMA_ERR: | ||
833 | case INT_CMD_BLK_ERR: | ||
834 | /*BA */ printk("%s: Whaa. Error occurred...\n", DEVICE_NAME); | ||
835 | dump_cmd_complete_status(int_ret_code); | ||
836 | outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); | ||
837 | break; | ||
838 | default: | ||
839 | printk("%s: Unknown interrupt reason: %02X\n", | ||
840 | DEVICE_NAME, int_ret_code & 0xf); | ||
841 | outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); | ||
842 | break; | ||
843 | } | ||
844 | |||
845 | wake_up(&ps2esdi_int); | ||
846 | no_int_yet = FALSE; | ||
847 | outb(CTRL_ENABLE_INTR, ESDI_CONTROL); | ||
848 | |||
849 | } | ||
850 | |||
851 | static void ps2esdi_normal_interrupt_handler(u_int int_ret_code) | ||
852 | { | ||
853 | unsigned long flags; | ||
854 | u_int status; | ||
855 | u_int ending; | ||
856 | int i; | ||
857 | |||
858 | switch (int_ret_code & 0x0f) { | ||
859 | case INT_TRANSFER_REQ: | ||
860 | ps2esdi_prep_dma(current_req->buffer, | ||
861 | current_req->current_nr_sectors, | ||
862 | (rq_data_dir(current_req) == READ) | ||
863 | ? MCA_DMA_MODE_16 | MCA_DMA_MODE_WRITE | MCA_DMA_MODE_XFER | ||
864 | : MCA_DMA_MODE_16 | MCA_DMA_MODE_READ); | ||
865 | outb(CTRL_ENABLE_DMA | CTRL_ENABLE_INTR, ESDI_CONTROL); | ||
866 | ending = -1; | ||
867 | break; | ||
868 | |||
869 | case INT_ATTN_ERROR: | ||
870 | printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME, | ||
871 | int_ret_code); | ||
872 | outb(CTRL_ENABLE_INTR, ESDI_CONTROL); | ||
873 | ending = FAIL; | ||
874 | break; | ||
875 | |||
876 | case INT_CMD_COMPLETE: | ||
877 | for (i = ESDI_TIMEOUT; i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--); | ||
878 | if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) { | ||
879 | printk("%s: timeout reading status word\n", DEVICE_NAME); | ||
880 | outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); | ||
881 | outb(CTRL_ENABLE_INTR, ESDI_CONTROL); | ||
882 | if ((++current_req->errors) >= MAX_RETRIES) | ||
883 | ending = FAIL; | ||
884 | else | ||
885 | ending = -1; | ||
886 | break; | ||
887 | } | ||
888 | status = inw(ESDI_STT_INT); | ||
889 | switch (status & 0x1F) { | ||
890 | case (CMD_READ & 0xff): | ||
891 | case (CMD_WRITE & 0xff): | ||
892 | LITE_OFF; | ||
893 | outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); | ||
894 | outb(CTRL_ENABLE_INTR, ESDI_CONTROL); | ||
895 | ending = SUCCES; | ||
896 | break; | ||
897 | default: | ||
898 | printk("%s: interrupt for unknown command %02X\n", | ||
899 | DEVICE_NAME, status & 0x1f); | ||
900 | outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); | ||
901 | outb(CTRL_ENABLE_INTR, ESDI_CONTROL); | ||
902 | ending = -1; | ||
903 | break; | ||
904 | } | ||
905 | break; | ||
906 | case INT_CMD_ECC: | ||
907 | case INT_CMD_RETRY: | ||
908 | case INT_CMD_ECC_RETRY: | ||
909 | LITE_OFF; | ||
910 | dump_cmd_complete_status(int_ret_code); | ||
911 | outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); | ||
912 | outb(CTRL_ENABLE_INTR, ESDI_CONTROL); | ||
913 | ending = SUCCES; | ||
914 | break; | ||
915 | case INT_CMD_WARNING: | ||
916 | case INT_CMD_ABORT: | ||
917 | case INT_CMD_FAILED: | ||
918 | case INT_DMA_ERR: | ||
919 | LITE_OFF; | ||
920 | dump_cmd_complete_status(int_ret_code); | ||
921 | outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); | ||
922 | outb(CTRL_ENABLE_INTR, ESDI_CONTROL); | ||
923 | if ((++current_req->errors) >= MAX_RETRIES) | ||
924 | ending = FAIL; | ||
925 | else | ||
926 | ending = -1; | ||
927 | break; | ||
928 | |||
929 | case INT_CMD_BLK_ERR: | ||
930 | dump_cmd_complete_status(int_ret_code); | ||
931 | outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); | ||
932 | outb(CTRL_ENABLE_INTR, ESDI_CONTROL); | ||
933 | ending = FAIL; | ||
934 | break; | ||
935 | |||
936 | case INT_CMD_FORMAT: | ||
937 | printk("%s: huh ? Who issued this format command ?\n" | ||
938 | ,DEVICE_NAME); | ||
939 | outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); | ||
940 | outb(CTRL_ENABLE_INTR, ESDI_CONTROL); | ||
941 | ending = -1; | ||
942 | break; | ||
943 | |||
944 | case INT_RESET: | ||
945 | /* BA printk("%s: reset completed.\n", DEVICE_NAME) */ ; | ||
946 | outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); | ||
947 | outb(CTRL_ENABLE_INTR, ESDI_CONTROL); | ||
948 | ending = -1; | ||
949 | break; | ||
950 | |||
951 | default: | ||
952 | printk("%s: Unknown interrupt reason: %02X\n", | ||
953 | DEVICE_NAME, int_ret_code & 0xf); | ||
954 | outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); | ||
955 | outb(CTRL_ENABLE_INTR, ESDI_CONTROL); | ||
956 | ending = -1; | ||
957 | break; | ||
958 | } | ||
959 | if(ending != -1) { | ||
960 | spin_lock_irqsave(&ps2esdi_lock, flags); | ||
961 | end_request(current_req, ending); | ||
962 | current_req = NULL; | ||
963 | do_ps2esdi_request(ps2esdi_queue); | ||
964 | spin_unlock_irqrestore(&ps2esdi_lock, flags); | ||
965 | } | ||
966 | } /* handle interrupts */ | ||
967 | |||
968 | |||
969 | |||
970 | static int ps2esdi_read_status_words(int num_words, | ||
971 | int max_words, | ||
972 | u_short * buffer) | ||
973 | { | ||
974 | int i; | ||
975 | |||
976 | for (; max_words && num_words; max_words--, num_words--, buffer++) { | ||
977 | for (i = ESDI_TIMEOUT; i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--); | ||
978 | if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) { | ||
979 | printk("%s: timeout reading status word\n", DEVICE_NAME); | ||
980 | return FAIL; | ||
981 | } | ||
982 | *buffer = inw(ESDI_STT_INT); | ||
983 | } | ||
984 | return SUCCES; | ||
985 | } | ||
986 | |||
987 | |||
988 | |||
989 | |||
990 | static void dump_cmd_complete_status(u_int int_ret_code) | ||
991 | { | ||
992 | #define WAIT_FOR_STATUS \ | ||
993 | for(i=ESDI_TIMEOUT;i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL);i--); \ | ||
994 | if(!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) { \ | ||
995 | printk("%s: timeout reading status word\n",DEVICE_NAME); \ | ||
996 | return; \ | ||
997 | } | ||
998 | |||
999 | int i, word_count; | ||
1000 | u_short stat_word; | ||
1001 | u_long rba; | ||
1002 | |||
1003 | printk("%s: Device: %u, interrupt ID: %02X\n", | ||
1004 | DEVICE_NAME, int_ret_code >> 5, | ||
1005 | int_ret_code & 0xf); | ||
1006 | |||
1007 | WAIT_FOR_STATUS; | ||
1008 | stat_word = inw(ESDI_STT_INT); | ||
1009 | word_count = (stat_word >> 8) - 1; | ||
1010 | printk("%s: %u status words, command: %02X\n", DEVICE_NAME, word_count, | ||
1011 | stat_word & 0xff); | ||
1012 | |||
1013 | if (word_count--) { | ||
1014 | WAIT_FOR_STATUS; | ||
1015 | stat_word = inw(ESDI_STT_INT); | ||
1016 | printk("%s: command status code: %02X, command error code: %02X\n", | ||
1017 | DEVICE_NAME, stat_word >> 8, stat_word & 0xff); | ||
1018 | } | ||
1019 | if (word_count--) { | ||
1020 | WAIT_FOR_STATUS; | ||
1021 | stat_word = inw(ESDI_STT_INT); | ||
1022 | printk("%s: device error code: %s%s%s%s%s,%02X\n", DEVICE_NAME, | ||
1023 | (stat_word & 0x1000) ? "Ready, " : "Not Ready, ", | ||
1024 | (stat_word & 0x0800) ? "Selected, " : "Not Selected, ", | ||
1025 | (stat_word & 0x0400) ? "Write Fault, " : "", | ||
1026 | (stat_word & 0x0200) ? "Track 0, " : "", | ||
1027 | (stat_word & 0x0100) ? "Seek or command complete, " : "", | ||
1028 | stat_word >> 8); | ||
1029 | } | ||
1030 | if (word_count--) { | ||
1031 | WAIT_FOR_STATUS; | ||
1032 | stat_word = inw(ESDI_STT_INT); | ||
1033 | printk("%s: Blocks to do: %u", DEVICE_NAME, stat_word); | ||
1034 | } | ||
1035 | if (word_count -= 2) { | ||
1036 | WAIT_FOR_STATUS; | ||
1037 | rba = inw(ESDI_STT_INT); | ||
1038 | WAIT_FOR_STATUS; | ||
1039 | rba |= inw(ESDI_STT_INT) << 16; | ||
1040 | printk(", Last Cyl: %u Head: %u Sector: %u\n", | ||
1041 | (u_short) ((rba & 0x1ff80000) >> 11), | ||
1042 | (u_short) ((rba & 0x7E0) >> 5), (u_short) (rba & 0x1f)); | ||
1043 | } else | ||
1044 | printk("\n"); | ||
1045 | |||
1046 | if (word_count--) { | ||
1047 | WAIT_FOR_STATUS; | ||
1048 | stat_word = inw(ESDI_STT_INT); | ||
1049 | printk("%s: Blocks required ECC: %u", DEVICE_NAME, stat_word); | ||
1050 | } | ||
1051 | printk("\n"); | ||
1052 | |||
1053 | #undef WAIT_FOR_STATUS | ||
1054 | |||
1055 | } | ||
1056 | |||
1057 | static int ps2esdi_getgeo(struct block_device *bdev, struct hd_geometry *geo) | ||
1058 | { | ||
1059 | struct ps2esdi_i_struct *p = bdev->bd_disk->private_data; | ||
1060 | |||
1061 | geo->heads = p->head; | ||
1062 | geo->sectors = p->sect; | ||
1063 | geo->cylinders = p->cyl; | ||
1064 | return 0; | ||
1065 | } | ||
1066 | |||
1067 | static void ps2esdi_reset_timer(unsigned long unused) | ||
1068 | { | ||
1069 | |||
1070 | int status; | ||
1071 | |||
1072 | status = inb(ESDI_INTRPT); | ||
1073 | if ((status & 0xf) == INT_RESET) { | ||
1074 | outb((status & 0xe0) | ATT_EOI, ESDI_ATTN); | ||
1075 | outb(CTRL_ENABLE_INTR, ESDI_CONTROL); | ||
1076 | reset_status = 1; | ||
1077 | } | ||
1078 | wake_up(&ps2esdi_int); | ||
1079 | } | ||
diff --git a/drivers/block/sx8.c b/drivers/block/sx8.c index cd5674b63faf..a18e1ca0f761 100644 --- a/drivers/block/sx8.c +++ b/drivers/block/sx8.c | |||
@@ -79,9 +79,9 @@ MODULE_PARM_DESC(max_queue, "Maximum number of queued commands. (min==1, max==30 | |||
79 | 79 | ||
80 | /* note: prints function name for you */ | 80 | /* note: prints function name for you */ |
81 | #ifdef CARM_DEBUG | 81 | #ifdef CARM_DEBUG |
82 | #define DPRINTK(fmt, args...) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ## args) | 82 | #define DPRINTK(fmt, args...) printk(KERN_ERR "%s: " fmt, __func__, ## args) |
83 | #ifdef CARM_VERBOSE_DEBUG | 83 | #ifdef CARM_VERBOSE_DEBUG |
84 | #define VPRINTK(fmt, args...) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ## args) | 84 | #define VPRINTK(fmt, args...) printk(KERN_ERR "%s: " fmt, __func__, ## args) |
85 | #else | 85 | #else |
86 | #define VPRINTK(fmt, args...) | 86 | #define VPRINTK(fmt, args...) |
87 | #endif /* CARM_VERBOSE_DEBUG */ | 87 | #endif /* CARM_VERBOSE_DEBUG */ |
@@ -96,7 +96,7 @@ MODULE_PARM_DESC(max_queue, "Maximum number of queued commands. (min==1, max==30 | |||
96 | #define assert(expr) \ | 96 | #define assert(expr) \ |
97 | if(unlikely(!(expr))) { \ | 97 | if(unlikely(!(expr))) { \ |
98 | printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \ | 98 | printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \ |
99 | #expr,__FILE__,__FUNCTION__,__LINE__); \ | 99 | #expr, __FILE__, __func__, __LINE__); \ |
100 | } | 100 | } |
101 | #endif | 101 | #endif |
102 | 102 | ||
diff --git a/drivers/block/ub.c b/drivers/block/ub.c index c452e2d355ee..27bfe72aab59 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c | |||
@@ -8,6 +8,7 @@ | |||
8 | * and is not licensed separately. See file COPYING for details. | 8 | * and is not licensed separately. See file COPYING for details. |
9 | * | 9 | * |
10 | * TODO (sorted by decreasing priority) | 10 | * TODO (sorted by decreasing priority) |
11 | * -- Return sense now that rq allows it (we always auto-sense anyway). | ||
11 | * -- set readonly flag for CDs, set removable flag for CF readers | 12 | * -- set readonly flag for CDs, set removable flag for CF readers |
12 | * -- do inquiry and verify we got a disk and not a tape (for LUN mismatch) | 13 | * -- do inquiry and verify we got a disk and not a tape (for LUN mismatch) |
13 | * -- verify the 13 conditions and do bulk resets | 14 | * -- verify the 13 conditions and do bulk resets |
@@ -359,7 +360,8 @@ static void ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun, | |||
359 | static void ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun, | 360 | static void ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun, |
360 | struct ub_scsi_cmd *cmd, struct ub_request *urq); | 361 | struct ub_scsi_cmd *cmd, struct ub_request *urq); |
361 | static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd); | 362 | static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd); |
362 | static void ub_end_rq(struct request *rq, unsigned int status); | 363 | static void ub_end_rq(struct request *rq, unsigned int status, |
364 | unsigned int cmd_len); | ||
363 | static int ub_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun, | 365 | static int ub_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun, |
364 | struct ub_request *urq, struct ub_scsi_cmd *cmd); | 366 | struct ub_request *urq, struct ub_scsi_cmd *cmd); |
365 | static int ub_submit_scsi(struct ub_dev *sc, struct ub_scsi_cmd *cmd); | 367 | static int ub_submit_scsi(struct ub_dev *sc, struct ub_scsi_cmd *cmd); |
@@ -642,13 +644,13 @@ static int ub_request_fn_1(struct ub_lun *lun, struct request *rq) | |||
642 | 644 | ||
643 | if (atomic_read(&sc->poison)) { | 645 | if (atomic_read(&sc->poison)) { |
644 | blkdev_dequeue_request(rq); | 646 | blkdev_dequeue_request(rq); |
645 | ub_end_rq(rq, DID_NO_CONNECT << 16); | 647 | ub_end_rq(rq, DID_NO_CONNECT << 16, blk_rq_bytes(rq)); |
646 | return 0; | 648 | return 0; |
647 | } | 649 | } |
648 | 650 | ||
649 | if (lun->changed && !blk_pc_request(rq)) { | 651 | if (lun->changed && !blk_pc_request(rq)) { |
650 | blkdev_dequeue_request(rq); | 652 | blkdev_dequeue_request(rq); |
651 | ub_end_rq(rq, SAM_STAT_CHECK_CONDITION); | 653 | ub_end_rq(rq, SAM_STAT_CHECK_CONDITION, blk_rq_bytes(rq)); |
652 | return 0; | 654 | return 0; |
653 | } | 655 | } |
654 | 656 | ||
@@ -701,7 +703,7 @@ static int ub_request_fn_1(struct ub_lun *lun, struct request *rq) | |||
701 | 703 | ||
702 | drop: | 704 | drop: |
703 | ub_put_cmd(lun, cmd); | 705 | ub_put_cmd(lun, cmd); |
704 | ub_end_rq(rq, DID_ERROR << 16); | 706 | ub_end_rq(rq, DID_ERROR << 16, blk_rq_bytes(rq)); |
705 | return 0; | 707 | return 0; |
706 | } | 708 | } |
707 | 709 | ||
@@ -770,6 +772,7 @@ static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd) | |||
770 | struct ub_request *urq = cmd->back; | 772 | struct ub_request *urq = cmd->back; |
771 | struct request *rq; | 773 | struct request *rq; |
772 | unsigned int scsi_status; | 774 | unsigned int scsi_status; |
775 | unsigned int cmd_len; | ||
773 | 776 | ||
774 | rq = urq->rq; | 777 | rq = urq->rq; |
775 | 778 | ||
@@ -779,8 +782,18 @@ static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd) | |||
779 | rq->data_len = 0; | 782 | rq->data_len = 0; |
780 | else | 783 | else |
781 | rq->data_len -= cmd->act_len; | 784 | rq->data_len -= cmd->act_len; |
785 | scsi_status = 0; | ||
786 | } else { | ||
787 | if (cmd->act_len != cmd->len) { | ||
788 | if ((cmd->key == MEDIUM_ERROR || | ||
789 | cmd->key == UNIT_ATTENTION) && | ||
790 | ub_rw_cmd_retry(sc, lun, urq, cmd) == 0) | ||
791 | return; | ||
792 | scsi_status = SAM_STAT_CHECK_CONDITION; | ||
793 | } else { | ||
794 | scsi_status = 0; | ||
795 | } | ||
782 | } | 796 | } |
783 | scsi_status = 0; | ||
784 | } else { | 797 | } else { |
785 | if (blk_pc_request(rq)) { | 798 | if (blk_pc_request(rq)) { |
786 | /* UB_SENSE_SIZE is smaller than SCSI_SENSE_BUFFERSIZE */ | 799 | /* UB_SENSE_SIZE is smaller than SCSI_SENSE_BUFFERSIZE */ |
@@ -801,14 +814,17 @@ static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd) | |||
801 | 814 | ||
802 | urq->rq = NULL; | 815 | urq->rq = NULL; |
803 | 816 | ||
817 | cmd_len = cmd->len; | ||
804 | ub_put_cmd(lun, cmd); | 818 | ub_put_cmd(lun, cmd); |
805 | ub_end_rq(rq, scsi_status); | 819 | ub_end_rq(rq, scsi_status, cmd_len); |
806 | blk_start_queue(lun->disk->queue); | 820 | blk_start_queue(lun->disk->queue); |
807 | } | 821 | } |
808 | 822 | ||
809 | static void ub_end_rq(struct request *rq, unsigned int scsi_status) | 823 | static void ub_end_rq(struct request *rq, unsigned int scsi_status, |
824 | unsigned int cmd_len) | ||
810 | { | 825 | { |
811 | int error; | 826 | int error; |
827 | long rqlen; | ||
812 | 828 | ||
813 | if (scsi_status == 0) { | 829 | if (scsi_status == 0) { |
814 | error = 0; | 830 | error = 0; |
@@ -816,8 +832,12 @@ static void ub_end_rq(struct request *rq, unsigned int scsi_status) | |||
816 | error = -EIO; | 832 | error = -EIO; |
817 | rq->errors = scsi_status; | 833 | rq->errors = scsi_status; |
818 | } | 834 | } |
819 | if (__blk_end_request(rq, error, blk_rq_bytes(rq))) | 835 | rqlen = blk_rq_bytes(rq); /* Oddly enough, this is the residue. */ |
820 | BUG(); | 836 | if (__blk_end_request(rq, error, cmd_len)) { |
837 | printk(KERN_WARNING DRV_NAME | ||
838 | ": __blk_end_request blew, %s-cmd total %u rqlen %ld\n", | ||
839 | blk_pc_request(rq)? "pc": "fs", cmd_len, rqlen); | ||
840 | } | ||
821 | } | 841 | } |
822 | 842 | ||
823 | static int ub_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun, | 843 | static int ub_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun, |
diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c index 9e61fca46117..ebfe038d859e 100644 --- a/drivers/block/viodasd.c +++ b/drivers/block/viodasd.c | |||
@@ -69,7 +69,7 @@ MODULE_LICENSE("GPL"); | |||
69 | enum { | 69 | enum { |
70 | PARTITION_SHIFT = 3, | 70 | PARTITION_SHIFT = 3, |
71 | MAX_DISKNO = HVMAXARCHITECTEDVIRTUALDISKS, | 71 | MAX_DISKNO = HVMAXARCHITECTEDVIRTUALDISKS, |
72 | MAX_DISK_NAME = sizeof(((struct gendisk *)0)->disk_name) | 72 | MAX_DISK_NAME = FIELD_SIZEOF(struct gendisk, disk_name) |
73 | }; | 73 | }; |
74 | 74 | ||
75 | static DEFINE_SPINLOCK(viodasd_spinlock); | 75 | static DEFINE_SPINLOCK(viodasd_spinlock); |
@@ -528,8 +528,7 @@ static int block_event_to_scatterlist(const struct vioblocklpevent *bevent, | |||
528 | numsg = VIOMAXBLOCKDMA; | 528 | numsg = VIOMAXBLOCKDMA; |
529 | 529 | ||
530 | *total_len = 0; | 530 | *total_len = 0; |
531 | memset(sg, 0, sizeof(sg[0]) * VIOMAXBLOCKDMA); | 531 | sg_init_table(sg, VIOMAXBLOCKDMA); |
532 | |||
533 | for (i = 0; (i < numsg) && (rw_data->dma_info[i].len > 0); ++i) { | 532 | for (i = 0; (i < numsg) && (rw_data->dma_info[i].len > 0); ++i) { |
534 | sg_dma_address(&sg[i]) = rw_data->dma_info[i].token; | 533 | sg_dma_address(&sg[i]) = rw_data->dma_info[i].token; |
535 | sg_dma_len(&sg[i]) = rw_data->dma_info[i].len; | 534 | sg_dma_len(&sg[i]) = rw_data->dma_info[i].len; |
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 3b1a68d6eddb..0cfbe8c594a5 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c | |||
@@ -238,6 +238,7 @@ static int virtblk_probe(struct virtio_device *vdev) | |||
238 | vblk->disk->first_minor = index_to_minor(index); | 238 | vblk->disk->first_minor = index_to_minor(index); |
239 | vblk->disk->private_data = vblk; | 239 | vblk->disk->private_data = vblk; |
240 | vblk->disk->fops = &virtblk_fops; | 240 | vblk->disk->fops = &virtblk_fops; |
241 | vblk->disk->driverfs_dev = &vdev->dev; | ||
241 | index++; | 242 | index++; |
242 | 243 | ||
243 | /* If barriers are supported, tell block layer that queue is ordered */ | 244 | /* If barriers are supported, tell block layer that queue is ordered */ |
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 8afce67c0aa5..9c6f3f99208d 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c | |||
@@ -37,6 +37,7 @@ | |||
37 | 37 | ||
38 | #include <linux/interrupt.h> | 38 | #include <linux/interrupt.h> |
39 | #include <linux/blkdev.h> | 39 | #include <linux/blkdev.h> |
40 | #include <linux/hdreg.h> | ||
40 | #include <linux/module.h> | 41 | #include <linux/module.h> |
41 | 42 | ||
42 | #include <xen/xenbus.h> | 43 | #include <xen/xenbus.h> |
@@ -135,6 +136,22 @@ static void blkif_restart_queue_callback(void *arg) | |||
135 | schedule_work(&info->work); | 136 | schedule_work(&info->work); |
136 | } | 137 | } |
137 | 138 | ||
139 | int blkif_getgeo(struct block_device *bd, struct hd_geometry *hg) | ||
140 | { | ||
141 | /* We don't have real geometry info, but let's at least return | ||
142 | values consistent with the size of the device */ | ||
143 | sector_t nsect = get_capacity(bd->bd_disk); | ||
144 | sector_t cylinders = nsect; | ||
145 | |||
146 | hg->heads = 0xff; | ||
147 | hg->sectors = 0x3f; | ||
148 | sector_div(cylinders, hg->heads * hg->sectors); | ||
149 | hg->cylinders = cylinders; | ||
150 | if ((sector_t)(hg->cylinders + 1) * hg->heads * hg->sectors < nsect) | ||
151 | hg->cylinders = 0xffff; | ||
152 | return 0; | ||
153 | } | ||
154 | |||
138 | /* | 155 | /* |
139 | * blkif_queue_request | 156 | * blkif_queue_request |
140 | * | 157 | * |
@@ -937,6 +954,7 @@ static struct block_device_operations xlvbd_block_fops = | |||
937 | .owner = THIS_MODULE, | 954 | .owner = THIS_MODULE, |
938 | .open = blkif_open, | 955 | .open = blkif_open, |
939 | .release = blkif_release, | 956 | .release = blkif_release, |
957 | .getgeo = blkif_getgeo, | ||
940 | }; | 958 | }; |
941 | 959 | ||
942 | 960 | ||