summaryrefslogtreecommitdiffstats
path: root/target/device/AMD/DBAu1500/kernel-patches/029-cdrom_blocksize.patch
blob: 90c2961baeff7176ae3069a8fcb76d79b27ffa80 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
--- orig/include/linux/cdrom.h	2005-10-28 10:14:52.000000000 -0600
+++ linux-2.6.14/include/linux/cdrom.h	2005-10-28 10:14:52.000000000 -0600
@@ -946,7 +946,8 @@
     	char name[20];                  /* name of the device type */
 /* per-device flags */
         __u8 sanyo_slot		: 2;	/* Sanyo 3 CD changer support */
-        __u8 reserved		: 6;	/* not used yet */
+	__u8 use_read10		: 1;	/* Use READ10 instead of READCD */
+	__u8 reserved		: 5;	/* not used yet */
 	int cdda_method;		/* see flags */
 	__u8 last_sense;
 	__u8 media_written;		/* dirty flag, DVD+RW bookkeeping */
--- orig/drivers/cdrom/cdrom.c	2005-10-28 10:14:52.000000000 -0600
+++ linux-2.6.14/drivers/cdrom/cdrom.c	2005-10-28 10:14:52.000000000 -0600
@@ -1982,6 +1982,8 @@
 	return 0;
 }
 
+static int cdrom_switch_blocksize(struct cdrom_device_info *cdi, int size);
+
 /*
  * Specific READ_10 interface
  */
@@ -1990,6 +1992,7 @@
 			 int blocksize, int nblocks)
 {
 	struct cdrom_device_ops *cdo = cdi->ops;
+	int ret = 0;
 
 	memset(&cgc->cmd, 0, sizeof(cgc->cmd));
 	cgc->cmd[0] = GPCMD_READ_10;
@@ -2001,7 +2004,22 @@
 	cgc->cmd[7] = (nblocks >>  8) & 0xff;
 	cgc->cmd[8] = nblocks & 0xff;
 	cgc->buflen = blocksize * nblocks;
-	return cdo->generic_packet(cdi, cgc);
+
+	if (blocksize != CD_FRAMESIZE) {
+		ret = cdrom_switch_blocksize(cdi, blocksize);
+		ret |= cdo->generic_packet(cdi, cgc);
+		ret |= cdrom_switch_blocksize(cdi, CD_FRAMESIZE);
+	} else ret = cdo->generic_packet(cdi, cgc);
+
+	/*
+	 * Switch cdrom_read_block back to default behaviour
+	 * if we get an error.
+	 * FIXME: Maybe this should not be done on all errors.
+	 */
+	if (ret != 0)
+		cdi->use_read10 = 0;
+
+	return ret;
 }
 
 /* very generic interface for reading the various types of blocks */
@@ -2010,8 +2028,15 @@
 			    int lba, int nblocks, int format, int blksize)
 {
 	struct cdrom_device_ops *cdo = cdi->ops;
+	int ret;
+
+	if (cdi->use_read10)
+		return cdrom_read_cd(cdi, cgc, lba, blksize, nblocks);
 
 	memset(&cgc->cmd, 0, sizeof(cgc->cmd));
+	/*
+	 * SCSI-II devices are not required to support READ_CD.
+	 */
 	cgc->cmd[0] = GPCMD_READ_CD;
 	/* expected sector size - cdda,mode1,etc. */
 	cgc->cmd[1] = format << 2;
@@ -2034,7 +2059,15 @@
 	default			: cgc->cmd[9] = 0x10;
 	}
 	
-	return cdo->generic_packet(cdi, cgc);
+	ret = cdo->generic_packet(cdi, cgc);
+	if (ret && cgc->sense && cgc->sense->sense_key==0x05 && cgc->sense->asc==0x20 && cgc->sense->ascq==0x00) {
+		ret = cdrom_read_cd(cdi, cgc, lba, blksize, nblocks);
+		if (ret == 0) {
+			cdi->use_read10 = 1;
+			printk(KERN_INFO "cdrom.c: drive does not like READ_CD for blksize=%d, switching to READ_10.\n", blksize);
+		}
+	}
+	return ret;
 }
 
 static int cdrom_read_cdda_old(struct cdrom_device_info *cdi, __u8 __user *ubuf,
@@ -2671,20 +2704,6 @@
 		cgc.sense = &sense;
 		cgc.data_direction = CGC_DATA_READ;
 		ret = cdrom_read_block(cdi, &cgc, lba, 1, format, blocksize);
-		if (ret && sense.sense_key==0x05 && sense.asc==0x20 && sense.ascq==0x00) {
-			/*
-			 * SCSI-II devices are not required to support
-			 * READ_CD, so let's try switching block size
-			 */
-			/* FIXME: switch back again... */
-			if ((ret = cdrom_switch_blocksize(cdi, blocksize))) {
-				kfree(cgc.buffer);
-				return ret;
-			}
-			cgc.sense = NULL;
-			ret = cdrom_read_cd(cdi, &cgc, lba, blocksize, 1);
-			ret |= cdrom_switch_blocksize(cdi, blocksize);
-		}
 		if (!ret && copy_to_user((char __user *)arg, cgc.buffer, blocksize))
 			ret = -EFAULT;
 		kfree(cgc.buffer);