From: Adrian Bunk <bunk@stusta.de>
To: Andrew Morton <akpm@osdl.org>
Cc: linux-kernel@vger.kernel.org
Subject: [2.6 patch] kill drivers/cdrom/mcd.c
Date: Tue, 15 Mar 2005 13:16:11 +0100 [thread overview]
Message-ID: <20050315121611.GD3189@stusta.de> (raw)
As described in my patch that marked this obsolete driver as BROKEN,
this patch completely removes it.
Signed-off-by: Adrian Bunk <bunk@stusta.de>
---
Documentation/cdrom/mcd | 4
Documentation/cdrom/mcdx | 17
drivers/cdrom/Kconfig | 56 -
drivers/cdrom/Makefile | 1
drivers/cdrom/mcd.c | 1565 ---------------------------------------
drivers/cdrom/mcd.h | 106 --
6 files changed, 6 insertions(+), 1743 deletions(-)
--- linux-2.6.11-mm3-full/drivers/cdrom/Kconfig.old 2005-03-15 04:14:03.000000000 +0100
+++ linux-2.6.11-mm3-full/drivers/cdrom/Kconfig 2005-03-15 04:20:07.000000000 +0100
@@ -103,60 +103,14 @@
To compile this driver as a module, choose M here: the
module will be called sbpcd.
-config MCD
- tristate "Mitsumi (standard) [no XA/Multisession] CDROM support"
- depends on CD_NO_IDESCSI && BROKEN
- ---help---
- This is the older of the two drivers for the older Mitsumi models
- LU-005, FX-001 and FX-001D. This is not the right driver for the
- FX-001DE and the triple or quad speed models (all these are
- IDE/ATAPI models). Please also the file
- <file:Documentation/cdrom/mcd>.
-
- With the old LU-005 model, the whole drive chassis slides out for cd
- insertion. The FX-xxx models use a motorized tray type mechanism.
- Note that this driver does not support XA or MultiSession CDs
- (PhotoCDs). There is a new driver (next question) which can do
- this. If you want that one, say N here.
-
- If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
- file system support" below, because that's the file system used on
- CD-ROMs.
-
- To compile this driver as a module, choose M here: the
- module will be called mcd.
-
-config MCD_IRQ
- int "MCD IRQ"
- depends on MCD
- default "11"
- help
- This allows you to specify the default value of the IRQ used by the
- driver. This setting can be overridden by passing the "mcd="
- parameter to the kernel at boot time (or at module load time if you
- said M to "Standard Mitsumi CD-ROM support").
-
-config MCD_BASE
- hex "MCD I/O base"
- depends on MCD
- default "300"
- help
- This allows you to specify the default value of the I/O base address
- used by the driver. This setting can be overridden by passing the
- "mcd=" parameter to the kernel at boot time (or at module load time
- if you said M to "Standard Mitsumi CD-ROM support").
-
config MCDX
- tristate "Mitsumi [XA/MultiSession] CDROM support"
+ tristate "Mitsumi CDROM support"
depends on CD_NO_IDESCSI
---help---
- Use this driver if you want to be able to read XA or MultiSession
- CDs (PhotoCDs) as well as ordinary CDs with your Mitsumi LU-005,
- FX-001 or FX-001D CD-ROM drive. In addition, this driver uses much
- less kernel memory than the old one, if that is a concern. This
- driver is able to support more than one drive, but each drive needs
- a separate interface card. Please read the file
- <file:Documentation/cdrom/mcdx>.
+ Use this driver if you want to be able to use your Mitsumi LU-005,
+ FX-001 or FX-001D CD-ROM drive.
+
+ Please read the file <file:Documentation/cdrom/mcdx>.
If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
file system support" below, because that's the file system used on
--- linux-2.6.11-mm3-full/drivers/cdrom/Makefile.old 2005-03-15 04:14:34.000000000 +0100
+++ linux-2.6.11-mm3-full/drivers/cdrom/Makefile 2005-03-15 04:14:43.000000000 +0100
@@ -15,7 +15,6 @@
obj-$(CONFIG_CM206) += cm206.o cdrom.o
obj-$(CONFIG_GSCD) += gscd.o
obj-$(CONFIG_ISP16_CDI) += isp16.o
-obj-$(CONFIG_MCD) += mcd.o cdrom.o
obj-$(CONFIG_MCDX) += mcdx.o cdrom.o
obj-$(CONFIG_OPTCD) += optcd.o
obj-$(CONFIG_SBPCD) += sbpcd.o cdrom.o
--- linux-2.6.11-mm3-full/Documentation/cdrom/mcdx.old 2005-03-15 04:21:07.000000000 +0100
+++ linux-2.6.11-mm3-full/Documentation/cdrom/mcdx 2005-03-15 04:21:40.000000000 +0100
@@ -1,16 +1,3 @@
-This is a first attempt to create an `improved' driver for the Mitsumi drives.
-It is able to "live together" with mcd.c, if you have at least two Mitsumi
-drives: each driver can use its own drive.
-
-To allow this "coexistence" as long as mcdx.c is not a superset of mcd.c,
-this driver has to use its own device files. We use MAJOR 20 for it. So,
-you have to do
-
- # mknod /dev/mcdx0 b 20 0
- # mknod /dev/mcdx1 b 20 1
-
-and so on, one entry for each drive to support, once.
-
If you are using the driver as a module, you can specify your ports and IRQs
like
@@ -25,9 +12,7 @@
ordinary CDs;
o supports up to 5 drives (of course, you'll need free
IRQs, i/o ports and slots);
- o uses much less kernel memory than the standard mcd driver
- (no extra driver internal buffers!).
- o plays audio (like the `old' driver, I hope)
+ o plays audio
This version doesn't support yet:
--- linux-2.6.11-mm3-full/Documentation/cdrom/mcd 2005-03-02 08:38:13.000000000 +0100
+++ /dev/null 2004-11-25 03:16:25.000000000 +0100
@@ -1,4 +0,0 @@
-This driver does not support XA or MultiSession CDs (PhotoCDs). Use the
-experimental driver mcdx.c for that.
-
-You can use mcd for one interface, and mcdx for another.
--- linux-2.6.11-mm3-full/drivers/cdrom/mcd.h 2005-03-02 08:38:00.000000000 +0100
+++ /dev/null 2004-11-25 03:16:25.000000000 +0100
@@ -1,106 +0,0 @@
-/*
- * Definitions for a Mitsumi CD-ROM interface
- *
- * Copyright (C) 1992 Martin Harriss
- *
- * martin@bdsi.com
- *
- * 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
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-/* Increase this if you get lots of timeouts */
-#define MCD_STATUS_DELAY 1000
-
-/* number of times to retry a command before giving up */
-#define MCD_RETRY_ATTEMPTS 10
-
-/* port access macro */
-#define MCDPORT(x) (mcd_port + (x))
-
-/* How many sectors to read at 1x when an error at 2x speed occurs. */
-/* You can change this to anything from 2 to 32767, but 30 seems to */
-/* work best for me. I have found that when the drive has problems */
-/* reading one sector, it will have troubles reading the next few. */
-#define SINGLE_HOLD_SECTORS 30
-
-#define MCMD_2X_READ 0xC1 /* Double Speed Read DON'T TOUCH! */
-
-/* status bits */
-
-#define MST_CMD_CHECK 0x01 /* command error */
-#define MST_BUSY 0x02 /* now playing */
-#define MST_READ_ERR 0x04 /* read error */
-#define MST_DSK_TYPE 0x08
-#define MST_SERVO_CHECK 0x10
-#define MST_DSK_CHG 0x20 /* disk removed or changed */
-#define MST_READY 0x40 /* disk in the drive */
-#define MST_DOOR_OPEN 0x80 /* door is open */
-
-/* flag bits */
-
-#define MFL_DATA 0x02 /* data available */
-#define MFL_STATUS 0x04 /* status available */
-
-/* commands */
-
-#define MCMD_GET_DISK_INFO 0x10 /* read info from disk */
-#define MCMD_GET_Q_CHANNEL 0x20 /* read info from q channel */
-#define MCMD_GET_STATUS 0x40
-#define MCMD_SET_MODE 0x50
-#define MCMD_SOFT_RESET 0x60
-#define MCMD_STOP 0x70 /* stop play */
-#define MCMD_CONFIG_DRIVE 0x90
-#define MCMD_SET_VOLUME 0xAE /* set audio level */
-#define MCMD_PLAY_READ 0xC0 /* play or read data */
-#define MCMD_GET_VERSION 0xDC
-#define MCMD_EJECT 0xF6 /* eject (FX drive) */
-
-/* borrowed from hd.c */
-
-#define MAX_TRACKS 104
-
-struct msf {
- unsigned char min;
- unsigned char sec;
- unsigned char frame;
-};
-
-struct mcd_Play_msf {
- struct msf start;
- struct msf end;
-};
-
-struct mcd_DiskInfo {
- unsigned char first;
- unsigned char last;
- struct msf diskLength;
- struct msf firstTrack;
-};
-
-struct mcd_Toc {
- unsigned char ctrl_addr;
- unsigned char track;
- unsigned char pointIndex;
- struct msf trackTime;
- struct msf diskTime;
-};
-
-#define test1(x)
-#define test2(x)
-#define test3(x)
-#define test4(x)
-#define test5(x)
-
--- linux-2.6.11-mm3-full/drivers/cdrom/mcd.c 2005-03-12 13:33:21.000000000 +0100
+++ /dev/null 2004-11-25 03:16:25.000000000 +0100
@@ -1,1565 +0,0 @@
-/*
- linux/kernel/blk_drv/mcd.c - Mitsumi CDROM driver
-
- Copyright (C) 1992 Martin Harriss
- Portions Copyright (C) 2001 Red Hat
-
- martin@bdsi.com (no longer valid - where are you now, Martin?)
-
- 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
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- HISTORY
-
- 0.1 First attempt - internal use only
- 0.2 Cleaned up delays and use of timer - alpha release
- 0.3 Audio support added
- 0.3.1 Changes for mitsumi CRMC LU005S march version
- (stud11@cc4.kuleuven.ac.be)
- 0.3.2 bug fixes to the ioctls and merged with ALPHA0.99-pl12
- (Jon Tombs <jon@robots.ox.ac.uk>)
- 0.3.3 Added more #defines and mcd_setup()
- (Jon Tombs <jon@gtex02.us.es>)
-
- October 1993 Bernd Huebner and Ruediger Helsch, Unifix Software GmbH,
- Braunschweig, Germany: rework to speed up data read operation.
- Also enabled definition of irq and address from bootstrap, using the
- environment.
- November 93 added code for FX001 S,D (single & double speed).
- February 94 added code for broken M 5/6 series of 16-bit single speed.
-
-
- 0.4
- Added support for loadable MODULEs, so mcd can now also be loaded by
- insmod and removed by rmmod during runtime.
- Werner Zimmermann (zimmerma@rz.fht-esslingen.de), Mar. 26, 95
-
- 0.5
- I added code for FX001 D to drop from double speed to single speed
- when encountering errors... this helps with some "problematic" CD's
- that are supposedly "OUT OF TOLERANCE" (but are really shitty presses!)
- severely scratched, or possibly slightly warped! I have noticed that
- the Mitsumi 2x/4x drives are just less tolerant and the firmware is
- not smart enough to drop speed, so let's just kludge it with software!
- ****** THE 4X SPEED MITSUMI DRIVES HAVE THE SAME PROBLEM!!!!!! ******
- Anyone want to "DONATE" one to me?! ;) I hear sometimes they are
- even WORSE! ;)
- ** HINT... HINT... TAKE NOTES MITSUMI This could save some hassles with
- certain "large" CD's that have data on the outside edge in your
- DOS DRIVERS .... Accuracy counts... speed is secondary ;)
- 17 June 95 Modifications By Andrew J. Kroll <ag784@freenet.buffalo.edu>
- 07 July 1995 Modifications by Andrew J. Kroll
-
- Bjorn Ekwall <bj0rn@blox.se> added unregister_blkdev to mcd_init()
-
- Michael K. Johnson <johnsonm@redhat.com> added retries on open
- for slow drives which take a while to recognize that they contain
- a CD.
-
- November 1997 -- ported to the Uniform CD-ROM driver by Erik Andersen.
- March 1999 -- made io base and irq CONFIG_ options (Tigran Aivazian).
-
- November 1999 -- Make kernel-parameter implementation work with 2.3.x
- Removed init_module & cleanup_module in favor of
- module_init & module_exit.
- Torben Mathiasen <tmm@image.dk>
-
- September 2001 - Reformatted and cleaned up the code
- Alan Cox <alan@redhat.com>
-*/
-
-#include <linux/module.h>
-
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/signal.h>
-#include <linux/mm.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/devfs_fs_kernel.h>
-#include <linux/cdrom.h>
-#include <linux/ioport.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/config.h>
-
-/* #define REALLY_SLOW_IO */
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/current.h>
-#include <asm/uaccess.h>
-#include <linux/blkdev.h>
-
-#include "mcd.h"
-
-/* I added A flag to drop to 1x speed if too many errors 0 = 1X ; 1 = 2X */
-static int mcdDouble;
-
-/* How many sectors to hold at 1x speed counter */
-static int mcd1xhold;
-
-/* Is the drive connected properly and responding?? */
-static int mcdPresent;
-static struct request_queue *mcd_queue;
-
-#define MAJOR_NR MITSUMI_CDROM_MAJOR
-#define QUEUE (mcd_queue)
-#define CURRENT elv_next_request(mcd_queue)
-
-#define QUICK_LOOP_DELAY udelay(45) /* use udelay */
-#define QUICK_LOOP_COUNT 20
-
-static int current_valid(void)
-{
- return CURRENT &&
- CURRENT->cmd == READ &&
- CURRENT->sector != -1;
-}
-
-#define MFL_STATUSorDATA (MFL_STATUS | MFL_DATA)
-#define MCD_BUF_SIZ 16
-static volatile int mcd_transfer_is_active;
-static char mcd_buf[2048 * MCD_BUF_SIZ]; /* buffer for block size conversion */
-static volatile int mcd_buf_bn[MCD_BUF_SIZ], mcd_next_bn;
-static volatile int mcd_buf_in, mcd_buf_out = -1;
-static volatile int mcd_error;
-static int mcd_open_count;
-enum mcd_state_e {
- MCD_S_IDLE, /* 0 */
- MCD_S_START, /* 1 */
- MCD_S_MODE, /* 2 */
- MCD_S_READ, /* 3 */
- MCD_S_DATA, /* 4 */
- MCD_S_STOP, /* 5 */
- MCD_S_STOPPING /* 6 */
-};
-static volatile enum mcd_state_e mcd_state = MCD_S_IDLE;
-static int mcd_mode = -1;
-static int MCMD_DATA_READ = MCMD_PLAY_READ;
-
-#define READ_TIMEOUT 3000
-
-int mitsumi_bug_93_wait;
-
-static short mcd_port = CONFIG_MCD_BASE; /* used as "mcd" by "insmod" */
-static int mcd_irq = CONFIG_MCD_IRQ; /* must directly follow mcd_port */
-
-static int McdTimeout, McdTries;
-static DECLARE_WAIT_QUEUE_HEAD(mcd_waitq);
-
-static struct mcd_DiskInfo DiskInfo;
-static struct mcd_Toc Toc[MAX_TRACKS];
-static struct mcd_Play_msf mcd_Play;
-
-static int audioStatus;
-static char mcdDiskChanged;
-static char tocUpToDate;
-static char mcdVersion;
-
-static void mcd_transfer(void);
-static void mcd_poll(unsigned long dummy);
-static void mcd_invalidate_buffers(void);
-static void hsg2msf(long hsg, struct msf *msf);
-static void bin2bcd(unsigned char *p);
-static int bcd2bin(unsigned char bcd);
-static int mcdStatus(void);
-static void sendMcdCmd(int cmd, struct mcd_Play_msf *params);
-static int getMcdStatus(int timeout);
-static int GetQChannelInfo(struct mcd_Toc *qp);
-static int updateToc(void);
-static int GetDiskInfo(void);
-static int GetToc(void);
-static int getValue(unsigned char *result);
-static int mcd_open(struct cdrom_device_info *cdi, int purpose);
-static void mcd_release(struct cdrom_device_info *cdi);
-static int mcd_media_changed(struct cdrom_device_info *cdi, int disc_nr);
-static int mcd_tray_move(struct cdrom_device_info *cdi, int position);
-static DEFINE_SPINLOCK(mcd_spinlock);
-static int mcd_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
- void *arg);
-static int mcd_drive_status(struct cdrom_device_info *cdi, int slot_nr);
-
-static struct timer_list mcd_timer = TIMER_INITIALIZER(NULL, 0, 0);
-
-static struct cdrom_device_ops mcd_dops = {
- .open = mcd_open,
- .release = mcd_release,
- .drive_status = mcd_drive_status,
- .media_changed = mcd_media_changed,
- .tray_move = mcd_tray_move,
- .audio_ioctl = mcd_audio_ioctl,
- .capability = CDC_OPEN_TRAY | CDC_MEDIA_CHANGED |
- CDC_PLAY_AUDIO | CDC_DRIVE_STATUS,
-};
-
-static struct cdrom_device_info mcd_info = {
- .ops = &mcd_dops,
- .speed = 2,
- .capacity = 1,
- .name = "mcd",
-};
-
-static int mcd_block_open(struct inode *inode, struct file *file)
-{
- return cdrom_open(&mcd_info, inode, file);
-}
-
-static int mcd_block_release(struct inode *inode, struct file *file)
-{
- return cdrom_release(&mcd_info, file);
-}
-
-static int mcd_block_ioctl(struct inode *inode, struct file *file,
- unsigned cmd, unsigned long arg)
-{
- return cdrom_ioctl(file, &mcd_info, inode, cmd, arg);
-}
-
-static int mcd_block_media_changed(struct gendisk *disk)
-{
- return cdrom_media_changed(&mcd_info);
-}
-
-static struct block_device_operations mcd_bdops =
-{
- .owner = THIS_MODULE,
- .open = mcd_block_open,
- .release = mcd_block_release,
- .ioctl = mcd_block_ioctl,
- .media_changed = mcd_block_media_changed,
-};
-
-static struct gendisk *mcd_gendisk;
-
-static int __init mcd_setup(const char *str)
-{
- int ints[9];
-
- (void) get_options(str, ARRAY_SIZE(ints), ints);
-
- if (ints[0] > 0)
- mcd_port = ints[1];
- if (ints[0] > 1)
- mcd_irq = ints[2];
- if (ints[0] > 2)
- mitsumi_bug_93_wait = ints[3];
-
- return 1;
-}
-
-__setup("mcd=", mcd_setup);
-
-#ifdef MODULE
-static int __init param_set_mcd(const char *val, struct kernel_param *kp)
-{
- mcd_setup(val);
- return 0;
-}
-module_param_call(mcd, param_set_mcd, NULL, NULL, 0);
-#endif
-
-static int mcd_media_changed(struct cdrom_device_info *cdi, int disc_nr)
-{
- return 0;
-}
-
-
-/*
- * Do a 'get status' command and get the result. Only use from the top half
- * because it calls 'getMcdStatus' which sleeps.
- */
-
-static int statusCmd(void)
-{
- int st = -1, retry;
-
- for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++) {
- /* send get-status cmd */
- outb(MCMD_GET_STATUS, MCDPORT(0));
-
- st = getMcdStatus(MCD_STATUS_DELAY);
- if (st != -1)
- break;
- }
-
- return st;
-}
-
-
-/*
- * Send a 'Play' command and get the status. Use only from the top half.
- */
-
-static int mcdPlay(struct mcd_Play_msf *arg)
-{
- int retry, st = -1;
-
- for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++) {
- sendMcdCmd(MCMD_PLAY_READ, arg);
- st = getMcdStatus(2 * MCD_STATUS_DELAY);
- if (st != -1)
- break;
- }
-
- return st;
-}
-
-
-static int mcd_tray_move(struct cdrom_device_info *cdi, int position)
-{
- int i;
- if (position) {
- /* Eject */
- /* all drives can at least stop! */
- if (audioStatus == CDROM_AUDIO_PLAY) {
- outb(MCMD_STOP, MCDPORT(0));
- i = getMcdStatus(MCD_STATUS_DELAY);
- }
-
- audioStatus = CDROM_AUDIO_NO_STATUS;
-
- outb(MCMD_EJECT, MCDPORT(0));
- /*
- * the status (i) shows failure on all but the FX drives.
- * But nothing we can do about that in software!
- * So just read the status and forget it. - Jon.
- */
- i = getMcdStatus(MCD_STATUS_DELAY);
- return 0;
- } else
- return -EINVAL;
-}
-
-long msf2hsg(struct msf *mp)
-{
- return bcd2bin(mp->frame) + bcd2bin(mp->sec) * 75 + bcd2bin(mp->min) * 4500 - 150;
-}
-
-
-int mcd_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
- void *arg)
-{
- int i, st;
- struct mcd_Toc qInfo;
- struct cdrom_ti *ti;
- struct cdrom_tochdr *tocHdr;
- struct cdrom_msf *msf;
- struct cdrom_subchnl *subchnl;
- struct cdrom_tocentry *entry;
- struct mcd_Toc *tocPtr;
- struct cdrom_volctrl *volctrl;
-
- st = statusCmd();
- if (st < 0)
- return -EIO;
-
- if (!tocUpToDate) {
- i = updateToc();
- if (i < 0)
- return i; /* error reading TOC */
- }
-
- switch (cmd) {
- case CDROMSTART: /* Spin up the drive */
- /* Don't think we can do this. Even if we could,
- * I think the drive times out and stops after a while
- * anyway. For now, ignore it.
- */
-
- return 0;
-
- case CDROMSTOP: /* Spin down the drive */
- outb(MCMD_STOP, MCDPORT(0));
- i = getMcdStatus(MCD_STATUS_DELAY);
-
- /* should we do anything if it fails? */
-
- audioStatus = CDROM_AUDIO_NO_STATUS;
- return 0;
-
- case CDROMPAUSE: /* Pause the drive */
- if (audioStatus != CDROM_AUDIO_PLAY)
- return -EINVAL;
-
- outb(MCMD_STOP, MCDPORT(0));
- i = getMcdStatus(MCD_STATUS_DELAY);
-
- if (GetQChannelInfo(&qInfo) < 0) {
- /* didn't get q channel info */
-
- audioStatus = CDROM_AUDIO_NO_STATUS;
- return 0;
- }
-
- mcd_Play.start = qInfo.diskTime; /* remember restart point */
-
- audioStatus = CDROM_AUDIO_PAUSED;
- return 0;
-
- case CDROMRESUME: /* Play it again, Sam */
- if (audioStatus != CDROM_AUDIO_PAUSED)
- return -EINVAL;
-
- /* restart the drive at the saved position. */
-
- i = mcdPlay(&mcd_Play);
- if (i < 0) {
- audioStatus = CDROM_AUDIO_ERROR;
- return -EIO;
- }
-
- audioStatus = CDROM_AUDIO_PLAY;
- return 0;
-
- case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */
-
- ti = (struct cdrom_ti *) arg;
-
- if (ti->cdti_trk0 < DiskInfo.first
- || ti->cdti_trk0 > DiskInfo.last
- || ti->cdti_trk1 < ti->cdti_trk0) {
- return -EINVAL;
- }
-
- if (ti->cdti_trk1 > DiskInfo.last)
- ti->cdti_trk1 = DiskInfo.last;
-
- mcd_Play.start = Toc[ti->cdti_trk0].diskTime;
- mcd_Play.end = Toc[ti->cdti_trk1 + 1].diskTime;
-
-#ifdef MCD_DEBUG
- printk("play: %02x:%02x.%02x to %02x:%02x.%02x\n",
- mcd_Play.start.min, mcd_Play.start.sec,
- mcd_Play.start.frame, mcd_Play.end.min,
- mcd_Play.end.sec, mcd_Play.end.frame);
-#endif
-
- i = mcdPlay(&mcd_Play);
- if (i < 0) {
- audioStatus = CDROM_AUDIO_ERROR;
- return -EIO;
- }
-
- audioStatus = CDROM_AUDIO_PLAY;
- return 0;
-
- case CDROMPLAYMSF: /* Play starting at the given MSF address. */
-
- if (audioStatus == CDROM_AUDIO_PLAY) {
- outb(MCMD_STOP, MCDPORT(0));
- i = getMcdStatus(MCD_STATUS_DELAY);
- audioStatus = CDROM_AUDIO_NO_STATUS;
- }
-
- msf = (struct cdrom_msf *) arg;
-
- /* convert to bcd */
-
- bin2bcd(&msf->cdmsf_min0);
- bin2bcd(&msf->cdmsf_sec0);
- bin2bcd(&msf->cdmsf_frame0);
- bin2bcd(&msf->cdmsf_min1);
- bin2bcd(&msf->cdmsf_sec1);
- bin2bcd(&msf->cdmsf_frame1);
-
- mcd_Play.start.min = msf->cdmsf_min0;
- mcd_Play.start.sec = msf->cdmsf_sec0;
- mcd_Play.start.frame = msf->cdmsf_frame0;
- mcd_Play.end.min = msf->cdmsf_min1;
- mcd_Play.end.sec = msf->cdmsf_sec1;
- mcd_Play.end.frame = msf->cdmsf_frame1;
-
-#ifdef MCD_DEBUG
- printk("play: %02x:%02x.%02x to %02x:%02x.%02x\n",
- mcd_Play.start.min, mcd_Play.start.sec,
- mcd_Play.start.frame, mcd_Play.end.min,
- mcd_Play.end.sec, mcd_Play.end.frame);
-#endif
-
- i = mcdPlay(&mcd_Play);
- if (i < 0) {
- audioStatus = CDROM_AUDIO_ERROR;
- return -EIO;
- }
-
- audioStatus = CDROM_AUDIO_PLAY;
- return 0;
-
- case CDROMREADTOCHDR: /* Read the table of contents header */
- tocHdr = (struct cdrom_tochdr *) arg;
- tocHdr->cdth_trk0 = DiskInfo.first;
- tocHdr->cdth_trk1 = DiskInfo.last;
- return 0;
-
- case CDROMREADTOCENTRY: /* Read an entry in the table of contents */
- entry = (struct cdrom_tocentry *) arg;
- if (entry->cdte_track == CDROM_LEADOUT)
- tocPtr = &Toc[DiskInfo.last - DiskInfo.first + 1];
-
- else if (entry->cdte_track > DiskInfo.last
- || entry->cdte_track < DiskInfo.first)
- return -EINVAL;
-
- else
- tocPtr = &Toc[entry->cdte_track];
-
- entry->cdte_adr = tocPtr->ctrl_addr;
- entry->cdte_ctrl = tocPtr->ctrl_addr >> 4;
-
- if (entry->cdte_format == CDROM_LBA)
- entry->cdte_addr.lba = msf2hsg(&tocPtr->diskTime);
-
- else if (entry->cdte_format == CDROM_MSF) {
- entry->cdte_addr.msf.minute =
- bcd2bin(tocPtr->diskTime.min);
- entry->cdte_addr.msf.second =
- bcd2bin(tocPtr->diskTime.sec);
- entry->cdte_addr.msf.frame =
- bcd2bin(tocPtr->diskTime.frame);
- }
-
- else
- return -EINVAL;
-
- return 0;
-
- case CDROMSUBCHNL: /* Get subchannel info */
-
- subchnl = (struct cdrom_subchnl *) arg;
- if (GetQChannelInfo(&qInfo) < 0)
- return -EIO;
-
- subchnl->cdsc_audiostatus = audioStatus;
- subchnl->cdsc_adr = qInfo.ctrl_addr;
- subchnl->cdsc_ctrl = qInfo.ctrl_addr >> 4;
- subchnl->cdsc_trk = bcd2bin(qInfo.track);
- subchnl->cdsc_ind = bcd2bin(qInfo.pointIndex);
- subchnl->cdsc_absaddr.msf.minute = bcd2bin(qInfo.diskTime.min);
- subchnl->cdsc_absaddr.msf.second = bcd2bin(qInfo.diskTime.sec);
- subchnl->cdsc_absaddr.msf.frame = bcd2bin(qInfo.diskTime.frame);
- subchnl->cdsc_reladdr.msf.minute = bcd2bin(qInfo.trackTime.min);
- subchnl->cdsc_reladdr.msf.second = bcd2bin(qInfo.trackTime.sec);
- subchnl->cdsc_reladdr.msf.frame = bcd2bin(qInfo.trackTime.frame);
- return (0);
-
- case CDROMVOLCTRL: /* Volume control */
- volctrl = (struct cdrom_volctrl *) arg;
- outb(MCMD_SET_VOLUME, MCDPORT(0));
- outb(volctrl->channel0, MCDPORT(0));
- outb(255, MCDPORT(0));
- outb(volctrl->channel1, MCDPORT(0));
- outb(255, MCDPORT(0));
-
- i = getMcdStatus(MCD_STATUS_DELAY);
- if (i < 0)
- return -EIO;
-
- {
- char a, b, c, d;
-
- getValue(&a);
- getValue(&b);
- getValue(&c);
- getValue(&d);
- }
-
- return 0;
-
- default:
- return -EINVAL;
- }
-}
-
-/*
- * Take care of the different block sizes between cdrom and Linux.
- * When Linux gets variable block sizes this will probably go away.
- */
-
-static void mcd_transfer(void)
-{
- if (!current_valid())
- return;
-
- while (CURRENT->nr_sectors) {
- int bn = CURRENT->sector / 4;
- int i;
- for (i = 0; i < MCD_BUF_SIZ && mcd_buf_bn[i] != bn; ++i)
- ;
- if (i < MCD_BUF_SIZ) {
- int offs =(i * 4 + (CURRENT->sector & 3)) * 512;
- int nr_sectors = 4 - (CURRENT->sector & 3);
- if (mcd_buf_out != i) {
- mcd_buf_out = i;
- if (mcd_buf_bn[i] != bn) {
- mcd_buf_out = -1;
- continue;
- }
- }
- if (nr_sectors > CURRENT->nr_sectors)
- nr_sectors = CURRENT->nr_sectors;
- memcpy(CURRENT->buffer, mcd_buf + offs, nr_sectors * 512);
- CURRENT->nr_sectors -= nr_sectors;
- CURRENT->sector += nr_sectors;
- CURRENT->buffer += nr_sectors * 512;
- } else {
- mcd_buf_out = -1;
- break;
- }
- }
-}
-
-
-/*
- * We only seem to get interrupts after an error.
- * Just take the interrupt and clear out the status reg.
- */
-
-static irqreturn_t mcd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- int st;
-
- st = inb(MCDPORT(1)) & 0xFF;
- test1(printk("<int1-%02X>", st));
- if (!(st & MFL_STATUS)) {
- st = inb(MCDPORT(0)) & 0xFF;
- test1(printk("<int0-%02X>", st));
- if ((st & 0xFF) != 0xFF)
- mcd_error = st ? st & 0xFF : -1;
- }
- return IRQ_HANDLED;
-}
-
-
-static void do_mcd_request(request_queue_t * q)
-{
- test2(printk(" do_mcd_request(%ld+%ld)\n", CURRENT->sector,
- CURRENT->nr_sectors));
-
- mcd_transfer_is_active = 1;
- while (current_valid()) {
- mcd_transfer();
- if (CURRENT->nr_sectors == 0) {
- end_request(CURRENT, 1);
- } else {
- mcd_buf_out = -1; /* Want to read a block not in buffer */
- if (mcd_state == MCD_S_IDLE) {
- if (!tocUpToDate) {
- if (updateToc() < 0) {
- while (current_valid())
- end_request(CURRENT, 0);
- break;
- }
- }
- mcd_state = MCD_S_START;
- McdTries = 5;
- mcd_timer.function = mcd_poll;
- mod_timer(&mcd_timer, jiffies + 1);
- }
- break;
- }
- }
- mcd_transfer_is_active = 0;
- test2(printk(" do_mcd_request ends\n"));
-}
-
-
-
-static void mcd_poll(unsigned long dummy)
-{
- int st;
-
-
- if (mcd_error) {
- if (mcd_error & 0xA5) {
- printk(KERN_ERR "mcd: I/O error 0x%02x", mcd_error);
- if (mcd_error & 0x80)
- printk(" (Door open)");
- if (mcd_error & 0x20)
- printk(" (Disk changed)");
- if (mcd_error & 0x04) {
- printk(" (Read error)"); /* Bitch about the problem. */
-
- /* Time to get fancy! If at 2x speed and 1 error, drop to 1x speed! */
- /* Interesting how it STAYS at MCD_RETRY_ATTEMPTS on first error! */
- /* But I find that rather HANDY!!! */
- /* Neat! it REALLY WORKS on those LOW QUALITY CD's!!! Smile! :) */
- /* AJK [06/17/95] */
-
- /* Slap the CD down to single speed! */
- if (mcdDouble == 1
- && McdTries == MCD_RETRY_ATTEMPTS
- && MCMD_DATA_READ == MCMD_2X_READ) {
- MCMD_DATA_READ = MCMD_PLAY_READ; /* Uhhh, Ummmm, muhuh-huh! */
- mcd1xhold = SINGLE_HOLD_SECTORS; /* Hey Beavis! */
- printk(" Speed now 1x"); /* Pull my finger! */
- }
- }
- printk("\n");
- mcd_invalidate_buffers();
-#ifdef WARN_IF_READ_FAILURE
- if (McdTries == MCD_RETRY_ATTEMPTS)
- printk(KERN_ERR "mcd: read of block %d failed\n",
- mcd_next_bn);
-#endif
- if (!McdTries--) {
- /* Nuts! This cd is ready for recycling! */
- /* When WAS the last time YOU cleaned it CORRECTLY?! */
- printk(KERN_ERR "mcd: read of block %d failed, giving up\n",
- mcd_next_bn);
- if (mcd_transfer_is_active) {
- McdTries = 0;
- goto ret;
- }
- if (current_valid())
- end_request(CURRENT, 0);
- McdTries = MCD_RETRY_ATTEMPTS;
- }
- }
- mcd_error = 0;
- mcd_state = MCD_S_STOP;
- }
- /* Switch back to Double speed if enough GOOD sectors were read! */
-
- /* Are we a double speed with a crappy CD?! */
- if (mcdDouble == 1 && McdTries == MCD_RETRY_ATTEMPTS
- && MCMD_DATA_READ == MCMD_PLAY_READ) {
- /* We ARE a double speed and we ARE bitching! */
- if (mcd1xhold == 0) { /* Okay, Like are we STILL at single speed? *//* We need to switch back to double speed now... */
- MCMD_DATA_READ = MCMD_2X_READ; /* Uhhh... BACK You GO! */
- printk(KERN_INFO "mcd: Switching back to 2X speed!\n"); /* Tell 'em! */
- } else
- mcd1xhold--; /* No?! Count down the good reads some more... */
- /* and try, try again! */
- }
-
-immediately:
- switch (mcd_state) {
- case MCD_S_IDLE:
- test3(printk("MCD_S_IDLE\n"));
- goto out;
-
- case MCD_S_START:
- test3(printk("MCD_S_START\n"));
- outb(MCMD_GET_STATUS, MCDPORT(0));
- mcd_state = mcd_mode == 1 ? MCD_S_READ : MCD_S_MODE;
- McdTimeout = 3000;
- break;
-
- case MCD_S_MODE:
- test3(printk("MCD_S_MODE\n"));
- if ((st = mcdStatus()) != -1) {
- if (st & MST_DSK_CHG) {
- mcdDiskChanged = 1;
- tocUpToDate = 0;
- mcd_invalidate_buffers();
- }
-
-set_mode_immediately:
- if ((st & MST_DOOR_OPEN) || !(st & MST_READY)) {
- mcdDiskChanged = 1;
- tocUpToDate = 0;
- if (mcd_transfer_is_active) {
- mcd_state = MCD_S_START;
- goto immediately;
- }
- printk(KERN_INFO);
- printk((st & MST_DOOR_OPEN) ?
- "mcd: door open\n" :
- "mcd: disk removed\n");
- mcd_state = MCD_S_IDLE;
- while (current_valid())
- end_request(CURRENT, 0);
- goto out;
- }
- outb(MCMD_SET_MODE, MCDPORT(0));
- outb(1, MCDPORT(0));
- mcd_mode = 1;
- mcd_state = MCD_S_READ;
- McdTimeout = 3000;
- }
- break;
-
- case MCD_S_READ:
- test3(printk("MCD_S_READ\n"));
- if ((st = mcdStatus()) != -1) {
- if (st & MST_DSK_CHG) {
- mcdDiskChanged = 1;
- tocUpToDate = 0;
- mcd_invalidate_buffers();
- }
-
-read_immediately:
- if ((st & MST_DOOR_OPEN) || !(st & MST_READY)) {
- mcdDiskChanged = 1;
- tocUpToDate = 0;
- if (mcd_transfer_is_active) {
- mcd_state = MCD_S_START;
- goto immediately;
- }
- printk(KERN_INFO);
- printk((st & MST_DOOR_OPEN) ?
- "mcd: door open\n" :
- "mcd: disk removed\n");
- mcd_state = MCD_S_IDLE;
- while (current_valid())
- end_request(CURRENT, 0);
- goto out;
- }
-
- if (current_valid()) {
- struct mcd_Play_msf msf;
- mcd_next_bn = CURRENT->sector / 4;
- hsg2msf(mcd_next_bn, &msf.start);
- msf.end.min = ~0;
- msf.end.sec = ~0;
- msf.end.frame = ~0;
- sendMcdCmd(MCMD_DATA_READ, &msf);
- mcd_state = MCD_S_DATA;
- McdTimeout = READ_TIMEOUT;
- } else {
- mcd_state = MCD_S_STOP;
- goto immediately;
- }
-
- }
- break;
-
- case MCD_S_DATA:
- test3(printk("MCD_S_DATA\n"));
- st = inb(MCDPORT(1)) & (MFL_STATUSorDATA);
-data_immediately:
- test5(printk("Status %02x\n", st))
- switch (st) {
- case MFL_DATA:
-#ifdef WARN_IF_READ_FAILURE
- if (McdTries == 5)
- printk(KERN_WARNING "mcd: read of block %d failed\n",
- mcd_next_bn);
-#endif
- if (!McdTries--) {
- printk(KERN_ERR "mcd: read of block %d failed, giving up\n", mcd_next_bn);
- if (mcd_transfer_is_active) {
- McdTries = 0;
- break;
- }
- if (current_valid())
- end_request(CURRENT, 0);
- McdTries = 5;
- }
- mcd_state = MCD_S_START;
- McdTimeout = READ_TIMEOUT;
- goto immediately;
-
- case MFL_STATUSorDATA:
- break;
-
- default:
- McdTries = 5;
- if (!current_valid() && mcd_buf_in == mcd_buf_out) {
- mcd_state = MCD_S_STOP;
- goto immediately;
- }
- mcd_buf_bn[mcd_buf_in] = -1;
- insb(MCDPORT(0), mcd_buf + 2048 * mcd_buf_in,
- 2048);
- mcd_buf_bn[mcd_buf_in] = mcd_next_bn++;
- if (mcd_buf_out == -1)
- mcd_buf_out = mcd_buf_in;
- mcd_buf_in = mcd_buf_in + 1 == MCD_BUF_SIZ ? 0 : mcd_buf_in + 1;
- if (!mcd_transfer_is_active) {
- while (current_valid()) {
- mcd_transfer();
- if (CURRENT->nr_sectors == 0)
- end_request(CURRENT, 1);
- else
- break;
- }
- }
-
- if (current_valid()
- && (CURRENT->sector / 4 < mcd_next_bn ||
- CURRENT->sector / 4 > mcd_next_bn + 16)) {
- mcd_state = MCD_S_STOP;
- goto immediately;
- }
- McdTimeout = READ_TIMEOUT;
- {
- int count = QUICK_LOOP_COUNT;
- while (count--) {
- QUICK_LOOP_DELAY;
- if ((st = (inb(MCDPORT(1))) & (MFL_STATUSorDATA)) != (MFL_STATUSorDATA)) {
- test4(printk(" %d ", QUICK_LOOP_COUNT - count));
- goto data_immediately;
- }
- }
- test4(printk("ended "));
- }
- break;
- }
- break;
-
- case MCD_S_STOP:
- test3(printk("MCD_S_STOP\n"));
- if (!mitsumi_bug_93_wait)
- goto do_not_work_around_mitsumi_bug_93_1;
-
- McdTimeout = mitsumi_bug_93_wait;
- mcd_state = 9 + 3 + 1;
- break;
-
- case 9 + 3 + 1:
- if (McdTimeout)
- break;
-
-do_not_work_around_mitsumi_bug_93_1:
- outb(MCMD_STOP, MCDPORT(0));
- if ((inb(MCDPORT(1)) & MFL_STATUSorDATA) == MFL_STATUS) {
- int i = 4096;
- do {
- inb(MCDPORT(0));
- } while ((inb(MCDPORT(1)) & MFL_STATUSorDATA) == MFL_STATUS && --i);
- outb(MCMD_STOP, MCDPORT(0));
- if ((inb(MCDPORT(1)) & MFL_STATUSorDATA) == MFL_STATUS) {
- i = 4096;
- do {
- inb(MCDPORT(0));
- } while ((inb(MCDPORT(1)) & MFL_STATUSorDATA) == MFL_STATUS && --i);
- outb(MCMD_STOP, MCDPORT(0));
- }
- }
-
- mcd_state = MCD_S_STOPPING;
- McdTimeout = 1000;
- break;
-
- case MCD_S_STOPPING:
- test3(printk("MCD_S_STOPPING\n"));
- if ((st = mcdStatus()) == -1 && McdTimeout)
- break;
-
- if ((st != -1) && (st & MST_DSK_CHG)) {
- mcdDiskChanged = 1;
- tocUpToDate = 0;
- mcd_invalidate_buffers();
- }
- if (!mitsumi_bug_93_wait)
- goto do_not_work_around_mitsumi_bug_93_2;
-
- McdTimeout = mitsumi_bug_93_wait;
- mcd_state = 9 + 3 + 2;
- break;
-
- case 9 + 3 + 2:
- if (McdTimeout)
- break;
- st = -1;
-
-do_not_work_around_mitsumi_bug_93_2:
- test3(printk("CURRENT_VALID %d mcd_mode %d\n", current_valid(),
- mcd_mode));
- if (current_valid()) {
- if (st != -1) {
- if (mcd_mode == 1)
- goto read_immediately;
- else
- goto set_mode_immediately;
- } else {
- mcd_state = MCD_S_START;
- McdTimeout = 1;
- }
- } else {
- mcd_state = MCD_S_IDLE;
- goto out;
- }
- break;
- default:
- printk(KERN_ERR "mcd: invalid state %d\n", mcd_state);
- goto out;
- }
-ret:
- if (!McdTimeout--) {
- printk(KERN_WARNING "mcd: timeout in state %d\n", mcd_state);
- mcd_state = MCD_S_STOP;
- }
- mcd_timer.function = mcd_poll;
- mod_timer(&mcd_timer, jiffies + 1);
-out:
- return;
-}
-
-static void mcd_invalidate_buffers(void)
-{
- int i;
- for (i = 0; i < MCD_BUF_SIZ; ++i)
- mcd_buf_bn[i] = -1;
- mcd_buf_out = -1;
-}
-
-/*
- * Open the device special file. Check that a disk is in.
- */
-static int mcd_open(struct cdrom_device_info *cdi, int purpose)
-{
- int st, count = 0;
- if (mcdPresent == 0)
- return -ENXIO; /* no hardware */
-
- if (mcd_open_count || mcd_state != MCD_S_IDLE)
- goto bump_count;
-
- mcd_invalidate_buffers();
- do {
- st = statusCmd(); /* check drive status */
- if (st == -1)
- goto err_out; /* drive doesn't respond */
- if ((st & MST_READY) == 0) /* no disk? wait a sec... */
- msleep(1000);
-
- } while (((st & MST_READY) == 0) && count++ < MCD_RETRY_ATTEMPTS);
-
- if (updateToc() < 0)
- goto err_out;
-
-bump_count:
- ++mcd_open_count;
- return 0;
-
-err_out:
- return -EIO;
-}
-
-
-/*
- * On close, we flush all mcd blocks from the buffer cache.
- */
-static void mcd_release(struct cdrom_device_info *cdi)
-{
- if (!--mcd_open_count) {
- mcd_invalidate_buffers();
- }
-}
-
-/*
- * Test for presence of drive and initialize it. Called at boot time.
- */
-
-int __init mcd_init(void)
-{
- struct gendisk *disk = alloc_disk(1);
- int count;
- unsigned char result[3];
- char msg[80];
-
- if (!disk) {
- printk(KERN_INFO "mcd: can't allocated disk.\n");
- return -ENOMEM;
- }
- if (mcd_port <= 0 || mcd_irq <= 0) {
- printk(KERN_INFO "mcd: not probing.\n");
- put_disk(disk);
- return -EIO;
- }
- if (register_blkdev(MAJOR_NR, "mcd")) {
- put_disk(disk);
- return -EIO;
- }
- if (!request_region(mcd_port, 4, "mcd")) {
- printk(KERN_ERR "mcd: Initialization failed, I/O port (%X) already in use\n", mcd_port);
- goto out_region;
- }
-
- mcd_queue = blk_init_queue(do_mcd_request, &mcd_spinlock);
- if (!mcd_queue)
- goto out_queue;
-
- /* check for card */
-
- outb(0, MCDPORT(1)); /* send reset */
- for (count = 0; count < 2000000; count++)
- (void) inb(MCDPORT(1)); /* delay a bit */
-
- outb(0x40, MCDPORT(0)); /* send get-stat cmd */
- for (count = 0; count < 2000000; count++)
- if (!(inb(MCDPORT(1)) & MFL_STATUS))
- break;
-
- if (count >= 2000000) {
- printk(KERN_INFO "mcd: initialisation failed - No mcd device at 0x%x irq %d\n",
- mcd_port, mcd_irq);
- goto out_probe;
- }
- count = inb(MCDPORT(0)); /* pick up the status */
-
- outb(MCMD_GET_VERSION, MCDPORT(0));
- for (count = 0; count < 3; count++)
- if (getValue(result + count)) {
- printk(KERN_ERR "mcd: mitsumi get version failed at 0x%x\n",
- mcd_port);
- goto out_probe;
- }
-
- if (result[0] == result[1] && result[1] == result[2])
- goto out_probe;
-
- mcdVersion = result[2];
-
- if (mcdVersion >= 4)
- outb(4, MCDPORT(2)); /* magic happens */
-
- /* don't get the IRQ until we know for sure the drive is there */
-
- if (request_irq(mcd_irq, mcd_interrupt, SA_INTERRUPT, "Mitsumi CD", NULL)) {
- printk(KERN_ERR "mcd: Unable to get IRQ%d for Mitsumi CD-ROM\n", mcd_irq);
- goto out_probe;
- }
-
- if (result[1] == 'D') {
- MCMD_DATA_READ = MCMD_2X_READ;
- /* Added flag to drop to 1x speed if too many errors */
- mcdDouble = 1;
- } else
- mcd_info.speed = 1;
- sprintf(msg, " mcd: Mitsumi %s Speed CD-ROM at port=0x%x,"
- " irq=%d\n", mcd_info.speed == 1 ? "Single" : "Double",
- mcd_port, mcd_irq);
-
- outb(MCMD_CONFIG_DRIVE, MCDPORT(0));
- outb(0x02, MCDPORT(0));
- outb(0x00, MCDPORT(0));
- getValue(result);
-
- outb(MCMD_CONFIG_DRIVE, MCDPORT(0));
- outb(0x10, MCDPORT(0));
- outb(0x04, MCDPORT(0));
- getValue(result);
-
- mcd_invalidate_buffers();
- mcdPresent = 1;
-
- disk->major = MAJOR_NR;
- disk->first_minor = 0;
- sprintf(disk->disk_name, "mcd");
- disk->fops = &mcd_bdops;
- disk->flags = GENHD_FL_CD;
- mcd_gendisk = disk;
-
- if (register_cdrom(&mcd_info) != 0) {
- printk(KERN_ERR "mcd: Unable to register Mitsumi CD-ROM.\n");
- goto out_cdrom;
- }
- disk->queue = mcd_queue;
- add_disk(disk);
- printk(msg);
- return 0;
-
-out_cdrom:
- free_irq(mcd_irq, NULL);
-out_queue:
- release_region(mcd_port, 4);
-out_probe:
- blk_cleanup_queue(mcd_queue);
-out_region:
- unregister_blkdev(MAJOR_NR, "mcd");
- put_disk(disk);
- return -EIO;
-}
-
-
-static void hsg2msf(long hsg, struct msf *msf)
-{
- hsg += 150;
- msf->min = hsg / 4500;
- hsg %= 4500;
- msf->sec = hsg / 75;
- msf->frame = hsg % 75;
-
- bin2bcd(&msf->min); /* convert to BCD */
- bin2bcd(&msf->sec);
- bin2bcd(&msf->frame);
-}
-
-
-static void bin2bcd(unsigned char *p)
-{
- int u, t;
-
- u = *p % 10;
- t = *p / 10;
- *p = u | (t << 4);
-}
-
-static int bcd2bin(unsigned char bcd)
-{
- return (bcd >> 4) * 10 + (bcd & 0xF);
-}
-
-
-/*
- * See if a status is ready from the drive and return it
- * if it is ready.
- */
-
-static int mcdStatus(void)
-{
- int i;
- int st;
-
- st = inb(MCDPORT(1)) & MFL_STATUS;
- if (!st) {
- i = inb(MCDPORT(0)) & 0xFF;
- return i;
- } else
- return -1;
-}
-
-
-/*
- * Send a play or read command to the drive
- */
-
-static void sendMcdCmd(int cmd, struct mcd_Play_msf *params)
-{
- outb(cmd, MCDPORT(0));
- outb(params->start.min, MCDPORT(0));
- outb(params->start.sec, MCDPORT(0));
- outb(params->start.frame, MCDPORT(0));
- outb(params->end.min, MCDPORT(0));
- outb(params->end.sec, MCDPORT(0));
- outb(params->end.frame, MCDPORT(0));
-}
-
-
-/*
- * Timer interrupt routine to test for status ready from the drive.
- * (see the next routine)
- */
-
-static void mcdStatTimer(unsigned long dummy)
-{
- if (!(inb(MCDPORT(1)) & MFL_STATUS)) {
- wake_up(&mcd_waitq);
- return;
- }
-
- McdTimeout--;
- if (McdTimeout <= 0) {
- wake_up(&mcd_waitq);
- return;
- }
- mcd_timer.function = mcdStatTimer;
- mod_timer(&mcd_timer, jiffies + 1);
-}
-
-
-/*
- * Wait for a status to be returned from the drive. The actual test
- * (see routine above) is done by the timer interrupt to avoid
- * excessive rescheduling.
- */
-
-static int getMcdStatus(int timeout)
-{
- int st;
-
- McdTimeout = timeout;
- mcd_timer.function = mcdStatTimer;
- mod_timer(&mcd_timer, jiffies + 1);
- sleep_on(&mcd_waitq);
- if (McdTimeout <= 0)
- return -1;
-
- st = inb(MCDPORT(0)) & 0xFF;
- if (st == 0xFF)
- return -1;
-
- if ((st & MST_BUSY) == 0 && audioStatus == CDROM_AUDIO_PLAY)
- /* XXX might be an error? look at q-channel? */
- audioStatus = CDROM_AUDIO_COMPLETED;
-
- if (st & MST_DSK_CHG) {
- mcdDiskChanged = 1;
- tocUpToDate = 0;
- audioStatus = CDROM_AUDIO_NO_STATUS;
- }
-
- return st;
-}
-
-
-/* gives current state of the drive This function is quite unreliable,
- and should probably be rewritten by someone, eventually... */
-
-int mcd_drive_status(struct cdrom_device_info *cdi, int slot_nr)
-{
- int st;
-
- st = statusCmd(); /* check drive status */
- if (st == -1)
- return -EIO; /* drive doesn't respond */
- if ((st & MST_READY))
- return CDS_DISC_OK;
- if ((st & MST_DOOR_OPEN))
- return CDS_TRAY_OPEN;
- if ((st & MST_DSK_CHG))
- return CDS_NO_DISC;
- if ((st & MST_BUSY))
- return CDS_DRIVE_NOT_READY;
- return -EIO;
-}
-
-
-/*
- * Read a value from the drive.
- */
-
-static int getValue(unsigned char *result)
-{
- int count;
- int s;
-
- for (count = 0; count < 2000; count++)
- if (!(inb(MCDPORT(1)) & MFL_STATUS))
- break;
-
- if (count >= 2000) {
- printk("mcd: getValue timeout\n");
- return -1;
- }
-
- s = inb(MCDPORT(0)) & 0xFF;
- *result = (unsigned char) s;
- return 0;
-}
-
-/*
- * Read the current Q-channel info. Also used for reading the
- * table of contents.
- */
-
-int GetQChannelInfo(struct mcd_Toc *qp)
-{
- unsigned char notUsed;
- int retry;
-
- for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++) {
- outb(MCMD_GET_Q_CHANNEL, MCDPORT(0));
- if (getMcdStatus(MCD_STATUS_DELAY) != -1)
- break;
- }
-
- if (retry >= MCD_RETRY_ATTEMPTS)
- return -1;
-
- if (getValue(&qp->ctrl_addr) < 0)
- return -1;
- if (getValue(&qp->track) < 0)
- return -1;
- if (getValue(&qp->pointIndex) < 0)
- return -1;
- if (getValue(&qp->trackTime.min) < 0)
- return -1;
- if (getValue(&qp->trackTime.sec) < 0)
- return -1;
- if (getValue(&qp->trackTime.frame) < 0)
- return -1;
- if (getValue(¬Used) < 0)
- return -1;
- if (getValue(&qp->diskTime.min) < 0)
- return -1;
- if (getValue(&qp->diskTime.sec) < 0)
- return -1;
- if (getValue(&qp->diskTime.frame) < 0)
- return -1;
-
- return 0;
-}
-
-/*
- * Read the table of contents (TOC) and TOC header if necessary
- */
-
-static int updateToc(void)
-{
- if (tocUpToDate)
- return 0;
-
- if (GetDiskInfo() < 0)
- return -EIO;
-
- if (GetToc() < 0)
- return -EIO;
-
- tocUpToDate = 1;
- return 0;
-}
-
-/*
- * Read the table of contents header
- */
-
-static int GetDiskInfo(void)
-{
- int retry;
-
- for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++) {
- outb(MCMD_GET_DISK_INFO, MCDPORT(0));
- if (getMcdStatus(MCD_STATUS_DELAY) != -1)
- break;
- }
-
- if (retry >= MCD_RETRY_ATTEMPTS)
- return -1;
-
- if (getValue(&DiskInfo.first) < 0)
- return -1;
- if (getValue(&DiskInfo.last) < 0)
- return -1;
-
- DiskInfo.first = bcd2bin(DiskInfo.first);
- DiskInfo.last = bcd2bin(DiskInfo.last);
-
-#ifdef MCD_DEBUG
- printk
- ("Disk Info: first %d last %d length %02x:%02x.%02x first %02x:%02x.%02x\n",
- DiskInfo.first, DiskInfo.last, DiskInfo.diskLength.min,
- DiskInfo.diskLength.sec, DiskInfo.diskLength.frame,
- DiskInfo.firstTrack.min, DiskInfo.firstTrack.sec,
- DiskInfo.firstTrack.frame);
-#endif
-
- if (getValue(&DiskInfo.diskLength.min) < 0)
- return -1;
- if (getValue(&DiskInfo.diskLength.sec) < 0)
- return -1;
- if (getValue(&DiskInfo.diskLength.frame) < 0)
- return -1;
- if (getValue(&DiskInfo.firstTrack.min) < 0)
- return -1;
- if (getValue(&DiskInfo.firstTrack.sec) < 0)
- return -1;
- if (getValue(&DiskInfo.firstTrack.frame) < 0)
- return -1;
-
- return 0;
-}
-
-/*
- * Read the table of contents (TOC)
- */
-
-static int GetToc(void)
-{
- int i, px;
- int limit;
- int retry;
- struct mcd_Toc qInfo;
-
- for (i = 0; i < MAX_TRACKS; i++)
- Toc[i].pointIndex = 0;
-
- i = DiskInfo.last + 3;
-
- for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++) {
- outb(MCMD_STOP, MCDPORT(0));
- if (getMcdStatus(MCD_STATUS_DELAY) != -1)
- break;
- }
-
- if (retry >= MCD_RETRY_ATTEMPTS)
- return -1;
-
- for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++) {
- outb(MCMD_SET_MODE, MCDPORT(0));
- outb(0x05, MCDPORT(0)); /* mode: toc */
- mcd_mode = 0x05;
- if (getMcdStatus(MCD_STATUS_DELAY) != -1)
- break;
- }
-
- if (retry >= MCD_RETRY_ATTEMPTS)
- return -1;
-
- for (limit = 300; limit > 0; limit--) {
- if (GetQChannelInfo(&qInfo) < 0)
- break;
-
- px = bcd2bin(qInfo.pointIndex);
- if (px > 0 && px < MAX_TRACKS && qInfo.track == 0)
- if (Toc[px].pointIndex == 0) {
- Toc[px] = qInfo;
- i--;
- }
-
- if (i <= 0)
- break;
- }
-
- Toc[DiskInfo.last + 1].diskTime = DiskInfo.diskLength;
-
- for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++) {
- outb(MCMD_SET_MODE, MCDPORT(0));
- outb(0x01, MCDPORT(0));
- mcd_mode = 1;
- if (getMcdStatus(MCD_STATUS_DELAY) != -1)
- break;
- }
-
-#ifdef MCD_DEBUG
- for (i = 1; i <= DiskInfo.last; i++)
- printk
- ("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X %02X:%02X.%02X\n",
- i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex,
- Toc[i].trackTime.min, Toc[i].trackTime.sec,
- Toc[i].trackTime.frame, Toc[i].diskTime.min,
- Toc[i].diskTime.sec, Toc[i].diskTime.frame);
- for (i = 100; i < 103; i++)
- printk
- ("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X %02X:%02X.%02X\n",
- i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex,
- Toc[i].trackTime.min, Toc[i].trackTime.sec,
- Toc[i].trackTime.frame, Toc[i].diskTime.min,
- Toc[i].diskTime.sec, Toc[i].diskTime.frame);
-#endif
-
- return limit > 0 ? 0 : -1;
-}
-
-void __exit mcd_exit(void)
-{
- del_gendisk(mcd_gendisk);
- put_disk(mcd_gendisk);
- if (unregister_cdrom(&mcd_info)) {
- printk(KERN_WARNING "Can't unregister cdrom mcd\n");
- return;
- }
- free_irq(mcd_irq, NULL);
- release_region(mcd_port, 4);
- if (unregister_blkdev(MAJOR_NR, "mcd")) {
- printk(KERN_WARNING "Can't unregister major mcd\n");
- return;
- }
- blk_cleanup_queue(mcd_queue);
- del_timer_sync(&mcd_timer);
-}
-
-#ifdef MODULE
-module_init(mcd_init);
-#endif
-module_exit(mcd_exit);
-
-MODULE_AUTHOR("Martin Harriss");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_BLOCKDEV_MAJOR(MITSUMI_CDROM_MAJOR);
reply other threads:[~2005-03-15 12:18 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20050315121611.GD3189@stusta.de \
--to=bunk@stusta.de \
--cc=akpm@osdl.org \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.