Commit 4e6b9ed5 authored by Linus Torvalds's avatar Linus Torvalds

Import 1.2.1

parent 27c44f56
VERSION = 1 VERSION = 1
PATCHLEVEL = 2 PATCHLEVEL = 2
SUBLEVEL = 0 SUBLEVEL = 1
ARCH = i386 ARCH = i386
......
Linux kernel release 1.1.xx Linux kernel release 1.2.xx
These are the release notes for linux version 1.1. Read them carefully, These are the release notes for linux version 1.2. Read them carefully,
as they tell you what this is all about, explain how to install the as they tell you what this is all about, explain how to install the
kernel, and what to do if something goes wrong. kernel, and what to do if something goes wrong.
Warning: This is a work in progress. If you are not reasonably at ease with
the C programming language, GCC, installing Linux, and recovering from
system crashes, please use the 1.0 version, or wait for 1.2.
WHAT IS LINUX? WHAT IS LINUX?
Linux is a Unix clone for 386/486-based PCs written from scratch by Linux is a Unix clone for 386/486-based PCs written from scratch by
...@@ -23,12 +19,21 @@ WHAT IS LINUX? ...@@ -23,12 +19,21 @@ WHAT IS LINUX?
It is distributed under the GNU General Public License - see the It is distributed under the GNU General Public License - see the
accompanying COPYING file for more details. accompanying COPYING file for more details.
DOCUMENTATION:
- there is a lot of documentation available both in electronic form on
the internet and in books, both Linux-specific and pertaining to
general UNIX questions. I'd recommend looking into the documentation
subdirectories on any Linux ftp site for the LDP (Linux Documentation
Project) books. This README is not meant to be documentation on the
system: there are much better sources available.
INSTALLING the kernel: INSTALLING the kernel:
- If you install the full sources, do a - If you install the full sources, do a
cd /usr/src cd /usr/src
gzip -cd linux-1.1.XX.tar.gz | tar xfv - gzip -cd linux-1.2.XX.tar.gz | tar xfv -
to get it all put in place. Replace "XX" with the version number of the to get it all put in place. Replace "XX" with the version number of the
latest kernel. latest kernel.
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
OBJS := ll_rw_blk.o ramdisk.o genhd.o OBJS := ll_rw_blk.o ramdisk.o genhd.o
SRCS := ll_rw_blk.c ramdisk.c genhd.c SRCS := ll_rw_blk.c ramdisk.c genhd.c
BLOCK_MODULE_OBJS =
ifdef CONFIG_BLK_DEV_FD ifdef CONFIG_BLK_DEV_FD
OBJS := $(OBJS) floppy.o OBJS := $(OBJS) floppy.o
...@@ -47,6 +48,8 @@ endif ...@@ -47,6 +48,8 @@ endif
ifdef CONFIG_SBPCD ifdef CONFIG_SBPCD
OBJS := $(OBJS) sbpcd.o OBJS := $(OBJS) sbpcd.o
SRCS := $(SRCS) sbpcd.c SRCS := $(SRCS) sbpcd.c
else
BLOCK_MODULE_OBJS := $(BLOCK_MODULE_OBJS) sbpcd.o
endif #CONFIG_SBPCD endif #CONFIG_SBPCD
ifdef CONFIG_SBPCD2 ifdef CONFIG_SBPCD2
...@@ -82,6 +85,8 @@ endif ...@@ -82,6 +85,8 @@ endif
ifdef CONFIG_CDU535 ifdef CONFIG_CDU535
OBJS := $(OBJS) sonycd535.o OBJS := $(OBJS) sonycd535.o
SRCS := $(SRCS) sonycd535.c SRCS := $(SRCS) sonycd535.c
else
BLOCK_MODULE_OBJS := $(BLOCK_MODULE_OBJS) sonycd535.o
endif endif
all: block.a all: block.a
...@@ -94,7 +99,10 @@ block.a: $(OBJS) ...@@ -94,7 +99,10 @@ block.a: $(OBJS)
dep: dep:
$(CPP) -M $(SRCS) > .depend $(CPP) -M $(SRCS) > .depend
modules: modules: $(BLOCK_MODULE_OBJS)
echo $(BLOCK_MODULE_OBJS) > ../../modules/BLOCK_MODULES
(cd ../../modules;for i in $(BLOCK_MODULE_OBJS); do ln -sf ../drivers/block/$$i .; done)
dummy: dummy:
# #
......
README.ide -- Information regarding ide.c and ide-cd.c (IDE driver in 1.1.95) README.ide -- Information regarding ide.c and ide-cd.c (IDE driver in 1.2.x)
================================================================================ ================================================================================
Supported by: mlord@bnr.ca -- disks, interfaces, probing Supported by: mlord@bnr.ca -- disks, interfaces, probing
snyder@fnald0.fnal.gov -- cdroms, ATAPI, audio snyder@fnald0.fnal.gov -- cdroms, ATAPI, audio
...@@ -9,8 +9,8 @@ Major features of ide.c & ide-cd.c: ...@@ -9,8 +9,8 @@ Major features of ide.c & ide-cd.c:
- support for up to two IDE interfaces on one or two IRQs - support for up to two IDE interfaces on one or two IRQs
- support for any mix of up to four disk and/or cdrom drives - support for any mix of up to four disk and/or cdrom drives
- support for reading IDE ATAPI cdrom drives (NEC, MITSUMI, VERSA, SONY) - support for reading IDE ATAPI cdrom drives (NEC,MITSUMI,VERTOS,SONY)
- support for audio functions on FX400,NEC-260 cdrom drives (others?) - support for audio functions
- auto-detection of interfaces, drives, IRQs, and disk geometries - auto-detection of interfaces, drives, IRQs, and disk geometries
-- "single" drives should be jumpered as "master", not "slave" -- "single" drives should be jumpered as "master", not "slave"
- support for BIOSs which report "more than 16 heads" on disk drives - support for BIOSs which report "more than 16 heads" on disk drives
......
This README belongs to release 3.2 or newer of the SoundBlaster Pro This README belongs to release 3.4 or newer of the SoundBlaster Pro
(Matsushita, Kotobuki, Panasonic, CreativeLabs, Longshine and soon TEAC, too) (Matsushita, Kotobuki, Panasonic, CreativeLabs, Longshine and soon TEAC, too)
CD-ROM driver for Linux. CD-ROM driver for Linux.
...@@ -18,12 +18,14 @@ a soundcard). ...@@ -18,12 +18,14 @@ a soundcard).
The quad-speed TEAC CD-55A drive uses the same interface types, but has a The quad-speed TEAC CD-55A drive uses the same interface types, but has a
totally different command and flow control scheme. Support is under totally different command and flow control scheme. Support is under
construction. construction, but splitted: Greg Nowicki (nowicki@tardis.larc.nasa.gov)
cares about the separate driver "teaccd". Please, do not mail him merely for
asking "user questions" at the moment - the project is still a "baby".
CreativeLabs has a new drive "CD-200". Support is under construction. CreativeLabs has a new drive "CD-200". Support is under construction.
Detection should already work. Detection should already work.
Regarding CD200 and CD-55A support: Regarding CD200 support:
Please, don't mail me about it if you are not a competent BETA tester Please, don't mail me about it if you are not a competent BETA tester
(if you are: mail!; I do not have such drives). (if you are: mail!; I do not have such drives).
Please, don't drop simple questions about the new drives in the Please, don't drop simple questions about the new drives in the
...@@ -189,15 +191,27 @@ and see the contents of your CD in the /CD directory, and/or hear music with ...@@ -189,15 +191,27 @@ and see the contents of your CD in the /CD directory, and/or hear music with
"workman -c /dev/sbpcd &". "workman -c /dev/sbpcd &".
Using sbpcd as a "loadable module":
-----------------------------------
If you do NOT select "Matsushita/Panasonic CDROM driver support" during the
"make config" of your kernel, you can build the "loadable module" sbpcd.o.
Read /usr/src/linux/README.modules on this.
If sbpcd gets used as a module, the "audio copy" feature is disabled, and the
internal read-ahead buffer has a reduced size (the latter may affect throughput
a little bit under "slow" CPUs). Further, support of more than one interface
card (i.e. drives 4...15) is disabled.
Things of interest: Things of interest:
------------------- -------------------
The driver is configured to try the SoundBlaster Pro type of interface at The driver is configured to try the LaserMate type of interface at I/O port
I/O port 0x0230 first. If this is not appropriate, sbpcd.h should get changed 0x0340 first. If this is not appropriate, sbpcd.h should get changed
(you will find the right place - just at the beginning). (you will find the right place - just at the beginning).
No DMA and no IRQ is used, so the IRQ line stays free for the SB Pro sound No DMA and no IRQ is used.
drivers.
To reduce or increase the amount of kernel messages, edit sbpcd.c and play To reduce or increase the amount of kernel messages, edit sbpcd.c and play
with the "DBG_xxx" switches (initialization of the variable "sbpcd_debug"). with the "DBG_xxx" switches (initialization of the variable "sbpcd_debug").
...@@ -356,6 +370,20 @@ right setup. ...@@ -356,6 +370,20 @@ right setup.
For every-day use, address and type should get configured within sbpcd.h. That For every-day use, address and type should get configured within sbpcd.h. That
will stop the auto-probing due to success with the first try. will stop the auto-probing due to success with the first try.
The kernel command "sbpcd=0" suppresses each auto-probing and causes
the driver not to find any drive; it is meant for people who love sbpcd
so much that they do not want to miss it, even if they miss the drives. ;-)
If you configure "#define CDROM_PORT 0" in sbpcd.h, the auto-probing is
initially disabled and needs an explicit kernel command to get activated.
Once activated, it does not stop before success or end-of-list. This may be
useful within "universal" CDROM installation boot floppies (but using the
loadable module would be better because it allows an "extended" auto-probing
without fearing NE2000 cards).
To shorten the auto-probing list to a single entry, set DISTRIBUTION 0 within
sbpcd.c.
Setting up address and interface type: Setting up address and interface type:
-------------------------------------- --------------------------------------
...@@ -532,10 +560,8 @@ is an all-zero number. I guess now almost no CD holds such a number. ...@@ -532,10 +560,8 @@ is an all-zero number. I guess now almost no CD holds such a number.
Bug reports, comments, wishes, donations (technical information is a donation, Bug reports, comments, wishes, donations (technical information is a donation,
too :-) etc. to too :-) etc. to
emoenke@gwdg.de emoenke@gwdg.de
or to eberhard_moenkeberg@rollo.central.de
or to my FIDO address: Eberhard Moenkeberg, 2:2437/210.27 or to my FIDO address: Eberhard Moenkeberg, 2:2437/210.27
SnailMail address, preferable for CD editors if they want to submit a free SnailMail address, preferable for CD editors if they want to submit a free
"cooperation" copy: "cooperation" copy:
Eberhard Moenkeberg Eberhard Moenkeberg
......
/* /*
* linux/drivers/block/ide.c Version 3.13 February 23, 1995 * linux/drivers/block/ide.c Version 3.14 March 7, 1995
* *
* Copyright (C) 1994, 1995 Linus Torvalds & authors (see below) * Copyright (C) 1994, 1995 Linus Torvalds & authors (see below)
*/ */
...@@ -104,6 +104,9 @@ ...@@ -104,6 +104,9 @@
* Version 3,12 simplify logic for selecting initial mult_count * Version 3,12 simplify logic for selecting initial mult_count
* (fixes problems with buggy WD drives) * (fixes problems with buggy WD drives)
* Version 3.13 remove excess "multiple mode disabled" messages * Version 3.13 remove excess "multiple mode disabled" messages
* Version 3.14 fix ide_error() handling of BUSY_STAT
* fix byte-swapped cdrom strings (again.. arghh!)
* ignore INDEX bit when checking the ALTSTATUS reg
* *
* To do: * To do:
* - special 32-bit controller-type detection & support * - special 32-bit controller-type detection & support
...@@ -612,17 +615,21 @@ static void ide_error (ide_dev_t *dev, const char *msg, byte stat) ...@@ -612,17 +615,21 @@ static void ide_error (ide_dev_t *dev, const char *msg, byte stat)
return; return;
} }
#endif /* IDE_DRIVE_CMD */ #endif /* IDE_DRIVE_CMD */
if (dev->type == disk && (stat & ERR_STAT)) { if (stat & BUSY_STAT) { /* other bits are useless when BUSY */
/* err has different meaning on cdrom */ rq->errors |= ERROR_RESET;
if (err & BBD_ERR) /* retries won't help this! */ } else {
rq->errors = ERROR_MAX; if (dev->type == disk && (stat & ERR_STAT)) {
else if (err & TRK0_ERR) /* help it find track zero */ /* err has different meaning on cdrom */
rq->errors |= ERROR_RECAL; if (err & BBD_ERR) /* retries won't help this! */
} rq->errors = ERROR_MAX;
if ((stat & DRQ_STAT) && rq->cmd == READ) { else if (err & TRK0_ERR) /* help it find track zero */
int i = dev->mult_count ? dev->mult_count<<8 : 1<<8; rq->errors |= ERROR_RECAL;
while (i-- > 0) /* try to flush data */ }
(void) IN_BYTE(HD_DATA, dev->hwif); if ((stat & DRQ_STAT) && rq->cmd == READ) {
int i = dev->mult_count ? dev->mult_count<<8 : 1<<8;
while (i-- > 0) /* try to flush data */
(void) IN_BYTE(HD_DATA, dev->hwif);
}
} }
if (GET_STAT(dev->hwif) & (BUSY_STAT|DRQ_STAT)) if (GET_STAT(dev->hwif) & (BUSY_STAT|DRQ_STAT))
rq->errors |= ERROR_RESET; /* Mmmm.. timing problem */ rq->errors |= ERROR_RESET; /* Mmmm.. timing problem */
...@@ -1612,9 +1619,14 @@ static void do_identify (ide_dev_t *dev, byte cmd) ...@@ -1612,9 +1619,14 @@ static void do_identify (ide_dev_t *dev, byte cmd)
/* /*
* WIN_IDENTIFY returns little-endian info, * WIN_IDENTIFY returns little-endian info,
* WIN_PIDENTIFY return big-endian info. * WIN_PIDENTIFY *usually* returns little-endian info.
*/ */
bswap = (cmd == WIN_IDENTIFY); bswap = 1;
if (cmd == WIN_PIDENTIFY) {
if ((id->model[0] == 'N' && id->model[1] == 'E')
|| (id->model[0] == 'F' && id->model[1] == 'X'))
bswap = 0; /* NEC and *some* Mitsumi units */
} /* Vertos drives may still be weird */
fixstring (id->model, sizeof(id->model), bswap); fixstring (id->model, sizeof(id->model), bswap);
fixstring (id->fw_rev, sizeof(id->fw_rev), bswap); fixstring (id->fw_rev, sizeof(id->fw_rev), bswap);
fixstring (id->serial_no, sizeof(id->serial_no), bswap); fixstring (id->serial_no, sizeof(id->serial_no), bswap);
...@@ -1738,10 +1750,11 @@ static int try_to_identify (ide_dev_t *dev, byte cmd) ...@@ -1738,10 +1750,11 @@ static int try_to_identify (ide_dev_t *dev, byte cmd)
} }
#endif /* PROBE_FOR_IRQS */ #endif /* PROBE_FOR_IRQS */
delay_10ms(); /* take a deep breath */ delay_10ms(); /* take a deep breath */
if (IN_BYTE(HD_ALTSTATUS,DEV_HWIF) == IN_BYTE(HD_STATUS,DEV_HWIF)) if ((IN_BYTE(HD_ALTSTATUS,DEV_HWIF) ^ IN_BYTE(HD_STATUS,DEV_HWIF)) & ~INDEX_STAT) {
hd_status = HD_ALTSTATUS; /* use non-intrusive polling */
else
hd_status = HD_STATUS; /* an ancient Seagate drive */ hd_status = HD_STATUS; /* an ancient Seagate drive */
printk("%s: probing with STATUS instead of ALTSTATUS\n", dev->name);
} else
hd_status = HD_ALTSTATUS; /* use non-intrusive polling */
OUT_BYTE(cmd,HD_COMMAND); /* ask drive for ID */ OUT_BYTE(cmd,HD_COMMAND); /* ask drive for ID */
timeout = ((cmd == WIN_IDENTIFY) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2; timeout = ((cmd == WIN_IDENTIFY) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2;
timeout += jiffies; timeout += jiffies;
......
...@@ -6,10 +6,11 @@ ...@@ -6,10 +6,11 @@
* Panasonic CI-101P. * Panasonic CI-101P.
* Also for the Longshine LCS-7260 drive. * Also for the Longshine LCS-7260 drive.
* Also for the IBM "External ISA CD-Rom" drive. * Also for the IBM "External ISA CD-Rom" drive.
* Not for the TEAC CD-55A drive (yet). * Still not for the CreativeLabs CD200 drive (but should work soon).
* Not for the CreativeLabs CD200 drive (who knows?). * Not for the TEAC CD-55A drive (separate project now).
* Not for Funai or Sanyo drives.
* *
* NOTE: This is release 3.3. * NOTE: This is release 3.4.
* It works with my SbPro & drive CR-521 V2.11 from 2/92 * It works with my SbPro & drive CR-521 V2.11 from 2/92
* and with the CR-562-B V0.75 on a "naked" Panasonic * and with the CR-562-B V0.75 on a "naked" Panasonic
* CI-101P interface. And vice versa. * CI-101P interface. And vice versa.
...@@ -180,6 +181,12 @@ ...@@ -180,6 +181,12 @@
* *
* 3.3 Working with CD200 support. Maybe a simple read is already possible. * 3.3 Working with CD200 support. Maybe a simple read is already possible.
* *
* 3.4 Auto-probing stops if an address of 0 is seen (to be entered with
* the kernel command line).
* Made the driver "loadable". If used as a module, "audio copy" is
* disabled, and the internal read ahead data buffer has a reduced size
* of 4 kB; so, throughput may be reduced a little bit with slow CPUs.
*
* TODO * TODO
* *
* disk change detection * disk change detection
...@@ -196,7 +203,6 @@ ...@@ -196,7 +203,6 @@
* *
* *
* Copyright (C) 1993, 1994, 1995 Eberhard Moenkeberg <emoenke@gwdg.de> * Copyright (C) 1993, 1994, 1995 Eberhard Moenkeberg <emoenke@gwdg.de>
* or <eberhard_moenkeberg@rollo.central.de>
* *
* If you change this software, you should mail a .diff * If you change this software, you should mail a .diff
* file with some description lines to emoenke@gwdg.de. * file with some description lines to emoenke@gwdg.de.
...@@ -224,9 +230,17 @@ ...@@ -224,9 +230,17 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/errno.h> #include <linux/errno.h>
#ifdef MODULE
#include <linux/malloc.h>
#include <linux/module.h>
#include <linux/version.h>
#ifndef CONFIG_MODVERSIONS
char kernel_version[]=UTS_RELEASE;
#endif
#endif MODULE
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/mm.h> #include <linux/mm.h>
/* #undef DS */
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -253,18 +267,19 @@ ...@@ -253,18 +267,19 @@
#define MAJOR_NR MATSUSHITA_CDROM4_MAJOR /* fourth driver issue */ #define MAJOR_NR MATSUSHITA_CDROM4_MAJOR /* fourth driver issue */
#endif #endif
#ifdef MODULE
#include "/usr/src/linux/drivers/block/blk.h"
#else
#include "blk.h" #include "blk.h"
#define MOD_INC_USE_COUNT
#define MOD_DEC_USE_COUNT
#endif MODULE
#define VERSION "3.3 Eberhard Moenkeberg <emoenke@gwdg.de>" #define VERSION "3.4 Eberhard Moenkeberg <emoenke@gwdg.de>"
/* /*
* still testing around... *
*/ */
#define TEAC 0 /* set to 1 for TEAC CD-55A detection test (not more) */
#define MULTISESSION_BY_DRIVER 0 /* if set to 0 here, we need the counterpart
* in linux/fs/isofs/inode.c
*/
#define READ_AUDIO 4 /* max. number of audio frames to read with one */ #define READ_AUDIO 4 /* max. number of audio frames to read with one */
/* request (allocates n* 2352 bytes kernel memory!) */ /* request (allocates n* 2352 bytes kernel memory!) */
#define JUKEBOX 1 /* tray control: eject tray if no disk is in */ #define JUKEBOX 1 /* tray control: eject tray if no disk is in */
...@@ -368,18 +383,18 @@ static int sbpcd_probe[] = ...@@ -368,18 +383,18 @@ static int sbpcd_probe[] =
/* due to incomplete address decoding of the SbPro card, these must be last */ /* due to incomplete address decoding of the SbPro card, these must be last */
0x630, 0, /* "sound card #9" (default) */ 0x630, 0, /* "sound card #9" (default) */
0x650, 0, /* "sound card #9" */ 0x650, 0, /* "sound card #9" */
#ifdef MODULE
/* /*
* some "hazardous" locations * some "hazardous" locations (no harm with the loadable version)
* (will stop the bus if a NE2000 ethernet card resides at offset -0x10) * (will stop the bus if a NE2000 ethernet card resides at offset -0x10)
*/ */
#if 0
0x330, 0, /* Lasermate, CI-101P, WDH-7001C */ 0x330, 0, /* Lasermate, CI-101P, WDH-7001C */
0x350, 0, /* Lasermate, CI-101P */ 0x350, 0, /* Lasermate, CI-101P */
0x350, 2, /* SPEA Media FX */ 0x350, 2, /* SPEA Media FX */
0x370, 0, /* Lasermate, CI-101P */ 0x370, 0, /* Lasermate, CI-101P */
0x290, 1, /* Soundblaster 16 */ 0x290, 1, /* Soundblaster 16 */
0x310, 0, /* Lasermate, CI-101P, WDH-7001C */ 0x310, 0, /* Lasermate, CI-101P, WDH-7001C */
#endif #endif MODULE
#endif DISTRIBUTION #endif DISTRIBUTION
}; };
#else #else
...@@ -448,7 +463,6 @@ static int sbpcd_chk_disk_change(dev_t); ...@@ -448,7 +463,6 @@ static int sbpcd_chk_disk_change(dev_t);
* (1<<DBG_AUD) "read audio" debugging * (1<<DBG_AUD) "read audio" debugging
* (1<<DBG_SEQ) Sequoia interface configuration trace * (1<<DBG_SEQ) Sequoia interface configuration trace
* (1<<DBG_LCS) Longshine LCS-7260 debugging trace * (1<<DBG_LCS) Longshine LCS-7260 debugging trace
* (1<<DBG_TEA) TEAC CD-55A debugging trace
* (1<<DBG_CD2) MKE CD200 debugging trace * (1<<DBG_CD2) MKE CD200 debugging trace
* (1<<DBG_000) unnecessary information * (1<<DBG_000) unnecessary information
*/ */
...@@ -480,8 +494,10 @@ static struct cdrom_read_audio read_audio; ...@@ -480,8 +494,10 @@ static struct cdrom_read_audio read_audio;
static struct cdrom_multisession ms_info; static struct cdrom_multisession ms_info;
static char *str_sb = "SoundBlaster"; static char *str_sb = "SoundBlaster";
static char *str_sb_l = "soundblaster";
static char *str_lm = "LaserMate"; static char *str_lm = "LaserMate";
static char *str_sp = "SPEA"; static char *str_sp = "SPEA";
static char *str_sp_l = "spea";
char *type; char *type;
#if !(SBPCD_ISSUE-1) #if !(SBPCD_ISSUE-1)
static char *major_name="sbpcd"; static char *major_name="sbpcd";
...@@ -503,16 +519,20 @@ static struct wait_queue *sbp_waitq = NULL; ...@@ -503,16 +519,20 @@ static struct wait_queue *sbp_waitq = NULL;
#endif FUTURE #endif FUTURE
/*==========================================================================*/ /*==========================================================================*/
#ifdef MODULE
/* some restrictions for the "loadable" version */
#define SBP_BUFFER_FRAMES 2 /* kmalloc() limit */
#define SBP_BUFFER_AUDIO_FRAMES 0
#else
#define SBP_BUFFER_FRAMES 4 /* driver's own read_ahead, data mode */ #define SBP_BUFFER_FRAMES 4 /* driver's own read_ahead, data mode */
#define SBP_BUFFER_AUDIO_FRAMES READ_AUDIO /* buffer for read audio mode */ #define SBP_BUFFER_AUDIO_FRAMES READ_AUDIO /* buffer for read audio mode */
#endif MODULE
/*==========================================================================*/ /*==========================================================================*/
static u_char family0[]="MATSHITA"; /* MKE CR-52x */ static u_char family0[]="MATSHITA"; /* MKE CR-52x */
static u_char family1[]="CR-56"; /* MKE CR-56x */ static u_char family1[]="CR-56"; /* MKE CR-56x */
static u_char family2[]="CD200"; /* MKE CD200 */ static u_char family2[]="CD200"; /* MKE CD200 */
static u_char familyL[]="LCS-7260"; /* Longshine LCS-7260 */ static u_char familyL[]="LCS-7260"; /* Longshine LCS-7260 */
static u_char familyT[]="CD-55A"; /* TEAC CD-55A (still unknown)*/
static u_int response_count=0; static u_int response_count=0;
static u_int flags_cmd_out; static u_int flags_cmd_out;
...@@ -580,9 +600,6 @@ static struct { ...@@ -580,9 +600,6 @@ static struct {
u_char f_multisession; u_char f_multisession;
u_int lba_multi; u_int lba_multi;
#if MULTISESSION_BY_DRIVER
u_int last_redirect;
#endif MULTISESSION_BY_DRIVER
int first_session; int first_session;
int last_session; int last_session;
...@@ -829,6 +846,10 @@ static void flush_status(void) ...@@ -829,6 +846,10 @@ static void flush_status(void)
#ifdef CDMKE #ifdef CDMKE
int i; int i;
#ifdef MODULE
sbp_sleep(150);
for (i=maxtim_data;i!=0;i--) inb(CDi_status);
#else
if (current == task[0]) if (current == task[0])
for (i=maxtim02;i!=0;i--) inb(CDi_status); for (i=maxtim02;i!=0;i--) inb(CDi_status);
else else
...@@ -836,6 +857,7 @@ static void flush_status(void) ...@@ -836,6 +857,7 @@ static void flush_status(void)
sbp_sleep(150); sbp_sleep(150);
for (i=maxtim_data;i!=0;i--) inb(CDi_status); for (i=maxtim_data;i!=0;i--) inb(CDi_status);
} }
#endif MODULE
#else #else
timed_out=0; timed_out=0;
#if 0 #if 0
...@@ -857,6 +879,20 @@ static int CDi_stat_loop(void) ...@@ -857,6 +879,20 @@ static int CDi_stat_loop(void)
int i,j; int i,j;
u_long timeout; u_long timeout;
#ifdef MODULE
for(timeout = jiffies + 1000, i=maxtim_data; timeout > jiffies; )
{
for ( ;i!=0;i--)
{
j=inb(CDi_status);
if (!(j&s_not_data_ready)) return (j);
if (!(j&s_not_result_ready)) return (j);
if (fam0L_drive) if (j&s_attention) return (j);
}
sbp_sleep(1);
i = 1;
}
#else
if (current == task[0]) if (current == task[0])
for(i=maxtim16;i!=0;i--) for(i=maxtim16;i!=0;i--)
{ {
...@@ -878,47 +914,35 @@ static int CDi_stat_loop(void) ...@@ -878,47 +914,35 @@ static int CDi_stat_loop(void)
sbp_sleep(1); sbp_sleep(1);
i = 1; i = 1;
} }
#endif MODULE
DPRINTF((DBG_LCS,"SBPCD: CDi_stat_loop failed\n")); DPRINTF((DBG_LCS,"SBPCD: CDi_stat_loop failed\n"));
return (-1); return (-1);
} }
/*==========================================================================*/ /*==========================================================================*/
#if TEAC-X
/*==========================================================================*/
static int tst_DataReady(void)
{
int i;
i=inb(CDi_status);
if (i&s_not_data_ready) return (0);
return (1);
}
/*==========================================================================*/
static int tst_ResultReady(void)
{
int i;
i=inb(CDi_status);
if (i&s_not_result_ready) return (0);
return (1);
}
/*==========================================================================*/
static int tst_Attention(void)
{
int i;
i=inb(CDi_status);
if (i&s_attention) return (1);
return (0);
}
/*==========================================================================*/
#endif TEAC-X
/*==========================================================================*/
static int ResponseInfo(void) static int ResponseInfo(void)
{ {
int i,j, st=0; int i,j, st=0;
u_long timeout; u_long timeout;
DPRINTF((DBG_000,"SBPCD: ResponseInfo entered.\n")); DPRINTF((DBG_000,"SBPCD: ResponseInfo entered.\n"));
#ifdef MODULE
for (i=0, timeout = jiffies + 100; i < response_count; i++)
{
for (j=maxtim_data; ; )
{
for ( ;j!=0;j-- )
{
st=inb(CDi_status);
if (!(st&s_not_result_ready)) break;
}
if (j != 0 || timeout <= jiffies) break;
sbp_sleep(0);
j = 1;
}
if (timeout <= jiffies) return (-1);
infobuf[i]=inb(CDi_info);
}
#else
if (current == task[0]) if (current == task[0])
for (i=0;i<response_count;i++) for (i=0;i<response_count;i++)
{ {
...@@ -953,15 +977,16 @@ static int ResponseInfo(void) ...@@ -953,15 +977,16 @@ static int ResponseInfo(void)
infobuf[i]=inb(CDi_info); infobuf[i]=inb(CDi_info);
} }
} }
#endif MODULE
DPRINTF((DBG_000,"SBPCD: ResponseInfo: done.\n")); DPRINTF((DBG_000,"SBPCD: ResponseInfo: done.\n"));
return (0); return (0);
} }
/*==========================================================================*/ /*==========================================================================*/
static int EvaluateStatus(int st) static void EvaluateStatus(int st)
{ {
DriveStruct[d].status_byte=0;
if (fam0_drive) if (fam0_drive)
{ {
DriveStruct[d].status_byte=0;
if (st&p_caddin_old) DriveStruct[d].status_byte |= p_door_closed|p_caddy_in; if (st&p_caddin_old) DriveStruct[d].status_byte |= p_door_closed|p_caddy_in;
if (st&p_spinning) DriveStruct[d].status_byte |= p_spinning; if (st&p_spinning) DriveStruct[d].status_byte |= p_spinning;
if (st&p_check) DriveStruct[d].status_byte |= p_check; if (st&p_check) DriveStruct[d].status_byte |= p_check;
...@@ -970,23 +995,26 @@ static int EvaluateStatus(int st) ...@@ -970,23 +995,26 @@ static int EvaluateStatus(int st)
} }
else if (famL_drive) else if (famL_drive)
{ {
DriveStruct[d].status_byte=0;
if (st&p_caddin_old) DriveStruct[d].status_byte |= p_disk_ok|p_caddy_in; if (st&p_caddin_old) DriveStruct[d].status_byte |= p_disk_ok|p_caddy_in;
if (st&p_spinning) DriveStruct[d].status_byte |= p_spinning; if (st&p_spinning) DriveStruct[d].status_byte |= p_spinning;
if (st&p_check) DriveStruct[d].status_byte |= p_check; if (st&p_check) DriveStruct[d].status_byte |= p_check;
if (st&p_busy_old) DriveStruct[d].status_byte |= p_busy_new; if (st&p_busy_old) DriveStruct[d].status_byte |= p_busy_new;
if (st&p_lcs_door_closed) DriveStruct[d].status_byte |= p_door_closed; if (st&p_lcs_door_closed) DriveStruct[d].status_byte |= p_door_closed;
if (st&p_lcs_door_locked) DriveStruct[d].status_byte |= p_door_locked; if (st&p_lcs_door_locked) DriveStruct[d].status_byte |= p_door_locked;
}
else if (fam1_drive)
{
DriveStruct[d].status_byte=st;
st=p_success_old; /* for new drives: fake "successful" bit of old drives */
} }
else /* CD200, CD-55A */ else if (fam2_drive)
{ {
if (st&p2_check) DriveStruct[d].status_byte |= p1_check;
if (st&p2_door_closed) DriveStruct[d].status_byte |= p1_door_closed;
if (st&p2_disk_in) DriveStruct[d].status_byte |= p1_disk_in;
if (st&p2_busy1) DriveStruct[d].status_byte |= p1_busy;
if (st&p2_busy2) DriveStruct[d].status_byte |= p1_busy;
if (st&p2_spinning) DriveStruct[d].status_byte |= p1_spinning;
if (st&p2_door_locked) DriveStruct[d].status_byte |= p1_door_locked;
if (st&p2_disk_ok) DriveStruct[d].status_byte |= p1_disk_ok;
} }
return (st); else if (fam1_drive) DriveStruct[d].status_byte=st;
return;
} }
/*==========================================================================*/ /*==========================================================================*/
static int ResponseStatus(void) static int ResponseStatus(void)
...@@ -995,7 +1023,24 @@ static int ResponseStatus(void) ...@@ -995,7 +1023,24 @@ static int ResponseStatus(void)
u_long timeout; u_long timeout;
DPRINTF((DBG_STA,"SBPCD: doing ResponseStatus...\n")); DPRINTF((DBG_STA,"SBPCD: doing ResponseStatus...\n"));
#ifdef MODULE
if (flags_cmd_out & f_respo3) timeout = jiffies;
else if (flags_cmd_out & f_respo2) timeout = jiffies + 1600;
else timeout = jiffies + 400;
j=maxtim_8;
do
{
for ( ;j!=0;j--)
{
i=inb(CDi_status);
if (!(i&s_not_result_ready)) break;
}
if (j != 0 || timeout <= jiffies) break;
sbp_sleep(0);
j = 1;
}
while (1);
#else
if (current == task[0]) if (current == task[0])
{ {
if (flags_cmd_out & f_respo3) j = maxtim_8; if (flags_cmd_out & f_respo3) j = maxtim_8;
...@@ -1026,16 +1071,17 @@ static int ResponseStatus(void) ...@@ -1026,16 +1071,17 @@ static int ResponseStatus(void)
} }
while (1); while (1);
} }
#endif MODULE
if (j==0) if (j==0)
{ if ((flags_cmd_out & f_respo3) == 0) { if ((flags_cmd_out & f_respo3) == 0)
DPRINTF((DBG_STA,"SBPCD: ResponseStatus: timeout.\n")); DPRINTF((DBG_STA,"SBPCD: ResponseStatus: timeout.\n"));
EvaluateStatus(0); DriveStruct[d].status_byte=0;
return (-1); return (-1);
} }
i=inb(CDi_info); i=inb(CDi_info);
DPRINTF((DBG_STA,"SBPCD: ResponseStatus: response %2X.\n", i)); DPRINTF((DBG_STA,"SBPCD: ResponseStatus: response %2X.\n", i));
i=EvaluateStatus(i); EvaluateStatus(i);
return (i); return (0);
} }
/*==========================================================================*/ /*==========================================================================*/
static void xx_ReadStatus(void) static void xx_ReadStatus(void)
...@@ -1046,9 +1092,7 @@ static void xx_ReadStatus(void) ...@@ -1046,9 +1092,7 @@ static void xx_ReadStatus(void)
SBPCD_CLI; SBPCD_CLI;
if (fam0L_drive) OUT(CDo_command,CMD0_STATUS); if (fam0L_drive) OUT(CDo_command,CMD0_STATUS);
else if (fam1_drive) OUT(CDo_command,CMD1_STATUS); else if (fam1_drive) OUT(CDo_command,CMD1_STATUS);
else /* CD200, CD-55A */ else if (fam2_drive) OUT(CDo_command,CMD2_STATUS);
{
}
if (!fam0L_drive) for (i=0;i<6;i++) OUT(CDo_command,0); if (!fam0L_drive) for (i=0;i<6;i++) OUT(CDo_command,0);
SBPCD_STI; SBPCD_STI;
} }
...@@ -1080,13 +1124,6 @@ static int xx_ReadError(void) ...@@ -1080,13 +1124,6 @@ static int xx_ReadError(void)
response_count=6; response_count=6;
flags_cmd_out=f_putcmd; flags_cmd_out=f_putcmd;
} }
else /* CD-55A */
{
return (-1);
drvcmd[0]=CMDT_READ_ERR;
response_count=5;
flags_cmd_out=f_putcmd;
}
i=cmd_out(7); i=cmd_out(7);
DriveStruct[d].error_byte=0; DriveStruct[d].error_byte=0;
DPRINTF((DBG_ERR,"SBPCD: xx_ReadError: cmd_out(82) returns %d (%02X)\n",i,i)); DPRINTF((DBG_ERR,"SBPCD: xx_ReadError: cmd_out(82) returns %d (%02X)\n",i,i));
...@@ -1201,10 +1238,6 @@ static int xx_Seek(u_int pos, char f_blk_msf) ...@@ -1201,10 +1238,6 @@ static int xx_Seek(u_int pos, char f_blk_msf)
drvcmd[5]=pos&0x00FF; drvcmd[5]=pos&0x00FF;
flags_cmd_out=f_putcmd|f_ResponseStatus; flags_cmd_out=f_putcmd|f_ResponseStatus;
} }
else /* CD-55A */
{
return (-1);
}
response_count=0; response_count=0;
i=cmd_out(7); i=cmd_out(7);
return (i); return (i);
...@@ -1234,10 +1267,6 @@ static int xx_SpinUp(void) ...@@ -1234,10 +1267,6 @@ static int xx_SpinUp(void)
drvcmd[4]=0x01; drvcmd[4]=0x01;
flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check; flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
} }
else /* CD-55A */
{
return (-1);
}
response_count=0; response_count=0;
i=cmd_out(7); i=cmd_out(7);
DriveStruct[d].in_SpinUp = 0; DriveStruct[d].in_SpinUp = 0;
...@@ -1268,10 +1297,6 @@ static int yy_SpinDown(void) ...@@ -1268,10 +1297,6 @@ static int yy_SpinDown(void)
drvcmd[1]=1; drvcmd[1]=1;
flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1; flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
} }
else /* CD-55A */
{
return (-1);
}
i=cmd_out(7); i=cmd_out(7);
return (i); return (i);
} }
...@@ -1307,10 +1332,6 @@ static int yy_SetSpeed(u_char speed, u_char x1, u_char x2) ...@@ -1307,10 +1332,6 @@ static int yy_SetSpeed(u_char speed, u_char x1, u_char x2)
} }
flags_cmd_out=f_putcmd|f_ResponseStatus; flags_cmd_out=f_putcmd|f_ResponseStatus;
} }
else /* CD-55A */
{
return (-1);
}
i=cmd_out(7); i=cmd_out(7);
return (i); return (i);
} }
...@@ -1462,10 +1483,6 @@ static int xx_SetVolume(void) ...@@ -1462,10 +1483,6 @@ static int xx_SetVolume(void)
drvcmd[5]=value0; drvcmd[5]=value0;
flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check; flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
} }
else /* CD-55A */
{
return (-1);
}
response_count=0; response_count=0;
i=cmd_out(7); i=cmd_out(7);
if (i>0) return (i); if (i>0) return (i);
...@@ -1505,10 +1522,6 @@ static int xy_DriveReset(void) ...@@ -1505,10 +1522,6 @@ static int xy_DriveReset(void)
i=cmd_out(7); i=cmd_out(7);
OUT(CDo_reset,0x00); OUT(CDo_reset,0x00);
} }
else /* CD-55A */
{
return (-1);
}
if (famL_drive) sbp_sleep(500); /* wait 5 seconds */ if (famL_drive) sbp_sleep(500); /* wait 5 seconds */
else sbp_sleep(100); /* wait a second */ else sbp_sleep(100); /* wait a second */
flush_status(); flush_status();
...@@ -1586,10 +1599,6 @@ static int xx_Pause_Resume(int pau_res) ...@@ -1586,10 +1599,6 @@ static int xx_Pause_Resume(int pau_res)
flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus| flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|
f_obey_p_check; f_obey_p_check;
} }
else /* CD-55A */
{
return (-1);
}
i=cmd_out(7); i=cmd_out(7);
return (i); return (i);
} }
...@@ -1621,10 +1630,6 @@ static int yy_LockDoor(char lock) ...@@ -1621,10 +1630,6 @@ static int yy_LockDoor(char lock)
if (lock==1) drvcmd[1]=0x01; if (lock==1) drvcmd[1]=0x01;
flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1; flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
} }
else /* CD-55A */
{
return (-1);
}
i=cmd_out(7); i=cmd_out(7);
DPRINTF((DBG_LCS,"SBPCD: p_door_locked bit %d after\n", st_door_locked)); DPRINTF((DBG_LCS,"SBPCD: p_door_locked bit %d after\n", st_door_locked));
return (i); return (i);
...@@ -1658,10 +1663,6 @@ static int yy_CloseTray(void) ...@@ -1658,10 +1663,6 @@ static int yy_CloseTray(void)
flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta| flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|
f_ResponseStatus|f_obey_p_check|f_bit1; f_ResponseStatus|f_obey_p_check|f_bit1;
} }
else /* CD-55A */
{
return (-1);
}
i=cmd_out(7); i=cmd_out(7);
DPRINTF((DBG_LCS,"SBPCD: p_door_closed bit %d after\n", st_door_closed)); DPRINTF((DBG_LCS,"SBPCD: p_door_closed bit %d after\n", st_door_closed));
return (i); return (i);
...@@ -1699,10 +1700,6 @@ static int xx_ReadSubQ(void) ...@@ -1699,10 +1700,6 @@ static int xx_ReadSubQ(void)
flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check; flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
response_count=13; response_count=13;
} }
else /* CD-55A */
{
return (-1);
}
i=cmd_out(7); i=cmd_out(7);
if (i<0) return (i); if (i<0) return (i);
DPRINTF((DBG_SQ,"SBPCD: xx_ReadSubQ:")); DPRINTF((DBG_SQ,"SBPCD: xx_ReadSubQ:"));
...@@ -1755,18 +1752,11 @@ static int xx_ModeSense(void) ...@@ -1755,18 +1752,11 @@ static int xx_ModeSense(void)
flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check; flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
response_count=2; response_count=2;
} }
else /* CD-55A */
{
return (-1);
}
i=cmd_out(7); i=cmd_out(7);
if (i<0) return (i); if (i<0) return (i);
i=0; i=0;
if (fam1_drive) DriveStruct[d].sense_byte=infobuf[i++]; if (fam1_drive) DriveStruct[d].sense_byte=infobuf[i++];
else if (fam0L_drive) DriveStruct[d].sense_byte=0; else if (fam0L_drive) DriveStruct[d].sense_byte=0;
else /* CD-55A */
{
}
DriveStruct[d].frame_size=make16(infobuf[i],infobuf[i+1]); DriveStruct[d].frame_size=make16(infobuf[i],infobuf[i+1]);
DPRINTF((DBG_XA,"SBPCD: xx_ModeSense: ")); DPRINTF((DBG_XA,"SBPCD: xx_ModeSense: "));
...@@ -1816,10 +1806,6 @@ static int xx_ModeSelect(int framesize) ...@@ -1816,10 +1806,6 @@ static int xx_ModeSelect(int framesize)
else else
flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check; flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
} }
else /* CD-55A */
{
return (-1);
}
response_count=0; response_count=0;
i=cmd_out(7); i=cmd_out(7);
if (i<0) return (i); if (i<0) return (i);
...@@ -1860,10 +1846,6 @@ static int xx_TellVolume(void) ...@@ -1860,10 +1846,6 @@ static int xx_TellVolume(void)
else else
flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check; flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
} }
else /* CD-55A */
{
return (-1);
}
i=cmd_out(7); i=cmd_out(7);
if (i<0) return (i); if (i<0) return (i);
if (fam1_drive) if (fam1_drive)
...@@ -1931,10 +1913,6 @@ static int xx_TellVolume(void) ...@@ -1931,10 +1913,6 @@ static int xx_TellVolume(void)
} }
} }
} }
else /* CD-55A */
{
return (-1);
}
DriveStruct[d].vol_chan0=chan0; DriveStruct[d].vol_chan0=chan0;
DriveStruct[d].vol_ctrl0=vol0; DriveStruct[d].vol_ctrl0=vol0;
DriveStruct[d].vol_chan1=chan1; DriveStruct[d].vol_chan1=chan1;
...@@ -1976,10 +1954,6 @@ static int xx_ReadCapacity(void) ...@@ -1976,10 +1954,6 @@ static int xx_ReadCapacity(void)
else else
flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check; flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
} }
else /* CD-55A */
{
return (-1);
}
i=cmd_out(7); i=cmd_out(7);
if (i<0) return (i); if (i<0) return (i);
if (fam1_drive) DriveStruct[d].CDsize_frm=msf2blk(make32(make16(0,infobuf[0]),make16(infobuf[1],infobuf[2])))+CD_BLOCK_OFFSET; if (fam1_drive) DriveStruct[d].CDsize_frm=msf2blk(make32(make16(0,infobuf[0]),make16(infobuf[1],infobuf[2])))+CD_BLOCK_OFFSET;
...@@ -2021,10 +1995,6 @@ static int xx_ReadTocDescr(void) ...@@ -2021,10 +1995,6 @@ static int xx_ReadTocDescr(void)
response_count=8; response_count=8;
flags_cmd_out=f_putcmd; flags_cmd_out=f_putcmd;
} }
else /* CD-55A */
{
return (-1);
}
i=cmd_out(7); i=cmd_out(7);
if (i<0) return (i); if (i<0) return (i);
DriveStruct[d].xa_byte=infobuf[0]; DriveStruct[d].xa_byte=infobuf[0];
...@@ -2117,10 +2087,6 @@ static int xx_ReadTocEntry(int num) ...@@ -2117,10 +2087,6 @@ static int xx_ReadTocEntry(int num)
else else
flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check; flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
} }
else /* CD-55A */
{
return (-1);
}
drvcmd[2]=num; drvcmd[2]=num;
i=cmd_out(7); i=cmd_out(7);
if (i<0) return (i); if (i<0) return (i);
...@@ -2159,10 +2125,7 @@ static int xx_ReadPacket(void) ...@@ -2159,10 +2125,7 @@ static int xx_ReadPacket(void)
flags_cmd_out=f_putcmd; flags_cmd_out=f_putcmd;
else if (fam01_drive) else if (fam01_drive)
flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check; flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
else /* CD200, CD-55A */ else if (fam2_drive) return (-1); /* not implemented yet */
{
return (-1);
}
i=cmd_out(7); i=cmd_out(7);
return (i); return (i);
} }
...@@ -2181,7 +2144,7 @@ static int convert_UPC(u_char *p) ...@@ -2181,7 +2144,7 @@ static int convert_UPC(u_char *p)
DriveStruct[d].UPC_buf[i]=((*p++)<<4)&0xFF; DriveStruct[d].UPC_buf[i]=((*p++)<<4)&0xFF;
DriveStruct[d].UPC_buf[i] |= *p++; DriveStruct[d].UPC_buf[i] |= *p++;
} }
else /* CD200, CD-55A */ else /* CD200 */
{ {
return (-1); return (-1);
} }
...@@ -2197,6 +2160,8 @@ static int xx_ReadUPC(void) ...@@ -2197,6 +2160,8 @@ static int xx_ReadUPC(void)
int block, checksum; int block, checksum;
#endif TEST_UPC #endif TEST_UPC
if (fam2_drive) return (0); /* not implemented yet */
DriveStruct[d].diskstate_flags &= ~upc_bit; DriveStruct[d].diskstate_flags &= ~upc_bit;
#if TEST_UPC #if TEST_UPC
for (block=CD_BLOCK_OFFSET+1;block<CD_BLOCK_OFFSET+200;block++) for (block=CD_BLOCK_OFFSET+1;block<CD_BLOCK_OFFSET+200;block++)
...@@ -2225,7 +2190,7 @@ static int xx_ReadUPC(void) ...@@ -2225,7 +2190,7 @@ static int xx_ReadUPC(void)
response_count=0; response_count=0;
flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1; flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
} }
else /* CD200, CD-55A */ else /* CD200 */
{ {
return (-1); return (-1);
} }
...@@ -2296,9 +2261,6 @@ static int yy_CheckMultiSession(void) ...@@ -2296,9 +2261,6 @@ static int yy_CheckMultiSession(void)
DriveStruct[d].f_multisession=1; DriveStruct[d].f_multisession=1;
DriveStruct[d].lba_multi=msf2blk(make32(make16(0,infobuf[1]), DriveStruct[d].lba_multi=msf2blk(make32(make16(0,infobuf[1]),
make16(infobuf[2],infobuf[3]))); make16(infobuf[2],infobuf[3])));
#if MULTISESSION_BY_DRIVER
DriveStruct[d].last_redirect=19;
#endif MULTISESSION_BY_DRIVER
DPRINTF((DBG_MUL,"SBPCD: MultiSession CD detected: %02X %02X %02X %02X %02X %02X (%d)\n", DPRINTF((DBG_MUL,"SBPCD: MultiSession CD detected: %02X %02X %02X %02X %02X %02X (%d)\n",
infobuf[0], infobuf[1], infobuf[2], infobuf[0], infobuf[1], infobuf[2],
infobuf[3], infobuf[4], infobuf[5], infobuf[3], infobuf[4], infobuf[5],
...@@ -2324,15 +2286,8 @@ static int yy_CheckMultiSession(void) ...@@ -2324,15 +2286,8 @@ static int yy_CheckMultiSession(void)
{ {
DPRINTF((DBG_MUL,"SBPCD: MultiSession base: %06X\n", DriveStruct[d].lba_multi)); DPRINTF((DBG_MUL,"SBPCD: MultiSession base: %06X\n", DriveStruct[d].lba_multi));
DriveStruct[d].f_multisession=1; DriveStruct[d].f_multisession=1;
#if MULTISESSION_BY_DRIVER
DriveStruct[d].last_redirect=19;
#endif MULTISESSION_BY_DRIVER
} }
} }
else /* CD-55A */
{
return (-1);
}
return (0); return (0);
} }
/*==========================================================================*/ /*==========================================================================*/
...@@ -2408,53 +2363,6 @@ static void check_datarate(void) ...@@ -2408,53 +2363,6 @@ static void check_datarate(void)
#endif CDMKE #endif CDMKE
} }
/*==========================================================================*/ /*==========================================================================*/
#if TEAC-X
/*==========================================================================*/
static void teac_reset(int drv_id)
{
int i;
OUT(CDo_sel_i_d,0);
OUT(CDo_enable,drv_id);
OUT(CDo_command,CMDT_RESET);
for (i=0;i<9;i++) OUT(CDo_command,0);
DPRINTF((DBG_TEA,"SBPCD: TEAC soft reset.\n"));
sbp_sleep(100); /* wait a second */
}
/*==========================================================================*/
static int look_for_TEAC_drive(int drv_id)
{
int i;
if (sbpro_type!=1) teac_reset(drv_id);
OUT(CDo_enable,drv_id);
OUT(CDo_sel_i_d,0);
i=inb(CDi_status);
if (i&s_not_result_ready) return (-1); /* drive not present */
i=inb(CDi_info);
DPRINTF((DBG_TEA,"SBPCD: TEAC look_for_drive: %02X.\n",i));
if (i!=0x55) return (-2); /* something else present */
return (1); /* drive found */
}
/*==========================================================================*/
static int find_teac_drives(void)
{
int i, j, found;
found=0;
for (i=0;i<4;i++)
{
j=look_for_TEAC_drive(i);
if (j<1) continue;
found++;
DPRINTF((DBG_TEA,"SBPCD: TEAC drive (id=%d) found.\n",i));
}
return (found);
}
/*==========================================================================*/
#endif TEAC-X
/*==========================================================================*/
/*==========================================================================*/
#ifdef CD200 #ifdef CD200
#if 0 #if 0
...@@ -2510,6 +2418,7 @@ static void ask_mail(void) ...@@ -2510,6 +2418,7 @@ static void ask_mail(void)
int i; int i;
printk("SBPCD: please mail the following lines to emoenke@gwdg.de:\n"); printk("SBPCD: please mail the following lines to emoenke@gwdg.de:\n");
printk("SBPCD: address %03X, type %s, drive ID %d\n", CDo_command, type, DriveStruct[d].drv_id);
printk("SBPCD: infobuf = \""); printk("SBPCD: infobuf = \"");
for (i=0;i<12;i++) printk("%02X ",infobuf[i]); for (i=0;i<12;i++) printk("%02X ",infobuf[i]);
printk("\"\nSBPCD: infobuf = \""); printk("\"\nSBPCD: infobuf = \"");
...@@ -2525,25 +2434,6 @@ static int check_version(void) ...@@ -2525,25 +2434,6 @@ static int check_version(void)
DPRINTF((DBG_INI,"SBPCD: check_version entered.\n")); DPRINTF((DBG_INI,"SBPCD: check_version entered.\n"));
DriveStruct[d].drv_type=0; DriveStruct[d].drv_type=0;
#if TEAC
/* check for CD-55A */
clr_cmdbuf();
drvcmd[0]=CMDT_READ_ERR;
response_count=5;
flags_cmd_out=f_putcmd;
i=cmd_out(7);
if (i<0) DPRINTF((DBG_INI,"SBPCD: CMDT_READERR returns %d (ok anyway).\n",i));
/* read drive version */
clr_cmdbuf();
for (i=0;i<12;i++) infobuf[i]=0;
if (sbpro_type==1) OUT(CDo_sel_i_d,0);
response_count=12; /* may be too much */
drvcmd[0]=CMDT_READ_VER;
drvcmd[4]=response_count;
flags_cmd_out=f_putcmd;
i=cmd_out(10); /* possibly only 6 */
if (i<0) DPRINTF((DBG_INI,"SBPCD: CMDT_READ_VER returns %d\n",i));
#else
/* check for CD200 */ /* check for CD200 */
clr_cmdbuf(); clr_cmdbuf();
drvcmd[0]=CMD2_READ_ERR; drvcmd[0]=CMD2_READ_ERR;
...@@ -2565,8 +2455,7 @@ static int check_version(void) ...@@ -2565,8 +2455,7 @@ static int check_version(void)
flags_cmd_out=f_putcmd; flags_cmd_out=f_putcmd;
i=cmd_out(7); i=cmd_out(7);
if (i<0) DPRINTF((DBG_INI,"SBPCD: CMD2_READ_VER returns %d\n",i)); if (i<0) DPRINTF((DBG_INI,"SBPCD: CMD2_READ_VER returns %d\n",i));
#endif TEAC if (i>=0) /* from CD200 */
if (i>=0) /* either from CD200 or CD-55A */
{ {
for (i=0, j=0;i<12;i++) j+=infobuf[i]; for (i=0, j=0;i<12;i++) j+=infobuf[i];
if (j) if (j)
...@@ -2589,23 +2478,6 @@ static int check_version(void) ...@@ -2589,23 +2478,6 @@ static int check_version(void)
DriveStruct[d].drive_model[7]=0; DriveStruct[d].drive_model[7]=0;
DriveStruct[d].drv_type=drv_fam2; DriveStruct[d].drv_type=drv_fam2;
} }
else
{
for (i=0;i<5;i++) if (infobuf[i]!=familyT[i]) break;
if (i==5)
{
DriveStruct[d].drive_model[0]='C';
DriveStruct[d].drive_model[1]='D';
DriveStruct[d].drive_model[2]='-';
DriveStruct[d].drive_model[3]='5';
DriveStruct[d].drive_model[4]='5';
DriveStruct[d].drive_model[5]='A';
DriveStruct[d].drive_model[6]=infobuf[i++];
DriveStruct[d].drive_model[7]=infobuf[i++];
DriveStruct[d].drive_model[8]=0;
}
DriveStruct[d].drv_type=drv_famT; /* assumed, not sure here */
}
} }
if (!DriveStruct[d].drv_type) if (!DriveStruct[d].drv_type)
...@@ -2692,14 +2564,6 @@ static int check_version(void) ...@@ -2692,14 +2564,6 @@ static int check_version(void)
if (j!=4) ask_mail(); if (j!=4) ask_mail();
DriveStruct[d].drv_type=drv_260; DriveStruct[d].drv_type=drv_260;
} }
else if (famT_drive)
{
printk("\n\nSBPCD: possibly TEAC CD-55A present.\n");
printk("SBPCD: support is not fulfilled yet - drive gets ignored.\n");
ask_mail();
DriveStruct[d].drv_type=0;
return (-1);
}
else else
{ {
j = (DriveStruct[d].firmware_version[0] & 0x0F) * 100 + j = (DriveStruct[d].firmware_version[0] & 0x0F) * 100 +
...@@ -2717,15 +2581,18 @@ static int check_version(void) ...@@ -2717,15 +2581,18 @@ static int check_version(void)
else if (fam1_drive) else if (fam1_drive)
{ {
if (j<100) DriveStruct[d].drv_type=drv_099; if (j<100) DriveStruct[d].drv_type=drv_099;
else DriveStruct[d].drv_type=drv_100; else
{
DriveStruct[d].drv_type=drv_100;
ask_mail();
}
} }
else if (fam2_drive) else if (fam2_drive)
{ {
printk("\n\nSBPCD: new drive CD200 (%s)detected.\n", printk("\n\nSBPCD: new drive CD200 (%s)detected.\n",
DriveStruct[d].firmware_version); DriveStruct[d].firmware_version);
printk("SBPCD: support is not fulfilled yet.\n"); printk("SBPCD: support is not fulfilled yet.\n");
if (j!=101) /* only 1.01 known at time */ if (j!=101) ask_mail(); /* only 1.01 known at time */
ask_mail();
} }
} }
DPRINTF((DBG_LCS,"SBPCD: drive type %02X\n",DriveStruct[d].drv_type)); DPRINTF((DBG_LCS,"SBPCD: drive type %02X\n",DriveStruct[d].drv_type));
...@@ -3035,9 +2902,7 @@ static int prepare(u_char func, u_char subfunc) ...@@ -3035,9 +2902,7 @@ static int prepare(u_char func, u_char subfunc)
if (i&s_attention) GetStatus(); if (i&s_attention) GetStatus();
} }
else if (fam1_drive) GetStatus(); else if (fam1_drive) GetStatus();
else /* CD200, CD-55A */ else if (fam2_drive) GetStatus();
{
}
if (DriveStruct[d].CD_changed==0xFF) if (DriveStruct[d].CD_changed==0xFF)
{ {
#if MANY_SESSION #if MANY_SESSION
...@@ -3134,15 +2999,17 @@ static int xx_PlayAudio(int pos_audio_start,int pos_audio_end) ...@@ -3134,15 +2999,17 @@ static int xx_PlayAudio(int pos_audio_start,int pos_audio_end)
flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus | flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus |
f_obey_p_check | f_wait_if_busy; f_obey_p_check | f_wait_if_busy;
} }
else if (fam2_drive)
{
drvcmd[0]=CMD2_PLAY_MSF;
flags_cmd_out = f_putcmd | f_ResponseStatus;
}
else if (fam0_drive) else if (fam0_drive)
{ {
drvcmd[0]=CMD0_PLAY_MSF; drvcmd[0]=CMD0_PLAY_MSF;
flags_cmd_out = f_putcmd | f_respo2 | f_lopsta | f_getsta | flags_cmd_out = f_putcmd | f_respo2 | f_lopsta | f_getsta |
f_ResponseStatus | f_obey_p_check | f_wait_if_busy; f_ResponseStatus | f_obey_p_check | f_wait_if_busy;
} }
else /* CD200, CD-55A */
{
}
drvcmd[1]=(pos_audio_start>>16)&0x00FF; drvcmd[1]=(pos_audio_start>>16)&0x00FF;
drvcmd[2]=(pos_audio_start>>8)&0x00FF; drvcmd[2]=(pos_audio_start>>8)&0x00FF;
drvcmd[3]=pos_audio_start&0x00FF; drvcmd[3]=pos_audio_start&0x00FF;
...@@ -3495,7 +3362,6 @@ static int sbpcd_ioctl(struct inode *inode, struct file *file, u_int cmd, ...@@ -3495,7 +3362,6 @@ static int sbpcd_ioctl(struct inode *inode, struct file *file, u_int cmd,
if (fam0_drive) return (-EINVAL); if (fam0_drive) return (-EINVAL);
if (famL_drive) return (-EINVAL); if (famL_drive) return (-EINVAL);
if (fam2_drive) return (-EINVAL); if (fam2_drive) return (-EINVAL);
if (famT_drive) return (-EINVAL);
if (DriveStruct[d].aud_buf==NULL) return (-EINVAL); if (DriveStruct[d].aud_buf==NULL) return (-EINVAL);
i=verify_area(VERIFY_READ, (void *) arg, sizeof(struct cdrom_read_audio)); i=verify_area(VERIFY_READ, (void *) arg, sizeof(struct cdrom_read_audio));
if (i) return (i); if (i) return (i);
...@@ -3559,7 +3425,7 @@ static int sbpcd_ioctl(struct inode *inode, struct file *file, u_int cmd, ...@@ -3559,7 +3425,7 @@ static int sbpcd_ioctl(struct inode *inode, struct file *file, u_int cmd,
drvcmd[5]=0; drvcmd[5]=0;
drvcmd[6]=read_audio.nframes; /* # of frames */ drvcmd[6]=read_audio.nframes; /* # of frames */
} }
else /* CD200, CD-55A */ else if (fam2_drive) /* CD200: not implemented yet */
{ {
} }
DPRINTF((DBG_AUD,"SBPCD: read_audio: before giving \"read\" command.\n")); DPRINTF((DBG_AUD,"SBPCD: read_audio: before giving \"read\" command.\n"));
...@@ -3743,29 +3609,26 @@ static void DO_SBPCD_REQUEST(void) ...@@ -3743,29 +3609,26 @@ static void DO_SBPCD_REQUEST(void)
int i, status_tries, data_tries; int i, status_tries, data_tries;
request_loop: request_loop:
INIT_REQUEST;
sti(); sti();
if ((CURRENT==NULL)||(CURRENT->dev<0)) goto done; if ((CURRENT==NULL)||(CURRENT->dev<0)) goto err_done;
if (CURRENT -> sector == -1) goto done; if (CURRENT -> sector == -1) goto err_done;
if (CURRENT->cmd != READ)
{
printk("SBPCD: bad cmd %d\n", CURRENT->cmd);
goto err_done;
}
i = MINOR(CURRENT->dev); i = MINOR(CURRENT->dev);
if ( (i<0) || (i>=NR_SBPCD) || (DriveStruct[i].drv_id==-1)) if ( (i<0) || (i>=NR_SBPCD) || (DriveStruct[i].drv_id==-1))
{ {
printk("SBPCD: do_request: bad device: %04X\n", CURRENT->dev); printk("SBPCD: do_request: bad device: %04X\n", CURRENT->dev);
goto done; goto err_done;
} }
switch_drive(i); switch_drive(i);
INIT_REQUEST;
block = CURRENT->sector; /* always numbered as 512-byte-pieces */ block = CURRENT->sector; /* always numbered as 512-byte-pieces */
nsect = CURRENT->nr_sectors; /* always counted as 512-byte-pieces */ nsect = CURRENT->nr_sectors; /* always counted as 512-byte-pieces */
if (CURRENT->cmd != READ)
{
printk("SBPCD: bad cmd %d\n", CURRENT->cmd);
end_request(0);
goto request_loop;
}
DPRINTF((DBG_BSZ,"SBPCD: read sector %d (%d sectors)\n", block, nsect)); DPRINTF((DBG_BSZ,"SBPCD: read sector %d (%d sectors)\n", block, nsect));
#if 0 #if 0
...@@ -3822,13 +3685,11 @@ static void DO_SBPCD_REQUEST(void) ...@@ -3822,13 +3685,11 @@ static void DO_SBPCD_REQUEST(void)
} }
} }
err_done:
busy_data=0;
end_request(0); end_request(0);
sbp_sleep(10); /* wait a bit, try again */ sbp_sleep(10); /* wait a bit, try again */
goto request_loop; goto request_loop;
done:
busy_data=0;
return;
} }
/*==========================================================================*/ /*==========================================================================*/
/* /*
...@@ -3842,32 +3703,6 @@ static void sbp_read_cmd(void) ...@@ -3842,32 +3703,6 @@ static void sbp_read_cmd(void)
DriveStruct[d].sbp_first_frame=DriveStruct[d].sbp_last_frame=-1; /* purge buffer */ DriveStruct[d].sbp_first_frame=DriveStruct[d].sbp_last_frame=-1; /* purge buffer */
block=CURRENT->sector/4; block=CURRENT->sector/4;
#if MULTISESSION_BY_DRIVER
if (!fam0_drive)
{
#if MANY_SESSION
DPRINTF((DBG_MUL,"SBPCD: read MSF %08X\n", blk2msf(block)));
if (DriveStruct[d].f_multisession)
{
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<=DriveStruct[d].last_redirect)
&& (DriveStruct[d].f_multisession))
{
DPRINTF((DBG_MUL,"SBPCD: MultiSession: use %08X for %08X (msf)\n",
blk2msf(DriveStruct[d].lba_multi+block),
blk2msf(block)));
block=DriveStruct[d].lba_multi+block;
}
#endif MANY_SESSION
}
#endif MULTISESSION_BY_DRIVER
if (block+SBP_BUFFER_FRAMES <= DriveStruct[d].CDsize_frm) if (block+SBP_BUFFER_FRAMES <= DriveStruct[d].CDsize_frm)
DriveStruct[d].sbp_read_frames = SBP_BUFFER_FRAMES; DriveStruct[d].sbp_read_frames = SBP_BUFFER_FRAMES;
else else
...@@ -3940,9 +3775,6 @@ static void sbp_read_cmd(void) ...@@ -3940,9 +3775,6 @@ static void sbp_read_cmd(void)
drvcmd[5]=DriveStruct[d].sbp_read_frames; drvcmd[5]=DriveStruct[d].sbp_read_frames;
drvcmd[6]=0x02; drvcmd[6]=0x02;
} }
else /* CD-55A */
{
}
SBPCD_CLI; SBPCD_CLI;
for (i=0;i<7;i++) OUT(CDo_command,drvcmd[i]); for (i=0;i<7;i++) OUT(CDo_command,drvcmd[i]);
SBPCD_STI; SBPCD_STI;
...@@ -4152,6 +3984,7 @@ static int sbpcd_open(struct inode *ip, struct file *fp) ...@@ -4152,6 +3984,7 @@ static int sbpcd_open(struct inode *ip, struct file *fp)
/* /*
* try to keep an "open" counter here and lock the door if 0->1. * try to keep an "open" counter here and lock the door if 0->1.
*/ */
MOD_INC_USE_COUNT;
DPRINTF((DBG_LCK,"SBPCD: open_count: %d -> %d\n", DPRINTF((DBG_LCK,"SBPCD: open_count: %d -> %d\n",
DriveStruct[d].open_count,DriveStruct[d].open_count+1)); DriveStruct[d].open_count,DriveStruct[d].open_count+1));
if (++DriveStruct[d].open_count==1) if (++DriveStruct[d].open_count==1)
...@@ -4190,6 +4023,7 @@ static void sbpcd_release(struct inode * ip, struct file * file) ...@@ -4190,6 +4023,7 @@ static void sbpcd_release(struct inode * ip, struct file * file)
/* /*
* try to keep an "open" counter here and unlock the door if 1->0. * try to keep an "open" counter here and unlock the door if 1->0.
*/ */
MOD_DEC_USE_COUNT;
DPRINTF((DBG_LCK,"SBPCD: open_count: %d -> %d\n", DPRINTF((DBG_LCK,"SBPCD: open_count: %d -> %d\n",
DriveStruct[d].open_count,DriveStruct[d].open_count-1)); DriveStruct[d].open_count,DriveStruct[d].open_count-1));
if (DriveStruct[d].open_count!=0) /* CDROMEJECT may have been done */ if (DriveStruct[d].open_count!=0) /* CDROMEJECT may have been done */
...@@ -4254,7 +4088,9 @@ void sbpcd_setup(char *s, int *p) ...@@ -4254,7 +4088,9 @@ void sbpcd_setup(char *s, int *p)
DPRINTF((DBG_INI,"SBPCD: sbpcd_setup called with %04X,%s\n",p[1], s)); DPRINTF((DBG_INI,"SBPCD: sbpcd_setup called with %04X,%s\n",p[1], s));
sbpro_type=0; sbpro_type=0;
if (!strcmp(s,str_sb)) sbpro_type=1; if (!strcmp(s,str_sb)) sbpro_type=1;
else if (!strcmp(s,str_sb_l)) sbpro_type=1;
else if (!strcmp(s,str_sp)) sbpro_type=2; else if (!strcmp(s,str_sp)) sbpro_type=2;
else if (!strcmp(s,str_sp_l)) sbpro_type=2;
if (p[0]>0) sbpcd_ioaddr=p[1]; if (p[0]>0) sbpcd_ioaddr=p[1];
CDo_command=sbpcd_ioaddr; CDo_command=sbpcd_ioaddr;
...@@ -4329,7 +4165,11 @@ static int config_spea(void) ...@@ -4329,7 +4165,11 @@ static int config_spea(void)
/* /*
* Test for presence of drive and initialize it. Called at boot time. * Test for presence of drive and initialize it. Called at boot time.
*/ */
#ifdef MODULE
int init_module(void)
#else
unsigned long SBPCD_INIT(u_long mem_start, u_long mem_end) unsigned long SBPCD_INIT(u_long mem_start, u_long mem_end)
#endif MODULE
{ {
int i=0, j=0; int i=0, j=0;
int addr[2]={1, CDROM_PORT}; int addr[2]={1, CDROM_PORT};
...@@ -4339,9 +4179,10 @@ unsigned long SBPCD_INIT(u_long mem_start, u_long mem_end) ...@@ -4339,9 +4179,10 @@ unsigned long SBPCD_INIT(u_long mem_start, u_long mem_end)
DPRINTF((DBG_INF,"SBPCD version %s\n", VERSION)); DPRINTF((DBG_INF,"SBPCD version %s\n", VERSION));
#ifndef MODULE
if (!setup_done) if (!setup_done)
{ {
DPRINTF((DBG_INF,"SBPCD: Looking for Matsushita, Panasonic, CreativeLabs, IBM, Longshine, TEAC CD-ROM drives\n")); DPRINTF((DBG_INF,"SBPCD: Looking for Matsushita, Panasonic, CreativeLabs, IBM, Longshine CD-ROM drives\n"));
DPRINTF((DBG_WRN,"SBPCD: \n")); DPRINTF((DBG_WRN,"SBPCD: \n"));
DPRINTF((DBG_WRN,"SBPCD: = = = = = = = = = = W A R N I N G = = = = = = = = = =\n")); DPRINTF((DBG_WRN,"SBPCD: = = = = = = = = = = W A R N I N G = = = = = = = = = =\n"));
DPRINTF((DBG_WRN,"SBPCD: Auto-Probing can cause a hang (f.e. touching an ethernet card).\n")); DPRINTF((DBG_WRN,"SBPCD: Auto-Probing can cause a hang (f.e. touching an ethernet card).\n"));
...@@ -4358,12 +4199,14 @@ unsigned long SBPCD_INIT(u_long mem_start, u_long mem_end) ...@@ -4358,12 +4199,14 @@ unsigned long SBPCD_INIT(u_long mem_start, u_long mem_end)
DPRINTF((DBG_WRN,"SBPCD: = = = = = = = = = = END of WARNING = = = = = = = = = =\n")); DPRINTF((DBG_WRN,"SBPCD: = = = = = = = = = = END of WARNING = = = = = = = = = =\n"));
DPRINTF((DBG_WRN,"SBPCD: \n")); DPRINTF((DBG_WRN,"SBPCD: \n"));
} }
#endif MODULE
sbpcd_probe[0]=sbpcd_ioaddr; /* possibly changed by kernel command line */ sbpcd_probe[0]=sbpcd_ioaddr; /* possibly changed by kernel command line */
sbpcd_probe[1]=sbpro_type; /* possibly changed by kernel command line */ sbpcd_probe[1]=sbpro_type; /* possibly changed by kernel command line */
for (port_index=0;port_index<NUM_PROBE;port_index+=2) for (port_index=0;port_index<NUM_PROBE;port_index+=2)
{ {
addr[1]=sbpcd_probe[port_index]; addr[1]=sbpcd_probe[port_index];
if (addr[1]==0) break;
if (check_region(addr[1],4)) if (check_region(addr[1],4))
{ {
DPRINTF((DBG_INI,"SBPCD: check_region: %03X is not free.\n",addr[1])); DPRINTF((DBG_INI,"SBPCD: check_region: %03X is not free.\n",addr[1]));
...@@ -4384,14 +4227,6 @@ unsigned long SBPCD_INIT(u_long mem_start, u_long mem_end) ...@@ -4384,14 +4227,6 @@ unsigned long SBPCD_INIT(u_long mem_start, u_long mem_end)
continue; continue;
} }
} }
#if TEAC
i=find_teac_drives();
if (i>0)
{
DPRINTF((DBG_INF,"SBPCD: found %d TEAC drives. A wonder.\n",i));
DPRINTF((DBG_INF,"SBPCD: - "));
}
#endif TEAC
i=check_drives(); i=check_drives();
DPRINTF((DBG_INI,"SBPCD: check_drives done.\n")); DPRINTF((DBG_INI,"SBPCD: check_drives done.\n"));
if (i>=0) break; /* drive found */ if (i>=0) break; /* drive found */
...@@ -4404,7 +4239,11 @@ unsigned long SBPCD_INIT(u_long mem_start, u_long mem_end) ...@@ -4404,7 +4239,11 @@ unsigned long SBPCD_INIT(u_long mem_start, u_long mem_end)
#if PRINTK_BUG #if PRINTK_BUG
sti(); /* to avoid possible "printk" bug */ sti(); /* to avoid possible "printk" bug */
#endif #endif
#ifdef MODULE
return -EIO;
#else
goto init_done; goto init_done;
#endif MODULE
} }
if (port_index>0) if (port_index>0)
...@@ -4501,7 +4340,11 @@ unsigned long SBPCD_INIT(u_long mem_start, u_long mem_end) ...@@ -4501,7 +4340,11 @@ unsigned long SBPCD_INIT(u_long mem_start, u_long mem_end)
#if PRINTK_BUG #if PRINTK_BUG
sti(); /* to avoid possible "printk" bug */ sti(); /* to avoid possible "printk" bug */
#endif #endif
#ifdef MODULE
return -EIO;
#else
goto init_done; goto init_done;
#endif MODULE
} }
blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
read_ahead[MAJOR_NR] = SBP_BUFFER_FRAMES * (CD_FRAMESIZE / 512); read_ahead[MAJOR_NR] = SBP_BUFFER_FRAMES * (CD_FRAMESIZE / 512);
...@@ -4514,7 +4357,11 @@ unsigned long SBPCD_INIT(u_long mem_start, u_long mem_end) ...@@ -4514,7 +4357,11 @@ unsigned long SBPCD_INIT(u_long mem_start, u_long mem_end)
switch_drive(j); switch_drive(j);
/* /*
* allocate memory for the frame buffers * allocate memory for the frame buffers
*/ */
#ifdef MODULE
DriveStruct[j].sbp_buf=(u_char *) kmalloc(SBP_BUFFER_FRAMES*CD_FRAMESIZE, GFP_KERNEL);
DriveStruct[j].aud_buf=NULL;
#else
DriveStruct[j].sbp_buf=(u_char *)mem_start; DriveStruct[j].sbp_buf=(u_char *)mem_start;
mem_start += SBP_BUFFER_FRAMES*CD_FRAMESIZE; mem_start += SBP_BUFFER_FRAMES*CD_FRAMESIZE;
if ((fam1_drive) && (SBP_BUFFER_AUDIO_FRAMES>0)) if ((fam1_drive) && (SBP_BUFFER_AUDIO_FRAMES>0))
...@@ -4523,6 +4370,7 @@ unsigned long SBPCD_INIT(u_long mem_start, u_long mem_end) ...@@ -4523,6 +4370,7 @@ unsigned long SBPCD_INIT(u_long mem_start, u_long mem_end)
mem_start += SBP_BUFFER_AUDIO_FRAMES*CD_FRAMESIZE_RAW; mem_start += SBP_BUFFER_AUDIO_FRAMES*CD_FRAMESIZE_RAW;
} }
else DriveStruct[j].aud_buf=NULL; else DriveStruct[j].aud_buf=NULL;
#endif MODULE
/* /*
* set the block size * set the block size
*/ */
...@@ -4530,6 +4378,9 @@ unsigned long SBPCD_INIT(u_long mem_start, u_long mem_end) ...@@ -4530,6 +4378,9 @@ unsigned long SBPCD_INIT(u_long mem_start, u_long mem_end)
} }
blksize_size[MAJOR_NR]=sbpcd_blocksizes; blksize_size[MAJOR_NR]=sbpcd_blocksizes;
#ifdef MODULE
return (0);
#else
init_done: init_done:
#if !(SBPCD_ISSUE-1) #if !(SBPCD_ISSUE-1)
#ifdef CONFIG_SBPCD2 #ifdef CONFIG_SBPCD2
...@@ -4546,7 +4397,34 @@ unsigned long SBPCD_INIT(u_long mem_start, u_long mem_end) ...@@ -4546,7 +4397,34 @@ unsigned long SBPCD_INIT(u_long mem_start, u_long mem_end)
DPRINTF((DBG_INF,"SBPCD: init done.\n")); DPRINTF((DBG_INF,"SBPCD: init done.\n"));
#endif #endif
return (mem_start); return (mem_start);
#endif MODULE
}
/*==========================================================================*/
#ifdef MODULE
void cleanup_module(void)
{
int j;
if (MOD_IN_USE)
{
printk("%s module in use - can't remove it.\n", major_name);
return;
}
if ((unregister_blkdev(MAJOR_NR, major_name) == -EINVAL))
{
printk("What's that: can't unregister %s\n", major_name);
return;
}
release_region(CDo_command,4);
for (j=0;j<NR_SBPCD;j++)
{
if (DriveStruct[j].drv_id==-1) continue;
kfree_s(DriveStruct[j].sbp_buf, SBP_BUFFER_FRAMES*CD_FRAMESIZE);
}
printk("%s module released.\n", major_name);
} }
#endif MODULE
/*==========================================================================*/ /*==========================================================================*/
/* /*
* Check if the media has changed in the CD-ROM drive. * Check if the media has changed in the CD-ROM drive.
......
...@@ -1686,11 +1686,8 @@ static int con_write(struct tty_struct * tty, int from_user, ...@@ -1686,11 +1686,8 @@ static int con_write(struct tty_struct * tty, int from_user,
case '@': /* defined in ISO 2022 */ case '@': /* defined in ISO 2022 */
utf = 0; utf = 0;
continue; continue;
case '8': case 'G': /* prelim official escape code */
/* ISO/ECMA hasn't yet registered an case '8': /* retained for compatibility */
official ESC sequence for UTF-8,
so this one (ESC %8) will likely
change in the future. */
utf = 1; utf = 1;
continue; continue;
} }
......
static char rcsid[] = static char rcsid[] =
"$Revision: 1.35 $$Date: 1994/12/16 13:54:18 $"; "$Revision: 1.36.1.1 $$Date: 1995/03/13 15:44:43 $";
/* /*
* linux/kernel/cyclades.c * linux/kernel/cyclades.c
* *
* Maintained by Marcio Saito (cyclades@netcom.com) and
* Randolph Bentson (bentson@grieg.seaslug.org)
*
* Much of the design and some of the code came from serial.c * Much of the design and some of the code came from serial.c
* which was copyright (C) 1991, 1992 Linus Torvalds. It was * which was copyright (C) 1991, 1992 Linus Torvalds. It was
* extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92, * extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92,
...@@ -15,6 +18,27 @@ static char rcsid[] = ...@@ -15,6 +18,27 @@ static char rcsid[] =
* int cy_open(struct tty_struct *tty, struct file *filp); * int cy_open(struct tty_struct *tty, struct file *filp);
* *
* $Log: cyclades.c,v $ * $Log: cyclades.c,v $
* Revision 1.36.1.1 1995/03/13 15:44:43 bentson
* initialize defaults for receive threshold and stale data timeout;
* cosmetic changes;
*
* Revision 1.36 1995/03/10 23:33:53 bentson
* added support of chips 4-7 in 32 port Cyclom-Ye;
* fix cy_interrupt pointer dereference problem
* (Joe Portman <baron@aa.net>);
* give better error response if open is attempted on non-existant port
* (Zachariah Vaum <jchryslr@netcom.com>);
* correct command timeout (Kenneth Lerman <lerman@@seltd.newnet.com>);
* conditional compilation for -16Y on systems with fast, noisy bus;
* comment out diagnostic print function;
* cleaned up table of base addresses;
* set receiver time-out period register to correct value,
* set receive threshold to better default values,
* set chip timer to more accurate 200 Hz ticking,
* add code to monitor and modify receive parameters
* (Rik Faith <faith@cs.unc.edu> Nick Simicich
* <njs@scifi.emi.net>);
*
* Revision 1.35 1994/12/16 13:54:18 steffen * Revision 1.35 1994/12/16 13:54:18 steffen
* additional patch by Marcio Saito for board detection * additional patch by Marcio Saito for board detection
* Accidently left out in 1.34 * Accidently left out in 1.34
...@@ -199,6 +223,8 @@ static char rcsid[] = ...@@ -199,6 +223,8 @@ static char rcsid[] =
#undef SERIAL_DEBUG_IO #undef SERIAL_DEBUG_IO
#undef SERIAL_DEBUG_COUNT #undef SERIAL_DEBUG_COUNT
#undef SERIAL_DEBUG_DTR #undef SERIAL_DEBUG_DTR
#undef CYCLOM_16Y_HACK
#undef CYCLOM_ENABLE_MONITORING
#ifndef MIN #ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b)) #define MIN(a,b) ((a) < (b) ? (a) : (b))
...@@ -221,25 +247,37 @@ static volatile int cy_triggered; ...@@ -221,25 +247,37 @@ static volatile int cy_triggered;
static int cy_wild_int_mask; static int cy_wild_int_mask;
static unsigned char *intr_base_addr; static unsigned char *intr_base_addr;
/* This is the per-card data structure */ /* This is the per-card data structure containing a card's base
address. Here are declarations for some common addresses.
Add entries to match your configuration (there are sixty-
four possible from 0x80000 to 0xFE000) */
struct cyclades_card cy_card[] = { struct cyclades_card cy_card[] = {
/* BASE_ADDR */ /* BASE_ADDR */
{0xD0000,0}, {0xD0000},
{0xD2000,0}, {0xD2000},
{0xD4000,10}, {0xD4000},
{0xD6000,11}, {0xD6000},
{0xD8000,12}, {0xD8000},
{0xDA000,15} {0xDA000},
{0xDC000},
{0xDE000}
}; };
#define NR_CARDS (sizeof(cy_card)/sizeof(struct cyclades_card)) #define NR_CARDS (sizeof(cy_card)/sizeof(struct cyclades_card))
/* No need has yet been found for this per-chip data structure /* The Cyclom-Ye has placed the sequential chips in non-sequential
* struct cyclades_chip cy_chip[] = { * address order. This look-up table overcomes that problem.
* {0}
* };
* #define NR_CHIPS (sizeof(cy_chip)/sizeof(struct cyclades_chip))
*/ */
int cy_chip_offset [] =
{ 0x0000,
0x0400,
0x0800,
0x0C00,
0x0200,
0x0600,
0x0A00,
0x0E00
};
/* This is the per-port data structure */ /* This is the per-port data structure */
struct cyclades_port cy_port[] = { struct cyclades_port cy_port[] = {
...@@ -328,7 +366,7 @@ static char baud_bpr[] = { /* 25 MHz baud rate period table */ ...@@ -328,7 +366,7 @@ static char baud_bpr[] = { /* 25 MHz baud rate period table */
static char baud_cor3[] = { /* receive threshold */ static char baud_cor3[] = { /* receive threshold */
0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
0x0a, 0x0a, 0x0a, 0x08, 0x04, 0x02, 0x01, 0x01, 0x01, 0x01}; 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x07};
...@@ -338,7 +376,9 @@ static void cy_throttle(struct tty_struct *); ...@@ -338,7 +376,9 @@ static void cy_throttle(struct tty_struct *);
static void cy_unthrottle(struct tty_struct *); static void cy_unthrottle(struct tty_struct *);
static void config_setup(struct cyclades_port *); static void config_setup(struct cyclades_port *);
extern void console_print(const char *); extern void console_print(const char *);
#ifdef CYCLOM_SHOW_STATUS
static void show_status(int); static void show_status(int);
#endif
...@@ -399,7 +439,7 @@ void CP4(int data) { CP2((data>>8) & 0xff); CP2(data & 0xff); }/* CP4 */ ...@@ -399,7 +439,7 @@ void CP4(int data) { CP2((data>>8) & 0xff); CP2(data & 0xff); }/* CP4 */
void CP8(long data) { CP4((data>>16) & 0xffff); CP4(data & 0xffff); }/* CP8 */ void CP8(long data) { CP4((data>>16) & 0xffff); CP4(data & 0xffff); }/* CP8 */
/* This routine waits up to 100 micro-seconds for the previous /* This routine waits up to 1000 micro-seconds for the previous
command to the Cirrus chip to complete and then issues the command to the Cirrus chip to complete and then issues the
new command. An error is returned if the previous command new command. An error is returned if the previous command
didn't finish within the time limit. didn't finish within the time limit.
...@@ -412,7 +452,7 @@ write_cy_cmd(u_char *base_addr, u_char cmd) ...@@ -412,7 +452,7 @@ write_cy_cmd(u_char *base_addr, u_char cmd)
save_flags(flags); cli(); save_flags(flags); cli();
/* Check to see that the previous command has completed */ /* Check to see that the previous command has completed */
for(i = 0 ; i < 10000 ; i++){ for(i = 0 ; i < 100 ; i++){
if (base_addr[CyCCR] == 0){ if (base_addr[CyCCR] == 0){
break; break;
} }
...@@ -456,7 +496,7 @@ cy_stop(struct tty_struct *tty) ...@@ -456,7 +496,7 @@ cy_stop(struct tty_struct *tty)
chip = channel>>2; chip = channel>>2;
channel &= 0x03; channel &= 0x03;
base_addr = (unsigned char*) base_addr = (unsigned char*)
(cy_card[info->card].base_addr + chip * CyRegSize); (cy_card[info->card].base_addr + cy_chip_offset[chip]);
save_flags(flags); cli(); save_flags(flags); cli();
base_addr[CyCAR] = (u_char)(channel & 0x0003); /* index channel */ base_addr[CyCAR] = (u_char)(channel & 0x0003); /* index channel */
...@@ -487,7 +527,7 @@ cy_start(struct tty_struct *tty) ...@@ -487,7 +527,7 @@ cy_start(struct tty_struct *tty)
chip = channel>>2; chip = channel>>2;
channel &= 0x03; channel &= 0x03;
base_addr = (unsigned char*) base_addr = (unsigned char*)
(cy_card[info->card].base_addr + chip * CyRegSize); (cy_card[info->card].base_addr + cy_chip_offset[chip]);
save_flags(flags); cli(); save_flags(flags); cli();
base_addr[CyCAR] = (u_char)(channel & 0x0003); base_addr[CyCAR] = (u_char)(channel & 0x0003);
...@@ -562,8 +602,8 @@ cy_interrupt(int irq, struct pt_regs *regs) ...@@ -562,8 +602,8 @@ cy_interrupt(int irq, struct pt_regs *regs)
do{ do{
had_work = 0; had_work = 0;
for ( chip = 0 ; chip < cinfo->num_chips ; chip ++) { for ( chip = 0 ; chip < cinfo->num_chips ; chip ++) {
base_addr = (unsigned char *)(cinfo->base_addr base_addr = (unsigned char *)
+ CyRegSize * chip); (cinfo->base_addr + cy_chip_offset[chip]);
too_many = 0; too_many = 0;
while ( (status = base_addr[CySVRR]) != 0x00) { while ( (status = base_addr[CySVRR]) != 0x00) {
had_work++; had_work++;
...@@ -661,6 +701,13 @@ cy_interrupt(int irq, struct pt_regs *regs) ...@@ -661,6 +701,13 @@ cy_interrupt(int irq, struct pt_regs *regs)
/* load # characters available from the chip */ /* load # characters available from the chip */
char_count = base_addr[CyRDCR]; char_count = base_addr[CyRDCR];
#ifdef CYCLOM_ENABLE_MONITORING
++info->mon.int_count;
info->mon.char_count += char_count;
if (char_count > info->mon.char_max)
info->mon.char_max = char_count;
info->mon.char_last = char_count;
#endif
while(char_count--){ while(char_count--){
if (tty->flip.count >= TTY_FLIPBUF_SIZE){ if (tty->flip.count >= TTY_FLIPBUF_SIZE){
break; break;
...@@ -669,6 +716,9 @@ cy_interrupt(int irq, struct pt_regs *regs) ...@@ -669,6 +716,9 @@ cy_interrupt(int irq, struct pt_regs *regs)
data = base_addr[CyRDSR]; data = base_addr[CyRDSR];
*tty->flip.flag_buf_ptr++ = TTY_NORMAL; *tty->flip.flag_buf_ptr++ = TTY_NORMAL;
*tty->flip.char_buf_ptr++ = data; *tty->flip.char_buf_ptr++ = data;
#ifdef CYCLOM_16Y_HACK
udelay(10L);
#endif
} }
} }
queue_task_irq_off(&tty->flip.tqueue, &tq_timer); queue_task_irq_off(&tty->flip.tqueue, &tq_timer);
...@@ -738,6 +788,10 @@ cy_interrupt(int irq, struct pt_regs *regs) ...@@ -738,6 +788,10 @@ cy_interrupt(int irq, struct pt_regs *regs)
base_addr[CySRER] &= ~CyTxMpty; base_addr[CySRER] &= ~CyTxMpty;
goto txdone; goto txdone;
} }
if (info->xmit_buf == 0){
base_addr[CySRER] &= ~CyTxMpty;
goto txdone;
}
if (info->tty->stopped || info->tty->hw_stopped){ if (info->tty->stopped || info->tty->hw_stopped){
base_addr[CySRER] &= ~CyTxMpty; base_addr[CySRER] &= ~CyTxMpty;
goto txdone; goto txdone;
...@@ -1103,7 +1157,7 @@ startup(struct cyclades_port * info) ...@@ -1103,7 +1157,7 @@ startup(struct cyclades_port * info)
chip = channel>>2; chip = channel>>2;
channel &= 0x03; channel &= 0x03;
base_addr = (unsigned char*) base_addr = (unsigned char*)
(cy_card[card].base_addr + chip * CyRegSize); (cy_card[card].base_addr + cy_chip_offset[chip]);
#ifdef SERIAL_DEBUG_OPEN #ifdef SERIAL_DEBUG_OPEN
printk("startup card %d, chip %d, channel %d, base_addr %lx", printk("startup card %d, chip %d, channel %d, base_addr %lx",
...@@ -1113,7 +1167,9 @@ startup(struct cyclades_port * info) ...@@ -1113,7 +1167,9 @@ startup(struct cyclades_port * info)
save_flags(flags); cli(); save_flags(flags); cli();
base_addr[CyCAR] = (u_char)channel; base_addr[CyCAR] = (u_char)channel;
base_addr[CyRTPR] = 0x20; /* 32ms rx timeout */ base_addr[CyRTPR] = (info->default_timeout
? info->default_timeout
: 0x02); /* 10ms rx timeout */
write_cy_cmd(base_addr,CyCHAN_CTL|CyENB_RCVR|CyENB_XMTR); write_cy_cmd(base_addr,CyCHAN_CTL|CyENB_RCVR|CyENB_XMTR);
...@@ -1155,7 +1211,7 @@ start_xmit( struct cyclades_port *info ) ...@@ -1155,7 +1211,7 @@ start_xmit( struct cyclades_port *info )
chip = channel>>2; chip = channel>>2;
channel &= 0x03; channel &= 0x03;
base_addr = (unsigned char*) base_addr = (unsigned char*)
(cy_card[card].base_addr + chip * CyRegSize); (cy_card[card].base_addr + cy_chip_offset[chip]);
save_flags(flags); cli(); save_flags(flags); cli();
base_addr[CyCAR] = channel; base_addr[CyCAR] = channel;
base_addr[CySRER] |= CyTxMpty; base_addr[CySRER] |= CyTxMpty;
...@@ -1183,7 +1239,7 @@ shutdown(struct cyclades_port * info) ...@@ -1183,7 +1239,7 @@ shutdown(struct cyclades_port * info)
chip = channel>>2; chip = channel>>2;
channel &= 0x03; channel &= 0x03;
base_addr = (unsigned char*) base_addr = (unsigned char*)
(cy_card[card].base_addr + chip * CyRegSize); (cy_card[card].base_addr + cy_chip_offset[chip]);
#ifdef SERIAL_DEBUG_OPEN #ifdef SERIAL_DEBUG_OPEN
printk("shutdown card %d, chip %d, channel %d, base_addr %lx\n", printk("shutdown card %d, chip %d, channel %d, base_addr %lx\n",
...@@ -1298,7 +1354,9 @@ config_setup(struct cyclades_port * info) ...@@ -1298,7 +1354,9 @@ config_setup(struct cyclades_port * info)
/* byte size and parity */ /* byte size and parity */
info->cor5 = 0; info->cor5 = 0;
info->cor4 = 0; info->cor4 = 0;
info->cor3 = baud_cor3[i]; /* receive threshold */ info->cor3 = (info->default_threshold
? info->default_threshold
: baud_cor3[i]); /* receive threshold */
info->cor2 = CyETC; info->cor2 = CyETC;
switch(cflag & CSIZE){ switch(cflag & CSIZE){
case CS5: case CS5:
...@@ -1343,7 +1401,7 @@ config_setup(struct cyclades_port * info) ...@@ -1343,7 +1401,7 @@ config_setup(struct cyclades_port * info)
chip = channel>>2; chip = channel>>2;
channel &= 0x03; channel &= 0x03;
base_addr = (unsigned char*) base_addr = (unsigned char*)
(cy_card[card].base_addr + chip * CyRegSize); (cy_card[card].base_addr + cy_chip_offset[chip]);
save_flags(flags); cli(); save_flags(flags); cli();
base_addr[CyCAR] = (u_char)channel; base_addr[CyCAR] = (u_char)channel;
...@@ -1369,7 +1427,9 @@ config_setup(struct cyclades_port * info) ...@@ -1369,7 +1427,9 @@ config_setup(struct cyclades_port * info)
base_addr[CyCAR] = (u_char)channel; /* !!! Is this needed? */ base_addr[CyCAR] = (u_char)channel; /* !!! Is this needed? */
base_addr[CyRTPR] = 0x20; /* 32ms rx timeout */ base_addr[CyRTPR] = (info->default_timeout
? info->default_timeout
: 0x02); /* 10ms rx timeout */
if (C_CLOCAL(info->tty)) { if (C_CLOCAL(info->tty)) {
base_addr[CySRER] |= 0; /* without modem intr */ base_addr[CySRER] |= 0; /* without modem intr */
...@@ -1474,7 +1534,7 @@ cy_flush_chars(struct tty_struct *tty) ...@@ -1474,7 +1534,7 @@ cy_flush_chars(struct tty_struct *tty)
chip = channel>>2; chip = channel>>2;
channel &= 0x03; channel &= 0x03;
base_addr = (unsigned char*) base_addr = (unsigned char*)
(cy_card[card].base_addr + chip * CyRegSize); (cy_card[card].base_addr + cy_chip_offset[chip]);
save_flags(flags); cli(); save_flags(flags); cli();
base_addr[CyCAR] = channel; base_addr[CyCAR] = channel;
...@@ -1636,7 +1696,7 @@ cy_throttle(struct tty_struct * tty) ...@@ -1636,7 +1696,7 @@ cy_throttle(struct tty_struct * tty)
chip = channel>>2; chip = channel>>2;
channel &= 0x03; channel &= 0x03;
base_addr = (unsigned char*) base_addr = (unsigned char*)
(cy_card[card].base_addr + chip * CyRegSize); (cy_card[card].base_addr + cy_chip_offset[chip]);
save_flags(flags); cli(); save_flags(flags); cli();
base_addr[CyCAR] = (u_char)channel; base_addr[CyCAR] = (u_char)channel;
...@@ -1677,7 +1737,7 @@ cy_unthrottle(struct tty_struct * tty) ...@@ -1677,7 +1737,7 @@ cy_unthrottle(struct tty_struct * tty)
chip = channel>>2; chip = channel>>2;
channel &= 0x03; channel &= 0x03;
base_addr = (unsigned char*) base_addr = (unsigned char*)
(cy_card[card].base_addr + chip * CyRegSize); (cy_card[card].base_addr + cy_chip_offset[chip]);
save_flags(flags); cli(); save_flags(flags); cli();
base_addr[CyCAR] = (u_char)channel; base_addr[CyCAR] = (u_char)channel;
...@@ -1768,7 +1828,7 @@ get_modem_info(struct cyclades_port * info, unsigned int *value) ...@@ -1768,7 +1828,7 @@ get_modem_info(struct cyclades_port * info, unsigned int *value)
chip = channel>>2; chip = channel>>2;
channel &= 0x03; channel &= 0x03;
base_addr = (unsigned char*) base_addr = (unsigned char*)
(cy_card[card].base_addr + chip * CyRegSize); (cy_card[card].base_addr + cy_chip_offset[chip]);
save_flags(flags); cli(); save_flags(flags); cli();
base_addr[CyCAR] = (u_char)channel; base_addr[CyCAR] = (u_char)channel;
...@@ -1799,7 +1859,7 @@ set_modem_info(struct cyclades_port * info, unsigned int cmd, ...@@ -1799,7 +1859,7 @@ set_modem_info(struct cyclades_port * info, unsigned int cmd,
chip = channel>>2; chip = channel>>2;
channel &= 0x03; channel &= 0x03;
base_addr = (unsigned char*) base_addr = (unsigned char*)
(cy_card[card].base_addr + chip * CyRegSize); (cy_card[card].base_addr + cy_chip_offset[chip]);
switch (cmd) { switch (cmd) {
case TIOCMBIS: case TIOCMBIS:
...@@ -1891,6 +1951,120 @@ send_break( struct cyclades_port * info, int duration) ...@@ -1891,6 +1951,120 @@ send_break( struct cyclades_port * info, int duration)
} }
} /* send_break */ } /* send_break */
static int
get_mon_info(struct cyclades_port * info, struct cyclades_monitor * mon)
{
memcpy_tofs(mon, &info->mon, sizeof(struct cyclades_monitor));
info->mon.int_count = 0;
info->mon.char_count = 0;
info->mon.char_max = 0;
info->mon.char_last = 0;
return 0;
}
static int
set_threshold(struct cyclades_port * info, unsigned long value)
{
unsigned char *base_addr;
int card,channel,chip;
card = info->card;
channel = info->line - cy_card[card].first_line;
chip = channel>>2;
channel &= 0x03;
base_addr = (unsigned char*)
(cy_card[card].base_addr + cy_chip_offset[chip]);
info->cor3 &= ~CyREC_FIFO;
info->cor3 |= value & CyREC_FIFO;
base_addr[CyCOR3] = info->cor3;
write_cy_cmd(base_addr,CyCOR_CHANGE|CyCOR3ch);
return 0;
}
static int
get_threshold(struct cyclades_port * info, unsigned long *value)
{
unsigned char *base_addr;
int card,channel,chip;
unsigned long tmp;
card = info->card;
channel = info->line - cy_card[card].first_line;
chip = channel>>2;
channel &= 0x03;
base_addr = (unsigned char*)
(cy_card[card].base_addr + cy_chip_offset[chip]);
tmp = base_addr[CyCOR3] & CyREC_FIFO;
put_fs_long(tmp,value);
return 0;
}
static int
set_default_threshold(struct cyclades_port * info, unsigned long value)
{
info->default_threshold = value & 0x0f;
return 0;
}
static int
get_default_threshold(struct cyclades_port * info, unsigned long *value)
{
put_fs_long(info->default_threshold,value);
return 0;
}
static int
set_timeout(struct cyclades_port * info, unsigned long value)
{
unsigned char *base_addr;
int card,channel,chip;
card = info->card;
channel = info->line - cy_card[card].first_line;
chip = channel>>2;
channel &= 0x03;
base_addr = (unsigned char*)
(cy_card[card].base_addr + cy_chip_offset[chip]);
base_addr[CyRTPR] = value & 0xff;
return 0;
}
static int
get_timeout(struct cyclades_port * info, unsigned long *value)
{
unsigned char *base_addr;
int card,channel,chip;
unsigned long tmp;
card = info->card;
channel = info->line - cy_card[card].first_line;
chip = channel>>2;
channel &= 0x03;
base_addr = (unsigned char*)
(cy_card[card].base_addr + cy_chip_offset[chip]);
tmp = base_addr[CyRTPR];
put_fs_long(tmp,value);
return 0;
}
static int
set_default_timeout(struct cyclades_port * info, unsigned long value)
{
info->default_timeout = value & 0xff;
return 0;
}
static int
get_default_timeout(struct cyclades_port * info, unsigned long *value)
{
put_fs_long(info->default_timeout,value);
return 0;
}
static int static int
cy_ioctl(struct tty_struct *tty, struct file * file, cy_ioctl(struct tty_struct *tty, struct file * file,
...@@ -1905,6 +2079,63 @@ cy_ioctl(struct tty_struct *tty, struct file * file, ...@@ -1905,6 +2079,63 @@ cy_ioctl(struct tty_struct *tty, struct file * file,
#endif #endif
switch (cmd) { switch (cmd) {
case CYGETMON:
error = verify_area(VERIFY_WRITE, (void *) arg
,sizeof(struct cyclades_monitor));
if (error){
ret_val = error;
break;
}
ret_val = get_mon_info(info, (struct cyclades_monitor *)arg);
break;
case CYGETTHRESH:
error = verify_area(VERIFY_WRITE, (void *) arg
,sizeof(unsigned long));
if (error){
ret_val = error;
break;
}
ret_val = get_threshold(info, (unsigned long *)arg);
break;
case CYSETTHRESH:
ret_val = set_threshold(info, (unsigned long)arg);
break;
case CYGETDEFTHRESH:
error = verify_area(VERIFY_WRITE, (void *) arg
,sizeof(unsigned long));
if (error){
ret_val = error;
break;
}
ret_val = get_default_threshold(info, (unsigned long *)arg);
break;
case CYSETDEFTHRESH:
ret_val = set_default_threshold(info, (unsigned long)arg);
break;
case CYGETTIMEOUT:
error = verify_area(VERIFY_WRITE, (void *) arg
,sizeof(unsigned long));
if (error){
ret_val = error;
break;
}
ret_val = get_timeout(info, (unsigned long *)arg);
break;
case CYSETTIMEOUT:
ret_val = set_timeout(info, (unsigned long)arg);
break;
case CYGETDEFTIMEOUT:
error = verify_area(VERIFY_WRITE, (void *) arg
,sizeof(unsigned long));
if (error){
ret_val = error;
break;
}
ret_val = get_default_timeout(info, (unsigned long *)arg);
break;
case CYSETDEFTIMEOUT:
ret_val = set_default_timeout(info, (unsigned long)arg);
break;
case TCSBRK: /* SVID version: non-zero arg --> no break */ case TCSBRK: /* SVID version: non-zero arg --> no break */
ret_val = tty_check_change(tty); ret_val = tty_check_change(tty);
if (ret_val) if (ret_val)
...@@ -2212,7 +2443,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp, ...@@ -2212,7 +2443,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
channel = info->line - cinfo->first_line; channel = info->line - cinfo->first_line;
chip = channel>>2; chip = channel>>2;
channel &= 0x03; channel &= 0x03;
base_addr = (char *) (cinfo->base_addr + chip * CyRegSize); base_addr = (char *) (cinfo->base_addr + cy_chip_offset[chip]);
while (1) { while (1) {
save_flags(flags); cli(); save_flags(flags); cli();
...@@ -2293,6 +2524,9 @@ cy_open(struct tty_struct *tty, struct file * filp) ...@@ -2293,6 +2524,9 @@ cy_open(struct tty_struct *tty, struct file * filp)
return -ENODEV; return -ENODEV;
} }
info = &cy_port[line]; info = &cy_port[line];
if (info->line < 0){
return -ENODEV;
}
#ifdef SERIAL_DEBUG_OTHER #ifdef SERIAL_DEBUG_OTHER
printk("cy_open ttyC%d\n", info->line); /* */ printk("cy_open ttyC%d\n", info->line); /* */
#endif #endif
...@@ -2372,16 +2606,18 @@ show_version(void) ...@@ -2372,16 +2606,18 @@ show_version(void)
/* initialize chips on card -- return number of valid /* initialize chips on card -- return number of valid
chips (which is number of ports/4) */ chips (which is number of ports/4) */
int int
cy_init_card(unsigned char *base_addr) cy_init_card(unsigned char *true_base_addr)
{ {
volatile unsigned short discard; volatile unsigned short discard;
unsigned int chip_number; unsigned int chip_number;
unsigned char* base_addr;
discard = base_addr[Cy_HwReset]; /* Cy_HwReset is 0x1400 */ discard = true_base_addr[Cy_HwReset]; /* Cy_HwReset is 0x1400 */
discard = base_addr[Cy_ClrIntr]; /* Cy_ClrIntr is 0x1800 */ discard = true_base_addr[Cy_ClrIntr]; /* Cy_ClrIntr is 0x1800 */
udelay(500L); udelay(500L);
for(chip_number=0; chip_number<CyMaxChipsPerCard; chip_number++){ for(chip_number=0; chip_number<CyMaxChipsPerCard; chip_number++){
base_addr = true_base_addr + cy_chip_offset[chip_number];
udelay(1000L); udelay(1000L);
if(base_addr[CyCCR] != 0x00){ if(base_addr[CyCCR] != 0x00){
/************* /*************
...@@ -2408,13 +2644,11 @@ cy_init_card(unsigned char *base_addr) ...@@ -2408,13 +2644,11 @@ cy_init_card(unsigned char *base_addr)
return chip_number; return chip_number;
} }
base_addr[CyGCR] = CyCH0_SERIAL; base_addr[CyGCR] = CyCH0_SERIAL;
base_addr[CyPPR] = CyCLOCK_25_1MS * 5; /* run clock at 200 Hz */ base_addr[CyPPR] = 244; /* better value than CyCLOCK_25_1MS * 5
to run clock at 200 Hz */
printk(" chip #%d at %#6lx is rev 0x%2x\n", printk(" chip #%d at %#6lx is rev 0x%2x\n",
chip_number, (unsigned long)base_addr, base_addr[CyGFRCR]); chip_number, (unsigned long)base_addr, base_addr[CyGFRCR]);
/* advance to next chip on card */
base_addr += CyRegSize;
} }
return chip_number; return chip_number;
...@@ -2567,6 +2801,8 @@ scrn[1] = '\0'; ...@@ -2567,6 +2801,8 @@ scrn[1] = '\0';
printk("cyc: %d: setting count to 0\n", __LINE__); printk("cyc: %d: setting count to 0\n", __LINE__);
#endif #endif
info->blocked_open = 0; info->blocked_open = 0;
info->default_threshold = 0;
info->default_timeout = 0;
info->tqueue.routine = do_softint; info->tqueue.routine = do_softint;
info->tqueue.data = info; info->tqueue.data = info;
info->callout_termios =cy_callout_driver.init_termios; info->callout_termios =cy_callout_driver.init_termios;
...@@ -2575,7 +2811,9 @@ scrn[1] = '\0'; ...@@ -2575,7 +2811,9 @@ scrn[1] = '\0';
info->close_wait = 0; info->close_wait = 0;
/* info->session */ /* info->session */
/* info->pgrp */ /* info->pgrp */
/* info->read_status_mask */ /*** !!!!!!!! this may expose new bugs !!!!!!!!! *********/
info->read_status_mask = CyTIMEOUT| CySPECHAR| CyBREAK
| CyPARITY| CyFRAME| CyOVERRUN;
/* info->timeout */ /* info->timeout */
printk("ttyC%1d ", info->line); printk("ttyC%1d ", info->line);
...@@ -2597,6 +2835,7 @@ scrn[1] = '\0'; ...@@ -2597,6 +2835,7 @@ scrn[1] = '\0';
} /* cy_init */ } /* cy_init */
#ifdef CYCLOM_SHOW_STATUS
static void static void
show_status(int line_num) show_status(int line_num)
{ {
...@@ -2638,7 +2877,7 @@ show_status(int line_num) ...@@ -2638,7 +2877,7 @@ show_status(int line_num)
save_flags(flags); cli(); save_flags(flags); cli();
base_addr = (unsigned char*) base_addr = (unsigned char*)
(cy_card[card].base_addr + chip * CyRegSize); (cy_card[card].base_addr + cy_chip_offset[chip]);
/* Global Registers */ /* Global Registers */
...@@ -2693,5 +2932,5 @@ show_status(int line_num) ...@@ -2693,5 +2932,5 @@ show_status(int line_num)
restore_flags(flags); restore_flags(flags);
} /* show_status */ } /* show_status */
#endif
...@@ -1051,7 +1051,9 @@ static void release_dev(struct file * filp) ...@@ -1051,7 +1051,9 @@ static void release_dev(struct file * filp)
if (o_tty->ldisc.close) if (o_tty->ldisc.close)
(o_tty->ldisc.close)(o_tty); (o_tty->ldisc.close)(o_tty);
o_tty->ldisc = ldiscs[N_TTY]; o_tty->ldisc = ldiscs[N_TTY];
#if 0 /* No way! We just released the termios struct! */
o_tty->termios->c_line = N_TTY; o_tty->termios->c_line = N_TTY;
#endif
} }
tty->driver.table[idx] = NULL; tty->driver.table[idx] = NULL;
...@@ -1659,7 +1661,7 @@ int tty_unregister_driver(struct tty_driver *driver) ...@@ -1659,7 +1661,7 @@ int tty_unregister_driver(struct tty_driver *driver)
int retval; int retval;
struct tty_driver *p; struct tty_driver *p;
int found = 0; int found = 0;
int major_inuse = 0; char *othername = NULL;
if (*driver->refcount) if (*driver->refcount)
return -EBUSY; return -EBUSY;
...@@ -1668,14 +1670,15 @@ int tty_unregister_driver(struct tty_driver *driver) ...@@ -1668,14 +1670,15 @@ int tty_unregister_driver(struct tty_driver *driver)
if (p == driver) if (p == driver)
found++; found++;
else if (p->major == driver->major) else if (p->major == driver->major)
major_inuse++; othername = p->name;
} }
if (!major_inuse) { if (othername == NULL) {
retval = unregister_chrdev(driver->major, driver->name); retval = unregister_chrdev(driver->major, driver->name);
if (retval) if (retval)
return retval; return retval;
} } else
register_chrdev(driver->major, othername, &tty_fops);
if (driver->prev) if (driver->prev)
driver->prev->next = driver->next; driver->prev->next = driver->next;
......
...@@ -45,6 +45,7 @@ bad_clone_list[] = { ...@@ -45,6 +45,7 @@ bad_clone_list[] = {
{"DE100", "DE200", {0x00, 0xDE, 0x01,}}, {"DE100", "DE200", {0x00, 0xDE, 0x01,}},
{"DE120", "DE220", {0x00, 0x80, 0xc8,}}, {"DE120", "DE220", {0x00, 0x80, 0xc8,}},
{"DFI1000", "DFI2000", {'D', 'F', 'I',}}, /* Original, eh? */ {"DFI1000", "DFI2000", {'D', 'F', 'I',}}, /* Original, eh? */
{"EtherNext UTP8", "EtherNext UTP16", {0x00, 0x00, 0x79}},
{0,} {0,}
}; };
......
...@@ -9,6 +9,13 @@ struct cyclades_chip { ...@@ -9,6 +9,13 @@ struct cyclades_chip {
int filler; int filler;
}; };
struct cyclades_monitor {
unsigned long int_count;
unsigned long char_count;
unsigned long char_max;
unsigned long char_last;
};
/* /*
* This is our internal structure for each serial port's state. * This is our internal structure for each serial port's state.
* *
...@@ -45,14 +52,28 @@ struct cyclades_port { ...@@ -45,14 +52,28 @@ struct cyclades_port {
int xmit_head; int xmit_head;
int xmit_tail; int xmit_tail;
int xmit_cnt; int xmit_cnt;
int default_threshold;
int default_timeout;
struct tq_struct tqueue; struct tq_struct tqueue;
struct termios normal_termios; struct termios normal_termios;
struct termios callout_termios; struct termios callout_termios;
struct wait_queue *open_wait; struct wait_queue *open_wait;
struct wait_queue *close_wait; struct wait_queue *close_wait;
struct cyclades_monitor mon;
}; };
#define CYCLADES_MAGIC 0x4359 #define CYCLADES_MAGIC 0x4359
#define CYGETMON 0x435901
#define CYGETTHRESH 0x435902
#define CYSETTHRESH 0x435903
#define CYGETDEFTHRESH 0x435904
#define CYSETDEFTHRESH 0x435905
#define CYGETTIMEOUT 0x435906
#define CYSETTIMEOUT 0x435907
#define CYGETDEFTIMEOUT 0x435908
#define CYSETDEFTIMEOUT 0x435909
/* /*
* Events are used to schedule things to happen at timer-interrupt * Events are used to schedule things to happen at timer-interrupt
* time, instead of at cy interrupt time. * time, instead of at cy interrupt time.
......
...@@ -227,6 +227,14 @@ typedef struct { ...@@ -227,6 +227,14 @@ typedef struct {
#define ELFCLASS64 2 #define ELFCLASS64 2
#define ELFCLASSNUM 3 #define ELFCLASSNUM 3
#define ELFDATANONE 0 /* e_ident[EI_DATA] */
#define ELFDATA2LSB 1
#define ELFDATA2MSB 2
#define EV_NONE 0 /* e_version, EI_VERSION */
#define EV_CURRENT 1
#define EV_NUM 2
#define ELF_START_MMAP 0x80000000 #define ELF_START_MMAP 0x80000000
#endif /* _LINUX_ELF_H */ #endif /* _LINUX_ELF_H */
...@@ -80,7 +80,7 @@ struct ip_fw ...@@ -80,7 +80,7 @@ struct ip_fw
* (ports[0] <= port <= ports[1]) * * (ports[0] <= port <= ports[1]) *
* */ * */
#define IP_FW_F_PRN 0x020 /* In verbose mode print this firewall*/ #define IP_FW_F_PRN 0x020 /* In verbose mode print this firewall*/
#define IP_FW_F_BIDIR 0x040 /* For accounting-count two way */ #define IP_FW_F_BIDIR 0x040 /* For bidirectional firewalls */
#define IP_FW_F_TCPSYN 0x080 /* For tcp packets-check SYN only */ #define IP_FW_F_TCPSYN 0x080 /* For tcp packets-check SYN only */
#define IP_FW_F_ICMPRPL 0x100 /* Send back icmp unreachable packet */ #define IP_FW_F_ICMPRPL 0x100 /* Send back icmp unreachable packet */
#define IP_FW_F_MASK 0x1FF /* All possible flag bits mask */ #define IP_FW_F_MASK 0x1FF /* All possible flag bits mask */
...@@ -111,6 +111,15 @@ struct ip_fw ...@@ -111,6 +111,15 @@ struct ip_fw
#define IP_ACCT_FLUSH (IP_FW_BASE_CTL+18) #define IP_ACCT_FLUSH (IP_FW_BASE_CTL+18)
#define IP_ACCT_ZERO (IP_FW_BASE_CTL+19) #define IP_ACCT_ZERO (IP_FW_BASE_CTL+19)
struct ip_fwpkt
{
struct iphdr fwp_iph; /* IP header */
union {
struct tcphdr fwp_tcph; /* TCP header or */
struct udphdr fwp_udph; /* UDP header */
} fwp_protoh;
struct in_addr fwp_via; /* interface address */
};
/* /*
* Main firewall chains definitions and global var's definitions. * Main firewall chains definitions and global var's definitions.
...@@ -129,10 +138,10 @@ extern int ip_fw_ctl(int, void *, int); ...@@ -129,10 +138,10 @@ extern int ip_fw_ctl(int, void *, int);
#endif #endif
#ifdef CONFIG_IP_ACCT #ifdef CONFIG_IP_ACCT
extern struct ip_fw *ip_acct_chain; extern struct ip_fw *ip_acct_chain;
extern int ip_acct_cnt(struct iphdr *, struct device *, struct ip_fw *); extern void ip_acct_cnt(struct iphdr *, struct device *, struct ip_fw *);
extern int ip_acct_ctl(int, void *, int); extern int ip_acct_ctl(int, void *, int);
#endif #endif
extern int ip_fw_chk(struct iphdr *, struct device *rif,struct ip_fw *, int); extern int ip_fw_chk(struct iphdr *, struct device *rif,struct ip_fw *, int, int);
#endif /* KERNEL */ #endif /* KERNEL */
#endif /* _IP_FW_H */ #endif /* _IP_FW_H */
...@@ -120,9 +120,8 @@ ...@@ -120,9 +120,8 @@
#define DBG_AUD 25 /* "read audio" debugging */ #define DBG_AUD 25 /* "read audio" debugging */
#define DBG_SEQ 26 /* Sequoia interface configuration trace */ #define DBG_SEQ 26 /* Sequoia interface configuration trace */
#define DBG_LCS 27 /* Longshine LCS-7260 debugging trace */ #define DBG_LCS 27 /* Longshine LCS-7260 debugging trace */
#define DBG_TEA 28 /* TEAC CD-55A debugging trace */ #define DBG_CD2 28 /* MKE CD200 debugging trace */
#define DBG_CD2 29 /* MKE CD200 debugging trace */ #define DBG_000 29 /* unnecessary information */
#define DBG_000 30 /* unnecessary information */
/*==========================================================================*/ /*==========================================================================*/
/*==========================================================================*/ /*==========================================================================*/
...@@ -254,13 +253,11 @@ ...@@ -254,13 +253,11 @@
#define drv_099 (drv_fam1+0x01) /* <100 */ #define drv_099 (drv_fam1+0x01) /* <100 */
#define drv_100 (drv_fam1+0x02) /* >=100 */ #define drv_100 (drv_fam1+0x02) /* >=100 */
#define drv_famT 0x40 /* TEAC CD-55A */
#define drv_fam2 0x80 /* CD200 family */ #define drv_fam2 0x80 /* CD200 family */
#define fam0_drive (DriveStruct[d].drv_type&drv_fam0) #define fam0_drive (DriveStruct[d].drv_type&drv_fam0)
#define famL_drive (DriveStruct[d].drv_type&drv_famL) #define famL_drive (DriveStruct[d].drv_type&drv_famL)
#define fam1_drive (DriveStruct[d].drv_type&drv_fam1) #define fam1_drive (DriveStruct[d].drv_type&drv_fam1)
#define famT_drive (DriveStruct[d].drv_type&drv_famT)
#define fam2_drive (DriveStruct[d].drv_type&drv_fam2) #define fam2_drive (DriveStruct[d].drv_type&drv_fam2)
#define fam0L_drive (DriveStruct[d].drv_type&(drv_fam0|drv_famL)) #define fam0L_drive (DriveStruct[d].drv_type&(drv_fam0|drv_famL))
#define fam1L_drive (DriveStruct[d].drv_type&(drv_fam1|drv_famL)) #define fam1L_drive (DriveStruct[d].drv_type&(drv_fam1|drv_famL))
...@@ -522,19 +519,15 @@ Read XA Parameter: ...@@ -522,19 +519,15 @@ Read XA Parameter:
* CR-56x: CMD1_ * CR-56x: CMD1_
* CD200: CMD2_ * CD200: CMD2_
* LCS-7260: CMDL_ * LCS-7260: CMDL_
* TEAC CD-55A: CMDT_
*/ */
#define CMD1_RESET 0x0a #define CMD1_RESET 0x0a
#define CMD2_RESET 0x01 #define CMD2_RESET 0x01
#define CMDT_RESET 0xc0
#define CMD1_LOCK_CTL 0x0c #define CMD1_LOCK_CTL 0x0c
#define CMD2_LOCK_CTL 0x1e #define CMD2_LOCK_CTL 0x1e
#define CMDL_LOCK_CTL 0x0e #define CMDL_LOCK_CTL 0x0e
#define CMDT_LOCK_CTL 0x1e
#define CMD1_TRAY_CTL 0x07 #define CMD1_TRAY_CTL 0x07
#define CMD2_TRAY_CTL 0x1b #define CMD2_TRAY_CTL 0x1b
#define CMDL_TRAY_CTL 0x0d #define CMDL_TRAY_CTL 0x0d
#define CMDT_TRAY_CTL 0x1b
#define CMD1_MULTISESS 0x8d #define CMD1_MULTISESS 0x8d
#define CMDL_MULTISESS 0x8c #define CMDL_MULTISESS 0x8c
#define CMD1_SUBCHANINF 0x11 #define CMD1_SUBCHANINF 0x11
...@@ -542,7 +535,6 @@ Read XA Parameter: ...@@ -542,7 +535,6 @@ Read XA Parameter:
#define CMD2_x02 0x02 #define CMD2_x02 0x02
#define CMD1_x08 0x08 #define CMD1_x08 0x08
#define CMD2_x08 0x08 #define CMD2_x08 0x08
#define CMDT_x08 0x08
#define CMD2_SETSPEED 0xda #define CMD2_SETSPEED 0xda
#define CMD0_PATH_CHECK 0x00 #define CMD0_PATH_CHECK 0x00
...@@ -553,12 +545,10 @@ Read XA Parameter: ...@@ -553,12 +545,10 @@ Read XA Parameter:
#define CMD1_SEEK 0x01 #define CMD1_SEEK 0x01
#define CMD2_SEEK 0x2b #define CMD2_SEEK 0x2b
#define CMDL_SEEK 0x01 #define CMDL_SEEK 0x01
#define CMDT_SEEK 0x2b
#define CMD0_READ 0x02 #define CMD0_READ 0x02
#define CMD1_READ 0x10 #define CMD1_READ 0x10
#define CMD2_READ 0x28 #define CMD2_READ 0x28
#define CMDL_READ 0x02 #define CMDL_READ 0x02
#define CMDT_READ 0x28
#define CMD0_READ_XA 0x03 #define CMD0_READ_XA 0x03
#define CMD2_READ_XA 0xd4 #define CMD2_READ_XA 0xd4
#define CMDL_READ_XA 0x03 /* really ?? */ #define CMDL_READ_XA 0x03 /* really ?? */
...@@ -585,33 +575,27 @@ Read XA Parameter: ...@@ -585,33 +575,27 @@ Read XA Parameter:
#define CMD1_PLAY_MSF 0x0e #define CMD1_PLAY_MSF 0x0e
#define CMD2_PLAY_MSF 0x47 #define CMD2_PLAY_MSF 0x47
#define CMDL_PLAY_MSF 0x #define CMDL_PLAY_MSF 0x
#define CMDT_PLAY_MSF 0x47
#define CMD0_PLAY_TI 0x0c #define CMD0_PLAY_TI 0x0c
#define CMD0_STATUS 0x81 #define CMD0_STATUS 0x81
#define CMD1_STATUS 0x05 #define CMD1_STATUS 0x05
#define CMD2_STATUS 0x00 #define CMD2_STATUS 0x00
#define CMDL_STATUS 0x81 #define CMDL_STATUS 0x81
#define CMDT_STATUS 0x00
#define CMD0_READ_ERR 0x82 #define CMD0_READ_ERR 0x82
#define CMD1_READ_ERR 0x82 #define CMD1_READ_ERR 0x82
#define CMD2_READ_ERR 0x03 #define CMD2_READ_ERR 0x03
#define CMDL_READ_ERR 0x82 #define CMDL_READ_ERR 0x82
#define CMDT_READ_ERR 0x03 /* get audio status */
#define CMD0_READ_VER 0x83 #define CMD0_READ_VER 0x83
#define CMD1_READ_VER 0x83 #define CMD1_READ_VER 0x83
#define CMD2_READ_VER 0x12 #define CMD2_READ_VER 0x12
#define CMDT_READ_VER 0x12 /* ??? (unused) */
#define CMDL_READ_VER 0x83 #define CMDL_READ_VER 0x83
#define CMD0_SETMODE 0x84 #define CMD0_SETMODE 0x84
#define CMD1_SETMODE 0x09 #define CMD1_SETMODE 0x09
#define CMD2_SETMODE 0x55 #define CMD2_SETMODE 0x55
#define CMDL_SETMODE 0x84 #define CMDL_SETMODE 0x84
#define CMDT_SETMODE 0x55
#define CMD0_GETMODE 0x85 #define CMD0_GETMODE 0x85
#define CMD1_GETMODE 0x84 #define CMD1_GETMODE 0x84
#define CMD2_GETMODE 0x5a #define CMD2_GETMODE 0x5a
#define CMDL_GETMODE 0x85 #define CMDL_GETMODE 0x85
#define CMDT_GETMODE 0x5a
#define CMD0_SET_XA 0x86 #define CMD0_SET_XA 0x86
#define CMD0_GET_XA 0x87 #define CMD0_GET_XA 0x87
#define CMD0_CAPACITY 0x88 #define CMD0_CAPACITY 0x88
...@@ -622,13 +606,11 @@ Read XA Parameter: ...@@ -622,13 +606,11 @@ Read XA Parameter:
#define CMD1_READSUBQ 0x87 #define CMD1_READSUBQ 0x87
#define CMD2_READSUBQ 0x42 #define CMD2_READSUBQ 0x42
#define CMDL_READSUBQ 0x89 #define CMDL_READSUBQ 0x89
#define CMDT_READSUBQ 0x42
#define CMD0_DISKCODE 0x8a #define CMD0_DISKCODE 0x8a
#define CMD0_DISKINFO 0x8b #define CMD0_DISKINFO 0x8b
#define CMD1_DISKINFO 0x8b #define CMD1_DISKINFO 0x8b
#define CMD2_DISKINFO 0x43 #define CMD2_DISKINFO 0x43
#define CMDL_DISKINFO 0x8b #define CMDL_DISKINFO 0x8b
#define CMDT_DISKINFO 0x43
#define CMD0_READTOC 0x8c #define CMD0_READTOC 0x8c
#define CMD1_READTOC 0x8c #define CMD1_READTOC 0x8c
#define CMD2_READTOC 0x #define CMD2_READTOC 0x
...@@ -637,7 +619,6 @@ Read XA Parameter: ...@@ -637,7 +619,6 @@ Read XA Parameter:
#define CMD1_PAU_RES 0x0d #define CMD1_PAU_RES 0x0d
#define CMD2_PAU_RES 0x4b #define CMD2_PAU_RES 0x4b
#define CMDL_PAU_RES 0x8d #define CMDL_PAU_RES 0x8d
#define CMDT_PAU_RES 0x4b
#define CMD0_PACKET 0x8e #define CMD0_PACKET 0x8e
#define CMD1_PACKET 0x8e #define CMD1_PACKET 0x8e
#define CMD2_PACKET 0x #define CMD2_PACKET 0x
......
Changes for NET3.017 Upgrade Notes from 1.0
[Alan Cox - Alan.Cox@linux.org]
This is mostly small stuff as follows: Upgrading to 1.2.0 from a 1.0 kernel networking set. If you are using
a complete 1.2 distribution you can ignore this.
o accept()ed socket don't end up with an invalid sk->socket and give bogus This doesn't attempt to list the changes. That would be too large. Instead
netstat output. just what you need and can change
o FASYNC/SIGIO now works with sockets.
o Fixed the permissions on F_SETOWN for all. Its now as broken/working
as other systems. Really we need something like a 32bit generation
number on processes.
o ARP allows proxy for whole networks (a la cisco routers)
o TCP sendto() reports ENOTCONN in the right cases
o Removed some surplus uncommented code from tcp.c
o Fixed protocol violation during closedown in tcp.c
[Still not got the window < MSS bug fix included]
Fixes for 1.1.58 arp,ifconfig, etc. Get net-tools-1.1.95 (or 1.2.0 if its out) from
ftp.linux.org.uk:/pub/Linux/Networking/PROGRAMS/NetTools, and install
these. You will also acquire a couple of new tools "plipconfig" for tuning
plip links and "ipfw" for ip firewall management.
o non blocking connect fail gets the error code right. bootpd: The original bootpd has a bug that the 1.2 kernel spots. You will
o select() not reporting read ok after an urgent read fixed. need to upgrade this to the version in
ftp.linux.org.uk:/pub/Linux/Networking/PROGRAMS/Upgrades
Standard programs that you ought to update are
named 4.7.x to 4.9.x Stops named dying occasionally
pop3d 1.001 to 1.004 Fixes a bug that can lose mail
A complete current networking set for Linux can be obtained by getting
the NetKit[A,B...] series archives from ftp.funet.fi. Funet also carries
binaries for Linux mbone applications if you now wish to make use of
these facilities.
For commercial UK custom Linux networking projects, drivers and development
(but not free support!) I can be contacted via
I^2IT Ltd, The Innovation Centre, University Of Wales
Swansea SA2 8PP.
Fax: +44 1792 295811
Tel: +44 1792 295213
Please don't send commercial queries to my email address as I have that
in an academic and _not_ commercial capacity. On the other hand feel
free to send bug reports, queries and enhancements that way.
Alan
...@@ -130,9 +130,15 @@ struct arp_table ...@@ -130,9 +130,15 @@ struct arp_table
#define ARP_CHECK_INTERVAL (60 * HZ) #define ARP_CHECK_INTERVAL (60 * HZ)
enum proxy {
PROXY_EXACT=0,
PROXY_ANY,
PROXY_NONE,
};
/* Forward declarations. */ /* Forward declarations. */
static void arp_check_expire (unsigned long); static void arp_check_expire (unsigned long);
static struct arp_table *arp_lookup(unsigned long paddr, int exact); static struct arp_table *arp_lookup(unsigned long paddr, enum proxy proxy);
static struct timer_list arp_timer = static struct timer_list arp_timer =
...@@ -497,6 +503,7 @@ void arp_destroy(unsigned long ip_addr, int force) ...@@ -497,6 +503,7 @@ void arp_destroy(unsigned long ip_addr, int force)
struct arp_table **pentry; struct arp_table **pentry;
unsigned long hash = HASH(ip_addr); unsigned long hash = HASH(ip_addr);
ugly:
cli(); cli();
pentry = &arp_tables[hash]; pentry = &arp_tables[hash];
if (! *pentry) /* also check proxy entries */ if (! *pentry) /* also check proxy entries */
...@@ -512,7 +519,12 @@ void arp_destroy(unsigned long ip_addr, int force) ...@@ -512,7 +519,12 @@ void arp_destroy(unsigned long ip_addr, int force)
del_timer(&entry->timer); del_timer(&entry->timer);
sti(); sti();
arp_release_entry(entry); arp_release_entry(entry);
return; /* this would have to be cleaned up */
goto ugly;
/* perhaps like this ?
cli();
entry = *pentry;
*/
} }
pentry = &entry->next; pentry = &entry->next;
if (!checked_proxies && ! *pentry) if (!checked_proxies && ! *pentry)
...@@ -842,7 +854,7 @@ int arp_find(unsigned char *haddr, unsigned long paddr, struct device *dev, ...@@ -842,7 +854,7 @@ int arp_find(unsigned char *haddr, unsigned long paddr, struct device *dev,
/* /*
* Find an entry * Find an entry
*/ */
entry = arp_lookup(paddr, 1); entry = arp_lookup(paddr, PROXY_NONE);
if (entry != NULL) /* It exists */ if (entry != NULL) /* It exists */
{ {
...@@ -1006,11 +1018,11 @@ int arp_get_info(char *buffer, char **start, off_t offset, int length) ...@@ -1006,11 +1018,11 @@ int arp_get_info(char *buffer, char **start, off_t offset, int length)
/* /*
* This will find an entry in the ARP table by looking at the IP address. * This will find an entry in the ARP table by looking at the IP address.
* If exact is true then only exact IP matches will be allowed * If proxy is PROXY_EXACT then only exact IP matches will be allowed
* for proxy entries, otherwise the netmask will be used * for proxy entries, otherwise the netmask will be used
*/ */
static struct arp_table *arp_lookup(unsigned long paddr, int exact) static struct arp_table *arp_lookup(unsigned long paddr, enum proxy proxy)
{ {
struct arp_table *entry; struct arp_table *entry;
unsigned long hash = HASH(paddr); unsigned long hash = HASH(paddr);
...@@ -1019,9 +1031,10 @@ static struct arp_table *arp_lookup(unsigned long paddr, int exact) ...@@ -1019,9 +1031,10 @@ static struct arp_table *arp_lookup(unsigned long paddr, int exact)
if (entry->ip == paddr) break; if (entry->ip == paddr) break;
/* it's possibly a proxy entry (with a netmask) */ /* it's possibly a proxy entry (with a netmask) */
if (!entry) if (!entry && proxy != PROXY_NONE)
for (entry=arp_tables[PROXY_HASH]; entry != NULL; entry = entry->next) for (entry=arp_tables[PROXY_HASH]; entry != NULL; entry = entry->next)
if (exact? (entry->ip==paddr) : !((entry->ip^paddr)&entry->mask)) if ((proxy==PROXY_EXACT) ? (entry->ip==paddr)
: !((entry->ip^paddr)&entry->mask))
break; break;
return entry; return entry;
...@@ -1099,7 +1112,7 @@ static int arp_req_set(struct arpreq *req) ...@@ -1099,7 +1112,7 @@ static int arp_req_set(struct arpreq *req)
/* /*
* Find the entry * Find the entry
*/ */
entry = arp_lookup(ip, 1); entry = arp_lookup(ip, PROXY_EXACT);
if (entry && (entry->flags & ATF_PUBL) != (r.arp_flags & ATF_PUBL)) if (entry && (entry->flags & ATF_PUBL) != (r.arp_flags & ATF_PUBL))
{ {
sti(); sti();
...@@ -1179,7 +1192,7 @@ static int arp_req_get(struct arpreq *req) ...@@ -1179,7 +1192,7 @@ static int arp_req_get(struct arpreq *req)
si = (struct sockaddr_in *) &r.arp_pa; si = (struct sockaddr_in *) &r.arp_pa;
cli(); cli();
entry = arp_lookup(si->sin_addr.s_addr,0); entry = arp_lookup(si->sin_addr.s_addr,PROXY_ANY);
if (entry == NULL) if (entry == NULL)
{ {
......
...@@ -109,6 +109,7 @@ ...@@ -109,6 +109,7 @@
#include "protocol.h" #include "protocol.h"
#include "route.h" #include "route.h"
#include "tcp.h" #include "tcp.h"
#include "udp.h"
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include "sock.h" #include "sock.h"
#include "arp.h" #include "arp.h"
...@@ -1270,7 +1271,7 @@ static void ip_forward(struct sk_buff *skb, struct device *dev, int is_frag) ...@@ -1270,7 +1271,7 @@ static void ip_forward(struct sk_buff *skb, struct device *dev, int is_frag)
#ifdef CONFIG_IP_FIREWALL #ifdef CONFIG_IP_FIREWALL
int err; int err;
if((err=ip_fw_chk(skb->h.iph, dev, ip_fw_fwd_chain, ip_fw_fwd_policy))!=1) if((err=ip_fw_chk(skb->h.iph, dev, ip_fw_fwd_chain, ip_fw_fwd_policy, 0))!=1)
{ {
if(err==-1) if(err==-1)
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0, dev); icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0, dev);
...@@ -1500,7 +1501,7 @@ int ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt) ...@@ -1500,7 +1501,7 @@ int ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
#ifdef CONFIG_IP_FIREWALL #ifdef CONFIG_IP_FIREWALL
if ((err=ip_fw_chk(iph,dev,ip_fw_blk_chain,ip_fw_blk_policy))!=1) if ((err=ip_fw_chk(iph,dev,ip_fw_blk_chain,ip_fw_blk_policy, 0))!=1)
{ {
if(err==-1) if(err==-1)
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0, dev); icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0, dev);
...@@ -1817,6 +1818,12 @@ void ip_queue_xmit(struct sock *sk, struct device *dev, ...@@ -1817,6 +1818,12 @@ void ip_queue_xmit(struct sock *sk, struct device *dev,
skb->ip_hdr = iph; skb->ip_hdr = iph;
iph->tot_len = ntohs(skb->len-dev->hard_header_len); iph->tot_len = ntohs(skb->len-dev->hard_header_len);
#ifdef CONFIG_IP_FIREWALL
if(ip_fw_chk(iph, dev, ip_fw_blk_chain, ip_fw_blk_policy, 0) != 1)
/* just don't send this packet */
return;
#endif
/* /*
* No reassigning numbers to fragments... * No reassigning numbers to fragments...
*/ */
......
...@@ -16,6 +16,9 @@ ...@@ -16,6 +16,9 @@
* appear it's not practical - Read: It works, it's not clean but please * appear it's not practical - Read: It works, it's not clean but please
* don't consider it to be his standard of finished work. * don't consider it to be his standard of finished work.
* Alan Cox 12/Feb/1995 * Alan Cox 12/Feb/1995
* Porting bidirectional entries from BSD, fixing accounting issues,
* adding struct ip_fwpkt for checking packets with interface address
* Jos Vos 5/Mar/1995.
* *
* All the real work was done by ..... * All the real work was done by .....
*/ */
...@@ -133,12 +136,17 @@ extern inline int port_match(unsigned short *portptr,int nports,unsigned short p ...@@ -133,12 +136,17 @@ extern inline int port_match(unsigned short *portptr,int nports,unsigned short p
/* /*
* Returns 0 if packet should be dropped, 1 or more if it should be accepted. * Returns 0 if packet should be dropped, 1 if it should be accepted,
* and -1 if an ICMP host unreachable packet should be sent.
* Also does accounting so you can feed it the accounting chain. * Also does accounting so you can feed it the accounting chain.
* If opt is set to 1, it means that we do this for accounting
* purposes (searches all entries and handles fragments different).
* If opt is set to 2, it doesn't count a matching packet, which
* is used when calling this for checking purposes (IP_FW_CHK_*).
*/ */
int ip_fw_chk(struct iphdr *ip, struct device *rif, struct ip_fw *chain, int policy) int ip_fw_chk(struct iphdr *ip, struct device *rif, struct ip_fw *chain, int policy, int opt)
{ {
struct ip_fw *f; struct ip_fw *f;
struct tcphdr *tcp=(struct tcphdr *)((unsigned long *)ip+ip->ihl); struct tcphdr *tcp=(struct tcphdr *)((unsigned long *)ip+ip->ihl);
...@@ -146,7 +154,7 @@ int ip_fw_chk(struct iphdr *ip, struct device *rif, struct ip_fw *chain, int pol ...@@ -146,7 +154,7 @@ int ip_fw_chk(struct iphdr *ip, struct device *rif, struct ip_fw *chain, int pol
__u32 src, dst; __u32 src, dst;
__u16 src_port=0, dst_port=0; __u16 src_port=0, dst_port=0;
unsigned short f_prt=0, prt; unsigned short f_prt=0, prt;
char notcpsyn=1; char notcpsyn=1, frag1, match;
unsigned short f_flag; unsigned short f_flag;
/* /*
...@@ -172,7 +180,9 @@ int ip_fw_chk(struct iphdr *ip, struct device *rif, struct ip_fw *chain, int pol ...@@ -172,7 +180,9 @@ int ip_fw_chk(struct iphdr *ip, struct device *rif, struct ip_fw *chain, int pol
* of system. * of system.
*/ */
if (ip->frag_off&IP_OFFSET) frag1 = ((ntohs(ip->frag_off) & IP_OFFSET) == 0);
if (!frag1 && (opt != 1) && (ip->protocol == IPPROTO_TCP ||
ip->protocol == IPPROTO_UDP))
return(1); return(1);
src = ip->saddr; src = ip->saddr;
...@@ -191,16 +201,23 @@ int ip_fw_chk(struct iphdr *ip, struct device *rif, struct ip_fw *chain, int pol ...@@ -191,16 +201,23 @@ int ip_fw_chk(struct iphdr *ip, struct device *rif, struct ip_fw *chain, int pol
{ {
case IPPROTO_TCP: case IPPROTO_TCP:
dprintf1("TCP "); dprintf1("TCP ");
src_port=ntohs(tcp->source); /* ports stay 0 if it is not the first fragment */
dst_port=ntohs(tcp->dest); if (frag1) {
if(tcp->syn && !tcp->ack) src_port=ntohs(tcp->source);
notcpsyn=0; /* We *DO* have SYN, value FALSE */ dst_port=ntohs(tcp->dest);
if(tcp->syn && !tcp->ack)
/* We *DO* have SYN, value FALSE */
notcpsyn=0;
}
prt=IP_FW_F_TCP; prt=IP_FW_F_TCP;
break; break;
case IPPROTO_UDP: case IPPROTO_UDP:
dprintf1("UDP "); dprintf1("UDP ");
src_port=ntohs(udp->source); /* ports stay 0 if it is not the first fragment */
dst_port=ntohs(udp->dest); if (frag1) {
src_port=ntohs(udp->source);
dst_port=ntohs(udp->dest);
}
prt=IP_FW_F_UDP; prt=IP_FW_F_UDP;
break; break;
case IPPROTO_ICMP: case IPPROTO_ICMP:
...@@ -214,10 +231,12 @@ int ip_fw_chk(struct iphdr *ip, struct device *rif, struct ip_fw *chain, int pol ...@@ -214,10 +231,12 @@ int ip_fw_chk(struct iphdr *ip, struct device *rif, struct ip_fw *chain, int pol
} }
dprint_ip(ip->saddr); dprint_ip(ip->saddr);
if (ip->protocol==IPPROTO_TCP || ip->protocol==IPPROTO_UDP) if (ip->protocol==IPPROTO_TCP || ip->protocol==IPPROTO_UDP)
/* This will print 0 when it is not the first fragment! */
dprintf2(":%d ", src_port); dprintf2(":%d ", src_port);
dprint_ip(ip->daddr); dprint_ip(ip->daddr);
if ( ip->protocol==IPPROTO_TCP || ip->protocol==IPPROTO_UDP) if (ip->protocol==IPPROTO_TCP || ip->protocol==IPPROTO_UDP)
/* This will print 0 when it is not the first fragment! */
dprintf2(":%d ",dst_port); dprintf2(":%d ",dst_port);
dprintf1("\n"); dprintf1("\n");
...@@ -228,8 +247,32 @@ int ip_fw_chk(struct iphdr *ip, struct device *rif, struct ip_fw *chain, int pol ...@@ -228,8 +247,32 @@ int ip_fw_chk(struct iphdr *ip, struct device *rif, struct ip_fw *chain, int pol
* an interface chain as you do in BSD - same logic * an interface chain as you do in BSD - same logic
* however. * however.
*/ */
/*
* Match can become 0x01 (a "normal" match was found),
* 0x02 (a reverse match was found), and 0x03 (the
* IP addresses match in both directions).
* Now we know in which direction(s) we should look
* for a match for the TCP/UDP ports. Both directions
* might match (e.g., when both addresses are on the
* same network for which an address/mask is given), but
* the ports might only match in one direction.
* This was obviously wrong in the original BSD code.
*/
match = 0x00;
if ((src&f->fw_smsk.s_addr)==f->fw_src.s_addr if ((src&f->fw_smsk.s_addr)==f->fw_src.s_addr
&& (dst&f->fw_dmsk.s_addr)==f->fw_dst.s_addr) && (dst&f->fw_dmsk.s_addr)==f->fw_dst.s_addr)
/* normal direction */
match |= 0x01;
if ((f->fw_flg & IP_FW_F_BIDIR) &&
(dst&f->fw_smsk.s_addr)==f->fw_src.s_addr
&& (src&f->fw_dmsk.s_addr)==f->fw_dst.s_addr)
/* reverse direction */
match |= 0x02;
if (match)
{ {
/* /*
* Look for a VIA match * Look for a VIA match
...@@ -270,11 +313,15 @@ int ip_fw_chk(struct iphdr *ip, struct device *rif, struct ip_fw *chain, int pol ...@@ -270,11 +313,15 @@ int ip_fw_chk(struct iphdr *ip, struct device *rif, struct ip_fw *chain, int pol
if(prt!=f_prt) if(prt!=f_prt)
continue; continue;
if(!(prt==IP_FW_F_ICMP ||( if(!(prt==IP_FW_F_ICMP || ((match & 0x01) &&
port_match(&f->fw_pts[0], f->fw_nsp, src_port, port_match(&f->fw_pts[0], f->fw_nsp, src_port,
f->fw_flg&IP_FW_F_SRNG) && f->fw_flg&IP_FW_F_SRNG) &&
port_match(&f->fw_pts[f->fw_nsp], f->fw_ndp, dst_port, port_match(&f->fw_pts[f->fw_nsp], f->fw_ndp, dst_port,
f->fw_flg&IP_FW_F_SRNG)))) f->fw_flg&IP_FW_F_DRNG)) || ((match & 0x02) &&
port_match(&f->fw_pts[0], f->fw_nsp, dst_port,
f->fw_flg&IP_FW_F_SRNG) &&
port_match(&f->fw_pts[f->fw_nsp], f->fw_ndp, src_port,
f->fw_flg&IP_FW_F_DRNG))))
{ {
continue; continue;
} }
...@@ -287,10 +334,14 @@ int ip_fw_chk(struct iphdr *ip, struct device *rif, struct ip_fw *chain, int pol ...@@ -287,10 +334,14 @@ int ip_fw_chk(struct iphdr *ip, struct device *rif, struct ip_fw *chain, int pol
if (f->fw_flg & IP_FW_F_PRN) if (f->fw_flg & IP_FW_F_PRN)
{ {
if(f->fw_flg&IP_FW_F_ACCEPT) if(opt != 1) {
printk("Accept "); if(f->fw_flg&IP_FW_F_ACCEPT)
else printk("Accept ");
printk("Deny "); else if(f->fw_flg&IP_FW_F_ICMPRPL)
printk("Reject ");
else
printk("Deny ");
}
switch(ip->protocol) switch(ip->protocol)
{ {
case IPPROTO_TCP: case IPPROTO_TCP:
...@@ -315,22 +366,24 @@ int ip_fw_chk(struct iphdr *ip, struct device *rif, struct ip_fw *chain, int pol ...@@ -315,22 +366,24 @@ int ip_fw_chk(struct iphdr *ip, struct device *rif, struct ip_fw *chain, int pol
printk("\n"); printk("\n");
} }
#endif #endif
if(f->fw_flg&IP_FW_F_ACCEPT) if (opt != 2) {
{
f->fw_bcnt+=ntohs(ip->tot_len); f->fw_bcnt+=ntohs(ip->tot_len);
f->fw_pcnt++; f->fw_pcnt++;
return 1;
} }
break; if (opt != 1)
break;
} /* Loop */ } /* Loop */
if(opt == 1)
return 0;
/* /*
* If we get here then none of the firewalls matched or one matched * We rely on policy defined in the rejecting entry or, if no match
* but was a no. So now we rely on policy defined in the rejecting * was found, we rely on the general policy variable for this type
* entry or if none was found in the policy variable * of firewall.
*/ */
if(f!=NULL) /* A deny match */ if(f!=NULL) /* A match was found */
f_flag=f->fw_flg; f_flag=f->fw_flg;
else else
f_flag=policy; f_flag=policy;
...@@ -342,9 +395,6 @@ int ip_fw_chk(struct iphdr *ip, struct device *rif, struct ip_fw *chain, int pol ...@@ -342,9 +395,6 @@ int ip_fw_chk(struct iphdr *ip, struct device *rif, struct ip_fw *chain, int pol
} }
static void zero_fw_chain(struct ip_fw *chainptr) static void zero_fw_chain(struct ip_fw *chainptr)
{ {
struct ip_fw *ctmp=chainptr; struct ip_fw *ctmp=chainptr;
...@@ -526,6 +576,10 @@ static int add_to_chain(struct ip_fw *volatile* chainptr, struct ip_fw *frwl) ...@@ -526,6 +576,10 @@ static int add_to_chain(struct ip_fw *volatile* chainptr, struct ip_fw *frwl)
addb4--; addb4--;
skip_check: skip_check:
} }
/* finally look at the interface address */
if ((addb4 == 0) && ftmp->fw_via.s_addr &&
!(chtmp->fw_via.s_addr))
addb4++;
} }
if (addb4>0) if (addb4>0)
{ {
...@@ -686,9 +740,10 @@ struct ip_fw *check_ipfw_struct(struct ip_fw *frwl, int len) ...@@ -686,9 +740,10 @@ struct ip_fw *check_ipfw_struct(struct ip_fw *frwl, int len)
#ifdef CONFIG_IP_ACCT #ifdef CONFIG_IP_ACCT
int ip_acct_cnt(struct iphdr *iph, struct device *dev, struct ip_fw *f) void ip_acct_cnt(struct iphdr *iph, struct device *dev, struct ip_fw *f)
{ {
return ip_fw_chk(iph, dev, f, 0); (void) ip_fw_chk(iph, dev, f, 0, 1);
return;
} }
int ip_acct_ctl(int stage, void *m, int len) int ip_acct_ctl(int stage, void *m, int len)
...@@ -738,6 +793,8 @@ int ip_acct_ctl(int stage, void *m, int len) ...@@ -738,6 +793,8 @@ int ip_acct_ctl(int stage, void *m, int len)
#ifdef CONFIG_IP_FIREWALL #ifdef CONFIG_IP_FIREWALL
int ip_fw_ctl(int stage, void *m, int len) int ip_fw_ctl(int stage, void *m, int len)
{ {
int ret;
if ( stage == IP_FW_FLUSH_BLK ) if ( stage == IP_FW_FLUSH_BLK )
{ {
free_fw_chain(&ip_fw_blk_chain); free_fw_chain(&ip_fw_blk_chain);
...@@ -775,18 +832,21 @@ int ip_fw_ctl(int stage, void *m, int len) ...@@ -775,18 +832,21 @@ int ip_fw_ctl(int stage, void *m, int len)
if ( stage == IP_FW_CHK_BLK || stage == IP_FW_CHK_FWD ) if ( stage == IP_FW_CHK_BLK || stage == IP_FW_CHK_FWD )
{ {
struct device viadev;
struct ip_fwpkt *ipfwp;
struct iphdr *ip; struct iphdr *ip;
if ( len < sizeof(struct iphdr) + 2 * sizeof(unsigned short) ) if ( len < sizeof(struct ip_fwpkt) )
{ {
#ifdef DEBUG_CONFIG_IP_FIREWALL #ifdef DEBUG_CONFIG_IP_FIREWALL
printf("ip_fw_ctl: len=%d, want at least %d\n", printf("ip_fw_ctl: length=%d, expected %d\n",
len,sizeof(struct ip) + 2 * sizeof(unsigned short)); len, sizeof(struct ip_fwpkt));
#endif #endif
return( EINVAL ); return( EINVAL );
} }
ip = (struct iphdr *)m; ipfwp = (struct ip_fwpkt *)m;
ip = &(ipfwp->fwp_iph);
if ( ip->ihl != sizeof(struct iphdr) / sizeof(int)) if ( ip->ihl != sizeof(struct iphdr) / sizeof(int))
{ {
...@@ -797,15 +857,19 @@ int ip_fw_ctl(int stage, void *m, int len) ...@@ -797,15 +857,19 @@ int ip_fw_ctl(int stage, void *m, int len)
return(EINVAL); return(EINVAL);
} }
if ( ip_fw_chk(ip, NULL, viadev.pa_addr = ipfwp->fwp_via.s_addr;
if ((ret = ip_fw_chk(ip, &viadev,
stage == IP_FW_CHK_BLK ? stage == IP_FW_CHK_BLK ?
ip_fw_blk_chain : ip_fw_fwd_chain, ip_fw_blk_chain : ip_fw_fwd_chain,
stage == IP_FW_CHK_BLK ? stage == IP_FW_CHK_BLK ?
ip_fw_blk_policy : ip_fw_fwd_policy ) ip_fw_blk_policy : ip_fw_fwd_policy, 2 )) > 0
) )
return(0); return(0);
else else if (ret == -1)
return(EACCES); return(ECONNREFUSED);
else
return(ETIMEDOUT);
} }
/* /*
...@@ -858,7 +922,7 @@ static int ip_chain_procinfo(int stage, char *buffer, char **start, ...@@ -858,7 +922,7 @@ static int ip_chain_procinfo(int stage, char *buffer, char **start,
off_t pos=0, begin=0; off_t pos=0, begin=0;
struct ip_fw *i; struct ip_fw *i;
unsigned long flags; unsigned long flags;
int len; int len, p;
switch(stage) switch(stage)
...@@ -866,12 +930,12 @@ static int ip_chain_procinfo(int stage, char *buffer, char **start, ...@@ -866,12 +930,12 @@ static int ip_chain_procinfo(int stage, char *buffer, char **start,
#ifdef CONFIG_IP_FIREWALL #ifdef CONFIG_IP_FIREWALL
case IP_INFO_BLK: case IP_INFO_BLK:
i = ip_fw_blk_chain; i = ip_fw_blk_chain;
len=sprintf(buffer, "IP firewall block rules, policy = %d\n", len=sprintf(buffer, "IP firewall block rules, default %d\n",
ip_fw_blk_policy); ip_fw_blk_policy);
break; break;
case IP_INFO_FWD: case IP_INFO_FWD:
i = ip_fw_fwd_chain; i = ip_fw_fwd_chain;
len=sprintf(buffer, "IP firewall forward rules, policy = %d\n", len=sprintf(buffer, "IP firewall forward rules, default %d\n",
ip_fw_fwd_policy); ip_fw_fwd_policy);
break; break;
#endif #endif
...@@ -897,12 +961,12 @@ static int ip_chain_procinfo(int stage, char *buffer, char **start, ...@@ -897,12 +961,12 @@ static int ip_chain_procinfo(int stage, char *buffer, char **start,
ntohl(i->fw_src.s_addr),ntohl(i->fw_smsk.s_addr), ntohl(i->fw_src.s_addr),ntohl(i->fw_smsk.s_addr),
ntohl(i->fw_dst.s_addr),ntohl(i->fw_dmsk.s_addr), ntohl(i->fw_dst.s_addr),ntohl(i->fw_dmsk.s_addr),
ntohl(i->fw_via.s_addr),i->fw_flg); ntohl(i->fw_via.s_addr),i->fw_flg);
len+=sprintf(buffer+len,"%u %u %lu %lu ", len+=sprintf(buffer+len,"%u %u %lu %lu",
i->fw_nsp,i->fw_ndp, i->fw_pcnt,i->fw_bcnt); i->fw_nsp,i->fw_ndp, i->fw_pcnt,i->fw_bcnt);
len+=sprintf(buffer+len,"%u %u %u %u %u %u %u %u %u %u\n", for (p = 0; p < IP_FW_MAX_PORTS; p++)
i->fw_pts[0],i->fw_pts[1],i->fw_pts[2],i->fw_pts[3], len+=sprintf(buffer+len, " %u", i->fw_pts[p]);
i->fw_pts[4],i->fw_pts[5],i->fw_pts[6],i->fw_pts[7], buffer[len++]='\n';
i->fw_pts[8],i->fw_pts[9]); buffer[len]='\0';
pos=begin+len; pos=begin+len;
if(pos<offset) if(pos<offset)
{ {
......
...@@ -465,6 +465,7 @@ ipxitf_send(ipx_interface *intrfc, struct sk_buff *skb, char *node) ...@@ -465,6 +465,7 @@ ipxitf_send(ipx_interface *intrfc, struct sk_buff *skb, char *node)
struct datalink_proto *dl = intrfc->if_dlink; struct datalink_proto *dl = intrfc->if_dlink;
char dest_node[IPX_NODE_LEN]; char dest_node[IPX_NODE_LEN];
int send_to_wire = 1; int send_to_wire = 1;
int addr_len;
/* We need to know how many skbuffs it will take to send out this /* We need to know how many skbuffs it will take to send out this
* packet to avoid unnecessary copies. * packet to avoid unnecessary copies.
...@@ -501,8 +502,13 @@ ipxitf_send(ipx_interface *intrfc, struct sk_buff *skb, char *node) ...@@ -501,8 +502,13 @@ ipxitf_send(ipx_interface *intrfc, struct sk_buff *skb, char *node)
return 0; return 0;
} }
/* In some case, ipxitf_adjust_skbuff can overwrite node */ /* determine the appropriate hardware address */
memcpy(dest_node, node, IPX_NODE_LEN); addr_len = dev->addr_len;
if (memcmp(ipx_broadcast_node, node, IPX_NODE_LEN) == 0) {
memcpy(dest_node, dev->broadcast, addr_len);
} else {
memcpy(dest_node, &(node[IPX_NODE_LEN-addr_len]), addr_len);
}
/* make any compensation for differing physical/data link size */ /* make any compensation for differing physical/data link size */
skb = ipxitf_adjust_skbuff(intrfc, skb); skb = ipxitf_adjust_skbuff(intrfc, skb);
...@@ -699,9 +705,6 @@ ipxitf_create(ipx_interface_definition *idef) ...@@ -699,9 +705,6 @@ ipxitf_create(ipx_interface_definition *idef)
if(dev->addr_len>IPX_NODE_LEN) if(dev->addr_len>IPX_NODE_LEN)
return -EINVAL; return -EINVAL;
if(dev->addr_len<2)
return -EINVAL;
if ((intrfc = ipxitf_find_using_phys(dev, dlink_type)) == NULL) { if ((intrfc = ipxitf_find_using_phys(dev, dlink_type)) == NULL) {
/* Ok now create */ /* Ok now create */
...@@ -782,8 +785,6 @@ ipxitf_auto_create(struct device *dev, unsigned short dlink_type) ...@@ -782,8 +785,6 @@ ipxitf_auto_create(struct device *dev, unsigned short dlink_type)
/* Check addresses are suitable */ /* Check addresses are suitable */
if(dev->addr_len>IPX_NODE_LEN) return NULL; if(dev->addr_len>IPX_NODE_LEN) return NULL;
if(dev->addr_len<2) return NULL;
intrfc=(ipx_interface *)kmalloc(sizeof(ipx_interface),GFP_ATOMIC); intrfc=(ipx_interface *)kmalloc(sizeof(ipx_interface),GFP_ATOMIC);
if (intrfc!=NULL) { if (intrfc!=NULL) {
intrfc->if_dev=dev; intrfc->if_dev=dev;
......
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