?? sbpcd.c
字號(hào):
/* * sbpcd.c CD-ROM device driver for the whole family of IDE-style * Kotobuki/Matsushita/Panasonic CR-5xx drives for * SoundBlaster ("Pro" or "16 ASP" or compatible) cards * and for "no-sound" interfaces like Lasermate and the * Panasonic CI-101P. * * NOTE: This is release 1.3. * It works with my SbPro & drive CR-521 V2.11 from 2/92 * and with the new CR-562-B V0.75 on a "naked" Panasonic * CI-101P interface. And vice versa. * * * VERSION HISTORY * * 0.1 initial release, April/May 93, after mcd.c (Martin Harriss) * * 0.2 the "repeat:"-loop in do_sbpcd_request did not check for * end-of-request_queue (resulting in kernel panic). * Flow control seems stable, but throughput is not better. * * 0.3 interrupt locking totally eliminated (maybe "inb" and "outb" * are still locking) - 0.2 made keyboard-type-ahead losses. * check_sbpcd_media_change added (to use by isofs/inode.c) * - but it detects almost nothing. * * 0.4 use MAJOR 25 definitely. * Almost total re-design to support double-speed drives and * "naked" (no sound) interface cards. * Flow control should be exact now (tell me if not). * Don't occupy the SbPro IRQ line (not needed either); will * live together with Hannu Savolainen's sndkit now. * Speeded up data transfer to 150 kB/sec, with help from Kai * Makisara, the "provider" of the "mt" tape utility. * Give "SpinUp" command if necessary. * First steps to support up to 4 drives (but currently only one). * Implemented audio capabilities - workman should work, xcdplayer * gives some problems. * This version is still consuming too much CPU time, and * sleeping still has to be worked on. * During "long" implied seeks, it seems possible that a * ReadStatus command gets ignored. That gives the message * "ResponseStatus timed out" (happens about 6 times here during * a "ls -alR" of the YGGDRASIL LGX-Beta CD). Such a case is * handled without data error, but it should get done better. * * 0.5 Free CPU during waits (again with help from Kai Makisara). * Made it work together with the LILO/kernel setup standard. * Included auto-probing code, as suggested by YGGDRASIL. * Formal redesign to add DDI debugging. * There are still flaws in IOCTL (workman with double speed drive). * * 1.0 Added support for all drive ids (0...3, no longer only 0) * and up to 4 drives on one controller. * Added "#define MANY_SESSION" for "old" multi session CDs. * * 1.1 Do SpinUp for new drives, too. * Revised for clean compile under "old" kernels (pl9). * * 1.2 Found the "workman with double-speed drive" bug: use the driver's * audio_state, not what the drive is reporting with ReadSubQ. * * 1.3 Minor cleanups. * Refinements regarding Workman. * * special thanks to Kai Makisara (kai.makisara@vtt.fi) for his fine * elaborated speed-up experiments (and the fabulous results!), for * the "push" towards load-free wait loops, and for the extensive mail * thread which brought additional hints and bug fixes. * * * Copyright (C) 1993, 1994 Eberhard Moenkeberg <emoenke@gwdg.de> * or <eberhard_moenkeberg@rollo.central.de> * * The FTP-home of this driver is * ftp.gwdg.de:/pub/linux/cdrom/drivers/sbpcd/. * * If you change this software, you should mail a .diff * file with some description lines to emoenke@gwdg.de. * I want to know about it. * * If you are the editor of a Linux CD, you should * enable sbpcd.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. * * You should have received a copy of the GNU General Public License * (for example /usr/src/linux/COPYING); if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */#include <linux/config.h>#include <linux/errno.h>#include <linux/sched.h>#include <linux/timer.h>#include <linux/fs.h>#include <linux/kernel.h>#include <linux/cdrom.h>#include <linux/ioport.h>#include <linux/sbpcd.h>#if SBPCD_USE_IRQ#include <linux/signal.h>#endif SBPCD_USE_IRQ#include <linux/ddi.h>#include <linux/major.h> #include <asm/system.h>#include <asm/io.h>#include <asm/segment.h>#include <stdarg.h>#define MAJOR_NR MATSUSHITA_CDROM_MAJOR#include "blk.h"#define VERSION "1.3 Eberhard Moenkeberg <emoenke@gwdg.de>"#define SBPCD_DEBUG#ifndef CONFIG_ISO9660_FS#error "SBPCD: \"make config\" again. File system iso9660 is necessary."#endif/* * still testing around... */#define MANY_SESSION 0#define CDMKE#undef FUTURE#define WORKMAN 1 /* some testing stuff to make it better *//*==========================================================================*//*==========================================================================*//* * auto-probing address list * inspired by Adam J. Richter from Yggdrasil * * still not good enough - can cause a hang. * example: a NE 2000 ethernet card at 300 will cause a hang probing 310. * if that happens, reboot and use the LILO (kernel) command line. * The possibly conflicting ethernet card addresses get NOT probed * by default - to minimize the hang possibilities. * * The SB Pro addresses get "mirrored" at 0x6xx - to avoid a type error, * the 0x2xx-addresses must get checked before 0x6xx. * * send mail to emoenke@gwdg.de if your interface card is not FULLY * represented here. */static int autoprobe[] = { CDROM_PORT, SBPRO, /* probe with user's setup first */ 0x230, 1, /* Soundblaster Pro and 16 (default) */ 0x300, 0, /* CI-101P (default), Galaxy (default), Reveal (one default) */ 0x250, 1, /* OmniCD default, Soundblaster Pro and 16 */ 0x260, 1, /* OmniCD */ 0x320, 0, /* Lasermate, CI-101P, Galaxy, Reveal (other default) */ 0x340, 0, /* Lasermate, CI-101P */ 0x360, 0, /* Lasermate, CI-101P */ 0x270, 1, /* Soundblaster 16 */ 0x630, 0, /* "sound card #9" (default) */ 0x650, 0, /* "sound card #9" */ 0x670, 0, /* "sound card #9" */ 0x690, 0, /* "sound card #9" */#if 0/* some "hazardous" locations (ethernet cards) */ 0x330, 0, /* Lasermate, CI-101P */ 0x350, 0, /* Lasermate, CI-101P */ 0x370, 0, /* Lasermate, CI-101P */ 0x290, 1, /* Soundblaster 16 */ 0x310, 0, /* Lasermate, CI-101P */#endif};#define NUM_AUTOPROBE (sizeof(autoprobe) / sizeof(int))/*==========================================================================*//* * the forward references: */static void sbp_read_cmd(void);static int sbp_data(void);/*==========================================================================*//* * pattern for printk selection: * * (1<<DBG_INF) necessary information * (1<<DBG_IRQ) interrupt trace * (1<<DBG_REA) "read" status trace * (1<<DBG_CHK) "media check" trace * (1<<DBG_TIM) datarate timer test * (1<<DBG_INI) initialization trace * (1<<DBG_TOC) tell TocEntry values * (1<<DBG_IOC) ioctl trace * (1<<DBG_STA) "ResponseStatus" trace * (1<<DBG_ERR) "xx_ReadError" trace * (1<<DBG_CMD) "cmd_out" trace * (1<<DBG_WRN) give explanation before auto-probing * (1<<DBG_MUL) multi session code test * (1<<DBG_ID) "drive_id != 0" test code * (1<<DBG_IOX) some special information * (1<<DBG_DID) drive ID test * (1<<DBG_RES) drive reset info * (1<<DBG_SPI) SpinUp test info * (1<<DBG_IOS) ioctl trace: "subchannel" * (1<<DBG_IO2) ioctl trace: general * (1<<DBG_000) unnecessary information */#if 1static int sbpcd_debug = (1<<DBG_INF) | (1<<DBG_WRN);#elsestatic int sbpcd_debug = (1<<DBG_INF) | (1<<DBG_TOC) | (1<<DBG_IOC) | (1<<DBG_IOX);#endifstatic int sbpcd_ioaddr = CDROM_PORT; /* default I/O base address */static int sbpro_type = SBPRO;static int CDo_command, CDo_reset;static int CDo_sel_d_i, CDo_enable;static int CDi_info, CDi_status, CDi_data;static int MIXER_addr, MIXER_data;static struct cdrom_msf msf;static struct cdrom_ti ti;static struct cdrom_tochdr tochdr;static struct cdrom_tocentry tocentry;static struct cdrom_subchnl SC;static struct cdrom_volctrl volctrl;char *str_sb = "SoundBlaster";char *str_lm = "LaserMate";char *type;/*==========================================================================*/#if FUTUREstatic struct wait_queue *sbp_waitq = NULL;#endif FUTURE/*==========================================================================*/#define SBP_BUFFER_FRAMES 4 /* driver's own read_ahead *//*==========================================================================*/static u_char drive_family[]="CR-5";static u_char drive_vendor[]="MATSHITA";static u_int response_count=0;static u_int flags_cmd_out;static u_char cmd_type=0;static u_char drvcmd[7];static u_char infobuf[20];static u_char timed_out=0;static u_int datarate= 1000000;static u_int maxtim16=16000000;static u_int maxtim04= 4000000;static u_int maxtim02= 2000000;static u_int maxtim_8= 30000;#if MANY_SESSIONstatic u_int maxtim_data= 9000;#elsestatic u_int maxtim_data= 3000;#endif MANY_SESSION/*==========================================================================*/static int ndrives=0;static u_char drv_pattern[4]={ 0x80, 0x80, 0x80, 0x80 }; /* auto speed *//* /X:... drv_pattern[0] |= (sax_n1|sax_n2); *//* /A:... for (i=0;i<4;i++) drv_pattern[i] |= sax_a; *//* /N:... ndrives=i-'0'; *//*==========================================================================*//* * drive space begins here (needed separate for each unit) */static int d=0; /* DS index: drive number */static struct { char drv_minor; /* minor number or -1 */ char drive_model[4]; char firmware_version[4]; u_char *sbp_buf; /* Pointer to internal data buffer, space allocated during sbpcd_init() */ int sbp_first_frame; /* First frame in buffer */ int sbp_last_frame; /* Last frame in buffer */ int sbp_read_frames; /* Number of frames being read to buffer */ int sbp_current; /* Frame being currently read */ u_char drv_type; u_char drv_options; u_char status_byte; u_char diskstate_flags; u_char sense_byte; u_char CD_changed; u_char error_byte; u_char f_multisession; u_int lba_multi; u_char audio_state; u_int pos_audio_start; u_int pos_audio_end; char vol_chan0; u_char vol_ctrl0; char vol_chan1; u_char vol_ctrl1;#if 000 char vol_chan2; u_char vol_ctrl2; char vol_chan3; u_char vol_ctrl3;#endif 000 u_char SubQ_audio; u_char SubQ_ctl_adr; u_char SubQ_trk; u_char SubQ_pnt_idx; u_int SubQ_run_tot; u_int SubQ_run_trk; u_char SubQ_whatisthis; u_char UPC_ctl_adr; u_char UPC_buf[7]; int CDsize_blk; int frame_size; int CDsize_frm; u_char xa_byte; /* 0x20: XA capabilities */ u_char n_first_track; /* binary */ u_char n_last_track; /* binary (not bcd), 0x01...0x63 */ u_int size_msf; /* time of whole CD, position of LeadOut track */ u_int size_blk; u_char TocEnt_nixbyte; /* em */ u_char TocEnt_ctl_adr; u_char TocEnt_number; u_char TocEnt_format; /* em */ u_int TocEnt_address; u_char ored_ctl_adr; /* to detect if CDROM contains data tracks */ struct { u_char nixbyte; /* em */ u_char ctl_adr; /* 0x4x: data, 0x0x: audio */ u_char number; u_char format; /* em */ /* 0x00: lba, 0x01: msf */ u_int address; } TocBuffer[MAX_TRACKS+1]; /* last entry faked */ int in_SpinUp; } DS[4];/* * drive space ends here (needed separate for each unit) *//*==========================================================================*//*==========================================================================*//* * DDI interface definitions */#ifdef SBPCD_DEBUG# define DPRINTF(x) sbpcd_dprintf xvoid sbpcd_dprintf(int level, char *fmt, ...){ char buff[256]; va_list args; extern int vsprintf(char *buf, const char *fmt, va_list args); if (! (sbpcd_debug & (1 << level))) return; va_start(args, fmt); vsprintf(buff, fmt, args); va_end(args); printk(buff);}#else# define DPRINTF(x) /* nothing */#endif SBPCD_DEBUG/* * maintain trace bit pattern */static int sbpcd_dbg_ioctl(unsigned long arg, int level){ int val; val = get_fs_long((int *) arg); switch(val) { case 0: /* OFF */ sbpcd_debug = 0; break; default: if (val >= 128) sbpcd_debug &= ~(1 << (val - 128)); else sbpcd_debug |= (1 << val); } return(0);}/*==========================================================================*//*==========================================================================*//* * Wait a little while (used for polling the drive). If in initialization, * setting a timeout doesn't work, so just loop for a while. */static inline void sbp_sleep(u_int jifs){ current->state = TASK_INTERRUPTIBLE; current->timeout = jiffies + jifs; schedule();}/*==========================================================================*//*==========================================================================*//* * convert logical_block_address to m-s-f_number (3 bytes only) */static void lba2msf(int lba, u_char *msf){ lba += CD_BLOCK_OFFSET; msf[0] = lba / (CD_SECS*CD_FRAMES); lba %= CD_SECS*CD_FRAMES; msf[1] = lba / CD_FRAMES; msf[2] = lba % CD_FRAMES;}/*==========================================================================*//*==========================================================================*//* * convert msf-bin to msf-bcd */static void bin2bcdx(u_char *p) /* must work only up to 75 or 99 */{ *p=((*p/10)<<4)|(*p%10);}/*==========================================================================*/static u_int blk2msf(u_int blk){ MSF msf; u_int mm; msf.c[3] = 0; msf.c[2] = (blk + CD_BLOCK_OFFSET) / (CD_SECS * CD_FRAMES); mm = (blk + CD_BLOCK_OFFSET) % (CD_SECS * CD_FRAMES); msf.c[1] = mm / CD_FRAMES; msf.c[0] = mm % CD_FRAMES; return (msf.n);}/*==========================================================================*/static u_int make16(u_char rh, u_char rl){ return ((rh<<8)|rl);}/*==========================================================================*/static u_int make32(u_int rh, u_int rl){ return ((rh<<16)|rl);}/*==========================================================================*/static u_char swap_nibbles(u_char i){ return ((i<<4)|(i>>4));
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -