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