Commit 5e4a8497 authored by Linus Torvalds's avatar Linus Torvalds

Import 1.1.24

parent 2651e5f8
VERSION = 1
PATCHLEVEL = 1
SUBLEVEL = 23
SUBLEVEL = 24
all: Version zImage
......
......@@ -825,7 +825,7 @@ idVRAM: .ascii "Stealth VRAM"
! Number of modes is the number of chip-specific svga modes plus the extended
! modes available on any vga (currently 2)
moati: .byte 0x04, 0x23, 0x33
moati: .byte 0x06, 0x23, 0x33, 0x22, 0x21
moahead: .byte 0x07, 0x22, 0x23, 0x24, 0x2f, 0x34
mocandt: .byte 0x04, 0x60, 0x61
mocirrus: .byte 0x06, 0x1f, 0x20, 0x22, 0x31
......@@ -844,7 +844,7 @@ mounknown: .byte 0x02
! The first two modes are standard vga modes available on any vga.
! mode 0 is 80x50 and mode 1 is 80x28
dscati: .word 0x5032, 0x501c, 0x8419, 0x842c
dscati: .word 0x5032, 0x501c, 0x8419, 0x842c, 0x641e, 0x6419
dscahead: .word 0x5032, 0x501c, 0x842c, 0x8419, 0x841c, 0xa032, 0x5042
dsccandt: .word 0x5032, 0x501c, 0x8419, 0x8432
dsccirrus: .word 0x5032, 0x501c, 0x8419, 0x842c, 0x841e, 0x6425
......
This README belongs to release 2.0 of the SoundBlaster Pro (Matsushita,
This README belongs to release 2.1 of the SoundBlaster Pro (Matsushita,
Kotobuki, Panasonic, CreativeLabs) CD-ROM driver for Linux.
The driver is able to drive the whole family of IDE-style
......@@ -48,14 +48,21 @@ CDplayer and WorkBone - tell me if it is not compatible with other software.
With the "new" drive family CR-562 and CR-563, the reading of audio frames is
possible. This is currently implemented by an IOCTL function which reads only
one frame of 2352 bytes at a time. The transfer rate is as slow as 32 kB/sec.
This will get better, and the software interface may change. We have to
standardize it the day the SCSI driver supports it too.
MultiSession is supported (even my "old" CR-521 can handle it), "ManySession"
(not recommended, see below) alternatively.
Photo CDs work, too. At ftp.gwdg.de:/pub/linux/hpcdtoppm/ is Hadmut Danisch's
package to convert photo CD image files.
up to 4 frames of 2352 bytes at once. Reading more than 1 frame at once gives
very poor quality. Reading the same frame a second time gives different data;
it seems that the drive is out-of-sync at the beginning. See the program
example below. This lack has to get corrected by higher level software.
The transfer rate with reading audio (1-frame-pieces) is as slow as 32 kB/sec.
This could be better reading bigger chunks, but the out-of-sync parts occur at
the beginning of each single frame.
The software interface possibly may change a bit the day the SCSI driver
supports it too.
MultiSession is supported, "ManySession" (not recommended, see below)
alternatively.
Photo CDs work, too (even with my "old" CR-521).
At ftp.gwdg.de:/pub/linux/hpcdtoppm/ is Hadmut Danisch's package to convert
photo CD image files.
The transfer rate will reach 150 kB/sec with "old" drives and 300 kB/sec with
double-speed drives. XA (PhotoCD) disks with "old" drives give only 50 kB/sec.
......@@ -340,6 +347,10 @@ entry[track+1].cdte_addr.lba=190;
}
/*===================== end program ========================================*/
At ftp.gwdg.de:/pub/linux/misc/cdda2wav-sbpcd.tar.gz is an adapted version of
Heiko Eissfeldt's digital-audio to .WAV converter (the original is there, too).
This is preliminary, as Heiko himself will care about it.
Known problems:
---------------
......
......@@ -407,7 +407,7 @@ void request_done(int uptodate)
* to the desired drive, but it will probably not survive the sleep if
* several floppies are used at the same time: thus the loop.
*/
int floppy_change(struct buffer_head * bh)
static int floppy_change(struct buffer_head * bh)
{
unsigned int mask = 1 << (bh->b_dev & 0x03);
......@@ -1289,14 +1289,13 @@ static int floppy_open(struct inode * inode, struct file * filp)
int drive;
int old_dev;
if (floppy_grab_irq_and_dma()) {
return -EBUSY;
}
drive = inode->i_rdev & 3;
old_dev = fd_device[drive];
if (fd_ref[drive])
if (old_dev != inode->i_rdev)
return -EBUSY;
if (floppy_grab_irq_and_dma())
return -EBUSY;
fd_ref[drive]++;
fd_device[drive] = inode->i_rdev;
buffer_drive = buffer_track = -1;
......@@ -1309,7 +1308,7 @@ static int floppy_open(struct inode * inode, struct file * filp)
static void floppy_release(struct inode * inode, struct file * filp)
{
sync_dev(inode->i_rdev);
fsync_dev(inode->i_rdev);
if (!fd_ref[inode->i_rdev & 3]--) {
printk("floppy_release with fd_ref == 0");
fd_ref[inode->i_rdev & 3] = 0;
......@@ -1317,6 +1316,18 @@ static void floppy_release(struct inode * inode, struct file * filp)
floppy_release_irq_and_dma();
}
static int check_floppy_change(dev_t dev)
{
int i;
struct buffer_head * bh;
if (!(bh = getblk(dev,0,1024)))
return 0;
i = floppy_change(bh);
brelse(bh);
return i;
}
static struct file_operations floppy_fops = {
NULL, /* lseek - default */
block_read, /* read - general block-dev read */
......@@ -1327,26 +1338,13 @@ static struct file_operations floppy_fops = {
NULL, /* mmap */
floppy_open, /* open */
floppy_release, /* release */
block_fsync /* fsync */
block_fsync, /* fsync */
NULL, /* fasync */
check_floppy_change, /* media_change */
NULL /* revalidate */
};
/*
* The version command is not supposed to generate an interrupt, but
* my FDC does, except when booting in SVGA screen mode.
* When it does generate an interrupt, it doesn't return any status bytes.
* It appears to have something to do with the version command...
*
* This should never be called, because of the reset after the version check.
*/
static void ignore_interrupt(void)
{
printk(DEVICE_NAME ": weird interrupt ignored (%d)\n", result());
reset = 1;
CLEAR_INTR; /* ignore only once */
}
static void floppy_interrupt(int unused)
{
void (*handler)(void) = DEVICE_INTR;
......@@ -1381,7 +1379,6 @@ void floppy_init(void)
timer_active &= ~(1 << FLOPPY_TIMER);
config_types();
/* Try to determine the floppy controller type */
DEVICE_INTR = ignore_interrupt; /* don't ask ... */
output_byte(FD_VERSION); /* get FDC version code */
if (result() != 1) {
printk(DEVICE_NAME ": FDC failed to return version byte\n");
......@@ -1404,8 +1401,12 @@ void floppy_init(void)
}
}
static int usage_count = 0;
static int floppy_grab_irq_and_dma(void)
{
if (usage_count++)
return 0;
if (irqaction(FLOPPY_IRQ,&floppy_sigaction)) {
printk("Unable to grab IRQ%d for the floppy driver\n", FLOPPY_IRQ);
return -1;
......@@ -1421,6 +1422,8 @@ static int floppy_grab_irq_and_dma(void)
static void floppy_release_irq_and_dma(void)
{
if (--usage_count)
return;
disable_dma(FLOPPY_DMA);
free_dma(FLOPPY_DMA);
disable_irq(FLOPPY_IRQ);
......
......@@ -5,7 +5,7 @@
* and for "no-sound" interfaces like Lasermate and the
* Panasonic CI-101P.
*
* NOTE: This is release 2.0.
* NOTE: This is release 2.1.
* 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.
......@@ -106,6 +106,21 @@
* reset the drive and do again. Needs lots of resets here and sometimes
* that does not cure, so this can't be the solution.
*
* 2.1 Found bug with multisession CDs (accessing frame 16).
* "read audio" works now with address type CDROM_MSF, too.
* Bigger audio frame buffer: allows reading max. 4 frames at time; but
* reading more than one frame at once gives poor quality.
*
*
* TODO
*
* disk change detection
* allow & synchronize multi-activity
* (data + audio + ioctl + disk change, multiple drives)
* implement multi-controller-support with a single driver
* implement "read all subchannel data" (96 bytes per frame)
*
*
* 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
......@@ -172,7 +187,7 @@
#include "blk.h"
#define VERSION "2.0 Eberhard Moenkeberg <emoenke@gwdg.de>"
#define VERSION "2.1 Eberhard Moenkeberg <emoenke@gwdg.de>"
#define SBPCD_DEBUG
......@@ -198,7 +213,6 @@
#define XA_TEST2
#define TEST_UPC 0
#define READ_AUDIO 1
#define SPEA_TEST 0
#define PRINTK_BUG 0
#define TEST_STI 0
......@@ -289,10 +303,11 @@ 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) */
0x300, 0, /* CI-101P (default), WDH-7001C (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) */
0x320, 0, /* Lasermate, CI-101P, WDH-7001C, Galaxy, Reveal (other default) */
0x340, 0, /* Lasermate, CI-101P */
0x360, 0, /* Lasermate, CI-101P */
0x270, 1, /* Soundblaster 16 */
......@@ -304,11 +319,11 @@ static int autoprobe[] =
0x350, 2, /* SPEA Media FX */
#if 0
/* some "hazardous" locations (ethernet cards) */
0x330, 0, /* Lasermate, CI-101P */
0x330, 0, /* Lasermate, CI-101P, WDH-7001C */
0x350, 0, /* Lasermate, CI-101P */
0x370, 0, /* Lasermate, CI-101P */
0x290, 1, /* Soundblaster 16 */
0x310, 0, /* Lasermate, CI-101P */
0x310, 0, /* Lasermate, CI-101P, WDH-7001C */
/* excluded due to incomplete address decoding of the SbPro card */
0x630, 0, /* "sound card #9" (default) */
0x650, 0, /* "sound card #9" */
......@@ -323,8 +338,9 @@ static int autoprobe[] =
* the forward references:
*/
static void sbp_read_cmd(void);
static int sbp_data(void);
static int sbp_data(void);
static int cmd_out(void);
static int DiskInfo(void);
/*==========================================================================*/
......@@ -370,12 +386,7 @@ static int sbpcd_debug = (1<<DBG_INF) |
#else
static int sbpcd_debug = (1<<DBG_INF) |
(1<<DBG_TOC) |
(1<<DBG_UPC) |
(1<<DBG_TIM) |
(1<<DBG_LCK) |
(1<<DBG_CHK) |
(1<<DBG_AUD) |
(1<<DBG_IOX);
(1<<DBG_UPC);
#endif
#endif
static int sbpcd_ioaddr = CDROM_PORT; /* default I/O base address */
......@@ -404,7 +415,8 @@ static struct wait_queue *sbp_waitq = NULL;
/*==========================================================================*/
#define SBP_BUFFER_FRAMES 4 /* driver's own read_ahead */
#define SBP_BUFFER_FRAMES 4 /* driver's own read_ahead, data mode */
#define SBP_BUFFER_AUDIO_FRAMES 4 /* driver's own read_ahead, read audio mode */
/*==========================================================================*/
......@@ -419,6 +431,7 @@ static u_char infobuf[20];
static u_char xa_head_buf[CD_XA_HEAD];
static u_char xa_tail_buf[CD_XA_TAIL];
static u_char busy_data=0, busy_audio=0; /* true semaphores would be safer */
static u_char timed_out=0;
static u_int datarate= 1000000;
static u_int maxtim16=16000000;
......@@ -460,11 +473,8 @@ static struct {
int sbp_current; /* Frame being currently read */
u_char mode; /* read_mode: READ_M1, READ_M2, READ_SC, READ_AU */
#if READ_AUDIO
u_char *aud_buf; /* Pointer to audio data buffer,
space allocated during sbpcd_init() */
#endif READ_AUDIO
u_char drv_type;
u_char drv_options;
u_char status_byte;
......@@ -671,22 +681,34 @@ static int msf2blk(int msfx)
return (i);
}
/*==========================================================================*/
/*
* convert m-s-f_number (3 bytes only) to logical_block_address
*/
static int msf2lba(u_char *msf)
{
int i;
i=(msf[0] * CD_SECS + msf[1]) * CD_FRAMES + msf[2] - CD_BLOCK_OFFSET;
if (i<0) return (0);
return (i);
}
/*==========================================================================*/
/* evaluate xx_ReadError code (still mysterious) */
static int sta2err(int sta)
{
if (sta<=2) return (sta);
if (sta==0x05) return (-4);
if (sta==0x06) return (-6);
if (sta==0x0d) return (-6);
if (sta==0x0e) return (-3);
if (sta==0x14) return (-3);
if (sta==0x0c) return (-11);
if (sta==0x0f) return (-11);
if (sta==0x10) return (-11);
if (sta>=0x16) return (-12);
if (sta==0x05) return (-4); /* CRC error */
if (sta==0x06) return (-6); /* seek error */
if (sta==0x0d) return (-6); /* seek error */
if (sta==0x0e) return (-3); /* unknown command */
if (sta==0x14) return (-3); /* unknown command */
if (sta==0x0c) return (-11); /* read fault */
if (sta==0x0f) return (-11); /* read fault */
if (sta==0x10) return (-11); /* read fault */
if (sta>=0x16) return (-12); /* general failure */
DriveStruct[d].CD_changed=0xFF;
if (sta==0x11) return (-15);
return (-2);
if (sta==0x11) return (-15); /* invalid disk change */
return (-2); /* drive not ready */
}
/*==========================================================================*/
static void clr_cmdbuf(void)
......@@ -1208,6 +1230,7 @@ static int xy_DriveReset(void)
response_count=0;
i=cmd_out();
}
sbp_sleep(100); /* wait a second */
flush_status();
i=GetStatus();
if (i>=0) return -1;
......@@ -1244,7 +1267,7 @@ static int DriveReset(void)
}
while (!st_diskok);
DriveStruct[d].CD_changed=1;
i=SetSpeed();
i=DiskInfo();
if (i<0) return (-2);
return (0);
}
......@@ -1730,13 +1753,13 @@ static int yy_CheckMultiSession(void)
/*==========================================================================*/
#if FUTURE
static int yy_SubChanInfo(int frame, int count, u_char *buffer)
/* "frame" is a RED BOOK address */
/* "frame" is a RED BOOK (msf-bin) address */
{
int i;
if (!new_drive) return (-3);
if (!new_drive) return (-ENOSYS); /* drive firmware lacks it */
#if 0
if (DriveStruct[d].audio_state!=audio_playing) return (-2);
if (DriveStruct[d].audio_state!=audio_playing) return (-ENODATA);
#endif
clr_cmdbuf();
drvcmd[0]=0x11;
......@@ -1748,7 +1771,7 @@ static int yy_SubChanInfo(int frame, int count, u_char *buffer)
flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
cmd_type=READ_SC;
DriveStruct[d].frame_size=CD_FRAMESIZE_SUB;
i=cmd_out(); /* read directly into user's buffer */
i=cmd_out(); /* which buffer to use? */
return (i);
}
#endif FUTURE
......@@ -2076,7 +2099,7 @@ static int ReadToC(void)
/* fake entry for LeadOut Track */
DriveStruct[d].TocBuffer[j].nixbyte=0;
DriveStruct[d].TocBuffer[j].ctl_adr=0;
DriveStruct[d].TocBuffer[j].number=0;
DriveStruct[d].TocBuffer[j].number=CDROM_LEADOUT;
DriveStruct[d].TocBuffer[j].format=0;
DriveStruct[d].TocBuffer[j].address=DriveStruct[d].size_msf;
......@@ -2088,9 +2111,7 @@ static int DiskInfo(void)
{
int i, j;
#if READ_AUDIO
DriveStruct[d].mode=READ_M1;
#endif READ_AUDIO
#undef LOOP_COUNT
#define LOOP_COUNT 20 /* needed for some "old" drives */
......@@ -2579,7 +2600,6 @@ static int SBPCD_IOCTL(struct inode *inode, struct file *file, u_int cmd,
DriveStruct[d].mode=READ_M2;
return (0);
#if READ_AUDIO
case CDROMREADAUDIO:
{ /* start of CDROMREADAUDIO */
int i=0, j=0, frame, block;
......@@ -2596,21 +2616,30 @@ static int SBPCD_IOCTL(struct inode *inode, struct file *file, u_int cmd,
DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMREADAUDIO requested.\n"));
#if 0
if (!new_drive) return (-EINVAL);
#endif
if (DriveStruct[d].aud_buf==NULL) return (-EINVAL);
i=verify_area(VERIFY_READ, (void *) arg, sizeof(struct cdrom_read_audio));
if (i) return (i);
memcpy_fromfs(&read_audio, (void *) arg, sizeof(struct cdrom_read_audio));
i=verify_area(VERIFY_WRITE, read_audio.buf, CD_FRAMESIZE_RAW);
if (read_audio.nframes>SBP_BUFFER_AUDIO_FRAMES) return (-EINVAL);
i=verify_area(VERIFY_WRITE, read_audio.buf,
read_audio.nframes*CD_FRAMESIZE_RAW);
if (i) return (i);
if (read_audio.addr_format==CDROM_MSF) /* MSF-bin specification of where to start */
block=msf2blk(read_audio.addr.lba);
block=msf2lba(&read_audio.addr.msf.minute);
else if (read_audio.addr_format==CDROM_LBA) /* lba specification of where to start */
block=read_audio.addr.lba;
else return (-EINVAL);
if (read_audio.nframes!=1) return (-EINVAL);
DPRINTF((DBG_AUD,"SBPCD: read_audio: lba: %d, msf: %06X\n",
block, blk2msf(block)));
DPRINTF((DBG_AUD,"SBPCD: read_audio: before xx_ReadStatus.\n"));
while (busy_data) sbp_sleep(10); /* wait a bit */
busy_audio=1;
for (data_tries=5; data_tries>0; data_tries--)
{
DPRINTF((DBG_AUD,"SBPCD: data_tries=%d ...\n", data_tries));
......@@ -2641,7 +2670,7 @@ static int SBPCD_IOCTL(struct inode *inode, struct file *file, u_int cmd,
drvcmd[2]=(block>>8)&0x000000ff;
drvcmd[3]=block&0x000000ff;
drvcmd[4]=0;
drvcmd[5]=1; /* # of frames */
drvcmd[5]=read_audio.nframes; /* # of frames */
drvcmd[6]=0;
}
else /* if new_drive */
......@@ -2692,7 +2721,13 @@ static int SBPCD_IOCTL(struct inode *inode, struct file *file, u_int cmd,
error_flag=0;
p = DriveStruct[d].aud_buf;
if (sbpro_type==1) OUT(CDo_sel_d_i,0x01);
READ_DATA(CDi_data, p, CD_FRAMESIZE_RAW);
#if 0
cli();
#endif
READ_DATA(CDi_data, p, read_audio.nframes*CD_FRAMESIZE_RAW);
#if 0
sti();
#endif
if (sbpro_type==1) OUT(CDo_sel_d_i,0x00);
data_retrying = 0;
}
......@@ -2747,13 +2782,15 @@ static int SBPCD_IOCTL(struct inode *inode, struct file *file, u_int cmd,
continue;
}
memcpy_tofs((u_char *) read_audio.buf,
(u_char *) DriveStruct[d].aud_buf, CD_FRAMESIZE_RAW);
(u_char *) DriveStruct[d].aud_buf,
read_audio.nframes*CD_FRAMESIZE_RAW);
DPRINTF((DBG_AUD,"SBPCD: read_audio: memcpy_tofs done.\n"));
break;
}
xx_ModeSelect(CD_FRAMESIZE);
xx_ModeSense();
DriveStruct[d].mode=READ_M1;
busy_audio=0;
if (data_tries == 0)
{
DPRINTF((DBG_AUD,"SBPCD: read_audio: failed after 5 tries.\n"));
......@@ -2762,7 +2799,6 @@ static int SBPCD_IOCTL(struct inode *inode, struct file *file, u_int cmd,
DPRINTF((DBG_AUD,"SBPCD: read_audio: successful return.\n"));
return (0);
} /* end of CDROMREADAUDIO */
#endif READ_AUDIO
case BLKRASET:
if(!suser()) return -EACCES;
......@@ -2811,14 +2847,14 @@ static void DO_SBPCD_REQUEST(void)
sti();
if ((CURRENT==NULL)||(CURRENT->dev<0)) return;
if (CURRENT -> sector == -1) return;
if ((CURRENT==NULL)||(CURRENT->dev<0)) goto done;
if (CURRENT -> sector == -1) goto done;
dev = MINOR(CURRENT->dev);
if ( (dev<0) || (dev>=NR_SBPCD) )
{
printk("SBPCD: do_request: bad device: %d\n", dev);
return;
goto done;
}
switch_drive(dev);
......@@ -2847,6 +2883,9 @@ static void DO_SBPCD_REQUEST(void)
if (i!=0)
DPRINTF((DBG_INF,"SBPCD: \"prepare\" tells error %d -- ignored\n", i));
while (busy_audio) sbp_sleep(100); /* wait a bit */
busy_data=1;
if (!st_spinning) xx_SpinUp();
#ifdef XA_TEST1
......@@ -2884,6 +2923,10 @@ static void DO_SBPCD_REQUEST(void)
end_request(0);
sbp_sleep(10); /* wait a bit, try again */
goto request_loop;
done:
busy_data=0;
return;
}
/*==========================================================================*/
/*
......@@ -2904,13 +2947,13 @@ static void sbp_read_cmd(void)
DPRINTF((DBG_MUL,"SBPCD: read MSF %08X\n", blk2msf(block)));
if ( (DriveStruct[d].f_multisession) && (multisession_valid) )
{
DPRINTF((DBG_MUL,"SBPCD: MultiSession: use %08X for %08X (msf)\n",
DPRINTF((DBG_MUL,"SBPCD: ManySession: use %08X for %08X (msf)\n",
blk2msf(DriveStruct[d].lba_multi+block),
blk2msf(block)));
block=DriveStruct[d].lba_multi+block;
}
#else
if ( (block==CD_BLOCK_OFFSET+16) && (DriveStruct[d].f_multisession) && (multisession_valid) )
if ( (block==16) && (DriveStruct[d].f_multisession) && (multisession_valid) )
{
DPRINTF((DBG_MUL,"SBPCD: MultiSession: use %08X for %08X (msf)\n",
blk2msf(DriveStruct[d].lba_multi+16),
......@@ -3418,6 +3461,9 @@ unsigned long SBPCD_INIT(u_long mem_start, u_long mem_end)
check_datarate();
DPRINTF((DBG_INI,"SBPCD: check_datarate done.\n"));
OUT(CDo_reset,0);
sbp_sleep(100);
for (j=0;j<NR_SBPCD;j++)
{
if (DriveStruct[j].drv_minor==-1) continue;
......@@ -3484,10 +3530,12 @@ unsigned long SBPCD_INIT(u_long mem_start, u_long mem_end)
*/
DriveStruct[j].sbp_buf=(u_char *)mem_start;
mem_start += SBP_BUFFER_FRAMES*CD_FRAMESIZE;
#if READ_AUDIO
DriveStruct[j].aud_buf=(u_char *)mem_start;
mem_start += CD_FRAMESIZE_RAW;
#endif READ_AUDIO
if (new_drive)
{
DriveStruct[j].aud_buf=(u_char *)mem_start;
mem_start += SBP_BUFFER_AUDIO_FRAMES*CD_FRAMESIZE_RAW;
}
else DriveStruct[j].aud_buf=NULL;
/*
* set the block size
*/
......
......@@ -29,25 +29,6 @@
#include <asm/segment.h>
#include <asm/io.h>
#ifdef CONFIG_SCSI
#ifdef CONFIG_BLK_DEV_SR
extern int check_cdrom_media_change(int, int);
#endif
#ifdef CONFIG_BLK_DEV_SD
extern int check_scsidisk_media_change(int, int);
extern int revalidate_scsidisk(int, int);
#endif
#endif
#ifdef CONFIG_CDU31A
extern int check_cdu31a_media_change(int, int);
#endif
#ifdef CONFIG_MCD
extern int check_mcd_media_change(int, int);
#endif
#ifdef CONFIG_SBPCD
extern int check_sbpcd_media_change(int, int);
#endif
#define NR_SIZES 4
static char buffersize_index[9] = {-1, 0, 1, -1, 2, -1, -1, -1, 3};
static short int bufferindex_size[NR_SIZES] = {512, 1024, 2048, 4096};
......@@ -286,85 +267,6 @@ void invalidate_buffers(dev_t dev)
}
}
/*
* This routine checks whether a floppy has been changed, and
* invalidates all buffer-cache-entries in that case. This
* is a relatively slow routine, so we have to try to minimize using
* it. Thus it is called only upon a 'mount' or 'open'. This
* is the best way of combining speed and utility, I think.
* People changing diskettes in the middle of an operation deserve
* to loose :-)
*
* NOTE! Although currently this is only for floppies, the idea is
* that any additional removable block-device will use this routine,
* and that mount/open needn't know that floppies/whatever are
* special.
*/
void check_disk_change(dev_t dev)
{
int i;
struct buffer_head * bh;
switch(MAJOR(dev)){
case FLOPPY_MAJOR:
if (!(bh = getblk(dev,0,1024)))
return;
i = floppy_change(bh);
brelse(bh);
break;
#if defined(CONFIG_BLK_DEV_SD) && defined(CONFIG_SCSI)
case SCSI_DISK_MAJOR:
i = check_scsidisk_media_change(dev, 0);
break;
#endif
#if defined(CONFIG_BLK_DEV_SR) && defined(CONFIG_SCSI)
case SCSI_CDROM_MAJOR:
i = check_cdrom_media_change(dev, 0);
break;
#endif
#if defined(CONFIG_CDU31A)
case CDU31A_CDROM_MAJOR:
i = check_cdu31a_media_change(dev, 0);
break;
#endif
#if defined(CONFIG_MCD)
case MITSUMI_CDROM_MAJOR:
i = check_mcd_media_change(dev, 0);
break;
#endif
#if defined(CONFIG_SBPCD)
case MATSUSHITA_CDROM_MAJOR:
i = check_sbpcd_media_change(dev, 0);
break;
#endif
default:
return;
};
if (!i) return;
printk("VFS: Disk change detected on device %d/%d\n",
MAJOR(dev), MINOR(dev));
for (i=0 ; i<NR_SUPER ; i++)
if (super_blocks[i].s_dev == dev)
put_super(super_blocks[i].s_dev);
invalidate_inodes(dev);
invalidate_buffers(dev);
#if defined(CONFIG_BLK_DEV_SD) && defined(CONFIG_SCSI)
/* This is trickier for a removable hardisk, because we have to invalidate
all of the partitions that lie on the disk. */
if (MAJOR(dev) == SCSI_DISK_MAJOR)
revalidate_scsidisk(dev, 0);
#endif
}
#define _hashfn(dev,block) (((unsigned)(dev^block))%nr_hash)
#define hash(dev,block) hash_table[_hashfn(dev,block)]
......
......@@ -15,6 +15,29 @@
#include <linux/fcntl.h>
#include <linux/errno.h>
/*
* Ugly. We'll fix this once all the drivers use the f_ops->check_media_change()
* stuff instead..
*/
#ifdef CONFIG_SCSI
#ifdef CONFIG_BLK_DEV_SR
extern int check_cdrom_media_change(int, int);
#endif
#ifdef CONFIG_BLK_DEV_SD
extern int check_scsidisk_media_change(int, int);
extern int revalidate_scsidisk(int, int);
#endif
#endif
#ifdef CONFIG_CDU31A
extern int check_cdu31a_media_change(int, int);
#endif
#ifdef CONFIG_MCD
extern int check_mcd_media_change(int, int);
#endif
#ifdef CONFIG_SBPCD
extern int check_sbpcd_media_change(int, int);
#endif
struct device_struct {
const char * name;
struct file_operations * fops;
......@@ -110,6 +133,88 @@ int unregister_blkdev(unsigned int major, const char * name)
return 0;
}
/*
* This routine checks whether a removable media has been changed,
* and invalidates all buffer-cache-entries in that case. This
* is a relatively slow routine, so we have to try to minimize using
* it. Thus it is called only upon a 'mount' or 'open'. This
* is the best way of combining speed and utility, I think.
* People changing diskettes in the middle of an operation deserve
* to loose :-)
*/
void check_disk_change(dev_t dev)
{
int i;
struct file_operations * fops;
i = MAJOR(dev);
if (i >= MAX_BLKDEV || (fops = blkdevs[i].fops) == NULL)
return;
if (fops->check_media_change != NULL) {
if (!fops->check_media_change(dev))
return;
}
#if 1 /* this will go soon.. */
else switch(MAJOR(dev)){
#if defined(CONFIG_BLK_DEV_SD) && defined(CONFIG_SCSI)
case SCSI_DISK_MAJOR:
if (!check_scsidisk_media_change(dev, 0))
return;
break;
#endif
#if defined(CONFIG_BLK_DEV_SR) && defined(CONFIG_SCSI)
case SCSI_CDROM_MAJOR:
if (!check_cdrom_media_change(dev, 0))
return;
break;
#endif
#if defined(CONFIG_CDU31A)
case CDU31A_CDROM_MAJOR:
if (!check_cdu31a_media_change(dev, 0))
return;
break;
#endif
#if defined(CONFIG_MCD)
case MITSUMI_CDROM_MAJOR:
if (!check_mcd_media_change(dev, 0))
return;
break;
#endif
#if defined(CONFIG_SBPCD)
case MATSUSHITA_CDROM_MAJOR:
if (!check_sbpcd_media_change(dev, 0))
return;
break;
#endif
default:
return;
}
#endif /* will go away */
printk("VFS: Disk change detected on device %d/%d\n",
MAJOR(dev), MINOR(dev));
for (i=0 ; i<NR_SUPER ; i++)
if (super_blocks[i].s_dev == dev)
put_super(super_blocks[i].s_dev);
invalidate_inodes(dev);
invalidate_buffers(dev);
if (fops->revalidate)
fops->revalidate(dev);
#if defined(CONFIG_BLK_DEV_SD) && defined(CONFIG_SCSI)
/* This is trickier for a removable hardisk, because we have to invalidate
all of the partitions that lie on the disk. */
if (MAJOR(dev) == SCSI_DISK_MAJOR)
revalidate_scsidisk(dev, 0);
#endif
}
/*
* Called every time a block special file is opened
*/
......
......@@ -14,7 +14,7 @@
/*
* some fix numbers
*/
#define CD_MINS 75 /* minutes per CD */
#define CD_MINS 74 /* max. minutes per CD */
#define CD_SECS 60 /* seconds per minute */
#define CD_FRAMES 75 /* frames per second */
#define CD_FRAMESIZE 2048 /* bytes per frame, cooked mode */
......@@ -238,9 +238,8 @@ struct cdrom_tocentry
/*
* CD-ROM address types (cdrom_tocentry.cdte_format)
*/
#define CDROM_LBA 0x01
#define CDROM_MSF 0x02
#define CDROM_LBA 0x01 /* "logical block": first frame is #0 */
#define CDROM_MSF 0x02 /* "minute-second-frame": binary, not bcd here! */
/*
* bit to tell whether track is data or audio
......@@ -328,7 +327,7 @@ struct cdrom_read_audio
int lba;
} addr; /* frame address */
u_char addr_format; /* CDROM_LBA or CDROM_MSF */
int nframes; /* number of 2352-byte-frames to read at once, currently only 1 allowed */
int nframes; /* number of 2352-byte-frames to read at once, limited by the drivers */
u_char *buf; /* frame buffer (size: nframes*2352 bytes) */
};
......@@ -366,7 +365,7 @@ struct cdrom_read_audio
/* vlume control */
#define CDROMSUBCHNL 0x530b /* (struct cdrom_subchnl) */
/* read sub-channel data */
/* read Q sub-channel data */
#define CDROMREADMODE2 0x530c /* (struct cdrom_read) */
/* read type-2 data (not suppt) */
......
......@@ -292,6 +292,8 @@ struct file_operations {
void (*release) (struct inode *, struct file *);
int (*fsync) (struct inode *, struct file *);
int (*fasync) (struct inode *, struct file *, int);
int (*check_media_change) (dev_t dev);
int (*revalidate) (dev_t dev);
};
struct inode_operations {
......@@ -414,7 +416,6 @@ extern inline void mark_buffer_dirty(struct buffer_head * bh, int flag)
extern void check_disk_change(dev_t dev);
extern void invalidate_inodes(dev_t dev);
extern void invalidate_buffers(dev_t dev);
extern int floppy_change(struct buffer_head * first_block);
extern void sync_inodes(dev_t dev);
extern void sync_dev(dev_t dev);
extern int fsync_dev(dev_t dev);
......
......@@ -25,7 +25,7 @@
#define MCD_BASE_ADDR 0x300
/* *** change this to set the interrupt number */
#define MCD_INTR_NR 11
#define MCD_INTR_NR 10
/* Increase this if you get lots of timeouts */
#define MCD_STATUS_DELAY 100
......
......@@ -23,7 +23,7 @@
* and specify the type of your interface in SBPRO.
*
* SBPRO addresses typically are 0x0230 (=0x220+0x10), 0x0250, ...
* LASERMATE (CI-101P) adresses typically are 0x0300, 0x0310, ...
* LASERMATE (CI-101P, WDH-7001C) adresses typically are 0x0300, 0x0310, ...
* SPEA addresses are 0x320, 0x330, 0x340, 0x350
* there are some soundcards on the market with 0x0630, 0x0650, ...
*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment