summaryrefslogtreecommitdiffstats
path: root/drivers/cdrom
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/cdrom')
-rw-r--r--drivers/cdrom/.cvsignore1
-rw-r--r--drivers/cdrom/Config.in1
-rw-r--r--drivers/cdrom/Makefile8
-rw-r--r--drivers/cdrom/bpcd.c793
-rw-r--r--drivers/cdrom/cdrom.c120
-rw-r--r--drivers/cdrom/cdu31a.c53
-rw-r--r--drivers/cdrom/cm206.c325
-rw-r--r--drivers/cdrom/mcd.c34
-rw-r--r--drivers/cdrom/mcdx.c285
-rw-r--r--drivers/cdrom/sbpcd.c238
-rw-r--r--drivers/cdrom/sbpcd.h12
11 files changed, 611 insertions, 1259 deletions
diff --git a/drivers/cdrom/.cvsignore b/drivers/cdrom/.cvsignore
index 4671378ae..857dd22e9 100644
--- a/drivers/cdrom/.cvsignore
+++ b/drivers/cdrom/.cvsignore
@@ -1 +1,2 @@
.depend
+.*.flags
diff --git a/drivers/cdrom/Config.in b/drivers/cdrom/Config.in
index f07e65539..bc69156a4 100644
--- a/drivers/cdrom/Config.in
+++ b/drivers/cdrom/Config.in
@@ -13,7 +13,6 @@ if [ "$CONFIG_SBPCD" = "y" ]; then
fi
fi
fi
-tristate 'MicroSolutions backpack CDROM support' CONFIG_BPCD
tristate 'Mitsumi (standard) [no XA/Multisession] CDROM support' CONFIG_MCD
tristate 'Mitsumi [XA/MultiSession] CDROM support' CONFIG_MCDX
tristate 'Optics Storage DOLPHIN 8000AT CDROM support' CONFIG_OPTCD
diff --git a/drivers/cdrom/Makefile b/drivers/cdrom/Makefile
index 0f54a6e2d..5681e2fe5 100644
--- a/drivers/cdrom/Makefile
+++ b/drivers/cdrom/Makefile
@@ -112,14 +112,6 @@ else
endif
endif #CONFIG_SJCD
-ifeq ($(CONFIG_BPCD),y)
-L_OBJS += bpcd.o
-else
- ifeq ($(CONFIG_BPCD),m)
- M_OBJS += bpcd.o
- endif
-endif #CONFIG_BPCD
-
ifeq ($(CONFIG_ISP16_CDI),y)
L_OBJS += isp16.o
else
diff --git a/drivers/cdrom/bpcd.c b/drivers/cdrom/bpcd.c
deleted file mode 100644
index 4ea0f66bc..000000000
--- a/drivers/cdrom/bpcd.c
+++ /dev/null
@@ -1,793 +0,0 @@
-/*
- bpcd.c (c) 1996 Grant R. Guenther <grant@torque.net>
- Under the terms of the GNU public license.
-
- bpcd.c is a driver for the MicroSolutions "backpack" CDrom,
- an external parallel port device.
-
- There are apparently two versions of the backpack protocol. This
- driver knows about the version 2 protocol - as is used in the 4x
- and 6x products. There is no support for the sound hardware that
- is included in some models. It should not be difficult to add
- support for the ATAPI audio play functions and the corresponding
- ioctls.
-
- The driver was developed by reverse engineering the protocol
- and testing it on the backpack model 164550. This model
- is actually a stock ATAPI drive packaged with a custom
- ASIC that implements the IDE over parallel protocol.
- I tested with a backpack that happened to contain a Goldstar
- drive, but I've seen reports of Sony and Mitsumi drives as well.
-
- bpcd.c can be compiled for version 1.2.13 of the Linux kernel
- and for the 2.0 series. (It should also work with most of the
- later 1.3 kernels.)
-
- If you have a copy of the driver that has not been integrated into
- the kernel source tree, you can compile the driver manually, as a
- module. Ensure that /usr/include/linux and /usr/include/asm are
- links to the correct include files for the target system. Compile
- the driver with
-
- cc -D__KERNEL__ -DMODULE -O2 -c bpcd.c
-
- You must then load it with insmod. If you are using
- MODVERSIONS, add the following to the cc command:
-
- -DMODVERSIONS -I /usr/include/linux/modversions.h
-
- Before attempting to access the new driver, you will need to
- create a new device special file. The following commands will
- do that for you:
-
- mknod /dev/bpcd b 41 0
- chown root:disk /dev/bpcd
- chmod 660 /dev/bpcd
-
- Afterward, you can mount a disk in the usual way:
-
- mount -t iso9660 /dev/bpcd /cdrom
-
- (assuming you have made a directory /cdrom to use as a
- mount point).
-
- The driver will attempt to detect which parallel port your
- backpack is connected to. If this fails for any reason, you
- can override it by specifying a port on the LILO command line
- (for built in drivers) or the insmod command (for drivers built
- as modules). If your drive is on the port at 0x3bc, you would
- use one of these commands:
-
- LILO: bpcd=0x3bc
-
- insmod: insmod bpcd bp_base=0x3bc
-
- The driver can detect if the parallel port supports 8-bit
- transfers. If so, it will use them. You can force it to use
- 4-bit (nybble) mode by setting the variable bp_nybble to 1 on
- an insmod command, or using the following LILO parameters:
-
- bpcd=0x3bc,1
-
- (you must specify the correct port address if you use this method.)
-
- There is currently no support for EPP or ECP modes. Also,
- as far as I can tell, the MicroSolutions protocol does not
- support interrupts in the 4-bit and 8-bit modes.
-
- MicroSolutions' protocol allows for several drives to be
- chained together off the same parallel port. Currently, this
- driver will recognise only one of them. If you do have more
- than one drive, it will choose the one with the lowest id number,
- where the id number is the last two digits of the product's
- serial number.
-
- It is not currently possible to connect a printer to the chained
- port on the BackPack and expect Linux to use both devices at once.
-
- If you need to use this driver together with a printer on the
- same port, build both the bpcd and lp drivers are modules.
-
- Keep an eye on http://www.torque.net/bpcd.html for news and
- other information about the driver. If you have any problems
- with this driver, please send me, grant@torque.net, some mail
- directly before posting into the newsgroups or mailing lists.
-
-*/
-
-#define BP_VERSION "0.14"
-
-#define BP_BASE 0 /* set to 0 for autoprobe */
-#define BP_REP 4
-
-#include <linux/version.h>
-#include <linux/module.h>
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/fs.h>
-#include <linux/major.h>
-#include <linux/kernel.h>
-#include <linux/tqueue.h>
-#include <linux/delay.h>
-#include <linux/cdrom.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-#ifndef BPCD_MAJOR
-#define BPCD_MAJOR 41
-#endif
-
-#define MAJOR_NR BPCD_MAJOR
-
-/* set up defines for blk.h, why don't all drivers do it this way ? */
-
-#define DEVICE_NAME "BackPack"
-#define DEVICE_REQUEST do_bp_request
-#define DEVICE_NR(device) (MINOR(device))
-#define DEVICE_ON(device)
-#define DEVICE_OFF(device)
-
-#include <linux/blk.h>
-
-#define BP_TMO 300 /* timeout in jiffies */
-#define BP_DELAY 50 /* spin delay in uS */
-
-#define BP_SPIN (10000/BP_DELAY)*BP_TMO
-
-int bpcd_init(void);
-void bpcd_setup(char * str, int * ints);
-void cleanup_module( void );
-
-static int bp_open(struct inode *inode, struct file *file);
-static void do_bp_request(void);
-static void do_bp_read(void);
-static int bp_ioctl(struct inode *inode,struct file *file,
- unsigned int cmd, unsigned long arg);
-static int bp_release (struct inode *inode, struct file *file);
-
-static int bp_detect(void);
-static int bp_lock(void);
-static void bp_unlock(void);
-static void bp_eject(void);
-static void bp_interrupt(void *data);
-
-static int bp_base = BP_BASE;
-static int bp_rep = BP_REP;
-static int bp_nybble = 0; /* force 4-bit mode ? */
-
-static int bp_unit_id;
-
-static int bp_access = 0; /* count of active opens ... */
-static int bp_mode = 1; /* 4- or 8-bit mode */
-static int bp_busy = 0; /* request being processed ? */
-static int bp_timeout; /* "interrupt" loop limiter */
-static int bp_sector; /* address of next requested sector */
-static int bp_count; /* number of blocks still to do */
-static char * bp_buf; /* buffer for request in progress */
-static char bp_buffer[2048]; /* raw block buffer */
-static int bp_bufblk = -1; /* block in buffer, in CD units,
- -1 for nothing there */
-static int nyb_map[256]; /* decodes a nybble */
-static int PortCache = 0; /* cache of the control port */
-
-static struct tq_struct bp_tq = {0,0,bp_interrupt,NULL};
-
-/* kernel glue structures */
-
-static struct file_operations bp_fops = {
- NULL, /* lseek - default */
- block_read, /* read - general block-dev read */
- block_write, /* write - general block-dev write */
- NULL, /* readdir - bad */
- NULL, /* poll */
- bp_ioctl, /* ioctl */
- NULL, /* mmap */
- bp_open, /* open */
- bp_release, /* release */
- block_fsync, /* fsync */
- NULL, /* fasync */
- NULL, /* media change ? */
- NULL /* revalidate new media */
-};
-
-
-/* the MicroSolutions protocol uses bits 3,4,5 & 7 of the status port to
- deliver a nybble in 4 bit mode. We use a table lookup to extract the
- nybble value. The following function initialises the table.
-*/
-
-__initfunc(static void init_nyb_map( void ))
-
-{ int i, j;
-
- for(i=0;i<256;i++) {
- j = (i >> 3) & 0x7;
- if (i & 0x80) j |= 8;
- nyb_map[i] = j;
- }
-}
-
-__initfunc(int bpcd_init (void)) /* preliminary initialisation */
-
-{ init_nyb_map();
-
- if (bp_detect()) return -1;
-
- if (register_blkdev(MAJOR_NR,"bpcd",&bp_fops)) {
- printk("bpcd: unable to get major number %d\n",MAJOR_NR);
- return -1;
- }
- blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
- read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read ahead */
-
- return 0;
-}
-
-static int bp_open (struct inode *inode, struct file *file)
-
-{
- if (file->f_mode & 2) return -EROFS; /* wants to write ? */
-
- MOD_INC_USE_COUNT;
-
- if (!bp_access)
- if (bp_lock()) {
- MOD_DEC_USE_COUNT;
- return -ENXIO;
- }
- bp_access++;
- return 0;
-}
-
-static void do_bp_request (void)
-
-{ if (bp_busy) return;
- while (1) {
- if ((!CURRENT) || (CURRENT->rq_status == RQ_INACTIVE)) return;
- INIT_REQUEST;
- if (CURRENT->cmd == READ) {
- bp_sector = CURRENT->sector;
- bp_count = CURRENT->nr_sectors;
- bp_buf = CURRENT->buffer;
- do_bp_read();
- if (bp_busy) return;
- }
- else end_request(0);
- }
-}
-
-static int bp_ioctl(struct inode *inode,struct file *file,
- unsigned int cmd, unsigned long arg)
-
-/* we currently support only the EJECT ioctl. */
-
-{ switch (cmd) {
- case CDROMEJECT: if (bp_access == 1) {
- bp_eject();
- return 0;
- }
- default:
- return -EINVAL;
- }
-}
-
-static int bp_release (struct inode *inode, struct file *file)
-
-{ kdev_t devp;
-
- bp_access--;
- if (!bp_access) {
- devp = inode->i_rdev;
- fsync_dev(devp);
- invalidate_inodes(devp);
- invalidate_buffers(devp);
- bp_unlock();
- }
- MOD_DEC_USE_COUNT;
- return 0;
-}
-
-#ifdef MODULE
-
-/* Glue for modules ... */
-
-int init_module(void)
-
-{ int err;
- long flags;
-
- save_flags(flags);
- cli();
-
- err = bpcd_init();
-
- restore_flags(flags);
- return err;
-}
-
-void cleanup_module(void)
-
-{ long flags;
-
- save_flags(flags);
- cli();
- unregister_blkdev(MAJOR_NR,"bpcd");
- release_region(bp_base,3);
- restore_flags(flags);
-}
-
-#else
-
-/* bpcd_setup: process lilo command parameters ...
-
- syntax: bpcd=base[,nybble[,rep]]
-*/
-
-__initfunc(void bpcd_setup(char *str, int *ints))
-
-{ if (ints[0] > 0) bp_base = ints[1];
- if (ints[0] > 1) bp_nybble = ints[2];
- if (ints[0] > 2) bp_rep = ints[3];
-}
-
-#endif
-
-static void out_p( short port, char byte)
-
-{ int i;
-
- for(i=0;i<bp_rep;i++) outb(byte,bp_base+port);
-}
-
-static int in_p( short port)
-
-{ int i;
- char c;
-
- for(i=0;i<bp_rep;i++) c=inb(bp_base+port);
- c=inb(bp_base+port);
- return c & 0xff;
-}
-
-/* Unlike other PP devices I've worked on, the backpack protocol seems
- to be driven by *changes* in the values of certain bits on the control
- port, rather than their absolute value. Hence the unusual macros ...
-*/
-
-#define w0(byte) out_p(0,byte)
-#define r0() (in_p(0) & 0xff)
-#define w1(byte) out_p(1,byte)
-#define r1() (in_p(1) & 0xff)
-#define w2(byte) out_p(2,byte) ; PortCache = byte
-#define t2(pat) PortCache ^= pat; out_p(2,PortCache)
-#define e2() PortCache &= 0xfe; out_p(2,PortCache)
-#define o2() PortCache |= 1; out_p(2,PortCache)
-
-static int read_byte( void )
-
-{ int l, h;
-
- t2(4);
- if (bp_mode == 2) return r0();
- l = nyb_map[r1()];
- t2(4);
- h = nyb_map[r1()];
- return (h << 4) + l;
-}
-
-static int read_regr( char regr )
-
-{ int r;
-
- w0(regr & 0xf); w0(regr); t2(2);
- if (bp_mode == 2) { e2(); t2(0x20); }
- r = read_byte();
- if (bp_mode == 2) { t2(1); t2(0x20); }
- return r;
-}
-
-static void write_regr( char regr, char val )
-
-{ w0(regr);
- t2(2);
- w0(val);
- o2(); t2(4); t2(1);
-}
-
-static void write_cmd( char * cmd, int len )
-
-{ int i, f;
-
- if (bp_mode == 2) f = 0x10; else f = 0;
- write_regr(4,0x40|f);
- w0(0x40); t2(2); t2(1);
- i = 0;
- while (i < len) {
- w0(cmd[i++]);
- t2(4);
- }
- write_regr(4,f);
-}
-
-static void read_data( char * buf, int len )
-
-{ int i, f;
-
- if (bp_mode == 2) f = 0x50; else f = 0x40;
- write_regr(4,f);
- w0(0x40); t2(2);
- if (bp_mode == 2) t2(0x20);
- for(i=0;i<len;i++) buf[i] = read_byte();
- if (bp_mode == 2) { t2(1); t2(0x20); }
-}
-
-__initfunc(static int probe( int id ))
-
-{ int l, h, t;
- int r = -1;
-
- w2(4); w2(0xe); w2(0xec); w1(0x7f);
- if ((r1() & 0xf8) != 0x78) return -1;
- w0(255-id); w2(4); w0(id);
- t2(8); t2(8); t2(8);
- t2(2); t = (r1() & 0xf8);
- if (t != 0x78) {
- l = nyb_map[t];
- t2(2); h = nyb_map[r1()];
- t2(8);
- r = 0;
- }
- w0(0); t2(2); w2(0x4c); w0(0x13);
- return r;
-}
-
-static void connect ( void )
-
-{ int f;
-
- w0(0xff-bp_unit_id); w2(4); w0(bp_unit_id);
- t2(8); t2(8); t2(8);
- t2(2); t2(2); t2(8);
- if (bp_mode == 2) f = 0x10; else f = 0;
- write_regr(4,f);
- write_regr(5,8);
- write_regr(0x46,0x10);
- write_regr(0x4c,0x38);
- write_regr(0x4d,0x88);
- write_regr(0x46,0xa0);
- write_regr(0x41,0);
- write_regr(0x4e,8);
-}
-
-static void disconnect ( void )
-
-{ w0(0); t2(2); w2(0x4c);
- if (bp_mode == 2) w0(0xff); else w0(0x13);
-}
-
-static int bp_wait_drq( char * lab, char * fun )
-
-{ int j, r, e;
-
- j = 0;
-
- while (1) {
- r = read_regr(0x47);
- e = read_regr(0x41);
- if ((r & 9) || (j++ >= BP_SPIN)) break;
- udelay(BP_DELAY);
- }
-
- if ((j >= BP_SPIN) || (r & 1)) {
- if (lab && fun)
- printk("bpcd: %s (%s): %s status: %x error: %x\n",
- lab,fun,(j >= BP_SPIN)?"timeout, ":"",r,e);
- return -1;
- }
- return 0;
-}
-
-static int bp_wait( char * lab, char * fun )
-
-{ int j, r, e;
-
- j = 0;
- while ((!(read_regr(0xb) & 0x80)) && (j++ < BP_SPIN)) udelay(BP_DELAY);
- r = read_regr(0x47);
- e = read_regr(0x41);
- if ((j >= BP_SPIN) || (r & 1)) {
- if (lab && fun)
- printk("bpcd: %s (%s): %s status: %x error: %x\n",
- lab,fun,(j >= BP_SPIN)?"timeout, ":"",r,e);
- return -1;
- }
- return 0;
-}
-
-static int bp_command( char * cmd, int dlen, char * fun )
-
-{ int r;
-
- connect();
- write_regr(0x44,dlen % 256);
- write_regr(0x45,dlen / 256);
- write_regr(0x46,0xa0); /* drive 0 */
- write_regr(0x47,0xa0); /* ATAPI packet command */
- if ((r=bp_wait_drq("bp_command",fun))) {
- disconnect();
- return r;
- }
- write_cmd(cmd,12);
- return 0;
-}
-
-static int bp_completion( char * fun )
-
-{ int r, n;
-
- if (!(r=bp_wait("bp_completion",fun))) {
- if (read_regr(0x42) == 2) {
- n = (read_regr(0x44) + 256*read_regr(0x45));
- read_data(bp_buffer,n);
- r=bp_wait("transfer done",fun);
- }
- }
- disconnect();
- return r;
-}
-
-static int bp_atapi( char * cmd, int dlen, char * fun )
-
-{ int r;
-
- if (!(r=bp_command(cmd,dlen,fun)))
- r = bp_completion(fun);
- return r;
-}
-
-static int bp_req_sense( char * msg )
-
-{ char rs_cmd[12] = { 0x03,0,0,0,18,0,0,0,0,0,0,0 };
- int r;
-
- r = bp_atapi(rs_cmd,18,"request sense");
- if (msg) printk("bpcd: %s: sense key: %x, ASC: %x, ASQ: %x\n",msg,
- bp_buffer[2]&0xf, bp_buffer[12], bp_buffer[13]);
- return r;
-}
-
-static int bp_lock(void)
-
-{ char lo_cmd[12] = { 0x1e,0,0,0,1,0,0,0,0,0,0,0 };
- char cl_cmd[12] = { 0x1b,0,0,0,3,0,0,0,0,0,0,0 };
-
- bp_atapi(cl_cmd,0,"close door");
- if (bp_req_sense(NULL)) return -1; /* check for disk */
- bp_atapi(lo_cmd,0,NULL);
- bp_req_sense(NULL); /* in case there was a media change */
- bp_atapi(lo_cmd,0,"lock door");
- return 0;
-}
-
-static void bp_unlock( void)
-
-{ char un_cmd[12] = { 0x1e,0,0,0,0,0,0,0,0,0,0,0 };
-
- bp_atapi(un_cmd,0,"unlock door");
-}
-
-static void bp_eject( void)
-
-{ char ej_cmd[12] = { 0x1b,0,0,0,2,0,0,0,0,0,0,0 };
-
- bp_unlock();
- bp_atapi(ej_cmd,0,"eject");
-}
-
-__initfunc(static int bp_reset( void ))
-
-/* the ATAPI standard actually specifies the contents of all 7 registers
- after a reset, but the specification is ambiguous concerning the last
- two bytes, and different drives interpret the standard differently.
-*/
-
-{ int i, flg;
- int expect[5] = {1,1,1,0x14,0xeb};
- long flags;
-
- connect();
- write_regr(0x46,0xa0);
- write_regr(0x47,8);
-
- save_flags(flags);
- sti();
- udelay(500000); /* delay 0.5 seconds */
- restore_flags(flags);
-
- flg = 1;
- for(i=0;i<5;i++) flg &= (read_regr(i+0x41) == expect[i]);
-
- disconnect();
- return flg-1;
-}
-
-__initfunc(static int bp_identify( char * id ))
-
-{ int k;
- char id_cmd[12] = {0x12,0,0,0,36,0,0,0,0,0,0,0};
-
- bp_bufblk = -1;
- if (bp_atapi(id_cmd,36,"identify")) return -1;
- for (k=0;k<16;k++) id[k] = bp_buffer[16+k];
- id[16] = 0;
- return 0;
-}
-
-__initfunc(static int bp_port_check( void )) /* check for 8-bit port */
-
-{ int r;
-
- w2(0);
- w0(0x55); if (r0() != 0x55) return 0;
- w0(0xaa); if (r0() != 0xaa) return 0;
- w2(0x20); w0(0x55); r = r0(); w0(0xaa);
- if (r0() == r) return 2;
- if (r0() == 0xaa) return 1;
- return 0;
-}
-
-__initfunc(static int bp_locate( void ))
-
-{ int k;
-
- for(k=0;k<100;k++)
- if (!probe(k)) {
- bp_unit_id = k;
- return 0;
- }
- return -1;
-}
-
-__initfunc(static int bp_do_detect( int autop ))
-
-{ char id[18];
-
- if (autop) bp_base = autop;
-
- if (check_region(bp_base,3)) {
- if (!autop)
- printk("bpcd: Ports at 0x%x are not available\n",bp_base);
- return -1;
- }
-
- bp_mode = bp_port_check();
-
- if (!bp_mode) {
- if (!autop)
- printk("bpcd: No parallel port at 0x%x\n",bp_base);
- return -1;
- }
-
- if (bp_nybble) bp_mode = 1;
-
- if (bp_locate()) {
- if (!autop)
- printk("bpcd: Couldn't find a backpack adapter at 0x%x\n",
- bp_base);
- return -1;
- }
-
- if (bp_reset()) {
- if (!autop)
- printk("bpcd: Failed to reset CD drive\n");
- return -1;
- }
-
- if (bp_identify(id)) {
- if (!autop)
- printk("bpcd: ATAPI inquiry failed\n");
- return -1;
- }
-
- request_region(bp_base,3,"bpcd");
-
- printk("bpcd: Found %s, ID %d, using port 0x%x in %d-bit mode\n",
- id,bp_unit_id,bp_base,4*bp_mode);
-
- return 0;
-}
-
-/* If you know about some other weird parallel port base address,
- add it here ....
-*/
-
-__initfunc(static int bp_detect( void ))
-
-{ if (bp_base) return bp_do_detect(0);
- if (!bp_do_detect(0x378)) return 0;
- if (!bp_do_detect(0x278)) return 0;
- if (!bp_do_detect(0x3bc)) return 0;
- printk("bpcd: Autoprobe failed\n");
- return -1;
-}
-
-
-static void bp_transfer( void )
-
-{ int k, o;
-
- while (bp_count && (bp_sector/4 == bp_bufblk)) {
- o = (bp_sector % 4) * 512;
- for(k=0;k<512;k++) bp_buf[k] = bp_buffer[o+k];
- bp_count--;
- bp_buf += 512;
- bp_sector++;
- }
-}
-
-static void do_bp_read( void )
-
-{ int b, i;
- char rd_cmd[12] = {0xa8,0,0,0,0,0,0,0,0,1,0,0};
-
- bp_busy = 1;
- bp_transfer();
- if (!bp_count) {
- end_request(1);
- bp_busy = 0;
- return;
- }
- sti();
-
- bp_bufblk = bp_sector / 4;
- b = bp_bufblk;
- for(i=0;i<4;i++) {
- rd_cmd[5-i] = b & 0xff;
- b = b >> 8;
- }
-
- if (bp_command(rd_cmd,2048,"read block")) {
- bp_bufblk = -1;
- bp_busy = 0;
- cli();
- bp_req_sense("send read command");
- end_request(0);
- return;
- }
- bp_timeout = jiffies + BP_TMO;
- queue_task(&bp_tq,&tq_scheduler);
-}
-
-static void bp_interrupt( void *data)
-
-{ if (!(read_regr(0xb) & 0x80)) {
- if (jiffies > bp_timeout) {
- bp_bufblk = -1;
- bp_busy = 0;
- bp_req_sense("interrupt timeout");
- end_request(0);
- do_bp_request();
- }
- queue_task(&bp_tq,&tq_scheduler);
- return;
- }
- sti();
- if (bp_completion("read completion")) {
- cli();
- bp_busy = 0;
- bp_bufblk = -1;
- bp_req_sense("read completion");
- end_request(0);
- do_bp_request();
- }
- do_bp_read();
- do_bp_request();
-}
-
-/* end of bpcd.c */
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index 4f1a2e877..48a3ae427 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -1,6 +1,6 @@
/* linux/drivers/cdrom/cdrom.c.
Copyright (c) 1996, 1997 David A. van Leeuwen.
- Copyright (c) 1997 Erik Andersen (andersee@debian.org)
+ Copyright (c) 1997, 1998 Erik Andersen <andersee@debian.org>
May be copied or modified under the terms of the GNU General Public
License. See linux/COPYING for more information.
@@ -10,46 +10,71 @@
The routines in the file provide a uniform interface between the
software that uses CD-ROMs and the various low-level drivers that
- actually talk to actual hardware devices. Suggestions are welcome.
+ actually talk to the hardware. Suggestions are welcome.
Patches that work are more welcome though. ;-)
+ To Do List:
+ ----------------------------------
- Recent Changes:
- ----------------------------------
+ -- Modify sysctl/proc interface. I plan on having one directory per
+ drive, with entries for outputing general drive information, and sysctl
+ based tunable parameters such as whether the tray should auto-close for
+ that drive. Suggestions (or patches) for this welcome!
- New maintainer! As David A. van Leeuwen has been too busy to activly
+ -- Change the CDROMREADMODE1, CDROMREADMODE2, CDROMREADAUDIO, and
+ CDROMREADRAW ioctls so they go through the Uniform CD-ROM driver.
+
+
+
+
+ Revision History
+ ----------------------------------
+ 1.00 Date Unknown -- David van Leeuwen <david@tm.tno.nl>
+ -- Initial version by David A. van Leeuwen. I don't have a detailed
+ changelog for the 1.x series, David?
+
+2.00 Dec 2, 1997 -- Erik Andersen <andersee@debian.org>
+ -- New maintainer! As David A. van Leeuwen has been too busy to activly
maintain and improve this driver, I am now carrying on the torch. If
you have a problem with this driver, please feel free to contact me.
- Added (rudimentary) sysctl interface. I realize this is really weak
- right now, and is _very_ badly implemented. It will be improved... I
- plan on having one directory per drive, with entries for outputing
- general drive information, and sysctl based tunable parameters such
- as whether the tray should auto-close for that drive. Suggestions (or
- patches) for improvements are very welcome.
+ -- Added (rudimentary) sysctl interface. I realize this is really weak
+ right now, and is _very_ badly implemented. It will be improved...
- Modified CDROM_DISC_STATUS so that it is now incorporated into
+ -- Modified CDROM_DISC_STATUS so that it is now incorporated into
the Uniform CD-ROM driver via the cdrom_count_tracks function.
The cdrom_count_tracks function helps resolve some of the false
assumptions of the CDROM_DISC_STATUS ioctl, and is also used to check
for the correct media type when mounting or playing audio from a CD.
- Remove the calls to verify_area and only use the copy_from_user and
+ -- Remove the calls to verify_area and only use the copy_from_user and
copy_to_user stuff, since these calls now provide their own memory
checking with the 2.1.x kernels.
- Major update to return codes so that errors from low-level drivers
+ -- Major update to return codes so that errors from low-level drivers
are passed on through (thanks to Gerd Knorr for pointing out this
problem).
- Made it so if a function isn't implemented in a low-level driver,
+ -- Made it so if a function isn't implemented in a low-level driver,
ENOSYS is now returned instead of EINVAL.
- Simplified some complex logic so that the source code is easier to read.
+ -- Simplified some complex logic so that the source code is easier to read.
- Other stuff I probably forgot to mention (lots of changes).
+ -- Other stuff I probably forgot to mention (lots of changes).
- */
+2.01 to 2.11 Dec 1997-Jan 1998
+ -- TO-DO! Write changelogs for 2.01 to 2.12.
+
+2.12 Jan 24, 1998 -- Erik Andersen <andersee@debian.org>
+ -- Fixed a bug in the IOCTL_IN and IOCTL_OUT macros. It turns out that
+ copy_*_user does not return EFAULT on error, but instead return the number
+ of bytes not copied. I was returning whatever non-zero stuff came back from
+ the copy_*_user functions directly, which would result in strange errors.
+
+-------------------------------------------------------------------------*/
+
+#define REVISION "Revision: 2.12"
+#define VERSION "Id: cdrom.c 2.12 1998/01/24 22:15:45 erik Exp"
#include <linux/config.h>
@@ -68,14 +93,6 @@
#include <asm/uaccess.h>
-#define VERSION "$Id: cdrom.c,v 2.0 1997/11/20 01:58:03 erik Exp $"
-#define REVISION "revision 2.0"
-#define FM_WRITE 0x2 /* file mode write bit */
-
-/* When VERBOSE_STATUS_INFO is not defined, the debugging printks don't
- get compiled in */
-#define VERBOSE_STATUS_INFO
-
/* I use an error-log mask to give fine grain control over the type of
error messages dumped to the system logs. The available masks include: */
#define CD_WARNING 0x1
@@ -83,9 +100,14 @@
#define CD_DO_IOCTL 0x4
#define CD_OPEN 0x8
#define CD_CLOSE 0x10
+#define CD_COUNT_TRACKS 0x20
+
+/* When VERBOSE_STATUS_INFO is not defined, the debugging printks don't
+ get compiled in at all */
+#define VERBOSE_STATUS_INFO
#define ERRLOGMASK (CD_WARNING)
-/* #define ERRLOGMASK (CD_WARNING|CD_OPEN|CD_CLOSE) */
+/* #define ERRLOGMASK (CD_WARNING|CD_OPEN|CD_COUNT_TRACKS|CD_CLOSE) */
/* #define ERRLOGMASK (CD_WARNING|CD_REG_UNREG|CD_DO_IOCTL|CD_OPEN|CD_CLOSE) */
#ifdef VERBOSE_STATUS_INFO
@@ -95,15 +117,17 @@
#define cdinfo(type, fmt, args...)
#endif
-
/* These are used to simplify getting data in from and back to user land */
#define IOCTL_IN(arg, type, in) { \
- int ret=copy_from_user(&in, (type *) arg, sizeof in); \
- if (ret) return ret; }
+ if ( copy_from_user(&in, (type *) arg, sizeof in) ) \
+ return -EFAULT; }
#define IOCTL_OUT(arg, type, out) { \
- int ret=copy_to_user((type *) arg, &out, sizeof out); \
- if (ret) return ret; }
+ if ( copy_to_user((type *) arg, &out, sizeof out) ) \
+ return -EFAULT; }
+
+
+#define FM_WRITE 0x2 /* file mode write bit */
/* Not-exported routines. */
static int cdrom_open(struct inode *ip, struct file *fp);
@@ -177,7 +201,8 @@ int register_cdrom(struct cdrom_device_info *cdi)
ENSURE(reset, CDC_RESET);
ENSURE(audio_ioctl, CDC_PLAY_AUDIO);
ENSURE(dev_ioctl, CDC_IOCTLS);
- cdi->options = CDO_AUTO_CLOSE | CDO_USE_FFLAGS | CDO_LOCK | CDO_CHECK_TYPE;
+ cdi->options = CDO_AUTO_CLOSE | CDO_USE_FFLAGS | CDO_LOCK;
+ /* default compatibility mode */
cdi->mc_flags = 0;
cdo->n_minors = 0;
cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" registered\n", cdi->name);
@@ -305,15 +330,13 @@ int open_for_data(struct cdrom_device_info * cdi)
ret=-ENOMEDIUM;
goto clean_up_and_return;
}
-#if 0
- /* this breaks CD-Players which don't use O_NONBLOCK, workman
- * for example, probably others too */
+ /* CD-Players which don't use O_NONBLOCK, workman
+ * for example, need bit CDO_CHECK_TYPE cleared! */
if (cdi->options & CDO_CHECK_TYPE && tracks.data==0) {
cdinfo(CD_OPEN, "bummer. wrong media type...\n");
ret=-EMEDIUMTYPE;
goto clean_up_and_return;
}
-#endif
cdinfo(CD_OPEN, "all seems well, opening the device...\n");
@@ -481,7 +504,7 @@ void cdrom_count_tracks(struct cdrom_device_info *cdi, tracktype* tracks)
tracks->cdi=0;
tracks->xa=0;
tracks->error=0;
- cdinfo(CD_OPEN, "entering cdrom_count_tracks\n");
+ cdinfo(CD_COUNT_TRACKS, "entering cdrom_count_tracks\n");
if (!(cdi->ops->capability & CDC_PLAY_AUDIO)) {
tracks->error=CDS_NO_INFO;
return;
@@ -509,10 +532,10 @@ void cdrom_count_tracks(struct cdrom_device_info *cdi, tracktype* tracks)
tracks->data++;
} else
tracks->audio++;
- cdinfo(CD_OPEN, "track %d: format=%d, ctrl=%d\n",
+ cdinfo(CD_COUNT_TRACKS, "track %d: format=%d, ctrl=%d\n",
i, entry.cdte_format, entry.cdte_ctrl);
}
- cdinfo(CD_OPEN, "disc has %d tracks: %d=audio %d=data %d=Cd-I %d=XA\n",
+ cdinfo(CD_COUNT_TRACKS, "disc has %d tracks: %d=audio %d=data %d=Cd-I %d=XA\n",
header.cdth_trk1, tracks->audio, tracks->data,
tracks->cdi, tracks->xa);
}
@@ -716,6 +739,10 @@ int cdrom_ioctl(struct inode *ip, struct file *fp,
returns with the above, but this more clearly demonstrates
the problem with the current interface. Too bad this wasn't
designed to use bitmasks... -Erik
+
+ Well, now we have the option CDS_MIXED: a mixed-type CD.
+ User level programmers might feel the ioctl is not very useful.
+ ---david
*/
case CDROM_DISC_STATUS: {
tracktype tracks;
@@ -725,11 +752,14 @@ int cdrom_ioctl(struct inode *ip, struct file *fp,
return(tracks.error);
/* Policy mode on */
- if (tracks.audio>0 && tracks.data==0 && tracks.cdi==0 && tracks.xa==0)
- return CDS_AUDIO;
- if (tracks.cdi>0) return CDS_XA_2_2;
- if (tracks.xa>0) return CDS_XA_2_1;
- if (tracks.data>0) return CDS_DATA_1;
+ if (tracks.audio > 0) {
+ if (tracks.data==0 && tracks.cdi==0 && tracks.xa==0)
+ return CDS_AUDIO;
+ else return CDS_MIXED;
+ }
+ if (tracks.cdi > 0) return CDS_XA_2_2;
+ if (tracks.xa > 0) return CDS_XA_2_1;
+ if (tracks.data > 0) return CDS_DATA_1;
/* Policy mode off */
cdinfo(CD_WARNING,"This disc doesn't have any tracks I recognise!\n");
diff --git a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c
index 231e00548..15481c9a8 100644
--- a/drivers/cdrom/cdu31a.c
+++ b/drivers/cdrom/cdu31a.c
@@ -186,6 +186,10 @@
* Heiko Eissfeldt <heiko@colossus.escape.de> with additional
* changes by Erik Andersen <andersee@debian.org>
*
+ * 24 January 1998 -- Removed the scd_disc_status() function, which was now
+ * just dead code left over from the port.
+ * Erik Andersen <andersee@debian.org>
+ *
*/
#include <linux/major.h>
@@ -416,7 +420,8 @@ static int scd_drive_status(struct cdrom_device_info *cdi, int slot_nr)
return -EINVAL;
}
- return sony_spun_up ? CDS_DISC_OK : CDS_DRIVE_NOT_READY;
+ /*return sony_spun_up ? CDS_DISC_OK : CDS_DRIVE_NOT_READY;*/
+ return sony_spun_up ? CDS_DISC_OK : CDS_TRAY_OPEN;
}
static inline void
@@ -1085,7 +1090,7 @@ handle_sony_cd_attention(void)
volatile int val;
-#if DEBUG
+#if 0*DEBUG
printk("Entering handle_sony_cd_attention\n");
#endif
if (is_attention())
@@ -1166,7 +1171,7 @@ handle_sony_cd_attention(void)
}
num_consecutive_attentions = 0;
-#if DEBUG
+#if 0*DEBUG
printk("Leaving handle_sony_cd_attention at %d\n", __LINE__);
#endif
return(0);
@@ -1241,33 +1246,6 @@ size_to_buf(unsigned int size,
buf[2] = size % 256;
}
-/* Uniform cdrom interface function.
- Return the status of the current disc:
- If it is recognized as CD-I -> return XA Mode 2 Form 2
- If it is recognized as XA -> return XA Mode 2 Form 1
- If there is at least one data track return Mode 1
- else return type AUDIO
- */
-static int scd_disc_status(struct cdrom_device_info *cdi)
-{
- if (sony_spun_up)
- {
- int i;
-
- sony_get_toc();
- /* look into the TOC */
- if (sony_toc.disk_type == 0x10) /* this is a CD-I disc */
- return CDS_XA_2_2;
- if (sony_toc.disk_type == 0x20) /* this is a XA disc */
- return CDS_XA_2_1;
- for (i = 0; i < sony_toc.track_entries; i++)
- if (sony_toc.tracks[i].control & CDROM_DATA_TRACK)
- return CDS_DATA_1;
- return CDS_AUDIO;
- } else
- return CDS_NO_INFO;
-}
-
/* Starts a read operation. Returns 0 on success and 1 on failure.
The read operation used here allows multiple sequential sectors
to be read and status returned for each sector. The driver will
@@ -2835,8 +2813,11 @@ static int scd_tray_move(struct cdrom_device_info *cdi, int position)
sony_audio_status = CDROM_AUDIO_INVALID;
return do_sony_cd_cmd_chk("EJECT",SONY_EJECT_CMD, NULL, 0, res_reg, &res_size);
- } else
- return 0;
+ } else {
+ if (0 == scd_spinup())
+ sony_spun_up = 1;
+ return 0;
+ }
}
/*
@@ -3230,7 +3211,6 @@ scd_open(struct cdrom_device_info *cdi, int openmode)
printk("CDU31A: Unable to set XA params: 0x%2.2x\n", res_reg[1]);
}
sony_xa_mode = 1;
-printk("sony_xa_mode is set\n");
}
/* A non-XA disk. Set the parms back if necessary. */
else if (sony_xa_mode)
@@ -3247,7 +3227,6 @@ printk("sony_xa_mode is set\n");
printk("CDU31A: Unable to reset XA params: 0x%2.2x\n", res_reg[1]);
}
sony_xa_mode = 0;
-printk("sony_xa_mode is reset\n");
}
sony_spun_up = 1;
@@ -3293,7 +3272,7 @@ static struct cdrom_device_ops scd_dops = {
scd_reset, /* hard reset */
scd_audio_ioctl, /* audio ioctl */
scd_dev_ioctl, /* device-specific ioctl */
- CDC_OPEN_TRAY | CDC_LOCK | CDC_SELECT_SPEED | CDC_MULTI_SESSION |
+ CDC_OPEN_TRAY | CDC_CLOSE_TRAY | CDC_LOCK | CDC_SELECT_SPEED | CDC_MULTI_SESSION |
CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO |
CDC_RESET | CDC_IOCTLS | CDC_DRIVE_STATUS, /* capability */
1, /* number of minor devices */
@@ -3303,7 +3282,7 @@ static struct cdrom_device_info scd_info = {
&scd_dops, /* device operations */
NULL, /* link */
NULL, /* handle */
- MKDEV(MAJOR_NR,0), /* dev */
+ 0, /* dev */
0, /* mask */
2, /* maximum speed */
1, /* number of discs */
@@ -3570,7 +3549,9 @@ cdu31a_init(void))
init_timer(&cdu31a_abort_timer);
cdu31a_abort_timer.function = handle_abort_timeout;
+ scd_info.dev = MKDEV(MAJOR_NR,0);
scd_info.mask = deficiency;
+ strncpy(scd_info.name, "cdu31a", sizeof(scd_info.name));
if (register_cdrom(&scd_info))
{
diff --git a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c
index e699cfa8e..c0bcc7bf4 100644
--- a/drivers/cdrom/cm206.c
+++ b/drivers/cdrom/cm206.c
@@ -1,5 +1,6 @@
/* cm206.c. A linux-driver for the cm206 cdrom player with cm260 adapter card.
- Copyright (c) 1995, 1996 David van Leeuwen.
+ Copyright (c) 1995--1997 David A. van Leeuwen.
+ $Id: cm206.c,v 1.5 1997/12/26 11:02:51 david Exp $
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -70,40 +71,86 @@ History:
open only for ioctl operation, e.g., for operation of
tray etc.
4 apr 1996: 0.97 First implementation of layer between VFS and cdrom
- driver, a Uniform interface. Much of the functionality
+ driver, a generic interface. Much of the functionality
of cm206_open() and cm206_ioctl() is transferred to a
- new file cdrom.c and its header cdrom.h.
+ new file cdrom.c and its header ucdrom.h.
Upgrade to Linux kernel 1.3.78.
11 apr 1996 0.98 Upgrade to Linux kernel 1.3.85
More code moved to cdrom.c
+
+ 0.99 Some more small changes to decrease number
+ of oopses at module load;
+
+ 27 jul 1996 0.100 Many hours of debugging, kernel change from 1.2.13
+ to 2.0.7 seems to have introduced some weird behavior
+ in (interruptible_)sleep_on(&cd->data): the process
+ seems to be woken without any explicit wake_up in my own
+ code. Patch to try 100x in case such untriggered wake_up's
+ occur.
- 0.99 Some more small changes to decrease number
- of oopses at module load;
-
- Branch from here:
-
- 0.99.1.0 Update to kernel release 2.0.10 dev_t -> kdev_t
- (emoenke) various typos found by others. extra
- module-load oops protection.
-
- 0.99.1.1 Initialization constant cdrom_dops.speed
- changed from float (2.0) to int (2); Cli()-sti() pair
- around cm260_reset() in module initialization code.
+ 28 jul 1996 0.101 Rewriting of the code that receives the command echo,
+ using a fifo to store echoed bytes.
- 0.99.1.2 Changes literally as proposed by Scott Snyder
- <snyder@d0sgif.fnal.gov>, which have to do mainly with
- the poor minor support i had. The major new concept is
- to change a cdrom driver's operations struct from the
- capabilities struct. This reflects the fact that there
- is one major for a driver, whilst there can be many
- minors whith completely different capabilities.
+ Branch from 0.99:
+
+ 0.99.1.0 Update to kernel release 2.0.10 dev_t -> kdev_t
+ (emoenke) various typos found by others. extra
+ module-load oops protection.
+
+ 0.99.1.1 Initialization constant cdrom_dops.speed
+ changed from float (2.0) to int (2); Cli()-sti() pair
+ around cm260_reset() in module initialization code.
+
+ 0.99.1.2 Changes literally as proposed by Scott Snyder
+ <snyder@d0sgif.fnal.gov> for the 2.1 kernel line, which
+ have to do mainly with the poor minor support i had. The
+ major new concept is to change a cdrom driver's
+ operations struct from the capabilities struct. This
+ reflects the fact that there is one major for a driver,
+ whilst there can be many minors whith completely
+ different capabilities.
0.99.1.3 More changes for operations/info separation.
0.99.1.4 Added speed selection (someone had to do this
first).
+
+ 23 jan 1997 0.99.1.5 MODULE_PARMS call added.
+
+ 23 jan 1997 0.100.1.2--0.100.1.5 following similar lines as
+ 0.99.1.1--0.99.1.5. I get too many complaints about the
+ drive making read errors. What't wrong with the 2.0+
+ kernel line? Why get i (and othe cm206 owners) weird
+ results? Why were things good in the good old 1.1--1.2
+ era? Why don't i throw away the drive?
+
+ 2 feb 1997 0.102 Added `volatile' to values in cm206_struct. Seems to
+ reduce many of the problems. Rewrote polling routines
+ to use fixed delays between polls.
+ 0.103 Changed printk behavior.
+ 0.104 Added a 0.100 -> 0.100.1.1 change
+
+11 feb 1997 0.105 Allow auto_probe during module load, disable
+ with module option "auto_probe=0". Moved some debugging
+ statements to lower priority. Implemented select_speed()
+ function.
+
+13 feb 1997 1.0 Final version for 2.0 kernel line.
+
+ All following changes will be for the 2.1 kernel line.
+
+15 feb 1997 1.1 Keep up with kernel 2.1.26, merge in changes from
+ cdrom.c 0.100.1.1--1.0. Add some more MODULE_PARMS.
+
+14 sep 1997 1.2 Upgrade to Linux 2.1.55. Added blksize_size[], patch
+ sent by James Bottomley <James.Bottomley@columbiasc.ncr.com>.
+
+21 dec 1997 1.4 Upgrade to Linux 2.1.72.
+
+24 jan 1998 Removed the cm206_disc_status() function, as it was now dead
+ code. The Uniform CDROM driver now provides this functionality.
*
* Parts of the code are based upon lmscd.c written by Kai Petzke,
* sbpcd.c written by Eberhard Moenkeberg, and mcd.c by Martin
@@ -123,8 +170,8 @@ History:
* - Philips/LMS cm206 and cm226 product specification
* - Philips/LMS cm260 product specification
*
- * David van Leeuwen, david@tm.tno.nl. */
-#define VERSION "$Id: cm206.c,v 0.99.1.4 1996/12/23 21:46:13 david Exp $"
+ * David van Leeuwen, david@tm.tno.nl. */
+#define REVISION "$Revision: 1.5 $"
#include <linux/module.h>
@@ -140,6 +187,8 @@ History:
#include <linux/malloc.h>
#include <linux/init.h>
+/* #include <linux/ucdrom.h> */
+
#include <asm/io.h>
#define MAJOR_NR CM206_CDROM_MAJOR
@@ -147,7 +196,7 @@ History:
#undef DEBUG
#define STATISTICS /* record times and frequencies of events */
-#undef AUTO_PROBE_MODULE
+#define AUTO_PROBE_MODULE
#define USE_INSW
#include "cm206.h"
@@ -160,15 +209,18 @@ static int auto_probe=1; /* Yes, why not? */
static int cm206_base = CM206_BASE;
static int cm206_irq = CM206_IRQ;
-MODULE_PARM(cm206_base, "i");
-MODULE_PARM(cm206_irq, "i");
+MODULE_PARM(cm206_base, "i"); /* base */
+MODULE_PARM(cm206_irq, "i"); /* irq */
+MODULE_PARM(cm206, "1-2i"); /* base,irq or irq,base */
+MODULE_PARM(auto_probe, "i"); /* auto probe base and irq */
-#define POLLOOP 10000
+#define POLLOOP 100 /* milliseconds */
#define READ_AHEAD 1 /* defines private buffer, waste! */
#define BACK_AHEAD 1 /* defines adapter-read ahead */
#define DATA_TIMEOUT (3*HZ) /* measured in jiffies (10 ms) */
#define UART_TIMEOUT (5*HZ/100)
#define DSB_TIMEOUT (7*HZ) /* time for the slowest command to finish */
+#define UR_SIZE 4 /* uart receive buffer fifo size */
#define LINUX_BLOCK_SIZE 512 /* WHERE is this defined? */
#define RAW_SECTOR_SIZE 2352 /* ok, is also defined in cdrom.h */
@@ -181,13 +233,14 @@ MODULE_PARM(cm206_irq, "i");
cd->last_stat[st_ ## i] = cd->stat_counter++; \
}
#else
-#define stats(i) (void) 0
+#define stats(i) (void) 0;
#endif
-#ifdef DEBUG /* from lmscd.c */
-#define debug(a) printk a
+#define Debug(a) {printk (KERN_DEBUG); printk a;}
+#ifdef DEBUG
+#define debug(a) Debug(a)
#else
-#define debug(a) (void) 0
+#define debug(a) (void) 0;
#endif
typedef unsigned char uch; /* 8-bits */
@@ -197,21 +250,23 @@ struct toc_struct{ /* private copy of Table of Contents */
uch track, fsm[3], q0;
};
+static int cm206_blocksizes[1] = { 2048 };
+
struct cm206_struct {
- ush intr_ds; /* data status read on last interrupt */
- ush intr_ls; /* uart line status read on last interrupt*/
- uch intr_ur; /* uart receive buffer */
- uch dsb, cc; /* drive status byte and condition (error) code */
- uch fool;
+ volatile ush intr_ds; /* data status read on last interrupt */
+ volatile ush intr_ls; /* uart line status read on last interrupt*/
+ volatile uch ur[UR_SIZE]; /* uart receive buffer fifo */
+ volatile uch ur_w, ur_r; /* write/read buffer index */
+ volatile uch dsb, cc; /* drive status byte and condition (error) code */
int command; /* command to be written to the uart */
int openfiles;
ush sector[READ_AHEAD*RAW_SECTOR_SIZE/2]; /* buffered cd-sector */
- int sector_first, sector_last; /* range of these sector */
- struct wait_queue * uart; /* wait for interrupt */
+ int sector_first, sector_last; /* range of these sectors */
+ struct wait_queue * uart; /* wait queues for interrupt */
struct wait_queue * data;
struct timer_list timer; /* time-out */
char timed_out;
- signed char max_sectors;
+ signed char max_sectors; /* number of sectors that fit in adapter mem */
char wait_back; /* we're waiting for a background-read */
char background; /* is a read going on in the background? */
int adapter_first; /* if so, that's the starting sector */
@@ -243,15 +298,20 @@ static struct cm206_struct * cd; /* the main memory structure */
void send_command_polled(int command)
{
int loop=POLLOOP;
- while (!(inw(r_line_status) & ls_transmitter_buffer_empty) && loop>0)
+ while (!(inw(r_line_status) & ls_transmitter_buffer_empty) && loop>0) {
+ udelay(1000); /* one millisec delay */
--loop;
+ }
outw(command, r_uart_transmit);
}
uch receive_echo_polled(void)
{
int loop=POLLOOP;
- while (!(inw(r_line_status) & ls_receive_buffer_full) && loop>0) --loop;
+ while (!(inw(r_line_status) & ls_receive_buffer_full) && loop>0) {
+ udelay(1000);
+ --loop;
+ }
return ((uch) inw(r_uart_receive));
}
@@ -261,6 +321,15 @@ uch send_receive_polled(int command)
return receive_echo_polled();
}
+inline void clear_ur(void) {
+ if (cd->ur_r != cd->ur_w) {
+ debug(("Deleting bytes from fifo:"));
+ for(;cd->ur_r != cd->ur_w; cd->ur_r++, cd->ur_r %= UR_SIZE)
+ debug((" 0x%x", cd->ur[cd->ur_r]));
+ debug(("\n"));
+ }
+}
+
/* The interrupt handler. When the cm260 generates an interrupt, very
much care has to be taken in reading out the registers in the right
order; in case of a receive_buffer_full interrupt, first the
@@ -282,18 +351,27 @@ static void cm206_interrupt(int sig, void *dev_id, struct pt_regs * regs)
crc_error, sync_error, toc_ready
interrupts */
cd->intr_ls = inw(r_line_status); /* resets overrun bit */
+ debug(("Intr, 0x%x 0x%x, %d\n", cd->intr_ds, cd->intr_ls, cd->background));
if (cd->intr_ls & ls_attention) stats(attention);
/* receive buffer full? */
if (cd->intr_ls & ls_receive_buffer_full) {
- cd->intr_ur = inb(r_uart_receive); /* get order right! */
+ cd->ur[cd->ur_w] = inb(r_uart_receive); /* get order right! */
cd->intr_ls = inw(r_line_status); /* resets rbf interrupt */
- if (!cd->background && cd->uart) wake_up_interruptible(&cd->uart);
+ debug(("receiving #%d: 0x%x\n", cd->ur_w, cd->ur[cd->ur_w]));
+ cd->ur_w++; cd->ur_w %= UR_SIZE;
+ if (cd->ur_w == cd->ur_r) debug(("cd->ur overflow!\n"));
+ if (cd->uart && cd->background < 2) {
+ del_timer(&cd->timer);
+ wake_up_interruptible(&cd->uart);
+ }
}
/* data ready in fifo? */
else if (cd->intr_ds & ds_data_ready) {
if (cd->background) ++cd->adapter_last;
- if ((cd->wait_back || !cd->background) && cd->data)
+ if (cd->data && (cd->wait_back || !cd->background)) {
+ del_timer(&cd->timer);
wake_up_interruptible(&cd->data);
+ }
stats(data_ready);
}
/* ready to issue a write command? */
@@ -340,6 +418,7 @@ static void cm206_interrupt(int sig, void *dev_id, struct pt_regs * regs)
void cm206_timeout(unsigned long who)
{
cd->timed_out = 1;
+ debug(("Timing out\n"));
wake_up_interruptible((struct wait_queue **) who);
}
@@ -347,9 +426,11 @@ void cm206_timeout(unsigned long who)
happened */
int sleep_or_timeout(struct wait_queue ** wait, int timeout)
{
+ cd->timed_out=0;
cd->timer.data=(unsigned long) wait;
cd->timer.expires = jiffies + timeout;
add_timer(&cd->timer);
+ debug(("going to sleep\n"));
interruptible_sleep_on(wait);
del_timer(&cd->timer);
if (cd->timed_out) {
@@ -359,14 +440,15 @@ int sleep_or_timeout(struct wait_queue ** wait, int timeout)
else return 0;
}
-void cm206_delay(int jiffies)
+void cm206_delay(int nr_jiffies)
{
struct wait_queue * wait = NULL;
- sleep_or_timeout(&wait, jiffies);
+ sleep_or_timeout(&wait, nr_jiffies);
}
void send_command(int command)
{
+ debug(("Sending 0x%x\n", command));
if (!(inw(r_line_status) & ls_transmitter_buffer_empty)) {
cd->command = command;
cli(); /* don't interrupt before sleep */
@@ -378,19 +460,40 @@ void send_command(int command)
stats(write_timeout);
outw(command, r_uart_transmit);
}
+ debug(("Write commmand delayed\n"));
}
else outw(command, r_uart_transmit);
}
-uch receive_echo(void)
+uch receive_byte(int timeout)
{
- if (!(inw(r_line_status) & ls_receive_buffer_full) &&
- sleep_or_timeout(&cd->uart, UART_TIMEOUT)) {
+ uch ret;
+ cli();
+ debug(("cli\n"));
+ ret = cd->ur[cd->ur_r];
+ if (cd->ur_r != cd->ur_w) {
+ sti();
+ debug(("returning #%d: 0x%x\n", cd->ur_r, cd->ur[cd->ur_r]));
+ cd->ur_r++; cd->ur_r %= UR_SIZE;
+ return ret;
+ }
+ else if (sleep_or_timeout(&cd->uart, timeout)) { /* does sti() */
debug(("Time out on receive-buffer\n"));
- stats(receive_timeout);
- return ((uch) inw(r_uart_receive));
+#ifdef STATISTICS
+ if (timeout==UART_TIMEOUT) stats(receive_timeout) /* no `;'! */
+ else stats(dsb_timeout);
+#endif
+ return 0xda;
}
- return cd->intr_ur;
+ ret = cd->ur[cd->ur_r];
+ debug(("slept; returning #%d: 0x%x\n", cd->ur_r, cd->ur[cd->ur_r]));
+ cd->ur_r++; cd->ur_r %= UR_SIZE;
+ return ret;
+}
+
+inline uch receive_echo(void)
+{
+ return receive_byte(UART_TIMEOUT);
}
inline uch send_receive(int command)
@@ -399,20 +502,15 @@ inline uch send_receive(int command)
return receive_echo();
}
-uch wait_dsb(void)
+inline uch wait_dsb(void)
{
- if (!(inw(r_line_status) & ls_receive_buffer_full) &&
- sleep_or_timeout(&cd->uart, DSB_TIMEOUT)) {
- debug(("Time out on Drive Status Byte\n"));
- stats(dsb_timeout);
- return ((uch) inw(r_uart_receive));
- }
- return cd->intr_ur;
+ return receive_byte(DSB_TIMEOUT);
}
int type_0_command(int command, int expect_dsb)
{
int e;
+ clear_ur();
if (command != (e=send_receive(command))) {
debug(("command 0x%x echoed as 0x%x\n", command, e));
stats(echo);
@@ -433,8 +531,8 @@ int type_1_command(int command, int bytes, uch * status) /* returns info */
return 0;
}
-/* This function resets the adapter card. We'd better not do this too */
-/* often, because it tends to generate `lost interrupts.' */
+/* This function resets the adapter card. We'd better not do this too
+ * often, because it tends to generate `lost interrupts.' */
void reset_cm260(void)
{
outw(dc_normal | dc_initialize | READ_AHEAD, r_data_control);
@@ -442,7 +540,7 @@ void reset_cm260(void)
outw(dc_normal | READ_AHEAD, r_data_control);
}
-/* fsm: frame-sec-min from linear address */
+/* fsm: frame-sec-min from linear address; one of many */
void fsm(int lba, uch * fsm)
{
fsm[0] = lba % 75;
@@ -466,20 +564,26 @@ int start_read(int start)
int i, e;
fsm(start, &read_sector[1]);
+ clear_ur();
for (i=0; i<4; i++)
if (read_sector[i] != (e=send_receive(read_sector[i]))) {
debug(("read_sector: %x echoes %x\n", read_sector[i], e));
stats(echo);
- return -1;
+ if (e==0xff) { /* this seems to happen often */
+ e = receive_echo();
+ debug(("Second try %x\n", e));
+ if (e!=read_sector[i]) return -1;
+ }
}
return 0;
}
int stop_read(void)
{
+ int e;
type_0_command(c_stop,0);
- if(receive_echo() != 0xff) {
- debug(("c_stop didn't send 0xff\n"));
+ if((e=receive_echo()) != 0xff) {
+ debug(("c_stop didn't send 0xff, but 0x%x\n", e));
stats(stop_0xff);
return -1;
}
@@ -515,8 +619,11 @@ void transport_data(int port, ush * dest, int count)
}
#endif
+
+#define MAX_TRIES 100
int read_sector(int start)
{
+ int tries=0;
if (cd->background) {
cd->background=0;
cd->adapter_last = -1; /* invalidate adapter memory */
@@ -525,12 +632,18 @@ int read_sector(int start)
cd->fifo_overflowed=0;
reset_cm260(); /* empty fifo etc. */
if (start_read(start)) return -1;
- if (sleep_or_timeout(&cd->data, DATA_TIMEOUT)) {
- debug(("Read timed out sector 0x%x\n", start));
- stats(read_timeout);
- stop_read();
- return -3;
- }
+ do {
+ if (sleep_or_timeout(&cd->data, DATA_TIMEOUT)) {
+ debug(("Read timed out sector 0x%x\n", start));
+ stats(read_timeout);
+ stop_read();
+ return -3;
+ }
+ tries++;
+ } while (cd->intr_ds & ds_fifo_empty && tries < MAX_TRIES);
+ if (tries>1) debug(("Took me some tries\n"))
+ else if (tries == MAX_TRIES)
+ debug(("MAX_TRIES tries for read sector\n"));
transport_data(r_fifo_output_buffer, cd->sector,
READ_AHEAD*RAW_SECTOR_SIZE/2);
if (read_background(start+READ_AHEAD,1)) stats(read_background);
@@ -569,16 +682,22 @@ void cm206_bh(void)
cd->background=3;
break;
case 3:
- if (cd->intr_ur != c_stop) {
- debug(("cm206_bh: c_stop echoed 0x%x\n", cd->intr_ur));
- stats(echo);
+ if (cd->ur_r != cd->ur_w) {
+ if (cd->ur[cd->ur_r] != c_stop) {
+ debug(("cm206_bh: c_stop echoed 0x%x\n", cd->ur[cd->ur_r]));
+ stats(echo);
+ }
+ cd->ur_r++; cd->ur_r %= UR_SIZE;
}
cd->background++;
break;
case 4:
- if (cd->intr_ur != 0xff) {
- debug(("cm206_bh: c_stop reacted with 0x%x\n", cd->intr_ur));
- stats(stop_0xff);
+ if (cd->ur_r != cd->ur_w) {
+ if (cd->ur[cd->ur_r] != 0xff) {
+ debug(("cm206_bh: c_stop reacted with 0x%x\n", cd->ur[cd->ur_r]));
+ stats(stop_0xff);
+ }
+ cd->ur_r++; cd->ur_r %= UR_SIZE;
}
cd->background=0;
}
@@ -699,6 +818,7 @@ static void do_cm206_request(void)
}
error=0;
for (i=0; i<CURRENT->nr_sectors; i++) {
+ int e1, e2;
cd_sec_no = (CURRENT->sector+i)/BLOCKS_ISO; /* 4 times 512 bytes */
quarter = (CURRENT->sector+i) % BLOCKS_ISO;
dest = CURRENT->buffer + i*LINUX_BLOCK_SIZE;
@@ -708,12 +828,14 @@ static void do_cm206_request(void)
+ (cd_sec_no-cd->sector_first)*RAW_SECTOR_SIZE;
memcpy(dest, source, LINUX_BLOCK_SIZE);
}
- else if (!try_adapter(cd_sec_no) || !read_sector(cd_sec_no)) {
+ else if (!(e1=try_adapter(cd_sec_no)) ||
+ !(e2=read_sector(cd_sec_no))) {
source = ((uch *) cd->sector)+16+quarter*LINUX_BLOCK_SIZE;
memcpy(dest, source, LINUX_BLOCK_SIZE);
}
else {
error=1;
+ debug(("cm206_request: %d %d\n", e1, e2));
}
}
end_request(!error);
@@ -758,21 +880,22 @@ inline uch normalize_track(uch track)
/* This function does a binary search for track start. It records all
* tracks seen in the process. Input $track$ must be between 1 and
- * #-of-tracks+1 */
+ * #-of-tracks+1. Note that the start of the disc must be in toc[1].fsm.
+ */
int get_toc_lba(uch track)
{
- int max=74*60*75-150, min=0;
+ int max=74*60*75-150, min=fsm2lba(cd->toc[1].fsm);
int i, lba, l, old_lba=0;
uch * q = cd->q;
uch ct; /* current track */
int binary=0;
- const skip = 3*60*75;
+ const int skip = 3*60*75; /* 3 minutes */
for (i=track; i>0; i--) if (cd->toc[i].track) {
min = fsm2lba(cd->toc[i].fsm);
break;
}
- lba = min + skip; /* 3 minutes */
+ lba = min + skip;
do {
seek(lba);
type_1_command(c_read_current_q, 10, q);
@@ -811,11 +934,11 @@ void update_toc_entry(uch track)
int read_toc_header(struct cdrom_tochdr * hp)
{
if (!FIRST_TRACK) get_disc_status();
- if (hp && DISC_STATUS & cds_all_audio) { /* all audio */
+ if (hp) {
int i;
hp->cdth_trk0 = FIRST_TRACK;
- hp->cdth_trk1 = LAST_TRACK;
- cd->toc[1].track=1; /* fill in first track position */
+ hp->cdth_trk1 = LAST_TRACK;
+ /* fill in first track position */
for (i=0; i<3; i++) cd->toc[1].fsm[i] = cd->disc_status[3+i];
update_toc_entry(LAST_TRACK+1); /* find most entries */
return 0;
@@ -988,7 +1111,7 @@ int cm206_media_changed(struct cdrom_device_info * cdi, int disc_nr)
else return -EIO;
}
-/* The new Uniform cdrom support. Routines should be concise, most of
+/* The new generic cdrom support. Routines should be concise, most of
the logic should be in cdrom.c */
/* returns number of times device is in use */
@@ -1029,7 +1152,7 @@ int cm206_lock_door(struct cdrom_device_info * cdi, int lock)
}
/* Although a session start should be in LBA format, we return it in
- MSF format because it is slightly easier, and the new Uniform ioctl
+ MSF format because it is slightly easier, and the new generic ioctl
will take care of the necessary conversion. */
int cm206_get_last_session(struct cdrom_device_info * cdi,
struct cdrom_multisession * mssp)
@@ -1114,7 +1237,9 @@ static struct cdrom_device_ops cm206_dops = {
cm206_audio_ioctl, /* audio ioctl */
cm206_ioctl, /* device-specific ioctl */
CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_MULTI_SESSION |
- CDC_MEDIA_CHANGED | CDC_MCN | CDC_PLAY_AUDIO, /* capability */
+ CDC_MEDIA_CHANGED | CDC_MCN | CDC_PLAY_AUDIO | CDC_SELECT_SPEED |
+ CDC_IOCTLS | CDC_DRIVE_STATUS,
+ /* capability */
1, /* number of minor devices */
};
@@ -1123,7 +1248,7 @@ static struct cdrom_device_info cm206_info = {
&cm206_dops, /* device operations */
NULL, /* link */
NULL, /* handle (not used by cm206) */
- MKDEV(MAJOR_NR,0), /* dev */
+ 0, /* dev */
0, /* mask */
2, /* maximum speed */
1, /* number of discs */
@@ -1133,9 +1258,9 @@ static struct cdrom_device_info cm206_info = {
"cm206" /* name of the device type */
};
-/* This routine gets called during initialization if thing go wrong,
+/* This routine gets called during initialization if things go wrong,
* can be used in cleanup_module as well. */
-void cleanup(int level)
+static void cleanup(int level)
{
switch (level) {
case 4:
@@ -1206,7 +1331,7 @@ __initfunc(int cm206_init(void))
uch e=0;
long int size=sizeof(struct cm206_struct);
- printk(KERN_INFO VERSION);
+ printk(KERN_INFO "cm206 cdrom driver " REVISION);
cm206_base = probe_base_port(auto_probe ? 0 : cm206_base);
if (!cm206_base) {
printk(" can't find adapter!\n");
@@ -1233,14 +1358,14 @@ __initfunc(int cm206_init(void))
/* Now, the problem here is that reset_cm260 can generate an
interrupt. It seems that this can cause a kernel oops some time
later. So we wait a while and `service' this interrupt. */
- udelay(10);
+ udelay(1000);
outw(dc_normal | READ_AHEAD, r_data_control);
sti();
printk(" using IRQ %d\n", cm206_irq);
#endif
if (send_receive_polled(c_drive_configuration) != c_drive_configuration)
{
- printk(" drive not there\n");
+ printk(KERN_INFO " drive not there\n");
cleanup(1);
return -EIO;
}
@@ -1257,16 +1382,18 @@ __initfunc(int cm206_init(void))
}
printk(".\n");
if (register_blkdev(MAJOR_NR, "cm206", &cdrom_fops) != 0) {
- printk("Cannot register for major %d!\n", MAJOR_NR);
+ printk(KERN_INFO "Cannot register for major %d!\n", MAJOR_NR);
cleanup(3);
return -EIO;
}
+ cm206_info.dev = MKDEV(MAJOR_NR,0);
if (register_cdrom(&cm206_info) != 0) {
- printk("Cannot register for cdrom %d!\n", MAJOR_NR);
+ printk(KERN_INFO "Cannot register for cdrom %d!\n", MAJOR_NR);
cleanup(3);
return -EIO;
}
blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
+ blksize_size[MAJOR_NR] = cm206_blocksizes;
read_ahead[MAJOR_NR] = 16; /* reads ahead what? */
init_bh(CM206_BH, cm206_bh);
@@ -1336,6 +1463,6 @@ __initfunc(void cm206_setup(char *s, int *p))
#endif /* MODULE */
/*
* Local variables:
- * compile-command: "gcc -DMODULE -D__KERNEL__ -I. -I/usr/src/linux/include/linux -Wall -Wstrict-prototypes -O2 -m486 -c cm206.c -o cm206.o"
+ * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -D__SMP__ -pipe -fno-strength-reduce -m486 -DCPU=486 -D__SMP__ -DMODULE -DMODVERSIONS -include /usr/src/linux/include/linux/modversions.h -c -o cm206.o cm206.c"
* End:
*/
diff --git a/drivers/cdrom/mcd.c b/drivers/cdrom/mcd.c
index 090d58498..1de0f7ba7 100644
--- a/drivers/cdrom/mcd.c
+++ b/drivers/cdrom/mcd.c
@@ -216,7 +216,7 @@ static struct cdrom_device_info mcd_info = {
&mcd_dops, /* device operations */
NULL, /* link */
NULL, /* handle */
- MKDEV(MAJOR_NR,0), /* dev */
+ 0, /* dev */
0, /* mask */
2, /* maximum speed */
1, /* number of discs */
@@ -243,15 +243,14 @@ __initfunc(void mcd_setup(char *str, int *ints))
static int mcd_media_changed(struct cdrom_device_info * cdi, int disc_nr)
{
- int retval, target;
+ int retval;
#if 1 /* the below is not reliable */
return 0;
#endif
- target = cdi->dev;
- if (target > 0) {
+ if (cdi->dev) {
printk("mcd: Mitsumi CD-ROM request error: invalid device.\n");
return 0;
}
@@ -1126,9 +1125,9 @@ static void mcd_release(struct cdrom_device_info * cdi)
-/* This routine gets called during initialization if thing go wrong,
+/* This routine gets called during initialization if things go wrong,
* and is used in cleanup_module as well. */
-void cleanup(int level)
+static void cleanup(int level)
{
switch (level) {
case 3:
@@ -1231,17 +1230,20 @@ __initfunc(int mcd_init(void))
if (result[1] == 'D')
{
- sprintf(msg, " mcd: Mitsumi Double Speed CD-ROM at port=0x%x, irq=%d\n", mcd_port, mcd_irq);
- MCMD_DATA_READ = MCMD_2X_READ;
- mcd_info.speed = 2;
- mcdDouble = 1; /* Added flag to drop to 1x speed if too many errors */
- }
- else {
- sprintf(msg, " mcd: Mitsumi Single Speed CD-ROM at port=0x%x, irq=%d\n", mcd_port, mcd_irq);
- mcd_info.speed = 2;
+ sprintf(msg, " mcd: Mitsumi Double Speed CD-ROM at port=0x%x,"
+ " irq=%d\n", mcd_port, mcd_irq);
+ MCMD_DATA_READ = MCMD_2X_READ;
+
+ mcd_info.speed = 2;
+ /* Added flag to drop to 1x speed if too many errors */
+ mcdDouble = 1;
+ } else {
+ sprintf(msg, " mcd: Mitsumi Single Speed CD-ROM at port=0x%x,"
+ " irq=%d\n", mcd_port, mcd_irq);
+ mcd_info.speed = 2;
}
- request_region(mcd_port, 4,"mcd");
+ request_region(mcd_port, 4, "mcd");
outb(MCMD_CONFIG_DRIVE, MCDPORT(0));
outb(0x02,MCDPORT(0));
@@ -1256,6 +1258,8 @@ __initfunc(int mcd_init(void))
mcd_invalidate_buffers();
mcdPresent = 1;
+ mcd_info.dev = MKDEV(MAJOR_NR,0);
+
if (register_cdrom(&mcd_info) != 0) {
printk("Cannot register Mitsumi CD-ROM!\n");
cleanup(3);
diff --git a/drivers/cdrom/mcdx.c b/drivers/cdrom/mcdx.c
index f46388d06..d27417be6 100644
--- a/drivers/cdrom/mcdx.c
+++ b/drivers/cdrom/mcdx.c
@@ -75,9 +75,6 @@ static const char *mcdx_c_version
#define mcdx_drive_map mcdx
#include "mcdx.h"
-#define MCDX_QUIET 0
-
-
#ifndef HZ
#error HZ not defined
#endif
@@ -288,7 +285,7 @@ static struct cdrom_device_ops mcdx_dops = {
NULL, /* hard reset */
mcdx_audio_ioctl, /* audio ioctl */
NULL, /* device-specific ioctl */
- CDC_OPEN_TRAY | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO
+ CDC_OPEN_TRAY | CDC_LOCK | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO
| CDC_DRIVE_STATUS, /* capability */
0, /* number of minor devices */
};
@@ -297,7 +294,7 @@ static struct cdrom_device_info mcdx_info = {
&mcdx_dops, /* device operations */
NULL, /* link */
NULL, /* handle */
- MKDEV(MAJOR_NR,0), /* dev */
+ 0, /* dev */
0, /* mask */
2, /* maximum speed */
1, /* number of discs */
@@ -1027,174 +1024,186 @@ void cleanup_module(void)
/* Support functions ************************************************/
-__initfunc(int mcdx_init(void))
+__initfunc(int mcdx_init_drive(int drive))
{
- int drive;
+ struct s_version version;
+ struct s_drive_stuff* stuffp;
+ int size = sizeof(*stuffp);
char msg[80];
-#ifdef MODULE
- xwarn("Version 2.14(hs) for " UTS_RELEASE "\n");
-#else
- xwarn("Version 2.14(hs) \n");
-#endif
-
- xwarn("$Id: mcdx.c,v 1.21 1997/01/26 07:12:59 davem Exp $\n");
-
- /* zero the pointer array */
- for (drive = 0; drive < MCDX_NDRIVES; drive++)
- mcdx_stuffp[drive] = NULL;
-
- /* do the initialisation */
- for (drive = 0; drive < MCDX_NDRIVES; drive++) {
- struct s_version version;
- struct s_drive_stuff* stuffp;
- int size;
-
- mcdx_blocksizes[drive] = 0;
- size = sizeof(*stuffp);
+ mcdx_blocksizes[drive] = 0;
- xtrace(INIT, "init() try drive %d\n", drive);
+ xtrace(INIT, "init() try drive %d\n", drive);
- xtrace(INIT, "kmalloc space for stuffpt's\n");
- xtrace(MALLOC, "init() malloc %d bytes\n", size);
- if (!(stuffp = kmalloc(size, GFP_KERNEL))) {
- xwarn("init() malloc failed\n");
- break;
- }
+ xtrace(INIT, "kmalloc space for stuffpt's\n");
+ xtrace(MALLOC, "init() malloc %d bytes\n", size);
+ if (!(stuffp = kmalloc(size, GFP_KERNEL))) {
+ xwarn("init() malloc failed\n");
+ return 1;
+ }
- xtrace(INIT, "init() got %d bytes for drive stuff @ %p\n", sizeof(*stuffp), stuffp);
-
- /* set default values */
- memset(stuffp, 0, sizeof(*stuffp));
-
- stuffp->present = 0; /* this should be 0 already */
- stuffp->toc = NULL; /* this should be NULL already */
-
- /* setup our irq and i/o addresses */
- stuffp->irq = irq(mcdx_drive_map[drive]);
- stuffp->wreg_data = stuffp->rreg_data = port(mcdx_drive_map[drive]);
- stuffp->wreg_reset = stuffp->rreg_status = stuffp->wreg_data + 1;
- stuffp->wreg_hcon = stuffp->wreg_reset + 1;
- stuffp->wreg_chn = stuffp->wreg_hcon + 1;
-
- /* check if i/o addresses are available */
- if (0 != check_region((unsigned int) stuffp->wreg_data, MCDX_IO_SIZE)) {
- xwarn("0x%3p,%d: "
- "Init failed. I/O ports (0x%3p..0x%3p) already in use.\n",
- stuffp->wreg_data, stuffp->irq,
- stuffp->wreg_data,
- stuffp->wreg_data + MCDX_IO_SIZE - 1);
- xtrace(MALLOC, "init() free stuffp @ %p\n", stuffp);
- kfree(stuffp);
- xtrace(INIT, "init() continue at next drive\n");
- continue; /* next drive */
- }
+ xtrace(INIT, "init() got %d bytes for drive stuff @ %p\n",
+ sizeof(*stuffp), stuffp);
+
+ /* set default values */
+ memset(stuffp, 0, sizeof(*stuffp));
+
+ stuffp->present = 0; /* this should be 0 already */
+ stuffp->toc = NULL; /* this should be NULL already */
+
+ /* setup our irq and i/o addresses */
+ stuffp->irq = irq(mcdx_drive_map[drive]);
+ stuffp->wreg_data = stuffp->rreg_data = port(mcdx_drive_map[drive]);
+ stuffp->wreg_reset = stuffp->rreg_status = stuffp->wreg_data + 1;
+ stuffp->wreg_hcon = stuffp->wreg_reset + 1;
+ stuffp->wreg_chn = stuffp->wreg_hcon + 1;
+
+ /* check if i/o addresses are available */
+ if (check_region((unsigned int) stuffp->wreg_data, MCDX_IO_SIZE)) {
+ xwarn("0x%3p,%d: Init failed. "
+ "I/O ports (0x%3p..0x%3p) already in use.\n",
+ stuffp->wreg_data, stuffp->irq,
+ stuffp->wreg_data,
+ stuffp->wreg_data + MCDX_IO_SIZE - 1);
+ xtrace(MALLOC, "init() free stuffp @ %p\n", stuffp);
+ kfree(stuffp);
+ xtrace(INIT, "init() continue at next drive\n");
+ return 0; /* next drive */
+ }
- xtrace(INIT, "init() i/o port is available at 0x%3p\n", stuffp->wreg_data);
-
- xtrace(INIT, "init() hardware reset\n");
- mcdx_reset(stuffp, HARD, 1);
-
- xtrace(INIT, "init() get version\n");
- if (-1 == mcdx_requestversion(stuffp, &version, 4)) {
- /* failed, next drive */
- xwarn("%s=0x%3p,%d: Init failed. Can't get version.\n",
- MCDX,
- stuffp->wreg_data, stuffp->irq);
- xtrace(MALLOC, "init() free stuffp @ %p\n", stuffp);
- kfree(stuffp);
- xtrace(INIT, "init() continue at next drive\n");
- continue;
- }
+ xtrace(INIT, "init() i/o port is available at 0x%3p\n",
+ stuffp->wreg_data);
+ xtrace(INIT, "init() hardware reset\n");
+ mcdx_reset(stuffp, HARD, 1);
+
+ xtrace(INIT, "init() get version\n");
+ if (-1 == mcdx_requestversion(stuffp, &version, 4)) {
+ /* failed, next drive */
+ xwarn("%s=0x%3p,%d: Init failed. Can't get version.\n",
+ MCDX,
+ stuffp->wreg_data, stuffp->irq);
+ xtrace(MALLOC, "init() free stuffp @ %p\n", stuffp);
+ kfree(stuffp);
+ xtrace(INIT, "init() continue at next drive\n");
+ return 0;
+ }
- switch (version.code) {
- case 'D':
+ switch (version.code) {
+ case 'D':
stuffp->readcmd = READ2X;
stuffp->present = DOUBLE | DOOR | MULTI;
break;
- case 'F':
+ case 'F':
stuffp->readcmd = READ1X;
stuffp->present = SINGLE | DOOR | MULTI;
break;
- case 'M':
+ case 'M':
stuffp->readcmd = READ1X;
stuffp->present = SINGLE;
break;
- default:
+ default:
stuffp->present = 0; break;
- }
+ }
stuffp->playcmd = READ1X;
+ if (!stuffp->present) {
+ xwarn("%s=0x%3p,%d: Init failed. No Mitsumi CD-ROM?.\n",
+ MCDX, stuffp->wreg_data, stuffp->irq);
+ kfree(stuffp);
+ return 0; /* next drive */
+ }
- if (!stuffp->present) {
- xwarn("%s=0x%3p,%d: Init failed. No Mitsumi CD-ROM?.\n",
- MCDX, stuffp->wreg_data, stuffp->irq);
- kfree(stuffp);
- continue; /* next drive */
- }
-
- xtrace(INIT, "init() register blkdev\n");
- if (register_blkdev(MAJOR_NR, "mcdx", &cdrom_fops) != 0) {
- xwarn("%s=0x%3p,%d: Init failed. Can't get major %d.\n",
- MCDX,
- stuffp->wreg_data, stuffp->irq, MAJOR_NR);
- kfree(stuffp);
- continue; /* next drive */
- }
-
- blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
- read_ahead[MAJOR_NR] = READ_AHEAD;
-
- blksize_size[MAJOR_NR] = mcdx_blocksizes;
+ xtrace(INIT, "init() register blkdev\n");
+ if (register_blkdev(MAJOR_NR, "mcdx", &cdrom_fops) != 0) {
+ xwarn("%s=0x%3p,%d: Init failed. Can't get major %d.\n",
+ MCDX,
+ stuffp->wreg_data, stuffp->irq, MAJOR_NR);
+ kfree(stuffp);
+ return 1;
+ }
- xtrace(INIT, "init() subscribe irq and i/o\n");
- mcdx_irq_map[stuffp->irq] = stuffp;
- if (request_irq(stuffp->irq, mcdx_intr, SA_INTERRUPT, "mcdx", NULL)) {
- xwarn("%s=0x%3p,%d: Init failed. Can't get irq (%d).\n",
- MCDX,
- stuffp->wreg_data, stuffp->irq, stuffp->irq);
- stuffp->irq = 0;
- kfree(stuffp);
- continue;
- }
- request_region((unsigned int) stuffp->wreg_data,
- MCDX_IO_SIZE,
- "mcdx");
+ blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
+ read_ahead[MAJOR_NR] = READ_AHEAD;
+ blksize_size[MAJOR_NR] = mcdx_blocksizes;
+
+ xtrace(INIT, "init() subscribe irq and i/o\n");
+ mcdx_irq_map[stuffp->irq] = stuffp;
+ if (request_irq(stuffp->irq, mcdx_intr, SA_INTERRUPT, "mcdx", NULL)) {
+ xwarn("%s=0x%3p,%d: Init failed. Can't get irq (%d).\n",
+ MCDX,
+ stuffp->wreg_data, stuffp->irq, stuffp->irq);
+ stuffp->irq = 0;
+ kfree(stuffp);
+ return 0;
+ }
+ request_region((unsigned int) stuffp->wreg_data,
+ MCDX_IO_SIZE,
+ "mcdx");
- xtrace(INIT, "init() get garbage\n");
- {
- int i;
- mcdx_delay(stuffp, HZ/2);
- for (i = 100; i; i--) (void) inb((unsigned int) stuffp->rreg_status);
- }
+ xtrace(INIT, "init() get garbage\n");
+ {
+ int i;
+ mcdx_delay(stuffp, HZ/2);
+ for (i = 100; i; i--)
+ (void) inb((unsigned int) stuffp->rreg_status);
+ }
#if WE_KNOW_WHY
- outb(0x50, (unsigned int) stuffp->wreg_chn); /* irq 11 -> channel register */
+ /* irq 11 -> channel register */
+ outb(0x50, (unsigned int) stuffp->wreg_chn);
#endif
- xtrace(INIT, "init() set non dma but irq mode\n");
- mcdx_config(stuffp, 1);
+ xtrace(INIT, "init() set non dma but irq mode\n");
+ mcdx_config(stuffp, 1);
- stuffp->minor = drive;
+ stuffp->minor = drive;
- sprintf(msg, " mcdx: Mitsumi CD-ROM installed at 0x%3p, irq %d."
- " (Firmware version %c %x)\n",
- stuffp->wreg_data, stuffp->irq, version.code,
- version.ver);
- mcdx_stuffp[drive] = stuffp;
- xtrace(INIT, "init() mcdx_stuffp[%d] = %p\n", drive, stuffp);
+ sprintf(msg, " mcdx: Mitsumi CD-ROM installed at 0x%3p, irq %d."
+ " (Firmware version %c %x)\n",
+ stuffp->wreg_data, stuffp->irq, version.code,
+ version.ver);
+ mcdx_stuffp[drive] = stuffp;
+ xtrace(INIT, "init() mcdx_stuffp[%d] = %p\n", drive, stuffp);
+ mcdx_info.dev = MKDEV(MAJOR_NR,0);
if (register_cdrom(&mcdx_info) != 0) {
- printk("Cannot register Mitsumi CD-ROM!\n");
- release_region((unsigned long) stuffp->wreg_data, MCDX_IO_SIZE);
- free_irq(stuffp->irq, NULL);
- kfree(stuffp);
- if (unregister_blkdev(MAJOR_NR, "mcdx") != 0)
+ printk("Cannot register Mitsumi CD-ROM!\n");
+ release_region((unsigned long) stuffp->wreg_data,
+ MCDX_IO_SIZE);
+ free_irq(stuffp->irq, NULL);
+ kfree(stuffp);
+ if (unregister_blkdev(MAJOR_NR, "mcdx") != 0)
xwarn("cleanup() unregister_blkdev() failed\n");
- return -EIO;
+ return 2;
}
printk(msg);
+ return 0;
+}
+
+__initfunc(int mcdx_init(void))
+{
+ int drive;
+#ifdef MODULE
+ xwarn("Version 2.14(hs) for " UTS_RELEASE "\n");
+#else
+ xwarn("Version 2.14(hs) \n");
+#endif
+
+ xwarn("$Id: mcdx.c,v 1.21 1997/01/26 07:12:59 davem Exp $\n");
+
+ /* zero the pointer array */
+ for (drive = 0; drive < MCDX_NDRIVES; drive++)
+ mcdx_stuffp[drive] = NULL;
+
+ /* do the initialisation */
+ for (drive = 0; drive < MCDX_NDRIVES; drive++) {
+ switch(mcdx_init_drive(drive)) {
+ case 2:
+ return -EIO;
+ case 1:
+ break;
+ }
}
return 0;
}
diff --git a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c
index 08de5a794..a3b3e2989 100644
--- a/drivers/cdrom/sbpcd.c
+++ b/drivers/cdrom/sbpcd.c
@@ -304,6 +304,9 @@
* Heiko Eissfeldt <heiko@colossus.escape.de> with additional
* changes by Erik Andersen <andersee@debian.org>
*
+ * 4.62 Fix a bug where playing audio left the drive in an unusable state.
+ * Heiko Eissfeldt <heiko@colossus.escape.de>
+ *
*
* TODO
* implement "read all subchannel data" (96 bytes per frame)
@@ -550,7 +553,6 @@ static struct cdrom_tocentry tocentry;
static struct cdrom_subchnl SC;
static struct cdrom_volctrl volctrl;
static struct cdrom_read_audio read_audio;
-static struct cdrom_multisession ms_info;
static unsigned char msgnum=0;
static char msgbuf[80];
@@ -1047,7 +1049,7 @@ static int CDi_stat_loop(void)
sbp_sleep(1);
i = 1;
}
- msg(DBG_LCS,"CDi_stat_loop failed\n");
+ msg(DBG_LCS,"CDi_stat_loop failed in line %d\n", __LINE__);
return (-1);
}
/*==========================================================================*/
@@ -2297,12 +2299,52 @@ static int cc_CloseTray(void)
}
i=cmd_out();
msg(DBG_LCS,"p_door_closed bit %d after\n", st_door_closed);
+
+ i=cc_ReadError();
+ flags_cmd_out |= f_respo2;
+ cc_ReadStatus(); /* command: give 1-byte status */
+ i=ResponseStatus();
+ if (famT_drive&&(i<0))
+ {
+ cc_DriveReset();
+ i=ResponseStatus();
+#if 0
+ sbp_sleep(HZ);
+#endif 0
+ i=ResponseStatus();
+ }
+ if (i<0)
+ {
+ msg(DBG_INF,"sbpcd cc_CloseTray: ResponseStatus timed out (%d).\n",i);
+ }
+ if (!(famT_drive))
+ {
+ if (!st_spinning)
+ {
+ cc_SpinUp();
+ if (st_check) i=cc_ReadError();
+ flags_cmd_out |= f_respo2;
+ cc_ReadStatus();
+ i=ResponseStatus();
+ } else {
+ }
+ }
+ i=DiskInfo();
return (i);
}
static int sbpcd_tray_move(struct cdrom_device_info *cdi, int position)
{
- return position ? cc_CloseTray() : 0;
+ int i;
+ i = MINOR(cdi->dev);
+
+ switch_drive(i);
+ if (position == 1) {
+ cc_SpinDown();
+ } else {
+ return cc_CloseTray();
+ }
+ return 0;
}
/*==========================================================================*/
@@ -2768,11 +2810,13 @@ static int cc_ReadTocDescr(void)
if (famLV_drive) D_S[d].CDsize_frm=D_S[d].size_blk+1;
}
D_S[d].diskstate_flags |= toc_bit;
- msg(DBG_TOC,"TocDesc: %02X %02X %02X %08X\n",
+ msg(DBG_TOC,"TocDesc: xa %02X firstt %02X lastt %02X size %08X firstses %02X lastsess %02X\n",
D_S[d].xa_byte,
D_S[d].n_first_track,
D_S[d].n_last_track,
- D_S[d].size_msf);
+ D_S[d].size_msf,
+ D_S[d].first_session,
+ D_S[d].last_session);
return (0);
}
/*==========================================================================*/
@@ -3886,6 +3930,7 @@ static int DiskInfo(void)
msg(DBG_000,"DiskInfo entered.\n");
for (j=1;j<LOOP_COUNT;j++)
{
+#if 0
i=SetSpeed();
if (i<0)
{
@@ -3898,10 +3943,14 @@ static int DiskInfo(void)
msg(DBG_INF,"DiskInfo: cc_ModeSense returns %d\n", i);
continue;
}
+#endif
i=cc_ReadCapacity();
if (i>=0) break;
msg(DBG_INF,"DiskInfo: ReadCapacity #%d returns %d\n", j, i);
+#if 0
i=cc_DriveReset();
+#endif
+ if (!fam0_drive && j == 2) break;
}
if (j==LOOP_COUNT) return (-33); /* give up */
@@ -3946,12 +3995,36 @@ static int DiskInfo(void)
static int sbpcd_drive_status(struct cdrom_device_info *cdi, int slot_nr)
{
- if (CDSL_CURRENT != slot_nr) {
- /* we have no changer support */
- return -EINVAL;
- }
+ int st;
- return D_S[d].status_bits & p1_disk_ok ? CDS_DISC_OK : CDS_DRIVE_NOT_READY;
+ if (CDSL_CURRENT != slot_nr) {
+ /* we have no changer support */
+ return -EINVAL;
+ }
+
+ cc_ReadStatus();
+ st=ResponseStatus();
+ if (st<0)
+ {
+ msg(DBG_INF,"sbpcd_drive_status: timeout.\n");
+ return (0);
+ }
+ msg(DBG_000,"Drive Status: door_locked =%d.\n", st_door_locked);
+ msg(DBG_000,"Drive Status: door_closed =%d.\n", st_door_closed);
+ msg(DBG_000,"Drive Status: caddy_in =%d.\n", st_caddy_in);
+ msg(DBG_000,"Drive Status: disk_ok =%d.\n", st_diskok);
+ msg(DBG_000,"Drive Status: spinning =%d.\n", st_spinning);
+ msg(DBG_000,"Drive Status: busy =%d.\n", st_busy);
+#if 0
+ if (!(D_S[MINOR(cdi->dev)].status_bits & p_door_closed)) return CDS_TRAY_OPEN;
+ if (D_S[MINOR(cdi->dev)].status_bits & p_disk_ok) return CDS_DISC_OK;
+ if (D_S[MINOR(cdi->dev)].status_bits & p_disk_in) return CDS_DRIVE_NOT_READY;
+
+ return CDS_NO_DISC;
+#else
+ if (D_S[MINOR(cdi->dev)].status_bits & p_spinning) return CDS_DISC_OK;
+ return CDS_TRAY_OPEN;
+#endif
}
@@ -4082,13 +4155,13 @@ static int sbp_status(void)
static int sbpcd_get_last_session(struct cdrom_device_info *cdi, struct cdrom_multisession *ms_infp)
{
ms_infp->addr_format = CDROM_LBA;
- ms_infp->addr.lba = D_S[d].lba_multi;
- if (D_S[d].f_multisession)
+ ms_infp->addr.lba = D_S[MINOR(cdi->dev)].lba_multi;
+ if (D_S[MINOR(cdi->dev)].f_multisession)
ms_infp->xa_flag=1; /* valid redirection address */
else
ms_infp->xa_flag=0; /* invalid redirection address */
- return 1;
+ return 0;
}
/*==========================================================================*/
@@ -4225,7 +4298,7 @@ static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd,
}
if (status_tries == 0)
{
- msg(DBG_AUD,"read_audio: sbp_status: failed after 3 tries.\n");
+ msg(DBG_AUD,"read_audio: sbp_status: failed after 3 tries in line %d.\n", __LINE__);
continue;
}
msg(DBG_AUD,"read_audio: sbp_status: ok.\n");
@@ -4304,8 +4377,30 @@ static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd,
error_flag=0;
p = D_S[d].aud_buf;
if (sbpro_type==1) OUT(CDo_sel_i_d,1);
- if (do_16bit) insw(CDi_data, p, read_audio.nframes*(CD_FRAMESIZE_RAW>>1));
- else insb(CDi_data, p, read_audio.nframes*CD_FRAMESIZE_RAW);
+ if (do_16bit)
+ {
+ u_short *p2 = (u_short *) p;
+
+ for (; (u_char *) p2 < D_S[d].aud_buf + read_audio.nframes*CD_FRAMESIZE_RAW;)
+ {
+ if ((inb_p(CDi_status)&s_not_data_ready)) continue;
+
+ /* get one sample */
+ *p2++ = inw_p(CDi_data);
+ *p2++ = inw_p(CDi_data);
+ }
+ } else {
+ for (; p < D_S[d].aud_buf + read_audio.nframes*CD_FRAMESIZE_RAW;)
+ {
+ if ((inb_p(CDi_status)&s_not_data_ready)) continue;
+
+ /* get one sample */
+ *p++ = inb_p(CDi_data);
+ *p++ = inb_p(CDi_data);
+ *p++ = inb_p(CDi_data);
+ *p++ = inb_p(CDi_data);
+ }
+ }
if (sbpro_type==1) OUT(CDo_sel_i_d,0);
data_retrying = 0;
}
@@ -4375,7 +4470,7 @@ static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd,
#endif OLD_BUSY
if (data_tries == 0)
{
- msg(DBG_AUD,"read_audio: failed after 5 tries.\n");
+ msg(DBG_AUD,"read_audio: failed after 5 tries in line %d.\n", __LINE__);
RETURN_UP(-EIO);
}
msg(DBG_AUD,"read_audio: successful return.\n");
@@ -4388,28 +4483,6 @@ static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd,
if(arg > 0xff) RETURN_UP(-EINVAL);
read_ahead[MAJOR(cdi->dev)] = arg;
RETURN_UP(0);
-#if 0
- case CDROMEJECT:
- msg(DBG_IOC,"ioctl: CDROMEJECT entered.\n");
- if (fam0_drive) return (0);
- if (D_S[d].open_count>1) RETURN_UP(-EBUSY);
- i=UnLockDoor();
- D_S[d].open_count=-9; /* to get it locked next time again */
- i=cc_SpinDown();
- msg(DBG_IOX,"ioctl: cc_SpinDown returned %d.\n", i);
- msg(DBG_TEA,"ioctl: cc_SpinDown returned %d.\n", i);
- if (i<0) RETURN_UP(-EIO);
- D_S[d].CD_changed=0xFF;
- D_S[d].diskstate_flags=0;
- D_S[d].audio_state=0;
- RETURN_UP(0);
-
- case CDROMEJECT_SW:
- msg(DBG_IOC,"ioctl: CDROMEJECT_SW entered.\n");
- if (fam0_drive) RETURN_UP(0);
- D_S[d].f_eject=arg;
- RETURN_UP(0);
-#endif
default:
msg(DBG_IOC,"ioctl: unknown function request %04X\n", cmd);
RETURN_UP(-EINVAL);
@@ -4581,6 +4654,7 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd,
#endif SAFE_MIXED
i=cc_Pause_Resume(1);
D_S[d].audio_state=0;
+ cc_DriveReset();
RETURN_UP(i);
case CDROMSTART: /* Spin up the drive */
@@ -4816,7 +4890,7 @@ static void DO_SBPCD_REQUEST(void)
}
if (status_tries == 0)
{
- msg(DBG_INF,"sbp_status: failed after 3 tries\n");
+ msg(DBG_INF,"sbp_status: failed after 3 tries in line %d\n", __LINE__);
break;
}
@@ -5242,54 +5316,13 @@ static int sbp_data(struct request *req)
static int sbpcd_open(struct cdrom_device_info *cdi, int purpose)
{
int i;
-
+
i = MINOR(cdi->dev);
- if ((i<0) || (i>=NR_SBPCD) || (D_S[i].drv_id==-1))
- {
- msg(DBG_INF, "open: bad device: %04X\n", cdi->dev);
- return (-ENXIO); /* no such drive */
- }
-
+
MOD_INC_USE_COUNT;
down(&ioctl_read_sem);
switch_drive(i);
-
- i=cc_ReadError();
- flags_cmd_out |= f_respo2;
- cc_ReadStatus(); /* command: give 1-byte status */
- i=ResponseStatus();
- if (famT_drive&&(i<0))
- {
- cc_DriveReset();
- i=ResponseStatus();
-#if 0
- sbp_sleep(HZ);
-#endif 0
- i=ResponseStatus();
- }
- if (i<0)
- {
- msg(DBG_INF,"sbpcd_open: ResponseStatus timed out (%d).\n",i);
- MOD_DEC_USE_COUNT;
- RETURN_UP(-EIO); /* drive doesn't respond */
- }
- if (famT_drive) msg(DBG_TEA,"sbpcd_open: ResponseStatus=%02X\n", i);
- if (!(famT_drive))
- if (!st_spinning)
- {
- cc_SpinUp();
- flags_cmd_out |= f_respo2;
- cc_ReadStatus();
- i=ResponseStatus();
- }
- if (famT_drive) msg(DBG_TEA,"sbpcd_open: status %02X\n", D_S[d].status_bits);
- if (!st_door_closed||!st_caddy_in)
- {
- msg(DBG_INF, "sbpcd_open: no disk in drive.\n");
- D_S[d].open_count=0;
- MOD_DEC_USE_COUNT;
- RETURN_UP(-ENXIO);
- }
+
/*
* try to keep an "open" counter here and lock the door if 0->1.
*/
@@ -5360,24 +5393,6 @@ static void sbpcd_release(struct cdrom_device_info * cdi)
/*
*
*/
-#if 0
-static struct file_operations sbpcd_fops =
-{
- NULL, /* lseek - default */
- block_read, /* read - general block-dev read */
- block_write, /* write - general block-dev write */
- NULL, /* readdir - bad */
- NULL, /* poll */
- sbpcd_ioctl, /* ioctl */
- NULL, /* mmap */
- sbpcd_open, /* open */
- sbpcd_release, /* release */
- NULL, /* fsync */
- NULL, /* fasync */
- sbpcd_chk_disk_change, /* media_change */
- NULL /* revalidate */
-};
-#endif
static int sbpcd_media_changed( struct cdrom_device_info *cdi, int disc_nr);
static struct cdrom_device_ops sbpcd_dops = {
sbpcd_open, /* open */
@@ -5394,7 +5409,7 @@ static struct cdrom_device_ops sbpcd_dops = {
sbpcd_audio_ioctl, /* audio ioctl */
sbpcd_dev_ioctl, /* device-specific ioctl */
CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_MULTI_SESSION |
- CDC_MEDIA_CHANGED | CDC_MCN | CDC_PLAY_AUDIO, /* capability */
+ CDC_MEDIA_CHANGED | CDC_MCN | CDC_PLAY_AUDIO | CDC_IOCTLS, /* capability */
1, /* number of minor devices */
};
@@ -5402,7 +5417,7 @@ static struct cdrom_device_info sbpcd_info = {
&sbpcd_dops, /* device operations */
NULL, /* link */
NULL, /* handle */
- MKDEV(MAJOR_NR,0), /* dev */
+ 0, /* dev */
0, /* mask */
2, /* maximum speed */
1, /* number of discs */
@@ -5556,7 +5571,7 @@ __initfunc(int SBPCD_INIT(void))
int i=0, j=0;
int addr[2]={1, CDROM_PORT};
int port_index;
-
+
sti();
msg(DBG_INF,"sbpcd.c %s\n", VERSION);
@@ -5630,14 +5645,6 @@ __initfunc(int SBPCD_INIT(void))
check_datarate();
msg(DBG_INI,"check_datarate done.\n");
-#if 0
- if (!famL_drive)
- {
- OUT(CDo_reset,0);
- sbp_sleep(HZ);
- }
-#endif 0
-
for (j=0;j<NR_SBPCD;j++)
{
if (D_S[j].drv_id==-1) continue;
@@ -5830,11 +5837,6 @@ static int sbpcd_chk_disk_change(kdev_t full_dev)
msg(DBG_CHK,"media_check (%d) called\n", MINOR(full_dev));
i=MINOR(full_dev);
- if ( (i<0) || (i>=NR_SBPCD) || (D_S[i].drv_id==-1) )
- {
- msg(DBG_INF, "media_check: invalid device %04X.\n", full_dev);
- return (-1);
- }
if (D_S[i].CD_changed==0xFF)
{
diff --git a/drivers/cdrom/sbpcd.h b/drivers/cdrom/sbpcd.h
index e9021316d..805e98a82 100644
--- a/drivers/cdrom/sbpcd.h
+++ b/drivers/cdrom/sbpcd.h
@@ -119,14 +119,14 @@
#define JUKEBOX 0
#else
#define JUKEBOX 1
-#endif DISTRIBUTION
+#endif /* DISTRIBUTION */
/* tray control: eject tray after last use */
#if DISTRIBUTION
#define EJECT 0
#else
#define EJECT 1
-#endif DISTRIBUTION
+#endif /* DISTRIBUTION */
/* max. number of audio frames to read with one */
/* request (allocates n* 2352 bytes kernel memory!) */
@@ -570,7 +570,7 @@ pause: 8d pr 00 00 00 00 00. (0) pause (pr=00)
resume (pr=80) audio playing
Mode Select:
- 84 00 nn-nn ??-?? 00 (0) nn-nn: 2048 or 2340
+ 84 00 nn-nn ??.?? 00 (0) nn-nn: 2048 or 2340
possibly defines transfer size
set_vol: 84 83 00 00 sw le 00. (0) sw(itch): lrxxxxxx (off=1)
@@ -604,12 +604,12 @@ seek: 01 00 ll-bb-aa 00 00. (0)
seek: 01 02 mm-ss-ff 00 00. (0)
Read Data:
-read: 02 xx-xx-xx nn-nn fl. (??) read nn-nn blocks of 2048 bytes,
+read: 02 xx-xx-xx nn-nn fl. (?) read nn-nn blocks of 2048 bytes,
starting at block xx-xx-xx
fl=0: "lba"-, =2:"msf-bcd"-coded xx-xx-xx
Read XA-Data:
-read: 03 xx-xx-xx nn-nn fl. (??) read nn-nn blocks of 2340 bytes,
+read: 03 xx-xx-xx nn-nn fl. (?) read nn-nn blocks of 2340 bytes,
starting at block xx-xx-xx
fl=0: "lba"-, =2:"msf-bcd"-coded xx-xx-xx
@@ -838,7 +838,7 @@ Read XA Parameter:
/*==========================================================================*/
/*==========================================================================*/
-#endif _LINUX_SBPCD_H
+#endif /* _LINUX_SBPCD_H */
/*==========================================================================*/
/*
* Overrides for Emacs so that we follow Linus's tabbing style.