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

📄 gscd.c

📁 powerpc内核 mpc8241芯片 linux系统下cdrom驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
#define GSCD_VERSION "0.4a Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de>"/*	linux/drivers/block/gscd.c - GoldStar R420 CDROM driver        Copyright (C) 1995  Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de>        based upon pre-works by   Eberhard Moenkeberg <emoenke@gwdg.de>                For all kind of other information about the GoldStar CDROM        and this Linux device driver I installed a WWW-URL:        http://linux.rz.fh-hannover.de/~raupach                     If you are the editor of a Linux CD, you should             enable gscd.c within your boot floppy kernel and             send me one of your CDs for free.        --------------------------------------------------------------------	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.*//* These settings are for various debug-level. Leave they untouched ... */ #define  NO_GSCD_DEBUG #define  NO_IOCTL_DEBUG#define  NO_MODULE_DEBUG#define  NO_FUTURE_WORK/*------------------------*/#include <linux/module.h>#include <linux/malloc.h>#include <linux/errno.h>#include <linux/signal.h>#include <linux/sched.h>#include <linux/timer.h>#include <linux/fs.h>#include <linux/mm.h>#include <linux/kernel.h>#include <linux/cdrom.h>#include <linux/ioport.h>#include <linux/major.h>#include <linux/string.h>#include <linux/init.h>#include <asm/system.h>#include <asm/io.h>#include <asm/uaccess.h>#define MAJOR_NR GOLDSTAR_CDROM_MAJOR#include <linux/blk.h>#define gscd_port gscd /* for compatible parameter passing with "insmod" */#include "gscd.h"static int gscd_blocksizes[1] = {512};static int gscdPresent            = 0;static unsigned char gscd_buf[2048];    /* buffer for block size conversion */static int   gscd_bn              = -1;static short gscd_port            = GSCD_BASE_ADDR;MODULE_PARM(gscd, "h");/* Kommt spaeter vielleicht noch mal dran ... *    static struct wait_queue *gscd_waitq = NULL; */ static void gscd_transfer         (void);static void gscd_read_cmd         (void);static void gscd_hsg2msf          (long hsg, struct msf *msf);static void gscd_bin2bcd          (unsigned char *p);/* Schnittstellen zum Kern/FS */static void do_gscd_request       (void);static int  gscd_ioctl            (struct inode *, struct file *, unsigned int, unsigned long);static int  gscd_open             (struct inode *, struct file *);static int  gscd_release          (struct inode *, struct file *);static int  check_gscd_med_chg    (kdev_t);/*      GoldStar Funktionen    */static void cc_Reset             (void);static int  wait_drv_ready       (void);static int  find_drives          (void);static void cmd_out              (int, char *, char *, int);static void cmd_status           (void);static void cc_Ident             (char *);static void cc_SetSpeed          (void);static void init_cd_drive        (int);static int  get_status           (void);static void clear_Audio          (void);static void cc_invalidate        (void);/* some things for the next version */#ifdef FUTURE_WORKstatic void update_state          (void);static long gscd_msf2hsg          (struct msf *mp);static int  gscd_bcd2bin          (unsigned char bcd);#endif/*    common GoldStar Initialization    */static int my_gscd_init (void);/*      lo-level cmd-Funktionen    */static void cmd_info_in          ( char *, int );static void cmd_end              ( void );static void cmd_read_b           ( char *, int, int );static void cmd_read_w           ( char *, int, int );static int  cmd_unit_alive       ( void );static void cmd_write_cmd        ( char * );/*      GoldStar Variablen     */static int  curr_drv_state;static int  drv_states[]       = {0,0,0,0,0,0,0,0};static int  drv_mode;static int  disk_state;static int  speed;static int  ndrives;static unsigned char drv_num_read;static unsigned char f_dsk_valid;static unsigned char current_drive;static unsigned char f_drv_ok;static char f_AudioPlay;static char f_AudioPause;static int  AudioStart_m;static int  AudioStart_f;static int  AudioEnd_m;static int  AudioEnd_f; static struct file_operations gscd_fops = {	NULL,			/* lseek - default */	block_read,		/* read - general block-dev read */	block_write,		/* write - general block-dev write */	NULL,			/* readdir - bad */	NULL,			/* poll */	gscd_ioctl,		/* ioctl */	NULL,			/* mmap */	gscd_open,		/* open */	NULL,			/* flush */	gscd_release,		/* release */	NULL,                   /* fsync */	NULL,                   /* fasync*/	check_gscd_med_chg,     /* media change */	NULL                    /* revalidate */};/*  * Checking if the media has been changed * (not yet implemented) */static int check_gscd_med_chg (kdev_t full_dev){   int target;   target = MINOR(full_dev);   if (target > 0)    {      printk("GSCD: GoldStar CD-ROM request error: invalid device.\n");      return 0;   }   #ifdef GSCD_DEBUG   printk ("gscd: check_med_change\n");   #endif   return 0;}__initfunc(void gscd_setup (char *str, int *ints)){  if (ints[0] > 0)   {     gscd_port = ints[1];  }}static int gscd_ioctl (struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg){unsigned char to_do[10];unsigned char dummy;                                 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 CDROMRESUME:   /* keine Ahnung was das ist */            return 0;       case CDROMEJECT:            cmd_status ();            to_do[0] = CMD_TRAY_CTL;            cmd_out (TYPE_INFO, (char *)&to_do, (char *)&dummy, 0);            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 gscd_transfer (void){long offs;	while (CURRENT -> nr_sectors > 0 && gscd_bn == CURRENT -> sector / 4)	{		offs = (CURRENT -> sector & 3) * 512;		memcpy(CURRENT -> buffer, gscd_buf + offs, 512);		CURRENT -> nr_sectors--;		CURRENT -> sector++;		CURRENT -> buffer += 512;	}}/* * I/O request routine called from Linux kernel. */static void do_gscd_request (void){unsigned int block,dev;unsigned int nsect;repeat:	if (!(CURRENT) || CURRENT->rq_status == RQ_INACTIVE) return;	INIT_REQUEST;	dev = MINOR(CURRENT->rq_dev);	block = CURRENT->sector;	nsect = CURRENT->nr_sectors;	if (CURRENT == NULL || CURRENT -> sector == -1)		return;	if (CURRENT -> cmd != READ)	{		printk("GSCD: bad cmd %d\n", CURRENT -> cmd);		end_request(0);		goto repeat;	}	if (MINOR(CURRENT -> rq_dev) != 0)	{		printk("GSCD: this version supports only one device\n");		end_request(0);		goto repeat;	}	gscd_transfer();	/* if we satisfied the request from the buffer, we're done. */	if (CURRENT -> nr_sectors == 0)	{		end_request(1);		goto repeat;	}#ifdef GSCD_DEBUG        printk ("GSCD: dev %d, block %d, nsect %d\n", dev, block, nsect );#endif	gscd_read_cmd ();}/* * Check the result of the set-mode command.  On success, send the * read-data command. */static voidgscd_read_cmd (void){long   block;struct gscd_Play_msf gscdcmd;char   cmd[] = { CMD_READ, 0x80, 0,0,0, 0,1 }; /* cmd mode M-S-F secth sectl */        cmd_status ();        if ( disk_state & (ST_NO_DISK | ST_DOOR_OPEN) )        {           printk ( "GSCD: no disk or door open\n" );           end_request (0);        }        else        {           if ( disk_state & ST_INVALID )           {              printk ( "GSCD: disk invalid\n" );              end_request (0);           }           else           {              gscd_bn = -1;		/* purge our buffer */              block = CURRENT -> sector / 4;              gscd_hsg2msf(block, &gscdcmd.start);	/* cvt to msf format */              cmd[2] = gscdcmd.start.min;              cmd[3] = gscdcmd.start.sec;              cmd[4] = gscdcmd.start.frame;#ifdef GSCD_DEBUG              printk ("GSCD: read msf %d:%d:%d\n", cmd[2], cmd[3], cmd[4] ); #endif               cmd_out ( TYPE_DATA, (char *)&cmd, (char *)&gscd_buf[0], 1 );                      gscd_bn = CURRENT -> sector / 4;              gscd_transfer();              end_request(1);	   }	}	SET_TIMER(do_gscd_request, 1);}/* * Open the device special file.  Check that a disk is in. */static int gscd_open (struct inode *ip, struct file *fp){int   st;#ifdef GSCD_DEBUGprintk ( "GSCD: open\n" );#endif	if (gscdPresent == 0)		return -ENXIO;			/* no hardware */	MOD_INC_USE_COUNT;        get_status ();        st = disk_state & (ST_NO_DISK | ST_DOOR_OPEN);        if ( st )        {           printk ( "GSCD: no disk or door open\n" );           MOD_DEC_USE_COUNT;           return -ENXIO;        }                   /*	if (updateToc() < 0)		return -EIO;*/	return 0;}/* * On close, we flush all gscd blocks from the buffer cache. */static int gscd_release (struct inode * inode, struct file * file){#ifdef GSCD_DEBUGprintk ( "GSCD: release\n" );#endif	gscd_bn = -1;	sync_dev(inode->i_rdev);	invalidate_buffers(inode -> i_rdev);	MOD_DEC_USE_COUNT;	return 0;}int get_status (void){int  status;    cmd_status ();    status = disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01);         if ( status == (ST_x08 | ST_x04 | ST_INVALID | ST_x01) )    {       cc_invalidate ();       return 1;    }    else    {       return 0;    }}void cc_invalidate (void){   drv_num_read  = 0xFF;   f_dsk_valid   = 0xFF;   current_drive = 0xFF;   f_drv_ok      = 0xFF;   clear_Audio ();   }   void clear_Audio (void){   f_AudioPlay = 0;   f_AudioPause = 0;   AudioStart_m = 0;   AudioStart_f = 0;   AudioEnd_m   = 0;   AudioEnd_f   = 0;   }/* *   waiting ?   */int wait_drv_ready (void){int found, read;   do   {         found = inb ( GSCDPORT(0) );        found &= 0x0f;       read  = inb ( GSCDPORT(0) );       read  &= 0x0f;   } while ( read != found );   #ifdef GSCD_DEBUGprintk ( "Wait for: %d\n", read );#endif         return read;}void cc_Ident (char * respons){char to_do [] = {CMD_IDENT, 0, 0};    cmd_out (TYPE_INFO, (char *)&to_do, (char *)respons, (int)0x1E );}void cc_SetSpeed (void){char to_do [] = {CMD_SETSPEED, 0, 0};char dummy;    if ( speed > 0 )    {       to_do[1] = speed & 0x0F;       cmd_out (TYPE_INFO, (char *)&to_do, (char *)&dummy, 0);    }}void cc_Reset (void){char to_do [] = {CMD_RESET, 0};char dummy;   cmd_out (TYPE_INFO, (char *)&to_do, (char *)&dummy, 0);}void cmd_status (void){char to_do [] = {CMD_STATUS, 0};char dummy;   cmd_out (TYPE_INFO, (char *)&to_do, (char *)&dummy, 0);#ifdef GSCD_DEBUGprintk ("GSCD: Status: %d\n", disk_state );#endif}void cmd_out ( int cmd_type, char * cmd, char * respo_buf, int respo_count ){int        result;       result = wait_drv_ready ();       if ( result != drv_mode )       {       unsigned long test_loops = 0xFFFF;       int           i,dummy;          outb ( curr_drv_state, GSCDPORT(0));                    /* LOCLOOP_170 */          do          {             result = wait_drv_ready ();             test_loops--;          } while ( (result != drv_mode) && (test_loops > 0) );          if ( result != drv_mode )          {             disk_state = ST_x08 | ST_x04 | ST_INVALID;             return;          }                            /* ...and waiting */          for ( i=1,dummy=1 ; i<0xFFFF ; i++ )          {             dummy *= i;          }                     }       /* LOC_172 */    

⌨️ 快捷键说明

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