diff options
Diffstat (limited to 'drivers/block/pktcdvd.c')
-rw-r--r-- | drivers/block/pktcdvd.c | 139 |
1 files changed, 60 insertions, 79 deletions
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 4e7dbcc425ff..bc9b2bcd7dba 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c | |||
@@ -58,6 +58,7 @@ | |||
58 | #include <linux/suspend.h> | 58 | #include <linux/suspend.h> |
59 | #include <scsi/scsi_cmnd.h> | 59 | #include <scsi/scsi_cmnd.h> |
60 | #include <scsi/scsi_ioctl.h> | 60 | #include <scsi/scsi_ioctl.h> |
61 | #include <scsi/scsi.h> | ||
61 | 62 | ||
62 | #include <asm/uaccess.h> | 63 | #include <asm/uaccess.h> |
63 | 64 | ||
@@ -380,6 +381,7 @@ static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command * | |||
380 | memcpy(rq->cmd, cgc->cmd, CDROM_PACKET_SIZE); | 381 | memcpy(rq->cmd, cgc->cmd, CDROM_PACKET_SIZE); |
381 | if (sizeof(rq->cmd) > CDROM_PACKET_SIZE) | 382 | if (sizeof(rq->cmd) > CDROM_PACKET_SIZE) |
382 | memset(rq->cmd + CDROM_PACKET_SIZE, 0, sizeof(rq->cmd) - CDROM_PACKET_SIZE); | 383 | memset(rq->cmd + CDROM_PACKET_SIZE, 0, sizeof(rq->cmd) - CDROM_PACKET_SIZE); |
384 | rq->cmd_len = COMMAND_SIZE(rq->cmd[0]); | ||
383 | 385 | ||
384 | rq->ref_count++; | 386 | rq->ref_count++; |
385 | rq->flags |= REQ_NOMERGE; | 387 | rq->flags |= REQ_NOMERGE; |
@@ -645,7 +647,7 @@ static void pkt_copy_bio_data(struct bio *src_bio, int seg, int offs, struct pag | |||
645 | * b) The data can be used as cache to avoid read requests if we receive a | 647 | * b) The data can be used as cache to avoid read requests if we receive a |
646 | * new write request for the same zone. | 648 | * new write request for the same zone. |
647 | */ | 649 | */ |
648 | static void pkt_make_local_copy(struct packet_data *pkt, struct page **pages, int *offsets) | 650 | static void pkt_make_local_copy(struct packet_data *pkt, struct bio_vec *bvec) |
649 | { | 651 | { |
650 | int f, p, offs; | 652 | int f, p, offs; |
651 | 653 | ||
@@ -653,15 +655,15 @@ static void pkt_make_local_copy(struct packet_data *pkt, struct page **pages, in | |||
653 | p = 0; | 655 | p = 0; |
654 | offs = 0; | 656 | offs = 0; |
655 | for (f = 0; f < pkt->frames; f++) { | 657 | for (f = 0; f < pkt->frames; f++) { |
656 | if (pages[f] != pkt->pages[p]) { | 658 | if (bvec[f].bv_page != pkt->pages[p]) { |
657 | void *vfrom = kmap_atomic(pages[f], KM_USER0) + offsets[f]; | 659 | void *vfrom = kmap_atomic(bvec[f].bv_page, KM_USER0) + bvec[f].bv_offset; |
658 | void *vto = page_address(pkt->pages[p]) + offs; | 660 | void *vto = page_address(pkt->pages[p]) + offs; |
659 | memcpy(vto, vfrom, CD_FRAMESIZE); | 661 | memcpy(vto, vfrom, CD_FRAMESIZE); |
660 | kunmap_atomic(vfrom, KM_USER0); | 662 | kunmap_atomic(vfrom, KM_USER0); |
661 | pages[f] = pkt->pages[p]; | 663 | bvec[f].bv_page = pkt->pages[p]; |
662 | offsets[f] = offs; | 664 | bvec[f].bv_offset = offs; |
663 | } else { | 665 | } else { |
664 | BUG_ON(offsets[f] != offs); | 666 | BUG_ON(bvec[f].bv_offset != offs); |
665 | } | 667 | } |
666 | offs += CD_FRAMESIZE; | 668 | offs += CD_FRAMESIZE; |
667 | if (offs >= PAGE_SIZE) { | 669 | if (offs >= PAGE_SIZE) { |
@@ -991,18 +993,17 @@ try_next_bio: | |||
991 | static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt) | 993 | static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt) |
992 | { | 994 | { |
993 | struct bio *bio; | 995 | struct bio *bio; |
994 | struct page *pages[PACKET_MAX_SIZE]; | ||
995 | int offsets[PACKET_MAX_SIZE]; | ||
996 | int f; | 996 | int f; |
997 | int frames_write; | 997 | int frames_write; |
998 | struct bio_vec *bvec = pkt->w_bio->bi_io_vec; | ||
998 | 999 | ||
999 | for (f = 0; f < pkt->frames; f++) { | 1000 | for (f = 0; f < pkt->frames; f++) { |
1000 | pages[f] = pkt->pages[(f * CD_FRAMESIZE) / PAGE_SIZE]; | 1001 | bvec[f].bv_page = pkt->pages[(f * CD_FRAMESIZE) / PAGE_SIZE]; |
1001 | offsets[f] = (f * CD_FRAMESIZE) % PAGE_SIZE; | 1002 | bvec[f].bv_offset = (f * CD_FRAMESIZE) % PAGE_SIZE; |
1002 | } | 1003 | } |
1003 | 1004 | ||
1004 | /* | 1005 | /* |
1005 | * Fill-in pages[] and offsets[] with data from orig_bios. | 1006 | * Fill-in bvec with data from orig_bios. |
1006 | */ | 1007 | */ |
1007 | frames_write = 0; | 1008 | frames_write = 0; |
1008 | spin_lock(&pkt->lock); | 1009 | spin_lock(&pkt->lock); |
@@ -1024,11 +1025,11 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt) | |||
1024 | } | 1025 | } |
1025 | 1026 | ||
1026 | if (src_bvl->bv_len - src_offs >= CD_FRAMESIZE) { | 1027 | if (src_bvl->bv_len - src_offs >= CD_FRAMESIZE) { |
1027 | pages[f] = src_bvl->bv_page; | 1028 | bvec[f].bv_page = src_bvl->bv_page; |
1028 | offsets[f] = src_bvl->bv_offset + src_offs; | 1029 | bvec[f].bv_offset = src_bvl->bv_offset + src_offs; |
1029 | } else { | 1030 | } else { |
1030 | pkt_copy_bio_data(bio, segment, src_offs, | 1031 | pkt_copy_bio_data(bio, segment, src_offs, |
1031 | pages[f], offsets[f]); | 1032 | bvec[f].bv_page, bvec[f].bv_offset); |
1032 | } | 1033 | } |
1033 | src_offs += CD_FRAMESIZE; | 1034 | src_offs += CD_FRAMESIZE; |
1034 | frames_write++; | 1035 | frames_write++; |
@@ -1042,7 +1043,7 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt) | |||
1042 | BUG_ON(frames_write != pkt->write_size); | 1043 | BUG_ON(frames_write != pkt->write_size); |
1043 | 1044 | ||
1044 | if (test_bit(PACKET_MERGE_SEGS, &pd->flags) || (pkt->write_size < pkt->frames)) { | 1045 | if (test_bit(PACKET_MERGE_SEGS, &pd->flags) || (pkt->write_size < pkt->frames)) { |
1045 | pkt_make_local_copy(pkt, pages, offsets); | 1046 | pkt_make_local_copy(pkt, bvec); |
1046 | pkt->cache_valid = 1; | 1047 | pkt->cache_valid = 1; |
1047 | } else { | 1048 | } else { |
1048 | pkt->cache_valid = 0; | 1049 | pkt->cache_valid = 0; |
@@ -1055,17 +1056,9 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt) | |||
1055 | pkt->w_bio->bi_bdev = pd->bdev; | 1056 | pkt->w_bio->bi_bdev = pd->bdev; |
1056 | pkt->w_bio->bi_end_io = pkt_end_io_packet_write; | 1057 | pkt->w_bio->bi_end_io = pkt_end_io_packet_write; |
1057 | pkt->w_bio->bi_private = pkt; | 1058 | pkt->w_bio->bi_private = pkt; |
1058 | for (f = 0; f < pkt->frames; f++) { | 1059 | for (f = 0; f < pkt->frames; f++) |
1059 | if ((f + 1 < pkt->frames) && (pages[f + 1] == pages[f]) && | 1060 | if (!bio_add_page(pkt->w_bio, bvec[f].bv_page, CD_FRAMESIZE, bvec[f].bv_offset)) |
1060 | (offsets[f + 1] = offsets[f] + CD_FRAMESIZE)) { | 1061 | BUG(); |
1061 | if (!bio_add_page(pkt->w_bio, pages[f], CD_FRAMESIZE * 2, offsets[f])) | ||
1062 | BUG(); | ||
1063 | f++; | ||
1064 | } else { | ||
1065 | if (!bio_add_page(pkt->w_bio, pages[f], CD_FRAMESIZE, offsets[f])) | ||
1066 | BUG(); | ||
1067 | } | ||
1068 | } | ||
1069 | VPRINTK("pktcdvd: vcnt=%d\n", pkt->w_bio->bi_vcnt); | 1062 | VPRINTK("pktcdvd: vcnt=%d\n", pkt->w_bio->bi_vcnt); |
1070 | 1063 | ||
1071 | atomic_set(&pkt->io_wait, 1); | 1064 | atomic_set(&pkt->io_wait, 1); |
@@ -1504,40 +1497,42 @@ static int pkt_set_write_settings(struct pktcdvd_device *pd) | |||
1504 | } | 1497 | } |
1505 | 1498 | ||
1506 | /* | 1499 | /* |
1507 | * 0 -- we can write to this track, 1 -- we can't | 1500 | * 1 -- we can write to this track, 0 -- we can't |
1508 | */ | 1501 | */ |
1509 | static int pkt_good_track(track_information *ti) | 1502 | static int pkt_writable_track(struct pktcdvd_device *pd, track_information *ti) |
1510 | { | 1503 | { |
1511 | /* | 1504 | switch (pd->mmc3_profile) { |
1512 | * only good for CD-RW at the moment, not DVD-RW | 1505 | case 0x1a: /* DVD+RW */ |
1513 | */ | 1506 | case 0x12: /* DVD-RAM */ |
1507 | /* The track is always writable on DVD+RW/DVD-RAM */ | ||
1508 | return 1; | ||
1509 | default: | ||
1510 | break; | ||
1511 | } | ||
1514 | 1512 | ||
1515 | /* | 1513 | if (!ti->packet || !ti->fp) |
1516 | * FIXME: only for FP | ||
1517 | */ | ||
1518 | if (ti->fp == 0) | ||
1519 | return 0; | 1514 | return 0; |
1520 | 1515 | ||
1521 | /* | 1516 | /* |
1522 | * "good" settings as per Mt Fuji. | 1517 | * "good" settings as per Mt Fuji. |
1523 | */ | 1518 | */ |
1524 | if (ti->rt == 0 && ti->blank == 0 && ti->packet == 1) | 1519 | if (ti->rt == 0 && ti->blank == 0) |
1525 | return 0; | 1520 | return 1; |
1526 | 1521 | ||
1527 | if (ti->rt == 0 && ti->blank == 1 && ti->packet == 1) | 1522 | if (ti->rt == 0 && ti->blank == 1) |
1528 | return 0; | 1523 | return 1; |
1529 | 1524 | ||
1530 | if (ti->rt == 1 && ti->blank == 0 && ti->packet == 1) | 1525 | if (ti->rt == 1 && ti->blank == 0) |
1531 | return 0; | 1526 | return 1; |
1532 | 1527 | ||
1533 | printk("pktcdvd: bad state %d-%d-%d\n", ti->rt, ti->blank, ti->packet); | 1528 | printk("pktcdvd: bad state %d-%d-%d\n", ti->rt, ti->blank, ti->packet); |
1534 | return 1; | 1529 | return 0; |
1535 | } | 1530 | } |
1536 | 1531 | ||
1537 | /* | 1532 | /* |
1538 | * 0 -- we can write to this disc, 1 -- we can't | 1533 | * 1 -- we can write to this disc, 0 -- we can't |
1539 | */ | 1534 | */ |
1540 | static int pkt_good_disc(struct pktcdvd_device *pd, disc_information *di) | 1535 | static int pkt_writable_disc(struct pktcdvd_device *pd, disc_information *di) |
1541 | { | 1536 | { |
1542 | switch (pd->mmc3_profile) { | 1537 | switch (pd->mmc3_profile) { |
1543 | case 0x0a: /* CD-RW */ | 1538 | case 0x0a: /* CD-RW */ |
@@ -1546,10 +1541,10 @@ static int pkt_good_disc(struct pktcdvd_device *pd, disc_information *di) | |||
1546 | case 0x1a: /* DVD+RW */ | 1541 | case 0x1a: /* DVD+RW */ |
1547 | case 0x13: /* DVD-RW */ | 1542 | case 0x13: /* DVD-RW */ |
1548 | case 0x12: /* DVD-RAM */ | 1543 | case 0x12: /* DVD-RAM */ |
1549 | return 0; | ||
1550 | default: | ||
1551 | printk("pktcdvd: Wrong disc profile (%x)\n", pd->mmc3_profile); | ||
1552 | return 1; | 1544 | return 1; |
1545 | default: | ||
1546 | VPRINTK("pktcdvd: Wrong disc profile (%x)\n", pd->mmc3_profile); | ||
1547 | return 0; | ||
1553 | } | 1548 | } |
1554 | 1549 | ||
1555 | /* | 1550 | /* |
@@ -1558,25 +1553,25 @@ static int pkt_good_disc(struct pktcdvd_device *pd, disc_information *di) | |||
1558 | */ | 1553 | */ |
1559 | if (di->disc_type == 0xff) { | 1554 | if (di->disc_type == 0xff) { |
1560 | printk("pktcdvd: Unknown disc. No track?\n"); | 1555 | printk("pktcdvd: Unknown disc. No track?\n"); |
1561 | return 1; | 1556 | return 0; |
1562 | } | 1557 | } |
1563 | 1558 | ||
1564 | if (di->disc_type != 0x20 && di->disc_type != 0) { | 1559 | if (di->disc_type != 0x20 && di->disc_type != 0) { |
1565 | printk("pktcdvd: Wrong disc type (%x)\n", di->disc_type); | 1560 | printk("pktcdvd: Wrong disc type (%x)\n", di->disc_type); |
1566 | return 1; | 1561 | return 0; |
1567 | } | 1562 | } |
1568 | 1563 | ||
1569 | if (di->erasable == 0) { | 1564 | if (di->erasable == 0) { |
1570 | printk("pktcdvd: Disc not erasable\n"); | 1565 | printk("pktcdvd: Disc not erasable\n"); |
1571 | return 1; | 1566 | return 0; |
1572 | } | 1567 | } |
1573 | 1568 | ||
1574 | if (di->border_status == PACKET_SESSION_RESERVED) { | 1569 | if (di->border_status == PACKET_SESSION_RESERVED) { |
1575 | printk("pktcdvd: Can't write to last track (reserved)\n"); | 1570 | printk("pktcdvd: Can't write to last track (reserved)\n"); |
1576 | return 1; | 1571 | return 0; |
1577 | } | 1572 | } |
1578 | 1573 | ||
1579 | return 0; | 1574 | return 1; |
1580 | } | 1575 | } |
1581 | 1576 | ||
1582 | static int pkt_probe_settings(struct pktcdvd_device *pd) | 1577 | static int pkt_probe_settings(struct pktcdvd_device *pd) |
@@ -1601,23 +1596,9 @@ static int pkt_probe_settings(struct pktcdvd_device *pd) | |||
1601 | return ret; | 1596 | return ret; |
1602 | } | 1597 | } |
1603 | 1598 | ||
1604 | if (pkt_good_disc(pd, &di)) | 1599 | if (!pkt_writable_disc(pd, &di)) |
1605 | return -ENXIO; | 1600 | return -EROFS; |
1606 | 1601 | ||
1607 | switch (pd->mmc3_profile) { | ||
1608 | case 0x1a: /* DVD+RW */ | ||
1609 | printk("pktcdvd: inserted media is DVD+RW\n"); | ||
1610 | break; | ||
1611 | case 0x13: /* DVD-RW */ | ||
1612 | printk("pktcdvd: inserted media is DVD-RW\n"); | ||
1613 | break; | ||
1614 | case 0x12: /* DVD-RAM */ | ||
1615 | printk("pktcdvd: inserted media is DVD-RAM\n"); | ||
1616 | break; | ||
1617 | default: | ||
1618 | printk("pktcdvd: inserted media is CD-R%s\n", di.erasable ? "W" : ""); | ||
1619 | break; | ||
1620 | } | ||
1621 | pd->type = di.erasable ? PACKET_CDRW : PACKET_CDR; | 1602 | pd->type = di.erasable ? PACKET_CDRW : PACKET_CDR; |
1622 | 1603 | ||
1623 | track = 1; /* (di.last_track_msb << 8) | di.last_track_lsb; */ | 1604 | track = 1; /* (di.last_track_msb << 8) | di.last_track_lsb; */ |
@@ -1626,9 +1607,9 @@ static int pkt_probe_settings(struct pktcdvd_device *pd) | |||
1626 | return ret; | 1607 | return ret; |
1627 | } | 1608 | } |
1628 | 1609 | ||
1629 | if (pkt_good_track(&ti)) { | 1610 | if (!pkt_writable_track(pd, &ti)) { |
1630 | printk("pktcdvd: can't write to this track\n"); | 1611 | printk("pktcdvd: can't write to this track\n"); |
1631 | return -ENXIO; | 1612 | return -EROFS; |
1632 | } | 1613 | } |
1633 | 1614 | ||
1634 | /* | 1615 | /* |
@@ -1642,7 +1623,7 @@ static int pkt_probe_settings(struct pktcdvd_device *pd) | |||
1642 | } | 1623 | } |
1643 | if (pd->settings.size > PACKET_MAX_SECTORS) { | 1624 | if (pd->settings.size > PACKET_MAX_SECTORS) { |
1644 | printk("pktcdvd: packet size is too big\n"); | 1625 | printk("pktcdvd: packet size is too big\n"); |
1645 | return -ENXIO; | 1626 | return -EROFS; |
1646 | } | 1627 | } |
1647 | pd->settings.fp = ti.fp; | 1628 | pd->settings.fp = ti.fp; |
1648 | pd->offset = (be32_to_cpu(ti.track_start) << 2) & (pd->settings.size - 1); | 1629 | pd->offset = (be32_to_cpu(ti.track_start) << 2) & (pd->settings.size - 1); |
@@ -1684,7 +1665,7 @@ static int pkt_probe_settings(struct pktcdvd_device *pd) | |||
1684 | break; | 1665 | break; |
1685 | default: | 1666 | default: |
1686 | printk("pktcdvd: unknown data mode\n"); | 1667 | printk("pktcdvd: unknown data mode\n"); |
1687 | return 1; | 1668 | return -EROFS; |
1688 | } | 1669 | } |
1689 | return 0; | 1670 | return 0; |
1690 | } | 1671 | } |
@@ -1894,8 +1875,8 @@ static int pkt_open_write(struct pktcdvd_device *pd) | |||
1894 | unsigned int write_speed, media_write_speed, read_speed; | 1875 | unsigned int write_speed, media_write_speed, read_speed; |
1895 | 1876 | ||
1896 | if ((ret = pkt_probe_settings(pd))) { | 1877 | if ((ret = pkt_probe_settings(pd))) { |
1897 | DPRINTK("pktcdvd: %s failed probe\n", pd->name); | 1878 | VPRINTK("pktcdvd: %s failed probe\n", pd->name); |
1898 | return -EIO; | 1879 | return ret; |
1899 | } | 1880 | } |
1900 | 1881 | ||
1901 | if ((ret = pkt_set_write_settings(pd))) { | 1882 | if ((ret = pkt_set_write_settings(pd))) { |
@@ -2053,10 +2034,9 @@ static int pkt_open(struct inode *inode, struct file *file) | |||
2053 | goto out_dec; | 2034 | goto out_dec; |
2054 | } | 2035 | } |
2055 | } else { | 2036 | } else { |
2056 | if (pkt_open_dev(pd, file->f_mode & FMODE_WRITE)) { | 2037 | ret = pkt_open_dev(pd, file->f_mode & FMODE_WRITE); |
2057 | ret = -EIO; | 2038 | if (ret) |
2058 | goto out_dec; | 2039 | goto out_dec; |
2059 | } | ||
2060 | /* | 2040 | /* |
2061 | * needed here as well, since ext2 (among others) may change | 2041 | * needed here as well, since ext2 (among others) may change |
2062 | * the blocksize at mount time | 2042 | * the blocksize at mount time |
@@ -2436,11 +2416,12 @@ static int pkt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u | |||
2436 | * The door gets locked when the device is opened, so we | 2416 | * The door gets locked when the device is opened, so we |
2437 | * have to unlock it or else the eject command fails. | 2417 | * have to unlock it or else the eject command fails. |
2438 | */ | 2418 | */ |
2439 | pkt_lock_door(pd, 0); | 2419 | if (pd->refcnt == 1) |
2420 | pkt_lock_door(pd, 0); | ||
2440 | return blkdev_ioctl(pd->bdev->bd_inode, file, cmd, arg); | 2421 | return blkdev_ioctl(pd->bdev->bd_inode, file, cmd, arg); |
2441 | 2422 | ||
2442 | default: | 2423 | default: |
2443 | printk("pktcdvd: Unknown ioctl for %s (%x)\n", pd->name, cmd); | 2424 | VPRINTK("pktcdvd: Unknown ioctl for %s (%x)\n", pd->name, cmd); |
2444 | return -ENOTTY; | 2425 | return -ENOTTY; |
2445 | } | 2426 | } |
2446 | 2427 | ||