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 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 * Things to do:
35 * - handle errors and status better, put everything into a single word
36 * - use interrupts (code mostly there, but a big hole still missing)
37 * - handle multi-session CDs?
38 * - use DMA?
39 *
40 * Known Bugs:
41 * -
42 *
43 * Ken Pizzini (ken@halcyon.com)
44 *
45 * Original by:
46 * Ron Jeppesen (ronj.an@site007.saic.com)
47 *
48 *
49 *------------------------------------------------------------------------
50 * Sony CDROM interface device driver.
51 *
52 * Corey Minyard (minyard@wf-rch.cirr.com) (CDU-535 complaints to Ken above)
53 *
54 * Colossians 3:17
55 *
56 * The Sony interface device driver handles Sony interface CDROM
57 * drives and provides a complete block-level interface as well as an
58 * ioctl() interface compatible with the Sun (as specified in
59 * include/linux/cdrom.h). With this interface, CDROMs can be
60 * accessed and standard audio CDs can be played back normally.
61 *
62 * This interface is (unfortunately) a polled interface. This is
63 * because most Sony interfaces are set up with DMA and interrupts
64 * disables. Some (like mine) do not even have the capability to
65 * handle interrupts or DMA. For this reason you will see a lot of
66 * the following:
67 *
68 * retry_count = jiffies+ SONY_JIFFIES_TIMEOUT;
69 * while ((retry_count > jiffies) && (! <some condition to wait for))
70 * {
71 * while (handle_sony_cd_attention())
72 * ;
73 *
74 * sony_sleep();
75 * }
76 * if (the condition not met)
77 * {
78 * return an error;
79 * }
80 *
81 * This ugly hack waits for something to happen, sleeping a little
82 * between every try. it also handles attentions, which are
83 * asynchronous events from the drive informing the driver that a disk
84 * has been inserted, removed, etc.
85 *
86 * One thing about these drives: They talk in MSF (Minute Second Frame) format.
87 * There are 75 frames a second, 60 seconds a minute, and up to 75 minutes on a
88 * disk. The funny thing is that these are sent to the drive in BCD, but the
89 * interface wants to see them in decimal. A lot of conversion goes on.
90 *
91 * Copyright (C) 1993 Corey Minyard
92 *
93 * This program is free software; you can redistribute it and/or modify
94 * it under the terms of the GNU General Public License as published by
95 * the Free Software Foundation; either version 2 of the License, or
96 * (at your option) any later version.
97 *
98 * This program is distributed in the hope that it will be useful,
99 * but WITHOUT ANY WARRANTY; without even the implied warranty of
100 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
101 * GNU General Public License for more details.
102 *
103 * You should have received a copy of the GNU General Public License
104 * along with this program; if not, write to the Free Software
105 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
106 *
107 */
108
109
110 # include <linux/module.h>
111
112 #include <linux/errno.h>
113 #include <linux/signal.h>
114 #include <linux/sched.h>
115 #include <linux/timer.h>
116 #include <linux/fs.h>
117 #include <linux/kernel.h>
118 #include <linux/ioport.h>
119 #include <linux/hdreg.h>
120 #include <linux/genhd.h>
121 #include <linux/mm.h>
122 #include <linux/malloc.h>
123
124 #define REALLY_SLOW_IO
125 #include <asm/system.h>
126 #include <asm/io.h>
127 #include <asm/segment.h>
128
129 #include <linux/cdrom.h>
130
131 #define MAJOR_NR CDU535_CDROM_MAJOR
132 # include <linux/blk.h>
133 #define sony535_cd_base_io sonycd535 /* for compatible parameter passing with "insmod" */
134 #include <linux/sonycd535.h>
135
136 /*
137 * this is the base address of the interface card for the Sony CDU-535
138 * CDROM drive. If your jumpers are set for an address other than
139 * this one (the default), change the following line to the
140 * proper address.
141 */
142 #ifndef CDU535_ADDRESS
143 # define CDU535_ADDRESS 0x340
144 #endif
145 #ifndef CDU535_INTERRUPT
146 # define CDU535_INTERRUPT 0
147 #endif
148 #ifndef CDU535_HANDLE
149 # define CDU535_HANDLE "cdu535"
150 #endif
151 #ifndef CDU535_MESSAGE_NAME
152 # define CDU535_MESSAGE_NAME "Sony CDU-535"
153 #endif
154
155 #ifndef MAX_SPINUP_RETRY
156 # define MAX_SPINUP_RETRY 3 /* 1 is sufficient for most drives... */
157 #endif
158 #ifndef RETRY_FOR_BAD_STATUS
159 # define RETRY_FOR_BAD_STATUS 100 /* in 10th of second */
160 #endif
161
162 #ifndef DEBUG
163 # define DEBUG 1
164 #endif
165
166 /*
167 * SONY535_BUFFER_SIZE determines the size of internal buffer used
168 * by the drive. It must be at least 2K and the larger the buffer
169 * the better the transfer rate. It does however take system memory.
170 * On my system I get the following transfer rates using dd to read
171 * 10 Mb off /dev/cdrom.
172 *
173 * 8K buffer 43 Kb/sec
174 * 16K buffer 66 Kb/sec
175 * 32K buffer 91 Kb/sec
176 * 64K buffer 111 Kb/sec
177 * 128K buffer 123 Kb/sec
178 * 512K buffer 123 Kb/sec
179 */
180 #define SONY535_BUFFER_SIZE (64*1024)
181
182 /*
183 * if LOCK_DOORS is defined then the eject button is disabled while
184 * the device is open.
185 */
186 #ifndef NO_LOCK_DOORS
187 # define LOCK_DOORS
188 #endif
189
190 static int read_subcode(void);
191 static void sony_get_toc(void);
192 static int cdu_open(struct inode *inode, struct file *filp);
193 static inline unsigned int int_to_bcd(unsigned int val);
194 static unsigned int bcd_to_int(unsigned int bcd);
195 static int do_sony_cmd(Byte * cmd, int nCmd, Byte status[2],
196 Byte * response, int n_response, int ignoreStatusBit7);
197
198 /* The base I/O address of the Sony Interface. This is a variable (not a
199 #define) so it can be easily changed via some future ioctl() */
200 static unsigned int sony535_cd_base_io = CDU535_ADDRESS;
201
202 /*
203 * The following are I/O addresses of the various registers for the drive. The
204 * comment for the base address also applies here.
205 */
206 static unsigned short select_unit_reg;
207 static unsigned short result_reg;
208 static unsigned short command_reg;
209 static unsigned short read_status_reg;
210 static unsigned short data_reg;
211
212 static int initialized = 0; /* Has the drive been initialized? */
213 static int sony_disc_changed = 1; /* Has the disk been changed
214 since the last check? */
215 static int sony_toc_read = 0; /* Has the table of contents been
216 read? */
217 static unsigned int sony_buffer_size; /* Size in bytes of the read-ahead
218 buffer. */
219 static unsigned int sony_buffer_sectors; /* Size (in 2048 byte records) of
220 the read-ahead buffer. */
221 static unsigned int sony_usage = 0; /* How many processes have the
222 drive open. */
223
224 static int sony_first_block = -1; /* First OS block (512 byte) in
225 the read-ahead buffer */
226 static int sony_last_block = -1; /* Last OS block (512 byte) in
227 the read-ahead buffer */
228
229 static struct s535_sony_toc *sony_toc; /* Points to the table of
230 contents. */
231
232 static struct s535_sony_subcode *last_sony_subcode; /* Points to the last
233 subcode address read */
234 static Byte **sony_buffer; /* Points to the pointers
235 to the sector buffers */
236
237 static int sony_inuse = 0; /* is the drive in use? Only one
238 open at a time allowed */
239
240 /*
241 * The audio status uses the values from read subchannel data as specified
242 * in include/linux/cdrom.h.
243 */
244 static int sony_audio_status = CDROM_AUDIO_NO_STATUS;
245
246 /*
247 * The following are a hack for pausing and resuming audio play. The drive
248 * does not work as I would expect it, if you stop it then start it again,
249 * the drive seeks back to the beginning and starts over. This holds the
250 * position during a pause so a resume can restart it. It uses the
251 * audio status variable above to tell if it is paused.
252 * I just kept the CDU-31A driver behavior rather than using the PAUSE
253 * command on the CDU-535.
254 */
255 static Byte cur_pos_msf[3] = {0, 0, 0};
256 static Byte final_pos_msf[3] = {0, 0, 0};
257
258 /* What IRQ is the drive using? 0 if none. */
259 static int sony535_irq_used = CDU535_INTERRUPT;
260
261 /* The interrupt handler will wake this queue up when it gets an interrupt. */
262 static struct wait_queue *cdu535_irq_wait = NULL;
263
264
265 /*
266 * This routine returns 1 if the disk has been changed since the last
267 * check or 0 if it hasn't. Setting flag to 0 resets the changed flag.
268 */
269 static int
270 cdu535_check_media_change(kdev_t full_dev)
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
271 {
272 int retval;
273
274 if (MINOR(full_dev) != 0) {
275 printk(CDU535_MESSAGE_NAME " request error: invalid device.\n");
276 return 0;
277 }
278
279 /* if driver is not initialized, always return 0 */
280 retval = initialized ? sony_disc_changed : 0;
281 sony_disc_changed = 0;
282 return retval;
283 }
284
285 static inline void
286 enable_interrupts(void)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
287 {
288 #ifdef USE_IRQ
289 /*
290 * This code was taken from cdu31a.c; it will not
291 * directly work for the cdu535 as written...
292 */
293 curr_control_reg |= ( SONY_ATTN_INT_EN_BIT
294 | SONY_RES_RDY_INT_EN_BIT
295 | SONY_DATA_RDY_INT_EN_BIT);
296 outb(curr_control_reg, sony_cd_control_reg);
297 #endif
298 }
299
300 static inline void
301 disable_interrupts(void)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
302 {
303 #ifdef USE_IRQ
304 /*
305 * This code was taken from cdu31a.c; it will not
306 * directly work for the cdu535 as written...
307 */
308 curr_control_reg &= ~(SONY_ATTN_INT_EN_BIT
309 | SONY_RES_RDY_INT_EN_BIT
310 | SONY_DATA_RDY_INT_EN_BIT);
311 outb(curr_control_reg, sony_cd_control_reg);
312 #endif
313 }
314
315 static void
316 cdu535_interrupt(int irq, struct pt_regs *regs)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
317 {
318 disable_interrupts();
319 if (cdu535_irq_wait != NULL)
320 wake_up(&cdu535_irq_wait);
321 else
322 printk(CDU535_MESSAGE_NAME
323 ": Got an interrupt but nothing was waiting\n");
324 }
325
326
327 /*
328 * Wait a little while (used for polling the drive). If in initialization,
329 * setting a timeout doesn't work, so just loop for a while. (We trust
330 * that the sony_sleep() call is protected by a test for proper jiffies count.)
331 */
332 static inline void
333 sony_sleep(void)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
334 {
335 if (sony535_irq_used <= 0) { /* poll */
336 current->state = TASK_INTERRUPTIBLE;
337 current->timeout = jiffies;
338 schedule();
339 } else { /* Interrupt driven */
340 cli();
341 enable_interrupts();
342 interruptible_sleep_on(&cdu535_irq_wait);
343 sti();
344 }
345 }
346
347 /*------------------start of SONY CDU535 very specific ---------------------*/
348
349 /****************************************************************************
350 * void select_unit( int unit_no )
351 *
352 * Select the specified unit (0-3) so that subsequent commands reference it
353 ****************************************************************************/
354 static void
355 select_unit(int unit_no)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
356 {
357 unsigned int select_mask = ~(1 << unit_no);
358 outb(select_mask, select_unit_reg);
359 }
360
361 /***************************************************************************
362 * int read_result_reg( Byte *data_ptr )
363 *
364 * Read a result byte from the Sony CDU controller, store in location pointed
365 * to by data_ptr. Return zero on success, TIME_OUT if we did not receive
366 * data.
367 ***************************************************************************/
368 static int
369 read_result_reg(Byte *data_ptr)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
370 {
371 int retry_count;
372 int read_status;
373
374 retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
375 while (jiffies < retry_count) {
376 if (((read_status = inb(read_status_reg)) & SONY535_RESULT_NOT_READY_BIT) == 0) {
377 #if DEBUG > 1
378 printk(CDU535_MESSAGE_NAME
379 ": read_result_reg(): readStatReg = 0x%x\n", read_status);
380 #endif
381 *data_ptr = inb(result_reg);
382 return 0;
383 } else {
384 sony_sleep();
385 }
386 }
387 printk(CDU535_MESSAGE_NAME " read_result_reg: TIME OUT!\n");
388 return TIME_OUT;
389 }
390
391 /****************************************************************************
392 * int read_exec_status( Byte status[2] )
393 *
394 * Read the execution status of the last command and put into status.
395 * Handles reading second status word if available. Returns 0 on success,
396 * TIME_OUT on failure.
397 ****************************************************************************/
398 static int
399 read_exec_status(Byte status[2])
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
400 {
401 status[1] = 0;
402 if (read_result_reg(&(status[0])) != 0)
403 return TIME_OUT;
404 if ((status[0] & 0x80) != 0) { /* byte two follows */
405 if (read_result_reg(&(status[1])) != 0)
406 return TIME_OUT;
407 }
408 #if DEBUG > 1
409 printk(CDU535_MESSAGE_NAME ": read_exec_status: read 0x%x 0x%x\n",
410 status[0], status[1]);
411 #endif
412 return 0;
413 }
414
415 /****************************************************************************
416 * int check_drive_status( void )
417 *
418 * Check the current drive status. Using this before executing a command
419 * takes care of the problem of unsolicited drive status-2 messages.
420 * Add a check of the audio status if we think the disk is playing.
421 ****************************************************************************/
422 static int
423 check_drive_status(void)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
424 {
425 Byte status, e_status[2];
426 int CDD, ATN;
427 Byte cmd;
428
429 select_unit(0);
430 if (sony_audio_status == CDROM_AUDIO_PLAY) { /* check status */
431 outb(SONY535_REQUEST_AUDIO_STATUS, command_reg);
432 if (read_result_reg(&status) == 0) {
433 switch (status) {
434 case 0x0:
435 break; /* play in progress */
436 case 0x1:
437 break; /* paused */
438 case 0x3: /* audio play completed */
439 case 0x5: /* play not requested */
440 sony_audio_status = CDROM_AUDIO_COMPLETED;
441 read_subcode();
442 break;
443 case 0x4: /* error during play */
444 sony_audio_status = CDROM_AUDIO_ERROR;
445 break;
446 }
447 }
448 }
449 /* now check drive status */
450 outb(SONY535_REQUEST_DRIVE_STATUS_2, command_reg);
451 if (read_result_reg(&status) != 0)
452 return TIME_OUT;
453
454 #if DEBUG > 1
455 printk(CDU535_MESSAGE_NAME ": check_drive_status() got 0x%x\n", status);
456 #endif
457
458 if (status == 0)
459 return 0;
460
461 ATN = status & 0xf;
462 CDD = (status >> 4) & 0xf;
463
464 switch (ATN) {
465 case 0x0:
466 break; /* go on to CDD stuff */
467 case SONY535_ATN_BUSY:
468 if (initialized)
469 printk(CDU535_MESSAGE_NAME " error: drive busy\n");
470 return CD_BUSY;
471 case SONY535_ATN_EJECT_IN_PROGRESS:
472 printk(CDU535_MESSAGE_NAME " error: eject in progress\n");
473 sony_audio_status = CDROM_AUDIO_INVALID;
474 return CD_BUSY;
475 case SONY535_ATN_RESET_OCCURRED:
476 case SONY535_ATN_DISC_CHANGED:
477 case SONY535_ATN_RESET_AND_DISC_CHANGED:
478 #if DEBUG > 0
479 printk(CDU535_MESSAGE_NAME " notice: reset occurred or disc changed\n");
480 #endif
481 sony_disc_changed = 1;
482 sony_toc_read = 0;
483 sony_audio_status = CDROM_AUDIO_NO_STATUS;
484 sony_first_block = -1;
485 sony_last_block = -1;
486 if (initialized) {
487 cmd = SONY535_SPIN_UP;
488 do_sony_cmd(&cmd, 1, e_status, NULL, 0, 0);
489 sony_get_toc();
490 }
491 return 0;
492 default:
493 printk(CDU535_MESSAGE_NAME " error: drive busy (ATN=0x%x)\n", ATN);
494 return CD_BUSY;
495 }
496 switch (CDD) { /* the 531 docs are not helpful in decoding this */
497 case 0x0: /* just use the values from the DOS driver */
498 case 0x2:
499 case 0xa:
500 break; /* no error */
501 case 0xc:
502 printk(CDU535_MESSAGE_NAME
503 ": check_drive_status(): CDD = 0xc! Not properly handled!\n");
504 return CD_BUSY; /* ? */
505 default:
506 return CD_BUSY;
507 }
508 return 0;
509 } /* check_drive_status() */
510
511 /*****************************************************************************
512 * int do_sony_cmd( Byte *cmd, int n_cmd, Byte status[2],
513 * Byte *response, int n_response, int ignore_status_bit7 )
514 *
515 * Generic routine for executing commands. The command and its parameters
516 * should be placed in the cmd[] array, number of bytes in the command is
517 * stored in nCmd. The response from the command will be stored in the
518 * response array. The number of bytes you expect back (excluding status)
519 * should be passed in n_response. Finally, some
520 * commands set bit 7 of the return status even when there is no second
521 * status byte, on these commands set ignoreStatusBit7 TRUE.
522 * If the command was sent and data received back, then we return 0,
523 * else we return TIME_OUT. You still have to check the status yourself.
524 * You should call check_drive_status() before calling this routine
525 * so that you do not lose notifications of disk changes, etc.
526 ****************************************************************************/
527 static int
528 do_sony_cmd(Byte * cmd, int n_cmd, Byte status[2],
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
529 Byte * response, int n_response, int ignore_status_bit7)
530 {
531 int i;
532
533 /* write out the command */
534 for (i = 0; i < n_cmd; i++)
535 outb(cmd[i], command_reg);
536
537 /* read back the status */
538 if (read_result_reg(status) != 0)
539 return TIME_OUT;
540 if (!ignore_status_bit7 && ((status[0] & 0x80) != 0)) {
541 /* get second status byte */
542 if (read_result_reg(status + 1) != 0)
543 return TIME_OUT;
544 } else {
545 status[1] = 0;
546 }
547 #if DEBUG > 2
548 printk(CDU535_MESSAGE_NAME ": do_sony_cmd %x: %x %x\n",
549 *cmd, status[0], status[1]);
550 #endif
551
552 /* do not know about when I should read set of data and when not to */
553 if ((status[0] & ((ignore_status_bit7 ? 0x7f : 0xff) & 0x8f)) != 0)
554 return 0;
555
556 /* else, read in rest of data */
557 for (i = 0; 0 < n_response; n_response--, i++)
558 if (read_result_reg(response + i) != 0)
559 return TIME_OUT;
560 return 0;
561 } /* do_sony_cmd() */
562
563 /**************************************************************************
564 * int set_drive_mode( int mode, Byte status[2] )
565 *
566 * Set the drive mode to the specified value (mode=0 is audio, mode=e0
567 * is mode-1 CDROM
568 **************************************************************************/
569 static int
570 set_drive_mode(int mode, Byte status[2])
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
571 {
572 Byte cmd_buff[2];
573 Byte ret_buff[1];
574
575 cmd_buff[0] = SONY535_SET_DRIVE_MODE;
576 cmd_buff[1] = mode;
577 return do_sony_cmd(cmd_buff, 2, status, ret_buff, 1, 1);
578 }
579
580 /***************************************************************************
581 * int seek_and_read_N_blocks( Byte params[], int n_blocks, Byte status[2],
582 * Byte *data_buff, int buff_size )
583 *
584 * Read n_blocks of data from the CDROM starting at position params[0:2],
585 * number of blocks in stored in params[3:5] -- both these are already
586 * int bcd format.
587 * Transfer the data into the buffer pointed at by data_buff. buff_size
588 * gives the number of bytes available in the buffer.
589 * The routine returns number of bytes read in if successful, otherwise
590 * it returns one of the standard error returns.
591 ***************************************************************************/
592 static int
593 seek_and_read_N_blocks(Byte params[], int n_blocks, Byte status[2],
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
594 Byte **buff, int buf_size)
595 {
596 const int block_size = 2048;
597 Byte cmd_buff[7];
598 int i;
599 int read_status;
600 int retry_count;
601 Byte *data_buff;
602 int sector_count = 0;
603
604 if (buf_size < ((long)block_size) * n_blocks)
605 return NO_ROOM;
606
607 set_drive_mode(SONY535_CDROM_DRIVE_MODE, status);
608
609 /* send command to read the data */
610 cmd_buff[0] = SONY535_SEEK_AND_READ_N_BLOCKS_1;
611 for (i = 0; i < 6; i++)
612 cmd_buff[i + 1] = params[i];
613 for (i = 0; i < 7; i++)
614 outb(cmd_buff[i], command_reg);
615
616 /* read back the data one block at a time */
617 while (0 < n_blocks--) {
618 /* wait for data to be ready */
619 retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
620 while (jiffies < retry_count) {
621 read_status = inb(read_status_reg);
622 if ((read_status & SONY535_RESULT_NOT_READY_BIT) == 0) {
623 read_exec_status(status);
624 return BAD_STATUS;
625 }
626 if ((read_status & SONY535_DATA_NOT_READY_BIT) == 0) {
627 /* data is ready, read it */
628 data_buff = buff[sector_count++];
629 for (i = 0; i < block_size; i++)
630 *data_buff++ = inb(data_reg); /* unrolling this loop does not seem to help */
631 break; /* exit the timeout loop */
632 }
633 sony_sleep(); /* data not ready, sleep a while */
634 }
635 if (retry_count <= jiffies)
636 return TIME_OUT; /* if we reach this stage */
637 }
638
639 /* read all the data, now read the status */
640 if ((i = read_exec_status(status)) != 0)
641 return i;
642 return block_size * sector_count;
643 } /* seek_and_read_N_blocks() */
644
645 /****************************************************************************
646 * int request_toc_data( Byte status[2], struct s535_sony_toc *toc )
647 *
648 * Read in the table of contents data. Converts all the bcd data
649 * into integers in the toc structure.
650 ****************************************************************************/
651 static int
652 request_toc_data(Byte status[2], struct s535_sony_toc *toc)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
653 {
654 int to_status;
655 int i, j, n_tracks, track_no;
656 int first_track_num, last_track_num;
657 Byte cmd_no = 0xb2;
658 Byte track_address_buffer[5];
659
660 /* read the fixed portion of the table of contents */
661 if ((to_status = do_sony_cmd(&cmd_no, 1, status, (Byte *) toc, 15, 1)) != 0)
662 return to_status;
663
664 /* convert the data into integers so we can use them */
665 first_track_num = bcd_to_int(toc->first_track_num);
666 last_track_num = bcd_to_int(toc->last_track_num);
667 n_tracks = last_track_num - first_track_num + 1;
668
669 /* read each of the track address descriptors */
670 for (i = 0; i < n_tracks; i++) {
671 /* read the descriptor into a temporary buffer */
672 for (j = 0; j < 5; j++) {
673 if (read_result_reg(track_address_buffer + j) != 0)
674 return TIME_OUT;
675 if (j == 1) /* need to convert from bcd */
676 track_no = bcd_to_int(track_address_buffer[j]);
677 }
678 /* copy the descriptor to proper location - sonycd.c just fills */
679 memcpy(toc->tracks + i, track_address_buffer, 5);
680 }
681 return 0;
682 } /* request_toc_data() */
683
684 /***************************************************************************
685 * int spin_up_drive( Byte status[2] )
686 *
687 * Spin up the drive (unless it is already spinning).
688 ***************************************************************************/
689 static int
690 spin_up_drive(Byte status[2])
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
691 {
692 Byte cmd;
693
694 /* first see if the drive is already spinning */
695 cmd = SONY535_REQUEST_DRIVE_STATUS_1;
696 if (do_sony_cmd(&cmd, 1, status, NULL, 0, 0) != 0)
697 return TIME_OUT;
698 if ((status[0] & SONY535_STATUS1_NOT_SPINNING) == 0)
699 return 0; /* it's already spinning */
700
701 /* otherwise, give the spin-up command */
702 cmd = SONY535_SPIN_UP;
703 return do_sony_cmd(&cmd, 1, status, NULL, 0, 0);
704 }
705
706 /*--------------------end of SONY CDU535 very specific ---------------------*/
707
708 /* Convert from an integer 0-99 to BCD */
709 static inline unsigned int
710 int_to_bcd(unsigned int val)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
711 {
712 int retval;
713
714 retval = (val / 10) << 4;
715 retval = retval | val % 10;
716 return retval;
717 }
718
719
720 /* Convert from BCD to an integer from 0-99 */
721 static unsigned int
722 bcd_to_int(unsigned int bcd)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
723 {
724 return (((bcd >> 4) & 0x0f) * 10) + (bcd & 0x0f);
725 }
726
727
728 /*
729 * Convert a logical sector value (like the OS would want to use for
730 * a block device) to an MSF format.
731 */
732 static void
733 log_to_msf(unsigned int log, Byte *msf)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
734 {
735 log = log + LOG_START_OFFSET;
736 msf[0] = int_to_bcd(log / 4500);
737 log = log % 4500;
738 msf[1] = int_to_bcd(log / 75);
739 msf[2] = int_to_bcd(log % 75);
740 }
741
742
743 /*
744 * Convert an MSF format to a logical sector.
745 */
746 static unsigned int
747 msf_to_log(Byte *msf)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
748 {
749 unsigned int log;
750
751
752 log = bcd_to_int(msf[2]);
753 log += bcd_to_int(msf[1]) * 75;
754 log += bcd_to_int(msf[0]) * 4500;
755 log = log - LOG_START_OFFSET;
756
757 return log;
758 }
759
760
761 /*
762 * Take in integer size value and put it into a buffer like
763 * the drive would want to see a number-of-sector value.
764 */
765 static void
766 size_to_buf(unsigned int size, Byte *buf)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
767 {
768 buf[0] = size / 65536;
769 size = size % 65536;
770 buf[1] = size / 256;
771 buf[2] = size % 256;
772 }
773
774
775 /*
776 * The OS calls this to perform a read or write operation to the drive.
777 * Write obviously fail. Reads to a read ahead of sony_buffer_size
778 * bytes to help speed operations. This especially helps since the OS
779 * uses 1024 byte blocks and the drive uses 2048 byte blocks. Since most
780 * data access on a CD is done sequentially, this saves a lot of operations.
781 */
782 static void
783 do_cdu535_request(void)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
784 {
785 unsigned int dev;
786 unsigned int read_size;
787 int block;
788 int nsect;
789 int copyoff;
790 int spin_up_retry;
791 Byte params[10];
792 Byte status[2];
793 Byte cmd[2];
794
795 if (!sony_inuse) {
796 cdu_open(NULL, NULL);
797 }
798 while (1) {
799 /*
800 * The beginning here is stolen from the hard disk driver. I hope
801 * it's right.
802 */
803 if (!(CURRENT) || CURRENT->rq_status == RQ_INACTIVE) {
804 return;
805 }
806 INIT_REQUEST;
807 dev = MINOR(CURRENT->rq_dev);
808 block = CURRENT->sector;
809 nsect = CURRENT->nr_sectors;
810 if (dev != 0) {
811 end_request(0);
812 continue;
813 }
814 switch (CURRENT->cmd) {
815 case READ:
816 /*
817 * If the block address is invalid or the request goes beyond the end of
818 * the media, return an error.
819 */
820
821 if (sony_toc->lead_out_start_lba <= (block / 4)) {
822 end_request(0);
823 return;
824 }
825 if (sony_toc->lead_out_start_lba <= ((block + nsect) / 4)) {
826 end_request(0);
827 return;
828 }
829 while (0 < nsect) {
830 /*
831 * If the requested sector is not currently in the read-ahead buffer,
832 * it must be read in.
833 */
834 if ((block < sony_first_block) || (sony_last_block < block)) {
835 sony_first_block = (block / 4) * 4;
836 log_to_msf(block / 4, params);
837
838 /*
839 * If the full read-ahead would go beyond the end of the media, trim
840 * it back to read just till the end of the media.
841 */
842 if (sony_toc->lead_out_start_lba <= ((block / 4) + sony_buffer_sectors)) {
843 sony_last_block = (sony_toc->lead_out_start_lba * 4) - 1;
844 read_size = sony_toc->lead_out_start_lba - (block / 4);
845 } else {
846 sony_last_block = sony_first_block + (sony_buffer_sectors * 4) - 1;
847 read_size = sony_buffer_sectors;
848 }
849 size_to_buf(read_size, ¶ms[3]);
850
851 /*
852 * Read the data. If the drive was not spinning,
853 * spin it up and try some more.
854 */
855 for (spin_up_retry=0 ;; ++spin_up_retry) {
856 /* This loop has been modified to support the Sony
857 * CDU-510/515 series, thanks to Claudio Porfiri
858 * <C.Porfiri@nisms.tei.ericsson.se>.
859 */
860 /*
861 * This part is to deal with very slow hardware. We
862 * try at most MAX_SPINUP_RETRY times to read the same
863 * block. A check for seek_and_read_N_blocks' result is
864 * performed; if the result is wrong, the CDROM's engine
865 * is restarted and the operation is tried again.
866 */
867 /*
868 * 1995-06-01: The system got problems when downloading
869 * from Slackware CDROM, the problem seems to be:
870 * seek_and_read_N_blocks returns BAD_STATUS and we
871 * should wait for a while before retrying, so a new
872 * part was added to discriminate the return value from
873 * seek_and_read_N_blocks for the various cases.
874 */
875 int readStatus = seek_and_read_N_blocks(params, read_size,
876 status, sony_buffer, (read_size * 2048));
877 if (0 <= readStatus) /* Good data; common case, placed first */
878 break;
879 if (readStatus == NO_ROOM || spin_up_retry == MAX_SPINUP_RETRY) {
880 /* give up */
881 if (readStatus == NO_ROOM)
882 printk(CDU535_MESSAGE_NAME " No room to read from CD\n");
883 else
884 printk(CDU535_MESSAGE_NAME " Read error: 0x%.2x\n",
885 status[0]);
886 sony_first_block = -1;
887 sony_last_block = -1;
888 end_request(0);
889 return;
890 }
891 if (readStatus == BAD_STATUS) {
892 /* Sleep for a while, then retry */
893 current->state = TASK_INTERRUPTIBLE;
894 current->timeout = jiffies + RETRY_FOR_BAD_STATUS;
895 schedule();
896 }
897 #if DEBUG > 0
898 printk(CDU535_MESSAGE_NAME
899 " debug: calling spin up when reading data!\n");
900 #endif
901 cmd[0] = SONY535_SPIN_UP;
902 do_sony_cmd(cmd, 1, status, NULL, 0, 0);
903 }
904 }
905 /*
906 * The data is in memory now, copy it to the buffer and advance to the
907 * next block to read.
908 */
909 copyoff = block - sony_first_block;
910 memcpy(CURRENT->buffer,
911 sony_buffer[copyoff / 4] + 512 * (copyoff % 4), 512);
912
913 block += 1;
914 nsect -= 1;
915 CURRENT->buffer += 512;
916 }
917
918 end_request(1);
919 break;
920
921 case WRITE:
922 end_request(0);
923 break;
924
925 default:
926 panic("Unknown SONY CD cmd");
927 }
928 }
929 }
930
931
932 /*
933 * Read the table of contents from the drive and set sony_toc_read if
934 * successful.
935 */
936 static void
937 sony_get_toc(void)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
938 {
939 Byte status[2];
940 if (!sony_toc_read) {
941 /* do not call check_drive_status() from here since it can call this routine */
942 if (request_toc_data(status, sony_toc) < 0)
943 return;
944 sony_toc->lead_out_start_lba = msf_to_log(sony_toc->lead_out_start_msf);
945 sony_toc_read = 1;
946 }
947 }
948
949
950 /*
951 * Search for a specific track in the table of contents. track is
952 * passed in bcd format
953 */
954 static int
955 find_track(int track)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
956 {
957 int i;
958 int num_tracks;
959
960
961 num_tracks = bcd_to_int(sony_toc->last_track_num) -
962 bcd_to_int(sony_toc->first_track_num) + 1;
963 for (i = 0; i < num_tracks; i++) {
964 if (sony_toc->tracks[i].track == track) {
965 return i;
966 }
967 }
968
969 return -1;
970 }
971
972 /*
973 * Read the subcode and put it int last_sony_subcode for future use.
974 */
975 static int
976 read_subcode(void)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
977 {
978 Byte cmd = SONY535_REQUEST_SUB_Q_DATA;
979 Byte status[2];
980 int dsc_status;
981
982 if (check_drive_status() != 0)
983 return -EIO;
984
985 if ((dsc_status = do_sony_cmd(&cmd, 1, status, (Byte *) last_sony_subcode,
986 sizeof(struct s535_sony_subcode), 1)) != 0) {
987 printk(CDU535_MESSAGE_NAME " error 0x%.2x, %d (read_subcode)\n",
988 status[0], dsc_status);
989 return -EIO;
990 }
991 return 0;
992 }
993
994
995 /*
996 * Get the subchannel info like the CDROMSUBCHNL command wants to see it. If
997 * the drive is playing, the subchannel needs to be read (since it would be
998 * changing). If the drive is paused or completed, the subcode information has
999 * already been stored, just use that. The ioctl call wants things in decimal
1000 * (not BCD), so all the conversions are done.
1001 */
1002 static int
1003 sony_get_subchnl_info(long arg)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
1004 {
1005 struct cdrom_subchnl schi;
1006 int err;
1007
1008 /* Get attention stuff */
1009 if (check_drive_status() != 0)
1010 return -EIO;
1011
1012 sony_get_toc();
1013 if (!sony_toc_read) {
1014 return -EIO;
1015 }
1016 err = verify_area(VERIFY_WRITE /* and read */ , (char *)arg, sizeof schi);
1017 if (err)
1018 return err;
1019
1020 memcpy_fromfs(&schi, (char *)arg, sizeof schi);
1021
1022 switch (sony_audio_status) {
1023 case CDROM_AUDIO_PLAY:
1024 if (read_subcode() < 0) {
1025 return -EIO;
1026 }
1027 break;
1028
1029 case CDROM_AUDIO_PAUSED:
1030 case CDROM_AUDIO_COMPLETED:
1031 break;
1032
1033 case CDROM_AUDIO_NO_STATUS:
1034 schi.cdsc_audiostatus = sony_audio_status;
1035 memcpy_tofs((char *)arg, &schi, sizeof schi);
1036 return 0;
1037 break;
1038
1039 case CDROM_AUDIO_INVALID:
1040 case CDROM_AUDIO_ERROR:
1041 default:
1042 return -EIO;
1043 }
1044
1045 schi.cdsc_audiostatus = sony_audio_status;
1046 schi.cdsc_adr = last_sony_subcode->address;
1047 schi.cdsc_ctrl = last_sony_subcode->control;
1048 schi.cdsc_trk = bcd_to_int(last_sony_subcode->track_num);
1049 schi.cdsc_ind = bcd_to_int(last_sony_subcode->index_num);
1050 if (schi.cdsc_format == CDROM_MSF) {
1051 schi.cdsc_absaddr.msf.minute = bcd_to_int(last_sony_subcode->abs_msf[0]);
1052 schi.cdsc_absaddr.msf.second = bcd_to_int(last_sony_subcode->abs_msf[1]);
1053 schi.cdsc_absaddr.msf.frame = bcd_to_int(last_sony_subcode->abs_msf[2]);
1054
1055 schi.cdsc_reladdr.msf.minute = bcd_to_int(last_sony_subcode->rel_msf[0]);
1056 schi.cdsc_reladdr.msf.second = bcd_to_int(last_sony_subcode->rel_msf[1]);
1057 schi.cdsc_reladdr.msf.frame = bcd_to_int(last_sony_subcode->rel_msf[2]);
1058 } else if (schi.cdsc_format == CDROM_LBA) {
1059 schi.cdsc_absaddr.lba = msf_to_log(last_sony_subcode->abs_msf);
1060 schi.cdsc_reladdr.lba = msf_to_log(last_sony_subcode->rel_msf);
1061 }
1062 memcpy_tofs((char *)arg, &schi, sizeof schi);
1063 return 0;
1064 }
1065
1066
1067 /*
1068 * The big ugly ioctl handler.
1069 */
1070 static int
1071 cdu_ioctl(struct inode *inode,
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
1072 struct file *file,
1073 unsigned int cmd,
1074 unsigned long arg)
1075 {
1076 unsigned int dev;
1077 Byte status[2];
1078 Byte cmd_buff[10], params[10];
1079 int i;
1080 int dsc_status;
1081 int err;
1082
1083 if (!inode) {
1084 return -EINVAL;
1085 }
1086 dev = MINOR(inode->i_rdev) >> 6;
1087 if (dev != 0) {
1088 return -EINVAL;
1089 }
1090 if (check_drive_status() != 0)
1091 return -EIO;
1092
1093 switch (cmd) {
1094 case CDROMSTART: /* Spin up the drive */
1095 if (spin_up_drive(status) < 0) {
1096 printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMSTART)\n",
1097 status[0]);
1098 return -EIO;
1099 }
1100 return 0;
1101 break;
1102
1103 case CDROMSTOP: /* Spin down the drive */
1104 cmd_buff[0] = SONY535_HOLD;
1105 do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
1106
1107 /*
1108 * Spin the drive down, ignoring the error if the disk was
1109 * already not spinning.
1110 */
1111 sony_audio_status = CDROM_AUDIO_NO_STATUS;
1112 cmd_buff[0] = SONY535_SPIN_DOWN;
1113 dsc_status = do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
1114 if (((dsc_status < 0) && (dsc_status != BAD_STATUS)) ||
1115 ((status[0] & ~(SONY535_STATUS1_NOT_SPINNING)) != 0)) {
1116 printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMSTOP)\n",
1117 status[0]);
1118 return -EIO;
1119 }
1120 return 0;
1121 break;
1122
1123 case CDROMPAUSE: /* Pause the drive */
1124 cmd_buff[0] = SONY535_HOLD; /* CDU-31 driver uses AUDIO_STOP, not pause */
1125 if (do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0) != 0) {
1126 printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMPAUSE)\n",
1127 status[0]);
1128 return -EIO;
1129 }
1130 /* Get the current position and save it for resuming */
1131 if (read_subcode() < 0) {
1132 return -EIO;
1133 }
1134 cur_pos_msf[0] = last_sony_subcode->abs_msf[0];
1135 cur_pos_msf[1] = last_sony_subcode->abs_msf[1];
1136 cur_pos_msf[2] = last_sony_subcode->abs_msf[2];
1137 sony_audio_status = CDROM_AUDIO_PAUSED;
1138 return 0;
1139 break;
1140
1141 case CDROMRESUME: /* Start the drive after being paused */
1142 set_drive_mode(SONY535_AUDIO_DRIVE_MODE, status);
1143
1144 if (sony_audio_status != CDROM_AUDIO_PAUSED) {
1145 return -EINVAL;
1146 }
1147 spin_up_drive(status);
1148
1149 /* Start the drive at the saved position. */
1150 cmd_buff[0] = SONY535_PLAY_AUDIO;
1151 cmd_buff[1] = 0; /* play back starting at this address */
1152 cmd_buff[2] = cur_pos_msf[0];
1153 cmd_buff[3] = cur_pos_msf[1];
1154 cmd_buff[4] = cur_pos_msf[2];
1155 cmd_buff[5] = SONY535_PLAY_AUDIO;
1156 cmd_buff[6] = 2; /* set ending address */
1157 cmd_buff[7] = final_pos_msf[0];
1158 cmd_buff[8] = final_pos_msf[1];
1159 cmd_buff[9] = final_pos_msf[2];
1160 if ((do_sony_cmd(cmd_buff, 5, status, NULL, 0, 0) != 0) ||
1161 (do_sony_cmd(cmd_buff + 5, 5, status, NULL, 0, 0) != 0)) {
1162 printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMRESUME)\n",
1163 status[0]);
1164 return -EIO;
1165 }
1166 sony_audio_status = CDROM_AUDIO_PLAY;
1167 return 0;
1168 break;
1169
1170 case CDROMPLAYMSF: /* Play starting at the given MSF address. */
1171 err = verify_area(VERIFY_READ, (char *)arg, 6);
1172 if (err)
1173 return err;
1174 spin_up_drive(status);
1175 set_drive_mode(SONY535_AUDIO_DRIVE_MODE, status);
1176 memcpy_fromfs(params, (void *)arg, 6);
1177
1178 /* The parameters are given in int, must be converted */
1179 for (i = 0; i < 3; i++) {
1180 cmd_buff[2 + i] = int_to_bcd(params[i]);
1181 cmd_buff[7 + i] = int_to_bcd(params[i + 3]);
1182 }
1183 cmd_buff[0] = SONY535_PLAY_AUDIO;
1184 cmd_buff[1] = 0; /* play back starting at this address */
1185 /* cmd_buff[2-4] are filled in for loop above */
1186 cmd_buff[5] = SONY535_PLAY_AUDIO;
1187 cmd_buff[6] = 2; /* set ending address */
1188 /* cmd_buff[7-9] are filled in for loop above */
1189 if ((do_sony_cmd(cmd_buff, 5, status, NULL, 0, 0) != 0) ||
1190 (do_sony_cmd(cmd_buff + 5, 5, status, NULL, 0, 0) != 0)) {
1191 printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMPLAYMSF)\n",
1192 status[0]);
1193 return -EIO;
1194 }
1195 /* Save the final position for pauses and resumes */
1196 final_pos_msf[0] = cmd_buff[7];
1197 final_pos_msf[1] = cmd_buff[8];
1198 final_pos_msf[2] = cmd_buff[9];
1199 sony_audio_status = CDROM_AUDIO_PLAY;
1200 return 0;
1201 break;
1202
1203 case CDROMREADTOCHDR: /* Read the table of contents header */
1204 {
1205 struct cdrom_tochdr *hdr;
1206 struct cdrom_tochdr loc_hdr;
1207
1208 sony_get_toc();
1209 if (!sony_toc_read)
1210 return -EIO;
1211 hdr = (struct cdrom_tochdr *)arg;
1212 err = verify_area(VERIFY_WRITE, hdr, sizeof *hdr);
1213 if (err)
1214 return err;
1215 loc_hdr.cdth_trk0 = bcd_to_int(sony_toc->first_track_num);
1216 loc_hdr.cdth_trk1 = bcd_to_int(sony_toc->last_track_num);
1217 memcpy_tofs(hdr, &loc_hdr, sizeof *hdr);
1218 }
1219 return 0;
1220 break;
1221
1222 case CDROMREADTOCENTRY: /* Read a given table of contents entry */
1223 {
1224 struct cdrom_tocentry *entry;
1225 struct cdrom_tocentry loc_entry;
1226 int track_idx;
1227 Byte *msf_val = NULL;
1228
1229 sony_get_toc();
1230 if (!sony_toc_read) {
1231 return -EIO;
1232 }
1233 entry = (struct cdrom_tocentry *)arg;
1234 err = verify_area(VERIFY_WRITE /* and read */ , entry, sizeof *entry);
1235 if (err)
1236 return err;
1237
1238 memcpy_fromfs(&loc_entry, entry, sizeof loc_entry);
1239
1240 /* Lead out is handled separately since it is special. */
1241 if (loc_entry.cdte_track == CDROM_LEADOUT) {
1242 loc_entry.cdte_adr = 0 /*sony_toc->address2 */ ;
1243 loc_entry.cdte_ctrl = sony_toc->control2;
1244 msf_val = sony_toc->lead_out_start_msf;
1245 } else {
1246 track_idx = find_track(int_to_bcd(loc_entry.cdte_track));
1247 if (track_idx < 0)
1248 return -EINVAL;
1249 loc_entry.cdte_adr = 0 /*sony_toc->tracks[track_idx].address */ ;
1250 loc_entry.cdte_ctrl = sony_toc->tracks[track_idx].control;
1251 msf_val = sony_toc->tracks[track_idx].track_start_msf;
1252 }
1253
1254 /* Logical buffer address or MSF format requested? */
1255 if (loc_entry.cdte_format == CDROM_LBA) {
1256 loc_entry.cdte_addr.lba = msf_to_log(msf_val);
1257 } else if (loc_entry.cdte_format == CDROM_MSF) {
1258 loc_entry.cdte_addr.msf.minute = bcd_to_int(*msf_val);
1259 loc_entry.cdte_addr.msf.second = bcd_to_int(*(msf_val + 1));
1260 loc_entry.cdte_addr.msf.frame = bcd_to_int(*(msf_val + 2));
1261 }
1262 memcpy_tofs(entry, &loc_entry, sizeof *entry);
1263 }
1264 return 0;
1265 break;
1266
1267 case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */
1268 {
1269 struct cdrom_ti ti;
1270 int track_idx;
1271
1272 sony_get_toc();
1273 if (!sony_toc_read)
1274 return -EIO;
1275 err = verify_area(VERIFY_READ, (char *)arg, sizeof ti);
1276 if (err)
1277 return err;
1278
1279 memcpy_fromfs(&ti, (char *)arg, sizeof ti);
1280 if ((ti.cdti_trk0 < sony_toc->first_track_num)
1281 || (sony_toc->last_track_num < ti.cdti_trk0)
1282 || (ti.cdti_trk1 < ti.cdti_trk0)) {
1283 return -EINVAL;
1284 }
1285 track_idx = find_track(int_to_bcd(ti.cdti_trk0));
1286 if (track_idx < 0)
1287 return -EINVAL;
1288 params[1] = sony_toc->tracks[track_idx].track_start_msf[0];
1289 params[2] = sony_toc->tracks[track_idx].track_start_msf[1];
1290 params[3] = sony_toc->tracks[track_idx].track_start_msf[2];
1291 /*
1292 * If we want to stop after the last track, use the lead-out
1293 * MSF to do that.
1294 */
1295 if (bcd_to_int(sony_toc->last_track_num) <= ti.cdti_trk1) {
1296 log_to_msf(msf_to_log(sony_toc->lead_out_start_msf) - 1,
1297 &(params[4]));
1298 } else {
1299 track_idx = find_track(int_to_bcd(ti.cdti_trk1 + 1));
1300 if (track_idx < 0)
1301 return -EINVAL;
1302 log_to_msf(msf_to_log(sony_toc->tracks[track_idx].track_start_msf) - 1,
1303 &(params[4]));
1304 }
1305 params[0] = 0x03;
1306
1307 spin_up_drive(status);
1308
1309 set_drive_mode(SONY535_AUDIO_DRIVE_MODE, status);
1310
1311 /* Start the drive at the saved position. */
1312 cmd_buff[0] = SONY535_PLAY_AUDIO;
1313 cmd_buff[1] = 0; /* play back starting at this address */
1314 cmd_buff[2] = params[1];
1315 cmd_buff[3] = params[2];
1316 cmd_buff[4] = params[3];
1317 cmd_buff[5] = SONY535_PLAY_AUDIO;
1318 cmd_buff[6] = 2; /* set ending address */
1319 cmd_buff[7] = params[4];
1320 cmd_buff[8] = params[5];
1321 cmd_buff[9] = params[6];
1322 if ((do_sony_cmd(cmd_buff, 5, status, NULL, 0, 0) != 0) ||
1323 (do_sony_cmd(cmd_buff + 5, 5, status, NULL, 0, 0) != 0)) {
1324 printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMPLAYTRKIND)\n",
1325 status[0]);
1326 printk("... Params: %x %x %x %x %x %x %x\n",
1327 params[0], params[1], params[2],
1328 params[3], params[4], params[5], params[6]);
1329 return -EIO;
1330 }
1331 /* Save the final position for pauses and resumes */
1332 final_pos_msf[0] = params[4];
1333 final_pos_msf[1] = params[5];
1334 final_pos_msf[2] = params[6];
1335 sony_audio_status = CDROM_AUDIO_PLAY;
1336 return 0;
1337 }
1338
1339 case CDROMSUBCHNL: /* Get subchannel info */
1340 return sony_get_subchnl_info(arg);
1341
1342 case CDROMVOLCTRL: /* Volume control. What volume does this change, anyway? */
1343 {
1344 struct cdrom_volctrl volctrl;
1345
1346 err = verify_area(VERIFY_READ, (char *)arg, sizeof volctrl);
1347 if (err)
1348 return err;
1349
1350 memcpy_fromfs(&volctrl, (char *)arg, sizeof volctrl);
1351 cmd_buff[0] = SONY535_SET_VOLUME;
1352 cmd_buff[1] = volctrl.channel0;
1353 cmd_buff[2] = volctrl.channel1;
1354 if (do_sony_cmd(cmd_buff, 3, status, NULL, 0, 0) != 0) {
1355 printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMVOLCTRL)\n",
1356 status[0]);
1357 return -EIO;
1358 }
1359 }
1360 return 0;
1361
1362 case CDROMEJECT: /* Eject the drive */
1363 cmd_buff[0] = SONY535_STOP;
1364 do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
1365 cmd_buff[0] = SONY535_SPIN_DOWN;
1366 do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
1367
1368 sony_audio_status = CDROM_AUDIO_INVALID;
1369 cmd_buff[0] = SONY535_EJECT_CADDY;
1370 if (do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0) != 0) {
1371 printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMEJECT)\n",
1372 status[0]);
1373 return -EIO;
1374 }
1375 return 0;
1376 break;
1377
1378 default:
1379 return -EINVAL;
1380 }
1381 }
1382
1383
1384 /*
1385 * Open the drive for operations. Spin the drive up and read the table of
1386 * contents if these have not already been done.
1387 */
1388 static int
1389 cdu_open(struct inode *inode,
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
1390 struct file *filp)
1391 {
1392 Byte status[2], cmd_buff[2];
1393
1394
1395 if (sony_inuse)
1396 return -EBUSY;
1397 if (check_drive_status() != 0)
1398 return -EIO;
1399 sony_inuse = 1;
1400 MOD_INC_USE_COUNT;
1401
1402 if (spin_up_drive(status) != 0) {
1403 printk(CDU535_MESSAGE_NAME " error 0x%.2x (cdu_open, spin up)\n",
1404 status[0]);
1405 sony_inuse = 0;
1406 MOD_DEC_USE_COUNT;
1407 return -EIO;
1408 }
1409 sony_get_toc();
1410 if (!sony_toc_read) {
1411 cmd_buff[0] = SONY535_SPIN_DOWN;
1412 do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
1413 sony_inuse = 0;
1414 MOD_DEC_USE_COUNT;
1415 return -EIO;
1416 }
1417 if (inode) {
1418 check_disk_change(inode->i_rdev);
1419 }
1420 sony_usage++;
1421
1422 #ifdef LOCK_DOORS
1423 /* disable the eject button while mounted */
1424 cmd_buff[0] = SONY535_DISABLE_EJECT_BUTTON;
1425 do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
1426 #endif
1427
1428 return 0;
1429 }
1430
1431
1432 /*
1433 * Close the drive. Spin it down if no task is using it. The spin
1434 * down will fail if playing audio, so audio play is OK.
1435 */
1436 static void
1437 cdu_release(struct inode *inode,
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
1438 struct file *filp)
1439 {
1440 Byte status[2], cmd_no;
1441
1442 sony_inuse = 0;
1443 MOD_DEC_USE_COUNT;
1444
1445 if (0 < sony_usage) {
1446 sony_usage--;
1447 }
1448 if (sony_usage == 0) {
1449 sync_dev(inode->i_rdev);
1450 check_drive_status();
1451
1452 if (sony_audio_status != CDROM_AUDIO_PLAY) {
1453 cmd_no = SONY535_SPIN_DOWN;
1454 do_sony_cmd(&cmd_no, 1, status, NULL, 0, 0);
1455 }
1456 #ifdef LOCK_DOORS
1457 /* enable the eject button after umount */
1458 cmd_no = SONY535_ENABLE_EJECT_BUTTON;
1459 do_sony_cmd(&cmd_no, 1, status, NULL, 0, 0);
1460 #endif
1461 }
1462 }
1463
1464
1465 static struct file_operations cdu_fops =
1466 {
1467 NULL, /* lseek - default */
1468 block_read, /* read - general block-dev read */
1469 block_write, /* write - general block-dev write */
1470 NULL, /* readdir - bad */
1471 NULL, /* select */
1472 cdu_ioctl, /* ioctl */
1473 NULL, /* mmap */
1474 cdu_open, /* open */
1475 cdu_release, /* release */
1476 NULL, /* fsync */
1477 NULL, /* fasync */
1478 cdu535_check_media_change, /* check media change */
1479 NULL /* revalidate */
1480 };
1481
1482 /*
1483 * Initialize the driver.
1484 */
1485 int
1486 sony535_init(void)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
1487 {
1488 struct s535_sony_drive_config drive_config;
1489 Byte cmd_buff[3];
1490 Byte ret_buff[2];
1491 Byte status[2];
1492 int retry_count;
1493 int tmp_irq;
1494 int i;
1495
1496 /* Setting the base I/O address to 0 will disable it. */
1497 if ((sony535_cd_base_io == 0xffff)||(sony535_cd_base_io == 0))
1498 return 0;
1499
1500 /* Set up all the register locations */
1501 result_reg = sony535_cd_base_io;
1502 command_reg = sony535_cd_base_io;
1503 data_reg = sony535_cd_base_io + 1;
1504 read_status_reg = sony535_cd_base_io + 2;
1505 select_unit_reg = sony535_cd_base_io + 3;
1506
1507 #ifndef USE_IRQ
1508 sony535_irq_used = 0; /* polling only until this is ready... */
1509 #endif
1510 /* we need to poll until things get initialized */
1511 tmp_irq = sony535_irq_used;
1512 sony535_irq_used = 0;
1513
1514 #if DEBUG > 0
1515 printk(CDU535_MESSAGE_NAME ": probing base address %03X\n",
1516 sony535_cd_base_io);
1517 #endif
1518 if (check_region(sony535_cd_base_io,4)) {
1519 printk(CDU535_MESSAGE_NAME ": my base address is not free!\n");
1520 return -EIO;
1521 }
1522 /* look for the CD-ROM, follows the procedure in the DOS driver */
1523 inb(select_unit_reg);
1524 retry_count = jiffies + 2 * HZ;
1525 while (jiffies < retry_count)
1526 sony_sleep(); /* wait for 40 18 Hz ticks (from DOS driver) */
1527 inb(result_reg);
1528
1529 outb(0, read_status_reg); /* does a reset? */
1530 retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
1531 while (jiffies < retry_count) {
1532 select_unit(0);
1533 if (inb(result_reg) != 0xff)
1534 break;
1535 sony_sleep();
1536 }
1537
1538 if ((jiffies < retry_count) && (check_drive_status() != TIME_OUT)) {
1539 /* CD-ROM drive responded -- get the drive configuration */
1540 cmd_buff[0] = SONY535_INQUIRY;
1541 if (do_sony_cmd(cmd_buff, 1, status,
1542 (Byte *)&drive_config, 28, 1) == 0) {
1543 /* was able to get the configuration,
1544 * set drive mode as rest of init
1545 */
1546 #if DEBUG > 0
1547 /* 0x50 == CADDY_NOT_INSERTED | NOT_SPINNING */
1548 if ( (status[0] & 0x7f) != 0 && (status[0] & 0x7f) != 0x50 )
1549 printk(CDU535_MESSAGE_NAME
1550 "Inquiry command returned status = 0x%x\n", status[0]);
1551 #endif
1552 /* now ready to use interrupts, if available */
1553 sony535_irq_used = tmp_irq;
1554 #ifndef MODULE
1555 /* This code is not in MODULEs by default, since the autoirq stuff might
1556 * not be in the module-accessible symbol table.
1557 */
1558 /* A negative sony535_irq_used will attempt an autoirq. */
1559 if (sony535_irq_used < 0) {
1560 autoirq_setup(0);
1561 enable_interrupts();
1562 outb(0, read_status_reg); /* does a reset? */
1563 sony535_irq_used = autoirq_report(10);
1564 disable_interrupts();
1565 }
1566 #endif
1567 if (sony535_irq_used > 0) {
1568 if (request_irq(sony535_irq_used, cdu535_interrupt,
1569 SA_INTERRUPT, CDU535_HANDLE)) {
1570 printk("Unable to grab IRQ%d for the " CDU535_MESSAGE_NAME
1571 " driver; polling instead.\n", sony535_irq_used);
1572 sony535_irq_used = 0;
1573 }
1574 }
1575 cmd_buff[0] = SONY535_SET_DRIVE_MODE;
1576 cmd_buff[1] = 0x0; /* default audio */
1577 if (do_sony_cmd(cmd_buff, 2, status, ret_buff, 1, 1) == 0) {
1578 /* set the drive mode successful, we are set! */
1579 sony_buffer_size = SONY535_BUFFER_SIZE;
1580 sony_buffer_sectors = sony_buffer_size / 2048;
1581
1582 printk(CDU535_MESSAGE_NAME " I/F CDROM : %8.8s %16.16s %4.4s",
1583 drive_config.vendor_id,
1584 drive_config.product_id,
1585 drive_config.product_rev_level);
1586 printk(" base address %03X, ", sony535_cd_base_io);
1587 if (tmp_irq > 0)
1588 printk("IRQ%d, ", tmp_irq);
1589 printk("using %d byte buffer\n", sony_buffer_size);
1590
1591 if (register_blkdev(MAJOR_NR, CDU535_HANDLE, &cdu_fops)) {
1592 printk("Unable to get major %d for %s\n",
1593 MAJOR_NR, CDU535_MESSAGE_NAME);
1594 return -EIO;
1595 }
1596 blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
1597 read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read-ahead */
1598
1599 sony_toc = (struct s535_sony_toc *)
1600 kmalloc(sizeof *sony_toc, GFP_KERNEL);
1601 if (sony_toc == NULL)
1602 return -ENOMEM;
1603 last_sony_subcode = (struct s535_sony_subcode *)
1604 kmalloc(sizeof *last_sony_subcode, GFP_KERNEL);
1605 if (last_sony_subcode == NULL) {
1606 kfree(sony_toc);
1607 return -ENOMEM;
1608 }
1609 sony_buffer = (Byte **)
1610 kmalloc(4 * sony_buffer_sectors, GFP_KERNEL);
1611 if (sony_buffer == NULL) {
1612 kfree(sony_toc);
1613 kfree(last_sony_subcode);
1614 return -ENOMEM;
1615 }
1616 for (i = 0; i < sony_buffer_sectors; i++) {
1617 sony_buffer[i] = (Byte *)kmalloc(2048, GFP_KERNEL);
1618 if (sony_buffer[i] == NULL) {
1619 while (--i>=0)
1620 kfree(sony_buffer[i]);
1621 kfree(sony_buffer);
1622 kfree(sony_toc);
1623 kfree(last_sony_subcode);
1624 return -ENOMEM;
1625 }
1626 }
1627 initialized = 1;
1628 }
1629 }
1630 }
1631
1632 if (!initialized) {
1633 printk("Did not find a " CDU535_MESSAGE_NAME " drive\n");
1634 return -EIO;
1635 }
1636 request_region(sony535_cd_base_io, 4, CDU535_HANDLE);
1637 return 0;
1638 }
1639
1640 #ifndef MODULE
1641 /*
1642 * accept "kernel command line" parameters
1643 * (added by emoenke@gwdg.de)
1644 *
1645 * use: tell LILO:
1646 * sonycd535=0x320
1647 *
1648 * the address value has to be the existing CDROM port address.
1649 */
1650 void
1651 sonycd535_setup(char *strings, int *ints)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
1652 {
1653 /* if IRQ change and default io base desired,
1654 * then call with io base of 0
1655 */
1656 if (ints[0] > 0)
1657 if (ints[0] != 0)
1658 sony535_cd_base_io = ints[1];
1659 if (ints[0] > 1)
1660 sony535_irq_used = ints[2];
1661 if ((strings != NULL) && (*strings != '\0'))
1662 printk(CDU535_MESSAGE_NAME
1663 ": Warning: Unknown interface type: %s\n", strings);
1664 }
1665
1666 #else /* MODULE */
1667
1668 int init_module(void)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
1669 {
1670 return sony535_init();
1671 }
1672
1673 void
1674 cleanup_module(void)
/* ![[previous]](../icons/left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
1675 {
1676 int i;
1677
1678 release_region(sony535_cd_base_io, 4);
1679 for (i = 0; i < sony_buffer_sectors; i++)
1680 kfree_s(sony_buffer[i], 2048);
1681 kfree_s(sony_buffer, 4 * sony_buffer_sectors);
1682 kfree_s(last_sony_subcode, sizeof *last_sony_subcode);
1683 kfree_s(sony_toc, sizeof *sony_toc);
1684 if (unregister_blkdev(MAJOR_NR, CDU535_HANDLE) == -EINVAL)
1685 printk("Uh oh, couldn't unregister " CDU535_HANDLE "\n");
1686 else
1687 printk(CDU535_HANDLE " module released\n");
1688 }
1689 #endif /* MODULE */