diff options
author | Jens Axboe <jens.axboe@oracle.com> | 2007-06-21 02:29:34 -0400 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2007-07-10 02:03:34 -0400 |
commit | f3f541f9ded9dd37edca103dd3be49bfbd9e730d (patch) | |
tree | b9b34955c9db6a10ad329731eaf66fe9c53cbf84 | |
parent | e654bc4393e85e326993256d80b9710a4d6411ff (diff) |
Remove legacy CDROM drivers
They are all broken beyond repair. Given that nobody has complained
about them (most haven't worked in 2.6 AT ALL), remove them from the
tree.
A new mitsumi driver that actually works is in progress, it'll get
added when completed.
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
-rw-r--r-- | drivers/Kconfig | 2 | ||||
-rw-r--r-- | drivers/cdrom/Kconfig | 213 | ||||
-rw-r--r-- | drivers/cdrom/Makefile | 10 | ||||
-rw-r--r-- | drivers/cdrom/aztcd.c | 2492 | ||||
-rw-r--r-- | drivers/cdrom/aztcd.h | 162 | ||||
-rw-r--r-- | drivers/cdrom/cdu31a.c | 3251 | ||||
-rw-r--r-- | drivers/cdrom/cdu31a.h | 411 | ||||
-rw-r--r-- | drivers/cdrom/cm206.c | 1594 | ||||
-rw-r--r-- | drivers/cdrom/cm206.h | 171 | ||||
-rw-r--r-- | drivers/cdrom/gscd.c | 1029 | ||||
-rw-r--r-- | drivers/cdrom/gscd.h | 108 | ||||
-rw-r--r-- | drivers/cdrom/isp16.c | 374 | ||||
-rw-r--r-- | drivers/cdrom/isp16.h | 72 | ||||
-rw-r--r-- | drivers/cdrom/mcdx.c | 1943 | ||||
-rw-r--r-- | drivers/cdrom/mcdx.h | 185 | ||||
-rw-r--r-- | drivers/cdrom/optcd.c | 2105 | ||||
-rw-r--r-- | drivers/cdrom/optcd.h | 52 | ||||
-rw-r--r-- | drivers/cdrom/sbpcd.c | 5966 | ||||
-rw-r--r-- | drivers/cdrom/sbpcd.h | 839 | ||||
-rw-r--r-- | drivers/cdrom/sjcd.c | 1815 | ||||
-rw-r--r-- | drivers/cdrom/sjcd.h | 181 | ||||
-rw-r--r-- | drivers/cdrom/sonycd535.c | 1689 | ||||
-rw-r--r-- | drivers/cdrom/sonycd535.h | 183 |
23 files changed, 0 insertions, 24847 deletions
diff --git a/drivers/Kconfig b/drivers/Kconfig index 050323fd79e9..4e6487d461f3 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig | |||
@@ -24,8 +24,6 @@ source "drivers/scsi/Kconfig" | |||
24 | 24 | ||
25 | source "drivers/ata/Kconfig" | 25 | source "drivers/ata/Kconfig" |
26 | 26 | ||
27 | source "drivers/cdrom/Kconfig" | ||
28 | |||
29 | source "drivers/md/Kconfig" | 27 | source "drivers/md/Kconfig" |
30 | 28 | ||
31 | source "drivers/message/fusion/Kconfig" | 29 | source "drivers/message/fusion/Kconfig" |
diff --git a/drivers/cdrom/Kconfig b/drivers/cdrom/Kconfig deleted file mode 100644 index 4b12e9031fb3..000000000000 --- a/drivers/cdrom/Kconfig +++ /dev/null | |||
@@ -1,213 +0,0 @@ | |||
1 | # | ||
2 | # CDROM driver configuration | ||
3 | # | ||
4 | |||
5 | menu "Old CD-ROM drivers (not SCSI, not IDE)" | ||
6 | depends on ISA && BLOCK | ||
7 | |||
8 | config CD_NO_IDESCSI | ||
9 | bool "Support non-SCSI/IDE/ATAPI CDROM drives" | ||
10 | ---help--- | ||
11 | If you have a CD-ROM drive that is neither SCSI nor IDE/ATAPI, say Y | ||
12 | here, otherwise N. Read the CD-ROM-HOWTO, available from | ||
13 | <http://www.tldp.org/docs.html#howto>. | ||
14 | |||
15 | Note that the answer to this question doesn't directly affect the | ||
16 | kernel: saying N will just cause the configurator to skip all | ||
17 | the questions about these CD-ROM drives. If you are unsure what you | ||
18 | have, say Y and find out whether you have one of the following | ||
19 | drives. | ||
20 | |||
21 | For each of these drivers, a <file:Documentation/cdrom/{driver_name}> | ||
22 | exists. Especially in cases where you do not know exactly which kind | ||
23 | of drive you have you should read there. Most of these drivers use a | ||
24 | file drivers/cdrom/{driver_name}.h where you can define your | ||
25 | interface parameters and switch some internal goodies. | ||
26 | |||
27 | To compile these CD-ROM drivers as a module, choose M instead of Y. | ||
28 | |||
29 | If you want to use any of these CD-ROM drivers, you also have to | ||
30 | answer Y or M to "ISO 9660 CD-ROM file system support" below (this | ||
31 | answer will get "defaulted" for you if you enable any of the Linux | ||
32 | CD-ROM drivers). | ||
33 | |||
34 | config AZTCD | ||
35 | tristate "Aztech/Orchid/Okano/Wearnes/TXC/CyDROM CDROM support" | ||
36 | depends on CD_NO_IDESCSI | ||
37 | ---help--- | ||
38 | This is your driver if you have an Aztech CDA268-01A, Orchid | ||
39 | CD-3110, Okano or Wearnes CDD110, Conrad TXC, or CyCD-ROM CR520 or | ||
40 | CR540 CD-ROM drive. This driver -- just like all these CD-ROM | ||
41 | drivers -- is NOT for CD-ROM drives with IDE/ATAPI interfaces, such | ||
42 | as Aztech CDA269-031SE. Please read the file | ||
43 | <file:Documentation/cdrom/aztcd>. | ||
44 | |||
45 | If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM | ||
46 | file system support" below, because that's the file system used on | ||
47 | CD-ROMs. | ||
48 | |||
49 | To compile this driver as a module, choose M here: the | ||
50 | module will be called aztcd. | ||
51 | |||
52 | config GSCD | ||
53 | tristate "Goldstar R420 CDROM support" | ||
54 | depends on CD_NO_IDESCSI | ||
55 | ---help--- | ||
56 | If this is your CD-ROM drive, say Y here. As described in the file | ||
57 | <file:Documentation/cdrom/gscd>, you might have to change a setting | ||
58 | in the file <file:drivers/cdrom/gscd.h> before compiling the | ||
59 | kernel. Please read the file <file:Documentation/cdrom/gscd>. | ||
60 | |||
61 | If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM | ||
62 | file system support" below, because that's the file system used on | ||
63 | CD-ROMs. | ||
64 | |||
65 | To compile this driver as a module, choose M here: the | ||
66 | module will be called gscd. | ||
67 | |||
68 | config SBPCD | ||
69 | tristate "Matsushita/Panasonic/Creative, Longshine, TEAC CDROM support" | ||
70 | depends on CD_NO_IDESCSI && BROKEN_ON_SMP | ||
71 | ---help--- | ||
72 | This driver supports most of the drives which use the Panasonic or | ||
73 | Sound Blaster interface. Please read the file | ||
74 | <file:Documentation/cdrom/sbpcd>. | ||
75 | |||
76 | The Matsushita CR-521, CR-522, CR-523, CR-562, CR-563 drives | ||
77 | (sometimes labeled "Creative"), the Creative Labs CD200, the | ||
78 | Longshine LCS-7260, the "IBM External ISA CD-ROM" (in fact a CR-56x | ||
79 | model), the TEAC CD-55A fall under this category. Some other | ||
80 | "electrically compatible" drives (Vertos, Genoa, some Funai models) | ||
81 | are currently not supported; for the Sanyo H94A drive currently a | ||
82 | separate driver (asked later) is responsible. Most drives have a | ||
83 | uniquely shaped faceplate, with a caddyless motorized drawer, but | ||
84 | without external brand markings. The older CR-52x drives have a | ||
85 | caddy and manual loading/eject, but still no external markings. The | ||
86 | driver is able to do an extended auto-probing for interface | ||
87 | addresses and drive types; this can help to find facts in cases you | ||
88 | are not sure, but can consume some time during the boot process if | ||
89 | none of the supported drives gets found. Once your drive got found, | ||
90 | you should enter the reported parameters into | ||
91 | <file:drivers/cdrom/sbpcd.h> and set "DISTRIBUTION 0" there. | ||
92 | |||
93 | This driver can support up to four CD-ROM controller cards, and each | ||
94 | card can support up to four CD-ROM drives; if you say Y here, you | ||
95 | will be asked how many controller cards you have. If compiled as a | ||
96 | module, only one controller card (but with up to four drives) is | ||
97 | usable. | ||
98 | |||
99 | If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM | ||
100 | file system support" below, because that's the file system used on | ||
101 | CD-ROMs. | ||
102 | |||
103 | To compile this driver as a module, choose M here: the | ||
104 | module will be called sbpcd. | ||
105 | |||
106 | config MCDX | ||
107 | tristate "Mitsumi CDROM support" | ||
108 | depends on CD_NO_IDESCSI | ||
109 | ---help--- | ||
110 | Use this driver if you want to be able to use your Mitsumi LU-005, | ||
111 | FX-001 or FX-001D CD-ROM drive. | ||
112 | |||
113 | Please read the file <file:Documentation/cdrom/mcdx>. | ||
114 | |||
115 | If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM | ||
116 | file system support" below, because that's the file system used on | ||
117 | CD-ROMs. | ||
118 | |||
119 | To compile this driver as a module, choose M here: the | ||
120 | module will be called mcdx. | ||
121 | |||
122 | config OPTCD | ||
123 | tristate "Optics Storage DOLPHIN 8000AT CDROM support" | ||
124 | depends on CD_NO_IDESCSI | ||
125 | ---help--- | ||
126 | This is the driver for the 'DOLPHIN' drive with a 34-pin Sony | ||
127 | compatible interface. It also works with the Lasermate CR328A. If | ||
128 | you have one of those, say Y. This driver does not work for the | ||
129 | Optics Storage 8001 drive; use the IDE-ATAPI CD-ROM driver for that | ||
130 | one. Please read the file <file:Documentation/cdrom/optcd>. | ||
131 | |||
132 | If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM | ||
133 | file system support" below, because that's the file system used on | ||
134 | CD-ROMs. | ||
135 | |||
136 | To compile this driver as a module, choose M here: the | ||
137 | module will be called optcd. | ||
138 | |||
139 | config CM206 | ||
140 | tristate "Philips/LMS CM206 CDROM support" | ||
141 | depends on CD_NO_IDESCSI && BROKEN_ON_SMP | ||
142 | ---help--- | ||
143 | If you have a Philips/LMS CD-ROM drive cm206 in combination with a | ||
144 | cm260 host adapter card, say Y here. Please also read the file | ||
145 | <file:Documentation/cdrom/cm206>. | ||
146 | |||
147 | If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM | ||
148 | file system support" below, because that's the file system used on | ||
149 | CD-ROMs. | ||
150 | |||
151 | To compile this driver as a module, choose M here: the | ||
152 | module will be called cm206. | ||
153 | |||
154 | config SJCD | ||
155 | tristate "Sanyo CDR-H94A CDROM support" | ||
156 | depends on CD_NO_IDESCSI | ||
157 | help | ||
158 | If this is your CD-ROM drive, say Y here and read the file | ||
159 | <file:Documentation/cdrom/sjcd>. You should then also say Y or M to | ||
160 | "ISO 9660 CD-ROM file system support" below, because that's the | ||
161 | file system used on CD-ROMs. | ||
162 | |||
163 | To compile this driver as a module, choose M here: the | ||
164 | module will be called sjcd. | ||
165 | |||
166 | config ISP16_CDI | ||
167 | tristate "ISP16/MAD16/Mozart soft configurable cdrom interface support" | ||
168 | depends on CD_NO_IDESCSI | ||
169 | ---help--- | ||
170 | These are sound cards with built-in cdrom interfaces using the OPTi | ||
171 | 82C928 or 82C929 chips. Say Y here to have them detected and | ||
172 | possibly configured at boot time. In addition, You'll have to say Y | ||
173 | to a driver for the particular cdrom drive you have attached to the | ||
174 | card. Read <file:Documentation/cdrom/isp16> for details. | ||
175 | |||
176 | To compile this driver as a module, choose M here: the | ||
177 | module will be called isp16. | ||
178 | |||
179 | config CDU31A | ||
180 | tristate "Sony CDU31A/CDU33A CDROM support" | ||
181 | depends on CD_NO_IDESCSI && BROKEN_ON_SMP | ||
182 | ---help--- | ||
183 | These CD-ROM drives have a spring-pop-out caddyless drawer, and a | ||
184 | rectangular green LED centered beneath it. NOTE: these CD-ROM | ||
185 | drives will not be auto detected by the kernel at boot time; you | ||
186 | have to provide the interface address as an option to the kernel at | ||
187 | boot time as described in <file:Documentation/cdrom/cdu31a> or fill | ||
188 | in your parameters into <file:drivers/cdrom/cdu31a.c>. Try "man | ||
189 | bootparam" or see the documentation of your boot loader (lilo or | ||
190 | loadlin) about how to pass options to the kernel. | ||
191 | |||
192 | If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM | ||
193 | file system support" below, because that's the file system used on | ||
194 | CD-ROMs. | ||
195 | |||
196 | To compile this driver as a module, choose M here: the | ||
197 | module will be called cdu31a. | ||
198 | |||
199 | config CDU535 | ||
200 | tristate "Sony CDU535 CDROM support" | ||
201 | depends on CD_NO_IDESCSI | ||
202 | ---help--- | ||
203 | This is the driver for the older Sony CDU-535 and CDU-531 CD-ROM | ||
204 | drives. Please read the file <file:Documentation/cdrom/sonycd535>. | ||
205 | |||
206 | If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM | ||
207 | file system support" below, because that's the file system used on | ||
208 | CD-ROMs. | ||
209 | |||
210 | To compile this driver as a module, choose M here: the | ||
211 | module will be called sonycd535. | ||
212 | |||
213 | endmenu | ||
diff --git a/drivers/cdrom/Makefile b/drivers/cdrom/Makefile index d1d1e5a4be73..774c180a4e11 100644 --- a/drivers/cdrom/Makefile +++ b/drivers/cdrom/Makefile | |||
@@ -10,14 +10,4 @@ obj-$(CONFIG_BLK_DEV_SR) += cdrom.o | |||
10 | obj-$(CONFIG_PARIDE_PCD) += cdrom.o | 10 | obj-$(CONFIG_PARIDE_PCD) += cdrom.o |
11 | obj-$(CONFIG_CDROM_PKTCDVD) += cdrom.o | 11 | obj-$(CONFIG_CDROM_PKTCDVD) += cdrom.o |
12 | 12 | ||
13 | obj-$(CONFIG_AZTCD) += aztcd.o | ||
14 | obj-$(CONFIG_CDU31A) += cdu31a.o cdrom.o | ||
15 | obj-$(CONFIG_CM206) += cm206.o cdrom.o | ||
16 | obj-$(CONFIG_GSCD) += gscd.o | ||
17 | obj-$(CONFIG_ISP16_CDI) += isp16.o | ||
18 | obj-$(CONFIG_MCDX) += mcdx.o cdrom.o | ||
19 | obj-$(CONFIG_OPTCD) += optcd.o | ||
20 | obj-$(CONFIG_SBPCD) += sbpcd.o cdrom.o | ||
21 | obj-$(CONFIG_SJCD) += sjcd.o | ||
22 | obj-$(CONFIG_CDU535) += sonycd535.o | ||
23 | obj-$(CONFIG_VIOCD) += viocd.o cdrom.o | 13 | obj-$(CONFIG_VIOCD) += viocd.o cdrom.o |
diff --git a/drivers/cdrom/aztcd.c b/drivers/cdrom/aztcd.c deleted file mode 100644 index d7fbfaae2449..000000000000 --- a/drivers/cdrom/aztcd.c +++ /dev/null | |||
@@ -1,2492 +0,0 @@ | |||
1 | #define AZT_VERSION "2.60" | ||
2 | |||
3 | /* $Id: aztcd.c,v 2.60 1997/11/29 09:51:19 root Exp root $ | ||
4 | linux/drivers/block/aztcd.c - Aztech CD268 CDROM driver | ||
5 | |||
6 | Copyright (C) 1994-98 Werner Zimmermann(Werner.Zimmermann@fht-esslingen.de) | ||
7 | |||
8 | based on Mitsumi CDROM driver by Martin Hariss and preworks by | ||
9 | Eberhard Moenkeberg; contains contributions by Joe Nardone and Robby | ||
10 | Schirmer. | ||
11 | |||
12 | This program is free software; you can redistribute it and/or modify | ||
13 | it under the terms of the GNU General Public License as published by | ||
14 | the Free Software Foundation; either version 2, or (at your option) | ||
15 | any later version. | ||
16 | |||
17 | This program is distributed in the hope that it will be useful, | ||
18 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | GNU General Public License for more details. | ||
21 | |||
22 | You should have received a copy of the GNU General Public License | ||
23 | along with this program; if not, write to the Free Software | ||
24 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | |||
26 | HISTORY | ||
27 | V0.0 Adaption to Aztech CD268-01A Version 1.3 | ||
28 | Version is PRE_ALPHA, unresolved points: | ||
29 | 1. I use busy wait instead of timer wait in STEN_LOW,DTEN_LOW | ||
30 | thus driver causes CPU overhead and is very slow | ||
31 | 2. could not find a way to stop the drive, when it is | ||
32 | in data read mode, therefore I had to set | ||
33 | msf.end.min/sec/frame to 0:0:1 (in azt_poll); so only one | ||
34 | frame can be read in sequence, this is also the reason for | ||
35 | 3. getting 'timeout in state 4' messages, but nevertheless | ||
36 | it works | ||
37 | W.Zimmermann, Oct. 31, 1994 | ||
38 | V0.1 Version is ALPHA, problems #2 and #3 resolved. | ||
39 | W.Zimmermann, Nov. 3, 1994 | ||
40 | V0.2 Modification to some comments, debugging aids for partial test | ||
41 | with Borland C under DOS eliminated. Timer interrupt wait | ||
42 | STEN_LOW_WAIT additionally to busy wait for STEN_LOW implemented; | ||
43 | use it only for the 'slow' commands (ACMD_GET_Q_CHANNEL, ACMD_ | ||
44 | SEEK_TO_LEAD_IN), all other commands are so 'fast', that busy | ||
45 | waiting seems better to me than interrupt rescheduling. | ||
46 | Besides that, when used in the wrong place, STEN_LOW_WAIT causes | ||
47 | kernel panic. | ||
48 | In function aztPlay command ACMD_PLAY_AUDIO added, should make | ||
49 | audio functions work. The Aztech drive needs different commands | ||
50 | to read data tracks and play audio tracks. | ||
51 | W.Zimmermann, Nov. 8, 1994 | ||
52 | V0.3 Recognition of missing drive during boot up improved (speeded up). | ||
53 | W.Zimmermann, Nov. 13, 1994 | ||
54 | V0.35 Rewrote the control mechanism in azt_poll (formerly mcd_poll) | ||
55 | including removal of all 'goto' commands. :-); | ||
56 | J. Nardone, Nov. 14, 1994 | ||
57 | V0.4 Renamed variables and constants to 'azt' instead of 'mcd'; had | ||
58 | to make some "compatibility" defines in azt.h; please note, | ||
59 | that the source file was renamed to azt.c, the include file to | ||
60 | azt.h | ||
61 | Speeded up drive recognition during init (will be a little bit | ||
62 | slower than before if no drive is installed!); suggested by | ||
63 | Robby Schirmer. | ||
64 | read_count declared volatile and set to AZT_BUF_SIZ to make | ||
65 | drive faster (now 300kB/sec, was 60kB/sec before, measured | ||
66 | by 'time dd if=/dev/cdrom of=/dev/null bs=2048 count=4096'; | ||
67 | different AZT_BUF_SIZes were test, above 16 no further im- | ||
68 | provement seems to be possible; suggested by E.Moenkeberg. | ||
69 | W.Zimmermann, Nov. 18, 1994 | ||
70 | V0.42 Included getAztStatus command in GetQChannelInfo() to allow | ||
71 | reading Q-channel info on audio disks, if drive is stopped, | ||
72 | and some other bug fixes in the audio stuff, suggested by | ||
73 | Robby Schirmer. | ||
74 | Added more ioctls (reading data in mode 1 and mode 2). | ||
75 | Completely removed the old azt_poll() routine. | ||
76 | Detection of ORCHID CDS-3110 in aztcd_init implemented. | ||
77 | Additional debugging aids (see the readme file). | ||
78 | W.Zimmermann, Dec. 9, 1994 | ||
79 | V0.50 Autodetection of drives implemented. | ||
80 | W.Zimmermann, Dec. 12, 1994 | ||
81 | V0.52 Prepared for including in the standard kernel, renamed most | ||
82 | variables to contain 'azt', included autoconf.h | ||
83 | W.Zimmermann, Dec. 16, 1994 | ||
84 | V0.6 Version for being included in the standard Linux kernel. | ||
85 | Renamed source and header file to aztcd.c and aztcd.h | ||
86 | W.Zimmermann, Dec. 24, 1994 | ||
87 | V0.7 Changed VERIFY_READ to VERIFY_WRITE in aztcd_ioctl, case | ||
88 | CDROMREADMODE1 and CDROMREADMODE2; bug fix in the ioctl, | ||
89 | which causes kernel crashes when playing audio, changed | ||
90 | include-files (config.h instead of autoconf.h, removed | ||
91 | delay.h) | ||
92 | W.Zimmermann, Jan. 8, 1995 | ||
93 | V0.72 Some more modifications for adaption to the standard kernel. | ||
94 | W.Zimmermann, Jan. 16, 1995 | ||
95 | V0.80 aztcd is now part of the standard kernel since version 1.1.83. | ||
96 | Modified the SET_TIMER and CLEAR_TIMER macros to comply with | ||
97 | the new timer scheme. | ||
98 | W.Zimmermann, Jan. 21, 1995 | ||
99 | V0.90 Included CDROMVOLCTRL, but with my Aztech drive I can only turn | ||
100 | the channels on and off. If it works better with your drive, | ||
101 | please mail me. Also implemented ACMD_CLOSE for CDROMSTART. | ||
102 | W.Zimmermann, Jan. 24, 1995 | ||
103 | V1.00 Implemented close and lock tray commands. Patches supplied by | ||
104 | Frank Racis | ||
105 | Added support for loadable MODULEs, so aztcd can now also be | ||
106 | loaded by insmod and removed by rmmod during run time | ||
107 | Werner Zimmermann, Mar. 24, 95 | ||
108 | V1.10 Implemented soundcard configuration for Orchid CDS-3110 drives | ||
109 | connected to Soundwave32 cards. Release for LST 2.1. | ||
110 | (still experimental) | ||
111 | Werner Zimmermann, May 8, 95 | ||
112 | V1.20 Implemented limited support for DOSEMU0.60's cdrom.c. Now it works, but | ||
113 | sometimes DOSEMU may hang for 30 seconds or so. A fully functional ver- | ||
114 | sion needs an update of Dosemu0.60's cdrom.c, which will come with the | ||
115 | next revision of Dosemu. | ||
116 | Also Soundwave32 support now works. | ||
117 | Werner Zimmermann, May 22, 95 | ||
118 | V1.30 Auto-eject feature. Inspired by Franc Racis (racis@psu.edu) | ||
119 | Werner Zimmermann, July 4, 95 | ||
120 | V1.40 Started multisession support. Implementation copied from mcdx.c | ||
121 | by Heiko Schlittermann. Not tested yet. | ||
122 | Werner Zimmermann, July 15, 95 | ||
123 | V1.50 Implementation of ioctl CDROMRESET, continued multisession, began | ||
124 | XA, but still untested. Heavy modifications to drive status de- | ||
125 | tection. | ||
126 | Werner Zimmermann, July 25, 95 | ||
127 | V1.60 XA support now should work. Speeded up drive recognition in cases, | ||
128 | where no drive is installed. | ||
129 | Werner Zimmermann, August 8, 1995 | ||
130 | V1.70 Multisession support now is completed, but there is still not | ||
131 | enough testing done. If you can test it, please contact me. For | ||
132 | details please read Documentation/cdrom/aztcd | ||
133 | Werner Zimmermann, August 19, 1995 | ||
134 | V1.80 Modification to suit the new kernel boot procedure introduced | ||
135 | with kernel 1.3.33. Will definitely not work with older kernels. | ||
136 | Programming done by Linus himself. | ||
137 | Werner Zimmermann, October 11, 1995 | ||
138 | V1.90 Support for Conrad TXC drives, thank's to Jochen Kunz and Olaf Kaluza. | ||
139 | Werner Zimmermann, October 21, 1995 | ||
140 | V2.00 Changed #include "blk.h" to <linux/blk.h> as the directory | ||
141 | structure was changed. README.aztcd is now /usr/src/docu- | ||
142 | mentation/cdrom/aztcd | ||
143 | Werner Zimmermann, November 10, 95 | ||
144 | V2.10 Started to modify azt_poll to prevent reading beyond end of | ||
145 | tracks. | ||
146 | Werner Zimmermann, December 3, 95 | ||
147 | V2.20 Changed some comments | ||
148 | Werner Zimmermann, April 1, 96 | ||
149 | V2.30 Implemented support for CyCDROM CR520, CR940, Code for CR520 | ||
150 | delivered by H.Berger with preworks by E.Moenkeberg. | ||
151 | Werner Zimmermann, April 29, 96 | ||
152 | V2.40 Reorganized the placement of functions in the source code file | ||
153 | to reflect the layered approach; did not actually change code | ||
154 | Werner Zimmermann, May 1, 96 | ||
155 | V2.50 Heiko Eissfeldt suggested to remove some VERIFY_READs in | ||
156 | aztcd_ioctl; check_aztcd_media_change modified | ||
157 | Werner Zimmermann, May 16, 96 | ||
158 | V2.60 Implemented Auto-Probing; made changes for kernel's 2.1.xx blocksize | ||
159 | Adaption to linux kernel > 2.1.0 | ||
160 | Werner Zimmermann, Nov 29, 97 | ||
161 | |||
162 | November 1999 -- Make kernel-parameter implementation work with 2.3.x | ||
163 | Removed init_module & cleanup_module in favor of | ||
164 | module_init & module_exit. | ||
165 | Torben Mathiasen <tmm@image.dk> | ||
166 | */ | ||
167 | |||
168 | #include <linux/blkdev.h> | ||
169 | #include "aztcd.h" | ||
170 | |||
171 | #include <linux/module.h> | ||
172 | #include <linux/errno.h> | ||
173 | #include <linux/mm.h> | ||
174 | #include <linux/timer.h> | ||
175 | #include <linux/fs.h> | ||
176 | #include <linux/kernel.h> | ||
177 | #include <linux/cdrom.h> | ||
178 | #include <linux/ioport.h> | ||
179 | #include <linux/string.h> | ||
180 | #include <linux/major.h> | ||
181 | |||
182 | #include <linux/init.h> | ||
183 | |||
184 | #include <asm/system.h> | ||
185 | #include <asm/io.h> | ||
186 | |||
187 | #include <asm/uaccess.h> | ||
188 | |||
189 | /*########################################################################### | ||
190 | Defines | ||
191 | ########################################################################### | ||
192 | */ | ||
193 | |||
194 | #define MAJOR_NR AZTECH_CDROM_MAJOR | ||
195 | #define QUEUE (azt_queue) | ||
196 | #define CURRENT elv_next_request(azt_queue) | ||
197 | #define SET_TIMER(func, jifs) delay_timer.expires = jiffies + (jifs); \ | ||
198 | delay_timer.function = (void *) (func); \ | ||
199 | add_timer(&delay_timer); | ||
200 | |||
201 | #define CLEAR_TIMER del_timer(&delay_timer); | ||
202 | |||
203 | #define RETURNM(message,value) {printk("aztcd: Warning: %s failed\n",message);\ | ||
204 | return value;} | ||
205 | #define RETURN(message) {printk("aztcd: Warning: %s failed\n",message);\ | ||
206 | return;} | ||
207 | |||
208 | /* Macros to switch the IDE-interface to the slave device and back to the master*/ | ||
209 | #define SWITCH_IDE_SLAVE outb_p(0xa0,azt_port+6); \ | ||
210 | outb_p(0x10,azt_port+6); \ | ||
211 | outb_p(0x00,azt_port+7); \ | ||
212 | outb_p(0x10,azt_port+6); | ||
213 | #define SWITCH_IDE_MASTER outb_p(0xa0,azt_port+6); | ||
214 | |||
215 | |||
216 | #if 0 | ||
217 | #define AZT_TEST | ||
218 | #define AZT_TEST1 /* <int-..> */ | ||
219 | #define AZT_TEST2 /* do_aztcd_request */ | ||
220 | #define AZT_TEST3 /* AZT_S_state */ | ||
221 | #define AZT_TEST4 /* QUICK_LOOP-counter */ | ||
222 | #define AZT_TEST5 /* port(1) state */ | ||
223 | #define AZT_DEBUG | ||
224 | #define AZT_DEBUG_MULTISESSION | ||
225 | #endif | ||
226 | |||
227 | static struct request_queue *azt_queue; | ||
228 | |||
229 | static int current_valid(void) | ||
230 | { | ||
231 | return CURRENT && | ||
232 | rq_data_dir(CURRENT) == READ && | ||
233 | CURRENT->sector != -1; | ||
234 | } | ||
235 | |||
236 | #define AFL_STATUSorDATA (AFL_STATUS | AFL_DATA) | ||
237 | #define AZT_BUF_SIZ 16 | ||
238 | |||
239 | #define READ_TIMEOUT 3000 | ||
240 | |||
241 | #define azt_port aztcd /*needed for the modutils */ | ||
242 | |||
243 | /*########################################################################## | ||
244 | Type Definitions | ||
245 | ########################################################################## | ||
246 | */ | ||
247 | enum azt_state_e { AZT_S_IDLE, /* 0 */ | ||
248 | AZT_S_START, /* 1 */ | ||
249 | AZT_S_MODE, /* 2 */ | ||
250 | AZT_S_READ, /* 3 */ | ||
251 | AZT_S_DATA, /* 4 */ | ||
252 | AZT_S_STOP, /* 5 */ | ||
253 | AZT_S_STOPPING /* 6 */ | ||
254 | }; | ||
255 | enum azt_read_modes { AZT_MODE_0, /*read mode for audio disks, not supported by Aztech firmware */ | ||
256 | AZT_MODE_1, /*read mode for normal CD-ROMs */ | ||
257 | AZT_MODE_2 /*read mode for XA CD-ROMs */ | ||
258 | }; | ||
259 | |||
260 | /*########################################################################## | ||
261 | Global Variables | ||
262 | ########################################################################## | ||
263 | */ | ||
264 | static int aztPresent = 0; | ||
265 | |||
266 | static volatile int azt_transfer_is_active = 0; | ||
267 | |||
268 | static char azt_buf[CD_FRAMESIZE_RAW * AZT_BUF_SIZ]; /*buffer for block size conversion */ | ||
269 | #if AZT_PRIVATE_IOCTLS | ||
270 | static char buf[CD_FRAMESIZE_RAW]; /*separate buffer for the ioctls */ | ||
271 | #endif | ||
272 | |||
273 | static volatile int azt_buf_bn[AZT_BUF_SIZ], azt_next_bn; | ||
274 | static volatile int azt_buf_in, azt_buf_out = -1; | ||
275 | static volatile int azt_error = 0; | ||
276 | static int azt_open_count = 0; | ||
277 | static volatile enum azt_state_e azt_state = AZT_S_IDLE; | ||
278 | #ifdef AZT_TEST3 | ||
279 | static volatile enum azt_state_e azt_state_old = AZT_S_STOP; | ||
280 | static volatile int azt_st_old = 0; | ||
281 | #endif | ||
282 | static volatile enum azt_read_modes azt_read_mode = AZT_MODE_1; | ||
283 | |||
284 | static int azt_mode = -1; | ||
285 | static volatile int azt_read_count = 1; | ||
286 | |||
287 | static int azt_port = AZT_BASE_ADDR; | ||
288 | |||
289 | module_param(azt_port, int, 0); | ||
290 | |||
291 | static int azt_port_auto[16] = AZT_BASE_AUTO; | ||
292 | |||
293 | static char azt_cont = 0; | ||
294 | static char azt_init_end = 0; | ||
295 | static char azt_auto_eject = AZT_AUTO_EJECT; | ||
296 | |||
297 | static int AztTimeout, AztTries; | ||
298 | static DECLARE_WAIT_QUEUE_HEAD(azt_waitq); | ||
299 | static DEFINE_TIMER(delay_timer, NULL, 0, 0); | ||
300 | |||
301 | static struct azt_DiskInfo DiskInfo; | ||
302 | static struct azt_Toc Toc[MAX_TRACKS]; | ||
303 | static struct azt_Play_msf azt_Play; | ||
304 | |||
305 | static int aztAudioStatus = CDROM_AUDIO_NO_STATUS; | ||
306 | static char aztDiskChanged = 1; | ||
307 | static char aztTocUpToDate = 0; | ||
308 | |||
309 | static unsigned char aztIndatum; | ||
310 | static unsigned long aztTimeOutCount; | ||
311 | static int aztCmd = 0; | ||
312 | |||
313 | static DEFINE_SPINLOCK(aztSpin); | ||
314 | |||
315 | /*########################################################################### | ||
316 | Function Prototypes | ||
317 | ########################################################################### | ||
318 | */ | ||
319 | /* CDROM Drive Low Level I/O Functions */ | ||
320 | static void aztStatTimer(void); | ||
321 | |||
322 | /* CDROM Drive Command Functions */ | ||
323 | static int aztGetDiskInfo(void); | ||
324 | #if AZT_MULTISESSION | ||
325 | static int aztGetMultiDiskInfo(void); | ||
326 | #endif | ||
327 | static int aztGetToc(int multi); | ||
328 | |||
329 | /* Kernel Interface Functions */ | ||
330 | static int check_aztcd_media_change(struct gendisk *disk); | ||
331 | static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, | ||
332 | unsigned long arg); | ||
333 | static int aztcd_open(struct inode *ip, struct file *fp); | ||
334 | static int aztcd_release(struct inode *inode, struct file *file); | ||
335 | |||
336 | static struct block_device_operations azt_fops = { | ||
337 | .owner = THIS_MODULE, | ||
338 | .open = aztcd_open, | ||
339 | .release = aztcd_release, | ||
340 | .ioctl = aztcd_ioctl, | ||
341 | .media_changed = check_aztcd_media_change, | ||
342 | }; | ||
343 | |||
344 | /* Aztcd State Machine: Controls Drive Operating State */ | ||
345 | static void azt_poll(void); | ||
346 | |||
347 | /* Miscellaneous support functions */ | ||
348 | static void azt_hsg2msf(long hsg, struct msf *msf); | ||
349 | static long azt_msf2hsg(struct msf *mp); | ||
350 | static void azt_bin2bcd(unsigned char *p); | ||
351 | static int azt_bcd2bin(unsigned char bcd); | ||
352 | |||
353 | /*########################################################################## | ||
354 | CDROM Drive Low Level I/O Functions | ||
355 | ########################################################################## | ||
356 | */ | ||
357 | /* Macros for the drive hardware interface handshake, these macros use | ||
358 | busy waiting */ | ||
359 | /* Wait for OP_OK = drive answers with AFL_OP_OK after receiving a command*/ | ||
360 | # define OP_OK op_ok() | ||
361 | static void op_ok(void) | ||
362 | { | ||
363 | aztTimeOutCount = 0; | ||
364 | do { | ||
365 | aztIndatum = inb(DATA_PORT); | ||
366 | aztTimeOutCount++; | ||
367 | if (aztTimeOutCount >= AZT_TIMEOUT) { | ||
368 | printk("aztcd: Error Wait OP_OK\n"); | ||
369 | break; | ||
370 | } | ||
371 | } while (aztIndatum != AFL_OP_OK); | ||
372 | } | ||
373 | |||
374 | /* Wait for PA_OK = drive answers with AFL_PA_OK after receiving parameters*/ | ||
375 | #if 0 | ||
376 | # define PA_OK pa_ok() | ||
377 | static void pa_ok(void) | ||
378 | { | ||
379 | aztTimeOutCount = 0; | ||
380 | do { | ||
381 | aztIndatum = inb(DATA_PORT); | ||
382 | aztTimeOutCount++; | ||
383 | if (aztTimeOutCount >= AZT_TIMEOUT) { | ||
384 | printk("aztcd: Error Wait PA_OK\n"); | ||
385 | break; | ||
386 | } | ||
387 | } while (aztIndatum != AFL_PA_OK); | ||
388 | } | ||
389 | #endif | ||
390 | |||
391 | /* Wait for STEN=Low = handshake signal 'AFL_.._OK available or command executed*/ | ||
392 | # define STEN_LOW sten_low() | ||
393 | static void sten_low(void) | ||
394 | { | ||
395 | aztTimeOutCount = 0; | ||
396 | do { | ||
397 | aztIndatum = inb(STATUS_PORT); | ||
398 | aztTimeOutCount++; | ||
399 | if (aztTimeOutCount >= AZT_TIMEOUT) { | ||
400 | if (azt_init_end) | ||
401 | printk | ||
402 | ("aztcd: Error Wait STEN_LOW commands:%x\n", | ||
403 | aztCmd); | ||
404 | break; | ||
405 | } | ||
406 | } while (aztIndatum & AFL_STATUS); | ||
407 | } | ||
408 | |||
409 | /* Wait for DTEN=Low = handshake signal 'Data available'*/ | ||
410 | # define DTEN_LOW dten_low() | ||
411 | static void dten_low(void) | ||
412 | { | ||
413 | aztTimeOutCount = 0; | ||
414 | do { | ||
415 | aztIndatum = inb(STATUS_PORT); | ||
416 | aztTimeOutCount++; | ||
417 | if (aztTimeOutCount >= AZT_TIMEOUT) { | ||
418 | printk("aztcd: Error Wait DTEN_OK\n"); | ||
419 | break; | ||
420 | } | ||
421 | } while (aztIndatum & AFL_DATA); | ||
422 | } | ||
423 | |||
424 | /* | ||
425 | * Macro for timer wait on STEN=Low, should only be used for 'slow' commands; | ||
426 | * may cause kernel panic when used in the wrong place | ||
427 | */ | ||
428 | #define STEN_LOW_WAIT statusAzt() | ||
429 | static void statusAzt(void) | ||
430 | { | ||
431 | AztTimeout = AZT_STATUS_DELAY; | ||
432 | SET_TIMER(aztStatTimer, HZ / 100); | ||
433 | sleep_on(&azt_waitq); | ||
434 | if (AztTimeout <= 0) | ||
435 | printk("aztcd: Error Wait STEN_LOW_WAIT command:%x\n", | ||
436 | aztCmd); | ||
437 | return; | ||
438 | } | ||
439 | |||
440 | static void aztStatTimer(void) | ||
441 | { | ||
442 | if (!(inb(STATUS_PORT) & AFL_STATUS)) { | ||
443 | wake_up(&azt_waitq); | ||
444 | return; | ||
445 | } | ||
446 | AztTimeout--; | ||
447 | if (AztTimeout <= 0) { | ||
448 | wake_up(&azt_waitq); | ||
449 | printk("aztcd: Error aztStatTimer: Timeout\n"); | ||
450 | return; | ||
451 | } | ||
452 | SET_TIMER(aztStatTimer, HZ / 100); | ||
453 | } | ||
454 | |||
455 | /*########################################################################## | ||
456 | CDROM Drive Command Functions | ||
457 | ########################################################################## | ||
458 | */ | ||
459 | /* | ||
460 | * Send a single command, return -1 on error, else 0 | ||
461 | */ | ||
462 | static int aztSendCmd(int cmd) | ||
463 | { | ||
464 | unsigned char data; | ||
465 | int retry; | ||
466 | |||
467 | #ifdef AZT_DEBUG | ||
468 | printk("aztcd: Executing command %x\n", cmd); | ||
469 | #endif | ||
470 | |||
471 | if ((azt_port == 0x1f0) || (azt_port == 0x170)) | ||
472 | SWITCH_IDE_SLAVE; /*switch IDE interface to slave configuration */ | ||
473 | |||
474 | aztCmd = cmd; | ||
475 | outb(POLLED, MODE_PORT); | ||
476 | do { | ||
477 | if (inb(STATUS_PORT) & AFL_STATUS) | ||
478 | break; | ||
479 | inb(DATA_PORT); /* if status left from last command, read and */ | ||
480 | } while (1); /* discard it */ | ||
481 | do { | ||
482 | if (inb(STATUS_PORT) & AFL_DATA) | ||
483 | break; | ||
484 | inb(DATA_PORT); /* if data left from last command, read and */ | ||
485 | } while (1); /* discard it */ | ||
486 | for (retry = 0; retry < AZT_RETRY_ATTEMPTS; retry++) { | ||
487 | outb((unsigned char) cmd, CMD_PORT); | ||
488 | STEN_LOW; | ||
489 | data = inb(DATA_PORT); | ||
490 | if (data == AFL_OP_OK) { | ||
491 | return 0; | ||
492 | } /*OP_OK? */ | ||
493 | if (data == AFL_OP_ERR) { | ||
494 | STEN_LOW; | ||
495 | data = inb(DATA_PORT); | ||
496 | printk | ||
497 | ("### Error 1 aztcd: aztSendCmd %x Error Code %x\n", | ||
498 | cmd, data); | ||
499 | } | ||
500 | } | ||
501 | if (retry >= AZT_RETRY_ATTEMPTS) { | ||
502 | printk("### Error 2 aztcd: aztSendCmd %x \n", cmd); | ||
503 | azt_error = 0xA5; | ||
504 | } | ||
505 | RETURNM("aztSendCmd", -1); | ||
506 | } | ||
507 | |||
508 | /* | ||
509 | * Send a play or read command to the drive, return -1 on error, else 0 | ||
510 | */ | ||
511 | static int sendAztCmd(int cmd, struct azt_Play_msf *params) | ||
512 | { | ||
513 | unsigned char data; | ||
514 | int retry; | ||
515 | |||
516 | #ifdef AZT_DEBUG | ||
517 | printk("aztcd: play start=%02x:%02x:%02x end=%02x:%02x:%02x\n", | ||
518 | params->start.min, params->start.sec, params->start.frame, | ||
519 | params->end.min, params->end.sec, params->end.frame); | ||
520 | #endif | ||
521 | for (retry = 0; retry < AZT_RETRY_ATTEMPTS; retry++) { | ||
522 | aztSendCmd(cmd); | ||
523 | outb(params->start.min, CMD_PORT); | ||
524 | outb(params->start.sec, CMD_PORT); | ||
525 | outb(params->start.frame, CMD_PORT); | ||
526 | outb(params->end.min, CMD_PORT); | ||
527 | outb(params->end.sec, CMD_PORT); | ||
528 | outb(params->end.frame, CMD_PORT); | ||
529 | STEN_LOW; | ||
530 | data = inb(DATA_PORT); | ||
531 | if (data == AFL_PA_OK) { | ||
532 | return 0; | ||
533 | } /*PA_OK ? */ | ||
534 | if (data == AFL_PA_ERR) { | ||
535 | STEN_LOW; | ||
536 | data = inb(DATA_PORT); | ||
537 | printk | ||
538 | ("### Error 1 aztcd: sendAztCmd %x Error Code %x\n", | ||
539 | cmd, data); | ||
540 | } | ||
541 | } | ||
542 | if (retry >= AZT_RETRY_ATTEMPTS) { | ||
543 | printk("### Error 2 aztcd: sendAztCmd %x\n ", cmd); | ||
544 | azt_error = 0xA5; | ||
545 | } | ||
546 | RETURNM("sendAztCmd", -1); | ||
547 | } | ||
548 | |||
549 | /* | ||
550 | * Send a seek command to the drive, return -1 on error, else 0 | ||
551 | */ | ||
552 | static int aztSeek(struct azt_Play_msf *params) | ||
553 | { | ||
554 | unsigned char data; | ||
555 | int retry; | ||
556 | |||
557 | #ifdef AZT_DEBUG | ||
558 | printk("aztcd: aztSeek %02x:%02x:%02x\n", | ||
559 | params->start.min, params->start.sec, params->start.frame); | ||
560 | #endif | ||
561 | for (retry = 0; retry < AZT_RETRY_ATTEMPTS; retry++) { | ||
562 | aztSendCmd(ACMD_SEEK); | ||
563 | outb(params->start.min, CMD_PORT); | ||
564 | outb(params->start.sec, CMD_PORT); | ||
565 | outb(params->start.frame, CMD_PORT); | ||
566 | STEN_LOW; | ||
567 | data = inb(DATA_PORT); | ||
568 | if (data == AFL_PA_OK) { | ||
569 | return 0; | ||
570 | } /*PA_OK ? */ | ||
571 | if (data == AFL_PA_ERR) { | ||
572 | STEN_LOW; | ||
573 | data = inb(DATA_PORT); | ||
574 | printk("### Error 1 aztcd: aztSeek\n"); | ||
575 | } | ||
576 | } | ||
577 | if (retry >= AZT_RETRY_ATTEMPTS) { | ||
578 | printk("### Error 2 aztcd: aztSeek\n "); | ||
579 | azt_error = 0xA5; | ||
580 | } | ||
581 | RETURNM("aztSeek", -1); | ||
582 | } | ||
583 | |||
584 | /* Send a Set Disk Type command | ||
585 | does not seem to work with Aztech drives, behavior is completely indepen- | ||
586 | dent on which mode is set ??? | ||
587 | */ | ||
588 | static int aztSetDiskType(int type) | ||
589 | { | ||
590 | unsigned char data; | ||
591 | int retry; | ||
592 | |||
593 | #ifdef AZT_DEBUG | ||
594 | printk("aztcd: set disk type command: type= %i\n", type); | ||
595 | #endif | ||
596 | for (retry = 0; retry < AZT_RETRY_ATTEMPTS; retry++) { | ||
597 | aztSendCmd(ACMD_SET_DISK_TYPE); | ||
598 | outb(type, CMD_PORT); | ||
599 | STEN_LOW; | ||
600 | data = inb(DATA_PORT); | ||
601 | if (data == AFL_PA_OK) { /*PA_OK ? */ | ||
602 | azt_read_mode = type; | ||
603 | return 0; | ||
604 | } | ||
605 | if (data == AFL_PA_ERR) { | ||
606 | STEN_LOW; | ||
607 | data = inb(DATA_PORT); | ||
608 | printk | ||
609 | ("### Error 1 aztcd: aztSetDiskType %x Error Code %x\n", | ||
610 | type, data); | ||
611 | } | ||
612 | } | ||
613 | if (retry >= AZT_RETRY_ATTEMPTS) { | ||
614 | printk("### Error 2 aztcd: aztSetDiskType %x\n ", type); | ||
615 | azt_error = 0xA5; | ||
616 | } | ||
617 | RETURNM("aztSetDiskType", -1); | ||
618 | } | ||
619 | |||
620 | |||
621 | /* used in azt_poll to poll the status, expects another program to issue a | ||
622 | * ACMD_GET_STATUS directly before | ||
623 | */ | ||
624 | static int aztStatus(void) | ||
625 | { | ||
626 | int st; | ||
627 | /* int i; | ||
628 | |||
629 | i = inb(STATUS_PORT) & AFL_STATUS; is STEN=0? ??? | ||
630 | if (!i) | ||
631 | */ STEN_LOW; | ||
632 | if (aztTimeOutCount < AZT_TIMEOUT) { | ||
633 | st = inb(DATA_PORT) & 0xFF; | ||
634 | return st; | ||
635 | } else | ||
636 | RETURNM("aztStatus", -1); | ||
637 | } | ||
638 | |||
639 | /* | ||
640 | * Get the drive status | ||
641 | */ | ||
642 | static int getAztStatus(void) | ||
643 | { | ||
644 | int st; | ||
645 | |||
646 | if (aztSendCmd(ACMD_GET_STATUS)) | ||
647 | RETURNM("getAztStatus 1", -1); | ||
648 | STEN_LOW; | ||
649 | st = inb(DATA_PORT) & 0xFF; | ||
650 | #ifdef AZT_DEBUG | ||
651 | printk("aztcd: Status = %x\n", st); | ||
652 | #endif | ||
653 | if ((st == 0xFF) || (st & AST_CMD_CHECK)) { | ||
654 | printk | ||
655 | ("aztcd: AST_CMD_CHECK error or no status available\n"); | ||
656 | return -1; | ||
657 | } | ||
658 | |||
659 | if (((st & AST_MODE_BITS) != AST_BUSY) | ||
660 | && (aztAudioStatus == CDROM_AUDIO_PLAY)) | ||
661 | /* XXX might be an error? look at q-channel? */ | ||
662 | aztAudioStatus = CDROM_AUDIO_COMPLETED; | ||
663 | |||
664 | if ((st & AST_DSK_CHG) || (st & AST_NOT_READY)) { | ||
665 | aztDiskChanged = 1; | ||
666 | aztTocUpToDate = 0; | ||
667 | aztAudioStatus = CDROM_AUDIO_NO_STATUS; | ||
668 | } | ||
669 | return st; | ||
670 | } | ||
671 | |||
672 | |||
673 | /* | ||
674 | * Send a 'Play' command and get the status. Use only from the top half. | ||
675 | */ | ||
676 | static int aztPlay(struct azt_Play_msf *arg) | ||
677 | { | ||
678 | if (sendAztCmd(ACMD_PLAY_AUDIO, arg) < 0) | ||
679 | RETURNM("aztPlay", -1); | ||
680 | return 0; | ||
681 | } | ||
682 | |||
683 | /* | ||
684 | * Subroutines to automatically close the door (tray) and | ||
685 | * lock it closed when the cd is mounted. Leave the tray | ||
686 | * locking as an option | ||
687 | */ | ||
688 | static void aztCloseDoor(void) | ||
689 | { | ||
690 | aztSendCmd(ACMD_CLOSE); | ||
691 | STEN_LOW; | ||
692 | return; | ||
693 | } | ||
694 | |||
695 | static void aztLockDoor(void) | ||
696 | { | ||
697 | #if AZT_ALLOW_TRAY_LOCK | ||
698 | aztSendCmd(ACMD_LOCK); | ||
699 | STEN_LOW; | ||
700 | #endif | ||
701 | return; | ||
702 | } | ||
703 | |||
704 | static void aztUnlockDoor(void) | ||
705 | { | ||
706 | #if AZT_ALLOW_TRAY_LOCK | ||
707 | aztSendCmd(ACMD_UNLOCK); | ||
708 | STEN_LOW; | ||
709 | #endif | ||
710 | return; | ||
711 | } | ||
712 | |||
713 | /* | ||
714 | * Read a value from the drive. Should return quickly, so a busy wait | ||
715 | * is used to avoid excessive rescheduling. The read command itself must | ||
716 | * be issued with aztSendCmd() directly before | ||
717 | */ | ||
718 | static int aztGetValue(unsigned char *result) | ||
719 | { | ||
720 | int s; | ||
721 | |||
722 | STEN_LOW; | ||
723 | if (aztTimeOutCount >= AZT_TIMEOUT) { | ||
724 | printk("aztcd: aztGetValue timeout\n"); | ||
725 | return -1; | ||
726 | } | ||
727 | s = inb(DATA_PORT) & 0xFF; | ||
728 | *result = (unsigned char) s; | ||
729 | return 0; | ||
730 | } | ||
731 | |||
732 | /* | ||
733 | * Read the current Q-channel info. Also used for reading the | ||
734 | * table of contents. | ||
735 | */ | ||
736 | static int aztGetQChannelInfo(struct azt_Toc *qp) | ||
737 | { | ||
738 | unsigned char notUsed; | ||
739 | int st; | ||
740 | |||
741 | #ifdef AZT_DEBUG | ||
742 | printk("aztcd: starting aztGetQChannelInfo Time:%li\n", jiffies); | ||
743 | #endif | ||
744 | if ((st = getAztStatus()) == -1) | ||
745 | RETURNM("aztGetQChannelInfo 1", -1); | ||
746 | if (aztSendCmd(ACMD_GET_Q_CHANNEL)) | ||
747 | RETURNM("aztGetQChannelInfo 2", -1); | ||
748 | /*STEN_LOW_WAIT; ??? Dosemu0.60's cdrom.c does not like STEN_LOW_WAIT here */ | ||
749 | if (aztGetValue(¬Used)) | ||
750 | RETURNM("aztGetQChannelInfo 3", -1); /*??? Nullbyte einlesen */ | ||
751 | if ((st & AST_MODE_BITS) == AST_INITIAL) { | ||
752 | qp->ctrl_addr = 0; /* when audio stop ACMD_GET_Q_CHANNEL returns */ | ||
753 | qp->track = 0; /* only one byte with Aztech drives */ | ||
754 | qp->pointIndex = 0; | ||
755 | qp->trackTime.min = 0; | ||
756 | qp->trackTime.sec = 0; | ||
757 | qp->trackTime.frame = 0; | ||
758 | qp->diskTime.min = 0; | ||
759 | qp->diskTime.sec = 0; | ||
760 | qp->diskTime.frame = 0; | ||
761 | return 0; | ||
762 | } else { | ||
763 | if (aztGetValue(&qp->ctrl_addr) < 0) | ||
764 | RETURNM("aztGetQChannelInfo 4", -1); | ||
765 | if (aztGetValue(&qp->track) < 0) | ||
766 | RETURNM("aztGetQChannelInfo 4", -1); | ||
767 | if (aztGetValue(&qp->pointIndex) < 0) | ||
768 | RETURNM("aztGetQChannelInfo 4", -1); | ||
769 | if (aztGetValue(&qp->trackTime.min) < 0) | ||
770 | RETURNM("aztGetQChannelInfo 4", -1); | ||
771 | if (aztGetValue(&qp->trackTime.sec) < 0) | ||
772 | RETURNM("aztGetQChannelInfo 4", -1); | ||
773 | if (aztGetValue(&qp->trackTime.frame) < 0) | ||
774 | RETURNM("aztGetQChannelInfo 4", -1); | ||
775 | if (aztGetValue(¬Used) < 0) | ||
776 | RETURNM("aztGetQChannelInfo 4", -1); | ||
777 | if (aztGetValue(&qp->diskTime.min) < 0) | ||
778 | RETURNM("aztGetQChannelInfo 4", -1); | ||
779 | if (aztGetValue(&qp->diskTime.sec) < 0) | ||
780 | RETURNM("aztGetQChannelInfo 4", -1); | ||
781 | if (aztGetValue(&qp->diskTime.frame) < 0) | ||
782 | RETURNM("aztGetQChannelInfo 4", -1); | ||
783 | } | ||
784 | #ifdef AZT_DEBUG | ||
785 | printk("aztcd: exiting aztGetQChannelInfo Time:%li\n", jiffies); | ||
786 | #endif | ||
787 | return 0; | ||
788 | } | ||
789 | |||
790 | /* | ||
791 | * Read the table of contents (TOC) and TOC header if necessary | ||
792 | */ | ||
793 | static int aztUpdateToc(void) | ||
794 | { | ||
795 | int st; | ||
796 | |||
797 | #ifdef AZT_DEBUG | ||
798 | printk("aztcd: starting aztUpdateToc Time:%li\n", jiffies); | ||
799 | #endif | ||
800 | if (aztTocUpToDate) | ||
801 | return 0; | ||
802 | |||
803 | if (aztGetDiskInfo() < 0) | ||
804 | return -EIO; | ||
805 | |||
806 | if (aztGetToc(0) < 0) | ||
807 | return -EIO; | ||
808 | |||
809 | /*audio disk detection | ||
810 | with my Aztech drive there is no audio status bit, so I use the copy | ||
811 | protection bit of the first track. If this track is copy protected | ||
812 | (copy bit = 0), I assume, it's an audio disk. Strange, but works ??? */ | ||
813 | if (!(Toc[DiskInfo.first].ctrl_addr & 0x40)) | ||
814 | DiskInfo.audio = 1; | ||
815 | else | ||
816 | DiskInfo.audio = 0; | ||
817 | |||
818 | /* XA detection */ | ||
819 | if (!DiskInfo.audio) { | ||
820 | azt_Play.start.min = 0; /*XA detection only seems to work */ | ||
821 | azt_Play.start.sec = 2; /*when we play a track */ | ||
822 | azt_Play.start.frame = 0; | ||
823 | azt_Play.end.min = 0; | ||
824 | azt_Play.end.sec = 0; | ||
825 | azt_Play.end.frame = 1; | ||
826 | if (sendAztCmd(ACMD_PLAY_READ, &azt_Play)) | ||
827 | return -1; | ||
828 | DTEN_LOW; | ||
829 | for (st = 0; st < CD_FRAMESIZE; st++) | ||
830 | inb(DATA_PORT); | ||
831 | } | ||
832 | DiskInfo.xa = getAztStatus() & AST_MODE; | ||
833 | if (DiskInfo.xa) { | ||
834 | printk | ||
835 | ("aztcd: XA support experimental - mail results to Werner.Zimmermann@fht-esslingen.de\n"); | ||
836 | } | ||
837 | |||
838 | /*multisession detection | ||
839 | support for multisession CDs is done automatically with Aztech drives, | ||
840 | we don't have to take care about TOC redirection; if we want the isofs | ||
841 | to take care about redirection, we have to set AZT_MULTISESSION to 1 */ | ||
842 | DiskInfo.multi = 0; | ||
843 | #if AZT_MULTISESSION | ||
844 | if (DiskInfo.xa) { | ||
845 | aztGetMultiDiskInfo(); /*here Disk.Info.multi is set */ | ||
846 | } | ||
847 | #endif | ||
848 | if (DiskInfo.multi) { | ||
849 | DiskInfo.lastSession.min = Toc[DiskInfo.next].diskTime.min; | ||
850 | DiskInfo.lastSession.sec = Toc[DiskInfo.next].diskTime.sec; | ||
851 | DiskInfo.lastSession.frame = | ||
852 | Toc[DiskInfo.next].diskTime.frame; | ||
853 | printk("aztcd: Multisession support experimental\n"); | ||
854 | } else { | ||
855 | DiskInfo.lastSession.min = | ||
856 | Toc[DiskInfo.first].diskTime.min; | ||
857 | DiskInfo.lastSession.sec = | ||
858 | Toc[DiskInfo.first].diskTime.sec; | ||
859 | DiskInfo.lastSession.frame = | ||
860 | Toc[DiskInfo.first].diskTime.frame; | ||
861 | } | ||
862 | |||
863 | aztTocUpToDate = 1; | ||
864 | #ifdef AZT_DEBUG | ||
865 | printk("aztcd: exiting aztUpdateToc Time:%li\n", jiffies); | ||
866 | #endif | ||
867 | return 0; | ||
868 | } | ||
869 | |||
870 | |||
871 | /* Read the table of contents header, i.e. no. of tracks and start of first | ||
872 | * track | ||
873 | */ | ||
874 | static int aztGetDiskInfo(void) | ||
875 | { | ||
876 | int limit; | ||
877 | unsigned char test; | ||
878 | struct azt_Toc qInfo; | ||
879 | |||
880 | #ifdef AZT_DEBUG | ||
881 | printk("aztcd: starting aztGetDiskInfo Time:%li\n", jiffies); | ||
882 | #endif | ||
883 | if (aztSendCmd(ACMD_SEEK_TO_LEADIN)) | ||
884 | RETURNM("aztGetDiskInfo 1", -1); | ||
885 | STEN_LOW_WAIT; | ||
886 | test = 0; | ||
887 | for (limit = 300; limit > 0; limit--) { | ||
888 | if (aztGetQChannelInfo(&qInfo) < 0) | ||
889 | RETURNM("aztGetDiskInfo 2", -1); | ||
890 | if (qInfo.pointIndex == 0xA0) { /*Number of FirstTrack */ | ||
891 | DiskInfo.first = qInfo.diskTime.min; | ||
892 | DiskInfo.first = azt_bcd2bin(DiskInfo.first); | ||
893 | test = test | 0x01; | ||
894 | } | ||
895 | if (qInfo.pointIndex == 0xA1) { /*Number of LastTrack */ | ||
896 | DiskInfo.last = qInfo.diskTime.min; | ||
897 | DiskInfo.last = azt_bcd2bin(DiskInfo.last); | ||
898 | test = test | 0x02; | ||
899 | } | ||
900 | if (qInfo.pointIndex == 0xA2) { /*DiskLength */ | ||
901 | DiskInfo.diskLength.min = qInfo.diskTime.min; | ||
902 | DiskInfo.diskLength.sec = qInfo.diskTime.sec; | ||
903 | DiskInfo.diskLength.frame = qInfo.diskTime.frame; | ||
904 | test = test | 0x04; | ||
905 | } | ||
906 | if ((qInfo.pointIndex == DiskInfo.first) && (test & 0x01)) { /*StartTime of First Track */ | ||
907 | DiskInfo.firstTrack.min = qInfo.diskTime.min; | ||
908 | DiskInfo.firstTrack.sec = qInfo.diskTime.sec; | ||
909 | DiskInfo.firstTrack.frame = qInfo.diskTime.frame; | ||
910 | test = test | 0x08; | ||
911 | } | ||
912 | if (test == 0x0F) | ||
913 | break; | ||
914 | } | ||
915 | #ifdef AZT_DEBUG | ||
916 | printk("aztcd: exiting aztGetDiskInfo Time:%li\n", jiffies); | ||
917 | printk | ||
918 | ("Disk Info: first %d last %d length %02X:%02X.%02X dez first %02X:%02X.%02X dez\n", | ||
919 | DiskInfo.first, DiskInfo.last, DiskInfo.diskLength.min, | ||
920 | DiskInfo.diskLength.sec, DiskInfo.diskLength.frame, | ||
921 | DiskInfo.firstTrack.min, DiskInfo.firstTrack.sec, | ||
922 | DiskInfo.firstTrack.frame); | ||
923 | #endif | ||
924 | if (test != 0x0F) | ||
925 | return -1; | ||
926 | return 0; | ||
927 | } | ||
928 | |||
929 | #if AZT_MULTISESSION | ||
930 | /* | ||
931 | * Get Multisession Disk Info | ||
932 | */ | ||
933 | static int aztGetMultiDiskInfo(void) | ||
934 | { | ||
935 | int limit, k = 5; | ||
936 | unsigned char test; | ||
937 | struct azt_Toc qInfo; | ||
938 | |||
939 | #ifdef AZT_DEBUG | ||
940 | printk("aztcd: starting aztGetMultiDiskInfo\n"); | ||
941 | #endif | ||
942 | |||
943 | do { | ||
944 | azt_Play.start.min = Toc[DiskInfo.last + 1].diskTime.min; | ||
945 | azt_Play.start.sec = Toc[DiskInfo.last + 1].diskTime.sec; | ||
946 | azt_Play.start.frame = | ||
947 | Toc[DiskInfo.last + 1].diskTime.frame; | ||
948 | test = 0; | ||
949 | |||
950 | for (limit = 30; limit > 0; limit--) { /*Seek for LeadIn of next session */ | ||
951 | if (aztSeek(&azt_Play)) | ||
952 | RETURNM("aztGetMultiDiskInfo 1", -1); | ||
953 | if (aztGetQChannelInfo(&qInfo) < 0) | ||
954 | RETURNM("aztGetMultiDiskInfo 2", -1); | ||
955 | if ((qInfo.track == 0) && (qInfo.pointIndex)) | ||
956 | break; /*LeadIn found */ | ||
957 | if ((azt_Play.start.sec += 10) > 59) { | ||
958 | azt_Play.start.sec = 0; | ||
959 | azt_Play.start.min++; | ||
960 | } | ||
961 | } | ||
962 | if (!limit) | ||
963 | break; /*Check, if a leadin track was found, if not we're | ||
964 | at the end of the disk */ | ||
965 | #ifdef AZT_DEBUG_MULTISESSION | ||
966 | printk("leadin found track %d pointIndex %x limit %d\n", | ||
967 | qInfo.track, qInfo.pointIndex, limit); | ||
968 | #endif | ||
969 | for (limit = 300; limit > 0; limit--) { | ||
970 | if (++azt_Play.start.frame > 74) { | ||
971 | azt_Play.start.frame = 0; | ||
972 | if (azt_Play.start.sec > 59) { | ||
973 | azt_Play.start.sec = 0; | ||
974 | azt_Play.start.min++; | ||
975 | } | ||
976 | } | ||
977 | if (aztSeek(&azt_Play)) | ||
978 | RETURNM("aztGetMultiDiskInfo 3", -1); | ||
979 | if (aztGetQChannelInfo(&qInfo) < 0) | ||
980 | RETURNM("aztGetMultiDiskInfo 4", -1); | ||
981 | if (qInfo.pointIndex == 0xA0) { /*Number of NextTrack */ | ||
982 | DiskInfo.next = qInfo.diskTime.min; | ||
983 | DiskInfo.next = azt_bcd2bin(DiskInfo.next); | ||
984 | test = test | 0x01; | ||
985 | } | ||
986 | if (qInfo.pointIndex == 0xA1) { /*Number of LastTrack */ | ||
987 | DiskInfo.last = qInfo.diskTime.min; | ||
988 | DiskInfo.last = azt_bcd2bin(DiskInfo.last); | ||
989 | test = test | 0x02; | ||
990 | } | ||
991 | if (qInfo.pointIndex == 0xA2) { /*DiskLength */ | ||
992 | DiskInfo.diskLength.min = | ||
993 | qInfo.diskTime.min; | ||
994 | DiskInfo.diskLength.sec = | ||
995 | qInfo.diskTime.sec; | ||
996 | DiskInfo.diskLength.frame = | ||
997 | qInfo.diskTime.frame; | ||
998 | test = test | 0x04; | ||
999 | } | ||
1000 | if ((qInfo.pointIndex == DiskInfo.next) && (test & 0x01)) { /*StartTime of Next Track */ | ||
1001 | DiskInfo.nextSession.min = | ||
1002 | qInfo.diskTime.min; | ||
1003 | DiskInfo.nextSession.sec = | ||
1004 | qInfo.diskTime.sec; | ||
1005 | DiskInfo.nextSession.frame = | ||
1006 | qInfo.diskTime.frame; | ||
1007 | test = test | 0x08; | ||
1008 | } | ||
1009 | if (test == 0x0F) | ||
1010 | break; | ||
1011 | } | ||
1012 | #ifdef AZT_DEBUG_MULTISESSION | ||
1013 | printk | ||
1014 | ("MultiDisk Info: first %d next %d last %d length %02x:%02x.%02x dez first %02x:%02x.%02x dez next %02x:%02x.%02x dez\n", | ||
1015 | DiskInfo.first, DiskInfo.next, DiskInfo.last, | ||
1016 | DiskInfo.diskLength.min, DiskInfo.diskLength.sec, | ||
1017 | DiskInfo.diskLength.frame, DiskInfo.firstTrack.min, | ||
1018 | DiskInfo.firstTrack.sec, DiskInfo.firstTrack.frame, | ||
1019 | DiskInfo.nextSession.min, DiskInfo.nextSession.sec, | ||
1020 | DiskInfo.nextSession.frame); | ||
1021 | #endif | ||
1022 | if (test != 0x0F) | ||
1023 | break; | ||
1024 | else | ||
1025 | DiskInfo.multi = 1; /*found TOC of more than one session */ | ||
1026 | aztGetToc(1); | ||
1027 | } while (--k); | ||
1028 | |||
1029 | #ifdef AZT_DEBUG | ||
1030 | printk("aztcd: exiting aztGetMultiDiskInfo Time:%li\n", jiffies); | ||
1031 | #endif | ||
1032 | return 0; | ||
1033 | } | ||
1034 | #endif | ||
1035 | |||
1036 | /* | ||
1037 | * Read the table of contents (TOC) | ||
1038 | */ | ||
1039 | static int aztGetToc(int multi) | ||
1040 | { | ||
1041 | int i, px; | ||
1042 | int limit; | ||
1043 | struct azt_Toc qInfo; | ||
1044 | |||
1045 | #ifdef AZT_DEBUG | ||
1046 | printk("aztcd: starting aztGetToc Time:%li\n", jiffies); | ||
1047 | #endif | ||
1048 | if (!multi) { | ||
1049 | for (i = 0; i < MAX_TRACKS; i++) | ||
1050 | Toc[i].pointIndex = 0; | ||
1051 | i = DiskInfo.last + 3; | ||
1052 | } else { | ||
1053 | for (i = DiskInfo.next; i < MAX_TRACKS; i++) | ||
1054 | Toc[i].pointIndex = 0; | ||
1055 | i = DiskInfo.last + 4 - DiskInfo.next; | ||
1056 | } | ||
1057 | |||
1058 | /*Is there a good reason to stop motor before TOC read? | ||
1059 | if (aztSendCmd(ACMD_STOP)) RETURNM("aztGetToc 1",-1); | ||
1060 | STEN_LOW_WAIT; | ||
1061 | */ | ||
1062 | |||
1063 | if (!multi) { | ||
1064 | azt_mode = 0x05; | ||
1065 | if (aztSendCmd(ACMD_SEEK_TO_LEADIN)) | ||
1066 | RETURNM("aztGetToc 2", -1); | ||
1067 | STEN_LOW_WAIT; | ||
1068 | } | ||
1069 | for (limit = 300; limit > 0; limit--) { | ||
1070 | if (multi) { | ||
1071 | if (++azt_Play.start.sec > 59) { | ||
1072 | azt_Play.start.sec = 0; | ||
1073 | azt_Play.start.min++; | ||
1074 | } | ||
1075 | if (aztSeek(&azt_Play)) | ||
1076 | RETURNM("aztGetToc 3", -1); | ||
1077 | } | ||
1078 | if (aztGetQChannelInfo(&qInfo) < 0) | ||
1079 | break; | ||
1080 | |||
1081 | px = azt_bcd2bin(qInfo.pointIndex); | ||
1082 | |||
1083 | if (px > 0 && px < MAX_TRACKS && qInfo.track == 0) | ||
1084 | if (Toc[px].pointIndex == 0) { | ||
1085 | Toc[px] = qInfo; | ||
1086 | i--; | ||
1087 | } | ||
1088 | |||
1089 | if (i <= 0) | ||
1090 | break; | ||
1091 | } | ||
1092 | |||
1093 | Toc[DiskInfo.last + 1].diskTime = DiskInfo.diskLength; | ||
1094 | Toc[DiskInfo.last].trackTime = DiskInfo.diskLength; | ||
1095 | |||
1096 | #ifdef AZT_DEBUG_MULTISESSION | ||
1097 | printk("aztcd: exiting aztGetToc\n"); | ||
1098 | for (i = 1; i <= DiskInfo.last + 1; i++) | ||
1099 | printk | ||
1100 | ("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X dez %02X:%02X.%02X dez\n", | ||
1101 | i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex, | ||
1102 | Toc[i].trackTime.min, Toc[i].trackTime.sec, | ||
1103 | Toc[i].trackTime.frame, Toc[i].diskTime.min, | ||
1104 | Toc[i].diskTime.sec, Toc[i].diskTime.frame); | ||
1105 | for (i = 100; i < 103; i++) | ||
1106 | printk | ||
1107 | ("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X dez %02X:%02X.%02X dez\n", | ||
1108 | i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex, | ||
1109 | Toc[i].trackTime.min, Toc[i].trackTime.sec, | ||
1110 | Toc[i].trackTime.frame, Toc[i].diskTime.min, | ||
1111 | Toc[i].diskTime.sec, Toc[i].diskTime.frame); | ||
1112 | #endif | ||
1113 | |||
1114 | return limit > 0 ? 0 : -1; | ||
1115 | } | ||
1116 | |||
1117 | |||
1118 | /*########################################################################## | ||
1119 | Kernel Interface Functions | ||
1120 | ########################################################################## | ||
1121 | */ | ||
1122 | |||
1123 | #ifndef MODULE | ||
1124 | static int __init aztcd_setup(char *str) | ||
1125 | { | ||
1126 | int ints[4]; | ||
1127 | |||
1128 | (void) get_options(str, ARRAY_SIZE(ints), ints); | ||
1129 | |||
1130 | if (ints[0] > 0) | ||
1131 | azt_port = ints[1]; | ||
1132 | if (ints[1] > 1) | ||
1133 | azt_cont = ints[2]; | ||
1134 | return 1; | ||
1135 | } | ||
1136 | |||
1137 | __setup("aztcd=", aztcd_setup); | ||
1138 | |||
1139 | #endif /* !MODULE */ | ||
1140 | |||
1141 | /* | ||
1142 | * Checking if the media has been changed | ||
1143 | */ | ||
1144 | static int check_aztcd_media_change(struct gendisk *disk) | ||
1145 | { | ||
1146 | if (aztDiskChanged) { /* disk changed */ | ||
1147 | aztDiskChanged = 0; | ||
1148 | return 1; | ||
1149 | } else | ||
1150 | return 0; /* no change */ | ||
1151 | } | ||
1152 | |||
1153 | /* | ||
1154 | * Kernel IO-controls | ||
1155 | */ | ||
1156 | static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, | ||
1157 | unsigned long arg) | ||
1158 | { | ||
1159 | int i; | ||
1160 | struct azt_Toc qInfo; | ||
1161 | struct cdrom_ti ti; | ||
1162 | struct cdrom_tochdr tocHdr; | ||
1163 | struct cdrom_msf msf; | ||
1164 | struct cdrom_tocentry entry; | ||
1165 | struct azt_Toc *tocPtr; | ||
1166 | struct cdrom_subchnl subchnl; | ||
1167 | struct cdrom_volctrl volctrl; | ||
1168 | void __user *argp = (void __user *)arg; | ||
1169 | |||
1170 | #ifdef AZT_DEBUG | ||
1171 | printk("aztcd: starting aztcd_ioctl - Command:%x Time: %li\n", | ||
1172 | cmd, jiffies); | ||
1173 | printk("aztcd Status %x\n", getAztStatus()); | ||
1174 | #endif | ||
1175 | if (!ip) | ||
1176 | RETURNM("aztcd_ioctl 1", -EINVAL); | ||
1177 | if (getAztStatus() < 0) | ||
1178 | RETURNM("aztcd_ioctl 2", -EIO); | ||
1179 | if ((!aztTocUpToDate) || (aztDiskChanged)) { | ||
1180 | if ((i = aztUpdateToc()) < 0) | ||
1181 | RETURNM("aztcd_ioctl 3", i); /* error reading TOC */ | ||
1182 | } | ||
1183 | |||
1184 | switch (cmd) { | ||
1185 | case CDROMSTART: /* Spin up the drive. Don't know, what to do, | ||
1186 | at least close the tray */ | ||
1187 | #if AZT_PRIVATE_IOCTLS | ||
1188 | if (aztSendCmd(ACMD_CLOSE)) | ||
1189 | RETURNM("aztcd_ioctl 4", -1); | ||
1190 | STEN_LOW_WAIT; | ||
1191 | #endif | ||
1192 | break; | ||
1193 | case CDROMSTOP: /* Spin down the drive */ | ||
1194 | if (aztSendCmd(ACMD_STOP)) | ||
1195 | RETURNM("aztcd_ioctl 5", -1); | ||
1196 | STEN_LOW_WAIT; | ||
1197 | /* should we do anything if it fails? */ | ||
1198 | aztAudioStatus = CDROM_AUDIO_NO_STATUS; | ||
1199 | break; | ||
1200 | case CDROMPAUSE: /* Pause the drive */ | ||
1201 | if (aztAudioStatus != CDROM_AUDIO_PLAY) | ||
1202 | return -EINVAL; | ||
1203 | |||
1204 | if (aztGetQChannelInfo(&qInfo) < 0) { /* didn't get q channel info */ | ||
1205 | aztAudioStatus = CDROM_AUDIO_NO_STATUS; | ||
1206 | RETURNM("aztcd_ioctl 7", 0); | ||
1207 | } | ||
1208 | azt_Play.start = qInfo.diskTime; /* remember restart point */ | ||
1209 | |||
1210 | if (aztSendCmd(ACMD_PAUSE)) | ||
1211 | RETURNM("aztcd_ioctl 8", -1); | ||
1212 | STEN_LOW_WAIT; | ||
1213 | aztAudioStatus = CDROM_AUDIO_PAUSED; | ||
1214 | break; | ||
1215 | case CDROMRESUME: /* Play it again, Sam */ | ||
1216 | if (aztAudioStatus != CDROM_AUDIO_PAUSED) | ||
1217 | return -EINVAL; | ||
1218 | /* restart the drive at the saved position. */ | ||
1219 | i = aztPlay(&azt_Play); | ||
1220 | if (i < 0) { | ||
1221 | aztAudioStatus = CDROM_AUDIO_ERROR; | ||
1222 | return -EIO; | ||
1223 | } | ||
1224 | aztAudioStatus = CDROM_AUDIO_PLAY; | ||
1225 | break; | ||
1226 | case CDROMMULTISESSION: /*multisession support -- experimental */ | ||
1227 | { | ||
1228 | struct cdrom_multisession ms; | ||
1229 | #ifdef AZT_DEBUG | ||
1230 | printk("aztcd ioctl MULTISESSION\n"); | ||
1231 | #endif | ||
1232 | if (copy_from_user(&ms, argp, | ||
1233 | sizeof(struct cdrom_multisession))) | ||
1234 | return -EFAULT; | ||
1235 | if (ms.addr_format == CDROM_MSF) { | ||
1236 | ms.addr.msf.minute = | ||
1237 | azt_bcd2bin(DiskInfo.lastSession.min); | ||
1238 | ms.addr.msf.second = | ||
1239 | azt_bcd2bin(DiskInfo.lastSession.sec); | ||
1240 | ms.addr.msf.frame = | ||
1241 | azt_bcd2bin(DiskInfo.lastSession. | ||
1242 | frame); | ||
1243 | } else if (ms.addr_format == CDROM_LBA) | ||
1244 | ms.addr.lba = | ||
1245 | azt_msf2hsg(&DiskInfo.lastSession); | ||
1246 | else | ||
1247 | return -EINVAL; | ||
1248 | ms.xa_flag = DiskInfo.xa; | ||
1249 | if (copy_to_user(argp, &ms, | ||
1250 | sizeof(struct cdrom_multisession))) | ||
1251 | return -EFAULT; | ||
1252 | #ifdef AZT_DEBUG | ||
1253 | if (ms.addr_format == CDROM_MSF) | ||
1254 | printk | ||
1255 | ("aztcd multisession xa:%d, msf:%02x:%02x.%02x [%02x:%02x.%02x])\n", | ||
1256 | ms.xa_flag, ms.addr.msf.minute, | ||
1257 | ms.addr.msf.second, ms.addr.msf.frame, | ||
1258 | DiskInfo.lastSession.min, | ||
1259 | DiskInfo.lastSession.sec, | ||
1260 | DiskInfo.lastSession.frame); | ||
1261 | else | ||
1262 | printk | ||
1263 | ("aztcd multisession %d, lba:0x%08x [%02x:%02x.%02x])\n", | ||
1264 | ms.xa_flag, ms.addr.lba, | ||
1265 | DiskInfo.lastSession.min, | ||
1266 | DiskInfo.lastSession.sec, | ||
1267 | DiskInfo.lastSession.frame); | ||
1268 | #endif | ||
1269 | return 0; | ||
1270 | } | ||
1271 | case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */ | ||
1272 | if (copy_from_user(&ti, argp, sizeof ti)) | ||
1273 | return -EFAULT; | ||
1274 | if (ti.cdti_trk0 < DiskInfo.first | ||
1275 | || ti.cdti_trk0 > DiskInfo.last | ||
1276 | || ti.cdti_trk1 < ti.cdti_trk0) { | ||
1277 | return -EINVAL; | ||
1278 | } | ||
1279 | if (ti.cdti_trk1 > DiskInfo.last) | ||
1280 | ti.cdti_trk1 = DiskInfo.last; | ||
1281 | azt_Play.start = Toc[ti.cdti_trk0].diskTime; | ||
1282 | azt_Play.end = Toc[ti.cdti_trk1 + 1].diskTime; | ||
1283 | #ifdef AZT_DEBUG | ||
1284 | printk("aztcd play: %02x:%02x.%02x to %02x:%02x.%02x\n", | ||
1285 | azt_Play.start.min, azt_Play.start.sec, | ||
1286 | azt_Play.start.frame, azt_Play.end.min, | ||
1287 | azt_Play.end.sec, azt_Play.end.frame); | ||
1288 | #endif | ||
1289 | i = aztPlay(&azt_Play); | ||
1290 | if (i < 0) { | ||
1291 | aztAudioStatus = CDROM_AUDIO_ERROR; | ||
1292 | return -EIO; | ||
1293 | } | ||
1294 | aztAudioStatus = CDROM_AUDIO_PLAY; | ||
1295 | break; | ||
1296 | case CDROMPLAYMSF: /* Play starting at the given MSF address. */ | ||
1297 | /* if (aztAudioStatus == CDROM_AUDIO_PLAY) | ||
1298 | { if (aztSendCmd(ACMD_STOP)) RETURNM("aztcd_ioctl 9",-1); | ||
1299 | STEN_LOW; | ||
1300 | aztAudioStatus = CDROM_AUDIO_NO_STATUS; | ||
1301 | } | ||
1302 | */ | ||
1303 | if (copy_from_user(&msf, argp, sizeof msf)) | ||
1304 | return -EFAULT; | ||
1305 | /* convert to bcd */ | ||
1306 | azt_bin2bcd(&msf.cdmsf_min0); | ||
1307 | azt_bin2bcd(&msf.cdmsf_sec0); | ||
1308 | azt_bin2bcd(&msf.cdmsf_frame0); | ||
1309 | azt_bin2bcd(&msf.cdmsf_min1); | ||
1310 | azt_bin2bcd(&msf.cdmsf_sec1); | ||
1311 | azt_bin2bcd(&msf.cdmsf_frame1); | ||
1312 | azt_Play.start.min = msf.cdmsf_min0; | ||
1313 | azt_Play.start.sec = msf.cdmsf_sec0; | ||
1314 | azt_Play.start.frame = msf.cdmsf_frame0; | ||
1315 | azt_Play.end.min = msf.cdmsf_min1; | ||
1316 | azt_Play.end.sec = msf.cdmsf_sec1; | ||
1317 | azt_Play.end.frame = msf.cdmsf_frame1; | ||
1318 | #ifdef AZT_DEBUG | ||
1319 | printk("aztcd play: %02x:%02x.%02x to %02x:%02x.%02x\n", | ||
1320 | azt_Play.start.min, azt_Play.start.sec, | ||
1321 | azt_Play.start.frame, azt_Play.end.min, | ||
1322 | azt_Play.end.sec, azt_Play.end.frame); | ||
1323 | #endif | ||
1324 | i = aztPlay(&azt_Play); | ||
1325 | if (i < 0) { | ||
1326 | aztAudioStatus = CDROM_AUDIO_ERROR; | ||
1327 | return -EIO; | ||
1328 | } | ||
1329 | aztAudioStatus = CDROM_AUDIO_PLAY; | ||
1330 | break; | ||
1331 | |||
1332 | case CDROMREADTOCHDR: /* Read the table of contents header */ | ||
1333 | tocHdr.cdth_trk0 = DiskInfo.first; | ||
1334 | tocHdr.cdth_trk1 = DiskInfo.last; | ||
1335 | if (copy_to_user(argp, &tocHdr, sizeof tocHdr)) | ||
1336 | return -EFAULT; | ||
1337 | break; | ||
1338 | case CDROMREADTOCENTRY: /* Read an entry in the table of contents */ | ||
1339 | if (copy_from_user(&entry, argp, sizeof entry)) | ||
1340 | return -EFAULT; | ||
1341 | if ((!aztTocUpToDate) || aztDiskChanged) | ||
1342 | aztUpdateToc(); | ||
1343 | if (entry.cdte_track == CDROM_LEADOUT) | ||
1344 | tocPtr = &Toc[DiskInfo.last + 1]; | ||
1345 | else if (entry.cdte_track > DiskInfo.last | ||
1346 | || entry.cdte_track < DiskInfo.first) { | ||
1347 | return -EINVAL; | ||
1348 | } else | ||
1349 | tocPtr = &Toc[entry.cdte_track]; | ||
1350 | entry.cdte_adr = tocPtr->ctrl_addr; | ||
1351 | entry.cdte_ctrl = tocPtr->ctrl_addr >> 4; | ||
1352 | if (entry.cdte_format == CDROM_LBA) | ||
1353 | entry.cdte_addr.lba = | ||
1354 | azt_msf2hsg(&tocPtr->diskTime); | ||
1355 | else if (entry.cdte_format == CDROM_MSF) { | ||
1356 | entry.cdte_addr.msf.minute = | ||
1357 | azt_bcd2bin(tocPtr->diskTime.min); | ||
1358 | entry.cdte_addr.msf.second = | ||
1359 | azt_bcd2bin(tocPtr->diskTime.sec); | ||
1360 | entry.cdte_addr.msf.frame = | ||
1361 | azt_bcd2bin(tocPtr->diskTime.frame); | ||
1362 | } else { | ||
1363 | return -EINVAL; | ||
1364 | } | ||
1365 | if (copy_to_user(argp, &entry, sizeof entry)) | ||
1366 | return -EFAULT; | ||
1367 | break; | ||
1368 | case CDROMSUBCHNL: /* Get subchannel info */ | ||
1369 | if (copy_from_user | ||
1370 | (&subchnl, argp, sizeof(struct cdrom_subchnl))) | ||
1371 | return -EFAULT; | ||
1372 | if (aztGetQChannelInfo(&qInfo) < 0) { | ||
1373 | #ifdef AZT_DEBUG | ||
1374 | printk | ||
1375 | ("aztcd: exiting aztcd_ioctl - Error 3 - Command:%x\n", | ||
1376 | cmd); | ||
1377 | #endif | ||
1378 | return -EIO; | ||
1379 | } | ||
1380 | subchnl.cdsc_audiostatus = aztAudioStatus; | ||
1381 | subchnl.cdsc_adr = qInfo.ctrl_addr; | ||
1382 | subchnl.cdsc_ctrl = qInfo.ctrl_addr >> 4; | ||
1383 | subchnl.cdsc_trk = azt_bcd2bin(qInfo.track); | ||
1384 | subchnl.cdsc_ind = azt_bcd2bin(qInfo.pointIndex); | ||
1385 | if (subchnl.cdsc_format == CDROM_LBA) { | ||
1386 | subchnl.cdsc_absaddr.lba = | ||
1387 | azt_msf2hsg(&qInfo.diskTime); | ||
1388 | subchnl.cdsc_reladdr.lba = | ||
1389 | azt_msf2hsg(&qInfo.trackTime); | ||
1390 | } else { /*default */ | ||
1391 | subchnl.cdsc_format = CDROM_MSF; | ||
1392 | subchnl.cdsc_absaddr.msf.minute = | ||
1393 | azt_bcd2bin(qInfo.diskTime.min); | ||
1394 | subchnl.cdsc_absaddr.msf.second = | ||
1395 | azt_bcd2bin(qInfo.diskTime.sec); | ||
1396 | subchnl.cdsc_absaddr.msf.frame = | ||
1397 | azt_bcd2bin(qInfo.diskTime.frame); | ||
1398 | subchnl.cdsc_reladdr.msf.minute = | ||
1399 | azt_bcd2bin(qInfo.trackTime.min); | ||
1400 | subchnl.cdsc_reladdr.msf.second = | ||
1401 | azt_bcd2bin(qInfo.trackTime.sec); | ||
1402 | subchnl.cdsc_reladdr.msf.frame = | ||
1403 | azt_bcd2bin(qInfo.trackTime.frame); | ||
1404 | } | ||
1405 | if (copy_to_user(argp, &subchnl, sizeof(struct cdrom_subchnl))) | ||
1406 | return -EFAULT; | ||
1407 | break; | ||
1408 | case CDROMVOLCTRL: /* Volume control | ||
1409 | * With my Aztech CD268-01A volume control does not work, I can only | ||
1410 | turn the channels on (any value !=0) or off (value==0). Maybe it | ||
1411 | works better with your drive */ | ||
1412 | if (copy_from_user(&volctrl, argp, sizeof(volctrl))) | ||
1413 | return -EFAULT; | ||
1414 | azt_Play.start.min = 0x21; | ||
1415 | azt_Play.start.sec = 0x84; | ||
1416 | azt_Play.start.frame = volctrl.channel0; | ||
1417 | azt_Play.end.min = volctrl.channel1; | ||
1418 | azt_Play.end.sec = volctrl.channel2; | ||
1419 | azt_Play.end.frame = volctrl.channel3; | ||
1420 | sendAztCmd(ACMD_SET_VOLUME, &azt_Play); | ||
1421 | STEN_LOW_WAIT; | ||
1422 | break; | ||
1423 | case CDROMEJECT: | ||
1424 | aztUnlockDoor(); /* Assume user knows what they're doing */ | ||
1425 | /* all drives can at least stop! */ | ||
1426 | if (aztAudioStatus == CDROM_AUDIO_PLAY) { | ||
1427 | if (aztSendCmd(ACMD_STOP)) | ||
1428 | RETURNM("azt_ioctl 10", -1); | ||
1429 | STEN_LOW_WAIT; | ||
1430 | } | ||
1431 | if (aztSendCmd(ACMD_EJECT)) | ||
1432 | RETURNM("azt_ioctl 11", -1); | ||
1433 | STEN_LOW_WAIT; | ||
1434 | aztAudioStatus = CDROM_AUDIO_NO_STATUS; | ||
1435 | break; | ||
1436 | case CDROMEJECT_SW: | ||
1437 | azt_auto_eject = (char) arg; | ||
1438 | break; | ||
1439 | case CDROMRESET: | ||
1440 | outb(ACMD_SOFT_RESET, CMD_PORT); /*send reset */ | ||
1441 | STEN_LOW; | ||
1442 | if (inb(DATA_PORT) != AFL_OP_OK) { /*OP_OK? */ | ||
1443 | printk | ||
1444 | ("aztcd: AZTECH CD-ROM drive does not respond\n"); | ||
1445 | } | ||
1446 | break; | ||
1447 | /*Take care, the following code is not compatible with other CD-ROM drivers, | ||
1448 | use it at your own risk with cdplay.c. Set AZT_PRIVATE_IOCTLS to 0 in aztcd.h, | ||
1449 | if you do not want to use it! | ||
1450 | */ | ||
1451 | #if AZT_PRIVATE_IOCTLS | ||
1452 | case CDROMREADCOOKED: /*read data in mode 1 (2048 Bytes) */ | ||
1453 | case CDROMREADRAW: /*read data in mode 2 (2336 Bytes) */ | ||
1454 | { | ||
1455 | if (copy_from_user(&msf, argp, sizeof msf)) | ||
1456 | return -EFAULT; | ||
1457 | /* convert to bcd */ | ||
1458 | azt_bin2bcd(&msf.cdmsf_min0); | ||
1459 | azt_bin2bcd(&msf.cdmsf_sec0); | ||
1460 | azt_bin2bcd(&msf.cdmsf_frame0); | ||
1461 | msf.cdmsf_min1 = 0; | ||
1462 | msf.cdmsf_sec1 = 0; | ||
1463 | msf.cdmsf_frame1 = 1; /*read only one frame */ | ||
1464 | azt_Play.start.min = msf.cdmsf_min0; | ||
1465 | azt_Play.start.sec = msf.cdmsf_sec0; | ||
1466 | azt_Play.start.frame = msf.cdmsf_frame0; | ||
1467 | azt_Play.end.min = msf.cdmsf_min1; | ||
1468 | azt_Play.end.sec = msf.cdmsf_sec1; | ||
1469 | azt_Play.end.frame = msf.cdmsf_frame1; | ||
1470 | if (cmd == CDROMREADRAW) { | ||
1471 | if (DiskInfo.xa) { | ||
1472 | return -1; /*XA Disks can't be read raw */ | ||
1473 | } else { | ||
1474 | if (sendAztCmd(ACMD_PLAY_READ_RAW, &azt_Play)) | ||
1475 | return -1; | ||
1476 | DTEN_LOW; | ||
1477 | insb(DATA_PORT, buf, CD_FRAMESIZE_RAW); | ||
1478 | if (copy_to_user(argp, &buf, CD_FRAMESIZE_RAW)) | ||
1479 | return -EFAULT; | ||
1480 | } | ||
1481 | } else | ||
1482 | /*CDROMREADCOOKED*/ { | ||
1483 | if (sendAztCmd(ACMD_PLAY_READ, &azt_Play)) | ||
1484 | return -1; | ||
1485 | DTEN_LOW; | ||
1486 | insb(DATA_PORT, buf, CD_FRAMESIZE); | ||
1487 | if (copy_to_user(argp, &buf, CD_FRAMESIZE)) | ||
1488 | return -EFAULT; | ||
1489 | } | ||
1490 | } | ||
1491 | break; | ||
1492 | case CDROMSEEK: /*seek msf address */ | ||
1493 | if (copy_from_user(&msf, argp, sizeof msf)) | ||
1494 | return -EFAULT; | ||
1495 | /* convert to bcd */ | ||
1496 | azt_bin2bcd(&msf.cdmsf_min0); | ||
1497 | azt_bin2bcd(&msf.cdmsf_sec0); | ||
1498 | azt_bin2bcd(&msf.cdmsf_frame0); | ||
1499 | azt_Play.start.min = msf.cdmsf_min0; | ||
1500 | azt_Play.start.sec = msf.cdmsf_sec0; | ||
1501 | azt_Play.start.frame = msf.cdmsf_frame0; | ||
1502 | if (aztSeek(&azt_Play)) | ||
1503 | return -1; | ||
1504 | break; | ||
1505 | #endif /*end of incompatible code */ | ||
1506 | case CDROMREADMODE1: /*set read data in mode 1 */ | ||
1507 | return aztSetDiskType(AZT_MODE_1); | ||
1508 | case CDROMREADMODE2: /*set read data in mode 2 */ | ||
1509 | return aztSetDiskType(AZT_MODE_2); | ||
1510 | default: | ||
1511 | return -EINVAL; | ||
1512 | } | ||
1513 | #ifdef AZT_DEBUG | ||
1514 | printk("aztcd: exiting aztcd_ioctl Command:%x Time:%li\n", cmd, | ||
1515 | jiffies); | ||
1516 | #endif | ||
1517 | return 0; | ||
1518 | } | ||
1519 | |||
1520 | /* | ||
1521 | * Take care of the different block sizes between cdrom and Linux. | ||
1522 | * When Linux gets variable block sizes this will probably go away. | ||
1523 | */ | ||
1524 | static void azt_transfer(void) | ||
1525 | { | ||
1526 | #ifdef AZT_TEST | ||
1527 | printk("aztcd: executing azt_transfer Time:%li\n", jiffies); | ||
1528 | #endif | ||
1529 | if (!current_valid()) | ||
1530 | return; | ||
1531 | |||
1532 | while (CURRENT->nr_sectors) { | ||
1533 | int bn = CURRENT->sector / 4; | ||
1534 | int i; | ||
1535 | for (i = 0; i < AZT_BUF_SIZ && azt_buf_bn[i] != bn; ++i); | ||
1536 | if (i < AZT_BUF_SIZ) { | ||
1537 | int offs = (i * 4 + (CURRENT->sector & 3)) * 512; | ||
1538 | int nr_sectors = 4 - (CURRENT->sector & 3); | ||
1539 | if (azt_buf_out != i) { | ||
1540 | azt_buf_out = i; | ||
1541 | if (azt_buf_bn[i] != bn) { | ||
1542 | azt_buf_out = -1; | ||
1543 | continue; | ||
1544 | } | ||
1545 | } | ||
1546 | if (nr_sectors > CURRENT->nr_sectors) | ||
1547 | nr_sectors = CURRENT->nr_sectors; | ||
1548 | memcpy(CURRENT->buffer, azt_buf + offs, | ||
1549 | nr_sectors * 512); | ||
1550 | CURRENT->nr_sectors -= nr_sectors; | ||
1551 | CURRENT->sector += nr_sectors; | ||
1552 | CURRENT->buffer += nr_sectors * 512; | ||
1553 | } else { | ||
1554 | azt_buf_out = -1; | ||
1555 | break; | ||
1556 | } | ||
1557 | } | ||
1558 | } | ||
1559 | |||
1560 | static void do_aztcd_request(request_queue_t * q) | ||
1561 | { | ||
1562 | #ifdef AZT_TEST | ||
1563 | printk(" do_aztcd_request(%ld+%ld) Time:%li\n", CURRENT->sector, | ||
1564 | CURRENT->nr_sectors, jiffies); | ||
1565 | #endif | ||
1566 | if (DiskInfo.audio) { | ||
1567 | printk("aztcd: Error, tried to mount an Audio CD\n"); | ||
1568 | end_request(CURRENT, 0); | ||
1569 | return; | ||
1570 | } | ||
1571 | azt_transfer_is_active = 1; | ||
1572 | while (current_valid()) { | ||
1573 | azt_transfer(); | ||
1574 | if (CURRENT->nr_sectors == 0) { | ||
1575 | end_request(CURRENT, 1); | ||
1576 | } else { | ||
1577 | azt_buf_out = -1; /* Want to read a block not in buffer */ | ||
1578 | if (azt_state == AZT_S_IDLE) { | ||
1579 | if ((!aztTocUpToDate) || aztDiskChanged) { | ||
1580 | if (aztUpdateToc() < 0) { | ||
1581 | while (current_valid()) | ||
1582 | end_request(CURRENT, 0); | ||
1583 | break; | ||
1584 | } | ||
1585 | } | ||
1586 | azt_state = AZT_S_START; | ||
1587 | AztTries = 5; | ||
1588 | SET_TIMER(azt_poll, HZ / 100); | ||
1589 | } | ||
1590 | break; | ||
1591 | } | ||
1592 | } | ||
1593 | azt_transfer_is_active = 0; | ||
1594 | #ifdef AZT_TEST2 | ||
1595 | printk | ||
1596 | ("azt_next_bn:%x azt_buf_in:%x azt_buf_out:%x azt_buf_bn:%x\n", | ||
1597 | azt_next_bn, azt_buf_in, azt_buf_out, azt_buf_bn[azt_buf_in]); | ||
1598 | printk(" do_aztcd_request ends Time:%li\n", jiffies); | ||
1599 | #endif | ||
1600 | } | ||
1601 | |||
1602 | |||
1603 | static void azt_invalidate_buffers(void) | ||
1604 | { | ||
1605 | int i; | ||
1606 | |||
1607 | #ifdef AZT_DEBUG | ||
1608 | printk("aztcd: executing azt_invalidate_buffers\n"); | ||
1609 | #endif | ||
1610 | for (i = 0; i < AZT_BUF_SIZ; ++i) | ||
1611 | azt_buf_bn[i] = -1; | ||
1612 | azt_buf_out = -1; | ||
1613 | } | ||
1614 | |||
1615 | /* | ||
1616 | * Open the device special file. Check that a disk is in. | ||
1617 | */ | ||
1618 | static int aztcd_open(struct inode *ip, struct file *fp) | ||
1619 | { | ||
1620 | int st; | ||
1621 | |||
1622 | #ifdef AZT_DEBUG | ||
1623 | printk("aztcd: starting aztcd_open\n"); | ||
1624 | #endif | ||
1625 | |||
1626 | if (aztPresent == 0) | ||
1627 | return -ENXIO; /* no hardware */ | ||
1628 | |||
1629 | if (!azt_open_count && azt_state == AZT_S_IDLE) { | ||
1630 | azt_invalidate_buffers(); | ||
1631 | |||
1632 | st = getAztStatus(); /* check drive status */ | ||
1633 | if (st == -1) | ||
1634 | goto err_out; /* drive doesn't respond */ | ||
1635 | |||
1636 | if (st & AST_DOOR_OPEN) { /* close door, then get the status again. */ | ||
1637 | printk("aztcd: Door Open?\n"); | ||
1638 | aztCloseDoor(); | ||
1639 | st = getAztStatus(); | ||
1640 | } | ||
1641 | |||
1642 | if ((st & AST_NOT_READY) || (st & AST_DSK_CHG)) { /*no disk in drive or changed */ | ||
1643 | printk | ||
1644 | ("aztcd: Disk Changed or No Disk in Drive?\n"); | ||
1645 | aztTocUpToDate = 0; | ||
1646 | } | ||
1647 | if (aztUpdateToc()) | ||
1648 | goto err_out; | ||
1649 | |||
1650 | } | ||
1651 | ++azt_open_count; | ||
1652 | aztLockDoor(); | ||
1653 | |||
1654 | #ifdef AZT_DEBUG | ||
1655 | printk("aztcd: exiting aztcd_open\n"); | ||
1656 | #endif | ||
1657 | return 0; | ||
1658 | |||
1659 | err_out: | ||
1660 | return -EIO; | ||
1661 | } | ||
1662 | |||
1663 | |||
1664 | /* | ||
1665 | * On close, we flush all azt blocks from the buffer cache. | ||
1666 | */ | ||
1667 | static int aztcd_release(struct inode *inode, struct file *file) | ||
1668 | { | ||
1669 | #ifdef AZT_DEBUG | ||
1670 | printk("aztcd: executing aztcd_release\n"); | ||
1671 | printk("inode: %p, device: %s file: %p\n", inode, | ||
1672 | inode->i_bdev->bd_disk->disk_name, file); | ||
1673 | #endif | ||
1674 | if (!--azt_open_count) { | ||
1675 | azt_invalidate_buffers(); | ||
1676 | aztUnlockDoor(); | ||
1677 | if (azt_auto_eject) | ||
1678 | aztSendCmd(ACMD_EJECT); | ||
1679 | CLEAR_TIMER; | ||
1680 | } | ||
1681 | return 0; | ||
1682 | } | ||
1683 | |||
1684 | static struct gendisk *azt_disk; | ||
1685 | |||
1686 | /* | ||
1687 | * Test for presence of drive and initialize it. Called at boot time. | ||
1688 | */ | ||
1689 | |||
1690 | static int __init aztcd_init(void) | ||
1691 | { | ||
1692 | long int count, max_count; | ||
1693 | unsigned char result[50]; | ||
1694 | int st; | ||
1695 | void* status = NULL; | ||
1696 | int i = 0; | ||
1697 | int ret = 0; | ||
1698 | |||
1699 | if (azt_port == 0) { | ||
1700 | printk(KERN_INFO "aztcd: no Aztech CD-ROM Initialization"); | ||
1701 | return -EIO; | ||
1702 | } | ||
1703 | |||
1704 | printk(KERN_INFO "aztcd: AZTECH, ORCHID, OKANO, WEARNES, TXC, CyDROM " | ||
1705 | "CD-ROM Driver\n"); | ||
1706 | printk(KERN_INFO "aztcd: (C) 1994-98 W.Zimmermann\n"); | ||
1707 | if (azt_port == -1) { | ||
1708 | printk | ||
1709 | ("aztcd: DriverVersion=%s For IDE/ATAPI-drives use ide-cd.c\n", | ||
1710 | AZT_VERSION); | ||
1711 | } else | ||
1712 | printk | ||
1713 | ("aztcd: DriverVersion=%s BaseAddress=0x%x For IDE/ATAPI-drives use ide-cd.c\n", | ||
1714 | AZT_VERSION, azt_port); | ||
1715 | printk(KERN_INFO "aztcd: If you have problems, read /usr/src/linux/" | ||
1716 | "Documentation/cdrom/aztcd\n"); | ||
1717 | |||
1718 | |||
1719 | #ifdef AZT_SW32 /*CDROM connected to Soundwave32 card */ | ||
1720 | if ((0xFF00 & inw(AZT_SW32_ID_REG)) != 0x4500) { | ||
1721 | printk | ||
1722 | ("aztcd: no Soundwave32 card detected at base:%x init:%x config:%x id:%x\n", | ||
1723 | AZT_SW32_BASE_ADDR, AZT_SW32_INIT, | ||
1724 | AZT_SW32_CONFIG_REG, AZT_SW32_ID_REG); | ||
1725 | return -EIO; | ||
1726 | } else { | ||
1727 | printk(KERN_INFO | ||
1728 | "aztcd: Soundwave32 card detected at %x Version %x\n", | ||
1729 | AZT_SW32_BASE_ADDR, inw(AZT_SW32_ID_REG)); | ||
1730 | outw(AZT_SW32_INIT, AZT_SW32_CONFIG_REG); | ||
1731 | for (count = 0; count < 10000; count++); /*delay a bit */ | ||
1732 | } | ||
1733 | #endif | ||
1734 | |||
1735 | /* check for presence of drive */ | ||
1736 | |||
1737 | if (azt_port == -1) { /* autoprobing for proprietary interface */ | ||
1738 | for (i = 0; (azt_port_auto[i] != 0) && (i < 16); i++) { | ||
1739 | azt_port = azt_port_auto[i]; | ||
1740 | printk(KERN_INFO "aztcd: Autoprobing BaseAddress=0x%x" | ||
1741 | "\n", azt_port); | ||
1742 | /*proprietary interfaces need 4 bytes */ | ||
1743 | if (!request_region(azt_port, 4, "aztcd")) { | ||
1744 | continue; | ||
1745 | } | ||
1746 | outb(POLLED, MODE_PORT); | ||
1747 | inb(CMD_PORT); | ||
1748 | inb(CMD_PORT); | ||
1749 | outb(ACMD_GET_VERSION, CMD_PORT); /*Try to get version info */ | ||
1750 | |||
1751 | aztTimeOutCount = 0; | ||
1752 | do { | ||
1753 | aztIndatum = inb(STATUS_PORT); | ||
1754 | aztTimeOutCount++; | ||
1755 | if (aztTimeOutCount >= AZT_FAST_TIMEOUT) | ||
1756 | break; | ||
1757 | } while (aztIndatum & AFL_STATUS); | ||
1758 | if (inb(DATA_PORT) == AFL_OP_OK) { /* OK drive found */ | ||
1759 | break; | ||
1760 | } | ||
1761 | else { /* Drive not found on this port - try next one */ | ||
1762 | release_region(azt_port, 4); | ||
1763 | } | ||
1764 | } | ||
1765 | if ((i == 16) || (azt_port_auto[i] == 0)) { | ||
1766 | printk(KERN_INFO "aztcd: no AZTECH CD-ROM drive found\n"); | ||
1767 | return -EIO; | ||
1768 | } | ||
1769 | } else { /* no autoprobing */ | ||
1770 | if ((azt_port == 0x1f0) || (azt_port == 0x170)) | ||
1771 | status = request_region(azt_port, 8, "aztcd"); /*IDE-interfaces need 8 bytes */ | ||
1772 | else | ||
1773 | status = request_region(azt_port, 4, "aztcd"); /*proprietary interfaces need 4 bytes */ | ||
1774 | if (!status) { | ||
1775 | printk(KERN_WARNING "aztcd: conflict, I/O port (%X) " | ||
1776 | "already used\n", azt_port); | ||
1777 | return -EIO; | ||
1778 | } | ||
1779 | |||
1780 | if ((azt_port == 0x1f0) || (azt_port == 0x170)) | ||
1781 | SWITCH_IDE_SLAVE; /*switch IDE interface to slave configuration */ | ||
1782 | |||
1783 | outb(POLLED, MODE_PORT); | ||
1784 | inb(CMD_PORT); | ||
1785 | inb(CMD_PORT); | ||
1786 | outb(ACMD_GET_VERSION, CMD_PORT); /*Try to get version info */ | ||
1787 | |||
1788 | aztTimeOutCount = 0; | ||
1789 | do { | ||
1790 | aztIndatum = inb(STATUS_PORT); | ||
1791 | aztTimeOutCount++; | ||
1792 | if (aztTimeOutCount >= AZT_FAST_TIMEOUT) | ||
1793 | break; | ||
1794 | } while (aztIndatum & AFL_STATUS); | ||
1795 | |||
1796 | if (inb(DATA_PORT) != AFL_OP_OK) { /*OP_OK? If not, reset and try again */ | ||
1797 | #ifndef MODULE | ||
1798 | if (azt_cont != 0x79) { | ||
1799 | printk(KERN_WARNING "aztcd: no AZTECH CD-ROM " | ||
1800 | "drive found-Try boot parameter aztcd=" | ||
1801 | "<BaseAddress>,0x79\n"); | ||
1802 | ret = -EIO; | ||
1803 | goto err_out; | ||
1804 | } | ||
1805 | #else | ||
1806 | if (0) { | ||
1807 | } | ||
1808 | #endif | ||
1809 | else { | ||
1810 | printk(KERN_INFO "aztcd: drive reset - " | ||
1811 | "please wait\n"); | ||
1812 | for (count = 0; count < 50; count++) { | ||
1813 | inb(STATUS_PORT); /*removing all data from earlier tries */ | ||
1814 | inb(DATA_PORT); | ||
1815 | } | ||
1816 | outb(POLLED, MODE_PORT); | ||
1817 | inb(CMD_PORT); | ||
1818 | inb(CMD_PORT); | ||
1819 | getAztStatus(); /*trap errors */ | ||
1820 | outb(ACMD_SOFT_RESET, CMD_PORT); /*send reset */ | ||
1821 | STEN_LOW; | ||
1822 | if (inb(DATA_PORT) != AFL_OP_OK) { /*OP_OK? */ | ||
1823 | printk(KERN_WARNING "aztcd: no AZTECH " | ||
1824 | "CD-ROM drive found\n"); | ||
1825 | ret = -EIO; | ||
1826 | goto err_out; | ||
1827 | } | ||
1828 | |||
1829 | for (count = 0; count < AZT_TIMEOUT; | ||
1830 | count++) | ||
1831 | barrier(); /* Stop gcc 2.96 being smart */ | ||
1832 | /* use udelay(), damnit -- AV */ | ||
1833 | |||
1834 | if ((st = getAztStatus()) == -1) { | ||
1835 | printk(KERN_WARNING "aztcd: Drive Status" | ||
1836 | " Error Status=%x\n", st); | ||
1837 | ret = -EIO; | ||
1838 | goto err_out; | ||
1839 | } | ||
1840 | #ifdef AZT_DEBUG | ||
1841 | printk(KERN_DEBUG "aztcd: Status = %x\n", st); | ||
1842 | #endif | ||
1843 | outb(POLLED, MODE_PORT); | ||
1844 | inb(CMD_PORT); | ||
1845 | inb(CMD_PORT); | ||
1846 | outb(ACMD_GET_VERSION, CMD_PORT); /*GetVersion */ | ||
1847 | STEN_LOW; | ||
1848 | OP_OK; | ||
1849 | } | ||
1850 | } | ||
1851 | } | ||
1852 | |||
1853 | azt_init_end = 1; | ||
1854 | STEN_LOW; | ||
1855 | result[0] = inb(DATA_PORT); /*reading in a null byte??? */ | ||
1856 | for (count = 1; count < 50; count++) { /*Reading version string */ | ||
1857 | aztTimeOutCount = 0; /*here we must implement STEN_LOW differently */ | ||
1858 | do { | ||
1859 | aztIndatum = inb(STATUS_PORT); /*because we want to exit by timeout */ | ||
1860 | aztTimeOutCount++; | ||
1861 | if (aztTimeOutCount >= AZT_FAST_TIMEOUT) | ||
1862 | break; | ||
1863 | } while (aztIndatum & AFL_STATUS); | ||
1864 | if (aztTimeOutCount >= AZT_FAST_TIMEOUT) | ||
1865 | break; /*all chars read? */ | ||
1866 | result[count] = inb(DATA_PORT); | ||
1867 | } | ||
1868 | if (count > 30) | ||
1869 | max_count = 30; /*print max.30 chars of the version string */ | ||
1870 | else | ||
1871 | max_count = count; | ||
1872 | printk(KERN_INFO "aztcd: FirmwareVersion="); | ||
1873 | for (count = 1; count < max_count; count++) | ||
1874 | printk("%c", result[count]); | ||
1875 | printk("<<>> "); | ||
1876 | |||
1877 | if ((result[1] == 'A') && (result[2] == 'Z') && (result[3] == 'T')) { | ||
1878 | printk("AZTECH drive detected\n"); | ||
1879 | /*AZTECH*/} | ||
1880 | else if ((result[2] == 'C') && (result[3] == 'D') | ||
1881 | && (result[4] == 'D')) { | ||
1882 | printk("ORCHID or WEARNES drive detected\n"); /*ORCHID or WEARNES */ | ||
1883 | } else if ((result[1] == 0x03) && (result[2] == '5')) { | ||
1884 | printk("TXC or CyCDROM drive detected\n"); /*Conrad TXC, CyCDROM */ | ||
1885 | } else { /*OTHERS or none */ | ||
1886 | printk("\nunknown drive or firmware version detected\n"); | ||
1887 | printk | ||
1888 | ("aztcd may not run stable, if you want to try anyhow,\n"); | ||
1889 | printk("boot with: aztcd=<BaseAddress>,0x79\n"); | ||
1890 | if ((azt_cont != 0x79)) { | ||
1891 | printk("aztcd: FirmwareVersion="); | ||
1892 | for (count = 1; count < 5; count++) | ||
1893 | printk("%c", result[count]); | ||
1894 | printk("<<>> "); | ||
1895 | printk("Aborted\n"); | ||
1896 | ret = -EIO; | ||
1897 | goto err_out; | ||
1898 | } | ||
1899 | } | ||
1900 | azt_disk = alloc_disk(1); | ||
1901 | if (!azt_disk) | ||
1902 | goto err_out; | ||
1903 | |||
1904 | if (register_blkdev(MAJOR_NR, "aztcd")) { | ||
1905 | ret = -EIO; | ||
1906 | goto err_out2; | ||
1907 | } | ||
1908 | |||
1909 | azt_queue = blk_init_queue(do_aztcd_request, &aztSpin); | ||
1910 | if (!azt_queue) { | ||
1911 | ret = -ENOMEM; | ||
1912 | goto err_out3; | ||
1913 | } | ||
1914 | |||
1915 | blk_queue_hardsect_size(azt_queue, 2048); | ||
1916 | azt_disk->major = MAJOR_NR; | ||
1917 | azt_disk->first_minor = 0; | ||
1918 | azt_disk->fops = &azt_fops; | ||
1919 | sprintf(azt_disk->disk_name, "aztcd"); | ||
1920 | azt_disk->queue = azt_queue; | ||
1921 | add_disk(azt_disk); | ||
1922 | azt_invalidate_buffers(); | ||
1923 | aztPresent = 1; | ||
1924 | aztCloseDoor(); | ||
1925 | return 0; | ||
1926 | err_out3: | ||
1927 | unregister_blkdev(MAJOR_NR, "aztcd"); | ||
1928 | err_out2: | ||
1929 | put_disk(azt_disk); | ||
1930 | err_out: | ||
1931 | if ((azt_port == 0x1f0) || (azt_port == 0x170)) { | ||
1932 | SWITCH_IDE_MASTER; | ||
1933 | release_region(azt_port, 8); /*IDE-interface */ | ||
1934 | } else | ||
1935 | release_region(azt_port, 4); /*proprietary interface */ | ||
1936 | return ret; | ||
1937 | |||
1938 | } | ||
1939 | |||
1940 | static void __exit aztcd_exit(void) | ||
1941 | { | ||
1942 | del_gendisk(azt_disk); | ||
1943 | put_disk(azt_disk); | ||
1944 | if ((unregister_blkdev(MAJOR_NR, "aztcd") == -EINVAL)) { | ||
1945 | printk("What's that: can't unregister aztcd\n"); | ||
1946 | return; | ||
1947 | } | ||
1948 | blk_cleanup_queue(azt_queue); | ||
1949 | if ((azt_port == 0x1f0) || (azt_port == 0x170)) { | ||
1950 | SWITCH_IDE_MASTER; | ||
1951 | release_region(azt_port, 8); /*IDE-interface */ | ||
1952 | } else | ||
1953 | release_region(azt_port, 4); /*proprietary interface */ | ||
1954 | printk(KERN_INFO "aztcd module released.\n"); | ||
1955 | } | ||
1956 | |||
1957 | module_init(aztcd_init); | ||
1958 | module_exit(aztcd_exit); | ||
1959 | |||
1960 | /*########################################################################## | ||
1961 | Aztcd State Machine: Controls Drive Operating State | ||
1962 | ########################################################################## | ||
1963 | */ | ||
1964 | static void azt_poll(void) | ||
1965 | { | ||
1966 | int st = 0; | ||
1967 | int loop_ctl = 1; | ||
1968 | int skip = 0; | ||
1969 | |||
1970 | if (azt_error) { | ||
1971 | if (aztSendCmd(ACMD_GET_ERROR)) | ||
1972 | RETURN("azt_poll 1"); | ||
1973 | STEN_LOW; | ||
1974 | azt_error = inb(DATA_PORT) & 0xFF; | ||
1975 | printk("aztcd: I/O error 0x%02x\n", azt_error); | ||
1976 | azt_invalidate_buffers(); | ||
1977 | #ifdef WARN_IF_READ_FAILURE | ||
1978 | if (AztTries == 5) | ||
1979 | printk | ||
1980 | ("aztcd: Read of Block %d Failed - Maybe Audio Disk?\n", | ||
1981 | azt_next_bn); | ||
1982 | #endif | ||
1983 | if (!AztTries--) { | ||
1984 | printk | ||
1985 | ("aztcd: Read of Block %d Failed, Maybe Audio Disk? Giving up\n", | ||
1986 | azt_next_bn); | ||
1987 | if (azt_transfer_is_active) { | ||
1988 | AztTries = 0; | ||
1989 | loop_ctl = 0; | ||
1990 | } | ||
1991 | if (current_valid()) | ||
1992 | end_request(CURRENT, 0); | ||
1993 | AztTries = 5; | ||
1994 | } | ||
1995 | azt_error = 0; | ||
1996 | azt_state = AZT_S_STOP; | ||
1997 | } | ||
1998 | |||
1999 | while (loop_ctl) { | ||
2000 | loop_ctl = 0; /* each case must flip this back to 1 if we want | ||
2001 | to come back up here */ | ||
2002 | switch (azt_state) { | ||
2003 | |||
2004 | case AZT_S_IDLE: | ||
2005 | #ifdef AZT_TEST3 | ||
2006 | if (azt_state != azt_state_old) { | ||
2007 | azt_state_old = azt_state; | ||
2008 | printk("AZT_S_IDLE\n"); | ||
2009 | } | ||
2010 | #endif | ||
2011 | return; | ||
2012 | |||
2013 | case AZT_S_START: | ||
2014 | #ifdef AZT_TEST3 | ||
2015 | if (azt_state != azt_state_old) { | ||
2016 | azt_state_old = azt_state; | ||
2017 | printk("AZT_S_START\n"); | ||
2018 | } | ||
2019 | #endif | ||
2020 | if (aztSendCmd(ACMD_GET_STATUS)) | ||
2021 | RETURN("azt_poll 2"); /*result will be checked by aztStatus() */ | ||
2022 | azt_state = | ||
2023 | azt_mode == 1 ? AZT_S_READ : AZT_S_MODE; | ||
2024 | AztTimeout = 3000; | ||
2025 | break; | ||
2026 | |||
2027 | case AZT_S_MODE: | ||
2028 | #ifdef AZT_TEST3 | ||
2029 | if (azt_state != azt_state_old) { | ||
2030 | azt_state_old = azt_state; | ||
2031 | printk("AZT_S_MODE\n"); | ||
2032 | } | ||
2033 | #endif | ||
2034 | if (!skip) { | ||
2035 | if ((st = aztStatus()) != -1) { | ||
2036 | if ((st & AST_DSK_CHG) | ||
2037 | || (st & AST_NOT_READY)) { | ||
2038 | aztDiskChanged = 1; | ||
2039 | aztTocUpToDate = 0; | ||
2040 | azt_invalidate_buffers(); | ||
2041 | end_request(CURRENT, 0); | ||
2042 | printk | ||
2043 | ("aztcd: Disk Changed or Not Ready 1 - Unmount Disk!\n"); | ||
2044 | } | ||
2045 | } else | ||
2046 | break; | ||
2047 | } | ||
2048 | skip = 0; | ||
2049 | |||
2050 | if ((st & AST_DOOR_OPEN) || (st & AST_NOT_READY)) { | ||
2051 | aztDiskChanged = 1; | ||
2052 | aztTocUpToDate = 0; | ||
2053 | printk | ||
2054 | ("aztcd: Disk Changed or Not Ready 2 - Unmount Disk!\n"); | ||
2055 | end_request(CURRENT, 0); | ||
2056 | printk((st & AST_DOOR_OPEN) ? | ||
2057 | "aztcd: door open\n" : | ||
2058 | "aztcd: disk removed\n"); | ||
2059 | if (azt_transfer_is_active) { | ||
2060 | azt_state = AZT_S_START; | ||
2061 | loop_ctl = 1; /* goto immediately */ | ||
2062 | break; | ||
2063 | } | ||
2064 | azt_state = AZT_S_IDLE; | ||
2065 | while (current_valid()) | ||
2066 | end_request(CURRENT, 0); | ||
2067 | return; | ||
2068 | } | ||
2069 | |||
2070 | /* if (aztSendCmd(ACMD_SET_MODE)) RETURN("azt_poll 3"); | ||
2071 | outb(0x01, DATA_PORT); | ||
2072 | PA_OK; | ||
2073 | STEN_LOW; | ||
2074 | */ | ||
2075 | if (aztSendCmd(ACMD_GET_STATUS)) | ||
2076 | RETURN("azt_poll 4"); | ||
2077 | STEN_LOW; | ||
2078 | azt_mode = 1; | ||
2079 | azt_state = AZT_S_READ; | ||
2080 | AztTimeout = 3000; | ||
2081 | |||
2082 | break; | ||
2083 | |||
2084 | |||
2085 | case AZT_S_READ: | ||
2086 | #ifdef AZT_TEST3 | ||
2087 | if (azt_state != azt_state_old) { | ||
2088 | azt_state_old = azt_state; | ||
2089 | printk("AZT_S_READ\n"); | ||
2090 | } | ||
2091 | #endif | ||
2092 | if (!skip) { | ||
2093 | if ((st = aztStatus()) != -1) { | ||
2094 | if ((st & AST_DSK_CHG) | ||
2095 | || (st & AST_NOT_READY)) { | ||
2096 | aztDiskChanged = 1; | ||
2097 | aztTocUpToDate = 0; | ||
2098 | azt_invalidate_buffers(); | ||
2099 | printk | ||
2100 | ("aztcd: Disk Changed or Not Ready 3 - Unmount Disk!\n"); | ||
2101 | end_request(CURRENT, 0); | ||
2102 | } | ||
2103 | } else | ||
2104 | break; | ||
2105 | } | ||
2106 | |||
2107 | skip = 0; | ||
2108 | if ((st & AST_DOOR_OPEN) || (st & AST_NOT_READY)) { | ||
2109 | aztDiskChanged = 1; | ||
2110 | aztTocUpToDate = 0; | ||
2111 | printk((st & AST_DOOR_OPEN) ? | ||
2112 | "aztcd: door open\n" : | ||
2113 | "aztcd: disk removed\n"); | ||
2114 | if (azt_transfer_is_active) { | ||
2115 | azt_state = AZT_S_START; | ||
2116 | loop_ctl = 1; | ||
2117 | break; | ||
2118 | } | ||
2119 | azt_state = AZT_S_IDLE; | ||
2120 | while (current_valid()) | ||
2121 | end_request(CURRENT, 0); | ||
2122 | return; | ||
2123 | } | ||
2124 | |||
2125 | if (current_valid()) { | ||
2126 | struct azt_Play_msf msf; | ||
2127 | int i; | ||
2128 | azt_next_bn = CURRENT->sector / 4; | ||
2129 | azt_hsg2msf(azt_next_bn, &msf.start); | ||
2130 | i = 0; | ||
2131 | /* find out in which track we are */ | ||
2132 | while (azt_msf2hsg(&msf.start) > | ||
2133 | azt_msf2hsg(&Toc[++i].trackTime)) { | ||
2134 | }; | ||
2135 | if (azt_msf2hsg(&msf.start) < | ||
2136 | azt_msf2hsg(&Toc[i].trackTime) - | ||
2137 | AZT_BUF_SIZ) { | ||
2138 | azt_read_count = AZT_BUF_SIZ; /*fast, because we read ahead */ | ||
2139 | /*azt_read_count=CURRENT->nr_sectors; slow, no read ahead */ | ||
2140 | } else /* don't read beyond end of track */ | ||
2141 | #if AZT_MULTISESSION | ||
2142 | { | ||
2143 | azt_read_count = | ||
2144 | (azt_msf2hsg(&Toc[i].trackTime) | ||
2145 | / 4) * 4 - | ||
2146 | azt_msf2hsg(&msf.start); | ||
2147 | if (azt_read_count < 0) | ||
2148 | azt_read_count = 0; | ||
2149 | if (azt_read_count > AZT_BUF_SIZ) | ||
2150 | azt_read_count = | ||
2151 | AZT_BUF_SIZ; | ||
2152 | printk | ||
2153 | ("aztcd: warning - trying to read beyond end of track\n"); | ||
2154 | /* printk("%i %i %li %li\n",i,azt_read_count,azt_msf2hsg(&msf.start),azt_msf2hsg(&Toc[i].trackTime)); | ||
2155 | */ } | ||
2156 | #else | ||
2157 | { | ||
2158 | azt_read_count = AZT_BUF_SIZ; | ||
2159 | } | ||
2160 | #endif | ||
2161 | msf.end.min = 0; | ||
2162 | msf.end.sec = 0; | ||
2163 | msf.end.frame = azt_read_count; /*Mitsumi here reads 0xffffff sectors */ | ||
2164 | #ifdef AZT_TEST3 | ||
2165 | printk | ||
2166 | ("---reading msf-address %x:%x:%x %x:%x:%x\n", | ||
2167 | msf.start.min, msf.start.sec, | ||
2168 | msf.start.frame, msf.end.min, | ||
2169 | msf.end.sec, msf.end.frame); | ||
2170 | printk | ||
2171 | ("azt_next_bn:%x azt_buf_in:%x azt_buf_out:%x azt_buf_bn:%x\n", | ||
2172 | azt_next_bn, azt_buf_in, azt_buf_out, | ||
2173 | azt_buf_bn[azt_buf_in]); | ||
2174 | #endif | ||
2175 | if (azt_read_mode == AZT_MODE_2) { | ||
2176 | sendAztCmd(ACMD_PLAY_READ_RAW, &msf); /*XA disks in raw mode */ | ||
2177 | } else { | ||
2178 | sendAztCmd(ACMD_PLAY_READ, &msf); /*others in cooked mode */ | ||
2179 | } | ||
2180 | azt_state = AZT_S_DATA; | ||
2181 | AztTimeout = READ_TIMEOUT; | ||
2182 | } else { | ||
2183 | azt_state = AZT_S_STOP; | ||
2184 | loop_ctl = 1; | ||
2185 | break; | ||
2186 | } | ||
2187 | |||
2188 | break; | ||
2189 | |||
2190 | |||
2191 | case AZT_S_DATA: | ||
2192 | #ifdef AZT_TEST3 | ||
2193 | if (azt_state != azt_state_old) { | ||
2194 | azt_state_old = azt_state; | ||
2195 | printk("AZT_S_DATA\n"); | ||
2196 | } | ||
2197 | #endif | ||
2198 | |||
2199 | st = inb(STATUS_PORT) & AFL_STATUSorDATA; | ||
2200 | |||
2201 | switch (st) { | ||
2202 | |||
2203 | case AFL_DATA: | ||
2204 | #ifdef AZT_TEST3 | ||
2205 | if (st != azt_st_old) { | ||
2206 | azt_st_old = st; | ||
2207 | printk("---AFL_DATA st:%x\n", st); | ||
2208 | } | ||
2209 | #endif | ||
2210 | if (!AztTries--) { | ||
2211 | printk | ||
2212 | ("aztcd: Read of Block %d Failed, Maybe Audio Disk ? Giving up\n", | ||
2213 | azt_next_bn); | ||
2214 | if (azt_transfer_is_active) { | ||
2215 | AztTries = 0; | ||
2216 | break; | ||
2217 | } | ||
2218 | if (current_valid()) | ||
2219 | end_request(CURRENT, 0); | ||
2220 | AztTries = 5; | ||
2221 | } | ||
2222 | azt_state = AZT_S_START; | ||
2223 | AztTimeout = READ_TIMEOUT; | ||
2224 | loop_ctl = 1; | ||
2225 | break; | ||
2226 | |||
2227 | case AFL_STATUSorDATA: | ||
2228 | #ifdef AZT_TEST3 | ||
2229 | if (st != azt_st_old) { | ||
2230 | azt_st_old = st; | ||
2231 | printk | ||
2232 | ("---AFL_STATUSorDATA st:%x\n", | ||
2233 | st); | ||
2234 | } | ||
2235 | #endif | ||
2236 | break; | ||
2237 | |||
2238 | default: | ||
2239 | #ifdef AZT_TEST3 | ||
2240 | if (st != azt_st_old) { | ||
2241 | azt_st_old = st; | ||
2242 | printk("---default: st:%x\n", st); | ||
2243 | } | ||
2244 | #endif | ||
2245 | AztTries = 5; | ||
2246 | if (!current_valid() && azt_buf_in == azt_buf_out) { | ||
2247 | azt_state = AZT_S_STOP; | ||
2248 | loop_ctl = 1; | ||
2249 | break; | ||
2250 | } | ||
2251 | if (azt_read_count <= 0) | ||
2252 | printk | ||
2253 | ("aztcd: warning - try to read 0 frames\n"); | ||
2254 | while (azt_read_count) { /*??? fast read ahead loop */ | ||
2255 | azt_buf_bn[azt_buf_in] = -1; | ||
2256 | DTEN_LOW; /*??? unsolved problem, very | ||
2257 | seldom we get timeouts | ||
2258 | here, don't now the real | ||
2259 | reason. With my drive this | ||
2260 | sometimes also happens with | ||
2261 | Aztech's original driver under | ||
2262 | DOS. Is it a hardware bug? | ||
2263 | I tried to recover from such | ||
2264 | situations here. Zimmermann */ | ||
2265 | if (aztTimeOutCount >= AZT_TIMEOUT) { | ||
2266 | printk | ||
2267 | ("read_count:%d CURRENT->nr_sectors:%ld azt_buf_in:%d\n", | ||
2268 | azt_read_count, | ||
2269 | CURRENT->nr_sectors, | ||
2270 | azt_buf_in); | ||
2271 | printk | ||
2272 | ("azt_transfer_is_active:%x\n", | ||
2273 | azt_transfer_is_active); | ||
2274 | azt_read_count = 0; | ||
2275 | azt_state = AZT_S_STOP; | ||
2276 | loop_ctl = 1; | ||
2277 | end_request(CURRENT, 1); /*should we have here (1) or (0)? */ | ||
2278 | } else { | ||
2279 | if (azt_read_mode == | ||
2280 | AZT_MODE_2) { | ||
2281 | insb(DATA_PORT, | ||
2282 | azt_buf + | ||
2283 | CD_FRAMESIZE_RAW | ||
2284 | * azt_buf_in, | ||
2285 | CD_FRAMESIZE_RAW); | ||
2286 | } else { | ||
2287 | insb(DATA_PORT, | ||
2288 | azt_buf + | ||
2289 | CD_FRAMESIZE * | ||
2290 | azt_buf_in, | ||
2291 | CD_FRAMESIZE); | ||
2292 | } | ||
2293 | azt_read_count--; | ||
2294 | #ifdef AZT_TEST3 | ||
2295 | printk | ||
2296 | ("AZT_S_DATA; ---I've read data- read_count: %d\n", | ||
2297 | azt_read_count); | ||
2298 | printk | ||
2299 | ("azt_next_bn:%d azt_buf_in:%d azt_buf_out:%d azt_buf_bn:%d\n", | ||
2300 | azt_next_bn, | ||
2301 | azt_buf_in, | ||
2302 | azt_buf_out, | ||
2303 | azt_buf_bn | ||
2304 | [azt_buf_in]); | ||
2305 | #endif | ||
2306 | azt_buf_bn[azt_buf_in] = | ||
2307 | azt_next_bn++; | ||
2308 | if (azt_buf_out == -1) | ||
2309 | azt_buf_out = | ||
2310 | azt_buf_in; | ||
2311 | azt_buf_in = | ||
2312 | azt_buf_in + 1 == | ||
2313 | AZT_BUF_SIZ ? 0 : | ||
2314 | azt_buf_in + 1; | ||
2315 | } | ||
2316 | } | ||
2317 | if (!azt_transfer_is_active) { | ||
2318 | while (current_valid()) { | ||
2319 | azt_transfer(); | ||
2320 | if (CURRENT->nr_sectors == | ||
2321 | 0) | ||
2322 | end_request(CURRENT, 1); | ||
2323 | else | ||
2324 | break; | ||
2325 | } | ||
2326 | } | ||
2327 | |||
2328 | if (current_valid() | ||
2329 | && (CURRENT->sector / 4 < azt_next_bn | ||
2330 | || CURRENT->sector / 4 > | ||
2331 | azt_next_bn + AZT_BUF_SIZ)) { | ||
2332 | azt_state = AZT_S_STOP; | ||
2333 | loop_ctl = 1; | ||
2334 | break; | ||
2335 | } | ||
2336 | AztTimeout = READ_TIMEOUT; | ||
2337 | if (azt_read_count == 0) { | ||
2338 | azt_state = AZT_S_STOP; | ||
2339 | loop_ctl = 1; | ||
2340 | break; | ||
2341 | } | ||
2342 | break; | ||
2343 | } | ||
2344 | break; | ||
2345 | |||
2346 | |||
2347 | case AZT_S_STOP: | ||
2348 | #ifdef AZT_TEST3 | ||
2349 | if (azt_state != azt_state_old) { | ||
2350 | azt_state_old = azt_state; | ||
2351 | printk("AZT_S_STOP\n"); | ||
2352 | } | ||
2353 | #endif | ||
2354 | if (azt_read_count != 0) | ||
2355 | printk("aztcd: discard data=%x frames\n", | ||
2356 | azt_read_count); | ||
2357 | while (azt_read_count != 0) { | ||
2358 | int i; | ||
2359 | if (!(inb(STATUS_PORT) & AFL_DATA)) { | ||
2360 | if (azt_read_mode == AZT_MODE_2) | ||
2361 | for (i = 0; | ||
2362 | i < CD_FRAMESIZE_RAW; | ||
2363 | i++) | ||
2364 | inb(DATA_PORT); | ||
2365 | else | ||
2366 | for (i = 0; | ||
2367 | i < CD_FRAMESIZE; i++) | ||
2368 | inb(DATA_PORT); | ||
2369 | } | ||
2370 | azt_read_count--; | ||
2371 | } | ||
2372 | if (aztSendCmd(ACMD_GET_STATUS)) | ||
2373 | RETURN("azt_poll 5"); | ||
2374 | azt_state = AZT_S_STOPPING; | ||
2375 | AztTimeout = 1000; | ||
2376 | break; | ||
2377 | |||
2378 | case AZT_S_STOPPING: | ||
2379 | #ifdef AZT_TEST3 | ||
2380 | if (azt_state != azt_state_old) { | ||
2381 | azt_state_old = azt_state; | ||
2382 | printk("AZT_S_STOPPING\n"); | ||
2383 | } | ||
2384 | #endif | ||
2385 | |||
2386 | if ((st = aztStatus()) == -1 && AztTimeout) | ||
2387 | break; | ||
2388 | |||
2389 | if ((st != -1) | ||
2390 | && ((st & AST_DSK_CHG) | ||
2391 | || (st & AST_NOT_READY))) { | ||
2392 | aztDiskChanged = 1; | ||
2393 | aztTocUpToDate = 0; | ||
2394 | azt_invalidate_buffers(); | ||
2395 | printk | ||
2396 | ("aztcd: Disk Changed or Not Ready 4 - Unmount Disk!\n"); | ||
2397 | end_request(CURRENT, 0); | ||
2398 | } | ||
2399 | |||
2400 | #ifdef AZT_TEST3 | ||
2401 | printk("CURRENT_VALID %d azt_mode %d\n", | ||
2402 | current_valid(), azt_mode); | ||
2403 | #endif | ||
2404 | |||
2405 | if (current_valid()) { | ||
2406 | if (st != -1) { | ||
2407 | if (azt_mode == 1) { | ||
2408 | azt_state = AZT_S_READ; | ||
2409 | loop_ctl = 1; | ||
2410 | skip = 1; | ||
2411 | break; | ||
2412 | } else { | ||
2413 | azt_state = AZT_S_MODE; | ||
2414 | loop_ctl = 1; | ||
2415 | skip = 1; | ||
2416 | break; | ||
2417 | } | ||
2418 | } else { | ||
2419 | azt_state = AZT_S_START; | ||
2420 | AztTimeout = 1; | ||
2421 | } | ||
2422 | } else { | ||
2423 | azt_state = AZT_S_IDLE; | ||
2424 | return; | ||
2425 | } | ||
2426 | break; | ||
2427 | |||
2428 | default: | ||
2429 | printk("aztcd: invalid state %d\n", azt_state); | ||
2430 | return; | ||
2431 | } /* case */ | ||
2432 | } /* while */ | ||
2433 | |||
2434 | |||
2435 | if (!AztTimeout--) { | ||
2436 | printk("aztcd: timeout in state %d\n", azt_state); | ||
2437 | azt_state = AZT_S_STOP; | ||
2438 | if (aztSendCmd(ACMD_STOP)) | ||
2439 | RETURN("azt_poll 6"); | ||
2440 | STEN_LOW_WAIT; | ||
2441 | }; | ||
2442 | |||
2443 | SET_TIMER(azt_poll, HZ / 100); | ||
2444 | } | ||
2445 | |||
2446 | |||
2447 | /*########################################################################### | ||
2448 | * Miscellaneous support functions | ||
2449 | ########################################################################### | ||
2450 | */ | ||
2451 | static void azt_hsg2msf(long hsg, struct msf *msf) | ||
2452 | { | ||
2453 | hsg += 150; | ||
2454 | msf->min = hsg / 4500; | ||
2455 | hsg %= 4500; | ||
2456 | msf->sec = hsg / 75; | ||
2457 | msf->frame = hsg % 75; | ||
2458 | #ifdef AZT_DEBUG | ||
2459 | if (msf->min >= 70) | ||
2460 | printk("aztcd: Error hsg2msf address Minutes\n"); | ||
2461 | if (msf->sec >= 60) | ||
2462 | printk("aztcd: Error hsg2msf address Seconds\n"); | ||
2463 | if (msf->frame >= 75) | ||
2464 | printk("aztcd: Error hsg2msf address Frames\n"); | ||
2465 | #endif | ||
2466 | azt_bin2bcd(&msf->min); /* convert to BCD */ | ||
2467 | azt_bin2bcd(&msf->sec); | ||
2468 | azt_bin2bcd(&msf->frame); | ||
2469 | } | ||
2470 | |||
2471 | static long azt_msf2hsg(struct msf *mp) | ||
2472 | { | ||
2473 | return azt_bcd2bin(mp->frame) + azt_bcd2bin(mp->sec) * 75 | ||
2474 | + azt_bcd2bin(mp->min) * 4500 - CD_MSF_OFFSET; | ||
2475 | } | ||
2476 | |||
2477 | static void azt_bin2bcd(unsigned char *p) | ||
2478 | { | ||
2479 | int u, t; | ||
2480 | |||
2481 | u = *p % 10; | ||
2482 | t = *p / 10; | ||
2483 | *p = u | (t << 4); | ||
2484 | } | ||
2485 | |||
2486 | static int azt_bcd2bin(unsigned char bcd) | ||
2487 | { | ||
2488 | return (bcd >> 4) * 10 + (bcd & 0xF); | ||
2489 | } | ||
2490 | |||
2491 | MODULE_LICENSE("GPL"); | ||
2492 | MODULE_ALIAS_BLOCKDEV_MAJOR(AZTECH_CDROM_MAJOR); | ||
diff --git a/drivers/cdrom/aztcd.h b/drivers/cdrom/aztcd.h deleted file mode 100644 index 057501e31628..000000000000 --- a/drivers/cdrom/aztcd.h +++ /dev/null | |||
@@ -1,162 +0,0 @@ | |||
1 | /* $Id: aztcd.h,v 2.60 1997/11/29 09:51:22 root Exp root $ | ||
2 | * | ||
3 | * Definitions for a AztechCD268 CD-ROM interface | ||
4 | * Copyright (C) 1994-98 Werner Zimmermann | ||
5 | * | ||
6 | * based on Mitsumi CDROM driver by Martin Harriss | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | * | ||
22 | * History: W.Zimmermann adaption to Aztech CD268-01A Version 1.3 | ||
23 | * October 1994 Email: Werner.Zimmermann@fht-esslingen.de | ||
24 | */ | ||
25 | |||
26 | /* *** change this to set the I/O port address of your CD-ROM drive, | ||
27 | set to '-1', if you want autoprobing */ | ||
28 | #define AZT_BASE_ADDR -1 | ||
29 | |||
30 | /* list of autoprobing addresses (not more than 15), last value must be 0x000 | ||
31 | Note: Autoprobing is only enabled, if AZT_BASE_ADDR is set to '-1' ! */ | ||
32 | #define AZT_BASE_AUTO { 0x320, 0x300, 0x310, 0x330, 0x000 } | ||
33 | |||
34 | /* Uncomment this, if your CDROM is connected to a Soundwave32-soundcard | ||
35 | and configure AZT_BASE_ADDR and AZT_SW32_BASE_ADDR */ | ||
36 | /*#define AZT_SW32 1 | ||
37 | */ | ||
38 | |||
39 | #ifdef AZT_SW32 | ||
40 | #define AZT_SW32_BASE_ADDR 0x220 /*I/O port base address of your soundcard*/ | ||
41 | #endif | ||
42 | |||
43 | /* Set this to 1, if you want your tray to be locked, set to 0 to prevent tray | ||
44 | from locking */ | ||
45 | #define AZT_ALLOW_TRAY_LOCK 1 | ||
46 | |||
47 | /*Set this to 1 to allow auto-eject when unmounting a disk, set to 0, if you | ||
48 | don't want the auto-eject feature*/ | ||
49 | #define AZT_AUTO_EJECT 0 | ||
50 | |||
51 | /*Set this to 1, if you want to use incompatible ioctls for reading in raw and | ||
52 | cooked mode */ | ||
53 | #define AZT_PRIVATE_IOCTLS 1 | ||
54 | |||
55 | /*Set this to 1, if you want multisession support by the ISO fs. Even if you set | ||
56 | this value to '0' you can use multisession CDs. In that case the drive's firm- | ||
57 | ware will do the appropriate redirection automatically. The CD will then look | ||
58 | like a single session CD (but nevertheless all data may be read). Please read | ||
59 | chapter '5.1 Multisession support' in README.aztcd for details. Normally it's | ||
60 | uncritical to leave this setting untouched */ | ||
61 | #define AZT_MULTISESSION 1 | ||
62 | |||
63 | /*Uncomment this, if you are using a linux kernel version prior to 2.1.0 */ | ||
64 | /*#define AZT_KERNEL_PRIOR_2_1 */ | ||
65 | |||
66 | /*---------------------------------------------------------------------------*/ | ||
67 | /*-----nothing to be configured for normal applications below this line------*/ | ||
68 | |||
69 | |||
70 | /* Increase this if you get lots of timeouts; if you get kernel panic, replace | ||
71 | STEN_LOW_WAIT by STEN_LOW in the source code */ | ||
72 | #define AZT_STATUS_DELAY 400 /*for timer wait, STEN_LOW_WAIT*/ | ||
73 | #define AZT_TIMEOUT 8000000 /*for busy wait STEN_LOW, DTEN_LOW*/ | ||
74 | #define AZT_FAST_TIMEOUT 10000 /*for reading the version string*/ | ||
75 | |||
76 | /* number of times to retry a command before giving up */ | ||
77 | #define AZT_RETRY_ATTEMPTS 3 | ||
78 | |||
79 | /* port access macros */ | ||
80 | #define CMD_PORT azt_port | ||
81 | #define DATA_PORT azt_port | ||
82 | #define STATUS_PORT azt_port+1 | ||
83 | #define MODE_PORT azt_port+2 | ||
84 | #ifdef AZT_SW32 | ||
85 | #define AZT_SW32_INIT (unsigned int) (0xFF00 & (AZT_BASE_ADDR*16)) | ||
86 | #define AZT_SW32_CONFIG_REG AZT_SW32_BASE_ADDR+0x16 /*Soundwave32 Config. Register*/ | ||
87 | #define AZT_SW32_ID_REG AZT_SW32_BASE_ADDR+0x04 /*Soundwave32 ID Version Register*/ | ||
88 | #endif | ||
89 | |||
90 | /* status bits */ | ||
91 | #define AST_CMD_CHECK 0x80 /* 1 = command error */ | ||
92 | #define AST_DOOR_OPEN 0x40 /* 1 = door is open */ | ||
93 | #define AST_NOT_READY 0x20 /* 1 = no disk in the drive */ | ||
94 | #define AST_DSK_CHG 0x02 /* 1 = disk removed or changed */ | ||
95 | #define AST_MODE 0x01 /* 0=MODE1, 1=MODE2 */ | ||
96 | #define AST_MODE_BITS 0x1C /* Mode Bits */ | ||
97 | #define AST_INITIAL 0x0C /* initial, only valid ... */ | ||
98 | #define AST_BUSY 0x04 /* now playing, only valid | ||
99 | in combination with mode | ||
100 | bits */ | ||
101 | /* flag bits */ | ||
102 | #define AFL_DATA 0x02 /* data available if low */ | ||
103 | #define AFL_STATUS 0x04 /* status available if low */ | ||
104 | #define AFL_OP_OK 0x01 /* OP_OK command correct*/ | ||
105 | #define AFL_PA_OK 0x02 /* PA_OK parameter correct*/ | ||
106 | #define AFL_OP_ERR 0x05 /* error in command*/ | ||
107 | #define AFL_PA_ERR 0x06 /* error in parameters*/ | ||
108 | #define POLLED 0x04 /* polled mode */ | ||
109 | |||
110 | /* commands */ | ||
111 | #define ACMD_SOFT_RESET 0x10 /* reset drive */ | ||
112 | #define ACMD_PLAY_READ 0x20 /* read data track in cooked mode */ | ||
113 | #define ACMD_PLAY_READ_RAW 0x21 /* reading in raw mode*/ | ||
114 | #define ACMD_SEEK 0x30 /* seek msf address*/ | ||
115 | #define ACMD_SEEK_TO_LEADIN 0x31 /* seek to leadin track*/ | ||
116 | #define ACMD_GET_ERROR 0x40 /* get error code */ | ||
117 | #define ACMD_GET_STATUS 0x41 /* get status */ | ||
118 | #define ACMD_GET_Q_CHANNEL 0x50 /* read info from q channel */ | ||
119 | #define ACMD_EJECT 0x60 /* eject/open tray */ | ||
120 | #define ACMD_CLOSE 0x61 /* close tray */ | ||
121 | #define ACMD_LOCK 0x71 /* lock tray closed */ | ||
122 | #define ACMD_UNLOCK 0x72 /* unlock tray */ | ||
123 | #define ACMD_PAUSE 0x80 /* pause */ | ||
124 | #define ACMD_STOP 0x81 /* stop play */ | ||
125 | #define ACMD_PLAY_AUDIO 0x90 /* play audio track */ | ||
126 | #define ACMD_SET_VOLUME 0x93 /* set audio level */ | ||
127 | #define ACMD_GET_VERSION 0xA0 /* get firmware version */ | ||
128 | #define ACMD_SET_DISK_TYPE 0xA1 /* set disk data mode */ | ||
129 | |||
130 | #define MAX_TRACKS 104 | ||
131 | |||
132 | struct msf { | ||
133 | unsigned char min; | ||
134 | unsigned char sec; | ||
135 | unsigned char frame; | ||
136 | }; | ||
137 | |||
138 | struct azt_Play_msf { | ||
139 | struct msf start; | ||
140 | struct msf end; | ||
141 | }; | ||
142 | |||
143 | struct azt_DiskInfo { | ||
144 | unsigned char first; | ||
145 | unsigned char next; | ||
146 | unsigned char last; | ||
147 | struct msf diskLength; | ||
148 | struct msf firstTrack; | ||
149 | unsigned char multi; | ||
150 | struct msf nextSession; | ||
151 | struct msf lastSession; | ||
152 | unsigned char xa; | ||
153 | unsigned char audio; | ||
154 | }; | ||
155 | |||
156 | struct azt_Toc { | ||
157 | unsigned char ctrl_addr; | ||
158 | unsigned char track; | ||
159 | unsigned char pointIndex; | ||
160 | struct msf trackTime; | ||
161 | struct msf diskTime; | ||
162 | }; | ||
diff --git a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c deleted file mode 100644 index 2157c58755e0..000000000000 --- a/drivers/cdrom/cdu31a.c +++ /dev/null | |||
@@ -1,3251 +0,0 @@ | |||
1 | /* | ||
2 | * Sony CDU-31A CDROM interface device driver. | ||
3 | * | ||
4 | * Corey Minyard (minyard@wf-rch.cirr.com) | ||
5 | * | ||
6 | * Colossians 3:17 | ||
7 | * | ||
8 | * See Documentation/cdrom/cdu31a for additional details about this driver. | ||
9 | * | ||
10 | * The Sony interface device driver handles Sony interface CDROM | ||
11 | * drives and provides a complete block-level interface as well as an | ||
12 | * ioctl() interface compatible with the Sun (as specified in | ||
13 | * include/linux/cdrom.h). With this interface, CDROMs can be | ||
14 | * accessed and standard audio CDs can be played back normally. | ||
15 | * | ||
16 | * WARNING - All autoprobes have been removed from the driver. | ||
17 | * You MUST configure the CDU31A via a LILO config | ||
18 | * at boot time or in lilo.conf. I have the | ||
19 | * following in my lilo.conf: | ||
20 | * | ||
21 | * append="cdu31a=0x1f88,0,PAS" | ||
22 | * | ||
23 | * The first number is the I/O base address of the | ||
24 | * card. The second is the interrupt (0 means none). | ||
25 | * The third should be "PAS" if on a Pro-Audio | ||
26 | * spectrum, or nothing if on something else. | ||
27 | * | ||
28 | * This interface is (unfortunately) a polled interface. This is | ||
29 | * because most Sony interfaces are set up with DMA and interrupts | ||
30 | * disables. Some (like mine) do not even have the capability to | ||
31 | * handle interrupts or DMA. For this reason you will see a lot of | ||
32 | * the following: | ||
33 | * | ||
34 | * retry_count = jiffies+ SONY_JIFFIES_TIMEOUT; | ||
35 | * while (time_before(jiffies, retry_count) && (! <some condition to wait for)) | ||
36 | * { | ||
37 | * while (handle_sony_cd_attention()) | ||
38 | * ; | ||
39 | * | ||
40 | * sony_sleep(); | ||
41 | * } | ||
42 | * if (the condition not met) | ||
43 | * { | ||
44 | * return an error; | ||
45 | * } | ||
46 | * | ||
47 | * This ugly hack waits for something to happen, sleeping a little | ||
48 | * between every try. it also handles attentions, which are | ||
49 | * asynchronous events from the drive informing the driver that a disk | ||
50 | * has been inserted, removed, etc. | ||
51 | * | ||
52 | * NEWS FLASH - The driver now supports interrupts but they are | ||
53 | * turned off by default. Use of interrupts is highly encouraged, it | ||
54 | * cuts CPU usage down to a reasonable level. I had DMA in for a while | ||
55 | * but PC DMA is just too slow. Better to just insb() it. | ||
56 | * | ||
57 | * One thing about these drives: They talk in MSF (Minute Second Frame) format. | ||
58 | * There are 75 frames a second, 60 seconds a minute, and up to 75 minutes on a | ||
59 | * disk. The funny thing is that these are sent to the drive in BCD, but the | ||
60 | * interface wants to see them in decimal. A lot of conversion goes on. | ||
61 | * | ||
62 | * DRIVER SPECIAL FEATURES | ||
63 | * ----------------------- | ||
64 | * | ||
65 | * This section describes features beyond the normal audio and CD-ROM | ||
66 | * functions of the drive. | ||
67 | * | ||
68 | * XA compatibility | ||
69 | * | ||
70 | * The driver should support XA disks for both the CDU31A and CDU33A. | ||
71 | * It does this transparently, the using program doesn't need to set it. | ||
72 | * | ||
73 | * Multi-Session | ||
74 | * | ||
75 | * A multi-session disk looks just like a normal disk to the user. | ||
76 | * Just mount one normally, and all the data should be there. | ||
77 | * A special thanks to Koen for help with this! | ||
78 | * | ||
79 | * Raw sector I/O | ||
80 | * | ||
81 | * Using the CDROMREADAUDIO it is possible to read raw audio and data | ||
82 | * tracks. Both operations return 2352 bytes per sector. On the data | ||
83 | * tracks, the first 12 bytes is not returned by the drive and the value | ||
84 | * of that data is indeterminate. | ||
85 | * | ||
86 | * | ||
87 | * Copyright (C) 1993 Corey Minyard | ||
88 | * | ||
89 | * This program is free software; you can redistribute it and/or modify | ||
90 | * it under the terms of the GNU General Public License as published by | ||
91 | * the Free Software Foundation; either version 2 of the License, or | ||
92 | * (at your option) any later version. | ||
93 | * | ||
94 | * This program is distributed in the hope that it will be useful, | ||
95 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
96 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
97 | * GNU General Public License for more details. | ||
98 | * | ||
99 | * You should have received a copy of the GNU General Public License | ||
100 | * along with this program; if not, write to the Free Software | ||
101 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
102 | * | ||
103 | * TODO: | ||
104 | * CDs with form1 and form2 sectors cause problems | ||
105 | * with current read-ahead strategy. | ||
106 | * | ||
107 | * Credits: | ||
108 | * Heiko Eissfeldt <heiko@colossus.escape.de> | ||
109 | * For finding abug in the return of the track numbers. | ||
110 | * TOC processing redone for proper multisession support. | ||
111 | * | ||
112 | * | ||
113 | * It probably a little late to be adding a history, but I guess I | ||
114 | * will start. | ||
115 | * | ||
116 | * 10/24/95 - Added support for disabling the eject button when the | ||
117 | * drive is open. Note that there is a small problem | ||
118 | * still here, if the eject button is pushed while the | ||
119 | * drive light is flashing, the drive will return a bad | ||
120 | * status and be reset. It recovers, though. | ||
121 | * | ||
122 | * 03/07/97 - Fixed a problem with timers. | ||
123 | * | ||
124 | * | ||
125 | * 18 Spetember 1997 -- Ported to Uniform CD-ROM driver by | ||
126 | * Heiko Eissfeldt <heiko@colossus.escape.de> with additional | ||
127 | * changes by Erik Andersen <andersee@debian.org> | ||
128 | * | ||
129 | * 24 January 1998 -- Removed the scd_disc_status() function, which was now | ||
130 | * just dead code left over from the port. | ||
131 | * Erik Andersen <andersee@debian.org> | ||
132 | * | ||
133 | * 16 July 1998 -- Drive donated to Erik Andersen by John Kodis | ||
134 | * <kodis@jagunet.com>. Work begun on fixing driver to | ||
135 | * work under 2.1.X. Added temporary extra printks | ||
136 | * which seem to slow it down enough to work. | ||
137 | * | ||
138 | * 9 November 1999 -- Make kernel-parameter implementation work with 2.3.x | ||
139 | * Removed init_module & cleanup_module in favor of | ||
140 | * module_init & module_exit. | ||
141 | * Torben Mathiasen <tmm@image.dk> | ||
142 | * | ||
143 | * 22 October 2004 -- Make the driver work in 2.6.X | ||
144 | * Added workaround to fix hard lockups on eject | ||
145 | * Fixed door locking problem after mounting empty drive | ||
146 | * Set double-speed drives to double speed by default | ||
147 | * Removed all readahead things - not needed anymore | ||
148 | * Ondrej Zary <rainbow@rainbow-software.org> | ||
149 | */ | ||
150 | |||
151 | #define DEBUG 1 | ||
152 | |||
153 | #include <linux/major.h> | ||
154 | #include <linux/module.h> | ||
155 | #include <linux/errno.h> | ||
156 | #include <linux/signal.h> | ||
157 | #include <linux/sched.h> | ||
158 | #include <linux/timer.h> | ||
159 | #include <linux/fs.h> | ||
160 | #include <linux/kernel.h> | ||
161 | #include <linux/hdreg.h> | ||
162 | #include <linux/genhd.h> | ||
163 | #include <linux/ioport.h> | ||
164 | #include <linux/string.h> | ||
165 | #include <linux/slab.h> | ||
166 | #include <linux/init.h> | ||
167 | #include <linux/interrupt.h> | ||
168 | #include <linux/cdrom.h> | ||
169 | |||
170 | #include <asm/system.h> | ||
171 | #include <asm/io.h> | ||
172 | #include <asm/uaccess.h> | ||
173 | #include <asm/dma.h> | ||
174 | |||
175 | #include "cdu31a.h" | ||
176 | |||
177 | #define MAJOR_NR CDU31A_CDROM_MAJOR | ||
178 | #include <linux/blkdev.h> | ||
179 | |||
180 | #define CDU31A_MAX_CONSECUTIVE_ATTENTIONS 10 | ||
181 | |||
182 | #define PFX "CDU31A: " | ||
183 | |||
184 | /* | ||
185 | ** Edit the following data to change interrupts, DMA channels, etc. | ||
186 | ** Default is polled and no DMA. DMA is not recommended for double-speed | ||
187 | ** drives. | ||
188 | */ | ||
189 | static struct { | ||
190 | unsigned short base; /* I/O Base Address */ | ||
191 | short int_num; /* Interrupt Number (-1 means scan for it, | ||
192 | 0 means don't use) */ | ||
193 | } cdu31a_addresses[] __initdata = { | ||
194 | {0} | ||
195 | }; | ||
196 | |||
197 | static int handle_sony_cd_attention(void); | ||
198 | static int read_subcode(void); | ||
199 | static void sony_get_toc(void); | ||
200 | static int scd_spinup(void); | ||
201 | /*static int scd_open(struct inode *inode, struct file *filp);*/ | ||
202 | static int scd_open(struct cdrom_device_info *, int); | ||
203 | static void do_sony_cd_cmd(unsigned char cmd, | ||
204 | unsigned char *params, | ||
205 | unsigned int num_params, | ||
206 | unsigned char *result_buffer, | ||
207 | unsigned int *result_size); | ||
208 | static void size_to_buf(unsigned int size, unsigned char *buf); | ||
209 | |||
210 | /* Parameters for the read-ahead. */ | ||
211 | static unsigned int sony_next_block; /* Next 512 byte block offset */ | ||
212 | static unsigned int sony_blocks_left = 0; /* Number of 512 byte blocks left | ||
213 | in the current read command. */ | ||
214 | |||
215 | |||
216 | /* The base I/O address of the Sony Interface. This is a variable (not a | ||
217 | #define) so it can be easily changed via some future ioctl() */ | ||
218 | static unsigned int cdu31a_port = 0; | ||
219 | module_param(cdu31a_port, uint, 0); | ||
220 | |||
221 | /* | ||
222 | * The following are I/O addresses of the various registers for the drive. The | ||
223 | * comment for the base address also applies here. | ||
224 | */ | ||
225 | static volatile unsigned short sony_cd_cmd_reg; | ||
226 | static volatile unsigned short sony_cd_param_reg; | ||
227 | static volatile unsigned short sony_cd_write_reg; | ||
228 | static volatile unsigned short sony_cd_control_reg; | ||
229 | static volatile unsigned short sony_cd_status_reg; | ||
230 | static volatile unsigned short sony_cd_result_reg; | ||
231 | static volatile unsigned short sony_cd_read_reg; | ||
232 | static volatile unsigned short sony_cd_fifost_reg; | ||
233 | |||
234 | static struct request_queue *cdu31a_queue; | ||
235 | static DEFINE_SPINLOCK(cdu31a_lock); /* queue lock */ | ||
236 | |||
237 | static int sony_spun_up = 0; /* Has the drive been spun up? */ | ||
238 | |||
239 | static int sony_speed = 0; /* Last wanted speed */ | ||
240 | |||
241 | static int sony_xa_mode = 0; /* Is an XA disk in the drive | ||
242 | and the drive a CDU31A? */ | ||
243 | |||
244 | static int sony_raw_data_mode = 1; /* 1 if data tracks, 0 if audio. | ||
245 | For raw data reads. */ | ||
246 | |||
247 | static unsigned int sony_usage = 0; /* How many processes have the | ||
248 | drive open. */ | ||
249 | |||
250 | static int sony_pas_init = 0; /* Initialize the Pro-Audio | ||
251 | Spectrum card? */ | ||
252 | |||
253 | static struct s_sony_session_toc single_toc; /* Holds the | ||
254 | table of | ||
255 | contents. */ | ||
256 | |||
257 | static struct s_all_sessions_toc sony_toc; /* entries gathered from all | ||
258 | sessions */ | ||
259 | |||
260 | static int sony_toc_read = 0; /* Has the TOC been read for | ||
261 | the drive? */ | ||
262 | |||
263 | static struct s_sony_subcode last_sony_subcode; /* Points to the last | ||
264 | subcode address read */ | ||
265 | |||
266 | static DECLARE_MUTEX(sony_sem); /* Semaphore for drive hardware access */ | ||
267 | |||
268 | static int is_double_speed = 0; /* does the drive support double speed ? */ | ||
269 | |||
270 | static int is_auto_eject = 1; /* Door has been locked? 1=No/0=Yes */ | ||
271 | |||
272 | /* | ||
273 | * The audio status uses the values from read subchannel data as specified | ||
274 | * in include/linux/cdrom.h. | ||
275 | */ | ||
276 | static volatile int sony_audio_status = CDROM_AUDIO_NO_STATUS; | ||
277 | |||
278 | /* | ||
279 | * The following are a hack for pausing and resuming audio play. The drive | ||
280 | * does not work as I would expect it, if you stop it then start it again, | ||
281 | * the drive seeks back to the beginning and starts over. This holds the | ||
282 | * position during a pause so a resume can restart it. It uses the | ||
283 | * audio status variable above to tell if it is paused. | ||
284 | */ | ||
285 | static unsigned volatile char cur_pos_msf[3] = { 0, 0, 0 }; | ||
286 | static unsigned volatile char final_pos_msf[3] = { 0, 0, 0 }; | ||
287 | |||
288 | /* What IRQ is the drive using? 0 if none. */ | ||
289 | static int cdu31a_irq = 0; | ||
290 | module_param(cdu31a_irq, int, 0); | ||
291 | |||
292 | /* The interrupt handler will wake this queue up when it gets an | ||
293 | interrupts. */ | ||
294 | static DECLARE_WAIT_QUEUE_HEAD(cdu31a_irq_wait); | ||
295 | static int irq_flag = 0; | ||
296 | |||
297 | static int curr_control_reg = 0; /* Current value of the control register */ | ||
298 | |||
299 | /* A disk changed variable. When a disk change is detected, it will | ||
300 | all be set to TRUE. As the upper layers ask for disk_changed status | ||
301 | it will be cleared. */ | ||
302 | static char disk_changed; | ||
303 | |||
304 | /* This was readahead_buffer once... Now it's used only for audio reads */ | ||
305 | static char audio_buffer[CD_FRAMESIZE_RAW]; | ||
306 | |||
307 | /* Used to time a short period to abort an operation after the | ||
308 | drive has been idle for a while. This keeps the light on | ||
309 | the drive from flashing for very long. */ | ||
310 | static struct timer_list cdu31a_abort_timer; | ||
311 | |||
312 | /* Marks if the timeout has started an abort read. This is used | ||
313 | on entry to the drive to tell the code to read out the status | ||
314 | from the abort read. */ | ||
315 | static int abort_read_started = 0; | ||
316 | |||
317 | /* | ||
318 | * Uniform cdrom interface function | ||
319 | * report back, if disc has changed from time of last request. | ||
320 | */ | ||
321 | static int scd_media_changed(struct cdrom_device_info *cdi, int disc_nr) | ||
322 | { | ||
323 | int retval; | ||
324 | |||
325 | retval = disk_changed; | ||
326 | disk_changed = 0; | ||
327 | |||
328 | return retval; | ||
329 | } | ||
330 | |||
331 | /* | ||
332 | * Uniform cdrom interface function | ||
333 | * report back, if drive is ready | ||
334 | */ | ||
335 | static int scd_drive_status(struct cdrom_device_info *cdi, int slot_nr) | ||
336 | { | ||
337 | if (CDSL_CURRENT != slot_nr) | ||
338 | /* we have no changer support */ | ||
339 | return -EINVAL; | ||
340 | if (sony_spun_up) | ||
341 | return CDS_DISC_OK; | ||
342 | if (down_interruptible(&sony_sem)) | ||
343 | return -ERESTARTSYS; | ||
344 | if (scd_spinup() == 0) | ||
345 | sony_spun_up = 1; | ||
346 | up(&sony_sem); | ||
347 | return sony_spun_up ? CDS_DISC_OK : CDS_DRIVE_NOT_READY; | ||
348 | } | ||
349 | |||
350 | static inline void enable_interrupts(void) | ||
351 | { | ||
352 | curr_control_reg |= (SONY_ATTN_INT_EN_BIT | ||
353 | | SONY_RES_RDY_INT_EN_BIT | ||
354 | | SONY_DATA_RDY_INT_EN_BIT); | ||
355 | outb(curr_control_reg, sony_cd_control_reg); | ||
356 | } | ||
357 | |||
358 | static inline void disable_interrupts(void) | ||
359 | { | ||
360 | curr_control_reg &= ~(SONY_ATTN_INT_EN_BIT | ||
361 | | SONY_RES_RDY_INT_EN_BIT | ||
362 | | SONY_DATA_RDY_INT_EN_BIT); | ||
363 | outb(curr_control_reg, sony_cd_control_reg); | ||
364 | } | ||
365 | |||
366 | /* | ||
367 | * Wait a little while (used for polling the drive). If in initialization, | ||
368 | * setting a timeout doesn't work, so just loop for a while. | ||
369 | */ | ||
370 | static inline void sony_sleep(void) | ||
371 | { | ||
372 | if (cdu31a_irq <= 0) { | ||
373 | yield(); | ||
374 | } else { /* Interrupt driven */ | ||
375 | DEFINE_WAIT(w); | ||
376 | int first = 1; | ||
377 | |||
378 | while (1) { | ||
379 | prepare_to_wait(&cdu31a_irq_wait, &w, | ||
380 | TASK_INTERRUPTIBLE); | ||
381 | if (first) { | ||
382 | enable_interrupts(); | ||
383 | first = 0; | ||
384 | } | ||
385 | |||
386 | if (irq_flag != 0) | ||
387 | break; | ||
388 | if (!signal_pending(current)) { | ||
389 | schedule(); | ||
390 | continue; | ||
391 | } else | ||
392 | disable_interrupts(); | ||
393 | break; | ||
394 | } | ||
395 | finish_wait(&cdu31a_irq_wait, &w); | ||
396 | irq_flag = 0; | ||
397 | } | ||
398 | } | ||
399 | |||
400 | |||
401 | /* | ||
402 | * The following are convenience routine to read various status and set | ||
403 | * various conditions in the drive. | ||
404 | */ | ||
405 | static inline int is_attention(void) | ||
406 | { | ||
407 | return (inb(sony_cd_status_reg) & SONY_ATTN_BIT) != 0; | ||
408 | } | ||
409 | |||
410 | static inline int is_busy(void) | ||
411 | { | ||
412 | return (inb(sony_cd_status_reg) & SONY_BUSY_BIT) != 0; | ||
413 | } | ||
414 | |||
415 | static inline int is_data_ready(void) | ||
416 | { | ||
417 | return (inb(sony_cd_status_reg) & SONY_DATA_RDY_BIT) != 0; | ||
418 | } | ||
419 | |||
420 | static inline int is_data_requested(void) | ||
421 | { | ||
422 | return (inb(sony_cd_status_reg) & SONY_DATA_REQUEST_BIT) != 0; | ||
423 | } | ||
424 | |||
425 | static inline int is_result_ready(void) | ||
426 | { | ||
427 | return (inb(sony_cd_status_reg) & SONY_RES_RDY_BIT) != 0; | ||
428 | } | ||
429 | |||
430 | static inline int is_param_write_rdy(void) | ||
431 | { | ||
432 | return (inb(sony_cd_fifost_reg) & SONY_PARAM_WRITE_RDY_BIT) != 0; | ||
433 | } | ||
434 | |||
435 | static inline int is_result_reg_not_empty(void) | ||
436 | { | ||
437 | return (inb(sony_cd_fifost_reg) & SONY_RES_REG_NOT_EMP_BIT) != 0; | ||
438 | } | ||
439 | |||
440 | static inline void reset_drive(void) | ||
441 | { | ||
442 | curr_control_reg = 0; | ||
443 | sony_toc_read = 0; | ||
444 | outb(SONY_DRIVE_RESET_BIT, sony_cd_control_reg); | ||
445 | } | ||
446 | |||
447 | /* | ||
448 | * Uniform cdrom interface function | ||
449 | * reset drive and return when it is ready | ||
450 | */ | ||
451 | static int scd_reset(struct cdrom_device_info *cdi) | ||
452 | { | ||
453 | unsigned long retry_count; | ||
454 | |||
455 | if (down_interruptible(&sony_sem)) | ||
456 | return -ERESTARTSYS; | ||
457 | reset_drive(); | ||
458 | |||
459 | retry_count = jiffies + SONY_RESET_TIMEOUT; | ||
460 | while (time_before(jiffies, retry_count) && (!is_attention())) { | ||
461 | sony_sleep(); | ||
462 | } | ||
463 | |||
464 | up(&sony_sem); | ||
465 | return 0; | ||
466 | } | ||
467 | |||
468 | static inline void clear_attention(void) | ||
469 | { | ||
470 | outb(curr_control_reg | SONY_ATTN_CLR_BIT, sony_cd_control_reg); | ||
471 | } | ||
472 | |||
473 | static inline void clear_result_ready(void) | ||
474 | { | ||
475 | outb(curr_control_reg | SONY_RES_RDY_CLR_BIT, sony_cd_control_reg); | ||
476 | } | ||
477 | |||
478 | static inline void clear_data_ready(void) | ||
479 | { | ||
480 | outb(curr_control_reg | SONY_DATA_RDY_CLR_BIT, | ||
481 | sony_cd_control_reg); | ||
482 | } | ||
483 | |||
484 | static inline void clear_param_reg(void) | ||
485 | { | ||
486 | outb(curr_control_reg | SONY_PARAM_CLR_BIT, sony_cd_control_reg); | ||
487 | } | ||
488 | |||
489 | static inline unsigned char read_status_register(void) | ||
490 | { | ||
491 | return inb(sony_cd_status_reg); | ||
492 | } | ||
493 | |||
494 | static inline unsigned char read_result_register(void) | ||
495 | { | ||
496 | return inb(sony_cd_result_reg); | ||
497 | } | ||
498 | |||
499 | static inline unsigned char read_data_register(void) | ||
500 | { | ||
501 | return inb(sony_cd_read_reg); | ||
502 | } | ||
503 | |||
504 | static inline void write_param(unsigned char param) | ||
505 | { | ||
506 | outb(param, sony_cd_param_reg); | ||
507 | } | ||
508 | |||
509 | static inline void write_cmd(unsigned char cmd) | ||
510 | { | ||
511 | outb(curr_control_reg | SONY_RES_RDY_INT_EN_BIT, | ||
512 | sony_cd_control_reg); | ||
513 | outb(cmd, sony_cd_cmd_reg); | ||
514 | } | ||
515 | |||
516 | static irqreturn_t cdu31a_interrupt(int irq, void *dev_id) | ||
517 | { | ||
518 | unsigned char val; | ||
519 | |||
520 | if (abort_read_started) { | ||
521 | /* We might be waiting for an abort to finish. Don't | ||
522 | disable interrupts yet, though, because we handle | ||
523 | this one here. */ | ||
524 | /* Clear out the result registers. */ | ||
525 | while (is_result_reg_not_empty()) { | ||
526 | val = read_result_register(); | ||
527 | } | ||
528 | clear_data_ready(); | ||
529 | clear_result_ready(); | ||
530 | |||
531 | /* Clear out the data */ | ||
532 | while (is_data_requested()) { | ||
533 | val = read_data_register(); | ||
534 | } | ||
535 | abort_read_started = 0; | ||
536 | |||
537 | /* If something was waiting, wake it up now. */ | ||
538 | if (waitqueue_active(&cdu31a_irq_wait)) { | ||
539 | disable_interrupts(); | ||
540 | irq_flag = 1; | ||
541 | wake_up_interruptible(&cdu31a_irq_wait); | ||
542 | } | ||
543 | } else if (waitqueue_active(&cdu31a_irq_wait)) { | ||
544 | disable_interrupts(); | ||
545 | irq_flag = 1; | ||
546 | wake_up_interruptible(&cdu31a_irq_wait); | ||
547 | } else { | ||
548 | disable_interrupts(); | ||
549 | printk(KERN_NOTICE PFX | ||
550 | "Got an interrupt but nothing was waiting\n"); | ||
551 | } | ||
552 | return IRQ_HANDLED; | ||
553 | } | ||
554 | |||
555 | /* | ||
556 | * give more verbose error messages | ||
557 | */ | ||
558 | static unsigned char *translate_error(unsigned char err_code) | ||
559 | { | ||
560 | static unsigned char errbuf[80]; | ||
561 | |||
562 | switch (err_code) { | ||
563 | case 0x10: return "illegal command "; | ||
564 | case 0x11: return "illegal parameter "; | ||
565 | |||
566 | case 0x20: return "not loaded "; | ||
567 | case 0x21: return "no disc "; | ||
568 | case 0x22: return "not spinning "; | ||
569 | case 0x23: return "spinning "; | ||
570 | case 0x25: return "spindle servo "; | ||
571 | case 0x26: return "focus servo "; | ||
572 | case 0x29: return "eject mechanism "; | ||
573 | case 0x2a: return "audio playing "; | ||
574 | case 0x2c: return "emergency eject "; | ||
575 | |||
576 | case 0x30: return "focus "; | ||
577 | case 0x31: return "frame sync "; | ||
578 | case 0x32: return "subcode address "; | ||
579 | case 0x33: return "block sync "; | ||
580 | case 0x34: return "header address "; | ||
581 | |||
582 | case 0x40: return "illegal track read "; | ||
583 | case 0x41: return "mode 0 read "; | ||
584 | case 0x42: return "illegal mode read "; | ||
585 | case 0x43: return "illegal block size read "; | ||
586 | case 0x44: return "mode read "; | ||
587 | case 0x45: return "form read "; | ||
588 | case 0x46: return "leadout read "; | ||
589 | case 0x47: return "buffer overrun "; | ||
590 | |||
591 | case 0x53: return "unrecoverable CIRC "; | ||
592 | case 0x57: return "unrecoverable LECC "; | ||
593 | |||
594 | case 0x60: return "no TOC "; | ||
595 | case 0x61: return "invalid subcode data "; | ||
596 | case 0x63: return "focus on TOC read "; | ||
597 | case 0x64: return "frame sync on TOC read "; | ||
598 | case 0x65: return "TOC data "; | ||
599 | |||
600 | case 0x70: return "hardware failure "; | ||
601 | case 0x91: return "leadin "; | ||
602 | case 0x92: return "leadout "; | ||
603 | case 0x93: return "data track "; | ||
604 | } | ||
605 | sprintf(errbuf, "unknown 0x%02x ", err_code); | ||
606 | return errbuf; | ||
607 | } | ||
608 | |||
609 | /* | ||
610 | * Set the drive parameters so the drive will auto-spin-up when a | ||
611 | * disk is inserted. | ||
612 | */ | ||
613 | static void set_drive_params(int want_doublespeed) | ||
614 | { | ||
615 | unsigned char res_reg[12]; | ||
616 | unsigned int res_size; | ||
617 | unsigned char params[3]; | ||
618 | |||
619 | |||
620 | params[0] = SONY_SD_AUTO_SPIN_DOWN_TIME; | ||
621 | params[1] = 0x00; /* Never spin down the drive. */ | ||
622 | do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD, | ||
623 | params, 2, res_reg, &res_size); | ||
624 | if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) { | ||
625 | printk(KERN_NOTICE PFX | ||
626 | "Unable to set spin-down time: 0x%2.2x\n", res_reg[1]); | ||
627 | } | ||
628 | |||
629 | params[0] = SONY_SD_MECH_CONTROL; | ||
630 | params[1] = SONY_AUTO_SPIN_UP_BIT; /* Set auto spin up */ | ||
631 | |||
632 | if (is_auto_eject) | ||
633 | params[1] |= SONY_AUTO_EJECT_BIT; | ||
634 | |||
635 | if (is_double_speed && want_doublespeed) { | ||
636 | params[1] |= SONY_DOUBLE_SPEED_BIT; /* Set the drive to double speed if | ||
637 | possible */ | ||
638 | } | ||
639 | do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD, | ||
640 | params, 2, res_reg, &res_size); | ||
641 | if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) { | ||
642 | printk(KERN_NOTICE PFX "Unable to set mechanical " | ||
643 | "parameters: 0x%2.2x\n", res_reg[1]); | ||
644 | } | ||
645 | } | ||
646 | |||
647 | /* | ||
648 | * Uniform cdrom interface function | ||
649 | * select reading speed for data access | ||
650 | */ | ||
651 | static int scd_select_speed(struct cdrom_device_info *cdi, int speed) | ||
652 | { | ||
653 | if (speed == 0) | ||
654 | sony_speed = 1; | ||
655 | else | ||
656 | sony_speed = speed - 1; | ||
657 | |||
658 | if (down_interruptible(&sony_sem)) | ||
659 | return -ERESTARTSYS; | ||
660 | set_drive_params(sony_speed); | ||
661 | up(&sony_sem); | ||
662 | return 0; | ||
663 | } | ||
664 | |||
665 | /* | ||
666 | * Uniform cdrom interface function | ||
667 | * lock or unlock eject button | ||
668 | */ | ||
669 | static int scd_lock_door(struct cdrom_device_info *cdi, int lock) | ||
670 | { | ||
671 | if (lock == 0) { | ||
672 | is_auto_eject = 1; | ||
673 | } else { | ||
674 | is_auto_eject = 0; | ||
675 | } | ||
676 | if (down_interruptible(&sony_sem)) | ||
677 | return -ERESTARTSYS; | ||
678 | set_drive_params(sony_speed); | ||
679 | up(&sony_sem); | ||
680 | return 0; | ||
681 | } | ||
682 | |||
683 | /* | ||
684 | * This code will reset the drive and attempt to restore sane parameters. | ||
685 | */ | ||
686 | static void restart_on_error(void) | ||
687 | { | ||
688 | unsigned char res_reg[12]; | ||
689 | unsigned int res_size; | ||
690 | unsigned long retry_count; | ||
691 | |||
692 | |||
693 | printk(KERN_NOTICE PFX "Resetting drive on error\n"); | ||
694 | reset_drive(); | ||
695 | retry_count = jiffies + SONY_RESET_TIMEOUT; | ||
696 | while (time_before(jiffies, retry_count) && (!is_attention())) { | ||
697 | sony_sleep(); | ||
698 | } | ||
699 | set_drive_params(sony_speed); | ||
700 | do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size); | ||
701 | if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) { | ||
702 | printk(KERN_NOTICE PFX "Unable to spin up drive: 0x%2.2x\n", | ||
703 | res_reg[1]); | ||
704 | } | ||
705 | |||
706 | msleep(2000); | ||
707 | |||
708 | sony_get_toc(); | ||
709 | } | ||
710 | |||
711 | /* | ||
712 | * This routine writes data to the parameter register. Since this should | ||
713 | * happen fairly fast, it is polled with no OS waits between. | ||
714 | */ | ||
715 | static int write_params(unsigned char *params, int num_params) | ||
716 | { | ||
717 | unsigned int retry_count; | ||
718 | |||
719 | |||
720 | retry_count = SONY_READY_RETRIES; | ||
721 | while ((retry_count > 0) && (!is_param_write_rdy())) { | ||
722 | retry_count--; | ||
723 | } | ||
724 | if (!is_param_write_rdy()) { | ||
725 | return -EIO; | ||
726 | } | ||
727 | |||
728 | while (num_params > 0) { | ||
729 | write_param(*params); | ||
730 | params++; | ||
731 | num_params--; | ||
732 | } | ||
733 | |||
734 | return 0; | ||
735 | } | ||
736 | |||
737 | |||
738 | /* | ||
739 | * The following reads data from the command result register. It is a | ||
740 | * fairly complex routine, all status info flows back through this | ||
741 | * interface. The algorithm is stolen directly from the flowcharts in | ||
742 | * the drive manual. | ||
743 | */ | ||
744 | static void | ||
745 | get_result(unsigned char *result_buffer, unsigned int *result_size) | ||
746 | { | ||
747 | unsigned char a, b; | ||
748 | int i; | ||
749 | unsigned long retry_count; | ||
750 | |||
751 | |||
752 | while (handle_sony_cd_attention()); | ||
753 | /* Wait for the result data to be ready */ | ||
754 | retry_count = jiffies + SONY_JIFFIES_TIMEOUT; | ||
755 | while (time_before(jiffies, retry_count) | ||
756 | && (is_busy() || (!(is_result_ready())))) { | ||
757 | sony_sleep(); | ||
758 | |||
759 | while (handle_sony_cd_attention()); | ||
760 | } | ||
761 | if (is_busy() || (!(is_result_ready()))) { | ||
762 | pr_debug(PFX "timeout out %d\n", __LINE__); | ||
763 | result_buffer[0] = 0x20; | ||
764 | result_buffer[1] = SONY_TIMEOUT_OP_ERR; | ||
765 | *result_size = 2; | ||
766 | return; | ||
767 | } | ||
768 | |||
769 | /* | ||
770 | * Get the first two bytes. This determines what else needs | ||
771 | * to be done. | ||
772 | */ | ||
773 | clear_result_ready(); | ||
774 | a = read_result_register(); | ||
775 | *result_buffer = a; | ||
776 | result_buffer++; | ||
777 | |||
778 | /* Check for block error status result. */ | ||
779 | if ((a & 0xf0) == 0x50) { | ||
780 | *result_size = 1; | ||
781 | return; | ||
782 | } | ||
783 | |||
784 | b = read_result_register(); | ||
785 | *result_buffer = b; | ||
786 | result_buffer++; | ||
787 | *result_size = 2; | ||
788 | |||
789 | /* | ||
790 | * 0x20 means an error occurred. Byte 2 will have the error code. | ||
791 | * Otherwise, the command succeeded, byte 2 will have the count of | ||
792 | * how many more status bytes are coming. | ||
793 | * | ||
794 | * The result register can be read 10 bytes at a time, a wait for | ||
795 | * result ready to be asserted must be done between every 10 bytes. | ||
796 | */ | ||
797 | if ((a & 0xf0) != 0x20) { | ||
798 | if (b > 8) { | ||
799 | for (i = 0; i < 8; i++) { | ||
800 | *result_buffer = read_result_register(); | ||
801 | result_buffer++; | ||
802 | (*result_size)++; | ||
803 | } | ||
804 | b = b - 8; | ||
805 | |||
806 | while (b > 10) { | ||
807 | retry_count = SONY_READY_RETRIES; | ||
808 | while ((retry_count > 0) | ||
809 | && (!is_result_ready())) { | ||
810 | retry_count--; | ||
811 | } | ||
812 | if (!is_result_ready()) { | ||
813 | pr_debug(PFX "timeout out %d\n", | ||
814 | __LINE__); | ||
815 | result_buffer[0] = 0x20; | ||
816 | result_buffer[1] = | ||
817 | SONY_TIMEOUT_OP_ERR; | ||
818 | *result_size = 2; | ||
819 | return; | ||
820 | } | ||
821 | |||
822 | clear_result_ready(); | ||
823 | |||
824 | for (i = 0; i < 10; i++) { | ||
825 | *result_buffer = | ||
826 | read_result_register(); | ||
827 | result_buffer++; | ||
828 | (*result_size)++; | ||
829 | } | ||
830 | b = b - 10; | ||
831 | } | ||
832 | |||
833 | if (b > 0) { | ||
834 | retry_count = SONY_READY_RETRIES; | ||
835 | while ((retry_count > 0) | ||
836 | && (!is_result_ready())) { | ||
837 | retry_count--; | ||
838 | } | ||
839 | if (!is_result_ready()) { | ||
840 | pr_debug(PFX "timeout out %d\n", | ||
841 | __LINE__); | ||
842 | result_buffer[0] = 0x20; | ||
843 | result_buffer[1] = | ||
844 | SONY_TIMEOUT_OP_ERR; | ||
845 | *result_size = 2; | ||
846 | return; | ||
847 | } | ||
848 | } | ||
849 | } | ||
850 | |||
851 | while (b > 0) { | ||
852 | *result_buffer = read_result_register(); | ||
853 | result_buffer++; | ||
854 | (*result_size)++; | ||
855 | b--; | ||
856 | } | ||
857 | } | ||
858 | } | ||
859 | |||
860 | /* | ||
861 | * Do a command that does not involve data transfer. This routine must | ||
862 | * be re-entrant from the same task to support being called from the | ||
863 | * data operation code when an error occurs. | ||
864 | */ | ||
865 | static void | ||
866 | do_sony_cd_cmd(unsigned char cmd, | ||
867 | unsigned char *params, | ||
868 | unsigned int num_params, | ||
869 | unsigned char *result_buffer, unsigned int *result_size) | ||
870 | { | ||
871 | unsigned long retry_count; | ||
872 | int num_retries = 0; | ||
873 | |||
874 | retry_cd_operation: | ||
875 | |||
876 | while (handle_sony_cd_attention()); | ||
877 | |||
878 | retry_count = jiffies + SONY_JIFFIES_TIMEOUT; | ||
879 | while (time_before(jiffies, retry_count) && (is_busy())) { | ||
880 | sony_sleep(); | ||
881 | |||
882 | while (handle_sony_cd_attention()); | ||
883 | } | ||
884 | if (is_busy()) { | ||
885 | pr_debug(PFX "timeout out %d\n", __LINE__); | ||
886 | result_buffer[0] = 0x20; | ||
887 | result_buffer[1] = SONY_TIMEOUT_OP_ERR; | ||
888 | *result_size = 2; | ||
889 | } else { | ||
890 | clear_result_ready(); | ||
891 | clear_param_reg(); | ||
892 | |||
893 | write_params(params, num_params); | ||
894 | write_cmd(cmd); | ||
895 | |||
896 | get_result(result_buffer, result_size); | ||
897 | } | ||
898 | |||
899 | if (((result_buffer[0] & 0xf0) == 0x20) | ||
900 | && (num_retries < MAX_CDU31A_RETRIES)) { | ||
901 | num_retries++; | ||
902 | msleep(100); | ||
903 | goto retry_cd_operation; | ||
904 | } | ||
905 | } | ||
906 | |||
907 | |||
908 | /* | ||
909 | * Handle an attention from the drive. This will return 1 if it found one | ||
910 | * or 0 if not (if one is found, the caller might want to call again). | ||
911 | * | ||
912 | * This routine counts the number of consecutive times it is called | ||
913 | * (since this is always called from a while loop until it returns | ||
914 | * a 0), and returns a 0 if it happens too many times. This will help | ||
915 | * prevent a lockup. | ||
916 | */ | ||
917 | static int handle_sony_cd_attention(void) | ||
918 | { | ||
919 | unsigned char atten_code; | ||
920 | static int num_consecutive_attentions = 0; | ||
921 | volatile int val; | ||
922 | |||
923 | |||
924 | #if 0 | ||
925 | pr_debug(PFX "Entering %s\n", __FUNCTION__); | ||
926 | #endif | ||
927 | if (is_attention()) { | ||
928 | if (num_consecutive_attentions > | ||
929 | CDU31A_MAX_CONSECUTIVE_ATTENTIONS) { | ||
930 | printk(KERN_NOTICE PFX "Too many consecutive " | ||
931 | "attentions: %d\n", num_consecutive_attentions); | ||
932 | num_consecutive_attentions = 0; | ||
933 | pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, | ||
934 | __LINE__); | ||
935 | return 0; | ||
936 | } | ||
937 | |||
938 | clear_attention(); | ||
939 | atten_code = read_result_register(); | ||
940 | |||
941 | switch (atten_code) { | ||
942 | /* Someone changed the CD. Mark it as changed */ | ||
943 | case SONY_MECH_LOADED_ATTN: | ||
944 | disk_changed = 1; | ||
945 | sony_toc_read = 0; | ||
946 | sony_audio_status = CDROM_AUDIO_NO_STATUS; | ||
947 | sony_blocks_left = 0; | ||
948 | break; | ||
949 | |||
950 | case SONY_SPIN_DOWN_COMPLETE_ATTN: | ||
951 | /* Mark the disk as spun down. */ | ||
952 | sony_spun_up = 0; | ||
953 | break; | ||
954 | |||
955 | case SONY_AUDIO_PLAY_DONE_ATTN: | ||
956 | sony_audio_status = CDROM_AUDIO_COMPLETED; | ||
957 | read_subcode(); | ||
958 | break; | ||
959 | |||
960 | case SONY_EJECT_PUSHED_ATTN: | ||
961 | if (is_auto_eject) { | ||
962 | sony_audio_status = CDROM_AUDIO_INVALID; | ||
963 | } | ||
964 | break; | ||
965 | |||
966 | case SONY_LEAD_IN_ERR_ATTN: | ||
967 | case SONY_LEAD_OUT_ERR_ATTN: | ||
968 | case SONY_DATA_TRACK_ERR_ATTN: | ||
969 | case SONY_AUDIO_PLAYBACK_ERR_ATTN: | ||
970 | sony_audio_status = CDROM_AUDIO_ERROR; | ||
971 | break; | ||
972 | } | ||
973 | |||
974 | num_consecutive_attentions++; | ||
975 | pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__); | ||
976 | return 1; | ||
977 | } else if (abort_read_started) { | ||
978 | while (is_result_reg_not_empty()) { | ||
979 | val = read_result_register(); | ||
980 | } | ||
981 | clear_data_ready(); | ||
982 | clear_result_ready(); | ||
983 | /* Clear out the data */ | ||
984 | while (is_data_requested()) { | ||
985 | val = read_data_register(); | ||
986 | } | ||
987 | abort_read_started = 0; | ||
988 | pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__); | ||
989 | return 1; | ||
990 | } | ||
991 | |||
992 | num_consecutive_attentions = 0; | ||
993 | #if 0 | ||
994 | pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__); | ||
995 | #endif | ||
996 | return 0; | ||
997 | } | ||
998 | |||
999 | |||
1000 | /* Convert from an integer 0-99 to BCD */ | ||
1001 | static inline unsigned int int_to_bcd(unsigned int val) | ||
1002 | { | ||
1003 | int retval; | ||
1004 | |||
1005 | |||
1006 | retval = (val / 10) << 4; | ||
1007 | retval = retval | val % 10; | ||
1008 | return retval; | ||
1009 | } | ||
1010 | |||
1011 | |||
1012 | /* Convert from BCD to an integer from 0-99 */ | ||
1013 | static unsigned int bcd_to_int(unsigned int bcd) | ||
1014 | { | ||
1015 | return (((bcd >> 4) & 0x0f) * 10) + (bcd & 0x0f); | ||
1016 | } | ||
1017 | |||
1018 | |||
1019 | /* | ||
1020 | * Convert a logical sector value (like the OS would want to use for | ||
1021 | * a block device) to an MSF format. | ||
1022 | */ | ||
1023 | static void log_to_msf(unsigned int log, unsigned char *msf) | ||
1024 | { | ||
1025 | log = log + LOG_START_OFFSET; | ||
1026 | msf[0] = int_to_bcd(log / 4500); | ||
1027 | log = log % 4500; | ||
1028 | msf[1] = int_to_bcd(log / 75); | ||
1029 | msf[2] = int_to_bcd(log % 75); | ||
1030 | } | ||
1031 | |||
1032 | |||
1033 | /* | ||
1034 | * Convert an MSF format to a logical sector. | ||
1035 | */ | ||
1036 | static unsigned int msf_to_log(unsigned char *msf) | ||
1037 | { | ||
1038 | unsigned int log; | ||
1039 | |||
1040 | |||
1041 | log = msf[2]; | ||
1042 | log += msf[1] * 75; | ||
1043 | log += msf[0] * 4500; | ||
1044 | log = log - LOG_START_OFFSET; | ||
1045 | |||
1046 | return log; | ||
1047 | } | ||
1048 | |||
1049 | |||
1050 | /* | ||
1051 | * Take in integer size value and put it into a buffer like | ||
1052 | * the drive would want to see a number-of-sector value. | ||
1053 | */ | ||
1054 | static void size_to_buf(unsigned int size, unsigned char *buf) | ||
1055 | { | ||
1056 | buf[0] = size / 65536; | ||
1057 | size = size % 65536; | ||
1058 | buf[1] = size / 256; | ||
1059 | buf[2] = size % 256; | ||
1060 | } | ||
1061 | |||
1062 | /* Starts a read operation. Returns 0 on success and 1 on failure. | ||
1063 | The read operation used here allows multiple sequential sectors | ||
1064 | to be read and status returned for each sector. The driver will | ||
1065 | read the output one at a time as the requests come and abort the | ||
1066 | operation if the requested sector is not the next one from the | ||
1067 | drive. */ | ||
1068 | static int | ||
1069 | start_request(unsigned int sector, unsigned int nsect) | ||
1070 | { | ||
1071 | unsigned char params[6]; | ||
1072 | unsigned long retry_count; | ||
1073 | |||
1074 | |||
1075 | pr_debug(PFX "Entering %s\n", __FUNCTION__); | ||
1076 | log_to_msf(sector, params); | ||
1077 | size_to_buf(nsect, ¶ms[3]); | ||
1078 | |||
1079 | /* | ||
1080 | * Clear any outstanding attentions and wait for the drive to | ||
1081 | * complete any pending operations. | ||
1082 | */ | ||
1083 | while (handle_sony_cd_attention()); | ||
1084 | |||
1085 | retry_count = jiffies + SONY_JIFFIES_TIMEOUT; | ||
1086 | while (time_before(jiffies, retry_count) && (is_busy())) { | ||
1087 | sony_sleep(); | ||
1088 | |||
1089 | while (handle_sony_cd_attention()); | ||
1090 | } | ||
1091 | |||
1092 | if (is_busy()) { | ||
1093 | printk(KERN_NOTICE PFX "Timeout while waiting " | ||
1094 | "to issue command\n"); | ||
1095 | pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__); | ||
1096 | return 1; | ||
1097 | } else { | ||
1098 | /* Issue the command */ | ||
1099 | clear_result_ready(); | ||
1100 | clear_param_reg(); | ||
1101 | |||
1102 | write_params(params, 6); | ||
1103 | write_cmd(SONY_READ_BLKERR_STAT_CMD); | ||
1104 | |||
1105 | sony_blocks_left = nsect * 4; | ||
1106 | sony_next_block = sector * 4; | ||
1107 | pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__); | ||
1108 | return 0; | ||
1109 | } | ||
1110 | pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__); | ||
1111 | } | ||
1112 | |||
1113 | /* Abort a pending read operation. Clear all the drive status variables. */ | ||
1114 | static void abort_read(void) | ||
1115 | { | ||
1116 | unsigned char result_reg[2]; | ||
1117 | int result_size; | ||
1118 | volatile int val; | ||
1119 | |||
1120 | |||
1121 | do_sony_cd_cmd(SONY_ABORT_CMD, NULL, 0, result_reg, &result_size); | ||
1122 | if ((result_reg[0] & 0xf0) == 0x20) { | ||
1123 | printk(KERN_ERR PFX "Aborting read, %s error\n", | ||
1124 | translate_error(result_reg[1])); | ||
1125 | } | ||
1126 | |||
1127 | while (is_result_reg_not_empty()) { | ||
1128 | val = read_result_register(); | ||
1129 | } | ||
1130 | clear_data_ready(); | ||
1131 | clear_result_ready(); | ||
1132 | /* Clear out the data */ | ||
1133 | while (is_data_requested()) { | ||
1134 | val = read_data_register(); | ||
1135 | } | ||
1136 | |||
1137 | sony_blocks_left = 0; | ||
1138 | } | ||
1139 | |||
1140 | /* Called when the timer times out. This will abort the | ||
1141 | pending read operation. */ | ||
1142 | static void handle_abort_timeout(unsigned long data) | ||
1143 | { | ||
1144 | pr_debug(PFX "Entering %s\n", __FUNCTION__); | ||
1145 | /* If it is in use, ignore it. */ | ||
1146 | if (down_trylock(&sony_sem) == 0) { | ||
1147 | /* We can't use abort_read(), because it will sleep | ||
1148 | or schedule in the timer interrupt. Just start | ||
1149 | the operation, finish it on the next access to | ||
1150 | the drive. */ | ||
1151 | clear_result_ready(); | ||
1152 | clear_param_reg(); | ||
1153 | write_cmd(SONY_ABORT_CMD); | ||
1154 | |||
1155 | sony_blocks_left = 0; | ||
1156 | abort_read_started = 1; | ||
1157 | up(&sony_sem); | ||
1158 | } | ||
1159 | pr_debug(PFX "Leaving %s\n", __FUNCTION__); | ||
1160 | } | ||
1161 | |||
1162 | /* Actually get one sector of data from the drive. */ | ||
1163 | static void | ||
1164 | input_data_sector(char *buffer) | ||
1165 | { | ||
1166 | pr_debug(PFX "Entering %s\n", __FUNCTION__); | ||
1167 | |||
1168 | /* If an XA disk on a CDU31A, skip the first 12 bytes of data from | ||
1169 | the disk. The real data is after that. We can use audio_buffer. */ | ||
1170 | if (sony_xa_mode) | ||
1171 | insb(sony_cd_read_reg, audio_buffer, CD_XA_HEAD); | ||
1172 | |||
1173 | clear_data_ready(); | ||
1174 | |||
1175 | insb(sony_cd_read_reg, buffer, 2048); | ||
1176 | |||
1177 | /* If an XA disk, we have to clear out the rest of the unused | ||
1178 | error correction data. We can use audio_buffer for that. */ | ||
1179 | if (sony_xa_mode) | ||
1180 | insb(sony_cd_read_reg, audio_buffer, CD_XA_TAIL); | ||
1181 | |||
1182 | pr_debug(PFX "Leaving %s\n", __FUNCTION__); | ||
1183 | } | ||
1184 | |||
1185 | /* read data from the drive. Note the nsect must be <= 4. */ | ||
1186 | static void | ||
1187 | read_data_block(char *buffer, | ||
1188 | unsigned int block, | ||
1189 | unsigned int nblocks, | ||
1190 | unsigned char res_reg[], int *res_size) | ||
1191 | { | ||
1192 | unsigned long retry_count; | ||
1193 | |||
1194 | pr_debug(PFX "Entering %s\n", __FUNCTION__); | ||
1195 | |||
1196 | res_reg[0] = 0; | ||
1197 | res_reg[1] = 0; | ||
1198 | *res_size = 0; | ||
1199 | |||
1200 | /* Wait for the drive to tell us we have something */ | ||
1201 | retry_count = jiffies + SONY_JIFFIES_TIMEOUT; | ||
1202 | while (time_before(jiffies, retry_count) && !(is_data_ready())) { | ||
1203 | while (handle_sony_cd_attention()); | ||
1204 | |||
1205 | sony_sleep(); | ||
1206 | } | ||
1207 | if (!(is_data_ready())) { | ||
1208 | if (is_result_ready()) { | ||
1209 | get_result(res_reg, res_size); | ||
1210 | if ((res_reg[0] & 0xf0) != 0x20) { | ||
1211 | printk(KERN_NOTICE PFX "Got result that should" | ||
1212 | " have been error: %d\n", res_reg[0]); | ||
1213 | res_reg[0] = 0x20; | ||
1214 | res_reg[1] = SONY_BAD_DATA_ERR; | ||
1215 | *res_size = 2; | ||
1216 | } | ||
1217 | abort_read(); | ||
1218 | } else { | ||
1219 | pr_debug(PFX "timeout out %d\n", __LINE__); | ||
1220 | res_reg[0] = 0x20; | ||
1221 | res_reg[1] = SONY_TIMEOUT_OP_ERR; | ||
1222 | *res_size = 2; | ||
1223 | abort_read(); | ||
1224 | } | ||
1225 | } else { | ||
1226 | input_data_sector(buffer); | ||
1227 | sony_blocks_left -= nblocks; | ||
1228 | sony_next_block += nblocks; | ||
1229 | |||
1230 | /* Wait for the status from the drive. */ | ||
1231 | retry_count = jiffies + SONY_JIFFIES_TIMEOUT; | ||
1232 | while (time_before(jiffies, retry_count) | ||
1233 | && !(is_result_ready())) { | ||
1234 | while (handle_sony_cd_attention()); | ||
1235 | |||
1236 | sony_sleep(); | ||
1237 | } | ||
1238 | |||
1239 | if (!is_result_ready()) { | ||
1240 | pr_debug(PFX "timeout out %d\n", __LINE__); | ||
1241 | res_reg[0] = 0x20; | ||
1242 | res_reg[1] = SONY_TIMEOUT_OP_ERR; | ||
1243 | *res_size = 2; | ||
1244 | abort_read(); | ||
1245 | } else { | ||
1246 | get_result(res_reg, res_size); | ||
1247 | |||
1248 | /* If we got a buffer status, handle that. */ | ||
1249 | if ((res_reg[0] & 0xf0) == 0x50) { | ||
1250 | |||
1251 | if ((res_reg[0] == | ||
1252 | SONY_NO_CIRC_ERR_BLK_STAT) | ||
1253 | || (res_reg[0] == | ||
1254 | SONY_NO_LECC_ERR_BLK_STAT) | ||
1255 | || (res_reg[0] == | ||
1256 | SONY_RECOV_LECC_ERR_BLK_STAT)) { | ||
1257 | /* nothing here */ | ||
1258 | } else { | ||
1259 | printk(KERN_ERR PFX "Data block " | ||
1260 | "error: 0x%x\n", res_reg[0]); | ||
1261 | res_reg[0] = 0x20; | ||
1262 | res_reg[1] = SONY_BAD_DATA_ERR; | ||
1263 | *res_size = 2; | ||
1264 | } | ||
1265 | |||
1266 | /* Final transfer is done for read command, get final result. */ | ||
1267 | if (sony_blocks_left == 0) { | ||
1268 | get_result(res_reg, res_size); | ||
1269 | } | ||
1270 | } else if ((res_reg[0] & 0xf0) != 0x20) { | ||
1271 | /* The drive gave me bad status, I don't know what to do. | ||
1272 | Reset the driver and return an error. */ | ||
1273 | printk(KERN_ERR PFX "Invalid block " | ||
1274 | "status: 0x%x\n", res_reg[0]); | ||
1275 | restart_on_error(); | ||
1276 | res_reg[0] = 0x20; | ||
1277 | res_reg[1] = SONY_BAD_DATA_ERR; | ||
1278 | *res_size = 2; | ||
1279 | } | ||
1280 | } | ||
1281 | } | ||
1282 | pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__); | ||
1283 | } | ||
1284 | |||
1285 | |||
1286 | /* | ||
1287 | * The OS calls this to perform a read or write operation to the drive. | ||
1288 | * Write obviously fail. Reads to a read ahead of sony_buffer_size | ||
1289 | * bytes to help speed operations. This especially helps since the OS | ||
1290 | * uses 1024 byte blocks and the drive uses 2048 byte blocks. Since most | ||
1291 | * data access on a CD is done sequentially, this saves a lot of operations. | ||
1292 | */ | ||
1293 | static void do_cdu31a_request(request_queue_t * q) | ||
1294 | { | ||
1295 | struct request *req; | ||
1296 | int block, nblock, num_retries; | ||
1297 | unsigned char res_reg[12]; | ||
1298 | unsigned int res_size; | ||
1299 | |||
1300 | pr_debug(PFX "Entering %s\n", __FUNCTION__); | ||
1301 | |||
1302 | spin_unlock_irq(q->queue_lock); | ||
1303 | if (down_interruptible(&sony_sem)) { | ||
1304 | spin_lock_irq(q->queue_lock); | ||
1305 | return; | ||
1306 | } | ||
1307 | |||
1308 | /* Get drive status before doing anything. */ | ||
1309 | while (handle_sony_cd_attention()); | ||
1310 | |||
1311 | /* Make sure we have a valid TOC. */ | ||
1312 | sony_get_toc(); | ||
1313 | |||
1314 | |||
1315 | /* Make sure the timer is cancelled. */ | ||
1316 | del_timer(&cdu31a_abort_timer); | ||
1317 | |||
1318 | while (1) { | ||
1319 | /* | ||
1320 | * The beginning here is stolen from the hard disk driver. I hope | ||
1321 | * it's right. | ||
1322 | */ | ||
1323 | req = elv_next_request(q); | ||
1324 | if (!req) | ||
1325 | goto end_do_cdu31a_request; | ||
1326 | |||
1327 | if (!sony_spun_up) | ||
1328 | scd_spinup(); | ||
1329 | |||
1330 | block = req->sector; | ||
1331 | nblock = req->nr_sectors; | ||
1332 | pr_debug(PFX "request at block %d, length %d blocks\n", | ||
1333 | block, nblock); | ||
1334 | if (!sony_toc_read) { | ||
1335 | printk(KERN_NOTICE PFX "TOC not read\n"); | ||
1336 | end_request(req, 0); | ||
1337 | continue; | ||
1338 | } | ||
1339 | |||
1340 | /* WTF??? */ | ||
1341 | if (!blk_fs_request(req)) { | ||
1342 | end_request(req, 0); | ||
1343 | continue; | ||
1344 | } | ||
1345 | if (rq_data_dir(req) == WRITE) { | ||
1346 | end_request(req, 0); | ||
1347 | continue; | ||
1348 | } | ||
1349 | |||
1350 | /* | ||
1351 | * If the block address is invalid or the request goes beyond the end of | ||
1352 | * the media, return an error. | ||
1353 | */ | ||
1354 | if (((block + nblock) / 4) >= sony_toc.lead_out_start_lba) { | ||
1355 | printk(KERN_NOTICE PFX "Request past end of media\n"); | ||
1356 | end_request(req, 0); | ||
1357 | continue; | ||
1358 | } | ||
1359 | |||
1360 | if (nblock > 4) | ||
1361 | nblock = 4; | ||
1362 | num_retries = 0; | ||
1363 | |||
1364 | try_read_again: | ||
1365 | while (handle_sony_cd_attention()); | ||
1366 | |||
1367 | if (!sony_toc_read) { | ||
1368 | printk(KERN_NOTICE PFX "TOC not read\n"); | ||
1369 | end_request(req, 0); | ||
1370 | continue; | ||
1371 | } | ||
1372 | |||
1373 | /* If no data is left to be read from the drive, start the | ||
1374 | next request. */ | ||
1375 | if (sony_blocks_left == 0) { | ||
1376 | if (start_request(block / 4, nblock / 4)) { | ||
1377 | end_request(req, 0); | ||
1378 | continue; | ||
1379 | } | ||
1380 | } | ||
1381 | /* If the requested block is not the next one waiting in | ||
1382 | the driver, abort the current operation and start a | ||
1383 | new one. */ | ||
1384 | else if (block != sony_next_block) { | ||
1385 | pr_debug(PFX "Read for block %d, expected %d\n", | ||
1386 | block, sony_next_block); | ||
1387 | abort_read(); | ||
1388 | if (!sony_toc_read) { | ||
1389 | printk(KERN_NOTICE PFX "TOC not read\n"); | ||
1390 | end_request(req, 0); | ||
1391 | continue; | ||
1392 | } | ||
1393 | if (start_request(block / 4, nblock / 4)) { | ||
1394 | printk(KERN_NOTICE PFX "start request failed\n"); | ||
1395 | end_request(req, 0); | ||
1396 | continue; | ||
1397 | } | ||
1398 | } | ||
1399 | |||
1400 | read_data_block(req->buffer, block, nblock, res_reg, &res_size); | ||
1401 | |||
1402 | if (res_reg[0] != 0x20) { | ||
1403 | if (!end_that_request_first(req, 1, nblock)) { | ||
1404 | spin_lock_irq(q->queue_lock); | ||
1405 | blkdev_dequeue_request(req); | ||
1406 | end_that_request_last(req, 1); | ||
1407 | spin_unlock_irq(q->queue_lock); | ||
1408 | } | ||
1409 | continue; | ||
1410 | } | ||
1411 | |||
1412 | if (num_retries > MAX_CDU31A_RETRIES) { | ||
1413 | end_request(req, 0); | ||
1414 | continue; | ||
1415 | } | ||
1416 | |||
1417 | num_retries++; | ||
1418 | if (res_reg[1] == SONY_NOT_SPIN_ERR) { | ||
1419 | do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, | ||
1420 | &res_size); | ||
1421 | } else { | ||
1422 | printk(KERN_NOTICE PFX "%s error for block %d, nblock %d\n", | ||
1423 | translate_error(res_reg[1]), block, nblock); | ||
1424 | } | ||
1425 | goto try_read_again; | ||
1426 | } | ||
1427 | end_do_cdu31a_request: | ||
1428 | #if 0 | ||
1429 | /* After finished, cancel any pending operations. */ | ||
1430 | abort_read(); | ||
1431 | #else | ||
1432 | /* Start a timer to time out after a while to disable | ||
1433 | the read. */ | ||
1434 | cdu31a_abort_timer.expires = jiffies + 2 * HZ; /* Wait 2 seconds */ | ||
1435 | add_timer(&cdu31a_abort_timer); | ||
1436 | #endif | ||
1437 | |||
1438 | up(&sony_sem); | ||
1439 | spin_lock_irq(q->queue_lock); | ||
1440 | pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__); | ||
1441 | } | ||
1442 | |||
1443 | |||
1444 | /* | ||
1445 | * Read the table of contents from the drive and set up TOC if | ||
1446 | * successful. | ||
1447 | */ | ||
1448 | static void sony_get_toc(void) | ||
1449 | { | ||
1450 | unsigned char res_reg[2]; | ||
1451 | unsigned int res_size; | ||
1452 | unsigned char parms[1]; | ||
1453 | int session; | ||
1454 | int num_spin_ups; | ||
1455 | int totaltracks = 0; | ||
1456 | int mint = 99; | ||
1457 | int maxt = 0; | ||
1458 | |||
1459 | pr_debug(PFX "Entering %s\n", __FUNCTION__); | ||
1460 | |||
1461 | num_spin_ups = 0; | ||
1462 | if (!sony_toc_read) { | ||
1463 | respinup_on_gettoc: | ||
1464 | /* Ignore the result, since it might error if spinning already. */ | ||
1465 | do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, | ||
1466 | &res_size); | ||
1467 | |||
1468 | do_sony_cd_cmd(SONY_READ_TOC_CMD, NULL, 0, res_reg, | ||
1469 | &res_size); | ||
1470 | |||
1471 | /* The drive sometimes returns error 0. I don't know why, but ignore | ||
1472 | it. It seems to mean the drive has already done the operation. */ | ||
1473 | if ((res_size < 2) | ||
1474 | || ((res_reg[0] != 0) && (res_reg[1] != 0))) { | ||
1475 | /* If the drive is already playing, it's ok. */ | ||
1476 | if ((res_reg[1] == SONY_AUDIO_PLAYING_ERR) | ||
1477 | || (res_reg[1] == 0)) { | ||
1478 | goto gettoc_drive_spinning; | ||
1479 | } | ||
1480 | |||
1481 | /* If the drive says it is not spun up (even though we just did it!) | ||
1482 | then retry the operation at least a few times. */ | ||
1483 | if ((res_reg[1] == SONY_NOT_SPIN_ERR) | ||
1484 | && (num_spin_ups < MAX_CDU31A_RETRIES)) { | ||
1485 | num_spin_ups++; | ||
1486 | goto respinup_on_gettoc; | ||
1487 | } | ||
1488 | |||
1489 | printk("cdu31a: Error reading TOC: %x %s\n", | ||
1490 | res_reg[0], translate_error(res_reg[1])); | ||
1491 | return; | ||
1492 | } | ||
1493 | |||
1494 | gettoc_drive_spinning: | ||
1495 | |||
1496 | /* The idea here is we keep asking for sessions until the command | ||
1497 | fails. Then we know what the last valid session on the disk is. | ||
1498 | No need to check session 0, since session 0 is the same as session | ||
1499 | 1; the command returns different information if you give it 0. | ||
1500 | */ | ||
1501 | #if DEBUG | ||
1502 | memset(&sony_toc, 0x0e, sizeof(sony_toc)); | ||
1503 | memset(&single_toc, 0x0f, sizeof(single_toc)); | ||
1504 | #endif | ||
1505 | session = 1; | ||
1506 | while (1) { | ||
1507 | /* This seems to slow things down enough to make it work. This | ||
1508 | * appears to be a problem in do_sony_cd_cmd. This printk seems | ||
1509 | * to address the symptoms... -Erik */ | ||
1510 | pr_debug(PFX "Trying session %d\n", session); | ||
1511 | parms[0] = session; | ||
1512 | do_sony_cd_cmd(SONY_READ_TOC_SPEC_CMD, | ||
1513 | parms, 1, res_reg, &res_size); | ||
1514 | |||
1515 | pr_debug(PFX "%2.2x %2.2x\n", res_reg[0], res_reg[1]); | ||
1516 | |||
1517 | if ((res_size < 2) | ||
1518 | || ((res_reg[0] & 0xf0) == 0x20)) { | ||
1519 | /* An error reading the TOC, this must be past the last session. */ | ||
1520 | if (session == 1) | ||
1521 | printk | ||
1522 | ("Yikes! Couldn't read any sessions!"); | ||
1523 | break; | ||
1524 | } | ||
1525 | pr_debug(PFX "Reading session %d\n", session); | ||
1526 | |||
1527 | parms[0] = session; | ||
1528 | do_sony_cd_cmd(SONY_REQ_TOC_DATA_SPEC_CMD, | ||
1529 | parms, | ||
1530 | 1, | ||
1531 | (unsigned char *) &single_toc, | ||
1532 | &res_size); | ||
1533 | if ((res_size < 2) | ||
1534 | || ((single_toc.exec_status[0] & 0xf0) == | ||
1535 | 0x20)) { | ||
1536 | printk(KERN_ERR PFX "Error reading " | ||
1537 | "session %d: %x %s\n", | ||
1538 | session, single_toc.exec_status[0], | ||
1539 | translate_error(single_toc. | ||
1540 | exec_status[1])); | ||
1541 | /* An error reading the TOC. Return without sony_toc_read | ||
1542 | set. */ | ||
1543 | return; | ||
1544 | } | ||
1545 | pr_debug(PFX "add0 %01x, con0 %01x, poi0 %02x, " | ||
1546 | "1st trk %d, dsktyp %x, dum0 %x\n", | ||
1547 | single_toc.address0, single_toc.control0, | ||
1548 | single_toc.point0, | ||
1549 | bcd_to_int(single_toc.first_track_num), | ||
1550 | single_toc.disk_type, single_toc.dummy0); | ||
1551 | pr_debug(PFX "add1 %01x, con1 %01x, poi1 %02x, " | ||
1552 | "lst trk %d, dummy1 %x, dum2 %x\n", | ||
1553 | single_toc.address1, single_toc.control1, | ||
1554 | single_toc.point1, | ||
1555 | bcd_to_int(single_toc.last_track_num), | ||
1556 | single_toc.dummy1, single_toc.dummy2); | ||
1557 | pr_debug(PFX "add2 %01x, con2 %01x, poi2 %02x " | ||
1558 | "leadout start min %d, sec %d, frame %d\n", | ||
1559 | single_toc.address2, single_toc.control2, | ||
1560 | single_toc.point2, | ||
1561 | bcd_to_int(single_toc.lead_out_start_msf[0]), | ||
1562 | bcd_to_int(single_toc.lead_out_start_msf[1]), | ||
1563 | bcd_to_int(single_toc.lead_out_start_msf[2])); | ||
1564 | if (res_size > 18 && single_toc.pointb0 > 0xaf) | ||
1565 | pr_debug(PFX "addb0 %01x, conb0 %01x, poib0 %02x, nextsession min %d, sec %d, frame %d\n" | ||
1566 | "#mode5_ptrs %02d, max_start_outer_leadout_msf min %d, sec %d, frame %d\n", | ||
1567 | single_toc.addressb0, | ||
1568 | single_toc.controlb0, | ||
1569 | single_toc.pointb0, | ||
1570 | bcd_to_int(single_toc. | ||
1571 | next_poss_prog_area_msf | ||
1572 | [0]), | ||
1573 | bcd_to_int(single_toc. | ||
1574 | next_poss_prog_area_msf | ||
1575 | [1]), | ||
1576 | bcd_to_int(single_toc. | ||
1577 | next_poss_prog_area_msf | ||
1578 | [2]), | ||
1579 | single_toc.num_mode_5_pointers, | ||
1580 | bcd_to_int(single_toc. | ||
1581 | max_start_outer_leadout_msf | ||
1582 | [0]), | ||
1583 | bcd_to_int(single_toc. | ||
1584 | max_start_outer_leadout_msf | ||
1585 | [1]), | ||
1586 | bcd_to_int(single_toc. | ||
1587 | max_start_outer_leadout_msf | ||
1588 | [2])); | ||
1589 | if (res_size > 27 && single_toc.pointb1 > 0xaf) | ||
1590 | pr_debug(PFX "addb1 %01x, conb1 %01x, poib1 %02x, %x %x %x %x #skipint_ptrs %d, #skiptrkassign %d %x\n", | ||
1591 | single_toc.addressb1, | ||
1592 | single_toc.controlb1, | ||
1593 | single_toc.pointb1, | ||
1594 | single_toc.dummyb0_1[0], | ||
1595 | single_toc.dummyb0_1[1], | ||
1596 | single_toc.dummyb0_1[2], | ||
1597 | single_toc.dummyb0_1[3], | ||
1598 | single_toc.num_skip_interval_pointers, | ||
1599 | single_toc.num_skip_track_assignments, | ||
1600 | single_toc.dummyb0_2); | ||
1601 | if (res_size > 36 && single_toc.pointb2 > 0xaf) | ||
1602 | pr_debug(PFX "addb2 %01x, conb2 %01x, poib2 %02x, %02x %02x %02x %02x %02x %02x %02x\n", | ||
1603 | single_toc.addressb2, | ||
1604 | single_toc.controlb2, | ||
1605 | single_toc.pointb2, | ||
1606 | single_toc.tracksb2[0], | ||
1607 | single_toc.tracksb2[1], | ||
1608 | single_toc.tracksb2[2], | ||
1609 | single_toc.tracksb2[3], | ||
1610 | single_toc.tracksb2[4], | ||
1611 | single_toc.tracksb2[5], | ||
1612 | single_toc.tracksb2[6]); | ||
1613 | if (res_size > 45 && single_toc.pointb3 > 0xaf) | ||
1614 | pr_debug(PFX "addb3 %01x, conb3 %01x, poib3 %02x, %02x %02x %02x %02x %02x %02x %02x\n", | ||
1615 | single_toc.addressb3, | ||
1616 | single_toc.controlb3, | ||
1617 | single_toc.pointb3, | ||
1618 | single_toc.tracksb3[0], | ||
1619 | single_toc.tracksb3[1], | ||
1620 | single_toc.tracksb3[2], | ||
1621 | single_toc.tracksb3[3], | ||
1622 | single_toc.tracksb3[4], | ||
1623 | single_toc.tracksb3[5], | ||
1624 | single_toc.tracksb3[6]); | ||
1625 | if (res_size > 54 && single_toc.pointb4 > 0xaf) | ||
1626 | pr_debug(PFX "addb4 %01x, conb4 %01x, poib4 %02x, %02x %02x %02x %02x %02x %02x %02x\n", | ||
1627 | single_toc.addressb4, | ||
1628 | single_toc.controlb4, | ||
1629 | single_toc.pointb4, | ||
1630 | single_toc.tracksb4[0], | ||
1631 | single_toc.tracksb4[1], | ||
1632 | single_toc.tracksb4[2], | ||
1633 | single_toc.tracksb4[3], | ||
1634 | single_toc.tracksb4[4], | ||
1635 | single_toc.tracksb4[5], | ||
1636 | single_toc.tracksb4[6]); | ||
1637 | if (res_size > 63 && single_toc.pointc0 > 0xaf) | ||
1638 | pr_debug(PFX "addc0 %01x, conc0 %01x, poic0 %02x, %02x %02x %02x %02x %02x %02x %02x\n", | ||
1639 | single_toc.addressc0, | ||
1640 | single_toc.controlc0, | ||
1641 | single_toc.pointc0, | ||
1642 | single_toc.dummyc0[0], | ||
1643 | single_toc.dummyc0[1], | ||
1644 | single_toc.dummyc0[2], | ||
1645 | single_toc.dummyc0[3], | ||
1646 | single_toc.dummyc0[4], | ||
1647 | single_toc.dummyc0[5], | ||
1648 | single_toc.dummyc0[6]); | ||
1649 | #undef DEBUG | ||
1650 | #define DEBUG 0 | ||
1651 | |||
1652 | sony_toc.lead_out_start_msf[0] = | ||
1653 | bcd_to_int(single_toc.lead_out_start_msf[0]); | ||
1654 | sony_toc.lead_out_start_msf[1] = | ||
1655 | bcd_to_int(single_toc.lead_out_start_msf[1]); | ||
1656 | sony_toc.lead_out_start_msf[2] = | ||
1657 | bcd_to_int(single_toc.lead_out_start_msf[2]); | ||
1658 | sony_toc.lead_out_start_lba = | ||
1659 | single_toc.lead_out_start_lba = | ||
1660 | msf_to_log(sony_toc.lead_out_start_msf); | ||
1661 | |||
1662 | /* For points that do not exist, move the data over them | ||
1663 | to the right location. */ | ||
1664 | if (single_toc.pointb0 != 0xb0) { | ||
1665 | memmove(((char *) &single_toc) + 27, | ||
1666 | ((char *) &single_toc) + 18, | ||
1667 | res_size - 18); | ||
1668 | res_size += 9; | ||
1669 | } else if (res_size > 18) { | ||
1670 | sony_toc.lead_out_start_msf[0] = | ||
1671 | bcd_to_int(single_toc. | ||
1672 | max_start_outer_leadout_msf | ||
1673 | [0]); | ||
1674 | sony_toc.lead_out_start_msf[1] = | ||
1675 | bcd_to_int(single_toc. | ||
1676 | max_start_outer_leadout_msf | ||
1677 | [1]); | ||
1678 | sony_toc.lead_out_start_msf[2] = | ||
1679 | bcd_to_int(single_toc. | ||
1680 | max_start_outer_leadout_msf | ||
1681 | [2]); | ||
1682 | sony_toc.lead_out_start_lba = | ||
1683 | msf_to_log(sony_toc. | ||
1684 | lead_out_start_msf); | ||
1685 | } | ||
1686 | if (single_toc.pointb1 != 0xb1) { | ||
1687 | memmove(((char *) &single_toc) + 36, | ||
1688 | ((char *) &single_toc) + 27, | ||
1689 | res_size - 27); | ||
1690 | res_size += 9; | ||
1691 | } | ||
1692 | if (single_toc.pointb2 != 0xb2) { | ||
1693 | memmove(((char *) &single_toc) + 45, | ||
1694 | ((char *) &single_toc) + 36, | ||
1695 | res_size - 36); | ||
1696 | res_size += 9; | ||
1697 | } | ||
1698 | if (single_toc.pointb3 != 0xb3) { | ||
1699 | memmove(((char *) &single_toc) + 54, | ||
1700 | ((char *) &single_toc) + 45, | ||
1701 | res_size - 45); | ||
1702 | res_size += 9; | ||
1703 | } | ||
1704 | if (single_toc.pointb4 != 0xb4) { | ||
1705 | memmove(((char *) &single_toc) + 63, | ||
1706 | ((char *) &single_toc) + 54, | ||
1707 | res_size - 54); | ||
1708 | res_size += 9; | ||
1709 | } | ||
1710 | if (single_toc.pointc0 != 0xc0) { | ||
1711 | memmove(((char *) &single_toc) + 72, | ||
1712 | ((char *) &single_toc) + 63, | ||
1713 | res_size - 63); | ||
1714 | res_size += 9; | ||
1715 | } | ||
1716 | #if DEBUG | ||
1717 | printk(PRINT_INFO PFX "start track lba %u, " | ||
1718 | "leadout start lba %u\n", | ||
1719 | single_toc.start_track_lba, | ||
1720 | single_toc.lead_out_start_lba); | ||
1721 | { | ||
1722 | int i; | ||
1723 | for (i = 0; | ||
1724 | i < | ||
1725 | 1 + | ||
1726 | bcd_to_int(single_toc.last_track_num) | ||
1727 | - | ||
1728 | bcd_to_int(single_toc. | ||
1729 | first_track_num); i++) { | ||
1730 | printk(KERN_INFO PFX "trk %02d: add 0x%01x, con 0x%01x, track %02d, start min %02d, sec %02d, frame %02d\n", | ||
1731 | i, | ||
1732 | single_toc.tracks[i].address, | ||
1733 | single_toc.tracks[i].control, | ||
1734 | bcd_to_int(single_toc. | ||
1735 | tracks[i].track), | ||
1736 | bcd_to_int(single_toc. | ||
1737 | tracks[i]. | ||
1738 | track_start_msf | ||
1739 | [0]), | ||
1740 | bcd_to_int(single_toc. | ||
1741 | tracks[i]. | ||
1742 | track_start_msf | ||
1743 | [1]), | ||
1744 | bcd_to_int(single_toc. | ||
1745 | tracks[i]. | ||
1746 | track_start_msf | ||
1747 | [2])); | ||
1748 | if (mint > | ||
1749 | bcd_to_int(single_toc. | ||
1750 | tracks[i].track)) | ||
1751 | mint = | ||
1752 | bcd_to_int(single_toc. | ||
1753 | tracks[i]. | ||
1754 | track); | ||
1755 | if (maxt < | ||
1756 | bcd_to_int(single_toc. | ||
1757 | tracks[i].track)) | ||
1758 | maxt = | ||
1759 | bcd_to_int(single_toc. | ||
1760 | tracks[i]. | ||
1761 | track); | ||
1762 | } | ||
1763 | printk(KERN_INFO PFX "min track number %d, " | ||
1764 | "max track number %d\n", | ||
1765 | mint, maxt); | ||
1766 | } | ||
1767 | #endif | ||
1768 | |||
1769 | /* prepare a special table of contents for a CD-I disc. They don't have one. */ | ||
1770 | if (single_toc.disk_type == 0x10 && | ||
1771 | single_toc.first_track_num == 2 && | ||
1772 | single_toc.last_track_num == 2 /* CD-I */ ) { | ||
1773 | sony_toc.tracks[totaltracks].address = 1; | ||
1774 | sony_toc.tracks[totaltracks].control = 4; /* force data tracks */ | ||
1775 | sony_toc.tracks[totaltracks].track = 1; | ||
1776 | sony_toc.tracks[totaltracks]. | ||
1777 | track_start_msf[0] = 0; | ||
1778 | sony_toc.tracks[totaltracks]. | ||
1779 | track_start_msf[1] = 2; | ||
1780 | sony_toc.tracks[totaltracks]. | ||
1781 | track_start_msf[2] = 0; | ||
1782 | mint = maxt = 1; | ||
1783 | totaltracks++; | ||
1784 | } else | ||
1785 | /* gather track entries from this session */ | ||
1786 | { | ||
1787 | int i; | ||
1788 | for (i = 0; | ||
1789 | i < | ||
1790 | 1 + | ||
1791 | bcd_to_int(single_toc.last_track_num) | ||
1792 | - | ||
1793 | bcd_to_int(single_toc. | ||
1794 | first_track_num); | ||
1795 | i++, totaltracks++) { | ||
1796 | sony_toc.tracks[totaltracks]. | ||
1797 | address = | ||
1798 | single_toc.tracks[i].address; | ||
1799 | sony_toc.tracks[totaltracks]. | ||
1800 | control = | ||
1801 | single_toc.tracks[i].control; | ||
1802 | sony_toc.tracks[totaltracks]. | ||
1803 | track = | ||
1804 | bcd_to_int(single_toc. | ||
1805 | tracks[i].track); | ||
1806 | sony_toc.tracks[totaltracks]. | ||
1807 | track_start_msf[0] = | ||
1808 | bcd_to_int(single_toc. | ||
1809 | tracks[i]. | ||
1810 | track_start_msf[0]); | ||
1811 | sony_toc.tracks[totaltracks]. | ||
1812 | track_start_msf[1] = | ||
1813 | bcd_to_int(single_toc. | ||
1814 | tracks[i]. | ||
1815 | track_start_msf[1]); | ||
1816 | sony_toc.tracks[totaltracks]. | ||
1817 | track_start_msf[2] = | ||
1818 | bcd_to_int(single_toc. | ||
1819 | tracks[i]. | ||
1820 | track_start_msf[2]); | ||
1821 | if (i == 0) | ||
1822 | single_toc. | ||
1823 | start_track_lba = | ||
1824 | msf_to_log(sony_toc. | ||
1825 | tracks | ||
1826 | [totaltracks]. | ||
1827 | track_start_msf); | ||
1828 | if (mint > | ||
1829 | sony_toc.tracks[totaltracks]. | ||
1830 | track) | ||
1831 | mint = | ||
1832 | sony_toc. | ||
1833 | tracks[totaltracks]. | ||
1834 | track; | ||
1835 | if (maxt < | ||
1836 | sony_toc.tracks[totaltracks]. | ||
1837 | track) | ||
1838 | maxt = | ||
1839 | sony_toc. | ||
1840 | tracks[totaltracks]. | ||
1841 | track; | ||
1842 | } | ||
1843 | } | ||
1844 | sony_toc.first_track_num = mint; | ||
1845 | sony_toc.last_track_num = maxt; | ||
1846 | /* Disk type of last session wins. For example: | ||
1847 | CD-Extra has disk type 0 for the first session, so | ||
1848 | a dumb HiFi CD player thinks it is a plain audio CD. | ||
1849 | We are interested in the disk type of the last session, | ||
1850 | which is 0x20 (XA) for CD-Extra, so we can access the | ||
1851 | data track ... */ | ||
1852 | sony_toc.disk_type = single_toc.disk_type; | ||
1853 | sony_toc.sessions = session; | ||
1854 | |||
1855 | /* don't believe everything :-) */ | ||
1856 | if (session == 1) | ||
1857 | single_toc.start_track_lba = 0; | ||
1858 | sony_toc.start_track_lba = | ||
1859 | single_toc.start_track_lba; | ||
1860 | |||
1861 | if (session > 1 && single_toc.pointb0 == 0xb0 && | ||
1862 | sony_toc.lead_out_start_lba == | ||
1863 | single_toc.lead_out_start_lba) { | ||
1864 | break; | ||
1865 | } | ||
1866 | |||
1867 | /* Let's not get carried away... */ | ||
1868 | if (session > 40) { | ||
1869 | printk(KERN_NOTICE PFX "too many sessions: " | ||
1870 | "%d\n", session); | ||
1871 | break; | ||
1872 | } | ||
1873 | session++; | ||
1874 | } | ||
1875 | sony_toc.track_entries = totaltracks; | ||
1876 | /* add one entry for the LAST track with track number CDROM_LEADOUT */ | ||
1877 | sony_toc.tracks[totaltracks].address = single_toc.address2; | ||
1878 | sony_toc.tracks[totaltracks].control = single_toc.control2; | ||
1879 | sony_toc.tracks[totaltracks].track = CDROM_LEADOUT; | ||
1880 | sony_toc.tracks[totaltracks].track_start_msf[0] = | ||
1881 | sony_toc.lead_out_start_msf[0]; | ||
1882 | sony_toc.tracks[totaltracks].track_start_msf[1] = | ||
1883 | sony_toc.lead_out_start_msf[1]; | ||
1884 | sony_toc.tracks[totaltracks].track_start_msf[2] = | ||
1885 | sony_toc.lead_out_start_msf[2]; | ||
1886 | |||
1887 | sony_toc_read = 1; | ||
1888 | |||
1889 | pr_debug(PFX "Disk session %d, start track: %d, " | ||
1890 | "stop track: %d\n", | ||
1891 | session, single_toc.start_track_lba, | ||
1892 | single_toc.lead_out_start_lba); | ||
1893 | } | ||
1894 | pr_debug(PFX "Leaving %s\n", __FUNCTION__); | ||
1895 | } | ||
1896 | |||
1897 | |||
1898 | /* | ||
1899 | * Uniform cdrom interface function | ||
1900 | * return multisession offset and sector information | ||
1901 | */ | ||
1902 | static int scd_get_last_session(struct cdrom_device_info *cdi, | ||
1903 | struct cdrom_multisession *ms_info) | ||
1904 | { | ||
1905 | if (ms_info == NULL) | ||
1906 | return 1; | ||
1907 | |||
1908 | if (!sony_toc_read) { | ||
1909 | if (down_interruptible(&sony_sem)) | ||
1910 | return -ERESTARTSYS; | ||
1911 | sony_get_toc(); | ||
1912 | up(&sony_sem); | ||
1913 | } | ||
1914 | |||
1915 | ms_info->addr_format = CDROM_LBA; | ||
1916 | ms_info->addr.lba = sony_toc.start_track_lba; | ||
1917 | ms_info->xa_flag = sony_toc.disk_type == SONY_XA_DISK_TYPE || | ||
1918 | sony_toc.disk_type == 0x10 /* CDI */ ; | ||
1919 | |||
1920 | return 0; | ||
1921 | } | ||
1922 | |||
1923 | /* | ||
1924 | * Search for a specific track in the table of contents. | ||
1925 | */ | ||
1926 | static int find_track(int track) | ||
1927 | { | ||
1928 | int i; | ||
1929 | |||
1930 | for (i = 0; i <= sony_toc.track_entries; i++) { | ||
1931 | if (sony_toc.tracks[i].track == track) { | ||
1932 | return i; | ||
1933 | } | ||
1934 | } | ||
1935 | |||
1936 | return -1; | ||
1937 | } | ||
1938 | |||
1939 | |||
1940 | /* | ||
1941 | * Read the subcode and put it in last_sony_subcode for future use. | ||
1942 | */ | ||
1943 | static int read_subcode(void) | ||
1944 | { | ||
1945 | unsigned int res_size; | ||
1946 | |||
1947 | |||
1948 | do_sony_cd_cmd(SONY_REQ_SUBCODE_ADDRESS_CMD, | ||
1949 | NULL, | ||
1950 | 0, (unsigned char *) &last_sony_subcode, &res_size); | ||
1951 | if ((res_size < 2) | ||
1952 | || ((last_sony_subcode.exec_status[0] & 0xf0) == 0x20)) { | ||
1953 | printk(KERN_ERR PFX "Sony CDROM error %s (read_subcode)\n", | ||
1954 | translate_error(last_sony_subcode.exec_status[1])); | ||
1955 | return -EIO; | ||
1956 | } | ||
1957 | |||
1958 | last_sony_subcode.track_num = | ||
1959 | bcd_to_int(last_sony_subcode.track_num); | ||
1960 | last_sony_subcode.index_num = | ||
1961 | bcd_to_int(last_sony_subcode.index_num); | ||
1962 | last_sony_subcode.abs_msf[0] = | ||
1963 | bcd_to_int(last_sony_subcode.abs_msf[0]); | ||
1964 | last_sony_subcode.abs_msf[1] = | ||
1965 | bcd_to_int(last_sony_subcode.abs_msf[1]); | ||
1966 | last_sony_subcode.abs_msf[2] = | ||
1967 | bcd_to_int(last_sony_subcode.abs_msf[2]); | ||
1968 | |||
1969 | last_sony_subcode.rel_msf[0] = | ||
1970 | bcd_to_int(last_sony_subcode.rel_msf[0]); | ||
1971 | last_sony_subcode.rel_msf[1] = | ||
1972 | bcd_to_int(last_sony_subcode.rel_msf[1]); | ||
1973 | last_sony_subcode.rel_msf[2] = | ||
1974 | bcd_to_int(last_sony_subcode.rel_msf[2]); | ||
1975 | return 0; | ||
1976 | } | ||
1977 | |||
1978 | /* | ||
1979 | * Uniform cdrom interface function | ||
1980 | * return the media catalog number found on some older audio cds | ||
1981 | */ | ||
1982 | static int | ||
1983 | scd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn) | ||
1984 | { | ||
1985 | unsigned char resbuffer[2 + 14]; | ||
1986 | unsigned char *mcnp = mcn->medium_catalog_number; | ||
1987 | unsigned char *resp = resbuffer + 3; | ||
1988 | unsigned int res_size; | ||
1989 | |||
1990 | memset(mcn->medium_catalog_number, 0, 14); | ||
1991 | if (down_interruptible(&sony_sem)) | ||
1992 | return -ERESTARTSYS; | ||
1993 | do_sony_cd_cmd(SONY_REQ_UPC_EAN_CMD, | ||
1994 | NULL, 0, resbuffer, &res_size); | ||
1995 | up(&sony_sem); | ||
1996 | if ((res_size < 2) || ((resbuffer[0] & 0xf0) == 0x20)); | ||
1997 | else { | ||
1998 | /* packed bcd to single ASCII digits */ | ||
1999 | *mcnp++ = (*resp >> 4) + '0'; | ||
2000 | *mcnp++ = (*resp++ & 0x0f) + '0'; | ||
2001 | *mcnp++ = (*resp >> 4) + '0'; | ||
2002 | *mcnp++ = (*resp++ & 0x0f) + '0'; | ||
2003 | *mcnp++ = (*resp >> 4) + '0'; | ||
2004 | *mcnp++ = (*resp++ & 0x0f) + '0'; | ||
2005 | *mcnp++ = (*resp >> 4) + '0'; | ||
2006 | *mcnp++ = (*resp++ & 0x0f) + '0'; | ||
2007 | *mcnp++ = (*resp >> 4) + '0'; | ||
2008 | *mcnp++ = (*resp++ & 0x0f) + '0'; | ||
2009 | *mcnp++ = (*resp >> 4) + '0'; | ||
2010 | *mcnp++ = (*resp++ & 0x0f) + '0'; | ||
2011 | *mcnp++ = (*resp >> 4) + '0'; | ||
2012 | } | ||
2013 | *mcnp = '\0'; | ||
2014 | return 0; | ||
2015 | } | ||
2016 | |||
2017 | |||
2018 | /* | ||
2019 | * Get the subchannel info like the CDROMSUBCHNL command wants to see it. If | ||
2020 | * the drive is playing, the subchannel needs to be read (since it would be | ||
2021 | * changing). If the drive is paused or completed, the subcode information has | ||
2022 | * already been stored, just use that. The ioctl call wants things in decimal | ||
2023 | * (not BCD), so all the conversions are done. | ||
2024 | */ | ||
2025 | static int sony_get_subchnl_info(struct cdrom_subchnl *schi) | ||
2026 | { | ||
2027 | /* Get attention stuff */ | ||
2028 | while (handle_sony_cd_attention()); | ||
2029 | |||
2030 | sony_get_toc(); | ||
2031 | if (!sony_toc_read) { | ||
2032 | return -EIO; | ||
2033 | } | ||
2034 | |||
2035 | switch (sony_audio_status) { | ||
2036 | case CDROM_AUDIO_NO_STATUS: | ||
2037 | case CDROM_AUDIO_PLAY: | ||
2038 | if (read_subcode() < 0) { | ||
2039 | return -EIO; | ||
2040 | } | ||
2041 | break; | ||
2042 | |||
2043 | case CDROM_AUDIO_PAUSED: | ||
2044 | case CDROM_AUDIO_COMPLETED: | ||
2045 | break; | ||
2046 | |||
2047 | #if 0 | ||
2048 | case CDROM_AUDIO_NO_STATUS: | ||
2049 | schi->cdsc_audiostatus = sony_audio_status; | ||
2050 | return 0; | ||
2051 | break; | ||
2052 | #endif | ||
2053 | case CDROM_AUDIO_INVALID: | ||
2054 | case CDROM_AUDIO_ERROR: | ||
2055 | default: | ||
2056 | return -EIO; | ||
2057 | } | ||
2058 | |||
2059 | schi->cdsc_audiostatus = sony_audio_status; | ||
2060 | schi->cdsc_adr = last_sony_subcode.address; | ||
2061 | schi->cdsc_ctrl = last_sony_subcode.control; | ||
2062 | schi->cdsc_trk = last_sony_subcode.track_num; | ||
2063 | schi->cdsc_ind = last_sony_subcode.index_num; | ||
2064 | if (schi->cdsc_format == CDROM_MSF) { | ||
2065 | schi->cdsc_absaddr.msf.minute = | ||
2066 | last_sony_subcode.abs_msf[0]; | ||
2067 | schi->cdsc_absaddr.msf.second = | ||
2068 | last_sony_subcode.abs_msf[1]; | ||
2069 | schi->cdsc_absaddr.msf.frame = | ||
2070 | last_sony_subcode.abs_msf[2]; | ||
2071 | |||
2072 | schi->cdsc_reladdr.msf.minute = | ||
2073 | last_sony_subcode.rel_msf[0]; | ||
2074 | schi->cdsc_reladdr.msf.second = | ||
2075 | last_sony_subcode.rel_msf[1]; | ||
2076 | schi->cdsc_reladdr.msf.frame = | ||
2077 | last_sony_subcode.rel_msf[2]; | ||
2078 | } else if (schi->cdsc_format == CDROM_LBA) { | ||
2079 | schi->cdsc_absaddr.lba = | ||
2080 | msf_to_log(last_sony_subcode.abs_msf); | ||
2081 | schi->cdsc_reladdr.lba = | ||
2082 | msf_to_log(last_sony_subcode.rel_msf); | ||
2083 | } | ||
2084 | |||
2085 | return 0; | ||
2086 | } | ||
2087 | |||
2088 | /* Get audio data from the drive. This is fairly complex because I | ||
2089 | am looking for status and data at the same time, but if I get status | ||
2090 | then I just look for data. I need to get the status immediately so | ||
2091 | the switch from audio to data tracks will happen quickly. */ | ||
2092 | static void | ||
2093 | read_audio_data(char *buffer, unsigned char res_reg[], int *res_size) | ||
2094 | { | ||
2095 | unsigned long retry_count; | ||
2096 | int result_read; | ||
2097 | |||
2098 | |||
2099 | res_reg[0] = 0; | ||
2100 | res_reg[1] = 0; | ||
2101 | *res_size = 0; | ||
2102 | result_read = 0; | ||
2103 | |||
2104 | /* Wait for the drive to tell us we have something */ | ||
2105 | retry_count = jiffies + SONY_JIFFIES_TIMEOUT; | ||
2106 | continue_read_audio_wait: | ||
2107 | while (time_before(jiffies, retry_count) && !(is_data_ready()) | ||
2108 | && !(is_result_ready() || result_read)) { | ||
2109 | while (handle_sony_cd_attention()); | ||
2110 | |||
2111 | sony_sleep(); | ||
2112 | } | ||
2113 | if (!(is_data_ready())) { | ||
2114 | if (is_result_ready() && !result_read) { | ||
2115 | get_result(res_reg, res_size); | ||
2116 | |||
2117 | /* Read block status and continue waiting for data. */ | ||
2118 | if ((res_reg[0] & 0xf0) == 0x50) { | ||
2119 | result_read = 1; | ||
2120 | goto continue_read_audio_wait; | ||
2121 | } | ||
2122 | /* Invalid data from the drive. Shut down the operation. */ | ||
2123 | else if ((res_reg[0] & 0xf0) != 0x20) { | ||
2124 | printk(KERN_WARNING PFX "Got result that " | ||
2125 | "should have been error: %d\n", | ||
2126 | res_reg[0]); | ||
2127 | res_reg[0] = 0x20; | ||
2128 | res_reg[1] = SONY_BAD_DATA_ERR; | ||
2129 | *res_size = 2; | ||
2130 | } | ||
2131 | abort_read(); | ||
2132 | } else { | ||
2133 | pr_debug(PFX "timeout out %d\n", __LINE__); | ||
2134 | res_reg[0] = 0x20; | ||
2135 | res_reg[1] = SONY_TIMEOUT_OP_ERR; | ||
2136 | *res_size = 2; | ||
2137 | abort_read(); | ||
2138 | } | ||
2139 | } else { | ||
2140 | clear_data_ready(); | ||
2141 | |||
2142 | /* If data block, then get 2340 bytes offset by 12. */ | ||
2143 | if (sony_raw_data_mode) { | ||
2144 | insb(sony_cd_read_reg, buffer + CD_XA_HEAD, | ||
2145 | CD_FRAMESIZE_RAW1); | ||
2146 | } else { | ||
2147 | /* Audio gets the whole 2352 bytes. */ | ||
2148 | insb(sony_cd_read_reg, buffer, CD_FRAMESIZE_RAW); | ||
2149 | } | ||
2150 | |||
2151 | /* If I haven't already gotten the result, get it now. */ | ||
2152 | if (!result_read) { | ||
2153 | /* Wait for the drive to tell us we have something */ | ||
2154 | retry_count = jiffies + SONY_JIFFIES_TIMEOUT; | ||
2155 | while (time_before(jiffies, retry_count) | ||
2156 | && !(is_result_ready())) { | ||
2157 | while (handle_sony_cd_attention()); | ||
2158 | |||
2159 | sony_sleep(); | ||
2160 | } | ||
2161 | |||
2162 | if (!is_result_ready()) { | ||
2163 | pr_debug(PFX "timeout out %d\n", __LINE__); | ||
2164 | res_reg[0] = 0x20; | ||
2165 | res_reg[1] = SONY_TIMEOUT_OP_ERR; | ||
2166 | *res_size = 2; | ||
2167 | abort_read(); | ||
2168 | return; | ||
2169 | } else { | ||
2170 | get_result(res_reg, res_size); | ||
2171 | } | ||
2172 | } | ||
2173 | |||
2174 | if ((res_reg[0] & 0xf0) == 0x50) { | ||
2175 | if ((res_reg[0] == SONY_NO_CIRC_ERR_BLK_STAT) | ||
2176 | || (res_reg[0] == SONY_NO_LECC_ERR_BLK_STAT) | ||
2177 | || (res_reg[0] == SONY_RECOV_LECC_ERR_BLK_STAT) | ||
2178 | || (res_reg[0] == SONY_NO_ERR_DETECTION_STAT)) { | ||
2179 | /* Ok, nothing to do. */ | ||
2180 | } else { | ||
2181 | printk(KERN_ERR PFX "Data block error: 0x%x\n", | ||
2182 | res_reg[0]); | ||
2183 | res_reg[0] = 0x20; | ||
2184 | res_reg[1] = SONY_BAD_DATA_ERR; | ||
2185 | *res_size = 2; | ||
2186 | } | ||
2187 | } else if ((res_reg[0] & 0xf0) != 0x20) { | ||
2188 | /* The drive gave me bad status, I don't know what to do. | ||
2189 | Reset the driver and return an error. */ | ||
2190 | printk(KERN_NOTICE PFX "Invalid block status: 0x%x\n", | ||
2191 | res_reg[0]); | ||
2192 | restart_on_error(); | ||
2193 | res_reg[0] = 0x20; | ||
2194 | res_reg[1] = SONY_BAD_DATA_ERR; | ||
2195 | *res_size = 2; | ||
2196 | } | ||
2197 | } | ||
2198 | } | ||
2199 | |||
2200 | /* Perform a raw data read. This will automatically detect the | ||
2201 | track type and read the proper data (audio or data). */ | ||
2202 | static int read_audio(struct cdrom_read_audio *ra) | ||
2203 | { | ||
2204 | int retval; | ||
2205 | unsigned char params[2]; | ||
2206 | unsigned char res_reg[12]; | ||
2207 | unsigned int res_size; | ||
2208 | unsigned int cframe; | ||
2209 | |||
2210 | if (down_interruptible(&sony_sem)) | ||
2211 | return -ERESTARTSYS; | ||
2212 | if (!sony_spun_up) | ||
2213 | scd_spinup(); | ||
2214 | |||
2215 | /* Set the drive to do raw operations. */ | ||
2216 | params[0] = SONY_SD_DECODE_PARAM; | ||
2217 | params[1] = 0x06 | sony_raw_data_mode; | ||
2218 | do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD, | ||
2219 | params, 2, res_reg, &res_size); | ||
2220 | if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) { | ||
2221 | printk(KERN_ERR PFX "Unable to set decode params: 0x%2.2x\n", | ||
2222 | res_reg[1]); | ||
2223 | retval = -EIO; | ||
2224 | goto out_up; | ||
2225 | } | ||
2226 | |||
2227 | /* From here down, we have to goto exit_read_audio instead of returning | ||
2228 | because the drive parameters have to be set back to data before | ||
2229 | return. */ | ||
2230 | |||
2231 | retval = 0; | ||
2232 | if (start_request(ra->addr.lba, ra->nframes)) { | ||
2233 | retval = -EIO; | ||
2234 | goto exit_read_audio; | ||
2235 | } | ||
2236 | |||
2237 | /* For every requested frame. */ | ||
2238 | cframe = 0; | ||
2239 | while (cframe < ra->nframes) { | ||
2240 | read_audio_data(audio_buffer, res_reg, &res_size); | ||
2241 | if ((res_reg[0] & 0xf0) == 0x20) { | ||
2242 | if (res_reg[1] == SONY_BAD_DATA_ERR) { | ||
2243 | printk(KERN_ERR PFX "Data error on audio " | ||
2244 | "sector %d\n", | ||
2245 | ra->addr.lba + cframe); | ||
2246 | } else if (res_reg[1] == SONY_ILL_TRACK_R_ERR) { | ||
2247 | /* Illegal track type, change track types and start over. */ | ||
2248 | sony_raw_data_mode = | ||
2249 | (sony_raw_data_mode) ? 0 : 1; | ||
2250 | |||
2251 | /* Set the drive mode. */ | ||
2252 | params[0] = SONY_SD_DECODE_PARAM; | ||
2253 | params[1] = 0x06 | sony_raw_data_mode; | ||
2254 | do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD, | ||
2255 | params, | ||
2256 | 2, res_reg, &res_size); | ||
2257 | if ((res_size < 2) | ||
2258 | || ((res_reg[0] & 0xf0) == 0x20)) { | ||
2259 | printk(KERN_ERR PFX "Unable to set " | ||
2260 | "decode params: 0x%2.2x\n", | ||
2261 | res_reg[1]); | ||
2262 | retval = -EIO; | ||
2263 | goto exit_read_audio; | ||
2264 | } | ||
2265 | |||
2266 | /* Restart the request on the current frame. */ | ||
2267 | if (start_request | ||
2268 | (ra->addr.lba + cframe, | ||
2269 | ra->nframes - cframe)) { | ||
2270 | retval = -EIO; | ||
2271 | goto exit_read_audio; | ||
2272 | } | ||
2273 | |||
2274 | /* Don't go back to the top because don't want to get into | ||
2275 | and infinite loop. A lot of code gets duplicated, but | ||
2276 | that's no big deal, I don't guess. */ | ||
2277 | read_audio_data(audio_buffer, res_reg, | ||
2278 | &res_size); | ||
2279 | if ((res_reg[0] & 0xf0) == 0x20) { | ||
2280 | if (res_reg[1] == | ||
2281 | SONY_BAD_DATA_ERR) { | ||
2282 | printk(KERN_ERR PFX "Data error" | ||
2283 | " on audio sector %d\n", | ||
2284 | ra->addr.lba + | ||
2285 | cframe); | ||
2286 | } else { | ||
2287 | printk(KERN_ERR PFX "Error reading audio data on sector %d: %s\n", | ||
2288 | ra->addr.lba + cframe, | ||
2289 | translate_error | ||
2290 | (res_reg[1])); | ||
2291 | retval = -EIO; | ||
2292 | goto exit_read_audio; | ||
2293 | } | ||
2294 | } else if (copy_to_user(ra->buf + | ||
2295 | (CD_FRAMESIZE_RAW | ||
2296 | * cframe), | ||
2297 | audio_buffer, | ||
2298 | CD_FRAMESIZE_RAW)) { | ||
2299 | retval = -EFAULT; | ||
2300 | goto exit_read_audio; | ||
2301 | } | ||
2302 | } else { | ||
2303 | printk(KERN_ERR PFX "Error reading audio " | ||
2304 | "data on sector %d: %s\n", | ||
2305 | ra->addr.lba + cframe, | ||
2306 | translate_error(res_reg[1])); | ||
2307 | retval = -EIO; | ||
2308 | goto exit_read_audio; | ||
2309 | } | ||
2310 | } else if (copy_to_user(ra->buf + (CD_FRAMESIZE_RAW * cframe), | ||
2311 | (char *)audio_buffer, | ||
2312 | CD_FRAMESIZE_RAW)) { | ||
2313 | retval = -EFAULT; | ||
2314 | goto exit_read_audio; | ||
2315 | } | ||
2316 | |||
2317 | cframe++; | ||
2318 | } | ||
2319 | |||
2320 | get_result(res_reg, &res_size); | ||
2321 | if ((res_reg[0] & 0xf0) == 0x20) { | ||
2322 | printk(KERN_ERR PFX "Error return from audio read: %s\n", | ||
2323 | translate_error(res_reg[1])); | ||
2324 | retval = -EIO; | ||
2325 | goto exit_read_audio; | ||
2326 | } | ||
2327 | |||
2328 | exit_read_audio: | ||
2329 | |||
2330 | /* Set the drive mode back to the proper one for the disk. */ | ||
2331 | params[0] = SONY_SD_DECODE_PARAM; | ||
2332 | if (!sony_xa_mode) { | ||
2333 | params[1] = 0x0f; | ||
2334 | } else { | ||
2335 | params[1] = 0x07; | ||
2336 | } | ||
2337 | do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD, | ||
2338 | params, 2, res_reg, &res_size); | ||
2339 | if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) { | ||
2340 | printk(KERN_ERR PFX "Unable to reset decode params: 0x%2.2x\n", | ||
2341 | res_reg[1]); | ||
2342 | retval = -EIO; | ||
2343 | } | ||
2344 | |||
2345 | out_up: | ||
2346 | up(&sony_sem); | ||
2347 | |||
2348 | return retval; | ||
2349 | } | ||
2350 | |||
2351 | static int | ||
2352 | do_sony_cd_cmd_chk(const char *name, | ||
2353 | unsigned char cmd, | ||
2354 | unsigned char *params, | ||
2355 | unsigned int num_params, | ||
2356 | unsigned char *result_buffer, unsigned int *result_size) | ||
2357 | { | ||
2358 | do_sony_cd_cmd(cmd, params, num_params, result_buffer, | ||
2359 | result_size); | ||
2360 | if ((*result_size < 2) || ((result_buffer[0] & 0xf0) == 0x20)) { | ||
2361 | printk(KERN_ERR PFX "Error %s (CDROM%s)\n", | ||
2362 | translate_error(result_buffer[1]), name); | ||
2363 | return -EIO; | ||
2364 | } | ||
2365 | return 0; | ||
2366 | } | ||
2367 | |||
2368 | /* | ||
2369 | * Uniform cdrom interface function | ||
2370 | * open the tray | ||
2371 | */ | ||
2372 | static int scd_tray_move(struct cdrom_device_info *cdi, int position) | ||
2373 | { | ||
2374 | int retval; | ||
2375 | |||
2376 | if (down_interruptible(&sony_sem)) | ||
2377 | return -ERESTARTSYS; | ||
2378 | if (position == 1 /* open tray */ ) { | ||
2379 | unsigned char res_reg[12]; | ||
2380 | unsigned int res_size; | ||
2381 | |||
2382 | do_sony_cd_cmd(SONY_AUDIO_STOP_CMD, NULL, 0, res_reg, | ||
2383 | &res_size); | ||
2384 | do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg, | ||
2385 | &res_size); | ||
2386 | |||
2387 | sony_audio_status = CDROM_AUDIO_INVALID; | ||
2388 | retval = do_sony_cd_cmd_chk("EJECT", SONY_EJECT_CMD, NULL, 0, | ||
2389 | res_reg, &res_size); | ||
2390 | } else { | ||
2391 | if (0 == scd_spinup()) | ||
2392 | sony_spun_up = 1; | ||
2393 | retval = 0; | ||
2394 | } | ||
2395 | up(&sony_sem); | ||
2396 | return retval; | ||
2397 | } | ||
2398 | |||
2399 | /* | ||
2400 | * The big ugly ioctl handler. | ||
2401 | */ | ||
2402 | static int scd_audio_ioctl(struct cdrom_device_info *cdi, | ||
2403 | unsigned int cmd, void *arg) | ||
2404 | { | ||
2405 | unsigned char res_reg[12]; | ||
2406 | unsigned int res_size; | ||
2407 | unsigned char params[7]; | ||
2408 | int i, retval; | ||
2409 | |||
2410 | if (down_interruptible(&sony_sem)) | ||
2411 | return -ERESTARTSYS; | ||
2412 | switch (cmd) { | ||
2413 | case CDROMSTART: /* Spin up the drive */ | ||
2414 | retval = do_sony_cd_cmd_chk("START", SONY_SPIN_UP_CMD, NULL, | ||
2415 | 0, res_reg, &res_size); | ||
2416 | break; | ||
2417 | |||
2418 | case CDROMSTOP: /* Spin down the drive */ | ||
2419 | do_sony_cd_cmd(SONY_AUDIO_STOP_CMD, NULL, 0, res_reg, | ||
2420 | &res_size); | ||
2421 | |||
2422 | /* | ||
2423 | * Spin the drive down, ignoring the error if the disk was | ||
2424 | * already not spinning. | ||
2425 | */ | ||
2426 | sony_audio_status = CDROM_AUDIO_NO_STATUS; | ||
2427 | retval = do_sony_cd_cmd_chk("STOP", SONY_SPIN_DOWN_CMD, NULL, | ||
2428 | 0, res_reg, &res_size); | ||
2429 | break; | ||
2430 | |||
2431 | case CDROMPAUSE: /* Pause the drive */ | ||
2432 | if (do_sony_cd_cmd_chk | ||
2433 | ("PAUSE", SONY_AUDIO_STOP_CMD, NULL, 0, res_reg, | ||
2434 | &res_size)) { | ||
2435 | retval = -EIO; | ||
2436 | break; | ||
2437 | } | ||
2438 | /* Get the current position and save it for resuming */ | ||
2439 | if (read_subcode() < 0) { | ||
2440 | retval = -EIO; | ||
2441 | break; | ||
2442 | } | ||
2443 | cur_pos_msf[0] = last_sony_subcode.abs_msf[0]; | ||
2444 | cur_pos_msf[1] = last_sony_subcode.abs_msf[1]; | ||
2445 | cur_pos_msf[2] = last_sony_subcode.abs_msf[2]; | ||
2446 | sony_audio_status = CDROM_AUDIO_PAUSED; | ||
2447 | retval = 0; | ||
2448 | break; | ||
2449 | |||
2450 | case CDROMRESUME: /* Start the drive after being paused */ | ||
2451 | if (sony_audio_status != CDROM_AUDIO_PAUSED) { | ||
2452 | retval = -EINVAL; | ||
2453 | break; | ||
2454 | } | ||
2455 | |||
2456 | do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, | ||
2457 | &res_size); | ||
2458 | |||
2459 | /* Start the drive at the saved position. */ | ||
2460 | params[1] = int_to_bcd(cur_pos_msf[0]); | ||
2461 | params[2] = int_to_bcd(cur_pos_msf[1]); | ||
2462 | params[3] = int_to_bcd(cur_pos_msf[2]); | ||
2463 | params[4] = int_to_bcd(final_pos_msf[0]); | ||
2464 | params[5] = int_to_bcd(final_pos_msf[1]); | ||
2465 | params[6] = int_to_bcd(final_pos_msf[2]); | ||
2466 | params[0] = 0x03; | ||
2467 | if (do_sony_cd_cmd_chk | ||
2468 | ("RESUME", SONY_AUDIO_PLAYBACK_CMD, params, 7, res_reg, | ||
2469 | &res_size) < 0) { | ||
2470 | retval = -EIO; | ||
2471 | break; | ||
2472 | } | ||
2473 | sony_audio_status = CDROM_AUDIO_PLAY; | ||
2474 | retval = 0; | ||
2475 | break; | ||
2476 | |||
2477 | case CDROMPLAYMSF: /* Play starting at the given MSF address. */ | ||
2478 | do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, | ||
2479 | &res_size); | ||
2480 | |||
2481 | /* The parameters are given in int, must be converted */ | ||
2482 | for (i = 1; i < 7; i++) { | ||
2483 | params[i] = | ||
2484 | int_to_bcd(((unsigned char *) arg)[i - 1]); | ||
2485 | } | ||
2486 | params[0] = 0x03; | ||
2487 | if (do_sony_cd_cmd_chk | ||
2488 | ("PLAYMSF", SONY_AUDIO_PLAYBACK_CMD, params, 7, | ||
2489 | res_reg, &res_size) < 0) { | ||
2490 | retval = -EIO; | ||
2491 | break; | ||
2492 | } | ||
2493 | |||
2494 | /* Save the final position for pauses and resumes */ | ||
2495 | final_pos_msf[0] = bcd_to_int(params[4]); | ||
2496 | final_pos_msf[1] = bcd_to_int(params[5]); | ||
2497 | final_pos_msf[2] = bcd_to_int(params[6]); | ||
2498 | sony_audio_status = CDROM_AUDIO_PLAY; | ||
2499 | retval = 0; | ||
2500 | break; | ||
2501 | |||
2502 | case CDROMREADTOCHDR: /* Read the table of contents header */ | ||
2503 | { | ||
2504 | struct cdrom_tochdr *hdr; | ||
2505 | |||
2506 | sony_get_toc(); | ||
2507 | if (!sony_toc_read) { | ||
2508 | retval = -EIO; | ||
2509 | break; | ||
2510 | } | ||
2511 | |||
2512 | hdr = (struct cdrom_tochdr *) arg; | ||
2513 | hdr->cdth_trk0 = sony_toc.first_track_num; | ||
2514 | hdr->cdth_trk1 = sony_toc.last_track_num; | ||
2515 | } | ||
2516 | retval = 0; | ||
2517 | break; | ||
2518 | |||
2519 | case CDROMREADTOCENTRY: /* Read a given table of contents entry */ | ||
2520 | { | ||
2521 | struct cdrom_tocentry *entry; | ||
2522 | int track_idx; | ||
2523 | unsigned char *msf_val = NULL; | ||
2524 | |||
2525 | sony_get_toc(); | ||
2526 | if (!sony_toc_read) { | ||
2527 | retval = -EIO; | ||
2528 | break; | ||
2529 | } | ||
2530 | |||
2531 | entry = (struct cdrom_tocentry *) arg; | ||
2532 | |||
2533 | track_idx = find_track(entry->cdte_track); | ||
2534 | if (track_idx < 0) { | ||
2535 | retval = -EINVAL; | ||
2536 | break; | ||
2537 | } | ||
2538 | |||
2539 | entry->cdte_adr = | ||
2540 | sony_toc.tracks[track_idx].address; | ||
2541 | entry->cdte_ctrl = | ||
2542 | sony_toc.tracks[track_idx].control; | ||
2543 | msf_val = | ||
2544 | sony_toc.tracks[track_idx].track_start_msf; | ||
2545 | |||
2546 | /* Logical buffer address or MSF format requested? */ | ||
2547 | if (entry->cdte_format == CDROM_LBA) { | ||
2548 | entry->cdte_addr.lba = msf_to_log(msf_val); | ||
2549 | } else if (entry->cdte_format == CDROM_MSF) { | ||
2550 | entry->cdte_addr.msf.minute = *msf_val; | ||
2551 | entry->cdte_addr.msf.second = | ||
2552 | *(msf_val + 1); | ||
2553 | entry->cdte_addr.msf.frame = | ||
2554 | *(msf_val + 2); | ||
2555 | } | ||
2556 | } | ||
2557 | retval = 0; | ||
2558 | break; | ||
2559 | |||
2560 | case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */ | ||
2561 | { | ||
2562 | struct cdrom_ti *ti = (struct cdrom_ti *) arg; | ||
2563 | int track_idx; | ||
2564 | |||
2565 | sony_get_toc(); | ||
2566 | if (!sony_toc_read) { | ||
2567 | retval = -EIO; | ||
2568 | break; | ||
2569 | } | ||
2570 | |||
2571 | if ((ti->cdti_trk0 < sony_toc.first_track_num) | ||
2572 | || (ti->cdti_trk0 > sony_toc.last_track_num) | ||
2573 | || (ti->cdti_trk1 < ti->cdti_trk0)) { | ||
2574 | retval = -EINVAL; | ||
2575 | break; | ||
2576 | } | ||
2577 | |||
2578 | track_idx = find_track(ti->cdti_trk0); | ||
2579 | if (track_idx < 0) { | ||
2580 | retval = -EINVAL; | ||
2581 | break; | ||
2582 | } | ||
2583 | params[1] = | ||
2584 | int_to_bcd(sony_toc.tracks[track_idx]. | ||
2585 | track_start_msf[0]); | ||
2586 | params[2] = | ||
2587 | int_to_bcd(sony_toc.tracks[track_idx]. | ||
2588 | track_start_msf[1]); | ||
2589 | params[3] = | ||
2590 | int_to_bcd(sony_toc.tracks[track_idx]. | ||
2591 | track_start_msf[2]); | ||
2592 | |||
2593 | /* | ||
2594 | * If we want to stop after the last track, use the lead-out | ||
2595 | * MSF to do that. | ||
2596 | */ | ||
2597 | if (ti->cdti_trk1 >= sony_toc.last_track_num) { | ||
2598 | track_idx = find_track(CDROM_LEADOUT); | ||
2599 | } else { | ||
2600 | track_idx = find_track(ti->cdti_trk1 + 1); | ||
2601 | } | ||
2602 | if (track_idx < 0) { | ||
2603 | retval = -EINVAL; | ||
2604 | break; | ||
2605 | } | ||
2606 | params[4] = | ||
2607 | int_to_bcd(sony_toc.tracks[track_idx]. | ||
2608 | track_start_msf[0]); | ||
2609 | params[5] = | ||
2610 | int_to_bcd(sony_toc.tracks[track_idx]. | ||
2611 | track_start_msf[1]); | ||
2612 | params[6] = | ||
2613 | int_to_bcd(sony_toc.tracks[track_idx]. | ||
2614 | track_start_msf[2]); | ||
2615 | params[0] = 0x03; | ||
2616 | |||
2617 | do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, | ||
2618 | &res_size); | ||
2619 | |||
2620 | do_sony_cd_cmd(SONY_AUDIO_PLAYBACK_CMD, params, 7, | ||
2621 | res_reg, &res_size); | ||
2622 | |||
2623 | if ((res_size < 2) | ||
2624 | || ((res_reg[0] & 0xf0) == 0x20)) { | ||
2625 | printk(KERN_ERR PFX | ||
2626 | "Params: %x %x %x %x %x %x %x\n", | ||
2627 | params[0], params[1], params[2], | ||
2628 | params[3], params[4], params[5], | ||
2629 | params[6]); | ||
2630 | printk(KERN_ERR PFX | ||
2631 | "Error %s (CDROMPLAYTRKIND)\n", | ||
2632 | translate_error(res_reg[1])); | ||
2633 | retval = -EIO; | ||
2634 | break; | ||
2635 | } | ||
2636 | |||
2637 | /* Save the final position for pauses and resumes */ | ||
2638 | final_pos_msf[0] = bcd_to_int(params[4]); | ||
2639 | final_pos_msf[1] = bcd_to_int(params[5]); | ||
2640 | final_pos_msf[2] = bcd_to_int(params[6]); | ||
2641 | sony_audio_status = CDROM_AUDIO_PLAY; | ||
2642 | retval = 0; | ||
2643 | break; | ||
2644 | } | ||
2645 | |||
2646 | case CDROMVOLCTRL: /* Volume control. What volume does this change, anyway? */ | ||
2647 | { | ||
2648 | struct cdrom_volctrl *volctrl = | ||
2649 | (struct cdrom_volctrl *) arg; | ||
2650 | |||
2651 | params[0] = SONY_SD_AUDIO_VOLUME; | ||
2652 | params[1] = volctrl->channel0; | ||
2653 | params[2] = volctrl->channel1; | ||
2654 | retval = do_sony_cd_cmd_chk("VOLCTRL", | ||
2655 | SONY_SET_DRIVE_PARAM_CMD, | ||
2656 | params, 3, res_reg, | ||
2657 | &res_size); | ||
2658 | break; | ||
2659 | } | ||
2660 | case CDROMSUBCHNL: /* Get subchannel info */ | ||
2661 | retval = sony_get_subchnl_info((struct cdrom_subchnl *) arg); | ||
2662 | break; | ||
2663 | |||
2664 | default: | ||
2665 | retval = -EINVAL; | ||
2666 | break; | ||
2667 | } | ||
2668 | up(&sony_sem); | ||
2669 | return retval; | ||
2670 | } | ||
2671 | |||
2672 | static int scd_read_audio(struct cdrom_device_info *cdi, | ||
2673 | unsigned int cmd, unsigned long arg) | ||
2674 | { | ||
2675 | void __user *argp = (void __user *)arg; | ||
2676 | int retval; | ||
2677 | |||
2678 | if (down_interruptible(&sony_sem)) | ||
2679 | return -ERESTARTSYS; | ||
2680 | switch (cmd) { | ||
2681 | case CDROMREADAUDIO: /* Read 2352 byte audio tracks and 2340 byte | ||
2682 | raw data tracks. */ | ||
2683 | { | ||
2684 | struct cdrom_read_audio ra; | ||
2685 | |||
2686 | |||
2687 | sony_get_toc(); | ||
2688 | if (!sony_toc_read) { | ||
2689 | retval = -EIO; | ||
2690 | break; | ||
2691 | } | ||
2692 | |||
2693 | if (copy_from_user(&ra, argp, sizeof(ra))) { | ||
2694 | retval = -EFAULT; | ||
2695 | break; | ||
2696 | } | ||
2697 | |||
2698 | if (ra.nframes == 0) { | ||
2699 | retval = 0; | ||
2700 | break; | ||
2701 | } | ||
2702 | |||
2703 | if (!access_ok(VERIFY_WRITE, ra.buf, | ||
2704 | CD_FRAMESIZE_RAW * ra.nframes)) | ||
2705 | return -EFAULT; | ||
2706 | |||
2707 | if (ra.addr_format == CDROM_LBA) { | ||
2708 | if ((ra.addr.lba >= | ||
2709 | sony_toc.lead_out_start_lba) | ||
2710 | || (ra.addr.lba + ra.nframes >= | ||
2711 | sony_toc.lead_out_start_lba)) { | ||
2712 | retval = -EINVAL; | ||
2713 | break; | ||
2714 | } | ||
2715 | } else if (ra.addr_format == CDROM_MSF) { | ||
2716 | if ((ra.addr.msf.minute >= 75) | ||
2717 | || (ra.addr.msf.second >= 60) | ||
2718 | || (ra.addr.msf.frame >= 75)) { | ||
2719 | retval = -EINVAL; | ||
2720 | break; | ||
2721 | } | ||
2722 | |||
2723 | ra.addr.lba = ((ra.addr.msf.minute * 4500) | ||
2724 | + (ra.addr.msf.second * 75) | ||
2725 | + ra.addr.msf.frame); | ||
2726 | if ((ra.addr.lba >= | ||
2727 | sony_toc.lead_out_start_lba) | ||
2728 | || (ra.addr.lba + ra.nframes >= | ||
2729 | sony_toc.lead_out_start_lba)) { | ||
2730 | retval = -EINVAL; | ||
2731 | break; | ||
2732 | } | ||
2733 | |||
2734 | /* I know, this can go negative on an unsigned. However, | ||
2735 | the first thing done to the data is to add this value, | ||
2736 | so this should compensate and allow direct msf access. */ | ||
2737 | ra.addr.lba -= LOG_START_OFFSET; | ||
2738 | } else { | ||
2739 | retval = -EINVAL; | ||
2740 | break; | ||
2741 | } | ||
2742 | |||
2743 | retval = read_audio(&ra); | ||
2744 | break; | ||
2745 | } | ||
2746 | retval = 0; | ||
2747 | break; | ||
2748 | |||
2749 | default: | ||
2750 | retval = -EINVAL; | ||
2751 | } | ||
2752 | up(&sony_sem); | ||
2753 | return retval; | ||
2754 | } | ||
2755 | |||
2756 | static int scd_spinup(void) | ||
2757 | { | ||
2758 | unsigned char res_reg[12]; | ||
2759 | unsigned int res_size; | ||
2760 | int num_spin_ups; | ||
2761 | |||
2762 | num_spin_ups = 0; | ||
2763 | |||
2764 | respinup_on_open: | ||
2765 | do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size); | ||
2766 | |||
2767 | /* The drive sometimes returns error 0. I don't know why, but ignore | ||
2768 | it. It seems to mean the drive has already done the operation. */ | ||
2769 | if ((res_size < 2) || ((res_reg[0] != 0) && (res_reg[1] != 0))) { | ||
2770 | printk(KERN_ERR PFX "%s error (scd_open, spin up)\n", | ||
2771 | translate_error(res_reg[1])); | ||
2772 | return 1; | ||
2773 | } | ||
2774 | |||
2775 | do_sony_cd_cmd(SONY_READ_TOC_CMD, NULL, 0, res_reg, &res_size); | ||
2776 | |||
2777 | /* The drive sometimes returns error 0. I don't know why, but ignore | ||
2778 | it. It seems to mean the drive has already done the operation. */ | ||
2779 | if ((res_size < 2) || ((res_reg[0] != 0) && (res_reg[1] != 0))) { | ||
2780 | /* If the drive is already playing, it's ok. */ | ||
2781 | if ((res_reg[1] == SONY_AUDIO_PLAYING_ERR) | ||
2782 | || (res_reg[1] == 0)) { | ||
2783 | return 0; | ||
2784 | } | ||
2785 | |||
2786 | /* If the drive says it is not spun up (even though we just did it!) | ||
2787 | then retry the operation at least a few times. */ | ||
2788 | if ((res_reg[1] == SONY_NOT_SPIN_ERR) | ||
2789 | && (num_spin_ups < MAX_CDU31A_RETRIES)) { | ||
2790 | num_spin_ups++; | ||
2791 | goto respinup_on_open; | ||
2792 | } | ||
2793 | |||
2794 | printk(KERN_ERR PFX "Error %s (scd_open, read toc)\n", | ||
2795 | translate_error(res_reg[1])); | ||
2796 | do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg, | ||
2797 | &res_size); | ||
2798 | return 1; | ||
2799 | } | ||
2800 | return 0; | ||
2801 | } | ||
2802 | |||
2803 | /* | ||
2804 | * Open the drive for operations. Spin the drive up and read the table of | ||
2805 | * contents if these have not already been done. | ||
2806 | */ | ||
2807 | static int scd_open(struct cdrom_device_info *cdi, int purpose) | ||
2808 | { | ||
2809 | unsigned char res_reg[12]; | ||
2810 | unsigned int res_size; | ||
2811 | unsigned char params[2]; | ||
2812 | |||
2813 | if (purpose == 1) { | ||
2814 | /* Open for IOCTLs only - no media check */ | ||
2815 | sony_usage++; | ||
2816 | return 0; | ||
2817 | } | ||
2818 | |||
2819 | if (sony_usage == 0) { | ||
2820 | if (scd_spinup() != 0) | ||
2821 | return -EIO; | ||
2822 | sony_get_toc(); | ||
2823 | if (!sony_toc_read) { | ||
2824 | do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, | ||
2825 | res_reg, &res_size); | ||
2826 | return -EIO; | ||
2827 | } | ||
2828 | |||
2829 | /* For XA on the CDU31A only, we have to do special reads. | ||
2830 | The CDU33A handles XA automagically. */ | ||
2831 | /* if ( (sony_toc.disk_type == SONY_XA_DISK_TYPE) */ | ||
2832 | if ((sony_toc.disk_type != 0x00) | ||
2833 | && (!is_double_speed)) { | ||
2834 | params[0] = SONY_SD_DECODE_PARAM; | ||
2835 | params[1] = 0x07; | ||
2836 | do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD, | ||
2837 | params, 2, res_reg, &res_size); | ||
2838 | if ((res_size < 2) | ||
2839 | || ((res_reg[0] & 0xf0) == 0x20)) { | ||
2840 | printk(KERN_WARNING PFX "Unable to set " | ||
2841 | "XA params: 0x%2.2x\n", res_reg[1]); | ||
2842 | } | ||
2843 | sony_xa_mode = 1; | ||
2844 | } | ||
2845 | /* A non-XA disk. Set the parms back if necessary. */ | ||
2846 | else if (sony_xa_mode) { | ||
2847 | params[0] = SONY_SD_DECODE_PARAM; | ||
2848 | params[1] = 0x0f; | ||
2849 | do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD, | ||
2850 | params, 2, res_reg, &res_size); | ||
2851 | if ((res_size < 2) | ||
2852 | || ((res_reg[0] & 0xf0) == 0x20)) { | ||
2853 | printk(KERN_WARNING PFX "Unable to reset " | ||
2854 | "XA params: 0x%2.2x\n", res_reg[1]); | ||
2855 | } | ||
2856 | sony_xa_mode = 0; | ||
2857 | } | ||
2858 | |||
2859 | sony_spun_up = 1; | ||
2860 | } | ||
2861 | |||
2862 | sony_usage++; | ||
2863 | |||
2864 | return 0; | ||
2865 | } | ||
2866 | |||
2867 | |||
2868 | /* | ||
2869 | * Close the drive. Spin it down if no task is using it. The spin | ||
2870 | * down will fail if playing audio, so audio play is OK. | ||
2871 | */ | ||
2872 | static void scd_release(struct cdrom_device_info *cdi) | ||
2873 | { | ||
2874 | if (sony_usage == 1) { | ||
2875 | unsigned char res_reg[12]; | ||
2876 | unsigned int res_size; | ||
2877 | |||
2878 | do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg, | ||
2879 | &res_size); | ||
2880 | |||
2881 | sony_spun_up = 0; | ||
2882 | } | ||
2883 | sony_usage--; | ||
2884 | } | ||
2885 | |||
2886 | static struct cdrom_device_ops scd_dops = { | ||
2887 | .open = scd_open, | ||
2888 | .release = scd_release, | ||
2889 | .drive_status = scd_drive_status, | ||
2890 | .media_changed = scd_media_changed, | ||
2891 | .tray_move = scd_tray_move, | ||
2892 | .lock_door = scd_lock_door, | ||
2893 | .select_speed = scd_select_speed, | ||
2894 | .get_last_session = scd_get_last_session, | ||
2895 | .get_mcn = scd_get_mcn, | ||
2896 | .reset = scd_reset, | ||
2897 | .audio_ioctl = scd_audio_ioctl, | ||
2898 | .capability = CDC_OPEN_TRAY | CDC_CLOSE_TRAY | CDC_LOCK | | ||
2899 | CDC_SELECT_SPEED | CDC_MULTI_SESSION | | ||
2900 | CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | | ||
2901 | CDC_RESET | CDC_DRIVE_STATUS, | ||
2902 | .n_minors = 1, | ||
2903 | }; | ||
2904 | |||
2905 | static struct cdrom_device_info scd_info = { | ||
2906 | .ops = &scd_dops, | ||
2907 | .speed = 2, | ||
2908 | .capacity = 1, | ||
2909 | .name = "cdu31a" | ||
2910 | }; | ||
2911 | |||
2912 | static int scd_block_open(struct inode *inode, struct file *file) | ||
2913 | { | ||
2914 | return cdrom_open(&scd_info, inode, file); | ||
2915 | } | ||
2916 | |||
2917 | static int scd_block_release(struct inode *inode, struct file *file) | ||
2918 | { | ||
2919 | return cdrom_release(&scd_info, file); | ||
2920 | } | ||
2921 | |||
2922 | static int scd_block_ioctl(struct inode *inode, struct file *file, | ||
2923 | unsigned cmd, unsigned long arg) | ||
2924 | { | ||
2925 | int retval; | ||
2926 | |||
2927 | /* The eject and close commands should be handled by Uniform CD-ROM | ||
2928 | * driver - but I always got hard lockup instead of eject | ||
2929 | * until I put this here. | ||
2930 | */ | ||
2931 | switch (cmd) { | ||
2932 | case CDROMEJECT: | ||
2933 | scd_lock_door(&scd_info, 0); | ||
2934 | retval = scd_tray_move(&scd_info, 1); | ||
2935 | break; | ||
2936 | case CDROMCLOSETRAY: | ||
2937 | retval = scd_tray_move(&scd_info, 0); | ||
2938 | break; | ||
2939 | case CDROMREADAUDIO: | ||
2940 | retval = scd_read_audio(&scd_info, CDROMREADAUDIO, arg); | ||
2941 | break; | ||
2942 | default: | ||
2943 | retval = cdrom_ioctl(file, &scd_info, inode, cmd, arg); | ||
2944 | } | ||
2945 | return retval; | ||
2946 | } | ||
2947 | |||
2948 | static int scd_block_media_changed(struct gendisk *disk) | ||
2949 | { | ||
2950 | return cdrom_media_changed(&scd_info); | ||
2951 | } | ||
2952 | |||
2953 | static struct block_device_operations scd_bdops = | ||
2954 | { | ||
2955 | .owner = THIS_MODULE, | ||
2956 | .open = scd_block_open, | ||
2957 | .release = scd_block_release, | ||
2958 | .ioctl = scd_block_ioctl, | ||
2959 | .media_changed = scd_block_media_changed, | ||
2960 | }; | ||
2961 | |||
2962 | static struct gendisk *scd_gendisk; | ||
2963 | |||
2964 | /* The different types of disc loading mechanisms supported */ | ||
2965 | static char *load_mech[] __initdata = | ||
2966 | { "caddy", "tray", "pop-up", "unknown" }; | ||
2967 | |||
2968 | static int __init | ||
2969 | get_drive_configuration(unsigned short base_io, | ||
2970 | unsigned char res_reg[], unsigned int *res_size) | ||
2971 | { | ||
2972 | unsigned long retry_count; | ||
2973 | |||
2974 | |||
2975 | if (!request_region(base_io, 4, "cdu31a")) | ||
2976 | return 0; | ||
2977 | |||
2978 | /* Set the base address */ | ||
2979 | cdu31a_port = base_io; | ||
2980 | |||
2981 | /* Set up all the register locations */ | ||
2982 | sony_cd_cmd_reg = cdu31a_port + SONY_CMD_REG_OFFSET; | ||
2983 | sony_cd_param_reg = cdu31a_port + SONY_PARAM_REG_OFFSET; | ||
2984 | sony_cd_write_reg = cdu31a_port + SONY_WRITE_REG_OFFSET; | ||
2985 | sony_cd_control_reg = cdu31a_port + SONY_CONTROL_REG_OFFSET; | ||
2986 | sony_cd_status_reg = cdu31a_port + SONY_STATUS_REG_OFFSET; | ||
2987 | sony_cd_result_reg = cdu31a_port + SONY_RESULT_REG_OFFSET; | ||
2988 | sony_cd_read_reg = cdu31a_port + SONY_READ_REG_OFFSET; | ||
2989 | sony_cd_fifost_reg = cdu31a_port + SONY_FIFOST_REG_OFFSET; | ||
2990 | |||
2991 | /* | ||
2992 | * Check to see if anything exists at the status register location. | ||
2993 | * I don't know if this is a good way to check, but it seems to work | ||
2994 | * ok for me. | ||
2995 | */ | ||
2996 | if (read_status_register() != 0xff) { | ||
2997 | /* | ||
2998 | * Reset the drive and wait for attention from it (to say it's reset). | ||
2999 | * If you don't wait, the next operation will probably fail. | ||
3000 | */ | ||
3001 | reset_drive(); | ||
3002 | retry_count = jiffies + SONY_RESET_TIMEOUT; | ||
3003 | while (time_before(jiffies, retry_count) | ||
3004 | && (!is_attention())) { | ||
3005 | sony_sleep(); | ||
3006 | } | ||
3007 | |||
3008 | #if 0 | ||
3009 | /* If attention is never seen probably not a CDU31a present */ | ||
3010 | if (!is_attention()) { | ||
3011 | res_reg[0] = 0x20; | ||
3012 | goto out_err; | ||
3013 | } | ||
3014 | #endif | ||
3015 | |||
3016 | /* | ||
3017 | * Get the drive configuration. | ||
3018 | */ | ||
3019 | do_sony_cd_cmd(SONY_REQ_DRIVE_CONFIG_CMD, | ||
3020 | NULL, | ||
3021 | 0, (unsigned char *) res_reg, res_size); | ||
3022 | if (*res_size <= 2 || (res_reg[0] & 0xf0) != 0) | ||
3023 | goto out_err; | ||
3024 | return 1; | ||
3025 | } | ||
3026 | |||
3027 | /* Return an error */ | ||
3028 | res_reg[0] = 0x20; | ||
3029 | out_err: | ||
3030 | release_region(cdu31a_port, 4); | ||
3031 | cdu31a_port = 0; | ||
3032 | return 0; | ||
3033 | } | ||
3034 | |||
3035 | #ifndef MODULE | ||
3036 | /* | ||
3037 | * Set up base I/O and interrupts, called from main.c. | ||
3038 | */ | ||
3039 | |||
3040 | static int __init cdu31a_setup(char *strings) | ||
3041 | { | ||
3042 | int ints[4]; | ||
3043 | |||
3044 | (void) get_options(strings, ARRAY_SIZE(ints), ints); | ||
3045 | |||
3046 | if (ints[0] > 0) { | ||
3047 | cdu31a_port = ints[1]; | ||
3048 | } | ||
3049 | if (ints[0] > 1) { | ||
3050 | cdu31a_irq = ints[2]; | ||
3051 | } | ||
3052 | if ((strings != NULL) && (*strings != '\0')) { | ||
3053 | if (strcmp(strings, "PAS") == 0) { | ||
3054 | sony_pas_init = 1; | ||
3055 | } else { | ||
3056 | printk(KERN_NOTICE PFX "Unknown interface type: %s\n", | ||
3057 | strings); | ||
3058 | } | ||
3059 | } | ||
3060 | |||
3061 | return 1; | ||
3062 | } | ||
3063 | |||
3064 | __setup("cdu31a=", cdu31a_setup); | ||
3065 | |||
3066 | #endif | ||
3067 | |||
3068 | /* | ||
3069 | * Initialize the driver. | ||
3070 | */ | ||
3071 | int __init cdu31a_init(void) | ||
3072 | { | ||
3073 | struct s_sony_drive_config drive_config; | ||
3074 | struct gendisk *disk; | ||
3075 | int deficiency = 0; | ||
3076 | unsigned int res_size; | ||
3077 | char msg[255]; | ||
3078 | char buf[40]; | ||
3079 | int i; | ||
3080 | int tmp_irq; | ||
3081 | |||
3082 | /* | ||
3083 | * According to Alex Freed (freed@europa.orion.adobe.com), this is | ||
3084 | * required for the Fusion CD-16 package. If the sound driver is | ||
3085 | * loaded, it should work fine, but just in case... | ||
3086 | * | ||
3087 | * The following turn on the CD-ROM interface for a Fusion CD-16. | ||
3088 | */ | ||
3089 | if (sony_pas_init) { | ||
3090 | outb(0xbc, 0x9a01); | ||
3091 | outb(0xe2, 0x9a01); | ||
3092 | } | ||
3093 | |||
3094 | /* Setting the base I/O address to 0xffff will disable it. */ | ||
3095 | if (cdu31a_port == 0xffff) | ||
3096 | goto errout3; | ||
3097 | |||
3098 | if (cdu31a_port != 0) { | ||
3099 | /* Need IRQ 0 because we can't sleep here. */ | ||
3100 | tmp_irq = cdu31a_irq; | ||
3101 | cdu31a_irq = 0; | ||
3102 | if (!get_drive_configuration(cdu31a_port, | ||
3103 | drive_config.exec_status, | ||
3104 | &res_size)) | ||
3105 | goto errout3; | ||
3106 | cdu31a_irq = tmp_irq; | ||
3107 | } else { | ||
3108 | cdu31a_irq = 0; | ||
3109 | for (i = 0; cdu31a_addresses[i].base; i++) { | ||
3110 | if (get_drive_configuration(cdu31a_addresses[i].base, | ||
3111 | drive_config.exec_status, | ||
3112 | &res_size)) { | ||
3113 | cdu31a_irq = cdu31a_addresses[i].int_num; | ||
3114 | break; | ||
3115 | } | ||
3116 | } | ||
3117 | if (!cdu31a_port) | ||
3118 | goto errout3; | ||
3119 | } | ||
3120 | |||
3121 | if (register_blkdev(MAJOR_NR, "cdu31a")) | ||
3122 | goto errout2; | ||
3123 | |||
3124 | disk = alloc_disk(1); | ||
3125 | if (!disk) | ||
3126 | goto errout1; | ||
3127 | disk->major = MAJOR_NR; | ||
3128 | disk->first_minor = 0; | ||
3129 | sprintf(disk->disk_name, "cdu31a"); | ||
3130 | disk->fops = &scd_bdops; | ||
3131 | disk->flags = GENHD_FL_CD; | ||
3132 | |||
3133 | if (SONY_HWC_DOUBLE_SPEED(drive_config)) | ||
3134 | is_double_speed = 1; | ||
3135 | |||
3136 | tmp_irq = cdu31a_irq; /* Need IRQ 0 because we can't sleep here. */ | ||
3137 | cdu31a_irq = 0; | ||
3138 | |||
3139 | sony_speed = is_double_speed; /* Set 2X drives to 2X by default */ | ||
3140 | set_drive_params(sony_speed); | ||
3141 | |||
3142 | cdu31a_irq = tmp_irq; | ||
3143 | |||
3144 | if (cdu31a_irq > 0) { | ||
3145 | if (request_irq | ||
3146 | (cdu31a_irq, cdu31a_interrupt, IRQF_DISABLED, | ||
3147 | "cdu31a", NULL)) { | ||
3148 | printk(KERN_WARNING PFX "Unable to grab IRQ%d for " | ||
3149 | "the CDU31A driver\n", cdu31a_irq); | ||
3150 | cdu31a_irq = 0; | ||
3151 | } | ||
3152 | } | ||
3153 | |||
3154 | sprintf(msg, "Sony I/F CDROM : %8.8s %16.16s %8.8s\n", | ||
3155 | drive_config.vendor_id, | ||
3156 | drive_config.product_id, | ||
3157 | drive_config.product_rev_level); | ||
3158 | sprintf(buf, " Capabilities: %s", | ||
3159 | load_mech[SONY_HWC_GET_LOAD_MECH(drive_config)]); | ||
3160 | strcat(msg, buf); | ||
3161 | if (SONY_HWC_AUDIO_PLAYBACK(drive_config)) | ||
3162 | strcat(msg, ", audio"); | ||
3163 | else | ||
3164 | deficiency |= CDC_PLAY_AUDIO; | ||
3165 | if (SONY_HWC_EJECT(drive_config)) | ||
3166 | strcat(msg, ", eject"); | ||
3167 | else | ||
3168 | deficiency |= CDC_OPEN_TRAY; | ||
3169 | if (SONY_HWC_LED_SUPPORT(drive_config)) | ||
3170 | strcat(msg, ", LED"); | ||
3171 | if (SONY_HWC_ELECTRIC_VOLUME(drive_config)) | ||
3172 | strcat(msg, ", elec. Vol"); | ||
3173 | if (SONY_HWC_ELECTRIC_VOLUME_CTL(drive_config)) | ||
3174 | strcat(msg, ", sep. Vol"); | ||
3175 | if (is_double_speed) | ||
3176 | strcat(msg, ", double speed"); | ||
3177 | else | ||
3178 | deficiency |= CDC_SELECT_SPEED; | ||
3179 | if (cdu31a_irq > 0) { | ||
3180 | sprintf(buf, ", irq %d", cdu31a_irq); | ||
3181 | strcat(msg, buf); | ||
3182 | } | ||
3183 | strcat(msg, "\n"); | ||
3184 | printk(KERN_INFO PFX "%s",msg); | ||
3185 | |||
3186 | cdu31a_queue = blk_init_queue(do_cdu31a_request, &cdu31a_lock); | ||
3187 | if (!cdu31a_queue) | ||
3188 | goto errout0; | ||
3189 | blk_queue_hardsect_size(cdu31a_queue, 2048); | ||
3190 | |||
3191 | init_timer(&cdu31a_abort_timer); | ||
3192 | cdu31a_abort_timer.function = handle_abort_timeout; | ||
3193 | |||
3194 | scd_info.mask = deficiency; | ||
3195 | scd_gendisk = disk; | ||
3196 | if (register_cdrom(&scd_info)) | ||
3197 | goto err; | ||
3198 | disk->queue = cdu31a_queue; | ||
3199 | add_disk(disk); | ||
3200 | |||
3201 | disk_changed = 1; | ||
3202 | return 0; | ||
3203 | |||
3204 | err: | ||
3205 | blk_cleanup_queue(cdu31a_queue); | ||
3206 | errout0: | ||
3207 | if (cdu31a_irq) | ||
3208 | free_irq(cdu31a_irq, NULL); | ||
3209 | printk(KERN_ERR PFX "Unable to register with Uniform cdrom driver\n"); | ||
3210 | put_disk(disk); | ||
3211 | errout1: | ||
3212 | if (unregister_blkdev(MAJOR_NR, "cdu31a")) { | ||
3213 | printk(KERN_WARNING PFX "Can't unregister block device\n"); | ||
3214 | } | ||
3215 | errout2: | ||
3216 | release_region(cdu31a_port, 4); | ||
3217 | errout3: | ||
3218 | return -EIO; | ||
3219 | } | ||
3220 | |||
3221 | |||
3222 | static void __exit cdu31a_exit(void) | ||
3223 | { | ||
3224 | del_gendisk(scd_gendisk); | ||
3225 | put_disk(scd_gendisk); | ||
3226 | if (unregister_cdrom(&scd_info)) { | ||
3227 | printk(KERN_WARNING PFX "Can't unregister from Uniform " | ||
3228 | "cdrom driver\n"); | ||
3229 | return; | ||
3230 | } | ||
3231 | if ((unregister_blkdev(MAJOR_NR, "cdu31a") == -EINVAL)) { | ||
3232 | printk(KERN_WARNING PFX "Can't unregister\n"); | ||
3233 | return; | ||
3234 | } | ||
3235 | |||
3236 | blk_cleanup_queue(cdu31a_queue); | ||
3237 | |||
3238 | if (cdu31a_irq > 0) | ||
3239 | free_irq(cdu31a_irq, NULL); | ||
3240 | |||
3241 | release_region(cdu31a_port, 4); | ||
3242 | printk(KERN_INFO PFX "module released.\n"); | ||
3243 | } | ||
3244 | |||
3245 | #ifdef MODULE | ||
3246 | module_init(cdu31a_init); | ||
3247 | #endif | ||
3248 | module_exit(cdu31a_exit); | ||
3249 | |||
3250 | MODULE_LICENSE("GPL"); | ||
3251 | MODULE_ALIAS_BLOCKDEV_MAJOR(CDU31A_CDROM_MAJOR); | ||
diff --git a/drivers/cdrom/cdu31a.h b/drivers/cdrom/cdu31a.h deleted file mode 100644 index 61d4768c412e..000000000000 --- a/drivers/cdrom/cdu31a.h +++ /dev/null | |||
@@ -1,411 +0,0 @@ | |||
1 | /* | ||
2 | * Definitions for a Sony interface CDROM drive. | ||
3 | * | ||
4 | * Corey Minyard (minyard@wf-rch.cirr.com) | ||
5 | * | ||
6 | * Copyright (C) 1993 Corey Minyard | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | /* | ||
25 | * General defines. | ||
26 | */ | ||
27 | #define SONY_XA_DISK_TYPE 0x20 | ||
28 | |||
29 | /* | ||
30 | * Offsets (from the base address) and bits for the various write registers | ||
31 | * of the drive. | ||
32 | */ | ||
33 | #define SONY_CMD_REG_OFFSET 0 | ||
34 | #define SONY_PARAM_REG_OFFSET 1 | ||
35 | #define SONY_WRITE_REG_OFFSET 2 | ||
36 | #define SONY_CONTROL_REG_OFFSET 3 | ||
37 | # define SONY_ATTN_CLR_BIT 0x01 | ||
38 | # define SONY_RES_RDY_CLR_BIT 0x02 | ||
39 | # define SONY_DATA_RDY_CLR_BIT 0x04 | ||
40 | # define SONY_ATTN_INT_EN_BIT 0x08 | ||
41 | # define SONY_RES_RDY_INT_EN_BIT 0x10 | ||
42 | # define SONY_DATA_RDY_INT_EN_BIT 0x20 | ||
43 | # define SONY_PARAM_CLR_BIT 0x40 | ||
44 | # define SONY_DRIVE_RESET_BIT 0x80 | ||
45 | |||
46 | /* | ||
47 | * Offsets (from the base address) and bits for the various read registers | ||
48 | * of the drive. | ||
49 | */ | ||
50 | #define SONY_STATUS_REG_OFFSET 0 | ||
51 | # define SONY_ATTN_BIT 0x01 | ||
52 | # define SONY_RES_RDY_BIT 0x02 | ||
53 | # define SONY_DATA_RDY_BIT 0x04 | ||
54 | # define SONY_ATTN_INT_ST_BIT 0x08 | ||
55 | # define SONY_RES_RDY_INT_ST_BIT 0x10 | ||
56 | # define SONY_DATA_RDY_INT_ST_BIT 0x20 | ||
57 | # define SONY_DATA_REQUEST_BIT 0x40 | ||
58 | # define SONY_BUSY_BIT 0x80 | ||
59 | #define SONY_RESULT_REG_OFFSET 1 | ||
60 | #define SONY_READ_REG_OFFSET 2 | ||
61 | #define SONY_FIFOST_REG_OFFSET 3 | ||
62 | # define SONY_PARAM_WRITE_RDY_BIT 0x01 | ||
63 | # define SONY_PARAM_REG_EMPTY_BIT 0x02 | ||
64 | # define SONY_RES_REG_NOT_EMP_BIT 0x04 | ||
65 | # define SONY_RES_REG_FULL_BIT 0x08 | ||
66 | |||
67 | #define LOG_START_OFFSET 150 /* Offset of first logical sector */ | ||
68 | |||
69 | #define SONY_DETECT_TIMEOUT (8*HZ/10) /* Maximum amount of time | ||
70 | that drive detection code | ||
71 | will wait for response | ||
72 | from drive (in 1/100th's | ||
73 | of seconds). */ | ||
74 | |||
75 | #define SONY_JIFFIES_TIMEOUT (10*HZ) /* Maximum number of times the | ||
76 | drive will wait/try for an | ||
77 | operation */ | ||
78 | #define SONY_RESET_TIMEOUT HZ /* Maximum number of times the | ||
79 | drive will wait/try a reset | ||
80 | operation */ | ||
81 | #define SONY_READY_RETRIES 20000 /* How many times to retry a | ||
82 | spin waiting for a register | ||
83 | to come ready */ | ||
84 | |||
85 | #define MAX_CDU31A_RETRIES 3 /* How many times to retry an | ||
86 | operation */ | ||
87 | |||
88 | /* Commands to request or set drive control parameters and disc information */ | ||
89 | #define SONY_REQ_DRIVE_CONFIG_CMD 0x00 /* Returns s_sony_drive_config */ | ||
90 | #define SONY_REQ_DRIVE_MODE_CMD 0x01 | ||
91 | #define SONY_REQ_DRIVE_PARAM_CMD 0x02 | ||
92 | #define SONY_REQ_MECH_STATUS_CMD 0x03 | ||
93 | #define SONY_REQ_AUDIO_STATUS_CMD 0x04 | ||
94 | #define SONY_SET_DRIVE_PARAM_CMD 0x10 | ||
95 | #define SONY_REQ_TOC_DATA_CMD 0x20 /* Returns s_sony_toc */ | ||
96 | #define SONY_REQ_SUBCODE_ADDRESS_CMD 0x21 /* Returns s_sony_subcode */ | ||
97 | #define SONY_REQ_UPC_EAN_CMD 0x22 | ||
98 | #define SONY_REQ_ISRC_CMD 0x23 | ||
99 | #define SONY_REQ_TOC_DATA_SPEC_CMD 0x24 /* Returns s_sony_session_toc */ | ||
100 | |||
101 | /* Commands to request information from the drive */ | ||
102 | #define SONY_READ_TOC_CMD 0x30 /* let the drive firmware grab the TOC */ | ||
103 | #define SONY_SEEK_CMD 0x31 | ||
104 | #define SONY_READ_CMD 0x32 | ||
105 | #define SONY_READ_BLKERR_STAT_CMD 0x34 | ||
106 | #define SONY_ABORT_CMD 0x35 | ||
107 | #define SONY_READ_TOC_SPEC_CMD 0x36 | ||
108 | |||
109 | /* Commands to control audio */ | ||
110 | #define SONY_AUDIO_PLAYBACK_CMD 0x40 | ||
111 | #define SONY_AUDIO_STOP_CMD 0x41 | ||
112 | #define SONY_AUDIO_SCAN_CMD 0x42 | ||
113 | |||
114 | /* Miscellaneous control commands */ | ||
115 | #define SONY_EJECT_CMD 0x50 | ||
116 | #define SONY_SPIN_UP_CMD 0x51 | ||
117 | #define SONY_SPIN_DOWN_CMD 0x52 | ||
118 | |||
119 | /* Diagnostic commands */ | ||
120 | #define SONY_WRITE_BUFFER_CMD 0x60 | ||
121 | #define SONY_READ_BUFFER_CMD 0x61 | ||
122 | #define SONY_DIAGNOSTICS_CMD 0x62 | ||
123 | |||
124 | |||
125 | /* | ||
126 | * The following are command parameters for the set drive parameter command | ||
127 | */ | ||
128 | #define SONY_SD_DECODE_PARAM 0x00 | ||
129 | #define SONY_SD_INTERFACE_PARAM 0x01 | ||
130 | #define SONY_SD_BUFFERING_PARAM 0x02 | ||
131 | #define SONY_SD_AUDIO_PARAM 0x03 | ||
132 | #define SONY_SD_AUDIO_VOLUME 0x04 | ||
133 | #define SONY_SD_MECH_CONTROL 0x05 | ||
134 | #define SONY_SD_AUTO_SPIN_DOWN_TIME 0x06 | ||
135 | |||
136 | /* | ||
137 | * The following are parameter bits for the mechanical control command | ||
138 | */ | ||
139 | #define SONY_AUTO_SPIN_UP_BIT 0x01 | ||
140 | #define SONY_AUTO_EJECT_BIT 0x02 | ||
141 | #define SONY_DOUBLE_SPEED_BIT 0x04 | ||
142 | |||
143 | /* | ||
144 | * The following extract information from the drive configuration about | ||
145 | * the drive itself. | ||
146 | */ | ||
147 | #define SONY_HWC_GET_LOAD_MECH(c) (c.hw_config[0] & 0x03) | ||
148 | #define SONY_HWC_EJECT(c) (c.hw_config[0] & 0x04) | ||
149 | #define SONY_HWC_LED_SUPPORT(c) (c.hw_config[0] & 0x08) | ||
150 | #define SONY_HWC_DOUBLE_SPEED(c) (c.hw_config[0] & 0x10) | ||
151 | #define SONY_HWC_GET_BUF_MEM_SIZE(c) ((c.hw_config[0] & 0xc0) >> 6) | ||
152 | #define SONY_HWC_AUDIO_PLAYBACK(c) (c.hw_config[1] & 0x01) | ||
153 | #define SONY_HWC_ELECTRIC_VOLUME(c) (c.hw_config[1] & 0x02) | ||
154 | #define SONY_HWC_ELECTRIC_VOLUME_CTL(c) (c.hw_config[1] & 0x04) | ||
155 | |||
156 | #define SONY_HWC_CADDY_LOAD_MECH 0x00 | ||
157 | #define SONY_HWC_TRAY_LOAD_MECH 0x01 | ||
158 | #define SONY_HWC_POPUP_LOAD_MECH 0x02 | ||
159 | #define SONY_HWC_UNKWN_LOAD_MECH 0x03 | ||
160 | |||
161 | #define SONY_HWC_8KB_BUFFER 0x00 | ||
162 | #define SONY_HWC_32KB_BUFFER 0x01 | ||
163 | #define SONY_HWC_64KB_BUFFER 0x02 | ||
164 | #define SONY_HWC_UNKWN_BUFFER 0x03 | ||
165 | |||
166 | /* | ||
167 | * This is the complete status returned from the drive configuration request | ||
168 | * command. | ||
169 | */ | ||
170 | struct s_sony_drive_config | ||
171 | { | ||
172 | unsigned char exec_status[2]; | ||
173 | char vendor_id[8]; | ||
174 | char product_id[16]; | ||
175 | char product_rev_level[8]; | ||
176 | unsigned char hw_config[2]; | ||
177 | }; | ||
178 | |||
179 | /* The following is returned from the request subcode address command */ | ||
180 | struct s_sony_subcode | ||
181 | { | ||
182 | unsigned char exec_status[2]; | ||
183 | unsigned char address :4; | ||
184 | unsigned char control :4; | ||
185 | unsigned char track_num; | ||
186 | unsigned char index_num; | ||
187 | unsigned char rel_msf[3]; | ||
188 | unsigned char reserved1; | ||
189 | unsigned char abs_msf[3]; | ||
190 | }; | ||
191 | |||
192 | #define MAX_TRACKS 100 /* The maximum tracks a disk may have. */ | ||
193 | /* | ||
194 | * The following is returned from the request TOC (Table Of Contents) command. | ||
195 | * (last_track_num-first_track_num+1) values are valid in tracks. | ||
196 | */ | ||
197 | struct s_sony_toc | ||
198 | { | ||
199 | unsigned char exec_status[2]; | ||
200 | unsigned char address0 :4; | ||
201 | unsigned char control0 :4; | ||
202 | unsigned char point0; | ||
203 | unsigned char first_track_num; | ||
204 | unsigned char disk_type; | ||
205 | unsigned char dummy0; | ||
206 | unsigned char address1 :4; | ||
207 | unsigned char control1 :4; | ||
208 | unsigned char point1; | ||
209 | unsigned char last_track_num; | ||
210 | unsigned char dummy1; | ||
211 | unsigned char dummy2; | ||
212 | unsigned char address2 :4; | ||
213 | unsigned char control2 :4; | ||
214 | unsigned char point2; | ||
215 | unsigned char lead_out_start_msf[3]; | ||
216 | struct | ||
217 | { | ||
218 | unsigned char address :4; | ||
219 | unsigned char control :4; | ||
220 | unsigned char track; | ||
221 | unsigned char track_start_msf[3]; | ||
222 | } tracks[MAX_TRACKS]; | ||
223 | |||
224 | unsigned int lead_out_start_lba; | ||
225 | }; | ||
226 | |||
227 | struct s_sony_session_toc | ||
228 | { | ||
229 | unsigned char exec_status[2]; | ||
230 | unsigned char session_number; | ||
231 | unsigned char address0 :4; | ||
232 | unsigned char control0 :4; | ||
233 | unsigned char point0; | ||
234 | unsigned char first_track_num; | ||
235 | unsigned char disk_type; | ||
236 | unsigned char dummy0; | ||
237 | unsigned char address1 :4; | ||
238 | unsigned char control1 :4; | ||
239 | unsigned char point1; | ||
240 | unsigned char last_track_num; | ||
241 | unsigned char dummy1; | ||
242 | unsigned char dummy2; | ||
243 | unsigned char address2 :4; | ||
244 | unsigned char control2 :4; | ||
245 | unsigned char point2; | ||
246 | unsigned char lead_out_start_msf[3]; | ||
247 | unsigned char addressb0 :4; | ||
248 | unsigned char controlb0 :4; | ||
249 | unsigned char pointb0; | ||
250 | unsigned char next_poss_prog_area_msf[3]; | ||
251 | unsigned char num_mode_5_pointers; | ||
252 | unsigned char max_start_outer_leadout_msf[3]; | ||
253 | unsigned char addressb1 :4; | ||
254 | unsigned char controlb1 :4; | ||
255 | unsigned char pointb1; | ||
256 | unsigned char dummyb0_1[4]; | ||
257 | unsigned char num_skip_interval_pointers; | ||
258 | unsigned char num_skip_track_assignments; | ||
259 | unsigned char dummyb0_2; | ||
260 | unsigned char addressb2 :4; | ||
261 | unsigned char controlb2 :4; | ||
262 | unsigned char pointb2; | ||
263 | unsigned char tracksb2[7]; | ||
264 | unsigned char addressb3 :4; | ||
265 | unsigned char controlb3 :4; | ||
266 | unsigned char pointb3; | ||
267 | unsigned char tracksb3[7]; | ||
268 | unsigned char addressb4 :4; | ||
269 | unsigned char controlb4 :4; | ||
270 | unsigned char pointb4; | ||
271 | unsigned char tracksb4[7]; | ||
272 | unsigned char addressc0 :4; | ||
273 | unsigned char controlc0 :4; | ||
274 | unsigned char pointc0; | ||
275 | unsigned char dummyc0[7]; | ||
276 | struct | ||
277 | { | ||
278 | unsigned char address :4; | ||
279 | unsigned char control :4; | ||
280 | unsigned char track; | ||
281 | unsigned char track_start_msf[3]; | ||
282 | } tracks[MAX_TRACKS]; | ||
283 | |||
284 | unsigned int start_track_lba; | ||
285 | unsigned int lead_out_start_lba; | ||
286 | unsigned int mint; | ||
287 | unsigned int maxt; | ||
288 | }; | ||
289 | |||
290 | struct s_all_sessions_toc | ||
291 | { | ||
292 | unsigned char sessions; | ||
293 | unsigned int track_entries; | ||
294 | unsigned char first_track_num; | ||
295 | unsigned char last_track_num; | ||
296 | unsigned char disk_type; | ||
297 | unsigned char lead_out_start_msf[3]; | ||
298 | struct | ||
299 | { | ||
300 | unsigned char address :4; | ||
301 | unsigned char control :4; | ||
302 | unsigned char track; | ||
303 | unsigned char track_start_msf[3]; | ||
304 | } tracks[MAX_TRACKS]; | ||
305 | |||
306 | unsigned int start_track_lba; | ||
307 | unsigned int lead_out_start_lba; | ||
308 | }; | ||
309 | |||
310 | |||
311 | /* | ||
312 | * The following are errors returned from the drive. | ||
313 | */ | ||
314 | |||
315 | /* Command error group */ | ||
316 | #define SONY_ILL_CMD_ERR 0x10 | ||
317 | #define SONY_ILL_PARAM_ERR 0x11 | ||
318 | |||
319 | /* Mechanism group */ | ||
320 | #define SONY_NOT_LOAD_ERR 0x20 | ||
321 | #define SONY_NO_DISK_ERR 0x21 | ||
322 | #define SONY_NOT_SPIN_ERR 0x22 | ||
323 | #define SONY_SPIN_ERR 0x23 | ||
324 | #define SONY_SPINDLE_SERVO_ERR 0x25 | ||
325 | #define SONY_FOCUS_SERVO_ERR 0x26 | ||
326 | #define SONY_EJECT_MECH_ERR 0x29 | ||
327 | #define SONY_AUDIO_PLAYING_ERR 0x2a | ||
328 | #define SONY_EMERGENCY_EJECT_ERR 0x2c | ||
329 | |||
330 | /* Seek error group */ | ||
331 | #define SONY_FOCUS_ERR 0x30 | ||
332 | #define SONY_FRAME_SYNC_ERR 0x31 | ||
333 | #define SONY_SUBCODE_ADDR_ERR 0x32 | ||
334 | #define SONY_BLOCK_SYNC_ERR 0x33 | ||
335 | #define SONY_HEADER_ADDR_ERR 0x34 | ||
336 | |||
337 | /* Read error group */ | ||
338 | #define SONY_ILL_TRACK_R_ERR 0x40 | ||
339 | #define SONY_MODE_0_R_ERR 0x41 | ||
340 | #define SONY_ILL_MODE_R_ERR 0x42 | ||
341 | #define SONY_ILL_BLOCK_SIZE_R_ERR 0x43 | ||
342 | #define SONY_MODE_R_ERR 0x44 | ||
343 | #define SONY_FORM_R_ERR 0x45 | ||
344 | #define SONY_LEAD_OUT_R_ERR 0x46 | ||
345 | #define SONY_BUFFER_OVERRUN_R_ERR 0x47 | ||
346 | |||
347 | /* Data error group */ | ||
348 | #define SONY_UNREC_CIRC_ERR 0x53 | ||
349 | #define SONY_UNREC_LECC_ERR 0x57 | ||
350 | |||
351 | /* Subcode error group */ | ||
352 | #define SONY_NO_TOC_ERR 0x60 | ||
353 | #define SONY_SUBCODE_DATA_NVAL_ERR 0x61 | ||
354 | #define SONY_FOCUS_ON_TOC_READ_ERR 0x63 | ||
355 | #define SONY_FRAME_SYNC_ON_TOC_READ_ERR 0x64 | ||
356 | #define SONY_TOC_DATA_ERR 0x65 | ||
357 | |||
358 | /* Hardware failure group */ | ||
359 | #define SONY_HW_FAILURE_ERR 0x70 | ||
360 | #define SONY_LEAD_IN_A_ERR 0x91 | ||
361 | #define SONY_LEAD_OUT_A_ERR 0x92 | ||
362 | #define SONY_DATA_TRACK_A_ERR 0x93 | ||
363 | |||
364 | /* | ||
365 | * The following are returned from the Read With Block Error Status command. | ||
366 | * They are not errors but information (Errors from the 0x5x group above may | ||
367 | * also be returned | ||
368 | */ | ||
369 | #define SONY_NO_CIRC_ERR_BLK_STAT 0x50 | ||
370 | #define SONY_NO_LECC_ERR_BLK_STAT 0x54 | ||
371 | #define SONY_RECOV_LECC_ERR_BLK_STAT 0x55 | ||
372 | #define SONY_NO_ERR_DETECTION_STAT 0x59 | ||
373 | |||
374 | /* | ||
375 | * The following is not an error returned by the drive, but by the code | ||
376 | * that talks to the drive. It is returned because of a timeout. | ||
377 | */ | ||
378 | #define SONY_TIMEOUT_OP_ERR 0x01 | ||
379 | #define SONY_SIGNAL_OP_ERR 0x02 | ||
380 | #define SONY_BAD_DATA_ERR 0x03 | ||
381 | |||
382 | |||
383 | /* | ||
384 | * The following are attention code for asynchronous events from the drive. | ||
385 | */ | ||
386 | |||
387 | /* Standard attention group */ | ||
388 | #define SONY_EMER_EJECT_ATTN 0x2c | ||
389 | #define SONY_HW_FAILURE_ATTN 0x70 | ||
390 | #define SONY_MECH_LOADED_ATTN 0x80 | ||
391 | #define SONY_EJECT_PUSHED_ATTN 0x81 | ||
392 | |||
393 | /* Audio attention group */ | ||
394 | #define SONY_AUDIO_PLAY_DONE_ATTN 0x90 | ||
395 | #define SONY_LEAD_IN_ERR_ATTN 0x91 | ||
396 | #define SONY_LEAD_OUT_ERR_ATTN 0x92 | ||
397 | #define SONY_DATA_TRACK_ERR_ATTN 0x93 | ||
398 | #define SONY_AUDIO_PLAYBACK_ERR_ATTN 0x94 | ||
399 | |||
400 | /* Auto spin up group */ | ||
401 | #define SONY_SPIN_UP_COMPLETE_ATTN 0x24 | ||
402 | #define SONY_SPINDLE_SERVO_ERR_ATTN 0x25 | ||
403 | #define SONY_FOCUS_SERVO_ERR_ATTN 0x26 | ||
404 | #define SONY_TOC_READ_DONE_ATTN 0x62 | ||
405 | #define SONY_FOCUS_ON_TOC_READ_ERR_ATTN 0x63 | ||
406 | #define SONY_SYNC_ON_TOC_READ_ERR_ATTN 0x65 | ||
407 | |||
408 | /* Auto eject group */ | ||
409 | #define SONY_SPIN_DOWN_COMPLETE_ATTN 0x27 | ||
410 | #define SONY_EJECT_COMPLETE_ATTN 0x28 | ||
411 | #define SONY_EJECT_MECH_ERR_ATTN 0x29 | ||
diff --git a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c deleted file mode 100644 index 2f8fe3b6bbd0..000000000000 --- a/drivers/cdrom/cm206.c +++ /dev/null | |||
@@ -1,1594 +0,0 @@ | |||
1 | /* cm206.c. A linux-driver for the cm206 cdrom player with cm260 adapter card. | ||
2 | Copyright (c) 1995--1997 David A. van Leeuwen. | ||
3 | $Id: cm206.c,v 1.5 1997/12/26 11:02:51 david Exp $ | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2 of the License, or | ||
8 | (at your option) any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; if not, write to the Free Software | ||
17 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | |||
19 | History: | ||
20 | Started 25 jan 1994. Waiting for documentation... | ||
21 | 22 feb 1995: 0.1a first reasonably safe polling driver. | ||
22 | Two major bugs, one in read_sector and one in | ||
23 | do_cm206_request, happened to cancel! | ||
24 | 25 feb 1995: 0.2a first reasonable interrupt driven version of above. | ||
25 | uart writes are still done in polling mode. | ||
26 | 25 feb 1995: 0.21a writes also in interrupt mode, still some | ||
27 | small bugs to be found... Larger buffer. | ||
28 | 2 mrt 1995: 0.22 Bug found (cd-> nowhere, interrupt was called in | ||
29 | initialization), read_ahead of 16. Timeouts implemented. | ||
30 | unclear if they do something... | ||
31 | 7 mrt 1995: 0.23 Start of background read-ahead. | ||
32 | 18 mrt 1995: 0.24 Working background read-ahead. (still problems) | ||
33 | 26 mrt 1995: 0.25 Multi-session ioctl added (kernel v1.2). | ||
34 | Statistics implemented, though separate stats206.h. | ||
35 | Accessible through ioctl 0x1000 (just a number). | ||
36 | Hard to choose between v1.2 development and 1.1.75. | ||
37 | Bottom-half doesn't work with 1.2... | ||
38 | 0.25a: fixed... typo. Still problems... | ||
39 | 1 apr 1995: 0.26 Module support added. Most bugs found. Use kernel 1.2.n. | ||
40 | 5 apr 1995: 0.27 Auto-probe for the adapter card base address. | ||
41 | Auto-probe for the adaptor card irq line. | ||
42 | 7 apr 1995: 0.28 Added lilo setup support for base address and irq. | ||
43 | Use major number 32 (not in this source), officially | ||
44 | assigned to this driver. | ||
45 | 9 apr 1995: 0.29 Added very limited audio support. Toc_header, stop, pause, | ||
46 | resume, eject. Play_track ignores track info, because we can't | ||
47 | read a table-of-contents entry. Toc_entry is implemented | ||
48 | as a `placebo' function: always returns start of disc. | ||
49 | 3 may 1995: 0.30 Audio support completed. The get_toc_entry function | ||
50 | is implemented as a binary search. | ||
51 | 15 may 1995: 0.31 More work on audio stuff. Workman is not easy to | ||
52 | satisfy; changed binary search into linear search. | ||
53 | Auto-probe for base address somewhat relaxed. | ||
54 | 1 jun 1995: 0.32 Removed probe_irq_on/off for module version. | ||
55 | 10 jun 1995: 0.33 Workman still behaves funny, but you should be | ||
56 | able to eject and substitute another disc. | ||
57 | |||
58 | An adaptation of 0.33 is included in linux-1.3.7 by Eberhard Moenkeberg | ||
59 | |||
60 | 18 jul 1995: 0.34 Patch by Heiko Eissfeldt included, mainly considering | ||
61 | verify_area's in the ioctls. Some bugs introduced by | ||
62 | EM considering the base port and irq fixed. | ||
63 | |||
64 | 18 dec 1995: 0.35 Add some code for error checking... no luck... | ||
65 | |||
66 | We jump to reach our goal: version 1.0 in the next stable linux kernel. | ||
67 | |||
68 | 19 mar 1996: 0.95 Different implementation of CDROM_GET_UPC, on | ||
69 | request of Thomas Quinot. | ||
70 | 25 mar 1996: 0.96 Interpretation of opening with O_WRONLY or O_RDWR: | ||
71 | open only for ioctl operation, e.g., for operation of | ||
72 | tray etc. | ||
73 | 4 apr 1996: 0.97 First implementation of layer between VFS and cdrom | ||
74 | driver, a generic interface. Much of the functionality | ||
75 | of cm206_open() and cm206_ioctl() is transferred to a | ||
76 | new file cdrom.c and its header ucdrom.h. | ||
77 | |||
78 | Upgrade to Linux kernel 1.3.78. | ||
79 | |||
80 | 11 apr 1996 0.98 Upgrade to Linux kernel 1.3.85 | ||
81 | More code moved to cdrom.c | ||
82 | |||
83 | 0.99 Some more small changes to decrease number | ||
84 | of oopses at module load; | ||
85 | |||
86 | 27 jul 1996 0.100 Many hours of debugging, kernel change from 1.2.13 | ||
87 | to 2.0.7 seems to have introduced some weird behavior | ||
88 | in (interruptible_)sleep_on(&cd->data): the process | ||
89 | seems to be woken without any explicit wake_up in my own | ||
90 | code. Patch to try 100x in case such untriggered wake_up's | ||
91 | occur. | ||
92 | |||
93 | 28 jul 1996 0.101 Rewriting of the code that receives the command echo, | ||
94 | using a fifo to store echoed bytes. | ||
95 | |||
96 | Branch from 0.99: | ||
97 | |||
98 | 0.99.1.0 Update to kernel release 2.0.10 dev_t -> kdev_t | ||
99 | (emoenke) various typos found by others. extra | ||
100 | module-load oops protection. | ||
101 | |||
102 | 0.99.1.1 Initialization constant cdrom_dops.speed | ||
103 | changed from float (2.0) to int (2); Cli()-sti() pair | ||
104 | around cm260_reset() in module initialization code. | ||
105 | |||
106 | 0.99.1.2 Changes literally as proposed by Scott Snyder | ||
107 | <snyder@d0sgif.fnal.gov> for the 2.1 kernel line, which | ||
108 | have to do mainly with the poor minor support i had. The | ||
109 | major new concept is to change a cdrom driver's | ||
110 | operations struct from the capabilities struct. This | ||
111 | reflects the fact that there is one major for a driver, | ||
112 | whilst there can be many minors whith completely | ||
113 | different capabilities. | ||
114 | |||
115 | 0.99.1.3 More changes for operations/info separation. | ||
116 | |||
117 | 0.99.1.4 Added speed selection (someone had to do this | ||
118 | first). | ||
119 | |||
120 | 23 jan 1997 0.99.1.5 MODULE_PARMS call added. | ||
121 | |||
122 | 23 jan 1997 0.100.1.2--0.100.1.5 following similar lines as | ||
123 | 0.99.1.1--0.99.1.5. I get too many complaints about the | ||
124 | drive making read errors. What't wrong with the 2.0+ | ||
125 | kernel line? Why get i (and othe cm206 owners) weird | ||
126 | results? Why were things good in the good old 1.1--1.2 | ||
127 | era? Why don't i throw away the drive? | ||
128 | |||
129 | 2 feb 1997 0.102 Added `volatile' to values in cm206_struct. Seems to | ||
130 | reduce many of the problems. Rewrote polling routines | ||
131 | to use fixed delays between polls. | ||
132 | 0.103 Changed printk behavior. | ||
133 | 0.104 Added a 0.100 -> 0.100.1.1 change | ||
134 | |||
135 | 11 feb 1997 0.105 Allow auto_probe during module load, disable | ||
136 | with module option "auto_probe=0". Moved some debugging | ||
137 | statements to lower priority. Implemented select_speed() | ||
138 | function. | ||
139 | |||
140 | 13 feb 1997 1.0 Final version for 2.0 kernel line. | ||
141 | |||
142 | All following changes will be for the 2.1 kernel line. | ||
143 | |||
144 | 15 feb 1997 1.1 Keep up with kernel 2.1.26, merge in changes from | ||
145 | cdrom.c 0.100.1.1--1.0. Add some more MODULE_PARMS. | ||
146 | |||
147 | 14 sep 1997 1.2 Upgrade to Linux 2.1.55. Added blksize_size[], patch | ||
148 | sent by James Bottomley <James.Bottomley@columbiasc.ncr.com>. | ||
149 | |||
150 | 21 dec 1997 1.4 Upgrade to Linux 2.1.72. | ||
151 | |||
152 | 24 jan 1998 Removed the cm206_disc_status() function, as it was now dead | ||
153 | code. The Uniform CDROM driver now provides this functionality. | ||
154 | |||
155 | 9 Nov. 1999 Make kernel-parameter implementation work with 2.3.x | ||
156 | Removed init_module & cleanup_module in favor of | ||
157 | module_init & module_exit. | ||
158 | Torben Mathiasen <tmm@image.dk> | ||
159 | * | ||
160 | * Parts of the code are based upon lmscd.c written by Kai Petzke, | ||
161 | * sbpcd.c written by Eberhard Moenkeberg, and mcd.c by Martin | ||
162 | * Harriss, but any off-the-shelf dynamic programming algorithm won't | ||
163 | * be able to find them. | ||
164 | * | ||
165 | * The cm206 drive interface and the cm260 adapter card seem to be | ||
166 | * sufficiently different from their cm205/cm250 counterparts | ||
167 | * in order to write a complete new driver. | ||
168 | * | ||
169 | * I call all routines connected to the Linux kernel something | ||
170 | * with `cm206' in it, as this stuff is too series-dependent. | ||
171 | * | ||
172 | * Currently, my limited knowledge is based on: | ||
173 | * - The Linux Kernel Hacker's guide, v. 0.5, by Michael K. Johnson | ||
174 | * - Linux Kernel Programmierung, by Michael Beck and others | ||
175 | * - Philips/LMS cm206 and cm226 product specification | ||
176 | * - Philips/LMS cm260 product specification | ||
177 | * | ||
178 | * David van Leeuwen, david@tm.tno.nl. */ | ||
179 | #define REVISION "$Revision: 1.5 $" | ||
180 | |||
181 | #include <linux/module.h> | ||
182 | |||
183 | #include <linux/errno.h> /* These include what we really need */ | ||
184 | #include <linux/delay.h> | ||
185 | #include <linux/string.h> | ||
186 | #include <linux/interrupt.h> | ||
187 | #include <linux/timer.h> | ||
188 | #include <linux/cdrom.h> | ||
189 | #include <linux/ioport.h> | ||
190 | #include <linux/mm.h> | ||
191 | #include <linux/slab.h> | ||
192 | #include <linux/init.h> | ||
193 | |||
194 | /* #include <linux/ucdrom.h> */ | ||
195 | |||
196 | #include <asm/io.h> | ||
197 | |||
198 | #define MAJOR_NR CM206_CDROM_MAJOR | ||
199 | |||
200 | #include <linux/blkdev.h> | ||
201 | |||
202 | #undef DEBUG | ||
203 | #define STATISTICS /* record times and frequencies of events */ | ||
204 | #define AUTO_PROBE_MODULE | ||
205 | #define USE_INSW | ||
206 | |||
207 | #include "cm206.h" | ||
208 | |||
209 | /* This variable defines whether or not to probe for adapter base port | ||
210 | address and interrupt request. It can be overridden by the boot | ||
211 | parameter `auto'. | ||
212 | */ | ||
213 | static int auto_probe = 1; /* Yes, why not? */ | ||
214 | |||
215 | static int cm206_base = CM206_BASE; | ||
216 | static int cm206_irq = CM206_IRQ; | ||
217 | #ifdef MODULE | ||
218 | static int cm206[2] = { 0, 0 }; /* for compatible `insmod' parameter passing */ | ||
219 | module_param_array(cm206, int, NULL, 0); /* base,irq or irq,base */ | ||
220 | #endif | ||
221 | |||
222 | module_param(cm206_base, int, 0); /* base */ | ||
223 | module_param(cm206_irq, int, 0); /* irq */ | ||
224 | module_param(auto_probe, bool, 0); /* auto probe base and irq */ | ||
225 | MODULE_LICENSE("GPL"); | ||
226 | |||
227 | #define POLLOOP 100 /* milliseconds */ | ||
228 | #define READ_AHEAD 1 /* defines private buffer, waste! */ | ||
229 | #define BACK_AHEAD 1 /* defines adapter-read ahead */ | ||
230 | #define DATA_TIMEOUT (3*HZ) /* measured in jiffies (10 ms) */ | ||
231 | #define UART_TIMEOUT (5*HZ/100) | ||
232 | #define DSB_TIMEOUT (7*HZ) /* time for the slowest command to finish */ | ||
233 | #define UR_SIZE 4 /* uart receive buffer fifo size */ | ||
234 | |||
235 | #define LINUX_BLOCK_SIZE 512 /* WHERE is this defined? */ | ||
236 | #define RAW_SECTOR_SIZE 2352 /* ok, is also defined in cdrom.h */ | ||
237 | #define ISO_SECTOR_SIZE 2048 | ||
238 | #define BLOCKS_ISO (ISO_SECTOR_SIZE/LINUX_BLOCK_SIZE) /* 4 */ | ||
239 | #define CD_SYNC_HEAD 16 /* CD_SYNC + CD_HEAD */ | ||
240 | |||
241 | #ifdef STATISTICS /* keep track of errors in counters */ | ||
242 | #define stats(i) { ++cd->stats[st_ ## i]; \ | ||
243 | cd->last_stat[st_ ## i] = cd->stat_counter++; \ | ||
244 | } | ||
245 | #else | ||
246 | #define stats(i) (void) 0; | ||
247 | #endif | ||
248 | |||
249 | #define Debug(a) {printk (KERN_DEBUG); printk a;} | ||
250 | #ifdef DEBUG | ||
251 | #define debug(a) Debug(a) | ||
252 | #else | ||
253 | #define debug(a) (void) 0; | ||
254 | #endif | ||
255 | |||
256 | typedef unsigned char uch; /* 8-bits */ | ||
257 | typedef unsigned short ush; /* 16-bits */ | ||
258 | |||
259 | struct toc_struct { /* private copy of Table of Contents */ | ||
260 | uch track, fsm[3], q0; | ||
261 | }; | ||
262 | |||
263 | struct cm206_struct { | ||
264 | volatile ush intr_ds; /* data status read on last interrupt */ | ||
265 | volatile ush intr_ls; /* uart line status read on last interrupt */ | ||
266 | volatile uch ur[UR_SIZE]; /* uart receive buffer fifo */ | ||
267 | volatile uch ur_w, ur_r; /* write/read buffer index */ | ||
268 | volatile uch dsb, cc; /* drive status byte and condition (error) code */ | ||
269 | int command; /* command to be written to the uart */ | ||
270 | int openfiles; | ||
271 | ush sector[READ_AHEAD * RAW_SECTOR_SIZE / 2]; /* buffered cd-sector */ | ||
272 | int sector_first, sector_last; /* range of these sectors */ | ||
273 | wait_queue_head_t uart; /* wait queues for interrupt */ | ||
274 | wait_queue_head_t data; | ||
275 | struct timer_list timer; /* time-out */ | ||
276 | char timed_out; | ||
277 | signed char max_sectors; /* number of sectors that fit in adapter mem */ | ||
278 | char wait_back; /* we're waiting for a background-read */ | ||
279 | char background; /* is a read going on in the background? */ | ||
280 | int adapter_first; /* if so, that's the starting sector */ | ||
281 | int adapter_last; | ||
282 | char fifo_overflowed; | ||
283 | uch disc_status[7]; /* result of get_disc_status command */ | ||
284 | #ifdef STATISTICS | ||
285 | int stats[NR_STATS]; | ||
286 | int last_stat[NR_STATS]; /* `time' at which stat was stat */ | ||
287 | int stat_counter; | ||
288 | #endif | ||
289 | struct toc_struct toc[101]; /* The whole table of contents + lead-out */ | ||
290 | uch q[10]; /* Last read q-channel info */ | ||
291 | uch audio_status[5]; /* last read position on pause */ | ||
292 | uch media_changed; /* record if media changed */ | ||
293 | }; | ||
294 | |||
295 | #define DISC_STATUS cd->disc_status[0] | ||
296 | #define FIRST_TRACK cd->disc_status[1] | ||
297 | #define LAST_TRACK cd->disc_status[2] | ||
298 | #define PAUSED cd->audio_status[0] /* misuse this memory byte! */ | ||
299 | #define PLAY_TO cd->toc[0] /* toc[0] records end-time in play */ | ||
300 | |||
301 | static struct cm206_struct *cd; /* the main memory structure */ | ||
302 | static struct request_queue *cm206_queue; | ||
303 | static DEFINE_SPINLOCK(cm206_lock); | ||
304 | |||
305 | /* First, we define some polling functions. These are actually | ||
306 | only being used in the initialization. */ | ||
307 | |||
308 | static void send_command_polled(int command) | ||
309 | { | ||
310 | int loop = POLLOOP; | ||
311 | while (!(inw(r_line_status) & ls_transmitter_buffer_empty) | ||
312 | && loop > 0) { | ||
313 | mdelay(1); /* one millisec delay */ | ||
314 | --loop; | ||
315 | } | ||
316 | outw(command, r_uart_transmit); | ||
317 | } | ||
318 | |||
319 | static uch receive_echo_polled(void) | ||
320 | { | ||
321 | int loop = POLLOOP; | ||
322 | while (!(inw(r_line_status) & ls_receive_buffer_full) && loop > 0) { | ||
323 | mdelay(1); | ||
324 | --loop; | ||
325 | } | ||
326 | return ((uch) inw(r_uart_receive)); | ||
327 | } | ||
328 | |||
329 | static uch send_receive_polled(int command) | ||
330 | { | ||
331 | send_command_polled(command); | ||
332 | return receive_echo_polled(); | ||
333 | } | ||
334 | |||
335 | static inline void clear_ur(void) | ||
336 | { | ||
337 | if (cd->ur_r != cd->ur_w) { | ||
338 | debug(("Deleting bytes from fifo:")); | ||
339 | for (; cd->ur_r != cd->ur_w; | ||
340 | cd->ur_r++, cd->ur_r %= UR_SIZE) | ||
341 | debug((" 0x%x", cd->ur[cd->ur_r])); | ||
342 | debug(("\n")); | ||
343 | } | ||
344 | } | ||
345 | |||
346 | static struct tasklet_struct cm206_tasklet; | ||
347 | |||
348 | /* The interrupt handler. When the cm260 generates an interrupt, very | ||
349 | much care has to be taken in reading out the registers in the right | ||
350 | order; in case of a receive_buffer_full interrupt, first the | ||
351 | uart_receive must be read, and then the line status again to | ||
352 | de-assert the interrupt line. It took me a couple of hours to find | ||
353 | this out:-( | ||
354 | |||
355 | The function reset_cm206 appears to cause an interrupt, because | ||
356 | pulling up the INIT line clears both the uart-write-buffer /and/ | ||
357 | the uart-write-buffer-empty mask. We call this a `lost interrupt,' | ||
358 | as there seems so reason for this to happen. | ||
359 | */ | ||
360 | |||
361 | static irqreturn_t cm206_interrupt(int sig, void *dev_id) | ||
362 | { | ||
363 | volatile ush fool; | ||
364 | cd->intr_ds = inw(r_data_status); /* resets data_ready, data_error, | ||
365 | crc_error, sync_error, toc_ready | ||
366 | interrupts */ | ||
367 | cd->intr_ls = inw(r_line_status); /* resets overrun bit */ | ||
368 | debug(("Intr, 0x%x 0x%x, %d\n", cd->intr_ds, cd->intr_ls, | ||
369 | cd->background)); | ||
370 | if (cd->intr_ls & ls_attention) | ||
371 | stats(attention); | ||
372 | /* receive buffer full? */ | ||
373 | if (cd->intr_ls & ls_receive_buffer_full) { | ||
374 | cd->ur[cd->ur_w] = inb(r_uart_receive); /* get order right! */ | ||
375 | cd->intr_ls = inw(r_line_status); /* resets rbf interrupt */ | ||
376 | debug(("receiving #%d: 0x%x\n", cd->ur_w, | ||
377 | cd->ur[cd->ur_w])); | ||
378 | cd->ur_w++; | ||
379 | cd->ur_w %= UR_SIZE; | ||
380 | if (cd->ur_w == cd->ur_r) | ||
381 | debug(("cd->ur overflow!\n")); | ||
382 | if (waitqueue_active(&cd->uart) && cd->background < 2) { | ||
383 | del_timer(&cd->timer); | ||
384 | wake_up_interruptible(&cd->uart); | ||
385 | } | ||
386 | } | ||
387 | /* data ready in fifo? */ | ||
388 | else if (cd->intr_ds & ds_data_ready) { | ||
389 | if (cd->background) | ||
390 | ++cd->adapter_last; | ||
391 | if (waitqueue_active(&cd->data) | ||
392 | && (cd->wait_back || !cd->background)) { | ||
393 | del_timer(&cd->timer); | ||
394 | wake_up_interruptible(&cd->data); | ||
395 | } | ||
396 | stats(data_ready); | ||
397 | } | ||
398 | /* ready to issue a write command? */ | ||
399 | else if (cd->command && cd->intr_ls & ls_transmitter_buffer_empty) { | ||
400 | outw(dc_normal | (inw(r_data_status) & 0x7f), | ||
401 | r_data_control); | ||
402 | outw(cd->command, r_uart_transmit); | ||
403 | cd->command = 0; | ||
404 | if (!cd->background) | ||
405 | wake_up_interruptible(&cd->uart); | ||
406 | } | ||
407 | /* now treat errors (at least, identify them for debugging) */ | ||
408 | else if (cd->intr_ds & ds_fifo_overflow) { | ||
409 | debug(("Fifo overflow at sectors 0x%x\n", | ||
410 | cd->sector_first)); | ||
411 | fool = inw(r_fifo_output_buffer); /* de-assert the interrupt */ | ||
412 | cd->fifo_overflowed = 1; /* signal one word less should be read */ | ||
413 | stats(fifo_overflow); | ||
414 | } else if (cd->intr_ds & ds_data_error) { | ||
415 | debug(("Data error at sector 0x%x\n", cd->sector_first)); | ||
416 | stats(data_error); | ||
417 | } else if (cd->intr_ds & ds_crc_error) { | ||
418 | debug(("CRC error at sector 0x%x\n", cd->sector_first)); | ||
419 | stats(crc_error); | ||
420 | } else if (cd->intr_ds & ds_sync_error) { | ||
421 | debug(("Sync at sector 0x%x\n", cd->sector_first)); | ||
422 | stats(sync_error); | ||
423 | } else if (cd->intr_ds & ds_toc_ready) { | ||
424 | /* do something appropriate */ | ||
425 | } | ||
426 | /* couldn't see why this interrupt, maybe due to init */ | ||
427 | else { | ||
428 | outw(dc_normal | READ_AHEAD, r_data_control); | ||
429 | stats(lost_intr); | ||
430 | } | ||
431 | if (cd->background | ||
432 | && (cd->adapter_last - cd->adapter_first == cd->max_sectors | ||
433 | || cd->fifo_overflowed)) | ||
434 | tasklet_schedule(&cm206_tasklet); /* issue a stop read command */ | ||
435 | stats(interrupt); | ||
436 | return IRQ_HANDLED; | ||
437 | } | ||
438 | |||
439 | /* we have put the address of the wait queue in who */ | ||
440 | static void cm206_timeout(unsigned long who) | ||
441 | { | ||
442 | cd->timed_out = 1; | ||
443 | debug(("Timing out\n")); | ||
444 | wake_up_interruptible((wait_queue_head_t *) who); | ||
445 | } | ||
446 | |||
447 | /* This function returns 1 if a timeout occurred, 0 if an interrupt | ||
448 | happened */ | ||
449 | static int sleep_or_timeout(wait_queue_head_t * wait, int timeout) | ||
450 | { | ||
451 | cd->timed_out = 0; | ||
452 | init_timer(&cd->timer); | ||
453 | cd->timer.data = (unsigned long) wait; | ||
454 | cd->timer.expires = jiffies + timeout; | ||
455 | add_timer(&cd->timer); | ||
456 | debug(("going to sleep\n")); | ||
457 | interruptible_sleep_on(wait); | ||
458 | del_timer(&cd->timer); | ||
459 | if (cd->timed_out) { | ||
460 | cd->timed_out = 0; | ||
461 | return 1; | ||
462 | } else | ||
463 | return 0; | ||
464 | } | ||
465 | |||
466 | static void send_command(int command) | ||
467 | { | ||
468 | debug(("Sending 0x%x\n", command)); | ||
469 | if (!(inw(r_line_status) & ls_transmitter_buffer_empty)) { | ||
470 | cd->command = command; | ||
471 | cli(); /* don't interrupt before sleep */ | ||
472 | outw(dc_mask_sync_error | dc_no_stop_on_error | | ||
473 | (inw(r_data_status) & 0x7f), r_data_control); | ||
474 | /* interrupt routine sends command */ | ||
475 | if (sleep_or_timeout(&cd->uart, UART_TIMEOUT)) { | ||
476 | debug(("Time out on write-buffer\n")); | ||
477 | stats(write_timeout); | ||
478 | outw(command, r_uart_transmit); | ||
479 | } | ||
480 | debug(("Write commmand delayed\n")); | ||
481 | } else | ||
482 | outw(command, r_uart_transmit); | ||
483 | } | ||
484 | |||
485 | static uch receive_byte(int timeout) | ||
486 | { | ||
487 | uch ret; | ||
488 | cli(); | ||
489 | debug(("cli\n")); | ||
490 | ret = cd->ur[cd->ur_r]; | ||
491 | if (cd->ur_r != cd->ur_w) { | ||
492 | sti(); | ||
493 | debug(("returning #%d: 0x%x\n", cd->ur_r, | ||
494 | cd->ur[cd->ur_r])); | ||
495 | cd->ur_r++; | ||
496 | cd->ur_r %= UR_SIZE; | ||
497 | return ret; | ||
498 | } else if (sleep_or_timeout(&cd->uart, timeout)) { /* does sti() */ | ||
499 | debug(("Time out on receive-buffer\n")); | ||
500 | #ifdef STATISTICS | ||
501 | if (timeout == UART_TIMEOUT) | ||
502 | stats(receive_timeout) /* no `;'! */ | ||
503 | else | ||
504 | stats(dsb_timeout); | ||
505 | #endif | ||
506 | return 0xda; | ||
507 | } | ||
508 | ret = cd->ur[cd->ur_r]; | ||
509 | debug(("slept; returning #%d: 0x%x\n", cd->ur_r, | ||
510 | cd->ur[cd->ur_r])); | ||
511 | cd->ur_r++; | ||
512 | cd->ur_r %= UR_SIZE; | ||
513 | return ret; | ||
514 | } | ||
515 | |||
516 | static inline uch receive_echo(void) | ||
517 | { | ||
518 | return receive_byte(UART_TIMEOUT); | ||
519 | } | ||
520 | |||
521 | static inline uch send_receive(int command) | ||
522 | { | ||
523 | send_command(command); | ||
524 | return receive_echo(); | ||
525 | } | ||
526 | |||
527 | static inline uch wait_dsb(void) | ||
528 | { | ||
529 | return receive_byte(DSB_TIMEOUT); | ||
530 | } | ||
531 | |||
532 | static int type_0_command(int command, int expect_dsb) | ||
533 | { | ||
534 | int e; | ||
535 | clear_ur(); | ||
536 | if (command != (e = send_receive(command))) { | ||
537 | debug(("command 0x%x echoed as 0x%x\n", command, e)); | ||
538 | stats(echo); | ||
539 | return -1; | ||
540 | } | ||
541 | if (expect_dsb) { | ||
542 | cd->dsb = wait_dsb(); /* wait for command to finish */ | ||
543 | } | ||
544 | return 0; | ||
545 | } | ||
546 | |||
547 | static int type_1_command(int command, int bytes, uch * status) | ||
548 | { /* returns info */ | ||
549 | int i; | ||
550 | if (type_0_command(command, 0)) | ||
551 | return -1; | ||
552 | for (i = 0; i < bytes; i++) | ||
553 | status[i] = send_receive(c_gimme); | ||
554 | return 0; | ||
555 | } | ||
556 | |||
557 | /* This function resets the adapter card. We'd better not do this too | ||
558 | * often, because it tends to generate `lost interrupts.' */ | ||
559 | static void reset_cm260(void) | ||
560 | { | ||
561 | outw(dc_normal | dc_initialize | READ_AHEAD, r_data_control); | ||
562 | udelay(10); /* 3.3 mu sec minimum */ | ||
563 | outw(dc_normal | READ_AHEAD, r_data_control); | ||
564 | } | ||
565 | |||
566 | /* fsm: frame-sec-min from linear address; one of many */ | ||
567 | static void fsm(int lba, uch * fsm) | ||
568 | { | ||
569 | fsm[0] = lba % 75; | ||
570 | lba /= 75; | ||
571 | lba += 2; | ||
572 | fsm[1] = lba % 60; | ||
573 | fsm[2] = lba / 60; | ||
574 | } | ||
575 | |||
576 | static inline int fsm2lba(uch * fsm) | ||
577 | { | ||
578 | return fsm[0] + 75 * (fsm[1] - 2 + 60 * fsm[2]); | ||
579 | } | ||
580 | |||
581 | static inline int f_s_m2lba(uch f, uch s, uch m) | ||
582 | { | ||
583 | return f + 75 * (s - 2 + 60 * m); | ||
584 | } | ||
585 | |||
586 | static int start_read(int start) | ||
587 | { | ||
588 | uch read_sector[4] = { c_read_data, }; | ||
589 | int i, e; | ||
590 | |||
591 | fsm(start, &read_sector[1]); | ||
592 | clear_ur(); | ||
593 | for (i = 0; i < 4; i++) | ||
594 | if (read_sector[i] != (e = send_receive(read_sector[i]))) { | ||
595 | debug(("read_sector: %x echoes %x\n", | ||
596 | read_sector[i], e)); | ||
597 | stats(echo); | ||
598 | if (e == 0xff) { /* this seems to happen often */ | ||
599 | e = receive_echo(); | ||
600 | debug(("Second try %x\n", e)); | ||
601 | if (e != read_sector[i]) | ||
602 | return -1; | ||
603 | } | ||
604 | } | ||
605 | return 0; | ||
606 | } | ||
607 | |||
608 | static int stop_read(void) | ||
609 | { | ||
610 | int e; | ||
611 | type_0_command(c_stop, 0); | ||
612 | if ((e = receive_echo()) != 0xff) { | ||
613 | debug(("c_stop didn't send 0xff, but 0x%x\n", e)); | ||
614 | stats(stop_0xff); | ||
615 | return -1; | ||
616 | } | ||
617 | return 0; | ||
618 | } | ||
619 | |||
620 | /* This function starts to read sectors in adapter memory, the | ||
621 | interrupt routine should stop the read. In fact, the bottom_half | ||
622 | routine takes care of this. Set a flag `background' in the cd | ||
623 | struct to indicate the process. */ | ||
624 | |||
625 | static int read_background(int start, int reading) | ||
626 | { | ||
627 | if (cd->background) | ||
628 | return -1; /* can't do twice */ | ||
629 | outw(dc_normal | BACK_AHEAD, r_data_control); | ||
630 | if (!reading && start_read(start)) | ||
631 | return -2; | ||
632 | cd->adapter_first = cd->adapter_last = start; | ||
633 | cd->background = 1; /* flag a read is going on */ | ||
634 | return 0; | ||
635 | } | ||
636 | |||
637 | #ifdef USE_INSW | ||
638 | #define transport_data insw | ||
639 | #else | ||
640 | /* this routine implements insw(,,). There was a time i had the | ||
641 | impression that there would be any difference in error-behaviour. */ | ||
642 | void transport_data(int port, ush * dest, int count) | ||
643 | { | ||
644 | int i; | ||
645 | ush *d; | ||
646 | for (i = 0, d = dest; i < count; i++, d++) | ||
647 | *d = inw(port); | ||
648 | } | ||
649 | #endif | ||
650 | |||
651 | |||
652 | #define MAX_TRIES 100 | ||
653 | static int read_sector(int start) | ||
654 | { | ||
655 | int tries = 0; | ||
656 | if (cd->background) { | ||
657 | cd->background = 0; | ||
658 | cd->adapter_last = -1; /* invalidate adapter memory */ | ||
659 | stop_read(); | ||
660 | } | ||
661 | cd->fifo_overflowed = 0; | ||
662 | reset_cm260(); /* empty fifo etc. */ | ||
663 | if (start_read(start)) | ||
664 | return -1; | ||
665 | do { | ||
666 | if (sleep_or_timeout(&cd->data, DATA_TIMEOUT)) { | ||
667 | debug(("Read timed out sector 0x%x\n", start)); | ||
668 | stats(read_timeout); | ||
669 | stop_read(); | ||
670 | return -3; | ||
671 | } | ||
672 | tries++; | ||
673 | } while (cd->intr_ds & ds_fifo_empty && tries < MAX_TRIES); | ||
674 | if (tries > 1) | ||
675 | debug(("Took me some tries\n")) | ||
676 | else | ||
677 | if (tries == MAX_TRIES) | ||
678 | debug(("MAX_TRIES tries for read sector\n")); | ||
679 | transport_data(r_fifo_output_buffer, cd->sector, | ||
680 | READ_AHEAD * RAW_SECTOR_SIZE / 2); | ||
681 | if (read_background(start + READ_AHEAD, 1)) | ||
682 | stats(read_background); | ||
683 | cd->sector_first = start; | ||
684 | cd->sector_last = start + READ_AHEAD; | ||
685 | stats(read_restarted); | ||
686 | return 0; | ||
687 | } | ||
688 | |||
689 | /* The function of bottom-half is to send a stop command to the drive | ||
690 | This isn't easy because the routine is not `owned' by any process; | ||
691 | we can't go to sleep! The variable cd->background gives the status: | ||
692 | 0 no read pending | ||
693 | 1 a read is pending | ||
694 | 2 c_stop waits for write_buffer_empty | ||
695 | 3 c_stop waits for receive_buffer_full: echo | ||
696 | 4 c_stop waits for receive_buffer_full: 0xff | ||
697 | */ | ||
698 | |||
699 | static void cm206_tasklet_func(unsigned long ignore) | ||
700 | { | ||
701 | debug(("bh: %d\n", cd->background)); | ||
702 | switch (cd->background) { | ||
703 | case 1: | ||
704 | stats(bh); | ||
705 | if (!(cd->intr_ls & ls_transmitter_buffer_empty)) { | ||
706 | cd->command = c_stop; | ||
707 | outw(dc_mask_sync_error | dc_no_stop_on_error | | ||
708 | (inw(r_data_status) & 0x7f), r_data_control); | ||
709 | cd->background = 2; | ||
710 | break; /* we'd better not time-out here! */ | ||
711 | } else | ||
712 | outw(c_stop, r_uart_transmit); | ||
713 | /* fall into case 2: */ | ||
714 | case 2: | ||
715 | /* the write has been satisfied by interrupt routine */ | ||
716 | cd->background = 3; | ||
717 | break; | ||
718 | case 3: | ||
719 | if (cd->ur_r != cd->ur_w) { | ||
720 | if (cd->ur[cd->ur_r] != c_stop) { | ||
721 | debug(("cm206_bh: c_stop echoed 0x%x\n", | ||
722 | cd->ur[cd->ur_r])); | ||
723 | stats(echo); | ||
724 | } | ||
725 | cd->ur_r++; | ||
726 | cd->ur_r %= UR_SIZE; | ||
727 | } | ||
728 | cd->background++; | ||
729 | break; | ||
730 | case 4: | ||
731 | if (cd->ur_r != cd->ur_w) { | ||
732 | if (cd->ur[cd->ur_r] != 0xff) { | ||
733 | debug(("cm206_bh: c_stop reacted with 0x%x\n", cd->ur[cd->ur_r])); | ||
734 | stats(stop_0xff); | ||
735 | } | ||
736 | cd->ur_r++; | ||
737 | cd->ur_r %= UR_SIZE; | ||
738 | } | ||
739 | cd->background = 0; | ||
740 | } | ||
741 | } | ||
742 | |||
743 | static DECLARE_TASKLET(cm206_tasklet, cm206_tasklet_func, 0); | ||
744 | |||
745 | /* This command clears the dsb_possible_media_change flag, so we must | ||
746 | * retain it. | ||
747 | */ | ||
748 | static void get_drive_status(void) | ||
749 | { | ||
750 | uch status[2]; | ||
751 | type_1_command(c_drive_status, 2, status); /* this might be done faster */ | ||
752 | cd->dsb = status[0]; | ||
753 | cd->cc = status[1]; | ||
754 | cd->media_changed |= | ||
755 | !!(cd->dsb & (dsb_possible_media_change | | ||
756 | dsb_drive_not_ready | dsb_tray_not_closed)); | ||
757 | } | ||
758 | |||
759 | static void get_disc_status(void) | ||
760 | { | ||
761 | if (type_1_command(c_disc_status, 7, cd->disc_status)) { | ||
762 | debug(("get_disc_status: error\n")); | ||
763 | } | ||
764 | } | ||
765 | |||
766 | /* The new open. The real opening strategy is defined in cdrom.c. */ | ||
767 | |||
768 | static int cm206_open(struct cdrom_device_info *cdi, int purpose) | ||
769 | { | ||
770 | if (!cd->openfiles) { /* reset only first time */ | ||
771 | cd->background = 0; | ||
772 | reset_cm260(); | ||
773 | cd->adapter_last = -1; /* invalidate adapter memory */ | ||
774 | cd->sector_last = -1; | ||
775 | } | ||
776 | ++cd->openfiles; | ||
777 | stats(open); | ||
778 | return 0; | ||
779 | } | ||
780 | |||
781 | static void cm206_release(struct cdrom_device_info *cdi) | ||
782 | { | ||
783 | if (cd->openfiles == 1) { | ||
784 | if (cd->background) { | ||
785 | cd->background = 0; | ||
786 | stop_read(); | ||
787 | } | ||
788 | cd->sector_last = -1; /* Make our internal buffer invalid */ | ||
789 | FIRST_TRACK = 0; /* No valid disc status */ | ||
790 | } | ||
791 | --cd->openfiles; | ||
792 | } | ||
793 | |||
794 | /* Empty buffer empties $sectors$ sectors of the adapter card buffer, | ||
795 | * and then reads a sector in kernel memory. */ | ||
796 | static void empty_buffer(int sectors) | ||
797 | { | ||
798 | while (sectors >= 0) { | ||
799 | transport_data(r_fifo_output_buffer, | ||
800 | cd->sector + cd->fifo_overflowed, | ||
801 | RAW_SECTOR_SIZE / 2 - cd->fifo_overflowed); | ||
802 | --sectors; | ||
803 | ++cd->adapter_first; /* update the current adapter sector */ | ||
804 | cd->fifo_overflowed = 0; /* reset overflow bit */ | ||
805 | stats(sector_transferred); | ||
806 | } | ||
807 | cd->sector_first = cd->adapter_first - 1; | ||
808 | cd->sector_last = cd->adapter_first; /* update the buffer sector */ | ||
809 | } | ||
810 | |||
811 | /* try_adapter. This function determines if the requested sector is | ||
812 | in adapter memory, or will appear there soon. Returns 0 upon | ||
813 | success */ | ||
814 | static int try_adapter(int sector) | ||
815 | { | ||
816 | if (cd->adapter_first <= sector && sector < cd->adapter_last) { | ||
817 | /* sector is in adapter memory */ | ||
818 | empty_buffer(sector - cd->adapter_first); | ||
819 | return 0; | ||
820 | } else if (cd->background == 1 && cd->adapter_first <= sector | ||
821 | && sector < cd->adapter_first + cd->max_sectors) { | ||
822 | /* a read is going on, we can wait for it */ | ||
823 | cd->wait_back = 1; | ||
824 | while (sector >= cd->adapter_last) { | ||
825 | if (sleep_or_timeout(&cd->data, DATA_TIMEOUT)) { | ||
826 | debug(("Timed out during background wait: %d %d %d %d\n", sector, cd->adapter_last, cd->adapter_first, cd->background)); | ||
827 | stats(back_read_timeout); | ||
828 | cd->wait_back = 0; | ||
829 | return -1; | ||
830 | } | ||
831 | } | ||
832 | cd->wait_back = 0; | ||
833 | empty_buffer(sector - cd->adapter_first); | ||
834 | return 0; | ||
835 | } else | ||
836 | return -2; | ||
837 | } | ||
838 | |||
839 | /* This is not a very smart implementation. We could optimize for | ||
840 | consecutive block numbers. I'm not convinced this would really | ||
841 | bring down the processor load. */ | ||
842 | static void do_cm206_request(request_queue_t * q) | ||
843 | { | ||
844 | long int i, cd_sec_no; | ||
845 | int quarter, error; | ||
846 | uch *source, *dest; | ||
847 | struct request *req; | ||
848 | |||
849 | while (1) { /* repeat until all requests have been satisfied */ | ||
850 | req = elv_next_request(q); | ||
851 | if (!req) | ||
852 | return; | ||
853 | |||
854 | if (rq_data_dir(req) != READ) { | ||
855 | debug(("Non-read command %d on cdrom\n", req->cmd)); | ||
856 | end_request(req, 0); | ||
857 | continue; | ||
858 | } | ||
859 | spin_unlock_irq(q->queue_lock); | ||
860 | error = 0; | ||
861 | for (i = 0; i < req->nr_sectors; i++) { | ||
862 | int e1, e2; | ||
863 | cd_sec_no = (req->sector + i) / BLOCKS_ISO; /* 4 times 512 bytes */ | ||
864 | quarter = (req->sector + i) % BLOCKS_ISO; | ||
865 | dest = req->buffer + i * LINUX_BLOCK_SIZE; | ||
866 | /* is already in buffer memory? */ | ||
867 | if (cd->sector_first <= cd_sec_no | ||
868 | && cd_sec_no < cd->sector_last) { | ||
869 | source = | ||
870 | ((uch *) cd->sector) + 16 + | ||
871 | quarter * LINUX_BLOCK_SIZE + | ||
872 | (cd_sec_no - | ||
873 | cd->sector_first) * RAW_SECTOR_SIZE; | ||
874 | memcpy(dest, source, LINUX_BLOCK_SIZE); | ||
875 | } else if (!(e1 = try_adapter(cd_sec_no)) || | ||
876 | !(e2 = read_sector(cd_sec_no))) { | ||
877 | source = | ||
878 | ((uch *) cd->sector) + 16 + | ||
879 | quarter * LINUX_BLOCK_SIZE; | ||
880 | memcpy(dest, source, LINUX_BLOCK_SIZE); | ||
881 | } else { | ||
882 | error = 1; | ||
883 | debug(("cm206_request: %d %d\n", e1, e2)); | ||
884 | } | ||
885 | } | ||
886 | spin_lock_irq(q->queue_lock); | ||
887 | end_request(req, !error); | ||
888 | } | ||
889 | } | ||
890 | |||
891 | /* Audio support. I've tried very hard, but the cm206 drive doesn't | ||
892 | seem to have a get_toc (table-of-contents) function, while i'm | ||
893 | pretty sure it must read the toc upon disc insertion. Therefore | ||
894 | this function has been implemented through a binary search | ||
895 | strategy. All track starts that happen to be found are stored in | ||
896 | cd->toc[], for future use. | ||
897 | |||
898 | I've spent a whole day on a bug that only shows under Workman--- | ||
899 | I don't get it. Tried everything, nothing works. If workman asks | ||
900 | for track# 0xaa, it'll get the wrong time back. Any other program | ||
901 | receives the correct value. I'm stymied. | ||
902 | */ | ||
903 | |||
904 | /* seek seeks to address lba. It does wait to arrive there. */ | ||
905 | static void seek(int lba) | ||
906 | { | ||
907 | int i; | ||
908 | uch seek_command[4] = { c_seek, }; | ||
909 | |||
910 | fsm(lba, &seek_command[1]); | ||
911 | for (i = 0; i < 4; i++) | ||
912 | type_0_command(seek_command[i], 0); | ||
913 | cd->dsb = wait_dsb(); | ||
914 | } | ||
915 | |||
916 | static uch bcdbin(unsigned char bcd) | ||
917 | { /* stolen from mcd.c! */ | ||
918 | return (bcd >> 4) * 10 + (bcd & 0xf); | ||
919 | } | ||
920 | |||
921 | static inline uch normalize_track(uch track) | ||
922 | { | ||
923 | if (track < 1) | ||
924 | return 1; | ||
925 | if (track > LAST_TRACK) | ||
926 | return LAST_TRACK + 1; | ||
927 | return track; | ||
928 | } | ||
929 | |||
930 | /* This function does a binary search for track start. It records all | ||
931 | * tracks seen in the process. Input $track$ must be between 1 and | ||
932 | * #-of-tracks+1. Note that the start of the disc must be in toc[1].fsm. | ||
933 | */ | ||
934 | static int get_toc_lba(uch track) | ||
935 | { | ||
936 | int max = 74 * 60 * 75 - 150, min = fsm2lba(cd->toc[1].fsm); | ||
937 | int i, lba, l, old_lba = 0; | ||
938 | uch *q = cd->q; | ||
939 | uch ct; /* current track */ | ||
940 | int binary = 0; | ||
941 | const int skip = 3 * 60 * 75; /* 3 minutes */ | ||
942 | |||
943 | for (i = track; i > 0; i--) | ||
944 | if (cd->toc[i].track) { | ||
945 | min = fsm2lba(cd->toc[i].fsm); | ||
946 | break; | ||
947 | } | ||
948 | lba = min + skip; | ||
949 | do { | ||
950 | seek(lba); | ||
951 | type_1_command(c_read_current_q, 10, q); | ||
952 | ct = normalize_track(q[1]); | ||
953 | if (!cd->toc[ct].track) { | ||
954 | l = q[9] - bcdbin(q[5]) + 75 * (q[8] - | ||
955 | bcdbin(q[4]) - 2 + | ||
956 | 60 * (q[7] - | ||
957 | bcdbin(q | ||
958 | [3]))); | ||
959 | cd->toc[ct].track = q[1]; /* lead out still 0xaa */ | ||
960 | fsm(l, cd->toc[ct].fsm); | ||
961 | cd->toc[ct].q0 = q[0]; /* contains adr and ctrl info */ | ||
962 | if (ct == track) | ||
963 | return l; | ||
964 | } | ||
965 | old_lba = lba; | ||
966 | if (binary) { | ||
967 | if (ct < track) | ||
968 | min = lba; | ||
969 | else | ||
970 | max = lba; | ||
971 | lba = (min + max) / 2; | ||
972 | } else { | ||
973 | if (ct < track) | ||
974 | lba += skip; | ||
975 | else { | ||
976 | binary = 1; | ||
977 | max = lba; | ||
978 | min = lba - skip; | ||
979 | lba = (min + max) / 2; | ||
980 | } | ||
981 | } | ||
982 | } while (lba != old_lba); | ||
983 | return lba; | ||
984 | } | ||
985 | |||
986 | static void update_toc_entry(uch track) | ||
987 | { | ||
988 | track = normalize_track(track); | ||
989 | if (!cd->toc[track].track) | ||
990 | get_toc_lba(track); | ||
991 | } | ||
992 | |||
993 | /* return 0 upon success */ | ||
994 | static int read_toc_header(struct cdrom_tochdr *hp) | ||
995 | { | ||
996 | if (!FIRST_TRACK) | ||
997 | get_disc_status(); | ||
998 | if (hp) { | ||
999 | int i; | ||
1000 | hp->cdth_trk0 = FIRST_TRACK; | ||
1001 | hp->cdth_trk1 = LAST_TRACK; | ||
1002 | /* fill in first track position */ | ||
1003 | for (i = 0; i < 3; i++) | ||
1004 | cd->toc[1].fsm[i] = cd->disc_status[3 + i]; | ||
1005 | update_toc_entry(LAST_TRACK + 1); /* find most entries */ | ||
1006 | return 0; | ||
1007 | } | ||
1008 | return -1; | ||
1009 | } | ||
1010 | |||
1011 | static void play_from_to_msf(struct cdrom_msf *msfp) | ||
1012 | { | ||
1013 | uch play_command[] = { c_play, | ||
1014 | msfp->cdmsf_frame0, msfp->cdmsf_sec0, msfp->cdmsf_min0, | ||
1015 | msfp->cdmsf_frame1, msfp->cdmsf_sec1, msfp->cdmsf_min1, 2, | ||
1016 | 2 | ||
1017 | }; | ||
1018 | int i; | ||
1019 | for (i = 0; i < 9; i++) | ||
1020 | type_0_command(play_command[i], 0); | ||
1021 | for (i = 0; i < 3; i++) | ||
1022 | PLAY_TO.fsm[i] = play_command[i + 4]; | ||
1023 | PLAY_TO.track = 0; /* say no track end */ | ||
1024 | cd->dsb = wait_dsb(); | ||
1025 | } | ||
1026 | |||
1027 | static void play_from_to_track(int from, int to) | ||
1028 | { | ||
1029 | uch play_command[8] = { c_play, }; | ||
1030 | int i; | ||
1031 | |||
1032 | if (from == 0) { /* continue paused play */ | ||
1033 | for (i = 0; i < 3; i++) { | ||
1034 | play_command[i + 1] = cd->audio_status[i + 2]; | ||
1035 | play_command[i + 4] = PLAY_TO.fsm[i]; | ||
1036 | } | ||
1037 | } else { | ||
1038 | update_toc_entry(from); | ||
1039 | update_toc_entry(to + 1); | ||
1040 | for (i = 0; i < 3; i++) { | ||
1041 | play_command[i + 1] = cd->toc[from].fsm[i]; | ||
1042 | PLAY_TO.fsm[i] = play_command[i + 4] = | ||
1043 | cd->toc[to + 1].fsm[i]; | ||
1044 | } | ||
1045 | PLAY_TO.track = to; | ||
1046 | } | ||
1047 | for (i = 0; i < 7; i++) | ||
1048 | type_0_command(play_command[i], 0); | ||
1049 | for (i = 0; i < 2; i++) | ||
1050 | type_0_command(0x2, 0); /* volume */ | ||
1051 | cd->dsb = wait_dsb(); | ||
1052 | } | ||
1053 | |||
1054 | static int get_current_q(struct cdrom_subchnl *qp) | ||
1055 | { | ||
1056 | int i; | ||
1057 | uch *q = cd->q; | ||
1058 | if (type_1_command(c_read_current_q, 10, q)) | ||
1059 | return 0; | ||
1060 | /* q[0] = bcdbin(q[0]); Don't think so! */ | ||
1061 | for (i = 2; i < 6; i++) | ||
1062 | q[i] = bcdbin(q[i]); | ||
1063 | qp->cdsc_adr = q[0] & 0xf; | ||
1064 | qp->cdsc_ctrl = q[0] >> 4; /* from mcd.c */ | ||
1065 | qp->cdsc_trk = q[1]; | ||
1066 | qp->cdsc_ind = q[2]; | ||
1067 | if (qp->cdsc_format == CDROM_MSF) { | ||
1068 | qp->cdsc_reladdr.msf.minute = q[3]; | ||
1069 | qp->cdsc_reladdr.msf.second = q[4]; | ||
1070 | qp->cdsc_reladdr.msf.frame = q[5]; | ||
1071 | qp->cdsc_absaddr.msf.minute = q[7]; | ||
1072 | qp->cdsc_absaddr.msf.second = q[8]; | ||
1073 | qp->cdsc_absaddr.msf.frame = q[9]; | ||
1074 | } else { | ||
1075 | qp->cdsc_reladdr.lba = f_s_m2lba(q[5], q[4], q[3]); | ||
1076 | qp->cdsc_absaddr.lba = f_s_m2lba(q[9], q[8], q[7]); | ||
1077 | } | ||
1078 | get_drive_status(); | ||
1079 | if (cd->dsb & dsb_play_in_progress) | ||
1080 | qp->cdsc_audiostatus = CDROM_AUDIO_PLAY; | ||
1081 | else if (PAUSED) | ||
1082 | qp->cdsc_audiostatus = CDROM_AUDIO_PAUSED; | ||
1083 | else | ||
1084 | qp->cdsc_audiostatus = CDROM_AUDIO_NO_STATUS; | ||
1085 | return 0; | ||
1086 | } | ||
1087 | |||
1088 | static void invalidate_toc(void) | ||
1089 | { | ||
1090 | memset(cd->toc, 0, sizeof(cd->toc)); | ||
1091 | memset(cd->disc_status, 0, sizeof(cd->disc_status)); | ||
1092 | } | ||
1093 | |||
1094 | /* cdrom.c guarantees that cdte_format == CDROM_MSF */ | ||
1095 | static void get_toc_entry(struct cdrom_tocentry *ep) | ||
1096 | { | ||
1097 | uch track = normalize_track(ep->cdte_track); | ||
1098 | update_toc_entry(track); | ||
1099 | ep->cdte_addr.msf.frame = cd->toc[track].fsm[0]; | ||
1100 | ep->cdte_addr.msf.second = cd->toc[track].fsm[1]; | ||
1101 | ep->cdte_addr.msf.minute = cd->toc[track].fsm[2]; | ||
1102 | ep->cdte_adr = cd->toc[track].q0 & 0xf; | ||
1103 | ep->cdte_ctrl = cd->toc[track].q0 >> 4; | ||
1104 | ep->cdte_datamode = 0; | ||
1105 | } | ||
1106 | |||
1107 | /* Audio ioctl. Ioctl commands connected to audio are in such an | ||
1108 | * idiosyncratic i/o format, that we leave these untouched. Return 0 | ||
1109 | * upon success. Memory checking has been done by cdrom_ioctl(), the | ||
1110 | * calling function, as well as LBA/MSF sanitization. | ||
1111 | */ | ||
1112 | static int cm206_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, | ||
1113 | void *arg) | ||
1114 | { | ||
1115 | switch (cmd) { | ||
1116 | case CDROMREADTOCHDR: | ||
1117 | return read_toc_header((struct cdrom_tochdr *) arg); | ||
1118 | case CDROMREADTOCENTRY: | ||
1119 | get_toc_entry((struct cdrom_tocentry *) arg); | ||
1120 | return 0; | ||
1121 | case CDROMPLAYMSF: | ||
1122 | play_from_to_msf((struct cdrom_msf *) arg); | ||
1123 | return 0; | ||
1124 | case CDROMPLAYTRKIND: /* admittedly, not particularly beautiful */ | ||
1125 | play_from_to_track(((struct cdrom_ti *) arg)->cdti_trk0, | ||
1126 | ((struct cdrom_ti *) arg)->cdti_trk1); | ||
1127 | return 0; | ||
1128 | case CDROMSTOP: | ||
1129 | PAUSED = 0; | ||
1130 | if (cd->dsb & dsb_play_in_progress) | ||
1131 | return type_0_command(c_stop, 1); | ||
1132 | else | ||
1133 | return 0; | ||
1134 | case CDROMPAUSE: | ||
1135 | get_drive_status(); | ||
1136 | if (cd->dsb & dsb_play_in_progress) { | ||
1137 | type_0_command(c_stop, 1); | ||
1138 | type_1_command(c_audio_status, 5, | ||
1139 | cd->audio_status); | ||
1140 | PAUSED = 1; /* say we're paused */ | ||
1141 | } | ||
1142 | return 0; | ||
1143 | case CDROMRESUME: | ||
1144 | if (PAUSED) | ||
1145 | play_from_to_track(0, 0); | ||
1146 | PAUSED = 0; | ||
1147 | return 0; | ||
1148 | case CDROMSTART: | ||
1149 | case CDROMVOLCTRL: | ||
1150 | return 0; | ||
1151 | case CDROMSUBCHNL: | ||
1152 | return get_current_q((struct cdrom_subchnl *) arg); | ||
1153 | default: | ||
1154 | return -EINVAL; | ||
1155 | } | ||
1156 | } | ||
1157 | |||
1158 | static int cm206_media_changed(struct cdrom_device_info *cdi, int disc_nr) | ||
1159 | { | ||
1160 | if (cd != NULL) { | ||
1161 | int r; | ||
1162 | get_drive_status(); /* ensure cd->media_changed OK */ | ||
1163 | r = cd->media_changed; | ||
1164 | cd->media_changed = 0; /* clear bit */ | ||
1165 | return r; | ||
1166 | } else | ||
1167 | return -EIO; | ||
1168 | } | ||
1169 | |||
1170 | /* The new generic cdrom support. Routines should be concise, most of | ||
1171 | the logic should be in cdrom.c */ | ||
1172 | |||
1173 | |||
1174 | /* controls tray movement */ | ||
1175 | static int cm206_tray_move(struct cdrom_device_info *cdi, int position) | ||
1176 | { | ||
1177 | if (position) { /* 1: eject */ | ||
1178 | type_0_command(c_open_tray, 1); | ||
1179 | invalidate_toc(); | ||
1180 | } else | ||
1181 | type_0_command(c_close_tray, 1); /* 0: close */ | ||
1182 | return 0; | ||
1183 | } | ||
1184 | |||
1185 | /* gives current state of the drive */ | ||
1186 | static int cm206_drive_status(struct cdrom_device_info *cdi, int slot_nr) | ||
1187 | { | ||
1188 | get_drive_status(); | ||
1189 | if (cd->dsb & dsb_tray_not_closed) | ||
1190 | return CDS_TRAY_OPEN; | ||
1191 | if (!(cd->dsb & dsb_disc_present)) | ||
1192 | return CDS_NO_DISC; | ||
1193 | if (cd->dsb & dsb_drive_not_ready) | ||
1194 | return CDS_DRIVE_NOT_READY; | ||
1195 | return CDS_DISC_OK; | ||
1196 | } | ||
1197 | |||
1198 | /* locks or unlocks door lock==1: lock; return 0 upon success */ | ||
1199 | static int cm206_lock_door(struct cdrom_device_info *cdi, int lock) | ||
1200 | { | ||
1201 | uch command = (lock) ? c_lock_tray : c_unlock_tray; | ||
1202 | type_0_command(command, 1); /* wait and get dsb */ | ||
1203 | /* the logic calculates the success, 0 means successful */ | ||
1204 | return lock ^ ((cd->dsb & dsb_tray_locked) != 0); | ||
1205 | } | ||
1206 | |||
1207 | /* Although a session start should be in LBA format, we return it in | ||
1208 | MSF format because it is slightly easier, and the new generic ioctl | ||
1209 | will take care of the necessary conversion. */ | ||
1210 | static int cm206_get_last_session(struct cdrom_device_info *cdi, | ||
1211 | struct cdrom_multisession *mssp) | ||
1212 | { | ||
1213 | if (!FIRST_TRACK) | ||
1214 | get_disc_status(); | ||
1215 | if (mssp != NULL) { | ||
1216 | if (DISC_STATUS & cds_multi_session) { /* multi-session */ | ||
1217 | mssp->addr.msf.frame = cd->disc_status[3]; | ||
1218 | mssp->addr.msf.second = cd->disc_status[4]; | ||
1219 | mssp->addr.msf.minute = cd->disc_status[5]; | ||
1220 | mssp->addr_format = CDROM_MSF; | ||
1221 | mssp->xa_flag = 1; | ||
1222 | } else { | ||
1223 | mssp->xa_flag = 0; | ||
1224 | } | ||
1225 | return 1; | ||
1226 | } | ||
1227 | return 0; | ||
1228 | } | ||
1229 | |||
1230 | static int cm206_get_upc(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn) | ||
1231 | { | ||
1232 | uch upc[10]; | ||
1233 | char *ret = mcn->medium_catalog_number; | ||
1234 | int i; | ||
1235 | |||
1236 | if (type_1_command(c_read_upc, 10, upc)) | ||
1237 | return -EIO; | ||
1238 | for (i = 0; i < 13; i++) { | ||
1239 | int w = i / 2 + 1, r = i % 2; | ||
1240 | if (r) | ||
1241 | ret[i] = 0x30 | (upc[w] & 0x0f); | ||
1242 | else | ||
1243 | ret[i] = 0x30 | ((upc[w] >> 4) & 0x0f); | ||
1244 | } | ||
1245 | ret[13] = '\0'; | ||
1246 | return 0; | ||
1247 | } | ||
1248 | |||
1249 | static int cm206_reset(struct cdrom_device_info *cdi) | ||
1250 | { | ||
1251 | stop_read(); | ||
1252 | reset_cm260(); | ||
1253 | outw(dc_normal | dc_break | READ_AHEAD, r_data_control); | ||
1254 | mdelay(1); /* 750 musec minimum */ | ||
1255 | outw(dc_normal | READ_AHEAD, r_data_control); | ||
1256 | cd->sector_last = -1; /* flag no data buffered */ | ||
1257 | cd->adapter_last = -1; | ||
1258 | invalidate_toc(); | ||
1259 | return 0; | ||
1260 | } | ||
1261 | |||
1262 | static int cm206_select_speed(struct cdrom_device_info *cdi, int speed) | ||
1263 | { | ||
1264 | int r; | ||
1265 | switch (speed) { | ||
1266 | case 0: | ||
1267 | r = type_0_command(c_auto_mode, 1); | ||
1268 | break; | ||
1269 | case 1: | ||
1270 | r = type_0_command(c_force_1x, 1); | ||
1271 | break; | ||
1272 | case 2: | ||
1273 | r = type_0_command(c_force_2x, 1); | ||
1274 | break; | ||
1275 | default: | ||
1276 | return -1; | ||
1277 | } | ||
1278 | if (r < 0) | ||
1279 | return r; | ||
1280 | else | ||
1281 | return 1; | ||
1282 | } | ||
1283 | |||
1284 | static struct cdrom_device_ops cm206_dops = { | ||
1285 | .open = cm206_open, | ||
1286 | .release = cm206_release, | ||
1287 | .drive_status = cm206_drive_status, | ||
1288 | .media_changed = cm206_media_changed, | ||
1289 | .tray_move = cm206_tray_move, | ||
1290 | .lock_door = cm206_lock_door, | ||
1291 | .select_speed = cm206_select_speed, | ||
1292 | .get_last_session = cm206_get_last_session, | ||
1293 | .get_mcn = cm206_get_upc, | ||
1294 | .reset = cm206_reset, | ||
1295 | .audio_ioctl = cm206_audio_ioctl, | ||
1296 | .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | | ||
1297 | CDC_MULTI_SESSION | CDC_MEDIA_CHANGED | | ||
1298 | CDC_MCN | CDC_PLAY_AUDIO | CDC_SELECT_SPEED | | ||
1299 | CDC_DRIVE_STATUS, | ||
1300 | .n_minors = 1, | ||
1301 | }; | ||
1302 | |||
1303 | |||
1304 | static struct cdrom_device_info cm206_info = { | ||
1305 | .ops = &cm206_dops, | ||
1306 | .speed = 2, | ||
1307 | .capacity = 1, | ||
1308 | .name = "cm206", | ||
1309 | }; | ||
1310 | |||
1311 | static int cm206_block_open(struct inode *inode, struct file *file) | ||
1312 | { | ||
1313 | return cdrom_open(&cm206_info, inode, file); | ||
1314 | } | ||
1315 | |||
1316 | static int cm206_block_release(struct inode *inode, struct file *file) | ||
1317 | { | ||
1318 | return cdrom_release(&cm206_info, file); | ||
1319 | } | ||
1320 | |||
1321 | static int cm206_block_ioctl(struct inode *inode, struct file *file, | ||
1322 | unsigned cmd, unsigned long arg) | ||
1323 | { | ||
1324 | switch (cmd) { | ||
1325 | #ifdef STATISTICS | ||
1326 | case CM206CTL_GET_STAT: | ||
1327 | if (arg >= NR_STATS) | ||
1328 | return -EINVAL; | ||
1329 | return cd->stats[arg]; | ||
1330 | case CM206CTL_GET_LAST_STAT: | ||
1331 | if (arg >= NR_STATS) | ||
1332 | return -EINVAL; | ||
1333 | return cd->last_stat[arg]; | ||
1334 | #endif | ||
1335 | default: | ||
1336 | break; | ||
1337 | } | ||
1338 | |||
1339 | return cdrom_ioctl(file, &cm206_info, inode, cmd, arg); | ||
1340 | } | ||
1341 | |||
1342 | static int cm206_block_media_changed(struct gendisk *disk) | ||
1343 | { | ||
1344 | return cdrom_media_changed(&cm206_info); | ||
1345 | } | ||
1346 | |||
1347 | static struct block_device_operations cm206_bdops = | ||
1348 | { | ||
1349 | .owner = THIS_MODULE, | ||
1350 | .open = cm206_block_open, | ||
1351 | .release = cm206_block_release, | ||
1352 | .ioctl = cm206_block_ioctl, | ||
1353 | .media_changed = cm206_block_media_changed, | ||
1354 | }; | ||
1355 | |||
1356 | static struct gendisk *cm206_gendisk; | ||
1357 | |||
1358 | /* This function probes for the adapter card. It returns the base | ||
1359 | address if it has found the adapter card. One can specify a base | ||
1360 | port to probe specifically, or 0 which means span all possible | ||
1361 | bases. | ||
1362 | |||
1363 | Linus says it is too dangerous to use writes for probing, so we | ||
1364 | stick with pure reads for a while. Hope that 8 possible ranges, | ||
1365 | request_region, 15 bits of one port and 6 of another make things | ||
1366 | likely enough to accept the region on the first hit... | ||
1367 | */ | ||
1368 | static int __init probe_base_port(int base) | ||
1369 | { | ||
1370 | int b = 0x300, e = 0x370; /* this is the range of start addresses */ | ||
1371 | volatile int fool, i; | ||
1372 | |||
1373 | if (base) | ||
1374 | b = e = base; | ||
1375 | for (base = b; base <= e; base += 0x10) { | ||
1376 | if (!request_region(base, 0x10,"cm206")) | ||
1377 | continue; | ||
1378 | for (i = 0; i < 3; i++) | ||
1379 | fool = inw(base + 2); /* empty possibly uart_receive_buffer */ | ||
1380 | if ((inw(base + 6) & 0xffef) != 0x0001 || /* line_status */ | ||
1381 | (inw(base) & 0xad00) != 0) { /* data status */ | ||
1382 | release_region(base,0x10); | ||
1383 | continue; | ||
1384 | } | ||
1385 | return (base); | ||
1386 | } | ||
1387 | return 0; | ||
1388 | } | ||
1389 | |||
1390 | #if !defined(MODULE) || defined(AUTO_PROBE_MODULE) | ||
1391 | /* Probe for irq# nr. If nr==0, probe for all possible irq's. */ | ||
1392 | static int __init probe_irq(int nr) | ||
1393 | { | ||
1394 | int irqs, irq; | ||
1395 | outw(dc_normal | READ_AHEAD, r_data_control); /* disable irq-generation */ | ||
1396 | sti(); | ||
1397 | irqs = probe_irq_on(); | ||
1398 | reset_cm260(); /* causes interrupt */ | ||
1399 | udelay(100); /* wait for it */ | ||
1400 | irq = probe_irq_off(irqs); | ||
1401 | outw(dc_normal | READ_AHEAD, r_data_control); /* services interrupt */ | ||
1402 | if (nr && irq != nr && irq > 0) | ||
1403 | return 0; /* wrong interrupt happened */ | ||
1404 | else | ||
1405 | return irq; | ||
1406 | } | ||
1407 | #endif | ||
1408 | |||
1409 | int __init cm206_init(void) | ||
1410 | { | ||
1411 | uch e = 0; | ||
1412 | long int size = sizeof(struct cm206_struct); | ||
1413 | struct gendisk *disk; | ||
1414 | |||
1415 | printk(KERN_INFO "cm206 cdrom driver " REVISION); | ||
1416 | cm206_base = probe_base_port(auto_probe ? 0 : cm206_base); | ||
1417 | if (!cm206_base) { | ||
1418 | printk(" can't find adapter!\n"); | ||
1419 | return -EIO; | ||
1420 | } | ||
1421 | printk(" adapter at 0x%x", cm206_base); | ||
1422 | cd = kmalloc(size, GFP_KERNEL); | ||
1423 | if (!cd) | ||
1424 | goto out_base; | ||
1425 | /* Now we have found the adaptor card, try to reset it. As we have | ||
1426 | * found out earlier, this process generates an interrupt as well, | ||
1427 | * so we might just exploit that fact for irq probing! */ | ||
1428 | #if !defined(MODULE) || defined(AUTO_PROBE_MODULE) | ||
1429 | cm206_irq = probe_irq(auto_probe ? 0 : cm206_irq); | ||
1430 | if (cm206_irq <= 0) { | ||
1431 | printk("can't find IRQ!\n"); | ||
1432 | goto out_probe; | ||
1433 | } else | ||
1434 | printk(" IRQ %d found\n", cm206_irq); | ||
1435 | #else | ||
1436 | cli(); | ||
1437 | reset_cm260(); | ||
1438 | /* Now, the problem here is that reset_cm260 can generate an | ||
1439 | interrupt. It seems that this can cause a kernel oops some time | ||
1440 | later. So we wait a while and `service' this interrupt. */ | ||
1441 | mdelay(1); | ||
1442 | outw(dc_normal | READ_AHEAD, r_data_control); | ||
1443 | sti(); | ||
1444 | printk(" using IRQ %d\n", cm206_irq); | ||
1445 | #endif | ||
1446 | if (send_receive_polled(c_drive_configuration) != | ||
1447 | c_drive_configuration) { | ||
1448 | printk(KERN_INFO " drive not there\n"); | ||
1449 | goto out_probe; | ||
1450 | } | ||
1451 | e = send_receive_polled(c_gimme); | ||
1452 | printk(KERN_INFO "Firmware revision %d", e & dcf_revision_code); | ||
1453 | if (e & dcf_transfer_rate) | ||
1454 | printk(" double"); | ||
1455 | else | ||
1456 | printk(" single"); | ||
1457 | printk(" speed drive"); | ||
1458 | if (e & dcf_motorized_tray) | ||
1459 | printk(", motorized tray"); | ||
1460 | if (request_irq(cm206_irq, cm206_interrupt, 0, "cm206", NULL)) { | ||
1461 | printk("\nUnable to reserve IRQ---aborted\n"); | ||
1462 | goto out_probe; | ||
1463 | } | ||
1464 | printk(".\n"); | ||
1465 | |||
1466 | if (register_blkdev(MAJOR_NR, "cm206")) | ||
1467 | goto out_blkdev; | ||
1468 | |||
1469 | disk = alloc_disk(1); | ||
1470 | if (!disk) | ||
1471 | goto out_disk; | ||
1472 | disk->major = MAJOR_NR; | ||
1473 | disk->first_minor = 0; | ||
1474 | sprintf(disk->disk_name, "cm206cd"); | ||
1475 | disk->fops = &cm206_bdops; | ||
1476 | disk->flags = GENHD_FL_CD; | ||
1477 | cm206_gendisk = disk; | ||
1478 | if (register_cdrom(&cm206_info) != 0) { | ||
1479 | printk(KERN_INFO "Cannot register for cdrom %d!\n", MAJOR_NR); | ||
1480 | goto out_cdrom; | ||
1481 | } | ||
1482 | cm206_queue = blk_init_queue(do_cm206_request, &cm206_lock); | ||
1483 | if (!cm206_queue) | ||
1484 | goto out_queue; | ||
1485 | |||
1486 | blk_queue_hardsect_size(cm206_queue, 2048); | ||
1487 | disk->queue = cm206_queue; | ||
1488 | add_disk(disk); | ||
1489 | |||
1490 | memset(cd, 0, sizeof(*cd)); /* give'm some reasonable value */ | ||
1491 | cd->sector_last = -1; /* flag no data buffered */ | ||
1492 | cd->adapter_last = -1; | ||
1493 | init_timer(&cd->timer); | ||
1494 | cd->timer.function = cm206_timeout; | ||
1495 | cd->max_sectors = (inw(r_data_status) & ds_ram_size) ? 24 : 97; | ||
1496 | printk(KERN_INFO "%d kB adapter memory available, " | ||
1497 | " %ld bytes kernel memory used.\n", cd->max_sectors * 2, | ||
1498 | size); | ||
1499 | return 0; | ||
1500 | |||
1501 | out_queue: | ||
1502 | unregister_cdrom(&cm206_info); | ||
1503 | out_cdrom: | ||
1504 | put_disk(disk); | ||
1505 | out_disk: | ||
1506 | unregister_blkdev(MAJOR_NR, "cm206"); | ||
1507 | out_blkdev: | ||
1508 | free_irq(cm206_irq, NULL); | ||
1509 | out_probe: | ||
1510 | kfree(cd); | ||
1511 | out_base: | ||
1512 | release_region(cm206_base, 16); | ||
1513 | return -EIO; | ||
1514 | } | ||
1515 | |||
1516 | #ifdef MODULE | ||
1517 | |||
1518 | |||
1519 | static void __init parse_options(void) | ||
1520 | { | ||
1521 | int i; | ||
1522 | for (i = 0; i < 2; i++) { | ||
1523 | if (0x300 <= cm206[i] && i <= 0x370 | ||
1524 | && cm206[i] % 0x10 == 0) { | ||
1525 | cm206_base = cm206[i]; | ||
1526 | auto_probe = 0; | ||
1527 | } else if (3 <= cm206[i] && cm206[i] <= 15) { | ||
1528 | cm206_irq = cm206[i]; | ||
1529 | auto_probe = 0; | ||
1530 | } | ||
1531 | } | ||
1532 | } | ||
1533 | |||
1534 | static int __init __cm206_init(void) | ||
1535 | { | ||
1536 | parse_options(); | ||
1537 | #if !defined(AUTO_PROBE_MODULE) | ||
1538 | auto_probe = 0; | ||
1539 | #endif | ||
1540 | return cm206_init(); | ||
1541 | } | ||
1542 | |||
1543 | static void __exit cm206_exit(void) | ||
1544 | { | ||
1545 | del_gendisk(cm206_gendisk); | ||
1546 | put_disk(cm206_gendisk); | ||
1547 | if (unregister_cdrom(&cm206_info)) { | ||
1548 | printk("Can't unregister cdrom cm206\n"); | ||
1549 | return; | ||
1550 | } | ||
1551 | if (unregister_blkdev(MAJOR_NR, "cm206")) { | ||
1552 | printk("Can't unregister major cm206\n"); | ||
1553 | return; | ||
1554 | } | ||
1555 | blk_cleanup_queue(cm206_queue); | ||
1556 | free_irq(cm206_irq, NULL); | ||
1557 | kfree(cd); | ||
1558 | release_region(cm206_base, 16); | ||
1559 | printk(KERN_INFO "cm206 removed\n"); | ||
1560 | } | ||
1561 | |||
1562 | module_init(__cm206_init); | ||
1563 | module_exit(cm206_exit); | ||
1564 | |||
1565 | #else /* !MODULE */ | ||
1566 | |||
1567 | /* This setup function accepts either `auto' or numbers in the range | ||
1568 | * 3--11 (for irq) or 0x300--0x370 (for base port) or both. */ | ||
1569 | |||
1570 | static int __init cm206_setup(char *s) | ||
1571 | { | ||
1572 | int i, p[4]; | ||
1573 | |||
1574 | (void) get_options(s, ARRAY_SIZE(p), p); | ||
1575 | |||
1576 | if (!strcmp(s, "auto")) | ||
1577 | auto_probe = 1; | ||
1578 | for (i = 1; i <= p[0]; i++) { | ||
1579 | if (0x300 <= p[i] && i <= 0x370 && p[i] % 0x10 == 0) { | ||
1580 | cm206_base = p[i]; | ||
1581 | auto_probe = 0; | ||
1582 | } else if (3 <= p[i] && p[i] <= 15) { | ||
1583 | cm206_irq = p[i]; | ||
1584 | auto_probe = 0; | ||
1585 | } | ||
1586 | } | ||
1587 | return 1; | ||
1588 | } | ||
1589 | |||
1590 | __setup("cm206=", cm206_setup); | ||
1591 | |||
1592 | #endif /* !MODULE */ | ||
1593 | MODULE_ALIAS_BLOCKDEV_MAJOR(CM206_CDROM_MAJOR); | ||
1594 | |||
diff --git a/drivers/cdrom/cm206.h b/drivers/cdrom/cm206.h deleted file mode 100644 index 0ae51c1a0dac..000000000000 --- a/drivers/cdrom/cm206.h +++ /dev/null | |||
@@ -1,171 +0,0 @@ | |||
1 | /* cm206.h Header file for cm206.c. | ||
2 | Copyright (c) 1995 David van Leeuwen | ||
3 | */ | ||
4 | |||
5 | #ifndef LINUX_CM206_H | ||
6 | #define LINUX_CM206_H | ||
7 | |||
8 | #include <linux/ioctl.h> | ||
9 | |||
10 | /* First, the cm260 stuff */ | ||
11 | /* The ports and irq used. Although CM206_BASE and CM206_IRQ are defined | ||
12 | below, the values are not used unless autoprobing is turned off and | ||
13 | no LILO boot options or module command line options are given. Change | ||
14 | these values to your own as last resort if autoprobing and options | ||
15 | don't work. */ | ||
16 | |||
17 | #define CM206_BASE 0x340 | ||
18 | #define CM206_IRQ 11 | ||
19 | |||
20 | #define r_data_status (cm206_base) | ||
21 | #define r_uart_receive (cm206_base+0x2) | ||
22 | #define r_fifo_output_buffer (cm206_base+0x4) | ||
23 | #define r_line_status (cm206_base+0x6) | ||
24 | #define r_data_control (cm206_base+0x8) | ||
25 | #define r_uart_transmit (cm206_base+0xa) | ||
26 | #define r_test_clock (cm206_base+0xc) | ||
27 | #define r_test_control (cm206_base+0xe) | ||
28 | |||
29 | /* the data_status flags */ | ||
30 | #define ds_ram_size 0x4000 | ||
31 | #define ds_toc_ready 0x2000 | ||
32 | #define ds_fifo_empty 0x1000 | ||
33 | #define ds_sync_error 0x800 | ||
34 | #define ds_crc_error 0x400 | ||
35 | #define ds_data_error 0x200 | ||
36 | #define ds_fifo_overflow 0x100 | ||
37 | #define ds_data_ready 0x80 | ||
38 | |||
39 | /* the line_status flags */ | ||
40 | #define ls_attention 0x10 | ||
41 | #define ls_parity_error 0x8 | ||
42 | #define ls_overrun 0x4 | ||
43 | #define ls_receive_buffer_full 0x2 | ||
44 | #define ls_transmitter_buffer_empty 0x1 | ||
45 | |||
46 | /* the data control register flags */ | ||
47 | #define dc_read_q_channel 0x4000 | ||
48 | #define dc_mask_sync_error 0x2000 | ||
49 | #define dc_toc_enable 0x1000 | ||
50 | #define dc_no_stop_on_error 0x800 | ||
51 | #define dc_break 0x400 | ||
52 | #define dc_initialize 0x200 | ||
53 | #define dc_mask_transmit_ready 0x100 | ||
54 | #define dc_flag_enable 0x80 | ||
55 | |||
56 | /* Define the default data control register flags here */ | ||
57 | #define dc_normal (dc_mask_sync_error | dc_no_stop_on_error | \ | ||
58 | dc_mask_transmit_ready) | ||
59 | |||
60 | /* now some constants related to the cm206 */ | ||
61 | /* another drive status byte, echoed by the cm206 on most commands */ | ||
62 | |||
63 | #define dsb_error_condition 0x1 | ||
64 | #define dsb_play_in_progress 0x4 | ||
65 | #define dsb_possible_media_change 0x8 | ||
66 | #define dsb_disc_present 0x10 | ||
67 | #define dsb_drive_not_ready 0x20 | ||
68 | #define dsb_tray_locked 0x40 | ||
69 | #define dsb_tray_not_closed 0x80 | ||
70 | |||
71 | #define dsb_not_useful (dsb_drive_not_ready | dsb_tray_not_closed) | ||
72 | |||
73 | /* the cm206 command set */ | ||
74 | |||
75 | #define c_close_tray 0 | ||
76 | #define c_lock_tray 0x01 | ||
77 | #define c_unlock_tray 0x04 | ||
78 | #define c_open_tray 0x05 | ||
79 | #define c_seek 0x10 | ||
80 | #define c_read_data 0x20 | ||
81 | #define c_force_1x 0x21 | ||
82 | #define c_force_2x 0x22 | ||
83 | #define c_auto_mode 0x23 | ||
84 | #define c_play 0x30 | ||
85 | #define c_set_audio_mode 0x31 | ||
86 | #define c_read_current_q 0x41 | ||
87 | #define c_stream_q 0x42 | ||
88 | #define c_drive_status 0x50 | ||
89 | #define c_disc_status 0x51 | ||
90 | #define c_audio_status 0x52 | ||
91 | #define c_drive_configuration 0x53 | ||
92 | #define c_read_upc 0x60 | ||
93 | #define c_stop 0x70 | ||
94 | #define c_calc_checksum 0xe5 | ||
95 | |||
96 | #define c_gimme 0xf8 | ||
97 | |||
98 | /* finally, the (error) condition that the drive can be in * | ||
99 | * OK, this is not always an error, but let's prefix it with e_ */ | ||
100 | |||
101 | #define e_none 0 | ||
102 | #define e_illegal_command 0x01 | ||
103 | #define e_sync 0x02 | ||
104 | #define e_seek 0x03 | ||
105 | #define e_parity 0x04 | ||
106 | #define e_focus 0x05 | ||
107 | #define e_header_sync 0x06 | ||
108 | #define e_code_incompatibility 0x07 | ||
109 | #define e_reset_done 0x08 | ||
110 | #define e_bad_parameter 0x09 | ||
111 | #define e_radial 0x0a | ||
112 | #define e_sub_code 0x0b | ||
113 | #define e_no_data_track 0x0c | ||
114 | #define e_scan 0x0d | ||
115 | #define e_tray_open 0x0f | ||
116 | #define e_no_disc 0x10 | ||
117 | #define e_tray stalled 0x11 | ||
118 | |||
119 | /* drive configuration masks */ | ||
120 | |||
121 | #define dcf_revision_code 0x7 | ||
122 | #define dcf_transfer_rate 0x60 | ||
123 | #define dcf_motorized_tray 0x80 | ||
124 | |||
125 | /* disc status byte */ | ||
126 | |||
127 | #define cds_multi_session 0x2 | ||
128 | #define cds_all_audio 0x8 | ||
129 | #define cds_xa_mode 0xf0 | ||
130 | |||
131 | /* finally some ioctls for the driver */ | ||
132 | |||
133 | #define CM206CTL_GET_STAT _IO( 0x20, 0 ) | ||
134 | #define CM206CTL_GET_LAST_STAT _IO( 0x20, 1 ) | ||
135 | |||
136 | #ifdef STATISTICS | ||
137 | |||
138 | /* This is an ugly way to guarantee that the names of the statistics | ||
139 | * are the same in the code and in the diagnostics program. */ | ||
140 | |||
141 | #ifdef __KERNEL__ | ||
142 | #define x(a) st_ ## a | ||
143 | #define y enum | ||
144 | #else | ||
145 | #define x(a) #a | ||
146 | #define y char * stats_name[] = | ||
147 | #endif | ||
148 | |||
149 | y {x(interrupt), x(data_ready), x(fifo_overflow), x(data_error), | ||
150 | x(crc_error), x(sync_error), x(lost_intr), x(echo), | ||
151 | x(write_timeout), x(receive_timeout), x(read_timeout), | ||
152 | x(dsb_timeout), x(stop_0xff), x(back_read_timeout), | ||
153 | x(sector_transferred), x(read_restarted), x(read_background), | ||
154 | x(bh), x(open), x(ioctl_multisession), x(attention) | ||
155 | #ifdef __KERNEL__ | ||
156 | , x(last_entry) | ||
157 | #endif | ||
158 | }; | ||
159 | |||
160 | #ifdef __KERNEL__ | ||
161 | #define NR_STATS st_last_entry | ||
162 | #else | ||
163 | #define NR_STATS (sizeof(stats_name)/sizeof(char*)) | ||
164 | #endif | ||
165 | |||
166 | #undef y | ||
167 | #undef x | ||
168 | |||
169 | #endif /* STATISTICS */ | ||
170 | |||
171 | #endif /* LINUX_CM206_H */ | ||
diff --git a/drivers/cdrom/gscd.c b/drivers/cdrom/gscd.c deleted file mode 100644 index 176742ed007b..000000000000 --- a/drivers/cdrom/gscd.c +++ /dev/null | |||
@@ -1,1029 +0,0 @@ | |||
1 | #define GSCD_VERSION "0.4a Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de>" | ||
2 | |||
3 | /* | ||
4 | linux/drivers/block/gscd.c - GoldStar R420 CDROM driver | ||
5 | |||
6 | Copyright (C) 1995 Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de> | ||
7 | based upon pre-works by Eberhard Moenkeberg <emoenke@gwdg.de> | ||
8 | |||
9 | |||
10 | For all kind of other information about the GoldStar CDROM | ||
11 | and this Linux device driver I installed a WWW-URL: | ||
12 | http://linux.rz.fh-hannover.de/~raupach | ||
13 | |||
14 | |||
15 | If you are the editor of a Linux CD, you should | ||
16 | enable gscd.c within your boot floppy kernel and | ||
17 | send me one of your CDs for free. | ||
18 | |||
19 | |||
20 | -------------------------------------------------------------------- | ||
21 | This program is free software; you can redistribute it and/or modify | ||
22 | it under the terms of the GNU General Public License as published by | ||
23 | the Free Software Foundation; either version 2, or (at your option) | ||
24 | any later version. | ||
25 | |||
26 | This program is distributed in the hope that it will be useful, | ||
27 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
28 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
29 | GNU General Public License for more details. | ||
30 | |||
31 | You should have received a copy of the GNU General Public License | ||
32 | along with this program; if not, write to the Free Software | ||
33 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
34 | |||
35 | -------------------------------------------------------------------- | ||
36 | |||
37 | 9 November 1999 -- Make kernel-parameter implementation work with 2.3.x | ||
38 | Removed init_module & cleanup_module in favor of | ||
39 | module_init & module_exit. | ||
40 | Torben Mathiasen <tmm@image.dk> | ||
41 | |||
42 | */ | ||
43 | |||
44 | /* These settings are for various debug-level. Leave they untouched ... */ | ||
45 | #define NO_GSCD_DEBUG | ||
46 | #define NO_IOCTL_DEBUG | ||
47 | #define NO_MODULE_DEBUG | ||
48 | #define NO_FUTURE_WORK | ||
49 | /*------------------------*/ | ||
50 | |||
51 | #include <linux/module.h> | ||
52 | |||
53 | #include <linux/slab.h> | ||
54 | #include <linux/errno.h> | ||
55 | #include <linux/signal.h> | ||
56 | #include <linux/timer.h> | ||
57 | #include <linux/fs.h> | ||
58 | #include <linux/mm.h> | ||
59 | #include <linux/kernel.h> | ||
60 | #include <linux/cdrom.h> | ||
61 | #include <linux/ioport.h> | ||
62 | #include <linux/major.h> | ||
63 | #include <linux/string.h> | ||
64 | #include <linux/init.h> | ||
65 | |||
66 | #include <asm/system.h> | ||
67 | #include <asm/io.h> | ||
68 | #include <asm/uaccess.h> | ||
69 | |||
70 | #define MAJOR_NR GOLDSTAR_CDROM_MAJOR | ||
71 | #include <linux/blkdev.h> | ||
72 | #include "gscd.h" | ||
73 | |||
74 | static int gscdPresent = 0; | ||
75 | |||
76 | static unsigned char gscd_buf[2048]; /* buffer for block size conversion */ | ||
77 | static int gscd_bn = -1; | ||
78 | static short gscd_port = GSCD_BASE_ADDR; | ||
79 | module_param_named(gscd, gscd_port, short, 0); | ||
80 | |||
81 | /* Kommt spaeter vielleicht noch mal dran ... | ||
82 | * static DECLARE_WAIT_QUEUE_HEAD(gscd_waitq); | ||
83 | */ | ||
84 | |||
85 | static void gscd_read_cmd(struct request *req); | ||
86 | static void gscd_hsg2msf(long hsg, struct msf *msf); | ||
87 | static void gscd_bin2bcd(unsigned char *p); | ||
88 | |||
89 | /* Schnittstellen zum Kern/FS */ | ||
90 | |||
91 | static void __do_gscd_request(unsigned long dummy); | ||
92 | static int gscd_ioctl(struct inode *, struct file *, unsigned int, | ||
93 | unsigned long); | ||
94 | static int gscd_open(struct inode *, struct file *); | ||
95 | static int gscd_release(struct inode *, struct file *); | ||
96 | static int check_gscd_med_chg(struct gendisk *disk); | ||
97 | |||
98 | /* GoldStar Funktionen */ | ||
99 | |||
100 | static void cmd_out(int, char *, char *, int); | ||
101 | static void cmd_status(void); | ||
102 | static void init_cd_drive(int); | ||
103 | |||
104 | static int get_status(void); | ||
105 | static void clear_Audio(void); | ||
106 | static void cc_invalidate(void); | ||
107 | |||
108 | /* some things for the next version */ | ||
109 | #ifdef FUTURE_WORK | ||
110 | static void update_state(void); | ||
111 | static long gscd_msf2hsg(struct msf *mp); | ||
112 | static int gscd_bcd2bin(unsigned char bcd); | ||
113 | #endif | ||
114 | |||
115 | |||
116 | /* lo-level cmd-Funktionen */ | ||
117 | |||
118 | static void cmd_info_in(char *, int); | ||
119 | static void cmd_end(void); | ||
120 | static void cmd_read_b(char *, int, int); | ||
121 | static void cmd_read_w(char *, int, int); | ||
122 | static int cmd_unit_alive(void); | ||
123 | static void cmd_write_cmd(char *); | ||
124 | |||
125 | |||
126 | /* GoldStar Variablen */ | ||
127 | |||
128 | static int curr_drv_state; | ||
129 | static int drv_states[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
130 | static int drv_mode; | ||
131 | static int disk_state; | ||
132 | static int speed; | ||
133 | static int ndrives; | ||
134 | |||
135 | static unsigned char drv_num_read; | ||
136 | static unsigned char f_dsk_valid; | ||
137 | static unsigned char current_drive; | ||
138 | static unsigned char f_drv_ok; | ||
139 | |||
140 | |||
141 | static char f_AudioPlay; | ||
142 | static char f_AudioPause; | ||
143 | static int AudioStart_m; | ||
144 | static int AudioStart_f; | ||
145 | static int AudioEnd_m; | ||
146 | static int AudioEnd_f; | ||
147 | |||
148 | static DEFINE_TIMER(gscd_timer, NULL, 0, 0); | ||
149 | static DEFINE_SPINLOCK(gscd_lock); | ||
150 | static struct request_queue *gscd_queue; | ||
151 | |||
152 | static struct block_device_operations gscd_fops = { | ||
153 | .owner = THIS_MODULE, | ||
154 | .open = gscd_open, | ||
155 | .release = gscd_release, | ||
156 | .ioctl = gscd_ioctl, | ||
157 | .media_changed = check_gscd_med_chg, | ||
158 | }; | ||
159 | |||
160 | /* | ||
161 | * Checking if the media has been changed | ||
162 | * (not yet implemented) | ||
163 | */ | ||
164 | static int check_gscd_med_chg(struct gendisk *disk) | ||
165 | { | ||
166 | #ifdef GSCD_DEBUG | ||
167 | printk("gscd: check_med_change\n"); | ||
168 | #endif | ||
169 | return 0; | ||
170 | } | ||
171 | |||
172 | |||
173 | #ifndef MODULE | ||
174 | /* Using new interface for kernel-parameters */ | ||
175 | |||
176 | static int __init gscd_setup(char *str) | ||
177 | { | ||
178 | int ints[2]; | ||
179 | (void) get_options(str, ARRAY_SIZE(ints), ints); | ||
180 | |||
181 | if (ints[0] > 0) { | ||
182 | gscd_port = ints[1]; | ||
183 | } | ||
184 | return 1; | ||
185 | } | ||
186 | |||
187 | __setup("gscd=", gscd_setup); | ||
188 | |||
189 | #endif | ||
190 | |||
191 | static int gscd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, | ||
192 | unsigned long arg) | ||
193 | { | ||
194 | unsigned char to_do[10]; | ||
195 | unsigned char dummy; | ||
196 | |||
197 | |||
198 | switch (cmd) { | ||
199 | case CDROMSTART: /* Spin up the drive */ | ||
200 | /* Don't think we can do this. Even if we could, | ||
201 | * I think the drive times out and stops after a while | ||
202 | * anyway. For now, ignore it. | ||
203 | */ | ||
204 | return 0; | ||
205 | |||
206 | case CDROMRESUME: /* keine Ahnung was das ist */ | ||
207 | return 0; | ||
208 | |||
209 | |||
210 | case CDROMEJECT: | ||
211 | cmd_status(); | ||
212 | to_do[0] = CMD_TRAY_CTL; | ||
213 | cmd_out(TYPE_INFO, (char *) &to_do, (char *) &dummy, 0); | ||
214 | |||
215 | return 0; | ||
216 | |||
217 | default: | ||
218 | return -EINVAL; | ||
219 | } | ||
220 | |||
221 | } | ||
222 | |||
223 | |||
224 | /* | ||
225 | * Take care of the different block sizes between cdrom and Linux. | ||
226 | * When Linux gets variable block sizes this will probably go away. | ||
227 | */ | ||
228 | |||
229 | static void gscd_transfer(struct request *req) | ||
230 | { | ||
231 | while (req->nr_sectors > 0 && gscd_bn == req->sector / 4) { | ||
232 | long offs = (req->sector & 3) * 512; | ||
233 | memcpy(req->buffer, gscd_buf + offs, 512); | ||
234 | req->nr_sectors--; | ||
235 | req->sector++; | ||
236 | req->buffer += 512; | ||
237 | } | ||
238 | } | ||
239 | |||
240 | |||
241 | /* | ||
242 | * I/O request routine called from Linux kernel. | ||
243 | */ | ||
244 | |||
245 | static void do_gscd_request(request_queue_t * q) | ||
246 | { | ||
247 | __do_gscd_request(0); | ||
248 | } | ||
249 | |||
250 | static void __do_gscd_request(unsigned long dummy) | ||
251 | { | ||
252 | struct request *req; | ||
253 | unsigned int block; | ||
254 | unsigned int nsect; | ||
255 | |||
256 | repeat: | ||
257 | req = elv_next_request(gscd_queue); | ||
258 | if (!req) | ||
259 | return; | ||
260 | |||
261 | block = req->sector; | ||
262 | nsect = req->nr_sectors; | ||
263 | |||
264 | if (req->sector == -1) | ||
265 | goto out; | ||
266 | |||
267 | if (rq_data_dir(req) != READ) { | ||
268 | printk("GSCD: bad cmd %u\n", rq_data_dir(req)); | ||
269 | end_request(req, 0); | ||
270 | goto repeat; | ||
271 | } | ||
272 | |||
273 | gscd_transfer(req); | ||
274 | |||
275 | /* if we satisfied the request from the buffer, we're done. */ | ||
276 | |||
277 | if (req->nr_sectors == 0) { | ||
278 | end_request(req, 1); | ||
279 | goto repeat; | ||
280 | } | ||
281 | #ifdef GSCD_DEBUG | ||
282 | printk("GSCD: block %d, nsect %d\n", block, nsect); | ||
283 | #endif | ||
284 | gscd_read_cmd(req); | ||
285 | out: | ||
286 | return; | ||
287 | } | ||
288 | |||
289 | |||
290 | |||
291 | /* | ||
292 | * Check the result of the set-mode command. On success, send the | ||
293 | * read-data command. | ||
294 | */ | ||
295 | |||
296 | static void gscd_read_cmd(struct request *req) | ||
297 | { | ||
298 | long block; | ||
299 | struct gscd_Play_msf gscdcmd; | ||
300 | char cmd[] = { CMD_READ, 0x80, 0, 0, 0, 0, 1 }; /* cmd mode M-S-F secth sectl */ | ||
301 | |||
302 | cmd_status(); | ||
303 | if (disk_state & (ST_NO_DISK | ST_DOOR_OPEN)) { | ||
304 | printk("GSCD: no disk or door open\n"); | ||
305 | end_request(req, 0); | ||
306 | } else { | ||
307 | if (disk_state & ST_INVALID) { | ||
308 | printk("GSCD: disk invalid\n"); | ||
309 | end_request(req, 0); | ||
310 | } else { | ||
311 | gscd_bn = -1; /* purge our buffer */ | ||
312 | block = req->sector / 4; | ||
313 | gscd_hsg2msf(block, &gscdcmd.start); /* cvt to msf format */ | ||
314 | |||
315 | cmd[2] = gscdcmd.start.min; | ||
316 | cmd[3] = gscdcmd.start.sec; | ||
317 | cmd[4] = gscdcmd.start.frame; | ||
318 | |||
319 | #ifdef GSCD_DEBUG | ||
320 | printk("GSCD: read msf %d:%d:%d\n", cmd[2], cmd[3], | ||
321 | cmd[4]); | ||
322 | #endif | ||
323 | cmd_out(TYPE_DATA, (char *) &cmd, | ||
324 | (char *) &gscd_buf[0], 1); | ||
325 | |||
326 | gscd_bn = req->sector / 4; | ||
327 | gscd_transfer(req); | ||
328 | end_request(req, 1); | ||
329 | } | ||
330 | } | ||
331 | SET_TIMER(__do_gscd_request, 1); | ||
332 | } | ||
333 | |||
334 | |||
335 | /* | ||
336 | * Open the device special file. Check that a disk is in. | ||
337 | */ | ||
338 | |||
339 | static int gscd_open(struct inode *ip, struct file *fp) | ||
340 | { | ||
341 | int st; | ||
342 | |||
343 | #ifdef GSCD_DEBUG | ||
344 | printk("GSCD: open\n"); | ||
345 | #endif | ||
346 | |||
347 | if (gscdPresent == 0) | ||
348 | return -ENXIO; /* no hardware */ | ||
349 | |||
350 | get_status(); | ||
351 | st = disk_state & (ST_NO_DISK | ST_DOOR_OPEN); | ||
352 | if (st) { | ||
353 | printk("GSCD: no disk or door open\n"); | ||
354 | return -ENXIO; | ||
355 | } | ||
356 | |||
357 | /* if (updateToc() < 0) | ||
358 | return -EIO; | ||
359 | */ | ||
360 | |||
361 | return 0; | ||
362 | } | ||
363 | |||
364 | |||
365 | /* | ||
366 | * On close, we flush all gscd blocks from the buffer cache. | ||
367 | */ | ||
368 | |||
369 | static int gscd_release(struct inode *inode, struct file *file) | ||
370 | { | ||
371 | |||
372 | #ifdef GSCD_DEBUG | ||
373 | printk("GSCD: release\n"); | ||
374 | #endif | ||
375 | |||
376 | gscd_bn = -1; | ||
377 | |||
378 | return 0; | ||
379 | } | ||
380 | |||
381 | |||
382 | static int get_status(void) | ||
383 | { | ||
384 | int status; | ||
385 | |||
386 | cmd_status(); | ||
387 | status = disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01); | ||
388 | |||
389 | if (status == (ST_x08 | ST_x04 | ST_INVALID | ST_x01)) { | ||
390 | cc_invalidate(); | ||
391 | return 1; | ||
392 | } else { | ||
393 | return 0; | ||
394 | } | ||
395 | } | ||
396 | |||
397 | |||
398 | static void cc_invalidate(void) | ||
399 | { | ||
400 | drv_num_read = 0xFF; | ||
401 | f_dsk_valid = 0xFF; | ||
402 | current_drive = 0xFF; | ||
403 | f_drv_ok = 0xFF; | ||
404 | |||
405 | clear_Audio(); | ||
406 | |||
407 | } | ||
408 | |||
409 | static void clear_Audio(void) | ||
410 | { | ||
411 | |||
412 | f_AudioPlay = 0; | ||
413 | f_AudioPause = 0; | ||
414 | AudioStart_m = 0; | ||
415 | AudioStart_f = 0; | ||
416 | AudioEnd_m = 0; | ||
417 | AudioEnd_f = 0; | ||
418 | |||
419 | } | ||
420 | |||
421 | /* | ||
422 | * waiting ? | ||
423 | */ | ||
424 | |||
425 | static int wait_drv_ready(void) | ||
426 | { | ||
427 | int found, read; | ||
428 | |||
429 | do { | ||
430 | found = inb(GSCDPORT(0)); | ||
431 | found &= 0x0f; | ||
432 | read = inb(GSCDPORT(0)); | ||
433 | read &= 0x0f; | ||
434 | } while (read != found); | ||
435 | |||
436 | #ifdef GSCD_DEBUG | ||
437 | printk("Wait for: %d\n", read); | ||
438 | #endif | ||
439 | |||
440 | return read; | ||
441 | } | ||
442 | |||
443 | static void cc_Ident(char *respons) | ||
444 | { | ||
445 | char to_do[] = { CMD_IDENT, 0, 0 }; | ||
446 | |||
447 | cmd_out(TYPE_INFO, (char *) &to_do, (char *) respons, (int) 0x1E); | ||
448 | |||
449 | } | ||
450 | |||
451 | static void cc_SetSpeed(void) | ||
452 | { | ||
453 | char to_do[] = { CMD_SETSPEED, 0, 0 }; | ||
454 | char dummy; | ||
455 | |||
456 | if (speed > 0) { | ||
457 | to_do[1] = speed & 0x0F; | ||
458 | cmd_out(TYPE_INFO, (char *) &to_do, (char *) &dummy, 0); | ||
459 | } | ||
460 | } | ||
461 | |||
462 | static void cc_Reset(void) | ||
463 | { | ||
464 | char to_do[] = { CMD_RESET, 0 }; | ||
465 | char dummy; | ||
466 | |||
467 | cmd_out(TYPE_INFO, (char *) &to_do, (char *) &dummy, 0); | ||
468 | } | ||
469 | |||
470 | static void cmd_status(void) | ||
471 | { | ||
472 | char to_do[] = { CMD_STATUS, 0 }; | ||
473 | char dummy; | ||
474 | |||
475 | cmd_out(TYPE_INFO, (char *) &to_do, (char *) &dummy, 0); | ||
476 | |||
477 | #ifdef GSCD_DEBUG | ||
478 | printk("GSCD: Status: %d\n", disk_state); | ||
479 | #endif | ||
480 | |||
481 | } | ||
482 | |||
483 | static void cmd_out(int cmd_type, char *cmd, char *respo_buf, int respo_count) | ||
484 | { | ||
485 | int result; | ||
486 | |||
487 | |||
488 | result = wait_drv_ready(); | ||
489 | if (result != drv_mode) { | ||
490 | unsigned long test_loops = 0xFFFF; | ||
491 | int i, dummy; | ||
492 | |||
493 | outb(curr_drv_state, GSCDPORT(0)); | ||
494 | |||
495 | /* LOCLOOP_170 */ | ||
496 | do { | ||
497 | result = wait_drv_ready(); | ||
498 | test_loops--; | ||
499 | } while ((result != drv_mode) && (test_loops > 0)); | ||
500 | |||
501 | if (result != drv_mode) { | ||
502 | disk_state = ST_x08 | ST_x04 | ST_INVALID; | ||
503 | return; | ||
504 | } | ||
505 | |||
506 | /* ...and waiting */ | ||
507 | for (i = 1, dummy = 1; i < 0xFFFF; i++) { | ||
508 | dummy *= i; | ||
509 | } | ||
510 | } | ||
511 | |||
512 | /* LOC_172 */ | ||
513 | /* check the unit */ | ||
514 | /* and wake it up */ | ||
515 | if (cmd_unit_alive() != 0x08) { | ||
516 | /* LOC_174 */ | ||
517 | /* game over for this unit */ | ||
518 | disk_state = ST_x08 | ST_x04 | ST_INVALID; | ||
519 | return; | ||
520 | } | ||
521 | |||
522 | /* LOC_176 */ | ||
523 | #ifdef GSCD_DEBUG | ||
524 | printk("LOC_176 "); | ||
525 | #endif | ||
526 | if (drv_mode == 0x09) { | ||
527 | /* magic... */ | ||
528 | printk("GSCD: magic ...\n"); | ||
529 | outb(result, GSCDPORT(2)); | ||
530 | } | ||
531 | |||
532 | /* write the command to the drive */ | ||
533 | cmd_write_cmd(cmd); | ||
534 | |||
535 | /* LOC_178 */ | ||
536 | for (;;) { | ||
537 | result = wait_drv_ready(); | ||
538 | if (result != drv_mode) { | ||
539 | /* LOC_179 */ | ||
540 | if (result == 0x04) { /* Mode 4 */ | ||
541 | /* LOC_205 */ | ||
542 | #ifdef GSCD_DEBUG | ||
543 | printk("LOC_205 "); | ||
544 | #endif | ||
545 | disk_state = inb(GSCDPORT(2)); | ||
546 | |||
547 | do { | ||
548 | result = wait_drv_ready(); | ||
549 | } while (result != drv_mode); | ||
550 | return; | ||
551 | |||
552 | } else { | ||
553 | if (result == 0x06) { /* Mode 6 */ | ||
554 | /* LOC_181 */ | ||
555 | #ifdef GSCD_DEBUG | ||
556 | printk("LOC_181 "); | ||
557 | #endif | ||
558 | |||
559 | if (cmd_type == TYPE_DATA) { | ||
560 | /* read data */ | ||
561 | /* LOC_184 */ | ||
562 | if (drv_mode == 9) { | ||
563 | /* read the data to the buffer (word) */ | ||
564 | |||
565 | /* (*(cmd+1))?(CD_FRAMESIZE/2):(CD_FRAMESIZE_RAW/2) */ | ||
566 | cmd_read_w | ||
567 | (respo_buf, | ||
568 | respo_count, | ||
569 | CD_FRAMESIZE / | ||
570 | 2); | ||
571 | return; | ||
572 | } else { | ||
573 | /* read the data to the buffer (byte) */ | ||
574 | |||
575 | /* (*(cmd+1))?(CD_FRAMESIZE):(CD_FRAMESIZE_RAW) */ | ||
576 | cmd_read_b | ||
577 | (respo_buf, | ||
578 | respo_count, | ||
579 | CD_FRAMESIZE); | ||
580 | return; | ||
581 | } | ||
582 | } else { | ||
583 | /* read the info to the buffer */ | ||
584 | cmd_info_in(respo_buf, | ||
585 | respo_count); | ||
586 | return; | ||
587 | } | ||
588 | |||
589 | return; | ||
590 | } | ||
591 | } | ||
592 | |||
593 | } else { | ||
594 | disk_state = ST_x08 | ST_x04 | ST_INVALID; | ||
595 | return; | ||
596 | } | ||
597 | } /* for (;;) */ | ||
598 | |||
599 | |||
600 | #ifdef GSCD_DEBUG | ||
601 | printk("\n"); | ||
602 | #endif | ||
603 | } | ||
604 | |||
605 | |||
606 | static void cmd_write_cmd(char *pstr) | ||
607 | { | ||
608 | int i, j; | ||
609 | |||
610 | /* LOC_177 */ | ||
611 | #ifdef GSCD_DEBUG | ||
612 | printk("LOC_177 "); | ||
613 | #endif | ||
614 | |||
615 | /* calculate the number of parameter */ | ||
616 | j = *pstr & 0x0F; | ||
617 | |||
618 | /* shift it out */ | ||
619 | for (i = 0; i < j; i++) { | ||
620 | outb(*pstr, GSCDPORT(2)); | ||
621 | pstr++; | ||
622 | } | ||
623 | } | ||
624 | |||
625 | |||
626 | static int cmd_unit_alive(void) | ||
627 | { | ||
628 | int result; | ||
629 | unsigned long max_test_loops; | ||
630 | |||
631 | |||
632 | /* LOC_172 */ | ||
633 | #ifdef GSCD_DEBUG | ||
634 | printk("LOC_172 "); | ||
635 | #endif | ||
636 | |||
637 | outb(curr_drv_state, GSCDPORT(0)); | ||
638 | max_test_loops = 0xFFFF; | ||
639 | |||
640 | do { | ||
641 | result = wait_drv_ready(); | ||
642 | max_test_loops--; | ||
643 | } while ((result != 0x08) && (max_test_loops > 0)); | ||
644 | |||
645 | return result; | ||
646 | } | ||
647 | |||
648 | |||
649 | static void cmd_info_in(char *pb, int count) | ||
650 | { | ||
651 | int result; | ||
652 | char read; | ||
653 | |||
654 | |||
655 | /* read info */ | ||
656 | /* LOC_182 */ | ||
657 | #ifdef GSCD_DEBUG | ||
658 | printk("LOC_182 "); | ||
659 | #endif | ||
660 | |||
661 | do { | ||
662 | read = inb(GSCDPORT(2)); | ||
663 | if (count > 0) { | ||
664 | *pb = read; | ||
665 | pb++; | ||
666 | count--; | ||
667 | } | ||
668 | |||
669 | /* LOC_183 */ | ||
670 | do { | ||
671 | result = wait_drv_ready(); | ||
672 | } while (result == 0x0E); | ||
673 | } while (result == 6); | ||
674 | |||
675 | cmd_end(); | ||
676 | return; | ||
677 | } | ||
678 | |||
679 | |||
680 | static void cmd_read_b(char *pb, int count, int size) | ||
681 | { | ||
682 | int result; | ||
683 | int i; | ||
684 | |||
685 | |||
686 | /* LOC_188 */ | ||
687 | /* LOC_189 */ | ||
688 | #ifdef GSCD_DEBUG | ||
689 | printk("LOC_189 "); | ||
690 | #endif | ||
691 | |||
692 | do { | ||
693 | do { | ||
694 | result = wait_drv_ready(); | ||
695 | } while (result != 6 || result == 0x0E); | ||
696 | |||
697 | if (result != 6) { | ||
698 | cmd_end(); | ||
699 | return; | ||
700 | } | ||
701 | #ifdef GSCD_DEBUG | ||
702 | printk("LOC_191 "); | ||
703 | #endif | ||
704 | |||
705 | for (i = 0; i < size; i++) { | ||
706 | *pb = inb(GSCDPORT(2)); | ||
707 | pb++; | ||
708 | } | ||
709 | count--; | ||
710 | } while (count > 0); | ||
711 | |||
712 | cmd_end(); | ||
713 | return; | ||
714 | } | ||
715 | |||
716 | |||
717 | static void cmd_end(void) | ||
718 | { | ||
719 | int result; | ||
720 | |||
721 | |||
722 | /* LOC_204 */ | ||
723 | #ifdef GSCD_DEBUG | ||
724 | printk("LOC_204 "); | ||
725 | #endif | ||
726 | |||
727 | do { | ||
728 | result = wait_drv_ready(); | ||
729 | if (result == drv_mode) { | ||
730 | return; | ||
731 | } | ||
732 | } while (result != 4); | ||
733 | |||
734 | /* LOC_205 */ | ||
735 | #ifdef GSCD_DEBUG | ||
736 | printk("LOC_205 "); | ||
737 | #endif | ||
738 | |||
739 | disk_state = inb(GSCDPORT(2)); | ||
740 | |||
741 | do { | ||
742 | result = wait_drv_ready(); | ||
743 | } while (result != drv_mode); | ||
744 | return; | ||
745 | |||
746 | } | ||
747 | |||
748 | |||
749 | static void cmd_read_w(char *pb, int count, int size) | ||
750 | { | ||
751 | int result; | ||
752 | int i; | ||
753 | |||
754 | |||
755 | #ifdef GSCD_DEBUG | ||
756 | printk("LOC_185 "); | ||
757 | #endif | ||
758 | |||
759 | do { | ||
760 | /* LOC_185 */ | ||
761 | do { | ||
762 | result = wait_drv_ready(); | ||
763 | } while (result != 6 || result == 0x0E); | ||
764 | |||
765 | if (result != 6) { | ||
766 | cmd_end(); | ||
767 | return; | ||
768 | } | ||
769 | |||
770 | for (i = 0; i < size; i++) { | ||
771 | /* na, hier muss ich noch mal drueber nachdenken */ | ||
772 | *pb = inw(GSCDPORT(2)); | ||
773 | pb++; | ||
774 | } | ||
775 | count--; | ||
776 | } while (count > 0); | ||
777 | |||
778 | cmd_end(); | ||
779 | return; | ||
780 | } | ||
781 | |||
782 | static int __init find_drives(void) | ||
783 | { | ||
784 | int *pdrv; | ||
785 | int drvnum; | ||
786 | int subdrv; | ||
787 | int i; | ||
788 | |||
789 | speed = 0; | ||
790 | pdrv = (int *) &drv_states; | ||
791 | curr_drv_state = 0xFE; | ||
792 | subdrv = 0; | ||
793 | drvnum = 0; | ||
794 | |||
795 | for (i = 0; i < 8; i++) { | ||
796 | subdrv++; | ||
797 | cmd_status(); | ||
798 | disk_state &= ST_x08 | ST_x04 | ST_INVALID | ST_x01; | ||
799 | if (disk_state != (ST_x08 | ST_x04 | ST_INVALID)) { | ||
800 | /* LOC_240 */ | ||
801 | *pdrv = curr_drv_state; | ||
802 | init_cd_drive(drvnum); | ||
803 | pdrv++; | ||
804 | drvnum++; | ||
805 | } else { | ||
806 | if (subdrv < 2) { | ||
807 | continue; | ||
808 | } else { | ||
809 | subdrv = 0; | ||
810 | } | ||
811 | } | ||
812 | |||
813 | /* curr_drv_state<<1; <-- das geht irgendwie nicht */ | ||
814 | /* muss heissen: curr_drv_state <<= 1; (ist ja Wert-Zuweisung) */ | ||
815 | curr_drv_state *= 2; | ||
816 | curr_drv_state |= 1; | ||
817 | #ifdef GSCD_DEBUG | ||
818 | printk("DriveState: %d\n", curr_drv_state); | ||
819 | #endif | ||
820 | } | ||
821 | |||
822 | ndrives = drvnum; | ||
823 | return drvnum; | ||
824 | } | ||
825 | |||
826 | static void __init init_cd_drive(int num) | ||
827 | { | ||
828 | char resp[50]; | ||
829 | int i; | ||
830 | |||
831 | printk("GSCD: init unit %d\n", num); | ||
832 | cc_Ident((char *) &resp); | ||
833 | |||
834 | printk("GSCD: identification: "); | ||
835 | for (i = 0; i < 0x1E; i++) { | ||
836 | printk("%c", resp[i]); | ||
837 | } | ||
838 | printk("\n"); | ||
839 | |||
840 | cc_SetSpeed(); | ||
841 | |||
842 | } | ||
843 | |||
844 | #ifdef FUTURE_WORK | ||
845 | /* return_done */ | ||
846 | static void update_state(void) | ||
847 | { | ||
848 | unsigned int AX; | ||
849 | |||
850 | |||
851 | if ((disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01)) == 0) { | ||
852 | if (disk_state == (ST_x08 | ST_x04 | ST_INVALID)) { | ||
853 | AX = ST_INVALID; | ||
854 | } | ||
855 | |||
856 | if ((disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01)) | ||
857 | == 0) { | ||
858 | invalidate(); | ||
859 | f_drv_ok = 0; | ||
860 | } | ||
861 | |||
862 | AX |= 0x8000; | ||
863 | } | ||
864 | |||
865 | if (disk_state & ST_PLAYING) { | ||
866 | AX |= 0x200; | ||
867 | } | ||
868 | |||
869 | AX |= 0x100; | ||
870 | /* pkt_esbx = AX; */ | ||
871 | |||
872 | disk_state = 0; | ||
873 | |||
874 | } | ||
875 | #endif | ||
876 | |||
877 | static struct gendisk *gscd_disk; | ||
878 | |||
879 | static void __exit gscd_exit(void) | ||
880 | { | ||
881 | CLEAR_TIMER; | ||
882 | |||
883 | del_gendisk(gscd_disk); | ||
884 | put_disk(gscd_disk); | ||
885 | if ((unregister_blkdev(MAJOR_NR, "gscd") == -EINVAL)) { | ||
886 | printk("What's that: can't unregister GoldStar-module\n"); | ||
887 | return; | ||
888 | } | ||
889 | blk_cleanup_queue(gscd_queue); | ||
890 | release_region(gscd_port, GSCD_IO_EXTENT); | ||
891 | printk(KERN_INFO "GoldStar-module released.\n"); | ||
892 | } | ||
893 | |||
894 | /* This is the common initialisation for the GoldStar drive. */ | ||
895 | /* It is called at boot time AND for module init. */ | ||
896 | static int __init gscd_init(void) | ||
897 | { | ||
898 | int i; | ||
899 | int result; | ||
900 | int ret=0; | ||
901 | |||
902 | printk(KERN_INFO "GSCD: version %s\n", GSCD_VERSION); | ||
903 | printk(KERN_INFO | ||
904 | "GSCD: Trying to detect a Goldstar R420 CD-ROM drive at 0x%X.\n", | ||
905 | gscd_port); | ||
906 | |||
907 | if (!request_region(gscd_port, GSCD_IO_EXTENT, "gscd")) { | ||
908 | printk(KERN_WARNING "GSCD: Init failed, I/O port (%X) already" | ||
909 | " in use.\n", gscd_port); | ||
910 | return -EIO; | ||
911 | } | ||
912 | |||
913 | |||
914 | /* check for card */ | ||
915 | result = wait_drv_ready(); | ||
916 | if (result == 0x09) { | ||
917 | printk(KERN_WARNING "GSCD: DMA kann ich noch nicht!\n"); | ||
918 | ret = -EIO; | ||
919 | goto err_out1; | ||
920 | } | ||
921 | |||
922 | if (result == 0x0b) { | ||
923 | drv_mode = result; | ||
924 | i = find_drives(); | ||
925 | if (i == 0) { | ||
926 | printk(KERN_WARNING "GSCD: GoldStar CD-ROM Drive is" | ||
927 | " not found.\n"); | ||
928 | ret = -EIO; | ||
929 | goto err_out1; | ||
930 | } | ||
931 | } | ||
932 | |||
933 | if ((result != 0x0b) && (result != 0x09)) { | ||
934 | printk(KERN_WARNING "GSCD: GoldStar Interface Adapter does not " | ||
935 | "exist or H/W error\n"); | ||
936 | ret = -EIO; | ||
937 | goto err_out1; | ||
938 | } | ||
939 | |||
940 | /* reset all drives */ | ||
941 | i = 0; | ||
942 | while (drv_states[i] != 0) { | ||
943 | curr_drv_state = drv_states[i]; | ||
944 | printk(KERN_INFO "GSCD: Reset unit %d ... ", i); | ||
945 | cc_Reset(); | ||
946 | printk("done\n"); | ||
947 | i++; | ||
948 | } | ||
949 | |||
950 | gscd_disk = alloc_disk(1); | ||
951 | if (!gscd_disk) | ||
952 | goto err_out1; | ||
953 | gscd_disk->major = MAJOR_NR; | ||
954 | gscd_disk->first_minor = 0; | ||
955 | gscd_disk->fops = &gscd_fops; | ||
956 | sprintf(gscd_disk->disk_name, "gscd"); | ||
957 | |||
958 | if (register_blkdev(MAJOR_NR, "gscd")) { | ||
959 | ret = -EIO; | ||
960 | goto err_out2; | ||
961 | } | ||
962 | |||
963 | gscd_queue = blk_init_queue(do_gscd_request, &gscd_lock); | ||
964 | if (!gscd_queue) { | ||
965 | ret = -ENOMEM; | ||
966 | goto err_out3; | ||
967 | } | ||
968 | |||
969 | disk_state = 0; | ||
970 | gscdPresent = 1; | ||
971 | |||
972 | gscd_disk->queue = gscd_queue; | ||
973 | add_disk(gscd_disk); | ||
974 | |||
975 | printk(KERN_INFO "GSCD: GoldStar CD-ROM Drive found.\n"); | ||
976 | return 0; | ||
977 | |||
978 | err_out3: | ||
979 | unregister_blkdev(MAJOR_NR, "gscd"); | ||
980 | err_out2: | ||
981 | put_disk(gscd_disk); | ||
982 | err_out1: | ||
983 | release_region(gscd_port, GSCD_IO_EXTENT); | ||
984 | return ret; | ||
985 | } | ||
986 | |||
987 | static void gscd_hsg2msf(long hsg, struct msf *msf) | ||
988 | { | ||
989 | hsg += CD_MSF_OFFSET; | ||
990 | msf->min = hsg / (CD_FRAMES * CD_SECS); | ||
991 | hsg %= CD_FRAMES * CD_SECS; | ||
992 | msf->sec = hsg / CD_FRAMES; | ||
993 | msf->frame = hsg % CD_FRAMES; | ||
994 | |||
995 | gscd_bin2bcd(&msf->min); /* convert to BCD */ | ||
996 | gscd_bin2bcd(&msf->sec); | ||
997 | gscd_bin2bcd(&msf->frame); | ||
998 | } | ||
999 | |||
1000 | |||
1001 | static void gscd_bin2bcd(unsigned char *p) | ||
1002 | { | ||
1003 | int u, t; | ||
1004 | |||
1005 | u = *p % 10; | ||
1006 | t = *p / 10; | ||
1007 | *p = u | (t << 4); | ||
1008 | } | ||
1009 | |||
1010 | |||
1011 | #ifdef FUTURE_WORK | ||
1012 | static long gscd_msf2hsg(struct msf *mp) | ||
1013 | { | ||
1014 | return gscd_bcd2bin(mp->frame) | ||
1015 | + gscd_bcd2bin(mp->sec) * CD_FRAMES | ||
1016 | + gscd_bcd2bin(mp->min) * CD_FRAMES * CD_SECS - CD_MSF_OFFSET; | ||
1017 | } | ||
1018 | |||
1019 | static int gscd_bcd2bin(unsigned char bcd) | ||
1020 | { | ||
1021 | return (bcd >> 4) * 10 + (bcd & 0xF); | ||
1022 | } | ||
1023 | #endif | ||
1024 | |||
1025 | MODULE_AUTHOR("Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de>"); | ||
1026 | MODULE_LICENSE("GPL"); | ||
1027 | module_init(gscd_init); | ||
1028 | module_exit(gscd_exit); | ||
1029 | MODULE_ALIAS_BLOCKDEV_MAJOR(GOLDSTAR_CDROM_MAJOR); | ||
diff --git a/drivers/cdrom/gscd.h b/drivers/cdrom/gscd.h deleted file mode 100644 index a41e64bfc061..000000000000 --- a/drivers/cdrom/gscd.h +++ /dev/null | |||
@@ -1,108 +0,0 @@ | |||
1 | /* | ||
2 | * Definitions for a GoldStar R420 CD-ROM interface | ||
3 | * | ||
4 | * Copyright (C) 1995 Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de> | ||
5 | * Eberhard Moenkeberg <emoenke@gwdg.de> | ||
6 | * | ||
7 | * Published under the GPL. | ||
8 | * | ||
9 | */ | ||
10 | |||
11 | |||
12 | /* The Interface Card default address is 0x340. This will work for most | ||
13 | applications. Address selection is accomplished by jumpers PN801-1 to | ||
14 | PN801-4 on the GoldStar Interface Card. | ||
15 | Appropriate settings are: 0x300, 0x310, 0x320, 0x330, 0x340, 0x350, 0x360 | ||
16 | 0x370, 0x380, 0x390, 0x3A0, 0x3B0, 0x3C0, 0x3D0, 0x3E0, 0x3F0 */ | ||
17 | |||
18 | /* insert here the I/O port address and extent */ | ||
19 | #define GSCD_BASE_ADDR 0x340 | ||
20 | #define GSCD_IO_EXTENT 4 | ||
21 | |||
22 | |||
23 | /************** nothing to set up below here *********************/ | ||
24 | |||
25 | /* port access macro */ | ||
26 | #define GSCDPORT(x) (gscd_port + (x)) | ||
27 | |||
28 | /* | ||
29 | * commands | ||
30 | * the lower nibble holds the command length | ||
31 | */ | ||
32 | #define CMD_STATUS 0x01 | ||
33 | #define CMD_READSUBQ 0x02 /* 1: ?, 2: UPC, 5: ? */ | ||
34 | #define CMD_SEEK 0x05 /* read_mode M-S-F */ | ||
35 | #define CMD_READ 0x07 /* read_mode M-S-F nsec_h nsec_l */ | ||
36 | #define CMD_RESET 0x11 | ||
37 | #define CMD_SETMODE 0x15 | ||
38 | #define CMD_PLAY 0x17 /* M-S-F M-S-F */ | ||
39 | #define CMD_LOCK_CTL 0x22 /* 0: unlock, 1: lock */ | ||
40 | #define CMD_IDENT 0x31 | ||
41 | #define CMD_SETSPEED 0x32 /* 0: auto */ /* ??? */ | ||
42 | #define CMD_GETMODE 0x41 | ||
43 | #define CMD_PAUSE 0x51 | ||
44 | #define CMD_READTOC 0x61 | ||
45 | #define CMD_DISKINFO 0x71 | ||
46 | #define CMD_TRAY_CTL 0x81 | ||
47 | |||
48 | /* | ||
49 | * disk_state: | ||
50 | */ | ||
51 | #define ST_PLAYING 0x80 | ||
52 | #define ST_UNLOCKED 0x40 | ||
53 | #define ST_NO_DISK 0x20 | ||
54 | #define ST_DOOR_OPEN 0x10 | ||
55 | #define ST_x08 0x08 | ||
56 | #define ST_x04 0x04 | ||
57 | #define ST_INVALID 0x02 | ||
58 | #define ST_x01 0x01 | ||
59 | |||
60 | /* | ||
61 | * cmd_type: | ||
62 | */ | ||
63 | #define TYPE_INFO 0x01 | ||
64 | #define TYPE_DATA 0x02 | ||
65 | |||
66 | /* | ||
67 | * read_mode: | ||
68 | */ | ||
69 | #define MOD_POLLED 0x80 | ||
70 | #define MOD_x08 0x08 | ||
71 | #define MOD_RAW 0x04 | ||
72 | |||
73 | #define READ_DATA(port, buf, nr) insb(port, buf, nr) | ||
74 | |||
75 | #define SET_TIMER(func, jifs) \ | ||
76 | ((mod_timer(&gscd_timer, jiffies + jifs)), \ | ||
77 | (gscd_timer.function = func)) | ||
78 | |||
79 | #define CLEAR_TIMER del_timer_sync(&gscd_timer) | ||
80 | |||
81 | #define MAX_TRACKS 104 | ||
82 | |||
83 | struct msf { | ||
84 | unsigned char min; | ||
85 | unsigned char sec; | ||
86 | unsigned char frame; | ||
87 | }; | ||
88 | |||
89 | struct gscd_Play_msf { | ||
90 | struct msf start; | ||
91 | struct msf end; | ||
92 | }; | ||
93 | |||
94 | struct gscd_DiskInfo { | ||
95 | unsigned char first; | ||
96 | unsigned char last; | ||
97 | struct msf diskLength; | ||
98 | struct msf firstTrack; | ||
99 | }; | ||
100 | |||
101 | struct gscd_Toc { | ||
102 | unsigned char ctrl_addr; | ||
103 | unsigned char track; | ||
104 | unsigned char pointIndex; | ||
105 | struct msf trackTime; | ||
106 | struct msf diskTime; | ||
107 | }; | ||
108 | |||
diff --git a/drivers/cdrom/isp16.c b/drivers/cdrom/isp16.c deleted file mode 100644 index db0fd9a240e3..000000000000 --- a/drivers/cdrom/isp16.c +++ /dev/null | |||
@@ -1,374 +0,0 @@ | |||
1 | /* -- ISP16 cdrom detection and configuration | ||
2 | * | ||
3 | * Copyright (c) 1995,1996 Eric van der Maarel <H.T.M.v.d.Maarel@marin.nl> | ||
4 | * | ||
5 | * Version 0.6 | ||
6 | * | ||
7 | * History: | ||
8 | * 0.5 First release. | ||
9 | * Was included in the sjcd and optcd cdrom drivers. | ||
10 | * 0.6 First "stand-alone" version. | ||
11 | * Removed sound configuration. | ||
12 | * Added "module" support. | ||
13 | * | ||
14 | * 9 November 1999 -- Make kernel-parameter implementation work with 2.3.x | ||
15 | * Removed init_module & cleanup_module in favor of | ||
16 | * module_init & module_exit. | ||
17 | * Torben Mathiasen <tmm@image.dk> | ||
18 | * | ||
19 | * 19 June 2004 -- check_region() converted to request_region() | ||
20 | * and return statement cleanups. | ||
21 | * - Jesper Juhl | ||
22 | * | ||
23 | * Detect cdrom interface on ISP16 sound card. | ||
24 | * Configure cdrom interface. | ||
25 | * | ||
26 | * Algorithm for the card with OPTi 82C928 taken | ||
27 | * from the CDSETUP.SYS driver for MSDOS, | ||
28 | * by OPTi Computers, version 2.03. | ||
29 | * Algorithm for the card with OPTi 82C929 as communicated | ||
30 | * to me by Vadim Model and Leo Spiekman. | ||
31 | * | ||
32 | * This program is free software; you can redistribute it and/or modify | ||
33 | * it under the terms of the GNU General Public License as published by | ||
34 | * the Free Software Foundation; either version 2 of the License, or | ||
35 | * (at your option) any later version. | ||
36 | * | ||
37 | * This program is distributed in the hope that it will be useful, | ||
38 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
39 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
40 | * GNU General Public License for more details. | ||
41 | * | ||
42 | * You should have received a copy of the GNU General Public License | ||
43 | * along with this program; if not, write to the Free Software | ||
44 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
45 | * | ||
46 | */ | ||
47 | |||
48 | #define ISP16_VERSION_MAJOR 0 | ||
49 | #define ISP16_VERSION_MINOR 6 | ||
50 | |||
51 | #include <linux/module.h> | ||
52 | |||
53 | #include <linux/fs.h> | ||
54 | #include <linux/kernel.h> | ||
55 | #include <linux/string.h> | ||
56 | #include <linux/ioport.h> | ||
57 | #include <linux/init.h> | ||
58 | #include <asm/io.h> | ||
59 | #include "isp16.h" | ||
60 | |||
61 | static short isp16_detect(void); | ||
62 | static short isp16_c928__detect(void); | ||
63 | static short isp16_c929__detect(void); | ||
64 | static short isp16_cdi_config(int base, u_char drive_type, int irq, | ||
65 | int dma); | ||
66 | static short isp16_type; /* dependent on type of interface card */ | ||
67 | static u_char isp16_ctrl; | ||
68 | static u_short isp16_enable_port; | ||
69 | |||
70 | static int isp16_cdrom_base = ISP16_CDROM_IO_BASE; | ||
71 | static int isp16_cdrom_irq = ISP16_CDROM_IRQ; | ||
72 | static int isp16_cdrom_dma = ISP16_CDROM_DMA; | ||
73 | static char *isp16_cdrom_type = ISP16_CDROM_TYPE; | ||
74 | |||
75 | module_param(isp16_cdrom_base, int, 0); | ||
76 | module_param(isp16_cdrom_irq, int, 0); | ||
77 | module_param(isp16_cdrom_dma, int, 0); | ||
78 | module_param(isp16_cdrom_type, charp, 0); | ||
79 | |||
80 | #define ISP16_IN(p) (outb(isp16_ctrl,ISP16_CTRL_PORT), inb(p)) | ||
81 | #define ISP16_OUT(p,b) (outb(isp16_ctrl,ISP16_CTRL_PORT), outb(b,p)) | ||
82 | |||
83 | #ifndef MODULE | ||
84 | |||
85 | static int | ||
86 | __init isp16_setup(char *str) | ||
87 | { | ||
88 | int ints[4]; | ||
89 | |||
90 | (void) get_options(str, ARRAY_SIZE(ints), ints); | ||
91 | if (ints[0] > 0) | ||
92 | isp16_cdrom_base = ints[1]; | ||
93 | if (ints[0] > 1) | ||
94 | isp16_cdrom_irq = ints[2]; | ||
95 | if (ints[0] > 2) | ||
96 | isp16_cdrom_dma = ints[3]; | ||
97 | if (str) | ||
98 | isp16_cdrom_type = str; | ||
99 | |||
100 | return 1; | ||
101 | } | ||
102 | |||
103 | __setup("isp16=", isp16_setup); | ||
104 | |||
105 | #endif /* MODULE */ | ||
106 | |||
107 | /* | ||
108 | * ISP16 initialisation. | ||
109 | * | ||
110 | */ | ||
111 | static int __init isp16_init(void) | ||
112 | { | ||
113 | u_char expected_drive; | ||
114 | |||
115 | printk(KERN_INFO | ||
116 | "ISP16: configuration cdrom interface, version %d.%d.\n", | ||
117 | ISP16_VERSION_MAJOR, ISP16_VERSION_MINOR); | ||
118 | |||
119 | if (!strcmp(isp16_cdrom_type, "noisp16")) { | ||
120 | printk("ISP16: no cdrom interface configured.\n"); | ||
121 | return 0; | ||
122 | } | ||
123 | |||
124 | if (!request_region(ISP16_IO_BASE, ISP16_IO_SIZE, "isp16")) { | ||
125 | printk("ISP16: i/o ports already in use.\n"); | ||
126 | goto out; | ||
127 | } | ||
128 | |||
129 | if ((isp16_type = isp16_detect()) < 0) { | ||
130 | printk("ISP16: no cdrom interface found.\n"); | ||
131 | goto cleanup_out; | ||
132 | } | ||
133 | |||
134 | printk(KERN_INFO | ||
135 | "ISP16: cdrom interface (with OPTi 82C92%d chip) detected.\n", | ||
136 | (isp16_type == 2) ? 9 : 8); | ||
137 | |||
138 | if (!strcmp(isp16_cdrom_type, "Sanyo")) | ||
139 | expected_drive = | ||
140 | (isp16_type ? ISP16_SANYO1 : ISP16_SANYO0); | ||
141 | else if (!strcmp(isp16_cdrom_type, "Sony")) | ||
142 | expected_drive = ISP16_SONY; | ||
143 | else if (!strcmp(isp16_cdrom_type, "Panasonic")) | ||
144 | expected_drive = | ||
145 | (isp16_type ? ISP16_PANASONIC1 : ISP16_PANASONIC0); | ||
146 | else if (!strcmp(isp16_cdrom_type, "Mitsumi")) | ||
147 | expected_drive = ISP16_MITSUMI; | ||
148 | else { | ||
149 | printk("ISP16: %s not supported by cdrom interface.\n", | ||
150 | isp16_cdrom_type); | ||
151 | goto cleanup_out; | ||
152 | } | ||
153 | |||
154 | if (isp16_cdi_config(isp16_cdrom_base, expected_drive, | ||
155 | isp16_cdrom_irq, isp16_cdrom_dma) < 0) { | ||
156 | printk | ||
157 | ("ISP16: cdrom interface has not been properly configured.\n"); | ||
158 | goto cleanup_out; | ||
159 | } | ||
160 | printk(KERN_INFO | ||
161 | "ISP16: cdrom interface set up with io base 0x%03X, irq %d, dma %d," | ||
162 | " type %s.\n", isp16_cdrom_base, isp16_cdrom_irq, | ||
163 | isp16_cdrom_dma, isp16_cdrom_type); | ||
164 | return 0; | ||
165 | |||
166 | cleanup_out: | ||
167 | release_region(ISP16_IO_BASE, ISP16_IO_SIZE); | ||
168 | out: | ||
169 | return -EIO; | ||
170 | } | ||
171 | |||
172 | static short __init isp16_detect(void) | ||
173 | { | ||
174 | |||
175 | if (isp16_c929__detect() >= 0) | ||
176 | return 2; | ||
177 | else | ||
178 | return (isp16_c928__detect()); | ||
179 | } | ||
180 | |||
181 | static short __init isp16_c928__detect(void) | ||
182 | { | ||
183 | u_char ctrl; | ||
184 | u_char enable_cdrom; | ||
185 | u_char io; | ||
186 | short i = -1; | ||
187 | |||
188 | isp16_ctrl = ISP16_C928__CTRL; | ||
189 | isp16_enable_port = ISP16_C928__ENABLE_PORT; | ||
190 | |||
191 | /* read' and write' are a special read and write, respectively */ | ||
192 | |||
193 | /* read' ISP16_CTRL_PORT, clear last two bits and write' back the result */ | ||
194 | ctrl = ISP16_IN(ISP16_CTRL_PORT) & 0xFC; | ||
195 | ISP16_OUT(ISP16_CTRL_PORT, ctrl); | ||
196 | |||
197 | /* read' 3,4 and 5-bit from the cdrom enable port */ | ||
198 | enable_cdrom = ISP16_IN(ISP16_C928__ENABLE_PORT) & 0x38; | ||
199 | |||
200 | if (!(enable_cdrom & 0x20)) { /* 5-bit not set */ | ||
201 | /* read' last 2 bits of ISP16_IO_SET_PORT */ | ||
202 | io = ISP16_IN(ISP16_IO_SET_PORT) & 0x03; | ||
203 | if (((io & 0x01) << 1) == (io & 0x02)) { /* bits are the same */ | ||
204 | if (io == 0) { /* ...the same and 0 */ | ||
205 | i = 0; | ||
206 | enable_cdrom |= 0x20; | ||
207 | } else { /* ...the same and 1 *//* my card, first time 'round */ | ||
208 | i = 1; | ||
209 | enable_cdrom |= 0x28; | ||
210 | } | ||
211 | ISP16_OUT(ISP16_C928__ENABLE_PORT, enable_cdrom); | ||
212 | } else { /* bits are not the same */ | ||
213 | ISP16_OUT(ISP16_CTRL_PORT, ctrl); | ||
214 | return i; /* -> not detected: possibly incorrect conclusion */ | ||
215 | } | ||
216 | } else if (enable_cdrom == 0x20) | ||
217 | i = 0; | ||
218 | else if (enable_cdrom == 0x28) /* my card, already initialised */ | ||
219 | i = 1; | ||
220 | |||
221 | ISP16_OUT(ISP16_CTRL_PORT, ctrl); | ||
222 | |||
223 | return i; | ||
224 | } | ||
225 | |||
226 | static short __init isp16_c929__detect(void) | ||
227 | { | ||
228 | u_char ctrl; | ||
229 | u_char tmp; | ||
230 | |||
231 | isp16_ctrl = ISP16_C929__CTRL; | ||
232 | isp16_enable_port = ISP16_C929__ENABLE_PORT; | ||
233 | |||
234 | /* read' and write' are a special read and write, respectively */ | ||
235 | |||
236 | /* read' ISP16_CTRL_PORT and save */ | ||
237 | ctrl = ISP16_IN(ISP16_CTRL_PORT); | ||
238 | |||
239 | /* write' zero to the ctrl port and get response */ | ||
240 | ISP16_OUT(ISP16_CTRL_PORT, 0); | ||
241 | tmp = ISP16_IN(ISP16_CTRL_PORT); | ||
242 | |||
243 | if (tmp != 2) /* isp16 with 82C929 not detected */ | ||
244 | return -1; | ||
245 | |||
246 | /* restore ctrl port value */ | ||
247 | ISP16_OUT(ISP16_CTRL_PORT, ctrl); | ||
248 | |||
249 | return 2; | ||
250 | } | ||
251 | |||
252 | static short __init | ||
253 | isp16_cdi_config(int base, u_char drive_type, int irq, int dma) | ||
254 | { | ||
255 | u_char base_code; | ||
256 | u_char irq_code; | ||
257 | u_char dma_code; | ||
258 | u_char i; | ||
259 | |||
260 | if ((drive_type == ISP16_MITSUMI) && (dma != 0)) | ||
261 | printk("ISP16: Mitsumi cdrom drive has no dma support.\n"); | ||
262 | |||
263 | switch (base) { | ||
264 | case 0x340: | ||
265 | base_code = ISP16_BASE_340; | ||
266 | break; | ||
267 | case 0x330: | ||
268 | base_code = ISP16_BASE_330; | ||
269 | break; | ||
270 | case 0x360: | ||
271 | base_code = ISP16_BASE_360; | ||
272 | break; | ||
273 | case 0x320: | ||
274 | base_code = ISP16_BASE_320; | ||
275 | break; | ||
276 | default: | ||
277 | printk | ||
278 | ("ISP16: base address 0x%03X not supported by cdrom interface.\n", | ||
279 | base); | ||
280 | return -1; | ||
281 | } | ||
282 | switch (irq) { | ||
283 | case 0: | ||
284 | irq_code = ISP16_IRQ_X; | ||
285 | break; /* disable irq */ | ||
286 | case 5: | ||
287 | irq_code = ISP16_IRQ_5; | ||
288 | printk("ISP16: irq 5 shouldn't be used by cdrom interface," | ||
289 | " due to possible conflicts with the sound card.\n"); | ||
290 | break; | ||
291 | case 7: | ||
292 | irq_code = ISP16_IRQ_7; | ||
293 | printk("ISP16: irq 7 shouldn't be used by cdrom interface," | ||
294 | " due to possible conflicts with the sound card.\n"); | ||
295 | break; | ||
296 | case 3: | ||
297 | irq_code = ISP16_IRQ_3; | ||
298 | break; | ||
299 | case 9: | ||
300 | irq_code = ISP16_IRQ_9; | ||
301 | break; | ||
302 | case 10: | ||
303 | irq_code = ISP16_IRQ_10; | ||
304 | break; | ||
305 | case 11: | ||
306 | irq_code = ISP16_IRQ_11; | ||
307 | break; | ||
308 | default: | ||
309 | printk("ISP16: irq %d not supported by cdrom interface.\n", | ||
310 | irq); | ||
311 | return -1; | ||
312 | } | ||
313 | switch (dma) { | ||
314 | case 0: | ||
315 | dma_code = ISP16_DMA_X; | ||
316 | break; /* disable dma */ | ||
317 | case 1: | ||
318 | printk("ISP16: dma 1 cannot be used by cdrom interface," | ||
319 | " due to conflict with the sound card.\n"); | ||
320 | return -1; | ||
321 | break; | ||
322 | case 3: | ||
323 | dma_code = ISP16_DMA_3; | ||
324 | break; | ||
325 | case 5: | ||
326 | dma_code = ISP16_DMA_5; | ||
327 | break; | ||
328 | case 6: | ||
329 | dma_code = ISP16_DMA_6; | ||
330 | break; | ||
331 | case 7: | ||
332 | dma_code = ISP16_DMA_7; | ||
333 | break; | ||
334 | default: | ||
335 | printk("ISP16: dma %d not supported by cdrom interface.\n", | ||
336 | dma); | ||
337 | return -1; | ||
338 | } | ||
339 | |||
340 | if (drive_type != ISP16_SONY && drive_type != ISP16_PANASONIC0 && | ||
341 | drive_type != ISP16_PANASONIC1 && drive_type != ISP16_SANYO0 && | ||
342 | drive_type != ISP16_SANYO1 && drive_type != ISP16_MITSUMI && | ||
343 | drive_type != ISP16_DRIVE_X) { | ||
344 | printk | ||
345 | ("ISP16: drive type (code 0x%02X) not supported by cdrom" | ||
346 | " interface.\n", drive_type); | ||
347 | return -1; | ||
348 | } | ||
349 | |||
350 | /* set type of interface */ | ||
351 | i = ISP16_IN(ISP16_DRIVE_SET_PORT) & ISP16_DRIVE_SET_MASK; /* clear some bits */ | ||
352 | ISP16_OUT(ISP16_DRIVE_SET_PORT, i | drive_type); | ||
353 | |||
354 | /* enable cdrom on interface with 82C929 chip */ | ||
355 | if (isp16_type > 1) | ||
356 | ISP16_OUT(isp16_enable_port, ISP16_ENABLE_CDROM); | ||
357 | |||
358 | /* set base address, irq and dma */ | ||
359 | i = ISP16_IN(ISP16_IO_SET_PORT) & ISP16_IO_SET_MASK; /* keep some bits */ | ||
360 | ISP16_OUT(ISP16_IO_SET_PORT, i | base_code | irq_code | dma_code); | ||
361 | |||
362 | return 0; | ||
363 | } | ||
364 | |||
365 | static void __exit isp16_exit(void) | ||
366 | { | ||
367 | release_region(ISP16_IO_BASE, ISP16_IO_SIZE); | ||
368 | printk(KERN_INFO "ISP16: module released.\n"); | ||
369 | } | ||
370 | |||
371 | module_init(isp16_init); | ||
372 | module_exit(isp16_exit); | ||
373 | |||
374 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/cdrom/isp16.h b/drivers/cdrom/isp16.h deleted file mode 100644 index 5bd22c8f7a96..000000000000 --- a/drivers/cdrom/isp16.h +++ /dev/null | |||
@@ -1,72 +0,0 @@ | |||
1 | /* -- isp16.h | ||
2 | * | ||
3 | * Header for detection and initialisation of cdrom interface (only) on | ||
4 | * ISP16 (MAD16, Mozart) sound card. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | /* These are the default values */ | ||
23 | #define ISP16_CDROM_TYPE "Sanyo" | ||
24 | #define ISP16_CDROM_IO_BASE 0x340 | ||
25 | #define ISP16_CDROM_IRQ 0 | ||
26 | #define ISP16_CDROM_DMA 0 | ||
27 | |||
28 | /* Some (Media)Magic */ | ||
29 | /* define types of drive the interface on an ISP16 card may be looking at */ | ||
30 | #define ISP16_DRIVE_X 0x00 | ||
31 | #define ISP16_SONY 0x02 | ||
32 | #define ISP16_PANASONIC0 0x02 | ||
33 | #define ISP16_SANYO0 0x02 | ||
34 | #define ISP16_MITSUMI 0x04 | ||
35 | #define ISP16_PANASONIC1 0x06 | ||
36 | #define ISP16_SANYO1 0x06 | ||
37 | #define ISP16_DRIVE_NOT_USED 0x08 /* not used */ | ||
38 | #define ISP16_DRIVE_SET_MASK 0xF1 /* don't change 0-bit or 4-7-bits*/ | ||
39 | /* ...for port */ | ||
40 | #define ISP16_DRIVE_SET_PORT 0xF8D | ||
41 | /* set io parameters */ | ||
42 | #define ISP16_BASE_340 0x00 | ||
43 | #define ISP16_BASE_330 0x40 | ||
44 | #define ISP16_BASE_360 0x80 | ||
45 | #define ISP16_BASE_320 0xC0 | ||
46 | #define ISP16_IRQ_X 0x00 | ||
47 | #define ISP16_IRQ_5 0x04 /* shouldn't be used to avoid sound card conflicts */ | ||
48 | #define ISP16_IRQ_7 0x08 /* shouldn't be used to avoid sound card conflicts */ | ||
49 | #define ISP16_IRQ_3 0x0C | ||
50 | #define ISP16_IRQ_9 0x10 | ||
51 | #define ISP16_IRQ_10 0x14 | ||
52 | #define ISP16_IRQ_11 0x18 | ||
53 | #define ISP16_DMA_X 0x03 | ||
54 | #define ISP16_DMA_3 0x00 | ||
55 | #define ISP16_DMA_5 0x00 | ||
56 | #define ISP16_DMA_6 0x01 | ||
57 | #define ISP16_DMA_7 0x02 | ||
58 | #define ISP16_IO_SET_MASK 0x20 /* don't change 5-bit */ | ||
59 | /* ...for port */ | ||
60 | #define ISP16_IO_SET_PORT 0xF8E | ||
61 | /* enable the card */ | ||
62 | #define ISP16_C928__ENABLE_PORT 0xF90 /* ISP16 with OPTi 82C928 chip */ | ||
63 | #define ISP16_C929__ENABLE_PORT 0xF91 /* ISP16 with OPTi 82C929 chip */ | ||
64 | #define ISP16_ENABLE_CDROM 0x80 /* seven bit */ | ||
65 | |||
66 | /* the magic stuff */ | ||
67 | #define ISP16_CTRL_PORT 0xF8F | ||
68 | #define ISP16_C928__CTRL 0xE2 /* ISP16 with OPTi 82C928 chip */ | ||
69 | #define ISP16_C929__CTRL 0xE3 /* ISP16 with OPTi 82C929 chip */ | ||
70 | |||
71 | #define ISP16_IO_BASE 0xF8D | ||
72 | #define ISP16_IO_SIZE 5 /* ports used from 0xF8D up to 0xF91 */ | ||
diff --git a/drivers/cdrom/mcdx.c b/drivers/cdrom/mcdx.c deleted file mode 100644 index 972ee9c8247c..000000000000 --- a/drivers/cdrom/mcdx.c +++ /dev/null | |||
@@ -1,1943 +0,0 @@ | |||
1 | /* | ||
2 | * The Mitsumi CDROM interface | ||
3 | * Copyright (C) 1995 1996 Heiko Schlittermann <heiko@lotte.sax.de> | ||
4 | * VERSION: 2.14(hs) | ||
5 | * | ||
6 | * ... anyway, I'm back again, thanks to Marcin, he adopted | ||
7 | * large portions of my code (at least the parts containing | ||
8 | * my main thoughts ...) | ||
9 | * | ||
10 | ****************** H E L P ********************************* | ||
11 | * If you ever plan to update your CD ROM drive and perhaps | ||
12 | * want to sell or simply give away your Mitsumi FX-001[DS] | ||
13 | * -- Please -- | ||
14 | * mail me (heiko@lotte.sax.de). When my last drive goes | ||
15 | * ballistic no more driver support will be available from me! | ||
16 | ************************************************************* | ||
17 | * | ||
18 | * This program is free software; you can redistribute it and/or modify | ||
19 | * it under the terms of the GNU General Public License as published by | ||
20 | * the Free Software Foundation; either version 2, or (at your option) | ||
21 | * any later version. | ||
22 | * | ||
23 | * This program is distributed in the hope that it will be useful, | ||
24 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
26 | * GNU General Public License for more details. | ||
27 | * | ||
28 | * You should have received a copy of the GNU General Public License | ||
29 | * along with this program; see the file COPYING. If not, write to | ||
30 | * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
31 | * | ||
32 | * Thanks to | ||
33 | * The Linux Community at all and ... | ||
34 | * Martin Harriss (he wrote the first Mitsumi Driver) | ||
35 | * Eberhard Moenkeberg (he gave me much support and the initial kick) | ||
36 | * Bernd Huebner, Ruediger Helsch (Unifix-Software GmbH, they | ||
37 | * improved the original driver) | ||
38 | * Jon Tombs, Bjorn Ekwall (module support) | ||
39 | * Daniel v. Mosnenck (he sent me the Technical and Programming Reference) | ||
40 | * Gerd Knorr (he lent me his PhotoCD) | ||
41 | * Nils Faerber and Roger E. Wolff (extensively tested the LU portion) | ||
42 | * Andreas Kies (testing the mysterious hang-ups) | ||
43 | * Heiko Eissfeldt (VERIFY_READ/WRITE) | ||
44 | * Marcin Dalecki (improved performance, shortened code) | ||
45 | * ... somebody forgotten? | ||
46 | * | ||
47 | * 9 November 1999 -- Make kernel-parameter implementation work with 2.3.x | ||
48 | * Removed init_module & cleanup_module in favor of | ||
49 | * module_init & module_exit. | ||
50 | * Torben Mathiasen <tmm@image.dk> | ||
51 | */ | ||
52 | |||
53 | |||
54 | #ifdef RCS | ||
55 | static const char *mcdx_c_version | ||
56 | = "$Id: mcdx.c,v 1.21 1997/01/26 07:12:59 davem Exp $"; | ||
57 | #endif | ||
58 | |||
59 | #include <linux/module.h> | ||
60 | |||
61 | #include <linux/errno.h> | ||
62 | #include <linux/interrupt.h> | ||
63 | #include <linux/fs.h> | ||
64 | #include <linux/kernel.h> | ||
65 | #include <linux/cdrom.h> | ||
66 | #include <linux/ioport.h> | ||
67 | #include <linux/mm.h> | ||
68 | #include <linux/slab.h> | ||
69 | #include <linux/init.h> | ||
70 | #include <asm/io.h> | ||
71 | #include <asm/current.h> | ||
72 | #include <asm/uaccess.h> | ||
73 | |||
74 | #include <linux/major.h> | ||
75 | #define MAJOR_NR MITSUMI_X_CDROM_MAJOR | ||
76 | #include <linux/blkdev.h> | ||
77 | |||
78 | #include "mcdx.h" | ||
79 | |||
80 | #ifndef HZ | ||
81 | #error HZ not defined | ||
82 | #endif | ||
83 | |||
84 | #define xwarn(fmt, args...) printk(KERN_WARNING MCDX " " fmt, ## args) | ||
85 | |||
86 | #if !MCDX_QUIET | ||
87 | #define xinfo(fmt, args...) printk(KERN_INFO MCDX " " fmt, ## args) | ||
88 | #else | ||
89 | #define xinfo(fmt, args...) { ; } | ||
90 | #endif | ||
91 | |||
92 | #if MCDX_DEBUG | ||
93 | #define xtrace(lvl, fmt, args...) \ | ||
94 | { if (lvl > 0) \ | ||
95 | { printk(KERN_DEBUG MCDX ":: " fmt, ## args); } } | ||
96 | #define xdebug(fmt, args...) printk(KERN_DEBUG MCDX ":: " fmt, ## args) | ||
97 | #else | ||
98 | #define xtrace(lvl, fmt, args...) { ; } | ||
99 | #define xdebug(fmt, args...) { ; } | ||
100 | #endif | ||
101 | |||
102 | /* CONSTANTS *******************************************************/ | ||
103 | |||
104 | /* Following are the number of sectors we _request_ from the drive | ||
105 | every time an access outside the already requested range is done. | ||
106 | The _direct_ size is the number of sectors we're allowed to skip | ||
107 | directly (performing a read instead of requesting the new sector | ||
108 | needed */ | ||
109 | static const int REQUEST_SIZE = 800; /* should be less then 255 * 4 */ | ||
110 | static const int DIRECT_SIZE = 400; /* should be less then REQUEST_SIZE */ | ||
111 | |||
112 | enum drivemodes { TOC, DATA, RAW, COOKED }; | ||
113 | enum datamodes { MODE0, MODE1, MODE2 }; | ||
114 | enum resetmodes { SOFT, HARD }; | ||
115 | |||
116 | static const int SINGLE = 0x01; /* single speed drive (FX001S, LU) */ | ||
117 | static const int DOUBLE = 0x02; /* double speed drive (FX001D, ..? */ | ||
118 | static const int DOOR = 0x04; /* door locking capability */ | ||
119 | static const int MULTI = 0x08; /* multi session capability */ | ||
120 | |||
121 | static const unsigned char READ1X = 0xc0; | ||
122 | static const unsigned char READ2X = 0xc1; | ||
123 | |||
124 | |||
125 | /* DECLARATIONS ****************************************************/ | ||
126 | struct s_subqcode { | ||
127 | unsigned char control; | ||
128 | unsigned char tno; | ||
129 | unsigned char index; | ||
130 | struct cdrom_msf0 tt; | ||
131 | struct cdrom_msf0 dt; | ||
132 | }; | ||
133 | |||
134 | struct s_diskinfo { | ||
135 | unsigned int n_first; | ||
136 | unsigned int n_last; | ||
137 | struct cdrom_msf0 msf_leadout; | ||
138 | struct cdrom_msf0 msf_first; | ||
139 | }; | ||
140 | |||
141 | struct s_multi { | ||
142 | unsigned char multi; | ||
143 | struct cdrom_msf0 msf_last; | ||
144 | }; | ||
145 | |||
146 | struct s_version { | ||
147 | unsigned char code; | ||
148 | unsigned char ver; | ||
149 | }; | ||
150 | |||
151 | /* Per drive/controller stuff **************************************/ | ||
152 | |||
153 | struct s_drive_stuff { | ||
154 | /* waitqueues */ | ||
155 | wait_queue_head_t busyq; | ||
156 | wait_queue_head_t lockq; | ||
157 | wait_queue_head_t sleepq; | ||
158 | |||
159 | /* flags */ | ||
160 | volatile int introk; /* status of last irq operation */ | ||
161 | volatile int busy; /* drive performs an operation */ | ||
162 | volatile int lock; /* exclusive usage */ | ||
163 | |||
164 | /* cd infos */ | ||
165 | struct s_diskinfo di; | ||
166 | struct s_multi multi; | ||
167 | struct s_subqcode *toc; /* first entry of the toc array */ | ||
168 | struct s_subqcode start; | ||
169 | struct s_subqcode stop; | ||
170 | int xa; /* 1 if xa disk */ | ||
171 | int audio; /* 1 if audio disk */ | ||
172 | int audiostatus; | ||
173 | |||
174 | /* `buffer' control */ | ||
175 | volatile int valid; /* pending, ..., values are valid */ | ||
176 | volatile int pending; /* next sector to be read */ | ||
177 | volatile int low_border; /* first sector not to be skipped direct */ | ||
178 | volatile int high_border; /* first sector `out of area' */ | ||
179 | #ifdef AK2 | ||
180 | volatile int int_err; | ||
181 | #endif /* AK2 */ | ||
182 | |||
183 | /* adds and odds */ | ||
184 | unsigned wreg_data; /* w data */ | ||
185 | unsigned wreg_reset; /* w hardware reset */ | ||
186 | unsigned wreg_hcon; /* w hardware conf */ | ||
187 | unsigned wreg_chn; /* w channel */ | ||
188 | unsigned rreg_data; /* r data */ | ||
189 | unsigned rreg_status; /* r status */ | ||
190 | |||
191 | int irq; /* irq used by this drive */ | ||
192 | int present; /* drive present and its capabilities */ | ||
193 | unsigned char readcmd; /* read cmd depends on single/double speed */ | ||
194 | unsigned char playcmd; /* play should always be single speed */ | ||
195 | unsigned int xxx; /* set if changed, reset while open */ | ||
196 | unsigned int yyy; /* set if changed, reset by media_changed */ | ||
197 | int users; /* keeps track of open/close */ | ||
198 | int lastsector; /* last block accessible */ | ||
199 | int status; /* last operation's error / status */ | ||
200 | int readerrs; /* # of blocks read w/o error */ | ||
201 | struct cdrom_device_info info; | ||
202 | struct gendisk *disk; | ||
203 | }; | ||
204 | |||
205 | |||
206 | /* Prototypes ******************************************************/ | ||
207 | |||
208 | /* The following prototypes are already declared elsewhere. They are | ||
209 | repeated here to show what's going on. And to sense, if they're | ||
210 | changed elsewhere. */ | ||
211 | |||
212 | static int mcdx_init(void); | ||
213 | |||
214 | static int mcdx_block_open(struct inode *inode, struct file *file) | ||
215 | { | ||
216 | struct s_drive_stuff *p = inode->i_bdev->bd_disk->private_data; | ||
217 | return cdrom_open(&p->info, inode, file); | ||
218 | } | ||
219 | |||
220 | static int mcdx_block_release(struct inode *inode, struct file *file) | ||
221 | { | ||
222 | struct s_drive_stuff *p = inode->i_bdev->bd_disk->private_data; | ||
223 | return cdrom_release(&p->info, file); | ||
224 | } | ||
225 | |||
226 | static int mcdx_block_ioctl(struct inode *inode, struct file *file, | ||
227 | unsigned cmd, unsigned long arg) | ||
228 | { | ||
229 | struct s_drive_stuff *p = inode->i_bdev->bd_disk->private_data; | ||
230 | return cdrom_ioctl(file, &p->info, inode, cmd, arg); | ||
231 | } | ||
232 | |||
233 | static int mcdx_block_media_changed(struct gendisk *disk) | ||
234 | { | ||
235 | struct s_drive_stuff *p = disk->private_data; | ||
236 | return cdrom_media_changed(&p->info); | ||
237 | } | ||
238 | |||
239 | static struct block_device_operations mcdx_bdops = | ||
240 | { | ||
241 | .owner = THIS_MODULE, | ||
242 | .open = mcdx_block_open, | ||
243 | .release = mcdx_block_release, | ||
244 | .ioctl = mcdx_block_ioctl, | ||
245 | .media_changed = mcdx_block_media_changed, | ||
246 | }; | ||
247 | |||
248 | |||
249 | /* Indirect exported functions. These functions are exported by their | ||
250 | addresses, such as mcdx_open and mcdx_close in the | ||
251 | structure mcdx_dops. */ | ||
252 | |||
253 | /* exported by file_ops */ | ||
254 | static int mcdx_open(struct cdrom_device_info *cdi, int purpose); | ||
255 | static void mcdx_close(struct cdrom_device_info *cdi); | ||
256 | static int mcdx_media_changed(struct cdrom_device_info *cdi, int disc_nr); | ||
257 | static int mcdx_tray_move(struct cdrom_device_info *cdi, int position); | ||
258 | static int mcdx_lockdoor(struct cdrom_device_info *cdi, int lock); | ||
259 | static int mcdx_audio_ioctl(struct cdrom_device_info *cdi, | ||
260 | unsigned int cmd, void *arg); | ||
261 | |||
262 | /* misc internal support functions */ | ||
263 | static void log2msf(unsigned int, struct cdrom_msf0 *); | ||
264 | static unsigned int msf2log(const struct cdrom_msf0 *); | ||
265 | static unsigned int uint2bcd(unsigned int); | ||
266 | static unsigned int bcd2uint(unsigned char); | ||
267 | static unsigned port(int *); | ||
268 | static int irq(int *); | ||
269 | static void mcdx_delay(struct s_drive_stuff *, long jifs); | ||
270 | static int mcdx_transfer(struct s_drive_stuff *, char *buf, int sector, | ||
271 | int nr_sectors); | ||
272 | static int mcdx_xfer(struct s_drive_stuff *, char *buf, int sector, | ||
273 | int nr_sectors); | ||
274 | |||
275 | static int mcdx_config(struct s_drive_stuff *, int); | ||
276 | static int mcdx_requestversion(struct s_drive_stuff *, struct s_version *, | ||
277 | int); | ||
278 | static int mcdx_stop(struct s_drive_stuff *, int); | ||
279 | static int mcdx_hold(struct s_drive_stuff *, int); | ||
280 | static int mcdx_reset(struct s_drive_stuff *, enum resetmodes, int); | ||
281 | static int mcdx_setdrivemode(struct s_drive_stuff *, enum drivemodes, int); | ||
282 | static int mcdx_setdatamode(struct s_drive_stuff *, enum datamodes, int); | ||
283 | static int mcdx_requestsubqcode(struct s_drive_stuff *, | ||
284 | struct s_subqcode *, int); | ||
285 | static int mcdx_requestmultidiskinfo(struct s_drive_stuff *, | ||
286 | struct s_multi *, int); | ||
287 | static int mcdx_requesttocdata(struct s_drive_stuff *, struct s_diskinfo *, | ||
288 | int); | ||
289 | static int mcdx_getstatus(struct s_drive_stuff *, int); | ||
290 | static int mcdx_getval(struct s_drive_stuff *, int to, int delay, char *); | ||
291 | static int mcdx_talk(struct s_drive_stuff *, | ||
292 | const unsigned char *cmd, size_t, | ||
293 | void *buffer, size_t size, unsigned int timeout, int); | ||
294 | static int mcdx_readtoc(struct s_drive_stuff *); | ||
295 | static int mcdx_playtrk(struct s_drive_stuff *, const struct cdrom_ti *); | ||
296 | static int mcdx_playmsf(struct s_drive_stuff *, const struct cdrom_msf *); | ||
297 | static int mcdx_setattentuator(struct s_drive_stuff *, | ||
298 | struct cdrom_volctrl *, int); | ||
299 | |||
300 | /* static variables ************************************************/ | ||
301 | |||
302 | static int mcdx_drive_map[][2] = MCDX_DRIVEMAP; | ||
303 | static struct s_drive_stuff *mcdx_stuffp[MCDX_NDRIVES]; | ||
304 | static DEFINE_SPINLOCK(mcdx_lock); | ||
305 | static struct request_queue *mcdx_queue; | ||
306 | |||
307 | /* You can only set the first two pairs, from old MODULE_PARM code. */ | ||
308 | static int mcdx_set(const char *val, struct kernel_param *kp) | ||
309 | { | ||
310 | get_options((char *)val, 4, (int *)mcdx_drive_map); | ||
311 | return 0; | ||
312 | } | ||
313 | module_param_call(mcdx, mcdx_set, NULL, NULL, 0); | ||
314 | |||
315 | static struct cdrom_device_ops mcdx_dops = { | ||
316 | .open = mcdx_open, | ||
317 | .release = mcdx_close, | ||
318 | .media_changed = mcdx_media_changed, | ||
319 | .tray_move = mcdx_tray_move, | ||
320 | .lock_door = mcdx_lockdoor, | ||
321 | .audio_ioctl = mcdx_audio_ioctl, | ||
322 | .capability = CDC_OPEN_TRAY | CDC_LOCK | CDC_MEDIA_CHANGED | | ||
323 | CDC_PLAY_AUDIO | CDC_DRIVE_STATUS, | ||
324 | }; | ||
325 | |||
326 | /* KERNEL INTERFACE FUNCTIONS **************************************/ | ||
327 | |||
328 | |||
329 | static int mcdx_audio_ioctl(struct cdrom_device_info *cdi, | ||
330 | unsigned int cmd, void *arg) | ||
331 | { | ||
332 | struct s_drive_stuff *stuffp = cdi->handle; | ||
333 | |||
334 | if (!stuffp->present) | ||
335 | return -ENXIO; | ||
336 | |||
337 | if (stuffp->xxx) { | ||
338 | if (-1 == mcdx_requesttocdata(stuffp, &stuffp->di, 1)) { | ||
339 | stuffp->lastsector = -1; | ||
340 | } else { | ||
341 | stuffp->lastsector = (CD_FRAMESIZE / 512) | ||
342 | * msf2log(&stuffp->di.msf_leadout) - 1; | ||
343 | } | ||
344 | |||
345 | if (stuffp->toc) { | ||
346 | kfree(stuffp->toc); | ||
347 | stuffp->toc = NULL; | ||
348 | if (-1 == mcdx_readtoc(stuffp)) | ||
349 | return -1; | ||
350 | } | ||
351 | |||
352 | stuffp->xxx = 0; | ||
353 | } | ||
354 | |||
355 | switch (cmd) { | ||
356 | case CDROMSTART:{ | ||
357 | xtrace(IOCTL, "ioctl() START\n"); | ||
358 | /* Spin up the drive. Don't think we can do this. | ||
359 | * For now, ignore it. | ||
360 | */ | ||
361 | return 0; | ||
362 | } | ||
363 | |||
364 | case CDROMSTOP:{ | ||
365 | xtrace(IOCTL, "ioctl() STOP\n"); | ||
366 | stuffp->audiostatus = CDROM_AUDIO_INVALID; | ||
367 | if (-1 == mcdx_stop(stuffp, 1)) | ||
368 | return -EIO; | ||
369 | return 0; | ||
370 | } | ||
371 | |||
372 | case CDROMPLAYTRKIND:{ | ||
373 | struct cdrom_ti *ti = (struct cdrom_ti *) arg; | ||
374 | |||
375 | xtrace(IOCTL, "ioctl() PLAYTRKIND\n"); | ||
376 | if ((ti->cdti_trk0 < stuffp->di.n_first) | ||
377 | || (ti->cdti_trk0 > stuffp->di.n_last) | ||
378 | || (ti->cdti_trk1 < stuffp->di.n_first)) | ||
379 | return -EINVAL; | ||
380 | if (ti->cdti_trk1 > stuffp->di.n_last) | ||
381 | ti->cdti_trk1 = stuffp->di.n_last; | ||
382 | xtrace(PLAYTRK, "ioctl() track %d to %d\n", | ||
383 | ti->cdti_trk0, ti->cdti_trk1); | ||
384 | return mcdx_playtrk(stuffp, ti); | ||
385 | } | ||
386 | |||
387 | case CDROMPLAYMSF:{ | ||
388 | struct cdrom_msf *msf = (struct cdrom_msf *) arg; | ||
389 | |||
390 | xtrace(IOCTL, "ioctl() PLAYMSF\n"); | ||
391 | |||
392 | if ((stuffp->audiostatus == CDROM_AUDIO_PLAY) | ||
393 | && (-1 == mcdx_hold(stuffp, 1))) | ||
394 | return -EIO; | ||
395 | |||
396 | msf->cdmsf_min0 = uint2bcd(msf->cdmsf_min0); | ||
397 | msf->cdmsf_sec0 = uint2bcd(msf->cdmsf_sec0); | ||
398 | msf->cdmsf_frame0 = uint2bcd(msf->cdmsf_frame0); | ||
399 | |||
400 | msf->cdmsf_min1 = uint2bcd(msf->cdmsf_min1); | ||
401 | msf->cdmsf_sec1 = uint2bcd(msf->cdmsf_sec1); | ||
402 | msf->cdmsf_frame1 = uint2bcd(msf->cdmsf_frame1); | ||
403 | |||
404 | stuffp->stop.dt.minute = msf->cdmsf_min1; | ||
405 | stuffp->stop.dt.second = msf->cdmsf_sec1; | ||
406 | stuffp->stop.dt.frame = msf->cdmsf_frame1; | ||
407 | |||
408 | return mcdx_playmsf(stuffp, msf); | ||
409 | } | ||
410 | |||
411 | case CDROMRESUME:{ | ||
412 | xtrace(IOCTL, "ioctl() RESUME\n"); | ||
413 | return mcdx_playtrk(stuffp, NULL); | ||
414 | } | ||
415 | |||
416 | case CDROMREADTOCENTRY:{ | ||
417 | struct cdrom_tocentry *entry = | ||
418 | (struct cdrom_tocentry *) arg; | ||
419 | struct s_subqcode *tp = NULL; | ||
420 | xtrace(IOCTL, "ioctl() READTOCENTRY\n"); | ||
421 | |||
422 | if (-1 == mcdx_readtoc(stuffp)) | ||
423 | return -1; | ||
424 | if (entry->cdte_track == CDROM_LEADOUT) | ||
425 | tp = &stuffp->toc[stuffp->di.n_last - | ||
426 | stuffp->di.n_first + 1]; | ||
427 | else if (entry->cdte_track > stuffp->di.n_last | ||
428 | || entry->cdte_track < stuffp->di.n_first) | ||
429 | return -EINVAL; | ||
430 | else | ||
431 | tp = &stuffp->toc[entry->cdte_track - | ||
432 | stuffp->di.n_first]; | ||
433 | |||
434 | if (NULL == tp) | ||
435 | return -EIO; | ||
436 | entry->cdte_adr = tp->control; | ||
437 | entry->cdte_ctrl = tp->control >> 4; | ||
438 | /* Always return stuff in MSF, and let the Uniform cdrom driver | ||
439 | worry about what the user actually wants */ | ||
440 | entry->cdte_addr.msf.minute = | ||
441 | bcd2uint(tp->dt.minute); | ||
442 | entry->cdte_addr.msf.second = | ||
443 | bcd2uint(tp->dt.second); | ||
444 | entry->cdte_addr.msf.frame = | ||
445 | bcd2uint(tp->dt.frame); | ||
446 | return 0; | ||
447 | } | ||
448 | |||
449 | case CDROMSUBCHNL:{ | ||
450 | struct cdrom_subchnl *sub = | ||
451 | (struct cdrom_subchnl *) arg; | ||
452 | struct s_subqcode q; | ||
453 | |||
454 | xtrace(IOCTL, "ioctl() SUBCHNL\n"); | ||
455 | |||
456 | if (-1 == mcdx_requestsubqcode(stuffp, &q, 2)) | ||
457 | return -EIO; | ||
458 | |||
459 | xtrace(SUBCHNL, "audiostatus: %x\n", | ||
460 | stuffp->audiostatus); | ||
461 | sub->cdsc_audiostatus = stuffp->audiostatus; | ||
462 | sub->cdsc_adr = q.control; | ||
463 | sub->cdsc_ctrl = q.control >> 4; | ||
464 | sub->cdsc_trk = bcd2uint(q.tno); | ||
465 | sub->cdsc_ind = bcd2uint(q.index); | ||
466 | |||
467 | xtrace(SUBCHNL, "trk %d, ind %d\n", | ||
468 | sub->cdsc_trk, sub->cdsc_ind); | ||
469 | /* Always return stuff in MSF, and let the Uniform cdrom driver | ||
470 | worry about what the user actually wants */ | ||
471 | sub->cdsc_absaddr.msf.minute = | ||
472 | bcd2uint(q.dt.minute); | ||
473 | sub->cdsc_absaddr.msf.second = | ||
474 | bcd2uint(q.dt.second); | ||
475 | sub->cdsc_absaddr.msf.frame = bcd2uint(q.dt.frame); | ||
476 | sub->cdsc_reladdr.msf.minute = | ||
477 | bcd2uint(q.tt.minute); | ||
478 | sub->cdsc_reladdr.msf.second = | ||
479 | bcd2uint(q.tt.second); | ||
480 | sub->cdsc_reladdr.msf.frame = bcd2uint(q.tt.frame); | ||
481 | xtrace(SUBCHNL, | ||
482 | "msf: abs %02d:%02d:%02d, rel %02d:%02d:%02d\n", | ||
483 | sub->cdsc_absaddr.msf.minute, | ||
484 | sub->cdsc_absaddr.msf.second, | ||
485 | sub->cdsc_absaddr.msf.frame, | ||
486 | sub->cdsc_reladdr.msf.minute, | ||
487 | sub->cdsc_reladdr.msf.second, | ||
488 | sub->cdsc_reladdr.msf.frame); | ||
489 | |||
490 | return 0; | ||
491 | } | ||
492 | |||
493 | case CDROMREADTOCHDR:{ | ||
494 | struct cdrom_tochdr *toc = | ||
495 | (struct cdrom_tochdr *) arg; | ||
496 | |||
497 | xtrace(IOCTL, "ioctl() READTOCHDR\n"); | ||
498 | toc->cdth_trk0 = stuffp->di.n_first; | ||
499 | toc->cdth_trk1 = stuffp->di.n_last; | ||
500 | xtrace(TOCHDR, | ||
501 | "ioctl() track0 = %d, track1 = %d\n", | ||
502 | stuffp->di.n_first, stuffp->di.n_last); | ||
503 | return 0; | ||
504 | } | ||
505 | |||
506 | case CDROMPAUSE:{ | ||
507 | xtrace(IOCTL, "ioctl() PAUSE\n"); | ||
508 | if (stuffp->audiostatus != CDROM_AUDIO_PLAY) | ||
509 | return -EINVAL; | ||
510 | if (-1 == mcdx_stop(stuffp, 1)) | ||
511 | return -EIO; | ||
512 | stuffp->audiostatus = CDROM_AUDIO_PAUSED; | ||
513 | if (-1 == | ||
514 | mcdx_requestsubqcode(stuffp, &stuffp->start, | ||
515 | 1)) | ||
516 | return -EIO; | ||
517 | return 0; | ||
518 | } | ||
519 | |||
520 | case CDROMMULTISESSION:{ | ||
521 | struct cdrom_multisession *ms = | ||
522 | (struct cdrom_multisession *) arg; | ||
523 | xtrace(IOCTL, "ioctl() MULTISESSION\n"); | ||
524 | /* Always return stuff in LBA, and let the Uniform cdrom driver | ||
525 | worry about what the user actually wants */ | ||
526 | ms->addr.lba = msf2log(&stuffp->multi.msf_last); | ||
527 | ms->xa_flag = !!stuffp->multi.multi; | ||
528 | xtrace(MS, | ||
529 | "ioctl() (%d, 0x%08x [%02x:%02x.%02x])\n", | ||
530 | ms->xa_flag, ms->addr.lba, | ||
531 | stuffp->multi.msf_last.minute, | ||
532 | stuffp->multi.msf_last.second, | ||
533 | stuffp->multi.msf_last.frame); | ||
534 | |||
535 | return 0; | ||
536 | } | ||
537 | |||
538 | case CDROMEJECT:{ | ||
539 | xtrace(IOCTL, "ioctl() EJECT\n"); | ||
540 | if (stuffp->users > 1) | ||
541 | return -EBUSY; | ||
542 | return (mcdx_tray_move(cdi, 1)); | ||
543 | } | ||
544 | |||
545 | case CDROMCLOSETRAY:{ | ||
546 | xtrace(IOCTL, "ioctl() CDROMCLOSETRAY\n"); | ||
547 | return (mcdx_tray_move(cdi, 0)); | ||
548 | } | ||
549 | |||
550 | case CDROMVOLCTRL:{ | ||
551 | struct cdrom_volctrl *volctrl = | ||
552 | (struct cdrom_volctrl *) arg; | ||
553 | xtrace(IOCTL, "ioctl() VOLCTRL\n"); | ||
554 | |||
555 | #if 0 /* not tested! */ | ||
556 | /* adjust for the weirdness of workman (md) */ | ||
557 | /* can't test it (hs) */ | ||
558 | volctrl.channel2 = volctrl.channel1; | ||
559 | volctrl.channel1 = volctrl.channel3 = 0x00; | ||
560 | #endif | ||
561 | return mcdx_setattentuator(stuffp, volctrl, 2); | ||
562 | } | ||
563 | |||
564 | default: | ||
565 | return -EINVAL; | ||
566 | } | ||
567 | } | ||
568 | |||
569 | static void do_mcdx_request(request_queue_t * q) | ||
570 | { | ||
571 | struct s_drive_stuff *stuffp; | ||
572 | struct request *req; | ||
573 | |||
574 | again: | ||
575 | |||
576 | req = elv_next_request(q); | ||
577 | if (!req) | ||
578 | return; | ||
579 | |||
580 | stuffp = req->rq_disk->private_data; | ||
581 | |||
582 | if (!stuffp->present) { | ||
583 | xwarn("do_request(): bad device: %s\n",req->rq_disk->disk_name); | ||
584 | xtrace(REQUEST, "end_request(0): bad device\n"); | ||
585 | end_request(req, 0); | ||
586 | return; | ||
587 | } | ||
588 | |||
589 | if (stuffp->audio) { | ||
590 | xwarn("do_request() attempt to read from audio cd\n"); | ||
591 | xtrace(REQUEST, "end_request(0): read from audio\n"); | ||
592 | end_request(req, 0); | ||
593 | return; | ||
594 | } | ||
595 | |||
596 | xtrace(REQUEST, "do_request() (%lu + %lu)\n", | ||
597 | req->sector, req->nr_sectors); | ||
598 | |||
599 | if (rq_data_dir(req) != READ) { | ||
600 | xwarn("do_request(): non-read command to cd!!\n"); | ||
601 | xtrace(REQUEST, "end_request(0): write\n"); | ||
602 | end_request(req, 0); | ||
603 | return; | ||
604 | } | ||
605 | else { | ||
606 | stuffp->status = 0; | ||
607 | while (req->nr_sectors) { | ||
608 | int i; | ||
609 | |||
610 | i = mcdx_transfer(stuffp, | ||
611 | req->buffer, | ||
612 | req->sector, | ||
613 | req->nr_sectors); | ||
614 | |||
615 | if (i == -1) { | ||
616 | end_request(req, 0); | ||
617 | goto again; | ||
618 | } | ||
619 | req->sector += i; | ||
620 | req->nr_sectors -= i; | ||
621 | req->buffer += (i * 512); | ||
622 | } | ||
623 | end_request(req, 1); | ||
624 | goto again; | ||
625 | |||
626 | xtrace(REQUEST, "end_request(1)\n"); | ||
627 | end_request(req, 1); | ||
628 | } | ||
629 | |||
630 | goto again; | ||
631 | } | ||
632 | |||
633 | static int mcdx_open(struct cdrom_device_info *cdi, int purpose) | ||
634 | { | ||
635 | struct s_drive_stuff *stuffp; | ||
636 | xtrace(OPENCLOSE, "open()\n"); | ||
637 | stuffp = cdi->handle; | ||
638 | if (!stuffp->present) | ||
639 | return -ENXIO; | ||
640 | |||
641 | /* Make the modules looking used ... (thanx bjorn). | ||
642 | * But we shouldn't forget to decrement the module counter | ||
643 | * on error return */ | ||
644 | |||
645 | /* this is only done to test if the drive talks with us */ | ||
646 | if (-1 == mcdx_getstatus(stuffp, 1)) | ||
647 | return -EIO; | ||
648 | |||
649 | if (stuffp->xxx) { | ||
650 | |||
651 | xtrace(OPENCLOSE, "open() media changed\n"); | ||
652 | stuffp->audiostatus = CDROM_AUDIO_INVALID; | ||
653 | stuffp->readcmd = 0; | ||
654 | xtrace(OPENCLOSE, "open() Request multisession info\n"); | ||
655 | if (-1 == | ||
656 | mcdx_requestmultidiskinfo(stuffp, &stuffp->multi, 6)) | ||
657 | xinfo("No multidiskinfo\n"); | ||
658 | } else { | ||
659 | /* multisession ? */ | ||
660 | if (!stuffp->multi.multi) | ||
661 | stuffp->multi.msf_last.second = 2; | ||
662 | |||
663 | xtrace(OPENCLOSE, "open() MS: %d, last @ %02x:%02x.%02x\n", | ||
664 | stuffp->multi.multi, | ||
665 | stuffp->multi.msf_last.minute, | ||
666 | stuffp->multi.msf_last.second, | ||
667 | stuffp->multi.msf_last.frame); | ||
668 | |||
669 | {; | ||
670 | } /* got multisession information */ | ||
671 | /* request the disks table of contents (aka diskinfo) */ | ||
672 | if (-1 == mcdx_requesttocdata(stuffp, &stuffp->di, 1)) { | ||
673 | |||
674 | stuffp->lastsector = -1; | ||
675 | |||
676 | } else { | ||
677 | |||
678 | stuffp->lastsector = (CD_FRAMESIZE / 512) | ||
679 | * msf2log(&stuffp->di.msf_leadout) - 1; | ||
680 | |||
681 | xtrace(OPENCLOSE, | ||
682 | "open() start %d (%02x:%02x.%02x) %d\n", | ||
683 | stuffp->di.n_first, | ||
684 | stuffp->di.msf_first.minute, | ||
685 | stuffp->di.msf_first.second, | ||
686 | stuffp->di.msf_first.frame, | ||
687 | msf2log(&stuffp->di.msf_first)); | ||
688 | xtrace(OPENCLOSE, | ||
689 | "open() last %d (%02x:%02x.%02x) %d\n", | ||
690 | stuffp->di.n_last, | ||
691 | stuffp->di.msf_leadout.minute, | ||
692 | stuffp->di.msf_leadout.second, | ||
693 | stuffp->di.msf_leadout.frame, | ||
694 | msf2log(&stuffp->di.msf_leadout)); | ||
695 | } | ||
696 | |||
697 | if (stuffp->toc) { | ||
698 | xtrace(MALLOC, "open() free old toc @ %p\n", | ||
699 | stuffp->toc); | ||
700 | kfree(stuffp->toc); | ||
701 | |||
702 | stuffp->toc = NULL; | ||
703 | } | ||
704 | |||
705 | xtrace(OPENCLOSE, "open() init irq generation\n"); | ||
706 | if (-1 == mcdx_config(stuffp, 1)) | ||
707 | return -EIO; | ||
708 | #ifdef FALLBACK | ||
709 | /* Set the read speed */ | ||
710 | xwarn("AAA %x AAA\n", stuffp->readcmd); | ||
711 | if (stuffp->readerrs) | ||
712 | stuffp->readcmd = READ1X; | ||
713 | else | ||
714 | stuffp->readcmd = | ||
715 | stuffp->present | SINGLE ? READ1X : READ2X; | ||
716 | xwarn("XXX %x XXX\n", stuffp->readcmd); | ||
717 | #else | ||
718 | stuffp->readcmd = | ||
719 | stuffp->present | SINGLE ? READ1X : READ2X; | ||
720 | #endif | ||
721 | |||
722 | /* try to get the first sector, iff any ... */ | ||
723 | if (stuffp->lastsector >= 0) { | ||
724 | char buf[512]; | ||
725 | int ans; | ||
726 | int tries; | ||
727 | |||
728 | stuffp->xa = 0; | ||
729 | stuffp->audio = 0; | ||
730 | |||
731 | for (tries = 6; tries; tries--) { | ||
732 | |||
733 | stuffp->introk = 1; | ||
734 | |||
735 | xtrace(OPENCLOSE, "open() try as %s\n", | ||
736 | stuffp->xa ? "XA" : "normal"); | ||
737 | /* set data mode */ | ||
738 | if (-1 == (ans = mcdx_setdatamode(stuffp, | ||
739 | stuffp-> | ||
740 | xa ? | ||
741 | MODE2 : | ||
742 | MODE1, | ||
743 | 1))) { | ||
744 | /* return -EIO; */ | ||
745 | stuffp->xa = 0; | ||
746 | break; | ||
747 | } | ||
748 | |||
749 | if ((stuffp->audio = e_audio(ans))) | ||
750 | break; | ||
751 | |||
752 | while (0 == | ||
753 | (ans = | ||
754 | mcdx_transfer(stuffp, buf, 0, 1))); | ||
755 | |||
756 | if (ans == 1) | ||
757 | break; | ||
758 | stuffp->xa = !stuffp->xa; | ||
759 | } | ||
760 | } | ||
761 | /* xa disks will be read in raw mode, others not */ | ||
762 | if (-1 == mcdx_setdrivemode(stuffp, | ||
763 | stuffp->xa ? RAW : COOKED, | ||
764 | 1)) | ||
765 | return -EIO; | ||
766 | if (stuffp->audio) { | ||
767 | xinfo("open() audio disk found\n"); | ||
768 | } else if (stuffp->lastsector >= 0) { | ||
769 | xinfo("open() %s%s disk found\n", | ||
770 | stuffp->xa ? "XA / " : "", | ||
771 | stuffp->multi. | ||
772 | multi ? "Multi Session" : "Single Session"); | ||
773 | } | ||
774 | } | ||
775 | stuffp->xxx = 0; | ||
776 | stuffp->users++; | ||
777 | return 0; | ||
778 | } | ||
779 | |||
780 | static void mcdx_close(struct cdrom_device_info *cdi) | ||
781 | { | ||
782 | struct s_drive_stuff *stuffp; | ||
783 | |||
784 | xtrace(OPENCLOSE, "close()\n"); | ||
785 | |||
786 | stuffp = cdi->handle; | ||
787 | |||
788 | --stuffp->users; | ||
789 | } | ||
790 | |||
791 | static int mcdx_media_changed(struct cdrom_device_info *cdi, int disc_nr) | ||
792 | /* Return: 1 if media changed since last call to this function | ||
793 | 0 otherwise */ | ||
794 | { | ||
795 | struct s_drive_stuff *stuffp; | ||
796 | |||
797 | xinfo("mcdx_media_changed called for device %s\n", cdi->name); | ||
798 | |||
799 | stuffp = cdi->handle; | ||
800 | mcdx_getstatus(stuffp, 1); | ||
801 | |||
802 | if (stuffp->yyy == 0) | ||
803 | return 0; | ||
804 | |||
805 | stuffp->yyy = 0; | ||
806 | return 1; | ||
807 | } | ||
808 | |||
809 | #ifndef MODULE | ||
810 | static int __init mcdx_setup(char *str) | ||
811 | { | ||
812 | int pi[4]; | ||
813 | (void) get_options(str, ARRAY_SIZE(pi), pi); | ||
814 | |||
815 | if (pi[0] > 0) | ||
816 | mcdx_drive_map[0][0] = pi[1]; | ||
817 | if (pi[0] > 1) | ||
818 | mcdx_drive_map[0][1] = pi[2]; | ||
819 | return 1; | ||
820 | } | ||
821 | |||
822 | __setup("mcdx=", mcdx_setup); | ||
823 | |||
824 | #endif | ||
825 | |||
826 | /* DIRTY PART ******************************************************/ | ||
827 | |||
828 | static void mcdx_delay(struct s_drive_stuff *stuff, long jifs) | ||
829 | /* This routine is used for sleeping. | ||
830 | * A jifs value <0 means NO sleeping, | ||
831 | * =0 means minimal sleeping (let the kernel | ||
832 | * run for other processes) | ||
833 | * >0 means at least sleep for that amount. | ||
834 | * May be we could use a simple count loop w/ jumps to itself, but | ||
835 | * I wanna make this independent of cpu speed. [1 jiffy is 1/HZ] sec */ | ||
836 | { | ||
837 | if (jifs < 0) | ||
838 | return; | ||
839 | |||
840 | xtrace(SLEEP, "*** delay: sleepq\n"); | ||
841 | interruptible_sleep_on_timeout(&stuff->sleepq, jifs); | ||
842 | xtrace(SLEEP, "delay awoken\n"); | ||
843 | if (signal_pending(current)) { | ||
844 | xtrace(SLEEP, "got signal\n"); | ||
845 | } | ||
846 | } | ||
847 | |||
848 | static irqreturn_t mcdx_intr(int irq, void *dev_id) | ||
849 | { | ||
850 | struct s_drive_stuff *stuffp = dev_id; | ||
851 | unsigned char b; | ||
852 | |||
853 | #ifdef AK2 | ||
854 | if (!stuffp->busy && stuffp->pending) | ||
855 | stuffp->int_err = 1; | ||
856 | |||
857 | #endif /* AK2 */ | ||
858 | /* get the interrupt status */ | ||
859 | b = inb(stuffp->rreg_status); | ||
860 | stuffp->introk = ~b & MCDX_RBIT_DTEN; | ||
861 | |||
862 | /* NOTE: We only should get interrupts if the data we | ||
863 | * requested are ready to transfer. | ||
864 | * But the drive seems to generate ``asynchronous'' interrupts | ||
865 | * on several error conditions too. (Despite the err int enable | ||
866 | * setting during initialisation) */ | ||
867 | |||
868 | /* if not ok, read the next byte as the drives status */ | ||
869 | if (!stuffp->introk) { | ||
870 | xtrace(IRQ, "intr() irq %d hw status 0x%02x\n", irq, b); | ||
871 | if (~b & MCDX_RBIT_STEN) { | ||
872 | xinfo("intr() irq %d status 0x%02x\n", | ||
873 | irq, inb(stuffp->rreg_data)); | ||
874 | } else { | ||
875 | xinfo("intr() irq %d ambiguous hw status\n", irq); | ||
876 | } | ||
877 | } else { | ||
878 | xtrace(IRQ, "irq() irq %d ok, status %02x\n", irq, b); | ||
879 | } | ||
880 | |||
881 | stuffp->busy = 0; | ||
882 | wake_up_interruptible(&stuffp->busyq); | ||
883 | return IRQ_HANDLED; | ||
884 | } | ||
885 | |||
886 | |||
887 | static int mcdx_talk(struct s_drive_stuff *stuffp, | ||
888 | const unsigned char *cmd, size_t cmdlen, | ||
889 | void *buffer, size_t size, unsigned int timeout, int tries) | ||
890 | /* Send a command to the drive, wait for the result. | ||
891 | * returns -1 on timeout, drive status otherwise | ||
892 | * If buffer is not zero, the result (length size) is stored there. | ||
893 | * If buffer is zero the size should be the number of bytes to read | ||
894 | * from the drive. These bytes are discarded. | ||
895 | */ | ||
896 | { | ||
897 | int st; | ||
898 | char c; | ||
899 | int discard; | ||
900 | |||
901 | /* Somebody wants the data read? */ | ||
902 | if ((discard = (buffer == NULL))) | ||
903 | buffer = &c; | ||
904 | |||
905 | while (stuffp->lock) { | ||
906 | xtrace(SLEEP, "*** talk: lockq\n"); | ||
907 | interruptible_sleep_on(&stuffp->lockq); | ||
908 | xtrace(SLEEP, "talk: awoken\n"); | ||
909 | } | ||
910 | |||
911 | stuffp->lock = 1; | ||
912 | |||
913 | /* An operation other then reading data destroys the | ||
914 | * data already requested and remembered in stuffp->request, ... */ | ||
915 | stuffp->valid = 0; | ||
916 | |||
917 | #if MCDX_DEBUG & TALK | ||
918 | { | ||
919 | unsigned char i; | ||
920 | xtrace(TALK, | ||
921 | "talk() %d / %d tries, res.size %d, command 0x%02x", | ||
922 | tries, timeout, size, (unsigned char) cmd[0]); | ||
923 | for (i = 1; i < cmdlen; i++) | ||
924 | xtrace(TALK, " 0x%02x", cmd[i]); | ||
925 | xtrace(TALK, "\n"); | ||
926 | } | ||
927 | #endif | ||
928 | |||
929 | /* give up if all tries are done (bad) or if the status | ||
930 | * st != -1 (good) */ | ||
931 | for (st = -1; st == -1 && tries; tries--) { | ||
932 | |||
933 | char *bp = (char *) buffer; | ||
934 | size_t sz = size; | ||
935 | |||
936 | outsb(stuffp->wreg_data, cmd, cmdlen); | ||
937 | xtrace(TALK, "talk() command sent\n"); | ||
938 | |||
939 | /* get the status byte */ | ||
940 | if (-1 == mcdx_getval(stuffp, timeout, 0, bp)) { | ||
941 | xinfo("talk() %02x timed out (status), %d tr%s left\n", | ||
942 | cmd[0], tries - 1, tries == 2 ? "y" : "ies"); | ||
943 | continue; | ||
944 | } | ||
945 | st = *bp; | ||
946 | sz--; | ||
947 | if (!discard) | ||
948 | bp++; | ||
949 | |||
950 | xtrace(TALK, "talk() got status 0x%02x\n", st); | ||
951 | |||
952 | /* command error? */ | ||
953 | if (e_cmderr(st)) { | ||
954 | xwarn("command error cmd = %02x %s \n", | ||
955 | cmd[0], cmdlen > 1 ? "..." : ""); | ||
956 | st = -1; | ||
957 | continue; | ||
958 | } | ||
959 | |||
960 | /* audio status? */ | ||
961 | if (stuffp->audiostatus == CDROM_AUDIO_INVALID) | ||
962 | stuffp->audiostatus = | ||
963 | e_audiobusy(st) ? CDROM_AUDIO_PLAY : | ||
964 | CDROM_AUDIO_NO_STATUS; | ||
965 | else if (stuffp->audiostatus == CDROM_AUDIO_PLAY | ||
966 | && e_audiobusy(st) == 0) | ||
967 | stuffp->audiostatus = CDROM_AUDIO_COMPLETED; | ||
968 | |||
969 | /* media change? */ | ||
970 | if (e_changed(st)) { | ||
971 | xinfo("talk() media changed\n"); | ||
972 | stuffp->xxx = stuffp->yyy = 1; | ||
973 | } | ||
974 | |||
975 | /* now actually get the data */ | ||
976 | while (sz--) { | ||
977 | if (-1 == mcdx_getval(stuffp, timeout, 0, bp)) { | ||
978 | xinfo("talk() %02x timed out (data), %d tr%s left\n", | ||
979 | cmd[0], tries - 1, | ||
980 | tries == 2 ? "y" : "ies"); | ||
981 | st = -1; | ||
982 | break; | ||
983 | } | ||
984 | if (!discard) | ||
985 | bp++; | ||
986 | xtrace(TALK, "talk() got 0x%02x\n", *(bp - 1)); | ||
987 | } | ||
988 | } | ||
989 | |||
990 | #if !MCDX_QUIET | ||
991 | if (!tries && st == -1) | ||
992 | xinfo("talk() giving up\n"); | ||
993 | #endif | ||
994 | |||
995 | stuffp->lock = 0; | ||
996 | wake_up_interruptible(&stuffp->lockq); | ||
997 | |||
998 | xtrace(TALK, "talk() done with 0x%02x\n", st); | ||
999 | return st; | ||
1000 | } | ||
1001 | |||
1002 | /* MODULE STUFF ***********************************************************/ | ||
1003 | |||
1004 | static int __init __mcdx_init(void) | ||
1005 | { | ||
1006 | int i; | ||
1007 | int drives = 0; | ||
1008 | |||
1009 | mcdx_init(); | ||
1010 | for (i = 0; i < MCDX_NDRIVES; i++) { | ||
1011 | if (mcdx_stuffp[i]) { | ||
1012 | xtrace(INIT, "init_module() drive %d stuff @ %p\n", | ||
1013 | i, mcdx_stuffp[i]); | ||
1014 | drives++; | ||
1015 | } | ||
1016 | } | ||
1017 | |||
1018 | if (!drives) | ||
1019 | return -EIO; | ||
1020 | |||
1021 | return 0; | ||
1022 | } | ||
1023 | |||
1024 | static void __exit mcdx_exit(void) | ||
1025 | { | ||
1026 | int i; | ||
1027 | |||
1028 | xinfo("cleanup_module called\n"); | ||
1029 | |||
1030 | for (i = 0; i < MCDX_NDRIVES; i++) { | ||
1031 | struct s_drive_stuff *stuffp = mcdx_stuffp[i]; | ||
1032 | if (!stuffp) | ||
1033 | continue; | ||
1034 | del_gendisk(stuffp->disk); | ||
1035 | if (unregister_cdrom(&stuffp->info)) { | ||
1036 | printk(KERN_WARNING "Can't unregister cdrom mcdx\n"); | ||
1037 | continue; | ||
1038 | } | ||
1039 | put_disk(stuffp->disk); | ||
1040 | release_region(stuffp->wreg_data, MCDX_IO_SIZE); | ||
1041 | free_irq(stuffp->irq, NULL); | ||
1042 | if (stuffp->toc) { | ||
1043 | xtrace(MALLOC, "cleanup_module() free toc @ %p\n", | ||
1044 | stuffp->toc); | ||
1045 | kfree(stuffp->toc); | ||
1046 | } | ||
1047 | xtrace(MALLOC, "cleanup_module() free stuffp @ %p\n", | ||
1048 | stuffp); | ||
1049 | mcdx_stuffp[i] = NULL; | ||
1050 | kfree(stuffp); | ||
1051 | } | ||
1052 | |||
1053 | if (unregister_blkdev(MAJOR_NR, "mcdx") != 0) { | ||
1054 | xwarn("cleanup() unregister_blkdev() failed\n"); | ||
1055 | } | ||
1056 | #if !MCDX_QUIET | ||
1057 | else | ||
1058 | xinfo("cleanup() succeeded\n"); | ||
1059 | #endif | ||
1060 | blk_cleanup_queue(mcdx_queue); | ||
1061 | } | ||
1062 | |||
1063 | #ifdef MODULE | ||
1064 | module_init(__mcdx_init); | ||
1065 | #endif | ||
1066 | module_exit(mcdx_exit); | ||
1067 | |||
1068 | |||
1069 | /* Support functions ************************************************/ | ||
1070 | |||
1071 | static int __init mcdx_init_drive(int drive) | ||
1072 | { | ||
1073 | struct s_version version; | ||
1074 | struct gendisk *disk; | ||
1075 | struct s_drive_stuff *stuffp; | ||
1076 | int size = sizeof(*stuffp); | ||
1077 | char msg[80]; | ||
1078 | |||
1079 | xtrace(INIT, "init() try drive %d\n", drive); | ||
1080 | |||
1081 | xtrace(INIT, "kmalloc space for stuffpt's\n"); | ||
1082 | xtrace(MALLOC, "init() malloc %d bytes\n", size); | ||
1083 | if (!(stuffp = kzalloc(size, GFP_KERNEL))) { | ||
1084 | xwarn("init() malloc failed\n"); | ||
1085 | return 1; | ||
1086 | } | ||
1087 | |||
1088 | disk = alloc_disk(1); | ||
1089 | if (!disk) { | ||
1090 | xwarn("init() malloc failed\n"); | ||
1091 | kfree(stuffp); | ||
1092 | return 1; | ||
1093 | } | ||
1094 | |||
1095 | xtrace(INIT, "init() got %d bytes for drive stuff @ %p\n", | ||
1096 | sizeof(*stuffp), stuffp); | ||
1097 | |||
1098 | /* set default values */ | ||
1099 | stuffp->present = 0; /* this should be 0 already */ | ||
1100 | stuffp->toc = NULL; /* this should be NULL already */ | ||
1101 | |||
1102 | /* setup our irq and i/o addresses */ | ||
1103 | stuffp->irq = irq(mcdx_drive_map[drive]); | ||
1104 | stuffp->wreg_data = stuffp->rreg_data = port(mcdx_drive_map[drive]); | ||
1105 | stuffp->wreg_reset = stuffp->rreg_status = stuffp->wreg_data + 1; | ||
1106 | stuffp->wreg_hcon = stuffp->wreg_reset + 1; | ||
1107 | stuffp->wreg_chn = stuffp->wreg_hcon + 1; | ||
1108 | |||
1109 | init_waitqueue_head(&stuffp->busyq); | ||
1110 | init_waitqueue_head(&stuffp->lockq); | ||
1111 | init_waitqueue_head(&stuffp->sleepq); | ||
1112 | |||
1113 | /* check if i/o addresses are available */ | ||
1114 | if (!request_region(stuffp->wreg_data, MCDX_IO_SIZE, "mcdx")) { | ||
1115 | xwarn("0x%03x,%d: Init failed. " | ||
1116 | "I/O ports (0x%03x..0x%03x) already in use.\n", | ||
1117 | stuffp->wreg_data, stuffp->irq, | ||
1118 | stuffp->wreg_data, | ||
1119 | stuffp->wreg_data + MCDX_IO_SIZE - 1); | ||
1120 | xtrace(MALLOC, "init() free stuffp @ %p\n", stuffp); | ||
1121 | kfree(stuffp); | ||
1122 | put_disk(disk); | ||
1123 | xtrace(INIT, "init() continue at next drive\n"); | ||
1124 | return 0; /* next drive */ | ||
1125 | } | ||
1126 | |||
1127 | xtrace(INIT, "init() i/o port is available at 0x%03x\n" | ||
1128 | stuffp->wreg_data); | ||
1129 | xtrace(INIT, "init() hardware reset\n"); | ||
1130 | mcdx_reset(stuffp, HARD, 1); | ||
1131 | |||
1132 | xtrace(INIT, "init() get version\n"); | ||
1133 | if (-1 == mcdx_requestversion(stuffp, &version, 4)) { | ||
1134 | /* failed, next drive */ | ||
1135 | release_region(stuffp->wreg_data, MCDX_IO_SIZE); | ||
1136 | xwarn("%s=0x%03x,%d: Init failed. Can't get version.\n", | ||
1137 | MCDX, stuffp->wreg_data, stuffp->irq); | ||
1138 | xtrace(MALLOC, "init() free stuffp @ %p\n", stuffp); | ||
1139 | kfree(stuffp); | ||
1140 | put_disk(disk); | ||
1141 | xtrace(INIT, "init() continue at next drive\n"); | ||
1142 | return 0; | ||
1143 | } | ||
1144 | |||
1145 | switch (version.code) { | ||
1146 | case 'D': | ||
1147 | stuffp->readcmd = READ2X; | ||
1148 | stuffp->present = DOUBLE | DOOR | MULTI; | ||
1149 | break; | ||
1150 | case 'F': | ||
1151 | stuffp->readcmd = READ1X; | ||
1152 | stuffp->present = SINGLE | DOOR | MULTI; | ||
1153 | break; | ||
1154 | case 'M': | ||
1155 | stuffp->readcmd = READ1X; | ||
1156 | stuffp->present = SINGLE; | ||
1157 | break; | ||
1158 | default: | ||
1159 | stuffp->present = 0; | ||
1160 | break; | ||
1161 | } | ||
1162 | |||
1163 | stuffp->playcmd = READ1X; | ||
1164 | |||
1165 | if (!stuffp->present) { | ||
1166 | release_region(stuffp->wreg_data, MCDX_IO_SIZE); | ||
1167 | xwarn("%s=0x%03x,%d: Init failed. No Mitsumi CD-ROM?.\n", | ||
1168 | MCDX, stuffp->wreg_data, stuffp->irq); | ||
1169 | kfree(stuffp); | ||
1170 | put_disk(disk); | ||
1171 | return 0; /* next drive */ | ||
1172 | } | ||
1173 | |||
1174 | xtrace(INIT, "init() register blkdev\n"); | ||
1175 | if (register_blkdev(MAJOR_NR, "mcdx")) { | ||
1176 | release_region(stuffp->wreg_data, MCDX_IO_SIZE); | ||
1177 | kfree(stuffp); | ||
1178 | put_disk(disk); | ||
1179 | return 1; | ||
1180 | } | ||
1181 | |||
1182 | mcdx_queue = blk_init_queue(do_mcdx_request, &mcdx_lock); | ||
1183 | if (!mcdx_queue) { | ||
1184 | unregister_blkdev(MAJOR_NR, "mcdx"); | ||
1185 | release_region(stuffp->wreg_data, MCDX_IO_SIZE); | ||
1186 | kfree(stuffp); | ||
1187 | put_disk(disk); | ||
1188 | return 1; | ||
1189 | } | ||
1190 | |||
1191 | xtrace(INIT, "init() subscribe irq and i/o\n"); | ||
1192 | if (request_irq(stuffp->irq, mcdx_intr, IRQF_DISABLED, "mcdx", stuffp)) { | ||
1193 | release_region(stuffp->wreg_data, MCDX_IO_SIZE); | ||
1194 | xwarn("%s=0x%03x,%d: Init failed. Can't get irq (%d).\n", | ||
1195 | MCDX, stuffp->wreg_data, stuffp->irq, stuffp->irq); | ||
1196 | stuffp->irq = 0; | ||
1197 | blk_cleanup_queue(mcdx_queue); | ||
1198 | kfree(stuffp); | ||
1199 | put_disk(disk); | ||
1200 | return 0; | ||
1201 | } | ||
1202 | |||
1203 | xtrace(INIT, "init() get garbage\n"); | ||
1204 | { | ||
1205 | int i; | ||
1206 | mcdx_delay(stuffp, HZ / 2); | ||
1207 | for (i = 100; i; i--) | ||
1208 | (void) inb(stuffp->rreg_status); | ||
1209 | } | ||
1210 | |||
1211 | |||
1212 | #ifdef WE_KNOW_WHY | ||
1213 | /* irq 11 -> channel register */ | ||
1214 | outb(0x50, stuffp->wreg_chn); | ||
1215 | #endif | ||
1216 | |||
1217 | xtrace(INIT, "init() set non dma but irq mode\n"); | ||
1218 | mcdx_config(stuffp, 1); | ||
1219 | |||
1220 | stuffp->info.ops = &mcdx_dops; | ||
1221 | stuffp->info.speed = 2; | ||
1222 | stuffp->info.capacity = 1; | ||
1223 | stuffp->info.handle = stuffp; | ||
1224 | sprintf(stuffp->info.name, "mcdx%d", drive); | ||
1225 | disk->major = MAJOR_NR; | ||
1226 | disk->first_minor = drive; | ||
1227 | strcpy(disk->disk_name, stuffp->info.name); | ||
1228 | disk->fops = &mcdx_bdops; | ||
1229 | disk->flags = GENHD_FL_CD; | ||
1230 | stuffp->disk = disk; | ||
1231 | |||
1232 | sprintf(msg, " mcdx: Mitsumi CD-ROM installed at 0x%03x, irq %d." | ||
1233 | " (Firmware version %c %x)\n", | ||
1234 | stuffp->wreg_data, stuffp->irq, version.code, version.ver); | ||
1235 | mcdx_stuffp[drive] = stuffp; | ||
1236 | xtrace(INIT, "init() mcdx_stuffp[%d] = %p\n", drive, stuffp); | ||
1237 | if (register_cdrom(&stuffp->info) != 0) { | ||
1238 | printk("Cannot register Mitsumi CD-ROM!\n"); | ||
1239 | free_irq(stuffp->irq, NULL); | ||
1240 | release_region(stuffp->wreg_data, MCDX_IO_SIZE); | ||
1241 | kfree(stuffp); | ||
1242 | put_disk(disk); | ||
1243 | if (unregister_blkdev(MAJOR_NR, "mcdx") != 0) | ||
1244 | xwarn("cleanup() unregister_blkdev() failed\n"); | ||
1245 | blk_cleanup_queue(mcdx_queue); | ||
1246 | return 2; | ||
1247 | } | ||
1248 | disk->private_data = stuffp; | ||
1249 | disk->queue = mcdx_queue; | ||
1250 | add_disk(disk); | ||
1251 | printk(msg); | ||
1252 | return 0; | ||
1253 | } | ||
1254 | |||
1255 | static int __init mcdx_init(void) | ||
1256 | { | ||
1257 | int drive; | ||
1258 | xwarn("Version 2.14(hs) \n"); | ||
1259 | |||
1260 | xwarn("$Id: mcdx.c,v 1.21 1997/01/26 07:12:59 davem Exp $\n"); | ||
1261 | |||
1262 | /* zero the pointer array */ | ||
1263 | for (drive = 0; drive < MCDX_NDRIVES; drive++) | ||
1264 | mcdx_stuffp[drive] = NULL; | ||
1265 | |||
1266 | /* do the initialisation */ | ||
1267 | for (drive = 0; drive < MCDX_NDRIVES; drive++) { | ||
1268 | switch (mcdx_init_drive(drive)) { | ||
1269 | case 2: | ||
1270 | return -EIO; | ||
1271 | case 1: | ||
1272 | break; | ||
1273 | } | ||
1274 | } | ||
1275 | return 0; | ||
1276 | } | ||
1277 | |||
1278 | static int mcdx_transfer(struct s_drive_stuff *stuffp, | ||
1279 | char *p, int sector, int nr_sectors) | ||
1280 | /* This seems to do the actually transfer. But it does more. It | ||
1281 | keeps track of errors occurred and will (if possible) fall back | ||
1282 | to single speed on error. | ||
1283 | Return: -1 on timeout or other error | ||
1284 | else status byte (as in stuff->st) */ | ||
1285 | { | ||
1286 | int ans; | ||
1287 | |||
1288 | ans = mcdx_xfer(stuffp, p, sector, nr_sectors); | ||
1289 | return ans; | ||
1290 | #ifdef FALLBACK | ||
1291 | if (-1 == ans) | ||
1292 | stuffp->readerrs++; | ||
1293 | else | ||
1294 | return ans; | ||
1295 | |||
1296 | if (stuffp->readerrs && stuffp->readcmd == READ1X) { | ||
1297 | xwarn("XXX Already reading 1x -- no chance\n"); | ||
1298 | return -1; | ||
1299 | } | ||
1300 | |||
1301 | xwarn("XXX Fallback to 1x\n"); | ||
1302 | |||
1303 | stuffp->readcmd = READ1X; | ||
1304 | return mcdx_transfer(stuffp, p, sector, nr_sectors); | ||
1305 | #endif | ||
1306 | |||
1307 | } | ||
1308 | |||
1309 | |||
1310 | static int mcdx_xfer(struct s_drive_stuff *stuffp, | ||
1311 | char *p, int sector, int nr_sectors) | ||
1312 | /* This does actually the transfer from the drive. | ||
1313 | Return: -1 on timeout or other error | ||
1314 | else status byte (as in stuff->st) */ | ||
1315 | { | ||
1316 | int border; | ||
1317 | int done = 0; | ||
1318 | long timeout; | ||
1319 | |||
1320 | if (stuffp->audio) { | ||
1321 | xwarn("Attempt to read from audio CD.\n"); | ||
1322 | return -1; | ||
1323 | } | ||
1324 | |||
1325 | if (!stuffp->readcmd) { | ||
1326 | xinfo("Can't transfer from missing disk.\n"); | ||
1327 | return -1; | ||
1328 | } | ||
1329 | |||
1330 | while (stuffp->lock) { | ||
1331 | interruptible_sleep_on(&stuffp->lockq); | ||
1332 | } | ||
1333 | |||
1334 | if (stuffp->valid && (sector >= stuffp->pending) | ||
1335 | && (sector < stuffp->low_border)) { | ||
1336 | |||
1337 | /* All (or at least a part of the sectors requested) seems | ||
1338 | * to be already requested, so we don't need to bother the | ||
1339 | * drive with new requests ... | ||
1340 | * Wait for the drive become idle, but first | ||
1341 | * check for possible occurred errors --- the drive | ||
1342 | * seems to report them asynchronously */ | ||
1343 | |||
1344 | |||
1345 | border = stuffp->high_border < (border = | ||
1346 | sector + nr_sectors) | ||
1347 | ? stuffp->high_border : border; | ||
1348 | |||
1349 | stuffp->lock = current->pid; | ||
1350 | |||
1351 | do { | ||
1352 | |||
1353 | while (stuffp->busy) { | ||
1354 | |||
1355 | timeout = | ||
1356 | interruptible_sleep_on_timeout | ||
1357 | (&stuffp->busyq, 5 * HZ); | ||
1358 | |||
1359 | if (!stuffp->introk) { | ||
1360 | xtrace(XFER, | ||
1361 | "error via interrupt\n"); | ||
1362 | } else if (!timeout) { | ||
1363 | xtrace(XFER, "timeout\n"); | ||
1364 | } else if (signal_pending(current)) { | ||
1365 | xtrace(XFER, "signal\n"); | ||
1366 | } else | ||
1367 | continue; | ||
1368 | |||
1369 | stuffp->lock = 0; | ||
1370 | stuffp->busy = 0; | ||
1371 | stuffp->valid = 0; | ||
1372 | |||
1373 | wake_up_interruptible(&stuffp->lockq); | ||
1374 | xtrace(XFER, "transfer() done (-1)\n"); | ||
1375 | return -1; | ||
1376 | } | ||
1377 | |||
1378 | /* check if we need to set the busy flag (as we | ||
1379 | * expect an interrupt */ | ||
1380 | stuffp->busy = (3 == (stuffp->pending & 3)); | ||
1381 | |||
1382 | /* Test if it's the first sector of a block, | ||
1383 | * there we have to skip some bytes as we read raw data */ | ||
1384 | if (stuffp->xa && (0 == (stuffp->pending & 3))) { | ||
1385 | const int HEAD = | ||
1386 | CD_FRAMESIZE_RAW - CD_XA_TAIL - | ||
1387 | CD_FRAMESIZE; | ||
1388 | insb(stuffp->rreg_data, p, HEAD); | ||
1389 | } | ||
1390 | |||
1391 | /* now actually read the data */ | ||
1392 | insb(stuffp->rreg_data, p, 512); | ||
1393 | |||
1394 | /* test if it's the last sector of a block, | ||
1395 | * if so, we have to handle XA special */ | ||
1396 | if ((3 == (stuffp->pending & 3)) && stuffp->xa) { | ||
1397 | char dummy[CD_XA_TAIL]; | ||
1398 | insb(stuffp->rreg_data, &dummy[0], CD_XA_TAIL); | ||
1399 | } | ||
1400 | |||
1401 | if (stuffp->pending == sector) { | ||
1402 | p += 512; | ||
1403 | done++; | ||
1404 | sector++; | ||
1405 | } | ||
1406 | } while (++(stuffp->pending) < border); | ||
1407 | |||
1408 | stuffp->lock = 0; | ||
1409 | wake_up_interruptible(&stuffp->lockq); | ||
1410 | |||
1411 | } else { | ||
1412 | |||
1413 | /* The requested sector(s) is/are out of the | ||
1414 | * already requested range, so we have to bother the drive | ||
1415 | * with a new request. */ | ||
1416 | |||
1417 | static unsigned char cmd[] = { | ||
1418 | 0, | ||
1419 | 0, 0, 0, | ||
1420 | 0, 0, 0 | ||
1421 | }; | ||
1422 | |||
1423 | cmd[0] = stuffp->readcmd; | ||
1424 | |||
1425 | /* The numbers held in ->pending, ..., should be valid */ | ||
1426 | stuffp->valid = 1; | ||
1427 | stuffp->pending = sector & ~3; | ||
1428 | |||
1429 | /* do some sanity checks */ | ||
1430 | if (stuffp->pending > stuffp->lastsector) { | ||
1431 | xwarn | ||
1432 | ("transfer() sector %d from nirvana requested.\n", | ||
1433 | stuffp->pending); | ||
1434 | stuffp->status = MCDX_ST_EOM; | ||
1435 | stuffp->valid = 0; | ||
1436 | xtrace(XFER, "transfer() done (-1)\n"); | ||
1437 | return -1; | ||
1438 | } | ||
1439 | |||
1440 | if ((stuffp->low_border = stuffp->pending + DIRECT_SIZE) | ||
1441 | > stuffp->lastsector + 1) { | ||
1442 | xtrace(XFER, "cut low_border\n"); | ||
1443 | stuffp->low_border = stuffp->lastsector + 1; | ||
1444 | } | ||
1445 | if ((stuffp->high_border = stuffp->pending + REQUEST_SIZE) | ||
1446 | > stuffp->lastsector + 1) { | ||
1447 | xtrace(XFER, "cut high_border\n"); | ||
1448 | stuffp->high_border = stuffp->lastsector + 1; | ||
1449 | } | ||
1450 | |||
1451 | { /* Convert the sector to be requested to MSF format */ | ||
1452 | struct cdrom_msf0 pending; | ||
1453 | log2msf(stuffp->pending / 4, &pending); | ||
1454 | cmd[1] = pending.minute; | ||
1455 | cmd[2] = pending.second; | ||
1456 | cmd[3] = pending.frame; | ||
1457 | } | ||
1458 | |||
1459 | cmd[6] = | ||
1460 | (unsigned | ||
1461 | char) ((stuffp->high_border - stuffp->pending) / 4); | ||
1462 | xtrace(XFER, "[%2d]\n", cmd[6]); | ||
1463 | |||
1464 | stuffp->busy = 1; | ||
1465 | /* Now really issue the request command */ | ||
1466 | outsb(stuffp->wreg_data, cmd, sizeof cmd); | ||
1467 | |||
1468 | } | ||
1469 | #ifdef AK2 | ||
1470 | if (stuffp->int_err) { | ||
1471 | stuffp->valid = 0; | ||
1472 | stuffp->int_err = 0; | ||
1473 | return -1; | ||
1474 | } | ||
1475 | #endif /* AK2 */ | ||
1476 | |||
1477 | stuffp->low_border = (stuffp->low_border += | ||
1478 | done) < | ||
1479 | stuffp->high_border ? stuffp->low_border : stuffp->high_border; | ||
1480 | |||
1481 | return done; | ||
1482 | } | ||
1483 | |||
1484 | |||
1485 | /* Access to elements of the mcdx_drive_map members */ | ||
1486 | |||
1487 | static unsigned port(int *ip) | ||
1488 | { | ||
1489 | return ip[0]; | ||
1490 | } | ||
1491 | static int irq(int *ip) | ||
1492 | { | ||
1493 | return ip[1]; | ||
1494 | } | ||
1495 | |||
1496 | /* Misc number converters */ | ||
1497 | |||
1498 | static unsigned int bcd2uint(unsigned char c) | ||
1499 | { | ||
1500 | return (c >> 4) * 10 + (c & 0x0f); | ||
1501 | } | ||
1502 | |||
1503 | static unsigned int uint2bcd(unsigned int ival) | ||
1504 | { | ||
1505 | return ((ival / 10) << 4) | (ival % 10); | ||
1506 | } | ||
1507 | |||
1508 | static void log2msf(unsigned int l, struct cdrom_msf0 *pmsf) | ||
1509 | { | ||
1510 | l += CD_MSF_OFFSET; | ||
1511 | pmsf->minute = uint2bcd(l / 4500), l %= 4500; | ||
1512 | pmsf->second = uint2bcd(l / 75); | ||
1513 | pmsf->frame = uint2bcd(l % 75); | ||
1514 | } | ||
1515 | |||
1516 | static unsigned int msf2log(const struct cdrom_msf0 *pmsf) | ||
1517 | { | ||
1518 | return bcd2uint(pmsf->frame) | ||
1519 | + bcd2uint(pmsf->second) * 75 | ||
1520 | + bcd2uint(pmsf->minute) * 4500 - CD_MSF_OFFSET; | ||
1521 | } | ||
1522 | |||
1523 | int mcdx_readtoc(struct s_drive_stuff *stuffp) | ||
1524 | /* Read the toc entries from the CD, | ||
1525 | * Return: -1 on failure, else 0 */ | ||
1526 | { | ||
1527 | |||
1528 | if (stuffp->toc) { | ||
1529 | xtrace(READTOC, "ioctl() toc already read\n"); | ||
1530 | return 0; | ||
1531 | } | ||
1532 | |||
1533 | xtrace(READTOC, "ioctl() readtoc for %d tracks\n", | ||
1534 | stuffp->di.n_last - stuffp->di.n_first + 1); | ||
1535 | |||
1536 | if (-1 == mcdx_hold(stuffp, 1)) | ||
1537 | return -1; | ||
1538 | |||
1539 | xtrace(READTOC, "ioctl() tocmode\n"); | ||
1540 | if (-1 == mcdx_setdrivemode(stuffp, TOC, 1)) | ||
1541 | return -EIO; | ||
1542 | |||
1543 | /* all seems to be ok so far ... malloc */ | ||
1544 | { | ||
1545 | int size; | ||
1546 | size = | ||
1547 | sizeof(struct s_subqcode) * (stuffp->di.n_last - | ||
1548 | stuffp->di.n_first + 2); | ||
1549 | |||
1550 | xtrace(MALLOC, "ioctl() malloc %d bytes\n", size); | ||
1551 | stuffp->toc = kmalloc(size, GFP_KERNEL); | ||
1552 | if (!stuffp->toc) { | ||
1553 | xwarn("Cannot malloc %d bytes for toc\n", size); | ||
1554 | mcdx_setdrivemode(stuffp, DATA, 1); | ||
1555 | return -EIO; | ||
1556 | } | ||
1557 | } | ||
1558 | |||
1559 | /* now read actually the index */ | ||
1560 | { | ||
1561 | int trk; | ||
1562 | int retries; | ||
1563 | |||
1564 | for (trk = 0; | ||
1565 | trk < (stuffp->di.n_last - stuffp->di.n_first + 1); | ||
1566 | trk++) | ||
1567 | stuffp->toc[trk].index = 0; | ||
1568 | |||
1569 | for (retries = 300; retries; retries--) { /* why 300? */ | ||
1570 | struct s_subqcode q; | ||
1571 | unsigned int idx; | ||
1572 | |||
1573 | if (-1 == mcdx_requestsubqcode(stuffp, &q, 1)) { | ||
1574 | mcdx_setdrivemode(stuffp, DATA, 1); | ||
1575 | return -EIO; | ||
1576 | } | ||
1577 | |||
1578 | idx = bcd2uint(q.index); | ||
1579 | |||
1580 | if ((idx > 0) | ||
1581 | && (idx <= stuffp->di.n_last) | ||
1582 | && (q.tno == 0) | ||
1583 | && (stuffp->toc[idx - stuffp->di.n_first]. | ||
1584 | index == 0)) { | ||
1585 | stuffp->toc[idx - stuffp->di.n_first] = q; | ||
1586 | xtrace(READTOC, | ||
1587 | "ioctl() toc idx %d (trk %d)\n", | ||
1588 | idx, trk); | ||
1589 | trk--; | ||
1590 | } | ||
1591 | if (trk == 0) | ||
1592 | break; | ||
1593 | } | ||
1594 | memset(&stuffp-> | ||
1595 | toc[stuffp->di.n_last - stuffp->di.n_first + 1], 0, | ||
1596 | sizeof(stuffp->toc[0])); | ||
1597 | stuffp->toc[stuffp->di.n_last - stuffp->di.n_first + | ||
1598 | 1].dt = stuffp->di.msf_leadout; | ||
1599 | } | ||
1600 | |||
1601 | /* unset toc mode */ | ||
1602 | xtrace(READTOC, "ioctl() undo toc mode\n"); | ||
1603 | if (-1 == mcdx_setdrivemode(stuffp, DATA, 2)) | ||
1604 | return -EIO; | ||
1605 | |||
1606 | #if MCDX_DEBUG && READTOC | ||
1607 | { | ||
1608 | int trk; | ||
1609 | for (trk = 0; | ||
1610 | trk < (stuffp->di.n_last - stuffp->di.n_first + 2); | ||
1611 | trk++) | ||
1612 | xtrace(READTOC, "ioctl() %d readtoc %02x %02x %02x" | ||
1613 | " %02x:%02x.%02x %02x:%02x.%02x\n", | ||
1614 | trk + stuffp->di.n_first, | ||
1615 | stuffp->toc[trk].control, | ||
1616 | stuffp->toc[trk].tno, | ||
1617 | stuffp->toc[trk].index, | ||
1618 | stuffp->toc[trk].tt.minute, | ||
1619 | stuffp->toc[trk].tt.second, | ||
1620 | stuffp->toc[trk].tt.frame, | ||
1621 | stuffp->toc[trk].dt.minute, | ||
1622 | stuffp->toc[trk].dt.second, | ||
1623 | stuffp->toc[trk].dt.frame); | ||
1624 | } | ||
1625 | #endif | ||
1626 | |||
1627 | return 0; | ||
1628 | } | ||
1629 | |||
1630 | static int | ||
1631 | mcdx_playmsf(struct s_drive_stuff *stuffp, const struct cdrom_msf *msf) | ||
1632 | { | ||
1633 | unsigned char cmd[7] = { | ||
1634 | 0, 0, 0, 0, 0, 0, 0 | ||
1635 | }; | ||
1636 | |||
1637 | if (!stuffp->readcmd) { | ||
1638 | xinfo("Can't play from missing disk.\n"); | ||
1639 | return -1; | ||
1640 | } | ||
1641 | |||
1642 | cmd[0] = stuffp->playcmd; | ||
1643 | |||
1644 | cmd[1] = msf->cdmsf_min0; | ||
1645 | cmd[2] = msf->cdmsf_sec0; | ||
1646 | cmd[3] = msf->cdmsf_frame0; | ||
1647 | cmd[4] = msf->cdmsf_min1; | ||
1648 | cmd[5] = msf->cdmsf_sec1; | ||
1649 | cmd[6] = msf->cdmsf_frame1; | ||
1650 | |||
1651 | xtrace(PLAYMSF, "ioctl(): play %x " | ||
1652 | "%02x:%02x:%02x -- %02x:%02x:%02x\n", | ||
1653 | cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5], cmd[6]); | ||
1654 | |||
1655 | outsb(stuffp->wreg_data, cmd, sizeof cmd); | ||
1656 | |||
1657 | if (-1 == mcdx_getval(stuffp, 3 * HZ, 0, NULL)) { | ||
1658 | xwarn("playmsf() timeout\n"); | ||
1659 | return -1; | ||
1660 | } | ||
1661 | |||
1662 | stuffp->audiostatus = CDROM_AUDIO_PLAY; | ||
1663 | return 0; | ||
1664 | } | ||
1665 | |||
1666 | static int | ||
1667 | mcdx_playtrk(struct s_drive_stuff *stuffp, const struct cdrom_ti *ti) | ||
1668 | { | ||
1669 | struct s_subqcode *p; | ||
1670 | struct cdrom_msf msf; | ||
1671 | |||
1672 | if (-1 == mcdx_readtoc(stuffp)) | ||
1673 | return -1; | ||
1674 | |||
1675 | if (ti) | ||
1676 | p = &stuffp->toc[ti->cdti_trk0 - stuffp->di.n_first]; | ||
1677 | else | ||
1678 | p = &stuffp->start; | ||
1679 | |||
1680 | msf.cdmsf_min0 = p->dt.minute; | ||
1681 | msf.cdmsf_sec0 = p->dt.second; | ||
1682 | msf.cdmsf_frame0 = p->dt.frame; | ||
1683 | |||
1684 | if (ti) { | ||
1685 | p = &stuffp->toc[ti->cdti_trk1 - stuffp->di.n_first + 1]; | ||
1686 | stuffp->stop = *p; | ||
1687 | } else | ||
1688 | p = &stuffp->stop; | ||
1689 | |||
1690 | msf.cdmsf_min1 = p->dt.minute; | ||
1691 | msf.cdmsf_sec1 = p->dt.second; | ||
1692 | msf.cdmsf_frame1 = p->dt.frame; | ||
1693 | |||
1694 | return mcdx_playmsf(stuffp, &msf); | ||
1695 | } | ||
1696 | |||
1697 | |||
1698 | /* Drive functions ************************************************/ | ||
1699 | |||
1700 | static int mcdx_tray_move(struct cdrom_device_info *cdi, int position) | ||
1701 | { | ||
1702 | struct s_drive_stuff *stuffp = cdi->handle; | ||
1703 | |||
1704 | if (!stuffp->present) | ||
1705 | return -ENXIO; | ||
1706 | if (!(stuffp->present & DOOR)) | ||
1707 | return -ENOSYS; | ||
1708 | |||
1709 | if (position) /* 1: eject */ | ||
1710 | return mcdx_talk(stuffp, "\xf6", 1, NULL, 1, 5 * HZ, 3); | ||
1711 | else /* 0: close */ | ||
1712 | return mcdx_talk(stuffp, "\xf8", 1, NULL, 1, 5 * HZ, 3); | ||
1713 | return 1; | ||
1714 | } | ||
1715 | |||
1716 | static int mcdx_stop(struct s_drive_stuff *stuffp, int tries) | ||
1717 | { | ||
1718 | return mcdx_talk(stuffp, "\xf0", 1, NULL, 1, 2 * HZ, tries); | ||
1719 | } | ||
1720 | |||
1721 | static int mcdx_hold(struct s_drive_stuff *stuffp, int tries) | ||
1722 | { | ||
1723 | return mcdx_talk(stuffp, "\x70", 1, NULL, 1, 2 * HZ, tries); | ||
1724 | } | ||
1725 | |||
1726 | static int mcdx_requestsubqcode(struct s_drive_stuff *stuffp, | ||
1727 | struct s_subqcode *sub, int tries) | ||
1728 | { | ||
1729 | char buf[11]; | ||
1730 | int ans; | ||
1731 | |||
1732 | if (-1 == (ans = mcdx_talk(stuffp, "\x20", 1, buf, sizeof(buf), | ||
1733 | 2 * HZ, tries))) | ||
1734 | return -1; | ||
1735 | sub->control = buf[1]; | ||
1736 | sub->tno = buf[2]; | ||
1737 | sub->index = buf[3]; | ||
1738 | sub->tt.minute = buf[4]; | ||
1739 | sub->tt.second = buf[5]; | ||
1740 | sub->tt.frame = buf[6]; | ||
1741 | sub->dt.minute = buf[8]; | ||
1742 | sub->dt.second = buf[9]; | ||
1743 | sub->dt.frame = buf[10]; | ||
1744 | |||
1745 | return ans; | ||
1746 | } | ||
1747 | |||
1748 | static int mcdx_requestmultidiskinfo(struct s_drive_stuff *stuffp, | ||
1749 | struct s_multi *multi, int tries) | ||
1750 | { | ||
1751 | char buf[5]; | ||
1752 | int ans; | ||
1753 | |||
1754 | if (stuffp->present & MULTI) { | ||
1755 | ans = | ||
1756 | mcdx_talk(stuffp, "\x11", 1, buf, sizeof(buf), 2 * HZ, | ||
1757 | tries); | ||
1758 | multi->multi = buf[1]; | ||
1759 | multi->msf_last.minute = buf[2]; | ||
1760 | multi->msf_last.second = buf[3]; | ||
1761 | multi->msf_last.frame = buf[4]; | ||
1762 | return ans; | ||
1763 | } else { | ||
1764 | multi->multi = 0; | ||
1765 | return 0; | ||
1766 | } | ||
1767 | } | ||
1768 | |||
1769 | static int mcdx_requesttocdata(struct s_drive_stuff *stuffp, struct s_diskinfo *info, | ||
1770 | int tries) | ||
1771 | { | ||
1772 | char buf[9]; | ||
1773 | int ans; | ||
1774 | ans = | ||
1775 | mcdx_talk(stuffp, "\x10", 1, buf, sizeof(buf), 2 * HZ, tries); | ||
1776 | if (ans == -1) { | ||
1777 | info->n_first = 0; | ||
1778 | info->n_last = 0; | ||
1779 | } else { | ||
1780 | info->n_first = bcd2uint(buf[1]); | ||
1781 | info->n_last = bcd2uint(buf[2]); | ||
1782 | info->msf_leadout.minute = buf[3]; | ||
1783 | info->msf_leadout.second = buf[4]; | ||
1784 | info->msf_leadout.frame = buf[5]; | ||
1785 | info->msf_first.minute = buf[6]; | ||
1786 | info->msf_first.second = buf[7]; | ||
1787 | info->msf_first.frame = buf[8]; | ||
1788 | } | ||
1789 | return ans; | ||
1790 | } | ||
1791 | |||
1792 | static int mcdx_setdrivemode(struct s_drive_stuff *stuffp, enum drivemodes mode, | ||
1793 | int tries) | ||
1794 | { | ||
1795 | char cmd[2]; | ||
1796 | int ans; | ||
1797 | |||
1798 | xtrace(HW, "setdrivemode() %d\n", mode); | ||
1799 | |||
1800 | if (-1 == (ans = mcdx_talk(stuffp, "\xc2", 1, cmd, sizeof(cmd), 5 * HZ, tries))) | ||
1801 | return -1; | ||
1802 | |||
1803 | switch (mode) { | ||
1804 | case TOC: | ||
1805 | cmd[1] |= 0x04; | ||
1806 | break; | ||
1807 | case DATA: | ||
1808 | cmd[1] &= ~0x04; | ||
1809 | break; | ||
1810 | case RAW: | ||
1811 | cmd[1] |= 0x40; | ||
1812 | break; | ||
1813 | case COOKED: | ||
1814 | cmd[1] &= ~0x40; | ||
1815 | break; | ||
1816 | default: | ||
1817 | break; | ||
1818 | } | ||
1819 | cmd[0] = 0x50; | ||
1820 | return mcdx_talk(stuffp, cmd, 2, NULL, 1, 5 * HZ, tries); | ||
1821 | } | ||
1822 | |||
1823 | static int mcdx_setdatamode(struct s_drive_stuff *stuffp, enum datamodes mode, | ||
1824 | int tries) | ||
1825 | { | ||
1826 | unsigned char cmd[2] = { 0xa0 }; | ||
1827 | xtrace(HW, "setdatamode() %d\n", mode); | ||
1828 | switch (mode) { | ||
1829 | case MODE0: | ||
1830 | cmd[1] = 0x00; | ||
1831 | break; | ||
1832 | case MODE1: | ||
1833 | cmd[1] = 0x01; | ||
1834 | break; | ||
1835 | case MODE2: | ||
1836 | cmd[1] = 0x02; | ||
1837 | break; | ||
1838 | default: | ||
1839 | return -EINVAL; | ||
1840 | } | ||
1841 | return mcdx_talk(stuffp, cmd, 2, NULL, 1, 5 * HZ, tries); | ||
1842 | } | ||
1843 | |||
1844 | static int mcdx_config(struct s_drive_stuff *stuffp, int tries) | ||
1845 | { | ||
1846 | char cmd[4]; | ||
1847 | |||
1848 | xtrace(HW, "config()\n"); | ||
1849 | |||
1850 | cmd[0] = 0x90; | ||
1851 | |||
1852 | cmd[1] = 0x10; /* irq enable */ | ||
1853 | cmd[2] = 0x05; /* pre, err irq enable */ | ||
1854 | |||
1855 | if (-1 == mcdx_talk(stuffp, cmd, 3, NULL, 1, 1 * HZ, tries)) | ||
1856 | return -1; | ||
1857 | |||
1858 | cmd[1] = 0x02; /* dma select */ | ||
1859 | cmd[2] = 0x00; /* no dma */ | ||
1860 | |||
1861 | return mcdx_talk(stuffp, cmd, 3, NULL, 1, 1 * HZ, tries); | ||
1862 | } | ||
1863 | |||
1864 | static int mcdx_requestversion(struct s_drive_stuff *stuffp, struct s_version *ver, | ||
1865 | int tries) | ||
1866 | { | ||
1867 | char buf[3]; | ||
1868 | int ans; | ||
1869 | |||
1870 | if (-1 == (ans = mcdx_talk(stuffp, "\xdc", | ||
1871 | 1, buf, sizeof(buf), 2 * HZ, tries))) | ||
1872 | return ans; | ||
1873 | |||
1874 | ver->code = buf[1]; | ||
1875 | ver->ver = buf[2]; | ||
1876 | |||
1877 | return ans; | ||
1878 | } | ||
1879 | |||
1880 | static int mcdx_reset(struct s_drive_stuff *stuffp, enum resetmodes mode, int tries) | ||
1881 | { | ||
1882 | if (mode == HARD) { | ||
1883 | outb(0, stuffp->wreg_chn); /* no dma, no irq -> hardware */ | ||
1884 | outb(0, stuffp->wreg_reset); /* hw reset */ | ||
1885 | return 0; | ||
1886 | } else | ||
1887 | return mcdx_talk(stuffp, "\x60", 1, NULL, 1, 5 * HZ, tries); | ||
1888 | } | ||
1889 | |||
1890 | static int mcdx_lockdoor(struct cdrom_device_info *cdi, int lock) | ||
1891 | { | ||
1892 | struct s_drive_stuff *stuffp = cdi->handle; | ||
1893 | char cmd[2] = { 0xfe }; | ||
1894 | |||
1895 | if (!(stuffp->present & DOOR)) | ||
1896 | return -ENOSYS; | ||
1897 | if (stuffp->present & DOOR) { | ||
1898 | cmd[1] = lock ? 0x01 : 0x00; | ||
1899 | return mcdx_talk(stuffp, cmd, sizeof(cmd), NULL, 1, 5 * HZ, 3); | ||
1900 | } else | ||
1901 | return 0; | ||
1902 | } | ||
1903 | |||
1904 | static int mcdx_getstatus(struct s_drive_stuff *stuffp, int tries) | ||
1905 | { | ||
1906 | return mcdx_talk(stuffp, "\x40", 1, NULL, 1, 5 * HZ, tries); | ||
1907 | } | ||
1908 | |||
1909 | static int | ||
1910 | mcdx_getval(struct s_drive_stuff *stuffp, int to, int delay, char *buf) | ||
1911 | { | ||
1912 | unsigned long timeout = to + jiffies; | ||
1913 | char c; | ||
1914 | |||
1915 | if (!buf) | ||
1916 | buf = &c; | ||
1917 | |||
1918 | while (inb(stuffp->rreg_status) & MCDX_RBIT_STEN) { | ||
1919 | if (time_after(jiffies, timeout)) | ||
1920 | return -1; | ||
1921 | mcdx_delay(stuffp, delay); | ||
1922 | } | ||
1923 | |||
1924 | *buf = (unsigned char) inb(stuffp->rreg_data) & 0xff; | ||
1925 | |||
1926 | return 0; | ||
1927 | } | ||
1928 | |||
1929 | static int mcdx_setattentuator(struct s_drive_stuff *stuffp, | ||
1930 | struct cdrom_volctrl *vol, int tries) | ||
1931 | { | ||
1932 | char cmd[5]; | ||
1933 | cmd[0] = 0xae; | ||
1934 | cmd[1] = vol->channel0; | ||
1935 | cmd[2] = 0; | ||
1936 | cmd[3] = vol->channel1; | ||
1937 | cmd[4] = 0; | ||
1938 | |||
1939 | return mcdx_talk(stuffp, cmd, sizeof(cmd), NULL, 5, 200, tries); | ||
1940 | } | ||
1941 | |||
1942 | MODULE_LICENSE("GPL"); | ||
1943 | MODULE_ALIAS_BLOCKDEV_MAJOR(MITSUMI_X_CDROM_MAJOR); | ||
diff --git a/drivers/cdrom/mcdx.h b/drivers/cdrom/mcdx.h deleted file mode 100644 index 83c364a74dc4..000000000000 --- a/drivers/cdrom/mcdx.h +++ /dev/null | |||
@@ -1,185 +0,0 @@ | |||
1 | /* | ||
2 | * Definitions for the Mitsumi CDROM interface | ||
3 | * Copyright (C) 1995 1996 Heiko Schlittermann <heiko@lotte.sax.de> | ||
4 | * VERSION: @VERSION@ | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2, or (at your option) | ||
9 | * any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; see the file COPYING. If not, write to | ||
18 | * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | * | ||
20 | * Thanks to | ||
21 | * The Linux Community at all and ... | ||
22 | * Martin Harris (he wrote the first Mitsumi Driver) | ||
23 | * Eberhard Moenkeberg (he gave me much support and the initial kick) | ||
24 | * Bernd Huebner, Ruediger Helsch (Unifix-Software Gmbh, they | ||
25 | * improved the original driver) | ||
26 | * Jon Tombs, Bjorn Ekwall (module support) | ||
27 | * Daniel v. Mosnenck (he sent me the Technical and Programming Reference) | ||
28 | * Gerd Knorr (he lent me his PhotoCD) | ||
29 | * Nils Faerber and Roger E. Wolff (extensively tested the LU portion) | ||
30 | * Andreas Kies (testing the mysterious hang up's) | ||
31 | * ... somebody forgotten? | ||
32 | * Marcin Dalecki | ||
33 | * | ||
34 | */ | ||
35 | |||
36 | /* | ||
37 | * The following lines are for user configuration | ||
38 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
39 | * | ||
40 | * {0|1} -- 1 if you want the driver detect your drive, may crash and | ||
41 | * needs a long time to seek. The higher the address the longer the | ||
42 | * seek. | ||
43 | * | ||
44 | * WARNING: AUTOPROBE doesn't work. | ||
45 | */ | ||
46 | #define MCDX_AUTOPROBE 0 | ||
47 | |||
48 | /* | ||
49 | * Drive specific settings according to the jumpers on the controller | ||
50 | * board(s). | ||
51 | * o MCDX_NDRIVES : number of used entries of the following table | ||
52 | * o MCDX_DRIVEMAP : table of {i/o base, irq} per controller | ||
53 | * | ||
54 | * NOTE: I didn't get a drive at irq 9(2) working. Not even alone. | ||
55 | */ | ||
56 | #if MCDX_AUTOPROBE == 0 | ||
57 | #define MCDX_NDRIVES 1 | ||
58 | #define MCDX_DRIVEMAP { \ | ||
59 | {0x300, 11}, \ | ||
60 | {0x304, 05}, \ | ||
61 | {0x000, 00}, \ | ||
62 | {0x000, 00}, \ | ||
63 | {0x000, 00}, \ | ||
64 | } | ||
65 | #else | ||
66 | #error Autoprobing is not implemented yet. | ||
67 | #endif | ||
68 | |||
69 | #ifndef MCDX_QUIET | ||
70 | #define MCDX_QUIET 1 | ||
71 | #endif | ||
72 | |||
73 | #ifndef MCDX_DEBUG | ||
74 | #define MCDX_DEBUG 0 | ||
75 | #endif | ||
76 | |||
77 | /* *** make the following line uncommented, if you're sure, | ||
78 | * *** all configuration is done */ | ||
79 | /* #define I_WAS_HERE */ | ||
80 | |||
81 | /* The name of the device */ | ||
82 | #define MCDX "mcdx" | ||
83 | |||
84 | /* Flags for DEBUGGING */ | ||
85 | #define INIT 0 | ||
86 | #define MALLOC 0 | ||
87 | #define IOCTL 0 | ||
88 | #define PLAYTRK 0 | ||
89 | #define SUBCHNL 0 | ||
90 | #define TOCHDR 0 | ||
91 | #define MS 0 | ||
92 | #define PLAYMSF 0 | ||
93 | #define READTOC 0 | ||
94 | #define OPENCLOSE 0 | ||
95 | #define HW 0 | ||
96 | #define TALK 0 | ||
97 | #define IRQ 0 | ||
98 | #define XFER 0 | ||
99 | #define REQUEST 0 | ||
100 | #define SLEEP 0 | ||
101 | |||
102 | /* The following addresses are taken from the Mitsumi Reference | ||
103 | * and describe the possible i/o range for the controller. | ||
104 | */ | ||
105 | #define MCDX_IO_BEGIN ((char*) 0x300) /* first base of i/o addr */ | ||
106 | #define MCDX_IO_END ((char*) 0x3fc) /* last base of i/o addr */ | ||
107 | |||
108 | /* Per controller 4 bytes i/o are needed. */ | ||
109 | #define MCDX_IO_SIZE 4 | ||
110 | |||
111 | /* | ||
112 | * Bits | ||
113 | */ | ||
114 | |||
115 | /* The status byte, returned from every command, set if | ||
116 | * the description is true */ | ||
117 | #define MCDX_RBIT_OPEN 0x80 /* door is open */ | ||
118 | #define MCDX_RBIT_DISKSET 0x40 /* disk set (recognised) */ | ||
119 | #define MCDX_RBIT_CHANGED 0x20 /* disk was changed */ | ||
120 | #define MCDX_RBIT_CHECK 0x10 /* disk rotates, servo is on */ | ||
121 | #define MCDX_RBIT_AUDIOTR 0x08 /* current track is audio */ | ||
122 | #define MCDX_RBIT_RDERR 0x04 /* read error, refer SENSE KEY */ | ||
123 | #define MCDX_RBIT_AUDIOBS 0x02 /* currently playing audio */ | ||
124 | #define MCDX_RBIT_CMDERR 0x01 /* command, param or format error */ | ||
125 | |||
126 | /* The I/O Register holding the h/w status of the drive, | ||
127 | * can be read at i/o base + 1 */ | ||
128 | #define MCDX_RBIT_DOOR 0x10 /* door is open */ | ||
129 | #define MCDX_RBIT_STEN 0x04 /* if 0, i/o base contains drive status */ | ||
130 | #define MCDX_RBIT_DTEN 0x02 /* if 0, i/o base contains data */ | ||
131 | |||
132 | /* | ||
133 | * The commands. | ||
134 | */ | ||
135 | |||
136 | #define OPCODE 1 /* offset of opcode */ | ||
137 | #define MCDX_CMD_REQUEST_TOC 1, 0x10 | ||
138 | #define MCDX_CMD_REQUEST_STATUS 1, 0x40 | ||
139 | #define MCDX_CMD_RESET 1, 0x60 | ||
140 | #define MCDX_CMD_REQUEST_DRIVE_MODE 1, 0xc2 | ||
141 | #define MCDX_CMD_SET_INTERLEAVE 2, 0xc8, 0 | ||
142 | #define MCDX_CMD_DATAMODE_SET 2, 0xa0, 0 | ||
143 | #define MCDX_DATAMODE1 0x01 | ||
144 | #define MCDX_DATAMODE2 0x02 | ||
145 | #define MCDX_CMD_LOCK_DOOR 2, 0xfe, 0 | ||
146 | |||
147 | #define READ_AHEAD 4 /* 8 Sectors (4K) */ | ||
148 | |||
149 | /* Useful macros */ | ||
150 | #define e_door(x) ((x) & MCDX_RBIT_OPEN) | ||
151 | #define e_check(x) (~(x) & MCDX_RBIT_CHECK) | ||
152 | #define e_notset(x) (~(x) & MCDX_RBIT_DISKSET) | ||
153 | #define e_changed(x) ((x) & MCDX_RBIT_CHANGED) | ||
154 | #define e_audio(x) ((x) & MCDX_RBIT_AUDIOTR) | ||
155 | #define e_audiobusy(x) ((x) & MCDX_RBIT_AUDIOBS) | ||
156 | #define e_cmderr(x) ((x) & MCDX_RBIT_CMDERR) | ||
157 | #define e_readerr(x) ((x) & MCDX_RBIT_RDERR) | ||
158 | |||
159 | /** no drive specific */ | ||
160 | #define MCDX_CDBLK 2048 /* 2048 cooked data each blk */ | ||
161 | |||
162 | #define MCDX_DATA_TIMEOUT (HZ/10) /* 0.1 second */ | ||
163 | |||
164 | /* | ||
165 | * Access to the msf array | ||
166 | */ | ||
167 | #define MSF_MIN 0 /* minute */ | ||
168 | #define MSF_SEC 1 /* second */ | ||
169 | #define MSF_FRM 2 /* frame */ | ||
170 | |||
171 | /* | ||
172 | * Errors | ||
173 | */ | ||
174 | #define MCDX_E 1 /* unspec error */ | ||
175 | #define MCDX_ST_EOM 0x0100 /* end of media */ | ||
176 | #define MCDX_ST_DRV 0x00ff /* mask to query the drive status */ | ||
177 | |||
178 | #ifndef I_WAS_HERE | ||
179 | #ifndef MODULE | ||
180 | #warning You have not edited mcdx.h | ||
181 | #warning Perhaps irq and i/o settings are wrong. | ||
182 | #endif | ||
183 | #endif | ||
184 | |||
185 | /* ex:set ts=4 sw=4: */ | ||
diff --git a/drivers/cdrom/optcd.c b/drivers/cdrom/optcd.c deleted file mode 100644 index efd619c0fe10..000000000000 --- a/drivers/cdrom/optcd.c +++ /dev/null | |||
@@ -1,2105 +0,0 @@ | |||
1 | /* linux/drivers/cdrom/optcd.c - Optics Storage 8000 AT CDROM driver | ||
2 | $Id: optcd.c,v 1.11 1997/01/26 07:13:00 davem Exp $ | ||
3 | |||
4 | Copyright (C) 1995 Leo Spiekman (spiekman@dutette.et.tudelft.nl) | ||
5 | |||
6 | |||
7 | Based on Aztech CD268 CDROM driver by Werner Zimmermann and preworks | ||
8 | by Eberhard Moenkeberg (emoenke@gwdg.de). | ||
9 | |||
10 | This program is free software; you can redistribute it and/or modify | ||
11 | it under the terms of the GNU General Public License as published by | ||
12 | the Free Software Foundation; either version 2, or (at your option) | ||
13 | any later version. | ||
14 | |||
15 | This program is distributed in the hope that it will be useful, | ||
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | GNU General Public License for more details. | ||
19 | |||
20 | You should have received a copy of the GNU General Public License | ||
21 | along with this program; if not, write to the Free Software | ||
22 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | */ | ||
24 | |||
25 | /* Revision history | ||
26 | |||
27 | |||
28 | 14-5-95 v0.0 Plays sound tracks. No reading of data CDs yet. | ||
29 | Detection of disk change doesn't work. | ||
30 | 21-5-95 v0.1 First ALPHA version. CD can be mounted. The | ||
31 | device major nr is borrowed from the Aztech | ||
32 | driver. Speed is around 240 kb/s, as measured | ||
33 | with "time dd if=/dev/cdrom of=/dev/null \ | ||
34 | bs=2048 count=4096". | ||
35 | 24-6-95 v0.2 Reworked the #defines for the command codes | ||
36 | and the like, as well as the structure of | ||
37 | the hardware communication protocol, to | ||
38 | reflect the "official" documentation, kindly | ||
39 | supplied by C.K. Tan, Optics Storage Pte. Ltd. | ||
40 | Also tidied up the state machine somewhat. | ||
41 | 28-6-95 v0.3 Removed the ISP-16 interface code, as this | ||
42 | should go into its own driver. The driver now | ||
43 | has its own major nr. | ||
44 | Disk change detection now seems to work, too. | ||
45 | This version became part of the standard | ||
46 | kernel as of version 1.3.7 | ||
47 | 24-9-95 v0.4 Re-inserted ISP-16 interface code which I | ||
48 | copied from sjcd.c, with a few changes. | ||
49 | Updated README.optcd. Submitted for | ||
50 | inclusion in 1.3.21 | ||
51 | 29-9-95 v0.4a Fixed bug that prevented compilation as module | ||
52 | 25-10-95 v0.5 Started multisession code. Implementation | ||
53 | copied from Werner Zimmermann, who copied it | ||
54 | from Heiko Schlittermann's mcdx. | ||
55 | 17-1-96 v0.6 Multisession works; some cleanup too. | ||
56 | 18-4-96 v0.7 Increased some timing constants; | ||
57 | thanks to Luke McFarlane. Also tidied up some | ||
58 | printk behaviour. ISP16 initialization | ||
59 | is now handled by a separate driver. | ||
60 | |||
61 | 09-11-99 Make kernel-parameter implementation work with 2.3.x | ||
62 | Removed init_module & cleanup_module in favor of | ||
63 | module_init & module_exit. | ||
64 | Torben Mathiasen <tmm@image.dk> | ||
65 | */ | ||
66 | |||
67 | /* Includes */ | ||
68 | |||
69 | |||
70 | #include <linux/module.h> | ||
71 | #include <linux/mm.h> | ||
72 | #include <linux/ioport.h> | ||
73 | #include <linux/init.h> | ||
74 | |||
75 | #include <asm/io.h> | ||
76 | #include <linux/blkdev.h> | ||
77 | |||
78 | #include <linux/cdrom.h> | ||
79 | #include "optcd.h" | ||
80 | |||
81 | #include <asm/uaccess.h> | ||
82 | |||
83 | #define MAJOR_NR OPTICS_CDROM_MAJOR | ||
84 | #define QUEUE (opt_queue) | ||
85 | #define CURRENT elv_next_request(opt_queue) | ||
86 | |||
87 | |||
88 | /* Debug support */ | ||
89 | |||
90 | |||
91 | /* Don't forget to add new debug flags here. */ | ||
92 | #if DEBUG_DRIVE_IF | DEBUG_VFS | DEBUG_CONV | DEBUG_TOC | \ | ||
93 | DEBUG_BUFFERS | DEBUG_REQUEST | DEBUG_STATE | DEBUG_MULTIS | ||
94 | #define DEBUG(x) debug x | ||
95 | static void debug(int debug_this, const char* fmt, ...) | ||
96 | { | ||
97 | char s[1024]; | ||
98 | va_list args; | ||
99 | |||
100 | if (!debug_this) | ||
101 | return; | ||
102 | |||
103 | va_start(args, fmt); | ||
104 | vsnprintf(s, sizeof(s), fmt, args); | ||
105 | printk(KERN_DEBUG "optcd: %s\n", s); | ||
106 | va_end(args); | ||
107 | } | ||
108 | #else | ||
109 | #define DEBUG(x) | ||
110 | #endif | ||
111 | |||
112 | |||
113 | /* Drive hardware/firmware characteristics | ||
114 | Identifiers in accordance with Optics Storage documentation */ | ||
115 | |||
116 | |||
117 | #define optcd_port optcd /* Needed for the modutils. */ | ||
118 | static short optcd_port = OPTCD_PORTBASE; /* I/O base of drive. */ | ||
119 | module_param(optcd_port, short, 0); | ||
120 | /* Drive registers, read */ | ||
121 | #define DATA_PORT optcd_port /* Read data/status */ | ||
122 | #define STATUS_PORT optcd_port+1 /* Indicate data/status availability */ | ||
123 | |||
124 | /* Drive registers, write */ | ||
125 | #define COMIN_PORT optcd_port /* For passing command/parameter */ | ||
126 | #define RESET_PORT optcd_port+1 /* Write anything and wait 0.5 sec */ | ||
127 | #define HCON_PORT optcd_port+2 /* Host Xfer Configuration */ | ||
128 | |||
129 | |||
130 | /* Command completion/status read from DATA register */ | ||
131 | #define ST_DRVERR 0x80 | ||
132 | #define ST_DOOR_OPEN 0x40 | ||
133 | #define ST_MIXEDMODE_DISK 0x20 | ||
134 | #define ST_MODE_BITS 0x1c | ||
135 | #define ST_M_STOP 0x00 | ||
136 | #define ST_M_READ 0x04 | ||
137 | #define ST_M_AUDIO 0x04 | ||
138 | #define ST_M_PAUSE 0x08 | ||
139 | #define ST_M_INITIAL 0x0c | ||
140 | #define ST_M_ERROR 0x10 | ||
141 | #define ST_M_OTHERS 0x14 | ||
142 | #define ST_MODE2TRACK 0x02 | ||
143 | #define ST_DSK_CHG 0x01 | ||
144 | #define ST_L_LOCK 0x01 | ||
145 | #define ST_CMD_OK 0x00 | ||
146 | #define ST_OP_OK 0x01 | ||
147 | #define ST_PA_OK 0x02 | ||
148 | #define ST_OP_ERROR 0x05 | ||
149 | #define ST_PA_ERROR 0x06 | ||
150 | |||
151 | |||
152 | /* Error codes (appear as command completion code from DATA register) */ | ||
153 | /* Player related errors */ | ||
154 | #define ERR_ILLCMD 0x11 /* Illegal command to player module */ | ||
155 | #define ERR_ILLPARM 0x12 /* Illegal parameter to player module */ | ||
156 | #define ERR_SLEDGE 0x13 | ||
157 | #define ERR_FOCUS 0x14 | ||
158 | #define ERR_MOTOR 0x15 | ||
159 | #define ERR_RADIAL 0x16 | ||
160 | #define ERR_PLL 0x17 /* PLL lock error */ | ||
161 | #define ERR_SUB_TIM 0x18 /* Subcode timeout error */ | ||
162 | #define ERR_SUB_NF 0x19 /* Subcode not found error */ | ||
163 | #define ERR_TRAY 0x1a | ||
164 | #define ERR_TOC 0x1b /* Table of Contents read error */ | ||
165 | #define ERR_JUMP 0x1c | ||
166 | /* Data errors */ | ||
167 | #define ERR_MODE 0x21 | ||
168 | #define ERR_FORM 0x22 | ||
169 | #define ERR_HEADADDR 0x23 /* Header Address not found */ | ||
170 | #define ERR_CRC 0x24 | ||
171 | #define ERR_ECC 0x25 /* Uncorrectable ECC error */ | ||
172 | #define ERR_CRC_UNC 0x26 /* CRC error and uncorrectable error */ | ||
173 | #define ERR_ILLBSYNC 0x27 /* Illegal block sync error */ | ||
174 | #define ERR_VDST 0x28 /* VDST not found */ | ||
175 | /* Timeout errors */ | ||
176 | #define ERR_READ_TIM 0x31 /* Read timeout error */ | ||
177 | #define ERR_DEC_STP 0x32 /* Decoder stopped */ | ||
178 | #define ERR_DEC_TIM 0x33 /* Decoder interrupt timeout error */ | ||
179 | /* Function abort codes */ | ||
180 | #define ERR_KEY 0x41 /* Key -Detected abort */ | ||
181 | #define ERR_READ_FINISH 0x42 /* Read Finish */ | ||
182 | /* Second Byte diagnostic codes */ | ||
183 | #define ERR_NOBSYNC 0x01 /* No block sync */ | ||
184 | #define ERR_SHORTB 0x02 /* Short block */ | ||
185 | #define ERR_LONGB 0x03 /* Long block */ | ||
186 | #define ERR_SHORTDSP 0x04 /* Short DSP word */ | ||
187 | #define ERR_LONGDSP 0x05 /* Long DSP word */ | ||
188 | |||
189 | |||
190 | /* Status availability flags read from STATUS register */ | ||
191 | #define FL_EJECT 0x20 | ||
192 | #define FL_WAIT 0x10 /* active low */ | ||
193 | #define FL_EOP 0x08 /* active low */ | ||
194 | #define FL_STEN 0x04 /* Status available when low */ | ||
195 | #define FL_DTEN 0x02 /* Data available when low */ | ||
196 | #define FL_DRQ 0x01 /* active low */ | ||
197 | #define FL_RESET 0xde /* These bits are high after a reset */ | ||
198 | #define FL_STDT (FL_STEN|FL_DTEN) | ||
199 | |||
200 | |||
201 | /* Transfer mode, written to HCON register */ | ||
202 | #define HCON_DTS 0x08 | ||
203 | #define HCON_SDRQB 0x04 | ||
204 | #define HCON_LOHI 0x02 | ||
205 | #define HCON_DMA16 0x01 | ||
206 | |||
207 | |||
208 | /* Drive command set, written to COMIN register */ | ||
209 | /* Quick response commands */ | ||
210 | #define COMDRVST 0x20 /* Drive Status Read */ | ||
211 | #define COMERRST 0x21 /* Error Status Read */ | ||
212 | #define COMIOCTLISTAT 0x22 /* Status Read; reset disk changed bit */ | ||
213 | #define COMINITSINGLE 0x28 /* Initialize Single Speed */ | ||
214 | #define COMINITDOUBLE 0x29 /* Initialize Double Speed */ | ||
215 | #define COMUNLOCK 0x30 /* Unlock */ | ||
216 | #define COMLOCK 0x31 /* Lock */ | ||
217 | #define COMLOCKST 0x32 /* Lock/Unlock Status */ | ||
218 | #define COMVERSION 0x40 /* Get Firmware Revision */ | ||
219 | #define COMVOIDREADMODE 0x50 /* Void Data Read Mode */ | ||
220 | /* Read commands */ | ||
221 | #define COMFETCH 0x60 /* Prefetch Data */ | ||
222 | #define COMREAD 0x61 /* Read */ | ||
223 | #define COMREADRAW 0x62 /* Read Raw Data */ | ||
224 | #define COMREADALL 0x63 /* Read All 2646 Bytes */ | ||
225 | /* Player control commands */ | ||
226 | #define COMLEADIN 0x70 /* Seek To Lead-in */ | ||
227 | #define COMSEEK 0x71 /* Seek */ | ||
228 | #define COMPAUSEON 0x80 /* Pause On */ | ||
229 | #define COMPAUSEOFF 0x81 /* Pause Off */ | ||
230 | #define COMSTOP 0x82 /* Stop */ | ||
231 | #define COMOPEN 0x90 /* Open Tray Door */ | ||
232 | #define COMCLOSE 0x91 /* Close Tray Door */ | ||
233 | #define COMPLAY 0xa0 /* Audio Play */ | ||
234 | #define COMPLAY_TNO 0xa2 /* Audio Play By Track Number */ | ||
235 | #define COMSUBQ 0xb0 /* Read Sub-q Code */ | ||
236 | #define COMLOCATION 0xb1 /* Read Head Position */ | ||
237 | /* Audio control commands */ | ||
238 | #define COMCHCTRL 0xc0 /* Audio Channel Control */ | ||
239 | /* Miscellaneous (test) commands */ | ||
240 | #define COMDRVTEST 0xd0 /* Write Test Bytes */ | ||
241 | #define COMTEST 0xd1 /* Diagnostic Test */ | ||
242 | |||
243 | /* Low level drive interface. Only here we do actual I/O | ||
244 | Waiting for status / data available */ | ||
245 | |||
246 | |||
247 | /* Busy wait until FLAG goes low. Return 0 on timeout. */ | ||
248 | static inline int flag_low(int flag, unsigned long timeout) | ||
249 | { | ||
250 | int flag_high; | ||
251 | unsigned long count = 0; | ||
252 | |||
253 | while ((flag_high = (inb(STATUS_PORT) & flag))) | ||
254 | if (++count >= timeout) | ||
255 | break; | ||
256 | |||
257 | DEBUG((DEBUG_DRIVE_IF, "flag_low 0x%x count %ld%s", | ||
258 | flag, count, flag_high ? " timeout" : "")); | ||
259 | return !flag_high; | ||
260 | } | ||
261 | |||
262 | |||
263 | /* Timed waiting for status or data */ | ||
264 | static int sleep_timeout; /* max # of ticks to sleep */ | ||
265 | static DECLARE_WAIT_QUEUE_HEAD(waitq); | ||
266 | static void sleep_timer(unsigned long data); | ||
267 | static DEFINE_TIMER(delay_timer, sleep_timer, 0, 0); | ||
268 | static DEFINE_SPINLOCK(optcd_lock); | ||
269 | static struct request_queue *opt_queue; | ||
270 | |||
271 | /* Timer routine: wake up when desired flag goes low, | ||
272 | or when timeout expires. */ | ||
273 | static void sleep_timer(unsigned long data) | ||
274 | { | ||
275 | int flags = inb(STATUS_PORT) & FL_STDT; | ||
276 | |||
277 | if (flags == FL_STDT && --sleep_timeout > 0) { | ||
278 | mod_timer(&delay_timer, jiffies + HZ/100); /* multi-statement macro */ | ||
279 | } else | ||
280 | wake_up(&waitq); | ||
281 | } | ||
282 | |||
283 | |||
284 | /* Sleep until FLAG goes low. Return 0 on timeout or wrong flag low. */ | ||
285 | static int sleep_flag_low(int flag, unsigned long timeout) | ||
286 | { | ||
287 | int flag_high; | ||
288 | |||
289 | DEBUG((DEBUG_DRIVE_IF, "sleep_flag_low")); | ||
290 | |||
291 | sleep_timeout = timeout; | ||
292 | flag_high = inb(STATUS_PORT) & flag; | ||
293 | if (flag_high && sleep_timeout > 0) { | ||
294 | mod_timer(&delay_timer, jiffies + HZ/100); | ||
295 | sleep_on(&waitq); | ||
296 | flag_high = inb(STATUS_PORT) & flag; | ||
297 | } | ||
298 | |||
299 | DEBUG((DEBUG_DRIVE_IF, "flag 0x%x count %ld%s", | ||
300 | flag, timeout, flag_high ? " timeout" : "")); | ||
301 | return !flag_high; | ||
302 | } | ||
303 | |||
304 | /* Low level drive interface. Only here we do actual I/O | ||
305 | Sending commands and parameters */ | ||
306 | |||
307 | |||
308 | /* Errors in the command protocol */ | ||
309 | #define ERR_IF_CMD_TIMEOUT 0x100 | ||
310 | #define ERR_IF_ERR_TIMEOUT 0x101 | ||
311 | #define ERR_IF_RESP_TIMEOUT 0x102 | ||
312 | #define ERR_IF_DATA_TIMEOUT 0x103 | ||
313 | #define ERR_IF_NOSTAT 0x104 | ||
314 | |||
315 | |||
316 | /* Send command code. Return <0 indicates error */ | ||
317 | static int send_cmd(int cmd) | ||
318 | { | ||
319 | unsigned char ack; | ||
320 | |||
321 | DEBUG((DEBUG_DRIVE_IF, "sending command 0x%02x\n", cmd)); | ||
322 | |||
323 | outb(HCON_DTS, HCON_PORT); /* Enable Suspend Data Transfer */ | ||
324 | outb(cmd, COMIN_PORT); /* Send command code */ | ||
325 | if (!flag_low(FL_STEN, BUSY_TIMEOUT)) /* Wait for status */ | ||
326 | return -ERR_IF_CMD_TIMEOUT; | ||
327 | ack = inb(DATA_PORT); /* read command acknowledge */ | ||
328 | outb(HCON_SDRQB, HCON_PORT); /* Disable Suspend Data Transfer */ | ||
329 | return ack==ST_OP_OK ? 0 : -ack; | ||
330 | } | ||
331 | |||
332 | |||
333 | /* Send command parameters. Return <0 indicates error */ | ||
334 | static int send_params(struct cdrom_msf *params) | ||
335 | { | ||
336 | unsigned char ack; | ||
337 | |||
338 | DEBUG((DEBUG_DRIVE_IF, "sending parameters" | ||
339 | " %02x:%02x:%02x" | ||
340 | " %02x:%02x:%02x", | ||
341 | params->cdmsf_min0, | ||
342 | params->cdmsf_sec0, | ||
343 | params->cdmsf_frame0, | ||
344 | params->cdmsf_min1, | ||
345 | params->cdmsf_sec1, | ||
346 | params->cdmsf_frame1)); | ||
347 | |||
348 | outb(params->cdmsf_min0, COMIN_PORT); | ||
349 | outb(params->cdmsf_sec0, COMIN_PORT); | ||
350 | outb(params->cdmsf_frame0, COMIN_PORT); | ||
351 | outb(params->cdmsf_min1, COMIN_PORT); | ||
352 | outb(params->cdmsf_sec1, COMIN_PORT); | ||
353 | outb(params->cdmsf_frame1, COMIN_PORT); | ||
354 | if (!flag_low(FL_STEN, BUSY_TIMEOUT)) /* Wait for status */ | ||
355 | return -ERR_IF_CMD_TIMEOUT; | ||
356 | ack = inb(DATA_PORT); /* read command acknowledge */ | ||
357 | return ack==ST_PA_OK ? 0 : -ack; | ||
358 | } | ||
359 | |||
360 | |||
361 | /* Send parameters for SEEK command. Return <0 indicates error */ | ||
362 | static int send_seek_params(struct cdrom_msf *params) | ||
363 | { | ||
364 | unsigned char ack; | ||
365 | |||
366 | DEBUG((DEBUG_DRIVE_IF, "sending seek parameters" | ||
367 | " %02x:%02x:%02x", | ||
368 | params->cdmsf_min0, | ||
369 | params->cdmsf_sec0, | ||
370 | params->cdmsf_frame0)); | ||
371 | |||
372 | outb(params->cdmsf_min0, COMIN_PORT); | ||
373 | outb(params->cdmsf_sec0, COMIN_PORT); | ||
374 | outb(params->cdmsf_frame0, COMIN_PORT); | ||
375 | if (!flag_low(FL_STEN, BUSY_TIMEOUT)) /* Wait for status */ | ||
376 | return -ERR_IF_CMD_TIMEOUT; | ||
377 | ack = inb(DATA_PORT); /* read command acknowledge */ | ||
378 | return ack==ST_PA_OK ? 0 : -ack; | ||
379 | } | ||
380 | |||
381 | |||
382 | /* Wait for command execution status. Choice between busy waiting | ||
383 | and sleeping. Return value <0 indicates timeout. */ | ||
384 | static inline int get_exec_status(int busy_waiting) | ||
385 | { | ||
386 | unsigned char exec_status; | ||
387 | |||
388 | if (busy_waiting | ||
389 | ? !flag_low(FL_STEN, BUSY_TIMEOUT) | ||
390 | : !sleep_flag_low(FL_STEN, SLEEP_TIMEOUT)) | ||
391 | return -ERR_IF_CMD_TIMEOUT; | ||
392 | |||
393 | exec_status = inb(DATA_PORT); | ||
394 | DEBUG((DEBUG_DRIVE_IF, "returned exec status 0x%02x", exec_status)); | ||
395 | return exec_status; | ||
396 | } | ||
397 | |||
398 | |||
399 | /* Wait busy for extra byte of data that a command returns. | ||
400 | Return value <0 indicates timeout. */ | ||
401 | static inline int get_data(int short_timeout) | ||
402 | { | ||
403 | unsigned char data; | ||
404 | |||
405 | if (!flag_low(FL_STEN, short_timeout ? FAST_TIMEOUT : BUSY_TIMEOUT)) | ||
406 | return -ERR_IF_DATA_TIMEOUT; | ||
407 | |||
408 | data = inb(DATA_PORT); | ||
409 | DEBUG((DEBUG_DRIVE_IF, "returned data 0x%02x", data)); | ||
410 | return data; | ||
411 | } | ||
412 | |||
413 | |||
414 | /* Returns 0 if failed */ | ||
415 | static int reset_drive(void) | ||
416 | { | ||
417 | unsigned long count = 0; | ||
418 | int flags; | ||
419 | |||
420 | DEBUG((DEBUG_DRIVE_IF, "reset drive")); | ||
421 | |||
422 | outb(0, RESET_PORT); | ||
423 | while (++count < RESET_WAIT) | ||
424 | inb(DATA_PORT); | ||
425 | |||
426 | count = 0; | ||
427 | while ((flags = (inb(STATUS_PORT) & FL_RESET)) != FL_RESET) | ||
428 | if (++count >= BUSY_TIMEOUT) | ||
429 | break; | ||
430 | |||
431 | DEBUG((DEBUG_DRIVE_IF, "reset %s", | ||
432 | flags == FL_RESET ? "succeeded" : "failed")); | ||
433 | |||
434 | if (flags != FL_RESET) | ||
435 | return 0; /* Reset failed */ | ||
436 | outb(HCON_SDRQB, HCON_PORT); /* Disable Suspend Data Transfer */ | ||
437 | return 1; /* Reset succeeded */ | ||
438 | } | ||
439 | |||
440 | |||
441 | /* Facilities for asynchronous operation */ | ||
442 | |||
443 | /* Read status/data availability flags FL_STEN and FL_DTEN */ | ||
444 | static inline int stdt_flags(void) | ||
445 | { | ||
446 | return inb(STATUS_PORT) & FL_STDT; | ||
447 | } | ||
448 | |||
449 | |||
450 | /* Fetch status that has previously been waited for. <0 means not available */ | ||
451 | static inline int fetch_status(void) | ||
452 | { | ||
453 | unsigned char status; | ||
454 | |||
455 | if (inb(STATUS_PORT) & FL_STEN) | ||
456 | return -ERR_IF_NOSTAT; | ||
457 | |||
458 | status = inb(DATA_PORT); | ||
459 | DEBUG((DEBUG_DRIVE_IF, "fetched exec status 0x%02x", status)); | ||
460 | return status; | ||
461 | } | ||
462 | |||
463 | |||
464 | /* Fetch data that has previously been waited for. */ | ||
465 | static inline void fetch_data(char *buf, int n) | ||
466 | { | ||
467 | insb(DATA_PORT, buf, n); | ||
468 | DEBUG((DEBUG_DRIVE_IF, "fetched 0x%x bytes", n)); | ||
469 | } | ||
470 | |||
471 | |||
472 | /* Flush status and data fifos */ | ||
473 | static inline void flush_data(void) | ||
474 | { | ||
475 | while ((inb(STATUS_PORT) & FL_STDT) != FL_STDT) | ||
476 | inb(DATA_PORT); | ||
477 | DEBUG((DEBUG_DRIVE_IF, "flushed fifos")); | ||
478 | } | ||
479 | |||
480 | /* Command protocol */ | ||
481 | |||
482 | |||
483 | /* Send a simple command and wait for response. Command codes < COMFETCH | ||
484 | are quick response commands */ | ||
485 | static inline int exec_cmd(int cmd) | ||
486 | { | ||
487 | int ack = send_cmd(cmd); | ||
488 | if (ack < 0) | ||
489 | return ack; | ||
490 | return get_exec_status(cmd < COMFETCH); | ||
491 | } | ||
492 | |||
493 | |||
494 | /* Send a command with parameters. Don't wait for the response, | ||
495 | * which consists of data blocks read from the CD. */ | ||
496 | static inline int exec_read_cmd(int cmd, struct cdrom_msf *params) | ||
497 | { | ||
498 | int ack = send_cmd(cmd); | ||
499 | if (ack < 0) | ||
500 | return ack; | ||
501 | return send_params(params); | ||
502 | } | ||
503 | |||
504 | |||
505 | /* Send a seek command with parameters and wait for response */ | ||
506 | static inline int exec_seek_cmd(int cmd, struct cdrom_msf *params) | ||
507 | { | ||
508 | int ack = send_cmd(cmd); | ||
509 | if (ack < 0) | ||
510 | return ack; | ||
511 | ack = send_seek_params(params); | ||
512 | if (ack < 0) | ||
513 | return ack; | ||
514 | return 0; | ||
515 | } | ||
516 | |||
517 | |||
518 | /* Send a command with parameters and wait for response */ | ||
519 | static inline int exec_long_cmd(int cmd, struct cdrom_msf *params) | ||
520 | { | ||
521 | int ack = exec_read_cmd(cmd, params); | ||
522 | if (ack < 0) | ||
523 | return ack; | ||
524 | return get_exec_status(0); | ||
525 | } | ||
526 | |||
527 | /* Address conversion routines */ | ||
528 | |||
529 | |||
530 | /* Binary to BCD (2 digits) */ | ||
531 | static inline void single_bin2bcd(u_char *p) | ||
532 | { | ||
533 | DEBUG((DEBUG_CONV, "bin2bcd %02d", *p)); | ||
534 | *p = (*p % 10) | ((*p / 10) << 4); | ||
535 | } | ||
536 | |||
537 | |||
538 | /* Convert entire msf struct */ | ||
539 | static void bin2bcd(struct cdrom_msf *msf) | ||
540 | { | ||
541 | single_bin2bcd(&msf->cdmsf_min0); | ||
542 | single_bin2bcd(&msf->cdmsf_sec0); | ||
543 | single_bin2bcd(&msf->cdmsf_frame0); | ||
544 | single_bin2bcd(&msf->cdmsf_min1); | ||
545 | single_bin2bcd(&msf->cdmsf_sec1); | ||
546 | single_bin2bcd(&msf->cdmsf_frame1); | ||
547 | } | ||
548 | |||
549 | |||
550 | /* Linear block address to minute, second, frame form */ | ||
551 | #define CD_FPM (CD_SECS * CD_FRAMES) /* frames per minute */ | ||
552 | |||
553 | static void lba2msf(int lba, struct cdrom_msf *msf) | ||
554 | { | ||
555 | DEBUG((DEBUG_CONV, "lba2msf %d", lba)); | ||
556 | lba += CD_MSF_OFFSET; | ||
557 | msf->cdmsf_min0 = lba / CD_FPM; lba %= CD_FPM; | ||
558 | msf->cdmsf_sec0 = lba / CD_FRAMES; | ||
559 | msf->cdmsf_frame0 = lba % CD_FRAMES; | ||
560 | msf->cdmsf_min1 = 0; | ||
561 | msf->cdmsf_sec1 = 0; | ||
562 | msf->cdmsf_frame1 = 0; | ||
563 | bin2bcd(msf); | ||
564 | } | ||
565 | |||
566 | |||
567 | /* Two BCD digits to binary */ | ||
568 | static inline u_char bcd2bin(u_char bcd) | ||
569 | { | ||
570 | DEBUG((DEBUG_CONV, "bcd2bin %x%02x", bcd)); | ||
571 | return (bcd >> 4) * 10 + (bcd & 0x0f); | ||
572 | } | ||
573 | |||
574 | |||
575 | static void msf2lba(union cdrom_addr *addr) | ||
576 | { | ||
577 | addr->lba = addr->msf.minute * CD_FPM | ||
578 | + addr->msf.second * CD_FRAMES | ||
579 | + addr->msf.frame - CD_MSF_OFFSET; | ||
580 | } | ||
581 | |||
582 | |||
583 | /* Minute, second, frame address BCD to binary or to linear address, | ||
584 | depending on MODE */ | ||
585 | static void msf_bcd2bin(union cdrom_addr *addr) | ||
586 | { | ||
587 | addr->msf.minute = bcd2bin(addr->msf.minute); | ||
588 | addr->msf.second = bcd2bin(addr->msf.second); | ||
589 | addr->msf.frame = bcd2bin(addr->msf.frame); | ||
590 | } | ||
591 | |||
592 | /* High level drive commands */ | ||
593 | |||
594 | |||
595 | static int audio_status = CDROM_AUDIO_NO_STATUS; | ||
596 | static char toc_uptodate = 0; | ||
597 | static char disk_changed = 1; | ||
598 | |||
599 | /* Get drive status, flagging completion of audio play and disk changes. */ | ||
600 | static int drive_status(void) | ||
601 | { | ||
602 | int status; | ||
603 | |||
604 | status = exec_cmd(COMIOCTLISTAT); | ||
605 | DEBUG((DEBUG_DRIVE_IF, "IOCTLISTAT: %03x", status)); | ||
606 | if (status < 0) | ||
607 | return status; | ||
608 | if (status == 0xff) /* No status available */ | ||
609 | return -ERR_IF_NOSTAT; | ||
610 | |||
611 | if (((status & ST_MODE_BITS) != ST_M_AUDIO) && | ||
612 | (audio_status == CDROM_AUDIO_PLAY)) { | ||
613 | audio_status = CDROM_AUDIO_COMPLETED; | ||
614 | } | ||
615 | |||
616 | if (status & ST_DSK_CHG) { | ||
617 | toc_uptodate = 0; | ||
618 | disk_changed = 1; | ||
619 | audio_status = CDROM_AUDIO_NO_STATUS; | ||
620 | } | ||
621 | |||
622 | return status; | ||
623 | } | ||
624 | |||
625 | |||
626 | /* Read the current Q-channel info. Also used for reading the | ||
627 | table of contents. qp->cdsc_format must be set on entry to | ||
628 | indicate the desired address format */ | ||
629 | static int get_q_channel(struct cdrom_subchnl *qp) | ||
630 | { | ||
631 | int status, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10; | ||
632 | |||
633 | status = drive_status(); | ||
634 | if (status < 0) | ||
635 | return status; | ||
636 | qp->cdsc_audiostatus = audio_status; | ||
637 | |||
638 | status = exec_cmd(COMSUBQ); | ||
639 | if (status < 0) | ||
640 | return status; | ||
641 | |||
642 | d1 = get_data(0); | ||
643 | if (d1 < 0) | ||
644 | return d1; | ||
645 | qp->cdsc_adr = d1; | ||
646 | qp->cdsc_ctrl = d1 >> 4; | ||
647 | |||
648 | d2 = get_data(0); | ||
649 | if (d2 < 0) | ||
650 | return d2; | ||
651 | qp->cdsc_trk = bcd2bin(d2); | ||
652 | |||
653 | d3 = get_data(0); | ||
654 | if (d3 < 0) | ||
655 | return d3; | ||
656 | qp->cdsc_ind = bcd2bin(d3); | ||
657 | |||
658 | d4 = get_data(0); | ||
659 | if (d4 < 0) | ||
660 | return d4; | ||
661 | qp->cdsc_reladdr.msf.minute = d4; | ||
662 | |||
663 | d5 = get_data(0); | ||
664 | if (d5 < 0) | ||
665 | return d5; | ||
666 | qp->cdsc_reladdr.msf.second = d5; | ||
667 | |||
668 | d6 = get_data(0); | ||
669 | if (d6 < 0) | ||
670 | return d6; | ||
671 | qp->cdsc_reladdr.msf.frame = d6; | ||
672 | |||
673 | d7 = get_data(0); | ||
674 | if (d7 < 0) | ||
675 | return d7; | ||
676 | /* byte not used */ | ||
677 | |||
678 | d8 = get_data(0); | ||
679 | if (d8 < 0) | ||
680 | return d8; | ||
681 | qp->cdsc_absaddr.msf.minute = d8; | ||
682 | |||
683 | d9 = get_data(0); | ||
684 | if (d9 < 0) | ||
685 | return d9; | ||
686 | qp->cdsc_absaddr.msf.second = d9; | ||
687 | |||
688 | d10 = get_data(0); | ||
689 | if (d10 < 0) | ||
690 | return d10; | ||
691 | qp->cdsc_absaddr.msf.frame = d10; | ||
692 | |||
693 | DEBUG((DEBUG_TOC, "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", | ||
694 | d1, d2, d3, d4, d5, d6, d7, d8, d9, d10)); | ||
695 | |||
696 | msf_bcd2bin(&qp->cdsc_absaddr); | ||
697 | msf_bcd2bin(&qp->cdsc_reladdr); | ||
698 | if (qp->cdsc_format == CDROM_LBA) { | ||
699 | msf2lba(&qp->cdsc_absaddr); | ||
700 | msf2lba(&qp->cdsc_reladdr); | ||
701 | } | ||
702 | |||
703 | return 0; | ||
704 | } | ||
705 | |||
706 | /* Table of contents handling */ | ||
707 | |||
708 | |||
709 | /* Errors in table of contents */ | ||
710 | #define ERR_TOC_MISSINGINFO 0x120 | ||
711 | #define ERR_TOC_MISSINGENTRY 0x121 | ||
712 | |||
713 | |||
714 | struct cdrom_disk_info { | ||
715 | unsigned char first; | ||
716 | unsigned char last; | ||
717 | struct cdrom_msf0 disk_length; | ||
718 | struct cdrom_msf0 first_track; | ||
719 | /* Multisession info: */ | ||
720 | unsigned char next; | ||
721 | struct cdrom_msf0 next_session; | ||
722 | struct cdrom_msf0 last_session; | ||
723 | unsigned char multi; | ||
724 | unsigned char xa; | ||
725 | unsigned char audio; | ||
726 | }; | ||
727 | static struct cdrom_disk_info disk_info; | ||
728 | |||
729 | #define MAX_TRACKS 111 | ||
730 | static struct cdrom_subchnl toc[MAX_TRACKS]; | ||
731 | |||
732 | #define QINFO_FIRSTTRACK 100 /* bcd2bin(0xa0) */ | ||
733 | #define QINFO_LASTTRACK 101 /* bcd2bin(0xa1) */ | ||
734 | #define QINFO_DISKLENGTH 102 /* bcd2bin(0xa2) */ | ||
735 | #define QINFO_NEXTSESSION 110 /* bcd2bin(0xb0) */ | ||
736 | |||
737 | #define I_FIRSTTRACK 0x01 | ||
738 | #define I_LASTTRACK 0x02 | ||
739 | #define I_DISKLENGTH 0x04 | ||
740 | #define I_NEXTSESSION 0x08 | ||
741 | #define I_ALL (I_FIRSTTRACK | I_LASTTRACK | I_DISKLENGTH) | ||
742 | |||
743 | |||
744 | #if DEBUG_TOC | ||
745 | static void toc_debug_info(int i) | ||
746 | { | ||
747 | printk(KERN_DEBUG "#%3d ctl %1x, adr %1x, track %2d index %3d" | ||
748 | " %2d:%02d.%02d %2d:%02d.%02d\n", | ||
749 | i, toc[i].cdsc_ctrl, toc[i].cdsc_adr, | ||
750 | toc[i].cdsc_trk, toc[i].cdsc_ind, | ||
751 | toc[i].cdsc_reladdr.msf.minute, | ||
752 | toc[i].cdsc_reladdr.msf.second, | ||
753 | toc[i].cdsc_reladdr.msf.frame, | ||
754 | toc[i].cdsc_absaddr.msf.minute, | ||
755 | toc[i].cdsc_absaddr.msf.second, | ||
756 | toc[i].cdsc_absaddr.msf.frame); | ||
757 | } | ||
758 | #endif | ||
759 | |||
760 | |||
761 | static int read_toc(void) | ||
762 | { | ||
763 | int status, limit, count; | ||
764 | unsigned char got_info = 0; | ||
765 | struct cdrom_subchnl q_info; | ||
766 | #if DEBUG_TOC | ||
767 | int i; | ||
768 | #endif | ||
769 | |||
770 | DEBUG((DEBUG_TOC, "starting read_toc")); | ||
771 | |||
772 | count = 0; | ||
773 | for (limit = 60; limit > 0; limit--) { | ||
774 | int index; | ||
775 | |||
776 | q_info.cdsc_format = CDROM_MSF; | ||
777 | status = get_q_channel(&q_info); | ||
778 | if (status < 0) | ||
779 | return status; | ||
780 | |||
781 | index = q_info.cdsc_ind; | ||
782 | if (index > 0 && index < MAX_TRACKS | ||
783 | && q_info.cdsc_trk == 0 && toc[index].cdsc_ind == 0) { | ||
784 | toc[index] = q_info; | ||
785 | DEBUG((DEBUG_TOC, "got %d", index)); | ||
786 | if (index < 100) | ||
787 | count++; | ||
788 | |||
789 | switch (q_info.cdsc_ind) { | ||
790 | case QINFO_FIRSTTRACK: | ||
791 | got_info |= I_FIRSTTRACK; | ||
792 | break; | ||
793 | case QINFO_LASTTRACK: | ||
794 | got_info |= I_LASTTRACK; | ||
795 | break; | ||
796 | case QINFO_DISKLENGTH: | ||
797 | got_info |= I_DISKLENGTH; | ||
798 | break; | ||
799 | case QINFO_NEXTSESSION: | ||
800 | got_info |= I_NEXTSESSION; | ||
801 | break; | ||
802 | } | ||
803 | } | ||
804 | |||
805 | if ((got_info & I_ALL) == I_ALL | ||
806 | && toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute + count | ||
807 | >= toc[QINFO_LASTTRACK].cdsc_absaddr.msf.minute + 1) | ||
808 | break; | ||
809 | } | ||
810 | |||
811 | /* Construct disk_info from TOC */ | ||
812 | if (disk_info.first == 0) { | ||
813 | disk_info.first = toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute; | ||
814 | disk_info.first_track.minute = | ||
815 | toc[disk_info.first].cdsc_absaddr.msf.minute; | ||
816 | disk_info.first_track.second = | ||
817 | toc[disk_info.first].cdsc_absaddr.msf.second; | ||
818 | disk_info.first_track.frame = | ||
819 | toc[disk_info.first].cdsc_absaddr.msf.frame; | ||
820 | } | ||
821 | disk_info.last = toc[QINFO_LASTTRACK].cdsc_absaddr.msf.minute; | ||
822 | disk_info.disk_length.minute = | ||
823 | toc[QINFO_DISKLENGTH].cdsc_absaddr.msf.minute; | ||
824 | disk_info.disk_length.second = | ||
825 | toc[QINFO_DISKLENGTH].cdsc_absaddr.msf.second-2; | ||
826 | disk_info.disk_length.frame = | ||
827 | toc[QINFO_DISKLENGTH].cdsc_absaddr.msf.frame; | ||
828 | disk_info.next_session.minute = | ||
829 | toc[QINFO_NEXTSESSION].cdsc_reladdr.msf.minute; | ||
830 | disk_info.next_session.second = | ||
831 | toc[QINFO_NEXTSESSION].cdsc_reladdr.msf.second; | ||
832 | disk_info.next_session.frame = | ||
833 | toc[QINFO_NEXTSESSION].cdsc_reladdr.msf.frame; | ||
834 | disk_info.next = toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute; | ||
835 | disk_info.last_session.minute = | ||
836 | toc[disk_info.next].cdsc_absaddr.msf.minute; | ||
837 | disk_info.last_session.second = | ||
838 | toc[disk_info.next].cdsc_absaddr.msf.second; | ||
839 | disk_info.last_session.frame = | ||
840 | toc[disk_info.next].cdsc_absaddr.msf.frame; | ||
841 | toc[disk_info.last + 1].cdsc_absaddr.msf.minute = | ||
842 | disk_info.disk_length.minute; | ||
843 | toc[disk_info.last + 1].cdsc_absaddr.msf.second = | ||
844 | disk_info.disk_length.second; | ||
845 | toc[disk_info.last + 1].cdsc_absaddr.msf.frame = | ||
846 | disk_info.disk_length.frame; | ||
847 | #if DEBUG_TOC | ||
848 | for (i = 1; i <= disk_info.last + 1; i++) | ||
849 | toc_debug_info(i); | ||
850 | toc_debug_info(QINFO_FIRSTTRACK); | ||
851 | toc_debug_info(QINFO_LASTTRACK); | ||
852 | toc_debug_info(QINFO_DISKLENGTH); | ||
853 | toc_debug_info(QINFO_NEXTSESSION); | ||
854 | #endif | ||
855 | |||
856 | DEBUG((DEBUG_TOC, "exiting read_toc, got_info %x, count %d", | ||
857 | got_info, count)); | ||
858 | if ((got_info & I_ALL) != I_ALL | ||
859 | || toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute + count | ||
860 | < toc[QINFO_LASTTRACK].cdsc_absaddr.msf.minute + 1) | ||
861 | return -ERR_TOC_MISSINGINFO; | ||
862 | return 0; | ||
863 | } | ||
864 | |||
865 | |||
866 | #ifdef MULTISESSION | ||
867 | static int get_multi_disk_info(void) | ||
868 | { | ||
869 | int sessions, status; | ||
870 | struct cdrom_msf multi_index; | ||
871 | |||
872 | |||
873 | for (sessions = 2; sessions < 10 /* %%for now */; sessions++) { | ||
874 | int count; | ||
875 | |||
876 | for (count = 100; count < MAX_TRACKS; count++) | ||
877 | toc[count].cdsc_ind = 0; | ||
878 | |||
879 | multi_index.cdmsf_min0 = disk_info.next_session.minute; | ||
880 | multi_index.cdmsf_sec0 = disk_info.next_session.second; | ||
881 | multi_index.cdmsf_frame0 = disk_info.next_session.frame; | ||
882 | if (multi_index.cdmsf_sec0 >= 20) | ||
883 | multi_index.cdmsf_sec0 -= 20; | ||
884 | else { | ||
885 | multi_index.cdmsf_sec0 += 40; | ||
886 | multi_index.cdmsf_min0--; | ||
887 | } | ||
888 | DEBUG((DEBUG_MULTIS, "Try %d: %2d:%02d.%02d", sessions, | ||
889 | multi_index.cdmsf_min0, | ||
890 | multi_index.cdmsf_sec0, | ||
891 | multi_index.cdmsf_frame0)); | ||
892 | bin2bcd(&multi_index); | ||
893 | multi_index.cdmsf_min1 = 0; | ||
894 | multi_index.cdmsf_sec1 = 0; | ||
895 | multi_index.cdmsf_frame1 = 1; | ||
896 | |||
897 | status = exec_read_cmd(COMREAD, &multi_index); | ||
898 | if (status < 0) { | ||
899 | DEBUG((DEBUG_TOC, "exec_read_cmd COMREAD: %02x", | ||
900 | -status)); | ||
901 | break; | ||
902 | } | ||
903 | status = sleep_flag_low(FL_DTEN, MULTI_SEEK_TIMEOUT) ? | ||
904 | 0 : -ERR_TOC_MISSINGINFO; | ||
905 | flush_data(); | ||
906 | if (status < 0) { | ||
907 | DEBUG((DEBUG_TOC, "sleep_flag_low: %02x", -status)); | ||
908 | break; | ||
909 | } | ||
910 | |||
911 | status = read_toc(); | ||
912 | if (status < 0) { | ||
913 | DEBUG((DEBUG_TOC, "read_toc: %02x", -status)); | ||
914 | break; | ||
915 | } | ||
916 | |||
917 | disk_info.multi = 1; | ||
918 | } | ||
919 | |||
920 | exec_cmd(COMSTOP); | ||
921 | |||
922 | if (status < 0) | ||
923 | return -EIO; | ||
924 | return 0; | ||
925 | } | ||
926 | #endif /* MULTISESSION */ | ||
927 | |||
928 | |||
929 | static int update_toc(void) | ||
930 | { | ||
931 | int status, count; | ||
932 | |||
933 | if (toc_uptodate) | ||
934 | return 0; | ||
935 | |||
936 | DEBUG((DEBUG_TOC, "starting update_toc")); | ||
937 | |||
938 | disk_info.first = 0; | ||
939 | for (count = 0; count < MAX_TRACKS; count++) | ||
940 | toc[count].cdsc_ind = 0; | ||
941 | |||
942 | status = exec_cmd(COMLEADIN); | ||
943 | if (status < 0) | ||
944 | return -EIO; | ||
945 | |||
946 | status = read_toc(); | ||
947 | if (status < 0) { | ||
948 | DEBUG((DEBUG_TOC, "read_toc: %02x", -status)); | ||
949 | return -EIO; | ||
950 | } | ||
951 | |||
952 | /* Audio disk detection. Look at first track. */ | ||
953 | disk_info.audio = | ||
954 | (toc[disk_info.first].cdsc_ctrl & CDROM_DATA_TRACK) ? 0 : 1; | ||
955 | |||
956 | /* XA detection */ | ||
957 | disk_info.xa = drive_status() & ST_MODE2TRACK; | ||
958 | |||
959 | /* Multisession detection: if we want this, define MULTISESSION */ | ||
960 | disk_info.multi = 0; | ||
961 | #ifdef MULTISESSION | ||
962 | if (disk_info.xa) | ||
963 | get_multi_disk_info(); /* Here disk_info.multi is set */ | ||
964 | #endif /* MULTISESSION */ | ||
965 | if (disk_info.multi) | ||
966 | printk(KERN_WARNING "optcd: Multisession support experimental, " | ||
967 | "see Documentation/cdrom/optcd\n"); | ||
968 | |||
969 | DEBUG((DEBUG_TOC, "exiting update_toc")); | ||
970 | |||
971 | toc_uptodate = 1; | ||
972 | return 0; | ||
973 | } | ||
974 | |||
975 | /* Request handling */ | ||
976 | |||
977 | static int current_valid(void) | ||
978 | { | ||
979 | return CURRENT && | ||
980 | rq_data_dir(CURRENT) == READ && | ||
981 | CURRENT->sector != -1; | ||
982 | } | ||
983 | |||
984 | /* Buffers for block size conversion. */ | ||
985 | #define NOBUF -1 | ||
986 | |||
987 | static char buf[CD_FRAMESIZE * N_BUFS]; | ||
988 | static volatile int buf_bn[N_BUFS], next_bn; | ||
989 | static volatile int buf_in = 0, buf_out = NOBUF; | ||
990 | |||
991 | static inline void opt_invalidate_buffers(void) | ||
992 | { | ||
993 | int i; | ||
994 | |||
995 | DEBUG((DEBUG_BUFFERS, "executing opt_invalidate_buffers")); | ||
996 | |||
997 | for (i = 0; i < N_BUFS; i++) | ||
998 | buf_bn[i] = NOBUF; | ||
999 | buf_out = NOBUF; | ||
1000 | } | ||
1001 | |||
1002 | |||
1003 | /* Take care of the different block sizes between cdrom and Linux. | ||
1004 | When Linux gets variable block sizes this will probably go away. */ | ||
1005 | static void transfer(void) | ||
1006 | { | ||
1007 | #if DEBUG_BUFFERS | DEBUG_REQUEST | ||
1008 | printk(KERN_DEBUG "optcd: executing transfer\n"); | ||
1009 | #endif | ||
1010 | |||
1011 | if (!current_valid()) | ||
1012 | return; | ||
1013 | while (CURRENT -> nr_sectors) { | ||
1014 | int bn = CURRENT -> sector / 4; | ||
1015 | int i, offs, nr_sectors; | ||
1016 | for (i = 0; i < N_BUFS && buf_bn[i] != bn; ++i); | ||
1017 | |||
1018 | DEBUG((DEBUG_REQUEST, "found %d", i)); | ||
1019 | |||
1020 | if (i >= N_BUFS) { | ||
1021 | buf_out = NOBUF; | ||
1022 | break; | ||
1023 | } | ||
1024 | |||
1025 | offs = (i * 4 + (CURRENT -> sector & 3)) * 512; | ||
1026 | nr_sectors = 4 - (CURRENT -> sector & 3); | ||
1027 | |||
1028 | if (buf_out != i) { | ||
1029 | buf_out = i; | ||
1030 | if (buf_bn[i] != bn) { | ||
1031 | buf_out = NOBUF; | ||
1032 | continue; | ||
1033 | } | ||
1034 | } | ||
1035 | |||
1036 | if (nr_sectors > CURRENT -> nr_sectors) | ||
1037 | nr_sectors = CURRENT -> nr_sectors; | ||
1038 | memcpy(CURRENT -> buffer, buf + offs, nr_sectors * 512); | ||
1039 | CURRENT -> nr_sectors -= nr_sectors; | ||
1040 | CURRENT -> sector += nr_sectors; | ||
1041 | CURRENT -> buffer += nr_sectors * 512; | ||
1042 | } | ||
1043 | } | ||
1044 | |||
1045 | |||
1046 | /* State machine for reading disk blocks */ | ||
1047 | |||
1048 | enum state_e { | ||
1049 | S_IDLE, /* 0 */ | ||
1050 | S_START, /* 1 */ | ||
1051 | S_READ, /* 2 */ | ||
1052 | S_DATA, /* 3 */ | ||
1053 | S_STOP, /* 4 */ | ||
1054 | S_STOPPING /* 5 */ | ||
1055 | }; | ||
1056 | |||
1057 | static volatile enum state_e state = S_IDLE; | ||
1058 | #if DEBUG_STATE | ||
1059 | static volatile enum state_e state_old = S_STOP; | ||
1060 | static volatile int flags_old = 0; | ||
1061 | static volatile long state_n = 0; | ||
1062 | #endif | ||
1063 | |||
1064 | |||
1065 | /* Used as mutex to keep do_optcd_request (and other processes calling | ||
1066 | ioctl) out while some process is inside a VFS call. | ||
1067 | Reverse is accomplished by checking if state = S_IDLE upon entry | ||
1068 | of opt_ioctl and opt_media_change. */ | ||
1069 | static int in_vfs = 0; | ||
1070 | |||
1071 | |||
1072 | static volatile int transfer_is_active = 0; | ||
1073 | static volatile int error = 0; /* %% do something with this?? */ | ||
1074 | static int tries; /* ibid?? */ | ||
1075 | static int timeout = 0; | ||
1076 | |||
1077 | static void poll(unsigned long data); | ||
1078 | static struct timer_list req_timer = {.function = poll}; | ||
1079 | |||
1080 | |||
1081 | static void poll(unsigned long data) | ||
1082 | { | ||
1083 | static volatile int read_count = 1; | ||
1084 | int flags; | ||
1085 | int loop_again = 1; | ||
1086 | int status = 0; | ||
1087 | int skip = 0; | ||
1088 | |||
1089 | if (error) { | ||
1090 | printk(KERN_ERR "optcd: I/O error 0x%02x\n", error); | ||
1091 | opt_invalidate_buffers(); | ||
1092 | if (!tries--) { | ||
1093 | printk(KERN_ERR "optcd: read block %d failed;" | ||
1094 | " Giving up\n", next_bn); | ||
1095 | if (transfer_is_active) | ||
1096 | loop_again = 0; | ||
1097 | if (current_valid()) | ||
1098 | end_request(CURRENT, 0); | ||
1099 | tries = 5; | ||
1100 | } | ||
1101 | error = 0; | ||
1102 | state = S_STOP; | ||
1103 | } | ||
1104 | |||
1105 | while (loop_again) | ||
1106 | { | ||
1107 | loop_again = 0; /* each case must flip this back to 1 if we want | ||
1108 | to come back up here */ | ||
1109 | |||
1110 | #if DEBUG_STATE | ||
1111 | if (state == state_old) | ||
1112 | state_n++; | ||
1113 | else { | ||
1114 | state_old = state; | ||
1115 | if (++state_n > 1) | ||
1116 | printk(KERN_DEBUG "optcd: %ld times " | ||
1117 | "in previous state\n", state_n); | ||
1118 | printk(KERN_DEBUG "optcd: state %d\n", state); | ||
1119 | state_n = 0; | ||
1120 | } | ||
1121 | #endif | ||
1122 | |||
1123 | switch (state) { | ||
1124 | case S_IDLE: | ||
1125 | return; | ||
1126 | case S_START: | ||
1127 | if (in_vfs) | ||
1128 | break; | ||
1129 | if (send_cmd(COMDRVST)) { | ||
1130 | state = S_IDLE; | ||
1131 | while (current_valid()) | ||
1132 | end_request(CURRENT, 0); | ||
1133 | return; | ||
1134 | } | ||
1135 | state = S_READ; | ||
1136 | timeout = READ_TIMEOUT; | ||
1137 | break; | ||
1138 | case S_READ: { | ||
1139 | struct cdrom_msf msf; | ||
1140 | if (!skip) { | ||
1141 | status = fetch_status(); | ||
1142 | if (status < 0) | ||
1143 | break; | ||
1144 | if (status & ST_DSK_CHG) { | ||
1145 | toc_uptodate = 0; | ||
1146 | opt_invalidate_buffers(); | ||
1147 | } | ||
1148 | } | ||
1149 | skip = 0; | ||
1150 | if ((status & ST_DOOR_OPEN) || (status & ST_DRVERR)) { | ||
1151 | toc_uptodate = 0; | ||
1152 | opt_invalidate_buffers(); | ||
1153 | printk(KERN_WARNING "optcd: %s\n", | ||
1154 | (status & ST_DOOR_OPEN) | ||
1155 | ? "door open" | ||
1156 | : "disk removed"); | ||
1157 | state = S_IDLE; | ||
1158 | while (current_valid()) | ||
1159 | end_request(CURRENT, 0); | ||
1160 | return; | ||
1161 | } | ||
1162 | if (!current_valid()) { | ||
1163 | state = S_STOP; | ||
1164 | loop_again = 1; | ||
1165 | break; | ||
1166 | } | ||
1167 | next_bn = CURRENT -> sector / 4; | ||
1168 | lba2msf(next_bn, &msf); | ||
1169 | read_count = N_BUFS; | ||
1170 | msf.cdmsf_frame1 = read_count; /* Not BCD! */ | ||
1171 | |||
1172 | DEBUG((DEBUG_REQUEST, "reading %x:%x.%x %x:%x.%x", | ||
1173 | msf.cdmsf_min0, | ||
1174 | msf.cdmsf_sec0, | ||
1175 | msf.cdmsf_frame0, | ||
1176 | msf.cdmsf_min1, | ||
1177 | msf.cdmsf_sec1, | ||
1178 | msf.cdmsf_frame1)); | ||
1179 | DEBUG((DEBUG_REQUEST, "next_bn:%d buf_in:%d" | ||
1180 | " buf_out:%d buf_bn:%d", | ||
1181 | next_bn, | ||
1182 | buf_in, | ||
1183 | buf_out, | ||
1184 | buf_bn[buf_in])); | ||
1185 | |||
1186 | exec_read_cmd(COMREAD, &msf); | ||
1187 | state = S_DATA; | ||
1188 | timeout = READ_TIMEOUT; | ||
1189 | break; | ||
1190 | } | ||
1191 | case S_DATA: | ||
1192 | flags = stdt_flags() & (FL_STEN|FL_DTEN); | ||
1193 | |||
1194 | #if DEBUG_STATE | ||
1195 | if (flags != flags_old) { | ||
1196 | flags_old = flags; | ||
1197 | printk(KERN_DEBUG "optcd: flags:%x\n", flags); | ||
1198 | } | ||
1199 | if (flags == FL_STEN) | ||
1200 | printk(KERN_DEBUG "timeout cnt: %d\n", timeout); | ||
1201 | #endif | ||
1202 | |||
1203 | switch (flags) { | ||
1204 | case FL_DTEN: /* only STEN low */ | ||
1205 | if (!tries--) { | ||
1206 | printk(KERN_ERR | ||
1207 | "optcd: read block %d failed; " | ||
1208 | "Giving up\n", next_bn); | ||
1209 | if (transfer_is_active) { | ||
1210 | tries = 0; | ||
1211 | break; | ||
1212 | } | ||
1213 | if (current_valid()) | ||
1214 | end_request(CURRENT, 0); | ||
1215 | tries = 5; | ||
1216 | } | ||
1217 | state = S_START; | ||
1218 | timeout = READ_TIMEOUT; | ||
1219 | loop_again = 1; | ||
1220 | case (FL_STEN|FL_DTEN): /* both high */ | ||
1221 | break; | ||
1222 | default: /* DTEN low */ | ||
1223 | tries = 5; | ||
1224 | if (!current_valid() && buf_in == buf_out) { | ||
1225 | state = S_STOP; | ||
1226 | loop_again = 1; | ||
1227 | break; | ||
1228 | } | ||
1229 | if (read_count<=0) | ||
1230 | printk(KERN_WARNING | ||
1231 | "optcd: warning - try to read" | ||
1232 | " 0 frames\n"); | ||
1233 | while (read_count) { | ||
1234 | buf_bn[buf_in] = NOBUF; | ||
1235 | if (!flag_low(FL_DTEN, BUSY_TIMEOUT)) { | ||
1236 | /* should be no waiting here!?? */ | ||
1237 | printk(KERN_ERR | ||
1238 | "read_count:%d " | ||
1239 | "CURRENT->nr_sectors:%ld " | ||
1240 | "buf_in:%d\n", | ||
1241 | read_count, | ||
1242 | CURRENT->nr_sectors, | ||
1243 | buf_in); | ||
1244 | printk(KERN_ERR | ||
1245 | "transfer active: %x\n", | ||
1246 | transfer_is_active); | ||
1247 | read_count = 0; | ||
1248 | state = S_STOP; | ||
1249 | loop_again = 1; | ||
1250 | end_request(CURRENT, 0); | ||
1251 | break; | ||
1252 | } | ||
1253 | fetch_data(buf+ | ||
1254 | CD_FRAMESIZE*buf_in, | ||
1255 | CD_FRAMESIZE); | ||
1256 | read_count--; | ||
1257 | |||
1258 | DEBUG((DEBUG_REQUEST, | ||
1259 | "S_DATA; ---I've read data- " | ||
1260 | "read_count: %d", | ||
1261 | read_count)); | ||
1262 | DEBUG((DEBUG_REQUEST, | ||
1263 | "next_bn:%d buf_in:%d " | ||
1264 | "buf_out:%d buf_bn:%d", | ||
1265 | next_bn, | ||
1266 | buf_in, | ||
1267 | buf_out, | ||
1268 | buf_bn[buf_in])); | ||
1269 | |||
1270 | buf_bn[buf_in] = next_bn++; | ||
1271 | if (buf_out == NOBUF) | ||
1272 | buf_out = buf_in; | ||
1273 | buf_in = buf_in + 1 == | ||
1274 | N_BUFS ? 0 : buf_in + 1; | ||
1275 | } | ||
1276 | if (!transfer_is_active) { | ||
1277 | while (current_valid()) { | ||
1278 | transfer(); | ||
1279 | if (CURRENT -> nr_sectors == 0) | ||
1280 | end_request(CURRENT, 1); | ||
1281 | else | ||
1282 | break; | ||
1283 | } | ||
1284 | } | ||
1285 | |||
1286 | if (current_valid() | ||
1287 | && (CURRENT -> sector / 4 < next_bn || | ||
1288 | CURRENT -> sector / 4 > | ||
1289 | next_bn + N_BUFS)) { | ||
1290 | state = S_STOP; | ||
1291 | loop_again = 1; | ||
1292 | break; | ||
1293 | } | ||
1294 | timeout = READ_TIMEOUT; | ||
1295 | if (read_count == 0) { | ||
1296 | state = S_STOP; | ||
1297 | loop_again = 1; | ||
1298 | break; | ||
1299 | } | ||
1300 | } | ||
1301 | break; | ||
1302 | case S_STOP: | ||
1303 | if (read_count != 0) | ||
1304 | printk(KERN_ERR | ||
1305 | "optcd: discard data=%x frames\n", | ||
1306 | read_count); | ||
1307 | flush_data(); | ||
1308 | if (send_cmd(COMDRVST)) { | ||
1309 | state = S_IDLE; | ||
1310 | while (current_valid()) | ||
1311 | end_request(CURRENT, 0); | ||
1312 | return; | ||
1313 | } | ||
1314 | state = S_STOPPING; | ||
1315 | timeout = STOP_TIMEOUT; | ||
1316 | break; | ||
1317 | case S_STOPPING: | ||
1318 | status = fetch_status(); | ||
1319 | if (status < 0 && timeout) | ||
1320 | break; | ||
1321 | if ((status >= 0) && (status & ST_DSK_CHG)) { | ||
1322 | toc_uptodate = 0; | ||
1323 | opt_invalidate_buffers(); | ||
1324 | } | ||
1325 | if (current_valid()) { | ||
1326 | if (status >= 0) { | ||
1327 | state = S_READ; | ||
1328 | loop_again = 1; | ||
1329 | skip = 1; | ||
1330 | break; | ||
1331 | } else { | ||
1332 | state = S_START; | ||
1333 | timeout = 1; | ||
1334 | } | ||
1335 | } else { | ||
1336 | state = S_IDLE; | ||
1337 | return; | ||
1338 | } | ||
1339 | break; | ||
1340 | default: | ||
1341 | printk(KERN_ERR "optcd: invalid state %d\n", state); | ||
1342 | return; | ||
1343 | } /* case */ | ||
1344 | } /* while */ | ||
1345 | |||
1346 | if (!timeout--) { | ||
1347 | printk(KERN_ERR "optcd: timeout in state %d\n", state); | ||
1348 | state = S_STOP; | ||
1349 | if (exec_cmd(COMSTOP) < 0) { | ||
1350 | state = S_IDLE; | ||
1351 | while (current_valid()) | ||
1352 | end_request(CURRENT, 0); | ||
1353 | return; | ||
1354 | } | ||
1355 | } | ||
1356 | |||
1357 | mod_timer(&req_timer, jiffies + HZ/100); | ||
1358 | } | ||
1359 | |||
1360 | |||
1361 | static void do_optcd_request(request_queue_t * q) | ||
1362 | { | ||
1363 | DEBUG((DEBUG_REQUEST, "do_optcd_request(%ld+%ld)", | ||
1364 | CURRENT -> sector, CURRENT -> nr_sectors)); | ||
1365 | |||
1366 | if (disk_info.audio) { | ||
1367 | printk(KERN_WARNING "optcd: tried to mount an Audio CD\n"); | ||
1368 | end_request(CURRENT, 0); | ||
1369 | return; | ||
1370 | } | ||
1371 | |||
1372 | transfer_is_active = 1; | ||
1373 | while (current_valid()) { | ||
1374 | transfer(); /* First try to transfer block from buffers */ | ||
1375 | if (CURRENT -> nr_sectors == 0) { | ||
1376 | end_request(CURRENT, 1); | ||
1377 | } else { /* Want to read a block not in buffer */ | ||
1378 | buf_out = NOBUF; | ||
1379 | if (state == S_IDLE) { | ||
1380 | /* %% Should this block the request queue?? */ | ||
1381 | if (update_toc() < 0) { | ||
1382 | while (current_valid()) | ||
1383 | end_request(CURRENT, 0); | ||
1384 | break; | ||
1385 | } | ||
1386 | /* Start state machine */ | ||
1387 | state = S_START; | ||
1388 | timeout = READ_TIMEOUT; | ||
1389 | tries = 5; | ||
1390 | /* %% why not start right away?? */ | ||
1391 | mod_timer(&req_timer, jiffies + HZ/100); | ||
1392 | } | ||
1393 | break; | ||
1394 | } | ||
1395 | } | ||
1396 | transfer_is_active = 0; | ||
1397 | |||
1398 | DEBUG((DEBUG_REQUEST, "next_bn:%d buf_in:%d buf_out:%d buf_bn:%d", | ||
1399 | next_bn, buf_in, buf_out, buf_bn[buf_in])); | ||
1400 | DEBUG((DEBUG_REQUEST, "do_optcd_request ends")); | ||
1401 | } | ||
1402 | |||
1403 | /* IOCTLs */ | ||
1404 | |||
1405 | |||
1406 | static char auto_eject = 0; | ||
1407 | |||
1408 | static int cdrompause(void) | ||
1409 | { | ||
1410 | int status; | ||
1411 | |||
1412 | if (audio_status != CDROM_AUDIO_PLAY) | ||
1413 | return -EINVAL; | ||
1414 | |||
1415 | status = exec_cmd(COMPAUSEON); | ||
1416 | if (status < 0) { | ||
1417 | DEBUG((DEBUG_VFS, "exec_cmd COMPAUSEON: %02x", -status)); | ||
1418 | return -EIO; | ||
1419 | } | ||
1420 | audio_status = CDROM_AUDIO_PAUSED; | ||
1421 | return 0; | ||
1422 | } | ||
1423 | |||
1424 | |||
1425 | static int cdromresume(void) | ||
1426 | { | ||
1427 | int status; | ||
1428 | |||
1429 | if (audio_status != CDROM_AUDIO_PAUSED) | ||
1430 | return -EINVAL; | ||
1431 | |||
1432 | status = exec_cmd(COMPAUSEOFF); | ||
1433 | if (status < 0) { | ||
1434 | DEBUG((DEBUG_VFS, "exec_cmd COMPAUSEOFF: %02x", -status)); | ||
1435 | audio_status = CDROM_AUDIO_ERROR; | ||
1436 | return -EIO; | ||
1437 | } | ||
1438 | audio_status = CDROM_AUDIO_PLAY; | ||
1439 | return 0; | ||
1440 | } | ||
1441 | |||
1442 | |||
1443 | static int cdromplaymsf(void __user *arg) | ||
1444 | { | ||
1445 | int status; | ||
1446 | struct cdrom_msf msf; | ||
1447 | |||
1448 | if (copy_from_user(&msf, arg, sizeof msf)) | ||
1449 | return -EFAULT; | ||
1450 | |||
1451 | bin2bcd(&msf); | ||
1452 | status = exec_long_cmd(COMPLAY, &msf); | ||
1453 | if (status < 0) { | ||
1454 | DEBUG((DEBUG_VFS, "exec_long_cmd COMPLAY: %02x", -status)); | ||
1455 | audio_status = CDROM_AUDIO_ERROR; | ||
1456 | return -EIO; | ||
1457 | } | ||
1458 | |||
1459 | audio_status = CDROM_AUDIO_PLAY; | ||
1460 | return 0; | ||
1461 | } | ||
1462 | |||
1463 | |||
1464 | static int cdromplaytrkind(void __user *arg) | ||
1465 | { | ||
1466 | int status; | ||
1467 | struct cdrom_ti ti; | ||
1468 | struct cdrom_msf msf; | ||
1469 | |||
1470 | if (copy_from_user(&ti, arg, sizeof ti)) | ||
1471 | return -EFAULT; | ||
1472 | |||
1473 | if (ti.cdti_trk0 < disk_info.first | ||
1474 | || ti.cdti_trk0 > disk_info.last | ||
1475 | || ti.cdti_trk1 < ti.cdti_trk0) | ||
1476 | return -EINVAL; | ||
1477 | if (ti.cdti_trk1 > disk_info.last) | ||
1478 | ti.cdti_trk1 = disk_info.last; | ||
1479 | |||
1480 | msf.cdmsf_min0 = toc[ti.cdti_trk0].cdsc_absaddr.msf.minute; | ||
1481 | msf.cdmsf_sec0 = toc[ti.cdti_trk0].cdsc_absaddr.msf.second; | ||
1482 | msf.cdmsf_frame0 = toc[ti.cdti_trk0].cdsc_absaddr.msf.frame; | ||
1483 | msf.cdmsf_min1 = toc[ti.cdti_trk1 + 1].cdsc_absaddr.msf.minute; | ||
1484 | msf.cdmsf_sec1 = toc[ti.cdti_trk1 + 1].cdsc_absaddr.msf.second; | ||
1485 | msf.cdmsf_frame1 = toc[ti.cdti_trk1 + 1].cdsc_absaddr.msf.frame; | ||
1486 | |||
1487 | DEBUG((DEBUG_VFS, "play %02d:%02d.%02d to %02d:%02d.%02d", | ||
1488 | msf.cdmsf_min0, | ||
1489 | msf.cdmsf_sec0, | ||
1490 | msf.cdmsf_frame0, | ||
1491 | msf.cdmsf_min1, | ||
1492 | msf.cdmsf_sec1, | ||
1493 | msf.cdmsf_frame1)); | ||
1494 | |||
1495 | bin2bcd(&msf); | ||
1496 | status = exec_long_cmd(COMPLAY, &msf); | ||
1497 | if (status < 0) { | ||
1498 | DEBUG((DEBUG_VFS, "exec_long_cmd COMPLAY: %02x", -status)); | ||
1499 | audio_status = CDROM_AUDIO_ERROR; | ||
1500 | return -EIO; | ||
1501 | } | ||
1502 | |||
1503 | audio_status = CDROM_AUDIO_PLAY; | ||
1504 | return 0; | ||
1505 | } | ||
1506 | |||
1507 | |||
1508 | static int cdromreadtochdr(void __user *arg) | ||
1509 | { | ||
1510 | struct cdrom_tochdr tochdr; | ||
1511 | |||
1512 | tochdr.cdth_trk0 = disk_info.first; | ||
1513 | tochdr.cdth_trk1 = disk_info.last; | ||
1514 | |||
1515 | return copy_to_user(arg, &tochdr, sizeof tochdr) ? -EFAULT : 0; | ||
1516 | } | ||
1517 | |||
1518 | |||
1519 | static int cdromreadtocentry(void __user *arg) | ||
1520 | { | ||
1521 | struct cdrom_tocentry entry; | ||
1522 | struct cdrom_subchnl *tocptr; | ||
1523 | |||
1524 | if (copy_from_user(&entry, arg, sizeof entry)) | ||
1525 | return -EFAULT; | ||
1526 | |||
1527 | if (entry.cdte_track == CDROM_LEADOUT) | ||
1528 | tocptr = &toc[disk_info.last + 1]; | ||
1529 | else if (entry.cdte_track > disk_info.last | ||
1530 | || entry.cdte_track < disk_info.first) | ||
1531 | return -EINVAL; | ||
1532 | else | ||
1533 | tocptr = &toc[entry.cdte_track]; | ||
1534 | |||
1535 | entry.cdte_adr = tocptr->cdsc_adr; | ||
1536 | entry.cdte_ctrl = tocptr->cdsc_ctrl; | ||
1537 | entry.cdte_addr.msf.minute = tocptr->cdsc_absaddr.msf.minute; | ||
1538 | entry.cdte_addr.msf.second = tocptr->cdsc_absaddr.msf.second; | ||
1539 | entry.cdte_addr.msf.frame = tocptr->cdsc_absaddr.msf.frame; | ||
1540 | /* %% What should go into entry.cdte_datamode? */ | ||
1541 | |||
1542 | if (entry.cdte_format == CDROM_LBA) | ||
1543 | msf2lba(&entry.cdte_addr); | ||
1544 | else if (entry.cdte_format != CDROM_MSF) | ||
1545 | return -EINVAL; | ||
1546 | |||
1547 | return copy_to_user(arg, &entry, sizeof entry) ? -EFAULT : 0; | ||
1548 | } | ||
1549 | |||
1550 | |||
1551 | static int cdromvolctrl(void __user *arg) | ||
1552 | { | ||
1553 | int status; | ||
1554 | struct cdrom_volctrl volctrl; | ||
1555 | struct cdrom_msf msf; | ||
1556 | |||
1557 | if (copy_from_user(&volctrl, arg, sizeof volctrl)) | ||
1558 | return -EFAULT; | ||
1559 | |||
1560 | msf.cdmsf_min0 = 0x10; | ||
1561 | msf.cdmsf_sec0 = 0x32; | ||
1562 | msf.cdmsf_frame0 = volctrl.channel0; | ||
1563 | msf.cdmsf_min1 = volctrl.channel1; | ||
1564 | msf.cdmsf_sec1 = volctrl.channel2; | ||
1565 | msf.cdmsf_frame1 = volctrl.channel3; | ||
1566 | |||
1567 | status = exec_long_cmd(COMCHCTRL, &msf); | ||
1568 | if (status < 0) { | ||
1569 | DEBUG((DEBUG_VFS, "exec_long_cmd COMCHCTRL: %02x", -status)); | ||
1570 | return -EIO; | ||
1571 | } | ||
1572 | return 0; | ||
1573 | } | ||
1574 | |||
1575 | |||
1576 | static int cdromsubchnl(void __user *arg) | ||
1577 | { | ||
1578 | int status; | ||
1579 | struct cdrom_subchnl subchnl; | ||
1580 | |||
1581 | if (copy_from_user(&subchnl, arg, sizeof subchnl)) | ||
1582 | return -EFAULT; | ||
1583 | |||
1584 | if (subchnl.cdsc_format != CDROM_LBA | ||
1585 | && subchnl.cdsc_format != CDROM_MSF) | ||
1586 | return -EINVAL; | ||
1587 | |||
1588 | status = get_q_channel(&subchnl); | ||
1589 | if (status < 0) { | ||
1590 | DEBUG((DEBUG_VFS, "get_q_channel: %02x", -status)); | ||
1591 | return -EIO; | ||
1592 | } | ||
1593 | |||
1594 | if (copy_to_user(arg, &subchnl, sizeof subchnl)) | ||
1595 | return -EFAULT; | ||
1596 | return 0; | ||
1597 | } | ||
1598 | |||
1599 | |||
1600 | static struct gendisk *optcd_disk; | ||
1601 | |||
1602 | |||
1603 | static int cdromread(void __user *arg, int blocksize, int cmd) | ||
1604 | { | ||
1605 | int status; | ||
1606 | struct cdrom_msf msf; | ||
1607 | |||
1608 | if (copy_from_user(&msf, arg, sizeof msf)) | ||
1609 | return -EFAULT; | ||
1610 | |||
1611 | bin2bcd(&msf); | ||
1612 | msf.cdmsf_min1 = 0; | ||
1613 | msf.cdmsf_sec1 = 0; | ||
1614 | msf.cdmsf_frame1 = 1; /* read only one frame */ | ||
1615 | status = exec_read_cmd(cmd, &msf); | ||
1616 | |||
1617 | DEBUG((DEBUG_VFS, "read cmd status 0x%x", status)); | ||
1618 | |||
1619 | if (!sleep_flag_low(FL_DTEN, SLEEP_TIMEOUT)) | ||
1620 | return -EIO; | ||
1621 | |||
1622 | fetch_data(optcd_disk->private_data, blocksize); | ||
1623 | |||
1624 | if (copy_to_user(arg, optcd_disk->private_data, blocksize)) | ||
1625 | return -EFAULT; | ||
1626 | |||
1627 | return 0; | ||
1628 | } | ||
1629 | |||
1630 | |||
1631 | static int cdromseek(void __user *arg) | ||
1632 | { | ||
1633 | int status; | ||
1634 | struct cdrom_msf msf; | ||
1635 | |||
1636 | if (copy_from_user(&msf, arg, sizeof msf)) | ||
1637 | return -EFAULT; | ||
1638 | |||
1639 | bin2bcd(&msf); | ||
1640 | status = exec_seek_cmd(COMSEEK, &msf); | ||
1641 | |||
1642 | DEBUG((DEBUG_VFS, "COMSEEK status 0x%x", status)); | ||
1643 | |||
1644 | if (status < 0) | ||
1645 | return -EIO; | ||
1646 | return 0; | ||
1647 | } | ||
1648 | |||
1649 | |||
1650 | #ifdef MULTISESSION | ||
1651 | static int cdrommultisession(void __user *arg) | ||
1652 | { | ||
1653 | struct cdrom_multisession ms; | ||
1654 | |||
1655 | if (copy_from_user(&ms, arg, sizeof ms)) | ||
1656 | return -EFAULT; | ||
1657 | |||
1658 | ms.addr.msf.minute = disk_info.last_session.minute; | ||
1659 | ms.addr.msf.second = disk_info.last_session.second; | ||
1660 | ms.addr.msf.frame = disk_info.last_session.frame; | ||
1661 | |||
1662 | if (ms.addr_format != CDROM_LBA | ||
1663 | && ms.addr_format != CDROM_MSF) | ||
1664 | return -EINVAL; | ||
1665 | if (ms.addr_format == CDROM_LBA) | ||
1666 | msf2lba(&ms.addr); | ||
1667 | |||
1668 | ms.xa_flag = disk_info.xa; | ||
1669 | |||
1670 | if (copy_to_user(arg, &ms, sizeof(struct cdrom_multisession))) | ||
1671 | return -EFAULT; | ||
1672 | |||
1673 | #if DEBUG_MULTIS | ||
1674 | if (ms.addr_format == CDROM_MSF) | ||
1675 | printk(KERN_DEBUG | ||
1676 | "optcd: multisession xa:%d, msf:%02d:%02d.%02d\n", | ||
1677 | ms.xa_flag, | ||
1678 | ms.addr.msf.minute, | ||
1679 | ms.addr.msf.second, | ||
1680 | ms.addr.msf.frame); | ||
1681 | else | ||
1682 | printk(KERN_DEBUG | ||
1683 | "optcd: multisession %d, lba:0x%08x [%02d:%02d.%02d])\n", | ||
1684 | ms.xa_flag, | ||
1685 | ms.addr.lba, | ||
1686 | disk_info.last_session.minute, | ||
1687 | disk_info.last_session.second, | ||
1688 | disk_info.last_session.frame); | ||
1689 | #endif /* DEBUG_MULTIS */ | ||
1690 | |||
1691 | return 0; | ||
1692 | } | ||
1693 | #endif /* MULTISESSION */ | ||
1694 | |||
1695 | |||
1696 | static int cdromreset(void) | ||
1697 | { | ||
1698 | if (state != S_IDLE) { | ||
1699 | error = 1; | ||
1700 | tries = 0; | ||
1701 | } | ||
1702 | |||
1703 | toc_uptodate = 0; | ||
1704 | disk_changed = 1; | ||
1705 | opt_invalidate_buffers(); | ||
1706 | audio_status = CDROM_AUDIO_NO_STATUS; | ||
1707 | |||
1708 | if (!reset_drive()) | ||
1709 | return -EIO; | ||
1710 | return 0; | ||
1711 | } | ||
1712 | |||
1713 | /* VFS calls */ | ||
1714 | |||
1715 | |||
1716 | static int opt_ioctl(struct inode *ip, struct file *fp, | ||
1717 | unsigned int cmd, unsigned long arg) | ||
1718 | { | ||
1719 | int status, err, retval = 0; | ||
1720 | void __user *argp = (void __user *)arg; | ||
1721 | |||
1722 | DEBUG((DEBUG_VFS, "starting opt_ioctl")); | ||
1723 | |||
1724 | if (!ip) | ||
1725 | return -EINVAL; | ||
1726 | |||
1727 | if (cmd == CDROMRESET) | ||
1728 | return cdromreset(); | ||
1729 | |||
1730 | /* is do_optcd_request or another ioctl busy? */ | ||
1731 | if (state != S_IDLE || in_vfs) | ||
1732 | return -EBUSY; | ||
1733 | |||
1734 | in_vfs = 1; | ||
1735 | |||
1736 | status = drive_status(); | ||
1737 | if (status < 0) { | ||
1738 | DEBUG((DEBUG_VFS, "drive_status: %02x", -status)); | ||
1739 | in_vfs = 0; | ||
1740 | return -EIO; | ||
1741 | } | ||
1742 | |||
1743 | if (status & ST_DOOR_OPEN) | ||
1744 | switch (cmd) { /* Actions that can be taken with door open */ | ||
1745 | case CDROMCLOSETRAY: | ||
1746 | /* We do this before trying to read the toc. */ | ||
1747 | err = exec_cmd(COMCLOSE); | ||
1748 | if (err < 0) { | ||
1749 | DEBUG((DEBUG_VFS, | ||
1750 | "exec_cmd COMCLOSE: %02x", -err)); | ||
1751 | in_vfs = 0; | ||
1752 | return -EIO; | ||
1753 | } | ||
1754 | break; | ||
1755 | default: in_vfs = 0; | ||
1756 | return -EBUSY; | ||
1757 | } | ||
1758 | |||
1759 | err = update_toc(); | ||
1760 | if (err < 0) { | ||
1761 | DEBUG((DEBUG_VFS, "update_toc: %02x", -err)); | ||
1762 | in_vfs = 0; | ||
1763 | return -EIO; | ||
1764 | } | ||
1765 | |||
1766 | DEBUG((DEBUG_VFS, "ioctl cmd 0x%x", cmd)); | ||
1767 | |||
1768 | switch (cmd) { | ||
1769 | case CDROMPAUSE: retval = cdrompause(); break; | ||
1770 | case CDROMRESUME: retval = cdromresume(); break; | ||
1771 | case CDROMPLAYMSF: retval = cdromplaymsf(argp); break; | ||
1772 | case CDROMPLAYTRKIND: retval = cdromplaytrkind(argp); break; | ||
1773 | case CDROMREADTOCHDR: retval = cdromreadtochdr(argp); break; | ||
1774 | case CDROMREADTOCENTRY: retval = cdromreadtocentry(argp); break; | ||
1775 | |||
1776 | case CDROMSTOP: err = exec_cmd(COMSTOP); | ||
1777 | if (err < 0) { | ||
1778 | DEBUG((DEBUG_VFS, | ||
1779 | "exec_cmd COMSTOP: %02x", | ||
1780 | -err)); | ||
1781 | retval = -EIO; | ||
1782 | } else | ||
1783 | audio_status = CDROM_AUDIO_NO_STATUS; | ||
1784 | break; | ||
1785 | case CDROMSTART: break; /* This is a no-op */ | ||
1786 | case CDROMEJECT: err = exec_cmd(COMUNLOCK); | ||
1787 | if (err < 0) { | ||
1788 | DEBUG((DEBUG_VFS, | ||
1789 | "exec_cmd COMUNLOCK: %02x", | ||
1790 | -err)); | ||
1791 | retval = -EIO; | ||
1792 | break; | ||
1793 | } | ||
1794 | err = exec_cmd(COMOPEN); | ||
1795 | if (err < 0) { | ||
1796 | DEBUG((DEBUG_VFS, | ||
1797 | "exec_cmd COMOPEN: %02x", | ||
1798 | -err)); | ||
1799 | retval = -EIO; | ||
1800 | } | ||
1801 | break; | ||
1802 | |||
1803 | case CDROMVOLCTRL: retval = cdromvolctrl(argp); break; | ||
1804 | case CDROMSUBCHNL: retval = cdromsubchnl(argp); break; | ||
1805 | |||
1806 | /* The drive detects the mode and automatically delivers the | ||
1807 | correct 2048 bytes, so we don't need these IOCTLs */ | ||
1808 | case CDROMREADMODE2: retval = -EINVAL; break; | ||
1809 | case CDROMREADMODE1: retval = -EINVAL; break; | ||
1810 | |||
1811 | /* Drive doesn't support reading audio */ | ||
1812 | case CDROMREADAUDIO: retval = -EINVAL; break; | ||
1813 | |||
1814 | case CDROMEJECT_SW: auto_eject = (char) arg; | ||
1815 | break; | ||
1816 | |||
1817 | #ifdef MULTISESSION | ||
1818 | case CDROMMULTISESSION: retval = cdrommultisession(argp); break; | ||
1819 | #endif | ||
1820 | |||
1821 | case CDROM_GET_MCN: retval = -EINVAL; break; /* not implemented */ | ||
1822 | case CDROMVOLREAD: retval = -EINVAL; break; /* not implemented */ | ||
1823 | |||
1824 | case CDROMREADRAW: | ||
1825 | /* this drive delivers 2340 bytes in raw mode */ | ||
1826 | retval = cdromread(argp, CD_FRAMESIZE_RAW1, COMREADRAW); | ||
1827 | break; | ||
1828 | case CDROMREADCOOKED: | ||
1829 | retval = cdromread(argp, CD_FRAMESIZE, COMREAD); | ||
1830 | break; | ||
1831 | case CDROMREADALL: | ||
1832 | retval = cdromread(argp, CD_FRAMESIZE_RAWER, COMREADALL); | ||
1833 | break; | ||
1834 | |||
1835 | case CDROMSEEK: retval = cdromseek(argp); break; | ||
1836 | case CDROMPLAYBLK: retval = -EINVAL; break; /* not implemented */ | ||
1837 | case CDROMCLOSETRAY: break; /* The action was taken earlier */ | ||
1838 | default: retval = -EINVAL; | ||
1839 | } | ||
1840 | in_vfs = 0; | ||
1841 | return retval; | ||
1842 | } | ||
1843 | |||
1844 | |||
1845 | static int open_count = 0; | ||
1846 | |||
1847 | /* Open device special file; check that a disk is in. */ | ||
1848 | static int opt_open(struct inode *ip, struct file *fp) | ||
1849 | { | ||
1850 | DEBUG((DEBUG_VFS, "starting opt_open")); | ||
1851 | |||
1852 | if (!open_count && state == S_IDLE) { | ||
1853 | int status; | ||
1854 | char *buf; | ||
1855 | |||
1856 | buf = kmalloc(CD_FRAMESIZE_RAWER, GFP_KERNEL); | ||
1857 | if (!buf) { | ||
1858 | printk(KERN_INFO "optcd: cannot allocate read buffer\n"); | ||
1859 | return -ENOMEM; | ||
1860 | } | ||
1861 | optcd_disk->private_data = buf; /* save read buffer */ | ||
1862 | |||
1863 | toc_uptodate = 0; | ||
1864 | opt_invalidate_buffers(); | ||
1865 | |||
1866 | status = exec_cmd(COMCLOSE); /* close door */ | ||
1867 | if (status < 0) { | ||
1868 | DEBUG((DEBUG_VFS, "exec_cmd COMCLOSE: %02x", -status)); | ||
1869 | } | ||
1870 | |||
1871 | status = drive_status(); | ||
1872 | if (status < 0) { | ||
1873 | DEBUG((DEBUG_VFS, "drive_status: %02x", -status)); | ||
1874 | goto err_out; | ||
1875 | } | ||
1876 | DEBUG((DEBUG_VFS, "status: %02x", status)); | ||
1877 | if ((status & ST_DOOR_OPEN) || (status & ST_DRVERR)) { | ||
1878 | printk(KERN_INFO "optcd: no disk or door open\n"); | ||
1879 | goto err_out; | ||
1880 | } | ||
1881 | status = exec_cmd(COMLOCK); /* Lock door */ | ||
1882 | if (status < 0) { | ||
1883 | DEBUG((DEBUG_VFS, "exec_cmd COMLOCK: %02x", -status)); | ||
1884 | } | ||
1885 | status = update_toc(); /* Read table of contents */ | ||
1886 | if (status < 0) { | ||
1887 | DEBUG((DEBUG_VFS, "update_toc: %02x", -status)); | ||
1888 | status = exec_cmd(COMUNLOCK); /* Unlock door */ | ||
1889 | if (status < 0) { | ||
1890 | DEBUG((DEBUG_VFS, | ||
1891 | "exec_cmd COMUNLOCK: %02x", -status)); | ||
1892 | } | ||
1893 | goto err_out; | ||
1894 | } | ||
1895 | open_count++; | ||
1896 | } | ||
1897 | |||
1898 | DEBUG((DEBUG_VFS, "exiting opt_open")); | ||
1899 | |||
1900 | return 0; | ||
1901 | |||
1902 | err_out: | ||
1903 | return -EIO; | ||
1904 | } | ||
1905 | |||
1906 | |||
1907 | /* Release device special file; flush all blocks from the buffer cache */ | ||
1908 | static int opt_release(struct inode *ip, struct file *fp) | ||
1909 | { | ||
1910 | int status; | ||
1911 | |||
1912 | DEBUG((DEBUG_VFS, "executing opt_release")); | ||
1913 | DEBUG((DEBUG_VFS, "inode: %p, device: %s, file: %p\n", | ||
1914 | ip, ip->i_bdev->bd_disk->disk_name, fp)); | ||
1915 | |||
1916 | if (!--open_count) { | ||
1917 | toc_uptodate = 0; | ||
1918 | opt_invalidate_buffers(); | ||
1919 | status = exec_cmd(COMUNLOCK); /* Unlock door */ | ||
1920 | if (status < 0) { | ||
1921 | DEBUG((DEBUG_VFS, "exec_cmd COMUNLOCK: %02x", -status)); | ||
1922 | } | ||
1923 | if (auto_eject) { | ||
1924 | status = exec_cmd(COMOPEN); | ||
1925 | DEBUG((DEBUG_VFS, "exec_cmd COMOPEN: %02x", -status)); | ||
1926 | } | ||
1927 | kfree(optcd_disk->private_data); | ||
1928 | del_timer(&delay_timer); | ||
1929 | del_timer(&req_timer); | ||
1930 | } | ||
1931 | return 0; | ||
1932 | } | ||
1933 | |||
1934 | |||
1935 | /* Check if disk has been changed */ | ||
1936 | static int opt_media_change(struct gendisk *disk) | ||
1937 | { | ||
1938 | DEBUG((DEBUG_VFS, "executing opt_media_change")); | ||
1939 | DEBUG((DEBUG_VFS, "dev: %s; disk_changed = %d\n", | ||
1940 | disk->disk_name, disk_changed)); | ||
1941 | |||
1942 | if (disk_changed) { | ||
1943 | disk_changed = 0; | ||
1944 | return 1; | ||
1945 | } | ||
1946 | return 0; | ||
1947 | } | ||
1948 | |||
1949 | /* Driver initialisation */ | ||
1950 | |||
1951 | |||
1952 | /* Returns 1 if a drive is detected with a version string | ||
1953 | starting with "DOLPHIN". Otherwise 0. */ | ||
1954 | static int __init version_ok(void) | ||
1955 | { | ||
1956 | char devname[100]; | ||
1957 | int count, i, ch, status; | ||
1958 | |||
1959 | status = exec_cmd(COMVERSION); | ||
1960 | if (status < 0) { | ||
1961 | DEBUG((DEBUG_VFS, "exec_cmd COMVERSION: %02x", -status)); | ||
1962 | return 0; | ||
1963 | } | ||
1964 | if ((count = get_data(1)) < 0) { | ||
1965 | DEBUG((DEBUG_VFS, "get_data(1): %02x", -count)); | ||
1966 | return 0; | ||
1967 | } | ||
1968 | for (i = 0, ch = -1; count > 0; count--) { | ||
1969 | if ((ch = get_data(1)) < 0) { | ||
1970 | DEBUG((DEBUG_VFS, "get_data(1): %02x", -ch)); | ||
1971 | break; | ||
1972 | } | ||
1973 | if (i < 99) | ||
1974 | devname[i++] = ch; | ||
1975 | } | ||
1976 | devname[i] = '\0'; | ||
1977 | if (ch < 0) | ||
1978 | return 0; | ||
1979 | |||
1980 | printk(KERN_INFO "optcd: Device %s detected\n", devname); | ||
1981 | return ((devname[0] == 'D') | ||
1982 | && (devname[1] == 'O') | ||
1983 | && (devname[2] == 'L') | ||
1984 | && (devname[3] == 'P') | ||
1985 | && (devname[4] == 'H') | ||
1986 | && (devname[5] == 'I') | ||
1987 | && (devname[6] == 'N')); | ||
1988 | } | ||
1989 | |||
1990 | |||
1991 | static struct block_device_operations opt_fops = { | ||
1992 | .owner = THIS_MODULE, | ||
1993 | .open = opt_open, | ||
1994 | .release = opt_release, | ||
1995 | .ioctl = opt_ioctl, | ||
1996 | .media_changed = opt_media_change, | ||
1997 | }; | ||
1998 | |||
1999 | #ifndef MODULE | ||
2000 | /* Get kernel parameter when used as a kernel driver */ | ||
2001 | static int optcd_setup(char *str) | ||
2002 | { | ||
2003 | int ints[4]; | ||
2004 | (void)get_options(str, ARRAY_SIZE(ints), ints); | ||
2005 | |||
2006 | if (ints[0] > 0) | ||
2007 | optcd_port = ints[1]; | ||
2008 | |||
2009 | return 1; | ||
2010 | } | ||
2011 | |||
2012 | __setup("optcd=", optcd_setup); | ||
2013 | |||
2014 | #endif /* MODULE */ | ||
2015 | |||
2016 | /* Test for presence of drive and initialize it. Called at boot time | ||
2017 | or during module initialisation. */ | ||
2018 | static int __init optcd_init(void) | ||
2019 | { | ||
2020 | int status; | ||
2021 | |||
2022 | if (optcd_port <= 0) { | ||
2023 | printk(KERN_INFO | ||
2024 | "optcd: no Optics Storage CDROM Initialization\n"); | ||
2025 | return -EIO; | ||
2026 | } | ||
2027 | optcd_disk = alloc_disk(1); | ||
2028 | if (!optcd_disk) { | ||
2029 | printk(KERN_ERR "optcd: can't allocate disk\n"); | ||
2030 | return -ENOMEM; | ||
2031 | } | ||
2032 | optcd_disk->major = MAJOR_NR; | ||
2033 | optcd_disk->first_minor = 0; | ||
2034 | optcd_disk->fops = &opt_fops; | ||
2035 | sprintf(optcd_disk->disk_name, "optcd"); | ||
2036 | |||
2037 | if (!request_region(optcd_port, 4, "optcd")) { | ||
2038 | printk(KERN_ERR "optcd: conflict, I/O port 0x%x already used\n", | ||
2039 | optcd_port); | ||
2040 | put_disk(optcd_disk); | ||
2041 | return -EIO; | ||
2042 | } | ||
2043 | |||
2044 | if (!reset_drive()) { | ||
2045 | printk(KERN_ERR "optcd: drive at 0x%x not ready\n", optcd_port); | ||
2046 | release_region(optcd_port, 4); | ||
2047 | put_disk(optcd_disk); | ||
2048 | return -EIO; | ||
2049 | } | ||
2050 | if (!version_ok()) { | ||
2051 | printk(KERN_ERR "optcd: unknown drive detected; aborting\n"); | ||
2052 | release_region(optcd_port, 4); | ||
2053 | put_disk(optcd_disk); | ||
2054 | return -EIO; | ||
2055 | } | ||
2056 | status = exec_cmd(COMINITDOUBLE); | ||
2057 | if (status < 0) { | ||
2058 | printk(KERN_ERR "optcd: cannot init double speed mode\n"); | ||
2059 | release_region(optcd_port, 4); | ||
2060 | DEBUG((DEBUG_VFS, "exec_cmd COMINITDOUBLE: %02x", -status)); | ||
2061 | put_disk(optcd_disk); | ||
2062 | return -EIO; | ||
2063 | } | ||
2064 | if (register_blkdev(MAJOR_NR, "optcd")) { | ||
2065 | release_region(optcd_port, 4); | ||
2066 | put_disk(optcd_disk); | ||
2067 | return -EIO; | ||
2068 | } | ||
2069 | |||
2070 | |||
2071 | opt_queue = blk_init_queue(do_optcd_request, &optcd_lock); | ||
2072 | if (!opt_queue) { | ||
2073 | unregister_blkdev(MAJOR_NR, "optcd"); | ||
2074 | release_region(optcd_port, 4); | ||
2075 | put_disk(optcd_disk); | ||
2076 | return -ENOMEM; | ||
2077 | } | ||
2078 | |||
2079 | blk_queue_hardsect_size(opt_queue, 2048); | ||
2080 | optcd_disk->queue = opt_queue; | ||
2081 | add_disk(optcd_disk); | ||
2082 | |||
2083 | printk(KERN_INFO "optcd: DOLPHIN 8000 AT CDROM at 0x%x\n", optcd_port); | ||
2084 | return 0; | ||
2085 | } | ||
2086 | |||
2087 | |||
2088 | static void __exit optcd_exit(void) | ||
2089 | { | ||
2090 | del_gendisk(optcd_disk); | ||
2091 | put_disk(optcd_disk); | ||
2092 | if (unregister_blkdev(MAJOR_NR, "optcd") == -EINVAL) { | ||
2093 | printk(KERN_ERR "optcd: what's that: can't unregister\n"); | ||
2094 | return; | ||
2095 | } | ||
2096 | blk_cleanup_queue(opt_queue); | ||
2097 | release_region(optcd_port, 4); | ||
2098 | printk(KERN_INFO "optcd: module released.\n"); | ||
2099 | } | ||
2100 | |||
2101 | module_init(optcd_init); | ||
2102 | module_exit(optcd_exit); | ||
2103 | |||
2104 | MODULE_LICENSE("GPL"); | ||
2105 | MODULE_ALIAS_BLOCKDEV_MAJOR(OPTICS_CDROM_MAJOR); | ||
diff --git a/drivers/cdrom/optcd.h b/drivers/cdrom/optcd.h deleted file mode 100644 index 1911bb92ee28..000000000000 --- a/drivers/cdrom/optcd.h +++ /dev/null | |||
@@ -1,52 +0,0 @@ | |||
1 | /* linux/include/linux/optcd.h - Optics Storage 8000 AT CDROM driver | ||
2 | $Id: optcd.h,v 1.2 1996/01/15 18:43:44 root Exp root $ | ||
3 | |||
4 | Copyright (C) 1995 Leo Spiekman (spiekman@dutette.et.tudelft.nl) | ||
5 | |||
6 | |||
7 | Configuration file for linux/drivers/cdrom/optcd.c | ||
8 | */ | ||
9 | |||
10 | #ifndef _LINUX_OPTCD_H | ||
11 | #define _LINUX_OPTCD_H | ||
12 | |||
13 | |||
14 | /* I/O base of drive. Drive uses base to base+2. | ||
15 | This setting can be overridden with the kernel or insmod command | ||
16 | line option 'optcd=<portbase>'. Use address of 0 to disable driver. */ | ||
17 | #define OPTCD_PORTBASE 0x340 | ||
18 | |||
19 | |||
20 | /* enable / disable parts of driver by define / undef */ | ||
21 | #define MULTISESSION /* multisession support (ALPHA) */ | ||
22 | |||
23 | |||
24 | /* Change 0 to 1 to debug various parts of the driver */ | ||
25 | #define DEBUG_DRIVE_IF 0 /* Low level drive interface */ | ||
26 | #define DEBUG_CONV 0 /* Address conversions */ | ||
27 | #define DEBUG_BUFFERS 0 /* Buffering and block size conversion */ | ||
28 | #define DEBUG_REQUEST 0 /* Request mechanism */ | ||
29 | #define DEBUG_STATE 0 /* State machine */ | ||
30 | #define DEBUG_TOC 0 /* Q-channel and Table of Contents */ | ||
31 | #define DEBUG_MULTIS 0 /* Multisession code */ | ||
32 | #define DEBUG_VFS 0 /* VFS interface */ | ||
33 | |||
34 | |||
35 | /* Don't touch these unless you know what you're doing. */ | ||
36 | |||
37 | /* Various timeout loop repetition counts. */ | ||
38 | #define BUSY_TIMEOUT 10000000 /* for busy wait */ | ||
39 | #define FAST_TIMEOUT 100000 /* ibid. for probing */ | ||
40 | #define SLEEP_TIMEOUT 6000 /* for timer wait */ | ||
41 | #define MULTI_SEEK_TIMEOUT 1000 /* for timer wait */ | ||
42 | #define READ_TIMEOUT 6000 /* for poll wait */ | ||
43 | #define STOP_TIMEOUT 2000 /* for poll wait */ | ||
44 | #define RESET_WAIT 5000 /* busy wait at drive reset */ | ||
45 | |||
46 | /* # of buffers for block size conversion. 6 is optimal for my setup (P75), | ||
47 | giving 280 kb/s, with 0.4% CPU usage. Experiment to find your optimal | ||
48 | setting */ | ||
49 | #define N_BUFS 6 | ||
50 | |||
51 | |||
52 | #endif /* _LINUX_OPTCD_H */ | ||
diff --git a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c deleted file mode 100644 index a1283b1ef989..000000000000 --- a/drivers/cdrom/sbpcd.c +++ /dev/null | |||
@@ -1,5966 +0,0 @@ | |||
1 | /* | ||
2 | * sbpcd.c CD-ROM device driver for the whole family of traditional, | ||
3 | * non-ATAPI IDE-style Matsushita/Panasonic CR-5xx drives. | ||
4 | * Works with SoundBlaster compatible cards and with "no-sound" | ||
5 | * interface cards like Lasermate, Panasonic CI-101P, Teac, ... | ||
6 | * Also for the Longshine LCS-7260 drive. | ||
7 | * Also for the IBM "External ISA CD-Rom" drive. | ||
8 | * Also for the CreativeLabs CD200 drive. | ||
9 | * Also for the TEAC CD-55A drive. | ||
10 | * Also for the ECS-AT "Vertos 100" drive. | ||
11 | * Not for Sanyo drives (but for the H94A, sjcd is there...). | ||
12 | * Not for any other Funai drives than the CD200 types (sometimes | ||
13 | * labelled E2550UA or MK4015 or 2800F). | ||
14 | */ | ||
15 | |||
16 | #define VERSION "v4.63 Andrew J. Kroll <ag784@freenet.buffalo.edu> Wed Jul 26 04:24:10 EDT 2000" | ||
17 | |||
18 | /* Copyright (C) 1993, 1994, 1995 Eberhard Moenkeberg <emoenke@gwdg.de> | ||
19 | * | ||
20 | * This program is free software; you can redistribute it and/or modify | ||
21 | * it under the terms of the GNU General Public License as published by | ||
22 | * the Free Software Foundation; either version 2, or (at your option) | ||
23 | * any later version. | ||
24 | * | ||
25 | * You should have received a copy of the GNU General Public License | ||
26 | * (for example /usr/src/linux/COPYING); if not, write to the Free | ||
27 | * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
28 | * | ||
29 | * If you change this software, you should mail a .diff file with some | ||
30 | * description lines to emoenke@gwdg.de. I want to know about it. | ||
31 | * | ||
32 | * If you are the editor of a Linux CD, you should enable sbpcd.c within | ||
33 | * your boot floppy kernel and send me one of your CDs for free. | ||
34 | * | ||
35 | * If you would like to port the driver to an other operating system (f.e. | ||
36 | * FreeBSD or NetBSD) or use it as an information source, you shall not be | ||
37 | * restricted by the GPL under the following conditions: | ||
38 | * a) the source code of your work is freely available | ||
39 | * b) my part of the work gets mentioned at all places where your | ||
40 | * authorship gets mentioned | ||
41 | * c) I receive a copy of your code together with a full installation | ||
42 | * package of your operating system for free. | ||
43 | * | ||
44 | * | ||
45 | * VERSION HISTORY | ||
46 | * | ||
47 | * 0.1 initial release, April/May 93, after mcd.c (Martin Harriss) | ||
48 | * | ||
49 | * 0.2 thek "repeat:"-loop in do_sbpcd_request did not check for | ||
50 | * end-of-request_queue (resulting in kernel panic). | ||
51 | * Flow control seems stable, but throughput is not better. | ||
52 | * | ||
53 | * 0.3 interrupt locking totally eliminated (maybe "inb" and "outb" | ||
54 | * are still locking) - 0.2 made keyboard-type-ahead losses. | ||
55 | * check_sbpcd_media_change added (to use by isofs/inode.c) | ||
56 | * - but it detects almost nothing. | ||
57 | * | ||
58 | * 0.4 use MAJOR 25 definitely. | ||
59 | * Almost total re-design to support double-speed drives and | ||
60 | * "naked" (no sound) interface cards ("LaserMate" interface type). | ||
61 | * Flow control should be exact now. | ||
62 | * Don't occupy the SbPro IRQ line (not needed either); will | ||
63 | * live together with Hannu Savolainen's sndkit now. | ||
64 | * Speeded up data transfer to 150 kB/sec, with help from Kai | ||
65 | * Makisara, the "provider" of the "mt" tape utility. | ||
66 | * Give "SpinUp" command if necessary. | ||
67 | * First steps to support up to 4 drives (but currently only one). | ||
68 | * Implemented audio capabilities - workman should work, xcdplayer | ||
69 | * gives some problems. | ||
70 | * This version is still consuming too much CPU time, and | ||
71 | * sleeping still has to be worked on. | ||
72 | * During "long" implied seeks, it seems possible that a | ||
73 | * ReadStatus command gets ignored. That gives the message | ||
74 | * "ResponseStatus timed out" (happens about 6 times here during | ||
75 | * a "ls -alR" of the YGGDRASIL LGX-Beta CD). Such a case is | ||
76 | * handled without data error, but it should get done better. | ||
77 | * | ||
78 | * 0.5 Free CPU during waits (again with help from Kai Makisara). | ||
79 | * Made it work together with the LILO/kernel setup standard. | ||
80 | * Included auto-probing code, as suggested by YGGDRASIL. | ||
81 | * Formal redesign to add DDI debugging. | ||
82 | * There are still flaws in IOCTL (workman with double speed drive). | ||
83 | * | ||
84 | * 1.0 Added support for all drive IDs (0...3, no longer only 0) | ||
85 | * and up to 4 drives on one controller. | ||
86 | * Added "#define MANY_SESSION" for "old" multi session CDs. | ||
87 | * | ||
88 | * 1.1 Do SpinUp for new drives, too. | ||
89 | * Revised for clean compile under "old" kernels (0.99pl9). | ||
90 | * | ||
91 | * 1.2 Found the "workman with double-speed drive" bug: use the driver's | ||
92 | * audio_state, not what the drive is reporting with ReadSubQ. | ||
93 | * | ||
94 | * 1.3 Minor cleanups. | ||
95 | * Refinements regarding Workman. | ||
96 | * | ||
97 | * 1.4 Read XA disks (PhotoCDs) with "old" drives, too (but only the first | ||
98 | * session - no chance to fully access a "multi-session" CD). | ||
99 | * This currently still is too slow (50 kB/sec) - but possibly | ||
100 | * the old drives won't do it faster. | ||
101 | * Implemented "door (un)lock" for new drives (still does not work | ||
102 | * as wanted - no lock possible after an unlock). | ||
103 | * Added some debugging printout for the UPC/EAN code - but my drives | ||
104 | * return only zeroes. Is there no UPC/EAN code written? | ||
105 | * | ||
106 | * 1.5 Laborate with UPC/EAN code (not better yet). | ||
107 | * Adapt to kernel 1.1.8 change (have to explicitly include | ||
108 | * <linux/string.h> now). | ||
109 | * | ||
110 | * 1.6 Trying to read audio frames as data. Impossible with the current | ||
111 | * drive firmware levels, as it seems. Awaiting any hint. ;-) | ||
112 | * Changed "door unlock": repeat it until success. | ||
113 | * Changed CDROMSTOP routine (stop somewhat "softer" so that Workman | ||
114 | * won't get confused). | ||
115 | * Added a third interface type: Sequoia S-1000, as used with the SPEA | ||
116 | * Media FX sound card. This interface (usable for Sony and Mitsumi | ||
117 | * drives, too) needs a special configuration setup and behaves like a | ||
118 | * LaserMate type after that. Still experimental - I do not have such | ||
119 | * an interface. | ||
120 | * Use the "variable BLOCK_SIZE" feature (2048). But it does only work | ||
121 | * if you give the mount option "block=2048". | ||
122 | * The media_check routine is currently disabled; now that it gets | ||
123 | * called as it should I fear it must get synchronized for not to | ||
124 | * disturb the normal driver's activity. | ||
125 | * | ||
126 | * 2.0 Version number bumped - two reasons: | ||
127 | * - reading audio tracks as data works now with CR-562 and CR-563. We | ||
128 | * currently do it by an IOCTL (yet has to get standardized), one frame | ||
129 | * at a time; that is pretty slow. But it works. | ||
130 | * - we are maintaining now up to 4 interfaces (each up to 4 drives): | ||
131 | * did it the easy way - a different MAJOR (25, 26, ...) and a different | ||
132 | * copy of the driver (sbpcd.c, sbpcd2.c, sbpcd3.c, sbpcd4.c - only | ||
133 | * distinguished by the value of SBPCD_ISSUE and the driver's name), | ||
134 | * and a common sbpcd.h file. | ||
135 | * Bettered the "ReadCapacity error" problem with old CR-52x drives (the | ||
136 | * drives sometimes need a manual "eject/insert" before work): just | ||
137 | * reset the drive and do again. Needs lots of resets here and sometimes | ||
138 | * that does not cure, so this can't be the solution. | ||
139 | * | ||
140 | * 2.1 Found bug with multisession CDs (accessing frame 16). | ||
141 | * "read audio" works now with address type CDROM_MSF, too. | ||
142 | * Bigger audio frame buffer: allows reading max. 4 frames at time; this | ||
143 | * gives a significant speedup, but reading more than one frame at once | ||
144 | * gives missing chunks at each single frame boundary. | ||
145 | * | ||
146 | * 2.2 Kernel interface cleanups: timers, init, setup, media check. | ||
147 | * | ||
148 | * 2.3 Let "door lock" and "eject" live together. | ||
149 | * Implemented "close tray" (done automatically during open). | ||
150 | * | ||
151 | * 2.4 Use different names for device registering. | ||
152 | * | ||
153 | * 2.5 Added "#if EJECT" code (default: enabled) to automatically eject | ||
154 | * the tray during last call to "sbpcd_release". | ||
155 | * Added "#if JUKEBOX" code (default: disabled) to automatically eject | ||
156 | * the tray during call to "sbpcd_open" if no disk is in. | ||
157 | * Turn on the CD volume of "compatible" sound cards, too; just define | ||
158 | * SOUND_BASE (in sbpcd.h) accordingly (default: disabled). | ||
159 | * | ||
160 | * 2.6 Nothing new. | ||
161 | * | ||
162 | * 2.7 Added CDROMEJECT_SW ioctl to set the "EJECT" behavior on the fly: | ||
163 | * 0 disables, 1 enables auto-ejecting. Useful to keep the tray in | ||
164 | * during shutdown. | ||
165 | * | ||
166 | * 2.8 Added first support (still BETA, I need feedback or a drive) for | ||
167 | * the Longshine LCS-7260 drives. They appear as double-speed drives | ||
168 | * using the "old" command scheme, extended by tray control and door | ||
169 | * lock functions. | ||
170 | * Found (and fixed preliminary) a flaw with some multisession CDs: we | ||
171 | * have to re-direct not only the accesses to frame 16 (the isofs | ||
172 | * routines drive it up to max. 100), but also those to the continuation | ||
173 | * (repetition) frames (as far as they exist - currently set fix as | ||
174 | * 16..20). | ||
175 | * Changed default of the "JUKEBOX" define. If you use this default, | ||
176 | * your tray will eject if you try to mount without a disk in. Next | ||
177 | * mount command will insert the tray - so, just fill in a disk. ;-) | ||
178 | * | ||
179 | * 2.9 Fulfilled the Longshine LCS-7260 support; with great help and | ||
180 | * experiments by Serge Robyns. | ||
181 | * First attempts to support the TEAC CD-55A drives; but still not | ||
182 | * usable yet. | ||
183 | * Implemented the CDROMMULTISESSION ioctl; this is an attempt to handle | ||
184 | * multi session CDs more "transparent" (redirection handling has to be | ||
185 | * done within the isofs routines, and only for the special purpose of | ||
186 | * obtaining the "right" volume descriptor; accesses to the raw device | ||
187 | * should not get redirected). | ||
188 | * | ||
189 | * 3.0 Just a "normal" increment, with some provisions to do it better. ;-) | ||
190 | * Introduced "#define READ_AUDIO" to specify the maximum number of | ||
191 | * audio frames to grab with one request. This defines a buffer size | ||
192 | * within kernel space; a value of 0 will reserve no such space and | ||
193 | * disable the CDROMREADAUDIO ioctl. A value of 75 enables the reading | ||
194 | * of a whole second with one command, but will use a buffer of more | ||
195 | * than 172 kB. | ||
196 | * Started CD200 support. Drive detection should work, but nothing | ||
197 | * more. | ||
198 | * | ||
199 | * 3.1 Working to support the CD200 and the Teac CD-55A drives. | ||
200 | * AT-BUS style device numbering no longer used: use SCSI style now. | ||
201 | * So, the first "found" device has MINOR 0, regardless of the | ||
202 | * jumpered drive ID. This implies modifications to the /dev/sbpcd* | ||
203 | * entries for some people, but will help the DAU (german TLA, english: | ||
204 | * "newbie", maybe ;-) to install his "first" system from a CD. | ||
205 | * | ||
206 | * 3.2 Still testing with CD200 and CD-55A drives. | ||
207 | * | ||
208 | * 3.3 Working with CD200 support. | ||
209 | * | ||
210 | * 3.4 Auto-probing stops if an address of 0 is seen (to be entered with | ||
211 | * the kernel command line). | ||
212 | * Made the driver "loadable". If used as a module, "audio copy" is | ||
213 | * disabled, and the internal read ahead data buffer has a reduced size | ||
214 | * of 4 kB; so, throughput may be reduced a little bit with slow CPUs. | ||
215 | * | ||
216 | * 3.5 Provisions to handle weird photoCDs which have an interrupted | ||
217 | * "formatting" immediately after the last frames of some files: simply | ||
218 | * never "read ahead" with MultiSession CDs. By this, CPU usage may be | ||
219 | * increased with those CDs, and there may be a loss in speed. | ||
220 | * Re-structured the messaging system. | ||
221 | * The "loadable" version no longer has a limited READ_AUDIO buffer | ||
222 | * size. | ||
223 | * Removed "MANY_SESSION" handling for "old" multi session CDs. | ||
224 | * Added "private" IOCTLs CDROMRESET and CDROMVOLREAD. | ||
225 | * Started again to support the TEAC CD-55A drives, now that I found | ||
226 | * the money for "my own" drive. ;-) | ||
227 | * The TEAC CD-55A support is fairly working now. | ||
228 | * I have measured that the drive "delivers" at 600 kB/sec (even with | ||
229 | * bigger requests than the drive's 64 kB buffer can satisfy), but | ||
230 | * the "real" rate does not exceed 520 kB/sec at the moment. | ||
231 | * Caused by the various changes to build in TEAC support, the timed | ||
232 | * loops are de-optimized at the moment (less throughput with CR-52x | ||
233 | * drives, and the TEAC will give speed only with SBP_BUFFER_FRAMES 64). | ||
234 | * | ||
235 | * 3.6 Fixed TEAC data read problems with SbPro interfaces. | ||
236 | * Initial size of the READ_AUDIO buffer is 0. Can get set to any size | ||
237 | * during runtime. | ||
238 | * | ||
239 | * 3.7 Introduced MAX_DRIVES for some poor interface cards (seen with TEAC | ||
240 | * drives) which allow only one drive (ID 0); this avoids repetitive | ||
241 | * detection under IDs 1..3. | ||
242 | * Elongated cmd_out_T response waiting; necessary for photo CDs with | ||
243 | * a lot of sessions. | ||
244 | * Bettered the sbpcd_open() behavior with TEAC drives. | ||
245 | * | ||
246 | * 3.8 Elongated max_latency for CR-56x drives. | ||
247 | * | ||
248 | * 3.9 Finally fixed the long-known SoundScape/SPEA/Sequoia S-1000 interface | ||
249 | * configuration bug. | ||
250 | * Now Corey, Heiko, Ken, Leo, Vadim/Eric & Werner are invited to copy | ||
251 | * the config_spea() routine into their drivers. ;-) | ||
252 | * | ||
253 | * 4.0 No "big step" - normal version increment. | ||
254 | * Adapted the benefits from 1.3.33. | ||
255 | * Fiddled with CDROMREADAUDIO flaws. | ||
256 | * Avoid ReadCapacity command with CD200 drives (the MKE 1.01 version | ||
257 | * seems not to support it). | ||
258 | * Fulfilled "read audio" for CD200 drives, with help of Pete Heist | ||
259 | * (heistp@rpi.edu). | ||
260 | * | ||
261 | * 4.1 Use loglevel KERN_INFO with printk(). | ||
262 | * Added support for "Vertos 100" drive ("ECS-AT") - it is very similar | ||
263 | * to the Longshine LCS-7260. Give feedback if you can - I never saw | ||
264 | * such a drive, and I have no specs. | ||
265 | * | ||
266 | * 4.2 Support for Teac 16-bit interface cards. Can't get auto-detected, | ||
267 | * so you have to jumper your card to 0x2C0. Still not 100% - come | ||
268 | * in contact if you can give qualified feedback. | ||
269 | * Use loglevel KERN_NOTICE with printk(). If you get annoyed by a | ||
270 | * flood of unwanted messages and the accompanied delay, try to read | ||
271 | * my documentation. Especially the Linux CDROM drivers have to do an | ||
272 | * important job for the newcomers, so the "distributed" version has | ||
273 | * to fit some special needs. Since generations, the flood of messages | ||
274 | * is user-configurable (even at runtime), but to get aware of this, one | ||
275 | * needs a special mental quality: the ability to read. | ||
276 | * | ||
277 | * 4.3 CD200F does not like to receive a command while the drive is | ||
278 | * reading the ToC; still trying to solve it. | ||
279 | * Removed some redundant verify_area calls (yes, Heiko Eissfeldt | ||
280 | * is visiting all the Linux CDROM drivers ;-). | ||
281 | * | ||
282 | * 4.4 Adapted one idea from tiensivu@pilot.msu.edu's "stripping-down" | ||
283 | * experiments: "KLOGD_PAUSE". | ||
284 | * Inhibited "play audio" attempts with data CDs. Provisions for a | ||
285 | * "data-safe" handling of "mixed" (data plus audio) Cds. | ||
286 | * | ||
287 | * 4.5 Meanwhile Gonzalo Tornaria <tornaria@cmat.edu.uy> (GTL) built a | ||
288 | * special end_request routine: we seem to have to take care for not | ||
289 | * to have two processes working at the request list. My understanding | ||
290 | * was and is that ll_rw_blk should not call do_sbpcd_request as long | ||
291 | * as there is still one call active (the first call will care for all | ||
292 | * outstanding I/Os, and if a second call happens, that is a bug in | ||
293 | * ll_rw_blk.c). | ||
294 | * "Check media change" without touching any drive. | ||
295 | * | ||
296 | * 4.6 Use a semaphore to synchronize multi-activity; elaborated by Rob | ||
297 | * Riggs <rriggs@tesser.com>. At the moment, we simply block "read" | ||
298 | * against "ioctl" and vice versa. This could be refined further, but | ||
299 | * I guess with almost no performance increase. | ||
300 | * Experiments to speed up the CD-55A; again with help of Rob Riggs | ||
301 | * (to be true, he gave both, idea & code. ;-) | ||
302 | * | ||
303 | * 4.61 Ported to Uniform CD-ROM driver by | ||
304 | * Heiko Eissfeldt <heiko@colossus.escape.de> with additional | ||
305 | * changes by Erik Andersen <andersee@debian.org> | ||
306 | * | ||
307 | * 4.62 Fix a bug where playing audio left the drive in an unusable state. | ||
308 | * Heiko Eissfeldt <heiko@colossus.escape.de> | ||
309 | * | ||
310 | * November 1999 -- Make kernel-parameter implementation work with 2.3.x | ||
311 | * Removed init_module & cleanup_module in favor of | ||
312 | * module_init & module_exit. | ||
313 | * Torben Mathiasen <tmm@image.dk> | ||
314 | * | ||
315 | * 4.63 Bug fixes for audio annoyances, new legacy CDROM maintainer. | ||
316 | * Annoying things fixed: | ||
317 | * TOC reread on automated disk changes | ||
318 | * TOC reread on manual cd changes | ||
319 | * Play IOCTL tries to play CD before it's actually ready... sometimes. | ||
320 | * CD_AUDIO_COMPLETED state so workman (and other playes) can repeat play. | ||
321 | * Andrew J. Kroll <ag784@freenet.buffalo.edu> Wed Jul 26 04:24:10 EDT 2000 | ||
322 | * | ||
323 | * 4.64 Fix module parameters - were being completely ignored. | ||
324 | * Can also specify max_drives=N as a setup int to get rid of | ||
325 | * "ghost" drives on crap hardware (aren't they all?) Paul Gortmaker | ||
326 | * | ||
327 | * TODO | ||
328 | * implement "read all subchannel data" (96 bytes per frame) | ||
329 | * remove alot of the virtual status bits and deal with hardware status | ||
330 | * move the change of cd for audio to a better place | ||
331 | * add debug levels to insmod parameters (trivial) | ||
332 | * | ||
333 | * special thanks to Kai Makisara (kai.makisara@vtt.fi) for his fine | ||
334 | * elaborated speed-up experiments (and the fabulous results!), for | ||
335 | * the "push" towards load-free wait loops, and for the extensive mail | ||
336 | * thread which brought additional hints and bug fixes. | ||
337 | * | ||
338 | */ | ||
339 | |||
340 | /* | ||
341 | * Trying to merge requests breaks this driver horribly (as in it goes | ||
342 | * boom and apparently has done so since 2.3.41). As it is a legacy | ||
343 | * driver for a horribly slow double speed CD on a hideous interface | ||
344 | * designed for polled operation, I won't lose any sleep in simply | ||
345 | * disallowing merging. Paul G. 02/2001 | ||
346 | * | ||
347 | * Thu May 30 14:14:47 CEST 2002: | ||
348 | * | ||
349 | * I have presumably found the reson for the above - there was a bogous | ||
350 | * end_request substitute, which was manipulating the request queues | ||
351 | * incorrectly. If someone has access to the actual hardware, and it's | ||
352 | * still operations - well please free to test it. | ||
353 | * | ||
354 | * Marcin Dalecki | ||
355 | */ | ||
356 | |||
357 | /* | ||
358 | * Add bio/kdev_t changes for 2.5.x required to make it work again. | ||
359 | * Still room for improvement in the request handling here if anyone | ||
360 | * actually cares. Bring your own chainsaw. Paul G. 02/2002 | ||
361 | */ | ||
362 | |||
363 | |||
364 | #include <linux/module.h> | ||
365 | |||
366 | #include <linux/errno.h> | ||
367 | #include <linux/sched.h> | ||
368 | #include <linux/mm.h> | ||
369 | #include <linux/timer.h> | ||
370 | #include <linux/fs.h> | ||
371 | #include <linux/kernel.h> | ||
372 | #include <linux/cdrom.h> | ||
373 | #include <linux/ioport.h> | ||
374 | #include <linux/major.h> | ||
375 | #include <linux/string.h> | ||
376 | #include <linux/vmalloc.h> | ||
377 | #include <linux/init.h> | ||
378 | #include <linux/interrupt.h> | ||
379 | |||
380 | #include <asm/system.h> | ||
381 | #include <asm/io.h> | ||
382 | #include <asm/uaccess.h> | ||
383 | #include <stdarg.h> | ||
384 | #include "sbpcd.h" | ||
385 | |||
386 | #define MAJOR_NR MATSUSHITA_CDROM_MAJOR | ||
387 | #include <linux/blkdev.h> | ||
388 | |||
389 | /*==========================================================================*/ | ||
390 | #if SBPCD_DIS_IRQ | ||
391 | # define SBPCD_CLI cli() | ||
392 | # define SBPCD_STI sti() | ||
393 | #else | ||
394 | # define SBPCD_CLI | ||
395 | # define SBPCD_STI | ||
396 | #endif | ||
397 | |||
398 | /*==========================================================================*/ | ||
399 | /* | ||
400 | * auto-probing address list | ||
401 | * inspired by Adam J. Richter from Yggdrasil | ||
402 | * | ||
403 | * still not good enough - can cause a hang. | ||
404 | * example: a NE 2000 ethernet card at 300 will cause a hang probing 310. | ||
405 | * if that happens, reboot and use the LILO (kernel) command line. | ||
406 | * The possibly conflicting ethernet card addresses get NOT probed | ||
407 | * by default - to minimize the hang possibilities. | ||
408 | * | ||
409 | * The SB Pro addresses get "mirrored" at 0x6xx and some more locations - to | ||
410 | * avoid a type error, the 0x2xx-addresses must get checked before 0x6xx. | ||
411 | * | ||
412 | * send mail to emoenke@gwdg.de if your interface card is not FULLY | ||
413 | * represented here. | ||
414 | */ | ||
415 | static int sbpcd[] = | ||
416 | { | ||
417 | CDROM_PORT, SBPRO, /* probe with user's setup first */ | ||
418 | #if DISTRIBUTION | ||
419 | 0x230, 1, /* Soundblaster Pro and 16 (default) */ | ||
420 | #if 0 | ||
421 | 0x300, 0, /* CI-101P (default), WDH-7001C (default), | ||
422 | Galaxy (default), Reveal (one default) */ | ||
423 | 0x250, 1, /* OmniCD default, Soundblaster Pro and 16 */ | ||
424 | 0x2C0, 3, /* Teac 16-bit cards */ | ||
425 | 0x260, 1, /* OmniCD */ | ||
426 | 0x320, 0, /* Lasermate, CI-101P, WDH-7001C, Galaxy, Reveal (other default), | ||
427 | Longshine LCS-6853 (default) */ | ||
428 | 0x338, 0, /* Reveal Sound Wave 32 card model #SC600 */ | ||
429 | 0x340, 0, /* Mozart sound card (default), Lasermate, CI-101P */ | ||
430 | 0x360, 0, /* Lasermate, CI-101P */ | ||
431 | 0x270, 1, /* Soundblaster 16 */ | ||
432 | 0x670, 0, /* "sound card #9" */ | ||
433 | 0x690, 0, /* "sound card #9" */ | ||
434 | 0x338, 2, /* SPEA Media FX, Ensonic SoundScape (default) */ | ||
435 | 0x328, 2, /* SPEA Media FX */ | ||
436 | 0x348, 2, /* SPEA Media FX */ | ||
437 | 0x634, 0, /* some newer sound cards */ | ||
438 | 0x638, 0, /* some newer sound cards */ | ||
439 | 0x230, 1, /* some newer sound cards */ | ||
440 | /* due to incomplete address decoding of the SbPro card, these must be last */ | ||
441 | 0x630, 0, /* "sound card #9" (default) */ | ||
442 | 0x650, 0, /* "sound card #9" */ | ||
443 | #ifdef MODULE | ||
444 | /* | ||
445 | * some "hazardous" locations (no harm with the loadable version) | ||
446 | * (will stop the bus if a NE2000 ethernet card resides at offset -0x10) | ||
447 | */ | ||
448 | 0x330, 0, /* Lasermate, CI-101P, WDH-7001C */ | ||
449 | 0x350, 0, /* Lasermate, CI-101P */ | ||
450 | 0x358, 2, /* SPEA Media FX */ | ||
451 | 0x370, 0, /* Lasermate, CI-101P */ | ||
452 | 0x290, 1, /* Soundblaster 16 */ | ||
453 | 0x310, 0, /* Lasermate, CI-101P, WDH-7001C */ | ||
454 | #endif /* MODULE */ | ||
455 | #endif | ||
456 | #endif /* DISTRIBUTION */ | ||
457 | }; | ||
458 | |||
459 | /* | ||
460 | * Protects access to global structures etc. | ||
461 | */ | ||
462 | static __cacheline_aligned DEFINE_SPINLOCK(sbpcd_lock); | ||
463 | static struct request_queue *sbpcd_queue; | ||
464 | |||
465 | /* You can only set the first pair, from old MODULE_PARM code. */ | ||
466 | static int sbpcd_set(const char *val, struct kernel_param *kp) | ||
467 | { | ||
468 | get_options((char *)val, 2, (int *)sbpcd); | ||
469 | return 0; | ||
470 | } | ||
471 | module_param_call(sbpcd, sbpcd_set, NULL, NULL, 0); | ||
472 | |||
473 | #define NUM_PROBE (sizeof(sbpcd) / sizeof(int)) | ||
474 | |||
475 | /*==========================================================================*/ | ||
476 | |||
477 | #define INLINE inline | ||
478 | |||
479 | /*==========================================================================*/ | ||
480 | /* | ||
481 | * the forward references: | ||
482 | */ | ||
483 | static void sbp_sleep(u_int); | ||
484 | static void mark_timeout_delay(u_long); | ||
485 | static void mark_timeout_data(u_long); | ||
486 | #if 0 | ||
487 | static void mark_timeout_audio(u_long); | ||
488 | #endif | ||
489 | static void sbp_read_cmd(struct request *req); | ||
490 | static int sbp_data(struct request *req); | ||
491 | static int cmd_out(void); | ||
492 | static int DiskInfo(void); | ||
493 | |||
494 | /*==========================================================================*/ | ||
495 | |||
496 | /* | ||
497 | * pattern for printk selection: | ||
498 | * | ||
499 | * (1<<DBG_INF) necessary information | ||
500 | * (1<<DBG_BSZ) BLOCK_SIZE trace | ||
501 | * (1<<DBG_REA) "read" status trace | ||
502 | * (1<<DBG_CHK) "media check" trace | ||
503 | * (1<<DBG_TIM) datarate timer test | ||
504 | * (1<<DBG_INI) initialization trace | ||
505 | * (1<<DBG_TOC) tell TocEntry values | ||
506 | * (1<<DBG_IOC) ioctl trace | ||
507 | * (1<<DBG_STA) "ResponseStatus" trace | ||
508 | * (1<<DBG_ERR) "cc_ReadError" trace | ||
509 | * (1<<DBG_CMD) "cmd_out" trace | ||
510 | * (1<<DBG_WRN) give explanation before auto-probing | ||
511 | * (1<<DBG_MUL) multi session code test | ||
512 | * (1<<DBG_IDX) "drive_id != 0" test code | ||
513 | * (1<<DBG_IOX) some special information | ||
514 | * (1<<DBG_DID) drive ID test | ||
515 | * (1<<DBG_RES) drive reset info | ||
516 | * (1<<DBG_SPI) SpinUp test info | ||
517 | * (1<<DBG_IOS) ioctl trace: "subchannel" | ||
518 | * (1<<DBG_IO2) ioctl trace: general | ||
519 | * (1<<DBG_UPC) show UPC info | ||
520 | * (1<<DBG_XA1) XA mode debugging | ||
521 | * (1<<DBG_LCK) door (un)lock info | ||
522 | * (1<<DBG_SQ1) dump SubQ frame | ||
523 | * (1<<DBG_AUD) "read audio" debugging | ||
524 | * (1<<DBG_SEQ) Sequoia interface configuration trace | ||
525 | * (1<<DBG_LCS) Longshine LCS-7260 debugging trace | ||
526 | * (1<<DBG_CD2) MKE/Funai CD200 debugging trace | ||
527 | * (1<<DBG_TEA) TEAC CD-55A debugging trace | ||
528 | * (1<<DBG_ECS) ECS-AT (Vertos-100) debugging trace | ||
529 | * (1<<DBG_000) unnecessary information | ||
530 | */ | ||
531 | #if DISTRIBUTION | ||
532 | static int sbpcd_debug = (1<<DBG_INF); | ||
533 | #else | ||
534 | static int sbpcd_debug = 0 & ((1<<DBG_INF) | | ||
535 | (1<<DBG_TOC) | | ||
536 | (1<<DBG_MUL) | | ||
537 | (1<<DBG_UPC)); | ||
538 | #endif /* DISTRIBUTION */ | ||
539 | |||
540 | static int sbpcd_ioaddr = CDROM_PORT; /* default I/O base address */ | ||
541 | static int sbpro_type = SBPRO; | ||
542 | static unsigned char f_16bit; | ||
543 | static unsigned char do_16bit; | ||
544 | static int CDo_command, CDo_reset; | ||
545 | static int CDo_sel_i_d, CDo_enable; | ||
546 | static int CDi_info, CDi_status, CDi_data; | ||
547 | static struct cdrom_msf msf; | ||
548 | static struct cdrom_ti ti; | ||
549 | static struct cdrom_tochdr tochdr; | ||
550 | static struct cdrom_tocentry tocentry; | ||
551 | static struct cdrom_subchnl SC; | ||
552 | static struct cdrom_volctrl volctrl; | ||
553 | static struct cdrom_read_audio read_audio; | ||
554 | |||
555 | static unsigned char msgnum; | ||
556 | static char msgbuf[80]; | ||
557 | |||
558 | static int max_drives = MAX_DRIVES; | ||
559 | module_param(max_drives, int, 0); | ||
560 | #ifndef MODULE | ||
561 | static unsigned char setup_done; | ||
562 | static const char *str_sb_l = "soundblaster"; | ||
563 | static const char *str_sp_l = "spea"; | ||
564 | static const char *str_ss_l = "soundscape"; | ||
565 | static const char *str_t16_l = "teac16bit"; | ||
566 | static const char *str_ss = "SoundScape"; | ||
567 | #endif | ||
568 | static const char *str_sb = "SoundBlaster"; | ||
569 | static const char *str_lm = "LaserMate"; | ||
570 | static const char *str_sp = "SPEA"; | ||
571 | static const char *str_t16 = "Teac16bit"; | ||
572 | static const char *type; | ||
573 | static const char *major_name="sbpcd"; | ||
574 | |||
575 | /*==========================================================================*/ | ||
576 | |||
577 | #ifdef FUTURE | ||
578 | static DECLARE_WAIT_QUEUE_HEAD(sbp_waitq); | ||
579 | #endif /* FUTURE */ | ||
580 | |||
581 | static int teac=SBP_TEAC_SPEED; | ||
582 | static int buffers=SBP_BUFFER_FRAMES; | ||
583 | |||
584 | static u_char family0[]="MATSHITA"; /* MKE CR-521, CR-522, CR-523 */ | ||
585 | static u_char family1[]="CR-56"; /* MKE CR-562, CR-563 */ | ||
586 | static u_char family2[]="CD200"; /* MKE CD200, Funai CD200F */ | ||
587 | static u_char familyL[]="LCS-7260"; /* Longshine LCS-7260 */ | ||
588 | static u_char familyT[]="CD-55"; /* TEAC CD-55A */ | ||
589 | static u_char familyV[]="ECS-AT"; /* ECS Vertos 100 */ | ||
590 | |||
591 | static u_int recursion; /* internal testing only */ | ||
592 | static u_int fatal_err; /* internal testing only */ | ||
593 | static u_int response_count; | ||
594 | static u_int flags_cmd_out; | ||
595 | static u_char cmd_type; | ||
596 | static u_char drvcmd[10]; | ||
597 | static u_char infobuf[20]; | ||
598 | static u_char xa_head_buf[CD_XA_HEAD]; | ||
599 | static u_char xa_tail_buf[CD_XA_TAIL]; | ||
600 | |||
601 | #if OLD_BUSY | ||
602 | static volatile u_char busy_data; | ||
603 | static volatile u_char busy_audio; /* true semaphores would be safer */ | ||
604 | #endif /* OLD_BUSY */ | ||
605 | static DECLARE_MUTEX(ioctl_read_sem); | ||
606 | static u_long timeout; | ||
607 | static volatile u_char timed_out_delay; | ||
608 | static volatile u_char timed_out_data; | ||
609 | #if 0 | ||
610 | static volatile u_char timed_out_audio; | ||
611 | #endif | ||
612 | static u_int datarate= 1000000; | ||
613 | static u_int maxtim16=16000000; | ||
614 | static u_int maxtim04= 4000000; | ||
615 | static u_int maxtim02= 2000000; | ||
616 | static u_int maxtim_8= 30000; | ||
617 | #if LONG_TIMING | ||
618 | static u_int maxtim_data= 9000; | ||
619 | #else | ||
620 | static u_int maxtim_data= 3000; | ||
621 | #endif /* LONG_TIMING */ | ||
622 | #if DISTRIBUTION | ||
623 | static int n_retries=6; | ||
624 | #else | ||
625 | static int n_retries=6; | ||
626 | #endif | ||
627 | /*==========================================================================*/ | ||
628 | |||
629 | static int ndrives; | ||
630 | static u_char drv_pattern[NR_SBPCD]={speed_auto,speed_auto,speed_auto,speed_auto}; | ||
631 | |||
632 | /*==========================================================================*/ | ||
633 | /* | ||
634 | * drive space begins here (needed separate for each unit) | ||
635 | */ | ||
636 | static struct sbpcd_drive { | ||
637 | char drv_id; /* "jumpered" drive ID or -1 */ | ||
638 | char drv_sel; /* drive select lines bits */ | ||
639 | |||
640 | char drive_model[9]; | ||
641 | u_char firmware_version[4]; | ||
642 | char f_eject; /* auto-eject flag: 0 or 1 */ | ||
643 | u_char *sbp_buf; /* Pointer to internal data buffer, | ||
644 | space allocated during sbpcd_init() */ | ||
645 | u_int sbp_bufsiz; /* size of sbp_buf (# of frames) */ | ||
646 | int sbp_first_frame; /* First frame in buffer */ | ||
647 | int sbp_last_frame; /* Last frame in buffer */ | ||
648 | int sbp_read_frames; /* Number of frames being read to buffer */ | ||
649 | int sbp_current; /* Frame being currently read */ | ||
650 | |||
651 | u_char mode; /* read_mode: READ_M1, READ_M2, READ_SC, READ_AU */ | ||
652 | u_char *aud_buf; /* Pointer to audio data buffer, | ||
653 | space allocated during sbpcd_init() */ | ||
654 | u_int sbp_audsiz; /* size of aud_buf (# of raw frames) */ | ||
655 | u_int drv_type; | ||
656 | u_char drv_options; | ||
657 | int status_bits; | ||
658 | u_char diskstate_flags; | ||
659 | u_char sense_byte; | ||
660 | |||
661 | u_char CD_changed; | ||
662 | char open_count; | ||
663 | u_char error_byte; | ||
664 | |||
665 | u_char f_multisession; | ||
666 | u_int lba_multi; | ||
667 | int first_session; | ||
668 | int last_session; | ||
669 | int track_of_last_session; | ||
670 | |||
671 | u_char audio_state; | ||
672 | u_int pos_audio_start; | ||
673 | u_int pos_audio_end; | ||
674 | char vol_chan0; | ||
675 | u_char vol_ctrl0; | ||
676 | char vol_chan1; | ||
677 | u_char vol_ctrl1; | ||
678 | #if 000 /* no supported drive has it */ | ||
679 | char vol_chan2; | ||
680 | u_char vol_ctrl2; | ||
681 | char vol_chan3; | ||
682 | u_char vol_ctrl3; | ||
683 | #endif /*000 */ | ||
684 | u_char volume_control; /* TEAC on/off bits */ | ||
685 | |||
686 | u_char SubQ_ctl_adr; | ||
687 | u_char SubQ_trk; | ||
688 | u_char SubQ_pnt_idx; | ||
689 | u_int SubQ_run_tot; | ||
690 | u_int SubQ_run_trk; | ||
691 | u_char SubQ_whatisthis; | ||
692 | |||
693 | u_char UPC_ctl_adr; | ||
694 | u_char UPC_buf[7]; | ||
695 | |||
696 | int frame_size; | ||
697 | int CDsize_frm; | ||
698 | |||
699 | u_char xa_byte; /* 0x20: XA capabilities */ | ||
700 | u_char n_first_track; /* binary */ | ||
701 | u_char n_last_track; /* binary (not bcd), 0x01...0x63 */ | ||
702 | u_int size_msf; /* time of whole CD, position of LeadOut track */ | ||
703 | u_int size_blk; | ||
704 | |||
705 | u_char TocEnt_nixbyte; /* em */ | ||
706 | u_char TocEnt_ctl_adr; | ||
707 | u_char TocEnt_number; | ||
708 | u_char TocEnt_format; /* em */ | ||
709 | u_int TocEnt_address; | ||
710 | #ifdef SAFE_MIXED | ||
711 | char has_data; | ||
712 | #endif /* SAFE_MIXED */ | ||
713 | u_char ored_ctl_adr; /* to detect if CDROM contains data tracks */ | ||
714 | |||
715 | struct { | ||
716 | u_char nixbyte; /* em */ | ||
717 | u_char ctl_adr; /* 0x4x: data, 0x0x: audio */ | ||
718 | u_char number; | ||
719 | u_char format; /* em */ /* 0x00: lba, 0x01: msf */ | ||
720 | u_int address; | ||
721 | } TocBuffer[MAX_TRACKS+1]; /* last entry faked */ | ||
722 | |||
723 | int in_SpinUp; /* CR-52x test flag */ | ||
724 | int n_bytes; /* TEAC awaited response count */ | ||
725 | u_char error_state, b3, b4; /* TEAC command error state */ | ||
726 | u_char f_drv_error; /* TEAC command error flag */ | ||
727 | u_char speed_byte; | ||
728 | int frmsiz; | ||
729 | u_char f_XA; /* 1: XA */ | ||
730 | u_char type_byte; /* 0, 1, 3 */ | ||
731 | u_char mode_xb_6; | ||
732 | u_char mode_yb_7; | ||
733 | u_char mode_xb_8; | ||
734 | u_char delay; | ||
735 | struct cdrom_device_info *sbpcd_infop; | ||
736 | struct gendisk *disk; | ||
737 | } D_S[NR_SBPCD]; | ||
738 | |||
739 | static struct sbpcd_drive *current_drive = D_S; | ||
740 | |||
741 | /* | ||
742 | * drive space ends here (needed separate for each unit) | ||
743 | */ | ||
744 | /*==========================================================================*/ | ||
745 | #if 0 | ||
746 | unsigned long cli_sti; /* for saving the processor flags */ | ||
747 | #endif | ||
748 | /*==========================================================================*/ | ||
749 | static DEFINE_TIMER(delay_timer, mark_timeout_delay, 0, 0); | ||
750 | static DEFINE_TIMER(data_timer, mark_timeout_data, 0, 0); | ||
751 | #if 0 | ||
752 | static DEFINE_TIMER(audio_timer, mark_timeout_audio, 0, 0); | ||
753 | #endif | ||
754 | /*==========================================================================*/ | ||
755 | /* | ||
756 | * DDI interface | ||
757 | */ | ||
758 | static void msg(int level, const char *fmt, ...) | ||
759 | { | ||
760 | #if DISTRIBUTION | ||
761 | #define MSG_LEVEL KERN_NOTICE | ||
762 | #else | ||
763 | #define MSG_LEVEL KERN_INFO | ||
764 | #endif /* DISTRIBUTION */ | ||
765 | |||
766 | char buf[256]; | ||
767 | va_list args; | ||
768 | |||
769 | if (!(sbpcd_debug&(1<<level))) return; | ||
770 | |||
771 | msgnum++; | ||
772 | if (msgnum>99) msgnum=0; | ||
773 | va_start(args, fmt); | ||
774 | vsnprintf(buf, sizeof(buf), fmt, args); | ||
775 | va_end(args); | ||
776 | printk(MSG_LEVEL "%s-%d [%02d]: %s", major_name, current_drive - D_S, msgnum, buf); | ||
777 | #if KLOGD_PAUSE | ||
778 | sbp_sleep(KLOGD_PAUSE); /* else messages get lost */ | ||
779 | #endif /* KLOGD_PAUSE */ | ||
780 | return; | ||
781 | } | ||
782 | /*==========================================================================*/ | ||
783 | /* | ||
784 | * DDI interface: runtime trace bit pattern maintenance | ||
785 | */ | ||
786 | static int sbpcd_dbg_ioctl(unsigned long arg, int level) | ||
787 | { | ||
788 | switch(arg) | ||
789 | { | ||
790 | case 0: /* OFF */ | ||
791 | sbpcd_debug = DBG_INF; | ||
792 | break; | ||
793 | |||
794 | default: | ||
795 | if (arg>=128) sbpcd_debug &= ~(1<<(arg-128)); | ||
796 | else sbpcd_debug |= (1<<arg); | ||
797 | } | ||
798 | return (arg); | ||
799 | } | ||
800 | /*==========================================================================*/ | ||
801 | static void mark_timeout_delay(u_long i) | ||
802 | { | ||
803 | timed_out_delay=1; | ||
804 | #if 0 | ||
805 | msg(DBG_TIM,"delay timer expired.\n"); | ||
806 | #endif | ||
807 | } | ||
808 | /*==========================================================================*/ | ||
809 | static void mark_timeout_data(u_long i) | ||
810 | { | ||
811 | timed_out_data=1; | ||
812 | #if 0 | ||
813 | msg(DBG_TIM,"data timer expired.\n"); | ||
814 | #endif | ||
815 | } | ||
816 | /*==========================================================================*/ | ||
817 | #if 0 | ||
818 | static void mark_timeout_audio(u_long i) | ||
819 | { | ||
820 | timed_out_audio=1; | ||
821 | #if 0 | ||
822 | msg(DBG_TIM,"audio timer expired.\n"); | ||
823 | #endif | ||
824 | } | ||
825 | #endif | ||
826 | /*==========================================================================*/ | ||
827 | /* | ||
828 | * Wait a little while (used for polling the drive). | ||
829 | */ | ||
830 | static void sbp_sleep(u_int time) | ||
831 | { | ||
832 | sti(); | ||
833 | schedule_timeout_interruptible(time); | ||
834 | sti(); | ||
835 | } | ||
836 | /*==========================================================================*/ | ||
837 | #define RETURN_UP(rc) {up(&ioctl_read_sem); return(rc);} | ||
838 | /*==========================================================================*/ | ||
839 | /* | ||
840 | * convert logical_block_address to m-s-f_number (3 bytes only) | ||
841 | */ | ||
842 | static INLINE void lba2msf(int lba, u_char *msf) | ||
843 | { | ||
844 | lba += CD_MSF_OFFSET; | ||
845 | msf[0] = lba / (CD_SECS*CD_FRAMES); | ||
846 | lba %= CD_SECS*CD_FRAMES; | ||
847 | msf[1] = lba / CD_FRAMES; | ||
848 | msf[2] = lba % CD_FRAMES; | ||
849 | } | ||
850 | /*==========================================================================*/ | ||
851 | /*==========================================================================*/ | ||
852 | /* | ||
853 | * convert msf-bin to msf-bcd | ||
854 | */ | ||
855 | static INLINE void bin2bcdx(u_char *p) /* must work only up to 75 or 99 */ | ||
856 | { | ||
857 | *p=((*p/10)<<4)|(*p%10); | ||
858 | } | ||
859 | /*==========================================================================*/ | ||
860 | static INLINE u_int blk2msf(u_int blk) | ||
861 | { | ||
862 | MSF msf; | ||
863 | u_int mm; | ||
864 | |||
865 | msf.c[3] = 0; | ||
866 | msf.c[2] = (blk + CD_MSF_OFFSET) / (CD_SECS * CD_FRAMES); | ||
867 | mm = (blk + CD_MSF_OFFSET) % (CD_SECS * CD_FRAMES); | ||
868 | msf.c[1] = mm / CD_FRAMES; | ||
869 | msf.c[0] = mm % CD_FRAMES; | ||
870 | return (msf.n); | ||
871 | } | ||
872 | /*==========================================================================*/ | ||
873 | static INLINE u_int make16(u_char rh, u_char rl) | ||
874 | { | ||
875 | return ((rh<<8)|rl); | ||
876 | } | ||
877 | /*==========================================================================*/ | ||
878 | static INLINE u_int make32(u_int rh, u_int rl) | ||
879 | { | ||
880 | return ((rh<<16)|rl); | ||
881 | } | ||
882 | /*==========================================================================*/ | ||
883 | static INLINE u_char swap_nibbles(u_char i) | ||
884 | { | ||
885 | return ((i<<4)|(i>>4)); | ||
886 | } | ||
887 | /*==========================================================================*/ | ||
888 | static INLINE u_char byt2bcd(u_char i) | ||
889 | { | ||
890 | return (((i/10)<<4)+i%10); | ||
891 | } | ||
892 | /*==========================================================================*/ | ||
893 | static INLINE u_char bcd2bin(u_char bcd) | ||
894 | { | ||
895 | return ((bcd>>4)*10+(bcd&0x0F)); | ||
896 | } | ||
897 | /*==========================================================================*/ | ||
898 | static INLINE int msf2blk(int msfx) | ||
899 | { | ||
900 | MSF msf; | ||
901 | int i; | ||
902 | |||
903 | msf.n=msfx; | ||
904 | i=(msf.c[2] * CD_SECS + msf.c[1]) * CD_FRAMES + msf.c[0] - CD_MSF_OFFSET; | ||
905 | if (i<0) return (0); | ||
906 | return (i); | ||
907 | } | ||
908 | /*==========================================================================*/ | ||
909 | /* | ||
910 | * convert m-s-f_number (3 bytes only) to logical_block_address | ||
911 | */ | ||
912 | static INLINE int msf2lba(u_char *msf) | ||
913 | { | ||
914 | int i; | ||
915 | |||
916 | i=(msf[0] * CD_SECS + msf[1]) * CD_FRAMES + msf[2] - CD_MSF_OFFSET; | ||
917 | if (i<0) return (0); | ||
918 | return (i); | ||
919 | } | ||
920 | /*==========================================================================*/ | ||
921 | /* evaluate cc_ReadError code */ | ||
922 | static int sta2err(int sta) | ||
923 | { | ||
924 | if (famT_drive) | ||
925 | { | ||
926 | if (sta==0x00) return (0); | ||
927 | if (sta==0x01) return (-604); /* CRC error */ | ||
928 | if (sta==0x02) return (-602); /* drive not ready */ | ||
929 | if (sta==0x03) return (-607); /* unknown media */ | ||
930 | if (sta==0x04) return (-612); /* general failure */ | ||
931 | if (sta==0x05) return (0); | ||
932 | if (sta==0x06) return (-ERR_DISKCHANGE); /* disk change */ | ||
933 | if (sta==0x0b) return (-612); /* general failure */ | ||
934 | if (sta==0xff) return (-612); /* general failure */ | ||
935 | return (0); | ||
936 | } | ||
937 | else | ||
938 | { | ||
939 | if (sta<=2) return (sta); | ||
940 | if (sta==0x05) return (-604); /* CRC error */ | ||
941 | if (sta==0x06) return (-606); /* seek error */ | ||
942 | if (sta==0x0d) return (-606); /* seek error */ | ||
943 | if (sta==0x0e) return (-603); /* unknown command */ | ||
944 | if (sta==0x14) return (-603); /* unknown command */ | ||
945 | if (sta==0x0c) return (-611); /* read fault */ | ||
946 | if (sta==0x0f) return (-611); /* read fault */ | ||
947 | if (sta==0x10) return (-611); /* read fault */ | ||
948 | if (sta>=0x16) return (-612); /* general failure */ | ||
949 | if (sta==0x11) return (-ERR_DISKCHANGE); /* disk change (LCS: removed) */ | ||
950 | if (famL_drive) | ||
951 | if (sta==0x12) return (-ERR_DISKCHANGE); /* disk change (inserted) */ | ||
952 | return (-602); /* drive not ready */ | ||
953 | } | ||
954 | } | ||
955 | /*==========================================================================*/ | ||
956 | static INLINE void clr_cmdbuf(void) | ||
957 | { | ||
958 | int i; | ||
959 | |||
960 | for (i=0;i<10;i++) drvcmd[i]=0; | ||
961 | cmd_type=0; | ||
962 | } | ||
963 | /*==========================================================================*/ | ||
964 | static void flush_status(void) | ||
965 | { | ||
966 | int i; | ||
967 | |||
968 | sbp_sleep(15*HZ/10); | ||
969 | for (i=maxtim_data;i!=0;i--) inb(CDi_status); | ||
970 | } | ||
971 | /*====================================================================*/ | ||
972 | /* | ||
973 | * CDi status loop for Teac CD-55A (Rob Riggs) | ||
974 | * | ||
975 | * This is needed because for some strange reason | ||
976 | * the CD-55A can take a real long time to give a | ||
977 | * status response. This seems to happen after we | ||
978 | * issue a READ command where a long seek is involved. | ||
979 | * | ||
980 | * I tried to ensure that we get max throughput with | ||
981 | * minimal busy waiting. We busy wait at first, then | ||
982 | * "switch gears" and start sleeping. We sleep for | ||
983 | * longer periods of time the longer we wait. | ||
984 | * | ||
985 | */ | ||
986 | static int CDi_stat_loop_T(void) | ||
987 | { | ||
988 | int i, gear=1; | ||
989 | u_long timeout_1, timeout_2, timeout_3, timeout_4; | ||
990 | |||
991 | timeout_1 = jiffies + HZ / 50; /* sbp_sleep(0) for a short period */ | ||
992 | timeout_2 = jiffies + HZ / 5; /* nap for no more than 200ms */ | ||
993 | timeout_3 = jiffies + 5 * HZ; /* sleep for up to 5s */ | ||
994 | timeout_4 = jiffies + 45 * HZ; /* long sleep for up to 45s. */ | ||
995 | do | ||
996 | { | ||
997 | i = inb(CDi_status); | ||
998 | if (!(i&s_not_data_ready)) return (i); | ||
999 | if (!(i&s_not_result_ready)) return (i); | ||
1000 | switch(gear) | ||
1001 | { | ||
1002 | case 4: | ||
1003 | sbp_sleep(HZ); | ||
1004 | if (time_after(jiffies, timeout_4)) gear++; | ||
1005 | msg(DBG_TEA, "CDi_stat_loop_T: long sleep active.\n"); | ||
1006 | break; | ||
1007 | case 3: | ||
1008 | sbp_sleep(HZ/10); | ||
1009 | if (time_after(jiffies, timeout_3)) gear++; | ||
1010 | break; | ||
1011 | case 2: | ||
1012 | sbp_sleep(HZ/100); | ||
1013 | if (time_after(jiffies, timeout_2)) gear++; | ||
1014 | break; | ||
1015 | case 1: | ||
1016 | sbp_sleep(0); | ||
1017 | if (time_after(jiffies, timeout_1)) gear++; | ||
1018 | } | ||
1019 | } while (gear < 5); | ||
1020 | return -1; | ||
1021 | } | ||
1022 | /*==========================================================================*/ | ||
1023 | static int CDi_stat_loop(void) | ||
1024 | { | ||
1025 | int i,j; | ||
1026 | |||
1027 | for(timeout = jiffies + 10*HZ, i=maxtim_data; time_before(jiffies, timeout); ) | ||
1028 | { | ||
1029 | for ( ;i!=0;i--) | ||
1030 | { | ||
1031 | j=inb(CDi_status); | ||
1032 | if (!(j&s_not_data_ready)) return (j); | ||
1033 | if (!(j&s_not_result_ready)) return (j); | ||
1034 | if (fam0L_drive) if (j&s_attention) return (j); | ||
1035 | } | ||
1036 | sbp_sleep(1); | ||
1037 | i = 1; | ||
1038 | } | ||
1039 | msg(DBG_LCS,"CDi_stat_loop failed in line %d\n", __LINE__); | ||
1040 | return (-1); | ||
1041 | } | ||
1042 | /*==========================================================================*/ | ||
1043 | #if 00000 | ||
1044 | /*==========================================================================*/ | ||
1045 | static int tst_DataReady(void) | ||
1046 | { | ||
1047 | int i; | ||
1048 | |||
1049 | i=inb(CDi_status); | ||
1050 | if (i&s_not_data_ready) return (0); | ||
1051 | return (1); | ||
1052 | } | ||
1053 | /*==========================================================================*/ | ||
1054 | static int tst_ResultReady(void) | ||
1055 | { | ||
1056 | int i; | ||
1057 | |||
1058 | i=inb(CDi_status); | ||
1059 | if (i&s_not_result_ready) return (0); | ||
1060 | return (1); | ||
1061 | } | ||
1062 | /*==========================================================================*/ | ||
1063 | static int tst_Attention(void) | ||
1064 | { | ||
1065 | int i; | ||
1066 | |||
1067 | i=inb(CDi_status); | ||
1068 | if (i&s_attention) return (1); | ||
1069 | return (0); | ||
1070 | } | ||
1071 | /*==========================================================================*/ | ||
1072 | #endif | ||
1073 | /*==========================================================================*/ | ||
1074 | static int ResponseInfo(void) | ||
1075 | { | ||
1076 | int i,j,st=0; | ||
1077 | u_long timeout; | ||
1078 | |||
1079 | for (i=0,timeout=jiffies+HZ;i<response_count;i++) | ||
1080 | { | ||
1081 | for (j=maxtim_data; ; ) | ||
1082 | { | ||
1083 | for ( ;j!=0;j-- ) | ||
1084 | { | ||
1085 | st=inb(CDi_status); | ||
1086 | if (!(st&s_not_result_ready)) break; | ||
1087 | } | ||
1088 | if ((j!=0)||time_after_eq(jiffies, timeout)) break; | ||
1089 | sbp_sleep(1); | ||
1090 | j = 1; | ||
1091 | } | ||
1092 | if (time_after_eq(jiffies, timeout)) break; | ||
1093 | infobuf[i]=inb(CDi_info); | ||
1094 | } | ||
1095 | #if 000 | ||
1096 | while (!(inb(CDi_status)&s_not_result_ready)) | ||
1097 | { | ||
1098 | infobuf[i++]=inb(CDi_info); | ||
1099 | } | ||
1100 | j=i-response_count; | ||
1101 | if (j>0) msg(DBG_INF,"ResponseInfo: got %d trailing bytes.\n",j); | ||
1102 | #endif /* 000 */ | ||
1103 | for (j=0;j<i;j++) | ||
1104 | sprintf(&msgbuf[j*3]," %02X",infobuf[j]); | ||
1105 | msgbuf[j*3]=0; | ||
1106 | msg(DBG_CMD,"ResponseInfo:%s (%d,%d)\n",msgbuf,response_count,i); | ||
1107 | j=response_count-i; | ||
1108 | if (j>0) return (-j); | ||
1109 | else return (i); | ||
1110 | } | ||
1111 | /*==========================================================================*/ | ||
1112 | static void EvaluateStatus(int st) | ||
1113 | { | ||
1114 | current_drive->status_bits=0; | ||
1115 | if (fam1_drive) current_drive->status_bits=st|p_success; | ||
1116 | else if (fam0_drive) | ||
1117 | { | ||
1118 | if (st&p_caddin_old) current_drive->status_bits |= p_door_closed|p_caddy_in; | ||
1119 | if (st&p_spinning) current_drive->status_bits |= p_spinning; | ||
1120 | if (st&p_check) current_drive->status_bits |= p_check; | ||
1121 | if (st&p_success_old) current_drive->status_bits |= p_success; | ||
1122 | if (st&p_busy_old) current_drive->status_bits |= p_busy_new; | ||
1123 | if (st&p_disk_ok) current_drive->status_bits |= p_disk_ok; | ||
1124 | } | ||
1125 | else if (famLV_drive) | ||
1126 | { | ||
1127 | current_drive->status_bits |= p_success; | ||
1128 | if (st&p_caddin_old) current_drive->status_bits |= p_disk_ok|p_caddy_in; | ||
1129 | if (st&p_spinning) current_drive->status_bits |= p_spinning; | ||
1130 | if (st&p_check) current_drive->status_bits |= p_check; | ||
1131 | if (st&p_busy_old) current_drive->status_bits |= p_busy_new; | ||
1132 | if (st&p_lcs_door_closed) current_drive->status_bits |= p_door_closed; | ||
1133 | if (st&p_lcs_door_locked) current_drive->status_bits |= p_door_locked; | ||
1134 | } | ||
1135 | else if (fam2_drive) | ||
1136 | { | ||
1137 | current_drive->status_bits |= p_success; | ||
1138 | if (st&p2_check) current_drive->status_bits |= p1_check; | ||
1139 | if (st&p2_door_closed) current_drive->status_bits |= p1_door_closed; | ||
1140 | if (st&p2_disk_in) current_drive->status_bits |= p1_disk_in; | ||
1141 | if (st&p2_busy1) current_drive->status_bits |= p1_busy; | ||
1142 | if (st&p2_busy2) current_drive->status_bits |= p1_busy; | ||
1143 | if (st&p2_spinning) current_drive->status_bits |= p1_spinning; | ||
1144 | if (st&p2_door_locked) current_drive->status_bits |= p1_door_locked; | ||
1145 | if (st&p2_disk_ok) current_drive->status_bits |= p1_disk_ok; | ||
1146 | } | ||
1147 | else if (famT_drive) | ||
1148 | { | ||
1149 | return; /* still needs to get coded */ | ||
1150 | current_drive->status_bits |= p_success; | ||
1151 | if (st&p2_check) current_drive->status_bits |= p1_check; | ||
1152 | if (st&p2_door_closed) current_drive->status_bits |= p1_door_closed; | ||
1153 | if (st&p2_disk_in) current_drive->status_bits |= p1_disk_in; | ||
1154 | if (st&p2_busy1) current_drive->status_bits |= p1_busy; | ||
1155 | if (st&p2_busy2) current_drive->status_bits |= p1_busy; | ||
1156 | if (st&p2_spinning) current_drive->status_bits |= p1_spinning; | ||
1157 | if (st&p2_door_locked) current_drive->status_bits |= p1_door_locked; | ||
1158 | if (st&p2_disk_ok) current_drive->status_bits |= p1_disk_ok; | ||
1159 | } | ||
1160 | return; | ||
1161 | } | ||
1162 | /*==========================================================================*/ | ||
1163 | static int cmd_out_T(void); | ||
1164 | |||
1165 | static int get_state_T(void) | ||
1166 | { | ||
1167 | int i; | ||
1168 | |||
1169 | clr_cmdbuf(); | ||
1170 | current_drive->n_bytes=1; | ||
1171 | drvcmd[0]=CMDT_STATUS; | ||
1172 | i=cmd_out_T(); | ||
1173 | if (i>=0) i=infobuf[0]; | ||
1174 | else | ||
1175 | { | ||
1176 | msg(DBG_TEA,"get_state_T error %d\n", i); | ||
1177 | return (i); | ||
1178 | } | ||
1179 | if (i>=0) | ||
1180 | /* 2: closed, disk in */ | ||
1181 | current_drive->status_bits=p1_door_closed|p1_disk_in|p1_spinning|p1_disk_ok; | ||
1182 | else if (current_drive->error_state==6) | ||
1183 | { | ||
1184 | /* 3: closed, disk in, changed ("06 xx xx") */ | ||
1185 | current_drive->status_bits=p1_door_closed|p1_disk_in; | ||
1186 | current_drive->CD_changed=0xFF; | ||
1187 | current_drive->diskstate_flags &= ~toc_bit; | ||
1188 | } | ||
1189 | else if ((current_drive->error_state!=2)||(current_drive->b3!=0x3A)||(current_drive->b4==0x00)) | ||
1190 | { | ||
1191 | /* 1: closed, no disk ("xx yy zz"or "02 3A 00") */ | ||
1192 | current_drive->status_bits=p1_door_closed; | ||
1193 | current_drive->open_count=0; | ||
1194 | } | ||
1195 | else if (current_drive->b4==0x01) | ||
1196 | { | ||
1197 | /* 0: open ("02 3A 01") */ | ||
1198 | current_drive->status_bits=0; | ||
1199 | current_drive->open_count=0; | ||
1200 | } | ||
1201 | else | ||
1202 | { | ||
1203 | /* 1: closed, no disk ("02 3A xx") */ | ||
1204 | current_drive->status_bits=p1_door_closed; | ||
1205 | current_drive->open_count=0; | ||
1206 | } | ||
1207 | return (current_drive->status_bits); | ||
1208 | } | ||
1209 | /*==========================================================================*/ | ||
1210 | static int ResponseStatus(void) | ||
1211 | { | ||
1212 | int i,j; | ||
1213 | u_long timeout; | ||
1214 | |||
1215 | msg(DBG_STA,"doing ResponseStatus...\n"); | ||
1216 | if (famT_drive) return (get_state_T()); | ||
1217 | if (flags_cmd_out & f_respo3) timeout = jiffies; | ||
1218 | else if (flags_cmd_out & f_respo2) timeout = jiffies + 16*HZ; | ||
1219 | else timeout = jiffies + 4*HZ; | ||
1220 | j=maxtim_8; | ||
1221 | do | ||
1222 | { | ||
1223 | for ( ;j!=0;j--) | ||
1224 | { | ||
1225 | i=inb(CDi_status); | ||
1226 | if (!(i&s_not_result_ready)) break; | ||
1227 | } | ||
1228 | if ((j!=0)||time_after(jiffies, timeout)) break; | ||
1229 | sbp_sleep(1); | ||
1230 | j = 1; | ||
1231 | } | ||
1232 | while (1); | ||
1233 | if (j==0) | ||
1234 | { | ||
1235 | if ((flags_cmd_out & f_respo3) == 0) | ||
1236 | msg(DBG_STA,"ResponseStatus: timeout.\n"); | ||
1237 | current_drive->status_bits=0; | ||
1238 | return (-401); | ||
1239 | } | ||
1240 | i=inb(CDi_info); | ||
1241 | msg(DBG_STA,"ResponseStatus: response %02X.\n", i); | ||
1242 | EvaluateStatus(i); | ||
1243 | msg(DBG_STA,"status_bits=%02X, i=%02X\n",current_drive->status_bits,i); | ||
1244 | return (current_drive->status_bits); | ||
1245 | } | ||
1246 | /*==========================================================================*/ | ||
1247 | static void cc_ReadStatus(void) | ||
1248 | { | ||
1249 | int i; | ||
1250 | |||
1251 | msg(DBG_STA,"giving cc_ReadStatus command\n"); | ||
1252 | if (famT_drive) return; | ||
1253 | SBPCD_CLI; | ||
1254 | if (fam0LV_drive) OUT(CDo_command,CMD0_STATUS); | ||
1255 | else if (fam1_drive) OUT(CDo_command,CMD1_STATUS); | ||
1256 | else if (fam2_drive) OUT(CDo_command,CMD2_STATUS); | ||
1257 | if (!fam0LV_drive) for (i=0;i<6;i++) OUT(CDo_command,0); | ||
1258 | SBPCD_STI; | ||
1259 | } | ||
1260 | /*==========================================================================*/ | ||
1261 | static int cc_ReadError(void) | ||
1262 | { | ||
1263 | int i; | ||
1264 | |||
1265 | clr_cmdbuf(); | ||
1266 | msg(DBG_ERR,"giving cc_ReadError command.\n"); | ||
1267 | if (fam1_drive) | ||
1268 | { | ||
1269 | drvcmd[0]=CMD1_READ_ERR; | ||
1270 | response_count=8; | ||
1271 | flags_cmd_out=f_putcmd|f_ResponseStatus; | ||
1272 | } | ||
1273 | else if (fam0LV_drive) | ||
1274 | { | ||
1275 | drvcmd[0]=CMD0_READ_ERR; | ||
1276 | response_count=6; | ||
1277 | if (famLV_drive) | ||
1278 | flags_cmd_out=f_putcmd; | ||
1279 | else | ||
1280 | flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus; | ||
1281 | } | ||
1282 | else if (fam2_drive) | ||
1283 | { | ||
1284 | drvcmd[0]=CMD2_READ_ERR; | ||
1285 | response_count=6; | ||
1286 | flags_cmd_out=f_putcmd; | ||
1287 | } | ||
1288 | else if (famT_drive) | ||
1289 | { | ||
1290 | response_count=5; | ||
1291 | drvcmd[0]=CMDT_READ_ERR; | ||
1292 | } | ||
1293 | i=cmd_out(); | ||
1294 | current_drive->error_byte=0; | ||
1295 | msg(DBG_ERR,"cc_ReadError: cmd_out(CMDx_READ_ERR) returns %d (%02X)\n",i,i); | ||
1296 | if (i<0) return (i); | ||
1297 | if (fam0V_drive) i=1; | ||
1298 | else i=2; | ||
1299 | current_drive->error_byte=infobuf[i]; | ||
1300 | msg(DBG_ERR,"cc_ReadError: infobuf[%d] is %d (%02X)\n",i,current_drive->error_byte,current_drive->error_byte); | ||
1301 | i=sta2err(infobuf[i]); | ||
1302 | if (i==-ERR_DISKCHANGE) | ||
1303 | { | ||
1304 | current_drive->CD_changed=0xFF; | ||
1305 | current_drive->diskstate_flags &= ~toc_bit; | ||
1306 | } | ||
1307 | return (i); | ||
1308 | } | ||
1309 | /*==========================================================================*/ | ||
1310 | static int cc_DriveReset(void); | ||
1311 | |||
1312 | static int cmd_out_T(void) | ||
1313 | { | ||
1314 | #undef CMDT_TRIES | ||
1315 | #define CMDT_TRIES 1000 | ||
1316 | #define TEST_FALSE_FF 1 | ||
1317 | |||
1318 | int i, j, l=0, m, ntries; | ||
1319 | unsigned long flags; | ||
1320 | |||
1321 | current_drive->error_state=0; | ||
1322 | current_drive->b3=0; | ||
1323 | current_drive->b4=0; | ||
1324 | current_drive->f_drv_error=0; | ||
1325 | for (i=0;i<10;i++) sprintf(&msgbuf[i*3]," %02X",drvcmd[i]); | ||
1326 | msgbuf[i*3]=0; | ||
1327 | msg(DBG_CMD,"cmd_out_T:%s\n",msgbuf); | ||
1328 | |||
1329 | OUT(CDo_sel_i_d,0); | ||
1330 | OUT(CDo_enable,current_drive->drv_sel); | ||
1331 | i=inb(CDi_status); | ||
1332 | do_16bit=0; | ||
1333 | if ((f_16bit)&&(!(i&0x80))) | ||
1334 | { | ||
1335 | do_16bit=1; | ||
1336 | msg(DBG_TEA,"cmd_out_T: do_16bit set.\n"); | ||
1337 | } | ||
1338 | if (!(i&s_not_result_ready)) | ||
1339 | do | ||
1340 | { | ||
1341 | j=inb(CDi_info); | ||
1342 | i=inb(CDi_status); | ||
1343 | sbp_sleep(0); | ||
1344 | msg(DBG_TEA,"cmd_out_T: spurious !s_not_result_ready. (%02X)\n", j); | ||
1345 | } | ||
1346 | while (!(i&s_not_result_ready)); | ||
1347 | save_flags(flags); cli(); | ||
1348 | for (i=0;i<10;i++) OUT(CDo_command,drvcmd[i]); | ||
1349 | restore_flags(flags); | ||
1350 | for (ntries=CMDT_TRIES;ntries>0;ntries--) | ||
1351 | { | ||
1352 | if (drvcmd[0]==CMDT_READ_VER) sbp_sleep(HZ); /* fixme */ | ||
1353 | #if 01 | ||
1354 | OUT(CDo_sel_i_d,1); | ||
1355 | #endif /* 01 */ | ||
1356 | if (teac==2) | ||
1357 | { | ||
1358 | if ((i=CDi_stat_loop_T()) == -1) break; | ||
1359 | } | ||
1360 | else | ||
1361 | { | ||
1362 | #if 0 | ||
1363 | OUT(CDo_sel_i_d,1); | ||
1364 | #endif /* 0 */ | ||
1365 | i=inb(CDi_status); | ||
1366 | } | ||
1367 | if (!(i&s_not_data_ready)) /* f.e. CMDT_DISKINFO */ | ||
1368 | { | ||
1369 | OUT(CDo_sel_i_d,1); | ||
1370 | if (drvcmd[0]==CMDT_READ) return (0); /* handled elsewhere */ | ||
1371 | if (drvcmd[0]==CMDT_DISKINFO) | ||
1372 | { | ||
1373 | l=0; | ||
1374 | do | ||
1375 | { | ||
1376 | if (do_16bit) | ||
1377 | { | ||
1378 | i=inw(CDi_data); | ||
1379 | infobuf[l++]=i&0x0ff; | ||
1380 | infobuf[l++]=i>>8; | ||
1381 | #if TEST_FALSE_FF | ||
1382 | if ((l==2)&&(infobuf[0]==0x0ff)) | ||
1383 | { | ||
1384 | infobuf[0]=infobuf[1]; | ||
1385 | l=1; | ||
1386 | msg(DBG_TEA,"cmd_out_T: do_16bit: false first byte!\n"); | ||
1387 | } | ||
1388 | #endif /* TEST_FALSE_FF */ | ||
1389 | } | ||
1390 | else infobuf[l++]=inb(CDi_data); | ||
1391 | i=inb(CDi_status); | ||
1392 | } | ||
1393 | while (!(i&s_not_data_ready)); | ||
1394 | for (j=0;j<l;j++) sprintf(&msgbuf[j*3]," %02X",infobuf[j]); | ||
1395 | msgbuf[j*3]=0; | ||
1396 | msg(DBG_CMD,"cmd_out_T data response:%s\n", msgbuf); | ||
1397 | } | ||
1398 | else | ||
1399 | { | ||
1400 | msg(DBG_TEA,"cmd_out_T: data response with cmd_%02X!\n", | ||
1401 | drvcmd[0]); | ||
1402 | j=0; | ||
1403 | do | ||
1404 | { | ||
1405 | if (do_16bit) i=inw(CDi_data); | ||
1406 | else i=inb(CDi_data); | ||
1407 | j++; | ||
1408 | i=inb(CDi_status); | ||
1409 | } | ||
1410 | while (!(i&s_not_data_ready)); | ||
1411 | msg(DBG_TEA,"cmd_out_T: data response: discarded %d bytes/words.\n", j); | ||
1412 | fatal_err++; | ||
1413 | } | ||
1414 | } | ||
1415 | i=inb(CDi_status); | ||
1416 | if (!(i&s_not_result_ready)) | ||
1417 | { | ||
1418 | OUT(CDo_sel_i_d,0); | ||
1419 | if (drvcmd[0]==CMDT_DISKINFO) m=l; | ||
1420 | else m=0; | ||
1421 | do | ||
1422 | { | ||
1423 | infobuf[m++]=inb(CDi_info); | ||
1424 | i=inb(CDi_status); | ||
1425 | } | ||
1426 | while (!(i&s_not_result_ready)); | ||
1427 | for (j=0;j<m;j++) sprintf(&msgbuf[j*3]," %02X",infobuf[j]); | ||
1428 | msgbuf[j*3]=0; | ||
1429 | msg(DBG_CMD,"cmd_out_T info response:%s\n", msgbuf); | ||
1430 | if (drvcmd[0]==CMDT_DISKINFO) | ||
1431 | { | ||
1432 | infobuf[0]=infobuf[l]; | ||
1433 | if (infobuf[0]!=0x02) return (l); /* data length */ | ||
1434 | } | ||
1435 | else if (infobuf[0]!=0x02) return (m); /* info length */ | ||
1436 | do | ||
1437 | { | ||
1438 | ++recursion; | ||
1439 | if (recursion>1) msg(DBG_TEA,"cmd_out_T READ_ERR recursion (%02X): %d !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n", drvcmd[0], recursion); | ||
1440 | clr_cmdbuf(); | ||
1441 | drvcmd[0]=CMDT_READ_ERR; | ||
1442 | j=cmd_out_T(); /* !!! recursive here !!! */ | ||
1443 | --recursion; | ||
1444 | sbp_sleep(1); | ||
1445 | } | ||
1446 | while (j<0); | ||
1447 | current_drive->error_state=infobuf[2]; | ||
1448 | current_drive->b3=infobuf[3]; | ||
1449 | current_drive->b4=infobuf[4]; | ||
1450 | if (current_drive->f_drv_error) | ||
1451 | { | ||
1452 | current_drive->f_drv_error=0; | ||
1453 | cc_DriveReset(); | ||
1454 | current_drive->error_state=2; | ||
1455 | } | ||
1456 | return (-current_drive->error_state-400); | ||
1457 | } | ||
1458 | if (drvcmd[0]==CMDT_READ) return (0); /* handled elsewhere */ | ||
1459 | if ((teac==0)||(ntries<(CMDT_TRIES-5))) sbp_sleep(HZ/10); | ||
1460 | else sbp_sleep(HZ/100); | ||
1461 | if (ntries>(CMDT_TRIES-50)) continue; | ||
1462 | msg(DBG_TEA,"cmd_out_T: next CMDT_TRIES (%02X): %d.\n", drvcmd[0], ntries-1); | ||
1463 | } | ||
1464 | current_drive->f_drv_error=1; | ||
1465 | cc_DriveReset(); | ||
1466 | current_drive->error_state=2; | ||
1467 | return (-99); | ||
1468 | } | ||
1469 | /*==========================================================================*/ | ||
1470 | static int cmd_out(void) | ||
1471 | { | ||
1472 | int i=0; | ||
1473 | |||
1474 | if (famT_drive) return(cmd_out_T()); | ||
1475 | |||
1476 | if (flags_cmd_out&f_putcmd) | ||
1477 | { | ||
1478 | unsigned long flags; | ||
1479 | for (i=0;i<7;i++) | ||
1480 | sprintf(&msgbuf[i*3], " %02X", drvcmd[i]); | ||
1481 | msgbuf[i*3]=0; | ||
1482 | msg(DBG_CMD,"cmd_out:%s\n", msgbuf); | ||
1483 | save_flags(flags); cli(); | ||
1484 | for (i=0;i<7;i++) OUT(CDo_command,drvcmd[i]); | ||
1485 | restore_flags(flags); | ||
1486 | } | ||
1487 | if (response_count!=0) | ||
1488 | { | ||
1489 | if (cmd_type!=0) | ||
1490 | { | ||
1491 | if (sbpro_type==1) OUT(CDo_sel_i_d,1); | ||
1492 | msg(DBG_INF,"misleaded to try ResponseData.\n"); | ||
1493 | if (sbpro_type==1) OUT(CDo_sel_i_d,0); | ||
1494 | return (-22); | ||
1495 | } | ||
1496 | else i=ResponseInfo(); | ||
1497 | if (i<0) return (i); | ||
1498 | } | ||
1499 | if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to CDi_stat_loop.\n"); | ||
1500 | if (flags_cmd_out&f_lopsta) | ||
1501 | { | ||
1502 | i=CDi_stat_loop(); | ||
1503 | if ((i<0)||!(i&s_attention)) return (-8); | ||
1504 | } | ||
1505 | if (!(flags_cmd_out&f_getsta)) goto LOC_229; | ||
1506 | |||
1507 | LOC_228: | ||
1508 | if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to cc_ReadStatus.\n"); | ||
1509 | cc_ReadStatus(); | ||
1510 | |||
1511 | LOC_229: | ||
1512 | if (flags_cmd_out&f_ResponseStatus) | ||
1513 | { | ||
1514 | if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to ResponseStatus.\n"); | ||
1515 | i=ResponseStatus(); | ||
1516 | /* builds status_bits, returns orig. status or p_busy_new */ | ||
1517 | if (i<0) return (i); | ||
1518 | if (flags_cmd_out&(f_bit1|f_wait_if_busy)) | ||
1519 | { | ||
1520 | if (!st_check) | ||
1521 | { | ||
1522 | if ((flags_cmd_out&f_bit1)&&(i&p_success)) goto LOC_232; | ||
1523 | if ((!(flags_cmd_out&f_wait_if_busy))||(!st_busy)) goto LOC_228; | ||
1524 | } | ||
1525 | } | ||
1526 | } | ||
1527 | LOC_232: | ||
1528 | if (!(flags_cmd_out&f_obey_p_check)) return (0); | ||
1529 | if (!st_check) return (0); | ||
1530 | if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to cc_ReadError.\n"); | ||
1531 | i=cc_ReadError(); | ||
1532 | if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to cmd_out OK.\n"); | ||
1533 | msg(DBG_000,"cmd_out: cc_ReadError=%d\n", i); | ||
1534 | return (i); | ||
1535 | } | ||
1536 | /*==========================================================================*/ | ||
1537 | static int cc_Seek(u_int pos, char f_blk_msf) | ||
1538 | { | ||
1539 | int i; | ||
1540 | |||
1541 | clr_cmdbuf(); | ||
1542 | if (f_blk_msf>1) return (-3); | ||
1543 | if (fam0V_drive) | ||
1544 | { | ||
1545 | drvcmd[0]=CMD0_SEEK; | ||
1546 | if (f_blk_msf==1) pos=msf2blk(pos); | ||
1547 | drvcmd[2]=(pos>>16)&0x00FF; | ||
1548 | drvcmd[3]=(pos>>8)&0x00FF; | ||
1549 | drvcmd[4]=pos&0x00FF; | ||
1550 | if (fam0_drive) | ||
1551 | flags_cmd_out = f_putcmd | f_respo2 | f_lopsta | f_getsta | | ||
1552 | f_ResponseStatus | f_obey_p_check | f_bit1; | ||
1553 | else | ||
1554 | flags_cmd_out = f_putcmd; | ||
1555 | } | ||
1556 | else if (fam1L_drive) | ||
1557 | { | ||
1558 | drvcmd[0]=CMD1_SEEK; /* same as CMD1_ and CMDL_ */ | ||
1559 | if (f_blk_msf==0) pos=blk2msf(pos); | ||
1560 | drvcmd[1]=(pos>>16)&0x00FF; | ||
1561 | drvcmd[2]=(pos>>8)&0x00FF; | ||
1562 | drvcmd[3]=pos&0x00FF; | ||
1563 | if (famL_drive) | ||
1564 | flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1; | ||
1565 | else | ||
1566 | flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check; | ||
1567 | } | ||
1568 | else if (fam2_drive) | ||
1569 | { | ||
1570 | drvcmd[0]=CMD2_SEEK; | ||
1571 | if (f_blk_msf==0) pos=blk2msf(pos); | ||
1572 | drvcmd[2]=(pos>>24)&0x00FF; | ||
1573 | drvcmd[3]=(pos>>16)&0x00FF; | ||
1574 | drvcmd[4]=(pos>>8)&0x00FF; | ||
1575 | drvcmd[5]=pos&0x00FF; | ||
1576 | flags_cmd_out=f_putcmd|f_ResponseStatus; | ||
1577 | } | ||
1578 | else if (famT_drive) | ||
1579 | { | ||
1580 | drvcmd[0]=CMDT_SEEK; | ||
1581 | if (f_blk_msf==1) pos=msf2blk(pos); | ||
1582 | drvcmd[2]=(pos>>24)&0x00FF; | ||
1583 | drvcmd[3]=(pos>>16)&0x00FF; | ||
1584 | drvcmd[4]=(pos>>8)&0x00FF; | ||
1585 | drvcmd[5]=pos&0x00FF; | ||
1586 | current_drive->n_bytes=1; | ||
1587 | } | ||
1588 | response_count=0; | ||
1589 | i=cmd_out(); | ||
1590 | return (i); | ||
1591 | } | ||
1592 | /*==========================================================================*/ | ||
1593 | static int cc_SpinUp(void) | ||
1594 | { | ||
1595 | int i; | ||
1596 | |||
1597 | msg(DBG_SPI,"SpinUp.\n"); | ||
1598 | current_drive->in_SpinUp = 1; | ||
1599 | clr_cmdbuf(); | ||
1600 | if (fam0LV_drive) | ||
1601 | { | ||
1602 | drvcmd[0]=CMD0_SPINUP; | ||
1603 | if (fam0L_drive) | ||
1604 | flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta| | ||
1605 | f_ResponseStatus|f_obey_p_check|f_bit1; | ||
1606 | else | ||
1607 | flags_cmd_out=f_putcmd; | ||
1608 | } | ||
1609 | else if (fam1_drive) | ||
1610 | { | ||
1611 | drvcmd[0]=CMD1_SPINUP; | ||
1612 | flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check; | ||
1613 | } | ||
1614 | else if (fam2_drive) | ||
1615 | { | ||
1616 | drvcmd[0]=CMD2_TRAY_CTL; | ||
1617 | drvcmd[4]=0x01; /* "spinup" */ | ||
1618 | flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check; | ||
1619 | } | ||
1620 | else if (famT_drive) | ||
1621 | { | ||
1622 | drvcmd[0]=CMDT_TRAY_CTL; | ||
1623 | drvcmd[4]=0x03; /* "insert", it hopefully spins the drive up */ | ||
1624 | } | ||
1625 | response_count=0; | ||
1626 | i=cmd_out(); | ||
1627 | current_drive->in_SpinUp = 0; | ||
1628 | return (i); | ||
1629 | } | ||
1630 | /*==========================================================================*/ | ||
1631 | static int cc_SpinDown(void) | ||
1632 | { | ||
1633 | int i; | ||
1634 | |||
1635 | if (fam0_drive) return (0); | ||
1636 | clr_cmdbuf(); | ||
1637 | response_count=0; | ||
1638 | if (fam1_drive) | ||
1639 | { | ||
1640 | drvcmd[0]=CMD1_SPINDOWN; | ||
1641 | flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check; | ||
1642 | } | ||
1643 | else if (fam2_drive) | ||
1644 | { | ||
1645 | drvcmd[0]=CMD2_TRAY_CTL; | ||
1646 | drvcmd[4]=0x02; /* "eject" */ | ||
1647 | flags_cmd_out=f_putcmd|f_ResponseStatus; | ||
1648 | } | ||
1649 | else if (famL_drive) | ||
1650 | { | ||
1651 | drvcmd[0]=CMDL_SPINDOWN; | ||
1652 | drvcmd[1]=1; | ||
1653 | flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1; | ||
1654 | } | ||
1655 | else if (famV_drive) | ||
1656 | { | ||
1657 | drvcmd[0]=CMDV_SPINDOWN; | ||
1658 | flags_cmd_out=f_putcmd; | ||
1659 | } | ||
1660 | else if (famT_drive) | ||
1661 | { | ||
1662 | drvcmd[0]=CMDT_TRAY_CTL; | ||
1663 | drvcmd[4]=0x02; /* "eject" */ | ||
1664 | } | ||
1665 | i=cmd_out(); | ||
1666 | return (i); | ||
1667 | } | ||
1668 | /*==========================================================================*/ | ||
1669 | static int cc_get_mode_T(void) | ||
1670 | { | ||
1671 | int i; | ||
1672 | |||
1673 | clr_cmdbuf(); | ||
1674 | response_count=10; | ||
1675 | drvcmd[0]=CMDT_GETMODE; | ||
1676 | drvcmd[4]=response_count; | ||
1677 | i=cmd_out_T(); | ||
1678 | return (i); | ||
1679 | } | ||
1680 | /*==========================================================================*/ | ||
1681 | static int cc_set_mode_T(void) | ||
1682 | { | ||
1683 | int i; | ||
1684 | |||
1685 | clr_cmdbuf(); | ||
1686 | response_count=1; | ||
1687 | drvcmd[0]=CMDT_SETMODE; | ||
1688 | drvcmd[1]=current_drive->speed_byte; | ||
1689 | drvcmd[2]=current_drive->frmsiz>>8; | ||
1690 | drvcmd[3]=current_drive->frmsiz&0x0FF; | ||
1691 | drvcmd[4]=current_drive->f_XA; /* 1: XA */ | ||
1692 | drvcmd[5]=current_drive->type_byte; /* 0, 1, 3 */ | ||
1693 | drvcmd[6]=current_drive->mode_xb_6; | ||
1694 | drvcmd[7]=current_drive->mode_yb_7|current_drive->volume_control; | ||
1695 | drvcmd[8]=current_drive->mode_xb_8; | ||
1696 | drvcmd[9]=current_drive->delay; | ||
1697 | i=cmd_out_T(); | ||
1698 | return (i); | ||
1699 | } | ||
1700 | /*==========================================================================*/ | ||
1701 | static int cc_prep_mode_T(void) | ||
1702 | { | ||
1703 | int i, j; | ||
1704 | |||
1705 | i=cc_get_mode_T(); | ||
1706 | if (i<0) return (i); | ||
1707 | for (i=0;i<10;i++) | ||
1708 | sprintf(&msgbuf[i*3], " %02X", infobuf[i]); | ||
1709 | msgbuf[i*3]=0; | ||
1710 | msg(DBG_TEA,"CMDT_GETMODE:%s\n", msgbuf); | ||
1711 | current_drive->speed_byte=0x02; /* 0x02: auto quad, 0x82: quad, 0x81: double, 0x80: single */ | ||
1712 | current_drive->frmsiz=make16(infobuf[2],infobuf[3]); | ||
1713 | current_drive->f_XA=infobuf[4]; | ||
1714 | if (current_drive->f_XA==0) current_drive->type_byte=0; | ||
1715 | else current_drive->type_byte=1; | ||
1716 | current_drive->mode_xb_6=infobuf[6]; | ||
1717 | current_drive->mode_yb_7=1; | ||
1718 | current_drive->mode_xb_8=infobuf[8]; | ||
1719 | current_drive->delay=0; /* 0, 1, 2, 3 */ | ||
1720 | j=cc_set_mode_T(); | ||
1721 | i=cc_get_mode_T(); | ||
1722 | for (i=0;i<10;i++) | ||
1723 | sprintf(&msgbuf[i*3], " %02X", infobuf[i]); | ||
1724 | msgbuf[i*3]=0; | ||
1725 | msg(DBG_TEA,"CMDT_GETMODE:%s\n", msgbuf); | ||
1726 | return (j); | ||
1727 | } | ||
1728 | /*==========================================================================*/ | ||
1729 | static int cc_SetSpeed(u_char speed, u_char x1, u_char x2) | ||
1730 | { | ||
1731 | int i; | ||
1732 | |||
1733 | if (fam0LV_drive) return (0); | ||
1734 | clr_cmdbuf(); | ||
1735 | response_count=0; | ||
1736 | if (fam1_drive) | ||
1737 | { | ||
1738 | drvcmd[0]=CMD1_SETMODE; | ||
1739 | drvcmd[1]=0x03; | ||
1740 | drvcmd[2]=speed; | ||
1741 | drvcmd[3]=x1; | ||
1742 | drvcmd[4]=x2; | ||
1743 | flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; | ||
1744 | } | ||
1745 | else if (fam2_drive) | ||
1746 | { | ||
1747 | drvcmd[0]=CMD2_SETSPEED; | ||
1748 | if (speed&speed_auto) | ||
1749 | { | ||
1750 | drvcmd[2]=0xFF; | ||
1751 | drvcmd[3]=0xFF; | ||
1752 | } | ||
1753 | else | ||
1754 | { | ||
1755 | drvcmd[2]=0; | ||
1756 | drvcmd[3]=150; | ||
1757 | } | ||
1758 | flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; | ||
1759 | } | ||
1760 | else if (famT_drive) | ||
1761 | { | ||
1762 | return (0); | ||
1763 | } | ||
1764 | i=cmd_out(); | ||
1765 | return (i); | ||
1766 | } | ||
1767 | /*==========================================================================*/ | ||
1768 | static int cc_SetVolume(void) | ||
1769 | { | ||
1770 | int i; | ||
1771 | u_char channel0,channel1,volume0,volume1; | ||
1772 | u_char control0,value0,control1,value1; | ||
1773 | |||
1774 | current_drive->diskstate_flags &= ~volume_bit; | ||
1775 | clr_cmdbuf(); | ||
1776 | channel0=current_drive->vol_chan0; | ||
1777 | volume0=current_drive->vol_ctrl0; | ||
1778 | channel1=control1=current_drive->vol_chan1; | ||
1779 | volume1=value1=current_drive->vol_ctrl1; | ||
1780 | control0=value0=0; | ||
1781 | |||
1782 | if (famV_drive) return (0); | ||
1783 | |||
1784 | if (((current_drive->drv_options&audio_mono)!=0)&&(current_drive->drv_type>=drv_211)) | ||
1785 | { | ||
1786 | if ((volume0!=0)&&(volume1==0)) | ||
1787 | { | ||
1788 | volume1=volume0; | ||
1789 | channel1=channel0; | ||
1790 | } | ||
1791 | else if ((volume0==0)&&(volume1!=0)) | ||
1792 | { | ||
1793 | volume0=volume1; | ||
1794 | channel0=channel1; | ||
1795 | } | ||
1796 | } | ||
1797 | if (channel0>1) | ||
1798 | { | ||
1799 | channel0=0; | ||
1800 | volume0=0; | ||
1801 | } | ||
1802 | if (channel1>1) | ||
1803 | { | ||
1804 | channel1=1; | ||
1805 | volume1=0; | ||
1806 | } | ||
1807 | |||
1808 | if (fam1_drive) | ||
1809 | { | ||
1810 | control0=channel0+1; | ||
1811 | control1=channel1+1; | ||
1812 | value0=(volume0>volume1)?volume0:volume1; | ||
1813 | value1=value0; | ||
1814 | if (volume0==0) control0=0; | ||
1815 | if (volume1==0) control1=0; | ||
1816 | drvcmd[0]=CMD1_SETMODE; | ||
1817 | drvcmd[1]=0x05; | ||
1818 | drvcmd[3]=control0; | ||
1819 | drvcmd[4]=value0; | ||
1820 | drvcmd[5]=control1; | ||
1821 | drvcmd[6]=value1; | ||
1822 | flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; | ||
1823 | } | ||
1824 | else if (fam2_drive) | ||
1825 | { | ||
1826 | control0=channel0+1; | ||
1827 | control1=channel1+1; | ||
1828 | value0=(volume0>volume1)?volume0:volume1; | ||
1829 | value1=value0; | ||
1830 | if (volume0==0) control0=0; | ||
1831 | if (volume1==0) control1=0; | ||
1832 | drvcmd[0]=CMD2_SETMODE; | ||
1833 | drvcmd[1]=0x0E; | ||
1834 | drvcmd[3]=control0; | ||
1835 | drvcmd[4]=value0; | ||
1836 | drvcmd[5]=control1; | ||
1837 | drvcmd[6]=value1; | ||
1838 | flags_cmd_out=f_putcmd|f_ResponseStatus; | ||
1839 | } | ||
1840 | else if (famL_drive) | ||
1841 | { | ||
1842 | if ((volume0==0)||(channel0!=0)) control0 |= 0x80; | ||
1843 | if ((volume1==0)||(channel1!=1)) control0 |= 0x40; | ||
1844 | if (volume0|volume1) value0=0x80; | ||
1845 | drvcmd[0]=CMDL_SETMODE; | ||
1846 | drvcmd[1]=0x03; | ||
1847 | drvcmd[4]=control0; | ||
1848 | drvcmd[5]=value0; | ||
1849 | flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1; | ||
1850 | } | ||
1851 | else if (fam0_drive) /* different firmware levels */ | ||
1852 | { | ||
1853 | if (current_drive->drv_type>=drv_300) | ||
1854 | { | ||
1855 | control0=volume0&0xFC; | ||
1856 | value0=volume1&0xFC; | ||
1857 | if ((volume0!=0)&&(volume0<4)) control0 |= 0x04; | ||
1858 | if ((volume1!=0)&&(volume1<4)) value0 |= 0x04; | ||
1859 | if (channel0!=0) control0 |= 0x01; | ||
1860 | if (channel1==1) value0 |= 0x01; | ||
1861 | } | ||
1862 | else | ||
1863 | { | ||
1864 | value0=(volume0>volume1)?volume0:volume1; | ||
1865 | if (current_drive->drv_type<drv_211) | ||
1866 | { | ||
1867 | if (channel0!=0) | ||
1868 | { | ||
1869 | i=channel1; | ||
1870 | channel1=channel0; | ||
1871 | channel0=i; | ||
1872 | i=volume1; | ||
1873 | volume1=volume0; | ||
1874 | volume0=i; | ||
1875 | } | ||
1876 | if (channel0==channel1) | ||
1877 | { | ||
1878 | if (channel0==0) | ||
1879 | { | ||
1880 | channel1=1; | ||
1881 | volume1=0; | ||
1882 | volume0=value0; | ||
1883 | } | ||
1884 | else | ||
1885 | { | ||
1886 | channel0=0; | ||
1887 | volume0=0; | ||
1888 | volume1=value0; | ||
1889 | } | ||
1890 | } | ||
1891 | } | ||
1892 | |||
1893 | if ((volume0!=0)&&(volume1!=0)) | ||
1894 | { | ||
1895 | if (volume0==0xFF) volume1=0xFF; | ||
1896 | else if (volume1==0xFF) volume0=0xFF; | ||
1897 | } | ||
1898 | else if (current_drive->drv_type<drv_201) volume0=volume1=value0; | ||
1899 | |||
1900 | if (current_drive->drv_type>=drv_201) | ||
1901 | { | ||
1902 | if (volume0==0) control0 |= 0x80; | ||
1903 | if (volume1==0) control0 |= 0x40; | ||
1904 | } | ||
1905 | if (current_drive->drv_type>=drv_211) | ||
1906 | { | ||
1907 | if (channel0!=0) control0 |= 0x20; | ||
1908 | if (channel1!=1) control0 |= 0x10; | ||
1909 | } | ||
1910 | } | ||
1911 | drvcmd[0]=CMD0_SETMODE; | ||
1912 | drvcmd[1]=0x83; | ||
1913 | drvcmd[4]=control0; | ||
1914 | drvcmd[5]=value0; | ||
1915 | flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check; | ||
1916 | } | ||
1917 | else if (famT_drive) | ||
1918 | { | ||
1919 | current_drive->volume_control=0; | ||
1920 | if (!volume0) current_drive->volume_control|=0x10; | ||
1921 | if (!volume1) current_drive->volume_control|=0x20; | ||
1922 | i=cc_prep_mode_T(); | ||
1923 | if (i<0) return (i); | ||
1924 | } | ||
1925 | if (!famT_drive) | ||
1926 | { | ||
1927 | response_count=0; | ||
1928 | i=cmd_out(); | ||
1929 | if (i<0) return (i); | ||
1930 | } | ||
1931 | current_drive->diskstate_flags |= volume_bit; | ||
1932 | return (0); | ||
1933 | } | ||
1934 | /*==========================================================================*/ | ||
1935 | static int GetStatus(void) | ||
1936 | { | ||
1937 | int i; | ||
1938 | |||
1939 | if (famT_drive) return (0); | ||
1940 | flags_cmd_out=f_getsta|f_ResponseStatus|f_obey_p_check; | ||
1941 | response_count=0; | ||
1942 | cmd_type=0; | ||
1943 | i=cmd_out(); | ||
1944 | return (i); | ||
1945 | } | ||
1946 | /*==========================================================================*/ | ||
1947 | static int cc_DriveReset(void) | ||
1948 | { | ||
1949 | int i; | ||
1950 | |||
1951 | msg(DBG_RES,"cc_DriveReset called.\n"); | ||
1952 | clr_cmdbuf(); | ||
1953 | response_count=0; | ||
1954 | if (fam0LV_drive) OUT(CDo_reset,0x00); | ||
1955 | else if (fam1_drive) | ||
1956 | { | ||
1957 | drvcmd[0]=CMD1_RESET; | ||
1958 | flags_cmd_out=f_putcmd; | ||
1959 | i=cmd_out(); | ||
1960 | } | ||
1961 | else if (fam2_drive) | ||
1962 | { | ||
1963 | drvcmd[0]=CMD2_RESET; | ||
1964 | flags_cmd_out=f_putcmd; | ||
1965 | i=cmd_out(); | ||
1966 | OUT(CDo_reset,0x00); | ||
1967 | } | ||
1968 | else if (famT_drive) | ||
1969 | { | ||
1970 | OUT(CDo_sel_i_d,0); | ||
1971 | OUT(CDo_enable,current_drive->drv_sel); | ||
1972 | OUT(CDo_command,CMDT_RESET); | ||
1973 | for (i=1;i<10;i++) OUT(CDo_command,0); | ||
1974 | } | ||
1975 | if (fam0LV_drive) sbp_sleep(5*HZ); /* wait 5 seconds */ | ||
1976 | else sbp_sleep(1*HZ); /* wait a second */ | ||
1977 | #if 1 | ||
1978 | if (famT_drive) | ||
1979 | { | ||
1980 | msg(DBG_TEA, "================CMDT_RESET given=================.\n"); | ||
1981 | sbp_sleep(3*HZ); | ||
1982 | } | ||
1983 | #endif /* 1 */ | ||
1984 | flush_status(); | ||
1985 | i=GetStatus(); | ||
1986 | if (i<0) return i; | ||
1987 | if (!famT_drive) | ||
1988 | if (current_drive->error_byte!=aud_12) return -501; | ||
1989 | return (0); | ||
1990 | } | ||
1991 | |||
1992 | /*==========================================================================*/ | ||
1993 | static int SetSpeed(void) | ||
1994 | { | ||
1995 | int i, speed; | ||
1996 | |||
1997 | if (!(current_drive->drv_options&(speed_auto|speed_300|speed_150))) return (0); | ||
1998 | speed=speed_auto; | ||
1999 | if (!(current_drive->drv_options&speed_auto)) | ||
2000 | { | ||
2001 | speed |= speed_300; | ||
2002 | if (!(current_drive->drv_options&speed_300)) speed=0; | ||
2003 | } | ||
2004 | i=cc_SetSpeed(speed,0,0); | ||
2005 | return (i); | ||
2006 | } | ||
2007 | |||
2008 | static void switch_drive(struct sbpcd_drive *); | ||
2009 | |||
2010 | static int sbpcd_select_speed(struct cdrom_device_info *cdi, int speed) | ||
2011 | { | ||
2012 | struct sbpcd_drive *p = cdi->handle; | ||
2013 | if (p != current_drive) | ||
2014 | switch_drive(p); | ||
2015 | |||
2016 | return cc_SetSpeed(speed == 2 ? speed_300 : speed_150, 0, 0); | ||
2017 | } | ||
2018 | |||
2019 | /*==========================================================================*/ | ||
2020 | static int DriveReset(void) | ||
2021 | { | ||
2022 | int i; | ||
2023 | |||
2024 | i=cc_DriveReset(); | ||
2025 | if (i<0) return (-22); | ||
2026 | do | ||
2027 | { | ||
2028 | i=GetStatus(); | ||
2029 | if ((i<0)&&(i!=-ERR_DISKCHANGE)) { | ||
2030 | return (-2); /* from sta2err */ | ||
2031 | } | ||
2032 | if (!st_caddy_in) break; | ||
2033 | sbp_sleep(1); | ||
2034 | } | ||
2035 | while (!st_diskok); | ||
2036 | #if 000 | ||
2037 | current_drive->CD_changed=1; | ||
2038 | #endif | ||
2039 | if ((st_door_closed) && (st_caddy_in)) | ||
2040 | { | ||
2041 | i=DiskInfo(); | ||
2042 | if (i<0) return (-23); | ||
2043 | } | ||
2044 | return (0); | ||
2045 | } | ||
2046 | |||
2047 | static int sbpcd_reset(struct cdrom_device_info *cdi) | ||
2048 | { | ||
2049 | struct sbpcd_drive *p = cdi->handle; | ||
2050 | if (p != current_drive) | ||
2051 | switch_drive(p); | ||
2052 | return DriveReset(); | ||
2053 | } | ||
2054 | |||
2055 | /*==========================================================================*/ | ||
2056 | static int cc_PlayAudio(int pos_audio_start,int pos_audio_end) | ||
2057 | { | ||
2058 | int i, j, n; | ||
2059 | |||
2060 | if (current_drive->audio_state==audio_playing) return (-EINVAL); | ||
2061 | clr_cmdbuf(); | ||
2062 | response_count=0; | ||
2063 | if (famLV_drive) | ||
2064 | { | ||
2065 | drvcmd[0]=CMDL_PLAY; | ||
2066 | i=msf2blk(pos_audio_start); | ||
2067 | n=msf2blk(pos_audio_end)+1-i; | ||
2068 | drvcmd[1]=(i>>16)&0x00FF; | ||
2069 | drvcmd[2]=(i>>8)&0x00FF; | ||
2070 | drvcmd[3]=i&0x00FF; | ||
2071 | drvcmd[4]=(n>>16)&0x00FF; | ||
2072 | drvcmd[5]=(n>>8)&0x00FF; | ||
2073 | drvcmd[6]=n&0x00FF; | ||
2074 | if (famL_drive) | ||
2075 | flags_cmd_out = f_putcmd | f_respo2 | f_lopsta | f_getsta | | ||
2076 | f_ResponseStatus | f_obey_p_check | f_wait_if_busy; | ||
2077 | else | ||
2078 | flags_cmd_out = f_putcmd; | ||
2079 | } | ||
2080 | else | ||
2081 | { | ||
2082 | j=1; | ||
2083 | if (fam1_drive) | ||
2084 | { | ||
2085 | drvcmd[0]=CMD1_PLAY_MSF; | ||
2086 | flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus | | ||
2087 | f_obey_p_check | f_wait_if_busy; | ||
2088 | } | ||
2089 | else if (fam2_drive) | ||
2090 | { | ||
2091 | drvcmd[0]=CMD2_PLAY_MSF; | ||
2092 | flags_cmd_out = f_putcmd | f_ResponseStatus | f_obey_p_check; | ||
2093 | } | ||
2094 | else if (famT_drive) | ||
2095 | { | ||
2096 | drvcmd[0]=CMDT_PLAY_MSF; | ||
2097 | j=3; | ||
2098 | response_count=1; | ||
2099 | } | ||
2100 | else if (fam0_drive) | ||
2101 | { | ||
2102 | drvcmd[0]=CMD0_PLAY_MSF; | ||
2103 | flags_cmd_out = f_putcmd | f_respo2 | f_lopsta | f_getsta | | ||
2104 | f_ResponseStatus | f_obey_p_check | f_wait_if_busy; | ||
2105 | } | ||
2106 | drvcmd[j]=(pos_audio_start>>16)&0x00FF; | ||
2107 | drvcmd[j+1]=(pos_audio_start>>8)&0x00FF; | ||
2108 | drvcmd[j+2]=pos_audio_start&0x00FF; | ||
2109 | drvcmd[j+3]=(pos_audio_end>>16)&0x00FF; | ||
2110 | drvcmd[j+4]=(pos_audio_end>>8)&0x00FF; | ||
2111 | drvcmd[j+5]=pos_audio_end&0x00FF; | ||
2112 | } | ||
2113 | i=cmd_out(); | ||
2114 | return (i); | ||
2115 | } | ||
2116 | /*==========================================================================*/ | ||
2117 | static int cc_Pause_Resume(int pau_res) | ||
2118 | { | ||
2119 | int i; | ||
2120 | |||
2121 | clr_cmdbuf(); | ||
2122 | response_count=0; | ||
2123 | if (fam1_drive) | ||
2124 | { | ||
2125 | drvcmd[0]=CMD1_PAU_RES; | ||
2126 | if (pau_res!=1) drvcmd[1]=0x80; | ||
2127 | flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check; | ||
2128 | } | ||
2129 | else if (fam2_drive) | ||
2130 | { | ||
2131 | drvcmd[0]=CMD2_PAU_RES; | ||
2132 | if (pau_res!=1) drvcmd[2]=0x01; | ||
2133 | flags_cmd_out=f_putcmd|f_ResponseStatus; | ||
2134 | } | ||
2135 | else if (fam0LV_drive) | ||
2136 | { | ||
2137 | drvcmd[0]=CMD0_PAU_RES; | ||
2138 | if (pau_res!=1) drvcmd[1]=0x80; | ||
2139 | if (famL_drive) | ||
2140 | flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus| | ||
2141 | f_obey_p_check|f_bit1; | ||
2142 | else if (famV_drive) | ||
2143 | flags_cmd_out=f_putcmd; | ||
2144 | else | ||
2145 | flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus| | ||
2146 | f_obey_p_check; | ||
2147 | } | ||
2148 | else if (famT_drive) | ||
2149 | { | ||
2150 | if (pau_res==3) return (cc_PlayAudio(current_drive->pos_audio_start,current_drive->pos_audio_end)); | ||
2151 | else if (pau_res==1) drvcmd[0]=CMDT_PAUSE; | ||
2152 | else return (-56); | ||
2153 | } | ||
2154 | i=cmd_out(); | ||
2155 | return (i); | ||
2156 | } | ||
2157 | /*==========================================================================*/ | ||
2158 | static int cc_LockDoor(char lock) | ||
2159 | { | ||
2160 | int i; | ||
2161 | |||
2162 | if (fam0_drive) return (0); | ||
2163 | msg(DBG_LCK,"cc_LockDoor: %d (drive %d)\n", lock, current_drive - D_S); | ||
2164 | msg(DBG_LCS,"p_door_locked bit %d before\n", st_door_locked); | ||
2165 | clr_cmdbuf(); | ||
2166 | response_count=0; | ||
2167 | if (fam1_drive) | ||
2168 | { | ||
2169 | drvcmd[0]=CMD1_LOCK_CTL; | ||
2170 | if (lock==1) drvcmd[1]=0x01; | ||
2171 | flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; | ||
2172 | } | ||
2173 | else if (fam2_drive) | ||
2174 | { | ||
2175 | drvcmd[0]=CMD2_LOCK_CTL; | ||
2176 | if (lock==1) drvcmd[4]=0x01; | ||
2177 | flags_cmd_out=f_putcmd|f_ResponseStatus; | ||
2178 | } | ||
2179 | else if (famLV_drive) | ||
2180 | { | ||
2181 | drvcmd[0]=CMDL_LOCK_CTL; | ||
2182 | if (lock==1) drvcmd[1]=0x01; | ||
2183 | if (famL_drive) | ||
2184 | flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1; | ||
2185 | else | ||
2186 | flags_cmd_out=f_putcmd; | ||
2187 | } | ||
2188 | else if (famT_drive) | ||
2189 | { | ||
2190 | drvcmd[0]=CMDT_LOCK_CTL; | ||
2191 | if (lock==1) drvcmd[4]=0x01; | ||
2192 | } | ||
2193 | i=cmd_out(); | ||
2194 | msg(DBG_LCS,"p_door_locked bit %d after\n", st_door_locked); | ||
2195 | return (i); | ||
2196 | } | ||
2197 | /*==========================================================================*/ | ||
2198 | /*==========================================================================*/ | ||
2199 | static int UnLockDoor(void) | ||
2200 | { | ||
2201 | int i,j; | ||
2202 | |||
2203 | j=20; | ||
2204 | do | ||
2205 | { | ||
2206 | i=cc_LockDoor(0); | ||
2207 | --j; | ||
2208 | sbp_sleep(1); | ||
2209 | } | ||
2210 | while ((i<0)&&(j)); | ||
2211 | if (i<0) | ||
2212 | { | ||
2213 | cc_DriveReset(); | ||
2214 | return -84; | ||
2215 | } | ||
2216 | return (0); | ||
2217 | } | ||
2218 | /*==========================================================================*/ | ||
2219 | static int LockDoor(void) | ||
2220 | { | ||
2221 | int i,j; | ||
2222 | |||
2223 | j=20; | ||
2224 | do | ||
2225 | { | ||
2226 | i=cc_LockDoor(1); | ||
2227 | --j; | ||
2228 | sbp_sleep(1); | ||
2229 | } | ||
2230 | while ((i<0)&&(j)); | ||
2231 | if (j==0) | ||
2232 | { | ||
2233 | cc_DriveReset(); | ||
2234 | j=20; | ||
2235 | do | ||
2236 | { | ||
2237 | i=cc_LockDoor(1); | ||
2238 | --j; | ||
2239 | sbp_sleep(1); | ||
2240 | } | ||
2241 | while ((i<0)&&(j)); | ||
2242 | } | ||
2243 | return (i); | ||
2244 | } | ||
2245 | |||
2246 | static int sbpcd_lock_door(struct cdrom_device_info *cdi, int lock) | ||
2247 | { | ||
2248 | return lock ? LockDoor() : UnLockDoor(); | ||
2249 | } | ||
2250 | |||
2251 | /*==========================================================================*/ | ||
2252 | static int cc_CloseTray(void) | ||
2253 | { | ||
2254 | int i; | ||
2255 | |||
2256 | if (fam0_drive) return (0); | ||
2257 | msg(DBG_LCK,"cc_CloseTray (drive %d)\n", current_drive - D_S); | ||
2258 | msg(DBG_LCS,"p_door_closed bit %d before\n", st_door_closed); | ||
2259 | |||
2260 | clr_cmdbuf(); | ||
2261 | response_count=0; | ||
2262 | if (fam1_drive) | ||
2263 | { | ||
2264 | drvcmd[0]=CMD1_TRAY_CTL; | ||
2265 | flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check; | ||
2266 | } | ||
2267 | else if (fam2_drive) | ||
2268 | { | ||
2269 | drvcmd[0]=CMD2_TRAY_CTL; | ||
2270 | drvcmd[1]=0x01; | ||
2271 | drvcmd[4]=0x03; /* "insert" */ | ||
2272 | flags_cmd_out=f_putcmd|f_ResponseStatus; | ||
2273 | } | ||
2274 | else if (famLV_drive) | ||
2275 | { | ||
2276 | drvcmd[0]=CMDL_TRAY_CTL; | ||
2277 | if (famLV_drive) | ||
2278 | flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta| | ||
2279 | f_ResponseStatus|f_obey_p_check|f_bit1; | ||
2280 | else | ||
2281 | flags_cmd_out=f_putcmd; | ||
2282 | } | ||
2283 | else if (famT_drive) | ||
2284 | { | ||
2285 | drvcmd[0]=CMDT_TRAY_CTL; | ||
2286 | drvcmd[4]=0x03; /* "insert" */ | ||
2287 | } | ||
2288 | i=cmd_out(); | ||
2289 | msg(DBG_LCS,"p_door_closed bit %d after\n", st_door_closed); | ||
2290 | |||
2291 | i=cc_ReadError(); | ||
2292 | flags_cmd_out |= f_respo2; | ||
2293 | cc_ReadStatus(); /* command: give 1-byte status */ | ||
2294 | i=ResponseStatus(); | ||
2295 | if (famT_drive&&(i<0)) | ||
2296 | { | ||
2297 | cc_DriveReset(); | ||
2298 | i=ResponseStatus(); | ||
2299 | #if 0 | ||
2300 | sbp_sleep(HZ); | ||
2301 | #endif /* 0 */ | ||
2302 | i=ResponseStatus(); | ||
2303 | } | ||
2304 | if (i<0) | ||
2305 | { | ||
2306 | msg(DBG_INF,"sbpcd cc_CloseTray: ResponseStatus timed out (%d).\n",i); | ||
2307 | } | ||
2308 | if (!(famT_drive)) | ||
2309 | { | ||
2310 | if (!st_spinning) | ||
2311 | { | ||
2312 | cc_SpinUp(); | ||
2313 | if (st_check) i=cc_ReadError(); | ||
2314 | flags_cmd_out |= f_respo2; | ||
2315 | cc_ReadStatus(); | ||
2316 | i=ResponseStatus(); | ||
2317 | } else { | ||
2318 | } | ||
2319 | } | ||
2320 | i=DiskInfo(); | ||
2321 | return (i); | ||
2322 | } | ||
2323 | |||
2324 | static int sbpcd_tray_move(struct cdrom_device_info *cdi, int position) | ||
2325 | { | ||
2326 | int retval=0; | ||
2327 | switch_drive(cdi->handle); | ||
2328 | /* DUH! --AJK */ | ||
2329 | if(current_drive->CD_changed != 0xFF) { | ||
2330 | current_drive->CD_changed=0xFF; | ||
2331 | current_drive->diskstate_flags &= ~cd_size_bit; | ||
2332 | } | ||
2333 | if (position == 1) { | ||
2334 | cc_SpinDown(); | ||
2335 | } else { | ||
2336 | retval=cc_CloseTray(); | ||
2337 | } | ||
2338 | return retval; | ||
2339 | } | ||
2340 | |||
2341 | /*==========================================================================*/ | ||
2342 | static int cc_ReadSubQ(void) | ||
2343 | { | ||
2344 | int i,j; | ||
2345 | |||
2346 | current_drive->diskstate_flags &= ~subq_bit; | ||
2347 | for (j=255;j>0;j--) | ||
2348 | { | ||
2349 | clr_cmdbuf(); | ||
2350 | if (fam1_drive) | ||
2351 | { | ||
2352 | drvcmd[0]=CMD1_READSUBQ; | ||
2353 | flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; | ||
2354 | response_count=11; | ||
2355 | } | ||
2356 | else if (fam2_drive) | ||
2357 | { | ||
2358 | drvcmd[0]=CMD2_READSUBQ; | ||
2359 | drvcmd[1]=0x02; | ||
2360 | drvcmd[3]=0x01; | ||
2361 | flags_cmd_out=f_putcmd; | ||
2362 | response_count=10; | ||
2363 | } | ||
2364 | else if (fam0LV_drive) | ||
2365 | { | ||
2366 | drvcmd[0]=CMD0_READSUBQ; | ||
2367 | drvcmd[1]=0x02; | ||
2368 | if (famLV_drive) | ||
2369 | flags_cmd_out=f_putcmd; | ||
2370 | else | ||
2371 | flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check; | ||
2372 | response_count=13; | ||
2373 | } | ||
2374 | else if (famT_drive) | ||
2375 | { | ||
2376 | response_count=12; | ||
2377 | drvcmd[0]=CMDT_READSUBQ; | ||
2378 | drvcmd[1]=0x02; | ||
2379 | drvcmd[2]=0x40; | ||
2380 | drvcmd[3]=0x01; | ||
2381 | drvcmd[8]=response_count; | ||
2382 | } | ||
2383 | i=cmd_out(); | ||
2384 | if (i<0) return (i); | ||
2385 | for (i=0;i<response_count;i++) | ||
2386 | { | ||
2387 | sprintf(&msgbuf[i*3], " %02X", infobuf[i]); | ||
2388 | msgbuf[i*3]=0; | ||
2389 | msg(DBG_SQ1,"cc_ReadSubQ:%s\n", msgbuf); | ||
2390 | } | ||
2391 | if (famT_drive) break; | ||
2392 | if (infobuf[0]!=0) break; | ||
2393 | if ((!st_spinning) || (j==1)) | ||
2394 | { | ||
2395 | current_drive->SubQ_ctl_adr=current_drive->SubQ_trk=current_drive->SubQ_pnt_idx=current_drive->SubQ_whatisthis=0; | ||
2396 | current_drive->SubQ_run_tot=current_drive->SubQ_run_trk=0; | ||
2397 | return (0); | ||
2398 | } | ||
2399 | } | ||
2400 | if (famT_drive) current_drive->SubQ_ctl_adr=infobuf[1]; | ||
2401 | else current_drive->SubQ_ctl_adr=swap_nibbles(infobuf[1]); | ||
2402 | current_drive->SubQ_trk=byt2bcd(infobuf[2]); | ||
2403 | current_drive->SubQ_pnt_idx=byt2bcd(infobuf[3]); | ||
2404 | if (fam0LV_drive) i=5; | ||
2405 | else if (fam12_drive) i=4; | ||
2406 | else if (famT_drive) i=8; | ||
2407 | current_drive->SubQ_run_tot=make32(make16(0,infobuf[i]),make16(infobuf[i+1],infobuf[i+2])); /* msf-bin */ | ||
2408 | i=7; | ||
2409 | if (fam0LV_drive) i=9; | ||
2410 | else if (fam12_drive) i=7; | ||
2411 | else if (famT_drive) i=4; | ||
2412 | current_drive->SubQ_run_trk=make32(make16(0,infobuf[i]),make16(infobuf[i+1],infobuf[i+2])); /* msf-bin */ | ||
2413 | current_drive->SubQ_whatisthis=infobuf[i+3]; | ||
2414 | current_drive->diskstate_flags |= subq_bit; | ||
2415 | return (0); | ||
2416 | } | ||
2417 | /*==========================================================================*/ | ||
2418 | static int cc_ModeSense(void) | ||
2419 | { | ||
2420 | int i; | ||
2421 | |||
2422 | if (fam2_drive) return (0); | ||
2423 | if (famV_drive) return (0); | ||
2424 | current_drive->diskstate_flags &= ~frame_size_bit; | ||
2425 | clr_cmdbuf(); | ||
2426 | if (fam1_drive) | ||
2427 | { | ||
2428 | response_count=5; | ||
2429 | drvcmd[0]=CMD1_GETMODE; | ||
2430 | flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; | ||
2431 | } | ||
2432 | else if (fam0L_drive) | ||
2433 | { | ||
2434 | response_count=2; | ||
2435 | drvcmd[0]=CMD0_GETMODE; | ||
2436 | if (famL_drive) flags_cmd_out=f_putcmd; | ||
2437 | else flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check; | ||
2438 | } | ||
2439 | else if (famT_drive) | ||
2440 | { | ||
2441 | response_count=10; | ||
2442 | drvcmd[0]=CMDT_GETMODE; | ||
2443 | drvcmd[4]=response_count; | ||
2444 | } | ||
2445 | i=cmd_out(); | ||
2446 | if (i<0) return (i); | ||
2447 | i=0; | ||
2448 | current_drive->sense_byte=0; | ||
2449 | if (fam1_drive) current_drive->sense_byte=infobuf[i++]; | ||
2450 | else if (famT_drive) | ||
2451 | { | ||
2452 | if (infobuf[4]==0x01) current_drive->xa_byte=0x20; | ||
2453 | else current_drive->xa_byte=0; | ||
2454 | i=2; | ||
2455 | } | ||
2456 | current_drive->frame_size=make16(infobuf[i],infobuf[i+1]); | ||
2457 | for (i=0;i<response_count;i++) | ||
2458 | sprintf(&msgbuf[i*3], " %02X", infobuf[i]); | ||
2459 | msgbuf[i*3]=0; | ||
2460 | msg(DBG_XA1,"cc_ModeSense:%s\n", msgbuf); | ||
2461 | |||
2462 | current_drive->diskstate_flags |= frame_size_bit; | ||
2463 | return (0); | ||
2464 | } | ||
2465 | /*==========================================================================*/ | ||
2466 | /*==========================================================================*/ | ||
2467 | static int cc_ModeSelect(int framesize) | ||
2468 | { | ||
2469 | int i; | ||
2470 | |||
2471 | if (fam2_drive) return (0); | ||
2472 | if (famV_drive) return (0); | ||
2473 | current_drive->diskstate_flags &= ~frame_size_bit; | ||
2474 | clr_cmdbuf(); | ||
2475 | current_drive->frame_size=framesize; | ||
2476 | if (framesize==CD_FRAMESIZE_RAW) current_drive->sense_byte=0x82; | ||
2477 | else current_drive->sense_byte=0x00; | ||
2478 | |||
2479 | msg(DBG_XA1,"cc_ModeSelect: %02X %04X\n", | ||
2480 | current_drive->sense_byte, current_drive->frame_size); | ||
2481 | |||
2482 | if (fam1_drive) | ||
2483 | { | ||
2484 | drvcmd[0]=CMD1_SETMODE; | ||
2485 | drvcmd[1]=0x00; | ||
2486 | drvcmd[2]=current_drive->sense_byte; | ||
2487 | drvcmd[3]=(current_drive->frame_size>>8)&0xFF; | ||
2488 | drvcmd[4]=current_drive->frame_size&0xFF; | ||
2489 | flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; | ||
2490 | } | ||
2491 | else if (fam0L_drive) | ||
2492 | { | ||
2493 | drvcmd[0]=CMD0_SETMODE; | ||
2494 | drvcmd[1]=0x00; | ||
2495 | drvcmd[2]=(current_drive->frame_size>>8)&0xFF; | ||
2496 | drvcmd[3]=current_drive->frame_size&0xFF; | ||
2497 | drvcmd[4]=0x00; | ||
2498 | if(famL_drive) | ||
2499 | flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check; | ||
2500 | else | ||
2501 | flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check; | ||
2502 | } | ||
2503 | else if (famT_drive) | ||
2504 | { | ||
2505 | return (-1); | ||
2506 | } | ||
2507 | response_count=0; | ||
2508 | i=cmd_out(); | ||
2509 | if (i<0) return (i); | ||
2510 | current_drive->diskstate_flags |= frame_size_bit; | ||
2511 | return (0); | ||
2512 | } | ||
2513 | /*==========================================================================*/ | ||
2514 | static int cc_GetVolume(void) | ||
2515 | { | ||
2516 | int i; | ||
2517 | u_char switches; | ||
2518 | u_char chan0=0; | ||
2519 | u_char vol0=0; | ||
2520 | u_char chan1=1; | ||
2521 | u_char vol1=0; | ||
2522 | |||
2523 | if (famV_drive) return (0); | ||
2524 | current_drive->diskstate_flags &= ~volume_bit; | ||
2525 | clr_cmdbuf(); | ||
2526 | if (fam1_drive) | ||
2527 | { | ||
2528 | drvcmd[0]=CMD1_GETMODE; | ||
2529 | drvcmd[1]=0x05; | ||
2530 | response_count=5; | ||
2531 | flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; | ||
2532 | } | ||
2533 | else if (fam2_drive) | ||
2534 | { | ||
2535 | drvcmd[0]=CMD2_GETMODE; | ||
2536 | drvcmd[1]=0x0E; | ||
2537 | response_count=5; | ||
2538 | flags_cmd_out=f_putcmd; | ||
2539 | } | ||
2540 | else if (fam0L_drive) | ||
2541 | { | ||
2542 | drvcmd[0]=CMD0_GETMODE; | ||
2543 | drvcmd[1]=0x03; | ||
2544 | response_count=2; | ||
2545 | if(famL_drive) | ||
2546 | flags_cmd_out=f_putcmd; | ||
2547 | else | ||
2548 | flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check; | ||
2549 | } | ||
2550 | else if (famT_drive) | ||
2551 | { | ||
2552 | i=cc_get_mode_T(); | ||
2553 | if (i<0) return (i); | ||
2554 | } | ||
2555 | if (!famT_drive) | ||
2556 | { | ||
2557 | i=cmd_out(); | ||
2558 | if (i<0) return (i); | ||
2559 | } | ||
2560 | if (fam1_drive) | ||
2561 | { | ||
2562 | chan0=infobuf[1]&0x0F; | ||
2563 | vol0=infobuf[2]; | ||
2564 | chan1=infobuf[3]&0x0F; | ||
2565 | vol1=infobuf[4]; | ||
2566 | if (chan0==0) | ||
2567 | { | ||
2568 | chan0=1; | ||
2569 | vol0=0; | ||
2570 | } | ||
2571 | if (chan1==0) | ||
2572 | { | ||
2573 | chan1=2; | ||
2574 | vol1=0; | ||
2575 | } | ||
2576 | chan0 >>= 1; | ||
2577 | chan1 >>= 1; | ||
2578 | } | ||
2579 | else if (fam2_drive) | ||
2580 | { | ||
2581 | chan0=infobuf[1]; | ||
2582 | vol0=infobuf[2]; | ||
2583 | chan1=infobuf[3]; | ||
2584 | vol1=infobuf[4]; | ||
2585 | } | ||
2586 | else if (famL_drive) | ||
2587 | { | ||
2588 | chan0=0; | ||
2589 | chan1=1; | ||
2590 | vol0=vol1=infobuf[1]; | ||
2591 | switches=infobuf[0]; | ||
2592 | if ((switches&0x80)!=0) chan0=1; | ||
2593 | if ((switches&0x40)!=0) chan1=0; | ||
2594 | } | ||
2595 | else if (fam0_drive) /* different firmware levels */ | ||
2596 | { | ||
2597 | chan0=0; | ||
2598 | chan1=1; | ||
2599 | vol0=vol1=infobuf[1]; | ||
2600 | if (current_drive->drv_type>=drv_201) | ||
2601 | { | ||
2602 | if (current_drive->drv_type<drv_300) | ||
2603 | { | ||
2604 | switches=infobuf[0]; | ||
2605 | if ((switches&0x80)!=0) vol0=0; | ||
2606 | if ((switches&0x40)!=0) vol1=0; | ||
2607 | if (current_drive->drv_type>=drv_211) | ||
2608 | { | ||
2609 | if ((switches&0x20)!=0) chan0=1; | ||
2610 | if ((switches&0x10)!=0) chan1=0; | ||
2611 | } | ||
2612 | } | ||
2613 | else | ||
2614 | { | ||
2615 | vol0=infobuf[0]; | ||
2616 | if ((vol0&0x01)!=0) chan0=1; | ||
2617 | if ((vol1&0x01)==0) chan1=0; | ||
2618 | vol0 &= 0xFC; | ||
2619 | vol1 &= 0xFC; | ||
2620 | if (vol0!=0) vol0 += 3; | ||
2621 | if (vol1!=0) vol1 += 3; | ||
2622 | } | ||
2623 | } | ||
2624 | } | ||
2625 | else if (famT_drive) | ||
2626 | { | ||
2627 | current_drive->volume_control=infobuf[7]; | ||
2628 | chan0=0; | ||
2629 | chan1=1; | ||
2630 | if (current_drive->volume_control&0x10) vol0=0; | ||
2631 | else vol0=0xff; | ||
2632 | if (current_drive->volume_control&0x20) vol1=0; | ||
2633 | else vol1=0xff; | ||
2634 | } | ||
2635 | current_drive->vol_chan0=chan0; | ||
2636 | current_drive->vol_ctrl0=vol0; | ||
2637 | current_drive->vol_chan1=chan1; | ||
2638 | current_drive->vol_ctrl1=vol1; | ||
2639 | #if 000 | ||
2640 | current_drive->vol_chan2=2; | ||
2641 | current_drive->vol_ctrl2=0xFF; | ||
2642 | current_drive->vol_chan3=3; | ||
2643 | current_drive->vol_ctrl3=0xFF; | ||
2644 | #endif /* 000 */ | ||
2645 | current_drive->diskstate_flags |= volume_bit; | ||
2646 | return (0); | ||
2647 | } | ||
2648 | /*==========================================================================*/ | ||
2649 | static int cc_ReadCapacity(void) | ||
2650 | { | ||
2651 | int i, j; | ||
2652 | |||
2653 | if (fam2_drive) return (0); /* some firmware lacks this command */ | ||
2654 | if (famLV_drive) return (0); /* some firmware lacks this command */ | ||
2655 | if (famT_drive) return (0); /* done with cc_ReadTocDescr() */ | ||
2656 | current_drive->diskstate_flags &= ~cd_size_bit; | ||
2657 | for (j=3;j>0;j--) | ||
2658 | { | ||
2659 | clr_cmdbuf(); | ||
2660 | if (fam1_drive) | ||
2661 | { | ||
2662 | drvcmd[0]=CMD1_CAPACITY; | ||
2663 | response_count=5; | ||
2664 | flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; | ||
2665 | } | ||
2666 | #if 00 | ||
2667 | else if (fam2_drive) | ||
2668 | { | ||
2669 | drvcmd[0]=CMD2_CAPACITY; | ||
2670 | response_count=8; | ||
2671 | flags_cmd_out=f_putcmd; | ||
2672 | } | ||
2673 | #endif | ||
2674 | else if (fam0_drive) | ||
2675 | { | ||
2676 | drvcmd[0]=CMD0_CAPACITY; | ||
2677 | response_count=5; | ||
2678 | flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check; | ||
2679 | } | ||
2680 | i=cmd_out(); | ||
2681 | if (i>=0) break; | ||
2682 | msg(DBG_000,"cc_ReadCapacity: cmd_out: err %d\n", i); | ||
2683 | cc_ReadError(); | ||
2684 | } | ||
2685 | if (j==0) return (i); | ||
2686 | if (fam1_drive) current_drive->CDsize_frm=msf2blk(make32(make16(0,infobuf[0]),make16(infobuf[1],infobuf[2])))+CD_MSF_OFFSET; | ||
2687 | else if (fam0_drive) current_drive->CDsize_frm=make32(make16(0,infobuf[0]),make16(infobuf[1],infobuf[2])); | ||
2688 | #if 00 | ||
2689 | else if (fam2_drive) current_drive->CDsize_frm=make32(make16(infobuf[0],infobuf[1]),make16(infobuf[2],infobuf[3])); | ||
2690 | #endif | ||
2691 | current_drive->diskstate_flags |= cd_size_bit; | ||
2692 | msg(DBG_000,"cc_ReadCapacity: %d frames.\n", current_drive->CDsize_frm); | ||
2693 | return (0); | ||
2694 | } | ||
2695 | /*==========================================================================*/ | ||
2696 | static int cc_ReadTocDescr(void) | ||
2697 | { | ||
2698 | int i; | ||
2699 | |||
2700 | current_drive->diskstate_flags &= ~toc_bit; | ||
2701 | clr_cmdbuf(); | ||
2702 | if (fam1_drive) | ||
2703 | { | ||
2704 | drvcmd[0]=CMD1_DISKINFO; | ||
2705 | response_count=6; | ||
2706 | flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; | ||
2707 | } | ||
2708 | else if (fam0LV_drive) | ||
2709 | { | ||
2710 | drvcmd[0]=CMD0_DISKINFO; | ||
2711 | response_count=6; | ||
2712 | if(famLV_drive) | ||
2713 | flags_cmd_out=f_putcmd; | ||
2714 | else | ||
2715 | flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check; | ||
2716 | } | ||
2717 | else if (fam2_drive) | ||
2718 | { | ||
2719 | /* possibly longer timeout periods necessary */ | ||
2720 | current_drive->f_multisession=0; | ||
2721 | drvcmd[0]=CMD2_DISKINFO; | ||
2722 | drvcmd[1]=0x02; | ||
2723 | drvcmd[2]=0xAB; | ||
2724 | drvcmd[3]=0xFF; /* session */ | ||
2725 | response_count=8; | ||
2726 | flags_cmd_out=f_putcmd; | ||
2727 | } | ||
2728 | else if (famT_drive) | ||
2729 | { | ||
2730 | current_drive->f_multisession=0; | ||
2731 | response_count=12; | ||
2732 | drvcmd[0]=CMDT_DISKINFO; | ||
2733 | drvcmd[1]=0x02; | ||
2734 | drvcmd[6]=CDROM_LEADOUT; | ||
2735 | drvcmd[8]=response_count; | ||
2736 | drvcmd[9]=0x00; | ||
2737 | } | ||
2738 | i=cmd_out(); | ||
2739 | if (i<0) return (i); | ||
2740 | if ((famT_drive)&&(i<response_count)) return (-100-i); | ||
2741 | if ((fam1_drive)||(fam2_drive)||(fam0LV_drive)) | ||
2742 | current_drive->xa_byte=infobuf[0]; | ||
2743 | if (fam2_drive) | ||
2744 | { | ||
2745 | current_drive->first_session=infobuf[1]; | ||
2746 | current_drive->last_session=infobuf[2]; | ||
2747 | current_drive->n_first_track=infobuf[3]; | ||
2748 | current_drive->n_last_track=infobuf[4]; | ||
2749 | if (current_drive->first_session!=current_drive->last_session) | ||
2750 | { | ||
2751 | current_drive->f_multisession=1; | ||
2752 | current_drive->lba_multi=msf2blk(make32(make16(0,infobuf[5]),make16(infobuf[6],infobuf[7]))); | ||
2753 | } | ||
2754 | #if 0 | ||
2755 | if (current_drive->first_session!=current_drive->last_session) | ||
2756 | { | ||
2757 | if (current_drive->last_session<=20) | ||
2758 | zwanzig=current_drive->last_session+1; | ||
2759 | else zwanzig=20; | ||
2760 | for (count=current_drive->first_session;count<zwanzig;count++) | ||
2761 | { | ||
2762 | drvcmd[0]=CMD2_DISKINFO; | ||
2763 | drvcmd[1]=0x02; | ||
2764 | drvcmd[2]=0xAB; | ||
2765 | drvcmd[3]=count; | ||
2766 | response_count=8; | ||
2767 | flags_cmd_out=f_putcmd; | ||
2768 | i=cmd_out(); | ||
2769 | if (i<0) return (i); | ||
2770 | current_drive->msf_multi_n[count]=make32(make16(0,infobuf[5]),make16(infobuf[6],infobuf[7])); | ||
2771 | } | ||
2772 | current_drive->diskstate_flags |= multisession_bit; | ||
2773 | } | ||
2774 | #endif | ||
2775 | drvcmd[0]=CMD2_DISKINFO; | ||
2776 | drvcmd[1]=0x02; | ||
2777 | drvcmd[2]=0xAA; | ||
2778 | drvcmd[3]=0xFF; | ||
2779 | response_count=5; | ||
2780 | flags_cmd_out=f_putcmd; | ||
2781 | i=cmd_out(); | ||
2782 | if (i<0) return (i); | ||
2783 | current_drive->size_msf=make32(make16(0,infobuf[2]),make16(infobuf[3],infobuf[4])); | ||
2784 | current_drive->size_blk=msf2blk(current_drive->size_msf); | ||
2785 | current_drive->CDsize_frm=current_drive->size_blk+1; | ||
2786 | } | ||
2787 | else if (famT_drive) | ||
2788 | { | ||
2789 | current_drive->size_msf=make32(make16(infobuf[8],infobuf[9]),make16(infobuf[10],infobuf[11])); | ||
2790 | current_drive->size_blk=msf2blk(current_drive->size_msf); | ||
2791 | current_drive->CDsize_frm=current_drive->size_blk+1; | ||
2792 | current_drive->n_first_track=infobuf[2]; | ||
2793 | current_drive->n_last_track=infobuf[3]; | ||
2794 | } | ||
2795 | else | ||
2796 | { | ||
2797 | current_drive->n_first_track=infobuf[1]; | ||
2798 | current_drive->n_last_track=infobuf[2]; | ||
2799 | current_drive->size_msf=make32(make16(0,infobuf[3]),make16(infobuf[4],infobuf[5])); | ||
2800 | current_drive->size_blk=msf2blk(current_drive->size_msf); | ||
2801 | if (famLV_drive) current_drive->CDsize_frm=current_drive->size_blk+1; | ||
2802 | } | ||
2803 | current_drive->diskstate_flags |= toc_bit; | ||
2804 | msg(DBG_TOC,"TocDesc: xa %02X firstt %02X lastt %02X size %08X firstses %02X lastsess %02X\n", | ||
2805 | current_drive->xa_byte, | ||
2806 | current_drive->n_first_track, | ||
2807 | current_drive->n_last_track, | ||
2808 | current_drive->size_msf, | ||
2809 | current_drive->first_session, | ||
2810 | current_drive->last_session); | ||
2811 | return (0); | ||
2812 | } | ||
2813 | /*==========================================================================*/ | ||
2814 | static int cc_ReadTocEntry(int num) | ||
2815 | { | ||
2816 | int i; | ||
2817 | |||
2818 | clr_cmdbuf(); | ||
2819 | if (fam1_drive) | ||
2820 | { | ||
2821 | drvcmd[0]=CMD1_READTOC; | ||
2822 | drvcmd[2]=num; | ||
2823 | response_count=8; | ||
2824 | flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; | ||
2825 | } | ||
2826 | else if (fam2_drive) | ||
2827 | { | ||
2828 | /* possibly longer timeout periods necessary */ | ||
2829 | drvcmd[0]=CMD2_DISKINFO; | ||
2830 | drvcmd[1]=0x02; | ||
2831 | drvcmd[2]=num; | ||
2832 | response_count=5; | ||
2833 | flags_cmd_out=f_putcmd; | ||
2834 | } | ||
2835 | else if (fam0LV_drive) | ||
2836 | { | ||
2837 | drvcmd[0]=CMD0_READTOC; | ||
2838 | drvcmd[1]=0x02; | ||
2839 | drvcmd[2]=num; | ||
2840 | response_count=8; | ||
2841 | if (famLV_drive) | ||
2842 | flags_cmd_out=f_putcmd; | ||
2843 | else | ||
2844 | flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check; | ||
2845 | } | ||
2846 | else if (famT_drive) | ||
2847 | { | ||
2848 | response_count=12; | ||
2849 | drvcmd[0]=CMDT_DISKINFO; | ||
2850 | drvcmd[1]=0x02; | ||
2851 | drvcmd[6]=num; | ||
2852 | drvcmd[8]=response_count; | ||
2853 | drvcmd[9]=0x00; | ||
2854 | } | ||
2855 | i=cmd_out(); | ||
2856 | if (i<0) return (i); | ||
2857 | if ((famT_drive)&&(i<response_count)) return (-100-i); | ||
2858 | if ((fam1_drive)||(fam0LV_drive)) | ||
2859 | { | ||
2860 | current_drive->TocEnt_nixbyte=infobuf[0]; | ||
2861 | i=1; | ||
2862 | } | ||
2863 | else if (fam2_drive) i=0; | ||
2864 | else if (famT_drive) i=5; | ||
2865 | current_drive->TocEnt_ctl_adr=swap_nibbles(infobuf[i++]); | ||
2866 | if ((fam1_drive)||(fam0L_drive)) | ||
2867 | { | ||
2868 | current_drive->TocEnt_number=infobuf[i++]; | ||
2869 | current_drive->TocEnt_format=infobuf[i]; | ||
2870 | } | ||
2871 | else | ||
2872 | { | ||
2873 | current_drive->TocEnt_number=num; | ||
2874 | current_drive->TocEnt_format=0; | ||
2875 | } | ||
2876 | if (fam1_drive) i=4; | ||
2877 | else if (fam0LV_drive) i=5; | ||
2878 | else if (fam2_drive) i=2; | ||
2879 | else if (famT_drive) i=9; | ||
2880 | current_drive->TocEnt_address=make32(make16(0,infobuf[i]), | ||
2881 | make16(infobuf[i+1],infobuf[i+2])); | ||
2882 | for (i=0;i<response_count;i++) | ||
2883 | sprintf(&msgbuf[i*3], " %02X", infobuf[i]); | ||
2884 | msgbuf[i*3]=0; | ||
2885 | msg(DBG_ECS,"TocEntry:%s\n", msgbuf); | ||
2886 | msg(DBG_TOC,"TocEntry: %02X %02X %02X %02X %08X\n", | ||
2887 | current_drive->TocEnt_nixbyte, current_drive->TocEnt_ctl_adr, | ||
2888 | current_drive->TocEnt_number, current_drive->TocEnt_format, | ||
2889 | current_drive->TocEnt_address); | ||
2890 | return (0); | ||
2891 | } | ||
2892 | /*==========================================================================*/ | ||
2893 | static int cc_ReadPacket(void) | ||
2894 | { | ||
2895 | int i; | ||
2896 | |||
2897 | clr_cmdbuf(); | ||
2898 | drvcmd[0]=CMD0_PACKET; | ||
2899 | drvcmd[1]=response_count; | ||
2900 | if(famL_drive) flags_cmd_out=f_putcmd; | ||
2901 | else if (fam01_drive) | ||
2902 | flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check; | ||
2903 | else if (fam2_drive) return (-1); /* not implemented yet */ | ||
2904 | else if (famT_drive) | ||
2905 | { | ||
2906 | return (-1); | ||
2907 | } | ||
2908 | i=cmd_out(); | ||
2909 | return (i); | ||
2910 | } | ||
2911 | /*==========================================================================*/ | ||
2912 | static int convert_UPC(u_char *p) | ||
2913 | { | ||
2914 | int i; | ||
2915 | |||
2916 | p++; | ||
2917 | if (fam0L_drive) p[13]=0; | ||
2918 | for (i=0;i<7;i++) | ||
2919 | { | ||
2920 | if (fam1_drive) current_drive->UPC_buf[i]=swap_nibbles(*p++); | ||
2921 | else if (fam0L_drive) | ||
2922 | { | ||
2923 | current_drive->UPC_buf[i]=((*p++)<<4)&0xFF; | ||
2924 | current_drive->UPC_buf[i] |= *p++; | ||
2925 | } | ||
2926 | else if (famT_drive) | ||
2927 | { | ||
2928 | return (-1); | ||
2929 | } | ||
2930 | else /* CD200 */ | ||
2931 | { | ||
2932 | return (-1); | ||
2933 | } | ||
2934 | } | ||
2935 | current_drive->UPC_buf[6] &= 0xF0; | ||
2936 | return (0); | ||
2937 | } | ||
2938 | /*==========================================================================*/ | ||
2939 | static int cc_ReadUPC(void) | ||
2940 | { | ||
2941 | int i; | ||
2942 | #if TEST_UPC | ||
2943 | int block, checksum; | ||
2944 | #endif /* TEST_UPC */ | ||
2945 | |||
2946 | if (fam2_drive) return (0); /* not implemented yet */ | ||
2947 | if (famT_drive) return (0); /* not implemented yet */ | ||
2948 | if (famV_drive) return (0); /* not implemented yet */ | ||
2949 | #if 1 | ||
2950 | if (fam0_drive) return (0); /* but it should work */ | ||
2951 | #endif | ||
2952 | |||
2953 | current_drive->diskstate_flags &= ~upc_bit; | ||
2954 | #if TEST_UPC | ||
2955 | for (block=CD_MSF_OFFSET+1;block<CD_MSF_OFFSET+200;block++) | ||
2956 | { | ||
2957 | #endif /* TEST_UPC */ | ||
2958 | clr_cmdbuf(); | ||
2959 | if (fam1_drive) | ||
2960 | { | ||
2961 | drvcmd[0]=CMD1_READ_UPC; | ||
2962 | #if TEST_UPC | ||
2963 | drvcmd[1]=(block>>16)&0xFF; | ||
2964 | drvcmd[2]=(block>>8)&0xFF; | ||
2965 | drvcmd[3]=block&0xFF; | ||
2966 | #endif /* TEST_UPC */ | ||
2967 | response_count=8; | ||
2968 | flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; | ||
2969 | } | ||
2970 | else if (fam0L_drive) | ||
2971 | { | ||
2972 | drvcmd[0]=CMD0_READ_UPC; | ||
2973 | #if TEST_UPC | ||
2974 | drvcmd[2]=(block>>16)&0xFF; | ||
2975 | drvcmd[3]=(block>>8)&0xFF; | ||
2976 | drvcmd[4]=block&0xFF; | ||
2977 | #endif /* TEST_UPC */ | ||
2978 | response_count=0; | ||
2979 | flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1; | ||
2980 | } | ||
2981 | else if (fam2_drive) | ||
2982 | { | ||
2983 | return (-1); | ||
2984 | } | ||
2985 | else if (famT_drive) | ||
2986 | { | ||
2987 | return (-1); | ||
2988 | } | ||
2989 | i=cmd_out(); | ||
2990 | if (i<0) | ||
2991 | { | ||
2992 | msg(DBG_000,"cc_ReadUPC cmd_out: err %d\n", i); | ||
2993 | return (i); | ||
2994 | } | ||
2995 | if (fam0L_drive) | ||
2996 | { | ||
2997 | response_count=16; | ||
2998 | if (famL_drive) flags_cmd_out=f_putcmd; | ||
2999 | i=cc_ReadPacket(); | ||
3000 | if (i<0) | ||
3001 | { | ||
3002 | msg(DBG_000,"cc_ReadUPC ReadPacket: err %d\n", i); | ||
3003 | return (i); | ||
3004 | } | ||
3005 | } | ||
3006 | #if TEST_UPC | ||
3007 | checksum=0; | ||
3008 | #endif /* TEST_UPC */ | ||
3009 | for (i=0;i<(fam1_drive?8:16);i++) | ||
3010 | { | ||
3011 | #if TEST_UPC | ||
3012 | checksum |= infobuf[i]; | ||
3013 | #endif /* TEST_UPC */ | ||
3014 | sprintf(&msgbuf[i*3], " %02X", infobuf[i]); | ||
3015 | } | ||
3016 | msgbuf[i*3]=0; | ||
3017 | msg(DBG_UPC,"UPC info:%s\n", msgbuf); | ||
3018 | #if TEST_UPC | ||
3019 | if ((checksum&0x7F)!=0) break; | ||
3020 | } | ||
3021 | #endif /* TEST_UPC */ | ||
3022 | current_drive->UPC_ctl_adr=0; | ||
3023 | if (fam1_drive) i=0; | ||
3024 | else i=2; | ||
3025 | if ((infobuf[i]&0x80)!=0) | ||
3026 | { | ||
3027 | convert_UPC(&infobuf[i]); | ||
3028 | current_drive->UPC_ctl_adr = (current_drive->TocEnt_ctl_adr & 0xF0) | 0x02; | ||
3029 | } | ||
3030 | for (i=0;i<7;i++) | ||
3031 | sprintf(&msgbuf[i*3], " %02X", current_drive->UPC_buf[i]); | ||
3032 | sprintf(&msgbuf[i*3], " (%02X)", current_drive->UPC_ctl_adr); | ||
3033 | msgbuf[i*3+5]=0; | ||
3034 | msg(DBG_UPC,"UPC code:%s\n", msgbuf); | ||
3035 | current_drive->diskstate_flags |= upc_bit; | ||
3036 | return (0); | ||
3037 | } | ||
3038 | |||
3039 | static int sbpcd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn) | ||
3040 | { | ||
3041 | int i; | ||
3042 | unsigned char *mcnp = mcn->medium_catalog_number; | ||
3043 | unsigned char *resp; | ||
3044 | |||
3045 | current_drive->diskstate_flags &= ~upc_bit; | ||
3046 | clr_cmdbuf(); | ||
3047 | if (fam1_drive) | ||
3048 | { | ||
3049 | drvcmd[0]=CMD1_READ_UPC; | ||
3050 | response_count=8; | ||
3051 | flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; | ||
3052 | } | ||
3053 | else if (fam0L_drive) | ||
3054 | { | ||
3055 | drvcmd[0]=CMD0_READ_UPC; | ||
3056 | response_count=0; | ||
3057 | flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1; | ||
3058 | } | ||
3059 | else if (fam2_drive) | ||
3060 | { | ||
3061 | return (-1); | ||
3062 | } | ||
3063 | else if (famT_drive) | ||
3064 | { | ||
3065 | return (-1); | ||
3066 | } | ||
3067 | i=cmd_out(); | ||
3068 | if (i<0) | ||
3069 | { | ||
3070 | msg(DBG_000,"cc_ReadUPC cmd_out: err %d\n", i); | ||
3071 | return (i); | ||
3072 | } | ||
3073 | if (fam0L_drive) | ||
3074 | { | ||
3075 | response_count=16; | ||
3076 | if (famL_drive) flags_cmd_out=f_putcmd; | ||
3077 | i=cc_ReadPacket(); | ||
3078 | if (i<0) | ||
3079 | { | ||
3080 | msg(DBG_000,"cc_ReadUPC ReadPacket: err %d\n", i); | ||
3081 | return (i); | ||
3082 | } | ||
3083 | } | ||
3084 | current_drive->UPC_ctl_adr=0; | ||
3085 | if (fam1_drive) i=0; | ||
3086 | else i=2; | ||
3087 | |||
3088 | resp = infobuf + i; | ||
3089 | if (*resp++ == 0x80) { | ||
3090 | /* packed bcd to single ASCII digits */ | ||
3091 | *mcnp++ = (*resp >> 4) + '0'; | ||
3092 | *mcnp++ = (*resp++ & 0x0f) + '0'; | ||
3093 | *mcnp++ = (*resp >> 4) + '0'; | ||
3094 | *mcnp++ = (*resp++ & 0x0f) + '0'; | ||
3095 | *mcnp++ = (*resp >> 4) + '0'; | ||
3096 | *mcnp++ = (*resp++ & 0x0f) + '0'; | ||
3097 | *mcnp++ = (*resp >> 4) + '0'; | ||
3098 | *mcnp++ = (*resp++ & 0x0f) + '0'; | ||
3099 | *mcnp++ = (*resp >> 4) + '0'; | ||
3100 | *mcnp++ = (*resp++ & 0x0f) + '0'; | ||
3101 | *mcnp++ = (*resp >> 4) + '0'; | ||
3102 | *mcnp++ = (*resp++ & 0x0f) + '0'; | ||
3103 | *mcnp++ = (*resp >> 4) + '0'; | ||
3104 | } | ||
3105 | *mcnp = '\0'; | ||
3106 | |||
3107 | current_drive->diskstate_flags |= upc_bit; | ||
3108 | return (0); | ||
3109 | } | ||
3110 | |||
3111 | /*==========================================================================*/ | ||
3112 | static int cc_CheckMultiSession(void) | ||
3113 | { | ||
3114 | int i; | ||
3115 | |||
3116 | if (fam2_drive) return (0); | ||
3117 | current_drive->f_multisession=0; | ||
3118 | current_drive->lba_multi=0; | ||
3119 | if (fam0_drive) return (0); | ||
3120 | clr_cmdbuf(); | ||
3121 | if (fam1_drive) | ||
3122 | { | ||
3123 | drvcmd[0]=CMD1_MULTISESS; | ||
3124 | response_count=6; | ||
3125 | flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; | ||
3126 | i=cmd_out(); | ||
3127 | if (i<0) return (i); | ||
3128 | if ((infobuf[0]&0x80)!=0) | ||
3129 | { | ||
3130 | current_drive->f_multisession=1; | ||
3131 | current_drive->lba_multi=msf2blk(make32(make16(0,infobuf[1]), | ||
3132 | make16(infobuf[2],infobuf[3]))); | ||
3133 | } | ||
3134 | } | ||
3135 | else if (famLV_drive) | ||
3136 | { | ||
3137 | drvcmd[0]=CMDL_MULTISESS; | ||
3138 | drvcmd[1]=3; | ||
3139 | drvcmd[2]=1; | ||
3140 | response_count=8; | ||
3141 | flags_cmd_out=f_putcmd; | ||
3142 | i=cmd_out(); | ||
3143 | if (i<0) return (i); | ||
3144 | current_drive->lba_multi=msf2blk(make32(make16(0,infobuf[5]), | ||
3145 | make16(infobuf[6],infobuf[7]))); | ||
3146 | } | ||
3147 | else if (famT_drive) | ||
3148 | { | ||
3149 | response_count=12; | ||
3150 | drvcmd[0]=CMDT_DISKINFO; | ||
3151 | drvcmd[1]=0x02; | ||
3152 | drvcmd[6]=0; | ||
3153 | drvcmd[8]=response_count; | ||
3154 | drvcmd[9]=0x40; | ||
3155 | i=cmd_out(); | ||
3156 | if (i<0) return (i); | ||
3157 | if (i<response_count) return (-100-i); | ||
3158 | current_drive->first_session=infobuf[2]; | ||
3159 | current_drive->last_session=infobuf[3]; | ||
3160 | current_drive->track_of_last_session=infobuf[6]; | ||
3161 | if (current_drive->first_session!=current_drive->last_session) | ||
3162 | { | ||
3163 | current_drive->f_multisession=1; | ||
3164 | current_drive->lba_multi=msf2blk(make32(make16(0,infobuf[9]),make16(infobuf[10],infobuf[11]))); | ||
3165 | } | ||
3166 | } | ||
3167 | for (i=0;i<response_count;i++) | ||
3168 | sprintf(&msgbuf[i*3], " %02X", infobuf[i]); | ||
3169 | msgbuf[i*3]=0; | ||
3170 | msg(DBG_MUL,"MultiSession Info:%s (%d)\n", msgbuf, current_drive->lba_multi); | ||
3171 | if (current_drive->lba_multi>200) | ||
3172 | { | ||
3173 | current_drive->f_multisession=1; | ||
3174 | msg(DBG_MUL,"MultiSession base: %06X\n", current_drive->lba_multi); | ||
3175 | } | ||
3176 | return (0); | ||
3177 | } | ||
3178 | /*==========================================================================*/ | ||
3179 | #ifdef FUTURE | ||
3180 | static int cc_SubChanInfo(int frame, int count, u_char *buffer) | ||
3181 | /* "frame" is a RED BOOK (msf-bin) address */ | ||
3182 | { | ||
3183 | int i; | ||
3184 | |||
3185 | if (fam0LV_drive) return (-ENOSYS); /* drive firmware lacks it */ | ||
3186 | if (famT_drive) | ||
3187 | { | ||
3188 | return (-1); | ||
3189 | } | ||
3190 | #if 0 | ||
3191 | if (current_drive->audio_state!=audio_playing) return (-ENODATA); | ||
3192 | #endif | ||
3193 | clr_cmdbuf(); | ||
3194 | drvcmd[0]=CMD1_SUBCHANINF; | ||
3195 | drvcmd[1]=(frame>>16)&0xFF; | ||
3196 | drvcmd[2]=(frame>>8)&0xFF; | ||
3197 | drvcmd[3]=frame&0xFF; | ||
3198 | drvcmd[5]=(count>>8)&0xFF; | ||
3199 | drvcmd[6]=count&0xFF; | ||
3200 | flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check; | ||
3201 | cmd_type=READ_SC; | ||
3202 | current_drive->frame_size=CD_FRAMESIZE_SUB; | ||
3203 | i=cmd_out(); /* which buffer to use? */ | ||
3204 | return (i); | ||
3205 | } | ||
3206 | #endif /* FUTURE */ | ||
3207 | /*==========================================================================*/ | ||
3208 | static void __init check_datarate(void) | ||
3209 | { | ||
3210 | int i=0; | ||
3211 | |||
3212 | msg(DBG_IOX,"check_datarate entered.\n"); | ||
3213 | datarate=0; | ||
3214 | #if TEST_STI | ||
3215 | for (i=0;i<=1000;i++) printk("."); | ||
3216 | #endif | ||
3217 | /* set a timer to make (timed_out_delay!=0) after 1.1 seconds */ | ||
3218 | #if 1 | ||
3219 | del_timer(&delay_timer); | ||
3220 | #endif | ||
3221 | delay_timer.expires=jiffies+11*HZ/10; | ||
3222 | timed_out_delay=0; | ||
3223 | add_timer(&delay_timer); | ||
3224 | #if 0 | ||
3225 | msg(DBG_TIM,"delay timer started (11*HZ/10).\n"); | ||
3226 | #endif | ||
3227 | do | ||
3228 | { | ||
3229 | i=inb(CDi_status); | ||
3230 | datarate++; | ||
3231 | #if 1 | ||
3232 | if (datarate>0x6FFFFFFF) break; | ||
3233 | #endif | ||
3234 | } | ||
3235 | while (!timed_out_delay); | ||
3236 | del_timer(&delay_timer); | ||
3237 | #if 0 | ||
3238 | msg(DBG_TIM,"datarate: %04X\n", datarate); | ||
3239 | #endif | ||
3240 | if (datarate<65536) datarate=65536; | ||
3241 | maxtim16=datarate*16; | ||
3242 | maxtim04=datarate*4; | ||
3243 | maxtim02=datarate*2; | ||
3244 | maxtim_8=datarate/32; | ||
3245 | #if LONG_TIMING | ||
3246 | maxtim_data=datarate/100; | ||
3247 | #else | ||
3248 | maxtim_data=datarate/300; | ||
3249 | #endif /* LONG_TIMING */ | ||
3250 | #if 0 | ||
3251 | msg(DBG_TIM,"maxtim_8 %d, maxtim_data %d.\n", maxtim_8, maxtim_data); | ||
3252 | #endif | ||
3253 | } | ||
3254 | /*==========================================================================*/ | ||
3255 | #if 0 | ||
3256 | static int c2_ReadError(int fam) | ||
3257 | { | ||
3258 | int i; | ||
3259 | |||
3260 | clr_cmdbuf(); | ||
3261 | response_count=9; | ||
3262 | clr_respo_buf(9); | ||
3263 | if (fam==1) | ||
3264 | { | ||
3265 | drvcmd[0]=CMD0_READ_ERR; /* same as CMD1_ and CMDL_ */ | ||
3266 | i=do_cmd(f_putcmd|f_lopsta|f_getsta|f_ResponseStatus); | ||
3267 | } | ||
3268 | else if (fam==2) | ||
3269 | { | ||
3270 | drvcmd[0]=CMD2_READ_ERR; | ||
3271 | i=do_cmd(f_putcmd); | ||
3272 | } | ||
3273 | else return (-1); | ||
3274 | return (i); | ||
3275 | } | ||
3276 | #endif | ||
3277 | /*==========================================================================*/ | ||
3278 | static void __init ask_mail(void) | ||
3279 | { | ||
3280 | int i; | ||
3281 | |||
3282 | msg(DBG_INF, "please mail the following lines to emoenke@gwdg.de\n"); | ||
3283 | msg(DBG_INF, "(don't mail if you are not using the actual kernel):\n"); | ||
3284 | msg(DBG_INF, "%s\n", VERSION); | ||
3285 | msg(DBG_INF, "address %03X, type %s, drive %s (ID %d)\n", | ||
3286 | CDo_command, type, current_drive->drive_model, current_drive->drv_id); | ||
3287 | for (i=0;i<12;i++) | ||
3288 | sprintf(&msgbuf[i*3], " %02X", infobuf[i]); | ||
3289 | msgbuf[i*3]=0; | ||
3290 | msg(DBG_INF,"infobuf =%s\n", msgbuf); | ||
3291 | for (i=0;i<12;i++) | ||
3292 | sprintf(&msgbuf[i*3], " %c ", infobuf[i]); | ||
3293 | msgbuf[i*3]=0; | ||
3294 | msg(DBG_INF,"infobuf =%s\n", msgbuf); | ||
3295 | } | ||
3296 | /*==========================================================================*/ | ||
3297 | static int __init check_version(void) | ||
3298 | { | ||
3299 | int i, j, l; | ||
3300 | int teac_possible=0; | ||
3301 | |||
3302 | msg(DBG_INI,"check_version: id=%d, d=%d.\n", current_drive->drv_id, current_drive - D_S); | ||
3303 | current_drive->drv_type=0; | ||
3304 | |||
3305 | /* check for CR-52x, CR-56x, LCS-7260 and ECS-AT */ | ||
3306 | /* clear any pending error state */ | ||
3307 | clr_cmdbuf(); | ||
3308 | drvcmd[0]=CMD0_READ_ERR; /* same as CMD1_ and CMDL_ */ | ||
3309 | response_count=9; | ||
3310 | flags_cmd_out=f_putcmd; | ||
3311 | i=cmd_out(); | ||
3312 | if (i<0) msg(DBG_INI,"CMD0_READ_ERR returns %d (ok anyway).\n",i); | ||
3313 | /* read drive version */ | ||
3314 | clr_cmdbuf(); | ||
3315 | for (i=0;i<12;i++) infobuf[i]=0; | ||
3316 | drvcmd[0]=CMD0_READ_VER; /* same as CMD1_ and CMDL_ */ | ||
3317 | response_count=12; /* fam1: only 11 */ | ||
3318 | flags_cmd_out=f_putcmd; | ||
3319 | i=cmd_out(); | ||
3320 | if (i<-1) msg(DBG_INI,"CMD0_READ_VER returns %d\n",i); | ||
3321 | if (i==-11) teac_possible++; | ||
3322 | j=0; | ||
3323 | for (i=0;i<12;i++) j+=infobuf[i]; | ||
3324 | if (j) | ||
3325 | { | ||
3326 | for (i=0;i<12;i++) | ||
3327 | sprintf(&msgbuf[i*3], " %02X", infobuf[i]); | ||
3328 | msgbuf[i*3]=0; | ||
3329 | msg(DBG_ECS,"infobuf =%s\n", msgbuf); | ||
3330 | for (i=0;i<12;i++) | ||
3331 | sprintf(&msgbuf[i*3], " %c ", infobuf[i]); | ||
3332 | msgbuf[i*3]=0; | ||
3333 | msg(DBG_ECS,"infobuf =%s\n", msgbuf); | ||
3334 | } | ||
3335 | for (i=0;i<4;i++) if (infobuf[i]!=family1[i]) break; | ||
3336 | if (i==4) | ||
3337 | { | ||
3338 | current_drive->drive_model[0]='C'; | ||
3339 | current_drive->drive_model[1]='R'; | ||
3340 | current_drive->drive_model[2]='-'; | ||
3341 | current_drive->drive_model[3]='5'; | ||
3342 | current_drive->drive_model[4]=infobuf[i++]; | ||
3343 | current_drive->drive_model[5]=infobuf[i++]; | ||
3344 | current_drive->drive_model[6]=0; | ||
3345 | current_drive->drv_type=drv_fam1; | ||
3346 | } | ||
3347 | if (!current_drive->drv_type) | ||
3348 | { | ||
3349 | for (i=0;i<8;i++) if (infobuf[i]!=family0[i]) break; | ||
3350 | if (i==8) | ||
3351 | { | ||
3352 | current_drive->drive_model[0]='C'; | ||
3353 | current_drive->drive_model[1]='R'; | ||
3354 | current_drive->drive_model[2]='-'; | ||
3355 | current_drive->drive_model[3]='5'; | ||
3356 | current_drive->drive_model[4]='2'; | ||
3357 | current_drive->drive_model[5]='x'; | ||
3358 | current_drive->drive_model[6]=0; | ||
3359 | current_drive->drv_type=drv_fam0; | ||
3360 | } | ||
3361 | } | ||
3362 | if (!current_drive->drv_type) | ||
3363 | { | ||
3364 | for (i=0;i<8;i++) if (infobuf[i]!=familyL[i]) break; | ||
3365 | if (i==8) | ||
3366 | { | ||
3367 | for (j=0;j<8;j++) | ||
3368 | current_drive->drive_model[j]=infobuf[j]; | ||
3369 | current_drive->drive_model[8]=0; | ||
3370 | current_drive->drv_type=drv_famL; | ||
3371 | } | ||
3372 | } | ||
3373 | if (!current_drive->drv_type) | ||
3374 | { | ||
3375 | for (i=0;i<6;i++) if (infobuf[i]!=familyV[i]) break; | ||
3376 | if (i==6) | ||
3377 | { | ||
3378 | for (j=0;j<6;j++) | ||
3379 | current_drive->drive_model[j]=infobuf[j]; | ||
3380 | current_drive->drive_model[6]=0; | ||
3381 | current_drive->drv_type=drv_famV; | ||
3382 | i+=2; /* 2 blanks before version */ | ||
3383 | } | ||
3384 | } | ||
3385 | if (!current_drive->drv_type) | ||
3386 | { | ||
3387 | /* check for CD200 */ | ||
3388 | clr_cmdbuf(); | ||
3389 | drvcmd[0]=CMD2_READ_ERR; | ||
3390 | response_count=9; | ||
3391 | flags_cmd_out=f_putcmd; | ||
3392 | i=cmd_out(); | ||
3393 | if (i<0) msg(DBG_INI,"CMD2_READERR returns %d (ok anyway).\n",i); | ||
3394 | if (i<0) msg(DBG_000,"CMD2_READERR returns %d (ok anyway).\n",i); | ||
3395 | /* read drive version */ | ||
3396 | clr_cmdbuf(); | ||
3397 | for (i=0;i<12;i++) infobuf[i]=0; | ||
3398 | if (sbpro_type==1) OUT(CDo_sel_i_d,0); | ||
3399 | #if 0 | ||
3400 | OUT(CDo_reset,0); | ||
3401 | sbp_sleep(6*HZ); | ||
3402 | OUT(CDo_enable,current_drive->drv_sel); | ||
3403 | #endif | ||
3404 | drvcmd[0]=CMD2_READ_VER; | ||
3405 | response_count=12; | ||
3406 | flags_cmd_out=f_putcmd; | ||
3407 | i=cmd_out(); | ||
3408 | if (i<0) msg(DBG_INI,"CMD2_READ_VER returns %d\n",i); | ||
3409 | if (i==-7) teac_possible++; | ||
3410 | j=0; | ||
3411 | for (i=0;i<12;i++) j+=infobuf[i]; | ||
3412 | if (j) | ||
3413 | { | ||
3414 | for (i=0;i<12;i++) | ||
3415 | sprintf(&msgbuf[i*3], " %02X", infobuf[i]); | ||
3416 | msgbuf[i*3]=0; | ||
3417 | msg(DBG_IDX,"infobuf =%s\n", msgbuf); | ||
3418 | for (i=0;i<12;i++) | ||
3419 | sprintf(&msgbuf[i*3], " %c ", infobuf[i]); | ||
3420 | msgbuf[i*3]=0; | ||
3421 | msg(DBG_IDX,"infobuf =%s\n", msgbuf); | ||
3422 | } | ||
3423 | if (i>=0) | ||
3424 | { | ||
3425 | for (i=0;i<5;i++) if (infobuf[i]!=family2[i]) break; | ||
3426 | if (i==5) | ||
3427 | { | ||
3428 | current_drive->drive_model[0]='C'; | ||
3429 | current_drive->drive_model[1]='D'; | ||
3430 | current_drive->drive_model[2]='2'; | ||
3431 | current_drive->drive_model[3]='0'; | ||
3432 | current_drive->drive_model[4]='0'; | ||
3433 | current_drive->drive_model[5]=infobuf[i++]; | ||
3434 | current_drive->drive_model[6]=infobuf[i++]; | ||
3435 | current_drive->drive_model[7]=0; | ||
3436 | current_drive->drv_type=drv_fam2; | ||
3437 | } | ||
3438 | } | ||
3439 | } | ||
3440 | if (!current_drive->drv_type) | ||
3441 | { | ||
3442 | /* check for TEAC CD-55A */ | ||
3443 | msg(DBG_TEA,"teac_possible: %d\n",teac_possible); | ||
3444 | for (j=1;j<=((current_drive->drv_id==0)?3:1);j++) | ||
3445 | { | ||
3446 | for (l=1;l<=((current_drive->drv_id==0)?10:1);l++) | ||
3447 | { | ||
3448 | msg(DBG_TEA,"TEAC reset #%d-%d.\n", j, l); | ||
3449 | if (sbpro_type==1) OUT(CDo_reset,0); | ||
3450 | else | ||
3451 | { | ||
3452 | OUT(CDo_enable,current_drive->drv_sel); | ||
3453 | OUT(CDo_sel_i_d,0); | ||
3454 | OUT(CDo_command,CMDT_RESET); | ||
3455 | for (i=0;i<9;i++) OUT(CDo_command,0); | ||
3456 | } | ||
3457 | sbp_sleep(5*HZ/10); | ||
3458 | OUT(CDo_enable,current_drive->drv_sel); | ||
3459 | OUT(CDo_sel_i_d,0); | ||
3460 | i=inb(CDi_status); | ||
3461 | msg(DBG_TEA,"TEAC CDi_status: %02X.\n",i); | ||
3462 | #if 0 | ||
3463 | if (i&s_not_result_ready) continue; /* drive not present or ready */ | ||
3464 | #endif | ||
3465 | i=inb(CDi_info); | ||
3466 | msg(DBG_TEA,"TEAC CDi_info: %02X.\n",i); | ||
3467 | if (i==0x55) break; /* drive found */ | ||
3468 | } | ||
3469 | if (i==0x55) break; /* drive found */ | ||
3470 | } | ||
3471 | if (i==0x55) /* drive found */ | ||
3472 | { | ||
3473 | msg(DBG_TEA,"TEAC drive found.\n"); | ||
3474 | clr_cmdbuf(); | ||
3475 | flags_cmd_out=f_putcmd; | ||
3476 | response_count=12; | ||
3477 | drvcmd[0]=CMDT_READ_VER; | ||
3478 | drvcmd[4]=response_count; | ||
3479 | for (i=0;i<12;i++) infobuf[i]=0; | ||
3480 | i=cmd_out_T(); | ||
3481 | if (i!=0) msg(DBG_TEA,"cmd_out_T(CMDT_READ_VER) returns %d.\n",i); | ||
3482 | for (i=1;i<6;i++) if (infobuf[i]!=familyT[i-1]) break; | ||
3483 | if (i==6) | ||
3484 | { | ||
3485 | current_drive->drive_model[0]='C'; | ||
3486 | current_drive->drive_model[1]='D'; | ||
3487 | current_drive->drive_model[2]='-'; | ||
3488 | current_drive->drive_model[3]='5'; | ||
3489 | current_drive->drive_model[4]='5'; | ||
3490 | current_drive->drive_model[5]=0; | ||
3491 | current_drive->drv_type=drv_famT; | ||
3492 | } | ||
3493 | } | ||
3494 | } | ||
3495 | if (!current_drive->drv_type) | ||
3496 | { | ||
3497 | msg(DBG_TEA,"no drive found at address %03X under ID %d.\n",CDo_command,current_drive->drv_id); | ||
3498 | return (-522); | ||
3499 | } | ||
3500 | for (j=0;j<4;j++) current_drive->firmware_version[j]=infobuf[i+j]; | ||
3501 | if (famL_drive) | ||
3502 | { | ||
3503 | u_char lcs_firm_e1[]="A E1"; | ||
3504 | u_char lcs_firm_f4[]="A4F4"; | ||
3505 | |||
3506 | for (j=0;j<4;j++) | ||
3507 | if (current_drive->firmware_version[j]!=lcs_firm_e1[j]) break; | ||
3508 | if (j==4) current_drive->drv_type=drv_e1; | ||
3509 | |||
3510 | for (j=0;j<4;j++) | ||
3511 | if (current_drive->firmware_version[j]!=lcs_firm_f4[j]) break; | ||
3512 | if (j==4) current_drive->drv_type=drv_f4; | ||
3513 | |||
3514 | if (current_drive->drv_type==drv_famL) ask_mail(); | ||
3515 | } | ||
3516 | else if (famT_drive) | ||
3517 | { | ||
3518 | j=infobuf[4]; /* one-byte version??? - here: 0x15 */ | ||
3519 | if (j=='5') | ||
3520 | { | ||
3521 | current_drive->firmware_version[0]=infobuf[7]; | ||
3522 | current_drive->firmware_version[1]=infobuf[8]; | ||
3523 | current_drive->firmware_version[2]=infobuf[10]; | ||
3524 | current_drive->firmware_version[3]=infobuf[11]; | ||
3525 | } | ||
3526 | else | ||
3527 | { | ||
3528 | if (j!=0x15) ask_mail(); | ||
3529 | current_drive->firmware_version[0]='0'; | ||
3530 | current_drive->firmware_version[1]='.'; | ||
3531 | current_drive->firmware_version[2]='0'+(j>>4); | ||
3532 | current_drive->firmware_version[3]='0'+(j&0x0f); | ||
3533 | } | ||
3534 | } | ||
3535 | else /* CR-52x, CR-56x, CD200, ECS-AT */ | ||
3536 | { | ||
3537 | j = (current_drive->firmware_version[0] & 0x0F) * 100 + | ||
3538 | (current_drive->firmware_version[2] & 0x0F) *10 + | ||
3539 | (current_drive->firmware_version[3] & 0x0F); | ||
3540 | if (fam0_drive) | ||
3541 | { | ||
3542 | if (j<200) current_drive->drv_type=drv_199; | ||
3543 | else if (j<201) current_drive->drv_type=drv_200; | ||
3544 | else if (j<210) current_drive->drv_type=drv_201; | ||
3545 | else if (j<211) current_drive->drv_type=drv_210; | ||
3546 | else if (j<300) current_drive->drv_type=drv_211; | ||
3547 | else if (j>=300) current_drive->drv_type=drv_300; | ||
3548 | } | ||
3549 | else if (fam1_drive) | ||
3550 | { | ||
3551 | if (j<100) current_drive->drv_type=drv_099; | ||
3552 | else | ||
3553 | { | ||
3554 | current_drive->drv_type=drv_100; | ||
3555 | if ((j!=500)&&(j!=102)) ask_mail(); | ||
3556 | } | ||
3557 | } | ||
3558 | else if (fam2_drive) | ||
3559 | { | ||
3560 | if (current_drive->drive_model[5]=='F') | ||
3561 | { | ||
3562 | if ((j!=1)&&(j!=35)&&(j!=200)&&(j!=210)) | ||
3563 | ask_mail(); /* unknown version at time */ | ||
3564 | } | ||
3565 | else | ||
3566 | { | ||
3567 | msg(DBG_INF,"this CD200 drive is not fully supported yet - only audio will work.\n"); | ||
3568 | if ((j!=101)&&(j!=35)) | ||
3569 | ask_mail(); /* unknown version at time */ | ||
3570 | } | ||
3571 | } | ||
3572 | else if (famV_drive) | ||
3573 | { | ||
3574 | if ((j==100)||(j==150)) current_drive->drv_type=drv_at; | ||
3575 | ask_mail(); /* hopefully we get some feedback by this */ | ||
3576 | } | ||
3577 | } | ||
3578 | msg(DBG_LCS,"drive type %02X\n",current_drive->drv_type); | ||
3579 | msg(DBG_INI,"check_version done.\n"); | ||
3580 | return (0); | ||
3581 | } | ||
3582 | /*==========================================================================*/ | ||
3583 | static void switch_drive(struct sbpcd_drive *p) | ||
3584 | { | ||
3585 | current_drive = p; | ||
3586 | OUT(CDo_enable,current_drive->drv_sel); | ||
3587 | msg(DBG_DID,"drive %d (ID=%d) activated.\n", | ||
3588 | current_drive - D_S, current_drive->drv_id); | ||
3589 | return; | ||
3590 | } | ||
3591 | /*==========================================================================*/ | ||
3592 | #ifdef PATH_CHECK | ||
3593 | /* | ||
3594 | * probe for the presence of an interface card | ||
3595 | */ | ||
3596 | static int __init check_card(int port) | ||
3597 | { | ||
3598 | #undef N_RESPO | ||
3599 | #define N_RESPO 20 | ||
3600 | int i, j, k; | ||
3601 | u_char response[N_RESPO]; | ||
3602 | u_char save_port0; | ||
3603 | u_char save_port3; | ||
3604 | |||
3605 | msg(DBG_INI,"check_card entered.\n"); | ||
3606 | save_port0=inb(port+0); | ||
3607 | save_port3=inb(port+3); | ||
3608 | |||
3609 | for (j=0;j<NR_SBPCD;j++) | ||
3610 | { | ||
3611 | OUT(port+3,j) ; /* enable drive #j */ | ||
3612 | OUT(port+0,CMD0_PATH_CHECK); | ||
3613 | for (i=10;i>0;i--) OUT(port+0,0); | ||
3614 | for (k=0;k<N_RESPO;k++) response[k]=0; | ||
3615 | for (k=0;k<N_RESPO;k++) | ||
3616 | { | ||
3617 | for (i=10000;i>0;i--) | ||
3618 | { | ||
3619 | if (inb(port+1)&s_not_result_ready) continue; | ||
3620 | response[k]=inb(port+0); | ||
3621 | break; | ||
3622 | } | ||
3623 | } | ||
3624 | for (i=0;i<N_RESPO;i++) | ||
3625 | sprintf(&msgbuf[i*3], " %02X", response[i]); | ||
3626 | msgbuf[i*3]=0; | ||
3627 | msg(DBG_TEA,"path check 00 (%d): %s\n", j, msgbuf); | ||
3628 | OUT(port+0,CMD0_PATH_CHECK); | ||
3629 | for (i=10;i>0;i--) OUT(port+0,0); | ||
3630 | for (k=0;k<N_RESPO;k++) response[k]=0xFF; | ||
3631 | for (k=0;k<N_RESPO;k++) | ||
3632 | { | ||
3633 | for (i=10000;i>0;i--) | ||
3634 | { | ||
3635 | if (inb(port+1)&s_not_result_ready) continue; | ||
3636 | response[k]=inb(port+0); | ||
3637 | break; | ||
3638 | } | ||
3639 | } | ||
3640 | for (i=0;i<N_RESPO;i++) | ||
3641 | sprintf(&msgbuf[i*3], " %02X", response[i]); | ||
3642 | msgbuf[i*3]=0; | ||
3643 | msg(DBG_TEA,"path check 00 (%d): %s\n", j, msgbuf); | ||
3644 | |||
3645 | if (response[0]==0xAA) | ||
3646 | if (response[1]==0x55) | ||
3647 | return (0); | ||
3648 | } | ||
3649 | for (j=0;j<NR_SBPCD;j++) | ||
3650 | { | ||
3651 | OUT(port+3,j) ; /* enable drive #j */ | ||
3652 | OUT(port+0,CMD2_READ_VER); | ||
3653 | for (i=10;i>0;i--) OUT(port+0,0); | ||
3654 | for (k=0;k<N_RESPO;k++) response[k]=0; | ||
3655 | for (k=0;k<N_RESPO;k++) | ||
3656 | { | ||
3657 | for (i=1000000;i>0;i--) | ||
3658 | { | ||
3659 | if (inb(port+1)&s_not_result_ready) continue; | ||
3660 | response[k]=inb(port+0); | ||
3661 | break; | ||
3662 | } | ||
3663 | } | ||
3664 | for (i=0;i<N_RESPO;i++) | ||
3665 | sprintf(&msgbuf[i*3], " %02X", response[i]); | ||
3666 | msgbuf[i*3]=0; | ||
3667 | msg(DBG_TEA,"path check 12 (%d): %s\n", j, msgbuf); | ||
3668 | |||
3669 | OUT(port+0,CMD2_READ_VER); | ||
3670 | for (i=10;i>0;i--) OUT(port+0,0); | ||
3671 | for (k=0;k<N_RESPO;k++) response[k]=0xFF; | ||
3672 | for (k=0;k<N_RESPO;k++) | ||
3673 | { | ||
3674 | for (i=1000000;i>0;i--) | ||
3675 | { | ||
3676 | if (inb(port+1)&s_not_result_ready) continue; | ||
3677 | response[k]=inb(port+0); | ||
3678 | break; | ||
3679 | } | ||
3680 | } | ||
3681 | for (i=0;i<N_RESPO;i++) | ||
3682 | sprintf(&msgbuf[i*3], " %02X", response[i]); | ||
3683 | msgbuf[i*3]=0; | ||
3684 | msg(DBG_TEA,"path check 12 (%d): %s\n", j, msgbuf); | ||
3685 | |||
3686 | if (response[0]==0xAA) | ||
3687 | if (response[1]==0x55) | ||
3688 | return (0); | ||
3689 | } | ||
3690 | OUT(port+0,save_port0); | ||
3691 | OUT(port+3,save_port3); | ||
3692 | return (0); /* in any case - no real "function" at time */ | ||
3693 | } | ||
3694 | #endif /* PATH_CHECK */ | ||
3695 | /*==========================================================================*/ | ||
3696 | /*==========================================================================*/ | ||
3697 | /* | ||
3698 | * probe for the presence of drives on the selected controller | ||
3699 | */ | ||
3700 | static int __init check_drives(void) | ||
3701 | { | ||
3702 | int i, j; | ||
3703 | |||
3704 | msg(DBG_INI,"check_drives entered.\n"); | ||
3705 | ndrives=0; | ||
3706 | for (j=0;j<max_drives;j++) | ||
3707 | { | ||
3708 | struct sbpcd_drive *p = D_S + ndrives; | ||
3709 | p->drv_id=j; | ||
3710 | if (sbpro_type==1) p->drv_sel=(j&0x01)<<1|(j&0x02)>>1; | ||
3711 | else p->drv_sel=j; | ||
3712 | switch_drive(p); | ||
3713 | msg(DBG_INI,"check_drives: drive %d (ID=%d) activated.\n",ndrives,j); | ||
3714 | msg(DBG_000,"check_drives: drive %d (ID=%d) activated.\n",ndrives,j); | ||
3715 | i=check_version(); | ||
3716 | if (i<0) msg(DBG_INI,"check_version returns %d.\n",i); | ||
3717 | else | ||
3718 | { | ||
3719 | current_drive->drv_options=drv_pattern[j]; | ||
3720 | if (fam0L_drive) current_drive->drv_options&=~(speed_auto|speed_300|speed_150); | ||
3721 | msg(DBG_INF, "Drive %d (ID=%d): %.9s (%.4s) at 0x%03X (type %d)\n", | ||
3722 | current_drive - D_S, | ||
3723 | current_drive->drv_id, | ||
3724 | current_drive->drive_model, | ||
3725 | current_drive->firmware_version, | ||
3726 | CDo_command, | ||
3727 | sbpro_type); | ||
3728 | ndrives++; | ||
3729 | } | ||
3730 | } | ||
3731 | for (j=ndrives;j<NR_SBPCD;j++) D_S[j].drv_id=-1; | ||
3732 | if (ndrives==0) return (-1); | ||
3733 | return (0); | ||
3734 | } | ||
3735 | /*==========================================================================*/ | ||
3736 | #ifdef FUTURE | ||
3737 | /* | ||
3738 | * obtain if requested service disturbs current audio state | ||
3739 | */ | ||
3740 | static int obey_audio_state(u_char audio_state, u_char func,u_char subfunc) | ||
3741 | { | ||
3742 | switch (audio_state) /* audio status from controller */ | ||
3743 | { | ||
3744 | case aud_11: /* "audio play in progress" */ | ||
3745 | case audx11: | ||
3746 | switch (func) /* DOS command code */ | ||
3747 | { | ||
3748 | case cmd_07: /* input flush */ | ||
3749 | case cmd_0d: /* open device */ | ||
3750 | case cmd_0e: /* close device */ | ||
3751 | case cmd_0c: /* ioctl output */ | ||
3752 | return (1); | ||
3753 | case cmd_03: /* ioctl input */ | ||
3754 | switch (subfunc) | ||
3755 | /* DOS ioctl input subfunction */ | ||
3756 | { | ||
3757 | case cxi_00: | ||
3758 | case cxi_06: | ||
3759 | case cxi_09: | ||
3760 | return (1); | ||
3761 | default: | ||
3762 | return (ERROR15); | ||
3763 | } | ||
3764 | return (1); | ||
3765 | default: | ||
3766 | return (ERROR15); | ||
3767 | } | ||
3768 | return (1); | ||
3769 | case aud_12: /* "audio play paused" */ | ||
3770 | case audx12: | ||
3771 | return (1); | ||
3772 | default: | ||
3773 | return (2); | ||
3774 | } | ||
3775 | } | ||
3776 | /*==========================================================================*/ | ||
3777 | /* allowed is only | ||
3778 | * ioctl_o, flush_input, open_device, close_device, | ||
3779 | * tell_address, tell_volume, tell_capabiliti, | ||
3780 | * tell_framesize, tell_CD_changed, tell_audio_posi | ||
3781 | */ | ||
3782 | static int check_allowed1(u_char func1, u_char func2) | ||
3783 | { | ||
3784 | #if 000 | ||
3785 | if (func1==ioctl_o) return (0); | ||
3786 | if (func1==read_long) return (-1); | ||
3787 | if (func1==read_long_prefetch) return (-1); | ||
3788 | if (func1==seek) return (-1); | ||
3789 | if (func1==audio_play) return (-1); | ||
3790 | if (func1==audio_pause) return (-1); | ||
3791 | if (func1==audio_resume) return (-1); | ||
3792 | if (func1!=ioctl_i) return (0); | ||
3793 | if (func2==tell_SubQ_run_tot) return (-1); | ||
3794 | if (func2==tell_cdsize) return (-1); | ||
3795 | if (func2==tell_TocDescrip) return (-1); | ||
3796 | if (func2==tell_TocEntry) return (-1); | ||
3797 | if (func2==tell_subQ_info) return (-1); | ||
3798 | if (fam1_drive) if (func2==tell_SubChanInfo) return (-1); | ||
3799 | if (func2==tell_UPC) return (-1); | ||
3800 | #else | ||
3801 | return (0); | ||
3802 | #endif | ||
3803 | } | ||
3804 | /*==========================================================================*/ | ||
3805 | static int check_allowed2(u_char func1, u_char func2) | ||
3806 | { | ||
3807 | #if 000 | ||
3808 | if (func1==read_long) return (-1); | ||
3809 | if (func1==read_long_prefetch) return (-1); | ||
3810 | if (func1==seek) return (-1); | ||
3811 | if (func1==audio_play) return (-1); | ||
3812 | if (func1!=ioctl_o) return (0); | ||
3813 | if (fam1_drive) | ||
3814 | { | ||
3815 | if (func2==EjectDisk) return (-1); | ||
3816 | if (func2==CloseTray) return (-1); | ||
3817 | } | ||
3818 | #else | ||
3819 | return (0); | ||
3820 | #endif | ||
3821 | } | ||
3822 | /*==========================================================================*/ | ||
3823 | static int check_allowed3(u_char func1, u_char func2) | ||
3824 | { | ||
3825 | #if 000 | ||
3826 | if (func1==ioctl_i) | ||
3827 | { | ||
3828 | if (func2==tell_address) return (0); | ||
3829 | if (func2==tell_capabiliti) return (0); | ||
3830 | if (func2==tell_CD_changed) return (0); | ||
3831 | if (fam0L_drive) if (func2==tell_SubChanInfo) return (0); | ||
3832 | return (-1); | ||
3833 | } | ||
3834 | if (func1==ioctl_o) | ||
3835 | { | ||
3836 | if (func2==DriveReset) return (0); | ||
3837 | if (fam0L_drive) | ||
3838 | { | ||
3839 | if (func2==EjectDisk) return (0); | ||
3840 | if (func2==LockDoor) return (0); | ||
3841 | if (func2==CloseTray) return (0); | ||
3842 | } | ||
3843 | return (-1); | ||
3844 | } | ||
3845 | if (func1==flush_input) return (-1); | ||
3846 | if (func1==read_long) return (-1); | ||
3847 | if (func1==read_long_prefetch) return (-1); | ||
3848 | if (func1==seek) return (-1); | ||
3849 | if (func1==audio_play) return (-1); | ||
3850 | if (func1==audio_pause) return (-1); | ||
3851 | if (func1==audio_resume) return (-1); | ||
3852 | #else | ||
3853 | return (0); | ||
3854 | #endif | ||
3855 | } | ||
3856 | /*==========================================================================*/ | ||
3857 | static int seek_pos_audio_end(void) | ||
3858 | { | ||
3859 | int i; | ||
3860 | |||
3861 | i=msf2blk(current_drive->pos_audio_end)-1; | ||
3862 | if (i<0) return (-1); | ||
3863 | i=cc_Seek(i,0); | ||
3864 | return (i); | ||
3865 | } | ||
3866 | #endif /* FUTURE */ | ||
3867 | /*==========================================================================*/ | ||
3868 | static int ReadToC(void) | ||
3869 | { | ||
3870 | int i, j; | ||
3871 | current_drive->diskstate_flags &= ~toc_bit; | ||
3872 | current_drive->ored_ctl_adr=0; | ||
3873 | /* special handling of CD-I HE */ | ||
3874 | if ((current_drive->n_first_track == 2 && current_drive->n_last_track == 2) || | ||
3875 | current_drive->xa_byte == 0x10) | ||
3876 | { | ||
3877 | current_drive->TocBuffer[1].nixbyte=0; | ||
3878 | current_drive->TocBuffer[1].ctl_adr=0x40; | ||
3879 | current_drive->TocBuffer[1].number=1; | ||
3880 | current_drive->TocBuffer[1].format=0; | ||
3881 | current_drive->TocBuffer[1].address=blk2msf(0); | ||
3882 | current_drive->ored_ctl_adr |= 0x40; | ||
3883 | current_drive->n_first_track = 1; | ||
3884 | current_drive->n_last_track = 1; | ||
3885 | current_drive->xa_byte = 0x10; | ||
3886 | j = 2; | ||
3887 | } else | ||
3888 | for (j=current_drive->n_first_track;j<=current_drive->n_last_track;j++) | ||
3889 | { | ||
3890 | i=cc_ReadTocEntry(j); | ||
3891 | if (i<0) | ||
3892 | { | ||
3893 | msg(DBG_INF,"cc_ReadTocEntry(%d) returns %d.\n",j,i); | ||
3894 | return (i); | ||
3895 | } | ||
3896 | current_drive->TocBuffer[j].nixbyte=current_drive->TocEnt_nixbyte; | ||
3897 | current_drive->TocBuffer[j].ctl_adr=current_drive->TocEnt_ctl_adr; | ||
3898 | current_drive->TocBuffer[j].number=current_drive->TocEnt_number; | ||
3899 | current_drive->TocBuffer[j].format=current_drive->TocEnt_format; | ||
3900 | current_drive->TocBuffer[j].address=current_drive->TocEnt_address; | ||
3901 | current_drive->ored_ctl_adr |= current_drive->TocEnt_ctl_adr; | ||
3902 | } | ||
3903 | /* fake entry for LeadOut Track */ | ||
3904 | current_drive->TocBuffer[j].nixbyte=0; | ||
3905 | current_drive->TocBuffer[j].ctl_adr=0; | ||
3906 | current_drive->TocBuffer[j].number=CDROM_LEADOUT; | ||
3907 | current_drive->TocBuffer[j].format=0; | ||
3908 | current_drive->TocBuffer[j].address=current_drive->size_msf; | ||
3909 | |||
3910 | current_drive->diskstate_flags |= toc_bit; | ||
3911 | return (0); | ||
3912 | } | ||
3913 | /*==========================================================================*/ | ||
3914 | static int DiskInfo(void) | ||
3915 | { | ||
3916 | int i, j; | ||
3917 | |||
3918 | current_drive->mode=READ_M1; | ||
3919 | |||
3920 | #undef LOOP_COUNT | ||
3921 | #define LOOP_COUNT 10 /* needed for some "old" drives */ | ||
3922 | |||
3923 | msg(DBG_000,"DiskInfo entered.\n"); | ||
3924 | for (j=1;j<LOOP_COUNT;j++) | ||
3925 | { | ||
3926 | #if 0 | ||
3927 | i=SetSpeed(); | ||
3928 | if (i<0) | ||
3929 | { | ||
3930 | msg(DBG_INF,"DiskInfo: SetSpeed returns %d\n", i); | ||
3931 | continue; | ||
3932 | } | ||
3933 | i=cc_ModeSense(); | ||
3934 | if (i<0) | ||
3935 | { | ||
3936 | msg(DBG_INF,"DiskInfo: cc_ModeSense returns %d\n", i); | ||
3937 | continue; | ||
3938 | } | ||
3939 | #endif | ||
3940 | i=cc_ReadCapacity(); | ||
3941 | if (i>=0) break; | ||
3942 | msg(DBG_INF,"DiskInfo: ReadCapacity #%d returns %d\n", j, i); | ||
3943 | #if 0 | ||
3944 | i=cc_DriveReset(); | ||
3945 | #endif | ||
3946 | if (!fam0_drive && j == 2) break; | ||
3947 | } | ||
3948 | if (j==LOOP_COUNT) return (-33); /* give up */ | ||
3949 | |||
3950 | i=cc_ReadTocDescr(); | ||
3951 | if (i<0) | ||
3952 | { | ||
3953 | msg(DBG_INF,"DiskInfo: ReadTocDescr returns %d\n", i); | ||
3954 | return (i); | ||
3955 | } | ||
3956 | i=ReadToC(); | ||
3957 | if (i<0) | ||
3958 | { | ||
3959 | msg(DBG_INF,"DiskInfo: ReadToC returns %d\n", i); | ||
3960 | return (i); | ||
3961 | } | ||
3962 | i=cc_CheckMultiSession(); | ||
3963 | if (i<0) | ||
3964 | { | ||
3965 | msg(DBG_INF,"DiskInfo: cc_CheckMultiSession returns %d\n", i); | ||
3966 | return (i); | ||
3967 | } | ||
3968 | if (current_drive->f_multisession) current_drive->sbp_bufsiz=1; /* possibly a weird PhotoCD */ | ||
3969 | else current_drive->sbp_bufsiz=buffers; | ||
3970 | i=cc_ReadTocEntry(current_drive->n_first_track); | ||
3971 | if (i<0) | ||
3972 | { | ||
3973 | msg(DBG_INF,"DiskInfo: cc_ReadTocEntry(1) returns %d\n", i); | ||
3974 | return (i); | ||
3975 | } | ||
3976 | i=cc_ReadUPC(); | ||
3977 | if (i<0) msg(DBG_INF,"DiskInfo: cc_ReadUPC returns %d\n", i); | ||
3978 | if ((fam0L_drive) && (current_drive->xa_byte==0x20 || current_drive->xa_byte == 0x10)) | ||
3979 | { | ||
3980 | /* XA disk with old drive */ | ||
3981 | cc_ModeSelect(CD_FRAMESIZE_RAW1); | ||
3982 | cc_ModeSense(); | ||
3983 | } | ||
3984 | if (famT_drive) cc_prep_mode_T(); | ||
3985 | msg(DBG_000,"DiskInfo done.\n"); | ||
3986 | return (0); | ||
3987 | } | ||
3988 | |||
3989 | static int sbpcd_drive_status(struct cdrom_device_info *cdi, int slot_nr) | ||
3990 | { | ||
3991 | struct sbpcd_drive *p = cdi->handle; | ||
3992 | int st; | ||
3993 | |||
3994 | if (CDSL_CURRENT != slot_nr) { | ||
3995 | /* we have no changer support */ | ||
3996 | return -EINVAL; | ||
3997 | } | ||
3998 | |||
3999 | cc_ReadStatus(); | ||
4000 | st=ResponseStatus(); | ||
4001 | if (st<0) | ||
4002 | { | ||
4003 | msg(DBG_INF,"sbpcd_drive_status: timeout.\n"); | ||
4004 | return (0); | ||
4005 | } | ||
4006 | msg(DBG_000,"Drive Status: door_locked =%d.\n", st_door_locked); | ||
4007 | msg(DBG_000,"Drive Status: door_closed =%d.\n", st_door_closed); | ||
4008 | msg(DBG_000,"Drive Status: caddy_in =%d.\n", st_caddy_in); | ||
4009 | msg(DBG_000,"Drive Status: disk_ok =%d.\n", st_diskok); | ||
4010 | msg(DBG_000,"Drive Status: spinning =%d.\n", st_spinning); | ||
4011 | msg(DBG_000,"Drive Status: busy =%d.\n", st_busy); | ||
4012 | |||
4013 | #if 0 | ||
4014 | if (!(p->status_bits & p_door_closed)) return CDS_TRAY_OPEN; | ||
4015 | if (p->status_bits & p_disk_ok) return CDS_DISC_OK; | ||
4016 | if (p->status_bits & p_disk_in) return CDS_DRIVE_NOT_READY; | ||
4017 | |||
4018 | return CDS_NO_DISC; | ||
4019 | #else | ||
4020 | if (p->status_bits & p_spinning) return CDS_DISC_OK; | ||
4021 | /* return CDS_TRAY_OPEN; */ | ||
4022 | return CDS_NO_DISC; | ||
4023 | |||
4024 | #endif | ||
4025 | |||
4026 | } | ||
4027 | |||
4028 | |||
4029 | /*==========================================================================*/ | ||
4030 | #ifdef FUTURE | ||
4031 | /* | ||
4032 | * called always if driver gets entered | ||
4033 | * returns 0 or ERROR2 or ERROR15 | ||
4034 | */ | ||
4035 | static int prepare(u_char func, u_char subfunc) | ||
4036 | { | ||
4037 | int i; | ||
4038 | |||
4039 | if (fam0L_drive) | ||
4040 | { | ||
4041 | i=inb(CDi_status); | ||
4042 | if (i&s_attention) GetStatus(); | ||
4043 | } | ||
4044 | else if (fam1_drive) GetStatus(); | ||
4045 | else if (fam2_drive) GetStatus(); | ||
4046 | else if (famT_drive) GetStatus(); | ||
4047 | if (current_drive->CD_changed==0xFF) | ||
4048 | { | ||
4049 | current_drive->diskstate_flags=0; | ||
4050 | current_drive->audio_state=0; | ||
4051 | if (!st_diskok) | ||
4052 | { | ||
4053 | i=check_allowed1(func,subfunc); | ||
4054 | if (i<0) return (-2); | ||
4055 | } | ||
4056 | else | ||
4057 | { | ||
4058 | i=check_allowed3(func,subfunc); | ||
4059 | if (i<0) | ||
4060 | { | ||
4061 | current_drive->CD_changed=1; | ||
4062 | return (-15); | ||
4063 | } | ||
4064 | } | ||
4065 | } | ||
4066 | else | ||
4067 | { | ||
4068 | if (!st_diskok) | ||
4069 | { | ||
4070 | current_drive->diskstate_flags=0; | ||
4071 | current_drive->audio_state=0; | ||
4072 | i=check_allowed1(func,subfunc); | ||
4073 | if (i<0) return (-2); | ||
4074 | } | ||
4075 | else | ||
4076 | { | ||
4077 | if (st_busy) | ||
4078 | { | ||
4079 | if (current_drive->audio_state!=audio_pausing) | ||
4080 | { | ||
4081 | i=check_allowed2(func,subfunc); | ||
4082 | if (i<0) return (-2); | ||
4083 | } | ||
4084 | } | ||
4085 | else | ||
4086 | { | ||
4087 | if (current_drive->audio_state==audio_playing) seek_pos_audio_end(); | ||
4088 | current_drive->audio_state=0; | ||
4089 | } | ||
4090 | if (!frame_size_valid) | ||
4091 | { | ||
4092 | i=DiskInfo(); | ||
4093 | if (i<0) | ||
4094 | { | ||
4095 | current_drive->diskstate_flags=0; | ||
4096 | current_drive->audio_state=0; | ||
4097 | i=check_allowed1(func,subfunc); | ||
4098 | if (i<0) return (-2); | ||
4099 | } | ||
4100 | } | ||
4101 | } | ||
4102 | } | ||
4103 | return (0); | ||
4104 | } | ||
4105 | #endif /* FUTURE */ | ||
4106 | /*==========================================================================*/ | ||
4107 | /*==========================================================================*/ | ||
4108 | /* | ||
4109 | * Check the results of the "get status" command. | ||
4110 | */ | ||
4111 | static int sbp_status(void) | ||
4112 | { | ||
4113 | int st; | ||
4114 | |||
4115 | st=ResponseStatus(); | ||
4116 | if (st<0) | ||
4117 | { | ||
4118 | msg(DBG_INF,"sbp_status: timeout.\n"); | ||
4119 | return (0); | ||
4120 | } | ||
4121 | |||
4122 | if (!st_spinning) msg(DBG_SPI,"motor got off - ignoring.\n"); | ||
4123 | |||
4124 | if (st_check) | ||
4125 | { | ||
4126 | msg(DBG_INF,"st_check detected - retrying.\n"); | ||
4127 | return (0); | ||
4128 | } | ||
4129 | if (!st_door_closed) | ||
4130 | { | ||
4131 | msg(DBG_INF,"door is open - retrying.\n"); | ||
4132 | return (0); | ||
4133 | } | ||
4134 | if (!st_caddy_in) | ||
4135 | { | ||
4136 | msg(DBG_INF,"disk removed - retrying.\n"); | ||
4137 | return (0); | ||
4138 | } | ||
4139 | if (!st_diskok) | ||
4140 | { | ||
4141 | msg(DBG_INF,"!st_diskok detected - retrying.\n"); | ||
4142 | return (0); | ||
4143 | } | ||
4144 | if (st_busy) | ||
4145 | { | ||
4146 | msg(DBG_INF,"st_busy detected - retrying.\n"); | ||
4147 | return (0); | ||
4148 | } | ||
4149 | return (1); | ||
4150 | } | ||
4151 | /*==========================================================================*/ | ||
4152 | |||
4153 | static int sbpcd_get_last_session(struct cdrom_device_info *cdi, struct cdrom_multisession *ms_infp) | ||
4154 | { | ||
4155 | struct sbpcd_drive *p = cdi->handle; | ||
4156 | ms_infp->addr_format = CDROM_LBA; | ||
4157 | ms_infp->addr.lba = p->lba_multi; | ||
4158 | if (p->f_multisession) | ||
4159 | ms_infp->xa_flag=1; /* valid redirection address */ | ||
4160 | else | ||
4161 | ms_infp->xa_flag=0; /* invalid redirection address */ | ||
4162 | |||
4163 | return 0; | ||
4164 | } | ||
4165 | |||
4166 | static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, | ||
4167 | void * arg) | ||
4168 | { | ||
4169 | struct sbpcd_drive *p = cdi->handle; | ||
4170 | int i, st, j; | ||
4171 | |||
4172 | msg(DBG_IO2,"ioctl(%s, 0x%08lX, 0x%08p)\n", cdi->name, cmd, arg); | ||
4173 | if (p->drv_id==-1) { | ||
4174 | msg(DBG_INF, "ioctl: bad device: %s\n", cdi->name); | ||
4175 | return (-ENXIO); /* no such drive */ | ||
4176 | } | ||
4177 | down(&ioctl_read_sem); | ||
4178 | if (p != current_drive) | ||
4179 | switch_drive(p); | ||
4180 | |||
4181 | msg(DBG_IO2,"ioctl: device %s, request %04X\n",cdi->name,cmd); | ||
4182 | switch (cmd) /* Sun-compatible */ | ||
4183 | { | ||
4184 | |||
4185 | case CDROMPAUSE: /* Pause the drive */ | ||
4186 | msg(DBG_IOC,"ioctl: CDROMPAUSE entered.\n"); | ||
4187 | /* pause the drive unit when it is currently in PLAY mode, */ | ||
4188 | /* or reset the starting and ending locations when in PAUSED mode. */ | ||
4189 | /* If applicable, at the next stopping point it reaches */ | ||
4190 | /* the drive will discontinue playing. */ | ||
4191 | switch (current_drive->audio_state) | ||
4192 | { | ||
4193 | case audio_playing: | ||
4194 | if (famL_drive) i=cc_ReadSubQ(); | ||
4195 | else i=cc_Pause_Resume(1); | ||
4196 | if (i<0) RETURN_UP(-EIO); | ||
4197 | if (famL_drive) i=cc_Pause_Resume(1); | ||
4198 | else i=cc_ReadSubQ(); | ||
4199 | if (i<0) RETURN_UP(-EIO); | ||
4200 | current_drive->pos_audio_start=current_drive->SubQ_run_tot; | ||
4201 | current_drive->audio_state=audio_pausing; | ||
4202 | RETURN_UP(0); | ||
4203 | case audio_pausing: | ||
4204 | i=cc_Seek(current_drive->pos_audio_start,1); | ||
4205 | if (i<0) RETURN_UP(-EIO); | ||
4206 | RETURN_UP(0); | ||
4207 | default: | ||
4208 | RETURN_UP(-EINVAL); | ||
4209 | } | ||
4210 | |||
4211 | case CDROMRESUME: /* resume paused audio play */ | ||
4212 | msg(DBG_IOC,"ioctl: CDROMRESUME entered.\n"); | ||
4213 | /* resume playing audio tracks when a previous PLAY AUDIO call has */ | ||
4214 | /* been paused with a PAUSE command. */ | ||
4215 | /* It will resume playing from the location saved in SubQ_run_tot. */ | ||
4216 | if (current_drive->audio_state!=audio_pausing) RETURN_UP(-EINVAL); | ||
4217 | if (famL_drive) | ||
4218 | i=cc_PlayAudio(current_drive->pos_audio_start, | ||
4219 | current_drive->pos_audio_end); | ||
4220 | else i=cc_Pause_Resume(3); | ||
4221 | if (i<0) RETURN_UP(-EIO); | ||
4222 | current_drive->audio_state=audio_playing; | ||
4223 | RETURN_UP(0); | ||
4224 | |||
4225 | case CDROMPLAYMSF: | ||
4226 | msg(DBG_IOC,"ioctl: CDROMPLAYMSF entered.\n"); | ||
4227 | #ifdef SAFE_MIXED | ||
4228 | if (current_drive->has_data>1) RETURN_UP(-EBUSY); | ||
4229 | #endif /* SAFE_MIXED */ | ||
4230 | if (current_drive->audio_state==audio_playing) | ||
4231 | { | ||
4232 | i=cc_Pause_Resume(1); | ||
4233 | if (i<0) RETURN_UP(-EIO); | ||
4234 | i=cc_ReadSubQ(); | ||
4235 | if (i<0) RETURN_UP(-EIO); | ||
4236 | current_drive->pos_audio_start=current_drive->SubQ_run_tot; | ||
4237 | i=cc_Seek(current_drive->pos_audio_start,1); | ||
4238 | } | ||
4239 | memcpy(&msf, (void *) arg, sizeof(struct cdrom_msf)); | ||
4240 | /* values come as msf-bin */ | ||
4241 | current_drive->pos_audio_start = (msf.cdmsf_min0<<16) | | ||
4242 | (msf.cdmsf_sec0<<8) | | ||
4243 | msf.cdmsf_frame0; | ||
4244 | current_drive->pos_audio_end = (msf.cdmsf_min1<<16) | | ||
4245 | (msf.cdmsf_sec1<<8) | | ||
4246 | msf.cdmsf_frame1; | ||
4247 | msg(DBG_IOX,"ioctl: CDROMPLAYMSF %08X %08X\n", | ||
4248 | current_drive->pos_audio_start,current_drive->pos_audio_end); | ||
4249 | i=cc_PlayAudio(current_drive->pos_audio_start,current_drive->pos_audio_end); | ||
4250 | if (i<0) | ||
4251 | { | ||
4252 | msg(DBG_INF,"ioctl: cc_PlayAudio returns %d\n",i); | ||
4253 | DriveReset(); | ||
4254 | current_drive->audio_state=0; | ||
4255 | RETURN_UP(-EIO); | ||
4256 | } | ||
4257 | current_drive->audio_state=audio_playing; | ||
4258 | RETURN_UP(0); | ||
4259 | |||
4260 | case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */ | ||
4261 | msg(DBG_IOC,"ioctl: CDROMPLAYTRKIND entered.\n"); | ||
4262 | #ifdef SAFE_MIXED | ||
4263 | if (current_drive->has_data>1) RETURN_UP(-EBUSY); | ||
4264 | #endif /* SAFE_MIXED */ | ||
4265 | if (current_drive->audio_state==audio_playing) | ||
4266 | { | ||
4267 | msg(DBG_IOX,"CDROMPLAYTRKIND: already audio_playing.\n"); | ||
4268 | #if 1 | ||
4269 | RETURN_UP(0); /* just let us play on */ | ||
4270 | #else | ||
4271 | RETURN_UP(-EINVAL); /* play on, but say "error" */ | ||
4272 | #endif | ||
4273 | } | ||
4274 | memcpy(&ti,(void *) arg,sizeof(struct cdrom_ti)); | ||
4275 | msg(DBG_IOX,"ioctl: trk0: %d, ind0: %d, trk1:%d, ind1:%d\n", | ||
4276 | ti.cdti_trk0,ti.cdti_ind0,ti.cdti_trk1,ti.cdti_ind1); | ||
4277 | if (ti.cdti_trk0<current_drive->n_first_track) RETURN_UP(-EINVAL); | ||
4278 | if (ti.cdti_trk0>current_drive->n_last_track) RETURN_UP(-EINVAL); | ||
4279 | if (ti.cdti_trk1<ti.cdti_trk0) ti.cdti_trk1=ti.cdti_trk0; | ||
4280 | if (ti.cdti_trk1>current_drive->n_last_track) ti.cdti_trk1=current_drive->n_last_track; | ||
4281 | current_drive->pos_audio_start=current_drive->TocBuffer[ti.cdti_trk0].address; | ||
4282 | current_drive->pos_audio_end=current_drive->TocBuffer[ti.cdti_trk1+1].address; | ||
4283 | i=cc_PlayAudio(current_drive->pos_audio_start,current_drive->pos_audio_end); | ||
4284 | if (i<0) | ||
4285 | { | ||
4286 | msg(DBG_INF,"ioctl: cc_PlayAudio returns %d\n",i); | ||
4287 | DriveReset(); | ||
4288 | current_drive->audio_state=0; | ||
4289 | RETURN_UP(-EIO); | ||
4290 | } | ||
4291 | current_drive->audio_state=audio_playing; | ||
4292 | RETURN_UP(0); | ||
4293 | |||
4294 | case CDROMREADTOCHDR: /* Read the table of contents header */ | ||
4295 | msg(DBG_IOC,"ioctl: CDROMREADTOCHDR entered.\n"); | ||
4296 | tochdr.cdth_trk0=current_drive->n_first_track; | ||
4297 | tochdr.cdth_trk1=current_drive->n_last_track; | ||
4298 | memcpy((void *) arg, &tochdr, sizeof(struct cdrom_tochdr)); | ||
4299 | RETURN_UP(0); | ||
4300 | |||
4301 | case CDROMREADTOCENTRY: /* Read an entry in the table of contents */ | ||
4302 | msg(DBG_IOC,"ioctl: CDROMREADTOCENTRY entered.\n"); | ||
4303 | memcpy(&tocentry, (void *) arg, sizeof(struct cdrom_tocentry)); | ||
4304 | i=tocentry.cdte_track; | ||
4305 | if (i==CDROM_LEADOUT) i=current_drive->n_last_track+1; | ||
4306 | else if (i<current_drive->n_first_track||i>current_drive->n_last_track) | ||
4307 | RETURN_UP(-EINVAL); | ||
4308 | tocentry.cdte_adr=current_drive->TocBuffer[i].ctl_adr&0x0F; | ||
4309 | tocentry.cdte_ctrl=(current_drive->TocBuffer[i].ctl_adr>>4)&0x0F; | ||
4310 | tocentry.cdte_datamode=current_drive->TocBuffer[i].format; | ||
4311 | if (tocentry.cdte_format==CDROM_MSF) /* MSF-bin required */ | ||
4312 | { | ||
4313 | tocentry.cdte_addr.msf.minute=(current_drive->TocBuffer[i].address>>16)&0x00FF; | ||
4314 | tocentry.cdte_addr.msf.second=(current_drive->TocBuffer[i].address>>8)&0x00FF; | ||
4315 | tocentry.cdte_addr.msf.frame=current_drive->TocBuffer[i].address&0x00FF; | ||
4316 | } | ||
4317 | else if (tocentry.cdte_format==CDROM_LBA) /* blk required */ | ||
4318 | tocentry.cdte_addr.lba=msf2blk(current_drive->TocBuffer[i].address); | ||
4319 | else RETURN_UP(-EINVAL); | ||
4320 | memcpy((void *) arg, &tocentry, sizeof(struct cdrom_tocentry)); | ||
4321 | RETURN_UP(0); | ||
4322 | |||
4323 | case CDROMSTOP: /* Spin down the drive */ | ||
4324 | msg(DBG_IOC,"ioctl: CDROMSTOP entered.\n"); | ||
4325 | #ifdef SAFE_MIXED | ||
4326 | if (current_drive->has_data>1) RETURN_UP(-EBUSY); | ||
4327 | #endif /* SAFE_MIXED */ | ||
4328 | i=cc_Pause_Resume(1); | ||
4329 | current_drive->audio_state=0; | ||
4330 | #if 0 | ||
4331 | cc_DriveReset(); | ||
4332 | #endif | ||
4333 | RETURN_UP(i); | ||
4334 | |||
4335 | case CDROMSTART: /* Spin up the drive */ | ||
4336 | msg(DBG_IOC,"ioctl: CDROMSTART entered.\n"); | ||
4337 | cc_SpinUp(); | ||
4338 | current_drive->audio_state=0; | ||
4339 | RETURN_UP(0); | ||
4340 | |||
4341 | case CDROMVOLCTRL: /* Volume control */ | ||
4342 | msg(DBG_IOC,"ioctl: CDROMVOLCTRL entered.\n"); | ||
4343 | memcpy(&volctrl,(char *) arg,sizeof(volctrl)); | ||
4344 | current_drive->vol_chan0=0; | ||
4345 | current_drive->vol_ctrl0=volctrl.channel0; | ||
4346 | current_drive->vol_chan1=1; | ||
4347 | current_drive->vol_ctrl1=volctrl.channel1; | ||
4348 | i=cc_SetVolume(); | ||
4349 | RETURN_UP(0); | ||
4350 | |||
4351 | case CDROMVOLREAD: /* read Volume settings from drive */ | ||
4352 | msg(DBG_IOC,"ioctl: CDROMVOLREAD entered.\n"); | ||
4353 | st=cc_GetVolume(); | ||
4354 | if (st<0) RETURN_UP(st); | ||
4355 | volctrl.channel0=current_drive->vol_ctrl0; | ||
4356 | volctrl.channel1=current_drive->vol_ctrl1; | ||
4357 | volctrl.channel2=0; | ||
4358 | volctrl.channel2=0; | ||
4359 | memcpy((void *)arg,&volctrl,sizeof(volctrl)); | ||
4360 | RETURN_UP(0); | ||
4361 | |||
4362 | case CDROMSUBCHNL: /* Get subchannel info */ | ||
4363 | msg(DBG_IOS,"ioctl: CDROMSUBCHNL entered.\n"); | ||
4364 | /* Bogus, I can do better than this! --AJK | ||
4365 | if ((st_spinning)||(!subq_valid)) { | ||
4366 | i=cc_ReadSubQ(); | ||
4367 | if (i<0) RETURN_UP(-EIO); | ||
4368 | } | ||
4369 | */ | ||
4370 | i=cc_ReadSubQ(); | ||
4371 | if (i<0) { | ||
4372 | j=cc_ReadError(); /* clear out error status from drive */ | ||
4373 | current_drive->audio_state=CDROM_AUDIO_NO_STATUS; | ||
4374 | /* get and set the disk state here, | ||
4375 | probably not the right place, but who cares! | ||
4376 | It makes it work properly! --AJK */ | ||
4377 | if (current_drive->CD_changed==0xFF) { | ||
4378 | msg(DBG_000,"Disk changed detect\n"); | ||
4379 | current_drive->diskstate_flags &= ~cd_size_bit; | ||
4380 | } | ||
4381 | RETURN_UP(-EIO); | ||
4382 | } | ||
4383 | if (current_drive->CD_changed==0xFF) { | ||
4384 | /* reread the TOC because the disk has changed! --AJK */ | ||
4385 | msg(DBG_000,"Disk changed STILL detected, rereading TOC!\n"); | ||
4386 | i=DiskInfo(); | ||
4387 | if(i==0) { | ||
4388 | current_drive->CD_changed=0x00; /* cd has changed, procede, */ | ||
4389 | RETURN_UP(-EIO); /* and get TOC, etc on next try! --AJK */ | ||
4390 | } else { | ||
4391 | RETURN_UP(-EIO); /* we weren't ready yet! --AJK */ | ||
4392 | } | ||
4393 | } | ||
4394 | memcpy(&SC, (void *) arg, sizeof(struct cdrom_subchnl)); | ||
4395 | /* | ||
4396 | This virtual crap is very bogus! | ||
4397 | It doesn't detect when the cd is done playing audio! | ||
4398 | Lets do this right with proper hardware register reading! | ||
4399 | */ | ||
4400 | cc_ReadStatus(); | ||
4401 | i=ResponseStatus(); | ||
4402 | msg(DBG_000,"Drive Status: door_locked =%d.\n", st_door_locked); | ||
4403 | msg(DBG_000,"Drive Status: door_closed =%d.\n", st_door_closed); | ||
4404 | msg(DBG_000,"Drive Status: caddy_in =%d.\n", st_caddy_in); | ||
4405 | msg(DBG_000,"Drive Status: disk_ok =%d.\n", st_diskok); | ||
4406 | msg(DBG_000,"Drive Status: spinning =%d.\n", st_spinning); | ||
4407 | msg(DBG_000,"Drive Status: busy =%d.\n", st_busy); | ||
4408 | /* st_busy indicates if it's _ACTUALLY_ playing audio */ | ||
4409 | switch (current_drive->audio_state) | ||
4410 | { | ||
4411 | case audio_playing: | ||
4412 | if(st_busy==0) { | ||
4413 | /* CD has stopped playing audio --AJK */ | ||
4414 | current_drive->audio_state=audio_completed; | ||
4415 | SC.cdsc_audiostatus=CDROM_AUDIO_COMPLETED; | ||
4416 | } else { | ||
4417 | SC.cdsc_audiostatus=CDROM_AUDIO_PLAY; | ||
4418 | } | ||
4419 | break; | ||
4420 | case audio_pausing: | ||
4421 | SC.cdsc_audiostatus=CDROM_AUDIO_PAUSED; | ||
4422 | break; | ||
4423 | case audio_completed: | ||
4424 | SC.cdsc_audiostatus=CDROM_AUDIO_COMPLETED; | ||
4425 | break; | ||
4426 | default: | ||
4427 | SC.cdsc_audiostatus=CDROM_AUDIO_NO_STATUS; | ||
4428 | break; | ||
4429 | } | ||
4430 | SC.cdsc_adr=current_drive->SubQ_ctl_adr; | ||
4431 | SC.cdsc_ctrl=current_drive->SubQ_ctl_adr>>4; | ||
4432 | SC.cdsc_trk=bcd2bin(current_drive->SubQ_trk); | ||
4433 | SC.cdsc_ind=bcd2bin(current_drive->SubQ_pnt_idx); | ||
4434 | if (SC.cdsc_format==CDROM_LBA) | ||
4435 | { | ||
4436 | SC.cdsc_absaddr.lba=msf2blk(current_drive->SubQ_run_tot); | ||
4437 | SC.cdsc_reladdr.lba=msf2blk(current_drive->SubQ_run_trk); | ||
4438 | } | ||
4439 | else /* not only if (SC.cdsc_format==CDROM_MSF) */ | ||
4440 | { | ||
4441 | SC.cdsc_absaddr.msf.minute=(current_drive->SubQ_run_tot>>16)&0x00FF; | ||
4442 | SC.cdsc_absaddr.msf.second=(current_drive->SubQ_run_tot>>8)&0x00FF; | ||
4443 | SC.cdsc_absaddr.msf.frame=current_drive->SubQ_run_tot&0x00FF; | ||
4444 | SC.cdsc_reladdr.msf.minute=(current_drive->SubQ_run_trk>>16)&0x00FF; | ||
4445 | SC.cdsc_reladdr.msf.second=(current_drive->SubQ_run_trk>>8)&0x00FF; | ||
4446 | SC.cdsc_reladdr.msf.frame=current_drive->SubQ_run_trk&0x00FF; | ||
4447 | } | ||
4448 | memcpy((void *) arg, &SC, sizeof(struct cdrom_subchnl)); | ||
4449 | msg(DBG_IOS,"CDROMSUBCHNL: %1X %02X %08X %08X %02X %02X %06X %06X\n", | ||
4450 | SC.cdsc_format,SC.cdsc_audiostatus, | ||
4451 | SC.cdsc_adr,SC.cdsc_ctrl, | ||
4452 | SC.cdsc_trk,SC.cdsc_ind, | ||
4453 | SC.cdsc_absaddr,SC.cdsc_reladdr); | ||
4454 | RETURN_UP(0); | ||
4455 | |||
4456 | default: | ||
4457 | msg(DBG_IOC,"ioctl: unknown function request %04X\n", cmd); | ||
4458 | RETURN_UP(-EINVAL); | ||
4459 | } /* end switch(cmd) */ | ||
4460 | } | ||
4461 | /*==========================================================================*/ | ||
4462 | /* | ||
4463 | * Take care of the different block sizes between cdrom and Linux. | ||
4464 | */ | ||
4465 | static void sbp_transfer(struct request *req) | ||
4466 | { | ||
4467 | long offs; | ||
4468 | |||
4469 | while ( (req->nr_sectors > 0) && | ||
4470 | (req->sector/4 >= current_drive->sbp_first_frame) && | ||
4471 | (req->sector/4 <= current_drive->sbp_last_frame) ) | ||
4472 | { | ||
4473 | offs = (req->sector - current_drive->sbp_first_frame * 4) * 512; | ||
4474 | memcpy(req->buffer, current_drive->sbp_buf + offs, 512); | ||
4475 | req->nr_sectors--; | ||
4476 | req->sector++; | ||
4477 | req->buffer += 512; | ||
4478 | } | ||
4479 | } | ||
4480 | /*==========================================================================*/ | ||
4481 | /* | ||
4482 | * special end_request for sbpcd to solve CURRENT==NULL bug. (GTL) | ||
4483 | * GTL = Gonzalo Tornaria <tornaria@cmat.edu.uy> | ||
4484 | * | ||
4485 | * This is a kludge so we don't need to modify end_request. | ||
4486 | * We put the req we take out after INIT_REQUEST in the requests list, | ||
4487 | * so that end_request will discard it. | ||
4488 | * | ||
4489 | * The bug could be present in other block devices, perhaps we | ||
4490 | * should modify INIT_REQUEST and end_request instead, and | ||
4491 | * change every block device.. | ||
4492 | * | ||
4493 | * Could be a race here?? Could e.g. a timer interrupt schedule() us? | ||
4494 | * If so, we should copy end_request here, and do it right.. (or | ||
4495 | * modify end_request and the block devices). | ||
4496 | * | ||
4497 | * In any case, the race here would be much small than it was, and | ||
4498 | * I couldn't reproduce.. | ||
4499 | * | ||
4500 | * The race could be: suppose CURRENT==NULL. We put our req in the list, | ||
4501 | * and we are scheduled. Other process takes over, and gets into | ||
4502 | * do_sbpcd_request. It sees CURRENT!=NULL (it is == to our req), so | ||
4503 | * proceeds. It ends, so CURRENT is now NULL.. Now we awake somewhere in | ||
4504 | * end_request, but now CURRENT==NULL... oops! | ||
4505 | * | ||
4506 | */ | ||
4507 | #undef DEBUG_GTL | ||
4508 | |||
4509 | /*==========================================================================*/ | ||
4510 | /* | ||
4511 | * I/O request routine, called from Linux kernel. | ||
4512 | */ | ||
4513 | static void do_sbpcd_request(request_queue_t * q) | ||
4514 | { | ||
4515 | u_int block; | ||
4516 | u_int nsect; | ||
4517 | int status_tries, data_tries; | ||
4518 | struct request *req; | ||
4519 | struct sbpcd_drive *p; | ||
4520 | #ifdef DEBUG_GTL | ||
4521 | static int xx_nr=0; | ||
4522 | int xnr; | ||
4523 | #endif | ||
4524 | |||
4525 | request_loop: | ||
4526 | #ifdef DEBUG_GTL | ||
4527 | xnr=++xx_nr; | ||
4528 | |||
4529 | req = elv_next_request(q); | ||
4530 | |||
4531 | if (!req) | ||
4532 | { | ||
4533 | printk( "do_sbpcd_request[%di](NULL), Pid:%d, Time:%li\n", | ||
4534 | xnr, current->pid, jiffies); | ||
4535 | printk( "do_sbpcd_request[%do](NULL) end 0 (null), Time:%li\n", | ||
4536 | xnr, jiffies); | ||
4537 | return; | ||
4538 | } | ||
4539 | |||
4540 | printk(" do_sbpcd_request[%di](%p:%ld+%ld), Pid:%d, Time:%li\n", | ||
4541 | xnr, req, req->sector, req->nr_sectors, current->pid, jiffies); | ||
4542 | #endif | ||
4543 | |||
4544 | req = elv_next_request(q); /* take out our request so no other */ | ||
4545 | if (!req) | ||
4546 | return; | ||
4547 | |||
4548 | if (req -> sector == -1) | ||
4549 | end_request(req, 0); | ||
4550 | spin_unlock_irq(q->queue_lock); | ||
4551 | |||
4552 | down(&ioctl_read_sem); | ||
4553 | if (rq_data_dir(elv_next_request(q)) != READ) | ||
4554 | { | ||
4555 | msg(DBG_INF, "bad cmd %d\n", req->cmd[0]); | ||
4556 | goto err_done; | ||
4557 | } | ||
4558 | p = req->rq_disk->private_data; | ||
4559 | #if OLD_BUSY | ||
4560 | while (busy_audio) sbp_sleep(HZ); /* wait a bit */ | ||
4561 | busy_data=1; | ||
4562 | #endif /* OLD_BUSY */ | ||
4563 | |||
4564 | if (p->audio_state==audio_playing) goto err_done; | ||
4565 | if (p != current_drive) | ||
4566 | switch_drive(p); | ||
4567 | |||
4568 | block = req->sector; /* always numbered as 512-byte-pieces */ | ||
4569 | nsect = req->nr_sectors; /* always counted as 512-byte-pieces */ | ||
4570 | |||
4571 | msg(DBG_BSZ,"read sector %d (%d sectors)\n", block, nsect); | ||
4572 | #if 0 | ||
4573 | msg(DBG_MUL,"read LBA %d\n", block/4); | ||
4574 | #endif | ||
4575 | |||
4576 | sbp_transfer(req); | ||
4577 | /* if we satisfied the request from the buffer, we're done. */ | ||
4578 | if (req->nr_sectors == 0) | ||
4579 | { | ||
4580 | #ifdef DEBUG_GTL | ||
4581 | printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 2, Time:%li\n", | ||
4582 | xnr, req, req->sector, req->nr_sectors, jiffies); | ||
4583 | #endif | ||
4584 | up(&ioctl_read_sem); | ||
4585 | spin_lock_irq(q->queue_lock); | ||
4586 | end_request(req, 1); | ||
4587 | goto request_loop; | ||
4588 | } | ||
4589 | |||
4590 | #ifdef FUTURE | ||
4591 | i=prepare(0,0); /* at moment not really a hassle check, but ... */ | ||
4592 | if (i!=0) | ||
4593 | msg(DBG_INF,"\"prepare\" tells error %d -- ignored\n", i); | ||
4594 | #endif /* FUTURE */ | ||
4595 | |||
4596 | if (!st_spinning) cc_SpinUp(); | ||
4597 | |||
4598 | for (data_tries=n_retries; data_tries > 0; data_tries--) | ||
4599 | { | ||
4600 | for (status_tries=3; status_tries > 0; status_tries--) | ||
4601 | { | ||
4602 | flags_cmd_out |= f_respo3; | ||
4603 | cc_ReadStatus(); | ||
4604 | if (sbp_status() != 0) break; | ||
4605 | if (st_check) cc_ReadError(); | ||
4606 | sbp_sleep(1); /* wait a bit, try again */ | ||
4607 | } | ||
4608 | if (status_tries == 0) | ||
4609 | { | ||
4610 | msg(DBG_INF,"sbp_status: failed after 3 tries in line %d\n", __LINE__); | ||
4611 | break; | ||
4612 | } | ||
4613 | |||
4614 | sbp_read_cmd(req); | ||
4615 | sbp_sleep(0); | ||
4616 | if (sbp_data(req) != 0) | ||
4617 | { | ||
4618 | #ifdef SAFE_MIXED | ||
4619 | current_drive->has_data=2; /* is really a data disk */ | ||
4620 | #endif /* SAFE_MIXED */ | ||
4621 | #ifdef DEBUG_GTL | ||
4622 | printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 3, Time:%li\n", | ||
4623 | xnr, req, req->sector, req->nr_sectors, jiffies); | ||
4624 | #endif | ||
4625 | up(&ioctl_read_sem); | ||
4626 | spin_lock_irq(q->queue_lock); | ||
4627 | end_request(req, 1); | ||
4628 | goto request_loop; | ||
4629 | } | ||
4630 | } | ||
4631 | |||
4632 | err_done: | ||
4633 | #if OLD_BUSY | ||
4634 | busy_data=0; | ||
4635 | #endif /* OLD_BUSY */ | ||
4636 | #ifdef DEBUG_GTL | ||
4637 | printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 4 (error), Time:%li\n", | ||
4638 | xnr, req, req->sector, req->nr_sectors, jiffies); | ||
4639 | #endif | ||
4640 | up(&ioctl_read_sem); | ||
4641 | sbp_sleep(0); /* wait a bit, try again */ | ||
4642 | spin_lock_irq(q->queue_lock); | ||
4643 | end_request(req, 0); | ||
4644 | goto request_loop; | ||
4645 | } | ||
4646 | /*==========================================================================*/ | ||
4647 | /* | ||
4648 | * build and send the READ command. | ||
4649 | */ | ||
4650 | static void sbp_read_cmd(struct request *req) | ||
4651 | { | ||
4652 | #undef OLD | ||
4653 | |||
4654 | int i; | ||
4655 | int block; | ||
4656 | |||
4657 | current_drive->sbp_first_frame=current_drive->sbp_last_frame=-1; /* purge buffer */ | ||
4658 | current_drive->sbp_current = 0; | ||
4659 | block=req->sector/4; | ||
4660 | if (block+current_drive->sbp_bufsiz <= current_drive->CDsize_frm) | ||
4661 | current_drive->sbp_read_frames = current_drive->sbp_bufsiz; | ||
4662 | else | ||
4663 | { | ||
4664 | current_drive->sbp_read_frames=current_drive->CDsize_frm-block; | ||
4665 | /* avoid reading past end of data */ | ||
4666 | if (current_drive->sbp_read_frames < 1) | ||
4667 | { | ||
4668 | msg(DBG_INF,"requested frame %d, CD size %d ???\n", | ||
4669 | block, current_drive->CDsize_frm); | ||
4670 | current_drive->sbp_read_frames=1; | ||
4671 | } | ||
4672 | } | ||
4673 | |||
4674 | flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus | f_obey_p_check; | ||
4675 | clr_cmdbuf(); | ||
4676 | if (famV_drive) | ||
4677 | { | ||
4678 | drvcmd[0]=CMDV_READ; | ||
4679 | lba2msf(block,&drvcmd[1]); /* msf-bcd format required */ | ||
4680 | bin2bcdx(&drvcmd[1]); | ||
4681 | bin2bcdx(&drvcmd[2]); | ||
4682 | bin2bcdx(&drvcmd[3]); | ||
4683 | drvcmd[4]=current_drive->sbp_read_frames>>8; | ||
4684 | drvcmd[5]=current_drive->sbp_read_frames&0xff; | ||
4685 | drvcmd[6]=0x02; /* flag "msf-bcd" */ | ||
4686 | } | ||
4687 | else if (fam0L_drive) | ||
4688 | { | ||
4689 | flags_cmd_out |= f_lopsta | f_getsta | f_bit1; | ||
4690 | if (current_drive->xa_byte==0x20) | ||
4691 | { | ||
4692 | cmd_type=READ_M2; | ||
4693 | drvcmd[0]=CMD0_READ_XA; /* "read XA frames", old drives */ | ||
4694 | drvcmd[1]=(block>>16)&0x0ff; | ||
4695 | drvcmd[2]=(block>>8)&0x0ff; | ||
4696 | drvcmd[3]=block&0x0ff; | ||
4697 | drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff; | ||
4698 | drvcmd[5]=current_drive->sbp_read_frames&0x0ff; | ||
4699 | } | ||
4700 | else | ||
4701 | { | ||
4702 | drvcmd[0]=CMD0_READ; /* "read frames", old drives */ | ||
4703 | if (current_drive->drv_type>=drv_201) | ||
4704 | { | ||
4705 | lba2msf(block,&drvcmd[1]); /* msf-bcd format required */ | ||
4706 | bin2bcdx(&drvcmd[1]); | ||
4707 | bin2bcdx(&drvcmd[2]); | ||
4708 | bin2bcdx(&drvcmd[3]); | ||
4709 | } | ||
4710 | else | ||
4711 | { | ||
4712 | drvcmd[1]=(block>>16)&0x0ff; | ||
4713 | drvcmd[2]=(block>>8)&0x0ff; | ||
4714 | drvcmd[3]=block&0x0ff; | ||
4715 | } | ||
4716 | drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff; | ||
4717 | drvcmd[5]=current_drive->sbp_read_frames&0x0ff; | ||
4718 | drvcmd[6]=(current_drive->drv_type<drv_201)?0:2; /* flag "lba or msf-bcd format" */ | ||
4719 | } | ||
4720 | } | ||
4721 | else if (fam1_drive) | ||
4722 | { | ||
4723 | drvcmd[0]=CMD1_READ; | ||
4724 | lba2msf(block,&drvcmd[1]); /* msf-bin format required */ | ||
4725 | drvcmd[5]=(current_drive->sbp_read_frames>>8)&0x0ff; | ||
4726 | drvcmd[6]=current_drive->sbp_read_frames&0x0ff; | ||
4727 | } | ||
4728 | else if (fam2_drive) | ||
4729 | { | ||
4730 | drvcmd[0]=CMD2_READ; | ||
4731 | lba2msf(block,&drvcmd[1]); /* msf-bin format required */ | ||
4732 | drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff; | ||
4733 | drvcmd[5]=current_drive->sbp_read_frames&0x0ff; | ||
4734 | drvcmd[6]=0x02; | ||
4735 | } | ||
4736 | else if (famT_drive) | ||
4737 | { | ||
4738 | drvcmd[0]=CMDT_READ; | ||
4739 | drvcmd[2]=(block>>24)&0x0ff; | ||
4740 | drvcmd[3]=(block>>16)&0x0ff; | ||
4741 | drvcmd[4]=(block>>8)&0x0ff; | ||
4742 | drvcmd[5]=block&0x0ff; | ||
4743 | drvcmd[7]=(current_drive->sbp_read_frames>>8)&0x0ff; | ||
4744 | drvcmd[8]=current_drive->sbp_read_frames&0x0ff; | ||
4745 | } | ||
4746 | flags_cmd_out=f_putcmd; | ||
4747 | response_count=0; | ||
4748 | i=cmd_out(); | ||
4749 | if (i<0) msg(DBG_INF,"error giving READ command: %0d\n", i); | ||
4750 | return; | ||
4751 | } | ||
4752 | /*==========================================================================*/ | ||
4753 | /* | ||
4754 | * Check the completion of the read-data command. On success, read | ||
4755 | * the current_drive->sbp_bufsiz * 2048 bytes of data from the disk into buffer. | ||
4756 | */ | ||
4757 | static int sbp_data(struct request *req) | ||
4758 | { | ||
4759 | int i=0, j=0, l, frame; | ||
4760 | u_int try=0; | ||
4761 | u_long timeout; | ||
4762 | u_char *p; | ||
4763 | u_int data_tries = 0; | ||
4764 | u_int data_waits = 0; | ||
4765 | u_int data_retrying = 0; | ||
4766 | int error_flag; | ||
4767 | int xa_count; | ||
4768 | int max_latency; | ||
4769 | int success; | ||
4770 | int wait; | ||
4771 | int duration; | ||
4772 | |||
4773 | error_flag=0; | ||
4774 | success=0; | ||
4775 | #if LONG_TIMING | ||
4776 | max_latency=9*HZ; | ||
4777 | #else | ||
4778 | if (current_drive->f_multisession) max_latency=15*HZ; | ||
4779 | else max_latency=5*HZ; | ||
4780 | #endif | ||
4781 | duration=jiffies; | ||
4782 | for (frame=0;frame<current_drive->sbp_read_frames&&!error_flag; frame++) | ||
4783 | { | ||
4784 | SBPCD_CLI; | ||
4785 | |||
4786 | del_timer(&data_timer); | ||
4787 | data_timer.expires=jiffies+max_latency; | ||
4788 | timed_out_data=0; | ||
4789 | add_timer(&data_timer); | ||
4790 | while (!timed_out_data) | ||
4791 | { | ||
4792 | if (current_drive->f_multisession) try=maxtim_data*4; | ||
4793 | else try=maxtim_data; | ||
4794 | msg(DBG_000,"sbp_data: CDi_status loop: try=%d.\n",try); | ||
4795 | for ( ; try!=0;try--) | ||
4796 | { | ||
4797 | j=inb(CDi_status); | ||
4798 | if (!(j&s_not_data_ready)) break; | ||
4799 | if (!(j&s_not_result_ready)) break; | ||
4800 | if (fam0LV_drive) if (j&s_attention) break; | ||
4801 | } | ||
4802 | if (!(j&s_not_data_ready)) goto data_ready; | ||
4803 | if (try==0) | ||
4804 | { | ||
4805 | if (data_retrying == 0) data_waits++; | ||
4806 | data_retrying = 1; | ||
4807 | msg(DBG_000,"sbp_data: CDi_status loop: sleeping.\n"); | ||
4808 | sbp_sleep(1); | ||
4809 | try = 1; | ||
4810 | } | ||
4811 | } | ||
4812 | msg(DBG_INF,"sbp_data: CDi_status loop expired.\n"); | ||
4813 | data_ready: | ||
4814 | del_timer(&data_timer); | ||
4815 | |||
4816 | if (timed_out_data) | ||
4817 | { | ||
4818 | msg(DBG_INF,"sbp_data: CDi_status timeout (timed_out_data) (%02X).\n", j); | ||
4819 | error_flag++; | ||
4820 | } | ||
4821 | if (try==0) | ||
4822 | { | ||
4823 | msg(DBG_INF,"sbp_data: CDi_status timeout (try=0) (%02X).\n", j); | ||
4824 | error_flag++; | ||
4825 | } | ||
4826 | if (!(j&s_not_result_ready)) | ||
4827 | { | ||
4828 | msg(DBG_INF, "sbp_data: RESULT_READY where DATA_READY awaited (%02X).\n", j); | ||
4829 | response_count=20; | ||
4830 | j=ResponseInfo(); | ||
4831 | j=inb(CDi_status); | ||
4832 | } | ||
4833 | if (j&s_not_data_ready) | ||
4834 | { | ||
4835 | if ((current_drive->ored_ctl_adr&0x40)==0) | ||
4836 | msg(DBG_INF, "CD contains no data tracks.\n"); | ||
4837 | else msg(DBG_INF, "sbp_data: DATA_READY timeout (%02X).\n", j); | ||
4838 | error_flag++; | ||
4839 | } | ||
4840 | SBPCD_STI; | ||
4841 | if (error_flag) break; | ||
4842 | |||
4843 | msg(DBG_000, "sbp_data: beginning to read.\n"); | ||
4844 | p = current_drive->sbp_buf + frame * CD_FRAMESIZE; | ||
4845 | if (sbpro_type==1) OUT(CDo_sel_i_d,1); | ||
4846 | if (cmd_type==READ_M2) { | ||
4847 | if (do_16bit) insw(CDi_data, xa_head_buf, CD_XA_HEAD>>1); | ||
4848 | else insb(CDi_data, xa_head_buf, CD_XA_HEAD); | ||
4849 | } | ||
4850 | if (do_16bit) insw(CDi_data, p, CD_FRAMESIZE>>1); | ||
4851 | else insb(CDi_data, p, CD_FRAMESIZE); | ||
4852 | if (cmd_type==READ_M2) { | ||
4853 | if (do_16bit) insw(CDi_data, xa_tail_buf, CD_XA_TAIL>>1); | ||
4854 | else insb(CDi_data, xa_tail_buf, CD_XA_TAIL); | ||
4855 | } | ||
4856 | current_drive->sbp_current++; | ||
4857 | if (sbpro_type==1) OUT(CDo_sel_i_d,0); | ||
4858 | if (cmd_type==READ_M2) | ||
4859 | { | ||
4860 | for (xa_count=0;xa_count<CD_XA_HEAD;xa_count++) | ||
4861 | sprintf(&msgbuf[xa_count*3], " %02X", xa_head_buf[xa_count]); | ||
4862 | msgbuf[xa_count*3]=0; | ||
4863 | msg(DBG_XA1,"xa head:%s\n", msgbuf); | ||
4864 | } | ||
4865 | data_retrying = 0; | ||
4866 | data_tries++; | ||
4867 | if (data_tries >= 1000) | ||
4868 | { | ||
4869 | msg(DBG_INF,"sbp_data() statistics: %d waits in %d frames.\n", data_waits, data_tries); | ||
4870 | data_waits = data_tries = 0; | ||
4871 | } | ||
4872 | } | ||
4873 | duration=jiffies-duration; | ||
4874 | msg(DBG_TEA,"time to read %d frames: %d jiffies .\n",frame,duration); | ||
4875 | if (famT_drive) | ||
4876 | { | ||
4877 | wait=8; | ||
4878 | do | ||
4879 | { | ||
4880 | if (teac==2) | ||
4881 | { | ||
4882 | if ((i=CDi_stat_loop_T()) == -1) break; | ||
4883 | } | ||
4884 | else | ||
4885 | { | ||
4886 | sbp_sleep(1); | ||
4887 | OUT(CDo_sel_i_d,0); | ||
4888 | i=inb(CDi_status); | ||
4889 | } | ||
4890 | if (!(i&s_not_data_ready)) | ||
4891 | { | ||
4892 | OUT(CDo_sel_i_d,1); | ||
4893 | j=0; | ||
4894 | do | ||
4895 | { | ||
4896 | if (do_16bit) i=inw(CDi_data); | ||
4897 | else i=inb(CDi_data); | ||
4898 | j++; | ||
4899 | i=inb(CDi_status); | ||
4900 | } | ||
4901 | while (!(i&s_not_data_ready)); | ||
4902 | msg(DBG_TEA, "==========too much data (%d bytes/words)==============.\n", j); | ||
4903 | } | ||
4904 | if (!(i&s_not_result_ready)) | ||
4905 | { | ||
4906 | OUT(CDo_sel_i_d,0); | ||
4907 | l=0; | ||
4908 | do | ||
4909 | { | ||
4910 | infobuf[l++]=inb(CDi_info); | ||
4911 | i=inb(CDi_status); | ||
4912 | } | ||
4913 | while (!(i&s_not_result_ready)); | ||
4914 | if (infobuf[0]==0x00) success=1; | ||
4915 | #if 1 | ||
4916 | for (j=0;j<l;j++) sprintf(&msgbuf[j*3], " %02X", infobuf[j]); | ||
4917 | msgbuf[j*3]=0; | ||
4918 | msg(DBG_TEA,"sbp_data info response:%s\n", msgbuf); | ||
4919 | #endif | ||
4920 | if (infobuf[0]==0x02) | ||
4921 | { | ||
4922 | error_flag++; | ||
4923 | do | ||
4924 | { | ||
4925 | ++recursion; | ||
4926 | if (recursion>1) msg(DBG_TEA,"cmd_out_T READ_ERR recursion (sbp_data): %d !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n",recursion); | ||
4927 | else msg(DBG_TEA,"sbp_data: CMDT_READ_ERR necessary.\n"); | ||
4928 | clr_cmdbuf(); | ||
4929 | drvcmd[0]=CMDT_READ_ERR; | ||
4930 | j=cmd_out_T(); /* !!! recursive here !!! */ | ||
4931 | --recursion; | ||
4932 | sbp_sleep(1); | ||
4933 | } | ||
4934 | while (j<0); | ||
4935 | current_drive->error_state=infobuf[2]; | ||
4936 | current_drive->b3=infobuf[3]; | ||
4937 | current_drive->b4=infobuf[4]; | ||
4938 | } | ||
4939 | break; | ||
4940 | } | ||
4941 | else | ||
4942 | { | ||
4943 | #if 0 | ||
4944 | msg(DBG_TEA, "============= waiting for result=================.\n"); | ||
4945 | sbp_sleep(1); | ||
4946 | #endif | ||
4947 | } | ||
4948 | } | ||
4949 | while (wait--); | ||
4950 | } | ||
4951 | |||
4952 | if (error_flag) /* must have been spurious D_RDY or (ATTN&&!D_RDY) */ | ||
4953 | { | ||
4954 | msg(DBG_TEA, "================error flag: %d=================.\n", error_flag); | ||
4955 | msg(DBG_INF,"sbp_data: read aborted by drive.\n"); | ||
4956 | #if 1 | ||
4957 | i=cc_DriveReset(); /* ugly fix to prevent a hang */ | ||
4958 | #else | ||
4959 | i=cc_ReadError(); | ||
4960 | #endif | ||
4961 | return (0); | ||
4962 | } | ||
4963 | |||
4964 | if (fam0LV_drive) | ||
4965 | { | ||
4966 | SBPCD_CLI; | ||
4967 | i=maxtim_data; | ||
4968 | for (timeout=jiffies+HZ; time_before(jiffies, timeout); timeout--) | ||
4969 | { | ||
4970 | for ( ;i!=0;i--) | ||
4971 | { | ||
4972 | j=inb(CDi_status); | ||
4973 | if (!(j&s_not_data_ready)) break; | ||
4974 | if (!(j&s_not_result_ready)) break; | ||
4975 | if (j&s_attention) break; | ||
4976 | } | ||
4977 | if (i != 0 || time_after_eq(jiffies, timeout)) break; | ||
4978 | sbp_sleep(0); | ||
4979 | i = 1; | ||
4980 | } | ||
4981 | if (i==0) msg(DBG_INF,"status timeout after READ.\n"); | ||
4982 | if (!(j&s_attention)) | ||
4983 | { | ||
4984 | msg(DBG_INF,"sbp_data: timeout waiting DRV_ATTN - retrying.\n"); | ||
4985 | i=cc_DriveReset(); /* ugly fix to prevent a hang */ | ||
4986 | SBPCD_STI; | ||
4987 | return (0); | ||
4988 | } | ||
4989 | SBPCD_STI; | ||
4990 | } | ||
4991 | |||
4992 | #if 0 | ||
4993 | if (!success) | ||
4994 | #endif | ||
4995 | do | ||
4996 | { | ||
4997 | if (fam0LV_drive) cc_ReadStatus(); | ||
4998 | #if 1 | ||
4999 | if (famT_drive) msg(DBG_TEA, "================before ResponseStatus=================.\n", i); | ||
5000 | #endif | ||
5001 | i=ResponseStatus(); /* builds status_bits, returns orig. status (old) or faked p_success (new) */ | ||
5002 | #if 1 | ||
5003 | if (famT_drive) msg(DBG_TEA, "================ResponseStatus: %d=================.\n", i); | ||
5004 | #endif | ||
5005 | if (i<0) | ||
5006 | { | ||
5007 | msg(DBG_INF,"bad cc_ReadStatus after read: %02X\n", current_drive->status_bits); | ||
5008 | return (0); | ||
5009 | } | ||
5010 | } | ||
5011 | while ((fam0LV_drive)&&(!st_check)&&(!(i&p_success))); | ||
5012 | if (st_check) | ||
5013 | { | ||
5014 | i=cc_ReadError(); | ||
5015 | msg(DBG_INF,"cc_ReadError was necessary after read: %d\n",i); | ||
5016 | return (0); | ||
5017 | } | ||
5018 | if (fatal_err) | ||
5019 | { | ||
5020 | fatal_err=0; | ||
5021 | current_drive->sbp_first_frame=current_drive->sbp_last_frame=-1; /* purge buffer */ | ||
5022 | current_drive->sbp_current = 0; | ||
5023 | msg(DBG_INF,"sbp_data: fatal_err - retrying.\n"); | ||
5024 | return (0); | ||
5025 | } | ||
5026 | |||
5027 | current_drive->sbp_first_frame = req -> sector / 4; | ||
5028 | current_drive->sbp_last_frame = current_drive->sbp_first_frame + current_drive->sbp_read_frames - 1; | ||
5029 | sbp_transfer(req); | ||
5030 | return (1); | ||
5031 | } | ||
5032 | /*==========================================================================*/ | ||
5033 | |||
5034 | static int sbpcd_block_open(struct inode *inode, struct file *file) | ||
5035 | { | ||
5036 | struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data; | ||
5037 | return cdrom_open(p->sbpcd_infop, inode, file); | ||
5038 | } | ||
5039 | |||
5040 | static int sbpcd_block_release(struct inode *inode, struct file *file) | ||
5041 | { | ||
5042 | struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data; | ||
5043 | return cdrom_release(p->sbpcd_infop, file); | ||
5044 | } | ||
5045 | |||
5046 | static int sbpcd_block_ioctl(struct inode *inode, struct file *file, | ||
5047 | unsigned cmd, unsigned long arg) | ||
5048 | { | ||
5049 | struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data; | ||
5050 | struct cdrom_device_info *cdi = p->sbpcd_infop; | ||
5051 | int ret, i; | ||
5052 | |||
5053 | ret = cdrom_ioctl(file, p->sbpcd_infop, inode, cmd, arg); | ||
5054 | if (ret != -ENOSYS) | ||
5055 | return ret; | ||
5056 | |||
5057 | msg(DBG_IO2,"ioctl(%s, 0x%08lX, 0x%08lX)\n", cdi->name, cmd, arg); | ||
5058 | if (p->drv_id==-1) { | ||
5059 | msg(DBG_INF, "ioctl: bad device: %s\n", cdi->name); | ||
5060 | return (-ENXIO); /* no such drive */ | ||
5061 | } | ||
5062 | down(&ioctl_read_sem); | ||
5063 | if (p != current_drive) | ||
5064 | switch_drive(p); | ||
5065 | |||
5066 | msg(DBG_IO2,"ioctl: device %s, request %04X\n",cdi->name,cmd); | ||
5067 | switch (cmd) /* Sun-compatible */ | ||
5068 | { | ||
5069 | case DDIOCSDBG: /* DDI Debug */ | ||
5070 | if (!capable(CAP_SYS_ADMIN)) RETURN_UP(-EPERM); | ||
5071 | i=sbpcd_dbg_ioctl(arg,1); | ||
5072 | RETURN_UP(i); | ||
5073 | case CDROMRESET: /* hard reset the drive */ | ||
5074 | msg(DBG_IOC,"ioctl: CDROMRESET entered.\n"); | ||
5075 | i=DriveReset(); | ||
5076 | current_drive->audio_state=0; | ||
5077 | RETURN_UP(i); | ||
5078 | |||
5079 | case CDROMREADMODE1: | ||
5080 | msg(DBG_IOC,"ioctl: CDROMREADMODE1 requested.\n"); | ||
5081 | #ifdef SAFE_MIXED | ||
5082 | if (current_drive->has_data>1) RETURN_UP(-EBUSY); | ||
5083 | #endif /* SAFE_MIXED */ | ||
5084 | cc_ModeSelect(CD_FRAMESIZE); | ||
5085 | cc_ModeSense(); | ||
5086 | current_drive->mode=READ_M1; | ||
5087 | RETURN_UP(0); | ||
5088 | |||
5089 | case CDROMREADMODE2: /* not usable at the moment */ | ||
5090 | msg(DBG_IOC,"ioctl: CDROMREADMODE2 requested.\n"); | ||
5091 | #ifdef SAFE_MIXED | ||
5092 | if (current_drive->has_data>1) RETURN_UP(-EBUSY); | ||
5093 | #endif /* SAFE_MIXED */ | ||
5094 | cc_ModeSelect(CD_FRAMESIZE_RAW1); | ||
5095 | cc_ModeSense(); | ||
5096 | current_drive->mode=READ_M2; | ||
5097 | RETURN_UP(0); | ||
5098 | |||
5099 | case CDROMAUDIOBUFSIZ: /* configure the audio buffer size */ | ||
5100 | msg(DBG_IOC,"ioctl: CDROMAUDIOBUFSIZ entered.\n"); | ||
5101 | if (current_drive->sbp_audsiz>0) | ||
5102 | vfree(current_drive->aud_buf); | ||
5103 | current_drive->aud_buf=NULL; | ||
5104 | current_drive->sbp_audsiz=arg; | ||
5105 | |||
5106 | if (current_drive->sbp_audsiz>16) | ||
5107 | { | ||
5108 | current_drive->sbp_audsiz = 0; | ||
5109 | RETURN_UP(current_drive->sbp_audsiz); | ||
5110 | } | ||
5111 | |||
5112 | if (current_drive->sbp_audsiz>0) | ||
5113 | { | ||
5114 | current_drive->aud_buf=(u_char *) vmalloc(current_drive->sbp_audsiz*CD_FRAMESIZE_RAW); | ||
5115 | if (current_drive->aud_buf==NULL) | ||
5116 | { | ||
5117 | msg(DBG_INF,"audio buffer (%d frames) not available.\n",current_drive->sbp_audsiz); | ||
5118 | current_drive->sbp_audsiz=0; | ||
5119 | } | ||
5120 | else msg(DBG_INF,"audio buffer size: %d frames.\n",current_drive->sbp_audsiz); | ||
5121 | } | ||
5122 | RETURN_UP(current_drive->sbp_audsiz); | ||
5123 | |||
5124 | case CDROMREADAUDIO: | ||
5125 | { /* start of CDROMREADAUDIO */ | ||
5126 | int i=0, j=0, frame, block=0; | ||
5127 | u_int try=0; | ||
5128 | u_long timeout; | ||
5129 | u_char *p; | ||
5130 | u_int data_tries = 0; | ||
5131 | u_int data_waits = 0; | ||
5132 | u_int data_retrying = 0; | ||
5133 | int status_tries; | ||
5134 | int error_flag; | ||
5135 | |||
5136 | msg(DBG_IOC,"ioctl: CDROMREADAUDIO entered.\n"); | ||
5137 | if (fam0_drive) RETURN_UP(-EINVAL); | ||
5138 | if (famL_drive) RETURN_UP(-EINVAL); | ||
5139 | if (famV_drive) RETURN_UP(-EINVAL); | ||
5140 | if (famT_drive) RETURN_UP(-EINVAL); | ||
5141 | #ifdef SAFE_MIXED | ||
5142 | if (current_drive->has_data>1) RETURN_UP(-EBUSY); | ||
5143 | #endif /* SAFE_MIXED */ | ||
5144 | if (current_drive->aud_buf==NULL) RETURN_UP(-EINVAL); | ||
5145 | if (copy_from_user(&read_audio, (void __user *)arg, | ||
5146 | sizeof(struct cdrom_read_audio))) | ||
5147 | RETURN_UP(-EFAULT); | ||
5148 | if (read_audio.nframes < 0 || read_audio.nframes>current_drive->sbp_audsiz) RETURN_UP(-EINVAL); | ||
5149 | if (!access_ok(VERIFY_WRITE, read_audio.buf, | ||
5150 | read_audio.nframes*CD_FRAMESIZE_RAW)) | ||
5151 | RETURN_UP(-EFAULT); | ||
5152 | |||
5153 | if (read_audio.addr_format==CDROM_MSF) /* MSF-bin specification of where to start */ | ||
5154 | block=msf2lba(&read_audio.addr.msf.minute); | ||
5155 | else if (read_audio.addr_format==CDROM_LBA) /* lba specification of where to start */ | ||
5156 | block=read_audio.addr.lba; | ||
5157 | else RETURN_UP(-EINVAL); | ||
5158 | #if 000 | ||
5159 | i=cc_SetSpeed(speed_150,0,0); | ||
5160 | if (i) msg(DBG_AUD,"read_audio: SetSpeed error %d\n", i); | ||
5161 | #endif | ||
5162 | msg(DBG_AUD,"read_audio: lba: %d, msf: %06X\n", | ||
5163 | block, blk2msf(block)); | ||
5164 | msg(DBG_AUD,"read_audio: before cc_ReadStatus.\n"); | ||
5165 | #if OLD_BUSY | ||
5166 | while (busy_data) sbp_sleep(HZ/10); /* wait a bit */ | ||
5167 | busy_audio=1; | ||
5168 | #endif /* OLD_BUSY */ | ||
5169 | error_flag=0; | ||
5170 | for (data_tries=5; data_tries>0; data_tries--) | ||
5171 | { | ||
5172 | msg(DBG_AUD,"data_tries=%d ...\n", data_tries); | ||
5173 | current_drive->mode=READ_AU; | ||
5174 | cc_ModeSelect(CD_FRAMESIZE_RAW); | ||
5175 | cc_ModeSense(); | ||
5176 | for (status_tries=3; status_tries > 0; status_tries--) | ||
5177 | { | ||
5178 | flags_cmd_out |= f_respo3; | ||
5179 | cc_ReadStatus(); | ||
5180 | if (sbp_status() != 0) break; | ||
5181 | if (st_check) cc_ReadError(); | ||
5182 | sbp_sleep(1); /* wait a bit, try again */ | ||
5183 | } | ||
5184 | if (status_tries == 0) | ||
5185 | { | ||
5186 | msg(DBG_AUD,"read_audio: sbp_status: failed after 3 tries in line %d.\n", __LINE__); | ||
5187 | continue; | ||
5188 | } | ||
5189 | msg(DBG_AUD,"read_audio: sbp_status: ok.\n"); | ||
5190 | |||
5191 | flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus | f_obey_p_check; | ||
5192 | if (fam0L_drive) | ||
5193 | { | ||
5194 | flags_cmd_out |= f_lopsta | f_getsta | f_bit1; | ||
5195 | cmd_type=READ_M2; | ||
5196 | drvcmd[0]=CMD0_READ_XA; /* "read XA frames", old drives */ | ||
5197 | drvcmd[1]=(block>>16)&0x000000ff; | ||
5198 | drvcmd[2]=(block>>8)&0x000000ff; | ||
5199 | drvcmd[3]=block&0x000000ff; | ||
5200 | drvcmd[4]=0; | ||
5201 | drvcmd[5]=read_audio.nframes; /* # of frames */ | ||
5202 | drvcmd[6]=0; | ||
5203 | } | ||
5204 | else if (fam1_drive) | ||
5205 | { | ||
5206 | drvcmd[0]=CMD1_READ; /* "read frames", new drives */ | ||
5207 | lba2msf(block,&drvcmd[1]); /* msf-bin format required */ | ||
5208 | drvcmd[4]=0; | ||
5209 | drvcmd[5]=0; | ||
5210 | drvcmd[6]=read_audio.nframes; /* # of frames */ | ||
5211 | } | ||
5212 | else if (fam2_drive) | ||
5213 | { | ||
5214 | drvcmd[0]=CMD2_READ_XA2; | ||
5215 | lba2msf(block,&drvcmd[1]); /* msf-bin format required */ | ||
5216 | drvcmd[4]=0; | ||
5217 | drvcmd[5]=read_audio.nframes; /* # of frames */ | ||
5218 | drvcmd[6]=0x11; /* raw mode */ | ||
5219 | } | ||
5220 | else if (famT_drive) /* CD-55A: not tested yet */ | ||
5221 | { | ||
5222 | } | ||
5223 | msg(DBG_AUD,"read_audio: before giving \"read\" command.\n"); | ||
5224 | flags_cmd_out=f_putcmd; | ||
5225 | response_count=0; | ||
5226 | i=cmd_out(); | ||
5227 | if (i<0) msg(DBG_INF,"error giving READ AUDIO command: %0d\n", i); | ||
5228 | sbp_sleep(0); | ||
5229 | msg(DBG_AUD,"read_audio: after giving \"read\" command.\n"); | ||
5230 | for (frame=1;frame<2 && !error_flag; frame++) | ||
5231 | { | ||
5232 | try=maxtim_data; | ||
5233 | for (timeout=jiffies+9*HZ; ; ) | ||
5234 | { | ||
5235 | for ( ; try!=0;try--) | ||
5236 | { | ||
5237 | j=inb(CDi_status); | ||
5238 | if (!(j&s_not_data_ready)) break; | ||
5239 | if (!(j&s_not_result_ready)) break; | ||
5240 | if (fam0L_drive) if (j&s_attention) break; | ||
5241 | } | ||
5242 | if (try != 0 || time_after_eq(jiffies, timeout)) break; | ||
5243 | if (data_retrying == 0) data_waits++; | ||
5244 | data_retrying = 1; | ||
5245 | sbp_sleep(1); | ||
5246 | try = 1; | ||
5247 | } | ||
5248 | if (try==0) | ||
5249 | { | ||
5250 | msg(DBG_INF,"read_audio: sbp_data: CDi_status timeout.\n"); | ||
5251 | error_flag++; | ||
5252 | break; | ||
5253 | } | ||
5254 | msg(DBG_AUD,"read_audio: sbp_data: CDi_status ok.\n"); | ||
5255 | if (j&s_not_data_ready) | ||
5256 | { | ||
5257 | msg(DBG_INF, "read_audio: sbp_data: DATA_READY timeout.\n"); | ||
5258 | error_flag++; | ||
5259 | break; | ||
5260 | } | ||
5261 | msg(DBG_AUD,"read_audio: before reading data.\n"); | ||
5262 | error_flag=0; | ||
5263 | p = current_drive->aud_buf; | ||
5264 | if (sbpro_type==1) OUT(CDo_sel_i_d,1); | ||
5265 | if (do_16bit) | ||
5266 | { | ||
5267 | u_short *p2 = (u_short *) p; | ||
5268 | |||
5269 | for (; (u_char *) p2 < current_drive->aud_buf + read_audio.nframes*CD_FRAMESIZE_RAW;) | ||
5270 | { | ||
5271 | if ((inb_p(CDi_status)&s_not_data_ready)) continue; | ||
5272 | |||
5273 | /* get one sample */ | ||
5274 | *p2++ = inw_p(CDi_data); | ||
5275 | *p2++ = inw_p(CDi_data); | ||
5276 | } | ||
5277 | } else { | ||
5278 | for (; p < current_drive->aud_buf + read_audio.nframes*CD_FRAMESIZE_RAW;) | ||
5279 | { | ||
5280 | if ((inb_p(CDi_status)&s_not_data_ready)) continue; | ||
5281 | |||
5282 | /* get one sample */ | ||
5283 | *p++ = inb_p(CDi_data); | ||
5284 | *p++ = inb_p(CDi_data); | ||
5285 | *p++ = inb_p(CDi_data); | ||
5286 | *p++ = inb_p(CDi_data); | ||
5287 | } | ||
5288 | } | ||
5289 | if (sbpro_type==1) OUT(CDo_sel_i_d,0); | ||
5290 | data_retrying = 0; | ||
5291 | } | ||
5292 | msg(DBG_AUD,"read_audio: after reading data.\n"); | ||
5293 | if (error_flag) /* must have been spurious D_RDY or (ATTN&&!D_RDY) */ | ||
5294 | { | ||
5295 | msg(DBG_AUD,"read_audio: read aborted by drive\n"); | ||
5296 | #if 0000 | ||
5297 | i=cc_DriveReset(); /* ugly fix to prevent a hang */ | ||
5298 | #else | ||
5299 | i=cc_ReadError(); | ||
5300 | #endif | ||
5301 | continue; | ||
5302 | } | ||
5303 | if (fam0L_drive) | ||
5304 | { | ||
5305 | i=maxtim_data; | ||
5306 | for (timeout=jiffies+9*HZ; time_before(jiffies, timeout); timeout--) | ||
5307 | { | ||
5308 | for ( ;i!=0;i--) | ||
5309 | { | ||
5310 | j=inb(CDi_status); | ||
5311 | if (!(j&s_not_data_ready)) break; | ||
5312 | if (!(j&s_not_result_ready)) break; | ||
5313 | if (j&s_attention) break; | ||
5314 | } | ||
5315 | if (i != 0 || time_after_eq(jiffies, timeout)) break; | ||
5316 | sbp_sleep(0); | ||
5317 | i = 1; | ||
5318 | } | ||
5319 | if (i==0) msg(DBG_AUD,"read_audio: STATUS TIMEOUT AFTER READ"); | ||
5320 | if (!(j&s_attention)) | ||
5321 | { | ||
5322 | msg(DBG_AUD,"read_audio: sbp_data: timeout waiting DRV_ATTN - retrying\n"); | ||
5323 | i=cc_DriveReset(); /* ugly fix to prevent a hang */ | ||
5324 | continue; | ||
5325 | } | ||
5326 | } | ||
5327 | do | ||
5328 | { | ||
5329 | if (fam0L_drive) cc_ReadStatus(); | ||
5330 | i=ResponseStatus(); /* builds status_bits, returns orig. status (old) or faked p_success (new) */ | ||
5331 | if (i<0) { msg(DBG_AUD, | ||
5332 | "read_audio: cc_ReadStatus error after read: %02X\n", | ||
5333 | current_drive->status_bits); | ||
5334 | continue; /* FIXME */ | ||
5335 | } | ||
5336 | } | ||
5337 | while ((fam0L_drive)&&(!st_check)&&(!(i&p_success))); | ||
5338 | if (st_check) | ||
5339 | { | ||
5340 | i=cc_ReadError(); | ||
5341 | msg(DBG_AUD,"read_audio: cc_ReadError was necessary after read: %02X\n",i); | ||
5342 | continue; | ||
5343 | } | ||
5344 | if (copy_to_user(read_audio.buf, | ||
5345 | current_drive->aud_buf, | ||
5346 | read_audio.nframes * CD_FRAMESIZE_RAW)) | ||
5347 | RETURN_UP(-EFAULT); | ||
5348 | msg(DBG_AUD,"read_audio: copy_to_user done.\n"); | ||
5349 | break; | ||
5350 | } | ||
5351 | cc_ModeSelect(CD_FRAMESIZE); | ||
5352 | cc_ModeSense(); | ||
5353 | current_drive->mode=READ_M1; | ||
5354 | #if OLD_BUSY | ||
5355 | busy_audio=0; | ||
5356 | #endif /* OLD_BUSY */ | ||
5357 | if (data_tries == 0) | ||
5358 | { | ||
5359 | msg(DBG_AUD,"read_audio: failed after 5 tries in line %d.\n", __LINE__); | ||
5360 | RETURN_UP(-EIO); | ||
5361 | } | ||
5362 | msg(DBG_AUD,"read_audio: successful return.\n"); | ||
5363 | RETURN_UP(0); | ||
5364 | } /* end of CDROMREADAUDIO */ | ||
5365 | |||
5366 | default: | ||
5367 | msg(DBG_IOC,"ioctl: unknown function request %04X\n", cmd); | ||
5368 | RETURN_UP(-EINVAL); | ||
5369 | } /* end switch(cmd) */ | ||
5370 | } | ||
5371 | |||
5372 | static int sbpcd_block_media_changed(struct gendisk *disk) | ||
5373 | { | ||
5374 | struct sbpcd_drive *p = disk->private_data; | ||
5375 | return cdrom_media_changed(p->sbpcd_infop); | ||
5376 | } | ||
5377 | |||
5378 | static struct block_device_operations sbpcd_bdops = | ||
5379 | { | ||
5380 | .owner = THIS_MODULE, | ||
5381 | .open = sbpcd_block_open, | ||
5382 | .release = sbpcd_block_release, | ||
5383 | .ioctl = sbpcd_block_ioctl, | ||
5384 | .media_changed = sbpcd_block_media_changed, | ||
5385 | }; | ||
5386 | /*==========================================================================*/ | ||
5387 | /* | ||
5388 | * Open the device special file. Check that a disk is in. Read TOC. | ||
5389 | */ | ||
5390 | static int sbpcd_open(struct cdrom_device_info *cdi, int purpose) | ||
5391 | { | ||
5392 | struct sbpcd_drive *p = cdi->handle; | ||
5393 | |||
5394 | down(&ioctl_read_sem); | ||
5395 | switch_drive(p); | ||
5396 | |||
5397 | /* | ||
5398 | * try to keep an "open" counter here and lock the door if 0->1. | ||
5399 | */ | ||
5400 | msg(DBG_LCK,"open_count: %d -> %d\n", | ||
5401 | current_drive->open_count,current_drive->open_count+1); | ||
5402 | if (++current_drive->open_count<=1) | ||
5403 | { | ||
5404 | int i; | ||
5405 | i=LockDoor(); | ||
5406 | current_drive->open_count=1; | ||
5407 | if (famT_drive) msg(DBG_TEA,"sbpcd_open: before i=DiskInfo();.\n"); | ||
5408 | i=DiskInfo(); | ||
5409 | if (famT_drive) msg(DBG_TEA,"sbpcd_open: after i=DiskInfo();.\n"); | ||
5410 | if ((current_drive->ored_ctl_adr&0x40)==0) | ||
5411 | { | ||
5412 | msg(DBG_INF,"CD contains no data tracks.\n"); | ||
5413 | #ifdef SAFE_MIXED | ||
5414 | current_drive->has_data=0; | ||
5415 | #endif /* SAFE_MIXED */ | ||
5416 | } | ||
5417 | #ifdef SAFE_MIXED | ||
5418 | else if (current_drive->has_data<1) current_drive->has_data=1; | ||
5419 | #endif /* SAFE_MIXED */ | ||
5420 | } | ||
5421 | if (!st_spinning) cc_SpinUp(); | ||
5422 | RETURN_UP(0); | ||
5423 | } | ||
5424 | /*==========================================================================*/ | ||
5425 | /* | ||
5426 | * On close, we flush all sbp blocks from the buffer cache. | ||
5427 | */ | ||
5428 | static void sbpcd_release(struct cdrom_device_info * cdi) | ||
5429 | { | ||
5430 | struct sbpcd_drive *p = cdi->handle; | ||
5431 | |||
5432 | if (p->drv_id==-1) { | ||
5433 | msg(DBG_INF, "release: bad device: %s\n", cdi->name); | ||
5434 | return; | ||
5435 | } | ||
5436 | down(&ioctl_read_sem); | ||
5437 | switch_drive(p); | ||
5438 | /* | ||
5439 | * try to keep an "open" counter here and unlock the door if 1->0. | ||
5440 | */ | ||
5441 | msg(DBG_LCK,"open_count: %d -> %d\n", | ||
5442 | p->open_count,p->open_count-1); | ||
5443 | if (p->open_count>-2) /* CDROMEJECT may have been done */ | ||
5444 | { | ||
5445 | if (--p->open_count<=0) | ||
5446 | { | ||
5447 | p->sbp_first_frame=p->sbp_last_frame=-1; | ||
5448 | if (p->audio_state!=audio_playing) | ||
5449 | if (p->f_eject) cc_SpinDown(); | ||
5450 | p->diskstate_flags &= ~cd_size_bit; | ||
5451 | p->open_count=0; | ||
5452 | #ifdef SAFE_MIXED | ||
5453 | p->has_data=0; | ||
5454 | #endif /* SAFE_MIXED */ | ||
5455 | } | ||
5456 | } | ||
5457 | up(&ioctl_read_sem); | ||
5458 | return ; | ||
5459 | } | ||
5460 | /*==========================================================================*/ | ||
5461 | /* | ||
5462 | * | ||
5463 | */ | ||
5464 | static int sbpcd_media_changed( struct cdrom_device_info *cdi, int disc_nr); | ||
5465 | static struct cdrom_device_ops sbpcd_dops = { | ||
5466 | .open = sbpcd_open, | ||
5467 | .release = sbpcd_release, | ||
5468 | .drive_status = sbpcd_drive_status, | ||
5469 | .media_changed = sbpcd_media_changed, | ||
5470 | .tray_move = sbpcd_tray_move, | ||
5471 | .lock_door = sbpcd_lock_door, | ||
5472 | .select_speed = sbpcd_select_speed, | ||
5473 | .get_last_session = sbpcd_get_last_session, | ||
5474 | .get_mcn = sbpcd_get_mcn, | ||
5475 | .reset = sbpcd_reset, | ||
5476 | .audio_ioctl = sbpcd_audio_ioctl, | ||
5477 | .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | | ||
5478 | CDC_MULTI_SESSION | CDC_MEDIA_CHANGED | | ||
5479 | CDC_MCN | CDC_PLAY_AUDIO, | ||
5480 | .n_minors = 1, | ||
5481 | }; | ||
5482 | |||
5483 | /*==========================================================================*/ | ||
5484 | /* | ||
5485 | * accept "kernel command line" parameters | ||
5486 | * (suggested by Peter MacDonald with SLS 1.03) | ||
5487 | * | ||
5488 | * This is only implemented for the first controller. Should be enough to | ||
5489 | * allow installing with a "strange" distribution kernel. | ||
5490 | * | ||
5491 | * use: tell LILO: | ||
5492 | * sbpcd=0x230,SoundBlaster | ||
5493 | * or | ||
5494 | * sbpcd=0x300,LaserMate | ||
5495 | * or | ||
5496 | * sbpcd=0x338,SoundScape | ||
5497 | * or | ||
5498 | * sbpcd=0x2C0,Teac16bit | ||
5499 | * | ||
5500 | * (upper/lower case sensitive here - but all-lowercase is ok!!!). | ||
5501 | * | ||
5502 | * the address value has to be the CDROM PORT ADDRESS - | ||
5503 | * not the soundcard base address. | ||
5504 | * For the SPEA/SoundScape setup, DO NOT specify the "configuration port" | ||
5505 | * address, but the address which is really used for the CDROM (usually 8 | ||
5506 | * bytes above). | ||
5507 | * | ||
5508 | */ | ||
5509 | |||
5510 | int sbpcd_setup(char *s) | ||
5511 | { | ||
5512 | #ifndef MODULE | ||
5513 | int p[4]; | ||
5514 | (void)get_options(s, ARRAY_SIZE(p), p); | ||
5515 | setup_done++; | ||
5516 | msg(DBG_INI,"sbpcd_setup called with %04X,%s\n",p[1], s); | ||
5517 | sbpro_type=0; /* default: "LaserMate" */ | ||
5518 | if (p[0]>1) sbpro_type=p[2]; | ||
5519 | else if (!strcmp(s,str_sb)) sbpro_type=1; | ||
5520 | else if (!strcmp(s,str_sb_l)) sbpro_type=1; | ||
5521 | else if (!strcmp(s,str_sp)) sbpro_type=2; | ||
5522 | else if (!strcmp(s,str_sp_l)) sbpro_type=2; | ||
5523 | else if (!strcmp(s,str_ss)) sbpro_type=2; | ||
5524 | else if (!strcmp(s,str_ss_l)) sbpro_type=2; | ||
5525 | else if (!strcmp(s,str_t16)) sbpro_type=3; | ||
5526 | else if (!strcmp(s,str_t16_l)) sbpro_type=3; | ||
5527 | if (p[0]>0) sbpcd_ioaddr=p[1]; | ||
5528 | if (p[0]>2) max_drives=p[3]; | ||
5529 | #else | ||
5530 | sbpcd_ioaddr = sbpcd[0]; | ||
5531 | sbpro_type = sbpcd[1]; | ||
5532 | #endif | ||
5533 | |||
5534 | CDo_command=sbpcd_ioaddr; | ||
5535 | CDi_info=sbpcd_ioaddr; | ||
5536 | CDi_status=sbpcd_ioaddr+1; | ||
5537 | CDo_sel_i_d=sbpcd_ioaddr+1; | ||
5538 | CDo_reset=sbpcd_ioaddr+2; | ||
5539 | CDo_enable=sbpcd_ioaddr+3; | ||
5540 | f_16bit=0; | ||
5541 | if ((sbpro_type==1)||(sbpro_type==3)) | ||
5542 | { | ||
5543 | CDi_data=sbpcd_ioaddr; | ||
5544 | if (sbpro_type==3) | ||
5545 | { | ||
5546 | f_16bit=1; | ||
5547 | sbpro_type=1; | ||
5548 | } | ||
5549 | } | ||
5550 | else CDi_data=sbpcd_ioaddr+2; | ||
5551 | |||
5552 | return 1; | ||
5553 | } | ||
5554 | |||
5555 | __setup("sbpcd=", sbpcd_setup); | ||
5556 | |||
5557 | |||
5558 | /*==========================================================================*/ | ||
5559 | /* | ||
5560 | * Sequoia S-1000 CD-ROM Interface Configuration | ||
5561 | * as used within SPEA Media FX, Ensonic SoundScape and some Reveal cards | ||
5562 | * The soundcard has to get jumpered for the interface type "Panasonic" | ||
5563 | * (not Sony or Mitsumi) and to get soft-configured for | ||
5564 | * -> configuration port address | ||
5565 | * -> CDROM port offset (num_ports): has to be 8 here. Possibly this | ||
5566 | * offset value determines the interface type (none, Panasonic, | ||
5567 | * Mitsumi, Sony). | ||
5568 | * The interface uses a configuration port (0x320, 0x330, 0x340, 0x350) | ||
5569 | * some bytes below the real CDROM address. | ||
5570 | * | ||
5571 | * For the Panasonic style (LaserMate) interface and the configuration | ||
5572 | * port 0x330, we have to use an offset of 8; so, the real CDROM port | ||
5573 | * address is 0x338. | ||
5574 | */ | ||
5575 | static int __init config_spea(void) | ||
5576 | { | ||
5577 | /* | ||
5578 | * base address offset between configuration port and CDROM port, | ||
5579 | * this probably defines the interface type | ||
5580 | * 2 (type=??): 0x00 | ||
5581 | * 8 (type=LaserMate):0x10 | ||
5582 | * 16 (type=??):0x20 | ||
5583 | * 32 (type=??):0x30 | ||
5584 | */ | ||
5585 | int n_ports=0x10; | ||
5586 | |||
5587 | int irq_number=0; /* off:0x00, 2/9:0x01, 7:0x03, 12:0x05, 15:0x07 */ | ||
5588 | int dma_channel=0; /* off: 0x00, 0:0x08, 1:0x18, 3:0x38, 5:0x58, 6:0x68 */ | ||
5589 | int dack_polarity=0; /* L:0x00, H:0x80 */ | ||
5590 | int drq_polarity=0x40; /* L:0x00, H:0x40 */ | ||
5591 | int i; | ||
5592 | |||
5593 | #define SPEA_REG_1 sbpcd_ioaddr-0x08+4 | ||
5594 | #define SPEA_REG_2 sbpcd_ioaddr-0x08+5 | ||
5595 | |||
5596 | OUT(SPEA_REG_1,0xFF); | ||
5597 | i=inb(SPEA_REG_1); | ||
5598 | if (i!=0x0F) | ||
5599 | { | ||
5600 | msg(DBG_SEQ,"no SPEA interface at %04X present.\n", sbpcd_ioaddr); | ||
5601 | return (-1); /* no interface found */ | ||
5602 | } | ||
5603 | OUT(SPEA_REG_1,0x04); | ||
5604 | OUT(SPEA_REG_2,0xC0); | ||
5605 | |||
5606 | OUT(SPEA_REG_1,0x05); | ||
5607 | OUT(SPEA_REG_2,0x10|drq_polarity|dack_polarity); | ||
5608 | |||
5609 | #if 1 | ||
5610 | #define SPEA_PATTERN 0x80 | ||
5611 | #else | ||
5612 | #define SPEA_PATTERN 0x00 | ||
5613 | #endif | ||
5614 | OUT(SPEA_REG_1,0x06); | ||
5615 | OUT(SPEA_REG_2,dma_channel|irq_number|SPEA_PATTERN); | ||
5616 | OUT(SPEA_REG_2,dma_channel|irq_number|SPEA_PATTERN); | ||
5617 | |||
5618 | OUT(SPEA_REG_1,0x09); | ||
5619 | i=(inb(SPEA_REG_2)&0xCF)|n_ports; | ||
5620 | OUT(SPEA_REG_2,i); | ||
5621 | |||
5622 | sbpro_type = 0; /* acts like a LaserMate interface now */ | ||
5623 | msg(DBG_SEQ,"found SoundScape interface at %04X.\n", sbpcd_ioaddr); | ||
5624 | return (0); | ||
5625 | } | ||
5626 | |||
5627 | /*==========================================================================*/ | ||
5628 | /* | ||
5629 | * Test for presence of drive and initialize it. | ||
5630 | * Called once at boot or load time. | ||
5631 | */ | ||
5632 | |||
5633 | /* FIXME: cleanups after failed allocations are too ugly for words */ | ||
5634 | #ifdef MODULE | ||
5635 | int __init __sbpcd_init(void) | ||
5636 | #else | ||
5637 | int __init sbpcd_init(void) | ||
5638 | #endif | ||
5639 | { | ||
5640 | int i=0, j=0; | ||
5641 | int addr[2]={1, CDROM_PORT}; | ||
5642 | int port_index; | ||
5643 | |||
5644 | sti(); | ||
5645 | |||
5646 | msg(DBG_INF,"sbpcd.c %s\n", VERSION); | ||
5647 | #ifndef MODULE | ||
5648 | #if DISTRIBUTION | ||
5649 | if (!setup_done) | ||
5650 | { | ||
5651 | msg(DBG_INF,"Looking for Matsushita/Panasonic, CreativeLabs, Longshine, TEAC CD-ROM drives\n"); | ||
5652 | msg(DBG_INF,"= = = = = = = = = = W A R N I N G = = = = = = = = = =\n"); | ||
5653 | msg(DBG_INF,"Auto-Probing can cause a hang (f.e. touching an NE2000 card).\n"); | ||
5654 | msg(DBG_INF,"If that happens, you have to reboot and use the\n"); | ||
5655 | msg(DBG_INF,"LILO (kernel) command line feature like:\n"); | ||
5656 | msg(DBG_INF," LILO boot: ... sbpcd=0x230,SoundBlaster\n"); | ||
5657 | msg(DBG_INF,"or like:\n"); | ||
5658 | msg(DBG_INF," LILO boot: ... sbpcd=0x300,LaserMate\n"); | ||
5659 | msg(DBG_INF,"or like:\n"); | ||
5660 | msg(DBG_INF," LILO boot: ... sbpcd=0x338,SoundScape\n"); | ||
5661 | msg(DBG_INF,"with your REAL address.\n"); | ||
5662 | msg(DBG_INF,"= = = = = = = = = = END of WARNING = = = = = == = = =\n"); | ||
5663 | } | ||
5664 | #endif /* DISTRIBUTION */ | ||
5665 | sbpcd[0]=sbpcd_ioaddr; /* possibly changed by kernel command line */ | ||
5666 | sbpcd[1]=sbpro_type; /* possibly changed by kernel command line */ | ||
5667 | #endif /* MODULE */ | ||
5668 | |||
5669 | for (port_index=0;port_index<NUM_PROBE;port_index+=2) | ||
5670 | { | ||
5671 | addr[1]=sbpcd[port_index]; | ||
5672 | if (addr[1]==0) break; | ||
5673 | if (check_region(addr[1],4)) | ||
5674 | { | ||
5675 | msg(DBG_INF,"check_region: %03X is not free.\n",addr[1]); | ||
5676 | continue; | ||
5677 | } | ||
5678 | if (sbpcd[port_index+1]==2) type=str_sp; | ||
5679 | else if (sbpcd[port_index+1]==1) type=str_sb; | ||
5680 | else if (sbpcd[port_index+1]==3) type=str_t16; | ||
5681 | else type=str_lm; | ||
5682 | sbpcd_setup((char *)type); | ||
5683 | #if DISTRIBUTION | ||
5684 | msg(DBG_INF,"Scanning 0x%X (%s)...\n", CDo_command, type); | ||
5685 | #endif /* DISTRIBUTION */ | ||
5686 | if (sbpcd[port_index+1]==2) | ||
5687 | { | ||
5688 | i=config_spea(); | ||
5689 | if (i<0) continue; | ||
5690 | } | ||
5691 | #ifdef PATH_CHECK | ||
5692 | if (check_card(addr[1])) continue; | ||
5693 | #endif /* PATH_CHECK */ | ||
5694 | i=check_drives(); | ||
5695 | msg(DBG_INI,"check_drives done.\n"); | ||
5696 | if (i>=0) break; /* drive found */ | ||
5697 | } /* end of cycling through the set of possible I/O port addresses */ | ||
5698 | |||
5699 | if (ndrives==0) | ||
5700 | { | ||
5701 | msg(DBG_INF, "No drive found.\n"); | ||
5702 | #ifdef MODULE | ||
5703 | return -EIO; | ||
5704 | #else | ||
5705 | goto init_done; | ||
5706 | #endif /* MODULE */ | ||
5707 | } | ||
5708 | |||
5709 | if (port_index>0) | ||
5710 | { | ||
5711 | msg(DBG_INF, "You should read Documentation/cdrom/sbpcd\n"); | ||
5712 | msg(DBG_INF, "and then configure sbpcd.h for your hardware.\n"); | ||
5713 | } | ||
5714 | check_datarate(); | ||
5715 | msg(DBG_INI,"check_datarate done.\n"); | ||
5716 | |||
5717 | for (j=0;j<NR_SBPCD;j++) | ||
5718 | { | ||
5719 | struct sbpcd_drive *p = D_S + j; | ||
5720 | if (p->drv_id==-1) | ||
5721 | continue; | ||
5722 | switch_drive(p); | ||
5723 | #if 1 | ||
5724 | if (!famL_drive) cc_DriveReset(); | ||
5725 | #endif | ||
5726 | if (!st_spinning) cc_SpinUp(); | ||
5727 | p->sbp_first_frame = -1; /* First frame in buffer */ | ||
5728 | p->sbp_last_frame = -1; /* Last frame in buffer */ | ||
5729 | p->sbp_read_frames = 0; /* Number of frames being read to buffer */ | ||
5730 | p->sbp_current = 0; /* Frame being currently read */ | ||
5731 | p->CD_changed=1; | ||
5732 | p->frame_size=CD_FRAMESIZE; | ||
5733 | p->f_eject=0; | ||
5734 | #if EJECT | ||
5735 | if (!fam0_drive) p->f_eject=1; | ||
5736 | #endif /* EJECT */ | ||
5737 | cc_ReadStatus(); | ||
5738 | i=ResponseStatus(); /* returns orig. status or p_busy_new */ | ||
5739 | if (famT_drive) i=ResponseStatus(); /* returns orig. status or p_busy_new */ | ||
5740 | if (i<0) | ||
5741 | { | ||
5742 | if (i!=-402) | ||
5743 | msg(DBG_INF,"init: ResponseStatus returns %d.\n",i); | ||
5744 | } | ||
5745 | else | ||
5746 | { | ||
5747 | if (st_check) | ||
5748 | { | ||
5749 | i=cc_ReadError(); | ||
5750 | msg(DBG_INI,"init: cc_ReadError returns %d\n",i); | ||
5751 | } | ||
5752 | } | ||
5753 | msg(DBG_INI,"init: first GetStatus: %d\n",i); | ||
5754 | msg(DBG_LCS,"init: first GetStatus: error_byte=%d\n", | ||
5755 | p->error_byte); | ||
5756 | if (p->error_byte==aud_12) | ||
5757 | { | ||
5758 | timeout=jiffies+2*HZ; | ||
5759 | do | ||
5760 | { | ||
5761 | i=GetStatus(); | ||
5762 | msg(DBG_INI,"init: second GetStatus: %02X\n",i); | ||
5763 | msg(DBG_LCS, | ||
5764 | "init: second GetStatus: error_byte=%d\n", | ||
5765 | p->error_byte); | ||
5766 | if (i<0) break; | ||
5767 | if (!st_caddy_in) break; | ||
5768 | } | ||
5769 | while ((!st_diskok)||time_after(jiffies, timeout)); | ||
5770 | } | ||
5771 | i=SetSpeed(); | ||
5772 | if (i>=0) p->CD_changed=1; | ||
5773 | } | ||
5774 | |||
5775 | if (!request_region(CDo_command,4,major_name)) | ||
5776 | { | ||
5777 | printk(KERN_WARNING "sbpcd: Unable to request region 0x%x\n", CDo_command); | ||
5778 | return -EIO; | ||
5779 | } | ||
5780 | |||
5781 | /* | ||
5782 | * Turn on the CD audio channels. | ||
5783 | * The addresses are obtained from SOUND_BASE (see sbpcd.h). | ||
5784 | */ | ||
5785 | #if SOUND_BASE | ||
5786 | OUT(MIXER_addr,MIXER_CD_Volume); /* select SB Pro mixer register */ | ||
5787 | OUT(MIXER_data,0xCC); /* one nibble per channel, max. value: 0xFF */ | ||
5788 | #endif /* SOUND_BASE */ | ||
5789 | |||
5790 | if (register_blkdev(MAJOR_NR, major_name)) { | ||
5791 | #ifdef MODULE | ||
5792 | return -EIO; | ||
5793 | #else | ||
5794 | goto init_done; | ||
5795 | #endif /* MODULE */ | ||
5796 | } | ||
5797 | |||
5798 | /* | ||
5799 | * init error handling is broken beyond belief in this driver... | ||
5800 | */ | ||
5801 | sbpcd_queue = blk_init_queue(do_sbpcd_request, &sbpcd_lock); | ||
5802 | if (!sbpcd_queue) { | ||
5803 | release_region(CDo_command,4); | ||
5804 | unregister_blkdev(MAJOR_NR, major_name); | ||
5805 | return -ENOMEM; | ||
5806 | } | ||
5807 | |||
5808 | for (j=0;j<NR_SBPCD;j++) | ||
5809 | { | ||
5810 | struct cdrom_device_info * sbpcd_infop; | ||
5811 | struct gendisk *disk; | ||
5812 | struct sbpcd_drive *p = D_S + j; | ||
5813 | |||
5814 | if (p->drv_id==-1) continue; | ||
5815 | switch_drive(p); | ||
5816 | #ifdef SAFE_MIXED | ||
5817 | p->has_data=0; | ||
5818 | #endif /* SAFE_MIXED */ | ||
5819 | /* | ||
5820 | * allocate memory for the frame buffers | ||
5821 | */ | ||
5822 | p->aud_buf=NULL; | ||
5823 | p->sbp_audsiz=0; | ||
5824 | p->sbp_bufsiz=buffers; | ||
5825 | if (p->drv_type&drv_fam1) | ||
5826 | if (READ_AUDIO>0) | ||
5827 | p->sbp_audsiz = READ_AUDIO; | ||
5828 | p->sbp_buf=(u_char *) vmalloc(buffers*CD_FRAMESIZE); | ||
5829 | if (!p->sbp_buf) { | ||
5830 | msg(DBG_INF,"data buffer (%d frames) not available.\n", | ||
5831 | buffers); | ||
5832 | if ((unregister_blkdev(MAJOR_NR, major_name) == -EINVAL)) | ||
5833 | { | ||
5834 | printk("Can't unregister %s\n", major_name); | ||
5835 | } | ||
5836 | release_region(CDo_command,4); | ||
5837 | blk_cleanup_queue(sbpcd_queue); | ||
5838 | return -EIO; | ||
5839 | } | ||
5840 | #ifdef MODULE | ||
5841 | msg(DBG_INF,"data buffer size: %d frames.\n",buffers); | ||
5842 | #endif /* MODULE */ | ||
5843 | if (p->sbp_audsiz>0) | ||
5844 | { | ||
5845 | p->aud_buf=(u_char *) vmalloc(p->sbp_audsiz*CD_FRAMESIZE_RAW); | ||
5846 | if (p->aud_buf==NULL) msg(DBG_INF,"audio buffer (%d frames) not available.\n",p->sbp_audsiz); | ||
5847 | else msg(DBG_INF,"audio buffer size: %d frames.\n",p->sbp_audsiz); | ||
5848 | } | ||
5849 | sbpcd_infop = vmalloc(sizeof (struct cdrom_device_info)); | ||
5850 | if (sbpcd_infop == NULL) | ||
5851 | { | ||
5852 | release_region(CDo_command,4); | ||
5853 | blk_cleanup_queue(sbpcd_queue); | ||
5854 | return -ENOMEM; | ||
5855 | } | ||
5856 | memset(sbpcd_infop, 0, sizeof(struct cdrom_device_info)); | ||
5857 | sbpcd_infop->ops = &sbpcd_dops; | ||
5858 | sbpcd_infop->speed = 2; | ||
5859 | sbpcd_infop->capacity = 1; | ||
5860 | sprintf(sbpcd_infop->name, "sbpcd%d", j); | ||
5861 | sbpcd_infop->handle = p; | ||
5862 | p->sbpcd_infop = sbpcd_infop; | ||
5863 | disk = alloc_disk(1); | ||
5864 | disk->major = MAJOR_NR; | ||
5865 | disk->first_minor = j; | ||
5866 | disk->fops = &sbpcd_bdops; | ||
5867 | strcpy(disk->disk_name, sbpcd_infop->name); | ||
5868 | disk->flags = GENHD_FL_CD; | ||
5869 | p->disk = disk; | ||
5870 | if (register_cdrom(sbpcd_infop)) | ||
5871 | { | ||
5872 | printk(" sbpcd: Unable to register with Uniform CD-ROm driver\n"); | ||
5873 | } | ||
5874 | disk->private_data = p; | ||
5875 | disk->queue = sbpcd_queue; | ||
5876 | add_disk(disk); | ||
5877 | } | ||
5878 | blk_queue_hardsect_size(sbpcd_queue, CD_FRAMESIZE); | ||
5879 | |||
5880 | #ifndef MODULE | ||
5881 | init_done: | ||
5882 | #endif | ||
5883 | return 0; | ||
5884 | } | ||
5885 | /*==========================================================================*/ | ||
5886 | #ifdef MODULE | ||
5887 | static void sbpcd_exit(void) | ||
5888 | { | ||
5889 | int j; | ||
5890 | |||
5891 | if ((unregister_blkdev(MAJOR_NR, major_name) == -EINVAL)) | ||
5892 | { | ||
5893 | msg(DBG_INF, "What's that: can't unregister %s.\n", major_name); | ||
5894 | return; | ||
5895 | } | ||
5896 | release_region(CDo_command,4); | ||
5897 | blk_cleanup_queue(sbpcd_queue); | ||
5898 | for (j=0;j<NR_SBPCD;j++) | ||
5899 | { | ||
5900 | if (D_S[j].drv_id==-1) continue; | ||
5901 | del_gendisk(D_S[j].disk); | ||
5902 | put_disk(D_S[j].disk); | ||
5903 | vfree(D_S[j].sbp_buf); | ||
5904 | if (D_S[j].sbp_audsiz>0) | ||
5905 | vfree(D_S[j].aud_buf); | ||
5906 | if ((unregister_cdrom(D_S[j].sbpcd_infop) == -EINVAL)) | ||
5907 | { | ||
5908 | msg(DBG_INF, "What's that: can't unregister info %s.\n", major_name); | ||
5909 | return; | ||
5910 | } | ||
5911 | vfree(D_S[j].sbpcd_infop); | ||
5912 | } | ||
5913 | msg(DBG_INF, "%s module released.\n", major_name); | ||
5914 | } | ||
5915 | |||
5916 | |||
5917 | module_init(__sbpcd_init) /*HACK!*/; | ||
5918 | module_exit(sbpcd_exit); | ||
5919 | |||
5920 | |||
5921 | #endif /* MODULE */ | ||
5922 | static int sbpcd_media_changed(struct cdrom_device_info *cdi, int disc_nr) | ||
5923 | { | ||
5924 | struct sbpcd_drive *p = cdi->handle; | ||
5925 | msg(DBG_CHK,"media_check (%s) called\n", cdi->name); | ||
5926 | |||
5927 | if (p->CD_changed==0xFF) | ||
5928 | { | ||
5929 | p->CD_changed=0; | ||
5930 | msg(DBG_CHK,"medium changed (drive %s)\n", cdi->name); | ||
5931 | current_drive->diskstate_flags &= ~toc_bit; | ||
5932 | /* we *don't* need invalidate here, it's done by caller */ | ||
5933 | current_drive->diskstate_flags &= ~cd_size_bit; | ||
5934 | #ifdef SAFE_MIXED | ||
5935 | current_drive->has_data=0; | ||
5936 | #endif /* SAFE_MIXED */ | ||
5937 | |||
5938 | return (1); | ||
5939 | } | ||
5940 | else | ||
5941 | return (0); | ||
5942 | } | ||
5943 | |||
5944 | MODULE_LICENSE("GPL"); | ||
5945 | /* FIXME: Old modules.conf claims MATSUSHITA_CDROM2_MAJOR and CDROM3, but | ||
5946 | AFAICT this doesn't support those majors, so why? --RR 30 Jul 2003 */ | ||
5947 | MODULE_ALIAS_BLOCKDEV_MAJOR(MATSUSHITA_CDROM_MAJOR); | ||
5948 | |||
5949 | /*==========================================================================*/ | ||
5950 | /* | ||
5951 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
5952 | * Emacs will notice this stuff at the end of the file and automatically | ||
5953 | * adjust the settings for this buffer only. This must remain at the end | ||
5954 | * of the file. | ||
5955 | * --------------------------------------------------------------------------- | ||
5956 | * Local variables: | ||
5957 | * c-indent-level: 8 | ||
5958 | * c-brace-imaginary-offset: 0 | ||
5959 | * c-brace-offset: -8 | ||
5960 | * c-argdecl-indent: 8 | ||
5961 | * c-label-offset: -8 | ||
5962 | * c-continued-statement-offset: 8 | ||
5963 | * c-continued-brace-offset: 0 | ||
5964 | * End: | ||
5965 | */ | ||
5966 | |||
diff --git a/drivers/cdrom/sbpcd.h b/drivers/cdrom/sbpcd.h deleted file mode 100644 index 2f2225f13c6f..000000000000 --- a/drivers/cdrom/sbpcd.h +++ /dev/null | |||
@@ -1,839 +0,0 @@ | |||
1 | /* | ||
2 | * sbpcd.h Specify interface address and interface type here. | ||
3 | */ | ||
4 | |||
5 | /* | ||
6 | * Attention! This file contains user-serviceable parts! | ||
7 | * I recommend to make use of it... | ||
8 | * If you feel helpless, look into Documentation/cdrom/sbpcd | ||
9 | * (good idea anyway, at least before mailing me). | ||
10 | * | ||
11 | * The definitions for the first controller can get overridden by | ||
12 | * the kernel command line ("lilo boot option"). | ||
13 | * Examples: | ||
14 | * sbpcd=0x300,LaserMate | ||
15 | * or | ||
16 | * sbpcd=0x230,SoundBlaster | ||
17 | * or | ||
18 | * sbpcd=0x338,SoundScape | ||
19 | * or | ||
20 | * sbpcd=0x2C0,Teac16bit | ||
21 | * | ||
22 | * If sbpcd gets used as a module, you can load it with | ||
23 | * insmod sbpcd.o sbpcd=0x300,0 | ||
24 | * or | ||
25 | * insmod sbpcd.o sbpcd=0x230,1 | ||
26 | * or | ||
27 | * insmod sbpcd.o sbpcd=0x338,2 | ||
28 | * or | ||
29 | * insmod sbpcd.o sbpcd=0x2C0,3 | ||
30 | * respective to override the configured address and type. | ||
31 | */ | ||
32 | |||
33 | /* | ||
34 | * define your CDROM port base address as CDROM_PORT | ||
35 | * and specify the type of your interface card as SBPRO. | ||
36 | * | ||
37 | * address: | ||
38 | * ======== | ||
39 | * SBPRO type addresses typically are 0x0230 (=0x220+0x10), 0x0250, ... | ||
40 | * LASERMATE type (CI-101P, WDH-7001C) addresses typically are 0x0300, ... | ||
41 | * SOUNDSCAPE addresses are from the LASERMATE type and range. You have to | ||
42 | * specify the REAL address here, not the configuration port address. Look | ||
43 | * at the CDROM driver's invoking line within your DOS CONFIG.SYS, or let | ||
44 | * sbpcd auto-probe, if you are not firm with the address. | ||
45 | * There are some soundcards on the market with 0x0630, 0x0650, ...; their | ||
46 | * type is not obvious (both types are possible). | ||
47 | * | ||
48 | * example: if your SBPRO audio address is 0x220, specify 0x230 and SBPRO 1. | ||
49 | * if your soundcard has its CDROM port above 0x300, specify | ||
50 | * that address and try SBPRO 0 first. | ||
51 | * if your SoundScape configuration port is at 0x330, specify | ||
52 | * 0x338 and SBPRO 2. | ||
53 | * | ||
54 | * interface type: | ||
55 | * =============== | ||
56 | * set SBPRO to 1 for "true" SoundBlaster card | ||
57 | * set SBPRO to 0 for "compatible" soundcards and | ||
58 | * for "poor" (no sound) interface cards. | ||
59 | * set SBPRO to 2 for Ensonic SoundScape or SPEA Media FX cards | ||
60 | * set SBPRO to 3 for Teac 16bit interface cards | ||
61 | * | ||
62 | * Almost all "compatible" sound boards need to set SBPRO to 0. | ||
63 | * If SBPRO is set wrong, the drives will get found - but any | ||
64 | * data access will give errors (audio access will work). | ||
65 | * The "OmniCD" no-sound interface card from CreativeLabs and most Teac | ||
66 | * interface cards need SBPRO 1. | ||
67 | * | ||
68 | * sound base: | ||
69 | * =========== | ||
70 | * The SOUND_BASE definition tells if we should try to turn the CD sound | ||
71 | * channels on. It will only be of use regarding soundcards with a SbPro | ||
72 | * compatible mixer. | ||
73 | * | ||
74 | * Example: #define SOUND_BASE 0x220 enables the sound card's CD channels | ||
75 | * #define SOUND_BASE 0 leaves the soundcard untouched | ||
76 | */ | ||
77 | #define CDROM_PORT 0x340 /* <-----------<< port address */ | ||
78 | #define SBPRO 0 /* <-----------<< interface type */ | ||
79 | #define MAX_DRIVES 4 /* set to 1 if the card does not use "drive select" */ | ||
80 | #define SOUND_BASE 0x220 /* <-----------<< sound address of this card or 0 */ | ||
81 | |||
82 | /* | ||
83 | * some more or less user dependent definitions - service them! | ||
84 | */ | ||
85 | |||
86 | /* Set this to 0 once you have configured your interface definitions right. */ | ||
87 | #define DISTRIBUTION 1 | ||
88 | |||
89 | /* | ||
90 | * Time to wait after giving a message. | ||
91 | * This gets important if you enable non-standard DBG_xxx flags. | ||
92 | * You will see what happens if you omit the pause or make it | ||
93 | * too short. Be warned! | ||
94 | */ | ||
95 | #define KLOGD_PAUSE 1 | ||
96 | |||
97 | /* tray control: eject tray if no disk is in */ | ||
98 | #if DISTRIBUTION | ||
99 | #define JUKEBOX 0 | ||
100 | #else | ||
101 | #define JUKEBOX 1 | ||
102 | #endif /* DISTRIBUTION */ | ||
103 | |||
104 | /* tray control: eject tray after last use */ | ||
105 | #if DISTRIBUTION | ||
106 | #define EJECT 0 | ||
107 | #else | ||
108 | #define EJECT 1 | ||
109 | #endif /* DISTRIBUTION */ | ||
110 | |||
111 | /* max. number of audio frames to read with one */ | ||
112 | /* request (allocates n* 2352 bytes kernel memory!) */ | ||
113 | /* may be freely adjusted, f.e. 75 (= 1 sec.), at */ | ||
114 | /* runtime by use of the CDROMAUDIOBUFSIZ ioctl. */ | ||
115 | #define READ_AUDIO 0 | ||
116 | |||
117 | /* Optimizations for the Teac CD-55A drive read performance. | ||
118 | * SBP_TEAC_SPEED can be changed here, or one can set the | ||
119 | * variable "teac" when loading as a module. | ||
120 | * Valid settings are: | ||
121 | * 0 - very slow - the recommended "DISTRIBUTION 1" setup. | ||
122 | * 1 - 2x performance with little overhead. No busy waiting. | ||
123 | * 2 - 4x performance with 5ms overhead per read. Busy wait. | ||
124 | * | ||
125 | * Setting SBP_TEAC_SPEED or the variable 'teac' to anything | ||
126 | * other than 0 may cause problems. If you run into them, first | ||
127 | * change SBP_TEAC_SPEED back to 0 and see if your drive responds | ||
128 | * normally. If yes, you are "allowed" to report your case - to help | ||
129 | * me with the driver, not to solve your hassle. Don´t mail if you | ||
130 | * simply are stuck into your own "tuning" experiments, you know? | ||
131 | */ | ||
132 | #define SBP_TEAC_SPEED 1 | ||
133 | |||
134 | /*==========================================================================*/ | ||
135 | /*==========================================================================*/ | ||
136 | /* | ||
137 | * nothing to change below here if you are not fully aware what you're doing | ||
138 | */ | ||
139 | #ifndef _LINUX_SBPCD_H | ||
140 | |||
141 | #define _LINUX_SBPCD_H | ||
142 | /*==========================================================================*/ | ||
143 | /*==========================================================================*/ | ||
144 | /* | ||
145 | * driver's own read_ahead, data mode | ||
146 | */ | ||
147 | #define SBP_BUFFER_FRAMES 8 | ||
148 | |||
149 | #define LONG_TIMING 0 /* test against timeouts with "gold" CDs on CR-521 */ | ||
150 | #undef FUTURE | ||
151 | #undef SAFE_MIXED | ||
152 | |||
153 | #define TEST_UPC 0 | ||
154 | #define SPEA_TEST 0 | ||
155 | #define TEST_STI 0 | ||
156 | #define OLD_BUSY 0 | ||
157 | #undef PATH_CHECK | ||
158 | #ifndef SOUND_BASE | ||
159 | #define SOUND_BASE 0 | ||
160 | #endif | ||
161 | #if DISTRIBUTION | ||
162 | #undef SBP_TEAC_SPEED | ||
163 | #define SBP_TEAC_SPEED 0 | ||
164 | #endif | ||
165 | /*==========================================================================*/ | ||
166 | /* | ||
167 | * DDI interface definitions | ||
168 | * "invented" by Fred N. van Kempen.. | ||
169 | */ | ||
170 | #define DDIOCSDBG 0x9000 | ||
171 | |||
172 | /*==========================================================================*/ | ||
173 | /* | ||
174 | * "private" IOCTL functions | ||
175 | */ | ||
176 | #define CDROMAUDIOBUFSIZ 0x5382 /* set the audio buffer size */ | ||
177 | |||
178 | /*==========================================================================*/ | ||
179 | /* | ||
180 | * Debug output levels | ||
181 | */ | ||
182 | #define DBG_INF 1 /* necessary information */ | ||
183 | #define DBG_BSZ 2 /* BLOCK_SIZE trace */ | ||
184 | #define DBG_REA 3 /* READ status trace */ | ||
185 | #define DBG_CHK 4 /* MEDIA CHECK trace */ | ||
186 | #define DBG_TIM 5 /* datarate timer test */ | ||
187 | #define DBG_INI 6 /* initialization trace */ | ||
188 | #define DBG_TOC 7 /* tell TocEntry values */ | ||
189 | #define DBG_IOC 8 /* ioctl trace */ | ||
190 | #define DBG_STA 9 /* ResponseStatus() trace */ | ||
191 | #define DBG_ERR 10 /* cc_ReadError() trace */ | ||
192 | #define DBG_CMD 11 /* cmd_out() trace */ | ||
193 | #define DBG_WRN 12 /* give explanation before auto-probing */ | ||
194 | #define DBG_MUL 13 /* multi session code test */ | ||
195 | #define DBG_IDX 14 /* test code for drive_id !=0 */ | ||
196 | #define DBG_IOX 15 /* some special information */ | ||
197 | #define DBG_DID 16 /* drive ID test */ | ||
198 | #define DBG_RES 17 /* drive reset info */ | ||
199 | #define DBG_SPI 18 /* SpinUp test */ | ||
200 | #define DBG_IOS 19 /* ioctl trace: subchannel functions */ | ||
201 | #define DBG_IO2 20 /* ioctl trace: general */ | ||
202 | #define DBG_UPC 21 /* show UPC information */ | ||
203 | #define DBG_XA1 22 /* XA mode debugging */ | ||
204 | #define DBG_LCK 23 /* door (un)lock info */ | ||
205 | #define DBG_SQ1 24 /* dump SubQ frame */ | ||
206 | #define DBG_AUD 25 /* READ AUDIO debugging */ | ||
207 | #define DBG_SEQ 26 /* Sequoia interface configuration trace */ | ||
208 | #define DBG_LCS 27 /* Longshine LCS-7260 debugging trace */ | ||
209 | #define DBG_CD2 28 /* MKE/Funai CD200 debugging trace */ | ||
210 | #define DBG_TEA 29 /* TEAC CD-55A debugging trace */ | ||
211 | #define DBG_ECS 30 /* ECS-AT (Vertos 100) debugging trace */ | ||
212 | #define DBG_000 31 /* unnecessary information */ | ||
213 | |||
214 | /*==========================================================================*/ | ||
215 | /*==========================================================================*/ | ||
216 | |||
217 | /* | ||
218 | * bits of flags_cmd_out: | ||
219 | */ | ||
220 | #define f_respo3 0x100 | ||
221 | #define f_putcmd 0x80 | ||
222 | #define f_respo2 0x40 | ||
223 | #define f_lopsta 0x20 | ||
224 | #define f_getsta 0x10 | ||
225 | #define f_ResponseStatus 0x08 | ||
226 | #define f_obey_p_check 0x04 | ||
227 | #define f_bit1 0x02 | ||
228 | #define f_wait_if_busy 0x01 | ||
229 | |||
230 | /* | ||
231 | * diskstate_flags: | ||
232 | */ | ||
233 | #define x80_bit 0x80 | ||
234 | #define upc_bit 0x40 | ||
235 | #define volume_bit 0x20 | ||
236 | #define toc_bit 0x10 | ||
237 | #define multisession_bit 0x08 | ||
238 | #define cd_size_bit 0x04 | ||
239 | #define subq_bit 0x02 | ||
240 | #define frame_size_bit 0x01 | ||
241 | |||
242 | /* | ||
243 | * disk states (bits of diskstate_flags): | ||
244 | */ | ||
245 | #define upc_valid (current_drive->diskstate_flags&upc_bit) | ||
246 | #define volume_valid (current_drive->diskstate_flags&volume_bit) | ||
247 | #define toc_valid (current_drive->diskstate_flags&toc_bit) | ||
248 | #define cd_size_valid (current_drive->diskstate_flags&cd_size_bit) | ||
249 | #define subq_valid (current_drive->diskstate_flags&subq_bit) | ||
250 | #define frame_size_valid (current_drive->diskstate_flags&frame_size_bit) | ||
251 | |||
252 | /* | ||
253 | * the status_bits variable | ||
254 | */ | ||
255 | #define p_success 0x100 | ||
256 | #define p_door_closed 0x80 | ||
257 | #define p_caddy_in 0x40 | ||
258 | #define p_spinning 0x20 | ||
259 | #define p_check 0x10 | ||
260 | #define p_busy_new 0x08 | ||
261 | #define p_door_locked 0x04 | ||
262 | #define p_disk_ok 0x01 | ||
263 | |||
264 | /* | ||
265 | * LCS-7260 special status result bits: | ||
266 | */ | ||
267 | #define p_lcs_door_locked 0x02 | ||
268 | #define p_lcs_door_closed 0x01 /* probably disk_in */ | ||
269 | |||
270 | /* | ||
271 | * CR-52x special status result bits: | ||
272 | */ | ||
273 | #define p_caddin_old 0x40 | ||
274 | #define p_success_old 0x08 | ||
275 | #define p_busy_old 0x04 | ||
276 | #define p_bit_1 0x02 /* hopefully unused now */ | ||
277 | |||
278 | /* | ||
279 | * "generation specific" defs of the status result bits: | ||
280 | */ | ||
281 | #define p0_door_closed 0x80 | ||
282 | #define p0_caddy_in 0x40 | ||
283 | #define p0_spinning 0x20 | ||
284 | #define p0_check 0x10 | ||
285 | #define p0_success 0x08 /* unused */ | ||
286 | #define p0_busy 0x04 | ||
287 | #define p0_bit_1 0x02 /* unused */ | ||
288 | #define p0_disk_ok 0x01 | ||
289 | |||
290 | #define pL_disk_in 0x40 | ||
291 | #define pL_spinning 0x20 | ||
292 | #define pL_check 0x10 | ||
293 | #define pL_success 0x08 /* unused ?? */ | ||
294 | #define pL_busy 0x04 | ||
295 | #define pL_door_locked 0x02 | ||
296 | #define pL_door_closed 0x01 | ||
297 | |||
298 | #define pV_door_closed 0x40 | ||
299 | #define pV_spinning 0x20 | ||
300 | #define pV_check 0x10 | ||
301 | #define pV_success 0x08 | ||
302 | #define pV_busy 0x04 | ||
303 | #define pV_door_locked 0x02 | ||
304 | #define pV_disk_ok 0x01 | ||
305 | |||
306 | #define p1_door_closed 0x80 | ||
307 | #define p1_disk_in 0x40 | ||
308 | #define p1_spinning 0x20 | ||
309 | #define p1_check 0x10 | ||
310 | #define p1_busy 0x08 | ||
311 | #define p1_door_locked 0x04 | ||
312 | #define p1_bit_1 0x02 /* unused */ | ||
313 | #define p1_disk_ok 0x01 | ||
314 | |||
315 | #define p2_disk_ok 0x80 | ||
316 | #define p2_door_locked 0x40 | ||
317 | #define p2_spinning 0x20 | ||
318 | #define p2_busy2 0x10 | ||
319 | #define p2_busy1 0x08 | ||
320 | #define p2_door_closed 0x04 | ||
321 | #define p2_disk_in 0x02 | ||
322 | #define p2_check 0x01 | ||
323 | |||
324 | /* | ||
325 | * used drive states: | ||
326 | */ | ||
327 | #define st_door_closed (current_drive->status_bits&p_door_closed) | ||
328 | #define st_caddy_in (current_drive->status_bits&p_caddy_in) | ||
329 | #define st_spinning (current_drive->status_bits&p_spinning) | ||
330 | #define st_check (current_drive->status_bits&p_check) | ||
331 | #define st_busy (current_drive->status_bits&p_busy_new) | ||
332 | #define st_door_locked (current_drive->status_bits&p_door_locked) | ||
333 | #define st_diskok (current_drive->status_bits&p_disk_ok) | ||
334 | |||
335 | /* | ||
336 | * bits of the CDi_status register: | ||
337 | */ | ||
338 | #define s_not_result_ready 0x04 /* 0: "result ready" */ | ||
339 | #define s_not_data_ready 0x02 /* 0: "data ready" */ | ||
340 | #define s_attention 0x01 /* 1: "attention required" */ | ||
341 | /* | ||
342 | * usable as: | ||
343 | */ | ||
344 | #define DRV_ATTN ((inb(CDi_status)&s_attention)!=0) | ||
345 | #define DATA_READY ((inb(CDi_status)&s_not_data_ready)==0) | ||
346 | #define RESULT_READY ((inb(CDi_status)&s_not_result_ready)==0) | ||
347 | |||
348 | /* | ||
349 | * drive families and types (firmware versions): | ||
350 | */ | ||
351 | #define drv_fam0 0x0100 /* CR-52x family */ | ||
352 | #define drv_199 (drv_fam0+0x01) /* <200 */ | ||
353 | #define drv_200 (drv_fam0+0x02) /* <201 */ | ||
354 | #define drv_201 (drv_fam0+0x03) /* <210 */ | ||
355 | #define drv_210 (drv_fam0+0x04) /* <211 */ | ||
356 | #define drv_211 (drv_fam0+0x05) /* <300 */ | ||
357 | #define drv_300 (drv_fam0+0x06) /* >=300 */ | ||
358 | |||
359 | #define drv_fam1 0x0200 /* CR-56x family */ | ||
360 | #define drv_099 (drv_fam1+0x01) /* <100 */ | ||
361 | #define drv_100 (drv_fam1+0x02) /* >=100, only 1.02 and 5.00 known */ | ||
362 | |||
363 | #define drv_fam2 0x0400 /* CD200 family */ | ||
364 | |||
365 | #define drv_famT 0x0800 /* TEAC CD-55A */ | ||
366 | |||
367 | #define drv_famL 0x1000 /* Longshine family */ | ||
368 | #define drv_260 (drv_famL+0x01) /* LCS-7260 */ | ||
369 | #define drv_e1 (drv_famL+0x01) /* LCS-7260, firmware "A E1" */ | ||
370 | #define drv_f4 (drv_famL+0x02) /* LCS-7260, firmware "A4F4" */ | ||
371 | |||
372 | #define drv_famV 0x2000 /* ECS-AT (vertos-100) family */ | ||
373 | #define drv_at (drv_famV+0x01) /* ECS-AT, firmware "1.00" */ | ||
374 | |||
375 | #define fam0_drive (current_drive->drv_type&drv_fam0) | ||
376 | #define famL_drive (current_drive->drv_type&drv_famL) | ||
377 | #define famV_drive (current_drive->drv_type&drv_famV) | ||
378 | #define fam1_drive (current_drive->drv_type&drv_fam1) | ||
379 | #define fam2_drive (current_drive->drv_type&drv_fam2) | ||
380 | #define famT_drive (current_drive->drv_type&drv_famT) | ||
381 | #define fam0L_drive (current_drive->drv_type&(drv_fam0|drv_famL)) | ||
382 | #define fam0V_drive (current_drive->drv_type&(drv_fam0|drv_famV)) | ||
383 | #define famLV_drive (current_drive->drv_type&(drv_famL|drv_famV)) | ||
384 | #define fam0LV_drive (current_drive->drv_type&(drv_fam0|drv_famL|drv_famV)) | ||
385 | #define fam1L_drive (current_drive->drv_type&(drv_fam1|drv_famL)) | ||
386 | #define fam1V_drive (current_drive->drv_type&(drv_fam1|drv_famV)) | ||
387 | #define fam1LV_drive (current_drive->drv_type&(drv_fam1|drv_famL|drv_famV)) | ||
388 | #define fam01_drive (current_drive->drv_type&(drv_fam0|drv_fam1)) | ||
389 | #define fam12_drive (current_drive->drv_type&(drv_fam1|drv_fam2)) | ||
390 | #define fam2T_drive (current_drive->drv_type&(drv_fam2|drv_famT)) | ||
391 | |||
392 | /* | ||
393 | * audio states: | ||
394 | */ | ||
395 | #define audio_completed 3 /* Forgot this one! --AJK */ | ||
396 | #define audio_playing 2 | ||
397 | #define audio_pausing 1 | ||
398 | |||
399 | /* | ||
400 | * drv_pattern, drv_options: | ||
401 | */ | ||
402 | #define speed_auto 0x80 | ||
403 | #define speed_300 0x40 | ||
404 | #define speed_150 0x20 | ||
405 | #define audio_mono 0x04 | ||
406 | |||
407 | /* | ||
408 | * values of cmd_type (0 else): | ||
409 | */ | ||
410 | #define READ_M1 0x01 /* "data mode 1": 2048 bytes per frame */ | ||
411 | #define READ_M2 0x02 /* "data mode 2": 12+2048+280 bytes per frame */ | ||
412 | #define READ_SC 0x04 /* "subchannel info": 96 bytes per frame */ | ||
413 | #define READ_AU 0x08 /* "audio frame": 2352 bytes per frame */ | ||
414 | |||
415 | /* | ||
416 | * sense_byte: | ||
417 | * | ||
418 | * values: 00 | ||
419 | * 01 | ||
420 | * 81 | ||
421 | * 82 "raw audio" mode | ||
422 | * xx from infobuf[0] after 85 00 00 00 00 00 00 | ||
423 | */ | ||
424 | |||
425 | /* audio status (bin) */ | ||
426 | #define aud_00 0x00 /* Audio status byte not supported or not valid */ | ||
427 | #define audx11 0x0b /* Audio play operation in progress */ | ||
428 | #define audx12 0x0c /* Audio play operation paused */ | ||
429 | #define audx13 0x0d /* Audio play operation successfully completed */ | ||
430 | #define audx14 0x0e /* Audio play operation stopped due to error */ | ||
431 | #define audx15 0x0f /* No current audio status to return */ | ||
432 | /* audio status (bcd) */ | ||
433 | #define aud_11 0x11 /* Audio play operation in progress */ | ||
434 | #define aud_12 0x12 /* Audio play operation paused */ | ||
435 | #define aud_13 0x13 /* Audio play operation successfully completed */ | ||
436 | #define aud_14 0x14 /* Audio play operation stopped due to error */ | ||
437 | #define aud_15 0x15 /* No current audio status to return */ | ||
438 | |||
439 | /* | ||
440 | * highest allowed drive number (MINOR+1) | ||
441 | */ | ||
442 | #define NR_SBPCD 4 | ||
443 | |||
444 | /* | ||
445 | * we try to never disable interrupts - seems to work | ||
446 | */ | ||
447 | #define SBPCD_DIS_IRQ 0 | ||
448 | |||
449 | /* | ||
450 | * "write byte to port" | ||
451 | */ | ||
452 | #define OUT(x,y) outb(y,x) | ||
453 | |||
454 | /*==========================================================================*/ | ||
455 | |||
456 | #define MIXER_addr SOUND_BASE+4 /* sound card's address register */ | ||
457 | #define MIXER_data SOUND_BASE+5 /* sound card's data register */ | ||
458 | #define MIXER_CD_Volume 0x28 /* internal SB Pro register address */ | ||
459 | |||
460 | /*==========================================================================*/ | ||
461 | |||
462 | #define MAX_TRACKS 99 | ||
463 | |||
464 | #define ERR_DISKCHANGE 615 | ||
465 | |||
466 | /*==========================================================================*/ | ||
467 | /* | ||
468 | * To make conversions easier (machine dependent!) | ||
469 | */ | ||
470 | typedef union _msf | ||
471 | { | ||
472 | u_int n; | ||
473 | u_char c[4]; | ||
474 | } MSF; | ||
475 | |||
476 | typedef union _blk | ||
477 | { | ||
478 | u_int n; | ||
479 | u_char c[4]; | ||
480 | } BLK; | ||
481 | |||
482 | /*==========================================================================*/ | ||
483 | |||
484 | /*============================================================================ | ||
485 | ============================================================================== | ||
486 | |||
487 | COMMAND SET of "old" drives like CR-521, CR-522 | ||
488 | (the CR-562 family is different): | ||
489 | |||
490 | No. Command Code | ||
491 | -------------------------------------------- | ||
492 | |||
493 | Drive Commands: | ||
494 | 1 Seek 01 | ||
495 | 2 Read Data 02 | ||
496 | 3 Read XA-Data 03 | ||
497 | 4 Read Header 04 | ||
498 | 5 Spin Up 05 | ||
499 | 6 Spin Down 06 | ||
500 | 7 Diagnostic 07 | ||
501 | 8 Read UPC 08 | ||
502 | 9 Read ISRC 09 | ||
503 | 10 Play Audio 0A | ||
504 | 11 Play Audio MSF 0B | ||
505 | 12 Play Audio Track/Index 0C | ||
506 | |||
507 | Status Commands: | ||
508 | 13 Read Status 81 | ||
509 | 14 Read Error 82 | ||
510 | 15 Read Drive Version 83 | ||
511 | 16 Mode Select 84 | ||
512 | 17 Mode Sense 85 | ||
513 | 18 Set XA Parameter 86 | ||
514 | 19 Read XA Parameter 87 | ||
515 | 20 Read Capacity 88 | ||
516 | 21 Read SUB_Q 89 | ||
517 | 22 Read Disc Code 8A | ||
518 | 23 Read Disc Information 8B | ||
519 | 24 Read TOC 8C | ||
520 | 25 Pause/Resume 8D | ||
521 | 26 Read Packet 8E | ||
522 | 27 Read Path Check 00 | ||
523 | |||
524 | |||
525 | all numbers (lba, msf-bin, msf-bcd, counts) to transfer high byte first | ||
526 | |||
527 | mnemo 7-byte command #bytes response (r0...rn) | ||
528 | ________ ____________________ ____ | ||
529 | |||
530 | Read Status: | ||
531 | status: 81. (1) one-byte command, gives the main | ||
532 | status byte | ||
533 | Read Error: | ||
534 | check1: 82 00 00 00 00 00 00. (6) r1: audio status | ||
535 | |||
536 | Read Packet: | ||
537 | check2: 8e xx 00 00 00 00 00. (xx) gets xx bytes response, relating | ||
538 | to commands 01 04 05 07 08 09 | ||
539 | |||
540 | Play Audio: | ||
541 | play: 0a ll-bb-aa nn-nn-nn. (0) play audio, ll-bb-aa: starting block (lba), | ||
542 | nn-nn-nn: #blocks | ||
543 | Play Audio MSF: | ||
544 | 0b mm-ss-ff mm-ss-ff (0) play audio from/to | ||
545 | |||
546 | Play Audio Track/Index: | ||
547 | 0c ... | ||
548 | |||
549 | Pause/Resume: | ||
550 | pause: 8d pr 00 00 00 00 00. (0) pause (pr=00) | ||
551 | resume (pr=80) audio playing | ||
552 | |||
553 | Mode Select: | ||
554 | 84 00 nn-nn ??.?? 00 (0) nn-nn: 2048 or 2340 | ||
555 | possibly defines transfer size | ||
556 | |||
557 | set_vol: 84 83 00 00 sw le 00. (0) sw(itch): lrxxxxxx (off=1) | ||
558 | le(vel): min=0, max=FF, else half | ||
559 | (firmware 2.11) | ||
560 | |||
561 | Mode Sense: | ||
562 | get_vol: 85 03 00 00 00 00 00. (2) tell current audio volume setting | ||
563 | |||
564 | Read Disc Information: | ||
565 | tocdesc: 8b 00 00 00 00 00 00. (6) read the toc descriptor ("msf-bin"-format) | ||
566 | |||
567 | Read TOC: | ||
568 | tocent: 8c fl nn 00 00 00 00. (8) read toc entry #nn | ||
569 | (fl=0:"lba"-, =2:"msf-bin"-format) | ||
570 | |||
571 | Read Capacity: | ||
572 | capacit: 88 00 00 00 00 00 00. (5) "read CD-ROM capacity" | ||
573 | |||
574 | |||
575 | Read Path Check: | ||
576 | ping: 00 00 00 00 00 00 00. (2) r0=AA, r1=55 | ||
577 | ("ping" if the drive is connected) | ||
578 | |||
579 | Read Drive Version: | ||
580 | ident: 83 00 00 00 00 00 00. (12) gives "MATSHITAn.nn" | ||
581 | (n.nn = 2.01, 2.11., 3.00, ...) | ||
582 | |||
583 | Seek: | ||
584 | seek: 01 00 ll-bb-aa 00 00. (0) | ||
585 | seek: 01 02 mm-ss-ff 00 00. (0) | ||
586 | |||
587 | Read Data: | ||
588 | read: 02 xx-xx-xx nn-nn fl. (?) read nn-nn blocks of 2048 bytes, | ||
589 | starting at block xx-xx-xx | ||
590 | fl=0: "lba"-, =2:"msf-bcd"-coded xx-xx-xx | ||
591 | |||
592 | Read XA-Data: | ||
593 | read: 03 xx-xx-xx nn-nn fl. (?) read nn-nn blocks of 2340 bytes, | ||
594 | starting at block xx-xx-xx | ||
595 | fl=0: "lba"-, =2:"msf-bcd"-coded xx-xx-xx | ||
596 | |||
597 | Read SUB_Q: | ||
598 | 89 fl 00 00 00 00 00. (13) r0: audio status, r4-r7: lba/msf, | ||
599 | fl=0: "lba", fl=2: "msf" | ||
600 | |||
601 | Read Disc Code: | ||
602 | 8a 00 00 00 00 00 00. (14) possibly extended "check condition"-info | ||
603 | |||
604 | Read Header: | ||
605 | 04 00 ll-bb-aa 00 00. (0) 4 bytes response with "check2" | ||
606 | 04 02 mm-ss-ff 00 00. (0) 4 bytes response with "check2" | ||
607 | |||
608 | Spin Up: | ||
609 | 05 00 ll-bb-aa 00 00. (0) possibly implies a "seek" | ||
610 | |||
611 | Spin Down: | ||
612 | 06 ... | ||
613 | |||
614 | Diagnostic: | ||
615 | 07 00 ll-bb-aa 00 00. (2) 2 bytes response with "check2" | ||
616 | 07 02 mm-ss-ff 00 00. (2) 2 bytes response with "check2" | ||
617 | |||
618 | Read UPC: | ||
619 | 08 00 ll-bb-aa 00 00. (16) | ||
620 | 08 02 mm-ss-ff 00 00. (16) | ||
621 | |||
622 | Read ISRC: | ||
623 | 09 00 ll-bb-aa 00 00. (15) 15 bytes response with "check2" | ||
624 | 09 02 mm-ss-ff 00 00. (15) 15 bytes response with "check2" | ||
625 | |||
626 | Set XA Parameter: | ||
627 | 86 ... | ||
628 | |||
629 | Read XA Parameter: | ||
630 | 87 ... | ||
631 | |||
632 | ============================================================================== | ||
633 | ============================================================================*/ | ||
634 | |||
635 | /* | ||
636 | * commands | ||
637 | * | ||
638 | * CR-52x: CMD0_ | ||
639 | * CR-56x: CMD1_ | ||
640 | * CD200: CMD2_ | ||
641 | * LCS-7260: CMDL_ | ||
642 | * TEAC CD-55A: CMDT_ | ||
643 | * ECS-AT: CMDV_ | ||
644 | */ | ||
645 | #define CMD1_RESET 0x0a | ||
646 | #define CMD2_RESET 0x01 | ||
647 | #define CMDT_RESET 0xc0 | ||
648 | |||
649 | #define CMD1_LOCK_CTL 0x0c | ||
650 | #define CMD2_LOCK_CTL 0x1e | ||
651 | #define CMDT_LOCK_CTL CMD2_LOCK_CTL | ||
652 | #define CMDL_LOCK_CTL 0x0e | ||
653 | #define CMDV_LOCK_CTL CMDL_LOCK_CTL | ||
654 | |||
655 | #define CMD1_TRAY_CTL 0x07 | ||
656 | #define CMD2_TRAY_CTL 0x1b | ||
657 | #define CMDT_TRAY_CTL CMD2_TRAY_CTL | ||
658 | #define CMDL_TRAY_CTL 0x0d | ||
659 | #define CMDV_TRAY_CTL CMDL_TRAY_CTL | ||
660 | |||
661 | #define CMD1_MULTISESS 0x8d | ||
662 | #define CMDL_MULTISESS 0x8c | ||
663 | #define CMDV_MULTISESS CMDL_MULTISESS | ||
664 | |||
665 | #define CMD1_SUBCHANINF 0x11 | ||
666 | #define CMD2_SUBCHANINF 0x?? | ||
667 | |||
668 | #define CMD1_ABORT 0x08 | ||
669 | #define CMD2_ABORT 0x08 | ||
670 | #define CMDT_ABORT 0x08 | ||
671 | |||
672 | #define CMD2_x02 0x02 | ||
673 | |||
674 | #define CMD2_SETSPEED 0xda | ||
675 | |||
676 | #define CMD0_PATH_CHECK 0x00 | ||
677 | #define CMD1_PATH_CHECK 0x??? | ||
678 | #define CMD2_PATH_CHECK 0x??? | ||
679 | #define CMDT_PATH_CHECK 0x??? | ||
680 | #define CMDL_PATH_CHECK CMD0_PATH_CHECK | ||
681 | #define CMDV_PATH_CHECK CMD0_PATH_CHECK | ||
682 | |||
683 | #define CMD0_SEEK 0x01 | ||
684 | #define CMD1_SEEK CMD0_SEEK | ||
685 | #define CMD2_SEEK 0x2b | ||
686 | #define CMDT_SEEK CMD2_SEEK | ||
687 | #define CMDL_SEEK CMD0_SEEK | ||
688 | #define CMDV_SEEK CMD0_SEEK | ||
689 | |||
690 | #define CMD0_READ 0x02 | ||
691 | #define CMD1_READ 0x10 | ||
692 | #define CMD2_READ 0x28 | ||
693 | #define CMDT_READ CMD2_READ | ||
694 | #define CMDL_READ CMD0_READ | ||
695 | #define CMDV_READ CMD0_READ | ||
696 | |||
697 | #define CMD0_READ_XA 0x03 | ||
698 | #define CMD2_READ_XA 0xd4 | ||
699 | #define CMD2_READ_XA2 0xd5 | ||
700 | #define CMDL_READ_XA CMD0_READ_XA /* really ?? */ | ||
701 | #define CMDV_READ_XA CMD0_READ_XA | ||
702 | |||
703 | #define CMD0_READ_HEAD 0x04 | ||
704 | |||
705 | #define CMD0_SPINUP 0x05 | ||
706 | #define CMD1_SPINUP 0x02 | ||
707 | #define CMD2_SPINUP CMD2_TRAY_CTL | ||
708 | #define CMDL_SPINUP CMD0_SPINUP | ||
709 | #define CMDV_SPINUP CMD0_SPINUP | ||
710 | |||
711 | #define CMD0_SPINDOWN 0x06 /* really??? */ | ||
712 | #define CMD1_SPINDOWN 0x06 | ||
713 | #define CMD2_SPINDOWN CMD2_TRAY_CTL | ||
714 | #define CMDL_SPINDOWN 0x0d | ||
715 | #define CMDV_SPINDOWN CMD0_SPINDOWN | ||
716 | |||
717 | #define CMD0_DIAG 0x07 | ||
718 | |||
719 | #define CMD0_READ_UPC 0x08 | ||
720 | #define CMD1_READ_UPC 0x88 | ||
721 | #define CMD2_READ_UPC 0x??? | ||
722 | #define CMDL_READ_UPC CMD0_READ_UPC | ||
723 | #define CMDV_READ_UPC 0x8f | ||
724 | |||
725 | #define CMD0_READ_ISRC 0x09 | ||
726 | |||
727 | #define CMD0_PLAY 0x0a | ||
728 | #define CMD1_PLAY 0x??? | ||
729 | #define CMD2_PLAY 0x??? | ||
730 | #define CMDL_PLAY CMD0_PLAY | ||
731 | #define CMDV_PLAY CMD0_PLAY | ||
732 | |||
733 | #define CMD0_PLAY_MSF 0x0b | ||
734 | #define CMD1_PLAY_MSF 0x0e | ||
735 | #define CMD2_PLAY_MSF 0x47 | ||
736 | #define CMDT_PLAY_MSF CMD2_PLAY_MSF | ||
737 | #define CMDL_PLAY_MSF 0x??? | ||
738 | |||
739 | #define CMD0_PLAY_TI 0x0c | ||
740 | #define CMD1_PLAY_TI 0x0f | ||
741 | |||
742 | #define CMD0_STATUS 0x81 | ||
743 | #define CMD1_STATUS 0x05 | ||
744 | #define CMD2_STATUS 0x00 | ||
745 | #define CMDT_STATUS CMD2_STATUS | ||
746 | #define CMDL_STATUS CMD0_STATUS | ||
747 | #define CMDV_STATUS CMD0_STATUS | ||
748 | #define CMD2_SEEK_LEADIN 0x00 | ||
749 | |||
750 | #define CMD0_READ_ERR 0x82 | ||
751 | #define CMD1_READ_ERR CMD0_READ_ERR | ||
752 | #define CMD2_READ_ERR 0x03 | ||
753 | #define CMDT_READ_ERR CMD2_READ_ERR /* get audio status */ | ||
754 | #define CMDL_READ_ERR CMD0_READ_ERR | ||
755 | #define CMDV_READ_ERR CMD0_READ_ERR | ||
756 | |||
757 | #define CMD0_READ_VER 0x83 | ||
758 | #define CMD1_READ_VER CMD0_READ_VER | ||
759 | #define CMD2_READ_VER 0x12 | ||
760 | #define CMDT_READ_VER CMD2_READ_VER /* really ?? */ | ||
761 | #define CMDL_READ_VER CMD0_READ_VER | ||
762 | #define CMDV_READ_VER CMD0_READ_VER | ||
763 | |||
764 | #define CMD0_SETMODE 0x84 | ||
765 | #define CMD1_SETMODE 0x09 | ||
766 | #define CMD2_SETMODE 0x55 | ||
767 | #define CMDT_SETMODE CMD2_SETMODE | ||
768 | #define CMDL_SETMODE CMD0_SETMODE | ||
769 | |||
770 | #define CMD0_GETMODE 0x85 | ||
771 | #define CMD1_GETMODE 0x84 | ||
772 | #define CMD2_GETMODE 0x5a | ||
773 | #define CMDT_GETMODE CMD2_GETMODE | ||
774 | #define CMDL_GETMODE CMD0_GETMODE | ||
775 | |||
776 | #define CMD0_SET_XA 0x86 | ||
777 | |||
778 | #define CMD0_GET_XA 0x87 | ||
779 | |||
780 | #define CMD0_CAPACITY 0x88 | ||
781 | #define CMD1_CAPACITY 0x85 | ||
782 | #define CMD2_CAPACITY 0x25 | ||
783 | #define CMDL_CAPACITY CMD0_CAPACITY /* missing in some firmware versions */ | ||
784 | |||
785 | #define CMD0_READSUBQ 0x89 | ||
786 | #define CMD1_READSUBQ 0x87 | ||
787 | #define CMD2_READSUBQ 0x42 | ||
788 | #define CMDT_READSUBQ CMD2_READSUBQ | ||
789 | #define CMDL_READSUBQ CMD0_READSUBQ | ||
790 | #define CMDV_READSUBQ CMD0_READSUBQ | ||
791 | |||
792 | #define CMD0_DISKCODE 0x8a | ||
793 | |||
794 | #define CMD0_DISKINFO 0x8b | ||
795 | #define CMD1_DISKINFO CMD0_DISKINFO | ||
796 | #define CMD2_DISKINFO 0x43 | ||
797 | #define CMDT_DISKINFO CMD2_DISKINFO | ||
798 | #define CMDL_DISKINFO CMD0_DISKINFO | ||
799 | #define CMDV_DISKINFO CMD0_DISKINFO | ||
800 | |||
801 | #define CMD0_READTOC 0x8c | ||
802 | #define CMD1_READTOC CMD0_READTOC | ||
803 | #define CMD2_READTOC 0x??? | ||
804 | #define CMDL_READTOC CMD0_READTOC | ||
805 | #define CMDV_READTOC CMD0_READTOC | ||
806 | |||
807 | #define CMD0_PAU_RES 0x8d | ||
808 | #define CMD1_PAU_RES 0x0d | ||
809 | #define CMD2_PAU_RES 0x4b | ||
810 | #define CMDT_PAUSE CMD2_PAU_RES | ||
811 | #define CMDL_PAU_RES CMD0_PAU_RES | ||
812 | #define CMDV_PAUSE CMD0_PAU_RES | ||
813 | |||
814 | #define CMD0_PACKET 0x8e | ||
815 | #define CMD1_PACKET CMD0_PACKET | ||
816 | #define CMD2_PACKET 0x??? | ||
817 | #define CMDL_PACKET CMD0_PACKET | ||
818 | #define CMDV_PACKET 0x??? | ||
819 | |||
820 | /*==========================================================================*/ | ||
821 | /*==========================================================================*/ | ||
822 | #endif /* _LINUX_SBPCD_H */ | ||
823 | /*==========================================================================*/ | ||
824 | /* | ||
825 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
826 | * Emacs will notice this stuff at the end of the file and automatically | ||
827 | * adjust the settings for this buffer only. This must remain at the end | ||
828 | * of the file. | ||
829 | * --------------------------------------------------------------------------- | ||
830 | * Local variables: | ||
831 | * c-indent-level: 8 | ||
832 | * c-brace-imaginary-offset: 0 | ||
833 | * c-brace-offset: -8 | ||
834 | * c-argdecl-indent: 8 | ||
835 | * c-label-offset: -8 | ||
836 | * c-continued-statement-offset: 8 | ||
837 | * c-continued-brace-offset: 0 | ||
838 | * End: | ||
839 | */ | ||
diff --git a/drivers/cdrom/sjcd.c b/drivers/cdrom/sjcd.c deleted file mode 100644 index 76c24e679e68..000000000000 --- a/drivers/cdrom/sjcd.c +++ /dev/null | |||
@@ -1,1815 +0,0 @@ | |||
1 | /* -- sjcd.c | ||
2 | * | ||
3 | * Sanyo CD-ROM device driver implementation, Version 1.6 | ||
4 | * Copyright (C) 1995 Vadim V. Model | ||
5 | * | ||
6 | * model@cecmow.enet.dec.com | ||
7 | * vadim@rbrf.ru | ||
8 | * vadim@ipsun.ras.ru | ||
9 | * | ||
10 | * | ||
11 | * This driver is based on pre-works by Eberhard Moenkeberg (emoenke@gwdg.de); | ||
12 | * it was developed under use of mcd.c from Martin Harriss, with help of | ||
13 | * Eric van der Maarel (H.T.M.v.d.Maarel@marin.nl). | ||
14 | * | ||
15 | * It is planned to include these routines into sbpcd.c later - to make | ||
16 | * a "mixed use" on one cable possible for all kinds of drives which use | ||
17 | * the SoundBlaster/Panasonic style CDROM interface. But today, the | ||
18 | * ability to install directly from CDROM is more important than flexibility. | ||
19 | * | ||
20 | * This program is free software; you can redistribute it and/or modify | ||
21 | * it under the terms of the GNU General Public License as published by | ||
22 | * the Free Software Foundation; either version 2 of the License, or | ||
23 | * (at your option) any later version. | ||
24 | * | ||
25 | * This program is distributed in the hope that it will be useful, | ||
26 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
27 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
28 | * GNU General Public License for more details. | ||
29 | * | ||
30 | * You should have received a copy of the GNU General Public License | ||
31 | * along with this program; if not, write to the Free Software | ||
32 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
33 | * | ||
34 | * History: | ||
35 | * 1.1 First public release with kernel version 1.3.7. | ||
36 | * Written by Vadim Model. | ||
37 | * 1.2 Added detection and configuration of cdrom interface | ||
38 | * on ISP16 soundcard. | ||
39 | * Allow for command line options: sjcd=<io_base>,<irq>,<dma> | ||
40 | * 1.3 Some minor changes to README.sjcd. | ||
41 | * 1.4 MSS Sound support!! Listen to a CD through the speakers. | ||
42 | * 1.5 Module support and bugfixes. | ||
43 | * Tray locking. | ||
44 | * 1.6 Removed ISP16 code from this driver. | ||
45 | * Allow only to set io base address on command line: sjcd=<io_base> | ||
46 | * Changes to Documentation/cdrom/sjcd | ||
47 | * Added cleanup after any error in the initialisation. | ||
48 | * 1.7 Added code to set the sector size tables to prevent the bug present in | ||
49 | * the previous version of this driver. Coded added by Anthony Barbachan | ||
50 | * from bugfix tip originally suggested by Alan Cox. | ||
51 | * | ||
52 | * November 1999 -- Make kernel-parameter implementation work with 2.3.x | ||
53 | * Removed init_module & cleanup_module in favor of | ||
54 | * module_init & module_exit. | ||
55 | * Torben Mathiasen <tmm@image.dk> | ||
56 | */ | ||
57 | |||
58 | #define SJCD_VERSION_MAJOR 1 | ||
59 | #define SJCD_VERSION_MINOR 7 | ||
60 | |||
61 | #include <linux/module.h> | ||
62 | #include <linux/errno.h> | ||
63 | #include <linux/mm.h> | ||
64 | #include <linux/timer.h> | ||
65 | #include <linux/fs.h> | ||
66 | #include <linux/kernel.h> | ||
67 | #include <linux/cdrom.h> | ||
68 | #include <linux/ioport.h> | ||
69 | #include <linux/string.h> | ||
70 | #include <linux/major.h> | ||
71 | #include <linux/init.h> | ||
72 | |||
73 | #include <asm/system.h> | ||
74 | #include <asm/io.h> | ||
75 | #include <asm/uaccess.h> | ||
76 | #include <linux/blkdev.h> | ||
77 | #include "sjcd.h" | ||
78 | |||
79 | static int sjcd_present = 0; | ||
80 | static struct request_queue *sjcd_queue; | ||
81 | |||
82 | #define MAJOR_NR SANYO_CDROM_MAJOR | ||
83 | #define QUEUE (sjcd_queue) | ||
84 | #define CURRENT elv_next_request(sjcd_queue) | ||
85 | |||
86 | #define SJCD_BUF_SIZ 32 /* cdr-h94a has internal 64K buffer */ | ||
87 | |||
88 | /* | ||
89 | * buffer for block size conversion | ||
90 | */ | ||
91 | static char sjcd_buf[2048 * SJCD_BUF_SIZ]; | ||
92 | static volatile int sjcd_buf_bn[SJCD_BUF_SIZ], sjcd_next_bn; | ||
93 | static volatile int sjcd_buf_in, sjcd_buf_out = -1; | ||
94 | |||
95 | /* | ||
96 | * Status. | ||
97 | */ | ||
98 | static unsigned short sjcd_status_valid = 0; | ||
99 | static unsigned short sjcd_door_closed; | ||
100 | static unsigned short sjcd_door_was_open; | ||
101 | static unsigned short sjcd_media_is_available; | ||
102 | static unsigned short sjcd_media_is_changed; | ||
103 | static unsigned short sjcd_toc_uptodate = 0; | ||
104 | static unsigned short sjcd_command_failed; | ||
105 | static volatile unsigned char sjcd_completion_status = 0; | ||
106 | static volatile unsigned char sjcd_completion_error = 0; | ||
107 | static unsigned short sjcd_command_is_in_progress = 0; | ||
108 | static unsigned short sjcd_error_reported = 0; | ||
109 | static DEFINE_SPINLOCK(sjcd_lock); | ||
110 | |||
111 | static int sjcd_open_count; | ||
112 | |||
113 | static int sjcd_audio_status; | ||
114 | static struct sjcd_play_msf sjcd_playing; | ||
115 | |||
116 | static int sjcd_base = SJCD_BASE_ADDR; | ||
117 | |||
118 | module_param(sjcd_base, int, 0); | ||
119 | |||
120 | static DECLARE_WAIT_QUEUE_HEAD(sjcd_waitq); | ||
121 | |||
122 | /* | ||
123 | * Data transfer. | ||
124 | */ | ||
125 | static volatile unsigned short sjcd_transfer_is_active = 0; | ||
126 | |||
127 | enum sjcd_transfer_state { | ||
128 | SJCD_S_IDLE = 0, | ||
129 | SJCD_S_START = 1, | ||
130 | SJCD_S_MODE = 2, | ||
131 | SJCD_S_READ = 3, | ||
132 | SJCD_S_DATA = 4, | ||
133 | SJCD_S_STOP = 5, | ||
134 | SJCD_S_STOPPING = 6 | ||
135 | }; | ||
136 | static enum sjcd_transfer_state sjcd_transfer_state = SJCD_S_IDLE; | ||
137 | static long sjcd_transfer_timeout = 0; | ||
138 | static int sjcd_read_count = 0; | ||
139 | static unsigned char sjcd_mode = 0; | ||
140 | |||
141 | #define SJCD_READ_TIMEOUT 5000 | ||
142 | |||
143 | #if defined( SJCD_GATHER_STAT ) | ||
144 | /* | ||
145 | * Statistic. | ||
146 | */ | ||
147 | static struct sjcd_stat statistic; | ||
148 | #endif | ||
149 | |||
150 | /* | ||
151 | * Timer. | ||
152 | */ | ||
153 | static DEFINE_TIMER(sjcd_delay_timer, NULL, 0, 0); | ||
154 | |||
155 | #define SJCD_SET_TIMER( func, tmout ) \ | ||
156 | ( sjcd_delay_timer.expires = jiffies+tmout, \ | ||
157 | sjcd_delay_timer.function = ( void * )func, \ | ||
158 | add_timer( &sjcd_delay_timer ) ) | ||
159 | |||
160 | #define CLEAR_TIMER del_timer( &sjcd_delay_timer ) | ||
161 | |||
162 | /* | ||
163 | * Set up device, i.e., use command line data to set | ||
164 | * base address. | ||
165 | */ | ||
166 | #ifndef MODULE | ||
167 | static int __init sjcd_setup(char *str) | ||
168 | { | ||
169 | int ints[2]; | ||
170 | (void) get_options(str, ARRAY_SIZE(ints), ints); | ||
171 | if (ints[0] > 0) | ||
172 | sjcd_base = ints[1]; | ||
173 | |||
174 | return 1; | ||
175 | } | ||
176 | |||
177 | __setup("sjcd=", sjcd_setup); | ||
178 | |||
179 | #endif | ||
180 | |||
181 | /* | ||
182 | * Special converters. | ||
183 | */ | ||
184 | static unsigned char bin2bcd(int bin) | ||
185 | { | ||
186 | int u, v; | ||
187 | |||
188 | u = bin % 10; | ||
189 | v = bin / 10; | ||
190 | return (u | (v << 4)); | ||
191 | } | ||
192 | |||
193 | static int bcd2bin(unsigned char bcd) | ||
194 | { | ||
195 | return ((bcd >> 4) * 10 + (bcd & 0x0F)); | ||
196 | } | ||
197 | |||
198 | static long msf2hsg(struct msf *mp) | ||
199 | { | ||
200 | return (bcd2bin(mp->frame) + bcd2bin(mp->sec) * 75 | ||
201 | + bcd2bin(mp->min) * 4500 - 150); | ||
202 | } | ||
203 | |||
204 | static void hsg2msf(long hsg, struct msf *msf) | ||
205 | { | ||
206 | hsg += 150; | ||
207 | msf->min = hsg / 4500; | ||
208 | hsg %= 4500; | ||
209 | msf->sec = hsg / 75; | ||
210 | msf->frame = hsg % 75; | ||
211 | msf->min = bin2bcd(msf->min); /* convert to BCD */ | ||
212 | msf->sec = bin2bcd(msf->sec); | ||
213 | msf->frame = bin2bcd(msf->frame); | ||
214 | } | ||
215 | |||
216 | /* | ||
217 | * Send a command to cdrom. Invalidate status. | ||
218 | */ | ||
219 | static void sjcd_send_cmd(unsigned char cmd) | ||
220 | { | ||
221 | #if defined( SJCD_TRACE ) | ||
222 | printk("SJCD: send_cmd( 0x%x )\n", cmd); | ||
223 | #endif | ||
224 | outb(cmd, SJCDPORT(0)); | ||
225 | sjcd_command_is_in_progress = 1; | ||
226 | sjcd_status_valid = 0; | ||
227 | sjcd_command_failed = 0; | ||
228 | } | ||
229 | |||
230 | /* | ||
231 | * Send a command with one arg to cdrom. Invalidate status. | ||
232 | */ | ||
233 | static void sjcd_send_1_cmd(unsigned char cmd, unsigned char a) | ||
234 | { | ||
235 | #if defined( SJCD_TRACE ) | ||
236 | printk("SJCD: send_1_cmd( 0x%x, 0x%x )\n", cmd, a); | ||
237 | #endif | ||
238 | outb(cmd, SJCDPORT(0)); | ||
239 | outb(a, SJCDPORT(0)); | ||
240 | sjcd_command_is_in_progress = 1; | ||
241 | sjcd_status_valid = 0; | ||
242 | sjcd_command_failed = 0; | ||
243 | } | ||
244 | |||
245 | /* | ||
246 | * Send a command with four args to cdrom. Invalidate status. | ||
247 | */ | ||
248 | static void sjcd_send_4_cmd(unsigned char cmd, unsigned char a, | ||
249 | unsigned char b, unsigned char c, | ||
250 | unsigned char d) | ||
251 | { | ||
252 | #if defined( SJCD_TRACE ) | ||
253 | printk("SJCD: send_4_cmd( 0x%x )\n", cmd); | ||
254 | #endif | ||
255 | outb(cmd, SJCDPORT(0)); | ||
256 | outb(a, SJCDPORT(0)); | ||
257 | outb(b, SJCDPORT(0)); | ||
258 | outb(c, SJCDPORT(0)); | ||
259 | outb(d, SJCDPORT(0)); | ||
260 | sjcd_command_is_in_progress = 1; | ||
261 | sjcd_status_valid = 0; | ||
262 | sjcd_command_failed = 0; | ||
263 | } | ||
264 | |||
265 | /* | ||
266 | * Send a play or read command to cdrom. Invalidate Status. | ||
267 | */ | ||
268 | static void sjcd_send_6_cmd(unsigned char cmd, struct sjcd_play_msf *pms) | ||
269 | { | ||
270 | #if defined( SJCD_TRACE ) | ||
271 | printk("SJCD: send_long_cmd( 0x%x )\n", cmd); | ||
272 | #endif | ||
273 | outb(cmd, SJCDPORT(0)); | ||
274 | outb(pms->start.min, SJCDPORT(0)); | ||
275 | outb(pms->start.sec, SJCDPORT(0)); | ||
276 | outb(pms->start.frame, SJCDPORT(0)); | ||
277 | outb(pms->end.min, SJCDPORT(0)); | ||
278 | outb(pms->end.sec, SJCDPORT(0)); | ||
279 | outb(pms->end.frame, SJCDPORT(0)); | ||
280 | sjcd_command_is_in_progress = 1; | ||
281 | sjcd_status_valid = 0; | ||
282 | sjcd_command_failed = 0; | ||
283 | } | ||
284 | |||
285 | /* | ||
286 | * Get a value from the data port. Should not block, so we use a little | ||
287 | * wait for a while. Returns 0 if OK. | ||
288 | */ | ||
289 | static int sjcd_load_response(void *buf, int len) | ||
290 | { | ||
291 | unsigned char *resp = (unsigned char *) buf; | ||
292 | |||
293 | for (; len; --len) { | ||
294 | int i; | ||
295 | for (i = 200; | ||
296 | i-- && !SJCD_STATUS_AVAILABLE(inb(SJCDPORT(1)));); | ||
297 | if (i > 0) | ||
298 | *resp++ = (unsigned char) inb(SJCDPORT(0)); | ||
299 | else | ||
300 | break; | ||
301 | } | ||
302 | return (len); | ||
303 | } | ||
304 | |||
305 | /* | ||
306 | * Load and parse command completion status (drive info byte and maybe error). | ||
307 | * Sorry, no error classification yet. | ||
308 | */ | ||
309 | static void sjcd_load_status(void) | ||
310 | { | ||
311 | sjcd_media_is_changed = 0; | ||
312 | sjcd_completion_error = 0; | ||
313 | sjcd_completion_status = inb(SJCDPORT(0)); | ||
314 | if (sjcd_completion_status & SST_DOOR_OPENED) { | ||
315 | sjcd_door_closed = sjcd_media_is_available = 0; | ||
316 | } else { | ||
317 | sjcd_door_closed = 1; | ||
318 | if (sjcd_completion_status & SST_MEDIA_CHANGED) | ||
319 | sjcd_media_is_available = sjcd_media_is_changed = | ||
320 | 1; | ||
321 | else if (sjcd_completion_status & 0x0F) { | ||
322 | /* | ||
323 | * OK, we seem to catch an error ... | ||
324 | */ | ||
325 | while (!SJCD_STATUS_AVAILABLE(inb(SJCDPORT(1)))); | ||
326 | sjcd_completion_error = inb(SJCDPORT(0)); | ||
327 | if ((sjcd_completion_status & 0x08) && | ||
328 | (sjcd_completion_error & 0x40)) | ||
329 | sjcd_media_is_available = 0; | ||
330 | else | ||
331 | sjcd_command_failed = 1; | ||
332 | } else | ||
333 | sjcd_media_is_available = 1; | ||
334 | } | ||
335 | /* | ||
336 | * Ok, status loaded successfully. | ||
337 | */ | ||
338 | sjcd_status_valid = 1, sjcd_error_reported = 0; | ||
339 | sjcd_command_is_in_progress = 0; | ||
340 | |||
341 | /* | ||
342 | * If the disk is changed, the TOC is not valid. | ||
343 | */ | ||
344 | if (sjcd_media_is_changed) | ||
345 | sjcd_toc_uptodate = 0; | ||
346 | #if defined( SJCD_TRACE ) | ||
347 | printk("SJCD: status %02x.%02x loaded.\n", | ||
348 | (int) sjcd_completion_status, (int) sjcd_completion_error); | ||
349 | #endif | ||
350 | } | ||
351 | |||
352 | /* | ||
353 | * Read status from cdrom. Check to see if the status is available. | ||
354 | */ | ||
355 | static int sjcd_check_status(void) | ||
356 | { | ||
357 | /* | ||
358 | * Try to load the response from cdrom into buffer. | ||
359 | */ | ||
360 | if (SJCD_STATUS_AVAILABLE(inb(SJCDPORT(1)))) { | ||
361 | sjcd_load_status(); | ||
362 | return (1); | ||
363 | } else { | ||
364 | /* | ||
365 | * No status is available. | ||
366 | */ | ||
367 | return (0); | ||
368 | } | ||
369 | } | ||
370 | |||
371 | /* | ||
372 | * This is just timeout counter, and nothing more. Surprised ? :-) | ||
373 | */ | ||
374 | static volatile long sjcd_status_timeout; | ||
375 | |||
376 | /* | ||
377 | * We need about 10 seconds to wait. The longest command takes about 5 seconds | ||
378 | * to probe the disk (usually after tray closed or drive reset). Other values | ||
379 | * should be thought of for other commands. | ||
380 | */ | ||
381 | #define SJCD_WAIT_FOR_STATUS_TIMEOUT 1000 | ||
382 | |||
383 | static void sjcd_status_timer(void) | ||
384 | { | ||
385 | if (sjcd_check_status()) { | ||
386 | /* | ||
387 | * The command completed and status is loaded, stop waiting. | ||
388 | */ | ||
389 | wake_up(&sjcd_waitq); | ||
390 | } else if (--sjcd_status_timeout <= 0) { | ||
391 | /* | ||
392 | * We are timed out. | ||
393 | */ | ||
394 | wake_up(&sjcd_waitq); | ||
395 | } else { | ||
396 | /* | ||
397 | * We have still some time to wait. Try again. | ||
398 | */ | ||
399 | SJCD_SET_TIMER(sjcd_status_timer, 1); | ||
400 | } | ||
401 | } | ||
402 | |||
403 | /* | ||
404 | * Wait for status for 10 sec approx. Returns non-positive when timed out. | ||
405 | * Should not be used while reading data CDs. | ||
406 | */ | ||
407 | static int sjcd_wait_for_status(void) | ||
408 | { | ||
409 | sjcd_status_timeout = SJCD_WAIT_FOR_STATUS_TIMEOUT; | ||
410 | SJCD_SET_TIMER(sjcd_status_timer, 1); | ||
411 | sleep_on(&sjcd_waitq); | ||
412 | #if defined( SJCD_DIAGNOSTIC ) || defined ( SJCD_TRACE ) | ||
413 | if (sjcd_status_timeout <= 0) | ||
414 | printk("SJCD: Error Wait For Status.\n"); | ||
415 | #endif | ||
416 | return (sjcd_status_timeout); | ||
417 | } | ||
418 | |||
419 | static int sjcd_receive_status(void) | ||
420 | { | ||
421 | int i; | ||
422 | #if defined( SJCD_TRACE ) | ||
423 | printk("SJCD: receive_status\n"); | ||
424 | #endif | ||
425 | /* | ||
426 | * Wait a bit for status available. | ||
427 | */ | ||
428 | for (i = 200; i-- && (sjcd_check_status() == 0);); | ||
429 | if (i < 0) { | ||
430 | #if defined( SJCD_TRACE ) | ||
431 | printk("SJCD: long wait for status\n"); | ||
432 | #endif | ||
433 | if (sjcd_wait_for_status() <= 0) | ||
434 | printk("SJCD: Timeout when read status.\n"); | ||
435 | else | ||
436 | i = 0; | ||
437 | } | ||
438 | return (i); | ||
439 | } | ||
440 | |||
441 | /* | ||
442 | * Load the status. Issue get status command and wait for status available. | ||
443 | */ | ||
444 | static void sjcd_get_status(void) | ||
445 | { | ||
446 | #if defined( SJCD_TRACE ) | ||
447 | printk("SJCD: get_status\n"); | ||
448 | #endif | ||
449 | sjcd_send_cmd(SCMD_GET_STATUS); | ||
450 | sjcd_receive_status(); | ||
451 | } | ||
452 | |||
453 | /* | ||
454 | * Check the drive if the disk is changed. Should be revised. | ||
455 | */ | ||
456 | static int sjcd_disk_change(struct gendisk *disk) | ||
457 | { | ||
458 | #if 0 | ||
459 | printk("SJCD: sjcd_disk_change(%s)\n", disk->disk_name); | ||
460 | #endif | ||
461 | if (!sjcd_command_is_in_progress) | ||
462 | sjcd_get_status(); | ||
463 | return (sjcd_status_valid ? sjcd_media_is_changed : 0); | ||
464 | } | ||
465 | |||
466 | /* | ||
467 | * Read the table of contents (TOC) and TOC header if necessary. | ||
468 | * We assume that the drive contains no more than 99 toc entries. | ||
469 | */ | ||
470 | static struct sjcd_hw_disk_info sjcd_table_of_contents[SJCD_MAX_TRACKS]; | ||
471 | static unsigned char sjcd_first_track_no, sjcd_last_track_no; | ||
472 | #define sjcd_disk_length sjcd_table_of_contents[0].un.track_msf | ||
473 | |||
474 | static int sjcd_update_toc(void) | ||
475 | { | ||
476 | struct sjcd_hw_disk_info info; | ||
477 | int i; | ||
478 | #if defined( SJCD_TRACE ) | ||
479 | printk("SJCD: update toc:\n"); | ||
480 | #endif | ||
481 | /* | ||
482 | * check to see if we need to do anything | ||
483 | */ | ||
484 | if (sjcd_toc_uptodate) | ||
485 | return (0); | ||
486 | |||
487 | /* | ||
488 | * Get the TOC start information. | ||
489 | */ | ||
490 | sjcd_send_1_cmd(SCMD_GET_DISK_INFO, SCMD_GET_1_TRACK); | ||
491 | sjcd_receive_status(); | ||
492 | |||
493 | if (!sjcd_status_valid) { | ||
494 | printk("SJCD: cannot load status.\n"); | ||
495 | return (-1); | ||
496 | } | ||
497 | |||
498 | if (!sjcd_media_is_available) { | ||
499 | printk("SJCD: no disk in drive\n"); | ||
500 | return (-1); | ||
501 | } | ||
502 | |||
503 | if (!sjcd_command_failed) { | ||
504 | if (sjcd_load_response(&info, sizeof(info)) != 0) { | ||
505 | printk | ||
506 | ("SJCD: cannot load response about TOC start.\n"); | ||
507 | return (-1); | ||
508 | } | ||
509 | sjcd_first_track_no = bcd2bin(info.un.track_no); | ||
510 | } else { | ||
511 | printk("SJCD: get first failed\n"); | ||
512 | return (-1); | ||
513 | } | ||
514 | #if defined( SJCD_TRACE ) | ||
515 | printk("SJCD: TOC start 0x%02x ", sjcd_first_track_no); | ||
516 | #endif | ||
517 | /* | ||
518 | * Get the TOC finish information. | ||
519 | */ | ||
520 | sjcd_send_1_cmd(SCMD_GET_DISK_INFO, SCMD_GET_L_TRACK); | ||
521 | sjcd_receive_status(); | ||
522 | |||
523 | if (!sjcd_status_valid) { | ||
524 | printk("SJCD: cannot load status.\n"); | ||
525 | return (-1); | ||
526 | } | ||
527 | |||
528 | if (!sjcd_media_is_available) { | ||
529 | printk("SJCD: no disk in drive\n"); | ||
530 | return (-1); | ||
531 | } | ||
532 | |||
533 | if (!sjcd_command_failed) { | ||
534 | if (sjcd_load_response(&info, sizeof(info)) != 0) { | ||
535 | printk | ||
536 | ("SJCD: cannot load response about TOC finish.\n"); | ||
537 | return (-1); | ||
538 | } | ||
539 | sjcd_last_track_no = bcd2bin(info.un.track_no); | ||
540 | } else { | ||
541 | printk("SJCD: get last failed\n"); | ||
542 | return (-1); | ||
543 | } | ||
544 | #if defined( SJCD_TRACE ) | ||
545 | printk("SJCD: TOC finish 0x%02x ", sjcd_last_track_no); | ||
546 | #endif | ||
547 | for (i = sjcd_first_track_no; i <= sjcd_last_track_no; i++) { | ||
548 | /* | ||
549 | * Get the first track information. | ||
550 | */ | ||
551 | sjcd_send_1_cmd(SCMD_GET_DISK_INFO, bin2bcd(i)); | ||
552 | sjcd_receive_status(); | ||
553 | |||
554 | if (!sjcd_status_valid) { | ||
555 | printk("SJCD: cannot load status.\n"); | ||
556 | return (-1); | ||
557 | } | ||
558 | |||
559 | if (!sjcd_media_is_available) { | ||
560 | printk("SJCD: no disk in drive\n"); | ||
561 | return (-1); | ||
562 | } | ||
563 | |||
564 | if (!sjcd_command_failed) { | ||
565 | if (sjcd_load_response(&sjcd_table_of_contents[i], | ||
566 | sizeof(struct | ||
567 | sjcd_hw_disk_info)) | ||
568 | != 0) { | ||
569 | printk | ||
570 | ("SJCD: cannot load info for %d track\n", | ||
571 | i); | ||
572 | return (-1); | ||
573 | } | ||
574 | } else { | ||
575 | printk("SJCD: get info %d failed\n", i); | ||
576 | return (-1); | ||
577 | } | ||
578 | } | ||
579 | |||
580 | /* | ||
581 | * Get the disk length info. | ||
582 | */ | ||
583 | sjcd_send_1_cmd(SCMD_GET_DISK_INFO, SCMD_GET_D_SIZE); | ||
584 | sjcd_receive_status(); | ||
585 | |||
586 | if (!sjcd_status_valid) { | ||
587 | printk("SJCD: cannot load status.\n"); | ||
588 | return (-1); | ||
589 | } | ||
590 | |||
591 | if (!sjcd_media_is_available) { | ||
592 | printk("SJCD: no disk in drive\n"); | ||
593 | return (-1); | ||
594 | } | ||
595 | |||
596 | if (!sjcd_command_failed) { | ||
597 | if (sjcd_load_response(&info, sizeof(info)) != 0) { | ||
598 | printk | ||
599 | ("SJCD: cannot load response about disk size.\n"); | ||
600 | return (-1); | ||
601 | } | ||
602 | sjcd_disk_length.min = info.un.track_msf.min; | ||
603 | sjcd_disk_length.sec = info.un.track_msf.sec; | ||
604 | sjcd_disk_length.frame = info.un.track_msf.frame; | ||
605 | } else { | ||
606 | printk("SJCD: get size failed\n"); | ||
607 | return (1); | ||
608 | } | ||
609 | #if defined( SJCD_TRACE ) | ||
610 | printk("SJCD: (%02x:%02x.%02x)\n", sjcd_disk_length.min, | ||
611 | sjcd_disk_length.sec, sjcd_disk_length.frame); | ||
612 | #endif | ||
613 | return (0); | ||
614 | } | ||
615 | |||
616 | /* | ||
617 | * Load subchannel information. | ||
618 | */ | ||
619 | static int sjcd_get_q_info(struct sjcd_hw_qinfo *qp) | ||
620 | { | ||
621 | int s; | ||
622 | #if defined( SJCD_TRACE ) | ||
623 | printk("SJCD: load sub q\n"); | ||
624 | #endif | ||
625 | sjcd_send_cmd(SCMD_GET_QINFO); | ||
626 | s = sjcd_receive_status(); | ||
627 | if (s < 0 || sjcd_command_failed || !sjcd_status_valid) { | ||
628 | sjcd_send_cmd(0xF2); | ||
629 | s = sjcd_receive_status(); | ||
630 | if (s < 0 || sjcd_command_failed || !sjcd_status_valid) | ||
631 | return (-1); | ||
632 | sjcd_send_cmd(SCMD_GET_QINFO); | ||
633 | s = sjcd_receive_status(); | ||
634 | if (s < 0 || sjcd_command_failed || !sjcd_status_valid) | ||
635 | return (-1); | ||
636 | } | ||
637 | if (sjcd_media_is_available) | ||
638 | if (sjcd_load_response(qp, sizeof(*qp)) == 0) | ||
639 | return (0); | ||
640 | return (-1); | ||
641 | } | ||
642 | |||
643 | /* | ||
644 | * Start playing from the specified position. | ||
645 | */ | ||
646 | static int sjcd_play(struct sjcd_play_msf *mp) | ||
647 | { | ||
648 | struct sjcd_play_msf msf; | ||
649 | |||
650 | /* | ||
651 | * Turn the device to play mode. | ||
652 | */ | ||
653 | sjcd_send_1_cmd(SCMD_SET_MODE, SCMD_MODE_PLAY); | ||
654 | if (sjcd_receive_status() < 0) | ||
655 | return (-1); | ||
656 | |||
657 | /* | ||
658 | * Seek to the starting point. | ||
659 | */ | ||
660 | msf.start = mp->start; | ||
661 | msf.end.min = msf.end.sec = msf.end.frame = 0x00; | ||
662 | sjcd_send_6_cmd(SCMD_SEEK, &msf); | ||
663 | if (sjcd_receive_status() < 0) | ||
664 | return (-1); | ||
665 | |||
666 | /* | ||
667 | * Start playing. | ||
668 | */ | ||
669 | sjcd_send_6_cmd(SCMD_PLAY, mp); | ||
670 | return (sjcd_receive_status()); | ||
671 | } | ||
672 | |||
673 | /* | ||
674 | * Tray control functions. | ||
675 | */ | ||
676 | static int sjcd_tray_close(void) | ||
677 | { | ||
678 | #if defined( SJCD_TRACE ) | ||
679 | printk("SJCD: tray_close\n"); | ||
680 | #endif | ||
681 | sjcd_send_cmd(SCMD_CLOSE_TRAY); | ||
682 | return (sjcd_receive_status()); | ||
683 | } | ||
684 | |||
685 | static int sjcd_tray_lock(void) | ||
686 | { | ||
687 | #if defined( SJCD_TRACE ) | ||
688 | printk("SJCD: tray_lock\n"); | ||
689 | #endif | ||
690 | sjcd_send_cmd(SCMD_LOCK_TRAY); | ||
691 | return (sjcd_receive_status()); | ||
692 | } | ||
693 | |||
694 | static int sjcd_tray_unlock(void) | ||
695 | { | ||
696 | #if defined( SJCD_TRACE ) | ||
697 | printk("SJCD: tray_unlock\n"); | ||
698 | #endif | ||
699 | sjcd_send_cmd(SCMD_UNLOCK_TRAY); | ||
700 | return (sjcd_receive_status()); | ||
701 | } | ||
702 | |||
703 | static int sjcd_tray_open(void) | ||
704 | { | ||
705 | #if defined( SJCD_TRACE ) | ||
706 | printk("SJCD: tray_open\n"); | ||
707 | #endif | ||
708 | sjcd_send_cmd(SCMD_EJECT_TRAY); | ||
709 | return (sjcd_receive_status()); | ||
710 | } | ||
711 | |||
712 | /* | ||
713 | * Do some user commands. | ||
714 | */ | ||
715 | static int sjcd_ioctl(struct inode *ip, struct file *fp, | ||
716 | unsigned int cmd, unsigned long arg) | ||
717 | { | ||
718 | void __user *argp = (void __user *)arg; | ||
719 | #if defined( SJCD_TRACE ) | ||
720 | printk("SJCD:ioctl\n"); | ||
721 | #endif | ||
722 | |||
723 | sjcd_get_status(); | ||
724 | if (!sjcd_status_valid) | ||
725 | return (-EIO); | ||
726 | if (sjcd_update_toc() < 0) | ||
727 | return (-EIO); | ||
728 | |||
729 | switch (cmd) { | ||
730 | case CDROMSTART:{ | ||
731 | #if defined( SJCD_TRACE ) | ||
732 | printk("SJCD: ioctl: start\n"); | ||
733 | #endif | ||
734 | return (0); | ||
735 | } | ||
736 | |||
737 | case CDROMSTOP:{ | ||
738 | #if defined( SJCD_TRACE ) | ||
739 | printk("SJCD: ioctl: stop\n"); | ||
740 | #endif | ||
741 | sjcd_send_cmd(SCMD_PAUSE); | ||
742 | (void) sjcd_receive_status(); | ||
743 | sjcd_audio_status = CDROM_AUDIO_NO_STATUS; | ||
744 | return (0); | ||
745 | } | ||
746 | |||
747 | case CDROMPAUSE:{ | ||
748 | struct sjcd_hw_qinfo q_info; | ||
749 | #if defined( SJCD_TRACE ) | ||
750 | printk("SJCD: ioctl: pause\n"); | ||
751 | #endif | ||
752 | if (sjcd_audio_status == CDROM_AUDIO_PLAY) { | ||
753 | sjcd_send_cmd(SCMD_PAUSE); | ||
754 | (void) sjcd_receive_status(); | ||
755 | if (sjcd_get_q_info(&q_info) < 0) { | ||
756 | sjcd_audio_status = | ||
757 | CDROM_AUDIO_NO_STATUS; | ||
758 | } else { | ||
759 | sjcd_audio_status = | ||
760 | CDROM_AUDIO_PAUSED; | ||
761 | sjcd_playing.start = q_info.abs; | ||
762 | } | ||
763 | return (0); | ||
764 | } else | ||
765 | return (-EINVAL); | ||
766 | } | ||
767 | |||
768 | case CDROMRESUME:{ | ||
769 | #if defined( SJCD_TRACE ) | ||
770 | printk("SJCD: ioctl: resume\n"); | ||
771 | #endif | ||
772 | if (sjcd_audio_status == CDROM_AUDIO_PAUSED) { | ||
773 | /* | ||
774 | * continue play starting at saved location | ||
775 | */ | ||
776 | if (sjcd_play(&sjcd_playing) < 0) { | ||
777 | sjcd_audio_status = | ||
778 | CDROM_AUDIO_ERROR; | ||
779 | return (-EIO); | ||
780 | } else { | ||
781 | sjcd_audio_status = | ||
782 | CDROM_AUDIO_PLAY; | ||
783 | return (0); | ||
784 | } | ||
785 | } else | ||
786 | return (-EINVAL); | ||
787 | } | ||
788 | |||
789 | case CDROMPLAYTRKIND:{ | ||
790 | struct cdrom_ti ti; | ||
791 | int s = -EFAULT; | ||
792 | #if defined( SJCD_TRACE ) | ||
793 | printk("SJCD: ioctl: playtrkind\n"); | ||
794 | #endif | ||
795 | if (!copy_from_user(&ti, argp, sizeof(ti))) { | ||
796 | s = 0; | ||
797 | if (ti.cdti_trk0 < sjcd_first_track_no) | ||
798 | return (-EINVAL); | ||
799 | if (ti.cdti_trk1 > sjcd_last_track_no) | ||
800 | ti.cdti_trk1 = sjcd_last_track_no; | ||
801 | if (ti.cdti_trk0 > ti.cdti_trk1) | ||
802 | return (-EINVAL); | ||
803 | |||
804 | sjcd_playing.start = | ||
805 | sjcd_table_of_contents[ti.cdti_trk0]. | ||
806 | un.track_msf; | ||
807 | sjcd_playing.end = | ||
808 | (ti.cdti_trk1 < | ||
809 | sjcd_last_track_no) ? | ||
810 | sjcd_table_of_contents[ti.cdti_trk1 + | ||
811 | 1].un. | ||
812 | track_msf : sjcd_table_of_contents[0]. | ||
813 | un.track_msf; | ||
814 | |||
815 | if (sjcd_play(&sjcd_playing) < 0) { | ||
816 | sjcd_audio_status = | ||
817 | CDROM_AUDIO_ERROR; | ||
818 | return (-EIO); | ||
819 | } else | ||
820 | sjcd_audio_status = | ||
821 | CDROM_AUDIO_PLAY; | ||
822 | } | ||
823 | return (s); | ||
824 | } | ||
825 | |||
826 | case CDROMPLAYMSF:{ | ||
827 | struct cdrom_msf sjcd_msf; | ||
828 | int s; | ||
829 | #if defined( SJCD_TRACE ) | ||
830 | printk("SJCD: ioctl: playmsf\n"); | ||
831 | #endif | ||
832 | if ((s = | ||
833 | access_ok(VERIFY_READ, argp, sizeof(sjcd_msf)) | ||
834 | ? 0 : -EFAULT) == 0) { | ||
835 | if (sjcd_audio_status == CDROM_AUDIO_PLAY) { | ||
836 | sjcd_send_cmd(SCMD_PAUSE); | ||
837 | (void) sjcd_receive_status(); | ||
838 | sjcd_audio_status = | ||
839 | CDROM_AUDIO_NO_STATUS; | ||
840 | } | ||
841 | |||
842 | if (copy_from_user(&sjcd_msf, argp, | ||
843 | sizeof(sjcd_msf))) | ||
844 | return (-EFAULT); | ||
845 | |||
846 | sjcd_playing.start.min = | ||
847 | bin2bcd(sjcd_msf.cdmsf_min0); | ||
848 | sjcd_playing.start.sec = | ||
849 | bin2bcd(sjcd_msf.cdmsf_sec0); | ||
850 | sjcd_playing.start.frame = | ||
851 | bin2bcd(sjcd_msf.cdmsf_frame0); | ||
852 | sjcd_playing.end.min = | ||
853 | bin2bcd(sjcd_msf.cdmsf_min1); | ||
854 | sjcd_playing.end.sec = | ||
855 | bin2bcd(sjcd_msf.cdmsf_sec1); | ||
856 | sjcd_playing.end.frame = | ||
857 | bin2bcd(sjcd_msf.cdmsf_frame1); | ||
858 | |||
859 | if (sjcd_play(&sjcd_playing) < 0) { | ||
860 | sjcd_audio_status = | ||
861 | CDROM_AUDIO_ERROR; | ||
862 | return (-EIO); | ||
863 | } else | ||
864 | sjcd_audio_status = | ||
865 | CDROM_AUDIO_PLAY; | ||
866 | } | ||
867 | return (s); | ||
868 | } | ||
869 | |||
870 | case CDROMREADTOCHDR:{ | ||
871 | struct cdrom_tochdr toc_header; | ||
872 | #if defined (SJCD_TRACE ) | ||
873 | printk("SJCD: ioctl: readtocheader\n"); | ||
874 | #endif | ||
875 | toc_header.cdth_trk0 = sjcd_first_track_no; | ||
876 | toc_header.cdth_trk1 = sjcd_last_track_no; | ||
877 | if (copy_to_user(argp, &toc_header, | ||
878 | sizeof(toc_header))) | ||
879 | return -EFAULT; | ||
880 | return 0; | ||
881 | } | ||
882 | |||
883 | case CDROMREADTOCENTRY:{ | ||
884 | struct cdrom_tocentry toc_entry; | ||
885 | int s; | ||
886 | #if defined( SJCD_TRACE ) | ||
887 | printk("SJCD: ioctl: readtocentry\n"); | ||
888 | #endif | ||
889 | if ((s = | ||
890 | access_ok(VERIFY_WRITE, argp, sizeof(toc_entry)) | ||
891 | ? 0 : -EFAULT) == 0) { | ||
892 | struct sjcd_hw_disk_info *tp; | ||
893 | |||
894 | if (copy_from_user(&toc_entry, argp, | ||
895 | sizeof(toc_entry))) | ||
896 | return (-EFAULT); | ||
897 | if (toc_entry.cdte_track == CDROM_LEADOUT) | ||
898 | tp = &sjcd_table_of_contents[0]; | ||
899 | else if (toc_entry.cdte_track < | ||
900 | sjcd_first_track_no) | ||
901 | return (-EINVAL); | ||
902 | else if (toc_entry.cdte_track > | ||
903 | sjcd_last_track_no) | ||
904 | return (-EINVAL); | ||
905 | else | ||
906 | tp = &sjcd_table_of_contents | ||
907 | [toc_entry.cdte_track]; | ||
908 | |||
909 | toc_entry.cdte_adr = | ||
910 | tp->track_control & 0x0F; | ||
911 | toc_entry.cdte_ctrl = | ||
912 | tp->track_control >> 4; | ||
913 | |||
914 | switch (toc_entry.cdte_format) { | ||
915 | case CDROM_LBA: | ||
916 | toc_entry.cdte_addr.lba = | ||
917 | msf2hsg(&(tp->un.track_msf)); | ||
918 | break; | ||
919 | case CDROM_MSF: | ||
920 | toc_entry.cdte_addr.msf.minute = | ||
921 | bcd2bin(tp->un.track_msf.min); | ||
922 | toc_entry.cdte_addr.msf.second = | ||
923 | bcd2bin(tp->un.track_msf.sec); | ||
924 | toc_entry.cdte_addr.msf.frame = | ||
925 | bcd2bin(tp->un.track_msf. | ||
926 | frame); | ||
927 | break; | ||
928 | default: | ||
929 | return (-EINVAL); | ||
930 | } | ||
931 | if (copy_to_user(argp, &toc_entry, | ||
932 | sizeof(toc_entry))) | ||
933 | s = -EFAULT; | ||
934 | } | ||
935 | return (s); | ||
936 | } | ||
937 | |||
938 | case CDROMSUBCHNL:{ | ||
939 | struct cdrom_subchnl subchnl; | ||
940 | int s; | ||
941 | #if defined( SJCD_TRACE ) | ||
942 | printk("SJCD: ioctl: subchnl\n"); | ||
943 | #endif | ||
944 | if ((s = | ||
945 | access_ok(VERIFY_WRITE, argp, sizeof(subchnl)) | ||
946 | ? 0 : -EFAULT) == 0) { | ||
947 | struct sjcd_hw_qinfo q_info; | ||
948 | |||
949 | if (copy_from_user(&subchnl, argp, | ||
950 | sizeof(subchnl))) | ||
951 | return (-EFAULT); | ||
952 | |||
953 | if (sjcd_get_q_info(&q_info) < 0) | ||
954 | return (-EIO); | ||
955 | |||
956 | subchnl.cdsc_audiostatus = | ||
957 | sjcd_audio_status; | ||
958 | subchnl.cdsc_adr = | ||
959 | q_info.track_control & 0x0F; | ||
960 | subchnl.cdsc_ctrl = | ||
961 | q_info.track_control >> 4; | ||
962 | subchnl.cdsc_trk = | ||
963 | bcd2bin(q_info.track_no); | ||
964 | subchnl.cdsc_ind = bcd2bin(q_info.x); | ||
965 | |||
966 | switch (subchnl.cdsc_format) { | ||
967 | case CDROM_LBA: | ||
968 | subchnl.cdsc_absaddr.lba = | ||
969 | msf2hsg(&(q_info.abs)); | ||
970 | subchnl.cdsc_reladdr.lba = | ||
971 | msf2hsg(&(q_info.rel)); | ||
972 | break; | ||
973 | case CDROM_MSF: | ||
974 | subchnl.cdsc_absaddr.msf.minute = | ||
975 | bcd2bin(q_info.abs.min); | ||
976 | subchnl.cdsc_absaddr.msf.second = | ||
977 | bcd2bin(q_info.abs.sec); | ||
978 | subchnl.cdsc_absaddr.msf.frame = | ||
979 | bcd2bin(q_info.abs.frame); | ||
980 | subchnl.cdsc_reladdr.msf.minute = | ||
981 | bcd2bin(q_info.rel.min); | ||
982 | subchnl.cdsc_reladdr.msf.second = | ||
983 | bcd2bin(q_info.rel.sec); | ||
984 | subchnl.cdsc_reladdr.msf.frame = | ||
985 | bcd2bin(q_info.rel.frame); | ||
986 | break; | ||
987 | default: | ||
988 | return (-EINVAL); | ||
989 | } | ||
990 | if (copy_to_user(argp, &subchnl, | ||
991 | sizeof(subchnl))) | ||
992 | s = -EFAULT; | ||
993 | } | ||
994 | return (s); | ||
995 | } | ||
996 | |||
997 | case CDROMVOLCTRL:{ | ||
998 | struct cdrom_volctrl vol_ctrl; | ||
999 | int s; | ||
1000 | #if defined( SJCD_TRACE ) | ||
1001 | printk("SJCD: ioctl: volctrl\n"); | ||
1002 | #endif | ||
1003 | if ((s = | ||
1004 | access_ok(VERIFY_READ, argp, sizeof(vol_ctrl)) | ||
1005 | ? 0 : -EFAULT) == 0) { | ||
1006 | unsigned char dummy[4]; | ||
1007 | |||
1008 | if (copy_from_user(&vol_ctrl, argp, | ||
1009 | sizeof(vol_ctrl))) | ||
1010 | return (-EFAULT); | ||
1011 | sjcd_send_4_cmd(SCMD_SET_VOLUME, | ||
1012 | vol_ctrl.channel0, 0xFF, | ||
1013 | vol_ctrl.channel1, 0xFF); | ||
1014 | if (sjcd_receive_status() < 0) | ||
1015 | return (-EIO); | ||
1016 | (void) sjcd_load_response(dummy, 4); | ||
1017 | } | ||
1018 | return (s); | ||
1019 | } | ||
1020 | |||
1021 | case CDROMEJECT:{ | ||
1022 | #if defined( SJCD_TRACE ) | ||
1023 | printk("SJCD: ioctl: eject\n"); | ||
1024 | #endif | ||
1025 | if (!sjcd_command_is_in_progress) { | ||
1026 | sjcd_tray_unlock(); | ||
1027 | sjcd_send_cmd(SCMD_EJECT_TRAY); | ||
1028 | (void) sjcd_receive_status(); | ||
1029 | } | ||
1030 | return (0); | ||
1031 | } | ||
1032 | |||
1033 | #if defined( SJCD_GATHER_STAT ) | ||
1034 | case 0xABCD:{ | ||
1035 | #if defined( SJCD_TRACE ) | ||
1036 | printk("SJCD: ioctl: statistic\n"); | ||
1037 | #endif | ||
1038 | if (copy_to_user(argp, &statistic, sizeof(statistic))) | ||
1039 | return -EFAULT; | ||
1040 | return 0; | ||
1041 | } | ||
1042 | #endif | ||
1043 | |||
1044 | default: | ||
1045 | return (-EINVAL); | ||
1046 | } | ||
1047 | } | ||
1048 | |||
1049 | /* | ||
1050 | * Invalidate internal buffers of the driver. | ||
1051 | */ | ||
1052 | static void sjcd_invalidate_buffers(void) | ||
1053 | { | ||
1054 | int i; | ||
1055 | for (i = 0; i < SJCD_BUF_SIZ; sjcd_buf_bn[i++] = -1); | ||
1056 | sjcd_buf_out = -1; | ||
1057 | } | ||
1058 | |||
1059 | /* | ||
1060 | * Take care of the different block sizes between cdrom and Linux. | ||
1061 | * When Linux gets variable block sizes this will probably go away. | ||
1062 | */ | ||
1063 | |||
1064 | static int current_valid(void) | ||
1065 | { | ||
1066 | return CURRENT && | ||
1067 | rq_data_dir(CURRENT) == READ && | ||
1068 | CURRENT->sector != -1; | ||
1069 | } | ||
1070 | |||
1071 | static void sjcd_transfer(void) | ||
1072 | { | ||
1073 | #if defined( SJCD_TRACE ) | ||
1074 | printk("SJCD: transfer:\n"); | ||
1075 | #endif | ||
1076 | if (current_valid()) { | ||
1077 | while (CURRENT->nr_sectors) { | ||
1078 | int i, bn = CURRENT->sector / 4; | ||
1079 | for (i = 0; | ||
1080 | i < SJCD_BUF_SIZ && sjcd_buf_bn[i] != bn; | ||
1081 | i++); | ||
1082 | if (i < SJCD_BUF_SIZ) { | ||
1083 | int offs = | ||
1084 | (i * 4 + (CURRENT->sector & 3)) * 512; | ||
1085 | int nr_sectors = 4 - (CURRENT->sector & 3); | ||
1086 | if (sjcd_buf_out != i) { | ||
1087 | sjcd_buf_out = i; | ||
1088 | if (sjcd_buf_bn[i] != bn) { | ||
1089 | sjcd_buf_out = -1; | ||
1090 | continue; | ||
1091 | } | ||
1092 | } | ||
1093 | if (nr_sectors > CURRENT->nr_sectors) | ||
1094 | nr_sectors = CURRENT->nr_sectors; | ||
1095 | #if defined( SJCD_TRACE ) | ||
1096 | printk("SJCD: copy out\n"); | ||
1097 | #endif | ||
1098 | memcpy(CURRENT->buffer, sjcd_buf + offs, | ||
1099 | nr_sectors * 512); | ||
1100 | CURRENT->nr_sectors -= nr_sectors; | ||
1101 | CURRENT->sector += nr_sectors; | ||
1102 | CURRENT->buffer += nr_sectors * 512; | ||
1103 | } else { | ||
1104 | sjcd_buf_out = -1; | ||
1105 | break; | ||
1106 | } | ||
1107 | } | ||
1108 | } | ||
1109 | #if defined( SJCD_TRACE ) | ||
1110 | printk("SJCD: transfer: done\n"); | ||
1111 | #endif | ||
1112 | } | ||
1113 | |||
1114 | static void sjcd_poll(void) | ||
1115 | { | ||
1116 | #if defined( SJCD_GATHER_STAT ) | ||
1117 | /* | ||
1118 | * Update total number of ticks. | ||
1119 | */ | ||
1120 | statistic.ticks++; | ||
1121 | statistic.tticks[sjcd_transfer_state]++; | ||
1122 | #endif | ||
1123 | |||
1124 | ReSwitch:switch (sjcd_transfer_state) { | ||
1125 | |||
1126 | case SJCD_S_IDLE:{ | ||
1127 | #if defined( SJCD_GATHER_STAT ) | ||
1128 | statistic.idle_ticks++; | ||
1129 | #endif | ||
1130 | #if defined( SJCD_TRACE ) | ||
1131 | printk("SJCD_S_IDLE\n"); | ||
1132 | #endif | ||
1133 | return; | ||
1134 | } | ||
1135 | |||
1136 | case SJCD_S_START:{ | ||
1137 | #if defined( SJCD_GATHER_STAT ) | ||
1138 | statistic.start_ticks++; | ||
1139 | #endif | ||
1140 | sjcd_send_cmd(SCMD_GET_STATUS); | ||
1141 | sjcd_transfer_state = | ||
1142 | sjcd_mode == | ||
1143 | SCMD_MODE_COOKED ? SJCD_S_READ : SJCD_S_MODE; | ||
1144 | sjcd_transfer_timeout = 500; | ||
1145 | #if defined( SJCD_TRACE ) | ||
1146 | printk("SJCD_S_START: goto SJCD_S_%s mode\n", | ||
1147 | sjcd_transfer_state == | ||
1148 | SJCD_S_READ ? "READ" : "MODE"); | ||
1149 | #endif | ||
1150 | break; | ||
1151 | } | ||
1152 | |||
1153 | case SJCD_S_MODE:{ | ||
1154 | if (sjcd_check_status()) { | ||
1155 | /* | ||
1156 | * Previous command is completed. | ||
1157 | */ | ||
1158 | if (!sjcd_status_valid | ||
1159 | || sjcd_command_failed) { | ||
1160 | #if defined( SJCD_TRACE ) | ||
1161 | printk | ||
1162 | ("SJCD_S_MODE: pre-cmd failed: goto to SJCD_S_STOP mode\n"); | ||
1163 | #endif | ||
1164 | sjcd_transfer_state = SJCD_S_STOP; | ||
1165 | goto ReSwitch; | ||
1166 | } | ||
1167 | |||
1168 | sjcd_mode = 0; /* unknown mode; should not be valid when failed */ | ||
1169 | sjcd_send_1_cmd(SCMD_SET_MODE, | ||
1170 | SCMD_MODE_COOKED); | ||
1171 | sjcd_transfer_state = SJCD_S_READ; | ||
1172 | sjcd_transfer_timeout = 1000; | ||
1173 | #if defined( SJCD_TRACE ) | ||
1174 | printk | ||
1175 | ("SJCD_S_MODE: goto SJCD_S_READ mode\n"); | ||
1176 | #endif | ||
1177 | } | ||
1178 | #if defined( SJCD_GATHER_STAT ) | ||
1179 | else | ||
1180 | statistic.mode_ticks++; | ||
1181 | #endif | ||
1182 | break; | ||
1183 | } | ||
1184 | |||
1185 | case SJCD_S_READ:{ | ||
1186 | if (sjcd_status_valid ? 1 : sjcd_check_status()) { | ||
1187 | /* | ||
1188 | * Previous command is completed. | ||
1189 | */ | ||
1190 | if (!sjcd_status_valid | ||
1191 | || sjcd_command_failed) { | ||
1192 | #if defined( SJCD_TRACE ) | ||
1193 | printk | ||
1194 | ("SJCD_S_READ: pre-cmd failed: goto to SJCD_S_STOP mode\n"); | ||
1195 | #endif | ||
1196 | sjcd_transfer_state = SJCD_S_STOP; | ||
1197 | goto ReSwitch; | ||
1198 | } | ||
1199 | if (!sjcd_media_is_available) { | ||
1200 | #if defined( SJCD_TRACE ) | ||
1201 | printk | ||
1202 | ("SJCD_S_READ: no disk: goto to SJCD_S_STOP mode\n"); | ||
1203 | #endif | ||
1204 | sjcd_transfer_state = SJCD_S_STOP; | ||
1205 | goto ReSwitch; | ||
1206 | } | ||
1207 | if (sjcd_mode != SCMD_MODE_COOKED) { | ||
1208 | /* | ||
1209 | * We seem to come from set mode. So discard one byte of result. | ||
1210 | */ | ||
1211 | if (sjcd_load_response | ||
1212 | (&sjcd_mode, 1) != 0) { | ||
1213 | #if defined( SJCD_TRACE ) | ||
1214 | printk | ||
1215 | ("SJCD_S_READ: load failed: goto to SJCD_S_STOP mode\n"); | ||
1216 | #endif | ||
1217 | sjcd_transfer_state = | ||
1218 | SJCD_S_STOP; | ||
1219 | goto ReSwitch; | ||
1220 | } | ||
1221 | if (sjcd_mode != SCMD_MODE_COOKED) { | ||
1222 | #if defined( SJCD_TRACE ) | ||
1223 | printk | ||
1224 | ("SJCD_S_READ: mode failed: goto to SJCD_S_STOP mode\n"); | ||
1225 | #endif | ||
1226 | sjcd_transfer_state = | ||
1227 | SJCD_S_STOP; | ||
1228 | goto ReSwitch; | ||
1229 | } | ||
1230 | } | ||
1231 | |||
1232 | if (current_valid()) { | ||
1233 | struct sjcd_play_msf msf; | ||
1234 | |||
1235 | sjcd_next_bn = CURRENT->sector / 4; | ||
1236 | hsg2msf(sjcd_next_bn, &msf.start); | ||
1237 | msf.end.min = 0; | ||
1238 | msf.end.sec = 0; | ||
1239 | msf.end.frame = sjcd_read_count = | ||
1240 | SJCD_BUF_SIZ; | ||
1241 | #if defined( SJCD_TRACE ) | ||
1242 | printk | ||
1243 | ("SJCD: ---reading msf-address %x:%x:%x %x:%x:%x\n", | ||
1244 | msf.start.min, msf.start.sec, | ||
1245 | msf.start.frame, msf.end.min, | ||
1246 | msf.end.sec, msf.end.frame); | ||
1247 | printk | ||
1248 | ("sjcd_next_bn:%x buf_in:%x buf_out:%x buf_bn:%x\n", | ||
1249 | sjcd_next_bn, sjcd_buf_in, | ||
1250 | sjcd_buf_out, | ||
1251 | sjcd_buf_bn[sjcd_buf_in]); | ||
1252 | #endif | ||
1253 | sjcd_send_6_cmd(SCMD_DATA_READ, | ||
1254 | &msf); | ||
1255 | sjcd_transfer_state = SJCD_S_DATA; | ||
1256 | sjcd_transfer_timeout = 500; | ||
1257 | #if defined( SJCD_TRACE ) | ||
1258 | printk | ||
1259 | ("SJCD_S_READ: go to SJCD_S_DATA mode\n"); | ||
1260 | #endif | ||
1261 | } else { | ||
1262 | #if defined( SJCD_TRACE ) | ||
1263 | printk | ||
1264 | ("SJCD_S_READ: nothing to read: go to SJCD_S_STOP mode\n"); | ||
1265 | #endif | ||
1266 | sjcd_transfer_state = SJCD_S_STOP; | ||
1267 | goto ReSwitch; | ||
1268 | } | ||
1269 | } | ||
1270 | #if defined( SJCD_GATHER_STAT ) | ||
1271 | else | ||
1272 | statistic.read_ticks++; | ||
1273 | #endif | ||
1274 | break; | ||
1275 | } | ||
1276 | |||
1277 | case SJCD_S_DATA:{ | ||
1278 | unsigned char stat; | ||
1279 | |||
1280 | sjcd_s_data:stat = | ||
1281 | inb(SJCDPORT | ||
1282 | (1)); | ||
1283 | #if defined( SJCD_TRACE ) | ||
1284 | printk("SJCD_S_DATA: status = 0x%02x\n", stat); | ||
1285 | #endif | ||
1286 | if (SJCD_STATUS_AVAILABLE(stat)) { | ||
1287 | /* | ||
1288 | * No data is waiting for us in the drive buffer. Status of operation | ||
1289 | * completion is available. Read and parse it. | ||
1290 | */ | ||
1291 | sjcd_load_status(); | ||
1292 | |||
1293 | if (!sjcd_status_valid | ||
1294 | || sjcd_command_failed) { | ||
1295 | #if defined( SJCD_TRACE ) | ||
1296 | printk | ||
1297 | ("SJCD: read block %d failed, maybe audio disk? Giving up\n", | ||
1298 | sjcd_next_bn); | ||
1299 | #endif | ||
1300 | if (current_valid()) | ||
1301 | end_request(CURRENT, 0); | ||
1302 | #if defined( SJCD_TRACE ) | ||
1303 | printk | ||
1304 | ("SJCD_S_DATA: pre-cmd failed: go to SJCD_S_STOP mode\n"); | ||
1305 | #endif | ||
1306 | sjcd_transfer_state = SJCD_S_STOP; | ||
1307 | goto ReSwitch; | ||
1308 | } | ||
1309 | |||
1310 | if (!sjcd_media_is_available) { | ||
1311 | printk | ||
1312 | ("SJCD_S_DATA: no disk: go to SJCD_S_STOP mode\n"); | ||
1313 | sjcd_transfer_state = SJCD_S_STOP; | ||
1314 | goto ReSwitch; | ||
1315 | } | ||
1316 | |||
1317 | sjcd_transfer_state = SJCD_S_READ; | ||
1318 | goto ReSwitch; | ||
1319 | } else if (SJCD_DATA_AVAILABLE(stat)) { | ||
1320 | /* | ||
1321 | * One frame is read into device buffer. We must copy it to our memory. | ||
1322 | * Otherwise cdrom hangs up. Check to see if we have something to copy | ||
1323 | * to. | ||
1324 | */ | ||
1325 | if (!current_valid() | ||
1326 | && sjcd_buf_in == sjcd_buf_out) { | ||
1327 | #if defined( SJCD_TRACE ) | ||
1328 | printk | ||
1329 | ("SJCD_S_DATA: nothing to read: go to SJCD_S_STOP mode\n"); | ||
1330 | printk | ||
1331 | (" ... all the date would be discarded\n"); | ||
1332 | #endif | ||
1333 | sjcd_transfer_state = SJCD_S_STOP; | ||
1334 | goto ReSwitch; | ||
1335 | } | ||
1336 | |||
1337 | /* | ||
1338 | * Everything seems to be OK. Just read the frame and recalculate | ||
1339 | * indices. | ||
1340 | */ | ||
1341 | sjcd_buf_bn[sjcd_buf_in] = -1; /* ??? */ | ||
1342 | insb(SJCDPORT(2), | ||
1343 | sjcd_buf + 2048 * sjcd_buf_in, 2048); | ||
1344 | #if defined( SJCD_TRACE ) | ||
1345 | printk | ||
1346 | ("SJCD_S_DATA: next_bn=%d, buf_in=%d, buf_out=%d, buf_bn=%d\n", | ||
1347 | sjcd_next_bn, sjcd_buf_in, | ||
1348 | sjcd_buf_out, | ||
1349 | sjcd_buf_bn[sjcd_buf_in]); | ||
1350 | #endif | ||
1351 | sjcd_buf_bn[sjcd_buf_in] = sjcd_next_bn++; | ||
1352 | if (sjcd_buf_out == -1) | ||
1353 | sjcd_buf_out = sjcd_buf_in; | ||
1354 | if (++sjcd_buf_in == SJCD_BUF_SIZ) | ||
1355 | sjcd_buf_in = 0; | ||
1356 | |||
1357 | /* | ||
1358 | * Only one frame is ready at time. So we should turn over to wait for | ||
1359 | * another frame. If we need that, of course. | ||
1360 | */ | ||
1361 | if (--sjcd_read_count == 0) { | ||
1362 | /* | ||
1363 | * OK, request seems to be precessed. Continue transferring... | ||
1364 | */ | ||
1365 | if (!sjcd_transfer_is_active) { | ||
1366 | while (current_valid()) { | ||
1367 | /* | ||
1368 | * Continue transferring. | ||
1369 | */ | ||
1370 | sjcd_transfer(); | ||
1371 | if (CURRENT-> | ||
1372 | nr_sectors == | ||
1373 | 0) | ||
1374 | end_request | ||
1375 | (CURRENT, 1); | ||
1376 | else | ||
1377 | break; | ||
1378 | } | ||
1379 | } | ||
1380 | if (current_valid() && | ||
1381 | (CURRENT->sector / 4 < | ||
1382 | sjcd_next_bn | ||
1383 | || CURRENT->sector / 4 > | ||
1384 | sjcd_next_bn + | ||
1385 | SJCD_BUF_SIZ)) { | ||
1386 | #if defined( SJCD_TRACE ) | ||
1387 | printk | ||
1388 | ("SJCD_S_DATA: can't read: go to SJCD_S_STOP mode\n"); | ||
1389 | #endif | ||
1390 | sjcd_transfer_state = | ||
1391 | SJCD_S_STOP; | ||
1392 | goto ReSwitch; | ||
1393 | } | ||
1394 | } | ||
1395 | /* | ||
1396 | * Now we should turn around rather than wait for while. | ||
1397 | */ | ||
1398 | goto sjcd_s_data; | ||
1399 | } | ||
1400 | #if defined( SJCD_GATHER_STAT ) | ||
1401 | else | ||
1402 | statistic.data_ticks++; | ||
1403 | #endif | ||
1404 | break; | ||
1405 | } | ||
1406 | |||
1407 | case SJCD_S_STOP:{ | ||
1408 | sjcd_read_count = 0; | ||
1409 | sjcd_send_cmd(SCMD_STOP); | ||
1410 | sjcd_transfer_state = SJCD_S_STOPPING; | ||
1411 | sjcd_transfer_timeout = 500; | ||
1412 | #if defined( SJCD_GATHER_STAT ) | ||
1413 | statistic.stop_ticks++; | ||
1414 | #endif | ||
1415 | break; | ||
1416 | } | ||
1417 | |||
1418 | case SJCD_S_STOPPING:{ | ||
1419 | unsigned char stat; | ||
1420 | |||
1421 | stat = inb(SJCDPORT(1)); | ||
1422 | #if defined( SJCD_TRACE ) | ||
1423 | printk("SJCD_S_STOP: status = 0x%02x\n", stat); | ||
1424 | #endif | ||
1425 | if (SJCD_DATA_AVAILABLE(stat)) { | ||
1426 | int i; | ||
1427 | #if defined( SJCD_TRACE ) | ||
1428 | printk("SJCD_S_STOP: discard data\n"); | ||
1429 | #endif | ||
1430 | /* | ||
1431 | * Discard all the data from the pipe. Foolish method. | ||
1432 | */ | ||
1433 | for (i = 2048; i--; | ||
1434 | (void) inb(SJCDPORT(2))); | ||
1435 | sjcd_transfer_timeout = 500; | ||
1436 | } else if (SJCD_STATUS_AVAILABLE(stat)) { | ||
1437 | sjcd_load_status(); | ||
1438 | if (sjcd_status_valid | ||
1439 | && sjcd_media_is_changed) { | ||
1440 | sjcd_toc_uptodate = 0; | ||
1441 | sjcd_invalidate_buffers(); | ||
1442 | } | ||
1443 | if (current_valid()) { | ||
1444 | if (sjcd_status_valid) | ||
1445 | sjcd_transfer_state = | ||
1446 | SJCD_S_READ; | ||
1447 | else | ||
1448 | sjcd_transfer_state = | ||
1449 | SJCD_S_START; | ||
1450 | } else | ||
1451 | sjcd_transfer_state = SJCD_S_IDLE; | ||
1452 | goto ReSwitch; | ||
1453 | } | ||
1454 | #if defined( SJCD_GATHER_STAT ) | ||
1455 | else | ||
1456 | statistic.stopping_ticks++; | ||
1457 | #endif | ||
1458 | break; | ||
1459 | } | ||
1460 | |||
1461 | default: | ||
1462 | printk("SJCD: poll: invalid state %d\n", | ||
1463 | sjcd_transfer_state); | ||
1464 | return; | ||
1465 | } | ||
1466 | |||
1467 | if (--sjcd_transfer_timeout == 0) { | ||
1468 | printk("SJCD: timeout in state %d\n", sjcd_transfer_state); | ||
1469 | while (current_valid()) | ||
1470 | end_request(CURRENT, 0); | ||
1471 | sjcd_send_cmd(SCMD_STOP); | ||
1472 | sjcd_transfer_state = SJCD_S_IDLE; | ||
1473 | goto ReSwitch; | ||
1474 | } | ||
1475 | |||
1476 | /* | ||
1477 | * Get back in some time. 1 should be replaced with count variable to | ||
1478 | * avoid unnecessary testings. | ||
1479 | */ | ||
1480 | SJCD_SET_TIMER(sjcd_poll, 1); | ||
1481 | } | ||
1482 | |||
1483 | static void do_sjcd_request(request_queue_t * q) | ||
1484 | { | ||
1485 | #if defined( SJCD_TRACE ) | ||
1486 | printk("SJCD: do_sjcd_request(%ld+%ld)\n", | ||
1487 | CURRENT->sector, CURRENT->nr_sectors); | ||
1488 | #endif | ||
1489 | sjcd_transfer_is_active = 1; | ||
1490 | while (current_valid()) { | ||
1491 | sjcd_transfer(); | ||
1492 | if (CURRENT->nr_sectors == 0) | ||
1493 | end_request(CURRENT, 1); | ||
1494 | else { | ||
1495 | sjcd_buf_out = -1; /* Want to read a block not in buffer */ | ||
1496 | if (sjcd_transfer_state == SJCD_S_IDLE) { | ||
1497 | if (!sjcd_toc_uptodate) { | ||
1498 | if (sjcd_update_toc() < 0) { | ||
1499 | printk | ||
1500 | ("SJCD: transfer: discard\n"); | ||
1501 | while (current_valid()) | ||
1502 | end_request(CURRENT, 0); | ||
1503 | break; | ||
1504 | } | ||
1505 | } | ||
1506 | sjcd_transfer_state = SJCD_S_START; | ||
1507 | SJCD_SET_TIMER(sjcd_poll, HZ / 100); | ||
1508 | } | ||
1509 | break; | ||
1510 | } | ||
1511 | } | ||
1512 | sjcd_transfer_is_active = 0; | ||
1513 | #if defined( SJCD_TRACE ) | ||
1514 | printk | ||
1515 | ("sjcd_next_bn:%x sjcd_buf_in:%x sjcd_buf_out:%x sjcd_buf_bn:%x\n", | ||
1516 | sjcd_next_bn, sjcd_buf_in, sjcd_buf_out, | ||
1517 | sjcd_buf_bn[sjcd_buf_in]); | ||
1518 | printk("do_sjcd_request ends\n"); | ||
1519 | #endif | ||
1520 | } | ||
1521 | |||
1522 | /* | ||
1523 | * Open the device special file. Check disk is in. | ||
1524 | */ | ||
1525 | static int sjcd_open(struct inode *ip, struct file *fp) | ||
1526 | { | ||
1527 | /* | ||
1528 | * Check the presence of device. | ||
1529 | */ | ||
1530 | if (!sjcd_present) | ||
1531 | return (-ENXIO); | ||
1532 | |||
1533 | /* | ||
1534 | * Only read operations are allowed. Really? (:-) | ||
1535 | */ | ||
1536 | if (fp->f_mode & 2) | ||
1537 | return (-EROFS); | ||
1538 | |||
1539 | if (sjcd_open_count == 0) { | ||
1540 | int s, sjcd_open_tries; | ||
1541 | /* We don't know that, do we? */ | ||
1542 | /* | ||
1543 | sjcd_audio_status = CDROM_AUDIO_NO_STATUS; | ||
1544 | */ | ||
1545 | sjcd_mode = 0; | ||
1546 | sjcd_door_was_open = 0; | ||
1547 | sjcd_transfer_state = SJCD_S_IDLE; | ||
1548 | sjcd_invalidate_buffers(); | ||
1549 | sjcd_status_valid = 0; | ||
1550 | |||
1551 | /* | ||
1552 | * Strict status checking. | ||
1553 | */ | ||
1554 | for (sjcd_open_tries = 4; --sjcd_open_tries;) { | ||
1555 | if (!sjcd_status_valid) | ||
1556 | sjcd_get_status(); | ||
1557 | if (!sjcd_status_valid) { | ||
1558 | #if defined( SJCD_DIAGNOSTIC ) | ||
1559 | printk | ||
1560 | ("SJCD: open: timed out when check status.\n"); | ||
1561 | #endif | ||
1562 | goto err_out; | ||
1563 | } else if (!sjcd_media_is_available) { | ||
1564 | #if defined( SJCD_DIAGNOSTIC ) | ||
1565 | printk("SJCD: open: no disk in drive\n"); | ||
1566 | #endif | ||
1567 | if (!sjcd_door_closed) { | ||
1568 | sjcd_door_was_open = 1; | ||
1569 | #if defined( SJCD_TRACE ) | ||
1570 | printk | ||
1571 | ("SJCD: open: close the tray\n"); | ||
1572 | #endif | ||
1573 | s = sjcd_tray_close(); | ||
1574 | if (s < 0 || !sjcd_status_valid | ||
1575 | || sjcd_command_failed) { | ||
1576 | #if defined( SJCD_DIAGNOSTIC ) | ||
1577 | printk | ||
1578 | ("SJCD: open: tray close attempt failed\n"); | ||
1579 | #endif | ||
1580 | goto err_out; | ||
1581 | } | ||
1582 | continue; | ||
1583 | } else | ||
1584 | goto err_out; | ||
1585 | } | ||
1586 | break; | ||
1587 | } | ||
1588 | s = sjcd_tray_lock(); | ||
1589 | if (s < 0 || !sjcd_status_valid || sjcd_command_failed) { | ||
1590 | #if defined( SJCD_DIAGNOSTIC ) | ||
1591 | printk("SJCD: open: tray lock attempt failed\n"); | ||
1592 | #endif | ||
1593 | goto err_out; | ||
1594 | } | ||
1595 | #if defined( SJCD_TRACE ) | ||
1596 | printk("SJCD: open: done\n"); | ||
1597 | #endif | ||
1598 | } | ||
1599 | |||
1600 | ++sjcd_open_count; | ||
1601 | return (0); | ||
1602 | |||
1603 | err_out: | ||
1604 | return (-EIO); | ||
1605 | } | ||
1606 | |||
1607 | /* | ||
1608 | * On close, we flush all sjcd blocks from the buffer cache. | ||
1609 | */ | ||
1610 | static int sjcd_release(struct inode *inode, struct file *file) | ||
1611 | { | ||
1612 | int s; | ||
1613 | |||
1614 | #if defined( SJCD_TRACE ) | ||
1615 | printk("SJCD: release\n"); | ||
1616 | #endif | ||
1617 | if (--sjcd_open_count == 0) { | ||
1618 | sjcd_invalidate_buffers(); | ||
1619 | s = sjcd_tray_unlock(); | ||
1620 | if (s < 0 || !sjcd_status_valid || sjcd_command_failed) { | ||
1621 | #if defined( SJCD_DIAGNOSTIC ) | ||
1622 | printk | ||
1623 | ("SJCD: release: tray unlock attempt failed.\n"); | ||
1624 | #endif | ||
1625 | } | ||
1626 | if (sjcd_door_was_open) { | ||
1627 | s = sjcd_tray_open(); | ||
1628 | if (s < 0 || !sjcd_status_valid | ||
1629 | || sjcd_command_failed) { | ||
1630 | #if defined( SJCD_DIAGNOSTIC ) | ||
1631 | printk | ||
1632 | ("SJCD: release: tray unload attempt failed.\n"); | ||
1633 | #endif | ||
1634 | } | ||
1635 | } | ||
1636 | } | ||
1637 | return 0; | ||
1638 | } | ||
1639 | |||
1640 | /* | ||
1641 | * A list of file operations allowed for this cdrom. | ||
1642 | */ | ||
1643 | static struct block_device_operations sjcd_fops = { | ||
1644 | .owner = THIS_MODULE, | ||
1645 | .open = sjcd_open, | ||
1646 | .release = sjcd_release, | ||
1647 | .ioctl = sjcd_ioctl, | ||
1648 | .media_changed = sjcd_disk_change, | ||
1649 | }; | ||
1650 | |||
1651 | /* | ||
1652 | * Following stuff is intended for initialization of the cdrom. It | ||
1653 | * first looks for presence of device. If the device is present, it | ||
1654 | * will be reset. Then read the version of the drive and load status. | ||
1655 | * The version is two BCD-coded bytes. | ||
1656 | */ | ||
1657 | static struct { | ||
1658 | unsigned char major, minor; | ||
1659 | } sjcd_version; | ||
1660 | |||
1661 | static struct gendisk *sjcd_disk; | ||
1662 | |||
1663 | /* | ||
1664 | * Test for presence of drive and initialize it. Called at boot time. | ||
1665 | * Probe cdrom, find out version and status. | ||
1666 | */ | ||
1667 | static int __init sjcd_init(void) | ||
1668 | { | ||
1669 | int i; | ||
1670 | |||
1671 | printk(KERN_INFO | ||
1672 | "SJCD: Sanyo CDR-H94A cdrom driver version %d.%d.\n", | ||
1673 | SJCD_VERSION_MAJOR, SJCD_VERSION_MINOR); | ||
1674 | |||
1675 | #if defined( SJCD_TRACE ) | ||
1676 | printk("SJCD: sjcd=0x%x: ", sjcd_base); | ||
1677 | #endif | ||
1678 | |||
1679 | if (register_blkdev(MAJOR_NR, "sjcd")) | ||
1680 | return -EIO; | ||
1681 | |||
1682 | sjcd_queue = blk_init_queue(do_sjcd_request, &sjcd_lock); | ||
1683 | if (!sjcd_queue) | ||
1684 | goto out0; | ||
1685 | |||
1686 | blk_queue_hardsect_size(sjcd_queue, 2048); | ||
1687 | |||
1688 | sjcd_disk = alloc_disk(1); | ||
1689 | if (!sjcd_disk) { | ||
1690 | printk(KERN_ERR "SJCD: can't allocate disk"); | ||
1691 | goto out1; | ||
1692 | } | ||
1693 | sjcd_disk->major = MAJOR_NR, | ||
1694 | sjcd_disk->first_minor = 0, | ||
1695 | sjcd_disk->fops = &sjcd_fops, | ||
1696 | sprintf(sjcd_disk->disk_name, "sjcd"); | ||
1697 | |||
1698 | if (!request_region(sjcd_base, 4,"sjcd")) { | ||
1699 | printk | ||
1700 | ("SJCD: Init failed, I/O port (%X) is already in use\n", | ||
1701 | sjcd_base); | ||
1702 | goto out2; | ||
1703 | } | ||
1704 | |||
1705 | /* | ||
1706 | * Check for card. Since we are booting now, we can't use standard | ||
1707 | * wait algorithm. | ||
1708 | */ | ||
1709 | printk(KERN_INFO "SJCD: Resetting: "); | ||
1710 | sjcd_send_cmd(SCMD_RESET); | ||
1711 | for (i = 1000; i > 0 && !sjcd_status_valid; --i) { | ||
1712 | unsigned long timer; | ||
1713 | |||
1714 | /* | ||
1715 | * Wait 10ms approx. | ||
1716 | */ | ||
1717 | for (timer = jiffies; time_before_eq(jiffies, timer);); | ||
1718 | if ((i % 100) == 0) | ||
1719 | printk("."); | ||
1720 | (void) sjcd_check_status(); | ||
1721 | } | ||
1722 | if (i == 0 || sjcd_command_failed) { | ||
1723 | printk(" reset failed, no drive found.\n"); | ||
1724 | goto out3; | ||
1725 | } else | ||
1726 | printk("\n"); | ||
1727 | |||
1728 | /* | ||
1729 | * Get and print out cdrom version. | ||
1730 | */ | ||
1731 | printk(KERN_INFO "SJCD: Getting version: "); | ||
1732 | sjcd_send_cmd(SCMD_GET_VERSION); | ||
1733 | for (i = 1000; i > 0 && !sjcd_status_valid; --i) { | ||
1734 | unsigned long timer; | ||
1735 | |||
1736 | /* | ||
1737 | * Wait 10ms approx. | ||
1738 | */ | ||
1739 | for (timer = jiffies; time_before_eq(jiffies, timer);); | ||
1740 | if ((i % 100) == 0) | ||
1741 | printk("."); | ||
1742 | (void) sjcd_check_status(); | ||
1743 | } | ||
1744 | if (i == 0 || sjcd_command_failed) { | ||
1745 | printk(" get version failed, no drive found.\n"); | ||
1746 | goto out3; | ||
1747 | } | ||
1748 | |||
1749 | if (sjcd_load_response(&sjcd_version, sizeof(sjcd_version)) == 0) { | ||
1750 | printk(" %1x.%02x\n", (int) sjcd_version.major, | ||
1751 | (int) sjcd_version.minor); | ||
1752 | } else { | ||
1753 | printk(" read version failed, no drive found.\n"); | ||
1754 | goto out3; | ||
1755 | } | ||
1756 | |||
1757 | /* | ||
1758 | * Check and print out the tray state. (if it is needed?). | ||
1759 | */ | ||
1760 | if (!sjcd_status_valid) { | ||
1761 | printk(KERN_INFO "SJCD: Getting status: "); | ||
1762 | sjcd_send_cmd(SCMD_GET_STATUS); | ||
1763 | for (i = 1000; i > 0 && !sjcd_status_valid; --i) { | ||
1764 | unsigned long timer; | ||
1765 | |||
1766 | /* | ||
1767 | * Wait 10ms approx. | ||
1768 | */ | ||
1769 | for (timer = jiffies; | ||
1770 | time_before_eq(jiffies, timer);); | ||
1771 | if ((i % 100) == 0) | ||
1772 | printk("."); | ||
1773 | (void) sjcd_check_status(); | ||
1774 | } | ||
1775 | if (i == 0 || sjcd_command_failed) { | ||
1776 | printk(" get status failed, no drive found.\n"); | ||
1777 | goto out3; | ||
1778 | } else | ||
1779 | printk("\n"); | ||
1780 | } | ||
1781 | |||
1782 | printk(KERN_INFO "SJCD: Status: port=0x%x.\n", sjcd_base); | ||
1783 | sjcd_disk->queue = sjcd_queue; | ||
1784 | add_disk(sjcd_disk); | ||
1785 | |||
1786 | sjcd_present++; | ||
1787 | return (0); | ||
1788 | out3: | ||
1789 | release_region(sjcd_base, 4); | ||
1790 | out2: | ||
1791 | put_disk(sjcd_disk); | ||
1792 | out1: | ||
1793 | blk_cleanup_queue(sjcd_queue); | ||
1794 | out0: | ||
1795 | if ((unregister_blkdev(MAJOR_NR, "sjcd") == -EINVAL)) | ||
1796 | printk("SJCD: cannot unregister device.\n"); | ||
1797 | return (-EIO); | ||
1798 | } | ||
1799 | |||
1800 | static void __exit sjcd_exit(void) | ||
1801 | { | ||
1802 | del_gendisk(sjcd_disk); | ||
1803 | put_disk(sjcd_disk); | ||
1804 | release_region(sjcd_base, 4); | ||
1805 | blk_cleanup_queue(sjcd_queue); | ||
1806 | if ((unregister_blkdev(MAJOR_NR, "sjcd") == -EINVAL)) | ||
1807 | printk("SJCD: cannot unregister device.\n"); | ||
1808 | printk(KERN_INFO "SJCD: module: removed.\n"); | ||
1809 | } | ||
1810 | |||
1811 | module_init(sjcd_init); | ||
1812 | module_exit(sjcd_exit); | ||
1813 | |||
1814 | MODULE_LICENSE("GPL"); | ||
1815 | MODULE_ALIAS_BLOCKDEV_MAJOR(SANYO_CDROM_MAJOR); | ||
diff --git a/drivers/cdrom/sjcd.h b/drivers/cdrom/sjcd.h deleted file mode 100644 index 0aa5e714659d..000000000000 --- a/drivers/cdrom/sjcd.h +++ /dev/null | |||
@@ -1,181 +0,0 @@ | |||
1 | /* | ||
2 | * Definitions for a Sanyo CD-ROM interface. | ||
3 | * | ||
4 | * Copyright (C) 1995 Vadim V. Model | ||
5 | * model@cecmow.enet.dec.com | ||
6 | * vadim@rbrf.msk.su | ||
7 | * vadim@ipsun.ras.ru | ||
8 | * Eric van der Maarel | ||
9 | * H.T.M.v.d.Maarel@marin.nl | ||
10 | * | ||
11 | * This information is based on mcd.c from M. Harriss and sjcd102.lst from | ||
12 | * E. Moenkeberg. | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License as published by | ||
16 | * the Free Software Foundation; either version 2 of the License, or | ||
17 | * (at your option) any later version. | ||
18 | * | ||
19 | * This program is distributed in the hope that it will be useful, | ||
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
22 | * GNU General Public License for more details. | ||
23 | * | ||
24 | * You should have received a copy of the GNU General Public License | ||
25 | * along with this program; if not, write to the Free Software | ||
26 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
27 | */ | ||
28 | |||
29 | #ifndef __SJCD_H__ | ||
30 | #define __SJCD_H__ | ||
31 | |||
32 | /* | ||
33 | * Change this to set the I/O port address as default. More flexibility | ||
34 | * come with setup implementation. | ||
35 | */ | ||
36 | #define SJCD_BASE_ADDR 0x340 | ||
37 | |||
38 | /* | ||
39 | * Change this to set the irq as default. Really SANYO do not use interrupts | ||
40 | * at all. | ||
41 | */ | ||
42 | #define SJCD_INTR_NR 0 | ||
43 | |||
44 | /* | ||
45 | * Change this to set the dma as default value. really SANYO does not use | ||
46 | * direct memory access at all. | ||
47 | */ | ||
48 | #define SJCD_DMA_NR 0 | ||
49 | |||
50 | /* | ||
51 | * Macros which allow us to find out the status of the drive. | ||
52 | */ | ||
53 | #define SJCD_STATUS_AVAILABLE( x ) (((x)&0x02)==0) | ||
54 | #define SJCD_DATA_AVAILABLE( x ) (((x)&0x01)==0) | ||
55 | |||
56 | /* | ||
57 | * Port access macro. Three ports are available: S-data port (command port), | ||
58 | * status port (read only) and D-data port (read only). | ||
59 | */ | ||
60 | #define SJCDPORT( x ) ( sjcd_base + ( x ) ) | ||
61 | #define SJCD_STATUS_PORT SJCDPORT( 1 ) | ||
62 | #define SJCD_S_DATA_PORT SJCDPORT( 0 ) | ||
63 | #define SJCD_COMMAND_PORT SJCDPORT( 0 ) | ||
64 | #define SJCD_D_DATA_PORT SJCDPORT( 2 ) | ||
65 | |||
66 | /* | ||
67 | * Drive info bits. Drive info available as first (mandatory) byte of | ||
68 | * command completion status. | ||
69 | */ | ||
70 | #define SST_NOT_READY 0x10 /* no disk in the drive (???) */ | ||
71 | #define SST_MEDIA_CHANGED 0x20 /* disk is changed */ | ||
72 | #define SST_DOOR_OPENED 0x40 /* door is open */ | ||
73 | |||
74 | /* commands */ | ||
75 | |||
76 | #define SCMD_EJECT_TRAY 0xD0 /* eject tray if not locked */ | ||
77 | #define SCMD_LOCK_TRAY 0xD2 /* lock tray when in */ | ||
78 | #define SCMD_UNLOCK_TRAY 0xD4 /* unlock tray when in */ | ||
79 | #define SCMD_CLOSE_TRAY 0xD6 /* load tray in */ | ||
80 | |||
81 | #define SCMD_RESET 0xFA /* soft reset */ | ||
82 | #define SCMD_GET_STATUS 0x80 | ||
83 | #define SCMD_GET_VERSION 0xCC | ||
84 | |||
85 | #define SCMD_DATA_READ 0xA0 /* are the same, depend on mode&args */ | ||
86 | #define SCMD_SEEK 0xA0 | ||
87 | #define SCMD_PLAY 0xA0 | ||
88 | |||
89 | #define SCMD_GET_QINFO 0xA8 | ||
90 | |||
91 | #define SCMD_SET_MODE 0xC4 | ||
92 | #define SCMD_MODE_PLAY 0xE0 | ||
93 | #define SCMD_MODE_COOKED (0xF8 & ~0x20) | ||
94 | #define SCMD_MODE_RAW 0xF9 | ||
95 | #define SCMD_MODE_x20_BIT 0x20 /* What is it for ? */ | ||
96 | |||
97 | #define SCMD_SET_VOLUME 0xAE | ||
98 | #define SCMD_PAUSE 0xE0 | ||
99 | #define SCMD_STOP 0xE0 | ||
100 | |||
101 | #define SCMD_GET_DISK_INFO 0xAA | ||
102 | |||
103 | /* | ||
104 | * Some standard arguments for SCMD_GET_DISK_INFO. | ||
105 | */ | ||
106 | #define SCMD_GET_1_TRACK 0xA0 /* get the first track information */ | ||
107 | #define SCMD_GET_L_TRACK 0xA1 /* get the last track information */ | ||
108 | #define SCMD_GET_D_SIZE 0xA2 /* get the whole disk information */ | ||
109 | |||
110 | /* | ||
111 | * Borrowed from hd.c. Allows to optimize multiple port read commands. | ||
112 | */ | ||
113 | #define S_READ_DATA( port, buf, nr ) insb( port, buf, nr ) | ||
114 | |||
115 | /* | ||
116 | * We assume that there are no audio disks with TOC length more than this | ||
117 | * number (I personally have never seen disks with more than 20 fragments). | ||
118 | */ | ||
119 | #define SJCD_MAX_TRACKS 100 | ||
120 | |||
121 | struct msf { | ||
122 | unsigned char min; | ||
123 | unsigned char sec; | ||
124 | unsigned char frame; | ||
125 | }; | ||
126 | |||
127 | struct sjcd_hw_disk_info { | ||
128 | unsigned char track_control; | ||
129 | unsigned char track_no; | ||
130 | unsigned char x, y, z; | ||
131 | union { | ||
132 | unsigned char track_no; | ||
133 | struct msf track_msf; | ||
134 | } un; | ||
135 | }; | ||
136 | |||
137 | struct sjcd_hw_qinfo { | ||
138 | unsigned char track_control; | ||
139 | unsigned char track_no; | ||
140 | unsigned char x; | ||
141 | struct msf rel; | ||
142 | struct msf abs; | ||
143 | }; | ||
144 | |||
145 | struct sjcd_play_msf { | ||
146 | struct msf start; | ||
147 | struct msf end; | ||
148 | }; | ||
149 | |||
150 | struct sjcd_disk_info { | ||
151 | unsigned char first; | ||
152 | unsigned char last; | ||
153 | struct msf disk_length; | ||
154 | struct msf first_track; | ||
155 | }; | ||
156 | |||
157 | struct sjcd_toc { | ||
158 | unsigned char ctrl_addr; | ||
159 | unsigned char track; | ||
160 | unsigned char point_index; | ||
161 | struct msf track_time; | ||
162 | struct msf disk_time; | ||
163 | }; | ||
164 | |||
165 | #if defined( SJCD_GATHER_STAT ) | ||
166 | |||
167 | struct sjcd_stat { | ||
168 | int ticks; | ||
169 | int tticks[ 8 ]; | ||
170 | int idle_ticks; | ||
171 | int start_ticks; | ||
172 | int mode_ticks; | ||
173 | int read_ticks; | ||
174 | int data_ticks; | ||
175 | int stop_ticks; | ||
176 | int stopping_ticks; | ||
177 | }; | ||
178 | |||
179 | #endif | ||
180 | |||
181 | #endif | ||
diff --git a/drivers/cdrom/sonycd535.c b/drivers/cdrom/sonycd535.c deleted file mode 100644 index f77ada933ea0..000000000000 --- a/drivers/cdrom/sonycd535.c +++ /dev/null | |||
@@ -1,1689 +0,0 @@ | |||
1 | /* | ||
2 | * Sony CDU-535 interface device driver | ||
3 | * | ||
4 | * This is a modified version of the CDU-31A device driver (see below). | ||
5 | * Changes were made using documentation for the CDU-531 (which Sony | ||
6 | * assures me is very similar to the 535) and partial disassembly of the | ||
7 | * DOS driver. I used Minyard's driver and replaced the CDU-31A | ||
8 | * commands with the CDU-531 commands. This was complicated by a different | ||
9 | * interface protocol with the drive. The driver is still polled. | ||
10 | * | ||
11 | * Data transfer rate is about 110 Kb/sec, theoretical maximum is 150 Kb/sec. | ||
12 | * I tried polling without the sony_sleep during the data transfers but | ||
13 | * it did not speed things up any. | ||
14 | * | ||
15 | * 1993-05-23 (rgj) changed the major number to 21 to get rid of conflict | ||
16 | * with CDU-31A driver. This is the also the number from the Linux | ||
17 | * Device Driver Registry for the Sony Drive. Hope nobody else is using it. | ||
18 | * | ||
19 | * 1993-08-29 (rgj) remove the configuring of the interface board address | ||
20 | * from the top level configuration, you have to modify it in this file. | ||
21 | * | ||
22 | * 1995-01-26 Made module-capable (Joel Katz <Stimpson@Panix.COM>) | ||
23 | * | ||
24 | * 1995-05-20 | ||
25 | * Modified to support CDU-510/515 series | ||
26 | * (Claudio Porfiri<C.Porfiri@nisms.tei.ericsson.se>) | ||
27 | * Fixed to report verify_area() failures | ||
28 | * (Heiko Eissfeldt <heiko@colossus.escape.de>) | ||
29 | * | ||
30 | * 1995-06-01 | ||
31 | * More changes to support CDU-510/515 series | ||
32 | * (Claudio Porfiri<C.Porfiri@nisms.tei.ericsson.se>) | ||
33 | * | ||
34 | * November 1999 -- Make kernel-parameter implementation work with 2.3.x | ||
35 | * Removed init_module & cleanup_module in favor of | ||
36 | * module_init & module_exit. | ||
37 | * Torben Mathiasen <tmm@image.dk> | ||
38 | * | ||
39 | * September 2003 - Fix SMP support by removing cli/sti calls. | ||
40 | * Using spinlocks with a wait_queue instead. | ||
41 | * Felipe Damasio <felipewd@terra.com.br> | ||
42 | * | ||
43 | * Things to do: | ||
44 | * - handle errors and status better, put everything into a single word | ||
45 | * - use interrupts (code mostly there, but a big hole still missing) | ||
46 | * - handle multi-session CDs? | ||
47 | * - use DMA? | ||
48 | * | ||
49 | * Known Bugs: | ||
50 | * - | ||
51 | * | ||
52 | * Ken Pizzini (ken@halcyon.com) | ||
53 | * | ||
54 | * Original by: | ||
55 | * Ron Jeppesen (ronj.an@site007.saic.com) | ||
56 | * | ||
57 | * | ||
58 | *------------------------------------------------------------------------ | ||
59 | * Sony CDROM interface device driver. | ||
60 | * | ||
61 | * Corey Minyard (minyard@wf-rch.cirr.com) (CDU-535 complaints to Ken above) | ||
62 | * | ||
63 | * Colossians 3:17 | ||
64 | * | ||
65 | * The Sony interface device driver handles Sony interface CDROM | ||
66 | * drives and provides a complete block-level interface as well as an | ||
67 | * ioctl() interface compatible with the Sun (as specified in | ||
68 | * include/linux/cdrom.h). With this interface, CDROMs can be | ||
69 | * accessed and standard audio CDs can be played back normally. | ||
70 | * | ||
71 | * This interface is (unfortunately) a polled interface. This is | ||
72 | * because most Sony interfaces are set up with DMA and interrupts | ||
73 | * disables. Some (like mine) do not even have the capability to | ||
74 | * handle interrupts or DMA. For this reason you will see a bit of | ||
75 | * the following: | ||
76 | * | ||
77 | * snap = jiffies; | ||
78 | * while (jiffies-snap < SONY_JIFFIES_TIMEOUT) | ||
79 | * { | ||
80 | * if (some_condition()) | ||
81 | * break; | ||
82 | * sony_sleep(); | ||
83 | * } | ||
84 | * if (some_condition not met) | ||
85 | * { | ||
86 | * return an_error; | ||
87 | * } | ||
88 | * | ||
89 | * This ugly hack waits for something to happen, sleeping a little | ||
90 | * between every try. (The conditional is written so that jiffies | ||
91 | * wrap-around is handled properly.) | ||
92 | * | ||
93 | * One thing about these drives: They talk in MSF (Minute Second Frame) format. | ||
94 | * There are 75 frames a second, 60 seconds a minute, and up to 75 minutes on a | ||
95 | * disk. The funny thing is that these are sent to the drive in BCD, but the | ||
96 | * interface wants to see them in decimal. A lot of conversion goes on. | ||
97 | * | ||
98 | * Copyright (C) 1993 Corey Minyard | ||
99 | * | ||
100 | * This program is free software; you can redistribute it and/or modify | ||
101 | * it under the terms of the GNU General Public License as published by | ||
102 | * the Free Software Foundation; either version 2 of the License, or | ||
103 | * (at your option) any later version. | ||
104 | * | ||
105 | * This program is distributed in the hope that it will be useful, | ||
106 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
107 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
108 | * GNU General Public License for more details. | ||
109 | * | ||
110 | * You should have received a copy of the GNU General Public License | ||
111 | * along with this program; if not, write to the Free Software | ||
112 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
113 | * | ||
114 | */ | ||
115 | |||
116 | |||
117 | # include <linux/module.h> | ||
118 | |||
119 | #include <linux/errno.h> | ||
120 | #include <linux/signal.h> | ||
121 | #include <linux/sched.h> | ||
122 | #include <linux/timer.h> | ||
123 | #include <linux/fs.h> | ||
124 | #include <linux/kernel.h> | ||
125 | #include <linux/interrupt.h> | ||
126 | #include <linux/ioport.h> | ||
127 | #include <linux/hdreg.h> | ||
128 | #include <linux/genhd.h> | ||
129 | #include <linux/mm.h> | ||
130 | #include <linux/slab.h> | ||
131 | #include <linux/init.h> | ||
132 | |||
133 | #define REALLY_SLOW_IO | ||
134 | #include <asm/system.h> | ||
135 | #include <asm/io.h> | ||
136 | #include <asm/uaccess.h> | ||
137 | |||
138 | #include <linux/cdrom.h> | ||
139 | |||
140 | #define MAJOR_NR CDU535_CDROM_MAJOR | ||
141 | #include <linux/blkdev.h> | ||
142 | |||
143 | #define sony535_cd_base_io sonycd535 /* for compatible parameter passing with "insmod" */ | ||
144 | #include "sonycd535.h" | ||
145 | |||
146 | /* | ||
147 | * this is the base address of the interface card for the Sony CDU-535 | ||
148 | * CDROM drive. If your jumpers are set for an address other than | ||
149 | * this one (the default), change the following line to the | ||
150 | * proper address. | ||
151 | */ | ||
152 | #ifndef CDU535_ADDRESS | ||
153 | # define CDU535_ADDRESS 0x340 | ||
154 | #endif | ||
155 | #ifndef CDU535_INTERRUPT | ||
156 | # define CDU535_INTERRUPT 0 | ||
157 | #endif | ||
158 | #ifndef CDU535_HANDLE | ||
159 | # define CDU535_HANDLE "cdu535" | ||
160 | #endif | ||
161 | #ifndef CDU535_MESSAGE_NAME | ||
162 | # define CDU535_MESSAGE_NAME "Sony CDU-535" | ||
163 | #endif | ||
164 | |||
165 | #define CDU535_BLOCK_SIZE 2048 | ||
166 | |||
167 | #ifndef MAX_SPINUP_RETRY | ||
168 | # define MAX_SPINUP_RETRY 3 /* 1 is sufficient for most drives... */ | ||
169 | #endif | ||
170 | #ifndef RETRY_FOR_BAD_STATUS | ||
171 | # define RETRY_FOR_BAD_STATUS 100 /* in 10th of second */ | ||
172 | #endif | ||
173 | |||
174 | #ifndef DEBUG | ||
175 | # define DEBUG 1 | ||
176 | #endif | ||
177 | |||
178 | /* | ||
179 | * SONY535_BUFFER_SIZE determines the size of internal buffer used | ||
180 | * by the drive. It must be at least 2K and the larger the buffer | ||
181 | * the better the transfer rate. It does however take system memory. | ||
182 | * On my system I get the following transfer rates using dd to read | ||
183 | * 10 Mb off /dev/cdrom. | ||
184 | * | ||
185 | * 8K buffer 43 Kb/sec | ||
186 | * 16K buffer 66 Kb/sec | ||
187 | * 32K buffer 91 Kb/sec | ||
188 | * 64K buffer 111 Kb/sec | ||
189 | * 128K buffer 123 Kb/sec | ||
190 | * 512K buffer 123 Kb/sec | ||
191 | */ | ||
192 | #define SONY535_BUFFER_SIZE (64*1024) | ||
193 | |||
194 | /* | ||
195 | * if LOCK_DOORS is defined then the eject button is disabled while | ||
196 | * the device is open. | ||
197 | */ | ||
198 | #ifndef NO_LOCK_DOORS | ||
199 | # define LOCK_DOORS | ||
200 | #endif | ||
201 | |||
202 | static int read_subcode(void); | ||
203 | static void sony_get_toc(void); | ||
204 | static int cdu_open(struct inode *inode, struct file *filp); | ||
205 | static inline unsigned int int_to_bcd(unsigned int val); | ||
206 | static unsigned int bcd_to_int(unsigned int bcd); | ||
207 | static int do_sony_cmd(Byte * cmd, int nCmd, Byte status[2], | ||
208 | Byte * response, int n_response, int ignoreStatusBit7); | ||
209 | |||
210 | /* The base I/O address of the Sony Interface. This is a variable (not a | ||
211 | #define) so it can be easily changed via some future ioctl() */ | ||
212 | static unsigned int sony535_cd_base_io = CDU535_ADDRESS; | ||
213 | module_param(sony535_cd_base_io, int, 0); | ||
214 | |||
215 | /* | ||
216 | * The following are I/O addresses of the various registers for the drive. The | ||
217 | * comment for the base address also applies here. | ||
218 | */ | ||
219 | static unsigned short select_unit_reg; | ||
220 | static unsigned short result_reg; | ||
221 | static unsigned short command_reg; | ||
222 | static unsigned short read_status_reg; | ||
223 | static unsigned short data_reg; | ||
224 | |||
225 | static DEFINE_SPINLOCK(sonycd535_lock); /* queue lock */ | ||
226 | static struct request_queue *sonycd535_queue; | ||
227 | |||
228 | static int initialized; /* Has the drive been initialized? */ | ||
229 | static int sony_disc_changed = 1; /* Has the disk been changed | ||
230 | since the last check? */ | ||
231 | static int sony_toc_read; /* Has the table of contents been | ||
232 | read? */ | ||
233 | static unsigned int sony_buffer_size; /* Size in bytes of the read-ahead | ||
234 | buffer. */ | ||
235 | static unsigned int sony_buffer_sectors; /* Size (in 2048 byte records) of | ||
236 | the read-ahead buffer. */ | ||
237 | static unsigned int sony_usage; /* How many processes have the | ||
238 | drive open. */ | ||
239 | |||
240 | static int sony_first_block = -1; /* First OS block (512 byte) in | ||
241 | the read-ahead buffer */ | ||
242 | static int sony_last_block = -1; /* Last OS block (512 byte) in | ||
243 | the read-ahead buffer */ | ||
244 | |||
245 | static struct s535_sony_toc *sony_toc; /* Points to the table of | ||
246 | contents. */ | ||
247 | |||
248 | static struct s535_sony_subcode *last_sony_subcode; /* Points to the last | ||
249 | subcode address read */ | ||
250 | static Byte **sony_buffer; /* Points to the pointers | ||
251 | to the sector buffers */ | ||
252 | |||
253 | static int sony_inuse; /* is the drive in use? Only one | ||
254 | open at a time allowed */ | ||
255 | |||
256 | /* | ||
257 | * The audio status uses the values from read subchannel data as specified | ||
258 | * in include/linux/cdrom.h. | ||
259 | */ | ||
260 | static int sony_audio_status = CDROM_AUDIO_NO_STATUS; | ||
261 | |||
262 | /* | ||
263 | * The following are a hack for pausing and resuming audio play. The drive | ||
264 | * does not work as I would expect it, if you stop it then start it again, | ||
265 | * the drive seeks back to the beginning and starts over. This holds the | ||
266 | * position during a pause so a resume can restart it. It uses the | ||
267 | * audio status variable above to tell if it is paused. | ||
268 | * I just kept the CDU-31A driver behavior rather than using the PAUSE | ||
269 | * command on the CDU-535. | ||
270 | */ | ||
271 | static Byte cur_pos_msf[3]; | ||
272 | static Byte final_pos_msf[3]; | ||
273 | |||
274 | /* What IRQ is the drive using? 0 if none. */ | ||
275 | static int sony535_irq_used = CDU535_INTERRUPT; | ||
276 | |||
277 | /* The interrupt handler will wake this queue up when it gets an interrupt. */ | ||
278 | static DECLARE_WAIT_QUEUE_HEAD(cdu535_irq_wait); | ||
279 | |||
280 | |||
281 | /* | ||
282 | * This routine returns 1 if the disk has been changed since the last | ||
283 | * check or 0 if it hasn't. Setting flag to 0 resets the changed flag. | ||
284 | */ | ||
285 | static int | ||
286 | cdu535_check_media_change(struct gendisk *disk) | ||
287 | { | ||
288 | /* if driver is not initialized, always return 0 */ | ||
289 | int retval = initialized ? sony_disc_changed : 0; | ||
290 | sony_disc_changed = 0; | ||
291 | return retval; | ||
292 | } | ||
293 | |||
294 | static inline void | ||
295 | enable_interrupts(void) | ||
296 | { | ||
297 | #ifdef USE_IRQ | ||
298 | /* | ||
299 | * This code was taken from cdu31a.c; it will not | ||
300 | * directly work for the cdu535 as written... | ||
301 | */ | ||
302 | curr_control_reg |= ( SONY_ATTN_INT_EN_BIT | ||
303 | | SONY_RES_RDY_INT_EN_BIT | ||
304 | | SONY_DATA_RDY_INT_EN_BIT); | ||
305 | outb(curr_control_reg, sony_cd_control_reg); | ||
306 | #endif | ||
307 | } | ||
308 | |||
309 | static inline void | ||
310 | disable_interrupts(void) | ||
311 | { | ||
312 | #ifdef USE_IRQ | ||
313 | /* | ||
314 | * This code was taken from cdu31a.c; it will not | ||
315 | * directly work for the cdu535 as written... | ||
316 | */ | ||
317 | curr_control_reg &= ~(SONY_ATTN_INT_EN_BIT | ||
318 | | SONY_RES_RDY_INT_EN_BIT | ||
319 | | SONY_DATA_RDY_INT_EN_BIT); | ||
320 | outb(curr_control_reg, sony_cd_control_reg); | ||
321 | #endif | ||
322 | } | ||
323 | |||
324 | static irqreturn_t | ||
325 | cdu535_interrupt(int irq, void *dev_id) | ||
326 | { | ||
327 | disable_interrupts(); | ||
328 | if (waitqueue_active(&cdu535_irq_wait)) { | ||
329 | wake_up(&cdu535_irq_wait); | ||
330 | return IRQ_HANDLED; | ||
331 | } | ||
332 | printk(CDU535_MESSAGE_NAME | ||
333 | ": Got an interrupt but nothing was waiting\n"); | ||
334 | return IRQ_NONE; | ||
335 | } | ||
336 | |||
337 | |||
338 | /* | ||
339 | * Wait a little while. | ||
340 | */ | ||
341 | static inline void | ||
342 | sony_sleep(void) | ||
343 | { | ||
344 | if (sony535_irq_used <= 0) { /* poll */ | ||
345 | yield(); | ||
346 | } else { /* Interrupt driven */ | ||
347 | DEFINE_WAIT(wait); | ||
348 | |||
349 | spin_lock_irq(&sonycd535_lock); | ||
350 | enable_interrupts(); | ||
351 | prepare_to_wait(&cdu535_irq_wait, &wait, TASK_INTERRUPTIBLE); | ||
352 | spin_unlock_irq(&sonycd535_lock); | ||
353 | schedule(); | ||
354 | finish_wait(&cdu535_irq_wait, &wait); | ||
355 | } | ||
356 | } | ||
357 | |||
358 | /*------------------start of SONY CDU535 very specific ---------------------*/ | ||
359 | |||
360 | /**************************************************************************** | ||
361 | * void select_unit( int unit_no ) | ||
362 | * | ||
363 | * Select the specified unit (0-3) so that subsequent commands reference it | ||
364 | ****************************************************************************/ | ||
365 | static void | ||
366 | select_unit(int unit_no) | ||
367 | { | ||
368 | unsigned int select_mask = ~(1 << unit_no); | ||
369 | outb(select_mask, select_unit_reg); | ||
370 | } | ||
371 | |||
372 | /*************************************************************************** | ||
373 | * int read_result_reg( Byte *data_ptr ) | ||
374 | * | ||
375 | * Read a result byte from the Sony CDU controller, store in location pointed | ||
376 | * to by data_ptr. Return zero on success, TIME_OUT if we did not receive | ||
377 | * data. | ||
378 | ***************************************************************************/ | ||
379 | static int | ||
380 | read_result_reg(Byte *data_ptr) | ||
381 | { | ||
382 | unsigned long snap; | ||
383 | int read_status; | ||
384 | |||
385 | snap = jiffies; | ||
386 | while (jiffies-snap < SONY_JIFFIES_TIMEOUT) { | ||
387 | read_status = inb(read_status_reg); | ||
388 | if ((read_status & SONY535_RESULT_NOT_READY_BIT) == 0) { | ||
389 | #if DEBUG > 1 | ||
390 | printk(CDU535_MESSAGE_NAME | ||
391 | ": read_result_reg(): readStatReg = 0x%x\n", read_status); | ||
392 | #endif | ||
393 | *data_ptr = inb(result_reg); | ||
394 | return 0; | ||
395 | } else { | ||
396 | sony_sleep(); | ||
397 | } | ||
398 | } | ||
399 | printk(CDU535_MESSAGE_NAME " read_result_reg: TIME OUT!\n"); | ||
400 | return TIME_OUT; | ||
401 | } | ||
402 | |||
403 | /**************************************************************************** | ||
404 | * int read_exec_status( Byte status[2] ) | ||
405 | * | ||
406 | * Read the execution status of the last command and put into status. | ||
407 | * Handles reading second status word if available. Returns 0 on success, | ||
408 | * TIME_OUT on failure. | ||
409 | ****************************************************************************/ | ||
410 | static int | ||
411 | read_exec_status(Byte status[2]) | ||
412 | { | ||
413 | status[1] = 0; | ||
414 | if (read_result_reg(&(status[0])) != 0) | ||
415 | return TIME_OUT; | ||
416 | if ((status[0] & 0x80) != 0) { /* byte two follows */ | ||
417 | if (read_result_reg(&(status[1])) != 0) | ||
418 | return TIME_OUT; | ||
419 | } | ||
420 | #if DEBUG > 1 | ||
421 | printk(CDU535_MESSAGE_NAME ": read_exec_status: read 0x%x 0x%x\n", | ||
422 | status[0], status[1]); | ||
423 | #endif | ||
424 | return 0; | ||
425 | } | ||
426 | |||
427 | /**************************************************************************** | ||
428 | * int check_drive_status( void ) | ||
429 | * | ||
430 | * Check the current drive status. Using this before executing a command | ||
431 | * takes care of the problem of unsolicited drive status-2 messages. | ||
432 | * Add a check of the audio status if we think the disk is playing. | ||
433 | ****************************************************************************/ | ||
434 | static int | ||
435 | check_drive_status(void) | ||
436 | { | ||
437 | Byte status, e_status[2]; | ||
438 | int CDD, ATN; | ||
439 | Byte cmd; | ||
440 | |||
441 | select_unit(0); | ||
442 | if (sony_audio_status == CDROM_AUDIO_PLAY) { /* check status */ | ||
443 | outb(SONY535_REQUEST_AUDIO_STATUS, command_reg); | ||
444 | if (read_result_reg(&status) == 0) { | ||
445 | switch (status) { | ||
446 | case 0x0: | ||
447 | break; /* play in progress */ | ||
448 | case 0x1: | ||
449 | break; /* paused */ | ||
450 | case 0x3: /* audio play completed */ | ||
451 | case 0x5: /* play not requested */ | ||
452 | sony_audio_status = CDROM_AUDIO_COMPLETED; | ||
453 | read_subcode(); | ||
454 | break; | ||
455 | case 0x4: /* error during play */ | ||
456 | sony_audio_status = CDROM_AUDIO_ERROR; | ||
457 | break; | ||
458 | } | ||
459 | } | ||
460 | } | ||
461 | /* now check drive status */ | ||
462 | outb(SONY535_REQUEST_DRIVE_STATUS_2, command_reg); | ||
463 | if (read_result_reg(&status) != 0) | ||
464 | return TIME_OUT; | ||
465 | |||
466 | #if DEBUG > 1 | ||
467 | printk(CDU535_MESSAGE_NAME ": check_drive_status() got 0x%x\n", status); | ||
468 | #endif | ||
469 | |||
470 | if (status == 0) | ||
471 | return 0; | ||
472 | |||
473 | ATN = status & 0xf; | ||
474 | CDD = (status >> 4) & 0xf; | ||
475 | |||
476 | switch (ATN) { | ||
477 | case 0x0: | ||
478 | break; /* go on to CDD stuff */ | ||
479 | case SONY535_ATN_BUSY: | ||
480 | if (initialized) | ||
481 | printk(CDU535_MESSAGE_NAME " error: drive busy\n"); | ||
482 | return CD_BUSY; | ||
483 | case SONY535_ATN_EJECT_IN_PROGRESS: | ||
484 | printk(CDU535_MESSAGE_NAME " error: eject in progress\n"); | ||
485 | sony_audio_status = CDROM_AUDIO_INVALID; | ||
486 | return CD_BUSY; | ||
487 | case SONY535_ATN_RESET_OCCURRED: | ||
488 | case SONY535_ATN_DISC_CHANGED: | ||
489 | case SONY535_ATN_RESET_AND_DISC_CHANGED: | ||
490 | #if DEBUG > 0 | ||
491 | printk(CDU535_MESSAGE_NAME " notice: reset occurred or disc changed\n"); | ||
492 | #endif | ||
493 | sony_disc_changed = 1; | ||
494 | sony_toc_read = 0; | ||
495 | sony_audio_status = CDROM_AUDIO_NO_STATUS; | ||
496 | sony_first_block = -1; | ||
497 | sony_last_block = -1; | ||
498 | if (initialized) { | ||
499 | cmd = SONY535_SPIN_UP; | ||
500 | do_sony_cmd(&cmd, 1, e_status, NULL, 0, 0); | ||
501 | sony_get_toc(); | ||
502 | } | ||
503 | return 0; | ||
504 | default: | ||
505 | printk(CDU535_MESSAGE_NAME " error: drive busy (ATN=0x%x)\n", ATN); | ||
506 | return CD_BUSY; | ||
507 | } | ||
508 | switch (CDD) { /* the 531 docs are not helpful in decoding this */ | ||
509 | case 0x0: /* just use the values from the DOS driver */ | ||
510 | case 0x2: | ||
511 | case 0xa: | ||
512 | break; /* no error */ | ||
513 | case 0xc: | ||
514 | printk(CDU535_MESSAGE_NAME | ||
515 | ": check_drive_status(): CDD = 0xc! Not properly handled!\n"); | ||
516 | return CD_BUSY; /* ? */ | ||
517 | default: | ||
518 | return CD_BUSY; | ||
519 | } | ||
520 | return 0; | ||
521 | } /* check_drive_status() */ | ||
522 | |||
523 | /***************************************************************************** | ||
524 | * int do_sony_cmd( Byte *cmd, int n_cmd, Byte status[2], | ||
525 | * Byte *response, int n_response, int ignore_status_bit7 ) | ||
526 | * | ||
527 | * Generic routine for executing commands. The command and its parameters | ||
528 | * should be placed in the cmd[] array, number of bytes in the command is | ||
529 | * stored in nCmd. The response from the command will be stored in the | ||
530 | * response array. The number of bytes you expect back (excluding status) | ||
531 | * should be passed in n_response. Finally, some | ||
532 | * commands set bit 7 of the return status even when there is no second | ||
533 | * status byte, on these commands set ignoreStatusBit7 TRUE. | ||
534 | * If the command was sent and data received back, then we return 0, | ||
535 | * else we return TIME_OUT. You still have to check the status yourself. | ||
536 | * You should call check_drive_status() before calling this routine | ||
537 | * so that you do not lose notifications of disk changes, etc. | ||
538 | ****************************************************************************/ | ||
539 | static int | ||
540 | do_sony_cmd(Byte * cmd, int n_cmd, Byte status[2], | ||
541 | Byte * response, int n_response, int ignore_status_bit7) | ||
542 | { | ||
543 | int i; | ||
544 | |||
545 | /* write out the command */ | ||
546 | for (i = 0; i < n_cmd; i++) | ||
547 | outb(cmd[i], command_reg); | ||
548 | |||
549 | /* read back the status */ | ||
550 | if (read_result_reg(status) != 0) | ||
551 | return TIME_OUT; | ||
552 | if (!ignore_status_bit7 && ((status[0] & 0x80) != 0)) { | ||
553 | /* get second status byte */ | ||
554 | if (read_result_reg(status + 1) != 0) | ||
555 | return TIME_OUT; | ||
556 | } else { | ||
557 | status[1] = 0; | ||
558 | } | ||
559 | #if DEBUG > 2 | ||
560 | printk(CDU535_MESSAGE_NAME ": do_sony_cmd %x: %x %x\n", | ||
561 | *cmd, status[0], status[1]); | ||
562 | #endif | ||
563 | |||
564 | /* do not know about when I should read set of data and when not to */ | ||
565 | if ((status[0] & ((ignore_status_bit7 ? 0x7f : 0xff) & 0x8f)) != 0) | ||
566 | return 0; | ||
567 | |||
568 | /* else, read in rest of data */ | ||
569 | for (i = 0; 0 < n_response; n_response--, i++) | ||
570 | if (read_result_reg(response + i) != 0) | ||
571 | return TIME_OUT; | ||
572 | return 0; | ||
573 | } /* do_sony_cmd() */ | ||
574 | |||
575 | /************************************************************************** | ||
576 | * int set_drive_mode( int mode, Byte status[2] ) | ||
577 | * | ||
578 | * Set the drive mode to the specified value (mode=0 is audio, mode=e0 | ||
579 | * is mode-1 CDROM | ||
580 | **************************************************************************/ | ||
581 | static int | ||
582 | set_drive_mode(int mode, Byte status[2]) | ||
583 | { | ||
584 | Byte cmd_buff[2]; | ||
585 | Byte ret_buff[1]; | ||
586 | |||
587 | cmd_buff[0] = SONY535_SET_DRIVE_MODE; | ||
588 | cmd_buff[1] = mode; | ||
589 | return do_sony_cmd(cmd_buff, 2, status, ret_buff, 1, 1); | ||
590 | } | ||
591 | |||
592 | /*************************************************************************** | ||
593 | * int seek_and_read_N_blocks( Byte params[], int n_blocks, Byte status[2], | ||
594 | * Byte *data_buff, int buff_size ) | ||
595 | * | ||
596 | * Read n_blocks of data from the CDROM starting at position params[0:2], | ||
597 | * number of blocks in stored in params[3:5] -- both these are already | ||
598 | * int bcd format. | ||
599 | * Transfer the data into the buffer pointed at by data_buff. buff_size | ||
600 | * gives the number of bytes available in the buffer. | ||
601 | * The routine returns number of bytes read in if successful, otherwise | ||
602 | * it returns one of the standard error returns. | ||
603 | ***************************************************************************/ | ||
604 | static int | ||
605 | seek_and_read_N_blocks(Byte params[], int n_blocks, Byte status[2], | ||
606 | Byte **buff, int buf_size) | ||
607 | { | ||
608 | Byte cmd_buff[7]; | ||
609 | int i; | ||
610 | int read_status; | ||
611 | unsigned long snap; | ||
612 | Byte *data_buff; | ||
613 | int sector_count = 0; | ||
614 | |||
615 | if (buf_size < CDU535_BLOCK_SIZE * n_blocks) | ||
616 | return NO_ROOM; | ||
617 | |||
618 | set_drive_mode(SONY535_CDROM_DRIVE_MODE, status); | ||
619 | |||
620 | /* send command to read the data */ | ||
621 | cmd_buff[0] = SONY535_SEEK_AND_READ_N_BLOCKS_1; | ||
622 | for (i = 0; i < 6; i++) | ||
623 | cmd_buff[i + 1] = params[i]; | ||
624 | for (i = 0; i < 7; i++) | ||
625 | outb(cmd_buff[i], command_reg); | ||
626 | |||
627 | /* read back the data one block at a time */ | ||
628 | while (0 < n_blocks--) { | ||
629 | /* wait for data to be ready */ | ||
630 | int data_valid = 0; | ||
631 | snap = jiffies; | ||
632 | while (jiffies-snap < SONY_JIFFIES_TIMEOUT) { | ||
633 | read_status = inb(read_status_reg); | ||
634 | if ((read_status & SONY535_RESULT_NOT_READY_BIT) == 0) { | ||
635 | read_exec_status(status); | ||
636 | return BAD_STATUS; | ||
637 | } | ||
638 | if ((read_status & SONY535_DATA_NOT_READY_BIT) == 0) { | ||
639 | /* data is ready, read it */ | ||
640 | data_buff = buff[sector_count++]; | ||
641 | for (i = 0; i < CDU535_BLOCK_SIZE; i++) | ||
642 | *data_buff++ = inb(data_reg); /* unrolling this loop does not seem to help */ | ||
643 | data_valid = 1; | ||
644 | break; /* exit the timeout loop */ | ||
645 | } | ||
646 | sony_sleep(); /* data not ready, sleep a while */ | ||
647 | } | ||
648 | if (!data_valid) | ||
649 | return TIME_OUT; /* if we reach this stage */ | ||
650 | } | ||
651 | |||
652 | /* read all the data, now read the status */ | ||
653 | if ((i = read_exec_status(status)) != 0) | ||
654 | return i; | ||
655 | return CDU535_BLOCK_SIZE * sector_count; | ||
656 | } /* seek_and_read_N_blocks() */ | ||
657 | |||
658 | /**************************************************************************** | ||
659 | * int request_toc_data( Byte status[2], struct s535_sony_toc *toc ) | ||
660 | * | ||
661 | * Read in the table of contents data. Converts all the bcd data | ||
662 | * into integers in the toc structure. | ||
663 | ****************************************************************************/ | ||
664 | static int | ||
665 | request_toc_data(Byte status[2], struct s535_sony_toc *toc) | ||
666 | { | ||
667 | int to_status; | ||
668 | int i, j, n_tracks, track_no; | ||
669 | int first_track_num, last_track_num; | ||
670 | Byte cmd_no = 0xb2; | ||
671 | Byte track_address_buffer[5]; | ||
672 | |||
673 | /* read the fixed portion of the table of contents */ | ||
674 | if ((to_status = do_sony_cmd(&cmd_no, 1, status, (Byte *) toc, 15, 1)) != 0) | ||
675 | return to_status; | ||
676 | |||
677 | /* convert the data into integers so we can use them */ | ||
678 | first_track_num = bcd_to_int(toc->first_track_num); | ||
679 | last_track_num = bcd_to_int(toc->last_track_num); | ||
680 | n_tracks = last_track_num - first_track_num + 1; | ||
681 | |||
682 | /* read each of the track address descriptors */ | ||
683 | for (i = 0; i < n_tracks; i++) { | ||
684 | /* read the descriptor into a temporary buffer */ | ||
685 | for (j = 0; j < 5; j++) { | ||
686 | if (read_result_reg(track_address_buffer + j) != 0) | ||
687 | return TIME_OUT; | ||
688 | if (j == 1) /* need to convert from bcd */ | ||
689 | track_no = bcd_to_int(track_address_buffer[j]); | ||
690 | } | ||
691 | /* copy the descriptor to proper location - sonycd.c just fills */ | ||
692 | memcpy(toc->tracks + i, track_address_buffer, 5); | ||
693 | } | ||
694 | return 0; | ||
695 | } /* request_toc_data() */ | ||
696 | |||
697 | /*************************************************************************** | ||
698 | * int spin_up_drive( Byte status[2] ) | ||
699 | * | ||
700 | * Spin up the drive (unless it is already spinning). | ||
701 | ***************************************************************************/ | ||
702 | static int | ||
703 | spin_up_drive(Byte status[2]) | ||
704 | { | ||
705 | Byte cmd; | ||
706 | |||
707 | /* first see if the drive is already spinning */ | ||
708 | cmd = SONY535_REQUEST_DRIVE_STATUS_1; | ||
709 | if (do_sony_cmd(&cmd, 1, status, NULL, 0, 0) != 0) | ||
710 | return TIME_OUT; | ||
711 | if ((status[0] & SONY535_STATUS1_NOT_SPINNING) == 0) | ||
712 | return 0; /* it's already spinning */ | ||
713 | |||
714 | /* otherwise, give the spin-up command */ | ||
715 | cmd = SONY535_SPIN_UP; | ||
716 | return do_sony_cmd(&cmd, 1, status, NULL, 0, 0); | ||
717 | } | ||
718 | |||
719 | /*--------------------end of SONY CDU535 very specific ---------------------*/ | ||
720 | |||
721 | /* Convert from an integer 0-99 to BCD */ | ||
722 | static inline unsigned int | ||
723 | int_to_bcd(unsigned int val) | ||
724 | { | ||
725 | int retval; | ||
726 | |||
727 | retval = (val / 10) << 4; | ||
728 | retval = retval | val % 10; | ||
729 | return retval; | ||
730 | } | ||
731 | |||
732 | |||
733 | /* Convert from BCD to an integer from 0-99 */ | ||
734 | static unsigned int | ||
735 | bcd_to_int(unsigned int bcd) | ||
736 | { | ||
737 | return (((bcd >> 4) & 0x0f) * 10) + (bcd & 0x0f); | ||
738 | } | ||
739 | |||
740 | |||
741 | /* | ||
742 | * Convert a logical sector value (like the OS would want to use for | ||
743 | * a block device) to an MSF format. | ||
744 | */ | ||
745 | static void | ||
746 | log_to_msf(unsigned int log, Byte *msf) | ||
747 | { | ||
748 | log = log + LOG_START_OFFSET; | ||
749 | msf[0] = int_to_bcd(log / 4500); | ||
750 | log = log % 4500; | ||
751 | msf[1] = int_to_bcd(log / 75); | ||
752 | msf[2] = int_to_bcd(log % 75); | ||
753 | } | ||
754 | |||
755 | |||
756 | /* | ||
757 | * Convert an MSF format to a logical sector. | ||
758 | */ | ||
759 | static unsigned int | ||
760 | msf_to_log(Byte *msf) | ||
761 | { | ||
762 | unsigned int log; | ||
763 | |||
764 | |||
765 | log = bcd_to_int(msf[2]); | ||
766 | log += bcd_to_int(msf[1]) * 75; | ||
767 | log += bcd_to_int(msf[0]) * 4500; | ||
768 | log = log - LOG_START_OFFSET; | ||
769 | |||
770 | return log; | ||
771 | } | ||
772 | |||
773 | |||
774 | /* | ||
775 | * Take in integer size value and put it into a buffer like | ||
776 | * the drive would want to see a number-of-sector value. | ||
777 | */ | ||
778 | static void | ||
779 | size_to_buf(unsigned int size, Byte *buf) | ||
780 | { | ||
781 | buf[0] = size / 65536; | ||
782 | size = size % 65536; | ||
783 | buf[1] = size / 256; | ||
784 | buf[2] = size % 256; | ||
785 | } | ||
786 | |||
787 | |||
788 | /* | ||
789 | * The OS calls this to perform a read or write operation to the drive. | ||
790 | * Write obviously fail. Reads to a read ahead of sony_buffer_size | ||
791 | * bytes to help speed operations. This especially helps since the OS | ||
792 | * may use 1024 byte blocks and the drive uses 2048 byte blocks. Since most | ||
793 | * data access on a CD is done sequentially, this saves a lot of operations. | ||
794 | */ | ||
795 | static void | ||
796 | do_cdu535_request(request_queue_t * q) | ||
797 | { | ||
798 | struct request *req; | ||
799 | unsigned int read_size; | ||
800 | int block; | ||
801 | int nsect; | ||
802 | int copyoff; | ||
803 | int spin_up_retry; | ||
804 | Byte params[10]; | ||
805 | Byte status[2]; | ||
806 | Byte cmd[2]; | ||
807 | |||
808 | while (1) { | ||
809 | req = elv_next_request(q); | ||
810 | if (!req) | ||
811 | return; | ||
812 | |||
813 | block = req->sector; | ||
814 | nsect = req->nr_sectors; | ||
815 | if (!blk_fs_request(req)) { | ||
816 | end_request(req, 0); | ||
817 | continue; | ||
818 | } | ||
819 | if (rq_data_dir(req) == WRITE) { | ||
820 | end_request(req, 0); | ||
821 | continue; | ||
822 | } | ||
823 | /* | ||
824 | * If the block address is invalid or the request goes beyond | ||
825 | * the end of the media, return an error. | ||
826 | */ | ||
827 | if (sony_toc->lead_out_start_lba <= (block/4)) { | ||
828 | end_request(req, 0); | ||
829 | return; | ||
830 | } | ||
831 | if (sony_toc->lead_out_start_lba <= ((block + nsect) / 4)) { | ||
832 | end_request(req, 0); | ||
833 | return; | ||
834 | } | ||
835 | while (0 < nsect) { | ||
836 | /* | ||
837 | * If the requested sector is not currently in | ||
838 | * the read-ahead buffer, it must be read in. | ||
839 | */ | ||
840 | if ((block < sony_first_block) || (sony_last_block < block)) { | ||
841 | sony_first_block = (block / 4) * 4; | ||
842 | log_to_msf(block / 4, params); | ||
843 | |||
844 | /* | ||
845 | * If the full read-ahead would go beyond the end of the media, trim | ||
846 | * it back to read just till the end of the media. | ||
847 | */ | ||
848 | if (sony_toc->lead_out_start_lba <= ((block / 4) + sony_buffer_sectors)) { | ||
849 | sony_last_block = (sony_toc->lead_out_start_lba * 4) - 1; | ||
850 | read_size = sony_toc->lead_out_start_lba - (block / 4); | ||
851 | } else { | ||
852 | sony_last_block = sony_first_block + (sony_buffer_sectors * 4) - 1; | ||
853 | read_size = sony_buffer_sectors; | ||
854 | } | ||
855 | size_to_buf(read_size, ¶ms[3]); | ||
856 | |||
857 | /* | ||
858 | * Read the data. If the drive was not spinning, | ||
859 | * spin it up and try some more. | ||
860 | */ | ||
861 | for (spin_up_retry=0 ;; ++spin_up_retry) { | ||
862 | /* This loop has been modified to support the Sony | ||
863 | * CDU-510/515 series, thanks to Claudio Porfiri | ||
864 | * <C.Porfiri@nisms.tei.ericsson.se>. | ||
865 | */ | ||
866 | /* | ||
867 | * This part is to deal with very slow hardware. We | ||
868 | * try at most MAX_SPINUP_RETRY times to read the same | ||
869 | * block. A check for seek_and_read_N_blocks' result is | ||
870 | * performed; if the result is wrong, the CDROM's engine | ||
871 | * is restarted and the operation is tried again. | ||
872 | */ | ||
873 | /* | ||
874 | * 1995-06-01: The system got problems when downloading | ||
875 | * from Slackware CDROM, the problem seems to be: | ||
876 | * seek_and_read_N_blocks returns BAD_STATUS and we | ||
877 | * should wait for a while before retrying, so a new | ||
878 | * part was added to discriminate the return value from | ||
879 | * seek_and_read_N_blocks for the various cases. | ||
880 | */ | ||
881 | int readStatus = seek_and_read_N_blocks(params, read_size, | ||
882 | status, sony_buffer, (read_size * CDU535_BLOCK_SIZE)); | ||
883 | if (0 <= readStatus) /* Good data; common case, placed first */ | ||
884 | break; | ||
885 | if (readStatus == NO_ROOM || spin_up_retry == MAX_SPINUP_RETRY) { | ||
886 | /* give up */ | ||
887 | if (readStatus == NO_ROOM) | ||
888 | printk(CDU535_MESSAGE_NAME " No room to read from CD\n"); | ||
889 | else | ||
890 | printk(CDU535_MESSAGE_NAME " Read error: 0x%.2x\n", | ||
891 | status[0]); | ||
892 | sony_first_block = -1; | ||
893 | sony_last_block = -1; | ||
894 | end_request(req, 0); | ||
895 | return; | ||
896 | } | ||
897 | if (readStatus == BAD_STATUS) { | ||
898 | /* Sleep for a while, then retry */ | ||
899 | set_current_state(TASK_INTERRUPTIBLE); | ||
900 | spin_unlock_irq(&sonycd535_lock); | ||
901 | schedule_timeout(RETRY_FOR_BAD_STATUS*HZ/10); | ||
902 | spin_lock_irq(&sonycd535_lock); | ||
903 | } | ||
904 | #if DEBUG > 0 | ||
905 | printk(CDU535_MESSAGE_NAME | ||
906 | " debug: calling spin up when reading data!\n"); | ||
907 | #endif | ||
908 | cmd[0] = SONY535_SPIN_UP; | ||
909 | do_sony_cmd(cmd, 1, status, NULL, 0, 0); | ||
910 | } | ||
911 | } | ||
912 | /* | ||
913 | * The data is in memory now, copy it to the buffer and advance to the | ||
914 | * next block to read. | ||
915 | */ | ||
916 | copyoff = block - sony_first_block; | ||
917 | memcpy(req->buffer, | ||
918 | sony_buffer[copyoff / 4] + 512 * (copyoff % 4), 512); | ||
919 | |||
920 | block += 1; | ||
921 | nsect -= 1; | ||
922 | req->buffer += 512; | ||
923 | } | ||
924 | |||
925 | end_request(req, 1); | ||
926 | } | ||
927 | } | ||
928 | |||
929 | /* | ||
930 | * Read the table of contents from the drive and set sony_toc_read if | ||
931 | * successful. | ||
932 | */ | ||
933 | static void | ||
934 | sony_get_toc(void) | ||
935 | { | ||
936 | Byte status[2]; | ||
937 | if (!sony_toc_read) { | ||
938 | /* do not call check_drive_status() from here since it can call this routine */ | ||
939 | if (request_toc_data(status, sony_toc) < 0) | ||
940 | return; | ||
941 | sony_toc->lead_out_start_lba = msf_to_log(sony_toc->lead_out_start_msf); | ||
942 | sony_toc_read = 1; | ||
943 | } | ||
944 | } | ||
945 | |||
946 | |||
947 | /* | ||
948 | * Search for a specific track in the table of contents. track is | ||
949 | * passed in bcd format | ||
950 | */ | ||
951 | static int | ||
952 | find_track(int track) | ||
953 | { | ||
954 | int i; | ||
955 | int num_tracks; | ||
956 | |||
957 | |||
958 | num_tracks = bcd_to_int(sony_toc->last_track_num) - | ||
959 | bcd_to_int(sony_toc->first_track_num) + 1; | ||
960 | for (i = 0; i < num_tracks; i++) { | ||
961 | if (sony_toc->tracks[i].track == track) { | ||
962 | return i; | ||
963 | } | ||
964 | } | ||
965 | |||
966 | return -1; | ||
967 | } | ||
968 | |||
969 | /* | ||
970 | * Read the subcode and put it int last_sony_subcode for future use. | ||
971 | */ | ||
972 | static int | ||
973 | read_subcode(void) | ||
974 | { | ||
975 | Byte cmd = SONY535_REQUEST_SUB_Q_DATA; | ||
976 | Byte status[2]; | ||
977 | int dsc_status; | ||
978 | |||
979 | if (check_drive_status() != 0) | ||
980 | return -EIO; | ||
981 | |||
982 | if ((dsc_status = do_sony_cmd(&cmd, 1, status, (Byte *) last_sony_subcode, | ||
983 | sizeof(struct s535_sony_subcode), 1)) != 0) { | ||
984 | printk(CDU535_MESSAGE_NAME " error 0x%.2x, %d (read_subcode)\n", | ||
985 | status[0], dsc_status); | ||
986 | return -EIO; | ||
987 | } | ||
988 | return 0; | ||
989 | } | ||
990 | |||
991 | |||
992 | /* | ||
993 | * Get the subchannel info like the CDROMSUBCHNL command wants to see it. If | ||
994 | * the drive is playing, the subchannel needs to be read (since it would be | ||
995 | * changing). If the drive is paused or completed, the subcode information has | ||
996 | * already been stored, just use that. The ioctl call wants things in decimal | ||
997 | * (not BCD), so all the conversions are done. | ||
998 | */ | ||
999 | static int | ||
1000 | sony_get_subchnl_info(void __user *arg) | ||
1001 | { | ||
1002 | struct cdrom_subchnl schi; | ||
1003 | |||
1004 | /* Get attention stuff */ | ||
1005 | if (check_drive_status() != 0) | ||
1006 | return -EIO; | ||
1007 | |||
1008 | sony_get_toc(); | ||
1009 | if (!sony_toc_read) { | ||
1010 | return -EIO; | ||
1011 | } | ||
1012 | if (copy_from_user(&schi, arg, sizeof schi)) | ||
1013 | return -EFAULT; | ||
1014 | |||
1015 | switch (sony_audio_status) { | ||
1016 | case CDROM_AUDIO_PLAY: | ||
1017 | if (read_subcode() < 0) { | ||
1018 | return -EIO; | ||
1019 | } | ||
1020 | break; | ||
1021 | |||
1022 | case CDROM_AUDIO_PAUSED: | ||
1023 | case CDROM_AUDIO_COMPLETED: | ||
1024 | break; | ||
1025 | |||
1026 | case CDROM_AUDIO_NO_STATUS: | ||
1027 | schi.cdsc_audiostatus = sony_audio_status; | ||
1028 | if (copy_to_user(arg, &schi, sizeof schi)) | ||
1029 | return -EFAULT; | ||
1030 | return 0; | ||
1031 | break; | ||
1032 | |||
1033 | case CDROM_AUDIO_INVALID: | ||
1034 | case CDROM_AUDIO_ERROR: | ||
1035 | default: | ||
1036 | return -EIO; | ||
1037 | } | ||
1038 | |||
1039 | schi.cdsc_audiostatus = sony_audio_status; | ||
1040 | schi.cdsc_adr = last_sony_subcode->address; | ||
1041 | schi.cdsc_ctrl = last_sony_subcode->control; | ||
1042 | schi.cdsc_trk = bcd_to_int(last_sony_subcode->track_num); | ||
1043 | schi.cdsc_ind = bcd_to_int(last_sony_subcode->index_num); | ||
1044 | if (schi.cdsc_format == CDROM_MSF) { | ||
1045 | schi.cdsc_absaddr.msf.minute = bcd_to_int(last_sony_subcode->abs_msf[0]); | ||
1046 | schi.cdsc_absaddr.msf.second = bcd_to_int(last_sony_subcode->abs_msf[1]); | ||
1047 | schi.cdsc_absaddr.msf.frame = bcd_to_int(last_sony_subcode->abs_msf[2]); | ||
1048 | |||
1049 | schi.cdsc_reladdr.msf.minute = bcd_to_int(last_sony_subcode->rel_msf[0]); | ||
1050 | schi.cdsc_reladdr.msf.second = bcd_to_int(last_sony_subcode->rel_msf[1]); | ||
1051 | schi.cdsc_reladdr.msf.frame = bcd_to_int(last_sony_subcode->rel_msf[2]); | ||
1052 | } else if (schi.cdsc_format == CDROM_LBA) { | ||
1053 | schi.cdsc_absaddr.lba = msf_to_log(last_sony_subcode->abs_msf); | ||
1054 | schi.cdsc_reladdr.lba = msf_to_log(last_sony_subcode->rel_msf); | ||
1055 | } | ||
1056 | return copy_to_user(arg, &schi, sizeof schi) ? -EFAULT : 0; | ||
1057 | } | ||
1058 | |||
1059 | |||
1060 | /* | ||
1061 | * The big ugly ioctl handler. | ||
1062 | */ | ||
1063 | static int | ||
1064 | cdu_ioctl(struct inode *inode, | ||
1065 | struct file *file, | ||
1066 | unsigned int cmd, | ||
1067 | unsigned long arg) | ||
1068 | { | ||
1069 | Byte status[2]; | ||
1070 | Byte cmd_buff[10], params[10]; | ||
1071 | int i; | ||
1072 | int dsc_status; | ||
1073 | void __user *argp = (void __user *)arg; | ||
1074 | |||
1075 | if (check_drive_status() != 0) | ||
1076 | return -EIO; | ||
1077 | |||
1078 | switch (cmd) { | ||
1079 | case CDROMSTART: /* Spin up the drive */ | ||
1080 | if (spin_up_drive(status) < 0) { | ||
1081 | printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMSTART)\n", | ||
1082 | status[0]); | ||
1083 | return -EIO; | ||
1084 | } | ||
1085 | return 0; | ||
1086 | break; | ||
1087 | |||
1088 | case CDROMSTOP: /* Spin down the drive */ | ||
1089 | cmd_buff[0] = SONY535_HOLD; | ||
1090 | do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0); | ||
1091 | |||
1092 | /* | ||
1093 | * Spin the drive down, ignoring the error if the disk was | ||
1094 | * already not spinning. | ||
1095 | */ | ||
1096 | sony_audio_status = CDROM_AUDIO_NO_STATUS; | ||
1097 | cmd_buff[0] = SONY535_SPIN_DOWN; | ||
1098 | dsc_status = do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0); | ||
1099 | if (((dsc_status < 0) && (dsc_status != BAD_STATUS)) || | ||
1100 | ((status[0] & ~(SONY535_STATUS1_NOT_SPINNING)) != 0)) { | ||
1101 | printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMSTOP)\n", | ||
1102 | status[0]); | ||
1103 | return -EIO; | ||
1104 | } | ||
1105 | return 0; | ||
1106 | break; | ||
1107 | |||
1108 | case CDROMPAUSE: /* Pause the drive */ | ||
1109 | cmd_buff[0] = SONY535_HOLD; /* CDU-31 driver uses AUDIO_STOP, not pause */ | ||
1110 | if (do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0) != 0) { | ||
1111 | printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMPAUSE)\n", | ||
1112 | status[0]); | ||
1113 | return -EIO; | ||
1114 | } | ||
1115 | /* Get the current position and save it for resuming */ | ||
1116 | if (read_subcode() < 0) { | ||
1117 | return -EIO; | ||
1118 | } | ||
1119 | cur_pos_msf[0] = last_sony_subcode->abs_msf[0]; | ||
1120 | cur_pos_msf[1] = last_sony_subcode->abs_msf[1]; | ||
1121 | cur_pos_msf[2] = last_sony_subcode->abs_msf[2]; | ||
1122 | sony_audio_status = CDROM_AUDIO_PAUSED; | ||
1123 | return 0; | ||
1124 | break; | ||
1125 | |||
1126 | case CDROMRESUME: /* Start the drive after being paused */ | ||
1127 | set_drive_mode(SONY535_AUDIO_DRIVE_MODE, status); | ||
1128 | |||
1129 | if (sony_audio_status != CDROM_AUDIO_PAUSED) { | ||
1130 | return -EINVAL; | ||
1131 | } | ||
1132 | spin_up_drive(status); | ||
1133 | |||
1134 | /* Start the drive at the saved position. */ | ||
1135 | cmd_buff[0] = SONY535_PLAY_AUDIO; | ||
1136 | cmd_buff[1] = 0; /* play back starting at this address */ | ||
1137 | cmd_buff[2] = cur_pos_msf[0]; | ||
1138 | cmd_buff[3] = cur_pos_msf[1]; | ||
1139 | cmd_buff[4] = cur_pos_msf[2]; | ||
1140 | cmd_buff[5] = SONY535_PLAY_AUDIO; | ||
1141 | cmd_buff[6] = 2; /* set ending address */ | ||
1142 | cmd_buff[7] = final_pos_msf[0]; | ||
1143 | cmd_buff[8] = final_pos_msf[1]; | ||
1144 | cmd_buff[9] = final_pos_msf[2]; | ||
1145 | if ((do_sony_cmd(cmd_buff, 5, status, NULL, 0, 0) != 0) || | ||
1146 | (do_sony_cmd(cmd_buff + 5, 5, status, NULL, 0, 0) != 0)) { | ||
1147 | printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMRESUME)\n", | ||
1148 | status[0]); | ||
1149 | return -EIO; | ||
1150 | } | ||
1151 | sony_audio_status = CDROM_AUDIO_PLAY; | ||
1152 | return 0; | ||
1153 | break; | ||
1154 | |||
1155 | case CDROMPLAYMSF: /* Play starting at the given MSF address. */ | ||
1156 | if (copy_from_user(params, argp, 6)) | ||
1157 | return -EFAULT; | ||
1158 | spin_up_drive(status); | ||
1159 | set_drive_mode(SONY535_AUDIO_DRIVE_MODE, status); | ||
1160 | |||
1161 | /* The parameters are given in int, must be converted */ | ||
1162 | for (i = 0; i < 3; i++) { | ||
1163 | cmd_buff[2 + i] = int_to_bcd(params[i]); | ||
1164 | cmd_buff[7 + i] = int_to_bcd(params[i + 3]); | ||
1165 | } | ||
1166 | cmd_buff[0] = SONY535_PLAY_AUDIO; | ||
1167 | cmd_buff[1] = 0; /* play back starting at this address */ | ||
1168 | /* cmd_buff[2-4] are filled in for loop above */ | ||
1169 | cmd_buff[5] = SONY535_PLAY_AUDIO; | ||
1170 | cmd_buff[6] = 2; /* set ending address */ | ||
1171 | /* cmd_buff[7-9] are filled in for loop above */ | ||
1172 | if ((do_sony_cmd(cmd_buff, 5, status, NULL, 0, 0) != 0) || | ||
1173 | (do_sony_cmd(cmd_buff + 5, 5, status, NULL, 0, 0) != 0)) { | ||
1174 | printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMPLAYMSF)\n", | ||
1175 | status[0]); | ||
1176 | return -EIO; | ||
1177 | } | ||
1178 | /* Save the final position for pauses and resumes */ | ||
1179 | final_pos_msf[0] = cmd_buff[7]; | ||
1180 | final_pos_msf[1] = cmd_buff[8]; | ||
1181 | final_pos_msf[2] = cmd_buff[9]; | ||
1182 | sony_audio_status = CDROM_AUDIO_PLAY; | ||
1183 | return 0; | ||
1184 | break; | ||
1185 | |||
1186 | case CDROMREADTOCHDR: /* Read the table of contents header */ | ||
1187 | { | ||
1188 | struct cdrom_tochdr __user *hdr = argp; | ||
1189 | struct cdrom_tochdr loc_hdr; | ||
1190 | |||
1191 | sony_get_toc(); | ||
1192 | if (!sony_toc_read) | ||
1193 | return -EIO; | ||
1194 | loc_hdr.cdth_trk0 = bcd_to_int(sony_toc->first_track_num); | ||
1195 | loc_hdr.cdth_trk1 = bcd_to_int(sony_toc->last_track_num); | ||
1196 | if (copy_to_user(hdr, &loc_hdr, sizeof *hdr)) | ||
1197 | return -EFAULT; | ||
1198 | } | ||
1199 | return 0; | ||
1200 | break; | ||
1201 | |||
1202 | case CDROMREADTOCENTRY: /* Read a given table of contents entry */ | ||
1203 | { | ||
1204 | struct cdrom_tocentry __user *entry = argp; | ||
1205 | struct cdrom_tocentry loc_entry; | ||
1206 | int track_idx; | ||
1207 | Byte *msf_val = NULL; | ||
1208 | |||
1209 | sony_get_toc(); | ||
1210 | if (!sony_toc_read) { | ||
1211 | return -EIO; | ||
1212 | } | ||
1213 | |||
1214 | if (copy_from_user(&loc_entry, entry, sizeof loc_entry)) | ||
1215 | return -EFAULT; | ||
1216 | |||
1217 | /* Lead out is handled separately since it is special. */ | ||
1218 | if (loc_entry.cdte_track == CDROM_LEADOUT) { | ||
1219 | loc_entry.cdte_adr = 0 /*sony_toc->address2 */ ; | ||
1220 | loc_entry.cdte_ctrl = sony_toc->control2; | ||
1221 | msf_val = sony_toc->lead_out_start_msf; | ||
1222 | } else { | ||
1223 | track_idx = find_track(int_to_bcd(loc_entry.cdte_track)); | ||
1224 | if (track_idx < 0) | ||
1225 | return -EINVAL; | ||
1226 | loc_entry.cdte_adr = 0 /*sony_toc->tracks[track_idx].address */ ; | ||
1227 | loc_entry.cdte_ctrl = sony_toc->tracks[track_idx].control; | ||
1228 | msf_val = sony_toc->tracks[track_idx].track_start_msf; | ||
1229 | } | ||
1230 | |||
1231 | /* Logical buffer address or MSF format requested? */ | ||
1232 | if (loc_entry.cdte_format == CDROM_LBA) { | ||
1233 | loc_entry.cdte_addr.lba = msf_to_log(msf_val); | ||
1234 | } else if (loc_entry.cdte_format == CDROM_MSF) { | ||
1235 | loc_entry.cdte_addr.msf.minute = bcd_to_int(*msf_val); | ||
1236 | loc_entry.cdte_addr.msf.second = bcd_to_int(*(msf_val + 1)); | ||
1237 | loc_entry.cdte_addr.msf.frame = bcd_to_int(*(msf_val + 2)); | ||
1238 | } | ||
1239 | if (copy_to_user(entry, &loc_entry, sizeof *entry)) | ||
1240 | return -EFAULT; | ||
1241 | } | ||
1242 | return 0; | ||
1243 | break; | ||
1244 | |||
1245 | case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */ | ||
1246 | { | ||
1247 | struct cdrom_ti ti; | ||
1248 | int track_idx; | ||
1249 | |||
1250 | sony_get_toc(); | ||
1251 | if (!sony_toc_read) | ||
1252 | return -EIO; | ||
1253 | |||
1254 | if (copy_from_user(&ti, argp, sizeof ti)) | ||
1255 | return -EFAULT; | ||
1256 | if ((ti.cdti_trk0 < sony_toc->first_track_num) | ||
1257 | || (sony_toc->last_track_num < ti.cdti_trk0) | ||
1258 | || (ti.cdti_trk1 < ti.cdti_trk0)) { | ||
1259 | return -EINVAL; | ||
1260 | } | ||
1261 | track_idx = find_track(int_to_bcd(ti.cdti_trk0)); | ||
1262 | if (track_idx < 0) | ||
1263 | return -EINVAL; | ||
1264 | params[1] = sony_toc->tracks[track_idx].track_start_msf[0]; | ||
1265 | params[2] = sony_toc->tracks[track_idx].track_start_msf[1]; | ||
1266 | params[3] = sony_toc->tracks[track_idx].track_start_msf[2]; | ||
1267 | /* | ||
1268 | * If we want to stop after the last track, use the lead-out | ||
1269 | * MSF to do that. | ||
1270 | */ | ||
1271 | if (bcd_to_int(sony_toc->last_track_num) <= ti.cdti_trk1) { | ||
1272 | log_to_msf(msf_to_log(sony_toc->lead_out_start_msf) - 1, | ||
1273 | &(params[4])); | ||
1274 | } else { | ||
1275 | track_idx = find_track(int_to_bcd(ti.cdti_trk1 + 1)); | ||
1276 | if (track_idx < 0) | ||
1277 | return -EINVAL; | ||
1278 | log_to_msf(msf_to_log(sony_toc->tracks[track_idx].track_start_msf) - 1, | ||
1279 | &(params[4])); | ||
1280 | } | ||
1281 | params[0] = 0x03; | ||
1282 | |||
1283 | spin_up_drive(status); | ||
1284 | |||
1285 | set_drive_mode(SONY535_AUDIO_DRIVE_MODE, status); | ||
1286 | |||
1287 | /* Start the drive at the saved position. */ | ||
1288 | cmd_buff[0] = SONY535_PLAY_AUDIO; | ||
1289 | cmd_buff[1] = 0; /* play back starting at this address */ | ||
1290 | cmd_buff[2] = params[1]; | ||
1291 | cmd_buff[3] = params[2]; | ||
1292 | cmd_buff[4] = params[3]; | ||
1293 | cmd_buff[5] = SONY535_PLAY_AUDIO; | ||
1294 | cmd_buff[6] = 2; /* set ending address */ | ||
1295 | cmd_buff[7] = params[4]; | ||
1296 | cmd_buff[8] = params[5]; | ||
1297 | cmd_buff[9] = params[6]; | ||
1298 | if ((do_sony_cmd(cmd_buff, 5, status, NULL, 0, 0) != 0) || | ||
1299 | (do_sony_cmd(cmd_buff + 5, 5, status, NULL, 0, 0) != 0)) { | ||
1300 | printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMPLAYTRKIND)\n", | ||
1301 | status[0]); | ||
1302 | printk("... Params: %x %x %x %x %x %x %x\n", | ||
1303 | params[0], params[1], params[2], | ||
1304 | params[3], params[4], params[5], params[6]); | ||
1305 | return -EIO; | ||
1306 | } | ||
1307 | /* Save the final position for pauses and resumes */ | ||
1308 | final_pos_msf[0] = params[4]; | ||
1309 | final_pos_msf[1] = params[5]; | ||
1310 | final_pos_msf[2] = params[6]; | ||
1311 | sony_audio_status = CDROM_AUDIO_PLAY; | ||
1312 | return 0; | ||
1313 | } | ||
1314 | |||
1315 | case CDROMSUBCHNL: /* Get subchannel info */ | ||
1316 | return sony_get_subchnl_info(argp); | ||
1317 | |||
1318 | case CDROMVOLCTRL: /* Volume control. What volume does this change, anyway? */ | ||
1319 | { | ||
1320 | struct cdrom_volctrl volctrl; | ||
1321 | |||
1322 | if (copy_from_user(&volctrl, argp, sizeof volctrl)) | ||
1323 | return -EFAULT; | ||
1324 | cmd_buff[0] = SONY535_SET_VOLUME; | ||
1325 | cmd_buff[1] = volctrl.channel0; | ||
1326 | cmd_buff[2] = volctrl.channel1; | ||
1327 | if (do_sony_cmd(cmd_buff, 3, status, NULL, 0, 0) != 0) { | ||
1328 | printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMVOLCTRL)\n", | ||
1329 | status[0]); | ||
1330 | return -EIO; | ||
1331 | } | ||
1332 | } | ||
1333 | return 0; | ||
1334 | |||
1335 | case CDROMEJECT: /* Eject the drive */ | ||
1336 | cmd_buff[0] = SONY535_STOP; | ||
1337 | do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0); | ||
1338 | cmd_buff[0] = SONY535_SPIN_DOWN; | ||
1339 | do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0); | ||
1340 | |||
1341 | sony_audio_status = CDROM_AUDIO_INVALID; | ||
1342 | cmd_buff[0] = SONY535_EJECT_CADDY; | ||
1343 | if (do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0) != 0) { | ||
1344 | printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMEJECT)\n", | ||
1345 | status[0]); | ||
1346 | return -EIO; | ||
1347 | } | ||
1348 | return 0; | ||
1349 | break; | ||
1350 | |||
1351 | default: | ||
1352 | return -EINVAL; | ||
1353 | } | ||
1354 | } | ||
1355 | |||
1356 | |||
1357 | /* | ||
1358 | * Open the drive for operations. Spin the drive up and read the table of | ||
1359 | * contents if these have not already been done. | ||
1360 | */ | ||
1361 | static int | ||
1362 | cdu_open(struct inode *inode, | ||
1363 | struct file *filp) | ||
1364 | { | ||
1365 | Byte status[2], cmd_buff[2]; | ||
1366 | |||
1367 | if (sony_inuse) | ||
1368 | return -EBUSY; | ||
1369 | if (check_drive_status() != 0) | ||
1370 | return -EIO; | ||
1371 | sony_inuse = 1; | ||
1372 | |||
1373 | if (spin_up_drive(status) != 0) { | ||
1374 | printk(CDU535_MESSAGE_NAME " error 0x%.2x (cdu_open, spin up)\n", | ||
1375 | status[0]); | ||
1376 | sony_inuse = 0; | ||
1377 | return -EIO; | ||
1378 | } | ||
1379 | sony_get_toc(); | ||
1380 | if (!sony_toc_read) { | ||
1381 | cmd_buff[0] = SONY535_SPIN_DOWN; | ||
1382 | do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0); | ||
1383 | sony_inuse = 0; | ||
1384 | return -EIO; | ||
1385 | } | ||
1386 | check_disk_change(inode->i_bdev); | ||
1387 | sony_usage++; | ||
1388 | |||
1389 | #ifdef LOCK_DOORS | ||
1390 | /* disable the eject button while mounted */ | ||
1391 | cmd_buff[0] = SONY535_DISABLE_EJECT_BUTTON; | ||
1392 | do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0); | ||
1393 | #endif | ||
1394 | |||
1395 | return 0; | ||
1396 | } | ||
1397 | |||
1398 | |||
1399 | /* | ||
1400 | * Close the drive. Spin it down if no task is using it. The spin | ||
1401 | * down will fail if playing audio, so audio play is OK. | ||
1402 | */ | ||
1403 | static int | ||
1404 | cdu_release(struct inode *inode, | ||
1405 | struct file *filp) | ||
1406 | { | ||
1407 | Byte status[2], cmd_no; | ||
1408 | |||
1409 | sony_inuse = 0; | ||
1410 | |||
1411 | if (0 < sony_usage) { | ||
1412 | sony_usage--; | ||
1413 | } | ||
1414 | if (sony_usage == 0) { | ||
1415 | check_drive_status(); | ||
1416 | |||
1417 | if (sony_audio_status != CDROM_AUDIO_PLAY) { | ||
1418 | cmd_no = SONY535_SPIN_DOWN; | ||
1419 | do_sony_cmd(&cmd_no, 1, status, NULL, 0, 0); | ||
1420 | } | ||
1421 | #ifdef LOCK_DOORS | ||
1422 | /* enable the eject button after umount */ | ||
1423 | cmd_no = SONY535_ENABLE_EJECT_BUTTON; | ||
1424 | do_sony_cmd(&cmd_no, 1, status, NULL, 0, 0); | ||
1425 | #endif | ||
1426 | } | ||
1427 | return 0; | ||
1428 | } | ||
1429 | |||
1430 | static struct block_device_operations cdu_fops = | ||
1431 | { | ||
1432 | .owner = THIS_MODULE, | ||
1433 | .open = cdu_open, | ||
1434 | .release = cdu_release, | ||
1435 | .ioctl = cdu_ioctl, | ||
1436 | .media_changed = cdu535_check_media_change, | ||
1437 | }; | ||
1438 | |||
1439 | static struct gendisk *cdu_disk; | ||
1440 | |||
1441 | /* | ||
1442 | * Initialize the driver. | ||
1443 | */ | ||
1444 | static int __init sony535_init(void) | ||
1445 | { | ||
1446 | struct s535_sony_drive_config drive_config; | ||
1447 | Byte cmd_buff[3]; | ||
1448 | Byte ret_buff[2]; | ||
1449 | Byte status[2]; | ||
1450 | unsigned long snap; | ||
1451 | int got_result = 0; | ||
1452 | int tmp_irq; | ||
1453 | int i; | ||
1454 | int err; | ||
1455 | |||
1456 | /* Setting the base I/O address to 0 will disable it. */ | ||
1457 | if ((sony535_cd_base_io == 0xffff)||(sony535_cd_base_io == 0)) | ||
1458 | return 0; | ||
1459 | |||
1460 | /* Set up all the register locations */ | ||
1461 | result_reg = sony535_cd_base_io; | ||
1462 | command_reg = sony535_cd_base_io; | ||
1463 | data_reg = sony535_cd_base_io + 1; | ||
1464 | read_status_reg = sony535_cd_base_io + 2; | ||
1465 | select_unit_reg = sony535_cd_base_io + 3; | ||
1466 | |||
1467 | #ifndef USE_IRQ | ||
1468 | sony535_irq_used = 0; /* polling only until this is ready... */ | ||
1469 | #endif | ||
1470 | /* we need to poll until things get initialized */ | ||
1471 | tmp_irq = sony535_irq_used; | ||
1472 | sony535_irq_used = 0; | ||
1473 | |||
1474 | #if DEBUG > 0 | ||
1475 | printk(KERN_INFO CDU535_MESSAGE_NAME ": probing base address %03X\n", | ||
1476 | sony535_cd_base_io); | ||
1477 | #endif | ||
1478 | /* look for the CD-ROM, follows the procedure in the DOS driver */ | ||
1479 | inb(select_unit_reg); | ||
1480 | /* wait for 40 18 Hz ticks (reverse-engineered from DOS driver) */ | ||
1481 | schedule_timeout_interruptible((HZ+17)*40/18); | ||
1482 | inb(result_reg); | ||
1483 | |||
1484 | outb(0, read_status_reg); /* does a reset? */ | ||
1485 | snap = jiffies; | ||
1486 | while (jiffies-snap < SONY_JIFFIES_TIMEOUT) { | ||
1487 | select_unit(0); | ||
1488 | if (inb(result_reg) != 0xff) { | ||
1489 | got_result = 1; | ||
1490 | break; | ||
1491 | } | ||
1492 | sony_sleep(); | ||
1493 | } | ||
1494 | |||
1495 | if (!got_result || check_drive_status() == TIME_OUT) | ||
1496 | goto Enodev; | ||
1497 | |||
1498 | /* CD-ROM drive responded -- get the drive configuration */ | ||
1499 | cmd_buff[0] = SONY535_INQUIRY; | ||
1500 | if (do_sony_cmd(cmd_buff, 1, status, (Byte *)&drive_config, 28, 1) != 0) | ||
1501 | goto Enodev; | ||
1502 | |||
1503 | /* was able to get the configuration, | ||
1504 | * set drive mode as rest of init | ||
1505 | */ | ||
1506 | #if DEBUG > 0 | ||
1507 | /* 0x50 == CADDY_NOT_INSERTED | NOT_SPINNING */ | ||
1508 | if ( (status[0] & 0x7f) != 0 && (status[0] & 0x7f) != 0x50 ) | ||
1509 | printk(CDU535_MESSAGE_NAME | ||
1510 | "Inquiry command returned status = 0x%x\n", status[0]); | ||
1511 | #endif | ||
1512 | /* now ready to use interrupts, if available */ | ||
1513 | sony535_irq_used = tmp_irq; | ||
1514 | |||
1515 | /* A negative sony535_irq_used will attempt an autoirq. */ | ||
1516 | if (sony535_irq_used < 0) { | ||
1517 | unsigned long irq_mask, delay; | ||
1518 | |||
1519 | irq_mask = probe_irq_on(); | ||
1520 | enable_interrupts(); | ||
1521 | outb(0, read_status_reg); /* does a reset? */ | ||
1522 | delay = jiffies + HZ/10; | ||
1523 | while (time_before(jiffies, delay)) ; | ||
1524 | |||
1525 | sony535_irq_used = probe_irq_off(irq_mask); | ||
1526 | disable_interrupts(); | ||
1527 | } | ||
1528 | if (sony535_irq_used > 0) { | ||
1529 | if (request_irq(sony535_irq_used, cdu535_interrupt, | ||
1530 | IRQF_DISABLED, CDU535_HANDLE, NULL)) { | ||
1531 | printk("Unable to grab IRQ%d for the " CDU535_MESSAGE_NAME | ||
1532 | " driver; polling instead.\n", sony535_irq_used); | ||
1533 | sony535_irq_used = 0; | ||
1534 | } | ||
1535 | } | ||
1536 | cmd_buff[0] = SONY535_SET_DRIVE_MODE; | ||
1537 | cmd_buff[1] = 0x0; /* default audio */ | ||
1538 | if (do_sony_cmd(cmd_buff, 2, status, ret_buff, 1, 1) != 0) | ||
1539 | goto Enodev_irq; | ||
1540 | |||
1541 | /* set the drive mode successful, we are set! */ | ||
1542 | sony_buffer_size = SONY535_BUFFER_SIZE; | ||
1543 | sony_buffer_sectors = sony_buffer_size / CDU535_BLOCK_SIZE; | ||
1544 | |||
1545 | printk(KERN_INFO CDU535_MESSAGE_NAME " I/F CDROM : %8.8s %16.16s %4.4s", | ||
1546 | drive_config.vendor_id, | ||
1547 | drive_config.product_id, | ||
1548 | drive_config.product_rev_level); | ||
1549 | printk(" base address %03X, ", sony535_cd_base_io); | ||
1550 | if (tmp_irq > 0) | ||
1551 | printk("IRQ%d, ", tmp_irq); | ||
1552 | printk("using %d byte buffer\n", sony_buffer_size); | ||
1553 | |||
1554 | if (register_blkdev(MAJOR_NR, CDU535_HANDLE)) { | ||
1555 | err = -EIO; | ||
1556 | goto out1; | ||
1557 | } | ||
1558 | sonycd535_queue = blk_init_queue(do_cdu535_request, &sonycd535_lock); | ||
1559 | if (!sonycd535_queue) { | ||
1560 | err = -ENOMEM; | ||
1561 | goto out1a; | ||
1562 | } | ||
1563 | |||
1564 | blk_queue_hardsect_size(sonycd535_queue, CDU535_BLOCK_SIZE); | ||
1565 | sony_toc = kmalloc(sizeof(struct s535_sony_toc), GFP_KERNEL); | ||
1566 | err = -ENOMEM; | ||
1567 | if (!sony_toc) | ||
1568 | goto out2; | ||
1569 | last_sony_subcode = kmalloc(sizeof(struct s535_sony_subcode), GFP_KERNEL); | ||
1570 | if (!last_sony_subcode) | ||
1571 | goto out3; | ||
1572 | sony_buffer = kmalloc(sizeof(Byte *) * sony_buffer_sectors, GFP_KERNEL); | ||
1573 | if (!sony_buffer) | ||
1574 | goto out4; | ||
1575 | for (i = 0; i < sony_buffer_sectors; i++) { | ||
1576 | sony_buffer[i] = kmalloc(CDU535_BLOCK_SIZE, GFP_KERNEL); | ||
1577 | if (!sony_buffer[i]) { | ||
1578 | while (--i>=0) | ||
1579 | kfree(sony_buffer[i]); | ||
1580 | goto out5; | ||
1581 | } | ||
1582 | } | ||
1583 | initialized = 1; | ||
1584 | |||
1585 | cdu_disk = alloc_disk(1); | ||
1586 | if (!cdu_disk) | ||
1587 | goto out6; | ||
1588 | cdu_disk->major = MAJOR_NR; | ||
1589 | cdu_disk->first_minor = 0; | ||
1590 | cdu_disk->fops = &cdu_fops; | ||
1591 | sprintf(cdu_disk->disk_name, "cdu"); | ||
1592 | |||
1593 | if (!request_region(sony535_cd_base_io, 4, CDU535_HANDLE)) { | ||
1594 | printk(KERN_WARNING"sonycd535: Unable to request region 0x%x\n", | ||
1595 | sony535_cd_base_io); | ||
1596 | goto out7; | ||
1597 | } | ||
1598 | cdu_disk->queue = sonycd535_queue; | ||
1599 | add_disk(cdu_disk); | ||
1600 | return 0; | ||
1601 | |||
1602 | out7: | ||
1603 | put_disk(cdu_disk); | ||
1604 | out6: | ||
1605 | for (i = 0; i < sony_buffer_sectors; i++) | ||
1606 | kfree(sony_buffer[i]); | ||
1607 | out5: | ||
1608 | kfree(sony_buffer); | ||
1609 | out4: | ||
1610 | kfree(last_sony_subcode); | ||
1611 | out3: | ||
1612 | kfree(sony_toc); | ||
1613 | out2: | ||
1614 | blk_cleanup_queue(sonycd535_queue); | ||
1615 | out1a: | ||
1616 | unregister_blkdev(MAJOR_NR, CDU535_HANDLE); | ||
1617 | out1: | ||
1618 | if (sony535_irq_used) | ||
1619 | free_irq(sony535_irq_used, NULL); | ||
1620 | return err; | ||
1621 | Enodev_irq: | ||
1622 | if (sony535_irq_used) | ||
1623 | free_irq(sony535_irq_used, NULL); | ||
1624 | Enodev: | ||
1625 | printk("Did not find a " CDU535_MESSAGE_NAME " drive\n"); | ||
1626 | return -EIO; | ||
1627 | } | ||
1628 | |||
1629 | #ifndef MODULE | ||
1630 | |||
1631 | /* | ||
1632 | * accept "kernel command line" parameters | ||
1633 | * (added by emoenke@gwdg.de) | ||
1634 | * | ||
1635 | * use: tell LILO: | ||
1636 | * sonycd535=0x320 | ||
1637 | * | ||
1638 | * the address value has to be the existing CDROM port address. | ||
1639 | */ | ||
1640 | static int __init | ||
1641 | sonycd535_setup(char *strings) | ||
1642 | { | ||
1643 | int ints[3]; | ||
1644 | (void)get_options(strings, ARRAY_SIZE(ints), ints); | ||
1645 | /* if IRQ change and default io base desired, | ||
1646 | * then call with io base of 0 | ||
1647 | */ | ||
1648 | if (ints[0] > 0) | ||
1649 | if (ints[1] != 0) | ||
1650 | sony535_cd_base_io = ints[1]; | ||
1651 | if (ints[0] > 1) | ||
1652 | sony535_irq_used = ints[2]; | ||
1653 | if ((strings != NULL) && (*strings != '\0')) | ||
1654 | printk(CDU535_MESSAGE_NAME | ||
1655 | ": Warning: Unknown interface type: %s\n", strings); | ||
1656 | |||
1657 | return 1; | ||
1658 | } | ||
1659 | |||
1660 | __setup("sonycd535=", sonycd535_setup); | ||
1661 | |||
1662 | #endif /* MODULE */ | ||
1663 | |||
1664 | static void __exit | ||
1665 | sony535_exit(void) | ||
1666 | { | ||
1667 | int i; | ||
1668 | |||
1669 | release_region(sony535_cd_base_io, 4); | ||
1670 | for (i = 0; i < sony_buffer_sectors; i++) | ||
1671 | kfree(sony_buffer[i]); | ||
1672 | kfree(sony_buffer); | ||
1673 | kfree(last_sony_subcode); | ||
1674 | kfree(sony_toc); | ||
1675 | del_gendisk(cdu_disk); | ||
1676 | put_disk(cdu_disk); | ||
1677 | blk_cleanup_queue(sonycd535_queue); | ||
1678 | if (unregister_blkdev(MAJOR_NR, CDU535_HANDLE) == -EINVAL) | ||
1679 | printk("Uh oh, couldn't unregister " CDU535_HANDLE "\n"); | ||
1680 | else | ||
1681 | printk(KERN_INFO CDU535_HANDLE " module released\n"); | ||
1682 | } | ||
1683 | |||
1684 | module_init(sony535_init); | ||
1685 | module_exit(sony535_exit); | ||
1686 | |||
1687 | |||
1688 | MODULE_LICENSE("GPL"); | ||
1689 | MODULE_ALIAS_BLOCKDEV_MAJOR(CDU535_CDROM_MAJOR); | ||
diff --git a/drivers/cdrom/sonycd535.h b/drivers/cdrom/sonycd535.h deleted file mode 100644 index 5dea1ef168d6..000000000000 --- a/drivers/cdrom/sonycd535.h +++ /dev/null | |||
@@ -1,183 +0,0 @@ | |||
1 | #ifndef SONYCD535_H | ||
2 | #define SONYCD535_H | ||
3 | |||
4 | /* | ||
5 | * define all the commands recognized by the CDU-531/5 | ||
6 | */ | ||
7 | #define SONY535_REQUEST_DRIVE_STATUS_1 (0x80) | ||
8 | #define SONY535_REQUEST_SENSE (0x82) | ||
9 | #define SONY535_REQUEST_DRIVE_STATUS_2 (0x84) | ||
10 | #define SONY535_REQUEST_ERROR_STATUS (0x86) | ||
11 | #define SONY535_REQUEST_AUDIO_STATUS (0x88) | ||
12 | #define SONY535_INQUIRY (0x8a) | ||
13 | |||
14 | #define SONY535_SET_INACTIVITY_TIME (0x90) | ||
15 | |||
16 | #define SONY535_SEEK_AND_READ_N_BLOCKS_1 (0xa0) | ||
17 | #define SONY535_SEEK_AND_READ_N_BLOCKS_2 (0xa4) | ||
18 | #define SONY535_PLAY_AUDIO (0xa6) | ||
19 | |||
20 | #define SONY535_REQUEST_DISC_CAPACITY (0xb0) | ||
21 | #define SONY535_REQUEST_TOC_DATA (0xb2) | ||
22 | #define SONY535_REQUEST_SUB_Q_DATA (0xb4) | ||
23 | #define SONY535_REQUEST_ISRC (0xb6) | ||
24 | #define SONY535_REQUEST_UPC_EAN (0xb8) | ||
25 | |||
26 | #define SONY535_SET_DRIVE_MODE (0xc0) | ||
27 | #define SONY535_REQUEST_DRIVE_MODE (0xc2) | ||
28 | #define SONY535_SET_RETRY_COUNT (0xc4) | ||
29 | |||
30 | #define SONY535_DIAGNOSTIC_1 (0xc6) | ||
31 | #define SONY535_DIAGNOSTIC_4 (0xcc) | ||
32 | #define SONY535_DIAGNOSTIC_5 (0xce) | ||
33 | |||
34 | #define SONY535_EJECT_CADDY (0xd0) | ||
35 | #define SONY535_DISABLE_EJECT_BUTTON (0xd2) | ||
36 | #define SONY535_ENABLE_EJECT_BUTTON (0xd4) | ||
37 | |||
38 | #define SONY535_HOLD (0xe0) | ||
39 | #define SONY535_AUDIO_PAUSE_ON_OFF (0xe2) | ||
40 | #define SONY535_SET_VOLUME (0xe8) | ||
41 | |||
42 | #define SONY535_STOP (0xf0) | ||
43 | #define SONY535_SPIN_UP (0xf2) | ||
44 | #define SONY535_SPIN_DOWN (0xf4) | ||
45 | |||
46 | #define SONY535_CLEAR_PARAMETERS (0xf6) | ||
47 | #define SONY535_CLEAR_ENDING_ADDRESS (0xf8) | ||
48 | |||
49 | /* | ||
50 | * define some masks | ||
51 | */ | ||
52 | #define SONY535_DATA_NOT_READY_BIT (0x1) | ||
53 | #define SONY535_RESULT_NOT_READY_BIT (0x2) | ||
54 | |||
55 | /* | ||
56 | * drive status 1 | ||
57 | */ | ||
58 | #define SONY535_STATUS1_COMMAND_ERROR (0x1) | ||
59 | #define SONY535_STATUS1_DATA_ERROR (0x2) | ||
60 | #define SONY535_STATUS1_SEEK_ERROR (0x4) | ||
61 | #define SONY535_STATUS1_DISC_TYPE_ERROR (0x8) | ||
62 | #define SONY535_STATUS1_NOT_SPINNING (0x10) | ||
63 | #define SONY535_STATUS1_EJECT_BUTTON_PRESSED (0x20) | ||
64 | #define SONY535_STATUS1_CADDY_NOT_INSERTED (0x40) | ||
65 | #define SONY535_STATUS1_BYTE_TWO_FOLLOWS (0x80) | ||
66 | |||
67 | /* | ||
68 | * drive status 2 | ||
69 | */ | ||
70 | #define SONY535_CDD_LOADING_ERROR (0x7) | ||
71 | #define SONY535_CDD_NO_DISC (0x8) | ||
72 | #define SONY535_CDD_UNLOADING_ERROR (0x9) | ||
73 | #define SONY535_CDD_CADDY_NOT_INSERTED (0xd) | ||
74 | #define SONY535_ATN_RESET_OCCURRED (0x2) | ||
75 | #define SONY535_ATN_DISC_CHANGED (0x4) | ||
76 | #define SONY535_ATN_RESET_AND_DISC_CHANGED (0x6) | ||
77 | #define SONY535_ATN_EJECT_IN_PROGRESS (0xe) | ||
78 | #define SONY535_ATN_BUSY (0xf) | ||
79 | |||
80 | /* | ||
81 | * define some parameters | ||
82 | */ | ||
83 | #define SONY535_AUDIO_DRIVE_MODE (0) | ||
84 | #define SONY535_CDROM_DRIVE_MODE (0xe0) | ||
85 | |||
86 | #define SONY535_PLAY_OP_PLAYBACK (0) | ||
87 | #define SONY535_PLAY_OP_ENTER_HOLD (1) | ||
88 | #define SONY535_PLAY_OP_SET_AUDIO_ENDING_ADDR (2) | ||
89 | #define SONY535_PLAY_OP_SCAN_FORWARD (3) | ||
90 | #define SONY535_PLAY_OP_SCAN_BACKWARD (4) | ||
91 | |||
92 | /* | ||
93 | * convert from msf format to block number | ||
94 | */ | ||
95 | #define SONY_BLOCK_NUMBER(m,s,f) (((m)*60L+(s))*75L+(f)) | ||
96 | #define SONY_BLOCK_NUMBER_MSF(x) (((x)[0]*60L+(x)[1])*75L+(x)[2]) | ||
97 | |||
98 | /* | ||
99 | * error return values from the doSonyCmd() routines | ||
100 | */ | ||
101 | #define TIME_OUT (-1) | ||
102 | #define NO_CDROM (-2) | ||
103 | #define BAD_STATUS (-3) | ||
104 | #define CD_BUSY (-4) | ||
105 | #define NOT_DATA_CD (-5) | ||
106 | #define NO_ROOM (-6) | ||
107 | |||
108 | #define LOG_START_OFFSET 150 /* Offset of first logical sector */ | ||
109 | |||
110 | #define SONY_JIFFIES_TIMEOUT (5*HZ) /* Maximum time | ||
111 | the drive will wait/try for an | ||
112 | operation */ | ||
113 | #define SONY_READY_RETRIES (50000) /* How many times to retry a | ||
114 | spin waiting for a register | ||
115 | to come ready */ | ||
116 | #define SONY535_FAST_POLLS (10000) /* how many times recheck | ||
117 | status waiting for a data | ||
118 | to become ready */ | ||
119 | |||
120 | typedef unsigned char Byte; | ||
121 | |||
122 | /* | ||
123 | * This is the complete status returned from the drive configuration request | ||
124 | * command. | ||
125 | */ | ||
126 | struct s535_sony_drive_config | ||
127 | { | ||
128 | char vendor_id[8]; | ||
129 | char product_id[16]; | ||
130 | char product_rev_level[4]; | ||
131 | }; | ||
132 | |||
133 | /* The following is returned from the request sub-q data command */ | ||
134 | struct s535_sony_subcode | ||
135 | { | ||
136 | unsigned char address :4; | ||
137 | unsigned char control :4; | ||
138 | unsigned char track_num; | ||
139 | unsigned char index_num; | ||
140 | unsigned char rel_msf[3]; | ||
141 | unsigned char abs_msf[3]; | ||
142 | }; | ||
143 | |||
144 | struct s535_sony_disc_capacity | ||
145 | { | ||
146 | Byte mFirstTrack, sFirstTrack, fFirstTrack; | ||
147 | Byte mLeadOut, sLeadOut, fLeadOut; | ||
148 | }; | ||
149 | |||
150 | /* | ||
151 | * The following is returned from the request TOC (Table Of Contents) command. | ||
152 | * (last_track_num-first_track_num+1) values are valid in tracks. | ||
153 | */ | ||
154 | struct s535_sony_toc | ||
155 | { | ||
156 | unsigned char reserved0 :4; | ||
157 | unsigned char control0 :4; | ||
158 | unsigned char point0; | ||
159 | unsigned char first_track_num; | ||
160 | unsigned char reserved0a; | ||
161 | unsigned char reserved0b; | ||
162 | unsigned char reserved1 :4; | ||
163 | unsigned char control1 :4; | ||
164 | unsigned char point1; | ||
165 | unsigned char last_track_num; | ||
166 | unsigned char dummy1; | ||
167 | unsigned char dummy2; | ||
168 | unsigned char reserved2 :4; | ||
169 | unsigned char control2 :4; | ||
170 | unsigned char point2; | ||
171 | unsigned char lead_out_start_msf[3]; | ||
172 | struct | ||
173 | { | ||
174 | unsigned char reserved :4; | ||
175 | unsigned char control :4; | ||
176 | unsigned char track; | ||
177 | unsigned char track_start_msf[3]; | ||
178 | } tracks[100]; | ||
179 | |||
180 | unsigned int lead_out_start_lba; | ||
181 | }; | ||
182 | |||
183 | #endif /* SONYCD535_H */ | ||