⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cdu31a.c.txt

📁 Linux块设备驱动分析与模拟实现
💻 TXT
📖 第 1 页 / 共 4 页
字号:
  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 + -