📄 cdu31a.c.txt
字号:
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 * The Sony interface device driver handles Sony interface CDROM
9 * drives and provides a complete block-level interface as well as an
10 * ioctl() interface compatible with the Sun (as specified in
11 * include/linux/cdrom.h). With this interface, CDROMs can be
12 * accessed and standard audio CDs can be played back normally.
13 *
14 * This interface is (unfortunatly) a polled interface. This is
15 * because most Sony interfaces are set up with DMA and interrupts
16 * disables. Some (like mine) do not even have the capability to
17 * handle interrupts or DMA. For this reason you will see a lot of
18 * the following:
19 *
20 * retry_count = jiffies+ SONY_JIFFIES_TIMEOUT;
21 * while ((retry_count > jiffies) && (! <some condition to wait for))
22 * {
23 * while (handle_sony_cd_attention())
24 * ;
25 *
26 * sony_sleep();
27 * }
28 * if (the condition not met)
29 * {
30 * return an error;
31 * }
32 *
33 * This ugly hack waits for something to happen, sleeping a little
34 * between every try. it also handles attentions, which are
35 * asyncronous events from the drive informing the driver that a disk
36 * has been inserted, removed, etc.
37 *
38 * One thing about these drives: They talk in MSF (Minute Second Frame) format.
39 * There are 75 frames a second, 60 seconds a minute, and up to 75 minutes on a
40 * disk. The funny thing is that these are sent to the drive in BCD, but the
41 * interface wants to see them in decimal. A lot of conversion goes on.
42 *
43 * Copyright (C) 1993 Corey Minyard
44 *
45 * This program is free software; you can redistribute it and/or modify
46 * it under the terms of the GNU General Public License as published by
47 * the Free Software Foundation; either version 2 of the License, or
48 * (at your option) any later version.
49 *
50 * This program is distributed in the hope that it will be useful,
51 * but WITHOUT ANY WARRANTY; without even the implied warranty of
52 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
53 * GNU General Public License for more details.
54 *
55 * You should have received a copy of the GNU General Public License
56 * along with this program; if not, write to the Free Software
57 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
58 *
59 */
60
61
62
63 #include <linux/errno.h>
64 #include <linux/signal.h>
65 #include <linux/sched.h>
66 #include <linux/timer.h>
67 #include <linux/fs.h>
68 #include <linux/kernel.h>
69 #include <linux/hdreg.h>
70 #include <linux/genhd.h>
71 #include <linux/ioport.h>
72
73 #include <asm/system.h>
74 #include <asm/io.h>
75 #include <asm/segment.h>
76
77 #include <linux/cdrom.h>
78 #include <linux/cdu31a.h>
79
80 #define MAJOR_NR CDU31A_CDROM_MAJOR
81 #include "blk.h"
82
83 #define CDU31A_MAX_CONSECUTIVE_ATTENTIONS 10
84
85 static unsigned short cdu31a_addresses[] =
86 {
87 0x340, /* Standard configuration Sony Interface */
88 0x1f88, /* Fusion CD-16 */
89 0x230, /* SoundBlaster 16 card */
90 0x360, /* Secondary standard Sony Interface */
91 0x320, /* Secondary standard Sony Interface */
92 0x330, /* Secondary standard Sony Interface */
93 0
94 };
95
96
97 static int handle_sony_cd_attention(void);
98 static int read_subcode(void);
99 static void sony_get_toc(void);
100 static int scd_open(struct inode *inode, struct file *filp);
101 static void do_sony_cd_cmd(unsigned char cmd,
102 unsigned char *params,
103 unsigned int num_params,
104 unsigned char *result_buffer,
105 unsigned int *result_size);
106 static void size_to_buf(unsigned int size,
107 unsigned char *buf);
108
109
110 /* The base I/O address of the Sony Interface. This is a variable (not a
111 #define) so it can be easily changed via some future ioctl() */
112 static unsigned short sony_cd_base_io = 0;
113
114 /*
115 * The following are I/O addresses of the various registers for the drive. The
116 * comment for the base address also applies here.
117 */
118 static volatile unsigned short sony_cd_cmd_reg;
119 static volatile unsigned short sony_cd_param_reg;
120 static volatile unsigned short sony_cd_write_reg;
121 static volatile unsigned short sony_cd_control_reg;
122 static volatile unsigned short sony_cd_status_reg;
123 static volatile unsigned short sony_cd_result_reg;
124 static volatile unsigned short sony_cd_read_reg;
125 static volatile unsigned short sony_cd_fifost_reg;
126
127
128 static int sony_disc_changed = 1; /* Has the disk been changed
129 since the last check? */
130 static int sony_toc_read = 0; /* Has the table of contents been
131 read? */
132 static int sony_spun_up = 0; /* Has the drive been spun up? */
133 static unsigned int sony_buffer_size; /* Size in bytes of the read-ahead
134 buffer. */
135 static unsigned int sony_buffer_sectors; /* Size (in 2048 byte records) of
136 the read-ahead buffer. */
137 static unsigned int sony_usage = 0; /* How many processes have the
138 drive open. */
139
140 static volatile int sony_first_block = -1; /* First OS block (512 byte) in
141 the read-ahead buffer */
142 static volatile int sony_last_block = -1; /* Last OS block (512 byte) in
143 the read-ahead buffer */
144
145 static struct s_sony_toc *sony_toc; /* Points to the table of
146 contents. */
147 static struct s_sony_subcode * volatile last_sony_subcode; /* Points to the last
148 subcode address read */
149 static unsigned char * volatile sony_buffer; /* Points to the read-ahead
150 buffer */
151
152 static volatile int sony_inuse = 0; /* Is the drive in use? Only one operation at a time
153 allowed */
154
155 static struct wait_queue * sony_wait = NULL;
156
157 static struct task_struct *has_cd_task = NULL; /* The task that is currently using the
158 CDROM drive, or NULL if none. */
159
160 /*
161 * The audio status uses the values from read subchannel data as specified
162 * in include/linux/cdrom.h.
163 */
164 static volatile int sony_audio_status = CDROM_AUDIO_NO_STATUS;
165
166 /*
167 * The following are a hack for pausing and resuming audio play. The drive
168 * does not work as I would expect it, if you stop it then start it again,
169 * the drive seeks back to the beginning and starts over. This holds the
170 * position during a pause so a resume can restart it. It uses the
171 * audio status variable above to tell if it is paused.
172 */
173 unsigned volatile char cur_pos_msf[3] = { 0, 0, 0 };
174 unsigned volatile char final_pos_msf[3] = { 0, 0, 0 };
175
176 /*
177 * This routine returns 1 if the disk has been changed since the last
178 * check or 0 if it hasn't. Setting flag to 0 resets the changed flag.
179 */
180 int
181 check_cdu31a_media_change(int full_dev, int flag)
182 {
183 int retval, target;
184
185
186 target = MINOR(full_dev);
187
188 if (target > 0) {
189 printk("Sony CD-ROM request error: invalid device.\n");
190 return 0;
191 }
192
193 retval = sony_disc_changed;
194 if (!flag)
195 {
196 sony_disc_changed = 0;
197 }
198
199 return retval;
200 }
201
202
203 /*
204 * Wait a little while (used for polling the drive). If in initialization,
205 * setting a timeout doesn't work, so just loop for a while.
206 */
207 static inline void
208 sony_sleep(void)
209 {
210 current->state = TASK_INTERRUPTIBLE;
211 current->timeout = jiffies;
212 schedule();
213 }
214
215
216 /*
217 * The following are convenience routine to read various status and set
218 * various conditions in the drive.
219 */
220 static inline int
221 is_attention(void)
222 {
223 return((inb(sony_cd_status_reg) & SONY_ATTN_BIT) != 0);
224 }
225
226 static inline int
227 is_busy(void)
228 {
229 return((inb(sony_cd_status_reg) & SONY_BUSY_BIT) != 0);
230 }
231
232 static inline int
233 is_data_ready(void)
234 {
235 return((inb(sony_cd_status_reg) & SONY_DATA_RDY_BIT) != 0);
236 }
237
238 static inline int
239 is_data_requested(void)
240 {
241 return((inb(sony_cd_status_reg) & SONY_DATA_REQUEST_BIT) != 0);
242 }
243
244 static inline int
245 is_result_ready(void)
246 {
247 return((inb(sony_cd_status_reg) & SONY_RES_RDY_BIT) != 0);
248 }
249
250 static inline int
251 is_param_write_rdy(void)
252 {
253 return((inb(sony_cd_fifost_reg) & SONY_PARAM_WRITE_RDY_BIT) != 0);
254 }
255
256 static inline void
257 reset_drive(void)
258 {
259 outb(SONY_DRIVE_RESET_BIT, sony_cd_control_reg);
260 }
261
262 static inline void
263 clear_attention(void)
264 {
265 outb(SONY_ATTN_CLR_BIT, sony_cd_control_reg);
266 }
267
268 static inline void
269 clear_result_ready(void)
270 {
271 outb(SONY_RES_RDY_CLR_BIT, sony_cd_control_reg);
272 }
273
274 static inline void
275 clear_data_ready(void)
276 {
277 outb(SONY_DATA_RDY_CLR_BIT, sony_cd_control_reg);
278 }
279
280 static inline void
281 clear_param_reg(void)
282 {
283 outb(SONY_PARAM_CLR_BIT, sony_cd_control_reg);
284 }
285
286 static inline unsigned char
287 read_status_register(void)
288 {
289 return(inb(sony_cd_status_reg));
290 }
291
292 static inline unsigned char
293 read_result_register(void)
294 {
295 return(inb(sony_cd_result_reg));
296 }
297
298 static inline unsigned char
299 read_data_register(void)
300 {
301 return(inb(sony_cd_read_reg));
302 }
303
304 static inline void
305 write_param(unsigned char param)
306 {
307 outb(param, sony_cd_param_reg);
308 }
309
310 static inline void
311 write_cmd(unsigned char cmd)
312 {
313 outb(cmd, sony_cd_cmd_reg);
314 outb(SONY_RES_RDY_INT_EN_BIT, sony_cd_control_reg);
315 }
316
317 /*
318 * Set the drive parameters so the drive will auto-spin-up when a
319 * disk is inserted.
320 */
321 static void
322 set_drive_params(void)
323 {
324 unsigned char res_reg[2];
325 unsigned int res_size;
326 unsigned char params[3];
327
328
329 params[0] = SONY_SD_MECH_CONTROL;
330 params[1] = 0x03;
331 do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
332 params,
333 2,
334 res_reg,
335 &res_size);
336 if ((res_size < 2) || ((res_reg[0] & 0x20) == 0x20))
337 {
338 printk(" Unable to set mechanical parameters: 0x%2.2x\n", res_reg[1]);
339 }
340 }
341
342 /*
343 * This code will reset the drive and attempt to restore sane parameters.
344 */
345 static void
346 restart_on_error(void)
347 {
348 unsigned char res_reg[2];
349 unsigned int res_size;
350 unsigned int retry_count;
351
352
353 printk("cdu31a: Resetting drive on error\n");
354 reset_drive();
355 retry_count = jiffies + SONY_RESET_TIMEOUT;
356 while ((retry_count > jiffies) && (!is_attention()))
357 {
358 sony_sleep();
359 }
360 set_drive_params();
361 do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size);
362 if ((res_size < 2) || ((res_reg[0] & 0x20) == 0x20))
363 {
364 printk("cdu31a: Unable to spin up drive: 0x%2.2x\n", res_reg[1]);
365 }
366
367 current->state = TASK_INTERRUPTIBLE;
368 current->timeout = jiffies + 200;
369 schedule();
370
371 do_sony_cd_cmd(SONY_READ_TOC_CMD, NULL, 0, res_reg, &res_size);
372 if ((res_size < 2) || ((res_reg[0] & 0x20) == 0x20))
373 {
374 printk("cdu31a: Unable to read TOC: 0x%2.2x\n", res_reg[1]);
375 }
376 sony_get_toc();
377 if (!sony_toc_read)
378 {
379 printk("cdu31a: Unable to get TOC data\n");
380 }
381 }
382
383 /*
384 * This routine writes data to the parameter register. Since this should
385 * happen fairly fast, it is polled with no OS waits between.
386 */
387 static int
388 write_params(unsigned char *params,
389 int num_params)
390 {
391 unsigned int retry_count;
392
393
394 retry_count = SONY_READY_RETRIES;
395 while ((retry_count > 0) && (!is_param_write_rdy()))
396 {
397 retry_count--;
398 }
399 if (!is_param_write_rdy())
400 {
401 return -EIO;
402 }
403
404 while (num_params > 0)
405 {
406 write_param(*params);
407 params++;
408 num_params--;
409 }
410
411 return 0;
412 }
413
414
415 /*
416 * The following reads data from the command result register. It is a
417 * fairly complex routine, all status info flows back through this
418 * interface. The algorithm is stolen directly from the flowcharts in
419 * the drive manual.
420 */
421 static void
422 get_result(unsigned char *result_buffer,
423 unsigned int *result_size)
424 {
425 unsigned char a, b;
426 int i;
427 unsigned int retry_count;
428
429
430 while (handle_sony_cd_attention())
431 ;
432 /* Wait for the result data to be ready */
433 retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
434 while ((retry_count > jiffies) && (is_busy() || (!(is_result_ready()))))
435 {
436 sony_sleep();
437
438 while (handle_sony_cd_attention())
439 ;
440 }
441 if (is_busy() || (!(is_result_ready())))
442 {
443 result_buffer[0] = 0x20;
444 result_buffer[1] = SONY_TIMEOUT_OP_ERR;
445 *result_size = 2;
446 return;
447 }
448
449 /*
450 * Get the first two bytes. This determines what else needs
451 * to be done.
452 */
453 clear_result_ready();
454 a = read_result_register();
455 *result_buffer = a;
456 result_buffer++;
457 b = read_result_register();
458 *result_buffer = b;
459 result_buffer++;
460 *result_size = 2;
461
462 /*
463 * 0x20 means an error occured. Byte 2 will have the error code.
464 * Otherwise, the command succeded, byte 2 will have the count of
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -