Commit f74492a2 authored by Linus Torvalds's avatar Linus Torvalds

Import 1.1.1

parent 75bcc1d5
......@@ -531,6 +531,14 @@ S: Obere Heerbergstrasse 17
S: 97078 Wuerzburg
S: Germany
N: Patrick Volkerding
E: volkerdi@ftp.cdrom.com
D: Produced the Slackware distribution, updated the SVGAlib
D: patches for ghostscript, worked on color 'ls', etc.
S: 301 15th Street S.
S: Moorhead, MN 56560
S: USA
N: Juergen Weigert
E: jnweiger@immd4.informatik.uni-erlangen.de
D: The Linux Support Team Erlangen
......
VERSION = 1
PATCHLEVEL = 1
SUBLEVEL = 0
SUBLEVEL = 1
all: Version zImage
......
This is release 1.3 of the SoundBlaster Pro (Matsushita, Kotobuki,
This is release 1.4 of the SoundBlaster Pro (Matsushita, Kotobuki,
Panasonic, CreativeLabs, Aztech) CD-ROM driver for Linux.
The driver is able to drive the whole family of IDE-style
......@@ -14,11 +14,11 @@ is a 2.11, but it should work with "old" drives <2.01 ... >3.00
and with "new" drives (which count the releases around 0.75 or
1.00).
Up to 4 drives are supported. CR-52x and CR-56x drives can be mixed,
but the CR-521 ones are hard-wired to drive ID 0. The drives have
to use different drive IDs, but the same controller (it will be a
little bit harder to support up to four interface cards - but I plan
to do it the day somebody wishes to connect a fifth drive).
Up to 4 drives are supported. CR-52x ("old") and CR-56x ("new") drives
can be mixed, but the CR-521 ones are hard-wired to drive ID 0.
The drives have to use different drive IDs, but the same controller
(it will be a little bit harder to support up to four interface cards -
but I plan to do it the day somebody wishes to connect a fifth drive).
Each drive has to get a unique minor number (0...3), corresponding
to it's drive ID. The drive IDs may be selected freely from 0 to 3 -
they must not be in consecutive order.
......@@ -28,12 +28,14 @@ audio tracks. The audio part should run with WorkMan, xcdplayer,
with the "non-X11" products CDplayer and WorkBone - tell me if
it is not compatible with other software.
MultiSession is supported, "ManySession" (see below) alternatively.
MultiSession is supported (but "old" drives lack this capability),
"ManySession" (see below) alternatively.
Photo CDs work, too. At ftp.gwdg.de:/pub/linux/hpcdtoppm/ is a package
to convert photo CD image files.
The transfer rate will reach 150 kB/sec with standard drives and
the full 300 kB/sec with double-speed drives.
The transfer rate will reach 150 kB/sec with "old" drives and
the full 300 kB/sec with double-speed drives. XA (PhotoCD) disks
with "old" drives are as slow as 50 kB/sec.
This release is part of the standard kernel and consists of
- this README file
......@@ -188,6 +190,13 @@ Known problems:
Currently, the detection of disk change or removal does not
work as good as it should.
The "door (un)lock" commands get done at every "(u)mount" (only the
"new" drives support it), but after an unlock, locking again does not
work.
All attempts to read the UPC/EAN code result in a stream of zeroes.
All my drives are telling there is no UPC/EAN code on disk or there
is, but it is an all-zero number.
Bug reports, comments, wishes, donations (technical information
is a donation, too :-) etc. to
......
......@@ -1241,6 +1241,9 @@ static struct floppy_struct *find_base(int drive,int code)
base = &floppy_types[(code-1)*2];
printk("fd%d is %s",drive,base->name);
return base;
} else if (!code) {
printk("fd%d is not installed", drive);
return NULL;
}
printk("fd%d is unknown type %d",drive,code);
return NULL;
......@@ -1250,7 +1253,7 @@ static void config_types(void)
{
printk("Floppy drive(s): ");
base_type[0] = find_base(0,(CMOS_READ(0x10) >> 4) & 15);
if (((CMOS_READ(0x14) >> 6) & 1) == 0)
if ((CMOS_READ(0x10) & 15) == 0)
base_type[1] = NULL;
else {
printk(", ");
......
......@@ -5,7 +5,7 @@
* and for "no-sound" interfaces like Lasermate and the
* Panasonic CI-101P.
*
* NOTE: This is release 1.3.
* NOTE: This is release 1.4.
* 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.
......@@ -63,6 +63,15 @@
* 1.3 Minor cleanups.
* Refinements regarding Workman.
*
* 1.4 Read XA disks (PhotoCDs) with "old" drives, too (but possibly only
* the first session - I could not try a "multi-session" CD yet).
* This currently still is too slow (50 kB/sec) - but possibly
* the old drives won't do it faster.
* Implemented "door (un)lock" for new drives (still does not work
* as wanted - no lock possible after an unlock).
* Added some debugging printout for the UPC/EAN code - but my drives
* return only zeroes. Is there no UPC/EAN code written?
*
* 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
......@@ -120,7 +129,7 @@
#define MAJOR_NR MATSUSHITA_CDROM_MAJOR
#include "blk.h"
#define VERSION "1.3 Eberhard Moenkeberg <emoenke@gwdg.de>"
#define VERSION "1.4 Eberhard Moenkeberg <emoenke@gwdg.de>"
#define SBPCD_DEBUG
......@@ -131,10 +140,22 @@
/*
* still testing around...
*/
#define MANY_SESSION 0
#define CDMKE
#define LONG_TIMING 0 /* test against timeouts with "gold" CDs on CR-521 */
#define MANY_SESSION 0 /* this will conflict with "true" multi-session! */
#undef FUTURE
#define WORKMAN 1 /* some testing stuff to make it better */
#define CDMKE /* makes timing independent of processor speed */
#undef XA_TEST1
#define XA_TEST2
/*==========================================================================*/
/*==========================================================================*/
#if MANY_SESSION
#undef LONG_TIMING
#define LONG_TIMING 1
#endif
/*==========================================================================*/
/*==========================================================================*/
......@@ -214,6 +235,9 @@ static int sbp_data(void);
* (1<<DBG_SPI) SpinUp test info
* (1<<DBG_IOS) ioctl trace: "subchannel"
* (1<<DBG_IO2) ioctl trace: general
* (1<<DBG_UPC) show UPC info
* (1<<DBG_XA) XA mode debugging
* (1<<DBG_LCK) door (un)lock info
* (1<<DBG_000) unnecessary information
*/
#if 1
......@@ -221,7 +245,10 @@ static int sbpcd_debug = (1<<DBG_INF) | (1<<DBG_WRN);
#else
static int sbpcd_debug = (1<<DBG_INF) |
(1<<DBG_TOC) |
(1<<DBG_UPC) |
(1<<DBG_IOC) |
(1<<DBG_XA) |
(1<<DBG_LCK) |
(1<<DBG_IOX);
#endif
static int sbpcd_ioaddr = CDROM_PORT; /* default I/O base address */
......@@ -260,6 +287,7 @@ 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 scratch_buf[CD_XA_TAIL];
static u_char timed_out=0;
static u_int datarate= 1000000;
......@@ -267,11 +295,11 @@ static u_int maxtim16=16000000;
static u_int maxtim04= 4000000;
static u_int maxtim02= 2000000;
static u_int maxtim_8= 30000;
#if MANY_SESSION
#if LONG_TIMING
static u_int maxtim_data= 9000;
#else
static u_int maxtim_data= 3000;
#endif MANY_SESSION
#endif LONG_TIMING
/*==========================================================================*/
......@@ -306,7 +334,7 @@ static struct {
u_char sense_byte;
u_char CD_changed;
u_char open_count;
u_char error_byte;
u_char f_multisession;
......@@ -369,7 +397,6 @@ static struct {
/*
* drive space ends here (needed separate for each unit)
*/
/*==========================================================================*/
/*==========================================================================*/
/*
......@@ -766,6 +793,7 @@ int cmd_out(void)
if (sbpro_type) OUT(CDo_sel_d_i,0x01);
DPRINTF((DBG_INF,"SBPCD: misleaded to try ResponseData.\n"));
if (sbpro_type) OUT(CDo_sel_d_i,0x00);
return (-22);
}
else i=ResponseInfo();
if (i<0) return (-9);
......@@ -1055,10 +1083,10 @@ static int SetSpeed(void)
int i, speed;
if (!(DS[d].drv_options&(speed_auto|speed_300|speed_150))) return (0);
speed=0x80;
speed=speed_auto;
if (!(DS[d].drv_options&speed_auto))
{
speed |= 0x40;
speed |= speed_300;
if (!(DS[d].drv_options&speed_300)) speed=0;
}
i=yy_SetSpeed(speed,0,0);
......@@ -1105,12 +1133,12 @@ static int xx_Pause_Resume(int pau_res)
return (i);
}
/*==========================================================================*/
#if 000
static int yy_LockDoor(char lock)
{
int i;
if (!new_drive) return (-3);
if (!new_drive) return (0);
DPRINTF((DBG_LCK,"SBPCD: yy_LockDoor: %d (drive %d)\n", lock, d));
clr_cmdbuf();
drvcmd[0]=0x0C;
if (lock==1) drvcmd[1]=0x01;
......@@ -1119,7 +1147,6 @@ static int yy_LockDoor(char lock)
i=cmd_out();
return (i);
}
#endif 000
/*==========================================================================*/
static int xx_ReadSubQ(void)
{
......@@ -1192,6 +1219,51 @@ static int xx_ModeSense(void)
i=0;
if (new_drive) DS[d].sense_byte=infobuf[i++];
DS[d].frame_size=make16(infobuf[i],infobuf[i+1]);
DPRINTF((DBG_XA,"SBPCD: xx_ModeSense: "));
for (i=0;i<(new_drive?5:2);i++)
{
DPRINTF((DBG_XA,"%02X ", infobuf[i]));
}
DPRINTF((DBG_XA,"\n"));
DS[d].diskstate_flags |= frame_size_bit;
return (0);
}
/*==========================================================================*/
/*==========================================================================*/
static int xx_ModeSelect(int framesize)
{
int i;
DS[d].diskstate_flags &= ~frame_size_bit;
clr_cmdbuf();
DS[d].frame_size=framesize;
DPRINTF((DBG_XA,"SBPCD: xx_ModeSelect: %02X %04X\n",
DS[d].sense_byte, DS[d].frame_size));
if (new_drive)
{
drvcmd[0]=0x09;
drvcmd[1]=0x00;
drvcmd[2]=DS[d].sense_byte;
drvcmd[3]=(DS[d].frame_size>>8)&0xFF;
drvcmd[4]=DS[d].frame_size&0xFF;
flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
}
else
{
drvcmd[0]=0x84;
drvcmd[1]=0x00;
drvcmd[2]=(DS[d].frame_size>>8)&0xFF;
drvcmd[3]=DS[d].frame_size&0xFF;
drvcmd[4]=0x00;
flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
}
response_count=0;
i=cmd_out();
if (i<0) return (i);
DS[d].diskstate_flags |= frame_size_bit;
return (0);
}
......@@ -1430,15 +1502,31 @@ static int xx_ReadUPC(void)
i=xx_ReadPacket();
if (i<0) return (i);
}
DPRINTF((DBG_UPC,"SBPCD: UPC info: "));
for (i=0;i<(new_drive?8:16);i++)
{
DPRINTF((DBG_UPC,"%02X ", infobuf[i]));
}
DPRINTF((DBG_UPC,"\n"));
DS[d].UPC_ctl_adr=0;
if (new_drive) i=0;
else i=2;
if ((infobuf[i]&0x80)!=0)
{
convert_UPC(&infobuf[i]);
DS[d].UPC_ctl_adr &= 0xF0;
DS[d].UPC_ctl_adr |= 0x02;
DS[d].UPC_ctl_adr = (DS[d].TocEnt_ctl_adr & 0xF0) | 0x02;
}
DPRINTF((DBG_UPC,"SBPCD: UPC code: "));
DPRINTF((DBG_UPC,"(%02X) ", DS[d].UPC_ctl_adr));
for (i=0;i<7;i++)
{
DPRINTF((DBG_UPC,"%02X ", DS[d].UPC_buf[i]));
}
DPRINTF((DBG_UPC,"\n"));
DS[d].diskstate_flags |= upc_bit;
return (0);
}
......@@ -1504,11 +1592,11 @@ static void check_datarate(void)
maxtim04=datarate*4;
maxtim02=datarate*2;
maxtim_8=datarate/32;
#if MANY_SESSION
#if LONG_TIMING
maxtim_data=datarate/100;
#else
maxtim_data=datarate/300;
#endif MANY_SESSION
#endif LONG_TIMING
DPRINTF((DBG_TIM,"SBPCD: maxtim_8 %d, maxtim_data %d.\n",
maxtim_8, maxtim_data));
#endif CDMKE
......@@ -1860,6 +1948,14 @@ static int DiskInfo(void)
DPRINTF((DBG_INF,"SBPCD: DiskInfo: xx_ReadUPC returns %d\n", i));
return (i);
}
#ifdef XA_TEST2
if ((!new_drive) && (DS[d].xa_byte==0x20)) /* XA disk with old drive */
{
xx_ModeSelect(CD_FRAMESIZE_XA);
xx_ModeSense();
}
#endif XA_TEST2
return (0);
}
/*==========================================================================*/
......@@ -2378,6 +2474,14 @@ static void do_sbpcd_request(void)
if (!st_spinning) xx_SpinUp();
#ifdef XA_TEST1
if ((!new_drive) && (DS[d].xa_byte==0x20)) /* XA disk with old drive */
{
xx_ModeSelect(CD_FRAMESIZE_XA);
xx_ModeSense();
}
#endif XA_TEST1
for (data_tries=3; data_tries > 0; data_tries--)
{
for (status_tries=3; status_tries > 0; status_tries--)
......@@ -2463,6 +2567,22 @@ static void sbp_read_cmd(void)
if (!new_drive)
{
flags_cmd_out |= f_lopsta | f_getsta | f_bit1;
if (DS[d].xa_byte==0x20)
{
cmd_type=READ_M2;
drvcmd[0]=0x03; /* "read XA frames" command for old drives */
drvcmd[1]=(block>>16)&0x000000ff;
drvcmd[2]=(block>>8)&0x000000ff;
drvcmd[3]=block&0x000000ff;
drvcmd[4]=0;
drvcmd[5]=DS[d].sbp_read_frames;
drvcmd[6]=0;
}
else
{
drvcmd[0]=0x02; /* "read frames" command for old drives */
if (DS[d].drv_type>=drv_201)
{
lba2msf(block,&drvcmd[1]); /* msf-bcd format required */
......@@ -2479,16 +2599,15 @@ static void sbp_read_cmd(void)
drvcmd[4]=0;
drvcmd[5]=DS[d].sbp_read_frames;
drvcmd[6]=(DS[d].drv_type<drv_201)?0:2; /* flag "lba or msf-bcd format" */
drvcmd[0]=0x02; /* "read frames" command for old drives */
flags_cmd_out |= f_lopsta|f_getsta|f_bit1;
}
}
else /* if new_drive */
{
drvcmd[0]=0x10; /* "read frames" command for new drives */
lba2msf(block,&drvcmd[1]); /* msf-bin format required */
drvcmd[4]=0;
drvcmd[5]=0;
drvcmd[6]=DS[d].sbp_read_frames;
drvcmd[0]=0x10; /* "read frames" command for new drives */
}
#if SBPCD_DIS_IRQ
cli();
......@@ -2524,7 +2643,11 @@ static int sbp_data(void)
cli();
#endif SBPCD_DIS_IRQ
try=maxtim_data;
#if LONG_TIMING
for (timeout=jiffies+900; ; )
#else
for (timeout=jiffies+100; ; )
#endif
{
for ( ; try!=0;try--)
{
......@@ -2564,7 +2687,9 @@ static int sbp_data(void)
p = DS[d].sbp_buf + frame * CD_FRAMESIZE;
if (sbpro_type) OUT(CDo_sel_d_i,0x01);
if (cmd_type==READ_M2) READ_DATA(CDi_data, scratch_buf, CD_XA_HEAD);
READ_DATA(CDi_data, p, CD_FRAMESIZE);
if (cmd_type==READ_M2) READ_DATA(CDi_data, scratch_buf, CD_XA_TAIL);
if (sbpro_type) OUT(CDo_sel_d_i,0x00);
DS[d].sbp_current++;
......@@ -2681,10 +2806,11 @@ int sbpcd_open(struct inode *ip, struct file *fp)
}
/*
* we could try to keep an "open" counter here and lock the door if 0->1.
* not done yet.
* try to keep an "open" counter here and lock the door if 0->1.
*/
DPRINTF((DBG_LCK,"SBPCD: open_count: %d -> %d\n",
DS[d].open_count,DS[d].open_count+1));
if (++DS[d].open_count==1) yy_LockDoor(1);
if (!st_spinning) xx_SpinUp();
......@@ -2700,11 +2826,6 @@ int sbpcd_open(struct inode *ip, struct file *fp)
static void sbpcd_release(struct inode * ip, struct file * file)
{
int i;
/*
* we could try to count down an "open" counter here
* and unlock the door if zero.
* not done yet.
*/
i = MINOR(ip->i_rdev);
if ( (i<0) || (i>=NR_SBPCD) )
......@@ -2718,6 +2839,13 @@ static void sbpcd_release(struct inode * ip, struct file * file)
sync_dev(ip->i_rdev); /* nonsense if read only device? */
invalidate_buffers(ip->i_rdev);
DS[d].diskstate_flags &= ~cd_size_bit;
/*
* try to keep an "open" counter here and unlock the door if 1->0.
*/
DPRINTF((DBG_LCK,"SBPCD: open_count: %d -> %d\n",
DS[d].open_count,DS[d].open_count-1));
if (--DS[d].open_count==0) yy_LockDoor(0);
}
/*==========================================================================*/
/*
......
/* fdomain.c -- Future Domain TMC-16x0 SCSI driver
* Created: Sun May 3 18:53:19 1992 by faith@cs.unc.edu
* Revised: Sun Jan 23 08:59:04 1994 by faith@cs.unc.edu
* Revised: Fri Apr 1 23:47:55 1994 by faith@cs.unc.edu
* Author: Rickard E. Faith, faith@cs.unc.edu
* Copyright 1992, 1993, 1994 Rickard E. Faith
*
* $Id: fdomain.c,v 5.9 1994/01/23 13:59:14 root Exp $
* $Id: fdomain.c,v 5.15 1994/04/02 04:48:04 root Exp $
* 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
......@@ -16,6 +16,10 @@
* 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.
**************************************************************************
DESCRIPTION:
......@@ -26,7 +30,7 @@
high-density external connector. The 1670 and 1680 have floppy disk
controllers built in.
Future Domain's older boards are based on the TMC-1800 chip, and the
Future Domain's older boards are based on the TMC-1800 chip, and this
driver was originally written for a TMC-1680 board with the TMC-1800
chip. More recently, boards are being produced with the TMC-18C50 chip.
The latest and greatest board may not work with this driver. If you have
......@@ -34,6 +38,12 @@
signature, then the driver may fail to function after the board is
detected.
The following BIOS versions are supported: 2.0, 3.0, 3.2, and 3.4.
The following chips are supported: TMC-1800, TMC-18C50.
Reports suggest that the driver will also work with the TMC-18C30 chip.
The support for the version 3.4 BIOS is new, as of March 1994, and may not
be stable.
If you have a TMC-8xx or TMC-9xx board, then this is not the driver for
your board. Please refer to the Seagate driver for more information and
possible support.
......@@ -60,6 +70,16 @@
Private communications, Drew Eckhardt (drew@cs.colorado.edu) and Eric
Youngdale (eric@tantalus.nrl.navy.mil), 1992.
Private communication, Tuong Le (Future Domain Engineering department),
1994. (Disk geometry computations for Future Domain BIOS version 3.4, and
TMC-18C30 detection.)
Hogan, Thom. The Programmer's PC Sourcebook. Microsoft Press, 1988. Page
60 (2.39: Disk Partition Table Layout).
"18C30 Technical Reference Manual", Future Domain Corporation, 1993, page
6-1.
NOTES ON REFERENCES:
......@@ -95,6 +115,9 @@
his 18C50-based card for debugging. He is the sole reason that this
driver works with the 18C50 chip.
Thanks to Dave Newman (dnewman@crl.com) for providing initial patches for
the version 3.4 BIOS.
All of the alpha testers deserve much thanks.
......@@ -128,11 +151,12 @@
of the two race conditions which were introduced by multiple outstanding
commands). The instability seems a very high price to pay just so that
you don't have to wait for the tape to rewind. When I have time, I will
work on this again. In the interim, if anyone want to work on the code, I
can give them my latest version.
work on this again. In the interim, if anyone wants to work on the code,
I can give them my latest version.
**************************************************************************/
#include <linux/config.h>
#include <linux/sched.h>
#include <asm/io.h>
#include "../block/blk.h"
......@@ -144,7 +168,7 @@
#include <linux/string.h>
#include <linux/ioport.h>
#define VERSION "$Revision: 5.9 $"
#define VERSION "$Revision: 5.15 $"
/* START OF USER DEFINABLE OPTIONS */
......@@ -189,6 +213,7 @@ enum chip_type {
unknown = 0x00,
tmc1800 = 0x01,
tmc18c50 = 0x02,
tmc18c30 = 0x03,
};
enum {
......@@ -204,15 +229,15 @@ enum in_port_type {
Read_SCSI_Data = 0,
SCSI_Status = 1,
TMC_Status = 2,
FIFO_Status = 3, /* tmc18c50 only */
Interrupt_Cond = 4, /* tmc18c50 only */
FIFO_Status = 3, /* tmc18c50/tmc18c30 only */
Interrupt_Cond = 4, /* tmc18c50/tmc18c30 only */
LSB_ID_Code = 5,
MSB_ID_Code = 6,
Read_Loopback = 7,
SCSI_Data_NoACK = 8,
Interrupt_Status = 9,
Configuration1 = 10,
Configuration2 = 11, /* tmc18c50 only */
Configuration2 = 11, /* tmc18c50/tmc18c30 only */
Read_FIFO = 12,
FIFO_Data_Count = 14
};
......@@ -223,8 +248,9 @@ enum out_port_type {
Interrupt_Cntl = 2,
SCSI_Mode_Cntl = 3,
TMC_Cntl = 4,
Memory_Cntl = 5, /* tmc18c50 only */
Memory_Cntl = 5, /* tmc18c50/tmc18c30 only */
Write_Loopback = 7,
IO_Control = 11, /* tmc18c30 only */
Write_FIFO = 12
};
......@@ -278,8 +304,9 @@ static unsigned short ints[] = { 3, 5, 10, 11, 12, 14, 15, 0 };
READ EVERY WORD, ESPECIALLY THE WORD *NOT*
This driver works *ONLY* for Future Domain cards using the TMC-1800 or
the TMC-18C50 chip. This includes models TMC-1650, 1660, 1670, and 1680.
This driver works *ONLY* for Future Domain cards using the TMC-1800,
TMC-18C50, or TMC-18C30 chip. This includes models TMC-1650, 1660, 1670,
and 1680.
The following BIOS signature signatures are for boards which do *NOT*
work with this driver (these TMC-8xx and TMC-9xx boards may work with the
......@@ -308,6 +335,7 @@ struct signature {
{ "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V1.07/28/89", 5, 50, 2, 0 },
{ "FUTURE DOMAIN CORP. (C) 1992 V3.00.004/02/92", 5, 44, 3, 0 },
{ "FUTURE DOMAIN TMC-18XX (C) 1993 V3.203/12/93", 5, 44, 3, 2 },
{ "Future Domain Corp. V1.0008/18/93", 5, 33, 3, 4 },
{ "FUTURE DOMAIN TMC-18XX", 5, 22, -1, -1 },
/* READ NOTICE ABOVE *BEFORE* YOU WASTE YOUR TIME ADDING A SIGANTURE
......@@ -331,7 +359,8 @@ static void print_banner( void )
printk( "Future Domain: BIOS version %d.%d, %s\n",
bios_major, bios_minor,
chip == tmc1800 ? "TMC-1800"
: (chip == tmc18c50 ? "TMC-18C50" : "Unknown") );
: (chip == tmc18c50 ? "TMC-18C50"
: (chip == tmc18c30 ? "TMC-18C30" : "Unknown")) );
if (interrupt_level) {
printk( "Future Domain: BIOS at %x; port base at %x; using IRQ %d\n",
......@@ -353,7 +382,7 @@ inline static void fdomain_make_bus_idle( void )
{
outb( 0, SCSI_Cntl_port );
outb( 0, SCSI_Mode_Cntl_port );
if (chip == tmc18c50)
if (chip == tmc18c50 || chip == tmc18c30)
outb( 0x21 | PARITY_MASK, TMC_Cntl_port ); /* Clear forced intr. */
else
outb( 0x01 | PARITY_MASK, TMC_Cntl_port );
......@@ -381,6 +410,28 @@ static int fdomain_is_valid_port( int port )
} else { /* test for 0xe960 id */
if (inb( port + MSB_ID_Code ) != 0x60) return 0;
chip = tmc18c50;
#if 0
/* Try to toggle 32-bit mode. This only
works on an 18c30 chip. (User reports
say that this doesn't work at all, so
we'll use the other method.) */
outb( 0x80, port + IO_Control );
if (inb( port + Configuration2 ) & 0x80 == 0x80) {
outb( 0x00, port + IO_Control );
if (inb( port + Configuration2 ) & 0x80 == 0x00) chip = tmc18c30;
}
#else
/* That should have worked, but appears to
have problems. Lets assume it is an
18c30 if the RAM is disabled. */
if (inb( port + Configuration2 ) & 0x02) chip = tmc18c30;
#endif
/* If that failed, we are an 18c50. */
}
/* We have a valid MCA ID for a TMC-1660/TMC-1680 Future Domain board.
......@@ -395,9 +446,13 @@ static int fdomain_is_valid_port( int port )
printk( " Options = %x\n", options );
#endif
/* Check for board with lowest bios_base. */
if (addresses[ (options & 0xc0) >> 6 ] != bios_base)
/* Check for board with lowest bios_base --
this isn't valid for the 18c30, so just
assume we have the right board. */
if (chip != tmc18c30 && addresses[ (options & 0xc0) >> 6 ] != bios_base)
return 0;
interrupt_level = ints[ (options & 0x0e) >> 1 ];
return 1;
......@@ -705,7 +760,7 @@ static int fdomain_arbitrate( void )
printk( "Arbitration failed, status = %x\n", status );
#endif
#if ERRORS_ONLY
printk( "Future Domain: Arbitration failed, status = %x", status );
printk( "Future Domain: Arbitration failed, status = %x\n", status );
#endif
return 1;
}
......@@ -723,7 +778,11 @@ static int fdomain_select( int target )
/* Stop arbitration and enable parity */
outb( PARITY_MASK, TMC_Cntl_port );
#if 0
timeout = jiffies + 25; /* 250mS */
#else
timeout = jiffies + 35; /* 350mS -- because of timeouts */
#endif
while (jiffies < timeout) {
status = inb( SCSI_Status_port ); /* Read adapter status */
if (status & 1) { /* Busy asserted */
......@@ -738,7 +797,7 @@ static int fdomain_select( int target )
if (!target) printk( "Selection failed\n" );
#endif
#if ERRORS_ONLY
if (!target) printk( "Future Domain: Selection failed" );
if (!target) printk( "Future Domain: Selection failed\n" );
#endif
return 1;
}
......@@ -858,13 +917,13 @@ void fdomain_16x0_intr( int unused )
current_SC->cmnd[ current_SC->SCp.sent_command - 1] );
#endif
break;
case 0x00: /* DATA OUT -- tmc18c50 only */
case 0x00: /* DATA OUT -- tmc18c50/tmc18c30 only */
if (chip != tmc1800 && !current_SC->SCp.have_data_in) {
current_SC->SCp.have_data_in = -1;
outb( 0xd0 | PARITY_MASK, TMC_Cntl_port );
}
break;
case 0x04: /* DATA IN -- tmc18c50 only */
case 0x04: /* DATA IN -- tmc18c50/tmc18c30 only */
if (chip != tmc1800 && !current_SC->SCp.have_data_in) {
current_SC->SCp.have_data_in = 1;
outb( 0x90 | PARITY_MASK, TMC_Cntl_port );
......@@ -1315,13 +1374,13 @@ void print_info( Scsi_Cmnd *SCpnt )
if (inb( Interrupt_Status_port ) & 0x08)
printk( " (enabled)" );
printk( "\n" );
if (chip == tmc18c50) {
if (chip == tmc18c50 || chip == tmc18c30) {
printk( "FIFO Status = 0x%02x\n", inb( port_base + FIFO_Status ) );
printk( "Int. Condition = 0x%02x\n",
inb( port_base + Interrupt_Cond ) );
}
printk( "Configuration 1 = 0x%02x\n", inb( port_base + Configuration1 ) );
if (chip == tmc18c50)
if (chip == tmc18c50 || chip == tmc18c30)
printk( "Configuration 2 = 0x%02x\n",
inb( port_base + Configuration2 ) );
}
......@@ -1396,9 +1455,20 @@ int fdomain_16x0_reset( Scsi_Cmnd *SCpnt )
return 0;
}
#ifdef CONFIG_BLK_DEV_SD
#include "sd.h"
#include "scsi_ioctl.h"
int fdomain_16x0_biosparam( int size, int dev, int *info_array )
{
int drive;
unsigned char buf[512 + sizeof( int ) * 2];
int *sizes = (int *)buf;
unsigned char *data = (unsigned char *)(sizes + 2);
unsigned char do_read[] = { READ_6, 0, 0, 0, 1, 0 };
int retcode;
Scsi_Device *disk;
struct drive_info {
unsigned short cylinders;
unsigned char heads;
......@@ -1438,43 +1508,84 @@ int fdomain_16x0_biosparam( int size, int dev, int *info_array )
*/
drive = MINOR(dev) / 16;
disk = rscsi_disks[ drive ].device;
if (bios_major == 2) {
i = (struct drive_info *)( (char *)bios_base + 0x1f31 + drive * 25 );
info_array[0] = i->heads;
info_array[1] = i->sectors;
info_array[2] = i->cylinders;
} else if (bios_major == 3) { /* Appears to be the same for 3.0 and 3.2 */
} else if (bios_major == 3 && bios_minor < 4) { /* 3.0 and 3.2 BIOS */
i = (struct drive_info *)( (char *)bios_base + 0x1f71 + drive * 10 );
info_array[0] = i->heads + 1;
info_array[1] = i->sectors;
info_array[2] = i->cylinders;
} else { /* 3.4 BIOS (and up?) */
/* This algorithm was provided by Future Domain (much thanks!). */
sizes[0] = 0; /* zero bytes out */
sizes[1] = 512; /* one sector in */
memcpy( data, do_read, sizeof( do_read ) );
retcode = kernel_scsi_ioctl( disk,
SCSI_IOCTL_SEND_COMMAND,
(void *)buf );
if (!retcode /* SCSI command ok */
&& data[511] == 0xaa && data[510] == 0x55 /* Partition table valid */
&& data[0x1c2]) { /* Partition type */
/* The partition table layout is as follows:
Start: 0x1b3h
Offset: 0 = partition status
1 = starting head
2 = starting sector and cylinder (word, encoded)
4 = partition type
5 = ending head
6 = ending sector and cylinder (word, encoded)
8 = starting absolute sector (double word)
c = number of sectors (double word)
Signature: 0x1fe = 0x55aa
So, this algorithm assumes:
1) the first partition table is in use,
2) the data in the first entry is correct, and
3) partitions never divide cylinders
Note that (1) may be FALSE for NetBSD (and other BSD flavors),
as well as for Linux. Note also, that Linux doesn't pay any
attention to the fields that are used by this algorithm -- it
only uses the absolute sector data. Recent versions of Linux's
fdisk(1) will fill this data in correctly, and forthcoming
versions will check for consistency.
Checking for a non-zero partition type is not part of the
Future Domain algorithm, but it seemed to be a reasonable thing
to do, especially in the Linux and BSD worlds. */
info_array[0] = data[0x1c3] + 1; /* heads */
info_array[1] = data[0x1c4] & 0x3f; /* sectors */
} else {
/* How the data is stored in the RAM area is very BIOS-dependent.
Therefore, assume a version 3 layout, and check for validity. */
i = (struct drive_info *)( (char *)bios_base + 0x1f71 + drive * 10 );
info_array[0] = i->heads + 1;
info_array[1] = i->sectors;
info_array[2] = i->cylinders;
if (!info_array[0]
|| !info_array[1]
|| !info_array[2]
|| info_array[2] > 1024 /* DOS uses only 10 bits.
Should this be changed
to support larger drives?
I.e., will the controller
"do the right thing"?
*/
) {
/* Note that this new method guarantees that there will always be
less than 1024 cylinders on a platter. This is good for drives
up to approximately 7.85GB (where 1GB = 1024 * 1024 kB). */
info_array[0]
= info_array[1]
= info_array[2]
= 0;
if ((unsigned int)size >= 0x7e0000U) {
info_array[0] = 0xff; /* heads = 255 */
info_array[1] = 0x3f; /* sectors = 63 */
} else if ((unsigned int)size >= 0x200000U) {
info_array[0] = 0x80; /* heads = 128 */
info_array[1] = 0x3f; /* sectors = 63 */
} else {
info_array[0] = 0x40; /* heads = 64 */
info_array[1] = 0x20; /* sectors = 32 */
}
}
/* For both methods, compute the cylinders */
info_array[2] = (unsigned int)size / (info_array[0] * info_array[1] );
}
return 0;
}
#endif /* CONFIG_BLK_DEV_SD */
/* fdomain.h -- Header for Future Domain TMC-16x0 driver
* Created: Sun May 3 18:47:33 1992 by faith@cs.unc.edu
* Revised: Tue Jan 4 20:44:04 1994 by faith@cs.unc.edu
* Revised: Sat Mar 19 16:07:14 1994 by faith@cs.unc.edu
* Author: Rickard E. Faith, faith@cs.unc.edu
* Copyright 1992, 1993, 1994 Rickard E. Faith
*
* $Id: fdomain.h,v 5.3 1994/01/05 01:44:16 root Exp $
* $Id: fdomain.h,v 5.5 1994/03/19 21:07:38 root Exp $
* 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
......@@ -16,6 +16,10 @@
* 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.
*/
#ifndef _FDOMAIN_H
......@@ -27,7 +31,12 @@ int fdomain_16x0_abort( Scsi_Cmnd *, int );
const char *fdomain_16x0_info( void );
int fdomain_16x0_reset( Scsi_Cmnd * );
int fdomain_16x0_queue( Scsi_Cmnd *, void (*done)(Scsi_Cmnd *) );
#ifdef CONFIG_BLK_DEV_SD
int fdomain_16x0_biosparam( int, int, int * );
#else
#define fdomain_16x0_biosparam NULL
#endif
#define FDOMAIN_16X0 { "Future Domain TMC-16x0", \
fdomain_16x0_detect, \
......
......@@ -71,7 +71,10 @@
#define DBG_SPI 18 /* SpinUp test */
#define DBG_IOS 19 /* ioctl trace: "subchannel" */
#define DBG_IO2 20 /* ioctl trace: general */
#define DBG_000 21 /* unnecessary information */
#define DBG_UPC 21 /* show UPC information */
#define DBG_XA 22 /* XA mode debugging */
#define DBG_LCK 23 /* door (un)lock info */
#define DBG_000 24 /* unnecessary information */
/*==========================================================================*/
/*==========================================================================*/
......@@ -192,9 +195,9 @@
/*
* values of cmd_type (0 else):
*/
#define cmd_type_READ_M1 0x01 /* "data mode 1": 2048 bytes per frame */
#define cmd_type_READ_M2 0x02 /* "data mode 2": 12+2048+280 bytes per frame */
#define cmd_type_READ_SC 0x04 /* "subchannel info": 96 bytes per frame */
#define READ_M1 0x01 /* "data mode 1": 2048 bytes per frame */
#define READ_M2 0x02 /* "data mode 2": 12+2048+280 bytes per frame */
#define READ_SC 0x04 /* "subchannel info": 96 bytes per frame */
/*
* sense byte: used only if new_drive
......@@ -213,7 +216,8 @@
#define CD_FRAMESIZE_XA 2340 /* bytes per frame, "xa" mode */
#define CD_FRAMESIZE_RAW 2352 /* bytes per frame, "raw" mode */
#define CD_BLOCK_OFFSET 150 /* offset of first logical frame */
#define CD_XA_HEAD 12 /* header size of XA frame */
#define CD_XA_TAIL 280 /* tail size of XA frame */
/* audio status (bin) */
#define aud_00 0x00 /* Audio status byte not supported or not valid */
......@@ -339,9 +343,8 @@ read: 02 xx-xx-xx nn-nn fl. (??) read nn-nn blocks of 2048 bytes,
fl=0: "lba"-, =2:"msf-bcd"-coded xx-xx-xx
Read XA-Data:
read: 03 xx-xx-xx nn-nn fl. (??) read nn-nn blocks of 2340 bytes,
starting at block xx-xx-xx
fl=0: "lba"-, =2:"msf-bcd"-coded xx-xx-xx
read: 03 ll-bb-aa nn-nn 00. (??) read nn-nn blocks of 2340 bytes,
starting at block ll-bb-aa
Read SUB_Q:
89 fl 00 00 00 00 00. (13) r0: audio status, r4-r7: lba/msf,
......
......@@ -9,7 +9,7 @@
#include <linux/fs.h>
#include <linux/sched.h>
#define X(name) { (void *) &name, #name }
#define X(name) { (void *) &name, "_" #name }
struct {
void *addr;
......
......@@ -285,6 +285,65 @@ icmp_echo(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev,
}
/* Handle ICMP Timestamp requests. */
static void
icmp_timestamp(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev,
unsigned long saddr, unsigned long daddr, int len,
struct options *opt)
{
struct icmphdr *icmphr;
struct sk_buff *skb2;
int size, offset;
unsigned long *timeptr, midtime;
extern struct timeval xtime; /* kernel/time.c */
size = sizeof(struct sk_buff) + dev->hard_header_len + 64 + len;
if (! (skb2 = alloc_skb(size, GFP_ATOMIC))) {
skb->sk = NULL;
kfree_skb(skb, FREE_READ);
return;
}
skb2->sk = NULL;
skb2->mem_addr = skb2;
skb2->mem_len = size;
skb2->free = 1;
/* Build Layer 2-3 headers for message back to source */
offset = ip_build_header(skb2, daddr, saddr, &dev, IPPROTO_ICMP, opt, len,
skb->ip_hdr->tos, 255);
if (offset < 0) {
printk("ICMP: Could not build IP Header for ICMP TIMESTAMP Response\n");
kfree_skb(skb2, FREE_WRITE);
skb->sk = NULL;
kfree_skb(skb, FREE_READ);
return;
}
/* Re-adjust length according to actual IP header size. */
skb2->len = offset + len;
/* Build ICMP_TIMESTAMP Response message. */
icmphr = (struct icmphdr *) ((char *) (skb2 + 1) + offset);
memcpy((char *) icmphr, (char *) icmph, len);
icmphr->type = ICMP_TIMESTAMPREPLY;
icmphr->code = icmphr->checksum = 0;
/* fill in the current time as ms since midnight UT: */
midtime = (xtime.tv_sec % 86400) * 1000 + xtime.tv_usec / 1000;
timeptr = (unsigned long *) (icmphr + 1);
/* the originate timestamp (timeptr [0]) is still in the copy: */
timeptr [1] = timeptr [2] = htonl(midtime);
icmphr->checksum = ip_compute_csum((unsigned char *) icmphr, len);
/* Ship it out - free it when done */
ip_queue_xmit((struct sock *) NULL, dev, skb2, 1);
skb->sk = NULL;
kfree_skb(skb, FREE_READ);
}
/* Handle the ICMP INFORMATION REQUEST. */
static void
icmp_info(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev,
......@@ -400,6 +459,13 @@ icmp_rcv(struct sk_buff *skb1, struct device *dev, struct options *opt,
skb1->sk = NULL;
kfree_skb(skb1, FREE_READ);
return(0);
case ICMP_TIMESTAMP:
icmp_timestamp(icmph, skb1, dev, saddr, daddr, len, opt);
return 0;
case ICMP_TIMESTAMPREPLY:
skb1->sk = NULL;
kfree_skb(skb1, FREE_READ);
return(0);
case ICMP_INFO_REQUEST:
icmp_info(icmph, skb1, dev, saddr, daddr, len, opt);
return 0;
......
......@@ -3388,6 +3388,15 @@ if (inet_debug == DBG_SLIP) printk("\rtcp_rcv: not in seq\n");
release_sock(sk);
return(0);
case TCP_SYN_RECV:
if (th->syn) {
/* Probably a retransmitted syn */
kfree_skb(skb, FREE_READ);
release_sock(sk);
return(0);
}
default:
if (!tcp_sequence(sk, th, len, opt, saddr,dev)) {
kfree_skb(skb, FREE_READ);
......
......@@ -24,7 +24,7 @@
#define MAX_FIN_SIZE 40 + sizeof (struct sk_buff) + MAX_HEADER
#define MAX_ACK_SIZE 40 + sizeof (struct sk_buff) + MAX_HEADER
#define MAX_RESET_SIZE 40 + sizeof (struct sk_buff) + MAX_HEADER
#define MAX_WINDOW 4096
#define MAX_WINDOW 8192
#define MIN_WINDOW 2048
#define MAX_ACK_BACKLOG 2
#define MIN_WRITE_SPACE 2048
......
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