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

📄 sonycd535.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * Sony CDU-535 interface device driver * * This is a modified version of the CDU-31A device driver (see below). * Changes were made using documentation for the CDU-531 (which Sony * assures me is very similar to the 535) and partial disassembly of the * DOS driver.  I used Minyard's driver and replaced the CDU-31A * commands with the CDU-531 commands.  This was complicated by a different * interface protocol with the drive.  The driver is still polled. * * Data transfer rate is about 110 Kb/sec, theoretical maximum is 150 Kb/sec. * I tried polling without the sony_sleep during the data transfers but * it did not speed things up any. * * 1993-05-23 (rgj) changed the major number to 21 to get rid of conflict * with CDU-31A driver.  This is the also the number from the Linux * Device Driver Registry for the Sony Drive.  Hope nobody else is using it. * * 1993-08-29 (rgj) remove the configuring of the interface board address * from the top level configuration, you have to modify it in this file. * * 1995-01-26 Made module-capable (Joel Katz <Stimpson@Panix.COM>) * * 1995-05-20 *  Modified to support CDU-510/515 series *      (Claudio Porfiri<C.Porfiri@nisms.tei.ericsson.se>) *  Fixed to report verify_area() failures *      (Heiko Eissfeldt <heiko@colossus.escape.de>) * * 1995-06-01 *  More changes to support CDU-510/515 series *      (Claudio Porfiri<C.Porfiri@nisms.tei.ericsson.se>) * * 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> * * Things to do: *  - handle errors and status better, put everything into a single word *  - use interrupts (code mostly there, but a big hole still missing) *  - handle multi-session CDs? *  - use DMA? * *  Known Bugs: *  - * *   Ken Pizzini (ken@halcyon.com) * * Original by: *   Ron Jeppesen (ronj.an@site007.saic.com) * * *------------------------------------------------------------------------ * Sony CDROM interface device driver. * * Corey Minyard (minyard@wf-rch.cirr.com) (CDU-535 complaints to Ken above) * * Colossians 3:17 * * The Sony interface device driver handles Sony interface CDROM * drives and provides a complete block-level interface as well as an * ioctl() interface compatible with the Sun (as specified in * include/linux/cdrom.h).  With this interface, CDROMs can be * accessed and standard audio CDs can be played back normally. * * This interface is (unfortunately) a polled interface.  This is * because most Sony interfaces are set up with DMA and interrupts * disables.  Some (like mine) do not even have the capability to * handle interrupts or DMA.  For this reason you will see a bit of * the following: * *   snap = jiffies; *   while (jiffies-snap < SONY_JIFFIES_TIMEOUT) *   { *		if (some_condition()) *         break; *      sony_sleep(); *   } *   if (some_condition not met) *   { *      return an_error; *   } * * This ugly hack waits for something to happen, sleeping a little * between every try.  (The conditional is written so that jiffies * wrap-around is handled properly.) * * One thing about these drives: They talk in MSF (Minute Second Frame) format. * There are 75 frames a second, 60 seconds a minute, and up to 75 minutes on a * disk.  The funny thing is that these are sent to the drive in BCD, but the * interface wants to see them in decimal.  A lot of conversion goes on. * *  Copyright (C) 1993  Corey Minyard * *  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. * */# include <linux/module.h>#include <linux/errno.h>#include <linux/signal.h>#include <linux/sched.h>#include <linux/timer.h>#include <linux/fs.h>#include <linux/kernel.h>#include <linux/ioport.h>#include <linux/hdreg.h>#include <linux/genhd.h>#include <linux/mm.h>#include <linux/slab.h>#include <linux/init.h>#include <linux/devfs_fs_kernel.h>#define REALLY_SLOW_IO#include <asm/system.h>#include <asm/io.h>#include <asm/uaccess.h>#include <linux/cdrom.h>#define MAJOR_NR CDU535_CDROM_MAJOR# include <linux/blk.h>#define sony535_cd_base_io sonycd535 /* for compatible parameter passing with "insmod" */#include "sonycd535.h"/* * this is the base address of the interface card for the Sony CDU-535 * CDROM drive.  If your jumpers are set for an address other than * this one (the default), change the following line to the * proper address. */#ifndef CDU535_ADDRESS# define CDU535_ADDRESS			0x340#endif#ifndef CDU535_INTERRUPT# define CDU535_INTERRUPT		0#endif#ifndef CDU535_HANDLE# define CDU535_HANDLE			"cdu535"#endif#ifndef CDU535_MESSAGE_NAME# define CDU535_MESSAGE_NAME	"Sony CDU-535"#endif#define CDU535_BLOCK_SIZE	2048  #ifndef MAX_SPINUP_RETRY# define MAX_SPINUP_RETRY		3	/* 1 is sufficient for most drives... */#endif#ifndef RETRY_FOR_BAD_STATUS# define RETRY_FOR_BAD_STATUS	100	/* in 10th of second */#endif#ifndef DEBUG# define DEBUG	1#endif/* *  SONY535_BUFFER_SIZE determines the size of internal buffer used *  by the drive.  It must be at least 2K and the larger the buffer *  the better the transfer rate.  It does however take system memory. *  On my system I get the following transfer rates using dd to read *  10 Mb off /dev/cdrom. * *    8K buffer      43 Kb/sec *   16K buffer      66 Kb/sec *   32K buffer      91 Kb/sec *   64K buffer     111 Kb/sec *  128K buffer     123 Kb/sec *  512K buffer     123 Kb/sec */#define SONY535_BUFFER_SIZE	(64*1024)/* *  if LOCK_DOORS is defined then the eject button is disabled while * the device is open. */#ifndef NO_LOCK_DOORS# define LOCK_DOORS#endifstatic int read_subcode(void);static void sony_get_toc(void);static int cdu_open(struct inode *inode, struct file *filp);static inline unsigned int int_to_bcd(unsigned int val);static unsigned int bcd_to_int(unsigned int bcd);static int do_sony_cmd(Byte * cmd, int nCmd, Byte status[2],					   Byte * response, int n_response, int ignoreStatusBit7);/* The base I/O address of the Sony Interface.  This is a variable (not a   #define) so it can be easily changed via some future ioctl() */static unsigned int sony535_cd_base_io = CDU535_ADDRESS;MODULE_PARM(sony535_cd_base_io, "i");/* * The following are I/O addresses of the various registers for the drive.  The * comment for the base address also applies here. */static unsigned short select_unit_reg;static unsigned short result_reg;static unsigned short command_reg;static unsigned short read_status_reg;static unsigned short data_reg;static int initialized;			/* Has the drive been initialized? */static int sony_disc_changed = 1;	/* Has the disk been changed					   since the last check? */static int sony_toc_read;		/* Has the table of contents been					   read? */static unsigned int sony_buffer_size;	/* Size in bytes of the read-ahead					   buffer. */static unsigned int sony_buffer_sectors;	/* Size (in 2048 byte records) of						   the read-ahead buffer. */static unsigned int sony_usage;		/* How many processes have the					   drive open. */static int sony_first_block = -1;	/* First OS block (512 byte) in					   the read-ahead buffer */static int sony_last_block = -1;	/* Last OS block (512 byte) in					   the read-ahead buffer */static struct s535_sony_toc *sony_toc;	/* Points to the table of					   contents. */static struct s535_sony_subcode *last_sony_subcode;		/* Points to the last								   subcode address read */static Byte **sony_buffer;		/* Points to the pointers					   to the sector buffers */static int sony_inuse;			/* is the drive in use? Only one					   open at a time allowed *//* * The audio status uses the values from read subchannel data as specified * in include/linux/cdrom.h. */static int sony_audio_status = CDROM_AUDIO_NO_STATUS;/* * The following are a hack for pausing and resuming audio play.  The drive * does not work as I would expect it, if you stop it then start it again, * the drive seeks back to the beginning and starts over.  This holds the * position during a pause so a resume can restart it.  It uses the * audio status variable above to tell if it is paused. *   I just kept the CDU-31A driver behavior rather than using the PAUSE * command on the CDU-535. */static Byte cur_pos_msf[3];static Byte final_pos_msf[3];/* What IRQ is the drive using?  0 if none. */static int sony535_irq_used = CDU535_INTERRUPT;/* The interrupt handler will wake this queue up when it gets an interrupt. */static DECLARE_WAIT_QUEUE_HEAD(cdu535_irq_wait);/* * This routine returns 1 if the disk has been changed since the last * check or 0 if it hasn't.  Setting flag to 0 resets the changed flag. */static intcdu535_check_media_change(kdev_t full_dev){	int retval;	if (MINOR(full_dev) != 0) {		printk(CDU535_MESSAGE_NAME " request error: invalid device.\n");		return 0;	}	/* if driver is not initialized, always return 0 */	retval = initialized ? sony_disc_changed : 0;	sony_disc_changed = 0;	return retval;}static inline voidenable_interrupts(void){#ifdef USE_IRQ	/*	 * This code was taken from cdu31a.c; it will not	 * directly work for the cdu535 as written...	 */	curr_control_reg |= ( SONY_ATTN_INT_EN_BIT						| SONY_RES_RDY_INT_EN_BIT						| SONY_DATA_RDY_INT_EN_BIT);	outb(curr_control_reg, sony_cd_control_reg);#endif}static inline voiddisable_interrupts(void){#ifdef USE_IRQ	/*	 * This code was taken from cdu31a.c; it will not	 * directly work for the cdu535 as written...	 */	curr_control_reg &= ~(SONY_ATTN_INT_EN_BIT						| SONY_RES_RDY_INT_EN_BIT						| SONY_DATA_RDY_INT_EN_BIT);	outb(curr_control_reg, sony_cd_control_reg);#endif}static voidcdu535_interrupt(int irq, void *dev_id, struct pt_regs *regs){	disable_interrupts();	if (waitqueue_active(&cdu535_irq_wait))		wake_up(&cdu535_irq_wait);	else		printk(CDU535_MESSAGE_NAME				": Got an interrupt but nothing was waiting\n");}/* * Wait a little while. */static inline voidsony_sleep(void){	if (sony535_irq_used <= 0) {	/* poll */		current->state = TASK_INTERRUPTIBLE;		schedule_timeout(0);	} else {	/* Interrupt driven */		cli();		enable_interrupts();		interruptible_sleep_on(&cdu535_irq_wait);		sti();	}}/*------------------start of SONY CDU535 very specific ---------------------*//**************************************************************************** * void select_unit( int unit_no ) * *  Select the specified unit (0-3) so that subsequent commands reference it ****************************************************************************/static voidselect_unit(int unit_no){	unsigned int select_mask = ~(1 << unit_no);	outb(select_mask, select_unit_reg);}/*************************************************************************** * int read_result_reg( Byte *data_ptr ) * *  Read a result byte from the Sony CDU controller, store in location pointed * to by data_ptr.  Return zero on success, TIME_OUT if we did not receive * data. ***************************************************************************/static intread_result_reg(Byte *data_ptr){	unsigned long snap;	int read_status;	snap = jiffies;	while (jiffies-snap < SONY_JIFFIES_TIMEOUT) {		read_status = inb(read_status_reg);		if ((read_status & SONY535_RESULT_NOT_READY_BIT) == 0) {#if DEBUG > 1			printk(CDU535_MESSAGE_NAME					": read_result_reg(): readStatReg = 0x%x\n", read_status);#endif			*data_ptr = inb(result_reg);			return 0;		} else {			sony_sleep();		}	}	printk(CDU535_MESSAGE_NAME " read_result_reg: TIME OUT!\n");	return TIME_OUT;}/**************************************************************************** * int read_exec_status( Byte status[2] ) * *  Read the execution status of the last command and put into status. * Handles reading second status word if available.  Returns 0 on success, * TIME_OUT on failure. ****************************************************************************/static intread_exec_status(Byte status[2]){	status[1] = 0;	if (read_result_reg(&(status[0])) != 0)		return TIME_OUT;	if ((status[0] & 0x80) != 0) {	/* byte two follows */		if (read_result_reg(&(status[1])) != 0)			return TIME_OUT;	}#if DEBUG > 1	printk(CDU535_MESSAGE_NAME ": read_exec_status: read 0x%x 0x%x\n",			status[0], status[1]);#endif	return 0;}/**************************************************************************** * int check_drive_status( void ) * *  Check the current drive status.  Using this before executing a command * takes care of the problem of unsolicited drive status-2 messages. * Add a check of the audio status if we think the disk is playing. ****************************************************************************/static int

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -