summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/Makefile10
-rw-r--r--drivers/ap1000/ddv.c9
-rw-r--r--drivers/block/Config.in24
-rw-r--r--drivers/block/Makefile12
-rw-r--r--drivers/block/ali14xx.c2
-rw-r--r--drivers/block/cmd640.c2
-rw-r--r--drivers/block/dtc2278.c2
-rw-r--r--drivers/block/floppy.c6
-rw-r--r--drivers/block/ht6560b.c2
-rw-r--r--drivers/block/ide-cd.c188
-rw-r--r--drivers/block/ide-cd.h12
-rw-r--r--drivers/block/ide-disk.c65
-rw-r--r--drivers/block/ide-floppy.c20
-rw-r--r--drivers/block/ide-probe.c39
-rw-r--r--drivers/block/ide-tape.c28
-rw-r--r--drivers/block/ide.c328
-rw-r--r--drivers/block/ide.h48
-rw-r--r--drivers/block/ll_rw_blk.c10
-rw-r--r--drivers/block/md.c8
-rw-r--r--drivers/block/nbd.c19
-rw-r--r--drivers/block/opti621.c197
-rw-r--r--drivers/block/promise.c362
-rw-r--r--drivers/block/promise.h52
-rw-r--r--drivers/block/qd6580.c2
-rw-r--r--drivers/block/rd.c2
-rw-r--r--drivers/block/rz1000.c58
-rw-r--r--drivers/block/triton.c631
-rw-r--r--drivers/block/umc8672.c3
-rw-r--r--drivers/cdrom/Config.in5
-rw-r--r--drivers/cdrom/Makefile32
-rw-r--r--drivers/cdrom/aztcd.c277
-rw-r--r--drivers/cdrom/cdi.c50
-rw-r--r--drivers/cdrom/cdrom.c899
-rw-r--r--drivers/cdrom/cdu31a.c1158
-rw-r--r--drivers/cdrom/cm206.c36
-rw-r--r--drivers/cdrom/gscd.c6
-rw-r--r--drivers/cdrom/isp16.c2
-rw-r--r--drivers/cdrom/mcd.c481
-rw-r--r--drivers/cdrom/mcdx.c727
-rw-r--r--drivers/cdrom/optcd.c4
-rw-r--r--drivers/cdrom/sbpcd.c879
-rw-r--r--drivers/cdrom/sjcd.c2
-rw-r--r--drivers/cdrom/sonycd535.c2
-rw-r--r--drivers/char/ChangeLog6
-rw-r--r--drivers/char/Config.in16
-rw-r--r--drivers/char/Makefile8
-rw-r--r--drivers/char/acquirewdt.c4
-rw-r--r--drivers/char/bttv.c3
-rw-r--r--drivers/char/console.c27
-rw-r--r--drivers/char/cyclades.c70
-rw-r--r--drivers/char/esp.c17
-rw-r--r--drivers/char/ftape/Config.in2
-rw-r--r--drivers/char/ftape/lowlevel/fdc-io.c2
-rw-r--r--drivers/char/ftape/lowlevel/ftape-init.c2
-rw-r--r--drivers/char/ftape/lowlevel/ftape-io.c2
-rw-r--r--drivers/char/hfmodem/main.c75
-rw-r--r--drivers/char/joystick.c4
-rw-r--r--drivers/char/keyboard.c4
-rw-r--r--drivers/char/lp.c46
-rw-r--r--drivers/char/mem.c2
-rw-r--r--drivers/char/n_tty.c159
-rw-r--r--drivers/char/pcwd.c25
-rw-r--r--drivers/char/rocket.c30
-rw-r--r--drivers/char/rtc.c2
-rw-r--r--drivers/char/serial.c242
-rw-r--r--drivers/char/softdog.c4
-rw-r--r--drivers/char/stallion.c62
-rw-r--r--drivers/char/tga.c13
-rw-r--r--drivers/char/tty_io.c78
-rw-r--r--drivers/char/vga.c52
-rw-r--r--drivers/char/videodev.c4
-rw-r--r--drivers/char/vt.c2
-rw-r--r--drivers/char/wdt.c10
-rw-r--r--drivers/isdn/avmb1/capi.c3
-rw-r--r--drivers/isdn/isdn_common.c2
-rw-r--r--drivers/isdn/isdn_ppp.c2
-rw-r--r--drivers/misc/Makefile10
-rw-r--r--drivers/misc/parport_ieee1284.c83
-rw-r--r--drivers/misc/parport_init.c19
-rw-r--r--drivers/misc/parport_pc.c10
-rw-r--r--drivers/misc/parport_procfs.c2
-rw-r--r--drivers/misc/parport_share.c17
-rw-r--r--drivers/net/3c59x.c4
-rw-r--r--drivers/net/Config.in46
-rw-r--r--drivers/net/Makefile106
-rw-r--r--drivers/net/Space.c1
-rw-r--r--drivers/net/at1700.c2
-rw-r--r--drivers/net/baycom.c1280
-rw-r--r--drivers/net/bpqether.c669
-rw-r--r--drivers/net/de600.c8
-rw-r--r--drivers/net/e2100.c3
-rw-r--r--drivers/net/eepro.c17
-rw-r--r--drivers/net/eepro100.c1
-rw-r--r--drivers/net/eexpress.h2
-rw-r--r--drivers/net/eql.c2
-rw-r--r--drivers/net/hdlcdrv.c1024
-rw-r--r--drivers/net/hp-plus.c8
-rw-r--r--drivers/net/hp.c5
-rw-r--r--drivers/net/mkiss.c1134
-rw-r--r--drivers/net/mkiss.h56
-rw-r--r--drivers/net/ne.c4
-rw-r--r--drivers/net/net_init.c301
-rw-r--r--drivers/net/pi2.c1677
-rw-r--r--drivers/net/plip.c3
-rw-r--r--drivers/net/ppp.c13
-rw-r--r--drivers/net/pt.c1778
-rw-r--r--drivers/net/scc.c2245
-rw-r--r--drivers/net/slip.c4
-rw-r--r--drivers/net/soundmodem/.cvsignore3
-rw-r--r--drivers/net/soundmodem/Makefile60
-rw-r--r--drivers/net/soundmodem/gentbl.c676
-rw-r--r--drivers/net/soundmodem/sm.c898
-rw-r--r--drivers/net/soundmodem/sm.h382
-rw-r--r--drivers/net/soundmodem/sm_afsk1200.c272
-rw-r--r--drivers/net/soundmodem/sm_afsk2400_7.c296
-rw-r--r--drivers/net/soundmodem/sm_afsk2400_8.c296
-rw-r--r--drivers/net/soundmodem/sm_fsk9600.c391
-rw-r--r--drivers/net/soundmodem/sm_hapn4800.c560
-rw-r--r--drivers/net/soundmodem/sm_sbc.c941
-rw-r--r--drivers/net/soundmodem/sm_wss.c965
-rw-r--r--drivers/net/soundmodem/smdma.h217
-rw-r--r--drivers/net/strip.c3
-rw-r--r--drivers/net/tlan.c185
-rw-r--r--drivers/net/tlan.h21
-rw-r--r--drivers/net/z8530.h243
-rw-r--r--drivers/pci/pci.c36
-rw-r--r--drivers/pnp/parport_probe.c20
-rw-r--r--drivers/scsi/BusLogic.h8
-rw-r--r--drivers/scsi/Config.in2
-rw-r--r--drivers/scsi/aic7xxx.c115
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx.reg30
-rw-r--r--drivers/scsi/aic7xxx_proc.c254
-rw-r--r--drivers/scsi/aic7xxx_reg.h64
-rw-r--r--drivers/scsi/ibmmca.c11
-rw-r--r--drivers/scsi/scsi_ioctl.c2
-rw-r--r--drivers/scsi/sr.c11
-rw-r--r--drivers/scsi/sr_ioctl.c5
-rw-r--r--drivers/scsi/sr_vendor.c3
-rw-r--r--drivers/sgi/char/sgicons.c5
-rw-r--r--drivers/sgi/char/sgiserial.c2
-rw-r--r--drivers/sgi/char/shmiq.c1
-rw-r--r--drivers/sgi/char/usema.c22
-rw-r--r--drivers/sound/Config.in162
-rw-r--r--drivers/sound/Makefile51
-rw-r--r--drivers/sound/Readme16
-rw-r--r--drivers/sound/Readme.cards20
-rw-r--r--drivers/sound/Readme.linux4
-rw-r--r--drivers/sound/audio.c31
-rw-r--r--drivers/sound/configure.c4
-rw-r--r--drivers/sound/dmabuf.c26
-rw-r--r--drivers/sound/dmasound.c2
-rw-r--r--drivers/sound/lowlevel/awe_wave.c16
-rw-r--r--drivers/sound/mad16.c12
-rw-r--r--drivers/sound/maui.c2
-rw-r--r--drivers/sound/midi_synth.c129
-rw-r--r--drivers/sound/midibuf.c8
-rw-r--r--drivers/sound/mpu401.c9
-rw-r--r--drivers/sound/pss.c95
-rw-r--r--drivers/sound/sequencer.c8
-rw-r--r--drivers/sound/sound_firmware.c2
-rw-r--r--drivers/sound/soundvers.h2
-rw-r--r--drivers/sound/uart401.c3
162 files changed, 4907 insertions, 20910 deletions
diff --git a/drivers/Makefile b/drivers/Makefile
index 69a78f46e..cdeb149f1 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -75,4 +75,14 @@ SUB_DIRS += ap1000
ALL_SUB_DIRS += ap1000
endif
+# make will try to add $(MOD_SUB_DIRS).o to modules/MOD_LIST_NAME
+# when MOD_LIST_NAME is set. We don't have hamradio.o and Linus
+# sort-of insisted on making hamradio a subdirectory to drivers/net.
+#
+
+ifeq ($(CONFIG_HAMRADIO),y)
+ SUB_DIRS += net/hamradio
+ MOD_SUB_DIRS += net/hamradio
+endif
+
include $(TOPDIR)/Rules.make
diff --git a/drivers/ap1000/ddv.c b/drivers/ap1000/ddv.c
index 7cfdafdc9..186dfe10b 100644
--- a/drivers/ap1000/ddv.c
+++ b/drivers/ap1000/ddv.c
@@ -363,7 +363,10 @@ static int ddv_daemon(void *unused)
current->session = 1;
current->pgrp = 1;
sprintf(current->comm, "ddv_daemon");
- current->blocked = ~0UL; /* block all signals */
+ spin_lock_irq(&current->sigmask_lock);
+ sigfillset(&current->blocked); /* block all signals */
+ recalc_sigpending(current);
+ spin_unlock_irq(&current->sigmask_lock);
/* Give it a realtime priority. */
current->policy = SCHED_FIFO;
@@ -382,7 +385,9 @@ static int ddv_daemon(void *unused)
save_flags(flags); cli();
while (!rem_queue) {
- current->signal = 0;
+ spin_lock_irq(&current->sigmask_lock);
+ flush_signals(current);
+ spin_unlock_irq(&current->sigmask_lock);
interruptible_sleep_on(&ddv_daemon_wait);
}
diff --git a/drivers/block/Config.in b/drivers/block/Config.in
index 9b52e48c1..220148670 100644
--- a/drivers/block/Config.in
+++ b/drivers/block/Config.in
@@ -23,22 +23,26 @@ else
fi
if [ "$CONFIG_PCI" = "y" ]; then
bool ' RZ1000 chipset bugfix/support' CONFIG_BLK_DEV_RZ1000
- bool ' Intel PIIX/PIIX3/PIIX4 (Triton 430FX/HX/VX/TX, 440FX) DMA support' CONFIG_BLK_DEV_TRITON
+ bool ' PCI bus-master DMA support' CONFIG_BLK_DEV_IDEDMA
+ if [ "$CONFIG_BLK_DEV_IDEDMA" = "y" ]; then
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ bool ' Tekram TRM290 DMA support (EXPERIMENTAL)' CONFIG_BLK_DEV_TRM290
+ bool ' OPTi 82C621 enhanced support (EXPERIMENTAL)' CONFIG_BLK_DEV_OPTI621
+ fi
+ fi
fi
bool ' Other IDE chipset support' CONFIG_IDE_CHIPSETS
if [ "$CONFIG_IDE_CHIPSETS" = "y" ]; then
comment 'Note: most of these also require special kernel boot parameters'
- bool ' ALI M14xx support' CONFIG_BLK_DEV_ALI14XX
- bool ' DTC-2278 support' CONFIG_BLK_DEV_DTC2278
- bool ' Holtek HT6560B support' CONFIG_BLK_DEV_HT6560B
+ bool ' Generic 4 drives/port support' CONFIG_BLK_DEV_4DRIVES
+ bool ' ALI M14xx support' CONFIG_BLK_DEV_ALI14XX
+ bool ' DTC-2278 support' CONFIG_BLK_DEV_DTC2278
+ bool ' Holtek HT6560B support' CONFIG_BLK_DEV_HT6560B
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
- bool ' PROMISE DC4030 support (EXPERIMENTAL)' CONFIG_BLK_DEV_PROMISE
- if [ "$CONFIG_PCI" = "y" ]; then
- bool ' OPTi 82C621 support (EXPERIMENTAL)' CONFIG_BLK_DEV_OPTI621
- fi
+ bool ' PROMISE DC4030 support (EXPERIMENTAL)' CONFIG_BLK_DEV_PDC4030
fi
- bool ' QDI QD6580 support' CONFIG_BLK_DEV_QD6580
- bool ' UMC 8672 support' CONFIG_BLK_DEV_UMC8672
+ bool ' QDI QD6580 support' CONFIG_BLK_DEV_QD6580
+ bool ' UMC-8672 support' CONFIG_BLK_DEV_UMC8672
fi
fi
fi
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index 89ce8a004..50e9f6be6 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -96,8 +96,8 @@ ifeq ($(CONFIG_BLK_DEV_CMD640),y)
L_OBJS += cmd640.o
endif
-ifeq ($(CONFIG_BLK_DEV_TRITON),y)
-L_OBJS += triton.o
+ifeq ($(CONFIG_BLK_DEV_IDEDMA),y)
+L_OBJS += ide-dma.o
endif
ifeq ($(CONFIG_BLK_DEV_PS2),y)
@@ -125,8 +125,12 @@ ifeq ($(CONFIG_BLK_DEV_ALI14XX),y)
L_OBJS += ali14xx.o
endif
-ifeq ($(CONFIG_BLK_DEV_PROMISE),y)
-L_OBJS += promise.o
+ifeq ($(CONFIG_BLK_DEV_PDC4030),y)
+L_OBJS += pdc4030.o
+endif
+
+ifeq ($(CONFIG_BLK_DEV_TRM290),y)
+L_OBJS += trm290.o
endif
ifeq ($(CONFIG_BLK_DEV_OPTI621),y)
diff --git a/drivers/block/ali14xx.c b/drivers/block/ali14xx.c
index 00de8e7cb..5f6c0f437 100644
--- a/drivers/block/ali14xx.c
+++ b/drivers/block/ali14xx.c
@@ -211,6 +211,8 @@ void init_ali14xx (void)
ide_hwifs[1].chipset = ide_ali14xx;
ide_hwifs[0].tuneproc = &ali14xx_tune_drive;
ide_hwifs[1].tuneproc = &ali14xx_tune_drive;
+ ide_hwifs[0].mate = &ide_hwifs[1];
+ ide_hwifs[1].mate = &ide_hwifs[0];
/* initialize controller registers */
if (!initRegisters()) {
diff --git a/drivers/block/cmd640.c b/drivers/block/cmd640.c
index 1110512e5..e833a2bd0 100644
--- a/drivers/block/cmd640.c
+++ b/drivers/block/cmd640.c
@@ -795,6 +795,8 @@ int ide_probe_for_cmd640x (void)
cmd_hwif0->serialized = 1;
cmd_hwif1->serialized = 1;
cmd_hwif1->chipset = ide_cmd640;
+ cmd_hwif0->mate = cmd_hwif1;
+ cmd_hwif1->mate = cmd_hwif0;
#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
cmd_hwif1->tuneproc = &cmd640_tune_drive;
#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
diff --git a/drivers/block/dtc2278.c b/drivers/block/dtc2278.c
index 25966debc..30988bd99 100644
--- a/drivers/block/dtc2278.c
+++ b/drivers/block/dtc2278.c
@@ -125,4 +125,6 @@ void init_dtc2278 (void)
ide_hwifs[0].drives[1].no_unmask = 1;
ide_hwifs[1].drives[0].no_unmask = 1;
ide_hwifs[1].drives[1].no_unmask = 1;
+ ide_hwifs[0].mate = &ide_hwifs[1];
+ ide_hwifs[1].mate = &ide_hwifs[0];
}
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index d374415e4..d479bc1be 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -3975,6 +3975,7 @@ __initfunc(int floppy_init(void))
fdc_state[0].address = FDC1;
if (fdc_state[0].address == -1) {
unregister_blkdev(MAJOR_NR,"fd");
+ del_timer(&fd_timeout);
return -ENODEV;
}
#if N_FDC > 1
@@ -3983,6 +3984,7 @@ __initfunc(int floppy_init(void))
if (floppy_grab_irq_and_dma()){
unregister_blkdev(MAJOR_NR,"fd");
+ del_timer(&fd_timeout);
return -EBUSY;
}
@@ -4065,8 +4067,8 @@ static int floppy_grab_irq_and_dma(void)
if (FDCS->address != -1){
if (check_region(FDCS->address, 6) < 0 ||
check_region(FDCS->address+7, 1) < 0) {
- DPRINT("Floppy io-port 0x%04x in use\n",
- (unsigned int) FDCS->address);
+ DPRINT("Floppy io-port 0x%04lx in use\n",
+ FDCS->address);
fd_free_irq(FLOPPY_IRQ);
fd_free_dma(FLOPPY_DMA);
while(--fdc >= 0) {
diff --git a/drivers/block/ht6560b.c b/drivers/block/ht6560b.c
index ec4f0f89f..9d888cfc0 100644
--- a/drivers/block/ht6560b.c
+++ b/drivers/block/ht6560b.c
@@ -227,6 +227,8 @@ void init_ht6560b (void)
ide_hwifs[1].tuneproc = &tune_ht6560b;
ide_hwifs[0].serialized = 1;
ide_hwifs[1].serialized = 1;
+ ide_hwifs[0].mate = &ide_hwifs[1];
+ ide_hwifs[1].mate = &ide_hwifs[0];
} else
printk("\nht6560b: not found\n");
}
diff --git a/drivers/block/ide-cd.c b/drivers/block/ide-cd.c
index 53ee1a13f..02f97ec6f 100644
--- a/drivers/block/ide-cd.c
+++ b/drivers/block/ide-cd.c
@@ -1,15 +1,46 @@
-/* #define VERBOSE_IDE_CD_ERRORS 1 */
+#define VERBOSE_IDE_CD_ERRORS 1
/*
* linux/drivers/block/ide-cd.c
- * ATAPI cd-rom driver. To be used with ide.c.
+ * Copyright (C) 1994, 1995, 1996 scott snyder <snyder@fnald0.fnal.gov>
+ * Copyright (C) 1996, 1997 Erik Andersen <andersee@debian.org>
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See linux/COPYING for more information.
+ *
+ * ATAPI CD-ROM driver. To be used with ide.c.
* See Documentation/cdrom/ide-cd for usage information.
*
- * Copyright (C) 1994, 1995, 1996 scott snyder <snyder@fnald0.fnal.gov>
- * Copyright (C) 1996 Erik Andersen <andersee@et.byu.edu>
+ * Suggestions are welcome. Patches that work are more welcome though.
+ * For those wishing to work on this driver, please be sure you download
+ * and comply with the latest ATAPI standard. This document can be
+ * obtained by anonymous ftp from fission.dt.wdc.com in directory:
+ * /pub/standards/SFF_atapi/spec/SFF8020-r2.6/PDF/8020r26.pdf
*
- * May be copied or modified under the terms of the GNU General Public License
- * see linux/COPYING for more information.
+ * Drives that deviate from the ATAPI standard will be accomodated as much
+ * as possible via compile options. Since I only have a few drives, you you
+ * generally need to send me patches...
*
+ * ----------------------------------
+ * TO DO LIST:
+ * -Avoid printing error messages for expected errors from the drive.
+ * (If you are using a cd changer, you may get errors in the kernel
+ * logs that are completly expected. Don't complain to me about this,
+ * unless you have a patch to fix it. I am working on it...)
+ * -Implement ide_cdrom_select_speed using the generic cdrom interface
+ * -Fix ide_cdrom_reset so that it works (it does nothing right now)
+ * -When trying to mount a cdrom with the tray open, you get an billion
+ * "tray open or drive not ready" messages until the tray gets closed.
+ * This is because ide-cd does not properly return drive_status immediatly,
+ * but instead waits for the drive to close first (bad, bad, bad)
+ * and keeps on trying, and failing... This bug was revealed by the
+ * recent changes to the Uniform CD-ROm driver, and I havn't had a
+ * chance to fix it yet.
+ *
+ * MOSTLY DONE LIST:
+ * Query the drive to find what features are available
+ * before trying to use them.
+ *
+ *
+ * ----------------------------------
* 1.00 Oct 31, 1994 -- Initial version.
* 1.01 Nov 2, 1994 -- Fixed problem with starting request in
* cdrom_check_status.
@@ -121,7 +152,7 @@
*
*
* 4.00 Nov 5, 1996 -- New ide-cd maintainer,
- * Erik B. Andersen <andersee@et.byu.edu>
+ * Erik B. Andersen <andersee@debian.org>
* -- Newer Creative drives don't always set the error
* register correctly. Make sure we see media changes
* regardless.
@@ -147,32 +178,16 @@
* 4.04 Dec 29, 1996 -- Added CDROMREADRAW ioclt based on patch
* by Ales Makarov (xmakarov@sun.felk.cvut.cz)
*
+ * 4.05 Nov 20, 1997 -- Modified to print more drive info on init
+ * Minor other changes
+ * Fix errors on CDROMSTOP (If you have a "Dolphin",
+ * you must define IHAVEADOLPHIN)
+ * Added identifier so new Sanyo CD-changer works
+ * Better detection if door locking isn't supported
*
- * MOSTLY DONE LIST:
- * Query the drive to find what features are available
- * before trying to use them.
- *
- * TO DO LIST:
- * Avoid printing error messages for expected errors from the drive.
- * (If you are using a cd changer, you may get errors in the kernel
- * logs that are completly expected. Don't complain to me about this,
- * unless you have a patch to fix it. I am working on it...)
- * Reset unlocks drive?
- * Implement ide_cdrom_disc_status using the generic cdrom interface
- * Implement ide_cdrom_select_speed using the generic cdrom interface
- * Fix ide_cdrom_reset so that it works (it does nothing right now)
- *
- * -- Suggestions are welcome. Patches that work are more welcome though.
- * For those wishing to work on this driver, please be sure you download
- * and comply with the latest ATAPI standard. This document can be
- * obtained by anonymous ftp from fission.dt.wdc.com in directory:
- * /pub/standards/atapi/spec/SFF8020-r2.6/PDF/8020r26.pdf
- *
- */
-
-
-/***************************************************************************/
+ *************************************************************************/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
@@ -185,7 +200,6 @@
#include <linux/errno.h>
#include <linux/hdreg.h>
#include <linux/cdrom.h>
-#include <linux/ucdrom.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/byteorder.h>
@@ -463,13 +477,16 @@ static int cdrom_decode_status (ide_drive_t *drive, int good_stat,
because workman constantly polls the drive
with this command, and we don't want
to uselessly fill up the syslog. */
- if (pc->c[0] != SCMD_READ_SUBCHANNEL)
+ if (pc->c[0] != SCMD_READ_SUBCHANNEL) {
printk ("%s: tray open or drive not ready\n",
drive->name);
+ return 1;
+ }
} else if (sense_key == UNIT_ATTENTION) {
/* Check for media change. */
cdrom_saw_media_change (drive);
- printk ("%s: media changed\n", drive->name);
+ printk (" %s: media changed\n", drive->name);
+ return 0;
} else {
/* Otherwise, print an error. */
ide_dump_status (drive, "packet command error",
@@ -1094,8 +1111,13 @@ static void cdrom_pc_intr (ide_drive_t *drive)
if (pc->buflen == 0)
cdrom_end_request (1, drive);
else {
+ /* Comment this out, because this always happins
+ right after a reset occurs, and it is annoying to
+ always print expected stuff. */
+ /*
printk ("%s: cdrom_pc_intr: data underrun %d\n",
drive->name, pc->buflen);
+ */
pc->stat = 1;
cdrom_end_request (1, drive);
}
@@ -1355,7 +1377,7 @@ void msf_from_bcd (struct atapi_msf *msf)
static inline
void lba_to_msf (int lba, byte *m, byte *s, byte *f)
{
- lba += CD_BLOCK_OFFSET;
+ lba += CD_MSF_OFFSET;
lba &= 0xffffff; /* negative lbas use only 24 bits */
*m = lba / (CD_SECS * CD_FRAMES);
lba %= (CD_SECS * CD_FRAMES);
@@ -1367,7 +1389,7 @@ void lba_to_msf (int lba, byte *m, byte *s, byte *f)
static inline
int msf_to_lba (byte m, byte s, byte f)
{
- return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_BLOCK_OFFSET;
+ return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_MSF_OFFSET;
}
@@ -1421,7 +1443,7 @@ cdrom_lockdoor (ide_drive_t *drive, int lockflag,
probably cannot lock the door. */
if (stat != 0 &&
reqbuf->sense_key == ILLEGAL_REQUEST &&
- reqbuf->asc == 0x24) {
+ (reqbuf->asc == 0x24 || reqbuf->asc == 0x20)) {
printk ("%s: door locking not supported\n",
drive->name);
CDROM_CONFIG_FLAGS (drive)->no_doorlock = 1;
@@ -2325,12 +2347,17 @@ int ide_cdrom_audio_ioctl (struct cdrom_device_info *cdi,
return cdrom_startstop (drive, 1, NULL);
case CDROMSTOP: {
- int stat;
-
- stat = cdrom_startstop (drive, 0, NULL);
- if (stat) return stat;
- /* pit says the Dolphin needs this. */
- return cdrom_eject (drive, 1, NULL);
+#ifdef IHAVEADOLPHIN
+ /* Certain Drives require this. Most don't
+ and will produce errors upon CDROMSTOP
+ pit says the Dolphin needs this. If you
+ own a dolphin, just define IHAVEADOLPHIN somewhere */
+ int stat;
+ stat = cdrom_startstop (drive, 0, NULL);
+ if (stat) return stat;
+ return cdrom_eject (drive, 1, NULL);
+#endif /* end of IHAVEADOLPHIN */
+ return cdrom_startstop (drive, 0, NULL);
}
case CDROMPAUSE:
@@ -2360,7 +2387,7 @@ int ide_cdrom_reset (struct cdrom_device_info *cdi)
return ide_do_drive_cmd (drive, &req, ide_wait);
#endif
-/* For now, just return 0, as if things worked... */
+/* For now, just return 0, as if things had worked... */
return 0;
@@ -2399,10 +2426,8 @@ int ide_cdrom_select_disc (struct cdrom_device_info *cdi, int slot)
int stat;
int nslots, curslot;
- if ( ! CDROM_CONFIG_FLAGS (drive)->is_changer) {
- printk ("%s: Not a changer.", drive->name);
- return -EINVAL;
- }
+ if ( ! CDROM_CONFIG_FLAGS (drive)->is_changer)
+ return -EDRIVE_CANT_DO_THIS;
#if ! STANDARD_ATAPI
if (CDROM_STATE_FLAGS (drive)->sanyo_slot > 0) {
@@ -2436,7 +2461,7 @@ int ide_cdrom_select_disc (struct cdrom_device_info *cdi, int slot)
stat = cdrom_check_status (drive, &my_reqbuf);
if (stat && my_reqbuf.sense_key == NOT_READY)
- return (-ENOENT);
+ return -ENOENT;
if (slot == CDSL_NONE) {
(void) cdrom_load_unload (drive, -1, NULL);
@@ -2449,11 +2474,8 @@ int ide_cdrom_select_disc (struct cdrom_device_info *cdi, int slot)
#if ! STANDARD_ATAPI
CDROM_STATE_FLAGS (drive)->sanyo_slot == 0 &&
#endif
- info->changer_info->slots[slot].disc_present
- == 0) {
- printk ("%s: Requested slot does not contain a CD.\n",
- drive->name);
- return (-ENOENT);
+ info->changer_info->slots[slot].disc_present == 0) {
+ return -ENOMEDIUM;
}
stat = cdrom_load_unload (drive, slot, NULL);
@@ -2519,7 +2541,6 @@ int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr)
}
}
-
static
int ide_cdrom_get_last_session (struct cdrom_device_info *cdi,
struct cdrom_multisession *ms_info)
@@ -2628,16 +2649,16 @@ void ide_cdrom_release_real (struct cdrom_device_info *cdi)
/****************************************************************************
* Device initialization.
*/
+
static
struct cdrom_device_ops ide_cdrom_dops = {
ide_cdrom_open_real, /* open */
ide_cdrom_release_real, /* release */
ide_cdrom_drive_status, /* drive_status */
- 0, /* disc_status */
ide_cdrom_check_media_change_real, /* media_changed */
ide_cdrom_tray_move, /* tray_move */
ide_cdrom_lock_door, /* lock_door */
- 0, /* select_speed */
+ NULL, /* select_speed */
ide_cdrom_select_disc, /* select_disc */
ide_cdrom_get_last_session, /* get_last_session */
ide_cdrom_get_mcn, /* get_mcn */
@@ -2646,11 +2667,11 @@ struct cdrom_device_ops ide_cdrom_dops = {
ide_cdrom_dev_ioctl, /* dev_ioctl */
CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK
| CDC_SELECT_DISC | CDC_MULTI_SESSION | CDC_MCN
- | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO, /* capability */
+ | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET
+ | CDC_IOCTLS | CDC_DRIVE_STATUS, /* capability */
0 /* n_minors */
};
-
static int ide_cdrom_register (ide_drive_t *drive, int nslots)
{
struct cdrom_info *info = drive->driver_data;
@@ -2660,11 +2681,11 @@ static int ide_cdrom_register (ide_drive_t *drive, int nslots)
devinfo->dev = MKDEV (HWIF(drive)->major, minor);
devinfo->ops = &ide_cdrom_dops;
devinfo->mask = 0;
- *(int *)&devinfo->speed = 0;
+ *(int *)&devinfo->speed = CDROM_CONFIG_FLAGS (drive)->max_speed;
*(int *)&devinfo->capacity = nslots;
devinfo->handle = (void *) drive;
-
- return register_cdrom (devinfo, drive->name);
+ strcpy(devinfo->name, drive->name);
+ return register_cdrom (devinfo);
}
@@ -2690,6 +2711,11 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive)
if (buf.cap.lock == 0)
CDROM_CONFIG_FLAGS (drive)->no_doorlock = 1;
+ if (buf.cap.cd_r_write)
+ CDROM_CONFIG_FLAGS (drive)->cd_r = 1;
+ if (buf.cap.cd_rw_write)
+ CDROM_CONFIG_FLAGS (drive)->cd_rw = 1;
+
#if ! STANDARD_ATAPI
if (CDROM_STATE_FLAGS (drive)->sanyo_slot > 0) {
CDROM_CONFIG_FLAGS (drive)->is_changer = 1;
@@ -2711,9 +2737,23 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive)
}
}
- if (CDROM_CONFIG_FLAGS (drive)->is_changer)
- printk (" %s: ATAPI CDROM changer with %d slots\n",
- drive->name, nslots);
+ CDROM_STATE_FLAGS (drive)->curent_speed = ntohs(buf.cap.curspeed)/176;
+ CDROM_CONFIG_FLAGS (drive)->max_speed = ntohs(buf.cap.maxspeed)/176;
+
+ stat=0;
+ printk ("%s: ATAPI %dx CDROM",
+ drive->name, CDROM_CONFIG_FLAGS (drive)->max_speed);
+ if (CDROM_CONFIG_FLAGS (drive)->cd_r|CDROM_CONFIG_FLAGS (drive)->cd_rw)
+ printk (" CD%s%s",
+ (CDROM_CONFIG_FLAGS (drive)->cd_r)? "-R" : "",
+ (CDROM_CONFIG_FLAGS (drive)->cd_rw)? "/RW" : "");
+ if (CDROM_CONFIG_FLAGS (drive)->is_changer)
+ printk (" changer w/%d slots", nslots);
+ else
+ printk (" drive");
+ printk (" %s/%dkB Cache\n",
+ (CDROM_CONFIG_FLAGS (drive)->is_changer)? "&" : "w",
+ ntohs(buf.cap.buffer_size) );
return nslots;
}
@@ -2751,6 +2791,8 @@ int ide_cdrom_setup (ide_drive_t *drive)
CDROM_CONFIG_FLAGS (drive)->drq_interrupt = 0;
CDROM_CONFIG_FLAGS (drive)->is_changer = 0;
+ CDROM_CONFIG_FLAGS (drive)->cd_r = 0;
+ CDROM_CONFIG_FLAGS (drive)->cd_rw = 0;
CDROM_CONFIG_FLAGS (drive)->supp_disc_present = 0;
#if ! STANDARD_ATAPI
@@ -2802,13 +2844,15 @@ int ide_cdrom_setup (ide_drive_t *drive)
CDROM_CONFIG_FLAGS (drive)->subchan_as_bcd = 1;
}
- /* Sanyo 3 CD changer uses a non-standard command
- for CD changing. */
- else if ((strcmp(drive->id->model, "CD-ROM CDR-C3 G") == 0) ||
- (strcmp(drive->id->model, "CD-ROM CDR-C3G") == 0)) {
- /* uses CD in slot 0 when value is set to 3 */
- CDROM_STATE_FLAGS (drive)->sanyo_slot = 3;
- }
+ /* Sanyo 3 CD changer uses a non-standard command
+ for CD changing */
+ else if ((strcmp(drive->id->model, "CD-ROM CDR-C3 G") == 0) ||
+ (strcmp(drive->id->model, "CD-ROM CDR-C3G") == 0) ||
+ (strcmp(drive->id->model, "CD-ROM CDR_C36") == 0)) {
+ /* uses CD in slot 0 when value is set to 3 */
+ CDROM_STATE_FLAGS (drive)->sanyo_slot = 3;
+ }
+
}
#endif /* not STANDARD_ATAPI */
diff --git a/drivers/block/ide-cd.h b/drivers/block/ide-cd.h
index 858994ee5..afb3e5dbe 100644
--- a/drivers/block/ide-cd.h
+++ b/drivers/block/ide-cd.h
@@ -115,8 +115,11 @@ struct ide_cd_config_flags {
__u8 toctracks_as_bcd : 1; /* TOC track numbers are in BCD. */
__u8 subchan_as_bcd : 1; /* Subchannel info is in BCD. */
__u8 is_changer : 1; /* Drive is a changer. */
+ __u8 cd_r : 1; /* Drive can write to CD-R media . */
+ __u8 cd_rw : 1; /* Drive can write to CD-R/W media . */
__u8 supp_disc_present: 1; /* Changer can report exact contents
of slots. */
+ __u8 max_speed : 4; /* Max speed of the drive */
__u8 seeking : 1; /* Seeking in progress */
__u8 reserved : 6;
};
@@ -130,6 +133,7 @@ struct ide_cd_state_flags {
__u8 toc_valid : 1; /* Saved TOC information is current. */
__u8 door_locked : 1; /* We think that the drive door is locked. */
__u8 sanyo_slot : 2; /* Sanyo 3 CD changer support */
+ __u8 curent_speed : 4; /* Current speed of the drive */
__u8 reserved : 3;
};
#define CDROM_STATE_FLAGS(drive) ((struct ide_cd_state_flags *)&((drive)->bios_head))
@@ -239,16 +243,16 @@ struct atapi_capabilities_page {
/* Drive supports read from CD-R discs (orange book, part II) */
unsigned cd_r_read : 1; /* reserved in 1.2 */
- /* Drive supports read from CD-E discs (orange book, part III) */
- unsigned cd_e_read : 1; /* reserved in 1.2 */
+ /* Drive supports read from CD-R/W (CD-E) discs (orange book, part III) */
+ unsigned cd_rw_read : 1; /* reserved in 1.2 */
/* Drive supports reading CD-R discs with addressing method 2 */
unsigned method2 : 1; /* reserved in 1.2 */
unsigned reserved2 : 5;
/* Drive supports write to CD-R discs (orange book, part II) */
unsigned cd_r_write : 1; /* reserved in 1.2 */
- /* Drive supports write to CD-E discs (orange book, part III) */
- unsigned cd_e_write : 1; /* reserved in 1.2 */
+ /* Drive supports write to CD-R/W (CD-E) discs (orange book, part III) */
+ unsigned cd_rw_write : 1; /* reserved in 1.2 */
unsigned reserved3 : 6;
/* Drive supports audio play operations. */
diff --git a/drivers/block/ide-disk.c b/drivers/block/ide-disk.c
index fbf8c3833..f75a1a5be 100644
--- a/drivers/block/ide-disk.c
+++ b/drivers/block/ide-disk.c
@@ -1,7 +1,7 @@
/*
- * linux/drivers/block/ide-disk.c Version 1.01 Nov 25, 1996
+ * linux/drivers/block/ide-disk.c Version 1.03 Nov 30, 1997
*
- * Copyright (C) 1994-1996 Linus Torvalds & authors (see below)
+ * Copyright (C) 1994-1998 Linus Torvalds & authors (see below)
*/
/*
@@ -39,6 +39,8 @@
* Version 1.00 move disk only code from ide.c to ide-disk.c
* support optional byte-swapping of all data
* Version 1.01 fix previous byte-swapping code
+ * Verions 1.02 remove ", LBA" from drive identification msgs
+ * Verions 1.03 fix display of id->buf_size for big-endian
*/
#undef REALLY_SLOW_IO /* most systems can safely undef this */
@@ -308,23 +310,23 @@ static void recal_intr (ide_drive_t *drive)
*/
static void do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block)
{
-#ifdef CONFIG_BLK_DEV_PROMISE
+#ifdef CONFIG_BLK_DEV_PDC4030
ide_hwif_t *hwif = HWIF(drive);
- int use_promise_io = 0;
-#endif /* CONFIG_BLK_DEV_PROMISE */
+ int use_pdc4030_io = 0;
+#endif /* CONFIG_BLK_DEV_PDC4030 */
OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
OUT_BYTE(rq->nr_sectors,IDE_NSECTOR_REG);
-#ifdef CONFIG_BLK_DEV_PROMISE
- if (IS_PROMISE_DRIVE) {
- if (hwif->is_promise2 || rq->cmd == READ) {
- use_promise_io = 1;
+#ifdef CONFIG_BLK_DEV_PDC4030
+ if (IS_PDC4030_DRIVE) {
+ if (hwif->is_pdc4030_2 || rq->cmd == READ) {
+ use_pdc4030_io = 1;
}
}
- if (drive->select.b.lba || use_promise_io) {
-#else /* !CONFIG_BLK_DEV_PROMISE */
+ if (drive->select.b.lba || use_pdc4030_io) {
+#else /* !CONFIG_BLK_DEV_PDC4030 */
if (drive->select.b.lba) {
-#endif /* CONFIG_BLK_DEV_PROMISE */
+#endif /* CONFIG_BLK_DEV_PDC4030 */
#ifdef DEBUG
printk("%s: %sing: LBAsect=%ld, sectors=%ld, buffer=0x%08lx\n",
drive->name, (rq->cmd==READ)?"read":"writ",
@@ -350,26 +352,27 @@ static void do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long bl
head, sect, rq->nr_sectors, (unsigned long) rq->buffer);
#endif
}
-#ifdef CONFIG_BLK_DEV_PROMISE
- if (use_promise_io) {
- do_promise_io (drive, rq);
+#ifdef CONFIG_BLK_DEV_PDC4030
+ if (use_pdc4030_io) {
+ extern void do_pdc4030_io(ide_drive_t *, struct request *);
+ do_pdc4030_io (drive, rq);
return;
}
-#endif /* CONFIG_BLK_DEV_PROMISE */
+#endif /* CONFIG_BLK_DEV_PDC4030 */
if (rq->cmd == READ) {
-#ifdef CONFIG_BLK_DEV_TRITON
+#ifdef CONFIG_BLK_DEV_IDEDMA
if (drive->using_dma && !(HWIF(drive)->dmaproc(ide_dma_read, drive)))
return;
-#endif /* CONFIG_BLK_DEV_TRITON */
+#endif /* CONFIG_BLK_DEV_IDEDMA */
ide_set_handler(drive, &read_intr, WAIT_CMD);
OUT_BYTE(drive->mult_count ? WIN_MULTREAD : WIN_READ, IDE_COMMAND_REG);
return;
}
if (rq->cmd == WRITE) {
-#ifdef CONFIG_BLK_DEV_TRITON
+#ifdef CONFIG_BLK_DEV_IDEDMA
if (drive->using_dma && !(HWIF(drive)->dmaproc(ide_dma_write, drive)))
return;
-#endif /* CONFIG_BLK_DEV_TRITON */
+#endif /* CONFIG_BLK_DEV_IDEDMA */
OUT_BYTE(drive->mult_count ? WIN_MULTWRITE : WIN_WRITE, IDE_COMMAND_REG);
if (ide_wait_stat(drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) {
printk(KERN_ERR "%s: no DRQ after issuing %s\n", drive->name,
@@ -459,17 +462,17 @@ static void idedisk_special (ide_drive_t *drive)
OUT_BYTE(drive->cyl,IDE_LCYL_REG);
OUT_BYTE(drive->cyl>>8,IDE_HCYL_REG);
OUT_BYTE(((drive->head-1)|drive->select.all)&0xBF,IDE_SELECT_REG);
- if (!IS_PROMISE_DRIVE)
+ if (!IS_PDC4030_DRIVE)
ide_cmd(drive, WIN_SPECIFY, drive->sect, &set_geometry_intr);
} else if (s->b.recalibrate) {
s->b.recalibrate = 0;
- if (!IS_PROMISE_DRIVE)
+ if (!IS_PDC4030_DRIVE)
ide_cmd(drive, WIN_RESTORE, drive->sect, &recal_intr);
} else if (s->b.set_multmode) {
s->b.set_multmode = 0;
if (drive->id && drive->mult_req > drive->id->max_multsect)
drive->mult_req = drive->id->max_multsect;
- if (!IS_PROMISE_DRIVE)
+ if (!IS_PDC4030_DRIVE)
ide_cmd(drive, WIN_SETMULT, drive->mult_req, &set_multmode_intr);
} else if (s->all) {
int special = s->all;
@@ -599,15 +602,21 @@ static void idedisk_setup (ide_drive_t *drive)
if (drive->cyl > drive->bios_cyl)
drive->bios_cyl = drive->cyl;
}
+ /* fix byte-ordering of buffer size field */
+ id->buf_size = le16_to_cpu(id->buf_size);
(void) idedisk_capacity (drive); /* initialize LBA selection */
- printk (KERN_INFO "%s: %.40s, %ldMB w/%dkB Cache, %sCHS=%d/%d/%d%s\n",
+ printk (KERN_INFO "%s: %.40s, %ldMB w/%dkB Cache, CHS=%d/%d/%d",
drive->name, id->model, idedisk_capacity(drive)/2048L, id->buf_size/2,
- drive->select.b.lba ? "LBA, " : "",
- drive->bios_cyl, drive->bios_head, drive->bios_sect,
- drive->using_dma ? ", DMA" : "");
-
+ drive->bios_cyl, drive->bios_head, drive->bios_sect);
+ if (drive->using_dma) {
+ if ((id->field_valid & 4) && (id->dma_ultra & (id->dma_ultra >> 8) & 7))
+ printk(", UDMA");
+ else
+ printk(", DMA");
+ }
+ printk("\n");
drive->mult_count = 0;
if (id->max_multsect) {
drive->mult_req = INITIAL_MULT_COUNT;
diff --git a/drivers/block/ide-floppy.c b/drivers/block/ide-floppy.c
index 5a0a603b5..2856f330f 100644
--- a/drivers/block/ide-floppy.c
+++ b/drivers/block/ide-floppy.c
@@ -532,7 +532,7 @@ static void idefloppy_output_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, un
}
}
-#ifdef CONFIG_BLK_DEV_TRITON
+#ifdef CONFIG_BLK_DEV_IDEDMA
static void idefloppy_update_buffers (ide_drive_t *drive, idefloppy_pc_t *pc)
{
struct request *rq = pc->rq;
@@ -541,7 +541,7 @@ static void idefloppy_update_buffers (ide_drive_t *drive, idefloppy_pc_t *pc)
while ((bh = rq->bh) != NULL)
idefloppy_end_request (1, HWGROUP(drive));
}
-#endif /* CONFIG_BLK_DEV_TRITON */
+#endif /* CONFIG_BLK_DEV_IDEDMA */
/*
* idefloppy_queue_pc_head generates a new packet command request in front
@@ -681,7 +681,7 @@ static void idefloppy_pc_intr (ide_drive_t *drive)
printk (KERN_INFO "ide-floppy: Reached idefloppy_pc_intr interrupt handler\n");
#endif /* IDEFLOPPY_DEBUG_LOG */
-#ifdef CONFIG_BLK_DEV_TRITON
+#ifdef CONFIG_BLK_DEV_IDEDMA
if (test_bit (PC_DMA_IN_PROGRESS, &pc->flags)) {
if (HWIF(drive)->dmaproc(ide_dma_status_bad, drive)) {
set_bit (PC_DMA_ERROR, &pc->flags);
@@ -694,7 +694,7 @@ static void idefloppy_pc_intr (ide_drive_t *drive)
printk (KERN_INFO "ide-floppy: DMA finished\n");
#endif /* IDEFLOPPY_DEBUG_LOG */
}
-#endif /* CONFIG_BLK_DEV_TRITON */
+#endif /* CONFIG_BLK_DEV_IDEDMA */
status.all = GET_STAT(); /* Clear the interrupt */
@@ -725,7 +725,7 @@ static void idefloppy_pc_intr (ide_drive_t *drive)
pc->callback(drive); /* Command finished - Call the callback function */
return;
}
-#ifdef CONFIG_BLK_DEV_TRITON
+#ifdef CONFIG_BLK_DEV_IDEDMA
if (test_and_clear_bit (PC_DMA_IN_PROGRESS, &pc->flags)) {
printk (KERN_ERR "ide-floppy: The floppy wants to issue more interrupts in DMA mode\n");
printk (KERN_ERR "ide-floppy: DMA disabled, reverting to PIO\n");
@@ -733,7 +733,7 @@ static void idefloppy_pc_intr (ide_drive_t *drive)
ide_do_reset (drive);
return;
}
-#endif /* CONFIG_BLK_DEV_TRITON */
+#endif /* CONFIG_BLK_DEV_IDEDMA */
bcount.b.high=IN_BYTE (IDE_BCOUNTH_REG); /* Get the number of bytes to transfer */
bcount.b.low=IN_BYTE (IDE_BCOUNTL_REG); /* on this interrupt */
ireason.all=IN_BYTE (IDE_IREASON_REG);
@@ -841,14 +841,14 @@ static void idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *pc)
pc->current_position=pc->buffer;
bcount.all=pc->request_transfer; /* Request to transfer the entire buffer at once */
-#ifdef CONFIG_BLK_DEV_TRITON
+#ifdef CONFIG_BLK_DEV_IDEDMA
if (test_and_clear_bit (PC_DMA_ERROR, &pc->flags)) {
printk (KERN_WARNING "ide-floppy: DMA disabled, reverting to PIO\n");
HWIF(drive)->dmaproc(ide_dma_off, drive);
}
if (test_bit (PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma)
dma_ok=!HWIF(drive)->dmaproc(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive);
-#endif /* CONFIG_BLK_DEV_TRITON */
+#endif /* CONFIG_BLK_DEV_IDEDMA */
OUT_BYTE (drive->ctl,IDE_CONTROL_REG);
OUT_BYTE (dma_ok ? 1:0,IDE_FEATURE_REG); /* Use PIO/DMA */
@@ -856,12 +856,12 @@ static void idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *pc)
OUT_BYTE (bcount.b.low,IDE_BCOUNTL_REG);
OUT_BYTE (drive->select.all,IDE_SELECT_REG);
-#ifdef CONFIG_BLK_DEV_TRITON
+#ifdef CONFIG_BLK_DEV_IDEDMA
if (dma_ok) { /* Begin DMA, if necessary */
set_bit (PC_DMA_IN_PROGRESS, &pc->flags);
(void) (HWIF(drive)->dmaproc(ide_dma_begin, drive));
}
-#endif /* CONFIG_BLK_DEV_TRITON */
+#endif /* CONFIG_BLK_DEV_IDEDMA */
if (test_bit (IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags)) {
ide_set_handler (drive, &idefloppy_transfer_pc, WAIT_CMD);
diff --git a/drivers/block/ide-probe.c b/drivers/block/ide-probe.c
index 3ce3e882a..9ae187b7e 100644
--- a/drivers/block/ide-probe.c
+++ b/drivers/block/ide-probe.c
@@ -114,20 +114,22 @@ static inline void do_identify (ide_drive_t *drive, byte cmd)
if (cmd == WIN_PIDENTIFY) {
byte type = (id->config >> 8) & 0x1f;
printk("ATAPI ");
-#ifdef CONFIG_BLK_DEV_PROMISE
- if (HWIF(drive)->is_promise2) {
+#ifdef CONFIG_BLK_DEV_PDC4030
+ if (HWIF(drive)->is_pdc4030_2) {
printk(" -- not supported on 2nd Promise port\n");
drive->present = 0;
return;
}
-#endif /* CONFIG_BLK_DEV_PROMISE */
+#endif /* CONFIG_BLK_DEV_PDC4030 */
switch (type) {
case ide_floppy:
- if (!strstr(id->model, "oppy") && !strstr(id->model, "poyp") && !strstr(id->model, "ZIP"))
- printk("cdrom or floppy?, assuming ");
- if (drive->media != ide_cdrom) {
- printk ("FLOPPY");
- break;
+ if (!strstr(id->model, "CD-ROM")) {
+ if (!strstr(id->model, "oppy") && !strstr(id->model, "poyp") && !strstr(id->model, "ZIP"))
+ printk("cdrom or floppy?, assuming ");
+ if (drive->media != ide_cdrom) {
+ printk ("FLOPPY");
+ break;
+ }
}
type = ide_cdrom; /* Early cdrom models used zero */
case ide_cdrom:
@@ -192,15 +194,16 @@ static int try_to_identify (ide_drive_t *drive, byte cmd)
} else
hd_status = IDE_ALTSTATUS_REG; /* use non-intrusive polling */
-#if CONFIG_BLK_DEV_PROMISE
- if (IS_PROMISE_DRIVE) {
- if (promise_cmd(drive,PROMISE_IDENTIFY)) {
+#if CONFIG_BLK_DEV_PDC4030
+ if (IS_PDC4030_DRIVE) {
+ extern int pdc4030_cmd(ide_drive_t *, byte);
+ if (pdc4030_cmd(drive,PROMISE_IDENTIFY)) {
if (irqs)
(void) probe_irq_off(irqs);
return 1;
}
} else
-#endif /* CONFIG_BLK_DEV_PROMISE */
+#endif /* CONFIG_BLK_DEV_PDC4030 */
OUT_BYTE(cmd,IDE_COMMAND_REG); /* ask drive for ID */
timeout = ((cmd == WIN_IDENTIFY) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2;
timeout += jiffies;
@@ -363,10 +366,10 @@ static void probe_cmos_for_drives (ide_hwif_t *hwif)
byte cmos_disks, *BIOS = (byte *) &drive_info;
int unit;
-#ifdef CONFIG_BLK_DEV_PROMISE
- if (hwif->is_promise2)
+#ifdef CONFIG_BLK_DEV_PDC4030
+ if (hwif->is_pdc4030_2)
return;
-#endif /* CONFIG_BLK_DEV_PROMISE */
+#endif /* CONFIG_BLK_DEV_PDC4030 */
outb_p(0x12,0x70); /* specify CMOS address 0x12 */
cmos_disks = inb_p(0x71); /* read the data from 0x12 */
/* Extract drive geometry from CMOS+BIOS if not already setup */
@@ -397,12 +400,12 @@ static void probe_hwif (ide_hwif_t *hwif)
return;
if (hwif->io_ports[IDE_DATA_OFFSET] == HD_DATA)
probe_cmos_for_drives (hwif);
-#if CONFIG_BLK_DEV_PROMISE
- if (!hwif->is_promise2 &&
+#if CONFIG_BLK_DEV_PDC4030
+ if (!hwif->is_pdc4030_2 &&
(ide_check_region(hwif->io_ports[IDE_DATA_OFFSET],8) || ide_check_region(hwif->io_ports[IDE_CONTROL_OFFSET],1))) {
#else
if (ide_check_region(hwif->io_ports[IDE_DATA_OFFSET],8) || ide_check_region(hwif->io_ports[IDE_CONTROL_OFFSET],1)) {
-#endif /* CONFIG_BLK_DEV_PROMISE */
+#endif /* CONFIG_BLK_DEV_PDC4030 */
int msgout = 0;
for (unit = 0; unit < MAX_DRIVES; ++unit) {
ide_drive_t *drive = &hwif->drives[unit];
diff --git a/drivers/block/ide-tape.c b/drivers/block/ide-tape.c
index 4df355141..e9d7f1433 100644
--- a/drivers/block/ide-tape.c
+++ b/drivers/block/ide-tape.c
@@ -170,13 +170,13 @@
* unit, making performance almost independent of the
* chosen user block size.
* Some improvements in error recovery.
- * By cooperating with triton.c, bus mastering DMA can
+ * By cooperating with ide-dma.c, bus mastering DMA can
* now sometimes be used with IDE tape drives as well.
* Bus mastering DMA has the potential to dramatically
* reduce the CPU's overhead when accessing the device,
* and can be enabled by using hdparm -d1 on the tape's
* block device interface. For more info, read the
- * comments in triton.c.
+ * comments in ide-dma.c.
* Ver 1.4 Mar 13 96 Fixed serialize support.
* Ver 1.5 Apr 12 96 Fixed shared interface operation, broken in 1.3.85.
* Fixed pipelined read mode inefficiency.
@@ -1093,7 +1093,7 @@ static void idetape_output_buffers (ide_drive_t *drive, idetape_pc_t *pc, unsign
}
}
-#ifdef CONFIG_BLK_DEV_TRITON
+#ifdef CONFIG_BLK_DEV_IDEDMA
static void idetape_update_buffers (idetape_pc_t *pc)
{
struct buffer_head *bh = pc->bh;
@@ -1116,7 +1116,7 @@ static void idetape_update_buffers (idetape_pc_t *pc)
}
pc->bh = bh;
}
-#endif /* CONFIG_BLK_DEV_TRITON */
+#endif /* CONFIG_BLK_DEV_IDEDMA */
/*
* idetape_postpone_request postpones the current request so that
@@ -1610,7 +1610,7 @@ static void idetape_analyze_error (ide_drive_t *drive,idetape_request_sense_resu
printk (KERN_INFO "ide-tape: pc = %x, sense key = %x, asc = %x, ascq = %x\n",pc->c[0],result->sense_key,result->asc,result->ascq);
#endif /* IDETAPE_DEBUG_LOG */
-#ifdef CONFIG_BLK_DEV_TRITON
+#ifdef CONFIG_BLK_DEV_IDEDMA
/*
* Correct pc->actually_transferred by asking the tape.
@@ -1619,7 +1619,7 @@ static void idetape_analyze_error (ide_drive_t *drive,idetape_request_sense_resu
pc->actually_transferred = pc->request_transfer - tape->tape_block_size * ntohl (get_unaligned (&result->information));
idetape_update_buffers (pc);
}
-#endif /* CONFIG_BLK_DEV_TRITON */
+#endif /* CONFIG_BLK_DEV_IDEDMA */
if (pc->c[0] == IDETAPE_READ_CMD && result->filemark) {
pc->error = IDETAPE_ERROR_FILEMARK;
set_bit (PC_ABORT, &pc->flags);
@@ -1721,7 +1721,7 @@ static void idetape_pc_intr (ide_drive_t *drive)
printk (KERN_INFO "ide-tape: Reached idetape_pc_intr interrupt handler\n");
#endif /* IDETAPE_DEBUG_LOG */
-#ifdef CONFIG_BLK_DEV_TRITON
+#ifdef CONFIG_BLK_DEV_IDEDMA
if (test_bit (PC_DMA_IN_PROGRESS, &pc->flags)) {
if (HWIF(drive)->dmaproc(ide_dma_status_bad, drive)) {
set_bit (PC_DMA_ERROR, &pc->flags);
@@ -1739,7 +1739,7 @@ static void idetape_pc_intr (ide_drive_t *drive)
printk (KERN_INFO "ide-tape: DMA finished\n");
#endif /* IDETAPE_DEBUG_LOG */
}
-#endif /* CONFIG_BLK_DEV_TRITON */
+#endif /* CONFIG_BLK_DEV_IDEDMA */
status.all = GET_STAT(); /* Clear the interrupt */
@@ -1776,7 +1776,7 @@ static void idetape_pc_intr (ide_drive_t *drive)
pc->callback(drive); /* Command finished - Call the callback function */
return;
}
-#ifdef CONFIG_BLK_DEV_TRITON
+#ifdef CONFIG_BLK_DEV_IDEDMA
if (test_and_clear_bit (PC_DMA_IN_PROGRESS, &pc->flags)) {
printk (KERN_ERR "ide-tape: The tape wants to issue more interrupts in DMA mode\n");
printk (KERN_ERR "ide-tape: DMA disabled, reverting to PIO\n");
@@ -1784,7 +1784,7 @@ static void idetape_pc_intr (ide_drive_t *drive)
ide_do_reset (drive);
return;
}
-#endif /* CONFIG_BLK_DEV_TRITON */
+#endif /* CONFIG_BLK_DEV_IDEDMA */
bcount.b.high=IN_BYTE (IDE_BCOUNTH_REG); /* Get the number of bytes to transfer */
bcount.b.low=IN_BYTE (IDE_BCOUNTL_REG); /* on this interrupt */
ireason.all=IN_BYTE (IDE_IREASON_REG);
@@ -1915,14 +1915,14 @@ static void idetape_issue_packet_command (ide_drive_t *drive, idetape_pc_t *pc)
pc->current_position=pc->buffer;
bcount.all=pc->request_transfer; /* Request to transfer the entire buffer at once */
-#ifdef CONFIG_BLK_DEV_TRITON
+#ifdef CONFIG_BLK_DEV_IDEDMA
if (test_and_clear_bit (PC_DMA_ERROR, &pc->flags)) {
printk (KERN_WARNING "ide-tape: DMA disabled, reverting to PIO\n");
HWIF(drive)->dmaproc(ide_dma_off, drive);
}
if (test_bit (PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma)
dma_ok=!HWIF(drive)->dmaproc(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive);
-#endif /* CONFIG_BLK_DEV_TRITON */
+#endif /* CONFIG_BLK_DEV_IDEDMA */
OUT_BYTE (drive->ctl,IDE_CONTROL_REG);
OUT_BYTE (dma_ok ? 1:0,IDE_FEATURE_REG); /* Use PIO/DMA */
@@ -1952,12 +1952,12 @@ static void idetape_issue_packet_command (ide_drive_t *drive, idetape_pc_t *pc)
return;
}
atapi_output_bytes (drive,pc->c,12); /* Send the actual packet */
-#ifdef CONFIG_BLK_DEV_TRITON
+#ifdef CONFIG_BLK_DEV_IDEDMA
if (dma_ok) { /* Begin DMA, if necessary */
set_bit (PC_DMA_IN_PROGRESS, &pc->flags);
(void) (HWIF(drive)->dmaproc(ide_dma_begin, drive));
}
-#endif /* CONFIG_BLK_DEV_TRITON */
+#endif /* CONFIG_BLK_DEV_IDEDMA */
}
static void idetape_media_access_finished (ide_drive_t *drive)
diff --git a/drivers/block/ide.c b/drivers/block/ide.c
index 1a5fdc5a8..50af139cd 100644
--- a/drivers/block/ide.c
+++ b/drivers/block/ide.c
@@ -1,7 +1,7 @@
/*
- * linux/drivers/block/ide.c Version 6.03 June 4, 1997
+ * linux/drivers/block/ide.c Version 6.05 November 30, 1997
*
- * Copyright (C) 1994-1997 Linus Torvalds & authors (see below)
+ * Copyright (C) 1994-1998 Linus Torvalds & authors (see below)
*/
#define _IDE_C /* needed by <linux/blk.h> */
@@ -65,197 +65,6 @@
* Version 1.4 BETA added auto probing for irq(s)
* Version 1.5 BETA added ALPHA (untested) support for IDE cd-roms,
* ...
- * Version 3.5 correct the bios_cyl field if it's too small
- * (linux 1.1.76) (to help fdisk with brain-dead BIOSs)
- * Version 3.6 cosmetic corrections to comments and stuff
- * (linux 1.1.77) reorganise probing code to make it understandable
- * added halfway retry to probing for drive identification
- * added "hdx=noprobe" command line option
- * allow setting multmode even when identification fails
- * Version 3.7 move set_geometry=1 from do_identify() to ide_init()
- * increase DRQ_WAIT to eliminate nuisance messages
- * wait for DRQ_STAT instead of DATA_READY during probing
- * (courtesy of Gary Thomas gary@efland.UU.NET)
- * Version 3.8 fixed byte-swapping for confused Mitsumi cdrom drives
- * update of ide-cd.c from Scott, allows blocksize=1024
- * cdrom probe fixes, inspired by jprang@uni-duisburg.de
- * Version 3.9 don't use LBA if lba_capacity looks funny
- * correct the drive capacity calculations
- * fix probing for old Seagates without IDE_ALTSTATUS_REG
- * fix byte-ordering for some NEC cdrom drives
- * Version 3.10 disable multiple mode by default; was causing trouble
- * Version 3.11 fix mis-identification of old WD disks as cdroms
- * Version 3,12 simplify logic for selecting initial mult_count
- * (fixes problems with buggy WD drives)
- * 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
- * Version 3.15 add SINGLE_THREADED flag for use with dual-CMD i/f
- * ignore WRERR_STAT for non-write operations
- * added vlb_sync support for DC-2000A & others,
- * (incl. some Promise chips), courtesy of Frank Gockel
- * Version 3.16 convert vlb_32bit and vlb_sync into runtime flags
- * add ioctls to get/set VLB flags (HDIO_[SG]ET_CHIPSET)
- * rename SINGLE_THREADED to SUPPORT_SERIALIZE,
- * add boot flag to "serialize" operation for CMD i/f
- * add optional support for DTC2278 interfaces,
- * courtesy of andy@cercle.cts.com (Dyan Wile).
- * add boot flag to enable "dtc2278" probe
- * add probe to avoid EATA (SCSI) interfaces,
- * courtesy of neuffer@goofy.zdv.uni-mainz.de.
- * Version 4.00 tidy up verify_area() calls - heiko@colossus.escape.de
- * add flag to ignore WRERR_STAT for some drives
- * courtesy of David.H.West@um.cc.umich.edu
- * assembly syntax tweak to vlb_sync
- * removable drive support from scuba@cs.tu-berlin.de
- * add transparent support for DiskManager-6.0x "Dynamic
- * Disk Overlay" (DDO), most of this is in genhd.c
- * eliminate "multiple mode turned off" message at boot
- * Version 4.10 fix bug in ioctl for "hdparm -c3"
- * fix DM6:DDO support -- now works with LILO, fdisk, ...
- * don't treat some naughty WD drives as removable
- * Version 4.11 updated DM6 support using info provided by OnTrack
- * Version 5.00 major overhaul, multmode setting fixed, vlb_sync fixed
- * added support for 3rd/4th/alternative IDE ports
- * created ide.h; ide-cd.c now compiles separate from ide.c
- * hopefully fixed infinite "unexpected_intr" from cdroms
- * zillions of other changes and restructuring
- * somehow reduced overall memory usage by several kB
- * probably slowed things down slightly, but worth it
- * Version 5.01 AT LAST!! Finally understood why "unexpected_intr"
- * was happening at various times/places: whenever the
- * ide-interface's ctl_port was used to "mask" the irq,
- * it also would trigger an edge in the process of masking
- * which would result in a self-inflicted interrupt!!
- * (such a stupid way to build a hardware interrupt mask).
- * This is now fixed (after a year of head-scratching).
- * Version 5.02 got rid of need for {enable,disable}_irq_list()
- * Version 5.03 tune-ups, comments, remove "busy wait" from drive resets
- * removed PROBE_FOR_IRQS option -- no longer needed
- * OOOPS! fixed "bad access" bug for 2nd drive on an i/f
- * Version 5.04 changed "ira %d" to "irq %d" in DEBUG message
- * added more comments, cleaned up unexpected_intr()
- * OOOPS! fixed null pointer problem in ide reset code
- * added autodetect for Triton chipset -- no effect yet
- * Version 5.05 OOOPS! fixed bug in revalidate_disk()
- * OOOPS! fixed bug in ide_do_request()
- * added ATAPI reset sequence for cdroms
- * Version 5.10 added Bus-Mastered DMA support for Triton Chipset
- * some (mostly) cosmetic changes
- * Version 5.11 added ht6560b support by malafoss@snakemail.hut.fi
- * reworked PCI scanning code
- * added automatic RZ1000 detection/support
- * added automatic PCI CMD640 detection/support
- * added option for VLB CMD640 support
- * tweaked probe to find cdrom on hdb with disks on hda,hdc
- * Version 5.12 some performance tuning
- * added message to alert user to bad /dev/hd[cd] entries
- * OOOPS! fixed bug in atapi reset
- * driver now forces "serialize" again for all cmd640 chips
- * noticed REALLY_SLOW_IO had no effect, moved it to ide.c
- * made do_drive_cmd() into public ide_do_drive_cmd()
- * Version 5.13 fixed typo ('B'), thanks to houston@boyd.geog.mcgill.ca
- * fixed ht6560b support
- * Version 5.13b (sss) fix problem in calling ide_cdrom_setup()
- * don't bother invalidating nonexistent partitions
- * Version 5.14 fixes to cmd640 support.. maybe it works now(?)
- * added & tested full EZ-DRIVE support -- don't use LILO!
- * don't enable 2nd CMD640 PCI port during init - conflict
- * Version 5.15 bug fix in init_cmd640_vlb()
- * bug fix in interrupt sharing code
- * Version 5.16 ugh.. fix "serialize" support, broken in 5.15
- * remove "Huh?" from cmd640 code
- * added qd6580 interface speed select from Colten Edwards
- * Version 5.17 kludge around bug in BIOS32 on Intel triton motherboards
- * Version 5.18 new CMD640 code, moved to cmd640.c, #include'd for now
- * new UMC8672 code, moved to umc8672.c, #include'd for now
- * disallow turning on DMA when h/w not capable of DMA
- * Version 5.19 fix potential infinite timeout on resets
- * extend reset poll into a general purpose polling scheme
- * add atapi tape drive support from Gadi Oxman
- * simplify exit from _intr routines -- no IDE_DO_REQUEST
- * Version 5.20 leave current rq on blkdev request list during I/O
- * generalized ide_do_drive_cmd() for tape/cdrom driver use
- * Version 5.21 fix nasty cdrom/tape bug (ide_preempt was messed up)
- * Version 5.22 fix ide_xlate_1024() to work with/without drive->id
- * Version 5.23 miscellaneous touch-ups
- * Version 5.24 fix #if's for SUPPORT_CMD640
- * Version 5.25 more touch-ups, fix cdrom resets, ...
- * cmd640.c now configs/compiles separate from ide.c
- * Version 5.26 keep_settings now maintains the using_dma flag
- * fix [EZD] remap message to only output at boot time
- * fix "bad /dev/ entry" message to say hdc, not hdc0
- * fix ide_xlate_1024() to respect user specified CHS
- * use CHS from partn table if it looks translated
- * re-merged flags chipset,vlb_32bit,vlb_sync into io_32bit
- * keep track of interface chipset type, when known
- * add generic PIO mode "tuneproc" mechanism
- * fix cmd640_vlb option
- * fix ht6560b support (was completely broken)
- * umc8672.c now configures/compiles separate from ide.c
- * move dtc2278 support to dtc2278.c
- * move ht6560b support to ht6560b.c
- * move qd6580 support to qd6580.c
- * add ali14xx support in ali14xx.c
- * Version 5.27 add [no]autotune parameters to help cmd640
- * move rz1000 support to rz1000.c
- * Version 5.28 #include "ide_modes.h"
- * fix disallow_unmask: now per-interface "no_unmask" bit
- * force io_32bit to be the same on drive pairs of dtc2278
- * improved IDE tape error handling, and tape DMA support
- * bugfix in ide_do_drive_cmd() for cdroms + serialize
- * Version 5.29 fixed non-IDE check for too many physical heads
- * don't use LBA if capacity is smaller than CHS
- * Version 5.30 remove real_devices kludge, formerly used by genhd.c
- * Version 5.32 change "KB" to "kB"
- * fix serialize (was broken in kernel 1.3.72)
- * add support for "hdparm -I"
- * use common code for disk/tape/cdrom IDE_DRIVE_CMDs
- * add support for Promise DC4030VL caching card
- * improved serialize support
- * put partition check back into alphabetical order
- * add config option for PCMCIA baggage
- * try to make PCMCIA support safer to use
- * improve security on ioctls(): all are suser() only
- * Version 5.33 improve handling of HDIO_DRIVE_CMDs that read data
- * Version 5.34 fix irq-sharing problem from 5.33
- * fix cdrom ioctl problem from 5.33
- * Version 5.35 cosmetic changes
- * fix cli() problem in try_to_identify()
- * Version 5.36 fixes to optional PCMCIA support
- * Version 5.37 don't use DMA when "noautotune" is specified
- * Version 5.37a (go) fix shared irq probing (was broken in kernel 1.3.72)
- * call unplug_device() from ide_do_drive_cmd()
- * Version 5.38 add "hdx=none" option, courtesy of Joel Maslak
- * mask drive irq after use, if sharing with another hwif
- * add code to help debug weird cmd640 problems
- * Version 5.39 fix horrible error in earlier irq sharing "fix"
- * Version 5.40 fix serialization -- was broken in 5.39
- * help sharing by masking device irq after probing
- * Version 5.41 more fixes to irq sharing/serialize detection
- * disable io_32bit by default on drive reset
- * Version 5.42 simplify irq-masking after probe
- * fix NULL pointer deref in save_match()
- * Version 5.43 Ugh.. unexpected_intr is back: try to exterminate it
- * Version 5.44 Fix for "irq probe failed" on cmd640
- * change path on message regarding MAKEDEV.ide
- * add a throttle to the unexpected_intr() messages
- * Version 5.45 fix ugly parameter parsing bugs (thanks Derek)
- * include Gadi's magic fix for cmd640 unexpected_intr
- * include mc68000 patches from Geert Uytterhoeven
- * add Gadi's fix for PCMCIA cdroms
- * Version 5.46 remove the mc68000 #ifdefs for 2.0.x
- * Version 5.47 fix set_tune race condition
- * fix bug in earlier PCMCIA cdrom update
- * Version 5.48 if def'd, invoke CMD640_DUMP_REGS when irq probe fails
- * lengthen the do_reset1() pulse, for laptops
- * add idebus=xx parameter for cmd640 and ali chipsets
- * no_unmask flag now per-drive instead of per-hwif
- * fix tune_req so that it gets done immediately
- * fix missing restore_flags() in ide_ioctl
- * prevent use of io_32bit on cmd640 with no prefetch
- * Version 5.49 fix minor quirks in probing routines
* Version 5.50 allow values as small as 20 for idebus=
* Version 5.51 force non io_32bit in drive_cmd_intr()
* change delay_10ms() to delay_50ms() to fix problems
@@ -281,6 +90,11 @@
* Version 6.02 fix ide_ack_intr() call
* check partition table on floppies
* Version 6.03 handle bad status bit sequencing in ide_wait_stat()
+ * Version 6.10 deleted old entries from this list of updates
+ * replaced triton.c with ide-dma.c generic PCI DMA
+ * added support for BIOS-enabled UltraDMA
+ * rename all "promise" things to "pdc4030"
+ * fix EZ-DRIVE handling on small disks
*
* Some additional driver compile-time options are in ide.h
*
@@ -867,14 +681,14 @@ byte ide_dump_status (ide_drive_t *drive, const char *msg, byte stat)
#if FANCY_STATUS_DUMPS
if (drive->media == ide_disk) {
printk(" { ");
- if (err & BBD_ERR) printk("BadSector ");
+ if (err & ABRT_ERR) printk("DriveStatusError ");
+ if (err & ICRC_ERR) printk((err & ABRT_ERR) ? "BadCRC " : "BadSector ");
if (err & ECC_ERR) printk("UncorrectableError ");
if (err & ID_ERR) printk("SectorIdNotFound ");
- if (err & ABRT_ERR) printk("DriveStatusError ");
if (err & TRK0_ERR) printk("TrackZeroNotFound ");
if (err & MARK_ERR) printk("AddrMarkNotFound ");
printk("}");
- if (err & (BBD_ERR|ECC_ERR|ID_ERR|MARK_ERR)) {
+ if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR || (err & (ECC_ERR|ID_ERR|MARK_ERR))) {
byte cur = IN_BYTE(IDE_SELECT_REG);
if (cur & 0x40) { /* using LBA? */
printk(", LBAsect=%ld", (unsigned long)
@@ -922,7 +736,7 @@ static void try_to_flush_leftover_data (ide_drive_t *drive)
}
/*
- * ide_error() takes action based on the error returned by the controller.
+ * ide_error() takes action based on the error returned by the drive.
*/
void ide_error (ide_drive_t *drive, const char *msg, byte stat)
{
@@ -943,7 +757,12 @@ void ide_error (ide_drive_t *drive, const char *msg, byte stat)
} else {
if (drive->media == ide_disk && (stat & ERR_STAT)) {
/* err has different meaning on cdrom and tape */
- if (err & (BBD_ERR | ECC_ERR)) /* retries won't help these */
+ if (err == ABRT_ERR) {
+ if (drive->select.b.lba && IN_BYTE(IDE_COMMAND_REG) == WIN_SPECIFY)
+ return; /* some newer drives don't support WIN_SPECIFY */
+ } else if ((err & (ABRT_ERR | ICRC_ERR)) == (ABRT_ERR | ICRC_ERR))
+ ; /* UDMA crc error -- just retry the operation */
+ else if (err & (BBD_ERR | ECC_ERR)) /* retries won't help these */
rq->errors = ERROR_MAX;
else if (err & TRK0_ERR) /* help it find track zero */
rq->errors |= ERROR_RECAL;
@@ -1545,7 +1364,7 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio
struct request *cur_rq;
struct semaphore sem = MUTEX_LOCKED;
- if (IS_PROMISE_DRIVE && rq->buffer != NULL)
+ if (IS_PDC4030_DRIVE && rq->buffer != NULL)
return -ENOSYS; /* special drive cmds not supported */
rq->errors = 0;
rq->rq_status = RQ_ACTIVE;
@@ -1931,8 +1750,13 @@ static int ide_ioctl (struct inode *inode, struct file *file,
return -EINVAL;
if (drive->id == NULL)
return -ENOMSG;
+#if 0
if (copy_to_user((char *)arg, (char *)drive->id, sizeof(*drive->id)))
return -EFAULT;
+#else
+ if (copy_to_user((char *)arg, (char *)drive->id, 142))
+ return -EFAULT;
+#endif
return 0;
case HDIO_GET_NOWERR:
@@ -2351,8 +2175,8 @@ __initfunc(void ide_setup (char *s))
/*
* Be VERY CAREFUL changing this: note hardcoded indexes below
*/
- const char *ide_words[] = {"noprobe", "serialize", "autotune", "noautotune",
- "qd6580", "ht6560b", "cmd640_vlb", "dtc2278", "umc8672", "ali14xx", "dc4030", "reset", NULL};
+ const char *ide_words[] = {"noprobe", "serialize", "autotune", "noautotune", "qd6580",
+ "ht6560b", "cmd640_vlb", "dtc2278", "umc8672", "ali14xx", "dc4030", "four", "reset", NULL};
hw = s[3] - '0';
hwif = &ide_hwifs[hw];
i = match_parm(&s[4], ide_words, vals, 3);
@@ -2360,7 +2184,7 @@ __initfunc(void ide_setup (char *s))
/*
* Cryptic check to ensure chipset not already set for hwif:
*/
- if (i > 0 || (i <= -5 && i != -12)) {
+ if (i > 0 || (i <= -5 && i != -13)) {
if (hwif->chipset != ide_unknown)
goto bad_option;
if (i <= -5) {
@@ -2376,16 +2200,32 @@ __initfunc(void ide_setup (char *s))
}
switch (i) {
- case -12: /* "reset" */
+ case -13: /* "reset" */
hwif->reset = 1;
goto done;
-#ifdef CONFIG_BLK_DEV_PROMISE
+#ifdef CONFIG_BLK_DEV_4DRIVES
+ case -12: /* "four" drives on one set of ports */
+ {
+ ide_hwif_t *mate = &ide_hwifs[hw^1];
+ mate->mate = hwif;
+ hwif->mate = mate;
+ hwif->chipset = mate->chipset = ide_4drives;
+ hwif->serialized = mate->serialized = 1;
+ mate->drives[0].select.all ^= 0x20;
+ mate->drives[1].select.all ^= 0x20;
+ memcpy(mate->io_ports, hwif->io_ports, sizeof(hwif->io_ports));
+ mate->irq = hwif->irq;
+ goto done;
+ }
+#endif /* CONFIG_BLK_DEV_4DRIVES */
+#ifdef CONFIG_BLK_DEV_PDC4030
case -11: /* "dc4030" */
{
- setup_dc4030(hwif);
+ extern void setup_pdc4030(ide_hwif_t *);
+ setup_pdc4030(hwif);
goto done;
}
-#endif /* CONFIG_BLK_DEV_PROMISE */
+#endif /* CONFIG_BLK_DEV_PDC4030 */
#ifdef CONFIG_BLK_DEV_ALI14XX
case -10: /* "ali14xx" */
{
@@ -2510,6 +2350,9 @@ int ide_xlate_1024 (kdev_t i_rdev, int xparm, const char *msg)
printk("%s ", msg);
+ if (xparm == -1 && drive->bios_cyl < 1024)
+ return 0; /* small disk: no translation needed */
+
if (drive->id) {
drive->cyl = drive->id->cyls;
drive->head = drive->id->heads;
@@ -2550,32 +2393,6 @@ int ide_xlate_1024 (kdev_t i_rdev, int xparm, const char *msg)
return 1;
}
-#ifdef CONFIG_PCI
-#if defined(CONFIG_BLK_DEV_RZ1000) || defined(CONFIG_BLK_DEV_TRITON) || defined(CONFIG_BLK_DEV_OPTI621)
-
-typedef void (ide_pci_init_proc_t)(byte, byte);
-
-/*
- * ide_probe_pci() scans PCI for a specific vendor/device function,
- * and invokes the supplied init routine for each instance detected.
- */
-__initfunc(static void ide_probe_pci (unsigned short vendor, unsigned short device, ide_pci_init_proc_t *init, int func_adj))
-{
- unsigned long flags;
- unsigned index;
- byte fn, bus;
-
- save_flags(flags);
- cli();
- for (index = 0; !pcibios_find_device (vendor, device, index, &bus, &fn); ++index) {
- init (bus, fn + func_adj);
- }
- restore_flags(flags);
-}
-
-#endif /* defined(CONFIG_BLK_DEV_RZ1000) || defined(CONFIG_BLK_DEV_TRITON) || defined(CONFIG_BLK_DEV_OPTI621) */
-#endif /* CONFIG_PCI */
-
/*
* probe_for_hwifs() finds/initializes "known" IDE interfaces
*
@@ -2588,50 +2405,43 @@ __initfunc(static void probe_for_hwifs (void))
/*
* Find/initialize PCI IDE interfaces
*/
- if (pcibios_present()) {
+ if (pcibios_present())
+ {
+#ifdef CONFIG_BLK_DEV_IDEDMA
+ {
+ extern void ide_scan_pcibus(void);
+ ide_scan_pcibus();
+ }
+#endif
#ifdef CONFIG_BLK_DEV_RZ1000
- ide_pci_init_proc_t init_rz1000;
- ide_probe_pci (PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000, &init_rz1000, 0);
- ide_probe_pci (PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1001, &init_rz1000, 0);
-#endif /* CONFIG_BLK_DEV_RZ1000 */
-#ifdef CONFIG_BLK_DEV_TRITON
- /*
- * Apparently the BIOS32 services on Intel motherboards are
- * buggy and won't find the PCI_DEVICE_ID_INTEL_82371_1 for us.
- * So instead, we search for PCI_DEVICE_ID_INTEL_82371_0,
- * and then add 1.
- */
- ide_probe_pci (PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371_0, &ide_init_triton, 1);
- ide_probe_pci (PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_1, &ide_init_triton, 0);
- ide_probe_pci (PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB, &ide_init_triton, 0);
- ide_probe_pci (PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, &ide_init_triton, 0);
-#endif /* CONFIG_BLK_DEV_TRITON */
-#ifdef CONFIG_BLK_DEV_OPTI621
- ide_probe_pci (PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C621, &ide_init_opti621, 0);
-#endif /* CONFIG_BLK_DEV_OPTI621 */
+ {
+ extern void ide_probe_for_rz100x(void);
+ ide_probe_for_rz100x();
+ }
+#endif
}
#endif /* CONFIG_PCI */
#ifdef CONFIG_BLK_DEV_CMD640
{
- extern void ide_probe_for_cmd640x (void);
+ extern void ide_probe_for_cmd640x(void);
ide_probe_for_cmd640x();
}
#endif
-#ifdef CONFIG_BLK_DEV_PROMISE
- init_dc4030();
+#ifdef CONFIG_BLK_DEV_PDC4030
+ {
+ extern int init_pdc4030(void);
+ (void) init_pdc4030();
+ }
#endif
}
__initfunc(void ide_init_builtin_drivers (void))
{
/*
- * Probe for special "known" interface chipsets
+ * Probe for special PCI and other "known" interface chipsets
*/
probe_for_hwifs ();
- /*
- * Probe for devices
- */
#ifdef CONFIG_BLK_DEV_IDE
#ifdef __mc68000__
if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) {
diff --git a/drivers/block/ide.h b/drivers/block/ide.h
index eb3f54a55..dd3549ac9 100644
--- a/drivers/block/ide.h
+++ b/drivers/block/ide.h
@@ -3,7 +3,7 @@
/*
* linux/drivers/block/ide.h
*
- * Copyright (C) 1994-1996 Linus Torvalds & authors
+ * Copyright (C) 1994-1998 Linus Torvalds & authors
*/
#include <linux/config.h>
@@ -164,7 +164,7 @@ typedef unsigned char byte; /* used everywhere */
#define WAIT_CMD (10*HZ) /* 10sec - maximum wait for an IRQ to happen */
#define WAIT_MIN_SLEEP (2*HZ/100) /* 20msec - minimum sleep time */
-#if defined(CONFIG_BLK_DEV_HT6560B) || defined(CONFIG_BLK_DEV_PROMISE)
+#if defined(CONFIG_BLK_DEV_HT6560B) || defined(CONFIG_BLK_DEV_PDC4030) || defined(CONFIG_BLK_DEV_TRM290)
#define SELECT_DRIVE(hwif,drive) \
{ \
if (hwif->selectproc) \
@@ -174,7 +174,7 @@ typedef unsigned char byte; /* used everywhere */
}
#else
#define SELECT_DRIVE(hwif,drive) OUT_BYTE((drive)->select.all, hwif->io_ports[IDE_SELECT_OFFSET]);
-#endif /* CONFIG_BLK_DEV_HT6560B || CONFIG_BLK_DEV_PROMISE */
+#endif /* CONFIG_BLK_DEV_HT6560B || CONFIG_BLK_DEV_PDC4030 */
/*
* Now for the data we need to maintain per-drive: ide_drive_t
@@ -248,6 +248,7 @@ typedef struct ide_drive_s {
byte bios_sect __attribute__ ((aligned (8))); /* BIOS/fdisk/LILO sectors per track */
unsigned short bios_cyl; /* BIOS/fdisk/LILO number of cyls */
unsigned short cyl; /* "real" number of cyls */
+ unsigned int timing_data; /* for use by tuneproc()'s */
void *hwif; /* actually (ide_hwif_t *) */
struct wait_queue *wqueue; /* used to wait for drive in open() */
struct hd_driveid *id; /* drive model identification info */
@@ -272,7 +273,7 @@ typedef enum { ide_dma_read = 0, ide_dma_write = 1,
ide_dma_abort = 2, ide_dma_check = 3,
ide_dma_status_bad = 4, ide_dma_transferred = 5,
ide_dma_begin = 6, ide_dma_on = 7,
- ide_dma_off = 8 }
+ ide_dma_off = 8, ide_dma_off_quietly = 9 }
ide_dma_action_t;
typedef int (ide_dmaproc_t)(ide_dma_action_t, ide_drive_t *);
@@ -292,7 +293,7 @@ typedef int (ide_dmaproc_t)(ide_dma_action_t, ide_drive_t *);
typedef void (ide_tuneproc_t)(ide_drive_t *, byte);
/*
- * This is used to provide HT6560B & PROMISE interface support.
+ * This is used to provide HT6560B & PDC4030 & TRM290 interface support.
*/
typedef void (ide_selectproc_t) (ide_drive_t *);
@@ -300,10 +301,11 @@ typedef void (ide_selectproc_t) (ide_drive_t *);
* hwif_chipset_t is used to keep track of the specific hardware
* chipset used by each IDE interface, if known.
*/
-typedef enum { ide_unknown, ide_generic, ide_triton,
+typedef enum { ide_unknown, ide_generic, ide_pci,
ide_cmd640, ide_dtc2278, ide_ali14xx,
ide_qd6580, ide_umc8672, ide_ht6560b,
- ide_promise, ide_via }
+ ide_pdc4030, ide_rz1000, ide_trm290,
+ ide_4drives }
hwif_chipset_t;
typedef struct hwif_s {
@@ -313,11 +315,12 @@ typedef struct hwif_s {
ide_drive_t drives[MAX_DRIVES]; /* drive info */
struct gendisk *gd; /* gendisk structure */
ide_tuneproc_t *tuneproc; /* routine to tune PIO mode for drives */
-#if defined(CONFIG_BLK_DEV_HT6560B) || defined(CONFIG_BLK_DEV_PROMISE)
+#if defined(CONFIG_BLK_DEV_HT6560B) || defined(CONFIG_BLK_DEV_PDC4030) || defined(CONFIG_BLK_DEV_TRM290)
ide_selectproc_t *selectproc; /* tweaks hardware to select drive */
#endif
ide_dmaproc_t *dmaproc; /* dma read/write/abort routine */
unsigned long *dmatable; /* dma physical region descriptor table */
+ struct hwif_s *mate; /* other hwif from same PCI chip */
unsigned short dma_base; /* base addr for dma ports (triton) */
int irq; /* our irq number */
byte major; /* our major number */
@@ -328,10 +331,11 @@ typedef struct hwif_s {
unsigned present : 1; /* this interface exists */
unsigned serialized : 1; /* serialized operation with mate hwif */
unsigned sharing_irq: 1; /* 1 = sharing irq with another hwif */
-#ifdef CONFIG_BLK_DEV_PROMISE
- unsigned is_promise2: 1; /* 2nd i/f on promise DC4030 */
-#endif /* CONFIG_BLK_DEV_PROMISE */
+#ifdef CONFIG_BLK_DEV_PDC4030
+ unsigned is_pdc4030_2: 1;/* 2nd i/f on pdc4030 */
+#endif /* CONFIG_BLK_DEV_PDC4030 */
unsigned reset : 1; /* reset after probe */
+ unsigned pci_port : 1; /* for dual-port chips: 0=primary, 1=secondary */
#if (DISK_RECOVERY_TIME > 0)
unsigned long last_time; /* time when previous rq was done */
#endif
@@ -613,23 +617,21 @@ ide_drive_t *ide_scan_devices (byte media, ide_driver_t *driver, int n);
int ide_register_subdriver (ide_drive_t *drive, ide_driver_t *driver, int version);
int ide_unregister_subdriver (ide_drive_t *drive);
-#ifdef CONFIG_BLK_DEV_TRITON
-void ide_init_triton (byte, byte);
-#endif /* CONFIG_BLK_DEV_TRITON */
-
-#ifdef CONFIG_BLK_DEV_OPTI621
-void ide_init_opti621 (byte, byte);
-#endif /* CONFIG_BLK_DEV_OPTI621 */
+#ifdef CONFIG_BLK_DEV_IDEDMA
+int ide_build_dmatable (ide_drive_t *drive);
+int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive);
+void ide_setup_dma (ide_hwif_t *hwif, unsigned short dmabase, unsigned int num_ports);
+#endif
#ifdef CONFIG_BLK_DEV_IDE
int ideprobe_init (void);
#endif /* CONFIG_BLK_DEV_IDE */
-#ifdef CONFIG_BLK_DEV_PROMISE
-#include "promise.h"
-#define IS_PROMISE_DRIVE (HWIF(drive)->chipset == ide_promise)
+#ifdef CONFIG_BLK_DEV_PDC4030
+#include "pdc4030.h"
+#define IS_PDC4030_DRIVE (HWIF(drive)->chipset == ide_pdc4030)
#else
-#define IS_PROMISE_DRIVE (0) /* auto-NULLs out Promise code */
-#endif /* CONFIG_BLK_DEV_PROMISE */
+#define IS_PDC4030_DRIVE (0) /* auto-NULLs out pdc4030 code */
+#endif /* CONFIG_BLK_DEV_PDC4030 */
#endif /* _IDE_H */
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index 07098974d..925423581 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -654,7 +654,6 @@ void ll_rw_swap_file(int rw, kdev_t dev, unsigned int *b, int nb, char *buf)
}
}
}
-
#ifdef CONFIG_BLK_DEV_EZ
extern void ez_init( void );
#endif
@@ -694,9 +693,12 @@ __initfunc(int blk_dev_init(void))
#ifdef CONFIG_BLK_DEV_LOOP
loop_init();
#endif
-#ifdef CONFIG_CDI_INIT
- cdi_init(); /* this MUST precede ide_init */
-#endif CONFIG_CDI_INIT
+#ifdef CONFIG_CDROM /* this must precede all CD-ROM drivers */
+ cdrom_init();
+#endif CONFIG_CDROM
+#ifdef CONFIG_ISP16_CDI
+ isp16_init();
+#endif CONFIG_ISP16_CDI
#ifdef CONFIG_BLK_DEV_IDE
ide_init(); /* this MUST precede hd_init */
#endif
diff --git a/drivers/block/md.c b/drivers/block/md.c
index 2018883ca..039e7919c 100644
--- a/drivers/block/md.c
+++ b/drivers/block/md.c
@@ -987,9 +987,11 @@ int md_thread(void * arg)
cli();
if (!test_bit(THREAD_WAKEUP, &thread->flags)) {
do {
- current->signal = 0;
- interruptible_sleep_on(&thread->wqueue);
- } while (current->signal);
+ spin_lock_irq(&current->sigmask_lock);
+ flush_signals(current);
+ spin_unlock_irq(&current->sigmask_lock);
+ interruptible_sleep_on(&thread->wqueue);
+ } while (signal_pending(current));
}
}
}
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 54920a912..9917963a9 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -70,7 +70,7 @@ static int nbd_open(struct inode *inode, struct file *file)
static
int nbd_xmit(int send, struct socket *sock, char *buf, int size)
{
- unsigned long oldfs;
+ mm_segment_t oldfs;
int result;
struct msghdr msg;
struct iovec iov;
@@ -78,7 +78,7 @@ int nbd_xmit(int send, struct socket *sock, char *buf, int size)
oldfs = get_fs();
set_fs(get_ds());
do {
- int save;
+ sigset_t oldset;
iov.iov_base = buf;
iov.iov_len = size;
@@ -91,13 +91,22 @@ int nbd_xmit(int send, struct socket *sock, char *buf, int size)
msg.msg_namelen = 0;
msg.msg_flags = 0;
- save = current->blocked;
- current->blocked = ~0UL;
+ spin_lock_irq(&current->sigmask_lock);
+ oldset = current->blocked;
+ sigfillset(&current->blocked);
+ recalc_sigpending(current);
+ spin_unlock_irq(&current->sigmask_lock);
+
if (send)
result = sock_sendmsg(sock, &msg, size);
else
result = sock_recvmsg(sock, &msg, size, 0);
- current->blocked = save;
+
+ spin_lock_irq(&current->sigmask_lock);
+ current->blocked = oldset;
+ recalc_sigpending(current);
+ spin_unlock_irq(&current->sigmask_lock);
+
if (result <= 0) {
#ifdef PARANOIA
printk(KERN_ERR "NBD: %s - sock=%d at buf=%d, size=%d returned %d.\n",
diff --git a/drivers/block/opti621.c b/drivers/block/opti621.c
index 2e7bd733c..0e0b23758 100644
--- a/drivers/block/opti621.c
+++ b/drivers/block/opti621.c
@@ -1,7 +1,7 @@
/*
- * linux/drivers/block/opti621.c Version 0.1 Oct 26, 1996
+ * linux/drivers/block/opti621.c Version 0.3 Nov 29, 1997
*
- * Copyright (C) 1996 Linus Torvalds & author (see below)
+ * Copyright (C) 1996-1998 Linus Torvalds & author (see below)
*/
/*
@@ -33,8 +33,8 @@
* PIO 3 and slave PIO 0, driver have to set some timings of
* master for PIO 0. Second problem is that opti621_tune_drive
* got only one drive to set, but have to set both drives.
- * This is solved in opti621_compute_pios. If you don't set
- * the second drive, opti621_compute_pios use ide_get_best_pio_mode
+ * This is solved in compute_pios. If you don't set
+ * the second drive, compute_pios use ide_get_best_pio_mode
* for autoselect mode (you can change it to PIO 0, if you want).
* If you then set the second drive to another PIO, the old value
* (automatically selected) will be overrided by yours.
@@ -48,7 +48,7 @@
* settings of jumpers on the card and I have to boot Linux with
* Loadlin except LILO, cause I have to run the setupvic.exe program
* already or I get disk errors (my test: rpm -Vf
- * /usr/X11R6/bin/XF86_SVGA - or any big file).
+ * /usr/X11R6/bin/XF86_SVGA - or any big file).
* Some numbers from hdparm -t /dev/hda:
* Timing buffer-cache reads: 32 MB in 3.02 seconds =10.60 MB/sec
* Timing buffered disk reads: 16 MB in 5.52 seconds = 2.90 MB/sec
@@ -84,7 +84,7 @@
* address: 25 ns, data: 25 ns, recovery: 50 ns;
* on 20MHz PCI bus (pulse 50 ns):
* address: 50 ns, data: 50 ns, recovery: 100 ns.
- */
+ */
/* #define READ_PREFETCH 0 */
/* Uncommnent for disable read prefetch.
@@ -103,58 +103,35 @@
#define MISC_REG 6 /* index of Miscellaneous register */
#define CNTRL_REG 3 /* index of Control register */
int reg_base;
-int opti621_primary_base, opti621_secondary_base;
#define PIO_NOT_EXIST 254
#define PIO_DONT_KNOW 255
-int opti621_drive_pio_modes[4];
+
/* there are stored pio numbers from other calls of opti621_tune_drive */
-void opti621_compute_pios(ide_hwif_t *drv, int second_contr, int slave_drive, byte pio)
-/* Store values into opti621_drive_pio_modes:
+static void compute_pios(ide_drive_t *drive, byte pio)
+/* Store values into drive->timing_data
* second_contr - 0 for primary controller, 1 for secondary
* slave_drive - 0 -> pio is for master, 1 -> pio is for slave
- * pio - PIO mode for selected drive (for other we don't know)
- */
+ * pio - PIO mode for selected drive (for other we don't know)
+ */
{
- ide_drive_t *p1, *p2, *drive;
- int i;
-
- i = 2*second_contr;
- p1 = &drv->drives[0];
- p2 = &drv->drives[1];
- drive = &drv->drives[slave_drive];
- pio = ide_get_best_pio_mode(drive, pio, OPTI621_MAX_PIO, NULL);
- opti621_drive_pio_modes[i+slave_drive]=pio;
+ int d;
+ ide_hwif_t *hwif = HWIF(drive);
- if (p1->present) {
- if (opti621_drive_pio_modes[i]==PIO_DONT_KNOW)
- opti621_drive_pio_modes[i]=ide_get_best_pio_mode(p1,
- 255, OPTI621_MAX_PIO, NULL);
- /* we don't know the selected PIO mode, so we have to autoselect */
- } else
- opti621_drive_pio_modes[i]=PIO_NOT_EXIST;
- if (p2->present) {
- if (opti621_drive_pio_modes[i+1]==PIO_DONT_KNOW)
- opti621_drive_pio_modes[i+1]=ide_get_best_pio_mode(p2,
- 255, OPTI621_MAX_PIO, NULL);
- /* we don't know the selected PIO mode, so we have to autoselect */
- } else
- opti621_drive_pio_modes[i+1]=PIO_NOT_EXIST;
- /* in opti621_drive_pio_modes[i] and [i+1] are valid PIO modes (or PIO_NOT_EXIST,
- if drive is not connected), we can continue */
+ drive->timing_data = ide_get_best_pio_mode(drive, pio, OPTI621_MAX_PIO, NULL);
+ for (d = 0; d < 2; ++d) {
+ drive = &hwif->drives[d];
+ if (drive->present) {
+ if (drive->timing_data == PIO_DONT_KNOW)
+ drive->timing_data = ide_get_best_pio_mode(drive, 255, OPTI621_MAX_PIO, NULL);
#ifdef OPTI621_DEBUG
- printk("%s: (master): ", p1->name);
- if (p1->present)
- printk("PIO mode %d\n", opti621_drive_pio_modes[i]);
- else
- printk("not present\n");
- printk("%s: (slave): ", p2->name);
- if (p2->present)
- printk("PIO mode %d\n", opti621_drive_pio_modes[i+1]);
- else
- printk("not present\n");
+ printk("%s: Selected PIO mode %d\n", drive->name, drive->timing_data);
#endif
+ } else {
+ drive->timing_data = PIO_NOT_EXIST;
+ }
+ }
}
int cmpt_clk(int time, int bus_speed)
@@ -169,7 +146,7 @@ int cmpt_clk(int time, int bus_speed)
return ((time*bus_speed+999)/1000);
}
-void write_reg(byte value, int reg)
+static void write_reg(byte value, int reg)
/* Write value to register reg, base of register
* is at reg_base (0x1f0 primary, 0x170 secondary,
* if not changed by PCI configuration).
@@ -180,12 +157,12 @@ void write_reg(byte value, int reg)
inw(reg_base+1);
outb(3, reg_base+2);
outb(value, reg_base+reg);
- outb(0x83, reg_base+2);
+ outb(0x83, reg_base+2);
}
-byte read_reg(int reg)
+static byte read_reg(int reg)
/* Read value from register reg, base of register
- * is at reg_base (0x1f0 primary, 0x170 secondary,
+ * is at reg_base (0x1f0 primary, 0x170 secondary,
* if not changed by PCI configuration).
* This is from setupvic.exe program.
*/
@@ -195,7 +172,7 @@ byte read_reg(int reg)
inw(reg_base+1);
outb(3, reg_base+2);
ret=inb(reg_base+reg);
- outb(0x83, reg_base+2);
+ outb(0x83, reg_base+2);
return ret;
}
@@ -205,9 +182,9 @@ typedef struct pio_clocks_s {
int recovery_time; /* Recovery time (clocks) */
} pio_clocks_t;
-void compute_clocks(int pio, pio_clocks_t *clks)
+static void compute_clocks(int pio, pio_clocks_t *clks)
{
- if (pio!=PIO_NOT_EXIST) {
+ if (pio != PIO_NOT_EXIST) {
int adr_setup, data_pls, bus_speed;
bus_speed = ide_system_bus_speed();
adr_setup = ide_pio_timings[pio].setup_time;
@@ -230,108 +207,78 @@ void compute_clocks(int pio, pio_clocks_t *clks)
}
}
-static void opti621_tune_drive (ide_drive_t *drive, byte pio)
/* Main tune procedure, hooked by tuneproc. */
+static void opti621_tune_drive (ide_drive_t *drive, byte pio)
{
- /* primary and secondary drives share some (but not same) registers,
- so we have to program both drives */
+ /* primary and secondary drives share some registers,
+ * so we have to program both drives
+ */
unsigned long flags;
byte pio1, pio2;
- int second_contr, slave_drive;
pio_clocks_t first, second;
int ax, drdy;
byte cycle1, cycle2, misc;
-
- second_contr=HWIF(drive)->index;
- if ((second_contr!=0) && (second_contr!=1))
- return; /* invalid controller number */
- if (((second_contr==0) && (opti621_primary_base==0)) ||
- ((second_contr==1) && (opti621_secondary_base==0)))
- return; /* controller is unaccessible/not exist */
- slave_drive = drive->select.b.unit;
- /* set opti621_drive_pio_modes[] */
- opti621_compute_pios(HWIF(drive), second_contr, slave_drive, pio);
-
- reg_base = second_contr ? opti621_primary_base : opti621_secondary_base;
+ ide_hwif_t *hwif = HWIF(drive);
+
+ /* set drive->timing_data for both drives */
+ compute_pios(drive, pio);
+ pio1 = hwif->drives[0].timing_data;
+ pio2 = hwif->drives[1].timing_data;
- pio1 = opti621_drive_pio_modes[second_contr*2];
- pio2 = opti621_drive_pio_modes[second_contr*2+1];
-
compute_clocks(pio1, &first);
compute_clocks(pio2, &second);
-
- ax = (first.address_time<second.address_time) ?
- (second.address_time) : (first.address_time); /* in ax is max(a1,a2) */
+
+ /* ax = max(a1,a2) */
+ ax = (first.address_time < second.address_time) ? second.address_time : first.address_time;
+
drdy = 2; /* DRDY is default 2 (by OPTi Databook) */
- cycle1 = ((first.data_time-1)<<4) | (first.recovery_time-2);
+ cycle1 = ((first.data_time-1)<<4) | (first.recovery_time-2);
cycle2 = ((second.data_time-1)<<4) | (second.recovery_time-2);
misc = READ_PREFETCH | ((ax-1)<<4) | ((drdy-2)<<1);
-
+
#ifdef OPTI621_DEBUG
printk("%s: master: address: %d, data: %d, recovery: %d, drdy: %d [clk]\n",
- HWIF(drive)->name, ax, first.data_time, first.recovery_time, drdy);
+ hwif->name, ax, first.data_time, first.recovery_time, drdy);
printk("%s: slave: address: %d, data: %d, recovery: %d, drdy: %d [clk]\n",
- HWIF(drive)->name, ax, second.data_time, second.recovery_time, drdy);
+ hwif->name, ax, second.data_time, second.recovery_time, drdy);
#endif
save_flags(flags);
cli();
-
+
+ reg_base = hwif->io_ports[IDE_DATA_OFFSET];
outb(0xc0, reg_base+CNTRL_REG); /* allow Register-B */
outb(0xff, reg_base+5); /* hmm, setupvic.exe does this ;-) */
inb(reg_base+CNTRL_REG); /* if reads 0xff, adapter not exist? */
read_reg(CNTRL_REG); /* if reads 0xc0, no interface exist? */
read_reg(5); /* read version, probably 0 */
-
- /* programming primary drive - 0 or 2 */
- write_reg(0, MISC_REG); /* select Index-0 for Register-A */
+
+ /* program primary drive */
+ write_reg(0, MISC_REG); /* select Index-0 for Register-A */
write_reg(cycle1, READ_REG); /* set read cycle timings */
write_reg(cycle1, WRITE_REG); /* set write cycle timings */
- /* programming secondary drive - 1 or 3 */
- write_reg(1, MISC_REG); /* select Index-1 for Register-B */
- write_reg(cycle2, READ_REG); /* set read cycle timings */
- write_reg(cycle2, WRITE_REG); /* set write cycle timings */
-
- write_reg(0x85, CNTRL_REG); /* use Register-A for drive 0 (or 2) and
- Register-B for drive 1 (or 3) */
-
- write_reg(misc, MISC_REG); /* set address setup, DRDY timings
- and read prefetch for both drives */
-
+ /* program secondary drive */
+ write_reg(1, MISC_REG); /* select Index-1 for Register-B */
+ write_reg(cycle2, READ_REG); /* set read cycle timings */
+ write_reg(cycle2, WRITE_REG); /* set write cycle timings */
+
+ write_reg(0x85, CNTRL_REG); /* use Register-A for drive 0 */
+ /* use Register-B for drive 1 */
+
+ write_reg(misc, MISC_REG); /* set address setup, DRDY timings, */
+ /* and read prefetch for both drives */
+
restore_flags(flags);
}
-void ide_init_opti621 (byte bus, byte fn)
-/* Init controller. Called on kernel boot. */
+/*
+ * ide_init_opti621() is Called from idedma.c once for each hwif found at boot.
+ */
+void ide_init_opti621 (byte bus, byte fn, ide_hwif_t *hwif)
{
- int rc, i;
- unsigned char sreg;
- unsigned short reg;
- unsigned int dreg;
- unsigned char revision;
- for (i=0; i<4; i++)
- opti621_drive_pio_modes[i] = PIO_DONT_KNOW;
- printk("ide: OPTi 82C621 on PCI bus %d function %d\n", bus, fn);
- if ((rc = pcibios_read_config_byte (bus, fn, 0x08, &sreg)))
- goto quit;
- revision = sreg;
- if ((rc = pcibios_read_config_dword (bus, fn, 0x10, &dreg)))
- goto quit;
- opti621_primary_base = ((dreg==0) || (dreg>0xffff)) ? 0 : dreg-1;
- if ((rc = pcibios_read_config_dword (bus, fn, 0x18, &dreg)))
- goto quit;
- opti621_secondary_base = ((dreg==0) || (dreg>0xffff)) ? 0 : dreg-1;
- printk("ide: revision %d, primary: 0x%04x, secondary: 0x%04x\n",
- revision, opti621_primary_base, opti621_secondary_base);
- if ((rc = pcibios_read_config_word (bus, fn, PCI_COMMAND, &reg)))
- goto quit;
- if (!(reg & 1)) {
- printk("ide: ports are not enabled (BIOS)\n");
- } else {
- ide_hwifs[0].tuneproc = &opti621_tune_drive;
- ide_hwifs[1].tuneproc = &opti621_tune_drive;
- }
- quit: if (rc) printk("ide: pcibios access failed - %s\n", pcibios_strerror(rc));
+ hwif->drives[0].timing_data = PIO_DONT_KNOW;
+ hwif->drives[1].timing_data = PIO_DONT_KNOW;
+ hwif->tuneproc = &opti621_tune_drive;
}
diff --git a/drivers/block/promise.c b/drivers/block/promise.c
index f3a8d5529..e69de29bb 100644
--- a/drivers/block/promise.c
+++ b/drivers/block/promise.c
@@ -1,362 +0,0 @@
-/* -*- linux-c -*-
- * linux/drivers/block/promise.c Version 0.07 Mar 26, 1996
- *
- * Copyright (C) 1995-1996 Linus Torvalds & authors (see below)
- */
-
-/*
- * Principal Author/Maintainer: peterd@pnd-pc.demon.co.uk
- *
- * This file provides support for the second port and cache of Promise
- * IDE interfaces, e.g. DC4030, DC5030.
- *
- * Thanks are due to Mark Lord for advice and patiently answering stupid
- * questions, and all those mugs^H^H^H^Hbrave souls who've tested this.
- *
- * Version 0.01 Initial version, #include'd in ide.c rather than
- * compiled separately.
- * Reads use Promise commands, writes as before. Drives
- * on second channel are read-only.
- * Version 0.02 Writes working on second channel, reads on both
- * channels. Writes fail under high load. Suspect
- * transfers of >127 sectors don't work.
- * Version 0.03 Brought into line with ide.c version 5.27.
- * Other minor changes.
- * Version 0.04 Updated for ide.c version 5.30
- * Changed initialization strategy
- * Version 0.05 Kernel integration. -ml
- * Version 0.06 Ooops. Add hwgroup to direct call of ide_intr() -ml
- * Version 0.07 Added support for DC4030 variants
- * Secondary interface autodetection
- */
-
-/*
- * Once you've compiled it in, you'll have to also enable the interface
- * setup routine from the kernel command line, as in
- *
- * 'linux ide0=dc4030'
- *
- * As before, it seems that somewhere around 3Megs when writing, bad things
- * start to happen [timeouts/retries -ml]. If anyone can give me more feedback,
- * I'd really appreciate it. [email: peterd@pnd-pc.demon.co.uk]
- *
- */
-
-
-#undef REALLY_SLOW_IO /* most systems can safely undef this */
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
-#include <linux/ioport.h>
-#include <linux/blkdev.h>
-#include <linux/hdreg.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include "ide.h"
-#include "promise.h"
-
-/* This is needed as the controller may not interrupt if the required data is
-available in the cache. We have to simulate an interrupt. Ugh! */
-
-extern void ide_intr(int, void *dev_id, struct pt_regs*);
-
-/*
- * promise_selectproc() is invoked by ide.c
- * in preparation for access to the specified drive.
- */
-static void promise_selectproc (ide_drive_t *drive)
-{
- unsigned int number;
-
- OUT_BYTE(drive->select.all,IDE_SELECT_REG);
- udelay(1); /* paranoia */
- number = ((HWIF(drive)->is_promise2)<<1) + drive->select.b.unit;
- OUT_BYTE(number,IDE_FEATURE_REG);
-}
-
-/*
- * promise_cmd handles the set of vendor specific commands that are initiated
- * by command F0. They all have the same success/failure notification.
- */
-int promise_cmd(ide_drive_t *drive, byte cmd)
-{
- unsigned long timeout, timer;
- byte status_val;
-
- promise_selectproc(drive); /* redundant? */
- OUT_BYTE(0xF3,IDE_SECTOR_REG);
- OUT_BYTE(cmd,IDE_SELECT_REG);
- OUT_BYTE(PROMISE_EXTENDED_COMMAND,IDE_COMMAND_REG);
- timeout = HZ * 10;
- timeout += jiffies;
- do {
- if(jiffies > timeout) {
- return 2; /* device timed out */
- }
- /* This is out of delay_10ms() */
- /* Delays at least 10ms to give interface a chance */
- timer = jiffies + (HZ + 99)/100 + 1;
- while (timer > jiffies);
- status_val = IN_BYTE(IDE_SECTOR_REG);
- } while (status_val != 0x50 && status_val != 0x70);
-
- if(status_val == 0x50)
- return 0; /* device returned success */
- else
- return 1; /* device returned failure */
-}
-
-ide_hwif_t *hwif_required = NULL;
-
-void setup_dc4030 (ide_hwif_t *hwif)
-{
- hwif_required = hwif;
-}
-
-/*
-init_dc4030: Test for presence of a Promise caching controller card.
-Returns: 0 if no Promise card present at this io_base
- 1 if Promise card found
-*/
-int init_dc4030 (void)
-{
- ide_hwif_t *hwif = hwif_required;
- ide_drive_t *drive;
- ide_hwif_t *second_hwif;
- struct dc_ident ident;
- int i;
-
- if (!hwif) return 0;
-
- drive = &hwif->drives[0];
- second_hwif = &ide_hwifs[hwif->index+1];
- if(hwif->is_promise2) /* we've already been found ! */
- return 1;
-
- if(IN_BYTE(IDE_NSECTOR_REG) == 0xFF || IN_BYTE(IDE_SECTOR_REG) == 0xFF)
- {
- return 0;
- }
- OUT_BYTE(0x08,IDE_CONTROL_REG);
- if(promise_cmd(drive,PROMISE_GET_CONFIG)) {
- return 0;
- }
- if(ide_wait_stat(drive,DATA_READY,BAD_W_STAT,WAIT_DRQ)) {
- printk("%s: Failed Promise read config!\n",hwif->name);
- return 0;
- }
- ide_input_data(drive,&ident,SECTOR_WORDS);
- if(ident.id[1] != 'P' || ident.id[0] != 'T') {
- return 0;
- }
- printk("%s: Promise caching controller, ",hwif->name);
- switch(ident.type) {
- case 0x43: printk("DC4030VL-2, "); break;
- case 0x41: printk("DC4030VL-1, "); break;
- case 0x40: printk("DC4030VL, "); break;
- default: printk("unknown - type 0x%02x - please report!\n"
- ,ident.type);
- return 0;
- }
- printk("%dKB cache, ",(int)ident.cache_mem);
- switch(ident.irq) {
- case 0x00: hwif->irq = 14; break;
- case 0x01: hwif->irq = 12; break;
- default: hwif->irq = 15; break;
- }
- printk("on IRQ %d\n",hwif->irq);
- hwif->chipset = second_hwif->chipset = ide_promise;
- hwif->selectproc = second_hwif->selectproc = &promise_selectproc;
-/* Shift the remaining interfaces down by one */
- for (i=MAX_HWIFS-1 ; i > hwif->index+1 ; i--) {
- ide_hwif_t *h = &ide_hwifs[i];
-
- printk("Shifting i/f %d values to i/f %d\n",i-1,i);
- ide_init_hwif_ports(h->io_ports, (h-1)->io_ports[IDE_DATA_OFFSET], NULL);
- h->io_ports[IDE_CONTROL_OFFSET] = (h-1)->io_ports[IDE_CONTROL_OFFSET];
- h->noprobe = (h-1)->noprobe;
- }
- second_hwif->is_promise2 = 1;
- ide_init_hwif_ports(second_hwif->io_ports, hwif->io_ports[IDE_DATA_OFFSET], NULL);
- second_hwif->io_ports[IDE_CONTROL_OFFSET] = hwif->io_ports[IDE_CONTROL_OFFSET];
- second_hwif->irq = hwif->irq;
- for (i=0; i<2 ; i++) {
- hwif->drives[i].io_32bit = 3;
- second_hwif->drives[i].io_32bit = 3;
- if(!ident.current_tm[i+2].cyl) second_hwif->drives[i].noprobe=1;
- }
- return 1;
-}
-
-/*
- * promise_read_intr() is the handler for disk read/multread interrupts
- */
-static void promise_read_intr (ide_drive_t *drive)
-{
- byte stat;
- int i;
- unsigned int sectors_left, sectors_avail, nsect;
- struct request *rq;
-
- if (!OK_STAT(stat=GET_STAT(),DATA_READY,BAD_R_STAT)) {
- ide_error(drive, "promise_read_intr", stat);
- return;
- }
-
-read_again:
- do {
- sectors_left = IN_BYTE(IDE_NSECTOR_REG);
- IN_BYTE(IDE_SECTOR_REG);
- } while (IN_BYTE(IDE_NSECTOR_REG) != sectors_left);
- rq = HWGROUP(drive)->rq;
- sectors_avail = rq->nr_sectors - sectors_left;
-
-read_next:
- rq = HWGROUP(drive)->rq;
- if ((nsect = rq->current_nr_sectors) > sectors_avail)
- nsect = sectors_avail;
- sectors_avail -= nsect;
- ide_input_data(drive, rq->buffer, nsect * SECTOR_WORDS);
-#ifdef DEBUG
- printk("%s: promise_read: sectors(%ld-%ld), buffer=0x%08lx, "
- "remaining=%ld\n", drive->name, rq->sector, rq->sector+nsect-1,
- (unsigned long) rq->buffer+(nsect<<9), rq->nr_sectors-nsect);
-#endif
- rq->sector += nsect;
- rq->buffer += nsect<<9;
- rq->errors = 0;
- i = (rq->nr_sectors -= nsect);
- if ((rq->current_nr_sectors -= nsect) <= 0)
- ide_end_request(1, HWGROUP(drive));
- if (i > 0) {
- if (sectors_avail)
- goto read_next;
- stat = GET_STAT();
- if(stat & DRQ_STAT)
- goto read_again;
- if(stat & BUSY_STAT) {
- ide_set_handler (drive, &promise_read_intr, WAIT_CMD);
- return;
- }
- printk("Ah! promise read intr: sectors left !DRQ !BUSY\n");
- ide_error(drive, "promise read intr", stat);
- }
-}
-
-/*
- * promise_write_pollfunc() is the handler for disk write completion polling.
- */
-static void promise_write_pollfunc (ide_drive_t *drive)
-{
- int i;
- ide_hwgroup_t *hwgroup = HWGROUP(drive);
- struct request *rq;
-
- if (IN_BYTE(IDE_NSECTOR_REG) != 0) {
- if (jiffies < hwgroup->poll_timeout) {
- ide_set_handler (drive, &promise_write_pollfunc, 1);
- return; /* continue polling... */
- }
- printk("%s: write timed-out!\n",drive->name);
- ide_error (drive, "write timeout", GET_STAT());
- return;
- }
-
- ide_multwrite(drive, 4);
- rq = hwgroup->rq;
- for (i = rq->nr_sectors; i > 0;) {
- i -= rq->current_nr_sectors;
- ide_end_request(1, hwgroup);
- }
- return;
-}
-
-/*
- * promise_write() transfers a block of one or more sectors of data to a
- * drive as part of a disk write operation. All but 4 sectors are transfered
- * in the first attempt, then the interface is polled (nicely!) for completion
- * before the final 4 sectors are transfered. Don't ask me why, but this is
- * how it's done in the drivers for other O/Ses. There is no interrupt
- * generated on writes, which is why we have to do it like this.
- */
-static void promise_write (ide_drive_t *drive)
-{
- ide_hwgroup_t *hwgroup = HWGROUP(drive);
- struct request *rq = &hwgroup->wrq;
- int i;
-
- if (rq->nr_sectors > 4) {
- ide_multwrite(drive, rq->nr_sectors - 4);
- hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
- ide_set_handler (drive, &promise_write_pollfunc, 1);
- return;
- } else {
- ide_multwrite(drive, rq->nr_sectors);
- rq = hwgroup->rq;
- for (i = rq->nr_sectors; i > 0;) {
- i -= rq->current_nr_sectors;
- ide_end_request(1, hwgroup);
- }
- }
-}
-
-/*
- * do_promise_io() is called from do_rw_disk, having had the block number
- * already set up. It issues a READ or WRITE command to the Promise
- * controller, assuming LBA has been used to set up the block number.
- */
-void do_promise_io (ide_drive_t *drive, struct request *rq)
-{
- unsigned long timeout;
- byte stat;
-
- if (rq->cmd == READ) {
- ide_set_handler(drive, &promise_read_intr, WAIT_CMD);
- OUT_BYTE(PROMISE_READ, IDE_COMMAND_REG);
-/* The card's behaviour is odd at this point. If the data is
- available, DRQ will be true, and no interrupt will be
- generated by the card. If this is the case, we need to simulate
- an interrupt. Ugh! Otherwise, if an interrupt will occur, bit0
- of the SELECT register will be high, so we can just return and
- be interrupted.*/
- timeout = jiffies + HZ/20; /* 50ms wait */
- do {
- stat=GET_STAT();
- if(stat & DRQ_STAT) {
-/* unsigned long flags;
- save_flags(flags);
- cli();
- disable_irq(HWIF(drive)->irq);
-*/
- ide_intr(HWIF(drive)->irq,HWGROUP(drive),NULL);
-/* enable_irq(HWIF(drive)->irq);
- restore_flags(flags);
-*/
- return;
- }
- if(IN_BYTE(IDE_SELECT_REG) & 0x01)
- return;
- udelay(1);
- } while (jiffies < timeout);
- printk("%s: reading: No DRQ and not waiting - Odd!\n",
- drive->name);
- return;
- }
- if (rq->cmd == WRITE) {
- OUT_BYTE(PROMISE_WRITE, IDE_COMMAND_REG);
- if (ide_wait_stat(drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) {
- printk("%s: no DRQ after issuing PROMISE_WRITE\n", drive->name);
- return;
- }
- if (!drive->unmask)
- cli();
- HWGROUP(drive)->wrq = *rq; /* scratchpad */
- promise_write(drive);
- return;
- }
- printk("%s: bad command: %d\n", drive->name, rq->cmd);
- ide_end_request(0, HWGROUP(drive));
-}
diff --git a/drivers/block/promise.h b/drivers/block/promise.h
index e82541d2a..e69de29bb 100644
--- a/drivers/block/promise.h
+++ b/drivers/block/promise.h
@@ -1,52 +0,0 @@
-/*
- * linux/drivers/block/promise.h
- *
- * Copyright (C) 1995-6 Linus Torvalds & authors
- */
-
-/*
- * Principal author: Peter Denison <peterd@pnd-pc.demon.co.uk>
- */
-
-#ifndef IDE_PROMISE_H
-#define IDE_PROMISE_H
-
-#define PROMISE_EXTENDED_COMMAND 0xF0
-#define PROMISE_READ 0xF2
-#define PROMISE_WRITE 0xF3
-/* Extended commands - main command code = 0xf0 */
-#define PROMISE_GET_CONFIG 0x10
-#define PROMISE_IDENTIFY 0x20
-
-struct translation_mode {
- u16 cyl;
- u8 head;
- u8 sect;
-};
-
-struct dc_ident {
- u8 type;
- u8 unknown1;
- u8 hw_revision;
- u8 firmware_major;
- u8 firmware_minor;
- u8 bios_address;
- u8 irq;
- u8 unknown2;
- u16 cache_mem;
- u16 unknown3;
- u8 id[2];
- u16 info;
- struct translation_mode current_tm[4];
- u8 pad[SECTOR_WORDS*4 - 32];
-};
-
-/*
- * Routines exported to ide.c:
- */
-void do_promise_io (ide_drive_t *, struct request *);
-int promise_cmd(ide_drive_t *, byte);
-void setup_dc4030 (ide_hwif_t *);
-int init_dc4030 (void);
-
-#endif IDE_PROMISE_H
diff --git a/drivers/block/qd6580.c b/drivers/block/qd6580.c
index 78c73cf39..296aef3a7 100644
--- a/drivers/block/qd6580.c
+++ b/drivers/block/qd6580.c
@@ -63,4 +63,6 @@ void init_qd6580 (void)
ide_hwifs[0].chipset = ide_qd6580;
ide_hwifs[1].chipset = ide_qd6580;
ide_hwifs[0].tuneproc = &tune_qd6580;
+ ide_hwifs[0].mate = &ide_hwifs[1];
+ ide_hwifs[1].mate = &ide_hwifs[0];
}
diff --git a/drivers/block/rd.c b/drivers/block/rd.c
index b57fc797c..de17158a7 100644
--- a/drivers/block/rd.c
+++ b/drivers/block/rd.c
@@ -446,7 +446,7 @@ __initfunc(static void rd_load_image(kdev_t device,int offset))
struct inode inode, out_inode;
struct file infile, outfile;
struct dentry in_dentry, out_dentry;
- unsigned long fs;
+ mm_segment_t fs;
kdev_t ram_device;
int nblocks, i;
char *buf;
diff --git a/drivers/block/rz1000.c b/drivers/block/rz1000.c
index 41b26f277..b7270c559 100644
--- a/drivers/block/rz1000.c
+++ b/drivers/block/rz1000.c
@@ -26,34 +26,42 @@
#include <linux/pci.h>
#include "ide.h"
-static void ide_pci_access_error (int rc)
+static void init_rz1000 (byte bus, byte fn, const char *name)
{
- printk("ide: pcibios access failed - %s\n", pcibios_strerror(rc));
+ unsigned short reg, h;
+
+ printk("%s: buggy IDE controller: ", name);
+ if (!pcibios_read_config_word (bus, fn, PCI_COMMAND, &reg) && !(reg & 1)) {
+ printk("disabled (BIOS)\n");
+ return;
+ }
+ if (!pcibios_read_config_word (bus, fn, 0x40, &reg)
+ && !pcibios_write_config_word(bus, fn, 0x40, reg & 0xdfff))
+ {
+ printk("disabled read-ahead\n");
+ } else {
+ printk("\n");
+ for (h = 0; h < MAX_HWIFS; ++h) {
+ ide_hwif_t *hwif = &ide_hwifs[h];
+ if ((hwif->io_ports[IDE_DATA_OFFSET] == 0x1f0 || hwif->io_ports[IDE_DATA_OFFSET] == 0x170)
+ && (hwif->chipset == ide_unknown || hwif->chipset == ide_generic))
+ {
+ hwif->chipset = ide_rz1000;
+ hwif->serialized = 1;
+ hwif->drives[0].no_unmask = 1;
+ hwif->drives[1].no_unmask = 1;
+ printk(" %s: serialized, disabled unmasking\n", hwif->name);
+ }
+ }
+ }
}
-void init_rz1000 (byte bus, byte fn)
+void ide_probe_for_rz100x (void)
{
- int rc;
- unsigned short reg;
+ byte index, bus, fn;
- printk("ide0: buggy RZ1000 interface: ");
- if ((rc = pcibios_read_config_word (bus, fn, PCI_COMMAND, &reg))) {
- ide_pci_access_error (rc);
- } else if (!(reg & 1)) {
- printk("not enabled\n");
- } else {
- if ((rc = pcibios_read_config_word(bus, fn, 0x40, &reg))
- || (rc = pcibios_write_config_word(bus, fn, 0x40, reg & 0xdfff)))
- {
- ide_hwifs[0].drives[0].no_unmask = 1;
- ide_hwifs[0].drives[1].no_unmask = 1;
- ide_hwifs[1].drives[0].no_unmask = 1;
- ide_hwifs[1].drives[1].no_unmask = 1;
- ide_hwifs[0].serialized = 1;
- ide_hwifs[1].serialized = 1;
- ide_pci_access_error (rc);
- printk("serialized, disabled unmasking\n");
- } else
- printk("disabled read-ahead\n");
- }
+ for (index = 0; !pcibios_find_device (PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000, index, &bus, &fn); ++index)
+ init_rz1000 (bus, fn, "RZ1000");
+ for (index = 0; !pcibios_find_device (PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1001, index, &bus, &fn); ++index)
+ init_rz1000 (bus, fn, "RZ1001");
}
diff --git a/drivers/block/triton.c b/drivers/block/triton.c
index 006051af6..e69de29bb 100644
--- a/drivers/block/triton.c
+++ b/drivers/block/triton.c
@@ -1,631 +0,0 @@
-/*
- * linux/drivers/block/triton.c Version 2.10 April 22, 1997
- *
- * Copyright (c) 1995-1997 Mark Lord
- * May be copied or modified under the terms of the GNU General Public License
- */
-
-/*
- * This module provides support for the bus-master IDE DMA function
- * of the Intel PCI Triton chipset families, which use the PIIX (i82371FB,
- * for the 430 FX chipset), the PIIX3 (i82371SB for the 430 HX/VX and
- * 440 chipsets), and the PIIX4 (i82371AB for the 430 TX chipset).
- *
- * "PIIX" stands for "PCI ISA IDE Xcellerator".
- *
- * Pretty much the same code could work for other IDE PCI bus-mastering chipsets.
- * Look for DMA support for this someday in the not too distant future.
- *
- * DMA is supported for all IDE devices (disk drives, cdroms, tapes, floppies).
- *
- * Up to four drives may be enabled for DMA, and the PIIX* chips
- * will arbitrate the PCI bus among them. Note that the PIIX/PIIX3
- * provides a single "line buffer" for the BM IDE function, so performance of
- * multiple (two) drives doing DMA simultaneously will suffer somewhat,
- * as they contest for that resource bottleneck. This is handled transparently
- * inside the PIIX/PIIX3. The PIIX4 does not have this problem.
- *
- * By default, DMA support is prepared for use, but is currently enabled only
- * for drives which support DMA mode2 (multi/single word), or which are
- * recognized as "good" (see table below). Drives with only mode0 or mode1
- * (multi/single word) DMA should also work with this chipset/driver (eg. MC2112A)
- * but are not enabled by default. Use "hdparm -i" to view modes supported
- * by a given drive.
- *
- * The hdparm-2.4 (or later) utility can be used for manually enabling/disabling
- * DMA support, but must be (re-)compiled against this kernel version or later.
- *
- * To enable DMA, use "hdparm -d1 /dev/hd?" on a per-drive basis after booting.
- * If problems arise, ide.c will disable DMA operation after a few retries.
- * This error recovery mechanism works and has been extremely well exercised.
- *
- * IDE drives, depending on their vintage, may support several different modes
- * of DMA operation. The boot-time modes are indicated with a "*" in
- * the "hdparm -i" listing, and can be changed with *knowledgeable* use of
- * the "hdparm -X" feature. There is seldom a need to do this, as drives
- * normally power-up with their "best" PIO/DMA modes enabled.
- *
- * Testing has been done with a rather extensive number of drives,
- * with Quantum & Western Digital models generally outperforming the pack,
- * and Fujitsu & Conner (and some Seagate which are really Conner) drives
- * showing more lackluster throughput.
- *
- * Keep an eye on /var/adm/messages for "DMA disabled" messages.
- *
- * Some people have reported trouble with Intel Zappa motherboards.
- * This can be fixed by upgrading the AMI BIOS to version 1.00.04.BS0,
- * available from ftp://ftp.intel.com/pub/bios/10004bs0.exe
- * (thanks to Glen Morrell <glen@spin.Stanford.edu> for researching this).
- *
- * Thanks to "Christopher J. Reimer" <reimer@doe.carleton.ca> for fixing the
- * problem with some (all?) ACER motherboards/BIOSs.
- *
- * Thanks to "Benoit Poulot-Cazajous" <poulot@chorus.fr> for testing
- * "TX" chipset compatibility and for providing patches for the "TX" chipset.
- *
- * And, yes, Intel Zappa boards really *do* use both PIIX IDE ports.
- */
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/blkdev.h>
-#include <linux/hdreg.h>
-#include <linux/pci.h>
-#include <linux/bios32.h>
-
-#include <asm/io.h>
-#include <asm/dma.h>
-
-#include "ide.h"
-#include "ide_modes.h"
-
-#define DISPLAY_PIIX_TIMINGS /* define this to display timings */
-
-/*
- * good_dma_drives() lists the model names (from "hdparm -i")
- * of drives which do not support mode2 DMA but which are
- * known to work fine with this interface under Linux.
- */
-const char *good_dma_drives[] = {"Micropolis 2112A",
- "CONNER CTMA 4000",
- NULL};
-
-/*
- * Our Physical Region Descriptor (PRD) table should be large enough
- * to handle the biggest I/O request we are likely to see. Since requests
- * can have no more than 256 sectors, and since the typical blocksize is
- * two sectors, we could get by with a limit of 128 entries here for the
- * usual worst case. Most requests seem to include some contiguous blocks,
- * further reducing the number of table entries required.
- *
- * The driver reverts to PIO mode for individual requests that exceed
- * this limit (possible with 512 byte blocksizes, eg. MSDOS f/s), so handling
- * 100% of all crazy scenarios here is not necessary.
- *
- * As it turns out though, we must allocate a full 4KB page for this,
- * so the two PRD tables (ide0 & ide1) will each get half of that,
- * allowing each to have about 256 entries (8 bytes each) from this.
- */
-#define PRD_BYTES 8
-#define PRD_ENTRIES (PAGE_SIZE / (2 * PRD_BYTES))
-
-/*
- * Interface to access piix registers
- */
-static unsigned int piix_key;
-
-#define PIIX_FLAGS_FAST_PIO 1
-#define PIIX_FLAGS_USE_IORDY 2
-#define PIIX_FLAGS_PREFETCH 4
-#define PIIX_FLAGS_FAST_DMA 8
-
-
-union chip_en_reg_u {
- struct {
- unsigned d0_flags :4;
- unsigned d1_flags :4;
- unsigned recovery :2;
- unsigned reserved :2;
- unsigned sample :2;
- unsigned sidetim_enabled:1;
- unsigned ports_enabled :1;
- } piix_s;
- struct {
- unsigned sec_en :1;
- unsigned pri_en :1;
- unsigned reserved :14;
- } via_s;
-};
-
-typedef union chip_en_reg_u piix_timing_t;
-
-typedef struct {
- unsigned pri_recovery :2;
- unsigned pri_sample :2;
- unsigned sec_recovery :2;
- unsigned sec_sample :2;
-} piix_sidetim_t;
-
-
-/*
- * We currently can handle only one PIIX chip here
- */
-static piix_pci_bus = 0;
-static piix_pci_fn = 0;
-
-static int config_drive_for_dma (ide_drive_t *);
-
-/*
- * dma_intr() is the handler for disk read/write DMA interrupts
- */
-static void dma_intr (ide_drive_t *drive)
-{
- byte stat, dma_stat;
- int i;
- struct request *rq = HWGROUP(drive)->rq;
- unsigned short dma_base = HWIF(drive)->dma_base;
-
- dma_stat = inb(dma_base+2); /* get DMA status */
- outb(inb(dma_base)&~1, dma_base); /* stop DMA operation */
- stat = GET_STAT(); /* get drive status */
- if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) {
- if ((dma_stat & 7) == 4) { /* verify good DMA status */
- rq = HWGROUP(drive)->rq;
- for (i = rq->nr_sectors; i > 0;) {
- i -= rq->current_nr_sectors;
- ide_end_request(1, HWGROUP(drive));
- }
- return;
- }
- printk("%s: bad DMA status: 0x%02x\n", drive->name, dma_stat);
- }
- sti();
- ide_error(drive, "dma_intr", stat);
-}
-
-/*
- * build_dmatable() prepares a dma request.
- * Returns 0 if all went okay, returns 1 otherwise.
- */
-static int build_dmatable (ide_drive_t *drive)
-{
- struct request *rq = HWGROUP(drive)->rq;
- struct buffer_head *bh = rq->bh;
- unsigned long size, addr, *table = HWIF(drive)->dmatable;
- unsigned int count = 0;
-
- do {
- /*
- * Determine addr and size of next buffer area. We assume that
- * individual virtual buffers are always composed linearly in
- * physical memory. For example, we assume that any 8kB buffer
- * is always composed of two adjacent physical 4kB pages rather
- * than two possibly non-adjacent physical 4kB pages.
- */
- if (bh == NULL) { /* paging requests have (rq->bh == NULL) */
- addr = virt_to_bus (rq->buffer);
- size = rq->nr_sectors << 9;
- } else {
- /* group sequential buffers into one large buffer */
- addr = virt_to_bus (bh->b_data);
- size = bh->b_size;
- while ((bh = bh->b_reqnext) != NULL) {
- if ((addr + size) != virt_to_bus (bh->b_data))
- break;
- size += bh->b_size;
- }
- }
-
- /*
- * Fill in the dma table, without crossing any 64kB boundaries.
- * We assume 16-bit alignment of all blocks.
- */
- while (size) {
- if (++count >= PRD_ENTRIES) {
- printk("%s: DMA table too small\n", drive->name);
- return 1; /* revert to PIO for this request */
- } else {
- unsigned long bcount = 0x10000 - (addr & 0xffff);
- if (bcount > size)
- bcount = size;
- *table++ = addr;
- *table++ = bcount & 0xffff;
- addr += bcount;
- size -= bcount;
- }
- }
- } while (bh != NULL);
- if (count) {
- *--table |= 0x80000000; /* set End-Of-Table (EOT) bit */
- return 0;
- }
- printk("%s: empty DMA table?\n", drive->name);
- return 1; /* let the PIO routines handle this weirdness */
-}
-
-/*
- * piix_dmaproc() initiates/aborts DMA read/write operations on a drive.
- *
- * The caller is assumed to have selected the drive and programmed the drive's
- * sector address using CHS or LBA. All that remains is to prepare for DMA
- * and then issue the actual read/write DMA/PIO command to the drive.
- *
- * For ATAPI devices, we just prepare for DMA and return. The caller should
- * then issue the packet command to the drive and call us again with
- * ide_dma_begin afterwards.
- *
- * Returns 0 if all went well.
- * Returns 1 if DMA read/write could not be started, in which case
- * the caller should revert to PIO for the current request.
- */
-static int piix_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
-{
- unsigned long dma_base = HWIF(drive)->dma_base;
- unsigned int reading = (1 << 3);
- piix_timing_t timing;
- unsigned short reg;
- byte dflags;
-
- switch (func) {
- case ide_dma_off:
- printk("%s: DMA disabled\n", drive->name);
- case ide_dma_on:
- drive->using_dma = (func == ide_dma_on);
- reg = (HWIF(drive)->io_ports[IDE_DATA_OFFSET] == 0x170) ? 0x42 : 0x40;
- if (pcibios_read_config_word(piix_pci_bus, piix_pci_fn, reg, (short *)&timing)) {
- printk("%s: pcibios read failed\n", HWIF(drive)->name);
- return 1;
- }
- dflags = drive->select.b.unit ? timing.piix_s.d1_flags : timing.piix_s.d0_flags;
- if (dflags & PIIX_FLAGS_FAST_PIO) {
- if (func == ide_dma_on && drive->media == ide_disk)
- dflags |= PIIX_FLAGS_FAST_DMA;
- else
- dflags &= ~PIIX_FLAGS_FAST_DMA;
- if (drive->select.b.unit == 0)
- timing.piix_s.d0_flags = dflags;
- else
- timing.piix_s.d1_flags = dflags;
- if (pcibios_write_config_word(piix_pci_bus, piix_pci_fn, reg, *(short *)&timing)) {
- printk("%s: pcibios write failed\n", HWIF(drive)->name);
- return 1;
- }
- }
- return 0;
- case ide_dma_abort:
- outb(inb(dma_base)&~1, dma_base); /* stop DMA */
- return 0;
- case ide_dma_check:
- return config_drive_for_dma (drive);
- case ide_dma_write:
- reading = 0;
- case ide_dma_read:
- break;
- case ide_dma_status_bad:
- return ((inb(dma_base+2) & 7) != 4); /* verify good DMA status */
- case ide_dma_transferred:
-#if 0
- return (number of bytes actually transferred);
-#else
- return (0);
-#endif
- case ide_dma_begin:
- outb(inb(dma_base)|1, dma_base); /* begin DMA */
- return 0;
- default:
- printk("piix_dmaproc: unsupported func: %d\n", func);
- return 1;
- }
- if (build_dmatable (drive))
- return 1;
- outl(virt_to_bus (HWIF(drive)->dmatable), dma_base + 4); /* PRD table */
- outb(reading, dma_base); /* specify r/w */
- outb(inb(dma_base+2)|0x06, dma_base+2); /* clear status bits */
- if (drive->media != ide_disk)
- return 0;
- ide_set_handler(drive, &dma_intr, WAIT_CMD); /* issue cmd to drive */
- OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
- outb(inb(dma_base)|1, dma_base); /* begin DMA */
- return 0;
-}
-
-static int config_drive_for_dma (ide_drive_t *drive)
-{
- const char **list;
-
- struct hd_driveid *id = drive->id;
- if (id && (id->capability & 1)) {
- /* Enable DMA on any drive that supports mode2 (multi/single word) DMA */
- if (id->field_valid & 2)
- if ((id->dma_mword & 0x404) == 0x404 || (id->dma_1word & 0x404) == 0x404)
- return piix_dmaproc(ide_dma_on, drive);
- /* Consult the list of known "good" drives */
- list = good_dma_drives;
- while (*list) {
- if (!strcmp(*list++,id->model))
- return piix_dmaproc(ide_dma_on, drive);
- }
- }
- return piix_dmaproc(ide_dma_off, drive);
-}
-
-#ifdef DISPLAY_PIIX_TIMINGS
-/*
- * print_piix_drive_flags() displays the currently programmed options
- * in the PIIX/PIIX3/PIIX4 for a given drive.
- */
-static void print_piix_drive_flags (const char *unit, byte dflags)
-{
- printk(" %s ", unit);
- printk( "fastDMA=%s", (dflags & PIIX_FLAGS_FAST_PIO) ? "yes" : "no ");
- printk(" PreFetch=%s", (dflags & PIIX_FLAGS_PREFETCH) ? "on " : "off");
- printk(" IORDY=%s", (dflags & PIIX_FLAGS_USE_IORDY) ? "on " : "off");
- printk(" fastPIO=%s\n", ((dflags & (PIIX_FLAGS_FAST_PIO|PIIX_FLAGS_FAST_DMA)) == PIIX_FLAGS_FAST_PIO) ? "on " : "off");
-}
-#endif /* DISPLAY_PIIX_TIMINGS */
-
-static void init_piix_dma (ide_hwif_t *hwif, unsigned short base)
-{
- static unsigned long dmatable = 0;
-
- printk(" %s: BM-DMA at 0x%04x-0x%04x", hwif->name, base, base+7);
- if (check_region(base, 8)) {
- printk(" -- ERROR, PORTS ALREADY IN USE");
- } else {
- request_region(base, 8, "IDE DMA");
- hwif->dma_base = base;
- if (!dmatable) {
- /*
- * The BM-DMA uses a full 32-bits, so we can
- * safely use __get_free_page() here instead
- * of __get_dma_pages() -- no ISA limitations.
- */
- dmatable = __get_free_page(GFP_KERNEL);
- }
- if (dmatable) {
- hwif->dmatable = (unsigned long *) dmatable;
- dmatable += (PRD_ENTRIES * PRD_BYTES);
- outl(virt_to_bus(hwif->dmatable), base + 4);
- hwif->dmaproc = &piix_dmaproc;
- }
- }
- printk("\n");
-}
-
-/* The next two functions were stolen from cmd640.c, with
- a few modifications */
-
-static void put_piix_reg (unsigned short reg, long val)
-{
- unsigned long flags;
-
- save_flags(flags);
- cli();
- outl_p((reg & 0xfc) | piix_key, 0xcf8);
- outl_p(val, (reg & 3) | 0xcfc);
- restore_flags(flags);
-}
-
-static long get_piix_reg (unsigned short reg)
-{
- long b;
- unsigned long flags;
-
- save_flags(flags);
- cli();
- outl_p((reg & 0xfc) | piix_key, 0xcf8);
- b = inl_p((reg & 3) | 0xcfc);
- restore_flags(flags);
- return b;
-}
-
-/*
- * Search for an (apparently) unused block of I/O space
- * of "size" bytes in length.
- */
-static short find_free_region (unsigned short size)
-{
- unsigned short i, base = 0xe800;
- for (base = 0xe800; base > 0; base -= 0x800) {
- if (!check_region(base,size)) {
- for (i = 0; i < size; i++) {
- if (inb(base+i) != 0xff)
- goto next;
- }
- return base; /* success */
- }
- next:
- }
- return 0; /* failure */
-}
-
-/*
- * ide_init_triton() prepares the IDE driver for DMA operation.
- * This routine is called once, from ide.c during driver initialization,
- * for each triton chipset which is found (unlikely to be more than one).
- */
-void ide_init_triton (byte bus, byte fn)
-{
- int rc = 0, h;
- int dma_enabled = 0;
- unsigned short pcicmd, devid;
- unsigned int bmiba;
- const char *chipset = "ide";
- piix_timing_t timings[2];
-
- piix_pci_bus = bus;
- piix_pci_fn = fn;
-
- if (pcibios_read_config_word(bus, fn, 0x02, &devid))
- goto quit;
-
- if (devid == PCI_DEVICE_ID_INTEL_82371AB)
- chipset = "PIIX4";
- else if (devid == PCI_DEVICE_ID_INTEL_82371SB_1)
- chipset = "PIIX3";
- else if (devid == PCI_DEVICE_ID_INTEL_82371_1)
- chipset = "PIIX";
- else if (devid == PCI_DEVICE_ID_VIA_82C586_1)
- chipset = "VP1";
- else {
- printk("Unknown PCI IDE interface 0x%x\n", devid);
- goto quit;
- }
-
- printk("%s: bus-master IDE device on PCI bus %d function %d\n", chipset, bus, fn);
-
- /*
- * See if IDE ports are enabled
- */
- if ((rc = pcibios_read_config_word(bus, fn, 0x04, &pcicmd)))
- goto quit;
- if ((pcicmd & 1) == 0) {
- printk("%s: IDE ports are not enabled (BIOS)\n", chipset);
- goto quit;
- }
- if (devid == PCI_DEVICE_ID_VIA_82C586_1) {
- /* pri and sec channel enables are in port 0x40 */
- if ((rc = pcibios_read_config_word(bus, fn, 0x40, (short *)&timings[0])))
- goto quit;
- if ((!timings[0].via_s.pri_en && (!timings[0].via_s.sec_en))) {
- printk("%s: neither IDE port is enabled\n", chipset);
- goto quit;
- }
- }
- else { /* INTEL piix */
- if ((rc = pcibios_read_config_word(bus, fn, 0x40, (short *)&timings[0])))
- goto quit;
- if ((rc = pcibios_read_config_word(bus, fn, 0x42, (short *)&timings[1])))
- goto quit;
- if ((!timings[0].piix_s.ports_enabled) && (!timings[1].piix_s.ports_enabled)) {
- printk("%s: neither IDE port is enabled\n", chipset);
- goto quit;
- }
- }
-
- /*
- * See if Bus-Mastered DMA is enabled
- */
- if ((pcicmd & 4) == 0) {
- printk("%s: bus-master DMA feature is not enabled (BIOS)\n", chipset);
- } else {
- /*
- * Get the bmiba base address
- */
- if ((rc = pcibios_read_config_dword(bus, fn, 0x20, &bmiba)))
- goto quit;
- bmiba &= 0xfff0; /* extract port base address */
- if (bmiba) {
- dma_enabled = 1;
- } else {
- unsigned short base;
- printk("%s: bus-master base address is invalid (0x%04x, BIOS problem)\n", chipset, bmiba);
- base = find_free_region(16);
- if (base) {
- printk("%s: bypassing BIOS; setting bus-master base address to 0x%04x\n", chipset, base);
- piix_key = 0x80000000 + (fn * 0x100);
- put_piix_reg(0x04,get_piix_reg(0x04)&~5);
- put_piix_reg(0x20,(get_piix_reg(0x20)&0xFFFF000F)|base|1);
- put_piix_reg(0x04,get_piix_reg(0x04)|5);
- bmiba = get_piix_reg(0x20)&0x0000FFF0;
- if (bmiba == base && (get_piix_reg(0x04) & 5) == 5)
- dma_enabled = 1;
- else
- printk("%s: operation failed\n", chipset);
- }
- if (!dma_enabled)
- printk("%s: DMA is disabled (BIOS)\n", chipset);
- }
- }
-
- /*
- * Save the dma_base port addr for each interface
- */
- for (h = 0; h < MAX_HWIFS; ++h) {
- unsigned int pri_sec;
- piix_timing_t timing;
- ide_hwif_t *hwif = &ide_hwifs[h];
- switch (hwif->io_ports[IDE_DATA_OFFSET]) {
- case 0x1f0: pri_sec = 0; break;
- case 0x170: pri_sec = 1; break;
- default: continue;
- }
-
- if (devid == PCI_DEVICE_ID_VIA_82C586_1) {
- timing = timings[0];
- switch (h) {
- case 0:
- if (!timing.piix_s.ports_enabled) {
- printk("port 0 DMA not enabled\n");
- continue;
- }
- case 1:
- if (!timing.piix_s.sidetim_enabled) {
- printk("port 1 DMA not enabled\n");
- continue;
- }
- }
- hwif->chipset = ide_via;
- }
- else { /* PIIX */
-
- timing = timings[pri_sec];
- if (!timing.piix_s.ports_enabled) /* interface disabled? */
- continue;
- hwif->chipset = ide_triton;
- }
- if (dma_enabled)
- init_piix_dma(hwif, bmiba + (pri_sec ? 8 : 0));
-#ifdef DISPLAY_PIIX_TIMINGS
- /*
- * Display drive timings/modes
- */
- {
- const char *slave;
- piix_sidetim_t sidetim;
- byte sample = 5 - timing.piix_s.sample;
- byte recovery = 4 - timing.piix_s.recovery;
- unsigned int drvtim;
-
- if (devid == PCI_DEVICE_ID_VIA_82C586_1) {
- pcibios_read_config_dword(bus, fn, 0x48, &drvtim);
- if (pri_sec == 0) {
- printk(" %s master: active_pulse_CLKs=%d, recovery_CLKs=%d\n", hwif->name, 1+(drvtim>>28), 1+((drvtim & 0x0f000000)>>24));
- printk(" %s slave: active_pulse_CLKs=%d, recovery_CLKs=%d\n", hwif->name, 1+((drvtim & 0xf00000)>>20), 1+((drvtim & 0x0f0000)>>16));
- continue;
- } else {
- printk(" %s master: active_pulse_CLKs=%d, recovery_CLKs=%d\n", hwif->name, 1+((drvtim & 0xf000)>>12), 1+((drvtim & 0x0f00)>>8));
- printk(" %s slave: active_pulse_CLKs=%d, recovery_CLKs=%d\n", hwif->name, 1+((drvtim & 0xf0)>>4), 1+(drvtim & 0x0f));
- continue;
- }
- }
-
- if ((devid == PCI_DEVICE_ID_INTEL_82371SB_1
- || devid == PCI_DEVICE_ID_INTEL_82371AB)
- && timing.piix_s.sidetim_enabled
- && !pcibios_read_config_byte(bus, fn, 0x44, (byte *) &sidetim))
- slave = ""; /* PIIX3 and later */
- else
- slave = "/slave"; /* PIIX, or PIIX3 in compatibility mode */
- printk(" %s master%s: sample_CLKs=%d, recovery_CLKs=%d\n", hwif->name, slave, sample, recovery);
- print_piix_drive_flags ("master:", timing.piix_s.d0_flags);
- if (!*slave) {
- if (pri_sec == 0) {
- sample = 5 - sidetim.pri_sample;
- recovery = 4 - sidetim.pri_recovery;
- } else {
- sample = 5 - sidetim.sec_sample;
- recovery = 4 - sidetim.sec_recovery;
- }
- printk(" slave : sample_CLKs=%d, recovery_CLKs=%d\n", sample, recovery);
- }
- print_piix_drive_flags ("slave :", timing.piix_s.d1_flags);
- }
-#endif /* DISPLAY_PIIX_TIMINGS */
- }
-
-quit: if (rc) printk("%s: pcibios access failed - %s\n", chipset, pcibios_strerror(rc));
-}
diff --git a/drivers/block/umc8672.c b/drivers/block/umc8672.c
index 3427f7077..628e13bb5 100644
--- a/drivers/block/umc8672.c
+++ b/drivers/block/umc8672.c
@@ -151,5 +151,6 @@ void init_umc8672 (void) /* called from ide.c */
ide_hwifs[1].chipset = ide_umc8672;
ide_hwifs[0].tuneproc = &tune_umc;
ide_hwifs[1].tuneproc = &tune_umc;
-
+ ide_hwifs[0].mate = &ide_hwifs[1];
+ ide_hwifs[1].mate = &ide_hwifs[0];
}
diff --git a/drivers/cdrom/Config.in b/drivers/cdrom/Config.in
index 5e2b09854..f07e65539 100644
--- a/drivers/cdrom/Config.in
+++ b/drivers/cdrom/Config.in
@@ -19,9 +19,6 @@ tristate 'Mitsumi [XA/MultiSession] CDROM support' CONFIG_MCDX
tristate 'Optics Storage DOLPHIN 8000AT CDROM support' CONFIG_OPTCD
tristate 'Philips/LMS CM206 CDROM support' CONFIG_CM206
tristate 'Sanyo CDR-H94A CDROM support' CONFIG_SJCD
-bool 'Soft configurable cdrom interface card support' CONFIG_CDI_INIT
-if [ "$CONFIG_CDI_INIT" = "y" ]; then
- tristate 'ISP16/MAD16/Mozart soft configurable cdrom interface support' CONFIG_ISP16_CDI
-fi
+tristate 'ISP16/MAD16/Mozart soft configurable cdrom interface support' CONFIG_ISP16_CDI
tristate 'Sony CDU31A/CDU33A CDROM support' CONFIG_CDU31A
tristate 'Sony CDU535 CDROM support' CONFIG_CDU535
diff --git a/drivers/cdrom/Makefile b/drivers/cdrom/Makefile
index 4956e3ead..0f54a6e2d 100644
--- a/drivers/cdrom/Makefile
+++ b/drivers/cdrom/Makefile
@@ -90,11 +90,9 @@ endif #CONFIG_GSCD
ifeq ($(CONFIG_CM206),y)
L_OBJS += cm206.o
-USE_GENERIC_CD=1
else
ifeq ($(CONFIG_CM206),m)
M_OBJS += cm206.o
- USE_MODULAR_GENERIC_CD=1
endif
endif #CONFIG_CM206
@@ -122,42 +120,20 @@ else
endif
endif #CONFIG_BPCD
-ifeq ($(CONFIG_CDI_INIT),y)
-L_OBJS += cdi.o
-endif #CONFIG_CDI_INIT
ifeq ($(CONFIG_ISP16_CDI),y)
L_OBJS += isp16.o
else
-# ifeq ($(CONFIG_CDI_INIT),m)
-# M_OBJS += cdi.o
-# endif
ifeq ($(CONFIG_ISP16_CDI),m)
M_OBJS += isp16.o
endif
endif #CONFIG_ISP16_CDI
-ifeq ($(CONFIG_BLK_DEV_SR),y)
-USE_GENERIC_CD=1
-else
- ifeq ($(CONFIG_BLK_DEV_SR),m)
- USE_MODULAR_GENERIC_CD=1
- endif
-endif #SCSI CDROM DRIVER
-
-ifeq ($(CONFIG_BLK_DEV_IDECD),y)
-USE_GENERIC_CD=1
-else
- ifeq ($(CONFIG_BLK_DEV_IDECD),m)
- USE_MODULAR_GENERIC_CD=1
- endif
-endif #CONFIG_BLK_DEV_IDECD
-
-ifdef USE_GENERIC_CD
+ifeq ($(CONFIG_CDROM),y)
LX_OBJS += cdrom.o
else
- ifdef USE_MODULAR_GENERIC_CD
+ ifeq ($(CONFIG_CDROM),m)
MX_OBJS += cdrom.o
endif
-endif #The Makefile configuration for the generic cdrom interface
-
+endif #CONFIG_CDROM for the Uniform CD-ROM driver
+
include $(TOPDIR)/Rules.make
diff --git a/drivers/cdrom/aztcd.c b/drivers/cdrom/aztcd.c
index c97133141..0d8848fdc 100644
--- a/drivers/cdrom/aztcd.c
+++ b/drivers/cdrom/aztcd.c
@@ -1,8 +1,9 @@
-#define AZT_VERSION "2.50"
-/* $Id: aztcd.c,v 1.16 1997/01/26 07:12:53 davem Exp $
+#define AZT_VERSION "2.60"
+
+/* $Id: aztcd.c,v 2.60 1997/11/29 09:51:19 root Exp root $
linux/drivers/block/aztcd.c - Aztech CD268 CDROM driver
- Copyright (C) 1994,95,96 Werner Zimmermann(zimmerma@rz.fht-esslingen.de)
+ Copyright (C) 1994-98 Werner Zimmermann(Werner.Zimmermann@fht-esslingen.de)
based on Mitsumi CDROM driver by Martin Hariss and preworks by
Eberhard Moenkeberg; contains contributions by Joe Nardone and Robby
@@ -154,7 +155,18 @@
V2.50 Heiko Eissfeldt suggested to remove some VERIFY_READs in
aztcd_ioctl; check_aztcd_media_change modified
Werner Zimmermann, May 16, 96
+ V2.60 Implemented Auto-Probing; made changes for kernel's 2.1.xx blocksize
+ Adaption to linux kernel > 2.1.0
+ Werner Zimmermann, Nov 29, 97
*/
+
+#include <linux/version.h>
+
+#define MAJOR_NR AZTECH_CDROM_MAJOR
+
+#include <linux/blk.h>
+#include "aztcd.h"
+
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/sched.h>
@@ -166,16 +178,21 @@
#include <linux/ioport.h>
#include <linux/string.h>
#include <linux/major.h>
+
+#ifndef AZT_KERNEL_PRIOR_2_1
#include <linux/init.h>
+#endif
#include <asm/system.h>
#include <asm/io.h>
-#include <asm/uaccess.h>
-#define MAJOR_NR AZTECH_CDROM_MAJOR
+#ifdef AZT_KERNEL_PRIOR_2_1
+#include <asm/segment.h>
+#else
+#include <asm/uaccess.h>
+static int aztcd_blocksizes[1] = {2048};
+#endif
-#include <linux/blk.h>
-#include <linux/aztcd.h>
/*###########################################################################
Defines
@@ -222,6 +239,11 @@
#define azt_port aztcd /*needed for the modutils*/
+#ifndef AZT_KERNEL_PRIOR_2_1
+#define memcpy_fromfs copy_from_user
+#define memcpy_tofs copy_to_user
+#endif
+
/*##########################################################################
Type Definitions
##########################################################################
@@ -269,7 +291,12 @@ static int azt_mode = -1;
static volatile int azt_read_count = 1;
static int azt_port = AZT_BASE_ADDR;
+
+#ifndef AZT_KERNEL_PRIOR_2_1
MODULE_PARM(azt_port, "i");
+#endif
+
+static int azt_port_auto[16] = AZT_BASE_AUTO;
static char azt_cont = 0;
static char azt_init_end = 0;
@@ -331,7 +358,13 @@ static void azt_transfer(void);
static void do_aztcd_request(void);
static void azt_invalidate_buffers(void);
int aztcd_open(struct inode *ip, struct file *fp);
+
+#ifdef AZT_KERNEL_PRIOR_2_1
+static void aztcd_release(struct inode * inode, struct file * file);
+#else
static int aztcd_release(struct inode * inode, struct file * file);
+#endif
+
int aztcd_init(void);
#ifdef MODULE
int init_module(void);
@@ -786,7 +819,7 @@ static int aztUpdateToc()
}
DiskInfo.xa = getAztStatus() & AST_MODE;
if (DiskInfo.xa)
- { printk("aztcd: XA support experimental - mail results to zimmerma@rz.fht-esslingen.de\n");
+ { printk("aztcd: XA support experimental - mail results to Werner.Zimmermann@fht-esslingen.de\n");
}
/*multisession detection
@@ -1050,7 +1083,11 @@ static int aztGetToc(int multi)
Kernel Interface Functions
##########################################################################
*/
+#ifdef AZT_KERNEL_PRIOR_2_1
+void aztcd_setup(char *str, int *ints)
+#else
__initfunc(void aztcd_setup(char *str, int *ints))
+#endif
{ if (ints[0] > 0)
azt_port = ints[1];
if (ints[0] > 1)
@@ -1139,7 +1176,7 @@ static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsi
#endif
st = verify_area(VERIFY_WRITE, (void*) arg, sizeof(struct cdrom_multisession));
if (st) return st;
- copy_from_user(&ms, (void*) arg, sizeof(struct cdrom_multisession));
+ memcpy_fromfs(&ms, (void*) arg, sizeof(struct cdrom_multisession));
if (ms.addr_format == CDROM_MSF)
{ ms.addr.msf.minute = azt_bcd2bin(DiskInfo.lastSession.min);
ms.addr.msf.second = azt_bcd2bin(DiskInfo.lastSession.sec);
@@ -1150,7 +1187,7 @@ static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsi
else
return -EINVAL;
ms.xa_flag = DiskInfo.xa;
- copy_to_user((void*) arg, &ms, sizeof(struct cdrom_multisession));
+ memcpy_tofs((void*) arg, &ms, sizeof(struct cdrom_multisession));
#ifdef AZT_DEBUG
if (ms.addr_format == CDROM_MSF)
printk("aztcd multisession xa:%d, msf:%02x:%02x.%02x [%02x:%02x.%02x])\n",
@@ -1167,7 +1204,7 @@ static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsi
case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */
st = verify_area(VERIFY_READ, (void *) arg, sizeof ti);
if (st) return st;
- copy_from_user(&ti, (void *) arg, sizeof ti);
+ memcpy_fromfs(&ti, (void *) arg, sizeof ti);
if (ti.cdti_trk0 < DiskInfo.first
|| ti.cdti_trk0 > DiskInfo.last
|| ti.cdti_trk1 < ti.cdti_trk0)
@@ -1198,7 +1235,7 @@ printk("aztcd play: %02x:%02x.%02x to %02x:%02x.%02x\n",
*/
st = verify_area(VERIFY_READ, (void *) arg, sizeof msf);
if (st) return st;
- copy_from_user(&msf, (void *) arg, sizeof msf);
+ memcpy_fromfs(&msf, (void *) arg, sizeof msf);
/* convert to bcd */
azt_bin2bcd(&msf.cdmsf_min0);
azt_bin2bcd(&msf.cdmsf_sec0);
@@ -1230,12 +1267,12 @@ azt_Play.end.min, azt_Play.end.sec, azt_Play.end.frame);
if (st) return st;
tocHdr.cdth_trk0 = DiskInfo.first;
tocHdr.cdth_trk1 = DiskInfo.last;
- copy_to_user((void *) arg, &tocHdr, sizeof tocHdr);
+ memcpy_tofs((void *) arg, &tocHdr, sizeof tocHdr);
break;
case CDROMREADTOCENTRY: /* Read an entry in the table of contents */
st = verify_area(VERIFY_WRITE, (void *) arg, sizeof entry);
if (st) return st;
- copy_from_user(&entry, (void *) arg, sizeof entry);
+ memcpy_fromfs(&entry, (void *) arg, sizeof entry);
if ((!aztTocUpToDate)||aztDiskChanged) aztUpdateToc();
if (entry.cdte_track == CDROM_LEADOUT)
tocPtr = &Toc[DiskInfo.last + 1];
@@ -1257,7 +1294,7 @@ azt_Play.end.min, azt_Play.end.sec, azt_Play.end.frame);
else
{ return -EINVAL;
}
- copy_to_user((void *) arg, &entry, sizeof entry);
+ memcpy_tofs((void *) arg, &entry, sizeof entry);
break;
case CDROMSUBCHNL: /* Get subchannel info */
st = verify_area(VERIFY_WRITE, (void *) arg, sizeof(struct cdrom_subchnl));
@@ -1267,7 +1304,7 @@ azt_Play.end.min, azt_Play.end.sec, azt_Play.end.frame);
#endif
return st;
}
- copy_from_user(&subchnl, (void *) arg, sizeof (struct cdrom_subchnl));
+ memcpy_fromfs(&subchnl, (void *) arg, sizeof (struct cdrom_subchnl));
if (aztGetQChannelInfo(&qInfo) < 0)
if (st) {
#ifdef AZT_DEBUG
@@ -1293,7 +1330,7 @@ azt_Play.end.min, azt_Play.end.sec, azt_Play.end.frame);
subchnl.cdsc_reladdr.msf.second = azt_bcd2bin(qInfo.trackTime.sec);
subchnl.cdsc_reladdr.msf.frame = azt_bcd2bin(qInfo.trackTime.frame);
}
- copy_to_user((void *) arg, &subchnl, sizeof (struct cdrom_subchnl));
+ memcpy_tofs((void *) arg, &subchnl, sizeof (struct cdrom_subchnl));
break;
case CDROMVOLCTRL: /* Volume control
* With my Aztech CD268-01A volume control does not work, I can only
@@ -1301,7 +1338,7 @@ azt_Play.end.min, azt_Play.end.sec, azt_Play.end.frame);
works better with your drive */
st=verify_area(VERIFY_READ,(void *) arg, sizeof(volctrl));
if (st) return (st);
- copy_from_user(&volctrl,(char *) arg,sizeof(volctrl));
+ memcpy_fromfs(&volctrl,(char *) arg,sizeof(volctrl));
azt_Play.start.min = 0x21;
azt_Play.start.sec = 0x84;
azt_Play.start.frame = volctrl.channel0;
@@ -1341,7 +1378,7 @@ azt_Play.end.min, azt_Play.end.sec, azt_Play.end.frame);
case CDROMREADRAW: /*read data in mode 2 (2336 Bytes)*/
{ st = verify_area(VERIFY_WRITE, (void *) arg, sizeof buf);
if (st) return st;
- copy_from_user(&msf, (void *) arg, sizeof msf);
+ memcpy_fromfs(&msf, (void *) arg, sizeof msf);
/* convert to bcd */
azt_bin2bcd(&msf.cdmsf_min0);
azt_bin2bcd(&msf.cdmsf_sec0);
@@ -1363,21 +1400,21 @@ azt_Play.end.min, azt_Play.end.sec, azt_Play.end.frame);
{ if (sendAztCmd(ACMD_PLAY_READ_RAW, &azt_Play)) return -1;
DTEN_LOW;
insb(DATA_PORT,buf,CD_FRAMESIZE_RAW);
- copy_to_user((void *) arg, &buf, CD_FRAMESIZE_RAW);
+ memcpy_tofs((void *) arg, &buf, CD_FRAMESIZE_RAW);
}
}
else /*CDROMREADCOOKED*/
{ if (sendAztCmd(ACMD_PLAY_READ, &azt_Play)) return -1;
DTEN_LOW;
insb(DATA_PORT,buf,CD_FRAMESIZE);
- copy_to_user((void *) arg, &buf, CD_FRAMESIZE);
+ memcpy_tofs((void *) arg, &buf, CD_FRAMESIZE);
}
}
break;
case CDROMSEEK: /*seek msf address*/
st = verify_area(VERIFY_READ, (void *) arg, sizeof msf);
if (st) return st;
- copy_from_user(&msf, (void *) arg, sizeof msf);
+ memcpy_fromfs(&msf, (void *) arg, sizeof msf);
/* convert to bcd */
azt_bin2bcd(&msf.cdmsf_min0);
azt_bin2bcd(&msf.cdmsf_sec0);
@@ -1543,7 +1580,11 @@ int aztcd_open(struct inode *ip, struct file *fp)
/*
* On close, we flush all azt blocks from the buffer cache.
*/
-static int aztcd_release(struct inode * inode, struct file * file)
+#ifdef AZT_KERNEL_PRIOR_2_1
+static void aztcd_release(struct inode * inode, struct file * file)
+#else
+static int aztcd_release(struct inode * inode, struct file * file)
+#endif
{
#ifdef AZT_DEBUG
printk("aztcd: executing aztcd_release\n");
@@ -1559,7 +1600,11 @@ static int aztcd_release(struct inode * inode, struct file * file)
aztSendCmd(ACMD_EJECT);
CLEAR_TIMER;
}
+#ifdef AZT_KERNEL_PRIOR_2_1
+ return;
+#else
return 0;
+#endif
}
@@ -1568,29 +1613,31 @@ static int aztcd_release(struct inode * inode, struct file * file)
* Test for presence of drive and initialize it. Called at boot time.
*/
+#ifdef AZT_KERNEL_PRIOR_2_1
+int aztcd_init(void)
+#else
__initfunc(int aztcd_init(void))
+#endif
{ long int count, max_count;
unsigned char result[50];
int st;
+ int i = 0;
- if (azt_port <= 0) {
- printk("aztcd: no Aztech CD-ROM Initialization");
+ if (azt_port == 0)
+ { printk("aztcd: no Aztech CD-ROM Initialization");
return -EIO;
}
- printk("aztcd: AZTECH, ORCHID, OKANO, WEARNES, TXC, CyDROM CD-ROM Driver\n");
- printk("aztcd: (C) 1994-96 W.Zimmermann\n");
- printk("aztcd: DriverVersion=%s BaseAddress=0x%x For IDE/ATAPI-drives use ide-cd.c\n",AZT_VERSION,azt_port);
- printk("aztcd: If you have problems, read /usr/src/linux/Documentation/cdrom/aztcd\n");
- if ((azt_port==0x1f0)||(azt_port==0x170))
- st = check_region(azt_port, 8); /*IDE-interfaces need 8 bytes*/
- else
- st = check_region(azt_port, 4); /*proprietary interfaces need 4 bytes*/
- if (st)
- { printk("aztcd: conflict, I/O port (%X) already used\n",azt_port);
- return -EIO;
+ printk("aztcd: AZTECH, ORCHID, OKANO, WEARNES, TXC, CyDROM CD-ROM Driver\n");
+ printk("aztcd: (C) 1994-98 W.Zimmermann\n");
+ if (azt_port == -1)
+ { printk("aztcd: KernelVersion=%s DriverVersion=%s For IDE/ATAPI-drives use ide-cd.c\n",UTS_RELEASE,AZT_VERSION);
}
+ else
+ printk("aztcd: DriverVersion=%s BaseAddress=0x%x For IDE/ATAPI-drives use ide-cd.c\n",AZT_VERSION,azt_port);
+ printk("aztcd: If you have problems, read /usr/src/linux/Documentation/cdrom/aztcd\n");
+
#ifdef AZT_SW32 /*CDROM connected to Soundwave32 card*/
if ((0xFF00 & inw(AZT_SW32_ID_REG)) != 0x4500)
{ printk("aztcd: no Soundwave32 card detected at base:%x init:%x config:%x id:%x\n",
@@ -1606,69 +1653,105 @@ __initfunc(int aztcd_init(void))
#endif
/* check for presence of drive */
+
+ if (azt_port == -1) /* autoprobing */
+ { for (i=0;(azt_port_auto[i]!=0)&&(i<16);i++)
+ { azt_port = azt_port_auto[i];
+ printk("aztcd: Autoprobing BaseAddress=0x%x \n",azt_port);
+ st = check_region(azt_port, 4); /*proprietary interfaces need 4 bytes*/
+ if (st) continue;
+
+ outb(POLLED,MODE_PORT);
+ inb(CMD_PORT);
+ inb(CMD_PORT);
+ outb(ACMD_GET_VERSION,CMD_PORT); /*Try to get version info*/
+
+ aztTimeOutCount=0;
+ do { aztIndatum=inb(STATUS_PORT);
+ aztTimeOutCount++;
+ if (aztTimeOutCount>=AZT_FAST_TIMEOUT) break;
+ } while (aztIndatum&AFL_STATUS);
+ if (inb(DATA_PORT)==AFL_OP_OK)
+ break;
+ }
+ if ((azt_port_auto[i]==0)||(i==16))
+ { printk("aztcd: no AZTECH CD-ROM drive found\n");
+ return -EIO;
+ }
+ }
+ else /* no autoprobing */
+ { if ((azt_port==0x1f0)||(azt_port==0x170))
+ st = check_region(azt_port, 8); /*IDE-interfaces need 8 bytes*/
+ else
+ st = check_region(azt_port, 4); /*proprietary interfaces need 4 bytes*/
+ if (st)
+ { printk("aztcd: conflict, I/O port (%X) already used\n",azt_port);
+ return -EIO;
+ }
- if ((azt_port==0x1f0)||(azt_port==0x170))
+ if ((azt_port==0x1f0)||(azt_port==0x170))
SWITCH_IDE_SLAVE; /*switch IDE interface to slave configuration*/
-
- outb(POLLED,MODE_PORT);
- inb(CMD_PORT);
- inb(CMD_PORT);
- outb(ACMD_GET_VERSION,CMD_PORT); /*Try to get version info*/
-
-/* STEN_LOW - special implementation for drive recognition
-*/ aztTimeOutCount=0;
- do { aztIndatum=inb(STATUS_PORT);
- aztTimeOutCount++;
- if (aztTimeOutCount>=AZT_FAST_TIMEOUT) break;
- } while (aztIndatum&AFL_STATUS);
-
- if (inb(DATA_PORT)!=AFL_OP_OK) /*OP_OK? If not, reset and try again*/
- {
+
+ outb(POLLED,MODE_PORT);
+ inb(CMD_PORT);
+ inb(CMD_PORT);
+ outb(ACMD_GET_VERSION,CMD_PORT); /*Try to get version info*/
+
+ aztTimeOutCount=0;
+ do { aztIndatum=inb(STATUS_PORT);
+ aztTimeOutCount++;
+ if (aztTimeOutCount>=AZT_FAST_TIMEOUT) break;
+ } while (aztIndatum&AFL_STATUS);
+
+ if (inb(DATA_PORT)!=AFL_OP_OK) /*OP_OK? If not, reset and try again*/
+ {
#ifndef MODULE
- if (azt_cont!=0x79)
- { printk("aztcd: no AZTECH CD-ROM drive found-Try boot parameter aztcd=<BaseAddress>,0x79\n");
- return -EIO;
- }
+ if (azt_cont!=0x79)
+ { printk("aztcd: no AZTECH CD-ROM drive found-Try boot parameter aztcd=<BaseAddress>,0x79\n");
+ return -EIO;
+ }
#else
- if (0)
- {
- }
+ if (0)
+ {
+ }
#endif
- else
- { printk("aztcd: drive reset - please wait\n");
- for (count=0;count<50;count++)
- { inb(STATUS_PORT); /*removing all data from earlier tries*/
- inb(DATA_PORT);
- }
- outb(POLLED,MODE_PORT);
- inb(CMD_PORT);
- inb(CMD_PORT);
- getAztStatus(); /*trap errors*/
- outb(ACMD_SOFT_RESET,CMD_PORT); /*send reset*/
- STEN_LOW;
- if (inb(DATA_PORT)!=AFL_OP_OK) /*OP_OK?*/
- { printk("aztcd: no AZTECH CD-ROM drive found\n");
- return -EIO;
- }
- for (count = 0; count < AZT_TIMEOUT; count++);
- { count=count*2; /* delay a bit */
- count=count/2;
- }
- if ((st=getAztStatus())==-1)
- { printk("aztcd: Drive Status Error Status=%x\n",st);
- return -EIO;
- }
+ else
+ { printk("aztcd: drive reset - please wait\n");
+ for (count=0;count<50;count++)
+ { inb(STATUS_PORT); /*removing all data from earlier tries*/
+ inb(DATA_PORT);
+ }
+ outb(POLLED,MODE_PORT);
+ inb(CMD_PORT);
+ inb(CMD_PORT);
+ getAztStatus(); /*trap errors*/
+ outb(ACMD_SOFT_RESET,CMD_PORT); /*send reset*/
+ STEN_LOW;
+ if (inb(DATA_PORT)!=AFL_OP_OK) /*OP_OK?*/
+ { printk("aztcd: no AZTECH CD-ROM drive found\n");
+ return -EIO;
+ }
+ for (count = 0; count < AZT_TIMEOUT; count++);
+ { count=count*2; /* delay a bit */
+ count=count/2;
+ }
+ if ((st=getAztStatus())==-1)
+ { printk("aztcd: Drive Status Error Status=%x\n",st);
+ return -EIO;
+ }
#ifdef AZT_DEBUG
- printk("aztcd: Status = %x\n",st);
-#endif
- outb(POLLED,MODE_PORT);
- inb(CMD_PORT);
- inb(CMD_PORT);
- outb(ACMD_GET_VERSION,CMD_PORT); /*GetVersion*/
- STEN_LOW;
- OP_OK;
- }
- }
+ printk("aztcd: Status = %x\n",st);
+#endif
+ outb(POLLED,MODE_PORT);
+ inb(CMD_PORT);
+ inb(CMD_PORT);
+ outb(ACMD_GET_VERSION,CMD_PORT); /*GetVersion*/
+ STEN_LOW;
+ OP_OK;
+ }
+ }
+ }
+
azt_init_end=1;
STEN_LOW;
result[0]=inb(DATA_PORT); /*reading in a null byte???*/
@@ -1715,6 +1798,9 @@ __initfunc(int aztcd_init(void))
return -EIO;
}
blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
+#ifndef AZT_KERNEL_PRIOR_2_1
+ blksize_size[MAJOR_NR] = aztcd_blocksizes;
+#endif
read_ahead[MAJOR_NR] = 4;
if ((azt_port==0x1f0)||(azt_port==0x170))
@@ -1725,8 +1811,7 @@ __initfunc(int aztcd_init(void))
azt_invalidate_buffers();
aztPresent = 1;
aztCloseDoor();
-/* printk("aztcd: End Init\n");
-*/ return (0);
+ return (0);
}
#ifdef MODULE
@@ -2183,7 +2268,7 @@ static void azt_hsg2msf(long hsg, struct msf *msf)
static long azt_msf2hsg(struct msf *mp)
{ return azt_bcd2bin(mp -> frame) + azt_bcd2bin(mp -> sec) * 75
- + azt_bcd2bin(mp -> min) * 4500 - CD_BLOCK_OFFSET;
+ + azt_bcd2bin(mp -> min) * 4500 - CD_MSF_OFFSET;
}
static void azt_bin2bcd(unsigned char *p)
diff --git a/drivers/cdrom/cdi.c b/drivers/cdrom/cdi.c
index ee90de9c6..e69de29bb 100644
--- a/drivers/cdrom/cdi.c
+++ b/drivers/cdrom/cdi.c
@@ -1,50 +0,0 @@
-/* -- cdi.c
- *
- * Initialisation of software configurable cdrom interface
- * cards goes here.
- *
- * Copyright (c) 1996 Eric van der Maarel <H.T.M.v.d.Maarel@marin.nl>
- *
- * Version 0.1
- *
- * History:
- * 0.1 First release. Only support for ISP16/MAD16/Mozart.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#include <linux/config.h>
-#include <linux/blk.h> /* where the proto type of cdi_init() is */
-#include <linux/init.h>
-#ifdef CONFIG_ISP16_CDI
-#include <linux/isp16.h>
-#endif CONFIG_ISP16_CDI
-
-/*
- * Cdrom interface configuration.
- */
-__initfunc(int
-cdi_init(void))
-{
- int ret_val = -1;
-
-#ifdef CONFIG_ISP16_CDI
- ret_val &= isp16_init();
-#endif CONFIG_ISP16_CDI
-
- return(ret_val);
-}
-
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index 1b55b5319..4f1a2e877 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -1,12 +1,58 @@
-/* cdrom.c. Common ioctl and open routines for various Linux cdrom drivers. -*- linux-c -*-
+/* linux/drivers/cdrom/cdrom.c.
Copyright (c) 1996, 1997 David A. van Leeuwen.
+ Copyright (c) 1997 Erik Andersen (andersee@debian.org)
- The routines in the file should provide an interface between
- software accessing cdroms and the various drivers that implement
- specific hardware devices.
+ May be copied or modified under the terms of the GNU General Public
+ License. See linux/COPYING for more information.
+
+ Uniform CD-ROM driver for Linux.
+ See Documentation/cdrom/cdrom-standard.tex for usage information.
+
+ The routines in the file provide a uniform interface between the
+ software that uses CD-ROMs and the various low-level drivers that
+ actually talk to actual hardware devices. Suggestions are welcome.
+ Patches that work are more welcome though. ;-)
+
+
+ Recent Changes:
+ ----------------------------------
+
+ New maintainer! As David A. van Leeuwen has been too busy to activly
+ maintain and improve this driver, I am now carrying on the torch. If
+ you have a problem with this driver, please feel free to contact me.
+
+ Added (rudimentary) sysctl interface. I realize this is really weak
+ right now, and is _very_ badly implemented. It will be improved... I
+ plan on having one directory per drive, with entries for outputing
+ general drive information, and sysctl based tunable parameters such
+ as whether the tray should auto-close for that drive. Suggestions (or
+ patches) for improvements are very welcome.
+
+ Modified CDROM_DISC_STATUS so that it is now incorporated into
+ the Uniform CD-ROM driver via the cdrom_count_tracks function.
+ The cdrom_count_tracks function helps resolve some of the false
+ assumptions of the CDROM_DISC_STATUS ioctl, and is also used to check
+ for the correct media type when mounting or playing audio from a CD.
+
+ Remove the calls to verify_area and only use the copy_from_user and
+ copy_to_user stuff, since these calls now provide their own memory
+ checking with the 2.1.x kernels.
+
+ Major update to return codes so that errors from low-level drivers
+ are passed on through (thanks to Gerd Knorr for pointing out this
+ problem).
+
+ Made it so if a function isn't implemented in a low-level driver,
+ ENOSYS is now returned instead of EINVAL.
+
+ Simplified some complex logic so that the source code is easier to read.
+
+ Other stuff I probably forgot to mention (lots of changes).
*/
+
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/major.h>
@@ -14,36 +60,50 @@
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/mm.h>
+#include <linux/malloc.h>
+#include <linux/cdrom.h>
+#include <linux/sysctl.h>
#include <asm/fcntl.h>
#include <asm/segment.h>
#include <asm/uaccess.h>
-#include <linux/cdrom.h>
-#include <linux/ucdrom.h>
-
-/* define CHECKTYPE if you want to check for audio/data cdrom. You
- must use cd player programs that respect the O_NONBLOCK option for
- opening the cdrom-device for ioctl-commanding only. (See
- Documentation/cdrom/cdrom-standard.tex). Patches for a number of cd
- players (CDplayer-2.0, cd-console-1.1, workbone-2.3, cdtool-1.0,
- cdp-0.33, cdplayer-0.4, cdthing-1.4, lyn0.8a, playcd-1.0) can be
- found in directory
- ftp://ftp.gwdg.de/pub/linux/cdrom/drivers/cm206/
+#define VERSION "$Id: cdrom.c,v 2.0 1997/11/20 01:58:03 erik Exp $"
+#define REVISION "revision 2.0"
+#define FM_WRITE 0x2 /* file mode write bit */
- A runtime configuration program "checktype.c" to allow for cdrom
- medium type checking can be found at the same location.
+/* When VERBOSE_STATUS_INFO is not defined, the debugging printks don't
+ get compiled in */
+#define VERBOSE_STATUS_INFO
+
+/* I use an error-log mask to give fine grain control over the type of
+ error messages dumped to the system logs. The available masks include: */
+#define CD_WARNING 0x1
+#define CD_REG_UNREG 0x2
+#define CD_DO_IOCTL 0x4
+#define CD_OPEN 0x8
+#define CD_CLOSE 0x10
+
+#define ERRLOGMASK (CD_WARNING)
+/* #define ERRLOGMASK (CD_WARNING|CD_OPEN|CD_CLOSE) */
+/* #define ERRLOGMASK (CD_WARNING|CD_REG_UNREG|CD_DO_IOCTL|CD_OPEN|CD_CLOSE) */
+
+#ifdef VERBOSE_STATUS_INFO
+#define cdinfo(type, fmt, args...) \
+ if (ERRLOGMASK & type) printk(KERN_INFO "cdrom: " fmt, ## args)
+#else
+#define cdinfo(type, fmt, args...)
+#endif
- In order to be able to get neat system errors like "No medium
- found" or "Wrong medium type" upon attempting to mount/play an
- empty slot, mount an audio disc or play a data disc, you need to
- have a new libc.5.so. */
-#undef CHECKTYPE
-#define FM_WRITE 0x2 /* file mode write bit */
+/* These are used to simplify getting data in from and back to user land */
+#define IOCTL_IN(arg, type, in) { \
+ int ret=copy_from_user(&in, (type *) arg, sizeof in); \
+ if (ret) return ret; }
-#define VERSION "$Id: cdrom.c,v 1.7 1997/02/27 22:14:26 david Exp $"
-#define REVISION "$Revision: 1.7 $"
+#define IOCTL_OUT(arg, type, out) { \
+ int ret=copy_to_user((type *) arg, &out, sizeof out); \
+ if (ret) return ret; }
/* Not-exported routines. */
static int cdrom_open(struct inode *ip, struct file *fp);
@@ -51,6 +111,21 @@ static int cdrom_release(struct inode *ip, struct file *fp);
static int cdrom_ioctl(struct inode *ip, struct file *fp,
unsigned int cmd, unsigned long arg);
static int cdrom_media_changed(kdev_t dev);
+static int open_for_data(struct cdrom_device_info * cdi);
+static int check_for_audio_disc(struct cdrom_device_info * cdi,
+ struct cdrom_device_ops * cdo);
+static void sanitize_format(union cdrom_addr *addr,
+ u_char * curr, u_char requested);
+typedef struct {
+ int data;
+ int audio;
+ int cdi;
+ int xa;
+ long error;
+} tracktype;
+
+static void cdrom_count_tracks(struct cdrom_device_info *cdi,tracktype* tracks);
+static struct cdrom_device_info *topCdromPtr = NULL;
struct file_operations cdrom_fops =
{
@@ -69,47 +144,45 @@ struct file_operations cdrom_fops =
NULL /* revalidate */
};
-static struct cdrom_device_info *cdromdevs[MAX_BLKDEV] = {
- NULL,
-};
+void cdrom_init(void) {
+ if (!topCdromPtr)
+ printk(KERN_INFO "Uniform CD-ROM driver " REVISION "\n");
+}
/* This macro makes sure we don't have to check on cdrom_device_ops
* existence in the run-time routines below. Change_capability is a
* hack to have the capability flags defined const, while we can still
* change it here without gcc complaining at every line.
*/
-
#define ENSURE(call, bits) if (cdo->call == NULL) *change_capability &= ~(bits)
-/* We don't use $name$ yet, but it could be used for the /proc
- * filesystem in the future, or for other purposes.
- */
-int register_cdrom(struct cdrom_device_info *cdi, char *name)
+int register_cdrom(struct cdrom_device_info *cdi)
{
int major = MAJOR (cdi->dev);
- struct cdrom_device_ops *cdo = cdi->ops;
- int *change_capability = (int *)&cdo->capability; /* hack */
+ struct cdrom_device_ops *cdo = cdi->ops;
+ int *change_capability = (int *)&cdo->capability; /* hack */
if (major < 0 || major >= MAX_BLKDEV)
return -1;
if (cdo->open == NULL || cdo->release == NULL)
return -2;
+ ENSURE(drive_status, CDC_DRIVE_STATUS );
+ ENSURE(media_changed, CDC_MEDIA_CHANGED);
ENSURE(tray_move, CDC_CLOSE_TRAY | CDC_OPEN_TRAY);
ENSURE(lock_door, CDC_LOCK);
ENSURE(select_speed, CDC_SELECT_SPEED);
ENSURE(select_disc, CDC_SELECT_DISC);
ENSURE(get_last_session, CDC_MULTI_SESSION);
+ ENSURE(get_mcn, CDC_MCN);
+ ENSURE(reset, CDC_RESET);
ENSURE(audio_ioctl, CDC_PLAY_AUDIO);
- ENSURE(media_changed, CDC_MEDIA_CHANGED);
- if (cdromdevs[major]==NULL) cdo->n_minors = 0;
- else cdo->n_minors++;
- cdi->next = cdromdevs[major];
- cdromdevs[major] = cdi;
- cdi->options = CDO_AUTO_CLOSE | CDO_USE_FFLAGS | CDO_LOCK;
-#ifdef CHECKTYPE
- cdi->options |= CDO_CHECK_TYPE;
-#endif
+ ENSURE(dev_ioctl, CDC_IOCTLS);
+ cdi->options = CDO_AUTO_CLOSE | CDO_USE_FFLAGS | CDO_LOCK | CDO_CHECK_TYPE;
cdi->mc_flags = 0;
+ cdo->n_minors = 0;
+ cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" registered\n", cdi->name);
+ cdi->next = topCdromPtr;
+ topCdromPtr = cdi;
return 0;
}
#undef ENSURE
@@ -123,7 +196,7 @@ int unregister_cdrom(struct cdrom_device_info *unreg)
return -1;
prev = NULL;
- cdi = cdromdevs[major];
+ cdi = topCdromPtr;
while (cdi != NULL && cdi->dev != unreg->dev) {
prev = cdi;
cdi = cdi->next;
@@ -134,16 +207,18 @@ int unregister_cdrom(struct cdrom_device_info *unreg)
if (prev)
prev->next = cdi->next;
else
- cdromdevs[major] = cdi->next;
+ topCdromPtr = cdi->next;
cdi->ops->n_minors--;
+ cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" unregistered\n", cdi->name);
return 0;
}
static
struct cdrom_device_info *cdrom_find_device (kdev_t dev)
{
- struct cdrom_device_info *cdi = cdromdevs[MAJOR (dev)];
+ struct cdrom_device_info *cdi;
+ cdi = topCdromPtr;
while (cdi != NULL && cdi->dev != dev)
cdi = cdi->next;
return cdi;
@@ -158,9 +233,6 @@ struct cdrom_device_info *cdrom_find_device (kdev_t dev)
* this way.
*/
static
-int open_for_data(struct cdrom_device_info * cdi);
-
-static
int cdrom_open(struct inode *ip, struct file *fp)
{
kdev_t dev = ip->i_rdev;
@@ -168,6 +240,7 @@ int cdrom_open(struct inode *ip, struct file *fp)
int purpose = !!(fp->f_flags & O_NONBLOCK);
int ret=0;
+ cdinfo(CD_OPEN, "entering cdrom_open\n");
if (cdi == NULL)
return -ENODEV;
if (fp->f_mode & FM_WRITE)
@@ -178,6 +251,7 @@ int cdrom_open(struct inode *ip, struct file *fp)
else
ret = open_for_data(cdi);
if (!ret) cdi->use_count++;
+ cdinfo(CD_OPEN, "Use count for \"/dev/%s\" now %d\n", cdi->name, cdi->use_count);
return ret;
}
@@ -186,58 +260,173 @@ int open_for_data(struct cdrom_device_info * cdi)
{
int ret;
struct cdrom_device_ops *cdo = cdi->ops;
+ tracktype tracks;
+ cdinfo(CD_OPEN, "entering open_for_data\n");
+ /* Check if the driver can report drive status. If it can we
+ can do clever things. If it can't, well, we at least tried! */
if (cdo->drive_status != NULL) {
- int ds = cdo->drive_status(cdi, CDSL_CURRENT);
- if (ds == CDS_TRAY_OPEN) {
+ ret = cdo->drive_status(cdi, CDSL_CURRENT);
+ cdinfo(CD_OPEN, "drive_status=%d\n", ret);
+ if (ret == CDS_TRAY_OPEN) {
+ cdinfo(CD_WARNING, "tray is open...\n");
/* can/may i close it? */
if (cdo->capability & ~cdi->mask & CDC_CLOSE_TRAY &&
cdi->options & CDO_AUTO_CLOSE) {
- if (cdo->tray_move(cdi,0))
- return -EIO;
- } else
- return -ENOMEDIUM; /* can't close: too bad */
- ds = cdo->drive_status(cdi, CDSL_CURRENT);
- if (ds == CDS_NO_DISC)
- return -ENOMEDIUM;
+ ret=cdo->tray_move(cdi,0);
+ if (ret) {
+ cdinfo(CD_WARNING, "bummer. tried to close tray but failed.\n");
+ /* Ignore the error from the low
+ level driver. We don't care why it
+ couldn't close the tray. We only care
+ that there is no disc in the drive,
+ since that is the _REAL_ problem here.*/
+ ret=-ENOMEDIUM;
+ goto clean_up_and_return;
+ }
+ } else {
+ cdinfo(CD_WARNING, "this driver can't close the tray.\n");
+ ret=-ENOMEDIUM;
+ goto clean_up_and_return;
+ }
+ /* Ok, the door should be closed now.. Check again */
+ ret = cdo->drive_status(cdi, CDSL_CURRENT);
+ cdinfo(CD_OPEN, "tried again. drive_status=%d\n", ret);
+ if ((ret == CDS_NO_DISC) || (ret==CDS_TRAY_OPEN)) {
+ ret=-ENOMEDIUM;
+ goto clean_up_and_return;
+ }
}
+ if (ret!=CDS_DISC_OK)
+ goto clean_up_and_return;
}
- if (cdo->disc_status != NULL) {
- int ds = cdo->disc_status(cdi);
- if (ds == CDS_NO_DISC)
- return -ENOMEDIUM;
- if (cdi->options & CDO_CHECK_TYPE &&
- ds != CDS_DATA_1)
- return -EMEDIUMTYPE;
+ cdrom_count_tracks(cdi, &tracks);
+ if (tracks.error == CDS_NO_DISC) {
+ cdinfo(CD_OPEN, "bummer. no disc...\n");
+ ret=-ENOMEDIUM;
+ goto clean_up_and_return;
}
- /* all is well, we can open the device */
+#if 0
+ /* this breaks CD-Players which don't use O_NONBLOCK, workman
+ * for example, probably others too */
+ if (cdi->options & CDO_CHECK_TYPE && tracks.data==0) {
+ cdinfo(CD_OPEN, "bummer. wrong media type...\n");
+ ret=-EMEDIUMTYPE;
+ goto clean_up_and_return;
+ }
+#endif
+
+ cdinfo(CD_OPEN, "all seems well, opening the device...\n");
+
+ /* all seems well, we can open the device */
ret = cdo->open(cdi, 0); /* open for data */
- if (cdo->capability & ~cdi->mask & CDC_LOCK &&
- cdi->options & CDO_LOCK)
- cdo->lock_door(cdi, 1);
+ cdinfo(CD_OPEN, "opening the device gave me %d.\n", ret);
+ /* After all this careful checking, we shouldn't have problems
+ opening the device, but we don't want the device locked if
+ this somehow fails... */
+ if (ret) {
+ cdinfo(CD_OPEN, "open device failed...\n");
+ goto clean_up_and_return;
+ }
+ if (cdo->capability & ~cdi->mask & CDC_LOCK &&
+ cdi->options & CDO_LOCK) {
+ cdo->lock_door(cdi, 1);
+ cdinfo(CD_OPEN, "door locked.\n");
+ }
+ cdinfo(CD_OPEN, "device opened sucessfully.\n");
+ return ret;
+
+ /* Something failed. Try to unlock the drive, because some drivers
+ (notably ide-cd) lock the drive after every command. This produced
+ a nasty bug where after mount failed, the drive would remain locked!
+ This ensures that the drive gets unlocked after a mount fails. This
+ is a goto to avoid adding bloating the driver with redundant code. */
+clean_up_and_return:
+ cdinfo(CD_WARNING, "failed to open the device.\n");
+ if (cdo->capability & ~cdi->mask & CDC_LOCK &&
+ cdi->options & CDO_LOCK) {
+ cdo->lock_door(cdi, 0);
+ cdinfo(CD_WARNING, "door unlocked.\n");
+ }
return ret;
}
+/* This code is similar to that in open_for_data. The routine is called
+ in case a audio play operation is requested. It doesn't make much sense
+ to do this on a data disc.
+*/
+int check_for_audio_disc(struct cdrom_device_info * cdi,
+ struct cdrom_device_ops * cdo)
+{
+ int ret;
+ tracktype tracks;
+ cdinfo(CD_OPEN, "entering check_for_audio_disc\n");
+ if (!(cdi->options & CDO_CHECK_TYPE))
+ return 0;
+ if (cdo->drive_status != NULL) {
+ ret = cdo->drive_status(cdi, CDSL_CURRENT);
+ cdinfo(CD_OPEN, "drive_status=%d\n", ret);
+ if (ret == CDS_TRAY_OPEN) {
+ cdinfo(CD_WARNING, "tray is open...\n");
+ /* can/may i close it? */
+ if (cdo->capability & ~cdi->mask & CDC_CLOSE_TRAY &&
+ cdi->options & CDO_AUTO_CLOSE) {
+ ret=cdo->tray_move(cdi,0);
+ if (ret) {
+ cdinfo(CD_WARNING, "bummer. tried to close tray but failed.\n");
+ /* Ignore the error from the low
+ level driver. We don't care why it
+ couldn't close the tray. We only care
+ that there is no disc in the drive,
+ since that is the _REAL_ problem here.*/
+ return -ENOMEDIUM;
+ }
+ } else {
+ cdinfo(CD_WARNING, "this driver can't close the tray.\n");
+ return -ENOMEDIUM;
+ }
+ /* Ok, the door should be closed now.. Check again */
+ ret = cdo->drive_status(cdi, CDSL_CURRENT);
+ cdinfo(CD_OPEN, "tried again. drive_status=%d\n", ret);
+ if ((ret == CDS_NO_DISC) || (ret==CDS_TRAY_OPEN))
+ return -ENOMEDIUM;
+ if (ret!=CDS_DISC_OK)
+ return -EIO;
+ }
+ }
+ cdrom_count_tracks(cdi, &tracks);
+ if (tracks.error)
+ return(tracks.error);
+
+ if (tracks.audio==0)
+ return -EMEDIUMTYPE;
+
+ return 0;
+}
+
+
/* Admittedly, the logic below could be performed in a nicer way. */
static
int cdrom_release(struct inode *ip, struct file *fp)
{
kdev_t dev = ip->i_rdev;
struct cdrom_device_info *cdi = cdrom_find_device (dev);
- struct cdrom_device_ops *cdo;
+ struct cdrom_device_ops *cdo = cdi->ops;
int opened_for_data;
+ cdinfo(CD_CLOSE, "entering cdrom_release\n");
if (cdi == NULL)
return 0;
+ if (cdi->use_count > 0) cdi->use_count--;
+ if (cdi->use_count == 0)
+ cdinfo(CD_CLOSE, "Use count for \"/dev/%s\" now zero\n", cdi->name);
+ if (cdi->use_count == 0 && /* last process that closes dev*/
+ cdo->capability & CDC_LOCK) {
+ cdinfo(CD_CLOSE, "Unlocking door!\n");
+ cdo->lock_door(cdi, 0);
+ }
opened_for_data = !(cdi->options & CDO_USE_FFLAGS) ||
!(fp && fp->f_flags & O_NONBLOCK);
- cdo = cdi->ops;
- if (cdi->use_count == 1 && /* last process that closes dev*/
- opened_for_data &&
- cdi->options & CDO_LOCK &&
- cdo->capability & ~cdi->mask & CDC_LOCK)
- cdo->lock_door(cdi, 0);
cdo->release(cdi);
- if (cdi->use_count > 0) cdi->use_count--;
if (cdi->use_count == 0) { /* last process that closes dev*/
sync_dev(dev);
invalidate_buffers(dev);
@@ -277,10 +466,57 @@ int cdrom_media_changed(kdev_t dev)
if (cdi == NULL)
return -ENODEV;
if (cdi->ops->media_changed == NULL)
- return -EINVAL;
+ return -ENOSYS;
return media_changed(cdi, 0);
}
+static
+void cdrom_count_tracks(struct cdrom_device_info *cdi, tracktype* tracks)
+{
+ struct cdrom_tochdr header;
+ struct cdrom_tocentry entry;
+ int ret, i;
+ tracks->data=0;
+ tracks->audio=0;
+ tracks->cdi=0;
+ tracks->xa=0;
+ tracks->error=0;
+ cdinfo(CD_OPEN, "entering cdrom_count_tracks\n");
+ if (!(cdi->ops->capability & CDC_PLAY_AUDIO)) {
+ tracks->error=CDS_NO_INFO;
+ return;
+ }
+ /* Grab the TOC header so we can see how many tracks there are */
+ ret=cdi->ops->audio_ioctl(cdi, CDROMREADTOCHDR, &header);
+ if (ret) {
+ tracks->error=(ret == -ENOMEDIUM) ? CDS_NO_DISC : CDS_NO_INFO;
+ return;
+ }
+ /* check what type of tracks are on this disc */
+ entry.cdte_format = CDROM_MSF;
+ for (i = header.cdth_trk0; i <= header.cdth_trk1; i++) {
+ entry.cdte_track = i;
+ if (cdi->ops->audio_ioctl(cdi, CDROMREADTOCENTRY, &entry)) {
+ tracks->error=CDS_NO_INFO;
+ return;
+ }
+ if (entry.cdte_ctrl & CDROM_DATA_TRACK) {
+ if (entry.cdte_format == 0x10)
+ tracks->cdi++;
+ else if (entry.cdte_format == 0x20)
+ tracks->xa++;
+ else
+ tracks->data++;
+ } else
+ tracks->audio++;
+ cdinfo(CD_OPEN, "track %d: format=%d, ctrl=%d\n",
+ i, entry.cdte_format, entry.cdte_ctrl);
+ }
+ cdinfo(CD_OPEN, "disc has %d tracks: %d=audio %d=data %d=Cd-I %d=XA\n",
+ header.cdth_trk1, tracks->audio, tracks->data,
+ tracks->cdi, tracks->xa);
+}
+
/* Requests to the low-level drivers will /always/ be done in the
following format convention:
@@ -317,21 +553,6 @@ void sanitize_format(union cdrom_addr *addr,
*curr = requested;
}
-/* All checking and format change makes this code really hard to read!
- * So let's make some check and memory move macros. These macros are
- * a little inefficient when both used in the same piece of code, as
- * verify_area is used twice, but who cares, as ioctl() calls
- * shouldn't be in inner loops.
- */
-#define GETARG(type, x) { \
- int ret=verify_area(VERIFY_READ, (void *) arg, sizeof x); \
- if (ret) return ret; \
- copy_from_user(&x, (type *) arg, sizeof x); }
-#define PUTARG(type, x) { \
- int ret=verify_area(VERIFY_WRITE, (void *) arg, sizeof x); \
- if (ret) return ret; \
- copy_to_user((type *) arg, &x, sizeof x); }
-
/* Some of the cdrom ioctls are not implemented here, because these
* appear to be either too device-specific, or it is not clear to me
* what use they are. These are (number of drivers that support them
@@ -346,10 +567,6 @@ void sanitize_format(union cdrom_addr *addr,
* memory-verification is performed for these ioctls.
*/
static
-int check_for_audio_disc(struct cdrom_device_info * cdi,
- struct cdrom_device_ops * cdo);
-
-static
int cdrom_ioctl(struct inode *ip, struct file *fp,
unsigned int cmd, unsigned long arg)
{
@@ -360,85 +577,103 @@ int cdrom_ioctl(struct inode *ip, struct file *fp,
if (cdi == NULL)
return -ENODEV;
cdo = cdi->ops;
- /* the first few commands do not deal with audio capabilities, but
+
+ /* the first few commands do not deal with audio drive_info, but
only with routines in cdrom device operations. */
switch (cmd) {
/* maybe we should order cases after statistics of use? */
- case CDROMMULTISESSION:
- {
+ case CDROMMULTISESSION: {
+ int ret;
struct cdrom_multisession ms_info;
u_char requested_format;
- if (!(cdo->capability & CDC_MULTI_SESSION))
- return -EINVAL;
- GETARG(struct cdrom_multisession, ms_info);
+ cdinfo(CD_DO_IOCTL, "entering CDROMMULTISESSION\n");
+ if (!(cdo->capability & CDC_MULTI_SESSION))
+ return -ENOSYS;
+ IOCTL_IN(arg, struct cdrom_multisession, ms_info);
requested_format = ms_info.addr_format;
+ if (!((requested_format == CDROM_MSF) ||
+ (requested_format == CDROM_LBA)))
+ return -EINVAL;
ms_info.addr_format = CDROM_LBA;
- cdo->get_last_session(cdi, &ms_info);
+ if ((ret=cdo->get_last_session(cdi, &ms_info)))
+ return ret;
sanitize_format(&ms_info.addr, &ms_info.addr_format,
requested_format);
- PUTARG(struct cdrom_multisession, ms_info);
+ IOCTL_OUT(arg, struct cdrom_multisession, ms_info);
+ cdinfo(CD_DO_IOCTL, "CDROMMULTISESSION sucessful\n");
return 0;
- }
+ }
- case CDROMEJECT:
- if (cdo->capability & ~cdi->mask & CDC_OPEN_TRAY) {
- if (cdi->use_count == 1) {
- if (cdo->capability & ~cdi->mask & CDC_LOCK)
- cdo->lock_door(cdi, 0);
- return cdo->tray_move(cdi, 1);
- } else
- return -EBUSY;
- } else
- return -EINVAL;
+ case CDROMEJECT: {
+ int ret;
+ cdinfo(CD_DO_IOCTL, "entering CDROMEJECT\n");
+ if (!(cdo->capability & ~cdi->mask & CDC_OPEN_TRAY))
+ return -ENOSYS;
+ if (cdi->use_count != 1)
+ return -EBUSY;
+ if (cdo->capability & ~cdi->mask & CDC_LOCK) {
+ if ((ret=cdo->lock_door(cdi, 0)))
+ return ret;
+ }
+ return cdo->tray_move(cdi, 1);
+ }
case CDROMCLOSETRAY:
- if (cdo->capability & ~cdi->mask & CDC_CLOSE_TRAY)
- return cdo->tray_move(cdi, 0);
- else
- return -EINVAL;
+ cdinfo(CD_DO_IOCTL, "entering CDROMCLOSETRAY\n");
+ if (!(cdo->capability & ~cdi->mask & CDC_OPEN_TRAY))
+ return -ENOSYS;
+ return cdo->tray_move(cdi, 0);
case CDROMEJECT_SW:
+ cdinfo(CD_DO_IOCTL, "entering CDROMEJECT_SW\n");
cdi->options &= ~(CDO_AUTO_CLOSE | CDO_AUTO_EJECT);
if (arg)
cdi->options |= CDO_AUTO_CLOSE | CDO_AUTO_EJECT;
return 0;
- case CDROM_MEDIA_CHANGED:
- if (cdo->capability & ~cdi->mask & CDC_MEDIA_CHANGED) {
- if (!(cdo->capability & ~cdi->mask & CDC_SELECT_DISC)
- || arg == CDSL_CURRENT)
- /* cannot select disc or select current disc */
- return media_changed(cdi, 1);
- if ((unsigned int)arg < cdi->capacity)
- return cdo->media_changed (cdi, arg);
- return -EINVAL;
- } else
+ case CDROM_MEDIA_CHANGED: {
+ cdinfo(CD_DO_IOCTL, "entering CDROM_MEDIA_CHANGED\n");
+ if (!(cdo->capability & ~cdi->mask & CDC_MEDIA_CHANGED))
+ return -ENOSYS;
+ if (!(cdo->capability & ~cdi->mask & CDC_SELECT_DISC)
+ || arg == CDSL_CURRENT)
+ /* cannot select disc or select current disc */
+ return media_changed(cdi, 1);
+ if ((unsigned int)arg >= cdi->capacity)
return -EINVAL;
+ return cdo->media_changed (cdi, arg);
+ }
case CDROM_SET_OPTIONS:
+ cdinfo(CD_DO_IOCTL, "entering CDROM_SET_OPTIONS\n");
cdi->options |= (int) arg;
return cdi->options;
case CDROM_CLEAR_OPTIONS:
+ cdinfo(CD_DO_IOCTL, "entering CDROM_CLEAR_OPTIONS\n");
cdi->options &= ~(int) arg;
return cdi->options;
- case CDROM_SELECT_SPEED:
- if ((int)arg <= cdi->speed &&
- cdo->capability & ~cdi->mask & CDC_SELECT_SPEED)
- return cdo->select_speed(cdi, arg);
- else
+ case CDROM_SELECT_SPEED: {
+ cdinfo(CD_DO_IOCTL, "entering CDROM_SELECT_SPEED\n");
+ if (!(cdo->capability & ~cdi->mask & CDC_SELECT_SPEED))
+ return -ENOSYS;
+ if ((int)arg > cdi->speed )
return -EINVAL;
+ return cdo->select_speed(cdi, arg);
+ }
- case CDROM_SELECT_DISC:
- if ((arg == CDSL_CURRENT) || (arg == CDSL_NONE))
- return cdo->select_disc(cdi, arg);
- if ((int)arg < cdi->capacity &&
- cdo->capability & ~cdi->mask & CDC_SELECT_DISC)
+ case CDROM_SELECT_DISC: {
+ cdinfo(CD_DO_IOCTL, "entering CDROM_SELECT_DISC\n");
+ if (!(cdo->capability & ~cdi->mask & CDC_SELECT_DISC))
+ return -ENOSYS;
+ if ((arg == CDSL_CURRENT) || (arg == CDSL_NONE))
return cdo->select_disc(cdi, arg);
- else
- return -EINVAL;
+ if ((int)arg >= cdi->capacity)
+ return -EDRIVE_CANT_DO_THIS;
+ return cdo->select_disc(cdi, arg);
+ }
/* The following function is implemented, although very few audio
* discs give Universal Product Code information, which should just be
@@ -446,51 +681,82 @@ int cdrom_ioctl(struct inode *ip, struct file *fp,
* is written on the CD is /not/ uniform across all discs!
*/
case CDROM_GET_MCN: {
+ int ret;
struct cdrom_mcn mcn;
+ cdinfo(CD_DO_IOCTL, "entering CDROM_GET_MCN\n");
if (!(cdo->capability & CDC_MCN))
- return -EINVAL;
- if (!cdo->get_mcn(cdi, &mcn)) {
- PUTARG(struct cdrom_mcn, mcn);
- return 0;
+ return -ENOSYS;
+ if ((ret=cdo->get_mcn(cdi, &mcn)))
+ return ret;
+ IOCTL_OUT(arg, struct cdrom_mcn, mcn);
+ cdinfo(CD_DO_IOCTL, "CDROM_GET_MCN sucessful\n");
+ return 0;
}
- return -EINVAL;
- }
- case CDROM_DRIVE_STATUS:
- if ((arg == CDSL_CURRENT) || (arg == CDSL_NONE))
+ case CDROM_DRIVE_STATUS: {
+ cdinfo(CD_DO_IOCTL, "entering CDROM_DRIVE_STATUS\n");
+ if (!(cdo->capability & CDC_DRIVE_STATUS))
+ return -ENOSYS;
+ if ((arg == CDSL_CURRENT) || (arg == CDSL_NONE))
return cdo->drive_status(cdi, arg);
- if (cdo->drive_status == NULL ||
- ((cdo->capability & ~cdi->mask & CDC_SELECT_DISC)
- && (int)arg >= cdi->capacity))
+ if (((int)arg > cdi->capacity))
return -EINVAL;
- else
- return cdo->drive_status(cdi, arg);
+ return cdo->drive_status(cdi, arg);
+ }
- case CDROM_DISC_STATUS:
- if (cdo->disc_status == NULL)
- return -EINVAL;
- else
- return cdo->disc_status(cdi);
+ /* Ok, this is where problems start. The current interface for the
+ CDROM_DISC_STATUS ioctl is flawed. It makes the false assumption
+ that CDs are all CDS_DATA_1 or all CDS_AUDIO, etc. Unfortunatly,
+ while this is often the case, it is also very common for CDs to
+ have some tracks with data, and some tracks with audio. Just
+ because I feel like it, I declare the following to be the best
+ way to cope. If the CD has ANY data tracks on it, it will be
+ returned as a data CD. If it has any XA tracks, I will return
+ it as that. Now I could simplify this interface by combining these
+ returns with the above, but this more clearly demonstrates
+ the problem with the current interface. Too bad this wasn't
+ designed to use bitmasks... -Erik
+ */
+ case CDROM_DISC_STATUS: {
+ tracktype tracks;
+ cdinfo(CD_DO_IOCTL, "entering CDROM_DISC_STATUS\n");
+ cdrom_count_tracks(cdi, &tracks);
+ if (tracks.error)
+ return(tracks.error);
+
+ /* Policy mode on */
+ if (tracks.audio>0 && tracks.data==0 && tracks.cdi==0 && tracks.xa==0)
+ return CDS_AUDIO;
+ if (tracks.cdi>0) return CDS_XA_2_2;
+ if (tracks.xa>0) return CDS_XA_2_1;
+ if (tracks.data>0) return CDS_DATA_1;
+ /* Policy mode off */
+
+ cdinfo(CD_WARNING,"This disc doesn't have any tracks I recognise!\n");
+ return CDS_NO_INFO;
+ }
case CDROM_CHANGER_NSLOTS:
- return cdi->capacity;
+ cdinfo(CD_DO_IOCTL, "entering CDROM_CHANGER_NSLOTS\n");
+ return cdi->capacity;
/* The following is not implemented, because there are too many
- * different data type. We could support /1/ raw mode, that is large
+ * different data types. We could support /1/ raw mode, that is large
* enough to hold everything.
*/
#if 0
case CDROMREADMODE1: {
+ int ret;
struct cdrom_msf msf;
char buf[CD_FRAMESIZE];
- GETARG(struct cdrom_msf, msf);
- if (!cdo->read_audio(dev, cmd, &msf, &buf, cdi)) {
- PUTARG(char *, buf);
- return 0;
+ cdinfo(CD_DO_IOCTL, "entering CDROMREADMODE1\n");
+ IOCTL_IN(arg, struct cdrom_msf, msf);
+ if (ret=cdo->read_audio(dev, cmd, &msf, &buf, cdi))
+ return ret;
+ IOCTL_OUT(arg, __typeof__(buf), buf);
+ return 0;
}
- return -EINVAL;
- }
#endif
} /* switch */
@@ -499,144 +765,261 @@ int cdrom_ioctl(struct inode *ip, struct file *fp,
#define CHECKAUDIO if ((ret=check_for_audio_disc(cdi, cdo))) return ret
- if (cdo->capability & CDC_PLAY_AUDIO) {
- int ret;
+ if (!(cdo->capability & CDC_PLAY_AUDIO))
+ return -ENOSYS;
+ else {
switch (cmd) {
- case CDROMSUBCHNL:
- {
+ case CDROMSUBCHNL: {
+ int ret;
struct cdrom_subchnl q;
u_char requested, back;
- GETARG(struct cdrom_subchnl, q);
+ /* comment out the cdinfo calls here because they
+ fill up the sys logs when CD players poll the drive*/
+ /* cdinfo(CD_DO_IOCTL,"entering CDROMSUBCHNL\n");*/
+ IOCTL_IN(arg, struct cdrom_subchnl, q);
requested = q.cdsc_format;
+ if (!((requested == CDROM_MSF) ||
+ (requested == CDROM_LBA)))
+ return -EINVAL;
q.cdsc_format = CDROM_MSF;
- if (!cdo->audio_ioctl(cdi, cmd, &q)) {
- back = q.cdsc_format; /* local copy */
- sanitize_format(&q.cdsc_absaddr, &back,
- requested);
- sanitize_format(&q.cdsc_reladdr,
- &q.cdsc_format, requested);
- PUTARG(struct cdrom_subchnl, q);
- return 0;
- } else
- return -EINVAL;
- }
+ if ((ret=cdo->audio_ioctl(cdi, cmd, &q)))
+ return ret;
+ back = q.cdsc_format; /* local copy */
+ sanitize_format(&q.cdsc_absaddr, &back, requested);
+ sanitize_format(&q.cdsc_reladdr, &q.cdsc_format, requested);
+ IOCTL_OUT(arg, struct cdrom_subchnl, q);
+ /* cdinfo(CD_DO_IOCTL, "CDROMSUBCHNL sucessful\n"); */
+ return 0;
+ }
case CDROMREADTOCHDR: {
+ int ret;
struct cdrom_tochdr header;
- GETARG(struct cdrom_tochdr, header);
- CHECKAUDIO;
- if (!cdo->audio_ioctl(cdi, cmd, &header)) {
- PUTARG(struct cdrom_tochdr, header);
- return 0;
- } else
- return -EINVAL;
- }
+ /* comment out the cdinfo calls here because they
+ fill up the sys logs when CD players poll the drive*/
+ /* cdinfo(CD_DO_IOCTL, "entering CDROMREADTOCHDR\n"); */
+ IOCTL_IN(arg, struct cdrom_tochdr, header);
+ if ((ret=cdo->audio_ioctl(cdi, cmd, &header)))
+ return ret;
+ IOCTL_OUT(arg, struct cdrom_tochdr, header);
+ /* cdinfo(CD_DO_IOCTL, "CDROMREADTOCHDR sucessful\n"); */
+ return 0;
+ }
case CDROMREADTOCENTRY: {
+ int ret;
struct cdrom_tocentry entry;
u_char requested_format;
- GETARG(struct cdrom_tocentry, entry);
+ /* comment out the cdinfo calls here because they
+ fill up the sys logs when CD players poll the drive*/
+ /* cdinfo(CD_DO_IOCTL, "entering CDROMREADTOCENTRY\n"); */
+ IOCTL_IN(arg, struct cdrom_tocentry, entry);
requested_format = entry.cdte_format;
+ if (!((requested_format == CDROM_MSF) ||
+ (requested_format == CDROM_LBA)))
+ return -EINVAL;
/* make interface to low-level uniform */
entry.cdte_format = CDROM_MSF;
- if (!(cdo->audio_ioctl(cdi, cmd, &entry))) {
- sanitize_format(&entry.cdte_addr,
- &entry.cdte_format, requested_format);
- PUTARG(struct cdrom_tocentry, entry);
- return 0;
- } else
- return -EINVAL;
- }
+ if ((ret=cdo->audio_ioctl(cdi, cmd, &entry)))
+ return ret;
+ sanitize_format(&entry.cdte_addr,
+ &entry.cdte_format, requested_format);
+ IOCTL_OUT(arg, struct cdrom_tocentry, entry);
+ /* cdinfo(CD_DO_IOCTL, "CDROMREADTOCENTRY sucessful\n"); */
+ return 0;
+ }
case CDROMPLAYMSF: {
+ int ret;
struct cdrom_msf msf;
- GETARG(struct cdrom_msf, msf);
+ cdinfo(CD_DO_IOCTL, "entering CDROMPLAYMSF\n");
+ IOCTL_IN(arg, struct cdrom_msf, msf);
CHECKAUDIO;
return cdo->audio_ioctl(cdi, cmd, &msf);
- }
+ }
case CDROMPLAYTRKIND: {
- struct cdrom_ti track_index;
- GETARG(struct cdrom_ti, track_index);
+ int ret;
+ struct cdrom_ti ti;
+ cdinfo(CD_DO_IOCTL, "entering CDROMPLAYTRKIND\n");
+ IOCTL_IN(arg, struct cdrom_ti, ti);
CHECKAUDIO;
- return cdo->audio_ioctl(cdi, cmd, &track_index);
- }
+ return cdo->audio_ioctl(cdi, cmd, &ti);
+ }
case CDROMVOLCTRL: {
struct cdrom_volctrl volume;
- GETARG(struct cdrom_volctrl, volume);
+ cdinfo(CD_DO_IOCTL, "entering CDROMVOLCTRL\n");
+ IOCTL_IN(arg, struct cdrom_volctrl, volume);
return cdo->audio_ioctl(cdi, cmd, &volume);
- }
+ }
case CDROMVOLREAD: {
+ int ret;
struct cdrom_volctrl volume;
- if (!cdo->audio_ioctl(cdi, cmd, &volume)) {
- PUTARG(struct cdrom_volctrl, volume);
- return 0;
+ cdinfo(CD_DO_IOCTL, "entering CDROMVOLREAD\n");
+ if ((ret=cdo->audio_ioctl(cdi, cmd, &volume)))
+ return ret;
+ IOCTL_OUT(arg, struct cdrom_volctrl, volume);
+ return 0;
}
- return -EINVAL;
- }
case CDROMSTART:
- CHECKAUDIO;
case CDROMSTOP:
case CDROMPAUSE:
- case CDROMRESUME:
+ case CDROMRESUME: {
+ int ret;
+ cdinfo(CD_DO_IOCTL, "doing audio ioctl (start/stop/pause/resume)\n");
+ CHECKAUDIO;
return cdo->audio_ioctl(cdi, cmd, NULL);
+ }
} /* switch */
}
- if (cdo->dev_ioctl != NULL) /* device specific ioctls? */
+ /* device specific ioctls? */
+ if (!(cdo->capability & CDC_IOCTLS))
+ return -ENOSYS;
+ else
return cdo->dev_ioctl(cdi, cmd, arg);
- return -EINVAL;
-}
-
-/* This code is similar to that in open_for_data. The routine is called
- in case a audio play operation is requested. It doesn't make much sense
- do do this on a data disc.
- */
-int check_for_audio_disc(struct cdrom_device_info * cdi,
- struct cdrom_device_ops * cdo)
-{
- if (!(cdi->options & CDO_CHECK_TYPE))
- return 0;
- if (cdo->drive_status != NULL) {
- int ds = cdo->drive_status(cdi, CDSL_CURRENT);
- if (ds == CDS_TRAY_OPEN) {
- /* can/may i close it? */
- if (cdo->capability & ~cdi->mask & CDC_CLOSE_TRAY &&
- cdi->options & CDO_AUTO_CLOSE) {
- if (cdo->tray_move(cdi,0))
- return -EIO;
- } else
- return -ENOMEDIUM; /* can't close: too bad */
- ds = cdo->drive_status(cdi, CDSL_CURRENT);
- if (ds == CDS_NO_DISC)
- return -ENOMEDIUM;
- }
- if (cdo->disc_status != NULL) {
- ds = cdo->disc_status(cdi);
- if (ds == CDS_NO_DISC)
- return -ENOMEDIUM;
- if (ds != CDS_AUDIO)
- return -EMEDIUMTYPE;
- }
- }
- return 0;
}
EXPORT_SYMBOL(register_cdrom);
EXPORT_SYMBOL(unregister_cdrom);
EXPORT_SYMBOL(cdrom_fops);
+#ifdef CONFIG_SYSCTL
+
+#define CDROM_STR_SIZE 1000
+
+static char cdrom_drive_info[CDROM_STR_SIZE]="info\n";
+
+int cdrom_sysctl_info(ctl_table *ctl, int write, struct file * filp,
+ void *buffer, size_t *lenp)
+{
+ int retv,pos;
+ struct cdrom_device_info *cdi;
+
+ pos = sprintf(cdrom_drive_info, "CD-ROM information\n");
+
+ pos += sprintf(cdrom_drive_info+pos, "\ndrive name:\t");
+ for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
+ pos += sprintf(cdrom_drive_info+pos, "\t%s", cdi->name);
+
+ pos += sprintf(cdrom_drive_info+pos, "\ndrive speed:\t");
+ for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
+ pos += sprintf(cdrom_drive_info+pos, "\t%d", cdi->speed);
+
+ pos += sprintf(cdrom_drive_info+pos, "\ndrive # of slots:");
+ for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
+ pos += sprintf(cdrom_drive_info+pos, "\t%d", cdi->capacity);
+
+ pos += sprintf(cdrom_drive_info+pos, "\nCan close tray:\t");
+ for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
+ pos += sprintf(cdrom_drive_info+pos, "\t%d",
+ ((cdi->ops->capability & CDC_CLOSE_TRAY)!=0));
+
+ pos += sprintf(cdrom_drive_info+pos, "\nCan open tray:\t");
+ for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
+ pos += sprintf(cdrom_drive_info+pos, "\t%d",
+ ((cdi->ops->capability & CDC_OPEN_TRAY)!=0));
+
+ pos += sprintf(cdrom_drive_info+pos, "\nCan lock tray:\t");
+ for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
+ pos += sprintf(cdrom_drive_info+pos, "\t%d",
+ ((cdi->ops->capability & CDC_LOCK)!=0));
+
+ pos += sprintf(cdrom_drive_info+pos, "\nCan change speed:");
+ for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
+ pos += sprintf(cdrom_drive_info+pos, "\t%d",
+ ((cdi->ops->capability & CDC_SELECT_SPEED)!=0));
+
+ pos += sprintf(cdrom_drive_info+pos, "\nCan select disk:");
+ for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
+ pos += sprintf(cdrom_drive_info+pos, "\t%d",
+ ((cdi->ops->capability & CDC_SELECT_DISC)!=0));
+
+ pos += sprintf(cdrom_drive_info+pos, "\nCan read multisession:");
+ for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
+ pos += sprintf(cdrom_drive_info+pos, "\t%d",
+ ((cdi->ops->capability & CDC_MULTI_SESSION)!=0));
+
+ pos += sprintf(cdrom_drive_info+pos, "\nCan read MCN:\t");
+ for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
+ pos += sprintf(cdrom_drive_info+pos, "\t%d",
+ ((cdi->ops->capability & CDC_MCN)!=0));
+
+ pos += sprintf(cdrom_drive_info+pos, "\nReports media changed:");
+ for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
+ pos += sprintf(cdrom_drive_info+pos, "\t%d",
+ ((cdi->ops->capability & CDC_MEDIA_CHANGED)!=0));
+
+ pos += sprintf(cdrom_drive_info+pos, "\nCan play audio:\t");
+ for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
+ pos += sprintf(cdrom_drive_info+pos, "\t%d",
+ ((cdi->ops->capability & CDC_PLAY_AUDIO)!=0));
+
+ strcpy(cdrom_drive_info+pos,"\n\n");
+ *lenp=pos+3;
+ if (!write) {
+ retv = proc_dostring(ctl, write, filp, buffer, lenp);
+ }
+ else
+ retv = proc_dostring(ctl, write, filp, buffer, lenp);
+ return retv;
+}
+
+/* Place files in /proc/sys/dev/cdrom */
+ctl_table cdrom_table[] = {
+ {DEV_CDROM_INFO, "info", &cdrom_drive_info,
+ CDROM_STR_SIZE*sizeof(char), 0444, NULL, &cdrom_sysctl_info},
+ {0}
+ };
+
+ctl_table cdrom_cdrom_table[] = {
+ {DEV_CDROM, "cdrom", NULL, 0, 0555, cdrom_table},
+ {0}
+ };
+
+/* Make sure that /proc/sys/dev is there */
+ctl_table cdrom_root_table[] = {
+ {CTL_DEV, "dev", NULL, 0, 0555, cdrom_cdrom_table},
+ {0}
+ };
+
+#endif /* endif CONFIG_SYSCTL */
+
+
#ifdef MODULE
+
+#ifdef CONFIG_SYSCTL
+
+static struct ctl_table_header *cdrom_sysctl_header;
+
+static void cdrom_sysctl_register(void)
+{
+ cdrom_sysctl_header = register_sysctl_table(cdrom_root_table, 0);
+}
+
+static void cdrom_sysctl_unregister(void)
+{
+ unregister_sysctl_table(cdrom_sysctl_header);
+}
+#endif /* endif CONFIG_SYSCTL */
+
int init_module(void)
{
- printk(KERN_INFO "Module cdrom: Generic CDROM driver " REVISION "\n");
+ cdrom_init();
+#ifdef CONFIG_SYSCTL
+ cdrom_sysctl_register();
+#endif /* CONFIG_SYSCTL */
return 0;
}
void cleanup_module(void)
{
- /*
- printk(KERN_INFO "Module cdrom removed\n");
- */
+ printk(KERN_INFO "Uniform CD-ROM driver unloaded\n");
+#ifdef CONFIG_SYSCTL
+ cdrom_sysctl_unregister();
+#endif /* CONFIG_SYSCTL */
}
-#endif
+#endif /* endif MODULE */
+
+
+
/*
* Local variables:
* comment-column: 40
diff --git a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c
index 8e4960525..231e00548 100644
--- a/drivers/cdrom/cdu31a.c
+++ b/drivers/cdrom/cdu31a.c
@@ -111,6 +111,13 @@
* Heiko Eissfeldt <heiko@colossus.escape.de>
* For finding abug in the return of the track numbers.
*/
+/* conversion to Uniform cdrom layer.
+ TOC processing redone for proper multisession support.
+
+ TODO:
+ CDs with form1 and form2 sectors cause problems
+ with current read-ahead strategy.
+ Heiko Eissfeldt Sep 97 */
/*
*
@@ -173,7 +180,13 @@
* status and be reset. It recovers, though.
*
* 03/07/97 - Fixed a problem with timers.
- */
+ *
+ *
+ * 18 Spetember 1997 -- Ported to Uniform CD-ROM driver by
+ * Heiko Eissfeldt <heiko@colossus.escape.de> with additional
+ * changes by Erik Andersen <andersee@debian.org>
+ *
+*/
#include <linux/major.h>
@@ -198,16 +211,16 @@
#include <asm/dma.h>
#include <linux/cdrom.h>
-#include <linux/cdu31a.h>
+#include "cdu31a.h"
#define MAJOR_NR CDU31A_CDROM_MAJOR
#include <linux/blk.h>
-#define DEBUG 0
-
-#define CDU31A_READAHEAD 128 /* 128 sector, 64kB, 32 reads read-ahead */
+#define CDU31A_READAHEAD 4 /* 128 sector, 64kB, 32 reads read-ahead */
#define CDU31A_MAX_CONSECUTIVE_ATTENTIONS 10
+#define DEBUG 0
+
/* Define the following if you have data corruption problems. */
#undef SONY_POLL_EACH_BYTE
@@ -240,7 +253,8 @@ static struct
static int handle_sony_cd_attention(void);
static int read_subcode(void);
static void sony_get_toc(void);
-static int scd_open(struct inode *inode, struct file *filp);
+/*static int scd_open(struct inode *inode, struct file *filp);*/
+static int scd_open(struct cdrom_device_info *, int);
static void do_sony_cd_cmd(unsigned char cmd,
unsigned char *params,
unsigned int num_params,
@@ -276,6 +290,8 @@ static volatile unsigned short sony_cd_fifost_reg;
static int sony_spun_up = 0; /* Has the drive been spun up? */
+static int sony_speed = 0; /* Last wanted speed */
+
static int sony_xa_mode = 0; /* Is an XA disk in the drive
and the drive a CDU31A? */
@@ -288,9 +304,12 @@ static unsigned int sony_usage = 0; /* How many processes have the
static int sony_pas_init = 0; /* Initialize the Pro-Audio
Spectrum card? */
-static struct s_sony_session_toc sony_toc; /* Holds the
- table of
- contents. */
+static struct s_sony_session_toc single_toc; /* Holds the
+ table of
+ contents. */
+
+static struct s_all_sessions_toc sony_toc; /* entries gathered from all
+ sessions */
static int sony_toc_read = 0; /* Has the TOC been read for
the drive? */
@@ -307,7 +326,8 @@ static struct task_struct *has_cd_task = NULL; /* The task that is currently
using the CDROM drive, or
NULL if none. */
-static int is_double_speed = 0; /* Is the drive a CDU33A? */
+static int is_double_speed = 0; /* does the drive support double speed ? */
+static int is_a_cdu31a = 1; /* Is the drive a CDU31A? */
static int is_auto_eject = 1; /* Door has been locked? 1=No/0=Yes */
@@ -375,6 +395,30 @@ scd_disk_change(kdev_t full_dev)
return retval;
}
+/*
+ * Uniform cdrom interface function
+ * report back, if disc has changed from time of last request.
+ */
+static int
+scd_media_changed(struct cdrom_device_info *cdi, int disc_nr)
+{
+ return scd_disk_change(cdi->dev);
+}
+
+/*
+ * Uniform cdrom interface function
+ * report back, if drive is ready
+ */
+static int scd_drive_status(struct cdrom_device_info *cdi, int slot_nr)
+{
+ if (CDSL_CURRENT != slot_nr) {
+ /* we have no changer support */
+ return -EINVAL;
+ }
+
+ return sony_spun_up ? CDS_DISC_OK : CDS_DRIVE_NOT_READY;
+}
+
static inline void
enable_interrupts(void)
{
@@ -474,6 +518,25 @@ reset_drive(void)
outb(SONY_DRIVE_RESET_BIT, sony_cd_control_reg);
}
+/*
+ * Uniform cdrom interface function
+ * reset drive and return when it is ready
+ */
+static int scd_reset(struct cdrom_device_info * cdi)
+{
+ int retry_count;
+
+ reset_drive();
+
+ retry_count = jiffies + SONY_RESET_TIMEOUT;
+ while ((retry_count > jiffies) && (!is_attention()))
+ {
+ sony_sleep();
+ }
+
+ return 0;
+}
+
static inline void
clear_attention(void)
{
@@ -574,11 +637,65 @@ cdu31a_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
/*
+ * give more verbose error messages
+ */
+static unsigned char *translate_error( unsigned char err_code )
+{
+ static unsigned char errbuf[80];
+
+ switch (err_code) {
+ case 0x10: return "illegal command ";
+ case 0x11: return "illegal parameter ";
+
+ case 0x20: return "not loaded ";
+ case 0x21: return "no disc ";
+ case 0x22: return "not spinning ";
+ case 0x23: return "spinning ";
+ case 0x25: return "spindle servo ";
+ case 0x26: return "focus servo ";
+ case 0x29: return "eject mechanism ";
+ case 0x2a: return "audio playing ";
+ case 0x2c: return "emergency eject ";
+
+ case 0x30: return "focus ";
+ case 0x31: return "frame sync ";
+ case 0x32: return "subcode address ";
+ case 0x33: return "block sync ";
+ case 0x34: return "header address ";
+
+ case 0x40: return "illegal track read ";
+ case 0x41: return "mode 0 read ";
+ case 0x42: return "illegal mode read ";
+ case 0x43: return "illegal block size read ";
+ case 0x44: return "mode read ";
+ case 0x45: return "form read ";
+ case 0x46: return "leadout read ";
+ case 0x47: return "buffer overrun ";
+
+ case 0x53: return "unrecoverable CIRC ";
+ case 0x57: return "unrecoverable LECC ";
+
+ case 0x60: return "no TOC ";
+ case 0x61: return "invalid subcode data ";
+ case 0x63: return "focus on TOC read ";
+ case 0x64: return "frame sync on TOC read ";
+ case 0x65: return "TOC data ";
+
+ case 0x70: return "hardware failure ";
+ case 0x91: return "leadin ";
+ case 0x92: return "leadout ";
+ case 0x93: return "data track ";
+ }
+ sprintf(errbuf, "unknown 0x%02x ", err_code);
+ return errbuf;
+}
+
+/*
* Set the drive parameters so the drive will auto-spin-up when a
* disk is inserted.
*/
static void
-set_drive_params(void)
+set_drive_params(int want_doublespeed)
{
unsigned char res_reg[12];
unsigned int res_size;
@@ -602,7 +719,7 @@ set_drive_params(void)
if (is_auto_eject) params[1] |= SONY_AUTO_EJECT_BIT;
- if (is_double_speed)
+ if (is_double_speed && want_doublespeed)
{
params[1] |= SONY_DOUBLE_SPEED_BIT; /* Set the drive to double speed if
possible */
@@ -619,6 +736,38 @@ set_drive_params(void)
}
/*
+ * Uniform cdrom interface function
+ * select reading speed for data access
+ */
+static int scd_select_speed(struct cdrom_device_info *cdi, int speed)
+{
+ if (speed == 0)
+ sony_speed = 1;
+ else
+ sony_speed = speed - 1;
+
+ set_drive_params(sony_speed);
+ return 0;
+}
+
+/*
+ * Uniform cdrom interface function
+ * lock or unlock eject button
+ */
+static int scd_lock_door(struct cdrom_device_info *cdi, int lock)
+{
+ if (lock == 0 && sony_usage == 1)
+ {
+ /* Unlock the door, only if nobody is using the drive */
+ is_auto_eject = 1;
+ } else {
+ is_auto_eject = 0;
+ }
+ set_drive_params(sony_speed);
+ return 0;
+}
+
+/*
* This code will reset the drive and attempt to restore sane parameters.
*/
static void
@@ -636,7 +785,7 @@ restart_on_error(void)
{
sony_sleep();
}
- set_drive_params();
+ set_drive_params(sony_speed);
do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size);
if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20))
{
@@ -1069,9 +1218,9 @@ msf_to_log(unsigned char *msf)
unsigned int log;
- log = bcd_to_int(msf[2]);
- log += bcd_to_int(msf[1]) * 75;
- log += bcd_to_int(msf[0]) * 4500;
+ log = msf[2];
+ log += msf[1] * 75;
+ log += msf[0] * 4500;
log = log - LOG_START_OFFSET;
return log;
@@ -1092,10 +1241,37 @@ size_to_buf(unsigned int size,
buf[2] = size % 256;
}
+/* Uniform cdrom interface function.
+ Return the status of the current disc:
+ If it is recognized as CD-I -> return XA Mode 2 Form 2
+ If it is recognized as XA -> return XA Mode 2 Form 1
+ If there is at least one data track return Mode 1
+ else return type AUDIO
+ */
+static int scd_disc_status(struct cdrom_device_info *cdi)
+{
+ if (sony_spun_up)
+ {
+ int i;
+
+ sony_get_toc();
+ /* look into the TOC */
+ if (sony_toc.disk_type == 0x10) /* this is a CD-I disc */
+ return CDS_XA_2_2;
+ if (sony_toc.disk_type == 0x20) /* this is a XA disc */
+ return CDS_XA_2_1;
+ for (i = 0; i < sony_toc.track_entries; i++)
+ if (sony_toc.tracks[i].control & CDROM_DATA_TRACK)
+ return CDS_DATA_1;
+ return CDS_AUDIO;
+ } else
+ return CDS_NO_INFO;
+}
+
/* Starts a read operation. Returns 0 on success and 1 on failure.
The read operation used here allows multiple sequential sectors
to be read and status returned for each sector. The driver will
- read the out one at a time as the requests come and abort the
+ read the output one at a time as the requests come and abort the
operation if the requested sector is not the next one from the
drive. */
static int
@@ -1128,7 +1304,7 @@ start_request(unsigned int sector,
/* Read the full readahead amount. */
else
{
- read_size = CDU31A_READAHEAD;
+ read_size = CDU31A_READAHEAD / 4;
}
size_to_buf(read_size, &params[3]);
@@ -1192,8 +1368,9 @@ abort_read(void)
do_sony_cd_cmd(SONY_ABORT_CMD, NULL, 0, result_reg, &result_size);
if ((result_reg[0] & 0xf0) == 0x20)
{
- printk("CDU31A: Error aborting read, error = 0x%2.2x\n",
- result_reg[1]);
+ printk("CDU31A: Error aborting read, %s error\n",
+ translate_error(
+ result_reg[1]));
}
while (is_result_reg_not_empty())
@@ -1525,6 +1702,8 @@ read_data_block(char *buffer,
#endif
}
+static int scd_spinup(void);
+
/*
* The OS calls this to perform a read or write operation to the drive.
* Write obviously fail. Reads to a read ahead of sony_buffer_size
@@ -1599,13 +1778,7 @@ cdu31a_request_startover:
if (!sony_spun_up)
{
- struct inode in;
-
- /* This is a kludge to get a valid dev in an inode that
- scd_open can take. That's the only thing scd_open()
- uses the inode for. */
- in.i_rdev = CURRENT->rq_dev;
- scd_open(&in,NULL);
+ scd_spinup();
}
/* I don't use INIT_REQUEST because it calls return, which would
@@ -1633,16 +1806,6 @@ cdu31a_request_startover:
goto cdu31a_request_startover;
}
- /* Check for base read of multi-session disk. This will still work
- for single session disks, so just do it. Blocks less than 80
- are for the volume info, so offset them by the start track (which
- should be zero for a single-session disk). */
- if (block < 80)
- {
- /* Offset the request into the session. */
- block += (sony_toc.start_track_lba * 4);
- }
-
switch(CURRENT->cmd)
{
case READ:
@@ -1735,7 +1898,7 @@ try_read_again:
}
else
{
- printk("CDU31A: Read error: 0x%2.2x\n", res_reg[1]);
+ printk("CDU31A: %s error for block %d, nblock %d\n", translate_error(res_reg[1]), block, nblock);
}
goto try_read_again;
}
@@ -1775,23 +1938,6 @@ end_do_cdu31a_request:
#endif
}
-/* Copy overlapping buffers. */
-static void
-mcovlp(char *dst,
- char *src,
- int size)
-{
- src += (size - 1);
- dst += (size - 1);
- while (size > 0)
- {
- *dst = *src;
- size--;
- dst--;
- src--;
- }
-}
-
/*
* Read the table of contents from the drive and set up TOC if
@@ -1805,7 +1951,9 @@ sony_get_toc(void)
unsigned char parms[1];
int session;
int num_spin_ups;
-
+ int totaltracks = 0;
+ int mint = 99;
+ int maxt = 0;
#if DEBUG
printk("Entering sony_get_toc\n");
@@ -1839,9 +1987,8 @@ respinup_on_gettoc:
goto respinup_on_gettoc;
}
- printk("cdu31a: Error reading TOC: %x %x\n",
- sony_toc.exec_status[0],
- sony_toc.exec_status[1]);
+ printk("cdu31a: Error reading TOC: %x %s\n",
+ res_reg[0], translate_error(res_reg[1]));
return;
}
@@ -1851,9 +1998,12 @@ gettoc_drive_spinning:
fails. Then we know what the last valid session on the disk is.
No need to check session 0, since session 0 is the same as session
1; the command returns different information if you give it 0.
- Don't check session 1 because that is the first session, it must
- be there. */
- session = 2;
+ */
+#if DEBUG
+ memset(&sony_toc, 0x0e, sizeof(sony_toc));
+ memset(&single_toc, 0x0f, sizeof(single_toc));
+#endif
+ session = 1;
while (1)
{
#if DEBUG
@@ -1875,95 +2025,265 @@ gettoc_drive_spinning:
/* An error reading the TOC, this must be past the last session. */
break;
}
-
- session++;
-
- /* Let's not get carried away... */
- if (session > 20)
- {
- printk("cdu31a: too many sessions: %d\n", session);
- return;
- }
- }
-
- session--;
-
#if DEBUG
- printk("Reading session %d\n", session);
+ printk("Reading session %d\n", session);
#endif
- parms[0] = session;
- do_sony_cd_cmd(SONY_REQ_TOC_DATA_SPEC_CMD,
+ parms[0] = session;
+ do_sony_cd_cmd(SONY_REQ_TOC_DATA_SPEC_CMD,
parms,
1,
- (unsigned char *) &sony_toc,
+ (unsigned char *) &single_toc,
&res_size);
- if ((res_size < 2) || ((sony_toc.exec_status[0] & 0xf0) == 0x20))
- {
- printk("cdu31a: Error reading session %d: %x %x\n",
+ if ((res_size < 2) || ((single_toc.exec_status[0] & 0xf0) == 0x20))
+ {
+ printk("cdu31a: Error reading session %d: %x %s\n",
session,
- sony_toc.exec_status[0],
- sony_toc.exec_status[1]);
- /* An error reading the TOC. Return without sony_toc_read
- set. */
- return;
- }
-
- sony_toc_read = 1;
+ single_toc.exec_status[0],
+ translate_error(single_toc.exec_status[1]));
+ /* An error reading the TOC. Return without sony_toc_read
+ set. */
+ return;
+ }
+#if DEBUG
+ printk("add0 %01x, con0 %01x, poi0 %02x, 1st trk %d, dsktyp %x, dum0 %x\n",
+ single_toc.address0, single_toc.control0, single_toc.point0,
+ bcd_to_int(single_toc.first_track_num), single_toc.disk_type, single_toc.dummy0);
+ printk("add1 %01x, con1 %01x, poi1 %02x, lst trk %d, dummy1 %x, dum2 %x\n",
+ single_toc.address1, single_toc.control1, single_toc.point1,
+ bcd_to_int(single_toc.last_track_num), single_toc.dummy1, single_toc.dummy2);
+ printk("add2 %01x, con2 %01x, poi2 %02x leadout start min %d, sec %d, frame %d\n",
+ single_toc.address2, single_toc.control2, single_toc.point2,
+ bcd_to_int(single_toc.lead_out_start_msf[0]),
+ bcd_to_int(single_toc.lead_out_start_msf[1]),
+ bcd_to_int(single_toc.lead_out_start_msf[2]));
+ if (res_size > 18 && single_toc.pointb0 > 0xaf)
+ printk("addb0 %01x, conb0 %01x, poib0 %02x, nextsession min %d, sec %d, frame %d\n"
+ "#mode5_ptrs %02d, max_start_outer_leadout_msf min %d, sec %d, frame %d\n",
+ single_toc.addressb0, single_toc.controlb0, single_toc.pointb0,
+ bcd_to_int(single_toc.next_poss_prog_area_msf[0]),
+ bcd_to_int(single_toc.next_poss_prog_area_msf[1]),
+ bcd_to_int(single_toc.next_poss_prog_area_msf[2]),
+ single_toc.num_mode_5_pointers,
+ bcd_to_int(single_toc.max_start_outer_leadout_msf[0]),
+ bcd_to_int(single_toc.max_start_outer_leadout_msf[1]),
+ bcd_to_int(single_toc.max_start_outer_leadout_msf[2]));
+ if (res_size > 27 && single_toc.pointb1 > 0xaf)
+ printk("addb1 %01x, conb1 %01x, poib1 %02x, %x %x %x %x #skipint_ptrs %d, #skiptrkassign %d %x\n",
+ single_toc.addressb1, single_toc.controlb1, single_toc.pointb1,
+ single_toc.dummyb0_1[0],
+ single_toc.dummyb0_1[1],
+ single_toc.dummyb0_1[2],
+ single_toc.dummyb0_1[3],
+ single_toc.num_skip_interval_pointers,
+ single_toc.num_skip_track_assignments,
+ single_toc.dummyb0_2);
+ if (res_size > 36 && single_toc.pointb2 > 0xaf)
+ printk("addb2 %01x, conb2 %01x, poib2 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
+ single_toc.addressb2, single_toc.controlb2, single_toc.pointb2,
+ single_toc.tracksb2[0],
+ single_toc.tracksb2[1],
+ single_toc.tracksb2[2],
+ single_toc.tracksb2[3],
+ single_toc.tracksb2[4],
+ single_toc.tracksb2[5],
+ single_toc.tracksb2[6]);
+ if (res_size > 45 && single_toc.pointb3 > 0xaf)
+ printk("addb3 %01x, conb3 %01x, poib3 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
+ single_toc.addressb3, single_toc.controlb3, single_toc.pointb3,
+ single_toc.tracksb3[0],
+ single_toc.tracksb3[1],
+ single_toc.tracksb3[2],
+ single_toc.tracksb3[3],
+ single_toc.tracksb3[4],
+ single_toc.tracksb3[5],
+ single_toc.tracksb3[6]);
+ if (res_size > 54 && single_toc.pointb4 > 0xaf)
+ printk("addb4 %01x, conb4 %01x, poib4 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
+ single_toc.addressb4, single_toc.controlb4, single_toc.pointb4,
+ single_toc.tracksb4[0],
+ single_toc.tracksb4[1],
+ single_toc.tracksb4[2],
+ single_toc.tracksb4[3],
+ single_toc.tracksb4[4],
+ single_toc.tracksb4[5],
+ single_toc.tracksb4[6]);
+ if (res_size > 63 && single_toc.pointc0 > 0xaf)
+ printk("addc0 %01x, conc0 %01x, poic0 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
+ single_toc.addressc0, single_toc.controlc0, single_toc.pointc0,
+ single_toc.dummyc0[0],
+ single_toc.dummyc0[1],
+ single_toc.dummyc0[2],
+ single_toc.dummyc0[3],
+ single_toc.dummyc0[4],
+ single_toc.dummyc0[5],
+ single_toc.dummyc0[6]);
+#endif
+#undef DEBUG
+#define DEBUG 0
+
+ sony_toc.lead_out_start_msf[0] = bcd_to_int(single_toc.lead_out_start_msf[0]);
+ sony_toc.lead_out_start_msf[1] = bcd_to_int(single_toc.lead_out_start_msf[1]);
+ sony_toc.lead_out_start_msf[2] = bcd_to_int(single_toc.lead_out_start_msf[2]);
+ sony_toc.lead_out_start_lba = single_toc.lead_out_start_lba =
+ msf_to_log(sony_toc.lead_out_start_msf);
/* For points that do not exist, move the data over them
to the right location. */
- if (sony_toc.pointb0 != 0xb0)
+ if (single_toc.pointb0 != 0xb0)
{
- mcovlp(((char *) &sony_toc) + 27,
- ((char *) &sony_toc) + 18,
- res_size - 18);
+ memmove(((char *) &single_toc) + 27,
+ ((char *) &single_toc) + 18,
+ res_size - 18);
res_size += 9;
}
- if (sony_toc.pointb1 != 0xb1)
+ else if (res_size > 18) {
+ sony_toc.lead_out_start_msf[0] = bcd_to_int(single_toc.max_start_outer_leadout_msf[0]);
+ sony_toc.lead_out_start_msf[1] = bcd_to_int(single_toc.max_start_outer_leadout_msf[1]);
+ sony_toc.lead_out_start_msf[2] = bcd_to_int(single_toc.max_start_outer_leadout_msf[2]);
+ sony_toc.lead_out_start_lba = msf_to_log(sony_toc.lead_out_start_msf);
+ }
+ if (single_toc.pointb1 != 0xb1)
{
- mcovlp(((char *) &sony_toc) + 36,
- ((char *) &sony_toc) + 27,
+ memmove(((char *) &single_toc) + 36,
+ ((char *) &single_toc) + 27,
res_size - 27);
res_size += 9;
}
- if (sony_toc.pointb2 != 0xb2)
+ if (single_toc.pointb2 != 0xb2)
{
- mcovlp(((char *) &sony_toc) + 45,
- ((char *) &sony_toc) + 36,
+ memmove(((char *) &single_toc) + 45,
+ ((char *) &single_toc) + 36,
res_size - 36);
res_size += 9;
}
- if (sony_toc.pointb3 != 0xb3)
+ if (single_toc.pointb3 != 0xb3)
{
- mcovlp(((char *) &sony_toc) + 54,
- ((char *) &sony_toc) + 45,
+ memmove(((char *) &single_toc) + 54,
+ ((char *) &single_toc) + 45,
res_size - 45);
res_size += 9;
}
- if (sony_toc.pointb4 != 0xb4)
+ if (single_toc.pointb4 != 0xb4)
{
- mcovlp(((char *) &sony_toc) + 63,
- ((char *) &sony_toc) + 54,
+ memmove(((char *) &single_toc) + 63,
+ ((char *) &single_toc) + 54,
res_size - 54);
res_size += 9;
}
- if (sony_toc.pointc0 != 0xc0)
+ if (single_toc.pointc0 != 0xc0)
{
- mcovlp(((char *) &sony_toc) + 72,
- ((char *) &sony_toc) + 63,
+ memmove(((char *) &single_toc) + 72,
+ ((char *) &single_toc) + 63,
res_size - 63);
res_size += 9;
}
- sony_toc.start_track_lba = msf_to_log(sony_toc.tracks[0].track_start_msf);
- sony_toc.lead_out_start_lba = msf_to_log(sony_toc.lead_out_start_msf);
+#if DEBUG
+ printk("start track lba %u, leadout start lba %u\n",
+ single_toc.start_track_lba, single_toc.lead_out_start_lba);
+ { int i;
+ for (i = 0; i < 1 + bcd_to_int(single_toc.last_track_num)
+ - bcd_to_int(single_toc.first_track_num); i++) {
+ printk("trk %02d: add 0x%01x, con 0x%01x, track %02d, start min %02d, sec %02d, frame %02d\n",
+ i, single_toc.tracks[i].address, single_toc.tracks[i].control,
+ bcd_to_int(single_toc.tracks[i].track),
+ bcd_to_int(single_toc.tracks[i].track_start_msf[0]),
+ bcd_to_int(single_toc.tracks[i].track_start_msf[1]),
+ bcd_to_int(single_toc.tracks[i].track_start_msf[2]));
+ if (mint > bcd_to_int(single_toc.tracks[i].track))
+ mint = bcd_to_int(single_toc.tracks[i].track);
+ if (maxt < bcd_to_int(single_toc.tracks[i].track))
+ maxt = bcd_to_int(single_toc.tracks[i].track);
+ }
+ printk("min track number %d, max track number %d\n", mint, maxt);
+ }
+#endif
+
+ /* prepare a special table of contents for a CD-I disc. They don't have one. */
+ if (single_toc.disk_type == 0x10 &&
+ single_toc.first_track_num == 2 &&
+ single_toc.last_track_num == 2 /* CD-I */)
+ {
+ sony_toc.tracks[totaltracks].address = 1;
+ sony_toc.tracks[totaltracks].control = 4; /* force data tracks */
+ sony_toc.tracks[totaltracks].track = 1;
+ sony_toc.tracks[totaltracks].track_start_msf[0] = 0;
+ sony_toc.tracks[totaltracks].track_start_msf[1] = 2;
+ sony_toc.tracks[totaltracks].track_start_msf[2] = 0;
+ mint = maxt = 1;
+ totaltracks++;
+ } else
+ /* gather track entries from this session */
+ { int i;
+ for (i = 0; i < 1 + bcd_to_int(single_toc.last_track_num)
+ - bcd_to_int(single_toc.first_track_num); i++, totaltracks++) {
+ sony_toc.tracks[totaltracks].address = single_toc.tracks[i].address;
+ sony_toc.tracks[totaltracks].control = single_toc.tracks[i].control;
+ sony_toc.tracks[totaltracks].track = bcd_to_int(single_toc.tracks[i].track);
+ sony_toc.tracks[totaltracks].track_start_msf[0] =
+ bcd_to_int(single_toc.tracks[i].track_start_msf[0]);
+ sony_toc.tracks[totaltracks].track_start_msf[1] =
+ bcd_to_int(single_toc.tracks[i].track_start_msf[1]);
+ sony_toc.tracks[totaltracks].track_start_msf[2] =
+ bcd_to_int(single_toc.tracks[i].track_start_msf[2]);
+ if (i == 0)
+ single_toc.start_track_lba = msf_to_log(sony_toc.tracks[totaltracks].track_start_msf);
+ if (mint > sony_toc.tracks[totaltracks].track)
+ mint = sony_toc.tracks[totaltracks].track;
+ if (maxt < sony_toc.tracks[totaltracks].track)
+ maxt = sony_toc.tracks[totaltracks].track;
+ }
+ }
+ sony_toc.first_track_num = mint;
+ sony_toc.last_track_num = maxt;
+ /* Disk type of last session wins. For example:
+ CD-Extra has disk type 0 for the first session, so
+ a dumb HiFi CD player thinks it is a plain audio CD.
+ We are interested in the disk type of the last session,
+ which is 0x20 (XA) for CD-Extra, so we can access the
+ data track ... */
+ sony_toc.disk_type = single_toc.disk_type;
+ sony_toc.sessions = session;
+
+ /* don't believe everything :-) */
+ if (session == 1)
+ single_toc.start_track_lba = 0;
+ sony_toc.start_track_lba = single_toc.start_track_lba;
+
+ if (session > 1 && single_toc.pointb0 == 0xb0 &&
+ sony_toc.lead_out_start_lba == single_toc.lead_out_start_lba)
+ {
+ break;
+ }
+ /* Let's not get carried away... */
+ if (session > 40)
+ {
+ printk("cdu31a: too many sessions: %d\n", session);
+ break;
+ }
+ session++;
+ }
+ sony_toc.track_entries = totaltracks;
+ /* add one entry for the LAST track with track number CDROM_LEADOUT */
+ sony_toc.tracks[totaltracks].address = single_toc.address2;
+ sony_toc.tracks[totaltracks].control = single_toc.control2;
+ sony_toc.tracks[totaltracks].track = CDROM_LEADOUT;
+ sony_toc.tracks[totaltracks].track_start_msf[0] =
+ sony_toc.lead_out_start_msf[0];
+ sony_toc.tracks[totaltracks].track_start_msf[1] =
+ sony_toc.lead_out_start_msf[1];
+ sony_toc.tracks[totaltracks].track_start_msf[2] =
+ sony_toc.lead_out_start_msf[2];
+
+ sony_toc_read = 1;
+#undef DEBUG
#if DEBUG
printk("Disk session %d, start track: %d, stop track: %d\n",
session,
- sony_toc.start_track_lba,
- sony_toc.lead_out_start_lba);
+ single_toc.start_track_lba,
+ single_toc.lead_out_start_lba);
#endif
}
#if DEBUG
@@ -1973,19 +2293,35 @@ gettoc_drive_spinning:
/*
+ * Uniform cdrom interface function
+ * return multisession offset and sector information
+ */
+static int scd_get_last_session(struct cdrom_device_info *cdi,
+ struct cdrom_multisession *ms_info)
+{
+ if (ms_info == NULL)
+ return 1;
+
+ if (!sony_toc_read)
+ sony_get_toc();
+
+ ms_info->addr_format = CDROM_LBA;
+ ms_info->addr.lba = sony_toc.start_track_lba;
+ ms_info->xa_flag = sony_toc.disk_type == SONY_XA_DISK_TYPE ||
+ sony_toc.disk_type == 0x10 /* CDI */;
+
+ return 0;
+}
+
+/*
* Search for a specific track in the table of contents.
*/
static int
find_track(int track)
{
int i;
- int num_tracks;
-
- num_tracks = ( bcd_to_int(sony_toc.last_track_num)
- - bcd_to_int(sony_toc.first_track_num)
- + 1);
- for (i = 0; i < num_tracks; i++)
+ for (i = 0; i <= sony_toc.track_entries; i++)
{
if (sony_toc.tracks[i].track == track)
{
@@ -1998,7 +2334,7 @@ find_track(int track)
/*
- * Read the subcode and put it int last_sony_subcode for future use.
+ * Read the subcode and put it in last_sony_subcode for future use.
*/
static int
read_subcode(void)
@@ -2013,11 +2349,60 @@ read_subcode(void)
&res_size);
if ((res_size < 2) || ((last_sony_subcode.exec_status[0] & 0xf0) == 0x20))
{
- printk("Sony CDROM error 0x%2.2x (read_subcode)\n",
- last_sony_subcode.exec_status[1]);
+ printk("Sony CDROM error %s (read_subcode)\n",
+ translate_error(last_sony_subcode.exec_status[1]));
return -EIO;
}
+ last_sony_subcode.track_num = bcd_to_int(last_sony_subcode.track_num);
+ last_sony_subcode.index_num = bcd_to_int(last_sony_subcode.index_num);
+ last_sony_subcode.abs_msf[0] = bcd_to_int(last_sony_subcode.abs_msf[0]);
+ last_sony_subcode.abs_msf[1] = bcd_to_int(last_sony_subcode.abs_msf[1]);
+ last_sony_subcode.abs_msf[2] = bcd_to_int(last_sony_subcode.abs_msf[2]);
+
+ last_sony_subcode.rel_msf[0] = bcd_to_int(last_sony_subcode.rel_msf[0]);
+ last_sony_subcode.rel_msf[1] = bcd_to_int(last_sony_subcode.rel_msf[1]);
+ last_sony_subcode.rel_msf[2] = bcd_to_int(last_sony_subcode.rel_msf[2]);
+ return 0;
+}
+
+/*
+ * Uniform cdrom interface function
+ * return the media catalog number found on some older audio cds
+ */
+static int
+scd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
+{
+ unsigned char resbuffer[2 + 14];
+ unsigned char *mcnp = mcn->medium_catalog_number;
+ unsigned char *resp = resbuffer + 3;
+ unsigned int res_size;
+
+ memset(mcn->medium_catalog_number, 0, 14);
+ do_sony_cd_cmd(SONY_REQ_UPC_EAN_CMD,
+ NULL,
+ 0,
+ resbuffer,
+ &res_size);
+ if ((res_size < 2) || ((resbuffer[0] & 0xf0) == 0x20))
+ ;
+ else {
+ /* packed bcd to single ASCII digits */
+ *mcnp++ = (*resp >> 4) + '0';
+ *mcnp++ = (*resp++ & 0x0f) + '0';
+ *mcnp++ = (*resp >> 4) + '0';
+ *mcnp++ = (*resp++ & 0x0f) + '0';
+ *mcnp++ = (*resp >> 4) + '0';
+ *mcnp++ = (*resp++ & 0x0f) + '0';
+ *mcnp++ = (*resp >> 4) + '0';
+ *mcnp++ = (*resp++ & 0x0f) + '0';
+ *mcnp++ = (*resp >> 4) + '0';
+ *mcnp++ = (*resp++ & 0x0f) + '0';
+ *mcnp++ = (*resp >> 4) + '0';
+ *mcnp++ = (*resp++ & 0x0f) + '0';
+ *mcnp++ = (*resp >> 4) + '0';
+ }
+ *mcnp = '\0';
return 0;
}
@@ -2030,12 +2415,8 @@ read_subcode(void)
* (not BCD), so all the conversions are done.
*/
static int
-sony_get_subchnl_info(long arg)
+sony_get_subchnl_info(struct cdrom_subchnl *schi)
{
- int err;
- struct cdrom_subchnl schi;
-
-
/* Get attention stuff */
while (handle_sony_cd_attention())
;
@@ -2046,13 +2427,9 @@ sony_get_subchnl_info(long arg)
return -EIO;
}
- err = verify_area(VERIFY_WRITE, (char *) arg, sizeof(schi));
- if (err) return err;
-
- copy_from_user(&schi, (char *) arg, sizeof(schi));
-
switch (sony_audio_status)
{
+ case CDROM_AUDIO_NO_STATUS:
case CDROM_AUDIO_PLAY:
if (read_subcode() < 0)
{
@@ -2064,40 +2441,39 @@ sony_get_subchnl_info(long arg)
case CDROM_AUDIO_COMPLETED:
break;
+#if 0
case CDROM_AUDIO_NO_STATUS:
- schi.cdsc_audiostatus = sony_audio_status;
- copy_to_user((char *) arg, &schi, sizeof(schi));
+ schi->cdsc_audiostatus = sony_audio_status;
return 0;
break;
-
+#endif
case CDROM_AUDIO_INVALID:
case CDROM_AUDIO_ERROR:
default:
return -EIO;
}
- schi.cdsc_audiostatus = sony_audio_status;
- schi.cdsc_adr = last_sony_subcode.address;
- schi.cdsc_ctrl = last_sony_subcode.control;
- schi.cdsc_trk = bcd_to_int(last_sony_subcode.track_num);
- schi.cdsc_ind = bcd_to_int(last_sony_subcode.index_num);
- if (schi.cdsc_format == CDROM_MSF)
+ schi->cdsc_audiostatus = sony_audio_status;
+ schi->cdsc_adr = last_sony_subcode.address;
+ schi->cdsc_ctrl = last_sony_subcode.control;
+ schi->cdsc_trk = last_sony_subcode.track_num;
+ schi->cdsc_ind = last_sony_subcode.index_num;
+ if (schi->cdsc_format == CDROM_MSF)
{
- schi.cdsc_absaddr.msf.minute = bcd_to_int(last_sony_subcode.abs_msf[0]);
- schi.cdsc_absaddr.msf.second = bcd_to_int(last_sony_subcode.abs_msf[1]);
- schi.cdsc_absaddr.msf.frame = bcd_to_int(last_sony_subcode.abs_msf[2]);
+ schi->cdsc_absaddr.msf.minute = last_sony_subcode.abs_msf[0];
+ schi->cdsc_absaddr.msf.second = last_sony_subcode.abs_msf[1];
+ schi->cdsc_absaddr.msf.frame = last_sony_subcode.abs_msf[2];
- schi.cdsc_reladdr.msf.minute = bcd_to_int(last_sony_subcode.rel_msf[0]);
- schi.cdsc_reladdr.msf.second = bcd_to_int(last_sony_subcode.rel_msf[1]);
- schi.cdsc_reladdr.msf.frame = bcd_to_int(last_sony_subcode.rel_msf[2]);
+ schi->cdsc_reladdr.msf.minute = last_sony_subcode.rel_msf[0];
+ schi->cdsc_reladdr.msf.second = last_sony_subcode.rel_msf[1];
+ schi->cdsc_reladdr.msf.frame = last_sony_subcode.rel_msf[2];
}
- else if (schi.cdsc_format == CDROM_LBA)
+ else if (schi->cdsc_format == CDROM_LBA)
{
- schi.cdsc_absaddr.lba = msf_to_log(last_sony_subcode.abs_msf);
- schi.cdsc_reladdr.lba = msf_to_log(last_sony_subcode.rel_msf);
+ schi->cdsc_absaddr.lba = msf_to_log(last_sony_subcode.abs_msf);
+ schi->cdsc_reladdr.lba = msf_to_log(last_sony_subcode.rel_msf);
}
- copy_to_user((char *) arg, &schi, sizeof(schi));
return 0;
}
@@ -2172,7 +2548,7 @@ continue_read_audio_wait:
/* If data block, then get 2340 bytes offset by 12. */
if (sony_raw_data_mode)
{
- insb(sony_cd_read_reg, buffer + CD_XA_HEAD, CD_FRAMESIZE_XA);
+ insb(sony_cd_read_reg, buffer + CD_XA_HEAD, CD_FRAMESIZE_RAW1);
}
else
{
@@ -2243,8 +2619,7 @@ continue_read_audio_wait:
/* Perform a raw data read. This will automatically detect the
track type and read the proper data (audio or data). */
static int
-read_audio(struct cdrom_read_audio *ra,
- struct inode *inode)
+read_audio(struct cdrom_read_audio *ra)
{
int retval;
unsigned char params[2];
@@ -2274,7 +2649,7 @@ read_audio(struct cdrom_read_audio *ra,
if (!sony_spun_up)
{
- scd_open (inode, NULL);
+ scd_spinup();
}
/* Set the drive to do raw operations. */
@@ -2355,9 +2730,9 @@ read_audio(struct cdrom_read_audio *ra,
}
else
{
- printk("CDU31A: Error reading audio data on sector %d: 0x%x\n",
+ printk("CDU31A: Error reading audio data on sector %d: %s\n",
ra->addr.lba + cframe,
- res_reg[1]);
+ translate_error(res_reg[1]));
retval = -EIO;
goto exit_read_audio;
}
@@ -2371,9 +2746,9 @@ read_audio(struct cdrom_read_audio *ra,
}
else
{
- printk("CDU31A: Error reading audio data on sector %d: 0x%x\n",
+ printk("CDU31A: Error reading audio data on sector %d: %s\n",
ra->addr.lba + cframe,
- res_reg[1]);
+ translate_error(res_reg[1]));
retval = -EIO;
goto exit_read_audio;
}
@@ -2391,8 +2766,8 @@ read_audio(struct cdrom_read_audio *ra,
get_result(res_reg, &res_size);
if ((res_reg[0] & 0xf0) == 0x20)
{
- printk("CDU31A: Error return from audio read: 0x%x\n",
- res_reg[1]);
+ printk("CDU31A: Error return from audio read: %s\n",
+ translate_error(res_reg[1]));
retval = -EIO;
goto exit_read_audio;
}
@@ -2438,19 +2813,38 @@ do_sony_cd_cmd_chk(const char *name,
do_sony_cd_cmd(cmd, params, num_params, result_buffer, result_size);
if ((*result_size < 2) || ((result_buffer[0] & 0xf0) == 0x20))
{
- printk("Sony CDROM error 0x%2.2x (CDROM%s)\n", result_buffer[1], name);
+ printk("Sony CDROM error %s (CDROM%s)\n", translate_error(result_buffer[1]), name);
return -EIO;
}
return 0;
}
/*
+ * Uniform cdrom interface function
+ * open the tray
+ */
+static int scd_tray_move(struct cdrom_device_info *cdi, int position)
+{
+ if (position == 1 /* open tray */)
+ {
+ unsigned char res_reg[12];
+ unsigned int res_size;
+
+ do_sony_cd_cmd(SONY_AUDIO_STOP_CMD, NULL, 0, res_reg, &res_size);
+ do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg, &res_size);
+
+ sony_audio_status = CDROM_AUDIO_INVALID;
+ return do_sony_cd_cmd_chk("EJECT",SONY_EJECT_CMD, NULL, 0, res_reg, &res_size);
+ } else
+ return 0;
+}
+
+/*
* The big ugly ioctl handler.
*/
-static int scd_ioctl(struct inode *inode,
- struct file *file,
+static int scd_audio_ioctl(struct cdrom_device_info *cdi,
unsigned int cmd,
- unsigned long arg)
+ void * arg)
{
unsigned char res_reg[12];
unsigned int res_size;
@@ -2458,16 +2852,10 @@ static int scd_ioctl(struct inode *inode,
int i;
- if (!inode)
- {
- return -EINVAL;
- }
-
switch (cmd)
{
case CDROMSTART: /* Spin up the drive */
return do_sony_cd_cmd_chk("START",SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size);
- return 0;
break;
case CDROMSTOP: /* Spin down the drive */
@@ -2504,12 +2892,12 @@ static int scd_ioctl(struct inode *inode,
do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size);
/* Start the drive at the saved position. */
- params[1] = cur_pos_msf[0];
- params[2] = cur_pos_msf[1];
- params[3] = cur_pos_msf[2];
- params[4] = final_pos_msf[0];
- params[5] = final_pos_msf[1];
- params[6] = final_pos_msf[2];
+ params[1] = int_to_bcd(cur_pos_msf[0]);
+ params[2] = int_to_bcd(cur_pos_msf[1]);
+ params[3] = int_to_bcd(cur_pos_msf[2]);
+ params[4] = int_to_bcd(final_pos_msf[0]);
+ params[5] = int_to_bcd(final_pos_msf[1]);
+ params[6] = int_to_bcd(final_pos_msf[2]);
params[0] = 0x03;
if(do_sony_cd_cmd_chk("RESUME",SONY_AUDIO_PLAYBACK_CMD, params, 7, res_reg, &res_size)<0)
return -EIO;
@@ -2517,32 +2905,27 @@ static int scd_ioctl(struct inode *inode,
return 0;
case CDROMPLAYMSF: /* Play starting at the given MSF address. */
- i=verify_area(VERIFY_READ, (char *) arg, 6);
- if(i)
- return i;
do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size);
- copy_from_user(&(params[1]), (void *) arg, 6);
/* The parameters are given in int, must be converted */
for (i=1; i<7; i++)
{
- params[i] = int_to_bcd(params[i]);
+ params[i] = int_to_bcd(((unsigned char *)arg)[i-1]);
}
params[0] = 0x03;
if(do_sony_cd_cmd_chk("PLAYMSF",SONY_AUDIO_PLAYBACK_CMD, params, 7, res_reg, &res_size)<0)
return -EIO;
/* Save the final position for pauses and resumes */
- final_pos_msf[0] = params[4];
- final_pos_msf[1] = params[5];
- final_pos_msf[2] = params[6];
+ final_pos_msf[0] = bcd_to_int(params[4]);
+ final_pos_msf[1] = bcd_to_int(params[5]);
+ final_pos_msf[2] = bcd_to_int(params[6]);
sony_audio_status = CDROM_AUDIO_PLAY;
return 0;
case CDROMREADTOCHDR: /* Read the table of contents header */
{
struct cdrom_tochdr *hdr;
- struct cdrom_tochdr loc_hdr;
sony_get_toc();
if (!sony_toc_read)
@@ -2551,19 +2934,14 @@ static int scd_ioctl(struct inode *inode,
}
hdr = (struct cdrom_tochdr *) arg;
- i=verify_area(VERIFY_WRITE, hdr, sizeof(*hdr));
- if(i<0)
- return i;
- loc_hdr.cdth_trk0 = bcd_to_int(sony_toc.first_track_num);
- loc_hdr.cdth_trk1 = bcd_to_int(sony_toc.last_track_num);
- copy_to_user(hdr, &loc_hdr, sizeof(*hdr));
+ hdr->cdth_trk0 = sony_toc.first_track_num;
+ hdr->cdth_trk1 = sony_toc.last_track_num;
}
return 0;
case CDROMREADTOCENTRY: /* Read a given table of contents entry */
{
struct cdrom_tocentry *entry;
- struct cdrom_tocentry loc_entry;
int track_idx;
unsigned char *msf_val = NULL;
@@ -2574,54 +2952,35 @@ static int scd_ioctl(struct inode *inode,
}
entry = (struct cdrom_tocentry *) arg;
- i=verify_area(VERIFY_READ, entry, sizeof(*entry));
- if(i<0)
- return i;
- i=verify_area(VERIFY_WRITE, entry, sizeof(*entry));
- if(i<0)
- return i;
- copy_from_user(&loc_entry, entry, sizeof(loc_entry));
-
- /* Lead out is handled separately since it is special. */
- if (loc_entry.cdte_track == CDROM_LEADOUT)
+ track_idx = find_track(entry->cdte_track);
+ if (track_idx < 0)
{
- loc_entry.cdte_adr = sony_toc.address2;
- loc_entry.cdte_ctrl = sony_toc.control2;
- msf_val = sony_toc.lead_out_start_msf;
+ return -EINVAL;
}
- else
- {
- track_idx = find_track(int_to_bcd(loc_entry.cdte_track));
- if (track_idx < 0)
- {
- return -EINVAL;
- }
- loc_entry.cdte_adr = sony_toc.tracks[track_idx].address;
- loc_entry.cdte_ctrl = sony_toc.tracks[track_idx].control;
- msf_val = sony_toc.tracks[track_idx].track_start_msf;
- }
+ entry->cdte_adr = sony_toc.tracks[track_idx].address;
+ entry->cdte_ctrl = sony_toc.tracks[track_idx].control;
+ msf_val = sony_toc.tracks[track_idx].track_start_msf;
/* Logical buffer address or MSF format requested? */
- if (loc_entry.cdte_format == CDROM_LBA)
+ if (entry->cdte_format == CDROM_LBA)
{
- loc_entry.cdte_addr.lba = msf_to_log(msf_val);
+ entry->cdte_addr.lba = msf_to_log(msf_val);
}
- else if (loc_entry.cdte_format == CDROM_MSF)
+ else if (entry->cdte_format == CDROM_MSF)
{
- loc_entry.cdte_addr.msf.minute = bcd_to_int(*msf_val);
- loc_entry.cdte_addr.msf.second = bcd_to_int(*(msf_val+1));
- loc_entry.cdte_addr.msf.frame = bcd_to_int(*(msf_val+2));
+ entry->cdte_addr.msf.minute = *msf_val;
+ entry->cdte_addr.msf.second = *(msf_val+1);
+ entry->cdte_addr.msf.frame = *(msf_val+2);
}
- copy_to_user(entry, &loc_entry, sizeof(*entry));
}
return 0;
break;
case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */
{
- struct cdrom_ti ti;
+ struct cdrom_ti *ti = (struct cdrom_ti *) arg;
int track_idx;
sony_get_toc();
@@ -2630,46 +2989,41 @@ static int scd_ioctl(struct inode *inode,
return -EIO;
}
- i=verify_area(VERIFY_READ, (char *) arg, sizeof(ti));
- if(i<0)
- return i;
-
- copy_from_user(&ti, (char *) arg, sizeof(ti));
- if ( (ti.cdti_trk0 < bcd_to_int(sony_toc.first_track_num))
- || (ti.cdti_trk0 > bcd_to_int(sony_toc.last_track_num))
- || (ti.cdti_trk1 < ti.cdti_trk0))
+ if ( (ti->cdti_trk0 < sony_toc.first_track_num)
+ || (ti->cdti_trk0 > sony_toc.last_track_num)
+ || (ti->cdti_trk1 < ti->cdti_trk0))
{
return -EINVAL;
}
- track_idx = find_track(int_to_bcd(ti.cdti_trk0));
+ track_idx = find_track(ti->cdti_trk0);
if (track_idx < 0)
{
return -EINVAL;
}
- params[1] = sony_toc.tracks[track_idx].track_start_msf[0];
- params[2] = sony_toc.tracks[track_idx].track_start_msf[1];
- params[3] = sony_toc.tracks[track_idx].track_start_msf[2];
+ params[1] = int_to_bcd(sony_toc.tracks[track_idx].track_start_msf[0]);
+ params[2] = int_to_bcd(sony_toc.tracks[track_idx].track_start_msf[1]);
+ params[3] = int_to_bcd(sony_toc.tracks[track_idx].track_start_msf[2]);
/*
* If we want to stop after the last track, use the lead-out
* MSF to do that.
*/
- if (ti.cdti_trk1 >= bcd_to_int(sony_toc.last_track_num))
+ if (ti->cdti_trk1 >= sony_toc.last_track_num)
{
- log_to_msf(msf_to_log(sony_toc.lead_out_start_msf)-1,
- &(params[4]));
+ track_idx = find_track(CDROM_LEADOUT);
}
else
{
- track_idx = find_track(int_to_bcd(ti.cdti_trk1+1));
- if (track_idx < 0)
- {
- return -EINVAL;
- }
- log_to_msf(msf_to_log(sony_toc.tracks[track_idx].track_start_msf)-1,
- &(params[4]));
+ track_idx = find_track(ti->cdti_trk1+1);
+ }
+ if (track_idx < 0)
+ {
+ return -EINVAL;
}
+ params[4] = int_to_bcd(sony_toc.tracks[track_idx].track_start_msf[0]);
+ params[5] = int_to_bcd(sony_toc.tracks[track_idx].track_start_msf[1]);
+ params[6] = int_to_bcd(sony_toc.tracks[track_idx].track_start_msf[2]);
params[0] = 0x03;
do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size);
@@ -2680,43 +3034,44 @@ static int scd_ioctl(struct inode *inode,
{
printk("Params: %x %x %x %x %x %x %x\n", params[0], params[1],
params[2], params[3], params[4], params[5], params[6]);
- printk("Sony CDROM error 0x%2.2x (CDROMPLAYTRKIND\n", res_reg[1]);
+ printk("Sony CDROM error %s (CDROMPLAYTRKIND)\n", translate_error(res_reg[1]));
return -EIO;
}
/* Save the final position for pauses and resumes */
- final_pos_msf[0] = params[4];
- final_pos_msf[1] = params[5];
- final_pos_msf[2] = params[6];
+ final_pos_msf[0] = bcd_to_int(params[4]);
+ final_pos_msf[1] = bcd_to_int(params[5]);
+ final_pos_msf[2] = bcd_to_int(params[6]);
sony_audio_status = CDROM_AUDIO_PLAY;
return 0;
}
- case CDROMSUBCHNL: /* Get subchannel info */
- return sony_get_subchnl_info(arg);
-
case CDROMVOLCTRL: /* Volume control. What volume does this change, anyway? */
{
- struct cdrom_volctrl volctrl;
+ struct cdrom_volctrl *volctrl = (struct cdrom_volctrl *) arg;
- i=verify_area(VERIFY_READ, (char *) arg, sizeof(volctrl));
- if(i<0)
- return i;
-
- copy_from_user(&volctrl, (char *) arg, sizeof(volctrl));
params[0] = SONY_SD_AUDIO_VOLUME;
- params[1] = volctrl.channel0;
- params[2] = volctrl.channel1;
+ params[1] = volctrl->channel0;
+ params[2] = volctrl->channel1;
return do_sony_cd_cmd_chk("VOLCTRL",SONY_SET_DRIVE_PARAM_CMD, params, 3, res_reg, &res_size);
}
- case CDROMEJECT: /* Eject the drive */
- do_sony_cd_cmd(SONY_AUDIO_STOP_CMD, NULL, 0, res_reg, &res_size);
- do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg, &res_size);
+ case CDROMSUBCHNL: /* Get subchannel info */
+ return sony_get_subchnl_info((struct cdrom_subchnl *)arg);
- sony_audio_status = CDROM_AUDIO_INVALID;
- return do_sony_cd_cmd_chk("EJECT",SONY_EJECT_CMD, NULL, 0, res_reg, &res_size);
-
- case CDROMREADAUDIO: /* Read 2352 byte audio tracks and 2340 byte
+ default:
+ return -EINVAL;
+ }
+}
+
+static int scd_dev_ioctl(struct cdrom_device_info *cdi,
+ unsigned int cmd,
+ unsigned long arg)
+{
+ int i;
+
+ switch (cmd)
+ {
+ case CDROMREADAUDIO: /* Read 2352 byte audio tracks and 2340 byte
raw data tracks. */
{
struct cdrom_read_audio ra;
@@ -2728,14 +3083,15 @@ static int scd_ioctl(struct inode *inode,
return -EIO;
}
- i=verify_area(VERIFY_READ, (char *) arg, sizeof(ra));
- if(i<0)
- return i;
- copy_from_user(&ra, (char *) arg, sizeof(ra));
+ if (ra.nframes == 0)
+ {
+ return 0;
+ }
i=verify_area(VERIFY_WRITE, ra.buf, CD_FRAMESIZE_RAW * ra.nframes);
if(i<0)
return i;
+ copy_from_user(&ra, (char *) arg, sizeof(ra));
if (ra.addr_format == CDROM_LBA)
{
@@ -2773,92 +3129,93 @@ static int scd_ioctl(struct inode *inode,
return -EINVAL;
}
- return(read_audio(&ra, inode));
+ return(read_audio(&ra));
}
return 0;
break;
- case CDROMEJECT_SW:
- is_auto_eject = arg;
- set_drive_params();
- return 0;
- break;
-
default:
return -EINVAL;
}
}
-
-/*
- * Open the drive for operations. Spin the drive up and read the table of
- * contents if these have not already been done.
- */
-static int
-scd_open(struct inode *inode,
- struct file *filp)
+static int scd_spinup(void)
{
unsigned char res_reg[12];
unsigned int res_size;
int num_spin_ups;
- unsigned char params[2];
+ num_spin_ups = 0;
- if ((filp) && filp->f_mode & 2)
- return -EROFS;
+respinup_on_open:
+ do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size);
- if (!sony_spun_up)
+ /* The drive sometimes returns error 0. I don't know why, but ignore
+ it. It seems to mean the drive has already done the operation. */
+ if ((res_size < 2) || ((res_reg[0] != 0) && (res_reg[1] != 0)))
{
- num_spin_ups = 0;
-
-respinup_on_open:
- do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size);
+ printk("Sony CDROM %s error (scd_open, spin up)\n", translate_error(res_reg[1]));
+ return 1;
+ }
+
+ do_sony_cd_cmd(SONY_READ_TOC_CMD, NULL, 0, res_reg, &res_size);
- /* The drive sometimes returns error 0. I don't know why, but ignore
- it. It seems to mean the drive has already done the operation. */
- if ((res_size < 2) || ((res_reg[0] != 0) && (res_reg[1] != 0)))
+ /* The drive sometimes returns error 0. I don't know why, but ignore
+ it. It seems to mean the drive has already done the operation. */
+ if ((res_size < 2) || ((res_reg[0] != 0) && (res_reg[1] != 0)))
+ {
+ /* If the drive is already playing, it's ok. */
+ if ((res_reg[1] == SONY_AUDIO_PLAYING_ERR) || (res_reg[1] == 0))
{
- printk("Sony CDROM error 0x%2.2x (scd_open, spin up)\n", res_reg[1]);
- return -EIO;
+ return 0;
}
-
- do_sony_cd_cmd(SONY_READ_TOC_CMD, NULL, 0, res_reg, &res_size);
- /* The drive sometimes returns error 0. I don't know why, but ignore
- it. It seems to mean the drive has already done the operation. */
- if ((res_size < 2) || ((res_reg[0] != 0) && (res_reg[1] != 0)))
+ /* If the drive says it is not spun up (even though we just did it!)
+ then retry the operation at least a few times. */
+ if ( (res_reg[1] == SONY_NOT_SPIN_ERR)
+ && (num_spin_ups < MAX_CDU31A_RETRIES))
{
- /* If the drive is already playing, it's ok. */
- if ((res_reg[1] == SONY_AUDIO_PLAYING_ERR) || (res_reg[1] == 0))
- {
- goto drive_spinning;
- }
+ num_spin_ups++;
+ goto respinup_on_open;
+ }
- /* If the drive says it is not spun up (even though we just did it!)
- then retry the operation at least a few times. */
- if ( (res_reg[1] == SONY_NOT_SPIN_ERR)
- && (num_spin_ups < MAX_CDU31A_RETRIES))
- {
- num_spin_ups++;
- goto respinup_on_open;
- }
+ printk("Sony CDROM error %s (scd_open, read toc)\n", translate_error(res_reg[1]));
+ do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg, &res_size);
+ return 1;
+ }
+ return 0;
+}
- printk("Sony CDROM error 0x%2.2x (scd_open, read toc)\n", res_reg[1]);
- do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg, &res_size);
-
+/*
+ * Open the drive for operations. Spin the drive up and read the table of
+ * contents if these have not already been done.
+ */
+static int
+scd_open(struct cdrom_device_info *cdi, int openmode)
+{
+ unsigned char res_reg[12];
+ unsigned int res_size;
+ unsigned char params[2];
+
+ MOD_INC_USE_COUNT;
+ if (sony_usage == 0)
+ {
+ if (scd_spinup() != 0) {
+ MOD_DEC_USE_COUNT;
return -EIO;
}
-
sony_get_toc();
if (!sony_toc_read)
{
do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg, &res_size);
+ MOD_DEC_USE_COUNT;
return -EIO;
}
/* For XA on the CDU31A only, we have to do special reads.
The CDU33A handles XA automagically. */
- if ( (sony_toc.disk_type == SONY_XA_DISK_TYPE)
+ /* if ( (sony_toc.disk_type == SONY_XA_DISK_TYPE) */
+ if ( (sony_toc.disk_type != 0x00)
&& (!is_double_speed))
{
params[0] = SONY_SD_DECODE_PARAM;
@@ -2873,6 +3230,7 @@ respinup_on_open:
printk("CDU31A: Unable to set XA params: 0x%2.2x\n", res_reg[1]);
}
sony_xa_mode = 1;
+printk("sony_xa_mode is set\n");
}
/* A non-XA disk. Set the parms back if necessary. */
else if (sony_xa_mode)
@@ -2889,25 +3247,13 @@ respinup_on_open:
printk("CDU31A: Unable to reset XA params: 0x%2.2x\n", res_reg[1]);
}
sony_xa_mode = 0;
+printk("sony_xa_mode is reset\n");
}
sony_spun_up = 1;
}
-drive_spinning:
-
- /* If filp is not NULL (standard open), try a disk change. */
- if (filp)
- {
- check_disk_change(inode->i_rdev);
- }
-
sony_usage++;
- MOD_INC_USE_COUNT;
-
- /* If all is OK (until now...), then lock the door */
- is_auto_eject = 0;
- set_drive_params();
return 0;
}
@@ -2917,51 +3263,54 @@ drive_spinning:
* Close the drive. Spin it down if no task is using it. The spin
* down will fail if playing audio, so audio play is OK.
*/
-static int
-scd_release(struct inode *inode,
- struct file *filp)
+static void
+scd_release(struct cdrom_device_info *cdi)
{
- unsigned char res_reg[12];
- unsigned int res_size;
-
-
- if (sony_usage > 0)
+ if (sony_usage == 1)
{
- sony_usage--;
- MOD_DEC_USE_COUNT;
- }
- if (sony_usage == 0)
- {
- sync_dev(inode->i_rdev);
-
- /* Unlock the door, only if nobody is using the drive */
- is_auto_eject = 1;
- set_drive_params();
+ unsigned char res_reg[12];
+ unsigned int res_size;
do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg, &res_size);
sony_spun_up = 0;
}
- return 0;
+ sony_usage--;
+ MOD_DEC_USE_COUNT;
}
-
-static struct file_operations scd_fops = {
- NULL, /* lseek - default */
- block_read, /* read - general block-dev read */
- block_write, /* write - general block-dev write */
- NULL, /* readdir - bad */
- NULL, /* poll */
- scd_ioctl, /* ioctl */
- NULL, /* mmap */
- scd_open, /* open */
- scd_release, /* release */
- NULL, /* fsync */
- NULL, /* fasync */
- scd_disk_change, /* media_change */
- NULL /* revalidate */
+static struct cdrom_device_ops scd_dops = {
+ scd_open, /* open */
+ scd_release, /* release */
+ scd_drive_status, /* drive status */
+ scd_media_changed, /* media changed */
+ scd_tray_move, /* tray move */
+ scd_lock_door, /* lock door */
+ scd_select_speed, /* select speed */
+ NULL, /* select disc */
+ scd_get_last_session, /* get last session */
+ scd_get_mcn, /* get universal product code */
+ scd_reset, /* hard reset */
+ scd_audio_ioctl, /* audio ioctl */
+ scd_dev_ioctl, /* device-specific ioctl */
+ CDC_OPEN_TRAY | CDC_LOCK | CDC_SELECT_SPEED | CDC_MULTI_SESSION |
+ CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO |
+ CDC_RESET | CDC_IOCTLS | CDC_DRIVE_STATUS, /* capability */
+ 1, /* number of minor devices */
};
+static struct cdrom_device_info scd_info = {
+ &scd_dops, /* device operations */
+ NULL, /* link */
+ NULL, /* handle */
+ MKDEV(MAJOR_NR,0), /* dev */
+ 0, /* mask */
+ 2, /* maximum speed */
+ 1, /* number of discs */
+ 0, /* options, not owned */
+ 0, /* mc_flags, not owned */
+ 0 /* use count, not owned */
+};
/* The different types of disc loading mechanisms supported */
static const char *load_mech[] __initdata = { "caddy", "tray", "pop-up", "unknown" };
@@ -3069,6 +3418,8 @@ cdu31a_init(void))
{
struct s_sony_drive_config drive_config;
unsigned int res_size;
+ char msg[255];
+ char buf[40];
int i;
int drive_found;
int tmp_irq;
@@ -3136,12 +3487,14 @@ cdu31a_init(void))
if (drive_found)
{
+ int deficiency=0;
+
request_region(cdu31a_port, 4,"cdu31a");
- if (register_blkdev(MAJOR_NR,"cdu31a",&scd_fops))
+ if (register_blkdev(MAJOR_NR,"cdu31a",&cdrom_fops))
{
printk("Unable to get major %d for CDU-31a\n", MAJOR_NR);
- return -EIO;
+ goto errout2;
}
if (SONY_HWC_DOUBLE_SPEED(drive_config))
@@ -3152,7 +3505,7 @@ cdu31a_init(void))
tmp_irq = cdu31a_irq; /* Need IRQ 0 because we can't sleep here. */
cdu31a_irq = 0;
- set_drive_params();
+ set_drive_params(sony_speed);
cdu31a_irq = tmp_irq;
@@ -3165,41 +3518,48 @@ cdu31a_init(void))
}
}
- printk(KERN_INFO "Sony I/F CDROM : %8.8s %16.16s %8.8s\n",
+ sprintf(msg, "Sony I/F CDROM : %8.8s %16.16s %8.8s\n",
drive_config.vendor_id,
drive_config.product_id,
drive_config.product_rev_level);
- printk(KERN_INFO " Capabilities: %s",
+ sprintf(buf, " Capabilities: %s",
load_mech[SONY_HWC_GET_LOAD_MECH(drive_config)]);
+ strcat(msg, buf);
if (SONY_HWC_AUDIO_PLAYBACK(drive_config))
{
- printk(", audio");
- }
+ strcat(msg, ", audio");
+ } else
+ deficiency |= CDC_PLAY_AUDIO;
if (SONY_HWC_EJECT(drive_config))
{
- printk(", eject");
- }
+ strcat(msg, ", eject");
+ } else
+ deficiency |= CDC_OPEN_TRAY;
if (SONY_HWC_LED_SUPPORT(drive_config))
{
- printk(", LED");
+ strcat(msg, ", LED");
}
if (SONY_HWC_ELECTRIC_VOLUME(drive_config))
{
- printk(", elec. Vol");
+ strcat(msg, ", elec. Vol");
}
if (SONY_HWC_ELECTRIC_VOLUME_CTL(drive_config))
{
- printk(", sep. Vol");
+ strcat(msg, ", sep. Vol");
}
if (is_double_speed)
{
- printk(", double speed");
- }
+ strcat(msg, ", double speed");
+ } else
+ deficiency |= CDC_SELECT_SPEED;
if (cdu31a_irq > 0)
{
- printk(", irq %d", cdu31a_irq);
+ sprintf(buf, ", irq %d", cdu31a_irq);
+ strcat(msg, buf);
}
- printk("\n");
+ strcat(msg, "\n");
+
+ is_a_cdu31a = strcmp("CD-ROM CDU31A", drive_config.product_id) == 0;
blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
read_ahead[MAJOR_NR] = CDU31A_READAHEAD;
@@ -3209,6 +3569,13 @@ cdu31a_init(void))
init_timer(&cdu31a_abort_timer);
cdu31a_abort_timer.function = handle_abort_timeout;
+
+ scd_info.mask = deficiency;
+
+ if (register_cdrom(&scd_info))
+ {
+ goto errout0;
+ }
}
@@ -3220,8 +3587,18 @@ cdu31a_init(void))
}
else
{
- return -EIO;
+ goto errout3;
+ }
+errout0:
+ printk("Unable to register CDU-31a with Uniform cdrom driver\n");
+ if (unregister_blkdev(MAJOR_NR, "cdu31a"))
+ {
+ printk("Can't unregister block device for cdu31a\n");
}
+errout2:
+ release_region(cdu31a_port,4);
+errout3:
+ return -EIO;
}
#ifdef MODULE
@@ -3235,6 +3612,11 @@ init_module(void)
void
cleanup_module(void)
{
+ if (unregister_cdrom(&scd_info))
+ {
+ printk("Can't unregister cdu31a from Uniform cdrom driver\n");
+ return;
+ }
if ((unregister_blkdev(MAJOR_NR, "cdu31a") == -EINVAL))
{
printk("Can't unregister cdu31a\n");
diff --git a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c
index fb5533706..e699cfa8e 100644
--- a/drivers/cdrom/cm206.c
+++ b/drivers/cdrom/cm206.c
@@ -70,9 +70,9 @@ History:
open only for ioctl operation, e.g., for operation of
tray etc.
4 apr 1996: 0.97 First implementation of layer between VFS and cdrom
- driver, a generic interface. Much of the functionality
+ driver, a Uniform interface. Much of the functionality
of cm206_open() and cm206_ioctl() is transferred to a
- new file cdrom.c and its header ucdrom.h.
+ new file cdrom.c and its header cdrom.h.
Upgrade to Linux kernel 1.3.78.
@@ -140,8 +140,6 @@ History:
#include <linux/malloc.h>
#include <linux/init.h>
-#include <linux/ucdrom.h>
-
#include <asm/io.h>
#define MAJOR_NR CM206_CDROM_MAJOR
@@ -152,7 +150,7 @@ History:
#undef AUTO_PROBE_MODULE
#define USE_INSW
-#include <linux/cm206.h>
+#include "cm206.h"
/* This variable defines whether or not to probe for adapter base port
address and interrupt request. It can be overridden by the boot
@@ -990,7 +988,7 @@ int cm206_media_changed(struct cdrom_device_info * cdi, int disc_nr)
else return -EIO;
}
-/* The new generic cdrom support. Routines should be concise, most of
+/* The new Uniform cdrom support. Routines should be concise, most of
the logic should be in cdrom.c */
/* returns number of times device is in use */
@@ -1021,24 +1019,6 @@ int cm206_drive_status(struct cdrom_device_info * cdi, int slot_nr)
return CDS_DISC_OK;
}
-/* gives current state of disc in drive */
-int cm206_disc_status(struct cdrom_device_info * cdi)
-{
- uch xa;
- get_drive_status();
- if ((cd->dsb & dsb_not_useful) | !(cd->dsb & dsb_disc_present))
- return CDS_NO_DISC;
- get_disc_status();
- if (DISC_STATUS & cds_all_audio) return CDS_AUDIO;
- xa = DISC_STATUS >> 4;
- switch (xa) {
- case 0: return CDS_DATA_1; /* can we detect CDS_DATA_2? */
- case 1: return CDS_XA_2_1; /* untested */
- case 2: return CDS_XA_2_2;
- }
- return 0;
-}
-
/* locks or unlocks door lock==1: lock; return 0 upon success */
int cm206_lock_door(struct cdrom_device_info * cdi, int lock)
{
@@ -1049,7 +1029,7 @@ int cm206_lock_door(struct cdrom_device_info * cdi, int lock)
}
/* Although a session start should be in LBA format, we return it in
- MSF format because it is slightly easier, and the new generic ioctl
+ MSF format because it is slightly easier, and the new Uniform ioctl
will take care of the necessary conversion. */
int cm206_get_last_session(struct cdrom_device_info * cdi,
struct cdrom_multisession * mssp)
@@ -1123,7 +1103,6 @@ static struct cdrom_device_ops cm206_dops = {
cm206_open, /* open */
cm206_release, /* release */
cm206_drive_status, /* drive status */
- cm206_disc_status, /* disc status */
cm206_media_changed, /* media changed */
cm206_tray_move, /* tray move */
cm206_lock_door, /* lock door */
@@ -1150,7 +1129,8 @@ static struct cdrom_device_info cm206_info = {
1, /* number of discs */
0, /* options, not owned */
0, /* mc_flags, not owned */
- 0 /* use count, not owned */
+ 0, /* use count, not owned */
+ "cm206" /* name of the device type */
};
/* This routine gets called during initialization if thing go wrong,
@@ -1281,7 +1261,7 @@ __initfunc(int cm206_init(void))
cleanup(3);
return -EIO;
}
- if (register_cdrom(&cm206_info, "cm206") != 0) {
+ if (register_cdrom(&cm206_info) != 0) {
printk("Cannot register for cdrom %d!\n", MAJOR_NR);
cleanup(3);
return -EIO;
diff --git a/drivers/cdrom/gscd.c b/drivers/cdrom/gscd.c
index 685990a77..3fad59c73 100644
--- a/drivers/cdrom/gscd.c
+++ b/drivers/cdrom/gscd.c
@@ -64,7 +64,7 @@
#define MAJOR_NR GOLDSTAR_CDROM_MAJOR
#include <linux/blk.h>
#define gscd_port gscd /* for compatible parameter passing with "insmod" */
-#include <linux/gscd.h>
+#include "gscd.h"
static int gscdPresent = 0;
@@ -1072,7 +1072,7 @@ int result;
static void gscd_hsg2msf (long hsg, struct msf *msf)
{
- hsg += CD_BLOCK_OFFSET;
+ hsg += CD_MSF_OFFSET;
msf -> min = hsg / (CD_FRAMES*CD_SECS);
hsg %= CD_FRAMES*CD_SECS;
msf -> sec = hsg / CD_FRAMES;
@@ -1100,7 +1100,7 @@ static long gscd_msf2hsg (struct msf *mp)
return gscd_bcd2bin(mp -> frame)
+ gscd_bcd2bin(mp -> sec) * CD_FRAMES
+ gscd_bcd2bin(mp -> min) * CD_FRAMES * CD_SECS
- - CD_BLOCK_OFFSET;
+ - CD_MSF_OFFSET;
}
static int gscd_bcd2bin (unsigned char bcd)
diff --git a/drivers/cdrom/isp16.c b/drivers/cdrom/isp16.c
index 88c070eba..f0b5e7499 100644
--- a/drivers/cdrom/isp16.c
+++ b/drivers/cdrom/isp16.c
@@ -47,9 +47,9 @@
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/ioport.h>
-#include <linux/isp16.h>
#include <linux/init.h>
#include <asm/io.h>
+#include "isp16.h"
static short isp16_detect(void);
static short isp16_c928__detect(void);
diff --git a/drivers/cdrom/mcd.c b/drivers/cdrom/mcd.c
index e4d1a73f6..090d58498 100644
--- a/drivers/cdrom/mcd.c
+++ b/drivers/cdrom/mcd.c
@@ -65,6 +65,8 @@
Michael K. Johnson <johnsonm@redhat.com> added retries on open
for slow drives which take a while to recognize that they contain
a CD.
+
+ November 1997 -- ported to the Uniform CD-ROM driver by Erik Andersen.
*/
#include <linux/module.h>
@@ -91,23 +93,10 @@
#include <linux/blk.h>
#define mcd_port mcd /* for compatible parameter passing with "insmod" */
-#include <linux/mcd.h>
+#include "mcd.h"
-#if 0
-static int mcd_sizes[] = { 0 };
-#endif
static int mcd_blocksizes[1] = { 0, };
-/* I know putting defines in this file is probably stupid, but it should be */
-/* the only place that they are really needed... I HOPE! :) */
-
-/* How many sectors to read at 1x when an error at 2x speed occurs. */
-/* You can change this to anything from 2 to 32767, but 30 seems to */
-/* work best for me. I have found that when the drive has problems */
-/* reading one sector, it will have troubles reading the next few. */
-#define SINGLE_HOLD_SECTORS 30
-
-#define MCMD_2X_READ 0xC1 /* Double Speed Read DON'T TOUCH! */
/* I added A flag to drop to 1x speed if too many errors 0 = 1X ; 1 = 2X */
static int mcdDouble = 0;
@@ -195,6 +184,48 @@ static int updateToc(void);
static int GetDiskInfo(void);
static int GetToc(void);
static int getValue(unsigned char *result);
+static int mcd_open(struct cdrom_device_info * cdi, int purpose);
+static void mcd_release(struct cdrom_device_info * cdi);
+static int mcd_media_changed(struct cdrom_device_info * cdi, int disc_nr);
+static int mcd_tray_move(struct cdrom_device_info * cdi, int position);
+int mcd_audio_ioctl(struct cdrom_device_info * cdi, unsigned int cmd,
+ void * arg);
+int mcd_drive_status(struct cdrom_device_info * cdi, int slot_nr);
+
+static struct cdrom_device_ops mcd_dops = {
+ mcd_open, /* open */
+ mcd_release, /* release */
+ mcd_drive_status, /* drive status */
+ //NULL, /* drive status */
+ mcd_media_changed, /* media changed */
+ mcd_tray_move, /* tray move */
+ NULL, /* lock door */
+ NULL, /* select speed */
+ NULL, /* select disc */
+ NULL, /* get last session */
+ NULL, /* get universal product code */
+ NULL, /* hard reset */
+ mcd_audio_ioctl, /* audio ioctl */
+ NULL, /* device-specific ioctl */
+ CDC_OPEN_TRAY | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO
+ | CDC_DRIVE_STATUS, /* capability */
+ 0, /* number of minor devices */
+};
+
+static struct cdrom_device_info mcd_info = {
+ &mcd_dops, /* device operations */
+ NULL, /* link */
+ NULL, /* handle */
+ MKDEV(MAJOR_NR,0), /* dev */
+ 0, /* mask */
+ 2, /* maximum speed */
+ 1, /* number of discs */
+ 0, /* options, not owned */
+ 0, /* mc_flags, not owned */
+ 0, /* use count, not owned */
+ "mcd", /* name of the device type */
+};
+
__initfunc(void mcd_setup(char *str, int *ints))
@@ -209,9 +240,8 @@ __initfunc(void mcd_setup(char *str, int *ints))
#endif /* WORK_AROUND_MITSUMI_BUG_93 */
}
-
-static int
-check_mcd_change(kdev_t full_dev)
+
+static int mcd_media_changed(struct cdrom_device_info * cdi, int disc_nr)
{
int retval, target;
@@ -219,7 +249,7 @@ check_mcd_change(kdev_t full_dev)
#if 1 /* the below is not reliable */
return 0;
#endif
- target = MINOR(full_dev);
+ target = cdi->dev;
if (target > 0) {
printk("mcd: Mitsumi CD-ROM request error: invalid device.\n");
@@ -245,11 +275,11 @@ statusCmd(void)
for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++)
{
+ outb(MCMD_GET_STATUS, MCDPORT(0)); /* send get-status cmd */
- outb(MCMD_GET_STATUS, MCDPORT(0)); /* send get-status cmd */
st = getMcdStatus(MCD_STATUS_DELAY);
- if (st != -1)
- break;
+ if (st != -1)
+ break;
}
return st;
@@ -277,6 +307,33 @@ mcdPlay(struct mcd_Play_msf *arg)
}
+static int
+mcd_tray_move(struct cdrom_device_info * cdi, int position)
+{
+ int i;
+ if (position) {
+ /* Eject */
+ /* all drives can at least stop! */
+ if (audioStatus == CDROM_AUDIO_PLAY) {
+ outb(MCMD_STOP, MCDPORT(0));
+ i = getMcdStatus(MCD_STATUS_DELAY);
+ }
+
+ audioStatus = CDROM_AUDIO_NO_STATUS;
+
+ outb(MCMD_EJECT, MCDPORT(0));
+ /*
+ * the status (i) shows failure on all but the FX drives.
+ * But nothing we can do about that in software!
+ * So just read the status and forget it. - Jon.
+ */
+ i = getMcdStatus(MCD_STATUS_DELAY);
+ return 0;
+ }
+ else
+ return -EINVAL;
+}
+
long
msf2hsg(struct msf *mp)
{
@@ -287,22 +344,18 @@ msf2hsg(struct msf *mp)
}
-static int
-mcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
- unsigned long arg)
+int mcd_audio_ioctl(struct cdrom_device_info * cdi, unsigned int cmd,
+ void * arg)
{
int i, st;
struct mcd_Toc qInfo;
- struct cdrom_ti ti;
- struct cdrom_tochdr tocHdr;
- struct cdrom_msf msf;
- struct cdrom_tocentry entry;
+ struct cdrom_ti *ti;
+ struct cdrom_tochdr *tocHdr;
+ struct cdrom_msf *msf;
+ struct cdrom_subchnl *subchnl;
+ struct cdrom_tocentry *entry;
struct mcd_Toc *tocPtr;
- struct cdrom_subchnl subchnl;
- struct cdrom_volctrl volctrl;
-
- if (!ip)
- return -EINVAL;
+ struct cdrom_volctrl *volctrl;
st = statusCmd();
if (st < 0)
@@ -311,7 +364,7 @@ mcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
if (!tocUpToDate)
{
i = updateToc();
- if (i < 0)
+ if (i < 0)
return i; /* error reading TOC */
}
@@ -372,24 +425,20 @@ mcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */
- st = verify_area(VERIFY_READ, (void *) arg, sizeof ti);
- if (st)
- return st;
+ ti=(struct cdrom_ti *) arg;
- copy_from_user(&ti, (void *) arg, sizeof ti);
-
- if (ti.cdti_trk0 < DiskInfo.first
- || ti.cdti_trk0 > DiskInfo.last
- || ti.cdti_trk1 < ti.cdti_trk0)
+ if (ti->cdti_trk0 < DiskInfo.first
+ || ti->cdti_trk0 > DiskInfo.last
+ || ti->cdti_trk1 < ti->cdti_trk0)
{
return -EINVAL;
}
- if (ti.cdti_trk1 > DiskInfo.last)
- ti. cdti_trk1 = DiskInfo.last;
+ if (ti->cdti_trk1 > DiskInfo.last)
+ ti->cdti_trk1 = DiskInfo.last;
- mcd_Play.start = Toc[ti.cdti_trk0].diskTime;
- mcd_Play.end = Toc[ti.cdti_trk1 + 1].diskTime;
+ mcd_Play.start = Toc[ti->cdti_trk0].diskTime;
+ mcd_Play.end = Toc[ti->cdti_trk1 + 1].diskTime;
#ifdef MCD_DEBUG
printk("play: %02x:%02x.%02x to %02x:%02x.%02x\n",
@@ -415,27 +464,23 @@ printk("play: %02x:%02x.%02x to %02x:%02x.%02x\n",
audioStatus = CDROM_AUDIO_NO_STATUS;
}
- st = verify_area(VERIFY_READ, (void *) arg, sizeof msf);
- if (st)
- return st;
-
- copy_from_user(&msf, (void *) arg, sizeof msf);
+ msf=(struct cdrom_msf *) arg;
/* convert to bcd */
- bin2bcd(&msf.cdmsf_min0);
- bin2bcd(&msf.cdmsf_sec0);
- bin2bcd(&msf.cdmsf_frame0);
- bin2bcd(&msf.cdmsf_min1);
- bin2bcd(&msf.cdmsf_sec1);
- bin2bcd(&msf.cdmsf_frame1);
+ bin2bcd(&msf->cdmsf_min0);
+ bin2bcd(&msf->cdmsf_sec0);
+ bin2bcd(&msf->cdmsf_frame0);
+ bin2bcd(&msf->cdmsf_min1);
+ bin2bcd(&msf->cdmsf_sec1);
+ bin2bcd(&msf->cdmsf_frame1);
- mcd_Play.start.min = msf.cdmsf_min0;
- mcd_Play.start.sec = msf.cdmsf_sec0;
- mcd_Play.start.frame = msf.cdmsf_frame0;
- mcd_Play.end.min = msf.cdmsf_min1;
- mcd_Play.end.sec = msf.cdmsf_sec1;
- mcd_Play.end.frame = msf.cdmsf_frame1;
+ mcd_Play.start.min = msf->cdmsf_min0;
+ mcd_Play.start.sec = msf->cdmsf_sec0;
+ mcd_Play.start.frame = msf->cdmsf_frame0;
+ mcd_Play.end.min = msf->cdmsf_min1;
+ mcd_Play.end.sec = msf->cdmsf_sec1;
+ mcd_Play.end.frame = msf->cdmsf_frame1;
#ifdef MCD_DEBUG
printk("play: %02x:%02x.%02x to %02x:%02x.%02x\n",
@@ -454,102 +499,66 @@ mcd_Play.end.min, mcd_Play.end.sec, mcd_Play.end.frame);
return 0;
case CDROMREADTOCHDR: /* Read the table of contents header */
- st = verify_area(VERIFY_WRITE, (void *) arg, sizeof tocHdr);
- if (st)
- return st;
-
- tocHdr.cdth_trk0 = DiskInfo.first;
- tocHdr.cdth_trk1 = DiskInfo.last;
- copy_to_user((void *) arg, &tocHdr, sizeof tocHdr);
+ tocHdr=(struct cdrom_tochdr *) arg;
+ tocHdr->cdth_trk0 = DiskInfo.first;
+ tocHdr->cdth_trk1 = DiskInfo.last;
return 0;
case CDROMREADTOCENTRY: /* Read an entry in the table of contents */
+ entry=(struct cdrom_tocentry *) arg;
+ if (entry->cdte_track == CDROM_LEADOUT)
+ tocPtr = &Toc[DiskInfo.last - DiskInfo.first + 1];
- st = verify_area(VERIFY_WRITE, (void *) arg, sizeof entry);
- if (st)
- return st;
-
- copy_from_user(&entry, (void *) arg, sizeof entry);
- if (entry.cdte_track == CDROM_LEADOUT)
- /* XXX */
- tocPtr = &Toc[DiskInfo.last + 1];
-
- else if (entry.cdte_track > DiskInfo.last
- || entry.cdte_track < DiskInfo.first)
+ else if (entry->cdte_track > DiskInfo.last
+ || entry->cdte_track < DiskInfo.first)
return -EINVAL;
else
- tocPtr = &Toc[entry.cdte_track];
+ tocPtr = &Toc[entry->cdte_track];
- entry.cdte_adr = tocPtr -> ctrl_addr;
- entry.cdte_ctrl = tocPtr -> ctrl_addr >> 4;
+ entry->cdte_adr = tocPtr -> ctrl_addr;
+ entry->cdte_ctrl = tocPtr -> ctrl_addr >> 4;
- if (entry.cdte_format == CDROM_LBA)
- entry.cdte_addr.lba = msf2hsg(&tocPtr -> diskTime);
+ if (entry->cdte_format == CDROM_LBA)
+ entry->cdte_addr.lba = msf2hsg(&tocPtr -> diskTime);
- else if (entry.cdte_format == CDROM_MSF)
+ else if (entry->cdte_format == CDROM_MSF)
{
- entry.cdte_addr.msf.minute = bcd2bin(tocPtr -> diskTime.min);
- entry.cdte_addr.msf.second = bcd2bin(tocPtr -> diskTime.sec);
- entry.cdte_addr.msf.frame = bcd2bin(tocPtr -> diskTime.frame);
+ entry->cdte_addr.msf.minute = bcd2bin(tocPtr -> diskTime.min);
+ entry->cdte_addr.msf.second = bcd2bin(tocPtr -> diskTime.sec);
+ entry->cdte_addr.msf.frame = bcd2bin(tocPtr -> diskTime.frame);
}
else
return -EINVAL;
- copy_to_user((void *) arg, &entry, sizeof entry);
return 0;
case CDROMSUBCHNL: /* Get subchannel info */
- st = verify_area(VERIFY_WRITE, (void *) arg, sizeof subchnl);
- if (st)
- return st;
-
- copy_from_user(&subchnl, (void *) arg, sizeof subchnl);
-
+ subchnl=(struct cdrom_subchnl *) arg;
if (GetQChannelInfo(&qInfo) < 0)
return -EIO;
- subchnl.cdsc_audiostatus = audioStatus;
- subchnl.cdsc_adr = qInfo.ctrl_addr;
- subchnl.cdsc_ctrl = qInfo.ctrl_addr >> 4;
- subchnl.cdsc_trk = bcd2bin(qInfo.track);
- subchnl.cdsc_ind = bcd2bin(qInfo.pointIndex);
-
- if (subchnl.cdsc_format == CDROM_LBA)
- {
- subchnl.cdsc_absaddr.lba = msf2hsg(&qInfo.diskTime);
- subchnl.cdsc_reladdr.lba = msf2hsg(&qInfo.trackTime);
- }
-
- else if (subchnl.cdsc_format == CDROM_MSF)
- {
- subchnl.cdsc_absaddr.msf.minute = bcd2bin(qInfo.diskTime.min);
- subchnl.cdsc_absaddr.msf.second = bcd2bin(qInfo.diskTime.sec);
- subchnl.cdsc_absaddr.msf.frame = bcd2bin(qInfo.diskTime.frame);
-
- subchnl.cdsc_reladdr.msf.minute = bcd2bin(qInfo.trackTime.min);
- subchnl.cdsc_reladdr.msf.second = bcd2bin(qInfo.trackTime.sec);
- subchnl.cdsc_reladdr.msf.frame = bcd2bin(qInfo.trackTime.frame);
- }
-
- else
- return -EINVAL;
-
- copy_to_user((void *) arg, &subchnl, sizeof subchnl);
- return 0;
+ subchnl->cdsc_audiostatus = audioStatus;
+ subchnl->cdsc_adr = qInfo.ctrl_addr;
+ subchnl->cdsc_ctrl = qInfo.ctrl_addr >> 4;
+ subchnl->cdsc_trk = bcd2bin(qInfo.track);
+ subchnl->cdsc_ind = bcd2bin(qInfo.pointIndex);
+ subchnl->cdsc_absaddr.msf.minute = bcd2bin(qInfo.diskTime.min);
+ subchnl->cdsc_absaddr.msf.second = bcd2bin(qInfo.diskTime.sec);
+ subchnl->cdsc_absaddr.msf.frame = bcd2bin(qInfo.diskTime.frame);
+ subchnl->cdsc_reladdr.msf.minute = bcd2bin(qInfo.trackTime.min);
+ subchnl->cdsc_reladdr.msf.second = bcd2bin(qInfo.trackTime.sec);
+ subchnl->cdsc_reladdr.msf.frame = bcd2bin(qInfo.trackTime.frame);
+ return(0);
case CDROMVOLCTRL: /* Volume control */
- st = verify_area(VERIFY_READ, (void *) arg, sizeof(volctrl));
- if (st)
- return st;
-
- copy_from_user(&volctrl, (char *) arg, sizeof(volctrl));
+ volctrl=(struct cdrom_volctrl *) arg;
outb(MCMD_SET_VOLUME, MCDPORT(0));
- outb(volctrl.channel0, MCDPORT(0));
+ outb(volctrl->channel0, MCDPORT(0));
outb(255, MCDPORT(0));
- outb(volctrl.channel1, MCDPORT(0));
+ outb(volctrl->channel1, MCDPORT(0));
outb(255, MCDPORT(0));
i = getMcdStatus(MCD_STATUS_DELAY);
@@ -567,29 +576,11 @@ mcd_Play.end.min, mcd_Play.end.sec, mcd_Play.end.frame);
return 0;
- case CDROMEJECT:
- /* all drives can at least stop! */
- if (audioStatus == CDROM_AUDIO_PLAY) {
- outb(MCMD_STOP, MCDPORT(0));
- i = getMcdStatus(MCD_STATUS_DELAY);
- }
-
- audioStatus = CDROM_AUDIO_NO_STATUS;
-
- outb(MCMD_EJECT, MCDPORT(0));
- /*
- * the status (i) shows failure on all but the FX drives.
- * But nothing we can do about that in software!
- * So just read the status and forget it. - Jon.
- */
- i = getMcdStatus(MCD_STATUS_DELAY);
- return 0;
default:
return -EINVAL;
}
}
-
/*
* Take care of the different block sizes between cdrom and Linux.
* When Linux gets variable block sizes this will probably go away.
@@ -1095,44 +1086,28 @@ mcd_invalidate_buffers(void)
/*
* Open the device special file. Check that a disk is in.
*/
-
-int
-mcd_open(struct inode *ip, struct file *fp)
+static int mcd_open(struct cdrom_device_info * cdi, int purpose)
{
- int st;
- int count = 0;
-
+ int st, count=0;
if (mcdPresent == 0)
return -ENXIO; /* no hardware */
-
- if (fp->f_mode & 2) /* write access? */
- return -EROFS;
-
- if (!mcd_open_count && mcd_state == MCD_S_IDLE) {
-
- mcd_invalidate_buffers();
-
- do {
- st = statusCmd(); /* check drive status */
- if (st == -1)
- return -EIO; /* drive doesn't respond */
- if ((st & MST_READY) == 0) { /* no disk? wait a sec... */
- current->state = TASK_INTERRUPTIBLE;
- current->timeout = jiffies + HZ;
- schedule();
- }
- } while (((st & MST_READY) == 0) && count++ < MCD_RETRY_ATTEMPTS);
-
- if ((st & MST_READY) == 0) /* no disk in drive */
- {
- printk("mcd: no disk in drive\n");
- return -EIO;
- }
-
- if (updateToc() < 0)
- return -EIO;
- }
+ if (!mcd_open_count && mcd_state == MCD_S_IDLE) {
+ mcd_invalidate_buffers();
+ do {
+ st = statusCmd(); /* check drive status */
+ if (st == -1)
+ return -EIO; /* drive doesn't respond */
+ if ((st & MST_READY) == 0) { /* no disk? wait a sec... */
+ current->state = TASK_INTERRUPTIBLE;
+ current->timeout = jiffies + HZ;
+ schedule();
+ }
+ } while (((st & MST_READY) == 0) && count++ < MCD_RETRY_ATTEMPTS);
+
+ if (updateToc() < 0)
+ return -EIO;
+ }
++mcd_open_count;
MOD_INC_USE_COUNT;
return 0;
@@ -1142,34 +1117,37 @@ mcd_open(struct inode *ip, struct file *fp)
/*
* On close, we flush all mcd blocks from the buffer cache.
*/
-
-static int
-mcd_release(struct inode * inode, struct file * file)
+static void mcd_release(struct cdrom_device_info * cdi)
{ MOD_DEC_USE_COUNT;
if (!--mcd_open_count) {
mcd_invalidate_buffers();
- sync_dev(inode->i_rdev);
- invalidate_buffers(inode -> i_rdev);
}
- return 0;
}
-static struct file_operations mcd_fops = {
- NULL, /* lseek - default */
- block_read, /* read - general block-dev read */
- block_write, /* write - general block-dev write */
- NULL, /* readdir - bad */
- NULL, /* poll */
- mcd_ioctl, /* ioctl */
- NULL, /* mmap */
- mcd_open, /* open */
- mcd_release, /* release */
- NULL, /* fsync */
- NULL, /* fasync */
- check_mcd_change, /* media change */
- NULL /* revalidate */
-};
+
+/* This routine gets called during initialization if thing go wrong,
+ * and is used in cleanup_module as well. */
+void cleanup(int level)
+{
+ switch (level) {
+ case 3:
+ if (unregister_cdrom(&mcd_info)) {
+ printk(KERN_WARNING "Can't unregister cdrom mcd\n");
+ return;
+ }
+ free_irq(mcd_irq, NULL);
+ case 2:
+ release_region(mcd_port,4);
+ case 1:
+ if (unregister_blkdev(MAJOR_NR, "mcd")) {
+ printk(KERN_WARNING "Can't unregister major mcd\n");
+ return;
+ }
+ default:
+ }
+}
+
/*
@@ -1180,23 +1158,21 @@ __initfunc(int mcd_init(void))
{
int count;
unsigned char result[3];
+ char msg[80];
if (mcd_port <= 0 || mcd_irq <= 0) {
printk("skip mcd_init\n");
return -EIO;
}
- printk(KERN_INFO "mcd=0x%x,%d: ", mcd_port, mcd_irq);
-
- if (register_blkdev(MAJOR_NR, "mcd", &mcd_fops) != 0)
+ if (register_blkdev(MAJOR_NR, "mcd", &cdrom_fops) != 0)
{
printk("Unable to get major %d for Mitsumi CD-ROM\n",
MAJOR_NR);
return -EIO;
}
-
if (check_region(mcd_port, 4)) {
- unregister_blkdev(MAJOR_NR, "mcd");
+ cleanup(1);
printk("Init failed, I/O port (%X) already in use\n",
mcd_port);
return -EIO;
@@ -1212,7 +1188,7 @@ __initfunc(int mcd_init(void))
for (count = 0; count < 2000000; count++)
(void) inb(MCDPORT(1)); /* delay a bit */
- outb(0x40, MCDPORT(0)); /* send get-stat cmd */
+ outb(0x40, MCDPORT(0)); /* send get-stat cmd */
for (count = 0; count < 2000000; count++)
if (!(inb(MCDPORT(1)) & MFL_STATUS))
break;
@@ -1220,7 +1196,7 @@ __initfunc(int mcd_init(void))
if (count >= 2000000) {
printk("Init failed. No mcd device at 0x%x irq %d\n",
mcd_port, mcd_irq);
- unregister_blkdev(MAJOR_NR, "mcd");
+ cleanup(1);
return -EIO;
}
count = inb(MCDPORT(0)); /* pick up the status */
@@ -1228,26 +1204,16 @@ __initfunc(int mcd_init(void))
outb(MCMD_GET_VERSION,MCDPORT(0));
for(count=0;count<3;count++)
if(getValue(result+count)) {
- unregister_blkdev(MAJOR_NR, "mcd");
printk("mitsumi get version failed at 0x%d\n",
mcd_port);
+ cleanup(1);
return -EIO;
}
if (result[0] == result[1] && result[1] == result[2]) {
- unregister_blkdev(MAJOR_NR, "mcd");
+ cleanup(1);
return -EIO;
}
- printk("Mitsumi status, type and version : %02X %c %x ",
- result[0],result[1],result[2]);
-
- if (result[1] == 'D')
- {
- printk("Double Speed CD ROM\n");
- MCMD_DATA_READ = MCMD_2X_READ;
- mcdDouble = 1; /* Added flag to drop to 1x speed if too many errors */
- }
- else printk("Single Speed CD ROM\n");
mcdVersion=result[2];
@@ -1259,9 +1225,22 @@ __initfunc(int mcd_init(void))
if (request_irq(mcd_irq, mcd_interrupt, SA_INTERRUPT, "Mitsumi CD", NULL))
{
printk("Unable to get IRQ%d for Mitsumi CD-ROM\n", mcd_irq);
- unregister_blkdev(MAJOR_NR, "mcd");
+ cleanup(1);
return -EIO;
}
+
+ if (result[1] == 'D')
+ {
+ sprintf(msg, " mcd: Mitsumi Double Speed CD-ROM at port=0x%x, irq=%d\n", mcd_port, mcd_irq);
+ MCMD_DATA_READ = MCMD_2X_READ;
+ mcd_info.speed = 2;
+ mcdDouble = 1; /* Added flag to drop to 1x speed if too many errors */
+ }
+ else {
+ sprintf(msg, " mcd: Mitsumi Single Speed CD-ROM at port=0x%x, irq=%d\n", mcd_port, mcd_irq);
+ mcd_info.speed = 2;
+ }
+
request_region(mcd_port, 4,"mcd");
outb(MCMD_CONFIG_DRIVE, MCDPORT(0));
@@ -1276,6 +1255,14 @@ __initfunc(int mcd_init(void))
mcd_invalidate_buffers();
mcdPresent = 1;
+
+ if (register_cdrom(&mcd_info) != 0) {
+ printk("Cannot register Mitsumi CD-ROM!\n");
+ cleanup(3);
+ return -EIO;
+ }
+ printk(msg);
+
return 0;
}
@@ -1412,15 +1399,31 @@ getMcdStatus(int timeout)
}
+/* gives current state of the drive This function is quite unreliable,
+ and should probably be rewritten by someone, eventually... */
+int mcd_drive_status(struct cdrom_device_info * cdi, int slot_nr)
+{
+ int st;
+
+ st = statusCmd(); /* check drive status */
+ if (st == -1)
+ return -EIO; /* drive doesn't respond */
+ if ((st & MST_READY)) return CDS_DISC_OK;
+ if ((st & MST_DOOR_OPEN)) return CDS_TRAY_OPEN;
+ if ((st & MST_DSK_CHG)) return CDS_NO_DISC;
+ if ((st & MST_BUSY)) return CDS_DRIVE_NOT_READY;
+ return -EIO;
+}
+
+
/*
- * Read a value from the drive. Should return quickly, so a busy wait
- * is used to avoid excessive rescheduling.
+ * Read a value from the drive.
*/
static int
getValue(unsigned char *result)
{
- int count;
+ int count;
int s;
for (count = 0; count < 2000; count++)
@@ -1521,13 +1524,6 @@ GetDiskInfo()
DiskInfo.first = bcd2bin(DiskInfo.first);
DiskInfo.last = bcd2bin(DiskInfo.last);
- if (getValue(&DiskInfo.diskLength.min) < 0) return -1;
- if (getValue(&DiskInfo.diskLength.sec) < 0) return -1;
- if (getValue(&DiskInfo.diskLength.frame) < 0) return -1;
- if (getValue(&DiskInfo.firstTrack.min) < 0) return -1;
- if (getValue(&DiskInfo.firstTrack.sec) < 0) return -1;
- if (getValue(&DiskInfo.firstTrack.frame) < 0) return -1;
-
#ifdef MCD_DEBUG
printk("Disk Info: first %d last %d length %02x:%02x.%02x first %02x:%02x.%02x\n",
DiskInfo.first,
@@ -1540,6 +1536,13 @@ printk("Disk Info: first %d last %d length %02x:%02x.%02x first %02x:%02x.%02x\n
DiskInfo.firstTrack.frame);
#endif
+ if (getValue(&DiskInfo.diskLength.min) < 0) return -1;
+ if (getValue(&DiskInfo.diskLength.sec) < 0) return -1;
+ if (getValue(&DiskInfo.diskLength.frame) < 0) return -1;
+ if (getValue(&DiskInfo.firstTrack.min) < 0) return -1;
+ if (getValue(&DiskInfo.firstTrack.sec) < 0) return -1;
+ if (getValue(&DiskInfo.firstTrack.frame) < 0) return -1;
+
return 0;
}
@@ -1635,12 +1638,6 @@ int init_module(void)
void cleanup_module(void)
{
- if ((unregister_blkdev(MAJOR_NR, "mcd") == -EINVAL))
- { printk("What's that: can't unregister mcd\n");
- return;
- }
- release_region(mcd_port,4);
- free_irq(mcd_irq, NULL);
- printk(KERN_INFO "mcd module released.\n");
+ cleanup(3);
}
#endif MODULE
diff --git a/drivers/cdrom/mcdx.c b/drivers/cdrom/mcdx.c
index dea152349..f46388d06 100644
--- a/drivers/cdrom/mcdx.c
+++ b/drivers/cdrom/mcdx.c
@@ -73,7 +73,10 @@ static const char *mcdx_c_version
/* for compatible parameter passing with "insmod" */
#define mcdx_drive_map mcdx
-#include <linux/mcdx.h>
+#include "mcdx.h"
+
+#define MCDX_QUIET 0
+
#ifndef HZ
#error HZ not defined
@@ -107,8 +110,6 @@ static const char *mcdx_c_version
const int REQUEST_SIZE = 800; /* should be less then 255 * 4 */
const int DIRECT_SIZE = 400; /* should be less then REQUEST_SIZE */
-const unsigned long ACLOSE_INHIBIT = 800; /* 1/100 s of autoclose inhibit */
-
enum drivemodes { TOC, DATA, RAW, COOKED };
enum datamodes { MODE0, MODE1, MODE2 };
enum resetmodes { SOFT, HARD };
@@ -160,8 +161,6 @@ struct s_drive_stuff {
volatile int introk; /* status of last irq operation */
volatile int busy; /* drive performs an operation */
volatile int lock; /* exclusive usage */
- int eject_sw; /* 1 - eject on last close (default 0) */
- int autoclose; /* 1 - close the door on open (default 1) */
/* cd infos */
struct s_diskinfo di;
@@ -197,7 +196,6 @@ struct s_drive_stuff {
unsigned char playcmd; /* play should always be single speed */
unsigned int xxx; /* set if changed, reset while open */
unsigned int yyy; /* set if changed, reset by media_changed */
- unsigned long ejected; /* time we called the eject function */
int users; /* keeps track of open/close */
int lastsector; /* last block accessible */
int status; /* last operation's error / status */
@@ -214,22 +212,25 @@ struct s_drive_stuff {
/* declared in blk.h */
int mcdx_init(void);
void do_mcdx_request(void);
-int check_mcdx_media_change(kdev_t);
/* already declared in init/main */
void mcdx_setup(char *, int *);
/* Indirect exported functions. These functions are exported by their
addresses, such as mcdx_open and mcdx_close in the
- structure fops. */
+ structure mcdx_dops. */
/* ??? exported by the mcdx_sigaction struct */
static void mcdx_intr(int, void *, struct pt_regs*);
/* exported by file_ops */
-static int mcdx_open(struct inode*, struct file*);
-static int mcdx_close(struct inode*, struct file*);
-static int mcdx_ioctl(struct inode*, struct file*, unsigned int, unsigned long);
+static int mcdx_open(struct cdrom_device_info * cdi, int purpose);
+static void mcdx_close(struct cdrom_device_info * cdi);
+static int mcdx_media_changed(struct cdrom_device_info * cdi, int disc_nr);
+static int mcdx_tray_move(struct cdrom_device_info * cdi, int position);
+static int mcdx_lockdoor(struct cdrom_device_info * cdi, int lock);
+static int mcdx_audio_ioctl(struct cdrom_device_info * cdi, unsigned int cmd,
+ void * arg);
/* misc internal support functions */
static void log2msf(unsigned int, struct cdrom_msf0*);
@@ -243,13 +244,10 @@ static int mcdx_transfer(struct s_drive_stuff*, char* buf, int sector, int nr_se
static int mcdx_xfer(struct s_drive_stuff*, char* buf, int sector, int nr_sectors);
static int mcdx_config(struct s_drive_stuff*, int);
-static int mcdx_closedoor(struct s_drive_stuff*, int);
static int mcdx_requestversion(struct s_drive_stuff*, struct s_version*, int);
-static int mcdx_lockdoor(struct s_drive_stuff*, int, int);
static int mcdx_stop(struct s_drive_stuff*, int);
static int mcdx_hold(struct s_drive_stuff*, int);
static int mcdx_reset(struct s_drive_stuff*, enum resetmodes, int);
-static int mcdx_eject(struct s_drive_stuff*, int);
static int mcdx_setdrivemode(struct s_drive_stuff*, enum drivemodes, int);
static int mcdx_setdatamode(struct s_drive_stuff*, enum datamodes, int);
static int mcdx_requestsubqcode(struct s_drive_stuff*, struct s_subqcode*, int);
@@ -276,37 +274,79 @@ static struct s_drive_stuff* mcdx_irq_map[16] =
0, 0, 0, 0, 0, 0, 0, 0};
MODULE_PARM(mcdx, "1-4i");
-static struct file_operations mcdx_fops = {
- NULL, /* lseek - use kernel default */
- block_read, /* read - general block-dev read */
- block_write, /* write - general block-dev write */
- NULL, /* no readdir */
- NULL, /* no poll */
- mcdx_ioctl, /* ioctl() */
- NULL, /* no mmap */
- mcdx_open, /* open() */
- mcdx_close, /* close() */
- NULL, /* fsync */
- NULL, /* fasync */
- check_mcdx_media_change, /* media_change */
- NULL /* revalidate */
+static struct cdrom_device_ops mcdx_dops = {
+ mcdx_open, /* open */
+ mcdx_close, /* release */
+ NULL, /* drive status */
+ mcdx_media_changed, /* media changed */
+ mcdx_tray_move, /* tray move */
+ mcdx_lockdoor, /* lock door */
+ NULL, /* select speed */
+ NULL, /* select disc */
+ NULL, /* get last session */
+ NULL, /* get universal product code */
+ NULL, /* hard reset */
+ mcdx_audio_ioctl, /* audio ioctl */
+ NULL, /* device-specific ioctl */
+ CDC_OPEN_TRAY | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO
+ | CDC_DRIVE_STATUS, /* capability */
+ 0, /* number of minor devices */
+};
+
+static struct cdrom_device_info mcdx_info = {
+ &mcdx_dops, /* device operations */
+ NULL, /* link */
+ NULL, /* handle */
+ MKDEV(MAJOR_NR,0), /* dev */
+ 0, /* mask */
+ 2, /* maximum speed */
+ 1, /* number of discs */
+ 0, /* options, not owned */
+ 0, /* mc_flags, not owned */
+ 0, /* use count, not owned */
+ "mcdx", /* name of the device type */
};
+
+
/* KERNEL INTERFACE FUNCTIONS **************************************/
-static int
-mcdx_ioctl(
- struct inode* ip, struct file* fp,
- unsigned int cmd, unsigned long arg)
+
+static int mcdx_audio_ioctl(struct cdrom_device_info * cdi, unsigned int cmd,
+ void * arg)
{
- struct s_drive_stuff *stuffp = mcdx_stuffp[MINOR(ip->i_rdev)];
+ struct s_drive_stuff *stuffp = mcdx_stuffp[MINOR(cdi->dev)];
if (!stuffp->present) return -ENXIO;
- if (!ip) return -EINVAL;
+
+ if (stuffp->xxx)
+ {
+ if(-1 == mcdx_requesttocdata(stuffp, &stuffp->di, 1))
+ {
+ stuffp->lastsector = -1;
+ }
+ else
+ {
+ stuffp->lastsector = (CD_FRAMESIZE / 512)
+ * msf2log(&stuffp->di.msf_leadout) - 1;
+ }
+
+ if (stuffp->toc)
+ {
+ kfree(stuffp->toc);
+ stuffp->toc = NULL;
+ if (-1 == mcdx_readtoc(stuffp)) return -1;
+ }
+
+ stuffp->xxx=0;
+ }
switch (cmd) {
- case CDROMSTART: {
- xtrace(IOCTL, "ioctl() START\n");
+ case CDROMSTART: {
+ xtrace(IOCTL, "ioctl() START\n");
+ /* Spin up the drive. Don't think we can do this.
+ * For now, ignore it.
+ */
return 0;
}
@@ -319,51 +359,40 @@ mcdx_ioctl(
}
case CDROMPLAYTRKIND: {
- int ans;
- struct cdrom_ti ti;
+ struct cdrom_ti *ti=(struct cdrom_ti *) arg;
xtrace(IOCTL, "ioctl() PLAYTRKIND\n");
- if ((ans = verify_area(VERIFY_READ, (void*) arg, sizeof(ti))))
- return ans;
- copy_from_user(&ti, (void*) arg, sizeof(ti));
- if ((ti.cdti_trk0 < stuffp->di.n_first)
- || (ti.cdti_trk0 > stuffp->di.n_last)
- || (ti.cdti_trk1 < stuffp->di.n_first))
- return -EINVAL;
- if (ti.cdti_trk1 > stuffp->di.n_last) ti.cdti_trk1 = stuffp->di.n_last;
- xtrace(PLAYTRK, "ioctl() track %d to %d\n", ti.cdti_trk0, ti.cdti_trk1);
-
- return mcdx_playtrk(stuffp, &ti);
+ if ((ti->cdti_trk0 < stuffp->di.n_first)
+ || (ti->cdti_trk0 > stuffp->di.n_last)
+ || (ti->cdti_trk1 < stuffp->di.n_first))
+ return -EINVAL;
+ if (ti->cdti_trk1 > stuffp->di.n_last)
+ ti->cdti_trk1 = stuffp->di.n_last;
+ xtrace(PLAYTRK, "ioctl() track %d to %d\n", ti->cdti_trk0, ti->cdti_trk1);
+ return mcdx_playtrk(stuffp, ti);
}
case CDROMPLAYMSF: {
- int ans;
- struct cdrom_msf msf;
+ struct cdrom_msf *msf=(struct cdrom_msf *) arg;
xtrace(IOCTL, "ioctl() PLAYMSF\n");
if ((stuffp->audiostatus == CDROM_AUDIO_PLAY)
&& (-1 == mcdx_hold(stuffp, 1))) return -EIO;
- if ((ans = verify_area(
- VERIFY_READ, (void*) arg, sizeof(struct cdrom_msf))))
- return ans;
-
- copy_from_user(&msf, (void*) arg, sizeof msf);
-
- msf.cdmsf_min0 = uint2bcd(msf.cdmsf_min0);
- msf.cdmsf_sec0 = uint2bcd(msf.cdmsf_sec0);
- msf.cdmsf_frame0 = uint2bcd(msf.cdmsf_frame0);
+ msf->cdmsf_min0 = uint2bcd(msf->cdmsf_min0);
+ msf->cdmsf_sec0 = uint2bcd(msf->cdmsf_sec0);
+ msf->cdmsf_frame0 = uint2bcd(msf->cdmsf_frame0);
- msf.cdmsf_min1 = uint2bcd(msf.cdmsf_min1);
- msf.cdmsf_sec1 = uint2bcd(msf.cdmsf_sec1);
- msf.cdmsf_frame1 = uint2bcd(msf.cdmsf_frame1);
+ msf->cdmsf_min1 = uint2bcd(msf->cdmsf_min1);
+ msf->cdmsf_sec1 = uint2bcd(msf->cdmsf_sec1);
+ msf->cdmsf_frame1 = uint2bcd(msf->cdmsf_frame1);
- stuffp->stop.dt.minute = msf.cdmsf_min1;
- stuffp->stop.dt.second = msf.cdmsf_sec1;
- stuffp->stop.dt.frame = msf.cdmsf_frame1;
+ stuffp->stop.dt.minute = msf->cdmsf_min1;
+ stuffp->stop.dt.second = msf->cdmsf_sec1;
+ stuffp->stop.dt.frame = msf->cdmsf_frame1;
- return mcdx_playmsf(stuffp, &msf);
+ return mcdx_playmsf(stuffp, msf);
}
case CDROMRESUME: {
@@ -372,103 +401,70 @@ mcdx_ioctl(
}
case CDROMREADTOCENTRY: {
- struct cdrom_tocentry entry;
+ struct cdrom_tocentry *entry=(struct cdrom_tocentry *) arg;
struct s_subqcode *tp = NULL;
- int ans;
-
xtrace(IOCTL, "ioctl() READTOCENTRY\n");
if (-1 == mcdx_readtoc(stuffp)) return -1;
-
- if ((ans = verify_area(VERIFY_WRITE, (void *) arg, sizeof(entry)))) return ans;
- copy_from_user(&entry, (void *) arg, sizeof(entry));
-
- if (entry.cdte_track == CDROM_LEADOUT)
+ if (entry->cdte_track == CDROM_LEADOUT)
tp = &stuffp->toc[stuffp->di.n_last - stuffp->di.n_first + 1];
- else if (entry.cdte_track > stuffp->di.n_last
- || entry.cdte_track < stuffp->di.n_first) return -EINVAL;
- else tp = &stuffp->toc[entry.cdte_track - stuffp->di.n_first];
-
- if (NULL == tp) xwarn("FATAL.\n");
-
- entry.cdte_adr = tp->control;
- entry.cdte_ctrl = tp->control >> 4;
-
- if (entry.cdte_format == CDROM_MSF) {
- entry.cdte_addr.msf.minute = bcd2uint(tp->dt.minute);
- entry.cdte_addr.msf.second = bcd2uint(tp->dt.second);
- entry.cdte_addr.msf.frame = bcd2uint(tp->dt.frame);
- } else if (entry.cdte_format == CDROM_LBA)
- entry.cdte_addr.lba = msf2log(&tp->dt);
- else return -EINVAL;
-
- copy_to_user((void*) arg, &entry, sizeof(entry));
+ else if (entry->cdte_track > stuffp->di.n_last
+ || entry->cdte_track < stuffp->di.n_first) return -EINVAL;
+ else tp = &stuffp->toc[entry->cdte_track - stuffp->di.n_first];
+ if (NULL == tp)
+ return -EIO;
+ entry->cdte_adr = tp->control;
+ entry->cdte_ctrl = tp->control >> 4;
+ /* Always return stuff in MSF, and let the Uniform cdrom driver
+ worry about what the user actually wants */
+ entry->cdte_addr.msf.minute = bcd2uint(tp->dt.minute);
+ entry->cdte_addr.msf.second = bcd2uint(tp->dt.second);
+ entry->cdte_addr.msf.frame = bcd2uint(tp->dt.frame);
return 0;
}
case CDROMSUBCHNL: {
- int ans;
- struct cdrom_subchnl sub;
+ struct cdrom_subchnl *sub= (struct cdrom_subchnl *)arg;
struct s_subqcode q;
xtrace(IOCTL, "ioctl() SUBCHNL\n");
- if ((ans = verify_area(VERIFY_WRITE,
- (void*) arg, sizeof(sub)))) return ans;
-
- copy_from_user(&sub, (void*) arg, sizeof(sub));
-
- if (-1 == mcdx_requestsubqcode(stuffp, &q, 2)) return -EIO;
+ if (-1 == mcdx_requestsubqcode(stuffp, &q, 2))
+ return -EIO;
xtrace(SUBCHNL, "audiostatus: %x\n", stuffp->audiostatus);
- sub.cdsc_audiostatus = stuffp->audiostatus;
- sub.cdsc_adr = q.control;
- sub.cdsc_ctrl = q.control >> 4;
- sub.cdsc_trk = bcd2uint(q.tno);
- sub.cdsc_ind = bcd2uint(q.index);
+ sub->cdsc_audiostatus = stuffp->audiostatus;
+ sub->cdsc_adr = q.control;
+ sub->cdsc_ctrl = q.control >> 4;
+ sub->cdsc_trk = bcd2uint(q.tno);
+ sub->cdsc_ind = bcd2uint(q.index);
xtrace(SUBCHNL, "trk %d, ind %d\n",
- sub.cdsc_trk, sub.cdsc_ind);
-
- if (sub.cdsc_format == CDROM_LBA) {
- sub.cdsc_absaddr.lba = msf2log(&q.dt);
- sub.cdsc_reladdr.lba = msf2log(&q.tt);
- xtrace(SUBCHNL, "lba: abs %d, rel %d\n",
- sub.cdsc_absaddr.lba,
- sub.cdsc_reladdr.lba);
- } else if (sub.cdsc_format == CDROM_MSF) {
- sub.cdsc_absaddr.msf.minute = bcd2uint(q.dt.minute);
- sub.cdsc_absaddr.msf.second = bcd2uint(q.dt.second);
- sub.cdsc_absaddr.msf.frame = bcd2uint(q.dt.frame);
- sub.cdsc_reladdr.msf.minute = bcd2uint(q.tt.minute);
- sub.cdsc_reladdr.msf.second = bcd2uint(q.tt.second);
- sub.cdsc_reladdr.msf.frame = bcd2uint(q.tt.frame);
- xtrace(SUBCHNL,
- "msf: abs %02d:%02d:%02d, rel %02d:%02d:%02d\n",
- sub.cdsc_absaddr.msf.minute,
- sub.cdsc_absaddr.msf.second,
- sub.cdsc_absaddr.msf.frame,
- sub.cdsc_reladdr.msf.minute,
- sub.cdsc_reladdr.msf.second,
- sub.cdsc_reladdr.msf.frame);
- } else return -EINVAL;
-
- copy_to_user((void*) arg, &sub, sizeof(sub));
+ sub->cdsc_trk, sub->cdsc_ind);
+ /* Always return stuff in MSF, and let the Uniform cdrom driver
+ worry about what the user actually wants */
+ sub->cdsc_absaddr.msf.minute = bcd2uint(q.dt.minute);
+ sub->cdsc_absaddr.msf.second = bcd2uint(q.dt.second);
+ sub->cdsc_absaddr.msf.frame = bcd2uint(q.dt.frame);
+ sub->cdsc_reladdr.msf.minute = bcd2uint(q.tt.minute);
+ sub->cdsc_reladdr.msf.second = bcd2uint(q.tt.second);
+ sub->cdsc_reladdr.msf.frame = bcd2uint(q.tt.frame);
+ xtrace(SUBCHNL,
+ "msf: abs %02d:%02d:%02d, rel %02d:%02d:%02d\n",
+ sub->cdsc_absaddr.msf.minute, sub->cdsc_absaddr.msf.second,
+ sub->cdsc_absaddr.msf.frame, sub->cdsc_reladdr.msf.minute,
+ sub->cdsc_reladdr.msf.second, sub->cdsc_reladdr.msf.frame);
return 0;
}
case CDROMREADTOCHDR: {
- struct cdrom_tochdr toc;
- int ans;
+ struct cdrom_tochdr *toc=(struct cdrom_tochdr *) arg;
xtrace(IOCTL, "ioctl() READTOCHDR\n");
- if ((ans = verify_area(VERIFY_WRITE, (void*) arg, sizeof toc)))
- return ans;
- toc.cdth_trk0 = stuffp->di.n_first;
- toc.cdth_trk1 = stuffp->di.n_last;
- copy_to_user((void*) arg, &toc, sizeof toc);
+ toc->cdth_trk0 = stuffp->di.n_first;
+ toc->cdth_trk1 = stuffp->di.n_last;
xtrace(TOCHDR, "ioctl() track0 = %d, track1 = %d\n",
stuffp->di.n_first, stuffp->di.n_last);
return 0;
@@ -485,78 +481,41 @@ mcdx_ioctl(
}
case CDROMMULTISESSION: {
- int ans;
- struct cdrom_multisession ms;
+ struct cdrom_multisession *ms=(struct cdrom_multisession *) arg;
xtrace(IOCTL, "ioctl() MULTISESSION\n");
- if (0 != (ans = verify_area(VERIFY_WRITE, (void*) arg,
- sizeof(struct cdrom_multisession))))
- return ans;
-
- copy_from_user(&ms, (void*) arg, sizeof(struct cdrom_multisession));
- if (ms.addr_format == CDROM_MSF) {
- ms.addr.msf.minute = bcd2uint(stuffp->multi.msf_last.minute);
- ms.addr.msf.second = bcd2uint(stuffp->multi.msf_last.second);
- ms.addr.msf.frame = bcd2uint(stuffp->multi.msf_last.frame);
- } else if (ms.addr_format == CDROM_LBA)
- ms.addr.lba = msf2log(&stuffp->multi.msf_last);
- else
- return -EINVAL;
- ms.xa_flag = !!stuffp->multi.multi;
-
- copy_to_user((void*) arg, &ms, sizeof(struct cdrom_multisession));
- if (ms.addr_format == CDROM_MSF) {
- xtrace(MS,
- "ioctl() (%d, %02x:%02x.%02x [%02x:%02x.%02x])\n",
- ms.xa_flag,
- ms.addr.msf.minute,
- ms.addr.msf.second,
- ms.addr.msf.frame,
- stuffp->multi.msf_last.minute,
- stuffp->multi.msf_last.second,
- stuffp->multi.msf_last.frame);
- } else {
- xtrace(MS,
- "ioctl() (%d, 0x%08x [%02x:%02x.%02x])\n",
- ms.xa_flag,
- ms.addr.lba,
- stuffp->multi.msf_last.minute,
- stuffp->multi.msf_last.second,
- stuffp->multi.msf_last.frame);
- }
+ /* Always return stuff in LBA, and let the Uniform cdrom driver
+ worry about what the user actually wants */
+ ms->addr.lba = msf2log(&stuffp->multi.msf_last);
+ ms->xa_flag = !!stuffp->multi.multi;
+ xtrace(MS, "ioctl() (%d, 0x%08x [%02x:%02x.%02x])\n",
+ ms->xa_flag, ms->addr.lba, stuffp->multi.msf_last.minute,
+ stuffp->multi.msf_last.second,stuffp->multi.msf_last.frame);
+
return 0;
}
case CDROMEJECT: {
xtrace(IOCTL, "ioctl() EJECT\n");
if (stuffp->users > 1) return -EBUSY;
- if (-1 == mcdx_eject(stuffp, 1)) return -EIO;
- return 0;
+ return(mcdx_tray_move(cdi, 1));
}
- case CDROMEJECT_SW: {
- stuffp->eject_sw = arg;
- return 0;
+ case CDROMCLOSETRAY: {
+ xtrace(IOCTL, "ioctl() CDROMCLOSETRAY\n");
+ return(mcdx_tray_move(cdi, 0));
}
case CDROMVOLCTRL: {
- int ans;
- struct cdrom_volctrl volctrl;
-
+ struct cdrom_volctrl *volctrl=(struct cdrom_volctrl *)arg;
xtrace(IOCTL, "ioctl() VOLCTRL\n");
- if ((ans = verify_area(
- VERIFY_READ,
- (void*) arg,
- sizeof(volctrl))))
- return ans;
- copy_from_user(&volctrl, (char *) arg, sizeof(volctrl));
#if 0 /* not tested! */
/* adjust for the weirdness of workman (md) */
/* can't test it (hs) */
volctrl.channel2 = volctrl.channel1;
volctrl.channel1 = volctrl.channel3 = 0x00;
#endif
- return mcdx_setattentuator(stuffp, &volctrl, 2);
+ return mcdx_setattentuator(stuffp, volctrl, 2);
}
default:
@@ -645,19 +604,12 @@ void do_mcdx_request()
goto again;
}
-static int
-mcdx_open(struct inode *ip, struct file *fp)
-/* actions done on open:
- * 1) get the drives status
- * 2) set the stuffp.readcmd if a CD is in.
- * (return no error if no CD is found, since ioctl()
- * needs an opened device */
+static int
+mcdx_open(struct cdrom_device_info * cdi, int purpose)
{
struct s_drive_stuff *stuffp;
-
xtrace(OPENCLOSE, "open()\n");
-
- stuffp = mcdx_stuffp[MINOR(ip->i_rdev)];
+ stuffp = mcdx_stuffp[MINOR(cdi->dev)];
if (!stuffp->present) return -ENXIO;
/* Make the modules looking used ... (thanx bjorn).
@@ -665,248 +617,154 @@ mcdx_open(struct inode *ip, struct file *fp)
* on error return */
MOD_INC_USE_COUNT;
-#if 0
- /* We don't allow multiple users of a drive. In case of data CDs
- * they'll be used by mounting, which ensures anyway exclusive
- * usage. In case of audio CDs it's meaningless to try playing to
- * different tracks at once! (md)
- * - Hey, what about cat /dev/cdrom? Why shouldn't it called by
- * more then one process at any time? (hs) */
- if (stuffp->users) {
- MOD_DEC_USE_COUNT;
- return -EBUSY;
- }
-#endif
-
/* this is only done to test if the drive talks with us */
if (-1 == mcdx_getstatus(stuffp, 1)) {
MOD_DEC_USE_COUNT;
return -EIO;
}
- /* close the door,
- * This should be explained ...
- * - If the door is open and its last close is too recent the
- * autoclose wouldn't probably be what we want.
- * - If we didn't try to close the door yet, close it and go on.
- * - If we autoclosed the door and couldn't succeed in find a valid
- * CD we shouldn't try autoclose any longer (until a valid CD is
- * in.) */
-
- if (inb((unsigned int) stuffp->rreg_status) & MCDX_RBIT_DOOR) {
- if (jiffies - stuffp->ejected < ACLOSE_INHIBIT) {
- MOD_DEC_USE_COUNT;
- return -EIO;
- }
- if (stuffp->autoclose) mcdx_closedoor(stuffp, 1);
- else {
- MOD_DEC_USE_COUNT;
- return -EIO;
- }
- }
-
- /* if the media changed we will have to do a little more */
- if (stuffp->xxx) {
-
- xtrace(OPENCLOSE, "open() media changed\n");
- /* but wait - the time of media change will be set at the
- * very last of this block - it seems, some of the following
- * talk() will detect a media change ... (I think, config()
- * is the reason. */
+ if (stuffp->xxx) {
+ xtrace(OPENCLOSE, "open() media changed\n");
stuffp->audiostatus = CDROM_AUDIO_INVALID;
- stuffp->readcmd = 0;
-
- /* get the multisession information */
- xtrace(OPENCLOSE, "open() Request multisession info\n");
- if (-1 == mcdx_requestmultidiskinfo(
- stuffp, &stuffp->multi, 6)) {
- xinfo("No multidiskinfo\n");
- stuffp->autoclose = 0;
- /*
- MOD_DEC_USE_COUNT;
- stuffp->xxx = 0;
- return -EIO;
- */
- } else {
- /* we succeeded, so on next open(2) we could try auto close
- * again */
- stuffp->autoclose = 1;
-
-#if !MCDX_QUIET
- if (stuffp->multi.multi > 2)
- xinfo("open() unknown multisession value (%d)\n",
- stuffp->multi.multi);
-#endif
-
- /* multisession ? */
- if (!stuffp->multi.multi)
- stuffp->multi.msf_last.second = 2;
-
- xtrace(OPENCLOSE, "open() MS: %d, last @ %02x:%02x.%02x\n",
- stuffp->multi.multi,
- stuffp->multi.msf_last.minute,
- stuffp->multi.msf_last.second,
- stuffp->multi.msf_last.frame);
-
- { ; } /* got multisession information */
-
- /* request the disks table of contents (aka diskinfo) */
- if (-1 == mcdx_requesttocdata(stuffp, &stuffp->di, 1)) {
-
- stuffp->lastsector = -1;
-
+ stuffp->readcmd = 0;
+ xtrace(OPENCLOSE, "open() Request multisession info\n");
+ if (-1 == mcdx_requestmultidiskinfo( stuffp, &stuffp->multi, 6))
+ xinfo("No multidiskinfo\n");
} else {
+ /* multisession ? */
+ if (!stuffp->multi.multi)
+ stuffp->multi.msf_last.second = 2;
+
+ xtrace(OPENCLOSE, "open() MS: %d, last @ %02x:%02x.%02x\n",
+ stuffp->multi.multi,
+ stuffp->multi.msf_last.minute,
+ stuffp->multi.msf_last.second,
+ stuffp->multi.msf_last.frame);
+
+ { ; } /* got multisession information */
+ /* request the disks table of contents (aka diskinfo) */
+ if (-1 == mcdx_requesttocdata(stuffp, &stuffp->di, 1)) {
+
+ stuffp->lastsector = -1;
+
+ } else {
+
+ stuffp->lastsector = (CD_FRAMESIZE / 512)
+ * msf2log(&stuffp->di.msf_leadout) - 1;
+
+ xtrace(OPENCLOSE, "open() start %d (%02x:%02x.%02x) %d\n",
+ stuffp->di.n_first,
+ stuffp->di.msf_first.minute,
+ stuffp->di.msf_first.second,
+ stuffp->di.msf_first.frame,
+ msf2log(&stuffp->di.msf_first));
+ xtrace(OPENCLOSE, "open() last %d (%02x:%02x.%02x) %d\n",
+ stuffp->di.n_last,
+ stuffp->di.msf_leadout.minute,
+ stuffp->di.msf_leadout.second,
+ stuffp->di.msf_leadout.frame,
+ msf2log(&stuffp->di.msf_leadout));
+ }
+
+ if (stuffp->toc) {
+ xtrace(MALLOC, "open() free old toc @ %p\n", stuffp->toc);
+ kfree(stuffp->toc);
- stuffp->lastsector = (CD_FRAMESIZE / 512)
- * msf2log(&stuffp->di.msf_leadout) - 1;
-
- xtrace(OPENCLOSE, "open() start %d (%02x:%02x.%02x) %d\n",
- stuffp->di.n_first,
- stuffp->di.msf_first.minute,
- stuffp->di.msf_first.second,
- stuffp->di.msf_first.frame,
- msf2log(&stuffp->di.msf_first));
- xtrace(OPENCLOSE, "open() last %d (%02x:%02x.%02x) %d\n",
- stuffp->di.n_last,
- stuffp->di.msf_leadout.minute,
- stuffp->di.msf_leadout.second,
- stuffp->di.msf_leadout.frame,
- msf2log(&stuffp->di.msf_leadout));
- }
-
- if (stuffp->toc) {
- xtrace(MALLOC, "open() free old toc @ %p\n", stuffp->toc);
- kfree(stuffp->toc);
-
- stuffp->toc = NULL;
- }
+ stuffp->toc = NULL;
+ }
- xtrace(OPENCLOSE, "open() init irq generation\n");
- if (-1 == mcdx_config(stuffp, 1)) {
- MOD_DEC_USE_COUNT;
- return -EIO;
- }
+ xtrace(OPENCLOSE, "open() init irq generation\n");
+ if (-1 == mcdx_config(stuffp, 1)) {
+ MOD_DEC_USE_COUNT;
+ return -EIO;
+ }
#if FALLBACK
- /* Set the read speed */
- xwarn("AAA %x AAA\n", stuffp->readcmd);
- if (stuffp->readerrs) stuffp->readcmd = READ1X;
- else stuffp->readcmd =
- stuffp->present | SINGLE ? READ1X : READ2X;
- xwarn("XXX %x XXX\n", stuffp->readcmd);
+ /* Set the read speed */
+ xwarn("AAA %x AAA\n", stuffp->readcmd);
+ if (stuffp->readerrs) stuffp->readcmd = READ1X;
+ else stuffp->readcmd =
+ stuffp->present | SINGLE ? READ1X : READ2X;
+ xwarn("XXX %x XXX\n", stuffp->readcmd);
#else
- stuffp->readcmd = stuffp->present | SINGLE ? READ1X : READ2X;
+ stuffp->readcmd = stuffp->present | SINGLE ? READ1X : READ2X;
#endif
- /* try to get the first sector, iff any ... */
- if (stuffp->lastsector >= 0) {
- char buf[512];
- int ans;
- int tries;
-
- stuffp->xa = 0;
- stuffp->audio = 0;
-
- for (tries = 6; tries; tries--) {
-
- stuffp->introk = 1;
-
- xtrace(OPENCLOSE, "open() try as %s\n",
- stuffp->xa ? "XA" : "normal");
-
- /* set data mode */
- if (-1 == (ans = mcdx_setdatamode(stuffp,
- stuffp->xa ? MODE2 : MODE1, 1))) {
- /* MOD_DEC_USE_COUNT, return -EIO; */
- stuffp->xa = 0;
- break;
- }
-
- if ((stuffp->audio = e_audio(ans))) break;
+ /* try to get the first sector, iff any ... */
+ if (stuffp->lastsector >= 0) {
+ char buf[512];
+ int ans;
+ int tries;
- while (0 == (ans = mcdx_transfer(stuffp, buf, 0, 1)))
- ;
+ stuffp->xa = 0;
+ stuffp->audio = 0;
- if (ans == 1) break;
- stuffp->xa = !stuffp->xa;
- }
- /* if (!tries) MOD_DEC_USE_COUNT, return -EIO; */
- }
+ for (tries = 6; tries; tries--) {
- /* xa disks will be read in raw mode, others not */
- if (-1 == mcdx_setdrivemode(stuffp,
- stuffp->xa ? RAW : COOKED, 1)) {
- MOD_DEC_USE_COUNT;
- return -EIO;
- }
+ stuffp->introk = 1;
- if (stuffp->audio) {
- xinfo("open() audio disk found\n");
- } else if (stuffp->lastsector >= 0) {
- xinfo("open() %s%s disk found\n",
- stuffp->xa ? "XA / " : "",
- stuffp->multi.multi ? "Multi Session" : "Single Session");
- }
+ xtrace(OPENCLOSE, "open() try as %s\n",
+ stuffp->xa ? "XA" : "normal");
+ /* set data mode */
+ if (-1 == (ans = mcdx_setdatamode(stuffp,
+ stuffp->xa ? MODE2 : MODE1, 1))) {
+ /* MOD_DEC_USE_COUNT, return -EIO; */
+ stuffp->xa = 0;
+ break;
+ }
- /* stuffp->xxx = 0; */
- }
+ if ((stuffp->audio = e_audio(ans))) break;
- /* lock the door if not already done */
- if (0 == stuffp->users && (-1 == mcdx_lockdoor(stuffp, 1, 1))) {
- MOD_DEC_USE_COUNT;
- return -EIO;
- }
- }
+ while (0 == (ans = mcdx_transfer(stuffp, buf, 0, 1)))
+ ;
+ if (ans == 1) break;
+ stuffp->xa = !stuffp->xa;
+ }
+ }
+ /* xa disks will be read in raw mode, others not */
+ if (-1 == mcdx_setdrivemode(stuffp,
+ stuffp->xa ? RAW : COOKED, 1)) {
+ MOD_DEC_USE_COUNT;
+ return -EIO;
+ }
+ if (stuffp->audio) {
+ xinfo("open() audio disk found\n");
+ } else if (stuffp->lastsector >= 0) {
+ xinfo("open() %s%s disk found\n",
+ stuffp->xa ? "XA / " : "",
+ stuffp->multi.multi ? "Multi Session" : "Single Session");
+ }
+ }
stuffp->xxx = 0;
stuffp->users++;
return 0;
-
}
-static int
-mcdx_close(struct inode *ip, struct file *fp)
+static void mcdx_close(struct cdrom_device_info * cdi)
{
struct s_drive_stuff *stuffp;
xtrace(OPENCLOSE, "close()\n");
- stuffp = mcdx_stuffp[MINOR(ip->i_rdev)];
-
- if (0 == --stuffp->users) {
- sync_dev(ip->i_rdev); /* needed for r/o device? */
-
- /* invalidate_inodes(ip->i_rdev); */
- invalidate_buffers(ip->i_rdev);
-
-
-#if !MCDX_QUIET
- if (-1 == mcdx_lockdoor(stuffp, 0, 3))
- xinfo("close() Cannot unlock the door\n");
-#else
- mcdx_lockdoor(stuffp, 0, 3);
-#endif
-
- /* eject if wished */
- if (stuffp->eject_sw) mcdx_eject(stuffp, 1);
+ stuffp = mcdx_stuffp[MINOR(cdi->dev)];
- }
+ --stuffp->users;
MOD_DEC_USE_COUNT;
- return 0;
}
-int check_mcdx_media_change(kdev_t full_dev)
+static int mcdx_media_changed(struct cdrom_device_info * cdi, int disc_nr)
/* Return: 1 if media changed since last call to this function
0 otherwise */
{
struct s_drive_stuff *stuffp;
- xinfo("check_mcdx_media_change called for device %s\n",
- kdevname(full_dev));
+ xinfo("mcdx_media_changed called for device %s\n",
+ kdevname(cdi->dev));
- stuffp = mcdx_stuffp[MINOR(full_dev)];
+ stuffp = mcdx_stuffp[MINOR(cdi->dev)];
mcdx_getstatus(stuffp, 1);
if (stuffp->yyy == 0) return 0;
@@ -1140,6 +998,10 @@ void cleanup_module(void)
for (i = 0; i < MCDX_NDRIVES; i++) {
struct s_drive_stuff *stuffp;
+ if (unregister_cdrom(&mcdx_info)) {
+ printk(KERN_WARNING "Can't unregister cdrom mcdx\n");
+ return;
+ }
stuffp = mcdx_stuffp[i];
if (!stuffp) continue;
release_region((unsigned long) stuffp->wreg_data, MCDX_IO_SIZE);
@@ -1153,7 +1015,7 @@ void cleanup_module(void)
kfree(stuffp);
}
- if (unregister_blkdev(MAJOR_NR, DEVICE_NAME) != 0) {
+ if (unregister_blkdev(MAJOR_NR, "mcdx") != 0) {
xwarn("cleanup() unregister_blkdev() failed\n");
}
#if !MCDX_QUIET
@@ -1168,7 +1030,7 @@ void cleanup_module(void)
__initfunc(int mcdx_init(void))
{
int drive;
-
+ char msg[80];
#ifdef MODULE
xwarn("Version 2.14(hs) for " UTS_RELEASE "\n");
#else
@@ -1204,7 +1066,6 @@ __initfunc(int mcdx_init(void))
/* set default values */
memset(stuffp, 0, sizeof(*stuffp));
- stuffp->autoclose = 1; /* close the door on open(2) */
stuffp->present = 0; /* this should be 0 already */
stuffp->toc = NULL; /* this should be NULL already */
@@ -1274,7 +1135,7 @@ __initfunc(int mcdx_init(void))
}
xtrace(INIT, "init() register blkdev\n");
- if (register_blkdev(MAJOR_NR, DEVICE_NAME, &mcdx_fops) != 0) {
+ if (register_blkdev(MAJOR_NR, "mcdx", &cdrom_fops) != 0) {
xwarn("%s=0x%3p,%d: Init failed. Can't get major %d.\n",
MCDX,
stuffp->wreg_data, stuffp->irq, MAJOR_NR);
@@ -1289,7 +1150,7 @@ __initfunc(int mcdx_init(void))
xtrace(INIT, "init() subscribe irq and i/o\n");
mcdx_irq_map[stuffp->irq] = stuffp;
- if (request_irq(stuffp->irq, mcdx_intr, SA_INTERRUPT, DEVICE_NAME, NULL)) {
+ if (request_irq(stuffp->irq, mcdx_intr, SA_INTERRUPT, "mcdx", NULL)) {
xwarn("%s=0x%3p,%d: Init failed. Can't get irq (%d).\n",
MCDX,
stuffp->wreg_data, stuffp->irq, stuffp->irq);
@@ -1299,7 +1160,7 @@ __initfunc(int mcdx_init(void))
}
request_region((unsigned int) stuffp->wreg_data,
MCDX_IO_SIZE,
- DEVICE_NAME);
+ "mcdx");
xtrace(INIT, "init() get garbage\n");
{
@@ -1318,15 +1179,23 @@ __initfunc(int mcdx_init(void))
stuffp->minor = drive;
- xwarn("(%s) installed at 0x%3p, irq %d."
- " (Firmware version %c %x)\n",
- DEVICE_NAME,
+ sprintf(msg, " mcdx: Mitsumi CD-ROM installed at 0x%3p, irq %d."
+ " (Firmware version %c %x)\n",
stuffp->wreg_data, stuffp->irq, version.code,
version.ver);
mcdx_stuffp[drive] = stuffp;
xtrace(INIT, "init() mcdx_stuffp[%d] = %p\n", drive, stuffp);
+ if (register_cdrom(&mcdx_info) != 0) {
+ printk("Cannot register Mitsumi CD-ROM!\n");
+ release_region((unsigned long) stuffp->wreg_data, MCDX_IO_SIZE);
+ free_irq(stuffp->irq, NULL);
+ kfree(stuffp);
+ if (unregister_blkdev(MAJOR_NR, "mcdx") != 0)
+ xwarn("cleanup() unregister_blkdev() failed\n");
+ return -EIO;
+ }
+ printk(msg);
}
-
return 0;
}
@@ -1539,7 +1408,7 @@ static unsigned int uint2bcd(unsigned int ival)
static void log2msf(unsigned int l, struct cdrom_msf0* pmsf)
{
- l += CD_BLOCK_OFFSET;
+ l += CD_MSF_OFFSET;
pmsf->minute = uint2bcd(l / 4500), l %= 4500;
pmsf->second = uint2bcd(l / 75);
pmsf->frame = uint2bcd(l % 75);
@@ -1550,7 +1419,7 @@ static unsigned int msf2log(const struct cdrom_msf0* pmsf)
return bcd2uint(pmsf->frame)
+ bcd2uint(pmsf->second) * 75
+ bcd2uint(pmsf->minute) * 4500
- - CD_BLOCK_OFFSET;
+ - CD_MSF_OFFSET;
}
int mcdx_readtoc(struct s_drive_stuff* stuffp)
@@ -1712,12 +1581,20 @@ mcdx_playtrk(struct s_drive_stuff* stuffp, const struct cdrom_ti* ti)
/* Drive functions ************************************************/
static int
-mcdx_closedoor(struct s_drive_stuff *stuffp, int tries)
+mcdx_tray_move(struct cdrom_device_info * cdi, int position)
{
- if (stuffp->present & DOOR)
- return mcdx_talk(stuffp, "\xf8", 1, NULL, 1, 5 * HZ, tries);
- else
- return 0;
+ struct s_drive_stuff *stuffp = mcdx_stuffp[MINOR(cdi->dev)];
+
+ if (!stuffp->present)
+ return -ENXIO;
+ if (!(stuffp->present & DOOR))
+ return -ENOSYS;
+
+ if (position) /* 1: eject */
+ return mcdx_talk(stuffp, "\xf6", 1, NULL, 1, 5 * HZ, 3);
+ else /* 0: close */
+ return mcdx_talk(stuffp, "\xf8", 1, NULL, 1, 5 * HZ, 3);
+ return 1;
}
static int
@@ -1729,15 +1606,6 @@ mcdx_hold(struct s_drive_stuff *stuffp, int tries)
{ return mcdx_talk(stuffp, "\x70", 1, NULL, 1, 2 * HZ, tries); }
static int
-mcdx_eject(struct s_drive_stuff *stuffp, int tries)
-{
- if (stuffp->present & DOOR) {
- stuffp->ejected = jiffies;
- return mcdx_talk(stuffp, "\xf6", 1, NULL, 1, 5 * HZ, tries);
- } else return 0;
-}
-
-static int
mcdx_requestsubqcode(struct s_drive_stuff *stuffp,
struct s_subqcode *sub,
int tries)
@@ -1886,13 +1754,16 @@ mcdx_reset(struct s_drive_stuff *stuffp, enum resetmodes mode, int tries)
} else return mcdx_talk(stuffp, "\x60", 1, NULL, 1, 5 * HZ, tries);
}
-static int
-mcdx_lockdoor(struct s_drive_stuff *stuffp, int lock, int tries)
+static int mcdx_lockdoor(struct cdrom_device_info * cdi, int lock)
{
+ struct s_drive_stuff *stuffp = mcdx_stuffp[MINOR(cdi->dev)];
char cmd[2] = { 0xfe };
+
+ if (!(stuffp->present & DOOR))
+ return -ENOSYS;
if (stuffp->present & DOOR) {
cmd[1] = lock ? 0x01 : 0x00;
- return mcdx_talk(stuffp, cmd, sizeof(cmd), NULL, 1, 5 * HZ, tries);
+ return mcdx_talk(stuffp, cmd, sizeof(cmd), NULL, 1, 5 * HZ, 3);
} else return 0;
}
diff --git a/drivers/cdrom/optcd.c b/drivers/cdrom/optcd.c
index 417769111..eae60ad3c 100644
--- a/drivers/cdrom/optcd.c
+++ b/drivers/cdrom/optcd.c
@@ -72,7 +72,7 @@
#include <linux/blk.h>
#include <linux/cdrom.h>
-#include <linux/optcd.h>
+#include "optcd.h"
#include <asm/uaccess.h>
@@ -1838,7 +1838,7 @@ static int opt_ioctl(struct inode *ip, struct file *fp,
case CDROMMULTISESSION: retval = cdrommultisession(arg); break;
#endif
- case CDROM_GET_UPC: retval = -EINVAL; break; /* not implemented */
+ case CDROM_GET_MCN: retval = -EINVAL; break; /* not implemented */
case CDROMVOLREAD: retval = -EINVAL; break; /* not implemented */
case CDROMREADRAW:
diff --git a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c
index 401dbc657..08de5a794 100644
--- a/drivers/cdrom/sbpcd.c
+++ b/drivers/cdrom/sbpcd.c
@@ -13,7 +13,7 @@
* labelled E2550UA or MK4015 or 2800F).
*/
-#define VERSION "v4.6 Eberhard Moenkeberg <emoenke@gwdg.de>"
+#define VERSION "v4.61 Eberhard Moenkeberg <emoenke@gwdg.de>"
/* Copyright (C) 1993, 1994, 1995 Eberhard Moenkeberg <emoenke@gwdg.de>
*
@@ -300,6 +300,10 @@
* Experiments to speed up the CD-55A; again with help of Rob Riggs
* (to be true, he gave both, idea & code. ;-)
*
+ * 4.61 Ported to Uniform CD-ROM driver by
+ * Heiko Eissfeldt <heiko@colossus.escape.de> with additional
+ * changes by Erik Andersen <andersee@debian.org>
+ *
*
* TODO
* implement "read all subchannel data" (96 bytes per frame)
@@ -334,8 +338,8 @@
#include <asm/io.h>
#include <asm/uaccess.h>
#include <stdarg.h>
-#include <linux/sbpcd.h>
#include <linux/config.h>
+#include "sbpcd.h"
#if !(SBPCD_ISSUE-1)
#define MAJOR_NR MATSUSHITA_CDROM_MAJOR
@@ -404,6 +408,7 @@ static int sbpcd[] =
CDROM_PORT, SBPRO, /* probe with user's setup first */
#if DISTRIBUTION
0x230, 1, /* Soundblaster Pro and 16 (default) */
+#if 0
0x300, 0, /* CI-101P (default), WDH-7001C (default),
Galaxy (default), Reveal (one default) */
0x250, 1, /* OmniCD default, Soundblaster Pro and 16 */
@@ -438,6 +443,7 @@ static int sbpcd[] =
0x290, 1, /* Soundblaster 16 */
0x310, 0, /* Lasermate, CI-101P, WDH-7001C */
#endif MODULE
+#endif
#endif DISTRIBUTION
};
#else
@@ -523,7 +529,7 @@ static int sbpcd_chk_disk_change(kdev_t);
#if DISTRIBUTION
static int sbpcd_debug = (1<<DBG_INF);
#else
-static int sbpcd_debug = ((1<<DBG_INF) |
+static int sbpcd_debug = 0 & ((1<<DBG_INF) |
(1<<DBG_TOC) |
(1<<DBG_MUL) |
(1<<DBG_UPC));
@@ -558,7 +564,7 @@ static const char *str_ss = "SoundScape";
static const char *str_ss_l = "soundscape";
static const char *str_t16 = "Teac16bit";
static const char *str_t16_l = "teac16bit";
-const char *type;
+static const char *type;
#if !(SBPCD_ISSUE-1)
static const char *major_name="sbpcd";
@@ -736,7 +742,8 @@ static struct {
u_char mode_yb_7;
u_char mode_xb_8;
u_char delay;
-
+ struct cdrom_device_info *sbpcd_infop;
+
} D_S[NR_SBPCD];
/*
@@ -1990,6 +1997,7 @@ static int cc_DriveReset(void)
if (D_S[d].error_byte!=aud_12) return -501;
return (0);
}
+
/*==========================================================================*/
static int SetSpeed(void)
{
@@ -2005,6 +2013,19 @@ static int SetSpeed(void)
i=cc_SetSpeed(speed,0,0);
return (i);
}
+
+static void switch_drive(int i);
+
+static int sbpcd_select_speed(struct cdrom_device_info *cdi, int speed)
+{
+ int i = MINOR(cdi->dev);
+
+ if (i != d)
+ switch_drive(i);
+
+ return cc_SetSpeed(speed == 2 ? speed_300 : speed_150, 0, 0);
+}
+
/*==========================================================================*/
static int DriveReset(void)
{
@@ -2030,6 +2051,17 @@ static int DriveReset(void)
}
return (0);
}
+
+static int sbpcd_reset(struct cdrom_device_info *cdi)
+{
+ int i = MINOR(cdi->dev);
+
+ if (i != d)
+ switch_drive(i);
+
+ return DriveReset();
+}
+
/*==========================================================================*/
static int cc_PlayAudio(int pos_audio_start,int pos_audio_end)
{
@@ -2220,6 +2252,12 @@ static int LockDoor(void)
}
return (i);
}
+
+static int sbpcd_lock_door(struct cdrom_device_info *cdi, int lock)
+{
+ return lock ? LockDoor() : UnLockDoor();
+}
+
/*==========================================================================*/
static int cc_CloseTray(void)
{
@@ -2261,6 +2299,12 @@ static int cc_CloseTray(void)
msg(DBG_LCS,"p_door_closed bit %d after\n", st_door_closed);
return (i);
}
+
+static int sbpcd_tray_move(struct cdrom_device_info *cdi, int position)
+{
+ return position ? cc_CloseTray() : 0;
+}
+
/*==========================================================================*/
static int cc_ReadSubQ(void)
{
@@ -2956,6 +3000,79 @@ static int cc_ReadUPC(void)
D_S[d].diskstate_flags |= upc_bit;
return (0);
}
+
+static int sbpcd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
+{
+ int i;
+ unsigned char *mcnp = mcn->medium_catalog_number;
+ unsigned char *resp;
+
+ D_S[d].diskstate_flags &= ~upc_bit;
+ clr_cmdbuf();
+ if (fam1_drive)
+ {
+ drvcmd[0]=CMD1_READ_UPC;
+ response_count=8;
+ flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
+ }
+ else if (fam0L_drive)
+ {
+ drvcmd[0]=CMD0_READ_UPC;
+ response_count=0;
+ flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
+ }
+ else if (fam2_drive)
+ {
+ return (-1);
+ }
+ else if (famT_drive)
+ {
+ return (-1);
+ }
+ i=cmd_out();
+ if (i<0)
+ {
+ msg(DBG_000,"cc_ReadUPC cmd_out: err %d\n", i);
+ return (i);
+ }
+ if (fam0L_drive)
+ {
+ response_count=16;
+ if (famL_drive) flags_cmd_out=f_putcmd;
+ i=cc_ReadPacket();
+ if (i<0)
+ {
+ msg(DBG_000,"cc_ReadUPC ReadPacket: err %d\n", i);
+ return (i);
+ }
+ }
+ D_S[d].UPC_ctl_adr=0;
+ if (fam1_drive) i=0;
+ else i=2;
+
+ resp = infobuf + i;
+ if (*resp++ == 0x80) {
+ /* packed bcd to single ASCII digits */
+ *mcnp++ = (*resp >> 4) + '0';
+ *mcnp++ = (*resp++ & 0x0f) + '0';
+ *mcnp++ = (*resp >> 4) + '0';
+ *mcnp++ = (*resp++ & 0x0f) + '0';
+ *mcnp++ = (*resp >> 4) + '0';
+ *mcnp++ = (*resp++ & 0x0f) + '0';
+ *mcnp++ = (*resp >> 4) + '0';
+ *mcnp++ = (*resp++ & 0x0f) + '0';
+ *mcnp++ = (*resp >> 4) + '0';
+ *mcnp++ = (*resp++ & 0x0f) + '0';
+ *mcnp++ = (*resp >> 4) + '0';
+ *mcnp++ = (*resp++ & 0x0f) + '0';
+ *mcnp++ = (*resp >> 4) + '0';
+ }
+ *mcnp = '\0';
+
+ D_S[d].diskstate_flags |= upc_bit;
+ return (0);
+}
+
/*==========================================================================*/
static int cc_CheckMultiSession(void)
{
@@ -3716,6 +3833,21 @@ static int ReadToC(void)
int i, j;
D_S[d].diskstate_flags &= ~toc_bit;
D_S[d].ored_ctl_adr=0;
+ /* special handling of CD-I HE */
+ if ((D_S[d].n_first_track == 2 && D_S[d].n_last_track == 2) ||
+ D_S[d].xa_byte == 0x10)
+ {
+ D_S[d].TocBuffer[1].nixbyte=0;
+ D_S[d].TocBuffer[1].ctl_adr=0x40;
+ D_S[d].TocBuffer[1].number=1;
+ D_S[d].TocBuffer[1].format=0;
+ D_S[d].TocBuffer[1].address=blk2msf(0);
+ D_S[d].ored_ctl_adr |= 0x40;
+ D_S[d].n_first_track = 1;
+ D_S[d].n_last_track = 1;
+ D_S[d].xa_byte = 0x10;
+ j = 2;
+ } else
for (j=D_S[d].n_first_track;j<=D_S[d].n_last_track;j++)
{
i=cc_ReadTocEntry(j);
@@ -3801,7 +3933,7 @@ static int DiskInfo(void)
}
i=cc_ReadUPC();
if (i<0) msg(DBG_INF,"DiskInfo: cc_ReadUPC returns %d\n", i);
- if ((fam0L_drive) && (D_S[d].xa_byte==0x20))
+ if ((fam0L_drive) && (D_S[d].xa_byte==0x20 || D_S[d].xa_byte == 0x10))
{
/* XA disk with old drive */
cc_ModeSelect(CD_FRAMESIZE_RAW1);
@@ -3811,6 +3943,18 @@ static int DiskInfo(void)
msg(DBG_000,"DiskInfo done.\n");
return (0);
}
+
+static int sbpcd_drive_status(struct cdrom_device_info *cdi, int slot_nr)
+{
+ if (CDSL_CURRENT != slot_nr) {
+ /* we have no changer support */
+ return -EINVAL;
+ }
+
+ return D_S[d].status_bits & p1_disk_ok ? CDS_DISC_OK : CDS_DRIVE_NOT_READY;
+}
+
+
/*==========================================================================*/
#if FUTURE
/*
@@ -3934,40 +4078,40 @@ static int sbp_status(void)
return (1);
}
/*==========================================================================*/
+
+static int sbpcd_get_last_session(struct cdrom_device_info *cdi, struct cdrom_multisession *ms_infp)
+{
+ ms_infp->addr_format = CDROM_LBA;
+ ms_infp->addr.lba = D_S[d].lba_multi;
+ if (D_S[d].f_multisession)
+ ms_infp->xa_flag=1; /* valid redirection address */
+ else
+ ms_infp->xa_flag=0; /* invalid redirection address */
+
+ return 1;
+}
/*==========================================================================*/
/*==========================================================================*/
/*
* ioctl support
*/
-static int sbpcd_ioctl(struct inode *inode, struct file *file, u_int cmd,
- u_long arg)
+static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd,
+ u_long arg)
{
- int i, st;
+ int i;
msg(DBG_IO2,"ioctl(%d, 0x%08lX, 0x%08lX)\n",
- MINOR(inode->i_rdev), cmd, arg);
- if (!inode) return (-EINVAL);
- i=MINOR(inode->i_rdev);
+ MINOR(cdi->dev), cmd, arg);
+ i=MINOR(cdi->dev);
if ((i<0) || (i>=NR_SBPCD) || (D_S[i].drv_id==-1))
{
- msg(DBG_INF, "ioctl: bad device: %04X\n", inode->i_rdev);
+ msg(DBG_INF, "ioctl: bad device: %04X\n", cdi->dev);
return (-ENXIO); /* no such drive */
}
down(&ioctl_read_sem);
if (d!=i) switch_drive(i);
-#if 0
- st=GetStatus();
- if (st<0) RETURN_UP(-EIO);
-
- if (!toc_valid)
- {
- i=DiskInfo();
- if (i<0) RETURN_UP(-EIO); /* error reading TOC */
- }
-#endif
-
msg(DBG_IO2,"ioctl: device %d, request %04X\n",i,cmd);
switch (cmd) /* Sun-compatible */
{
@@ -3975,271 +4119,12 @@ static int sbpcd_ioctl(struct inode *inode, struct file *file, u_int cmd,
if (!suser()) RETURN_UP(-EPERM);
i=sbpcd_dbg_ioctl(arg,1);
RETURN_UP(i);
-
- case CDROMPAUSE: /* Pause the drive */
- msg(DBG_IOC,"ioctl: CDROMPAUSE entered.\n");
- /* pause the drive unit when it is currently in PLAY mode, */
- /* or reset the starting and ending locations when in PAUSED mode. */
- /* If applicable, at the next stopping point it reaches */
- /* the drive will discontinue playing. */
- switch (D_S[d].audio_state)
- {
- case audio_playing:
- if (famL_drive) i=cc_ReadSubQ();
- else i=cc_Pause_Resume(1);
- if (i<0) RETURN_UP(-EIO);
- if (famL_drive) i=cc_Pause_Resume(1);
- else i=cc_ReadSubQ();
- if (i<0) RETURN_UP(-EIO);
- D_S[d].pos_audio_start=D_S[d].SubQ_run_tot;
- D_S[d].audio_state=audio_pausing;
- RETURN_UP(0);
- case audio_pausing:
- i=cc_Seek(D_S[d].pos_audio_start,1);
- if (i<0) RETURN_UP(-EIO);
- RETURN_UP(0);
- default:
- RETURN_UP(-EINVAL);
- }
-
- case CDROMRESUME: /* resume paused audio play */
- msg(DBG_IOC,"ioctl: CDROMRESUME entered.\n");
- /* resume playing audio tracks when a previous PLAY AUDIO call has */
- /* been paused with a PAUSE command. */
- /* It will resume playing from the location saved in SubQ_run_tot. */
- if (D_S[d].audio_state!=audio_pausing) return -EINVAL;
- if (famL_drive)
- i=cc_PlayAudio(D_S[d].pos_audio_start,
- D_S[d].pos_audio_end);
- else i=cc_Pause_Resume(3);
- if (i<0) RETURN_UP(-EIO);
- D_S[d].audio_state=audio_playing;
- RETURN_UP(0);
-
- case CDROMPLAYMSF:
- msg(DBG_IOC,"ioctl: CDROMPLAYMSF entered.\n");
-#if SAFE_MIXED
- if (D_S[d].has_data>1) RETURN_UP(-EBUSY);
-#endif SAFE_MIXED
- if (D_S[d].audio_state==audio_playing)
- {
- i=cc_Pause_Resume(1);
- if (i<0) RETURN_UP(-EIO);
- i=cc_ReadSubQ();
- if (i<0) RETURN_UP(-EIO);
- D_S[d].pos_audio_start=D_S[d].SubQ_run_tot;
- i=cc_Seek(D_S[d].pos_audio_start,1);
- }
- st=verify_area(VERIFY_READ, (void *) arg, sizeof(struct cdrom_msf));
- if (st) RETURN_UP(st);
- copy_from_user(&msf, (void *) arg, sizeof(struct cdrom_msf));
- /* values come as msf-bin */
- D_S[d].pos_audio_start = (msf.cdmsf_min0<<16) |
- (msf.cdmsf_sec0<<8) |
- msf.cdmsf_frame0;
- D_S[d].pos_audio_end = (msf.cdmsf_min1<<16) |
- (msf.cdmsf_sec1<<8) |
- msf.cdmsf_frame1;
- msg(DBG_IOX,"ioctl: CDROMPLAYMSF %08X %08X\n",
- D_S[d].pos_audio_start,D_S[d].pos_audio_end);
- i=cc_PlayAudio(D_S[d].pos_audio_start,D_S[d].pos_audio_end);
- if (i<0)
- {
- msg(DBG_INF,"ioctl: cc_PlayAudio returns %d\n",i);
- DriveReset();
- D_S[d].audio_state=0;
- RETURN_UP(-EIO);
- }
- D_S[d].audio_state=audio_playing;
- RETURN_UP(0);
-
- case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */
- msg(DBG_IOC,"ioctl: CDROMPLAYTRKIND entered.\n");
-#if SAFE_MIXED
- if (D_S[d].has_data>1) RETURN_UP(-EBUSY);
-#endif SAFE_MIXED
- if (D_S[d].audio_state==audio_playing)
- {
- msg(DBG_IOX,"CDROMPLAYTRKIND: already audio_playing.\n");
-#if 1
- RETURN_UP(0); /* just let us play on */
-#else
- RETURN_UP(-EINVAL); /* play on, but say "error" */
-#endif
- }
- st=verify_area(VERIFY_READ,(void *) arg,sizeof(struct cdrom_ti));
- if (st<0)
- {
- msg(DBG_IOX,"CDROMPLAYTRKIND: verify_area error.\n");
- RETURN_UP(st);
- }
- copy_from_user(&ti,(void *) arg,sizeof(struct cdrom_ti));
- msg(DBG_IOX,"ioctl: trk0: %d, ind0: %d, trk1:%d, ind1:%d\n",
- ti.cdti_trk0,ti.cdti_ind0,ti.cdti_trk1,ti.cdti_ind1);
- if (ti.cdti_trk0<D_S[d].n_first_track) RETURN_UP(-EINVAL);
- if (ti.cdti_trk0>D_S[d].n_last_track) RETURN_UP(-EINVAL);
- if (ti.cdti_trk1<ti.cdti_trk0) ti.cdti_trk1=ti.cdti_trk0;
- if (ti.cdti_trk1>D_S[d].n_last_track) ti.cdti_trk1=D_S[d].n_last_track;
- D_S[d].pos_audio_start=D_S[d].TocBuffer[ti.cdti_trk0].address;
- D_S[d].pos_audio_end=D_S[d].TocBuffer[ti.cdti_trk1+1].address;
- i=cc_PlayAudio(D_S[d].pos_audio_start,D_S[d].pos_audio_end);
- if (i<0)
- {
- msg(DBG_INF,"ioctl: cc_PlayAudio returns %d\n",i);
- DriveReset();
- D_S[d].audio_state=0;
- RETURN_UP(-EIO);
- }
- D_S[d].audio_state=audio_playing;
- RETURN_UP(0);
-
- case CDROMREADTOCHDR: /* Read the table of contents header */
- msg(DBG_IOC,"ioctl: CDROMREADTOCHDR entered.\n");
- tochdr.cdth_trk0=D_S[d].n_first_track;
- tochdr.cdth_trk1=D_S[d].n_last_track;
- st=verify_area(VERIFY_WRITE, (void *) arg, sizeof(struct cdrom_tochdr));
- if (st) RETURN_UP(st);
- copy_to_user((void *) arg, &tochdr, sizeof(struct cdrom_tochdr));
- RETURN_UP(0);
-
- case CDROMREADTOCENTRY: /* Read an entry in the table of contents */
- msg(DBG_IOC,"ioctl: CDROMREADTOCENTRY entered.\n");
- st=verify_area(VERIFY_WRITE,(void *) arg, sizeof(struct cdrom_tocentry));
- if (st) RETURN_UP(st);
- copy_from_user(&tocentry, (void *) arg, sizeof(struct cdrom_tocentry));
- i=tocentry.cdte_track;
- if (i==CDROM_LEADOUT) i=D_S[d].n_last_track+1;
- else if (i<D_S[d].n_first_track||i>D_S[d].n_last_track)
- RETURN_UP(-EINVAL);
- tocentry.cdte_adr=D_S[d].TocBuffer[i].ctl_adr&0x0F;
- tocentry.cdte_ctrl=(D_S[d].TocBuffer[i].ctl_adr>>4)&0x0F;
- tocentry.cdte_datamode=D_S[d].TocBuffer[i].format;
- if (tocentry.cdte_format==CDROM_MSF) /* MSF-bin required */
- {
- tocentry.cdte_addr.msf.minute=(D_S[d].TocBuffer[i].address>>16)&0x00FF;
- tocentry.cdte_addr.msf.second=(D_S[d].TocBuffer[i].address>>8)&0x00FF;
- tocentry.cdte_addr.msf.frame=D_S[d].TocBuffer[i].address&0x00FF;
- }
- else if (tocentry.cdte_format==CDROM_LBA) /* blk required */
- tocentry.cdte_addr.lba=msf2blk(D_S[d].TocBuffer[i].address);
- else RETURN_UP(-EINVAL);
- copy_to_user((void *) arg, &tocentry, sizeof(struct cdrom_tocentry));
- RETURN_UP(0);
-
case CDROMRESET: /* hard reset the drive */
msg(DBG_IOC,"ioctl: CDROMRESET entered.\n");
i=DriveReset();
D_S[d].audio_state=0;
RETURN_UP(i);
- case CDROMSTOP: /* Spin down the drive */
- msg(DBG_IOC,"ioctl: CDROMSTOP entered.\n");
-#if SAFE_MIXED
- if (D_S[d].has_data>1) RETURN_UP(-EBUSY);
-#endif SAFE_MIXED
- i=cc_Pause_Resume(1);
- D_S[d].audio_state=0;
- RETURN_UP(i);
-
- case CDROMSTART: /* Spin up the drive */
- msg(DBG_IOC,"ioctl: CDROMSTART entered.\n");
- cc_SpinUp();
- D_S[d].audio_state=0;
- RETURN_UP(0);
-
- case CDROMEJECT:
- msg(DBG_IOC,"ioctl: CDROMEJECT entered.\n");
- if (fam0_drive) return (0);
- if (D_S[d].open_count>1) RETURN_UP(-EBUSY);
- i=UnLockDoor();
- D_S[d].open_count=-9; /* to get it locked next time again */
- i=cc_SpinDown();
- msg(DBG_IOX,"ioctl: cc_SpinDown returned %d.\n", i);
- msg(DBG_TEA,"ioctl: cc_SpinDown returned %d.\n", i);
- if (i<0) RETURN_UP(-EIO);
- D_S[d].CD_changed=0xFF;
- D_S[d].diskstate_flags=0;
- D_S[d].audio_state=0;
- RETURN_UP(0);
-
- case CDROMEJECT_SW:
- msg(DBG_IOC,"ioctl: CDROMEJECT_SW entered.\n");
- if (fam0_drive) RETURN_UP(0);
- D_S[d].f_eject=arg;
- RETURN_UP(0);
-
- case CDROMVOLCTRL: /* Volume control */
- msg(DBG_IOC,"ioctl: CDROMVOLCTRL entered.\n");
- st=verify_area(VERIFY_READ,(void *) arg,sizeof(volctrl));
- if (st) RETURN_UP(st);
- copy_from_user(&volctrl,(char *) arg,sizeof(volctrl));
- D_S[d].vol_chan0=0;
- D_S[d].vol_ctrl0=volctrl.channel0;
- D_S[d].vol_chan1=1;
- D_S[d].vol_ctrl1=volctrl.channel1;
- i=cc_SetVolume();
- RETURN_UP(0);
-
- case CDROMVOLREAD: /* read Volume settings from drive */
- msg(DBG_IOC,"ioctl: CDROMVOLREAD entered.\n");
- st=verify_area(VERIFY_WRITE,(void *)arg,sizeof(volctrl));
- if (st) RETURN_UP(st);
- st=cc_GetVolume();
- if (st<0) return (st);
- volctrl.channel0=D_S[d].vol_ctrl0;
- volctrl.channel1=D_S[d].vol_ctrl1;
- volctrl.channel2=0;
- volctrl.channel2=0;
- copy_to_user((void *)arg,&volctrl,sizeof(volctrl));
- RETURN_UP(0);
-
- case CDROMSUBCHNL: /* Get subchannel info */
- msg(DBG_IOS,"ioctl: CDROMSUBCHNL entered.\n");
- if ((st_spinning)||(!subq_valid)) {
- i=cc_ReadSubQ();
- if (i<0) RETURN_UP(-EIO);
- }
- st=verify_area(VERIFY_WRITE, (void *) arg, sizeof(struct cdrom_subchnl));
- if (st) RETURN_UP(st);
- copy_from_user(&SC, (void *) arg, sizeof(struct cdrom_subchnl));
- switch (D_S[d].audio_state)
- {
- case audio_playing:
- SC.cdsc_audiostatus=CDROM_AUDIO_PLAY;
- break;
- case audio_pausing:
- SC.cdsc_audiostatus=CDROM_AUDIO_PAUSED;
- break;
- default:
- SC.cdsc_audiostatus=CDROM_AUDIO_NO_STATUS;
- break;
- }
- SC.cdsc_adr=D_S[d].SubQ_ctl_adr;
- SC.cdsc_ctrl=D_S[d].SubQ_ctl_adr>>4;
- SC.cdsc_trk=bcd2bin(D_S[d].SubQ_trk);
- SC.cdsc_ind=bcd2bin(D_S[d].SubQ_pnt_idx);
- if (SC.cdsc_format==CDROM_LBA)
- {
- SC.cdsc_absaddr.lba=msf2blk(D_S[d].SubQ_run_tot);
- SC.cdsc_reladdr.lba=msf2blk(D_S[d].SubQ_run_trk);
- }
- else /* not only if (SC.cdsc_format==CDROM_MSF) */
- {
- SC.cdsc_absaddr.msf.minute=(D_S[d].SubQ_run_tot>>16)&0x00FF;
- SC.cdsc_absaddr.msf.second=(D_S[d].SubQ_run_tot>>8)&0x00FF;
- SC.cdsc_absaddr.msf.frame=D_S[d].SubQ_run_tot&0x00FF;
- SC.cdsc_reladdr.msf.minute=(D_S[d].SubQ_run_trk>>16)&0x00FF;
- SC.cdsc_reladdr.msf.second=(D_S[d].SubQ_run_trk>>8)&0x00FF;
- SC.cdsc_reladdr.msf.frame=D_S[d].SubQ_run_trk&0x00FF;
- }
- copy_to_user((void *) arg, &SC, sizeof(struct cdrom_subchnl));
- msg(DBG_IOS,"CDROMSUBCHNL: %1X %02X %08X %08X %02X %02X %06X %06X\n",
- SC.cdsc_format,SC.cdsc_audiostatus,
- SC.cdsc_adr,SC.cdsc_ctrl,
- SC.cdsc_trk,SC.cdsc_ind,
- SC.cdsc_absaddr,SC.cdsc_reladdr);
- RETURN_UP(0);
-
case CDROMREADMODE1:
msg(DBG_IOC,"ioctl: CDROMREADMODE1 requested.\n");
#if SAFE_MIXED
@@ -4265,6 +4150,7 @@ static int sbpcd_ioctl(struct inode *inode, struct file *file, u_int cmd,
if (D_S[d].sbp_audsiz>0) vfree(D_S[d].aud_buf);
D_S[d].aud_buf=NULL;
D_S[d].sbp_audsiz=arg;
+
if (D_S[d].sbp_audsiz>0)
{
D_S[d].aud_buf=(u_char *) vmalloc(D_S[d].sbp_audsiz*CD_FRAMESIZE_RAW);
@@ -4496,28 +4382,277 @@ static int sbpcd_ioctl(struct inode *inode, struct file *file, u_int cmd,
RETURN_UP(0);
} /* end of CDROMREADAUDIO */
- case CDROMMULTISESSION: /* tell start-of-last-session */
- msg(DBG_IOC,"ioctl: CDROMMULTISESSION entered.\n");
- st=verify_area(VERIFY_WRITE,(void *) arg, sizeof(struct cdrom_multisession));
- if (st) RETURN_UP(st);
- copy_from_user(&ms_info, (void *) arg, sizeof(struct cdrom_multisession));
- if (ms_info.addr_format==CDROM_MSF) /* MSF-bin requested */
- lba2msf(D_S[d].lba_multi,&ms_info.addr.msf.minute);
- else if (ms_info.addr_format==CDROM_LBA) /* lba requested */
- ms_info.addr.lba=D_S[d].lba_multi;
- else RETURN_UP(-EINVAL);
- if (D_S[d].f_multisession) ms_info.xa_flag=1; /* valid redirection address */
- else ms_info.xa_flag=0; /* invalid redirection address */
- copy_to_user((void *) arg, &ms_info, sizeof(struct cdrom_multisession));
- msg(DBG_MUL,"ioctl: CDROMMULTISESSION done (%d, %08X).\n",
- ms_info.xa_flag, ms_info.addr.lba);
- RETURN_UP(0);
-
case BLKRASET:
if(!suser()) RETURN_UP(-EACCES);
- if(!(inode->i_rdev)) RETURN_UP(-EINVAL);
+ if(!(cdi->dev)) RETURN_UP(-EINVAL);
if(arg > 0xff) RETURN_UP(-EINVAL);
- read_ahead[MAJOR(inode->i_rdev)] = arg;
+ read_ahead[MAJOR(cdi->dev)] = arg;
+ RETURN_UP(0);
+#if 0
+ case CDROMEJECT:
+ msg(DBG_IOC,"ioctl: CDROMEJECT entered.\n");
+ if (fam0_drive) return (0);
+ if (D_S[d].open_count>1) RETURN_UP(-EBUSY);
+ i=UnLockDoor();
+ D_S[d].open_count=-9; /* to get it locked next time again */
+ i=cc_SpinDown();
+ msg(DBG_IOX,"ioctl: cc_SpinDown returned %d.\n", i);
+ msg(DBG_TEA,"ioctl: cc_SpinDown returned %d.\n", i);
+ if (i<0) RETURN_UP(-EIO);
+ D_S[d].CD_changed=0xFF;
+ D_S[d].diskstate_flags=0;
+ D_S[d].audio_state=0;
+ RETURN_UP(0);
+
+ case CDROMEJECT_SW:
+ msg(DBG_IOC,"ioctl: CDROMEJECT_SW entered.\n");
+ if (fam0_drive) RETURN_UP(0);
+ D_S[d].f_eject=arg;
+ RETURN_UP(0);
+#endif
+ default:
+ msg(DBG_IOC,"ioctl: unknown function request %04X\n", cmd);
+ RETURN_UP(-EINVAL);
+ } /* end switch(cmd) */
+}
+
+static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd,
+ void * arg)
+{
+ int i, st;
+
+ msg(DBG_IO2,"ioctl(%d, 0x%08lX, 0x%08p)\n",
+ MINOR(cdi->dev), cmd, arg);
+ i=MINOR(cdi->dev);
+ if ((i<0) || (i>=NR_SBPCD) || (D_S[i].drv_id==-1))
+ {
+ msg(DBG_INF, "ioctl: bad device: %04X\n", cdi->dev);
+ return (-ENXIO); /* no such drive */
+ }
+ down(&ioctl_read_sem);
+ if (d!=i) switch_drive(i);
+
+ msg(DBG_IO2,"ioctl: device %d, request %04X\n",i,cmd);
+ switch (cmd) /* Sun-compatible */
+ {
+
+ case CDROMPAUSE: /* Pause the drive */
+ msg(DBG_IOC,"ioctl: CDROMPAUSE entered.\n");
+ /* pause the drive unit when it is currently in PLAY mode, */
+ /* or reset the starting and ending locations when in PAUSED mode. */
+ /* If applicable, at the next stopping point it reaches */
+ /* the drive will discontinue playing. */
+ switch (D_S[d].audio_state)
+ {
+ case audio_playing:
+ if (famL_drive) i=cc_ReadSubQ();
+ else i=cc_Pause_Resume(1);
+ if (i<0) RETURN_UP(-EIO);
+ if (famL_drive) i=cc_Pause_Resume(1);
+ else i=cc_ReadSubQ();
+ if (i<0) RETURN_UP(-EIO);
+ D_S[d].pos_audio_start=D_S[d].SubQ_run_tot;
+ D_S[d].audio_state=audio_pausing;
+ RETURN_UP(0);
+ case audio_pausing:
+ i=cc_Seek(D_S[d].pos_audio_start,1);
+ if (i<0) RETURN_UP(-EIO);
+ RETURN_UP(0);
+ default:
+ RETURN_UP(-EINVAL);
+ }
+
+ case CDROMRESUME: /* resume paused audio play */
+ msg(DBG_IOC,"ioctl: CDROMRESUME entered.\n");
+ /* resume playing audio tracks when a previous PLAY AUDIO call has */
+ /* been paused with a PAUSE command. */
+ /* It will resume playing from the location saved in SubQ_run_tot. */
+ if (D_S[d].audio_state!=audio_pausing) return -EINVAL;
+ if (famL_drive)
+ i=cc_PlayAudio(D_S[d].pos_audio_start,
+ D_S[d].pos_audio_end);
+ else i=cc_Pause_Resume(3);
+ if (i<0) RETURN_UP(-EIO);
+ D_S[d].audio_state=audio_playing;
+ RETURN_UP(0);
+
+ case CDROMPLAYMSF:
+ msg(DBG_IOC,"ioctl: CDROMPLAYMSF entered.\n");
+#if SAFE_MIXED
+ if (D_S[d].has_data>1) RETURN_UP(-EBUSY);
+#endif SAFE_MIXED
+ if (D_S[d].audio_state==audio_playing)
+ {
+ i=cc_Pause_Resume(1);
+ if (i<0) RETURN_UP(-EIO);
+ i=cc_ReadSubQ();
+ if (i<0) RETURN_UP(-EIO);
+ D_S[d].pos_audio_start=D_S[d].SubQ_run_tot;
+ i=cc_Seek(D_S[d].pos_audio_start,1);
+ }
+ memcpy(&msf, (void *) arg, sizeof(struct cdrom_msf));
+ /* values come as msf-bin */
+ D_S[d].pos_audio_start = (msf.cdmsf_min0<<16) |
+ (msf.cdmsf_sec0<<8) |
+ msf.cdmsf_frame0;
+ D_S[d].pos_audio_end = (msf.cdmsf_min1<<16) |
+ (msf.cdmsf_sec1<<8) |
+ msf.cdmsf_frame1;
+ msg(DBG_IOX,"ioctl: CDROMPLAYMSF %08X %08X\n",
+ D_S[d].pos_audio_start,D_S[d].pos_audio_end);
+ i=cc_PlayAudio(D_S[d].pos_audio_start,D_S[d].pos_audio_end);
+ if (i<0)
+ {
+ msg(DBG_INF,"ioctl: cc_PlayAudio returns %d\n",i);
+ DriveReset();
+ D_S[d].audio_state=0;
+ RETURN_UP(-EIO);
+ }
+ D_S[d].audio_state=audio_playing;
+ RETURN_UP(0);
+
+ case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */
+ msg(DBG_IOC,"ioctl: CDROMPLAYTRKIND entered.\n");
+#if SAFE_MIXED
+ if (D_S[d].has_data>1) RETURN_UP(-EBUSY);
+#endif SAFE_MIXED
+ if (D_S[d].audio_state==audio_playing)
+ {
+ msg(DBG_IOX,"CDROMPLAYTRKIND: already audio_playing.\n");
+#if 1
+ RETURN_UP(0); /* just let us play on */
+#else
+ RETURN_UP(-EINVAL); /* play on, but say "error" */
+#endif
+ }
+ memcpy(&ti,(void *) arg,sizeof(struct cdrom_ti));
+ msg(DBG_IOX,"ioctl: trk0: %d, ind0: %d, trk1:%d, ind1:%d\n",
+ ti.cdti_trk0,ti.cdti_ind0,ti.cdti_trk1,ti.cdti_ind1);
+ if (ti.cdti_trk0<D_S[d].n_first_track) RETURN_UP(-EINVAL);
+ if (ti.cdti_trk0>D_S[d].n_last_track) RETURN_UP(-EINVAL);
+ if (ti.cdti_trk1<ti.cdti_trk0) ti.cdti_trk1=ti.cdti_trk0;
+ if (ti.cdti_trk1>D_S[d].n_last_track) ti.cdti_trk1=D_S[d].n_last_track;
+ D_S[d].pos_audio_start=D_S[d].TocBuffer[ti.cdti_trk0].address;
+ D_S[d].pos_audio_end=D_S[d].TocBuffer[ti.cdti_trk1+1].address;
+ i=cc_PlayAudio(D_S[d].pos_audio_start,D_S[d].pos_audio_end);
+ if (i<0)
+ {
+ msg(DBG_INF,"ioctl: cc_PlayAudio returns %d\n",i);
+ DriveReset();
+ D_S[d].audio_state=0;
+ RETURN_UP(-EIO);
+ }
+ D_S[d].audio_state=audio_playing;
+ RETURN_UP(0);
+
+ case CDROMREADTOCHDR: /* Read the table of contents header */
+ msg(DBG_IOC,"ioctl: CDROMREADTOCHDR entered.\n");
+ tochdr.cdth_trk0=D_S[d].n_first_track;
+ tochdr.cdth_trk1=D_S[d].n_last_track;
+ memcpy((void *) arg, &tochdr, sizeof(struct cdrom_tochdr));
+ RETURN_UP(0);
+
+ case CDROMREADTOCENTRY: /* Read an entry in the table of contents */
+ msg(DBG_IOC,"ioctl: CDROMREADTOCENTRY entered.\n");
+ memcpy(&tocentry, (void *) arg, sizeof(struct cdrom_tocentry));
+ i=tocentry.cdte_track;
+ if (i==CDROM_LEADOUT) i=D_S[d].n_last_track+1;
+ else if (i<D_S[d].n_first_track||i>D_S[d].n_last_track)
+ RETURN_UP(-EINVAL);
+ tocentry.cdte_adr=D_S[d].TocBuffer[i].ctl_adr&0x0F;
+ tocentry.cdte_ctrl=(D_S[d].TocBuffer[i].ctl_adr>>4)&0x0F;
+ tocentry.cdte_datamode=D_S[d].TocBuffer[i].format;
+ if (tocentry.cdte_format==CDROM_MSF) /* MSF-bin required */
+ {
+ tocentry.cdte_addr.msf.minute=(D_S[d].TocBuffer[i].address>>16)&0x00FF;
+ tocentry.cdte_addr.msf.second=(D_S[d].TocBuffer[i].address>>8)&0x00FF;
+ tocentry.cdte_addr.msf.frame=D_S[d].TocBuffer[i].address&0x00FF;
+ }
+ else if (tocentry.cdte_format==CDROM_LBA) /* blk required */
+ tocentry.cdte_addr.lba=msf2blk(D_S[d].TocBuffer[i].address);
+ else RETURN_UP(-EINVAL);
+ memcpy((void *) arg, &tocentry, sizeof(struct cdrom_tocentry));
+ RETURN_UP(0);
+
+ case CDROMSTOP: /* Spin down the drive */
+ msg(DBG_IOC,"ioctl: CDROMSTOP entered.\n");
+#if SAFE_MIXED
+ if (D_S[d].has_data>1) RETURN_UP(-EBUSY);
+#endif SAFE_MIXED
+ i=cc_Pause_Resume(1);
+ D_S[d].audio_state=0;
+ RETURN_UP(i);
+
+ case CDROMSTART: /* Spin up the drive */
+ msg(DBG_IOC,"ioctl: CDROMSTART entered.\n");
+ cc_SpinUp();
+ D_S[d].audio_state=0;
+ RETURN_UP(0);
+
+ case CDROMVOLCTRL: /* Volume control */
+ msg(DBG_IOC,"ioctl: CDROMVOLCTRL entered.\n");
+ memcpy(&volctrl,(char *) arg,sizeof(volctrl));
+ D_S[d].vol_chan0=0;
+ D_S[d].vol_ctrl0=volctrl.channel0;
+ D_S[d].vol_chan1=1;
+ D_S[d].vol_ctrl1=volctrl.channel1;
+ i=cc_SetVolume();
+ RETURN_UP(0);
+
+ case CDROMVOLREAD: /* read Volume settings from drive */
+ msg(DBG_IOC,"ioctl: CDROMVOLREAD entered.\n");
+ st=cc_GetVolume();
+ if (st<0) return (st);
+ volctrl.channel0=D_S[d].vol_ctrl0;
+ volctrl.channel1=D_S[d].vol_ctrl1;
+ volctrl.channel2=0;
+ volctrl.channel2=0;
+ memcpy((void *)arg,&volctrl,sizeof(volctrl));
+ RETURN_UP(0);
+
+ case CDROMSUBCHNL: /* Get subchannel info */
+ msg(DBG_IOS,"ioctl: CDROMSUBCHNL entered.\n");
+ if ((st_spinning)||(!subq_valid)) {
+ i=cc_ReadSubQ();
+ if (i<0) RETURN_UP(-EIO);
+ }
+ memcpy(&SC, (void *) arg, sizeof(struct cdrom_subchnl));
+ switch (D_S[d].audio_state)
+ {
+ case audio_playing:
+ SC.cdsc_audiostatus=CDROM_AUDIO_PLAY;
+ break;
+ case audio_pausing:
+ SC.cdsc_audiostatus=CDROM_AUDIO_PAUSED;
+ break;
+ default:
+ SC.cdsc_audiostatus=CDROM_AUDIO_NO_STATUS;
+ break;
+ }
+ SC.cdsc_adr=D_S[d].SubQ_ctl_adr;
+ SC.cdsc_ctrl=D_S[d].SubQ_ctl_adr>>4;
+ SC.cdsc_trk=bcd2bin(D_S[d].SubQ_trk);
+ SC.cdsc_ind=bcd2bin(D_S[d].SubQ_pnt_idx);
+ if (SC.cdsc_format==CDROM_LBA)
+ {
+ SC.cdsc_absaddr.lba=msf2blk(D_S[d].SubQ_run_tot);
+ SC.cdsc_reladdr.lba=msf2blk(D_S[d].SubQ_run_trk);
+ }
+ else /* not only if (SC.cdsc_format==CDROM_MSF) */
+ {
+ SC.cdsc_absaddr.msf.minute=(D_S[d].SubQ_run_tot>>16)&0x00FF;
+ SC.cdsc_absaddr.msf.second=(D_S[d].SubQ_run_tot>>8)&0x00FF;
+ SC.cdsc_absaddr.msf.frame=D_S[d].SubQ_run_tot&0x00FF;
+ SC.cdsc_reladdr.msf.minute=(D_S[d].SubQ_run_trk>>16)&0x00FF;
+ SC.cdsc_reladdr.msf.second=(D_S[d].SubQ_run_trk>>8)&0x00FF;
+ SC.cdsc_reladdr.msf.frame=D_S[d].SubQ_run_trk&0x00FF;
+ }
+ memcpy((void *) arg, &SC, sizeof(struct cdrom_subchnl));
+ msg(DBG_IOS,"CDROMSUBCHNL: %1X %02X %08X %08X %02X %02X %06X %06X\n",
+ SC.cdsc_format,SC.cdsc_audiostatus,
+ SC.cdsc_adr,SC.cdsc_ctrl,
+ SC.cdsc_trk,SC.cdsc_ind,
+ SC.cdsc_absaddr,SC.cdsc_reladdr);
RETURN_UP(0);
default:
@@ -5104,19 +5239,18 @@ static int sbp_data(struct request *req)
/*
* Open the device special file. Check that a disk is in. Read TOC.
*/
-static int sbpcd_open(struct inode *ip, struct file *fp)
+static int sbpcd_open(struct cdrom_device_info *cdi, int purpose)
{
int i;
- i = MINOR(ip->i_rdev);
+ i = MINOR(cdi->dev);
if ((i<0) || (i>=NR_SBPCD) || (D_S[i].drv_id==-1))
{
- msg(DBG_INF, "open: bad device: %04X\n", ip->i_rdev);
+ msg(DBG_INF, "open: bad device: %04X\n", cdi->dev);
return (-ENXIO); /* no such drive */
}
- if (fp->f_mode & 2)
- return -EROFS;
+ MOD_INC_USE_COUNT;
down(&ioctl_read_sem);
switch_drive(i);
@@ -5136,21 +5270,13 @@ static int sbpcd_open(struct inode *ip, struct file *fp)
if (i<0)
{
msg(DBG_INF,"sbpcd_open: ResponseStatus timed out (%d).\n",i);
+ MOD_DEC_USE_COUNT;
RETURN_UP(-EIO); /* drive doesn't respond */
}
if (famT_drive) msg(DBG_TEA,"sbpcd_open: ResponseStatus=%02X\n", i);
- if (!st_door_closed)
- {
- if (famT_drive) msg(DBG_TEA,"sbpcd_open: !st_door_closed.\n");
- cc_CloseTray();
- flags_cmd_out |= f_respo2;
- cc_ReadStatus();
- i=ResponseStatus();
- }
if (!(famT_drive))
if (!st_spinning)
{
- if (famT_drive) msg(DBG_TEA,"sbpcd_open: !st_spinning.\n");
cc_SpinUp();
flags_cmd_out |= f_respo2;
cc_ReadStatus();
@@ -5161,19 +5287,12 @@ static int sbpcd_open(struct inode *ip, struct file *fp)
{
msg(DBG_INF, "sbpcd_open: no disk in drive.\n");
D_S[d].open_count=0;
-#if JUKEBOX
- if (!fam0_drive)
- {
- i=UnLockDoor();
- cc_SpinDown(); /* eject tray */
- }
-#endif
+ MOD_DEC_USE_COUNT;
RETURN_UP(-ENXIO);
}
/*
* try to keep an "open" counter here and lock the door if 0->1.
*/
- MOD_INC_USE_COUNT;
msg(DBG_LCK,"open_count: %d -> %d\n",
D_S[d].open_count,D_S[d].open_count+1);
if (++D_S[d].open_count<=1)
@@ -5201,22 +5320,21 @@ static int sbpcd_open(struct inode *ip, struct file *fp)
/*
* On close, we flush all sbp blocks from the buffer cache.
*/
-static int sbpcd_release(struct inode * ip, struct file * file)
+static void sbpcd_release(struct cdrom_device_info * cdi)
{
int i;
- i = MINOR(ip->i_rdev);
+ i = MINOR(cdi->dev);
if ((i<0) || (i>=NR_SBPCD) || (D_S[i].drv_id==-1))
{
- msg(DBG_INF, "release: bad device: %04X\n", ip->i_rdev);
- return 0;
+ msg(DBG_INF, "release: bad device: %04X\n", cdi->dev);
+ return ;
}
down(&ioctl_read_sem);
switch_drive(i);
/*
* try to keep an "open" counter here and unlock the door if 1->0.
*/
- MOD_DEC_USE_COUNT;
msg(DBG_LCK,"open_count: %d -> %d\n",
D_S[d].open_count,D_S[d].open_count-1);
if (D_S[d].open_count>-2) /* CDROMEJECT may have been done */
@@ -5224,9 +5342,7 @@ static int sbpcd_release(struct inode * ip, struct file * file)
if (--D_S[d].open_count<=0)
{
D_S[d].sbp_first_frame=D_S[d].sbp_last_frame=-1;
- sync_dev(ip->i_rdev); /* nonsense if read only device? */
- invalidate_buffers(ip->i_rdev);
- i=UnLockDoor();
+ invalidate_buffers(cdi->dev);
if (D_S[d].audio_state!=audio_playing)
if (D_S[d].f_eject) cc_SpinDown();
D_S[d].diskstate_flags &= ~cd_size_bit;
@@ -5237,12 +5353,14 @@ static int sbpcd_release(struct inode * ip, struct file * file)
}
}
up(&ioctl_read_sem);
- return 0;
+ MOD_DEC_USE_COUNT;
+ return ;
}
/*==========================================================================*/
/*
*
*/
+#if 0
static struct file_operations sbpcd_fops =
{
NULL, /* lseek - default */
@@ -5259,6 +5377,39 @@ static struct file_operations sbpcd_fops =
sbpcd_chk_disk_change, /* media_change */
NULL /* revalidate */
};
+#endif
+static int sbpcd_media_changed( struct cdrom_device_info *cdi, int disc_nr);
+static struct cdrom_device_ops sbpcd_dops = {
+ sbpcd_open, /* open */
+ sbpcd_release, /* release */
+ sbpcd_drive_status, /* drive status */
+ sbpcd_media_changed, /* media changed */
+ sbpcd_tray_move, /* tray move */
+ sbpcd_lock_door, /* lock door */
+ sbpcd_select_speed, /* select speed */
+ NULL, /* select disc */
+ sbpcd_get_last_session, /* get last session */
+ sbpcd_get_mcn, /* get universal product code */
+ sbpcd_reset, /* hard reset */
+ sbpcd_audio_ioctl, /* audio ioctl */
+ sbpcd_dev_ioctl, /* device-specific ioctl */
+ CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_MULTI_SESSION |
+ CDC_MEDIA_CHANGED | CDC_MCN | CDC_PLAY_AUDIO, /* capability */
+ 1, /* number of minor devices */
+};
+
+static struct cdrom_device_info sbpcd_info = {
+ &sbpcd_dops, /* device operations */
+ NULL, /* link */
+ NULL, /* handle */
+ MKDEV(MAJOR_NR,0), /* dev */
+ 0, /* mask */
+ 2, /* maximum speed */
+ 1, /* number of discs */
+ 0, /* options, not owned */
+ 0, /* mc_flags, not owned */
+ 0 /* use count, not owned */
+};
/*==========================================================================*/
/*
* accept "kernel command line" parameters
@@ -5495,15 +5646,15 @@ __initfunc(int SBPCD_INIT(void))
if (!famL_drive) cc_DriveReset();
#endif 0
if (!st_spinning) cc_SpinUp();
- D_S[d].sbp_first_frame = -1; /* First frame in buffer */
- D_S[d].sbp_last_frame = -1; /* Last frame in buffer */
- D_S[d].sbp_read_frames = 0; /* Number of frames being read to buffer */
- D_S[d].sbp_current = 0; /* Frame being currently read */
- D_S[d].CD_changed=1;
- D_S[d].frame_size=CD_FRAMESIZE;
- D_S[d].f_eject=0;
+ D_S[j].sbp_first_frame = -1; /* First frame in buffer */
+ D_S[j].sbp_last_frame = -1; /* Last frame in buffer */
+ D_S[j].sbp_read_frames = 0; /* Number of frames being read to buffer */
+ D_S[j].sbp_current = 0; /* Frame being currently read */
+ D_S[j].CD_changed=1;
+ D_S[j].frame_size=CD_FRAMESIZE;
+ D_S[j].f_eject=0;
#if EJECT
- if (!fam0_drive) D_S[d].f_eject=1;
+ if (!fam0_drive) D_S[j].f_eject=1;
#endif EJECT
cc_ReadStatus();
i=ResponseStatus(); /* returns orig. status or p_busy_new */
@@ -5521,8 +5672,8 @@ __initfunc(int SBPCD_INIT(void))
}
msg(DBG_INI,"init: first GetStatus: %d\n",i);
msg(DBG_LCS,"init: first GetStatus: error_byte=%d\n",
- D_S[d].error_byte);
- if (D_S[d].error_byte==aud_12)
+ D_S[j].error_byte);
+ if (D_S[j].error_byte==aud_12)
{
timeout=jiffies+2*HZ;
do
@@ -5531,14 +5682,14 @@ __initfunc(int SBPCD_INIT(void))
msg(DBG_INI,"init: second GetStatus: %02X\n",i);
msg(DBG_LCS,
"init: second GetStatus: error_byte=%d\n",
- D_S[d].error_byte);
+ D_S[j].error_byte);
if (i<0) break;
if (!st_caddy_in) break;
}
while ((!st_diskok)||(timeout<jiffies));
}
i=SetSpeed();
- if (i>=0) D_S[d].CD_changed=1;
+ if (i>=0) D_S[j].CD_changed=1;
}
/*
@@ -5550,7 +5701,7 @@ __initfunc(int SBPCD_INIT(void))
OUT(MIXER_data,0xCC); /* one nibble per channel, max. value: 0xFF */
#endif SOUND_BASE
- if (register_blkdev(MAJOR_NR, major_name, &sbpcd_fops) != 0)
+ if (register_blkdev(MAJOR_NR, major_name, &cdrom_fops) != 0)
{
msg(DBG_INF, "Can't get MAJOR %d for Matsushita CDROM\n", MAJOR_NR);
#ifdef MODULE
@@ -5566,6 +5717,8 @@ __initfunc(int SBPCD_INIT(void))
for (j=0;j<NR_SBPCD;j++)
{
+ struct cdrom_device_info * sbpcd_infop;
+
if (D_S[j].drv_id==-1) continue;
switch_drive(j);
#if SAFE_MIXED
@@ -5583,6 +5736,11 @@ __initfunc(int SBPCD_INIT(void))
if (D_S[j].sbp_buf==NULL)
{
msg(DBG_INF,"data buffer (%d frames) not available.\n",D_S[j].sbp_bufsiz);
+ if ((unregister_blkdev(MAJOR_NR, major_name) == -EINVAL))
+ {
+ printk("Can't unregister %s\n", major_name);
+ }
+ release_region(CDo_command,4);
return -EIO;
}
#ifdef MODULE
@@ -5594,13 +5752,29 @@ __initfunc(int SBPCD_INIT(void))
if (D_S[j].aud_buf==NULL) msg(DBG_INF,"audio buffer (%d frames) not available.\n",D_S[j].sbp_audsiz);
else msg(DBG_INF,"audio buffer size: %d frames.\n",D_S[j].sbp_audsiz);
}
+ sbpcd_infop = vmalloc(sizeof (struct cdrom_device_info));
+ if (sbpcd_infop == NULL)
+ {
+ release_region(CDo_command,4);
+ return -ENOMEM;
+ }
+ D_S[j].sbpcd_infop = sbpcd_infop;
+ memcpy (sbpcd_infop, &sbpcd_info, sizeof(struct cdrom_device_info));
+ sbpcd_infop->dev = MKDEV(MAJOR_NR, j);
+ strncpy(sbpcd_infop->name,major_name, sizeof(sbpcd_infop->name));
+
+ if (register_cdrom(sbpcd_infop))
+ {
+ printk(" sbpcd: Unable to register with Uniform CD-ROm driver\n");
+ }
+
/*
* set the block size
*/
sbpcd_blocksizes[j]=CD_FRAMESIZE;
}
blksize_size[MAJOR_NR]=sbpcd_blocksizes;
-
+
#ifndef MODULE
init_done:
#if !(SBPCD_ISSUE-1)
@@ -5635,6 +5809,12 @@ void cleanup_module(void)
if (D_S[j].drv_id==-1) continue;
vfree(D_S[j].sbp_buf);
if (D_S[j].sbp_audsiz>0) vfree(D_S[j].aud_buf);
+ if ((unregister_cdrom(D_S[j].sbpcd_infop) == -EINVAL))
+ {
+ msg(DBG_INF, "What's that: can't unregister info %s.\n", major_name);
+ return;
+ }
+ vfree(D_S[j].sbpcd_infop);
}
msg(DBG_INF, "%s module released.\n", major_name);
}
@@ -5665,6 +5845,11 @@ static int sbpcd_chk_disk_change(kdev_t full_dev)
else
return (0);
}
+
+static int sbpcd_media_changed( struct cdrom_device_info *cdi, int disc_nr)
+{
+ return sbpcd_chk_disk_change(cdi->dev);
+}
/*==========================================================================*/
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/drivers/cdrom/sjcd.c b/drivers/cdrom/sjcd.c
index 67d04134d..dc6e243f1 100644
--- a/drivers/cdrom/sjcd.c
+++ b/drivers/cdrom/sjcd.c
@@ -73,7 +73,7 @@
#define MAJOR_NR SANYO_CDROM_MAJOR
#include <linux/blk.h>
-#include <linux/sjcd.h>
+#include "sjcd.h"
static int sjcd_present = 0;
diff --git a/drivers/cdrom/sonycd535.c b/drivers/cdrom/sonycd535.c
index b5c257f9b..5e0ae01b7 100644
--- a/drivers/cdrom/sonycd535.c
+++ b/drivers/cdrom/sonycd535.c
@@ -132,7 +132,7 @@
#define MAJOR_NR CDU535_CDROM_MAJOR
# include <linux/blk.h>
#define sony535_cd_base_io sonycd535 /* for compatible parameter passing with "insmod" */
-#include <linux/sonycd535.h>
+#include "sonycd535.h"
/*
* this is the base address of the interface card for the Sony CDU-535
diff --git a/drivers/char/ChangeLog b/drivers/char/ChangeLog
index 0e61fb819..56e762e71 100644
--- a/drivers/char/ChangeLog
+++ b/drivers/char/ChangeLog
@@ -1,3 +1,9 @@
+Mon Dec 1 08:24:15 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * tty_io.c (tty_get_baud_rate): Print a warning syslog if the
+ tty->alt_speed kludge is used; this means the system is
+ using the deprecated SPD_HI ioctls.
+
Mon Nov 24 10:37:49 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* serial.c, esp.c, rocket.c: Change drivers to take advantage of
diff --git a/drivers/char/Config.in b/drivers/char/Config.in
index 9b13a4d2d..8af5a5e44 100644
--- a/drivers/char/Config.in
+++ b/drivers/char/Config.in
@@ -6,16 +6,18 @@ comment 'Character devices'
bool 'Virtual terminal' CONFIG_VT
if [ "$CONFIG_VT" = "y" ]; then
- bool 'Console on virtual terminal' CONFIG_VT_CONSOLE
+ bool 'Support for console on virtual terminal' CONFIG_VT_CONSOLE
fi
tristate 'Standard/generic (dumb) serial support' CONFIG_SERIAL
+if [ "$CONFIG_SERIAL" = "y" ]; then
+ bool ' Support for console on serial port' CONFIG_SERIAL_CONSOLE
+fi
bool 'Extended dumb serial driver options' CONFIG_SERIAL_EXTENDED
if [ "$CONFIG_SERIAL_EXTENDED" = "y" ]; then
bool ' Support more than 4 serial ports' CONFIG_SERIAL_MANY_PORTS
bool ' Support for sharing serial interrupts' CONFIG_SERIAL_SHARE_IRQ
bool ' Support special multiport boards' CONFIG_SERIAL_MULTIPORT
bool ' Support the Bell Technologies HUB6 card' CONFIG_HUB6
- bool ' Console on serial port' CONFIG_SERIAL_CONSOLE
fi
bool 'Non-standard serial port support' CONFIG_SERIAL_NONSTANDARD
if [ "$CONFIG_SERIAL_NONSTANDARD" = "y" ]; then
@@ -31,6 +33,10 @@ if [ "$CONFIG_SERIAL_NONSTANDARD" = "y" ]; then
tristate ' Stallion EC8/64, ONboard, Brumby support' CONFIG_ISTALLION
fi
tristate 'SDL RISCom/8 card support' CONFIG_RISCOM8
+ tristate 'Specialix IO8+ card support' CONFIG_SPECIALIX
+ if [ "$CONFIG_SPECIALIX" = "y" -o "$CONFIG_SPECIALIX" = "m" ]; then
+ bool 'Specialix DTR/RTS pin is RTS' CONFIG_SPECIALIX_RTSCTS
+ fi
tristate 'Hayes ESP serial port support' CONFIG_ESPSERIAL
if [ "$CONFIG_ESPSERIAL" = "y" -o "$CONFIG_ESPSERIAL" = "m" ]; then
int ' DMA channel' CONFIG_ESPSERIAL_DMA_CHANNEL 1
@@ -60,7 +66,11 @@ if [ "$CONFIG_MOUSE" = "y" ]; then
tristate 'PC110 digitizer pad support' CONFIG_PC110_PAD
fi
-if [ "$CONFIG_MODULES" = "y" ]; then
+# IRIX compat stuff for X on the Indy relies on CONFIG_UMISC
+if [ "$CONFIG_SGI" = "y" ]; then
+ define_bool CONFIG_UMISC y
+ bool 'Support for SGI graphic devices' CONFIG_SGI_GRAPHICS
+elif [ "$CONFIG_MODULES" = "y" ]; then
bool 'Support for user misc device modules' CONFIG_UMISC
fi
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 58ca9aa09..807db2c3d 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -125,6 +125,14 @@ else
endif
endif
+ifeq ($(CONFIG_SPECIALIX),y)
+L_OBJS += specialix.o
+else
+ ifeq ($(CONFIG_SPECIALIX),m)
+ M_OBJS += specialix.o
+ endif
+endif
+
ifeq ($(CONFIG_ATIXL_BUSMOUSE),y)
M = y
L_OBJS += atixlmouse.o
diff --git a/drivers/char/acquirewdt.c b/drivers/char/acquirewdt.c
index 8d2600f41..be1c28456 100644
--- a/drivers/char/acquirewdt.c
+++ b/drivers/char/acquirewdt.c
@@ -64,6 +64,10 @@ static void acq_ping(void)
static ssize_t acq_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
{
+ /* Can't seek (pwrite) on this device */
+ if (ppos != &file->f_pos)
+ return -ESPIPE;
+
if(count)
{
acq_ping();
diff --git a/drivers/char/bttv.c b/drivers/char/bttv.c
index 56d38d7a2..4c1fa303c 100644
--- a/drivers/char/bttv.c
+++ b/drivers/char/bttv.c
@@ -54,6 +54,7 @@
static unsigned int remap=0;
static unsigned int vidmem=0;
static unsigned int tuner=0; /* Default tuner */
+MODULE_PARM(tuner,"i");
static int find_vga(void);
static void bt848_set_risc_jmps(struct bttv *btv);
@@ -603,7 +604,7 @@ static long bttv_read(struct video_device *v, char *buf, unsigned long count, in
}
interruptible_sleep_on(&btv->vbiq);
sti();
- if(current->signal & ~current->blocked)
+ if(signal_pending(current))
{
if(todo==count)
return -EINTR;
diff --git a/drivers/char/console.c b/drivers/char/console.c
index b24def4a2..02ce3a64e 100644
--- a/drivers/char/console.c
+++ b/drivers/char/console.c
@@ -174,6 +174,7 @@ extern void vesa_powerdown(void);
extern void compute_shiftstate(void);
extern void reset_palette(int currcons);
extern void set_palette(void);
+extern int con_is_present(void);
extern unsigned long con_type_init(unsigned long, const char **);
extern void con_type_init_finish(void);
extern int set_get_cmap(unsigned char *, int);
@@ -1867,7 +1868,7 @@ void poke_blanked_console(void)
}
#ifdef CONFIG_VT_CONSOLE
-void vt_console_print(const char * b, unsigned count)
+void vt_console_print(struct console *co, const char * b, unsigned count)
{
int currcons = fg_console;
unsigned char c;
@@ -1916,16 +1917,25 @@ void vt_console_print(const char * b, unsigned count)
printing = 0;
}
-static int vt_console_device(void)
+static kdev_t vt_console_device(struct console *c)
{
- return MKDEV(TTY_MAJOR, fg_console + 1);
+ return MKDEV(TTY_MAJOR, c->index ? c->index : fg_console + 1);
}
-extern void keyboard_wait_for_keypress(void);
+extern int keyboard_wait_for_keypress(struct console *);
struct console vt_console_driver = {
- vt_console_print, do_unblank_screen,
- keyboard_wait_for_keypress, vt_console_device
+ "tty",
+ vt_console_print,
+ NULL,
+ vt_console_device,
+ keyboard_wait_for_keypress,
+ do_unblank_screen,
+ NULL,
+ CON_PRINTBUFFER,
+ -1,
+ 0,
+ NULL
};
#endif
@@ -2014,6 +2024,9 @@ static void console_bh(void)
*
* Reads the information preserved by setup.s to determine the current display
* type and sets everything accordingly.
+ *
+ * FIXME: return early if we don't _have_ a video card installed.
+ *
*/
__initfunc(unsigned long con_init(unsigned long kmem_start))
{
@@ -2181,7 +2194,7 @@ __initfunc(unsigned long con_init(unsigned long kmem_start))
* within the bus probing code... :-(
*/
#ifdef CONFIG_VT_CONSOLE
- if (video_type != VIDEO_TYPE_TGAC)
+ if (video_type != VIDEO_TYPE_TGAC && con_is_present())
register_console(&vt_console_driver);
#endif
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index ed4ac9846..4535230ac 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -1,6 +1,6 @@
#define BLOCKMOVE
static char rcsid[] =
-"$Revision: 2.1 $$Date: 1997/11/01 17:42:41 $";
+"$Revision: 2.1.1.1 $$Date: 1997/12/03 17:31:19 $";
/*
* linux/drivers/char/cyclades.c
@@ -30,6 +30,12 @@ static char rcsid[] =
* void cleanup_module(void);
*
* $Log: cyclades.c,v $
+ * Revision 2.1.1.1 1997/12/03 17:31:19 ivan
+ * Code review for the module cleanup routine (fixed memory leak);
+ * fixed RTS and DTR status report for new CD1400's in get_modem_info;
+ * purged conditional code for older kernels;
+ * includes anonymous changes regarding signal_pending
+ *
* Revision 2.1 1997/11/01 17:42:41 ivan
* Changes in the driver to support Alpha systems (except 8Zo V_1);
* BREAK fix for the Cyclades-Z boards;
@@ -524,8 +530,6 @@ static char rcsid[] =
#include <linux/version.h>
-#if (LINUX_VERSION_CODE >= 0x020100)
-
#include <asm/uaccess.h>
#include <linux/init.h>
@@ -540,17 +544,6 @@ static unsigned long cy_get_user(unsigned long *addr)
return result;
}
-#else
-
-#define __initfunc(__arginit) __arginit
-#define copy_from_user memcpy_fromfs
-#define copy_to_user memcpy_tofs
-#define cy_get_user get_fs_long
-#define cy_put_user put_fs_long
-#define ioremap vremap
-
-#endif
-
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
@@ -875,7 +868,6 @@ do_softint(void *private_)
if (!tty)
return;
-#if (LINUX_VERSION_CODE >= 0x020125)
if (test_and_clear_bit(Cy_EVENT_HANGUP, &info->event)) {
tty_hangup(info->tty);
wake_up_interruptible(&info->open_wait);
@@ -892,24 +884,6 @@ do_softint(void *private_)
}
wake_up_interruptible(&tty->write_wait);
}
-#else
- if (clear_bit(Cy_EVENT_HANGUP, &info->event)) {
- tty_hangup(info->tty);
- wake_up_interruptible(&info->open_wait);
- info->flags &= ~(ASYNC_NORMAL_ACTIVE|
- ASYNC_CALLOUT_ACTIVE);
- }
- if (clear_bit(Cy_EVENT_OPEN_WAKEUP, &info->event)) {
- wake_up_interruptible(&info->open_wait);
- }
- if (clear_bit(Cy_EVENT_WRITE_WAKEUP, &info->event)) {
- if((tty->flags & (1<< TTY_DO_WRITE_WAKEUP))
- && tty->ldisc.write_wakeup){
- (tty->ldisc.write_wakeup)(tty);
- }
- wake_up_interruptible(&tty->write_wait);
- }
-#endif
} /* do_softint */
@@ -2339,7 +2313,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
break;
}
restore_flags(flags);
- if (current->signal & ~current->blocked) {
+ if (signal_pending(current)) {
retval = -ERESTARTSYS;
break;
}
@@ -2397,7 +2371,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
|| (cy_readl(&ch_ctrl[channel].rs_status) & C_RS_DCD))) {
break;
}
- if (current->signal & ~current->blocked) {
+ if (signal_pending(current)) {
retval = -ERESTARTSYS;
break;
}
@@ -3318,12 +3292,18 @@ get_modem_info(struct cyclades_port * info, unsigned int *value)
status |= cy_readb(base_addr+(CyMSVR2<<index));
restore_flags(flags);
- result = ((status & CyRTS) ? TIOCM_RTS : 0)
- | ((status & CyDTR) ? TIOCM_DTR : 0)
- | ((status & CyDCD) ? TIOCM_CAR : 0)
- | ((status & CyRI) ? TIOCM_RNG : 0)
- | ((status & CyDSR) ? TIOCM_DSR : 0)
- | ((status & CyCTS) ? TIOCM_CTS : 0);
+
+ if (info->rtsdtr_inv) {
+ result = ((status & CyRTS) ? TIOCM_DTR : 0)
+ | ((status & CyDTR) ? TIOCM_RTS : 0);
+ } else {
+ result = ((status & CyRTS) ? TIOCM_RTS : 0)
+ | ((status & CyDTR) ? TIOCM_DTR : 0);
+ }
+ result |= ((status & CyDCD) ? TIOCM_CAR : 0)
+ | ((status & CyRI) ? TIOCM_RNG : 0)
+ | ((status & CyDSR) ? TIOCM_DSR : 0)
+ | ((status & CyCTS) ? TIOCM_CTS : 0);
} else {
base_addr = (unsigned char*) (cy_card[card].base_addr);
@@ -4329,7 +4309,7 @@ cy_detect_isa(void))
/* probe for CD1400... */
-#if !defined(__alpha__) && (LINUX_VERSION_CODE >= 0x020100)
+#if !defined(__alpha__)
cy_isa_address = ioremap((unsigned int)cy_isa_address,
CyISA_Ywin);
#endif
@@ -4483,9 +4463,6 @@ cy_detect_pci(void))
continue;
}
#else
-#if (LINUX_VERSION_CODE < 0x020100)
- if ((ulong)cy_pci_addr2 >= 0x100000) /* above 1M? */
-#endif
cy_pci_addr2 = (ulong) ioremap(cy_pci_addr2, CyPCI_Ywin);
#endif
@@ -5098,10 +5075,13 @@ cleanup_module(void)
save_flags(flags);
cli();
remove_bh(CYCLADES_BH);
+
+ free_page((unsigned long)tmp_buf);
if (tty_unregister_driver(&cy_callout_driver))
printk("Couldn't unregister Cyclom callout driver\n");
if (tty_unregister_driver(&cy_serial_driver))
printk("Couldn't unregister Cyclom serial driver\n");
+
restore_flags(flags);
for (i = 0; i < NR_CARDS; i++) {
diff --git a/drivers/char/esp.c b/drivers/char/esp.c
index 5fdcd8a77..5f4c480c7 100644
--- a/drivers/char/esp.c
+++ b/drivers/char/esp.c
@@ -932,6 +932,20 @@ static int startup(struct esp_struct * info)
IRQ_ports[info->irq] = info;
/*
+ * Set up the tty->alt_speed kludge
+ */
+ if (info->tty) {
+ if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+ info->tty->alt_speed = 57600;
+ if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+ info->tty->alt_speed = 115200;
+ if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
+ info->tty->alt_speed = 230400;
+ if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
+ info->tty->alt_speed = 460800;
+ }
+
+ /*
* set the speed of the serial port
*/
change_speed(info);
@@ -1118,7 +1132,8 @@ static void change_speed(struct esp_struct *info)
#endif
baud = tty_get_baud_rate(info->tty);
- if (baud == 38400)
+ if (baud == 38400 &&
+ ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST))
quot = info->custom_divisor;
else {
if (baud == 134)
diff --git a/drivers/char/ftape/Config.in b/drivers/char/ftape/Config.in
index 858f327d3..2f837be5b 100644
--- a/drivers/char/ftape/Config.in
+++ b/drivers/char/ftape/Config.in
@@ -17,7 +17,7 @@ choice 'Debugging output' \
"Normal CONFIG_FT_NORMAL_DEBUG \
Excessive CONFIG_FT_FULL_DEBUG \
Reduced CONFIG_FT_NO_TRACE \
- None CONIFG_FT_NO_TRACE_AT_ALL" Normal
+ None CONFIG_FT_NO_TRACE_AT_ALL" Normal
comment 'Hardware configuration'
choice 'Floppy tape controllers' \
"Standard CONFIG_FT_STD_FDC \
diff --git a/drivers/char/ftape/lowlevel/fdc-io.c b/drivers/char/ftape/lowlevel/fdc-io.c
index 904a99ac5..47229c5b4 100644
--- a/drivers/char/ftape/lowlevel/fdc-io.c
+++ b/drivers/char/ftape/lowlevel/fdc-io.c
@@ -445,7 +445,7 @@ int fdc_interrupt_wait(unsigned int time)
fdc_reset();
resetting = 0;
}
- TRACE_EXIT (current->signal & ~current->blocked) ? -EINTR : -ETIME;
+ TRACE_EXIT (signal_pending(current)) ? -EINTR : -ETIME;
}
/* Start/stop drive motor. Enable DMA mode.
diff --git a/drivers/char/ftape/lowlevel/ftape-init.c b/drivers/char/ftape/lowlevel/ftape-init.c
index 7a8d15f5e..28cdd5739 100644
--- a/drivers/char/ftape/lowlevel/ftape-init.c
+++ b/drivers/char/ftape/lowlevel/ftape-init.c
@@ -94,7 +94,7 @@ KERN_INFO "Compiled for Linux version %s"
#ifdef MODULE
while (ftape_set_nr_buffers(CONFIG_FT_NR_BUFFERS) < 0) {
ftape_sleep(FT_SECOND/20);
- if (current->signal & ~current->blocked) {
+ if (signal_pending(current)) {
(void)ftape_set_nr_buffers(0);
TRACE(ft_t_bug,
"Killed by signal while allocating buffers.");
diff --git a/drivers/char/ftape/lowlevel/ftape-io.c b/drivers/char/ftape/lowlevel/ftape-io.c
index af81d1802..e43da1e27 100644
--- a/drivers/char/ftape/lowlevel/ftape-io.c
+++ b/drivers/char/ftape/lowlevel/ftape-io.c
@@ -103,7 +103,7 @@ void ftape_sleep(unsigned int time)
}
/* Mmm. Isn't current->blocked == 0xffffffff ?
*/
- if (current->signal & ~current->blocked) {
+ if (signal_pending(current)) {
TRACE(ft_t_err,
"awoken by non-blocked signal :-(");
break; /* exit on signal */
diff --git a/drivers/char/hfmodem/main.c b/drivers/char/hfmodem/main.c
index eb30cec3e..b39ba2854 100644
--- a/drivers/char/hfmodem/main.c
+++ b/drivers/char/hfmodem/main.c
@@ -136,8 +136,6 @@ struct hfmodem_state hfmodem_state[NR_DEVICE];
#define LPT_CONTROL(iobase) (iobase+2)
#define LPT_IRQ_ENABLE 0x10
-#define LPT_EXTENT 3
-
#define MIDI_DATA(iobase) (iobase)
#define MIDI_STATUS(iobase) (iobase+1)
#define MIDI_READ_FULL 0x80 /* attention: negative logic!! */
@@ -150,33 +148,37 @@ struct hfmodem_state hfmodem_state[NR_DEVICE];
#define SP_MIDI 4
/* ---------------------------------------------------------------------- */
-/*
- * returns 0 if ok and != 0 on error;
- * the same behaviour as par96_check_lpt in baycom.c
- */
-__initfunc(static int check_lpt(unsigned int iobase))
+static int parptt_preempt(void *handle)
{
- unsigned char b1,b2;
- int i;
+ /* we cannot relinquish the port in the middle of an operation */
+ return 1;
+}
- if (iobase <= 0 || iobase > 0x1000-LPT_EXTENT)
- return 0;
- if (check_region(iobase, LPT_EXTENT))
- return 0;
- b1 = inb(LPT_DATA(iobase));
- b2 = inb(LPT_CONTROL(iobase));
- outb(0xaa, LPT_DATA(iobase));
- i = inb(LPT_DATA(iobase)) == 0xaa;
- outb(0x55, LPT_DATA(iobase));
- i &= inb(LPT_DATA(iobase)) == 0x55;
- outb(0x0a, LPT_CONTROL(iobase));
- i &= (inb(LPT_CONTROL(iobase)) & 0xf) == 0x0a;
- outb(0x05, LPT_CONTROL(iobase));
- i &= (inb(LPT_CONTROL(iobase)) & 0xf) == 0x05;
- outb(b1, LPT_DATA(iobase));
- outb(b2, LPT_CONTROL(iobase));
- return !i;
+/* --------------------------------------------------------------------- */
+
+static void parptt_wakeup(void *handle)
+{
+ struct hfmodem_state *dev = (struct hfmodem_state *)handle;
+
+ printk(KERN_DEBUG "%s: parptt: why am I being woken up?\n", hfmodem_drvname);
+ if (!parport_claim(dev->ptt_out.pardev))
+ printk(KERN_DEBUG "%s: parptt: I'm broken.\n", hfmodem_drvname);
+}
+
+/* --------------------------------------------------------------------- */
+__initfunc(static int check_lpt(struct hfmodem_state *dev, unsigned int iobase))
+{
+ struct parport *pp = parport_enumerate();
+
+ while (pp && pp->base != iobase)
+ pp = pp->next;
+ if (!pp)
+ return 0;
+ if (!(dev->ptt_out.pardev = parport_register_device(pp, hfmodem_drvname, parptt_preempt, parptt_wakeup,
+ NULL, PARPORT_DEV_LURK, dev)))
+ return 0;
+ return 1;
}
/* --------------------------------------------------------------------- */
@@ -272,8 +274,7 @@ __initfunc(static void output_check(struct hfmodem_state *dev))
{
enum uart u = c_uart_unknown;
- if (dev->ptt_out.seriobase > 0 && dev->ptt_out.seriobase <= 0x1000-SER_EXTENT &&
- ((u = check_uart(dev->ptt_out.seriobase))) != c_uart_unknown)
+ if (((u = check_uart(dev->ptt_out.seriobase))) != c_uart_unknown)
printk(KERN_INFO "%s: PTT output: uart found at address 0x%x type %s\n",
hfmodem_drvname, dev->ptt_out.seriobase, uart_str[u]);
else {
@@ -282,8 +283,7 @@ __initfunc(static void output_check(struct hfmodem_state *dev))
hfmodem_drvname, dev->ptt_out.seriobase);
dev->ptt_out.seriobase = 0;
}
- if (dev->ptt_out.pariobase > 0 && dev->ptt_out.pariobase <= 0x1000-LPT_EXTENT &&
- !check_lpt(dev->ptt_out.pariobase))
+ if (check_lpt(dev, dev->ptt_out.pariobase))
printk(KERN_INFO "%s: PTT output: parallel port found at address 0x%x\n",
hfmodem_drvname, dev->ptt_out.pariobase);
else {
@@ -291,6 +291,7 @@ __initfunc(static void output_check(struct hfmodem_state *dev))
printk(KERN_WARNING "%s: PTT output: no parallel port found at address 0x%x\n",
hfmodem_drvname, dev->ptt_out.pariobase);
dev->ptt_out.pariobase = 0;
+ dev->ptt_out.pardev = NULL;
}
if (dev->ptt_out.midiiobase > 0 && dev->ptt_out.midiiobase <= 0x1000-MIDI_EXTENT &&
check_midi(dev->ptt_out.midiiobase))
@@ -324,12 +325,11 @@ static void output_open(struct hfmodem_state *dev)
hfmodem_drvname, dev->ptt_out.seriobase);
}
if (dev->ptt_out.pariobase > 0) {
- if (!check_region(dev->ptt_out.pariobase, LPT_EXTENT)) {
- request_region(dev->ptt_out.pariobase, LPT_EXTENT, "hfmodem par ptt");
- dev->ptt_out.flags |= SP_PAR;
- } else
+ if (parport_claim(dev->ptt_out.pardev))
printk(KERN_WARNING "%s: PTT output: parallel port at 0x%x busy\n",
hfmodem_drvname, dev->ptt_out.pariobase);
+ else
+ dev->ptt_out.flags |= SP_PAR;
}
if (dev->ptt_out.midiiobase > 0) {
if (!check_region(dev->ptt_out.midiiobase, MIDI_EXTENT)) {
@@ -361,7 +361,7 @@ static void output_close(struct hfmodem_state *dev)
if (dev->ptt_out.flags & SP_SER)
release_region(dev->ptt_out.seriobase, SER_EXTENT);
if (dev->ptt_out.flags & SP_PAR)
- release_region(dev->ptt_out.pariobase, LPT_EXTENT);
+ parport_release(dev->ptt_out.pardev);
if (dev->ptt_out.flags & SP_MIDI)
release_region(dev->ptt_out.midiiobase, MIDI_EXTENT);
dev->ptt_out.flags = 0;
@@ -671,6 +671,10 @@ __initfunc(int init_module(void))
void cleanup_module(void)
{
+ struct hfmodem_state *dev = &hfmodem_state[0];
+
+ if (dev->ptt_out.pariobase > 0)
+ parport_unregister_device(dev->ptt_out.pardev);
misc_deregister(&hfmodem_device);
}
@@ -733,4 +737,3 @@ __initfunc(void hfmodem_init(void))
/* --------------------------------------------------------------------- */
#endif /* MODULE */
-
diff --git a/drivers/char/joystick.c b/drivers/char/joystick.c
index c8c44d77a..82fa23627 100644
--- a/drivers/char/joystick.c
+++ b/drivers/char/joystick.c
@@ -1,5 +1,5 @@
/*
- * $Id: joystick.c,v 1.2 1997/10/31 19:11:48 mj Exp $
+ * $Id: joystick.c,v 1.2 1997/12/06 23:52:28 ralf Exp $
*
* Copyright (C) 1997 Vojtech Pavlik
*/
@@ -470,7 +470,7 @@ static ssize_t js_read(struct file *file, char *buf, size_t count, loff_t *ppos)
retval = -EAGAIN;
break;
}
- if (current->signal & ~current->blocked) {
+ if (signal_pending(current)) {
retval = -ERESTARTSYS;
break;
}
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index 932578806..6a427c684 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -63,10 +63,12 @@ extern void scrollback(int);
extern void scrollfront(int);
struct wait_queue * keypress_wait = NULL;
+struct console;
-void keyboard_wait_for_keypress(void)
+int keyboard_wait_for_keypress(struct console *co)
{
sleep_on(&keypress_wait);
+ return 0;
}
/*
diff --git a/drivers/char/lp.c b/drivers/char/lp.c
index fdfb961c7..fb30c3e0c 100644
--- a/drivers/char/lp.c
+++ b/drivers/char/lp.c
@@ -64,6 +64,11 @@ static char *dev_name = "lp";
#undef LP_DEBUG
#undef LP_READ_DEBUG
+/* Magic numbers */
+#define AUTO -3
+#define OFF -2
+#define UNSPEC -1
+
static inline void lp_parport_release (int minor)
{
parport_release (lp_table[minor].dev);
@@ -163,9 +168,7 @@ static inline int lp_char(char lpchar, int minor, int use_polling)
static void lp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- struct parport *pb = (struct parport *) dev_id;
- struct pardevice *pd = pb->cad;
- struct lp_struct *lp_dev = (struct lp_struct *) pd->private;
+ struct lp_struct *lp_dev = (struct lp_struct *) dev_id;
if (waitqueue_active (&lp_dev->lp_wait_q))
wake_up(&lp_dev->lp_wait_q);
@@ -272,11 +275,11 @@ static inline int lp_write_buf(unsigned int minor, const char *buf, int count)
return total_bytes_written;
}
-static ssize_t lp_write(struct file * file, const char * buf, size_t count, loff_t *ppos)
+static ssize_t lp_write(struct file * file, const char * buf,
+ size_t count, loff_t *ppos)
{
- struct inode *inode = file->f_dentry->d_inode;
- unsigned int minor = MINOR(inode->i_rdev);
- int retv;
+ unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
+ ssize_t retv;
if (jiffies-lp_table[minor].lastcall > LP_TIME(minor))
lp_table[minor].runchars = 0;
@@ -288,7 +291,7 @@ static ssize_t lp_write(struct file * file, const char * buf, size_t count, loff
*/
lp_parport_claim (minor);
- retv = lp_write_buf(minor, buf, count);
+ retv = lp_write_buf(minor, buf, count);
lp_parport_release (minor);
return retv;
@@ -315,15 +318,15 @@ static void lp_select_in_high(int minor) {
}
/* Status readback confirming to ieee1284 */
-static ssize_t lp_read(struct file * file, char * buf, size_t count, loff_t *ppos)
+static ssize_t lp_read(struct file * file, char * buf,
+ size_t count, loff_t *ppos)
{
- struct inode *inode = file->f_dentry->d_inode;
unsigned char z=0, Byte=0, status;
char *temp;
- int retval;
+ ssize_t retval;
unsigned int counter=0;
unsigned int i;
- unsigned int minor=MINOR(inode->i_rdev);
+ unsigned int minor=MINOR(file->f_dentry->d_inode->i_rdev);
/* Claim Parport or sleep until it becomes available
* (see lp_wakeup() for details)
@@ -568,7 +571,7 @@ static struct file_operations lp_fops = {
lp_release
};
-static int parport[LP_NO] = { -1, };
+static int parport[LP_NO] = { UNSPEC, };
#ifdef MODULE
#define lp_init init_module
@@ -589,11 +592,11 @@ void lp_setup(char *str, int *ints)
printk(KERN_INFO "lp: too many ports, %s ignored.\n",
str);
} else if (!strcmp(str, "auto")) {
- parport[0] = -3;
+ parport[0] = AUTO;
} else {
if (ints[0] == 0 || ints[1] == 0) {
/* disable driver on "lp=" or "lp=0" */
- parport[0] = -2;
+ parport[0] = OFF;
} else {
printk(KERN_WARNING "warning: 'lp=0x%x' is deprecated, ignored\n", ints[1]);
}
@@ -619,7 +622,7 @@ void lp_wakeup(void *ref)
static int inline lp_searchfor(int list[], int a)
{
int i;
- for (i = 0; i < LP_NO && list[i] != -1; i++) {
+ for (i = 0; i < LP_NO && list[i] != UNSPEC; i++) {
if (list[i] == a) return 1;
}
return 0;
@@ -630,15 +633,16 @@ int lp_init(void)
int count = 0;
struct parport *pb;
- if (parport[0] == -2) return 0;
+ if (parport[0] == OFF) return 0;
pb = parport_enumerate();
while (pb) {
/* We only understand PC-style ports. */
if (pb->modes & PARPORT_MODE_PCSPP) {
- if (parport[0] == -1 || lp_searchfor(parport, count) ||
- (parport[0] == -3 &&
+ if (parport[0] == UNSPEC ||
+ lp_searchfor(parport, count) ||
+ (parport[0] == AUTO &&
pb->probe_info.class == PARPORT_CLASS_PRINTER)) {
lp_table[count].dev =
parport_register_device(pb, dev_name,
@@ -646,6 +650,10 @@ int lp_init(void)
lp_interrupt, PARPORT_DEV_TRAN,
(void *) &lp_table[count]);
lp_table[count].flags |= LP_EXIST;
+ init_waitqueue (&lp_table[count].lp_wait_q);
+ lp_parport_claim (count);
+ lp_reset (count);
+ lp_parport_release (count);
printk(KERN_INFO "lp%d: using %s (%s).\n",
count, pb->name, (pb->irq == PARPORT_IRQ_NONE)?"polling":"interrupt-driven");
}
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 177862c2a..08d11b901 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -539,7 +539,7 @@ __initfunc(int chr_dev_init(void))
* Some joysticks only appear when the soundcard they are
* connected too is confgured. Keep the sound/joystick ordering.
*/
- joystick_init();
+ js_init();
#endif
#if CONFIG_QIC02_TAPE
qic02_tape_init();
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index 3581b81c3..251f73f96 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -40,6 +40,7 @@
#include <asm/bitops.h>
#define CONSOLE_DEV MKDEV(TTY_MAJOR,0)
+#define SYSCONS_DEV MKDEV(TTYAUX_MAJOR,1)
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
@@ -53,7 +54,7 @@
* unthrottling the TTY driver. These watermarks are used for
* controlling the space in the read buffer.
*/
-#define TTY_THRESHOLD_THROTTLE (N_TTY_BUF_SIZE - 128)
+#define TTY_THRESHOLD_THROTTLE 128 /* now based on remaining room */
#define TTY_THRESHOLD_UNTHROTTLE 128
static inline void put_tty_queue(unsigned char c, struct tty_struct *tty)
@@ -65,21 +66,42 @@ static inline void put_tty_queue(unsigned char c, struct tty_struct *tty)
}
}
+/*
+ * Check whether to call the driver.unthrottle function.
+ * We test the TTY_THROTTLED bit first so that it always
+ * indicates the current state.
+ */
+static void check_unthrottle(struct tty_struct * tty)
+{
+ if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) &&
+ tty->driver.unthrottle)
+ tty->driver.unthrottle(tty);
+}
+
/*
- * Flush the input buffer
+ * Reset the read buffer counters, clear the flags,
+ * and make sure the driver is unthrottled. Called
+ * from n_tty_open() and n_tty_flush_buffer().
*/
-void n_tty_flush_buffer(struct tty_struct * tty)
+static void reset_buffer_flags(struct tty_struct *tty)
{
tty->read_head = tty->read_tail = tty->read_cnt = 0;
tty->canon_head = tty->canon_data = tty->erasing = 0;
memset(&tty->read_flags, 0, sizeof tty->read_flags);
+ check_unthrottle(tty);
+}
+
+/*
+ * Flush the input buffer
+ */
+void n_tty_flush_buffer(struct tty_struct * tty)
+{
+ /* clear everything and unthrottle the driver */
+ reset_buffer_flags(tty);
if (!tty->link)
return;
- if (tty->driver.unthrottle &&
- test_and_clear_bit(TTY_THROTTLED, &tty->flags))
- tty->driver.unthrottle(tty);
if (tty->link->packet) {
tty->ctrl_status |= TIOCPKT_FLUSHREAD;
wake_up_interruptible(&tty->link->read_wait);
@@ -507,7 +529,7 @@ send_signal:
return;
}
}
- if (L_ICANON(tty)) {
+ if (tty->icanon) {
if (c == ERASE_CHAR(tty) || c == KILL_CHAR(tty) ||
(c == WERASE_CHAR(tty) && L_IEXTEN(tty))) {
eraser(c, tty);
@@ -610,11 +632,29 @@ send_signal:
put_tty_queue(c, tty);
}
+static int n_tty_receive_room(struct tty_struct *tty)
+{
+ int left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
+
+ /*
+ * If we are doing input canonicalization, and there are no
+ * pending newlines, let characters through without limit, so
+ * that erase characters will be handled. Other excess
+ * characters will be beeped.
+ */
+ if (tty->icanon && !tty->canon_data)
+ return N_TTY_BUF_SIZE;
+
+ if (left > 0)
+ return left;
+ return 0;
+}
+
static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
char *fp, int count)
{
const unsigned char *p;
- char *f, flags = 0;
+ char *f, flags = TTY_NORMAL;
int i;
if (!tty->read_buf)
@@ -669,34 +709,23 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
wake_up_interruptible(&tty->read_wait);
}
- if ((tty->read_cnt >= TTY_THRESHOLD_THROTTLE) &&
- tty->driver.throttle &&
- !test_and_set_bit(TTY_THROTTLED, &tty->flags))
- tty->driver.throttle(tty);
-}
-
-static int n_tty_receive_room(struct tty_struct *tty)
-{
- int left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
-
/*
- * If we are doing input canonicalization, and there are no
- * pending newlines, let characters through without limit, so
- * that erase characters will be handled. Other excess
- * characters will be beeped.
+ * Check the remaining room for the input canonicalization
+ * mode. We don't want to throttle the driver if we're in
+ * canonical mode and don't have a newline yet!
*/
- if (tty->icanon && !tty->canon_data)
- return N_TTY_BUF_SIZE;
-
- if (left > 0)
- return left;
- return 0;
+ if (n_tty_receive_room(tty) < TTY_THRESHOLD_THROTTLE) {
+ /* check TTY_THROTTLED first so it indicates our state */
+ if (!test_and_set_bit(TTY_THROTTLED, &tty->flags) &&
+ tty->driver.throttle)
+ tty->driver.throttle(tty);
+ }
}
int is_ignored(int sig)
{
- return ((current->blocked & (1<<(sig-1))) ||
- (current->sig->action[sig-1].sa_handler == SIG_IGN));
+ return (sigismember(&current->blocked, sig) ||
+ current->sig->action[sig-1].sa.sa_handler == SIG_IGN);
}
static void n_tty_set_termios(struct tty_struct *tty, struct termios * old)
@@ -785,10 +814,8 @@ static int n_tty_open(struct tty_struct *tty)
return -ENOMEM;
}
memset(tty->read_buf, 0, N_TTY_BUF_SIZE);
- tty->read_head = tty->read_tail = tty->read_cnt = 0;
- tty->canon_head = tty->canon_data = tty->erasing = 0;
+ reset_buffer_flags(tty);
tty->column = 0;
- memset(tty->read_flags, 0, sizeof(tty->read_flags));
n_tty_set_termios(tty, 0);
tty->minimum_to_wake = 1;
tty->closing = 0;
@@ -797,7 +824,7 @@ static int n_tty_open(struct tty_struct *tty)
static inline int input_available_p(struct tty_struct *tty, int amt)
{
- if (L_ICANON(tty)) {
+ if (tty->icanon) {
if (tty->canon_data)
return 1;
} else if (tty->read_cnt >= (amt ? amt : 1))
@@ -824,7 +851,8 @@ static inline void copy_from_read_buf(struct tty_struct *tty,
n = MIN(*nr, MIN(tty->read_cnt, N_TTY_BUF_SIZE - tty->read_tail));
if (!n)
return;
- copy_to_user(*b, &tty->read_buf[tty->read_tail], n);
+ /* N.B. copy_to_user may work only partially */
+ n -= copy_to_user(*b, &tty->read_buf[tty->read_tail], n);
tty->read_tail = (tty->read_tail + n) & (N_TTY_BUF_SIZE-1);
tty->read_cnt -= n;
*b += n;
@@ -854,6 +882,7 @@ do_it_again:
check of the logic of this change. -- jlc */
/* don't stop on /dev/console */
if (file->f_dentry->d_inode->i_rdev != CONSOLE_DEV &&
+ file->f_dentry->d_inode->i_rdev != SYSCONS_DEV &&
current->tty == tty) {
if (tty->pgrp <= 0)
printk("read_chan: tty->pgrp <= 0!\n");
@@ -866,7 +895,7 @@ do_it_again:
}
}
- if (L_ICANON(tty)) {
+ if (tty->icanon) {
minimum = time = 0;
current->timeout = (unsigned long) -1;
} else {
@@ -895,9 +924,10 @@ do_it_again:
while (1) {
/* First test for status change. */
if (tty->packet && tty->link->ctrl_status) {
- if (b != buf)
+ if (b != buf || !nr)
break;
put_user(tty->link->ctrl_status, b++);
+ nr--;
tty->link->ctrl_status = 0;
break;
}
@@ -935,50 +965,52 @@ do_it_again:
current->state = TASK_RUNNING;
/* Deal with packet mode. */
- if (tty->packet && b == buf) {
+ if (tty->packet && b == buf && nr) {
put_user(TIOCPKT_DATA, b++);
nr--;
}
- if (L_ICANON(tty)) {
- while (1) {
- int eol;
+ if (tty->icanon) {
+ /* N.B. avoid overrun if nr == 0 */
+ while (nr && tty->read_cnt) {
+ int eol;
- if (!tty->read_cnt) {
- break;
- }
eol = test_and_clear_bit(tty->read_tail,
&tty->read_flags);
c = tty->read_buf[tty->read_tail];
tty->read_tail = ((tty->read_tail+1) &
(N_TTY_BUF_SIZE-1));
tty->read_cnt--;
- if (!eol) {
- put_user(c, b++);
- if (--nr)
- continue;
- break;
- }
- if (--tty->canon_data < 0) {
- tty->canon_data = 0;
- }
- if (c != __DISABLED_CHAR) {
+
+ if (!eol || (c != __DISABLED_CHAR)) {
put_user(c, b++);
nr--;
}
- break;
+ if (eol) {
+ /* this test should be redundant:
+ * we shouldn't be reading data if
+ * canon_data is 0
+ */
+ if (--tty->canon_data < 0)
+ tty->canon_data = 0;
+ break;
+ }
}
} else {
+ /* N.B. check for errors writing to user space? */
copy_from_read_buf(tty, &b, &nr);
copy_from_read_buf(tty, &b, &nr);
}
/* If there is enough space in the read buffer now, let the
- low-level driver know. */
- if (tty->driver.unthrottle &&
- (tty->read_cnt <= TTY_THRESHOLD_UNTHROTTLE)
- && test_and_clear_bit(TTY_THROTTLED, &tty->flags))
- tty->driver.unthrottle(tty);
+ * low-level driver know. We use n_tty_chars_in_buffer() to
+ * check the buffer, as it now knows about canonical mode.
+ * Otherwise, if the driver is throttled and the line is
+ * longer than TTY_THRESHOLD_UNTHROTTLE in canonical mode,
+ * we won't get any more characters.
+ */
+ if (n_tty_chars_in_buffer(tty) <= TTY_THRESHOLD_UNTHROTTLE)
+ check_unthrottle(tty);
if (b - buf >= minimum || !nr)
break;
@@ -1012,7 +1044,8 @@ static ssize_t write_chan(struct tty_struct * tty, struct file * file,
ssize_t retval = 0, num;
/* Job control check -- must be done at start (POSIX.1 7.1.1.4). */
- if (L_TOSTOP(tty) && file->f_dentry->d_inode->i_rdev != CONSOLE_DEV) {
+ if (L_TOSTOP(tty) && file->f_dentry->d_inode->i_rdev != CONSOLE_DEV &&
+ file->f_dentry->d_inode->i_rdev != SYSCONS_DEV) {
retval = tty_check_change(tty);
if (retval)
return retval;
@@ -1045,6 +1078,10 @@ static ssize_t write_chan(struct tty_struct * tty, struct file * file,
tty->driver.flush_chars(tty);
} else {
c = tty->driver.write(tty, 1, b, nr);
+ if (c < 0) {
+ retval = c;
+ break;
+ }
b += c;
nr -= c;
}
diff --git a/drivers/char/pcwd.c b/drivers/char/pcwd.c
index 213306349..207fc4cf4 100644
--- a/drivers/char/pcwd.c
+++ b/drivers/char/pcwd.c
@@ -29,6 +29,7 @@
* 961118 Changed some verbiage on some of the output, tidied up
* code bits, and added compatibility to 2.1.x.
* 970912 Enabled board on open and disable on close.
+ * 971107 Took account of recent VFS changes (broke read).
*/
#include <linux/module.h>
@@ -222,7 +223,7 @@ static void pcwd_send_heartbeat(void)
}
static int pcwd_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
int i, cdat, rv;
static struct watchdog_info ident=
@@ -359,8 +360,13 @@ static int pcwd_ioctl(struct inode *inode, struct file *file,
return 0;
}
-static long pcwd_write(struct inode *inode, struct file *file, const char *buf, unsigned long len)
+static ssize_t pcwd_write(struct file *file, const char *buf, size_t len,
+ loff_t *ppos)
{
+ /* Can't seek (pwrite) on this device */
+ if (ppos != &file->f_pos)
+ return -ESPIPE;
+
if (len)
{
pcwd_send_heartbeat();
@@ -381,11 +387,15 @@ static int pcwd_open(struct inode *ino, struct file *filep)
return(0);
}
-static ssize_t pcwd_read(struct file *file, char *buf, size_t count, loff_t *ppos)
+static ssize_t pcwd_read(struct file *file, char *buf, size_t count,
+ loff_t *ppos)
{
unsigned short c = inb(current_readport);
unsigned char cp;
+ /* Can't seek (pread) on this device */
+ if (ppos != &file->f_pos)
+ return -ESPIPE;
switch(MINOR(file->f_dentry->d_inode->i_rdev))
{
case TEMP_MINOR:
@@ -488,11 +498,16 @@ static struct file_operations pcwd_fops = {
pcwd_read, /* Read */
pcwd_write, /* Write */
NULL, /* Readdir */
- NULL, /* Select */
+ NULL, /* Poll */
pcwd_ioctl, /* IOctl */
NULL, /* MMAP */
pcwd_open, /* Open */
- pcwd_close /* Close */
+ pcwd_close, /* Release */
+ NULL, /* Fsync */
+ NULL, /* Fasync */
+ NULL, /* CheckMediaChange */
+ NULL, /* Revalidate */
+ NULL, /* Lock */
};
static struct miscdevice pcwd_miscdev = {
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c
index ef9af462b..2a616142c 100644
--- a/drivers/char/rocket.c
+++ b/drivers/char/rocket.c
@@ -622,7 +622,7 @@ static void init_r_port(int board, int aiop, int chan)
rp_table[line] = info;
}
-#if (LINUX_VERSION_CODE < 131393) /* Linux 2.1.65 */
+#if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
static int baud_table[] = {
0, 50, 75, 110, 134, 150, 200, 300,
600, 1200, 1800, 2400, 4800, 9600, 19200,
@@ -673,7 +673,7 @@ static void configure_r_port(struct r_port *info)
}
/* baud rate */
-#if (LINUX_VERSION_CODE < 131393) /* Linux 2.1.65 */
+#if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
i = cflag & CBAUD;
if (i & CBAUDEX) {
i &= ~CBAUDEX;
@@ -974,7 +974,21 @@ static int rp_open(struct tty_struct *tty, struct file * filp)
sEnTransmit(cp);
info->flags |= ROCKET_INITIALIZED;
-
+
+#if (LINUX_VERSION_CODE >= 131394) /* Linux 2.1.66 */
+ /*
+ * Set up the tty->alt_speed kludge
+ */
+ if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_HI)
+ info->tty->alt_speed = 57600;
+ if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_VHI)
+ info->tty->alt_speed = 115200;
+ if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_SHI)
+ info->tty->alt_speed = 230400;
+ if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP)
+ info->tty->alt_speed = 460800;
+#endif
+
configure_r_port(info);
if (tty->termios->c_cflag & CBAUD) {
sSetDTR(cp);
@@ -1190,7 +1204,7 @@ static void rp_set_termios(struct tty_struct *tty, struct termios *old_termios)
/*
* Here are the routines used by rp_ioctl
*/
-#if (LINUX_VERSION_CODE < 131393) /* Linux 2.1.65 */
+#if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
static void send_break( struct r_port * info, int duration)
{
current->state = TASK_INTERRUPTIBLE;
@@ -1316,7 +1330,7 @@ static int set_config(struct r_port * info, struct rocket_config * new_info)
info->close_delay = new_serial.close_delay;
info->closing_wait = new_serial.closing_wait;
-#if (LINUX_VERSION_CODE >= 131393) /* Linux 2.1.65 */
+#if (LINUX_VERSION_CODE >= 131394) /* Linux 2.1.66 */
if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_HI)
info->tty->alt_speed = 57600;
if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_VHI)
@@ -1357,7 +1371,7 @@ static int rp_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg)
{
struct r_port * info = (struct r_port *)tty->driver_data;
-#if (LINUX_VERSION_CODE < 131393) /* Linux 2.1.65 */
+#if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
int retval, tmp;
#endif
@@ -1366,7 +1380,7 @@ static int rp_ioctl(struct tty_struct *tty, struct file * file,
return -ENODEV;
switch (cmd) {
-#if (LINUX_VERSION_CODE < 131393) /* Linux 2.1.65 */
+#if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
case TCSBRK: /* SVID version: non-zero arg --> no break */
retval = tty_check_change(tty);
if (retval)
@@ -2133,7 +2147,7 @@ __initfunc(int rp_init(void))
rocket_driver.stop = rp_stop;
rocket_driver.start = rp_start;
rocket_driver.hangup = rp_hangup;
-#if (LINUX_VERSION_CODE >= 131393) /* Linux 2.1.65 */
+#if (LINUX_VERSION_CODE >= 131394) /* Linux 2.1.66 */
rocket_driver.break_ctl = rp_break;
#endif
#if (LINUX_VERSION_CODE >= 131343)
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
index 26cfa4768..1b1990480 100644
--- a/drivers/char/rtc.c
+++ b/drivers/char/rtc.c
@@ -52,11 +52,11 @@
#include <linux/fcntl.h>
#include <linux/mc146818rtc.h>
#include <linux/init.h>
+#include <linux/poll.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/system.h>
-#include <asm/poll.h>
/* Adjust starting epoch if ARC console time is being used */
#ifdef CONFIG_RTC_ARC
diff --git a/drivers/char/serial.c b/drivers/char/serial.c
index 7d21673aa..7af575780 100644
--- a/drivers/char/serial.c
+++ b/drivers/char/serial.c
@@ -51,6 +51,9 @@
#include <linux/mm.h>
#include <linux/malloc.h>
#include <linux/init.h>
+#ifdef CONFIG_SERIAL_CONSOLE
+#include <linux/console.h>
+#endif
#include <asm/system.h>
#include <asm/io.h>
@@ -158,6 +161,9 @@ static int IRQ_timeout[16];
static volatile int rs_irq_triggered;
static volatile int rs_triggered;
static int rs_wild_int_mask;
+#ifdef CONFIG_SERIAL_CONSOLE
+static struct console sercons;
+#endif
static void autoconfig(struct serial_state * info);
static void change_speed(struct async_struct *info);
@@ -1303,6 +1309,20 @@ static int startup(struct async_struct * info)
timer_active |= 1 << RS_TIMER;
/*
+ * Set up the tty->alt_speed kludge
+ */
+ if (info->tty) {
+ if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+ info->tty->alt_speed = 57600;
+ if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+ info->tty->alt_speed = 115200;
+ if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
+ info->tty->alt_speed = 230400;
+ if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
+ info->tty->alt_speed = 460800;
+ }
+
+ /*
* and set the speed of the serial port
*/
change_speed(info);
@@ -1469,7 +1489,8 @@ static void change_speed(struct async_struct *info)
/* Determine divisor based on baud rate */
baud = tty_get_baud_rate(info->tty);
baud_base = info->state->baud_base;
- if (baud == 38400)
+ if (baud == 38400 &&
+ ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST))
quot = info->state->custom_divisor;
else {
if (baud == 134)
@@ -2830,7 +2851,13 @@ static int rs_open(struct tty_struct *tty, struct file * filp)
*tty->termios = info->state->callout_termios;
change_speed(info);
}
-
+#ifdef CONFIG_SERIAL_CONSOLE
+ if (sercons.cflag && sercons.index == line) {
+ tty->termios->c_cflag = sercons.cflag;
+ sercons.cflag = 0;
+ change_speed(info);
+ }
+#endif
info->session = current->session;
info->pgrp = current->pgrp;
@@ -3288,7 +3315,18 @@ __initfunc(int rs_init(void))
sizeof(struct rs_multiport_struct));
#endif
}
-
+#ifdef CONFIG_SERIAL_CONSOLE
+ /*
+ * The interrupt of the serial console port
+ * can't be shared.
+ */
+ if (sercons.flags & CON_FIRST) {
+ for(i = 0; i < NR_PORTS; i++)
+ if (i != sercons.index &&
+ rs_table[i].irq == rs_table[sercons.index].irq)
+ rs_table[i].irq = 0;
+ }
+#endif
show_serial_version();
/* Initialize the tty_driver structure */
@@ -3491,53 +3529,51 @@ void cleanup_module(void)
*/
#ifdef CONFIG_SERIAL_CONSOLE
-#include <linux/console.h>
+#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
/*
- * this defines the index into rs_table for the port to use
+ * Wait for transmitter & holding register to empty
*/
-#ifndef CONFIG_SERIAL_CONSOLE_PORT
-#define CONFIG_SERIAL_CONSOLE_PORT 0
-#endif
-
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-/* Wait for transmitter & holding register to empty */
static inline void wait_for_xmitr(struct serial_state *ser)
{
int lsr;
+ unsigned int tmout = 1000000;
+
do {
lsr = inb(ser->port + UART_LSR);
+ if (--tmout == 0) break;
} while ((lsr & BOTH_EMPTY) != BOTH_EMPTY);
}
/*
- * Print a string to the serial port trying not to disturb any possible
- * real use of the port...
+ * Print a string to the serial port trying not to disturb
+ * any possible real use of the port...
*/
-static void serial_console_write(const char *s, unsigned count)
+static void serial_console_write(struct console *co, const char *s,
+ unsigned count)
{
struct serial_state *ser;
int ier;
unsigned i;
- ser = rs_table + CONFIG_SERIAL_CONSOLE_PORT;
+ ser = rs_table + co->index;
/*
- * First save the IER then disable the interrupts
+ * First save the IER then disable the interrupts
*/
ier = inb(ser->port + UART_IER);
outb(0x00, ser->port + UART_IER);
/*
- * Now, do each character
+ * Now, do each character
*/
for (i = 0; i < count; i++, s++) {
wait_for_xmitr(ser);
- /* Send the character out. */
+ /*
+ * Send the character out.
+ * If a LF, also do CR...
+ */
outb(*s, ser->port + UART_TX);
-
- /* if a LF, also do CR... */
if (*s == 10) {
wait_for_xmitr(ser);
outb(13, ser->port + UART_TX);
@@ -3545,29 +3581,29 @@ static void serial_console_write(const char *s, unsigned count)
}
/*
- * Finally, Wait for transmitter & holding register to empty
- * and restore the IER
+ * Finally, Wait for transmitter & holding register to empty
+ * and restore the IER
*/
wait_for_xmitr(ser);
outb(ier, ser->port + UART_IER);
}
/*
- * Receive character from the serial port
+ * Receive character from the serial port
*/
-static void serial_console_wait_key(void)
+static int serial_console_wait_key(struct console *co)
{
struct serial_state *ser;
int ier;
int lsr;
int c;
- ser = rs_table + CONFIG_SERIAL_CONSOLE_PORT;
+ ser = rs_table + co->index;
/*
- * First save the IER then disable the interrupts so
- * that the real driver for the port does not get the
- * character.
+ * First save the IER then disable the interrupts so
+ * that the real driver for the port does not get the
+ * character.
*/
ier = inb(ser->port + UART_IER);
outb(0x00, ser->port + UART_IER);
@@ -3577,41 +3613,151 @@ static void serial_console_wait_key(void)
} while (!(lsr & UART_LSR_DR));
c = inb(ser->port + UART_RX);
- /* Restore the interrupts */
+ /*
+ * Restore the interrupts
+ */
outb(ier, ser->port + UART_IER);
+
+ return c;
}
-static int serial_console_device(void)
+static kdev_t serial_console_device(struct console *c)
{
- return MKDEV(TTYAUX_MAJOR, 64 + CONFIG_SERIAL_CONSOLE_PORT);
+ return MKDEV(TTY_MAJOR, 64 + c->index);
}
-long serial_console_init(long kmem_start, long kmem_end)
+/*
+ * Setup initial baud/bits/parity. We do two things here:
+ * - construct a cflag setting for the first rs_open()
+ * - initialize the serial port
+ * Return non-zero if we didn't find a serial port.
+ */
+__initfunc(static int serial_console_setup(struct console *co, char *options))
{
- static struct console console = {
- serial_console_write, 0,
- serial_console_wait_key, serial_console_device
- };
struct serial_state *ser;
+ unsigned cval;
+ int baud = 9600;
+ int bits = 8;
+ int parity = 'n';
+ int cflag = CREAD | HUPCL | CLOCAL;
+ int quot = 0;
+ char *s;
+
+ if (options) {
+ baud = simple_strtoul(options, NULL, 10);
+ s = options;
+ while(*s >= '0' && *s <= '9')
+ s++;
+ if (*s) parity = *s++;
+ if (*s) bits = *s - '0';
+ }
- ser = rs_table + CONFIG_SERIAL_CONSOLE_PORT;
+ /*
+ * Now construct a cflag setting.
+ */
+ switch(baud) {
+ case 1200:
+ cflag |= B1200;
+ break;
+ case 2400:
+ cflag |= B2400;
+ break;
+ case 4800:
+ cflag |= B4800;
+ break;
+ case 19200:
+ cflag |= B19200;
+ break;
+ case 38400:
+ cflag |= B38400;
+ break;
+ case 57600:
+ cflag |= B57600;
+ break;
+ case 115200:
+ cflag |= B115200;
+ break;
+ case 9600:
+ default:
+ cflag |= B9600;
+ break;
+ }
+ switch(bits) {
+ case 7:
+ cflag |= CS7;
+ break;
+ default:
+ case 8:
+ cflag |= CS8;
+ break;
+ }
+ switch(parity) {
+ case 'o': case 'O':
+ cflag |= PARODD;
+ break;
+ case 'e': case 'E':
+ cflag |= PARENB;
+ break;
+ }
+ co->cflag = cflag;
- /* Disable all interrupts, it works in polled mode */
- outb(0x00, ser->port + UART_IER);
+ /*
+ * Divisor, bytesize and parity
+ */
+ ser = rs_table + co->index;
+ quot = BASE_BAUD / baud;
+ cval = cflag & (CSIZE | CSTOPB);
+#if defined(__powerpc__) || defined(__alpha__)
+ cval >>= 8;
+#else /* !__powerpc__ && !__alpha__ */
+ cval >>= 4;
+#endif /* !__powerpc__ && !__alpha__ */
+ if (cflag & PARENB)
+ cval |= UART_LCR_PARITY;
+ if (!(cflag & PARODD))
+ cval |= UART_LCR_EPAR;
/*
- * now do hardwired init
+ * Disable UART interrupts, set DTR and RTS high
+ * and set speed.
*/
- outb(0x03, ser->port + UART_LCR); /* No parity, 8 data bits, 1 stop */
- outb(0x83, ser->port + UART_LCR); /* Access divisor latch */
- outb(0x00, ser->port + UART_DLM); /* 9600 baud */
- outb(0x0c, ser->port + UART_DLL);
- outb(0x03, ser->port + UART_LCR); /* Done with divisor */
+ outb(0, ser->port + UART_IER);
+ outb(UART_MCR_DTR | UART_MCR_RTS, ser->port + UART_MCR);
+ outb(cval | UART_LCR_DLAB, ser->port + UART_LCR); /* set DLAB */
+ outb(quot & 0xff, ser->port + UART_DLL); /* LS of divisor */
+ outb(quot >> 8, ser->port + UART_DLM); /* MS of divisor */
+ outb(cval, ser->port + UART_LCR); /* reset DLAB */
- register_console(&console);
- return kmem_start;
+ /*
+ * If we read 0xff from the LSR, there is no UART here.
+ */
+ if (inb(ser->port + UART_LSR) == 0xff)
+ return -1;
+ return 0;
}
+static struct console sercons = {
+ "ttyS",
+ serial_console_write,
+ NULL,
+ serial_console_device,
+ serial_console_wait_key,
+ NULL,
+ serial_console_setup,
+ CON_PRINTBUFFER,
+ -1,
+ 0,
+ NULL
+};
+
+/*
+ * Register console.
+ */
+__initfunc (long serial_console_init(long kmem_start, long kmem_end))
+{
+ register_console(&sercons);
+ return kmem_start;
+}
#endif
#ifdef CONFIG_REMOTE_DEBUG
diff --git a/drivers/char/softdog.c b/drivers/char/softdog.c
index be63f08b4..c0ecaccf4 100644
--- a/drivers/char/softdog.c
+++ b/drivers/char/softdog.c
@@ -115,6 +115,10 @@ static void softdog_ping(void)
static ssize_t softdog_write(struct file *file, const char *data, size_t len, loff_t *ppos)
{
+ /* Can't seek (pwrite) on this device */
+ if (ppos != &file->f_pos)
+ return -ESPIPE;
+
/*
* Refresh the timer.
*/
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index 8e378215f..9fadb9e4e 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -101,11 +101,34 @@ typedef struct {
int irqtype;
} stlconf_t;
+/*static stlconf_t stl_brdconf[] = {
+ { BRD_EASYIO, 0x2a0, 0, 0, 10, 0 },
+};*/
+
+#ifdef MODULE
+static char *brdtype[STL_MAXBRDS] = {"\0", };
+static int io[STL_MAXBRDS] = { 0, };
+static int secio[STL_MAXBRDS] = { 0, };
+static int irq[STL_MAXBRDS] = { 0, };
+
+MODULE_PARM(brdtype, "1-" __MODULE_STRING(STL_MAXBRDS) "s");
+MODULE_PARM(io, "1-" __MODULE_STRING(STL_MAXBRDS) "i");
+MODULE_PARM(secio, "1-" __MODULE_STRING(STL_MAXBRDS) "i");
+MODULE_PARM(irq, "1-" __MODULE_STRING(STL_MAXBRDS) "i");
+
+static stlconf_t stl_brdconf[STL_MAXBRDS];
+static int stl_nrbrds = 0;
+
+#else
static stlconf_t stl_brdconf[] = {
{ BRD_EASYIO, 0x2a0, 0, 0, 10, 0 },
+ { BRD_EASYIO, 0x2a8, 0, 0, 10, 0 },
+ { BRD_EASYIO, 0x2b0, 0, 0, 10, 0 },
+ { BRD_ECH, 0x2a0, 0x240, 0, 10, 0 },
};
static int stl_nrbrds = sizeof(stl_brdconf) / sizeof(stlconf_t);
+#endif
/*****************************************************************************/
@@ -616,9 +639,22 @@ static struct file_operations stl_fsiomem = {
* Loadable module initialization stuff.
*/
+struct board_type_elem
+{
+ int type_id;
+ char *name;
+};
+
+struct board_type_elem board_types[] = {
+ { BRD_EASYIO, "easyio" },
+ { BRD_ECH, "ech" },
+ { BRD_ECHMC, "echmc" },
+ { BRD_ECHPCI, "echpci" } };
+
int init_module()
{
unsigned long flags;
+ int i, j, num_board_types;
#if DEBUG
printk("init_module()\n");
@@ -626,6 +662,25 @@ int init_module()
save_flags(flags);
cli();
+
+ num_board_types = sizeof(board_types) / sizeof(struct board_type_elem);
+ for (i = 0; (i < STL_MAXBRDS && io[i]); i++)
+ {
+ stl_brdconf[stl_nrbrds].brdtype = 0;
+ for (j = 0; j < num_board_types; j++)
+ if(strcmp(board_types[j].name, brdtype[i]) == 0)
+ stl_brdconf[stl_nrbrds].brdtype = board_types[j].type_id;
+ if(stl_brdconf[stl_nrbrds].brdtype != 0)
+ {
+ stl_brdconf[stl_nrbrds].ioaddr1 = io[i];
+ stl_brdconf[stl_nrbrds].ioaddr2 = secio[i];
+ stl_brdconf[stl_nrbrds].memaddr = 0;
+ stl_brdconf[stl_nrbrds].irq = irq[i];
+ stl_brdconf[stl_nrbrds].irqtype = 0;
+ stl_nrbrds++;
+ }
+ }
+
stl_init();
restore_flags(flags);
@@ -823,7 +878,10 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
return(-EBUSY);
} else {
if ((rc = stl_waitcarrier(portp, filp)) != 0)
+ {
+ MOD_INC_USE_COUNT;
return(rc);
+ }
}
portp->flags |= ASYNC_NORMAL_ACTIVE;
}
@@ -838,6 +896,7 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
portp->session = current->session;
portp->pgrp = current->pgrp;
+ MOD_INC_USE_COUNT;
return(0);
}
@@ -925,6 +984,7 @@ static void stl_close(struct tty_struct *tty, struct file *filp)
restore_flags(flags);
return;
}
+ MOD_DEC_USE_COUNT;
if (portp->refcount-- > 1) {
restore_flags(flags);
return;
@@ -2237,10 +2297,12 @@ static inline int stl_initbrds()
printk("stl_initbrds()\n");
#endif
+#ifndef MODULE
if (stl_nrbrds > STL_MAXBRDS) {
printk("STALLION: too many boards in configuration table, truncating to %d\n", STL_MAXBRDS);
stl_nrbrds = STL_MAXBRDS;
}
+#endif
/*
* Firstly scan the list of static boards configured. Allocate
diff --git a/drivers/char/tga.c b/drivers/char/tga.c
index f4e7b48ab..d824294ec 100644
--- a/drivers/char/tga.c
+++ b/drivers/char/tga.c
@@ -443,6 +443,19 @@ void set_vesa_blanking(const unsigned long arg)
{
}
+
+/*
+ * See if we have a TGA card.
+ */
+__initfunc(int con_is_present())
+{
+ int status;
+
+ status = pcibios_find_device (PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TGA,
+ 0, &pci_bus, &pci_devfn);
+ return (status == PCIBIOS_DEVICE_NOT_FOUND) ? 0 : 1;
+}
+
/*
* video init code, called from within the PCI bus probing code;
* when TGA console is configured, at the end of the probing code,
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index a2f092b74..1c1beddab 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -90,6 +90,7 @@
#define CONSOLE_DEV MKDEV(TTY_MAJOR,0)
#define TTY_DEV MKDEV(TTYAUX_MAJOR,0)
+#define SYSCONS_DEV MKDEV(TTYAUX_MAJOR,1)
#undef TTY_DEBUG_HANGUP
@@ -386,7 +387,8 @@ void do_tty_hangup(void *data)
continue;
if (!filp->f_dentry->d_inode)
continue;
- if (filp->f_dentry->d_inode->i_rdev == CONSOLE_DEV)
+ if (filp->f_dentry->d_inode->i_rdev == CONSOLE_DEV ||
+ filp->f_dentry->d_inode->i_rdev == SYSCONS_DEV)
continue;
if (filp->f_op != &tty_fops)
continue;
@@ -517,9 +519,7 @@ void disassociate_ctty(int on_exit)
void wait_for_keypress(void)
{
struct console *c = console_drivers;
- while(c && !c->wait_key)
- c = c->next;
- if (c) c->wait_key();
+ if (c) c->wait_key(c);
}
void stop_tty(struct tty_struct *tty)
@@ -647,8 +647,13 @@ static ssize_t tty_write(struct file * file, const char * buf, size_t count,
if (ppos != &file->f_pos)
return -ESPIPE;
+ /*
+ * For now, we redirect writes from /dev/console as
+ * well as /dev/tty0.
+ */
inode = file->f_dentry->d_inode;
- is_console = (inode->i_rdev == CONSOLE_DEV);
+ is_console = (inode->i_rdev == SYSCONS_DEV ||
+ inode->i_rdev == CONSOLE_DEV);
if (is_console && redirect)
tty = redirect;
@@ -1182,13 +1187,20 @@ retry_open:
filp->f_flags |= O_NONBLOCK; /* Don't let /dev/tty block */
/* noctty = 1; */
}
+#ifdef CONFIG_VT
if (device == CONSOLE_DEV) {
+ extern int fg_console;
+ device = MKDEV(TTY_MAJOR, fg_console + 1);
+ noctty = 1;
+ }
+#endif
+ if (device == SYSCONS_DEV) {
struct console *c = console_drivers;
while(c && !c->device)
c = c->next;
if (!c)
return -ENODEV;
- device = c->device();
+ device = c->device(c);
noctty = 1;
}
minor = MINOR(device);
@@ -1369,7 +1381,8 @@ static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty,
static int tioccons(struct tty_struct *tty, struct tty_struct *real_tty)
{
- if (tty->driver.type == TTY_DRIVER_TYPE_CONSOLE) {
+ if (tty->driver.type == TTY_DRIVER_TYPE_CONSOLE ||
+ tty->driver.type == TTY_DRIVER_TYPE_SYSCONS) {
if (!suser())
return -EPERM;
redirect = NULL;
@@ -1466,6 +1479,19 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t
return 0;
}
+static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t *arg)
+{
+ /*
+ * (tty == real_tty) is a cheap way of
+ * testing if the tty is NOT a master pty.
+ */
+ if (tty == real_tty && current->tty != real_tty)
+ return -ENOTTY;
+ if (real_tty->session <= 0)
+ return -ENOTTY;
+ return put_user(real_tty->session, arg);
+}
+
static int tiocttygstruct(struct tty_struct *tty, struct tty_struct *arg)
{
if (copy_to_user(arg, tty, sizeof(*arg)))
@@ -1585,6 +1611,8 @@ static int tty_ioctl(struct inode * inode, struct file * file,
return tiocgpgrp(tty, real_tty, (pid_t *) arg);
case TIOCSPGRP:
return tiocspgrp(tty, real_tty, (pid_t *) arg);
+ case TIOCGSID:
+ return tiocgsid(tty, real_tty, (pid_t *) arg);
case TIOCGETD:
return put_user(tty->ldisc.num, (int *) arg);
case TIOCSETD:
@@ -1742,8 +1770,13 @@ int tty_get_baud_rate(struct tty_struct *tty)
else
i += 15;
}
- if (i==15 && tty->alt_speed)
+ if (i==15 && tty->alt_speed) {
+ if (!tty->warned) {
+ printk("Use of setserial/setrocket to set SPD_* flags is deprecated\n");
+ tty->warned = 1;
+ }
return(tty->alt_speed);
+ }
return baud_table[i];
}
@@ -1885,16 +1918,17 @@ long console_init(long kmem_start, long kmem_end)
* set up the console device so that later boot sequences can
* inform about problems etc..
*/
-#ifdef CONFIG_SERIAL_CONSOLE
- kmem_start = serial_console_init(kmem_start, kmem_end);
-#endif
#ifdef CONFIG_VT
kmem_start = con_init(kmem_start);
#endif
+#ifdef CONFIG_SERIAL_CONSOLE
+ kmem_start = serial_console_init(kmem_start, kmem_end);
+#endif
return kmem_start;
}
-static struct tty_driver dev_tty_driver, dev_console_driver;
+static struct tty_driver dev_tty_driver, dev_console_driver,
+ dev_syscons_driver;
/*
* Ok, now we can initialize the rest of the tty devices and can count
@@ -1925,17 +1959,28 @@ __initfunc(int tty_init(void))
if (tty_register_driver(&dev_tty_driver))
panic("Couldn't register /dev/tty driver\n");
+ dev_syscons_driver = dev_tty_driver;
+ dev_syscons_driver.driver_name = "/dev/console";
+ dev_syscons_driver.name = dev_syscons_driver.driver_name + 5;
+ dev_syscons_driver.major = TTYAUX_MAJOR;
+ dev_syscons_driver.minor_start = 1;
+ dev_syscons_driver.type = TTY_DRIVER_TYPE_SYSTEM;
+ dev_syscons_driver.subtype = SYSTEM_TYPE_SYSCONS;
+
+ if (tty_register_driver(&dev_syscons_driver))
+ panic("Couldn't register /dev/console driver\n");
+
+#ifdef CONFIG_VT
dev_console_driver = dev_tty_driver;
- dev_console_driver.driver_name = "/dev/console";
+ dev_console_driver.driver_name = "/dev/tty0";
dev_console_driver.name = dev_console_driver.driver_name + 5;
dev_console_driver.major = TTY_MAJOR;
dev_console_driver.type = TTY_DRIVER_TYPE_SYSTEM;
dev_console_driver.subtype = SYSTEM_TYPE_CONSOLE;
if (tty_register_driver(&dev_console_driver))
- panic("Couldn't register /dev/console driver\n");
+ panic("Couldn't register /dev/tty0 driver\n");
-#ifdef CONFIG_VT
kbd_init();
#endif
#ifdef CONFIG_ESPSERIAL /* init ESP before rs, so rs doesn't see the port */
@@ -1965,6 +2010,9 @@ __initfunc(int tty_init(void))
#ifdef CONFIG_RISCOM8
riscom8_init();
#endif
+#ifdef CONFIG_SPECIALIX
+ specialix_init();
+#endif
pty_init();
#ifdef CONFIG_VT
vcs_init();
diff --git a/drivers/char/vga.c b/drivers/char/vga.c
index c3fee1ae7..3c932ad7c 100644
--- a/drivers/char/vga.c
+++ b/drivers/char/vga.c
@@ -57,7 +57,6 @@
#ifdef __mips__
#include <asm/bootinfo.h>
-#include <asm/deskstation.h>
#include <asm/sni.h>
/*
* The video control ports are mapped at virtual address
@@ -166,6 +165,31 @@ set_cursor(int currcons)
hide_cursor();
}
+__initfunc(int con_is_present(void))
+{
+ unsigned short saved;
+ unsigned short *p;
+
+ /*
+ * Find out if there is a graphics card present.
+ * Are there smarter methods around?
+ */
+ p = (unsigned short *) video_mem_base;
+ saved = scr_readw(p);
+ scr_writew(0xAA55, p);
+ if (scr_readw(p) != 0xAA55) {
+ scr_writew(saved, p);
+ return 0;
+ }
+ scr_writew(0x55AA, p);
+ if (scr_readw(p) != 0x55AA) {
+ scr_writew(saved, p);
+ return 0;
+ }
+ scr_writew(saved, p);
+ return 1;
+}
+
__initfunc(unsigned long
con_type_init(unsigned long kmem_start, const char **display_desc))
{
@@ -219,32 +243,6 @@ con_type_init(unsigned long kmem_start, const char **display_desc))
}
else
#endif
-#ifdef CONFIG_DESKSTATION_RPC44
- /*
- * KLUDGE -- imp
- */
- if (mips_machgroup == MACH_GROUP_ARC
- && mips_machtype == MACH_DESKSTATION_RPC44)
- {
- /* XXX */
- can_do_color = 1;
- video_port_base = RPC44_PORT_BASE;
- video_port_reg = 0x3d4;
- video_port_val = 0x3d5;
- video_type = VIDEO_TYPE_VGAC;
- video_mem_base = 0xa00a000;
- video_mem_term = video_mem_base + 0x8000;
- *display_desc = "IMP-HACK";
- screen_info.orig_video_ega_bx = 0x11;
- screen_info.orig_video_mode = 8; /* not 7 */
- screen_info.orig_video_isVGA = 1;
- /*
- * Don't request a region - the video ports are outside of
- * the normal port address range.
- */
- }
- else
-#endif
if (ORIG_VIDEO_MODE == 7) /* Is this a monochrome display? */
{
video_mem_base = 0xb0000 + VGA_OFFSET;
diff --git a/drivers/char/videodev.c b/drivers/char/videodev.c
index 71e88f04c..38b9a6743 100644
--- a/drivers/char/videodev.c
+++ b/drivers/char/videodev.c
@@ -249,7 +249,7 @@ int videodev_init(void)
return 0;
}
-
+#ifdef MODULE
int init_module(void)
{
return videodev_init();
@@ -260,5 +260,7 @@ void cleanup_module(void)
unregister_chrdev(VIDEO_MAJOR, "video_capture");
}
+#endif
+
EXPORT_SYMBOL(video_register_device);
EXPORT_SYMBOL(video_unregister_device);
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 6ba0c687d..12924d2f5 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -730,7 +730,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
extern int spawnpid, spawnsig;
if (!perm)
return -EPERM;
- if (arg < 1 || arg > NSIG || arg == SIGKILL)
+ if (arg < 1 || arg > _NSIG || arg == SIGKILL)
return -EINVAL;
spawnpid = current->pid;
spawnsig = arg;
diff --git a/drivers/char/wdt.c b/drivers/char/wdt.c
index 37f444e29..36af5fdcc 100644
--- a/drivers/char/wdt.c
+++ b/drivers/char/wdt.c
@@ -53,7 +53,7 @@ static int wdt_is_open=0;
*/
static int io=0x240;
-static int irq=14;
+static int irq=11;
#define WD_TIMO (100*60) /* 1 minute */
@@ -171,6 +171,10 @@ static void wdt_ping(void)
static ssize_t wdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
{
+ /* Can't seek (pwrite) on this device */
+ if (ppos != &file->f_pos)
+ return -ESPIPE;
+
if(count)
{
wdt_ping();
@@ -189,6 +193,10 @@ static ssize_t wdt_read(struct file *file, char *buf, size_t count, loff_t *ptr)
unsigned char cp;
int err;
+ /* Can't seek (pread) on this device */
+ if (ptr != &file->f_pos)
+ return -ESPIPE;
+
switch(MINOR(file->f_dentry->d_inode->i_rdev))
{
case TEMP_MINOR:
diff --git a/drivers/isdn/avmb1/capi.c b/drivers/isdn/avmb1/capi.c
index aed5ca0f5..e02de0bdd 100644
--- a/drivers/isdn/avmb1/capi.c
+++ b/drivers/isdn/avmb1/capi.c
@@ -47,8 +47,7 @@
#include <linux/skbuff.h>
#include <linux/capi.h>
#include <linux/kernelcapi.h>
-
-#include <asm/poll.h>
+#include <linux/poll.h>
#include "compat.h"
#include "capiutil.h"
diff --git a/drivers/isdn/isdn_common.c b/drivers/isdn/isdn_common.c
index 5402c5b8d..1b2346496 100644
--- a/drivers/isdn/isdn_common.c
+++ b/drivers/isdn/isdn_common.c
@@ -201,7 +201,7 @@
#include <linux/module.h>
#include <linux/version.h>
#if (LINUX_VERSION_CODE >= 0x020117)
-#include <asm/poll.h>
+#include <linux/poll.h>
#endif
#include <linux/isdn.h>
#include "isdn_common.h"
diff --git a/drivers/isdn/isdn_ppp.c b/drivers/isdn/isdn_ppp.c
index f9eadc034..1cfcd07ab 100644
--- a/drivers/isdn/isdn_ppp.c
+++ b/drivers/isdn/isdn_ppp.c
@@ -129,7 +129,7 @@
#include <linux/version.h>
#include <linux/isdn.h>
#if (LINUX_VERSION_CODE >= 0x020117)
-#include <asm/poll.h>
+#include <linux/poll.h>
#endif
#include "isdn_common.h"
#include "isdn_ppp.h"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 795df5697..1137f6e80 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -30,6 +30,13 @@ ifeq ($(CONFIG_PARPORT),y)
M_OBJS += parport_pc.o
endif
endif
+ ifeq ($(CONFIG_PARPORT_AX),y)
+ LX_OBJS += parport_ax.o
+ else
+ ifeq ($(CONFIG_PARPORT_AX),m)
+ M_OBJS += parport_ax.o
+ endif
+ endif
LX_OBJS += parport_init.o
else
ifeq ($(CONFIG_PARPORT),m)
@@ -43,6 +50,9 @@ else
ifeq ($(CONFIG_PARPORT_PC),m)
MX_OBJS += parport_pc.o
endif
+ ifeq ($(CONFIG_PARPORT_AX),m)
+ MX_OBJS += parport_ax.o
+ endif
endif
include $(TOPDIR)/Rules.make
diff --git a/drivers/misc/parport_ieee1284.c b/drivers/misc/parport_ieee1284.c
index 6fad49911..23152fa41 100644
--- a/drivers/misc/parport_ieee1284.c
+++ b/drivers/misc/parport_ieee1284.c
@@ -1,4 +1,5 @@
-/* IEEE-1284 implementation for parport.
+/* $Id: parport_ieee1284.c,v 1.4 1997/12/15 10:37:47 ralf Exp $
+ * IEEE-1284 implementation for parport.
*
* Authors: Phil Blundell <Philip.Blundell@pobox.com>
* Carsten Gross <carsten@sol.wohnheim.uni-ulm.de>
@@ -6,83 +7,63 @@
*/
#include <linux/tasks.h>
-
#include <linux/parport.h>
#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
#include <linux/kernel.h>
-#include <linux/malloc.h>
-
-/* The following read functions are an implementation of a status readback
- * and device id request confirming to IEEE1284-1994.
- *
- * These probably ought to go in some seperate file, so people like the SPARC
- * don't have to pull them in.
- */
/* Wait for Status line(s) to change in 35 ms - see IEEE1284-1994 page 24 to
* 25 for this. After this time we can create a timeout because the
- * peripheral doesn't conform to IEEE1284. We want to save CPU time: we are
- * waiting a maximum time of 500 us busy (this is for speed). If there is
+ * peripheral doesn't conform to IEEE1284. We want to save CPU time: we are
+ * waiting a maximum time of 500 us busy (this is for speed). If there is
* not the right answer in this time, we call schedule and other processes
- * are able "to eat" the time up to 30ms. So the maximum load avarage can't
- * get above 5% for a read even if the peripheral is really slow. (but your
- * read gets very slow then - only about 10 characters per second. This
- * should be tuneable). Thanks to Andreas who pointed me to this and ordered
- * the documentation.
+ * are able to eat the time up to 40ms.
*/
int parport_wait_peripheral(struct parport *port, unsigned char mask,
unsigned char result)
{
- int counter=0;
+ int counter;
unsigned char status;
- do {
+ for (counter = 0; counter < 20; counter++) {
status = parport_read_status(port);
+ if ((status & mask) == result)
+ return 0;
udelay(25);
- counter++;
if (need_resched)
schedule();
- } while ( ((status & mask) != result) && (counter < 20) );
- if ( (counter == 20) && ((status & mask) != result) ) {
- current->state=TASK_INTERRUPTIBLE;
- current->timeout=jiffies+4;
- schedule(); /* wait for 4 scheduler runs (40ms) */
- status = parport_read_status(port);
- if ((status & mask) != result) return 1; /* timeout */
}
- return 0; /* okay right response from device */
+ current->state = TASK_INTERRUPTIBLE;
+ current->timeout = jiffies+4;
+ schedule(); /* wait for 40ms */
+ status = parport_read_status(port);
+ return ((status & mask) == result)?0:1;
}
-/* Test if nibble mode for status readback is okay. Returns the value false
- * if the printer doesn't support readback at all. If it supports readbacks
- * and printer data is available the function returns 1, otherwise 2. The
- * only valid values for "mode" are 0 and 4. 0 requests normal nibble mode,
- * 4 is for "request device id using nibble mode". The request for the
- * device id is best done in an ioctl (or at bootup time). There is no
- * check for an invalid value, the only function using this call at the
- * moment is lp_read and the ioctl LPGETDEVICEID both fixed calls from
- * trusted kernel.
+/* Test if the peripheral is IEEE 1284 compliant.
+ * return values are:
+ * 0 - handshake failed; peripheral is not compliant (or none present)
+ * 1 - handshake OK; IEEE1284 peripheral present but no data available
+ * 2 - handshake OK; IEEE1284 peripheral and data available
*/
int parport_ieee1284_nibble_mode_ok(struct parport *port, unsigned char mode)
{
parport_write_data(port, mode);
- udelay(5);
- parport_write_control(port, parport_read_control(port) & ~8); /* SelectIN low */
- parport_write_control(port, parport_read_control(port) | 2); /* AutoFeed high */
- if (parport_wait_peripheral(port, 0x78, 0x38)) { /* timeout? */
- parport_write_control(port, (parport_read_control(port) & ~2) | 8);
- return 0; /* first stage of negotiation failed,
- * no IEEE1284 compliant device on this port
- */
+ udelay(500);
+ /* nSelectIn high, nAutoFd low */
+ parport_write_control(port, (parport_read_control(port) & ~8) | 2);
+ if (parport_wait_peripheral(port, 0x78, 0x38)) {
+ parport_write_control(port,
+ (parport_read_control(port) & ~2) | 8);
+ return 0;
}
- parport_write_control(port, parport_read_control(port) | 1); /* Strobe high */
+ /* nStrobe low */
+ parport_write_control(port, parport_read_control(port) | 1);
udelay(5); /* Strobe wait */
- parport_write_control(port, parport_read_control(port) & ~1); /* Strobe low */
+ /* nStrobe high */
+ parport_write_control(port, parport_read_control(port) & ~1);
udelay(5);
- parport_write_control(port, parport_read_control(port) & ~2); /* AutoFeed low */
+ /* nAutoFd low */
+ parport_write_control(port, parport_read_control(port) & ~2);
return (parport_wait_peripheral(port, 0x20, 0))?2:1;
}
diff --git a/drivers/misc/parport_init.c b/drivers/misc/parport_init.c
index c6daf72cf..dbe4dd354 100644
--- a/drivers/misc/parport_init.c
+++ b/drivers/misc/parport_init.c
@@ -17,13 +17,15 @@
#include <linux/kernel.h>
#include <linux/malloc.h>
#include <linux/init.h>
+#include <linux/kerneld.h>
#ifndef MODULE
-static int io[PARPORT_MAX+1] __initdata = { 0, };
-static int irq[PARPORT_MAX] __initdata = { PARPORT_IRQ_NONE, };
-static int dma[PARPORT_MAX] __initdata = { PARPORT_DMA_NONE, };
+static int io[PARPORT_MAX+1] __initdata = { [0 ... PARPORT_MAX] = 0 };
+static int irq[PARPORT_MAX] __initdata = { [0 ... PARPORT_MAX-1] = PARPORT_IRQ_NONE };
+static int dma[PARPORT_MAX] __initdata = { [0 ... PARPORT_MAX-1] = PARPORT_DMA_NONE };
extern int parport_pc_init(int *io, int *irq, int *dma);
+extern int parport_ax_init(void);
static int parport_setup_ptr __initdata = 0;
@@ -68,11 +70,19 @@ __initfunc(int parport_init(void))
{
struct parport *pb;
- if (io[0] == PARPORT_DISABLE) return 1;
+ if (io[0] == PARPORT_DISABLE)
+ return 1;
+
+#ifdef CONFIG_PNP_PARPORT
+ parport_probe_hook = &parport_probe_one;
+#endif
parport_proc_init();
#ifdef CONFIG_PARPORT_PC
parport_pc_init(io, irq, dma);
#endif
+#ifdef CONFIG_PARPORT_AX
+ parport_ax_init();
+#endif
return 0;
}
#endif
@@ -91,6 +101,7 @@ EXPORT_SYMBOL(parport_ieee1284_nibble_mode_ok);
EXPORT_SYMBOL(parport_wait_peripheral);
EXPORT_SYMBOL(parport_proc_register);
EXPORT_SYMBOL(parport_proc_unregister);
+EXPORT_SYMBOL(parport_probe_hook);
void inc_parport_count(void)
{
diff --git a/drivers/misc/parport_pc.c b/drivers/misc/parport_pc.c
index c5a7a2a11..71eb184ac 100644
--- a/drivers/misc/parport_pc.c
+++ b/drivers/misc/parport_pc.c
@@ -141,7 +141,7 @@ static void pc_enable_irq(struct parport *p)
static void pc_release_resources(struct parport *p)
{
if (p->irq != PARPORT_IRQ_NONE)
- free_irq(p->irq, p);
+ free_irq(p->irq, NULL);
release_region(p->base, p->size);
if (p->modes & PARPORT_MODE_PCECR)
release_region(p->base+0x400, 3);
@@ -151,7 +151,7 @@ static int pc_claim_resources(struct parport *p)
{
/* FIXME check that resources are free */
if (p->irq != PARPORT_IRQ_NONE)
- request_irq(p->irq, pc_null_intr_func, 0, p->name, p);
+ request_irq(p->irq, pc_null_intr_func, 0, p->name, NULL);
request_region(p->base, p->size, p->name);
if (p->modes & PARPORT_MODE_PCECR)
request_region(p->base+0x400, 3, p->name);
@@ -837,7 +837,7 @@ static int probe_one_port(unsigned long int base, int irq, int dma)
}
p->size = (p->modes & (PARPORT_MODE_PCEPP
| PARPORT_MODE_PCECPEPP))?8:3;
- printk(KERN_INFO "%s: PC-style at 0x%x", p->name, p->base);
+ printk(KERN_INFO "%s: PC-style at 0x%lx", p->name, p->base);
if (p->irq == PARPORT_IRQ_AUTO) {
p->irq = PARPORT_IRQ_NONE;
parport_irq_probe(p);
@@ -868,6 +868,10 @@ static int probe_one_port(unsigned long int base, int irq, int dma)
/* Done probing. Now put the port into a sensible start-up state. */
pc_write_control(p, 0xc);
pc_write_data(p, 0);
+
+ if (parport_probe_hook)
+ (*parport_probe_hook)(p);
+
return 1;
}
diff --git a/drivers/misc/parport_procfs.c b/drivers/misc/parport_procfs.c
index f50754829..e75fba335 100644
--- a/drivers/misc/parport_procfs.c
+++ b/drivers/misc/parport_procfs.c
@@ -125,7 +125,7 @@ static int hardware_read_proc(char *page, char **start, off_t off,
struct parport *pp = (struct parport *)data;
int len=0;
- len += sprintf(page+len, "base:\t0x%x\n",pp->base);
+ len += sprintf(page+len, "base:\t0x%lx\n",pp->base);
if (pp->irq == PARPORT_IRQ_NONE)
len += sprintf(page+len, "irq:\tnone\n");
else
diff --git a/drivers/misc/parport_share.c b/drivers/misc/parport_share.c
index 6d518d284..2a8931957 100644
--- a/drivers/misc/parport_share.c
+++ b/drivers/misc/parport_share.c
@@ -1,4 +1,5 @@
-/* Parallel-port resource manager code.
+/* $Id: parport_share.c,v 1.7 1997/12/15 11:12:05 ralf Exp $
+ * Parallel-port resource manager code.
*
* Authors: David Campbell <campbell@tirian.che.curtin.edu.au>
* Tim Waugh <tim@cyberelk.demon.co.uk>
@@ -29,6 +30,8 @@
static struct parport *portlist = NULL, *portlist_tail = NULL;
static int portcount = 0;
+void (*parport_probe_hook)(struct parport *port) = NULL;
+
/* Return a list of all the ports we know about. */
struct parport *parport_enumerate(void)
{
@@ -275,11 +278,11 @@ int parport_claim(struct pardevice *dev)
dev->port->cad = dev;
/* Swap the IRQ handlers. */
- if (dev->port->irq >= 0) {
- free_irq(dev->port->irq, dev->port);
+ if (dev->port->irq != PARPORT_IRQ_NONE) {
+ free_irq(dev->port->irq, pd1?pd1->private:NULL);
request_irq(dev->port->irq, dev->irq_func ? dev->irq_func :
parport_null_intr_func, SA_INTERRUPT, dev->name,
- dev->port);
+ dev->private);
}
/* Restore control registers */
@@ -303,10 +306,10 @@ void parport_release(struct pardevice *dev)
dev->port->ops->save_state(dev->port, dev->state);
/* Point IRQs somewhere harmless. */
- if (dev->port->irq >= 0) {
- free_irq(dev->port->irq, dev->port);
+ if (dev->port->irq != PARPORT_IRQ_NONE) {
+ free_irq(dev->port->irq, dev->private);
request_irq(dev->port->irq, parport_null_intr_func,
- SA_INTERRUPT, dev->port->name, dev->port);
+ SA_INTERRUPT, dev->port->name, NULL);
}
/* Walk the list, offering a wakeup callback to everybody other
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index 56541f0c2..c2fa5b507 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -38,6 +38,8 @@ static char *version = "3c59x.c:v0.25 5/17/96 becker@cesdis.gsfc.nasa.gov\n";
#include <linux/interrupt.h>
#include <linux/init.h>
+#include <linux/delay.h>
+
#ifdef CONFIG_PCI
#include <linux/pci.h>
#include <linux/bios32.h>
@@ -498,7 +500,7 @@ __initfunc(static int vortex_probe1(struct device *dev))
outw(EEPROM_Read + PhysAddr01 + i, ioaddr + Wn0EepromCmd);
/* Pause for at least 162 us. for the read to take place. */
for (timer = 162*4 + 400; timer >= 0; timer--) {
- SLOW_DOWN_IO;
+ udelay(1);
if ((inw(ioaddr + Wn0EepromCmd) & 0x8000) == 0)
break;
}
diff --git a/drivers/net/Config.in b/drivers/net/Config.in
index 55f010e93..603657a85 100644
--- a/drivers/net/Config.in
+++ b/drivers/net/Config.in
@@ -141,51 +141,15 @@ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
fi
fi
-#if [ ! "$CONFIG_PARPORT" = "n" ]; then
-# dep_tristate 'PLIP (parallel port) support' CONFIG_PLIP $CONFIG_PARPORT
-#fi
+if [ ! "$CONFIG_PARPORT" = "n" ]; then
+ dep_tristate 'PLIP (parallel port) support' CONFIG_PLIP $CONFIG_PARPORT
+fi
tristate 'PPP (point-to-point) support' CONFIG_PPP
if [ ! "$CONFIG_PPP" = "n" ]; then
comment 'CCP compressors for PPP are only built as modules.'
fi
-bool 'Radio network interfaces' CONFIG_NET_RADIO
-if [ "$CONFIG_NET_RADIO" != "n" ]; then
- if [ "$CONFIG_AX25" != "n" ]; then
- tristate 'Serial port KISS driver for AX.25' CONFIG_MKISS
- tristate 'BPQ Ethernet driver for AX.25' CONFIG_BPQETHER
- tristate 'Gracilis PackeTwin driver for AX.25' CONFIG_PT
- tristate 'Ottawa PI and PI2 driver for AX.25' CONFIG_PI
- tristate 'Z8530 SCC driver for AX.25' CONFIG_SCC
- fi
- if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
- tristate 'BAYCOM ser12 and par96 driver for AX.25' CONFIG_BAYCOM
- tristate 'Soundcard modem driver for AX.25' CONFIG_SOUNDMODEM
- if [ "$CONFIG_SOUNDMODEM" != "n" ]; then
- bool 'Soundmodem support for Soundblaster and compatible cards' CONFIG_SOUNDMODEM_SBC
- bool 'Soundmodem support for WSS and Crystal cards' CONFIG_SOUNDMODEM_WSS
- bool 'Soundmodem support for 1200 baud AFSK modulation' CONFIG_SOUNDMODEM_AFSK1200
- bool 'Soundmodem support for 2400 baud AFSK modulation (7.3728MHz crystal)' CONFIG_SOUNDMODEM_AFSK2400_7
- bool 'Soundmodem support for 2400 baud AFSK modulation (8MHz crystal)' CONFIG_SOUNDMODEM_AFSK2400_8
- bool 'Soundmodem support for 4800 baud HAPN-1 modulation' CONFIG_SOUNDMODEM_HAPN4800
- bool 'Soundmodem support for 9600 baud FSK G3RUH modulation' CONFIG_SOUNDMODEM_FSK9600
- fi
- tristate 'Shortwave radio modem driver' CONFIG_HFMODEM
- if [ "$CONFIG_HFMODEM" != "n" ]; then
- bool 'HFmodem support for Soundblaster and compatible cards' CONFIG_HFMODEM_SBC
- bool 'HFmodem support for WSS and Crystal cards' CONFIG_HFMODEM_WSS
- fi
- tristate 'Shortwave radio modem driver' CONFIG_HFMODEM
- if [ "$CONFIG_HFMODEM" != "n" ]; then
- bool 'HFmodem support for Soundblaster and compatible cards' CONFIG_HFMODEM_SBC
- bool 'HFmodem support for WSS and Crystal cards' CONFIG_HFMODEM_WSS
- fi
- fi
-# tristate 'STRIP (Metricom starmode radio IP)' CONFIG_STRIP
- tristate 'AT&T WaveLAN & DEC RoamAbout DS support' CONFIG_WAVELAN
-fi
-
tristate 'SLIP (serial line) support' CONFIG_SLIP
if [ "$CONFIG_SLIP" != "n" ]; then
bool ' CSLIP compressed headers' CONFIG_SLIP_COMPRESSED
@@ -193,6 +157,9 @@ if [ "$CONFIG_SLIP" != "n" ]; then
bool ' Six bit SLIP encapsulation' CONFIG_SLIP_MODE_SLIP6
fi
+tristate 'STRIP (Metricom starmode radio IP)' CONFIG_STRIP
+tristate 'AT&T WaveLAN & DEC RoamAbout DS support' CONFIG_WAVELAN
+
bool 'Token Ring driver support' CONFIG_TR
if [ "$CONFIG_TR" = "y" ]; then
tristate 'IBM Tropic chipset based adaptor support' CONFIG_IBMTR
@@ -214,6 +181,7 @@ if [ "$CONFIG_WAN_ROUTER" != "n" ]; then
bool ' WANPIPE Frame Relay support' CONFIG_WANPIPE_FR
bool ' WANPIPE PPP support' CONFIG_WANPIPE_PPP
fi
+ dep_tristate 'High-speed (DMA) SCC driver for AX.25' CONFIG_DMASCC $CONFIG_AX25
fi
fi
#
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index a79d7b4ea..dfdc5327f 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -9,30 +9,32 @@ include CONFIG
SUB_DIRS :=
MOD_SUB_DIRS := $(SUB_DIRS)
-ALL_SUB_DIRS := $(SUB_DIRS)
+ALL_SUB_DIRS := $(SUB_DIRS) hamradio
L_TARGET := net.a
L_OBJS := auto_irq.o
M_OBJS :=
MOD_LIST_NAME := NET_MODULES
-# Need these to keep track of whether the 8390 and SLHC modules should
+# Need these to keep track of whether the 8390, PPP and SLHC modules should
# really go in the kernel or a module.
CONFIG_8390_BUILTIN :=
CONFIG_8390_MODULE :=
CONFIG_SLHC_BUILTIN :=
CONFIG_SLHC_MODULE :=
-CONFIG_HDLCDRV_BUILTIN :=
-CONFIG_HDLCDRV_MODULE :=
+CONFIG_PPPDEF_BUILTIN :=
+CONFIG_PPPDEF_MODULE :=
ifeq ($(CONFIG_ISDN),y)
ifeq ($(CONFIG_ISDN_PPP),y)
CONFIG_SLHC_BUILTIN = y
+ CONFIG_PPPDEF_BUILTIN = y
endif
else
ifeq ($(CONFIG_ISDN),m)
ifeq ($(CONFIG_ISDN_PPP),y)
CONFIG_SLHC_MODULE = y
+ CONFIG_PPPDEF_BUILTIN = y
endif
endif
endif
@@ -73,13 +75,6 @@ ifeq ($(CONFIG_SK_G16),y)
L_OBJS += sk_g16.o
endif
-ifeq ($(CONFIG_NET_IPIP),y)
-L_OBJS += tunnel.o
-else
- ifeq ($(CONFIG_NET_IPIP),m)
- M_OBJS += tunnel.o
- endif
-endif
ifeq ($(CONFIG_HP100),y)
L_OBJS += hp100.o
@@ -193,9 +188,11 @@ endif
ifeq ($(CONFIG_PPP),y)
LX_OBJS += ppp.o
CONFIG_SLHC_BUILTIN = y
+CONFIG_PPPDEF_BUILTIN = y
else
ifeq ($(CONFIG_PPP),m)
CONFIG_SLHC_MODULE = y
+ CONFIG_PPPDEF_MODULE = y
MX_OBJS += ppp.o
endif
endif
@@ -208,11 +205,13 @@ ifeq ($(CONFIG_SLIP),y)
L_OBJS += slip.o
ifeq ($(CONFIG_SLIP_COMPRESSED),y)
CONFIG_SLHC_BUILTIN = y
+ CONFIG_PPPDEF_BUILTIN = y
endif
else
ifeq ($(CONFIG_SLIP),m)
ifeq ($(CONFIG_SLIP_COMPRESSED),y)
CONFIG_SLHC_MODULE = y
+ CONFIG_PPPDEF_MODULE = y
endif
M_OBJS += slip.o
endif
@@ -545,46 +544,6 @@ else
endif
endif
-ifeq ($(CONFIG_SCC),y)
-L_OBJS += scc.o
-else
- ifeq ($(CONFIG_SCC),m)
- M_OBJS += scc.o
- endif
-endif
-
-ifeq ($(CONFIG_MKISS),y)
-L_OBJS += mkiss.o
-else
- ifeq ($(CONFIG_MKISS),m)
- M_OBJS += mkiss.o
- endif
-endif
-
-ifeq ($(CONFIG_PI),y)
-L_OBJS += pi2.o
-else
- ifeq ($(CONFIG_PI),m)
- M_OBJS += pi2.o
- endif
-endif
-
-ifeq ($(CONFIG_PT),y)
-L_OBJS += pt.o
-else
- ifeq ($(CONFIG_PT),m)
- M_OBJS += pt.o
- endif
-endif
-
-ifeq ($(CONFIG_BPQETHER),y)
-L_OBJS += bpqether.o
-else
- ifeq ($(CONFIG_BPQETHER),m)
- M_OBJS += bpqether.o
- endif
-endif
-
ifeq ($(CONFIG_LAPBETHER),y)
L_OBJS += lapbether.o
else
@@ -603,6 +562,15 @@ else
endif
endif
+# if anything built-in uses ppp_deflate, then build it into the kernel also.
+# If not, but a module uses it, build as a module:
+ifdef CONFIG_PPPDEF_BUILTIN
+LX_OBJS += ppp_deflate.o
+else
+ ifdef CONFIG_PPPDEF_MODULE
+ MX_OBJS += ppp_deflate.o
+ endif
+endif
# If anything built-in uses the 8390, then build it into the kernel also.
# If not, but a module uses it, build as a module.
@@ -735,43 +703,10 @@ else
endif
endif
-ifeq ($(CONFIG_BAYCOM),y)
-L_OBJS += baycom.o
-CONFIG_HDLCDRV_BUILTIN = y
-else
- ifeq ($(CONFIG_BAYCOM),m)
- CONFIG_HDLCDRV_MODULE = y
- M_OBJS += baycom.o
- endif
-endif
-
-ifeq ($(CONFIG_SOUNDMODEM),y)
-ALL_SUB_DIRS += soundmodem
-SUB_DIRS += soundmodem
-L_OBJS += soundmodem/soundmodem.o
-CONFIG_HDLCDRV_BUILTIN = y
-else
- ifeq ($(CONFIG_SOUNDMODEM),m)
- CONFIG_HDLCDRV_MODULE = y
- ALL_SUB_DIRS += soundmodem
- MOD_SUB_DIRS += soundmodem
- endif
-endif
-
ifeq ($(CONFIG_MACE),y)
L_OBJS += mace.o
endif
-# If anything built-in uses the hdlcdrv, then build it into the kernel also.
-# If not, but a module uses it, build as a module.
-ifdef CONFIG_HDLCDRV_BUILTIN
-LX_OBJS += hdlcdrv.o
-else
- ifdef CONFIG_HDLCDRV_MODULE
- MX_OBJS += hdlcdrv.o
- endif
-endif
-
ifeq ($(CONFIG_VENDOR_SANGOMA),y)
M_OBJS += sdladrv.o
M_OBJS += wanpipe.o
@@ -806,9 +741,6 @@ wd.o: wd.c CONFIG
3c503.o: 3c503.c CONFIG
$(CC) $(CPPFLAGS) $(CFLAGS) $(EL2_OPTS) -c $<
-pi2.o: pi2.c CONFIG
- $(CC) $(CPPFLAGS) $(CFLAGS) $(PI_OPTS) -c $<
-
3c505.o: 3c505.c CONFIG
$(CC) $(CPPFLAGS) $(CFLAGS) $(ELP_OPTS) -c $<
diff --git a/drivers/net/Space.c b/drivers/net/Space.c
index eedc48f98..81fbe3e46 100644
--- a/drivers/net/Space.c
+++ b/drivers/net/Space.c
@@ -31,6 +31,7 @@
#include <linux/netdevice.h>
#include <linux/errno.h>
#include <linux/init.h>
+#include <linux/netlink.h>
#define NEXT_DEV NULL
diff --git a/drivers/net/at1700.c b/drivers/net/at1700.c
index cbe2d968a..19b0dc7ed 100644
--- a/drivers/net/at1700.c
+++ b/drivers/net/at1700.c
@@ -102,7 +102,7 @@ struct net_local {
#define EE_DATA_READ 0x80 /* EEPROM chip data out, in reg. 17. */
/* Delay between EEPROM clock transitions. */
-#define eeprom_delay() do { int _i = 40; while (--_i > 0) { __SLOW_DOWN_IO; }} while (0)
+#define eeprom_delay() do { int _i = 40; while (--_i > 0) { inb(0x80); }} while (0)
/* The EEPROM commands include the alway-set leading bit. */
#define EE_WRITE_CMD (5 << 6)
diff --git a/drivers/net/baycom.c b/drivers/net/baycom.c
index ef99046dc..e69de29bb 100644
--- a/drivers/net/baycom.c
+++ b/drivers/net/baycom.c
@@ -1,1280 +0,0 @@
-/*****************************************************************************/
-
-/*
- * baycom.c -- baycom ser12 and par96 radio modem driver.
- *
- * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Please note that the GPL allows you to use the driver, NOT the radio.
- * In order to use the radio, you need a license from the communications
- * authority of your country.
- *
- *
- * Supported modems
- *
- * ser12: This is a very simple 1200 baud AFSK modem. The modem consists only
- * of a modulator/demodulator chip, usually a TI TCM3105. The computer
- * is responsible for regenerating the receiver bit clock, as well as
- * for handling the HDLC protocol. The modem connects to a serial port,
- * hence the name. Since the serial port is not used as an async serial
- * port, the kernel driver for serial ports cannot be used, and this
- * driver only supports standard serial hardware (8250, 16450, 16550)
- *
- * par96: This is a modem for 9600 baud FSK compatible to the G3RUH standard.
- * The modem does all the filtering and regenerates the receiver clock.
- * Data is transferred from and to the PC via a shift register.
- * The shift register is filled with 16 bits and an interrupt is
- * signalled. The PC then empties the shift register in a burst. This
- * modem connects to the parallel port, hence the name. The modem
- * leaves the implementation of the HDLC protocol and the scrambler
- * polynomial to the PC. This modem is no longer available (at least
- * from Baycom) and has been replaced by the PICPAR modem (see below).
- * You may however still build one from the schematics published in
- * cq-DL :-).
- *
- * picpar: This is a redesign of the par96 modem by Henning Rech, DF9IC. The
- * modem is protocol compatible to par96, but uses only three low
- * power ICs and can therefore be fed from the parallel port and
- * does not require an additional power supply. It features
- * built in DCD circuitry. The driver should therefore be configured
- * for hardware DCD.
- *
- *
- * Command line options (insmod command line)
- *
- * mode driver mode string. Valid choices are ser12 and par96. An
- * optional * enables software DCD.
- * 2=par96/par97, any other value invalid
- * iobase base address of the port; common values are for ser12 0x3f8,
- * 0x2f8, 0x3e8, 0x2e8 and for par96/par97 0x378, 0x278, 0x3bc
- * irq interrupt line of the port; common values are for ser12 3,4
- * and for par96/par97 7
- *
- *
- * History:
- * 0.1 26.06.96 Adapted from baycom.c and made network driver interface
- * 18.10.96 Changed to new user space access routines (copy_{to,from}_user)
- * 0.3 26.04.97 init code/data tagged
- * 0.4 08.07.97 alternative ser12 decoding algorithm (uses delta CTS ints)
- */
-
-/*****************************************************************************/
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/string.h>
-#include <asm/system.h>
-#include <asm/bitops.h>
-#include <asm/io.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/netdevice.h>
-#include <linux/hdlcdrv.h>
-#include <linux/baycom.h>
-
-/* --------------------------------------------------------------------- */
-
-/*
- * currently this module is supposed to support both module styles, i.e.
- * the old one present up to about 2.1.9, and the new one functioning
- * starting with 2.1.21. The reason is I have a kit allowing to compile
- * this module also under 2.0.x which was requested by several people.
- * This will go in 2.2
- */
-#include <linux/version.h>
-
-#if LINUX_VERSION_CODE >= 0x20100
-#include <asm/uaccess.h>
-#else
-#include <asm/segment.h>
-#include <linux/mm.h>
-
-#undef put_user
-#undef get_user
-
-#define put_user(x,ptr) ({ __put_user((unsigned long)(x),(ptr),sizeof(*(ptr))); 0; })
-#define get_user(x,ptr) ({ x = ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr)))); 0; })
-
-extern inline int copy_from_user(void *to, const void *from, unsigned long n)
-{
- int i = verify_area(VERIFY_READ, from, n);
- if (i)
- return i;
- memcpy_fromfs(to, from, n);
- return 0;
-}
-
-extern inline int copy_to_user(void *to, const void *from, unsigned long n)
-{
- int i = verify_area(VERIFY_WRITE, to, n);
- if (i)
- return i;
- memcpy_tofs(to, from, n);
- return 0;
-}
-#endif
-
-#if LINUX_VERSION_CODE >= 0x20123
-#include <linux/init.h>
-#else
-#define __init
-#define __initdata
-#define __initfunc(x) x
-#endif
-
-/* --------------------------------------------------------------------- */
-
-#define BAYCOM_DEBUG
-
-/*
- * modem options; bit mask
- */
-#define BAYCOM_OPTIONS_SOFTDCD 1
-#define BAYCOM_ALT_SER12
-
-/* --------------------------------------------------------------------- */
-
-static const char bc_drvname[] = "baycom";
-static const char bc_drvinfo[] = KERN_INFO "baycom: (C) 1996 Thomas Sailer, HB9JNX/AE4WA\n"
-KERN_INFO "baycom: version 0.4 compiled " __TIME__ " " __DATE__ "\n";
-
-/* --------------------------------------------------------------------- */
-
-#define NR_PORTS 4
-
-static struct device baycom_device[NR_PORTS];
-
-static struct {
- char *mode;
- int iobase, irq;
-} baycom_ports[NR_PORTS] = { { NULL, 0, 0 }, };
-
-/* --------------------------------------------------------------------- */
-
-#define RBR(iobase) (iobase+0)
-#define THR(iobase) (iobase+0)
-#define IER(iobase) (iobase+1)
-#define IIR(iobase) (iobase+2)
-#define FCR(iobase) (iobase+2)
-#define LCR(iobase) (iobase+3)
-#define MCR(iobase) (iobase+4)
-#define LSR(iobase) (iobase+5)
-#define MSR(iobase) (iobase+6)
-#define SCR(iobase) (iobase+7)
-#define DLL(iobase) (iobase+0)
-#define DLM(iobase) (iobase+1)
-
-#define SER12_EXTENT 8
-
-#define LPT_DATA(iobase) (iobase+0)
-#define LPT_STATUS(iobase) (iobase+1)
-#define LPT_CONTROL(iobase) (iobase+2)
-#define LPT_IRQ_ENABLE 0x10
-#define PAR96_BURSTBITS 16
-#define PAR96_BURST 4
-#define PAR96_PTT 2
-#define PAR96_TXBIT 1
-#define PAR96_ACK 0x40
-#define PAR96_RXBIT 0x20
-#define PAR96_DCD 0x10
-#define PAR97_POWER 0xf8
-
-#define PAR96_EXTENT 3
-
-/* ---------------------------------------------------------------------- */
-/*
- * Information that need to be kept for each board.
- */
-
-struct baycom_state {
- struct hdlcdrv_state hdrv;
-
- unsigned int options;
-
- struct modem_state {
- short arb_divider;
- unsigned char flags;
- unsigned int shreg;
- struct modem_state_ser12 {
- unsigned char tx_bit;
- int dcd_sum0, dcd_sum1, dcd_sum2;
- unsigned char last_sample;
- unsigned char last_rxbit;
- unsigned int dcd_shreg;
- unsigned int dcd_time;
- unsigned int bit_pll;
-#ifdef BAYCOM_ALT_SER12
- unsigned long last_jiffies;
- unsigned int pll_time;
- unsigned int txshreg;
-#else /* BAYCOM_ALT_SER12 */
- unsigned char interm_sample;
-#endif /* BAYCOM_ALT_SER12 */
- } ser12;
- struct modem_state_par96 {
- int dcd_count;
- unsigned int dcd_shreg;
- unsigned long descram;
- unsigned long scram;
- } par96;
- } modem;
-
-#ifdef BAYCOM_DEBUG
- struct debug_vals {
- unsigned long last_jiffies;
- unsigned cur_intcnt;
- unsigned last_intcnt;
- int cur_pllcorr;
- int last_pllcorr;
- } debug_vals;
-#endif /* BAYCOM_DEBUG */
-};
-
-/* --------------------------------------------------------------------- */
-
-#define min(a, b) (((a) < (b)) ? (a) : (b))
-#define max(a, b) (((a) > (b)) ? (a) : (b))
-
-/* --------------------------------------------------------------------- */
-
-static void inline baycom_int_freq(struct baycom_state *bc)
-{
-#ifdef BAYCOM_DEBUG
- unsigned long cur_jiffies = jiffies;
- /*
- * measure the interrupt frequency
- */
- bc->debug_vals.cur_intcnt++;
- if ((cur_jiffies - bc->debug_vals.last_jiffies) >= HZ) {
- bc->debug_vals.last_jiffies = cur_jiffies;
- bc->debug_vals.last_intcnt = bc->debug_vals.cur_intcnt;
- bc->debug_vals.cur_intcnt = 0;
- bc->debug_vals.last_pllcorr = bc->debug_vals.cur_pllcorr;
- bc->debug_vals.cur_pllcorr = 0;
- }
-#endif /* BAYCOM_DEBUG */
-}
-
-/* --------------------------------------------------------------------- */
-/*
- * ===================== SER12 specific routines =========================
- */
-
-#ifdef BAYCOM_ALT_SER12
-
-#define SER12_BAUD 1200
-
-/* --------------------------------------------------------------------- */
-
-extern inline unsigned int hweight16(unsigned short w)
- __attribute__ ((unused));
-extern inline unsigned int hweight8(unsigned char w)
- __attribute__ ((unused));
-
-extern inline unsigned int hweight16(unsigned short w)
-{
- unsigned short res = (w & 0x5555) + ((w >> 1) & 0x5555);
- res = (res & 0x3333) + ((res >> 2) & 0x3333);
- res = (res & 0x0F0F) + ((res >> 4) & 0x0F0F);
- return (res & 0x00FF) + ((res >> 8) & 0x00FF);
-}
-
-extern inline unsigned int hweight8(unsigned char w)
-{
- unsigned short res = (w & 0x55) + ((w >> 1) & 0x55);
- res = (res & 0x33) + ((res >> 2) & 0x33);
- return (res & 0x0F) + ((res >> 4) & 0x0F);
-}
-
-/* --------------------------------------------------------------------- */
-
-static __inline__ void ser12_rxsample(struct device *dev, struct baycom_state *bc, unsigned char news)
-{
- bc->modem.ser12.dcd_shreg <<= 1;
- bc->modem.ser12.bit_pll += 0x2000;
- if (bc->modem.ser12.last_sample != news) {
- bc->modem.ser12.last_sample = news;
- bc->modem.ser12.dcd_shreg |= 1;
- if (bc->modem.ser12.bit_pll < 0x9000)
- bc->modem.ser12.bit_pll += 0x1000;
- else
- bc->modem.ser12.bit_pll -= 0x1000;
- bc->modem.ser12.dcd_sum0 += 4 * hweight8(bc->modem.ser12.dcd_shreg & 0x38)
- - hweight16(bc->modem.ser12.dcd_shreg & 0x7c0);
- }
- hdlcdrv_channelbit(&bc->hdrv, !!bc->modem.ser12.last_sample);
- if ((--bc->modem.ser12.dcd_time) <= 0) {
- hdlcdrv_setdcd(&bc->hdrv, (bc->modem.ser12.dcd_sum0 +
- bc->modem.ser12.dcd_sum1 +
- bc->modem.ser12.dcd_sum2) < 0);
- bc->modem.ser12.dcd_sum2 = bc->modem.ser12.dcd_sum1;
- bc->modem.ser12.dcd_sum1 = bc->modem.ser12.dcd_sum0;
- bc->modem.ser12.dcd_sum0 = 2; /* slight bias */
- bc->modem.ser12.dcd_time = 120;
- }
- if (bc->modem.ser12.bit_pll >= 0x10000) {
- bc->modem.ser12.bit_pll &= 0xffff;
- bc->modem.shreg >>= 1;
- if (bc->modem.ser12.last_rxbit == bc->modem.ser12.last_sample)
- bc->modem.shreg |= 0x10000;
- bc->modem.ser12.last_rxbit = bc->modem.ser12.last_sample;
- if (bc->modem.shreg & 1) {
- hdlcdrv_putbits(&bc->hdrv, bc->modem.shreg >> 1);
- bc->modem.shreg = 0x10000;
- }
- }
-}
-
-/* --------------------------------------------------------------------- */
-
-static __inline__ void ser12_rx(struct device *dev, struct baycom_state *bc, unsigned char curs)
-{
- unsigned long curjiff;
- struct timeval tv;
- unsigned int timediff;
-
- /*
- * get current time
- */
- curjiff = jiffies;
- do_gettimeofday(&tv);
- if ((signed)(curjiff - bc->modem.ser12.last_jiffies) >= HZ/4) {
- /* long inactivity; clear HDLC and DCD */
- bc->modem.ser12.dcd_sum1 = 0;
- bc->modem.ser12.dcd_sum2 = 0;
- bc->modem.ser12.dcd_sum0 = 2;
- bc->modem.ser12.dcd_time = 120;
- hdlcdrv_setdcd(&bc->hdrv, 0);
- hdlcdrv_putbits(&bc->hdrv, 0xffff);
- bc->modem.ser12.last_jiffies = curjiff;
- bc->modem.ser12.pll_time = tv.tv_usec;
- }
- bc->modem.ser12.last_jiffies = curjiff;
- timediff = tv.tv_usec + 1000000 - bc->modem.ser12.pll_time;
- timediff %= 1000000;
- timediff /= 125000/SER12_BAUD;
- bc->modem.ser12.pll_time = (bc->modem.ser12.pll_time + timediff * (125000/SER12_BAUD)) % 1000000;
- for (; timediff > 1; timediff--)
- ser12_rxsample(dev, bc, bc->modem.ser12.last_sample);
- if (timediff >= 1)
- ser12_rxsample(dev, bc, curs);
-}
-
-/* --------------------------------------------------------------------- */
-
-static void ser12_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- struct device *dev = (struct device *)dev_id;
- struct baycom_state *bc = (struct baycom_state *)dev->priv;
- unsigned char iir, msr = 0;
- unsigned int txcount = 0;
- unsigned int rxcount = 0;
-
- if (!dev || !bc || bc->hdrv.magic != HDLCDRV_MAGIC)
- return;
-
- for (;;) {
- iir = inb(IIR(dev->base_addr));
- if (iir & 1)
- break;
- switch (iir & 6) {
- case 6:
- inb(LSR(dev->base_addr));
- continue;
-
- case 4:
- inb(RBR(dev->base_addr));
- continue;
-
- case 2:
- /*
- * make sure the next interrupt is generated;
- * 0 must be used to power the modem; the modem draws its
- * power from the TxD line
- */
- outb(0x00, THR(dev->base_addr));
- bc->modem.arb_divider--;
- baycom_int_freq(bc);
- if (hdlcdrv_ptt(&bc->hdrv)) {
- /*
- * first output the last bit (!) then call HDLC transmitter,
- * since this may take quite long
- */
- outb(0x0e | (!!bc->modem.ser12.tx_bit), MCR(dev->base_addr));
- txcount++;
- } else
- outb(0x0d, MCR(dev->base_addr)); /* transmitter off */
- continue;
-
- default:
- msr = inb(MSR(dev->base_addr));
- if (msr & 1) /* delta CTS interrupt */
- rxcount++;
- continue;
- }
- }
- if (rxcount)
- ser12_rx(dev, bc, msr & 0x10);
- if (txcount) {
-#ifdef BAYCOM_DEBUG
- if (bc->debug_vals.cur_pllcorr < txcount)
- bc->debug_vals.cur_pllcorr = txcount;
-#endif /* BAYCOM_DEBUG */
- if (bc->modem.ser12.txshreg <= 1)
- bc->modem.ser12.txshreg = 0x10000 | hdlcdrv_getbits(&bc->hdrv);
- bc->modem.ser12.tx_bit = !(bc->modem.ser12.tx_bit ^ (bc->modem.ser12.txshreg & 1));
- bc->modem.ser12.txshreg >>= 1;
- }
- sti();
- if (bc->modem.arb_divider <= 0) {
- bc->modem.arb_divider = SER12_BAUD/100;
- hdlcdrv_arbitrate(dev, &bc->hdrv);
- }
- hdlcdrv_transmitter(dev, &bc->hdrv);
- hdlcdrv_receiver(dev, &bc->hdrv);
-}
-
-/* --------------------------------------------------------------------- */
-#else /* BAYCOM_ALT_SER12 */
-
-static void inline ser12_set_divisor(struct device *dev,
- unsigned char divisor)
-{
- outb(0x81, LCR(dev->base_addr)); /* DLAB = 1 */
- outb(divisor, DLL(dev->base_addr));
- outb(0, DLM(dev->base_addr));
- outb(0x01, LCR(dev->base_addr)); /* word length = 6 */
- /*
- * make sure the next interrupt is generated;
- * 0 must be used to power the modem; the modem draws its
- * power from the TxD line
- */
- outb(0x00, THR(dev->base_addr));
- /*
- * it is important not to set the divider while transmitting;
- * this reportedly makes some UARTs generating interrupts
- * in the hundredthousands per second region
- * Reported by: Ignacio.Arenaza@studi.epfl.ch (Ignacio Arenaza Nuno)
- */
-}
-
-/* --------------------------------------------------------------------- */
-
-/*
- * must call the TX arbitrator every 10ms
- */
-#define SER12_ARB_DIVIDER(bc) ((bc->options & BAYCOM_OPTIONS_SOFTDCD) ? \
- 36 : 24)
-#define SER12_DCD_INTERVAL(bc) ((bc->options & BAYCOM_OPTIONS_SOFTDCD) ? \
- 240 : 12)
-
-static inline void ser12_tx(struct device *dev, struct baycom_state *bc)
-{
- /* one interrupt per channel bit */
- ser12_set_divisor(dev, 12);
- /*
- * first output the last bit (!) then call HDLC transmitter,
- * since this may take quite long
- */
- outb(0x0e | (!!bc->modem.ser12.tx_bit), MCR(dev->base_addr));
- if (bc->modem.shreg <= 1)
- bc->modem.shreg = 0x10000 | hdlcdrv_getbits(&bc->hdrv);
- bc->modem.ser12.tx_bit = !(bc->modem.ser12.tx_bit ^
- (bc->modem.shreg & 1));
- bc->modem.shreg >>= 1;
-}
-
-/* --------------------------------------------------------------------- */
-
-static inline void ser12_rx(struct device *dev, struct baycom_state *bc)
-{
- unsigned char cur_s;
- /*
- * do demodulator
- */
- cur_s = inb(MSR(dev->base_addr)) & 0x10; /* the CTS line */
- hdlcdrv_channelbit(&bc->hdrv, cur_s);
- bc->modem.ser12.dcd_shreg = (bc->modem.ser12.dcd_shreg << 1) |
- (cur_s != bc->modem.ser12.last_sample);
- bc->modem.ser12.last_sample = cur_s;
- if(bc->modem.ser12.dcd_shreg & 1) {
- if (bc->options & BAYCOM_OPTIONS_SOFTDCD) {
- unsigned int dcdspos, dcdsneg;
-
- dcdspos = dcdsneg = 0;
- dcdspos += ((bc->modem.ser12.dcd_shreg >> 1) & 1);
- if (!(bc->modem.ser12.dcd_shreg & 0x7ffffffe))
- dcdspos += 2;
- dcdsneg += ((bc->modem.ser12.dcd_shreg >> 2) & 1);
- dcdsneg += ((bc->modem.ser12.dcd_shreg >> 3) & 1);
- dcdsneg += ((bc->modem.ser12.dcd_shreg >> 4) & 1);
-
- bc->modem.ser12.dcd_sum0 += 16*dcdspos - dcdsneg;
- } else
- bc->modem.ser12.dcd_sum0--;
- }
- if(!bc->modem.ser12.dcd_time) {
- hdlcdrv_setdcd(&bc->hdrv, (bc->modem.ser12.dcd_sum0 +
- bc->modem.ser12.dcd_sum1 +
- bc->modem.ser12.dcd_sum2) < 0);
- bc->modem.ser12.dcd_sum2 = bc->modem.ser12.dcd_sum1;
- bc->modem.ser12.dcd_sum1 = bc->modem.ser12.dcd_sum0;
- /* offset to ensure DCD off on silent input */
- bc->modem.ser12.dcd_sum0 = 2;
- bc->modem.ser12.dcd_time = SER12_DCD_INTERVAL(bc);
- }
- bc->modem.ser12.dcd_time--;
- if (bc->options & BAYCOM_OPTIONS_SOFTDCD) {
- /*
- * PLL code for the improved software DCD algorithm
- */
- if (bc->modem.ser12.interm_sample) {
- /*
- * intermediate sample; set timing correction to normal
- */
- ser12_set_divisor(dev, 4);
- } else {
- /*
- * do PLL correction and call HDLC receiver
- */
- switch (bc->modem.ser12.dcd_shreg & 7) {
- case 1: /* transition too late */
- ser12_set_divisor(dev, 5);
-#ifdef BAYCOM_DEBUG
- bc->debug_vals.cur_pllcorr++;
-#endif /* BAYCOM_DEBUG */
- break;
- case 4: /* transition too early */
- ser12_set_divisor(dev, 3);
-#ifdef BAYCOM_DEBUG
- bc->debug_vals.cur_pllcorr--;
-#endif /* BAYCOM_DEBUG */
- break;
- default:
- ser12_set_divisor(dev, 4);
- break;
- }
- bc->modem.shreg >>= 1;
- if (bc->modem.ser12.last_sample ==
- bc->modem.ser12.last_rxbit)
- bc->modem.shreg |= 0x10000;
- bc->modem.ser12.last_rxbit =
- bc->modem.ser12.last_sample;
- }
- if (++bc->modem.ser12.interm_sample >= 3)
- bc->modem.ser12.interm_sample = 0;
- /*
- * DCD stuff
- */
- if (bc->modem.ser12.dcd_shreg & 1) {
- unsigned int dcdspos, dcdsneg;
-
- dcdspos = dcdsneg = 0;
- dcdspos += ((bc->modem.ser12.dcd_shreg >> 1) & 1);
- dcdspos += (!(bc->modem.ser12.dcd_shreg & 0x7ffffffe))
- << 1;
- dcdsneg += ((bc->modem.ser12.dcd_shreg >> 2) & 1);
- dcdsneg += ((bc->modem.ser12.dcd_shreg >> 3) & 1);
- dcdsneg += ((bc->modem.ser12.dcd_shreg >> 4) & 1);
-
- bc->modem.ser12.dcd_sum0 += 16*dcdspos - dcdsneg;
- }
- } else {
- /*
- * PLL algorithm for the hardware squelch DCD algorithm
- */
- if (bc->modem.ser12.interm_sample) {
- /*
- * intermediate sample; set timing correction to normal
- */
- ser12_set_divisor(dev, 6);
- } else {
- /*
- * do PLL correction and call HDLC receiver
- */
- switch (bc->modem.ser12.dcd_shreg & 3) {
- case 1: /* transition too late */
- ser12_set_divisor(dev, 7);
-#ifdef BAYCOM_DEBUG
- bc->debug_vals.cur_pllcorr++;
-#endif /* BAYCOM_DEBUG */
- break;
- case 2: /* transition too early */
- ser12_set_divisor(dev, 5);
-#ifdef BAYCOM_DEBUG
- bc->debug_vals.cur_pllcorr--;
-#endif /* BAYCOM_DEBUG */
- break;
- default:
- ser12_set_divisor(dev, 6);
- break;
- }
- bc->modem.shreg >>= 1;
- if (bc->modem.ser12.last_sample ==
- bc->modem.ser12.last_rxbit)
- bc->modem.shreg |= 0x10000;
- bc->modem.ser12.last_rxbit =
- bc->modem.ser12.last_sample;
- }
- bc->modem.ser12.interm_sample = !bc->modem.ser12.interm_sample;
- /*
- * DCD stuff
- */
- bc->modem.ser12.dcd_sum0 -= (bc->modem.ser12.dcd_shreg & 1);
- }
- outb(0x0d, MCR(dev->base_addr)); /* transmitter off */
- if (bc->modem.shreg & 1) {
- hdlcdrv_putbits(&bc->hdrv, bc->modem.shreg >> 1);
- bc->modem.shreg = 0x10000;
- }
- if(!bc->modem.ser12.dcd_time) {
- hdlcdrv_setdcd(&bc->hdrv, (bc->modem.ser12.dcd_sum0 +
- bc->modem.ser12.dcd_sum1 +
- bc->modem.ser12.dcd_sum2) < 0);
- bc->modem.ser12.dcd_sum2 = bc->modem.ser12.dcd_sum1;
- bc->modem.ser12.dcd_sum1 = bc->modem.ser12.dcd_sum0;
- /* offset to ensure DCD off on silent input */
- bc->modem.ser12.dcd_sum0 = 2;
- bc->modem.ser12.dcd_time = SER12_DCD_INTERVAL(bc);
- }
- bc->modem.ser12.dcd_time--;
-}
-
-/* --------------------------------------------------------------------- */
-
-static void ser12_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- struct device *dev = (struct device *)dev_id;
- struct baycom_state *bc = (struct baycom_state *)dev->priv;
-
- if (!dev || !bc || bc->hdrv.magic != HDLCDRV_MAGIC)
- return;
-
- baycom_int_freq(bc);
- /*
- * check if transmitter active
- */
- if (hdlcdrv_ptt(&bc->hdrv))
- ser12_tx(dev, bc);
- else {
- ser12_rx(dev, bc);
- if (--bc->modem.arb_divider <= 0) {
- bc->modem.arb_divider = SER12_ARB_DIVIDER(bc);
- sti();
- hdlcdrv_arbitrate(dev, &bc->hdrv);
- }
- }
- sti();
- hdlcdrv_transmitter(dev, &bc->hdrv);
- hdlcdrv_receiver(dev, &bc->hdrv);
-}
-#endif /* BAYCOM_ALT_SER12 */
-
-/* --------------------------------------------------------------------- */
-
-enum uart { c_uart_unknown, c_uart_8250,
- c_uart_16450, c_uart_16550, c_uart_16550A};
-static const char *uart_str[] = {
- "unknown", "8250", "16450", "16550", "16550A"
-};
-
-static enum uart ser12_check_uart(unsigned int iobase)
-{
- unsigned char b1,b2,b3;
- enum uart u;
- enum uart uart_tab[] =
- { c_uart_16450, c_uart_unknown, c_uart_16550, c_uart_16550A };
-
- b1 = inb(MCR(iobase));
- outb(b1 | 0x10, MCR(iobase)); /* loopback mode */
- b2 = inb(MSR(iobase));
- outb(0x1a, MCR(iobase));
- b3 = inb(MSR(iobase)) & 0xf0;
- outb(b1, MCR(iobase)); /* restore old values */
- outb(b2, MSR(iobase));
- if (b3 != 0x90)
- return c_uart_unknown;
- inb(RBR(iobase));
- inb(RBR(iobase));
- outb(0x01, FCR(iobase)); /* enable FIFOs */
- u = uart_tab[(inb(IIR(iobase)) >> 6) & 3];
- if (u == c_uart_16450) {
- outb(0x5a, SCR(iobase));
- b1 = inb(SCR(iobase));
- outb(0xa5, SCR(iobase));
- b2 = inb(SCR(iobase));
- if ((b1 != 0x5a) || (b2 != 0xa5))
- u = c_uart_8250;
- }
- return u;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int ser12_open(struct device *dev)
-{
- struct baycom_state *bc = (struct baycom_state *)dev->priv;
- enum uart u;
-
- if (!dev || !bc)
- return -ENXIO;
- if (!dev->base_addr || dev->base_addr > 0x1000-SER12_EXTENT ||
- dev->irq < 2 || dev->irq > 15)
- return -ENXIO;
- if (check_region(dev->base_addr, SER12_EXTENT))
- return -EACCES;
- memset(&bc->modem, 0, sizeof(bc->modem));
- bc->hdrv.par.bitrate = 1200;
- if ((u = ser12_check_uart(dev->base_addr)) == c_uart_unknown)
- return -EIO;
- outb(0, FCR(dev->base_addr)); /* disable FIFOs */
- outb(0x0d, MCR(dev->base_addr));
- outb(0x0d, MCR(dev->base_addr));
- outb(0, IER(dev->base_addr));
- if (request_irq(dev->irq, ser12_interrupt, SA_INTERRUPT,
- "baycom_ser12", dev))
- return -EBUSY;
- request_region(dev->base_addr, SER12_EXTENT, "baycom_ser12");
-#ifdef BAYCOM_ALT_SER12
- bc->hdrv.par.bitrate = SER12_BAUD;
- /*
- * set the SIO to 6 Bits/character and 19600 baud, so that
- * we get exactly (hopefully) one interrupt per radio symbol
- */
- outb(0x81, LCR(dev->base_addr)); /* DLAB = 1 */
- outb(115200/8/SER12_BAUD, DLL(dev->base_addr));
- outb(0, DLM(dev->base_addr));
- outb(0x01, LCR(dev->base_addr)); /* word length = 6 */
- /*
- * enable transmitter empty interrupt and modem status interrupt
- */
- outb(0x0a, IER(dev->base_addr));
- /*
- * make sure the next interrupt is generated;
- * 0 must be used to power the modem; the modem draws its
- * power from the TxD line
- */
- outb(0x00, THR(dev->base_addr));
- printk(KERN_INFO "%s: ser12(alt modem) at iobase 0x%lx irq %u options "
- "0x%x uart %s\n", bc_drvname, dev->base_addr, dev->irq,
- bc->options, uart_str[u]);
-#else /* BAYCOM_ALT_SER12 */
- /*
- * enable transmitter empty interrupt
- */
- outb(2, IER(dev->base_addr));
- /*
- * set the SIO to 6 Bits/character and 19200 or 28800 baud, so that
- * we get exactly (hopefully) 2 or 3 interrupts per radio symbol,
- * depending on the usage of the software DCD routine
- */
- ser12_set_divisor(dev, (bc->options & BAYCOM_OPTIONS_SOFTDCD) ? 4 : 6);
- printk(KERN_INFO "%s: ser12 at iobase 0x%lx irq %u options "
- "0x%x uart %s\n", bc_drvname, dev->base_addr, dev->irq,
- bc->options, uart_str[u]);
-#endif /* BAYCOM_ALT_SER12 */
- MOD_INC_USE_COUNT;
- return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int ser12_close(struct device *dev)
-{
- struct baycom_state *bc = (struct baycom_state *)dev->priv;
-
- if (!dev || !bc)
- return -EINVAL;
- /*
- * disable interrupts
- */
- outb(0, IER(dev->base_addr));
- outb(1, MCR(dev->base_addr));
- free_irq(dev->irq, dev);
- release_region(dev->base_addr, SER12_EXTENT);
- printk(KERN_INFO "%s: close ser12 at iobase 0x%lx irq %u\n",
- bc_drvname, dev->base_addr, dev->irq);
- MOD_DEC_USE_COUNT;
- return 0;
-}
-
-/* --------------------------------------------------------------------- */
-/*
- * ===================== PAR96 specific routines =========================
- */
-
-#define PAR96_DESCRAM_TAP1 0x20000
-#define PAR96_DESCRAM_TAP2 0x01000
-#define PAR96_DESCRAM_TAP3 0x00001
-
-#define PAR96_DESCRAM_TAPSH1 17
-#define PAR96_DESCRAM_TAPSH2 12
-#define PAR96_DESCRAM_TAPSH3 0
-
-#define PAR96_SCRAM_TAP1 0x20000 /* X^17 */
-#define PAR96_SCRAM_TAPN 0x00021 /* X^0+X^5 */
-
-/* --------------------------------------------------------------------- */
-
-static inline void par96_tx(struct device *dev, struct baycom_state *bc)
-{
- int i;
- unsigned int data = hdlcdrv_getbits(&bc->hdrv);
-
- for(i = 0; i < PAR96_BURSTBITS; i++, data >>= 1) {
- unsigned char val = PAR97_POWER;
- bc->modem.par96.scram = ((bc->modem.par96.scram << 1) |
- (bc->modem.par96.scram & 1));
- if (!(data & 1))
- bc->modem.par96.scram ^= 1;
- if (bc->modem.par96.scram & (PAR96_SCRAM_TAP1 << 1))
- bc->modem.par96.scram ^=
- (PAR96_SCRAM_TAPN << 1);
- if (bc->modem.par96.scram & (PAR96_SCRAM_TAP1 << 2))
- val |= PAR96_TXBIT;
- outb(val, LPT_DATA(dev->base_addr));
- outb(val | PAR96_BURST, LPT_DATA(dev->base_addr));
- }
-}
-
-/* --------------------------------------------------------------------- */
-
-static inline void par96_rx(struct device *dev, struct baycom_state *bc)
-{
- int i;
- unsigned int data, mask, mask2, descx;
-
- /*
- * do receiver; differential decode and descramble on the fly
- */
- for(data = i = 0; i < PAR96_BURSTBITS; i++) {
- bc->modem.par96.descram = (bc->modem.par96.descram << 1);
- if (inb(LPT_STATUS(dev->base_addr)) & PAR96_RXBIT)
- bc->modem.par96.descram |= 1;
- descx = bc->modem.par96.descram ^
- (bc->modem.par96.descram >> 1);
- /* now the diff decoded data is inverted in descram */
- outb(PAR97_POWER | PAR96_PTT, LPT_DATA(dev->base_addr));
- descx ^= ((descx >> PAR96_DESCRAM_TAPSH1) ^
- (descx >> PAR96_DESCRAM_TAPSH2));
- data >>= 1;
- if (!(descx & 1))
- data |= 0x8000;
- outb(PAR97_POWER | PAR96_PTT | PAR96_BURST,
- LPT_DATA(dev->base_addr));
- }
- hdlcdrv_putbits(&bc->hdrv, data);
- /*
- * do DCD algorithm
- */
- if (bc->options & BAYCOM_OPTIONS_SOFTDCD) {
- bc->modem.par96.dcd_shreg = (bc->modem.par96.dcd_shreg >> 16)
- | (data << 16);
- /* search for flags and set the dcd counter appropriately */
- for(mask = 0x1fe00, mask2 = 0xfc00, i = 0;
- i < PAR96_BURSTBITS; i++, mask <<= 1, mask2 <<= 1)
- if ((bc->modem.par96.dcd_shreg & mask) == mask2)
- bc->modem.par96.dcd_count = HDLCDRV_MAXFLEN+4;
- /* check for abort/noise sequences */
- for(mask = 0x1fe00, mask2 = 0x1fe00, i = 0;
- i < PAR96_BURSTBITS; i++, mask <<= 1, mask2 <<= 1)
- if (((bc->modem.par96.dcd_shreg & mask) == mask2) &&
- (bc->modem.par96.dcd_count >= 0))
- bc->modem.par96.dcd_count -= HDLCDRV_MAXFLEN-10;
- /* decrement and set the dcd variable */
- if (bc->modem.par96.dcd_count >= 0)
- bc->modem.par96.dcd_count -= 2;
- hdlcdrv_setdcd(&bc->hdrv, bc->modem.par96.dcd_count > 0);
- } else {
- hdlcdrv_setdcd(&bc->hdrv, !!(inb(LPT_STATUS(dev->base_addr))
- & PAR96_DCD));
- }
-}
-
-/* --------------------------------------------------------------------- */
-
-static void par96_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- struct device *dev = (struct device *)dev_id;
- struct baycom_state *bc = (struct baycom_state *)dev->priv;
-
- if (!dev || !bc || bc->hdrv.magic != HDLCDRV_MAGIC)
- return;
-
- baycom_int_freq(bc);
- /*
- * check if transmitter active
- */
- if (hdlcdrv_ptt(&bc->hdrv))
- par96_tx(dev, bc);
- else {
- par96_rx(dev, bc);
- if (--bc->modem.arb_divider <= 0) {
- bc->modem.arb_divider = 6;
- sti();
- hdlcdrv_arbitrate(dev, &bc->hdrv);
- }
- }
- sti();
- hdlcdrv_transmitter(dev, &bc->hdrv);
- hdlcdrv_receiver(dev, &bc->hdrv);
-}
-
-/* --------------------------------------------------------------------- */
-
-static int par96_check_lpt(unsigned int iobase)
-{
- unsigned char b1,b2;
- int i;
-
- b1 = inb(LPT_DATA(iobase));
- b2 = inb(LPT_CONTROL(iobase));
- outb(0xaa, LPT_DATA(iobase));
- i = inb(LPT_DATA(iobase)) == 0xaa;
- outb(0x55, LPT_DATA(iobase));
- i &= inb(LPT_DATA(iobase)) == 0x55;
- outb(0x0a, LPT_CONTROL(iobase));
- i &= (inb(LPT_CONTROL(iobase)) & 0xf) == 0x0a;
- outb(0x05, LPT_CONTROL(iobase));
- i &= (inb(LPT_CONTROL(iobase)) & 0xf) == 0x05;
- outb(b1, LPT_DATA(iobase));
- outb(b2, LPT_CONTROL(iobase));
- return !i;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int par96_open(struct device *dev)
-{
- struct baycom_state *bc = (struct baycom_state *)dev->priv;
-
- if (!dev || !bc)
- return -ENXIO;
- if (!dev->base_addr || dev->base_addr > 0x1000-PAR96_EXTENT ||
- dev->irq < 2 || dev->irq > 15)
- return -ENXIO;
- if (check_region(dev->base_addr, PAR96_EXTENT))
- return -EACCES;
- memset(&bc->modem, 0, sizeof(bc->modem));
- bc->hdrv.par.bitrate = 9600;
- if (par96_check_lpt(dev->base_addr))
- return -EIO;
- /* disable interrupt */
- outb(0, LPT_CONTROL(dev->base_addr));
- /* switch off PTT */
- outb(PAR96_PTT | PAR97_POWER, LPT_DATA(dev->base_addr));
- printk(KERN_INFO "%s: par96 at iobase 0x%lx irq %u options 0x%x\n",
- bc_drvname, dev->base_addr, dev->irq, bc->options);
- if (request_irq(dev->irq, par96_interrupt, SA_INTERRUPT,
- "baycom_par96", dev))
- return -EBUSY;
- request_region(dev->base_addr, PAR96_EXTENT, "baycom_par96");
- /* enable interrupt */
- outb(LPT_IRQ_ENABLE, LPT_CONTROL(dev->base_addr));
- MOD_INC_USE_COUNT;
- return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int par96_close(struct device *dev)
-{
- struct baycom_state *bc = (struct baycom_state *)dev->priv;
-
- if (!dev || !bc)
- return -EINVAL;
- /* disable interrupt */
- outb(0, LPT_CONTROL(dev->base_addr));
- /* switch off PTT */
- outb(PAR96_PTT | PAR97_POWER, LPT_DATA(dev->base_addr));
- free_irq(dev->irq, dev);
- release_region(dev->base_addr, PAR96_EXTENT);
- printk(KERN_INFO "%s: close par96 at iobase 0x%lx irq %u\n",
- bc_drvname, dev->base_addr, dev->irq);
- MOD_DEC_USE_COUNT;
- return 0;
-}
-
-/* --------------------------------------------------------------------- */
-/*
- * ===================== hdlcdrv driver interface =========================
- */
-
-/* --------------------------------------------------------------------- */
-
-static int baycom_ioctl(struct device *dev, struct ifreq *ifr,
- struct hdlcdrv_ioctl *hi, int cmd);
-
-/* --------------------------------------------------------------------- */
-
-static struct hdlcdrv_ops ser12_ops = {
- bc_drvname,
- bc_drvinfo,
- ser12_open,
- ser12_close,
- baycom_ioctl
-};
-
-/* --------------------------------------------------------------------- */
-
-static struct hdlcdrv_ops par96_ops = {
- bc_drvname,
- bc_drvinfo,
- par96_open,
- par96_close,
- baycom_ioctl
-};
-
-/* --------------------------------------------------------------------- */
-
-static struct hdlcdrv_ops dummy_ops = {
- bc_drvname,
- bc_drvinfo,
- NULL,
- NULL,
- baycom_ioctl
-};
-
-/* --------------------------------------------------------------------- */
-
-static int baycom_setmode(struct baycom_state *bc, char *modestr)
-{
- struct hdlcdrv_ops *newops = NULL;
- unsigned long flags;
-
- if (!strncmp(modestr, "off", 3))
- newops = &dummy_ops;
- else if (!strncmp(modestr, "ser12", 5))
- newops = &ser12_ops;
- else if (!strncmp(modestr, "par96", 5))
- newops = &par96_ops;
- else
- return -EINVAL;
- save_flags(flags);
- cli();
- bc->hdrv.ops = newops;
- bc->options = !!strchr(modestr, '*');
- restore_flags(flags);
- return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int baycom_ioctl(struct device *dev, struct ifreq *ifr,
- struct hdlcdrv_ioctl *hi, int cmd)
-{
- struct baycom_state *bc;
- struct baycom_ioctl bi;
- int cmd2;
-
- if (!dev || !dev->priv ||
- ((struct baycom_state *)dev->priv)->hdrv.magic != HDLCDRV_MAGIC) {
- printk(KERN_ERR "bc_ioctl: invalid device struct\n");
- return -EINVAL;
- }
- bc = (struct baycom_state *)dev->priv;
-
- if (cmd != SIOCDEVPRIVATE)
- return -ENOIOCTLCMD;
- if (get_user(cmd2, (int *)ifr->ifr_data))
- return -EFAULT;
- switch (hi->cmd) {
- default:
- break;
-
- case HDLCDRVCTL_GETMODE:
- if (bc->hdrv.ops == &ser12_ops)
- strcpy(hi->data.modename, "ser12");
- else if (bc->hdrv.ops == &par96_ops)
- strcpy(hi->data.modename, "par96");
- else if (bc->hdrv.ops == &dummy_ops)
- strcpy(hi->data.modename, "off");
- else
- strcpy(hi->data.modename, "invalid");
- if (bc->options & 1)
- strcat(hi->data.modename, "*");
- if (copy_to_user(ifr->ifr_data, hi, sizeof(struct hdlcdrv_ioctl)))
- return -EFAULT;
- return 0;
-
- case HDLCDRVCTL_SETMODE:
- if (!suser() || dev->start)
- return -EACCES;
- hi->data.modename[sizeof(hi->data.modename)-1] = '\0';
- return baycom_setmode(bc, hi->data.modename);
-
- case HDLCDRVCTL_MODELIST:
- strcpy(hi->data.modename, "ser12,par96");
- if (copy_to_user(ifr->ifr_data, hi, sizeof(struct hdlcdrv_ioctl)))
- return -EFAULT;
- return 0;
-
- case HDLCDRVCTL_MODEMPARMASK:
- return HDLCDRV_PARMASK_IOBASE | HDLCDRV_PARMASK_IRQ;
-
- }
-
- if (copy_from_user(&bi, ifr->ifr_data, sizeof(bi)))
- return -EFAULT;
- switch (bi.cmd) {
- default:
- return -ENOIOCTLCMD;
-
-#ifdef BAYCOM_DEBUG
- case BAYCOMCTL_GETDEBUG:
- bi.data.dbg.debug1 = bc->hdrv.ptt_keyed;
- bi.data.dbg.debug2 = bc->debug_vals.last_intcnt;
- bi.data.dbg.debug3 = bc->debug_vals.last_pllcorr;
- break;
-#endif /* BAYCOM_DEBUG */
-
- }
- if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi)))
- return -EFAULT;
- return 0;
-
-}
-
-/* --------------------------------------------------------------------- */
-
-__initfunc(int baycom_init(void))
-{
- int i, j, found = 0;
- char set_hw = 1;
- struct baycom_state *bc;
- char ifname[HDLCDRV_IFNAMELEN];
-
-
- printk(bc_drvinfo);
- /*
- * register net devices
- */
- for (i = 0; i < NR_PORTS; i++) {
- struct device *dev = baycom_device+i;
- sprintf(ifname, "bc%d", i);
-
- if (!baycom_ports[i].mode)
- set_hw = 0;
- if (!set_hw)
- baycom_ports[i].iobase = baycom_ports[i].irq = 0;
- j = hdlcdrv_register_hdlcdrv(dev, &dummy_ops,
- sizeof(struct baycom_state),
- ifname, baycom_ports[i].iobase,
- baycom_ports[i].irq, 0);
- if (!j) {
- bc = (struct baycom_state *)dev->priv;
- if (set_hw && baycom_setmode(bc, baycom_ports[i].mode))
- set_hw = 0;
- found++;
- } else {
- printk(KERN_WARNING "%s: cannot register net device\n",
- bc_drvname);
- }
- }
- if (!found)
- return -ENXIO;
- return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-#ifdef MODULE
-
-/*
- * command line settable parameters
- */
-static char *mode = NULL;
-static int iobase = 0x3f8;
-static int irq = 4;
-
-#if LINUX_VERSION_CODE >= 0x20115
-
-MODULE_PARM(mode, "s");
-MODULE_PARM_DESC(mode, "baycom operating mode; eg. ser12* or par96");
-MODULE_PARM(iobase, "i");
-MODULE_PARM_DESC(iobase, "baycom io base address");
-MODULE_PARM(irq, "i");
-MODULE_PARM_DESC(irq, "baycom irq number");
-
-MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");
-MODULE_DESCRIPTION("Baycom ser12, par96 and picpar amateur radio modem driver");
-
-#endif
-
-__initfunc(int init_module(void))
-{
- baycom_ports[0].mode = mode;
- baycom_ports[0].iobase = iobase;
- baycom_ports[0].irq = irq;
- baycom_ports[1].mode = NULL;
-
- return baycom_init();
-}
-
-/* --------------------------------------------------------------------- */
-
-void cleanup_module(void)
-{
- int i;
-
- for(i = 0; i < NR_PORTS; i++) {
- struct device *dev = baycom_device+i;
- struct baycom_state *bc = (struct baycom_state *)dev->priv;
-
- if (bc) {
- if (bc->hdrv.magic != HDLCDRV_MAGIC)
- printk(KERN_ERR "baycom: invalid magic in "
- "cleanup_module\n");
- else
- hdlcdrv_unregister_hdlcdrv(dev);
- }
- }
-}
-
-#else /* MODULE */
-/* --------------------------------------------------------------------- */
-/*
- * format: baycom=io,irq,mode
- * mode: {ser12,par96}[*]
- * * indicates sofware DCD
- */
-
-__initfunc(void baycom_setup(char *str, int *ints))
-{
- int i;
-
- for (i = 0; (i < NR_PORTS) && (baycom_ports[i].mode); i++);
- if ((i >= NR_PORTS) || (ints[0] < 2)) {
- printk(KERN_INFO "%s: too many or invalid interface "
- "specifications\n", bc_drvname);
- return;
- }
- baycom_ports[i].mode = str;
- baycom_ports[i].iobase = ints[1];
- baycom_ports[i].irq = ints[2];
- if (i < NR_PORTS-1)
- baycom_ports[i+1].mode = NULL;
-}
-
-#endif /* MODULE */
-/* --------------------------------------------------------------------- */
diff --git a/drivers/net/bpqether.c b/drivers/net/bpqether.c
index 54d63121e..e69de29bb 100644
--- a/drivers/net/bpqether.c
+++ b/drivers/net/bpqether.c
@@ -1,669 +0,0 @@
-/*
- * G8BPQ compatible "AX.25 via ethernet" driver release 003
- *
- * This code REQUIRES 2.0.0 or higher/ NET3.029
- *
- * This module:
- * This module is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
- * This is a "pseudo" network driver to allow AX.25 over Ethernet
- * using G8BPQ encapsulation. It has been extracted from the protocol
- * implementation because
- *
- * - things got unreadable within the protocol stack
- * - to cure the protocol stack from "feature-ism"
- * - a protocol implementation shouldn't need to know on
- * which hardware it is running
- * - user-level programs like the AX.25 utilities shouldn't
- * need to know about the hardware.
- * - IP over ethernet encapsulated AX.25 was impossible
- * - rxecho.c did not work
- * - to have room for extensions
- * - it just deserves to "live" as an own driver
- *
- * This driver can use any ethernet destination address, and can be
- * limited to accept frames from one dedicated ethernet card only.
- *
- * Note that the driver sets up the BPQ devices automagically on
- * startup or (if started before the "insmod" of an ethernet device)
- * on "ifconfig up". It hopefully will remove the BPQ on "rmmod"ing
- * the ethernet device (in fact: as soon as another ethernet or bpq
- * device gets "ifconfig"ured).
- *
- * I have heard that several people are thinking of experiments
- * with highspeed packet radio using existing ethernet cards.
- * Well, this driver is prepared for this purpose, just add
- * your tx key control and a txdelay / tailtime algorithm,
- * probably some buffering, and /voila/...
- *
- * History
- * BPQ 001 Joerg(DL1BKE) Extracted BPQ code from AX.25
- * protocol stack and added my own
- * yet existing patches
- * BPQ 002 Joerg(DL1BKE) Scan network device list on
- * startup.
- * BPQ 003 Joerg(DL1BKE) Ethernet destination address
- * and accepted source address
- * can be configured by an ioctl()
- * call.
- * Fixed to match Linux networking
- * changes - 2.1.15.
- */
-
-#include <linux/config.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/socket.h>
-#include <linux/in.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/net.h>
-#include <net/ax25.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/if_arp.h>
-#include <linux/skbuff.h>
-#include <net/sock.h>
-#include <asm/segment.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/notifier.h>
-#include <linux/proc_fs.h>
-#include <linux/stat.h>
-#include <linux/firewall.h>
-#include <linux/module.h>
-#include <linux/init.h>
-
-#include <net/ip.h>
-#include <net/arp.h>
-
-#include <linux/bpqether.h>
-
-static unsigned char ax25_bcast[AX25_ADDR_LEN] =
- {'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, '0' << 1};
-static unsigned char ax25_defaddr[AX25_ADDR_LEN] =
- {'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1, '1' << 1};
-
-static char bcast_addr[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
-
-static char bpq_eth_addr[6];
-
-static int bpq_rcv(struct sk_buff *, struct device *, struct packet_type *);
-static int bpq_device_event(struct notifier_block *, unsigned long, void *);
-static char *bpq_print_ethaddr(unsigned char *);
-
-static struct packet_type bpq_packet_type = {
- 0, /* ntohs(ETH_P_BPQ),*/
- 0, /* copy */
- bpq_rcv,
- NULL,
- NULL,
-};
-
-static struct notifier_block bpq_dev_notifier = {
- bpq_device_event,
- 0
-};
-
-
-#define MAXBPQDEV 100
-
-static struct bpqdev {
- struct bpqdev *next;
- char ethname[14]; /* ether device name */
- struct device *ethdev; /* link to ethernet device */
- struct device axdev; /* bpq device (bpq#) */
- struct net_device_stats stats; /* some statistics */
- char dest_addr[6]; /* ether destination address */
- char acpt_addr[6]; /* accept ether frames from this address only */
-} *bpq_devices = NULL;
-
-
-/* ------------------------------------------------------------------------ */
-
-
-/*
- * Get the ethernet device for a BPQ device
- */
-static __inline__ struct device *bpq_get_ether_dev(struct device *dev)
-{
- struct bpqdev *bpq;
-
- bpq = (struct bpqdev *)dev->priv;
-
- return (bpq != NULL) ? bpq->ethdev : NULL;
-}
-
-/*
- * Get the BPQ device for the ethernet device
- */
-static __inline__ struct device *bpq_get_ax25_dev(struct device *dev)
-{
- struct bpqdev *bpq;
-
- for (bpq = bpq_devices; bpq != NULL; bpq = bpq->next)
- if (bpq->ethdev == dev)
- return &bpq->axdev;
-
- return NULL;
-}
-
-static __inline__ int dev_is_ethdev(struct device *dev)
-{
- return (
- dev->type == ARPHRD_ETHER
- && strncmp(dev->name, "dummy", 5)
- );
-}
-
-/*
- * Sanity check: remove all devices that ceased to exists and
- * return '1' if the given BPQ device was affected.
- */
-static int bpq_check_devices(struct device *dev)
-{
- struct bpqdev *bpq, *bpq_prev;
- int result = 0;
- unsigned long flags;
-
- save_flags(flags);
- cli();
-
- bpq_prev = NULL;
-
- for (bpq = bpq_devices; bpq != NULL; bpq = bpq->next) {
- if (!dev_get(bpq->ethname)) {
- if (bpq_prev)
- bpq_prev->next = bpq->next;
- else
- bpq_devices = bpq->next;
-
- if (&bpq->axdev == dev)
- result = 1;
-
- unregister_netdev(&bpq->axdev);
- kfree(bpq);
- }
-
- bpq_prev = bpq;
- }
-
- restore_flags(flags);
-
- return result;
-}
-
-
-/* ------------------------------------------------------------------------ */
-
-
-/*
- * Receive an AX.25 frame via an ethernet interface.
- */
-static int bpq_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *ptype)
-{
- int len;
- char * ptr;
- struct ethhdr *eth = (struct ethhdr *)skb->mac.raw;
- struct bpqdev *bpq;
-
- skb->sk = NULL; /* Initially we don't know who it's for */
-
- dev = bpq_get_ax25_dev(dev);
-
- if (dev == NULL || dev->start == 0) {
- kfree_skb(skb, FREE_READ);
- return 0;
- }
-
- /*
- * if we want to accept frames from just one ethernet device
- * we check the source address of the sender.
- */
-
- bpq = (struct bpqdev *)dev->priv;
-
- if (!(bpq->acpt_addr[0] & 0x01) && memcmp(eth->h_source, bpq->acpt_addr, ETH_ALEN)) {
- printk(KERN_DEBUG "bpqether: wrong dest %s\n", bpq_print_ethaddr(eth->h_source));
- kfree_skb(skb, FREE_READ);
- return 0;
- }
-
- len = skb->data[0] + skb->data[1] * 256 - 5;
-
- skb_pull(skb, 2); /* Remove the length bytes */
- skb_trim(skb, len); /* Set the length of the data */
-
- ((struct bpqdev *)dev->priv)->stats.rx_packets++;
- ((struct bpqdev *)dev->priv)->stats.rx_bytes+=len;
-
- ptr = skb_push(skb, 1);
- *ptr = 0;
-
- skb->dev = dev;
- skb->protocol = htons(ETH_P_AX25);
- skb->mac.raw = skb->data;
- skb->pkt_type = PACKET_HOST;
-
- netif_rx(skb);
-
- return 0;
-}
-
-/*
- * Send an AX.25 frame via an ethernet interface
- */
-static int bpq_xmit(struct sk_buff *skb, struct device *dev)
-{
- struct sk_buff *newskb;
- unsigned char *ptr;
- struct bpqdev *bpq;
- int size;
-
- /*
- * Just to be *really* sure not to send anything if the interface
- * is down, the ethernet device may have gone.
- */
- if (!dev->start) {
- bpq_check_devices(dev);
- kfree_skb(skb, FREE_WRITE);
- return -ENODEV;
- }
-
- skb_pull(skb, 1);
- size = skb->len;
-
- /*
- * The AX.25 code leaves enough room for the ethernet header, but
- * sendto() does not.
- */
- if (skb_headroom(skb) < AX25_BPQ_HEADER_LEN) { /* Ough! */
- if ((newskb = skb_realloc_headroom(skb, AX25_BPQ_HEADER_LEN)) == NULL) {
- printk(KERN_WARNING "bpqether: out of memory\n");
- kfree_skb(skb, FREE_WRITE);
- return -ENOMEM;
- }
-
- if (skb->sk != NULL)
- skb_set_owner_w(newskb, skb->sk);
-
- kfree_skb(skb, FREE_WRITE);
- skb = newskb;
- }
-
- skb->protocol = htons(ETH_P_AX25);
-
- ptr = skb_push(skb, 2);
-
- *ptr++ = (size + 5) % 256;
- *ptr++ = (size + 5) / 256;
-
- bpq = (struct bpqdev *)dev->priv;
-
- if ((dev = bpq_get_ether_dev(dev)) == NULL) {
- bpq->stats.tx_dropped++;
- kfree_skb(skb, FREE_WRITE);
- return -ENODEV;
- }
-
- skb->dev = dev;
- dev->hard_header(skb, dev, ETH_P_BPQ, bpq->dest_addr, NULL, 0);
- bpq->stats.tx_packets++;
- bpq->stats.tx_bytes+=skb->len;
-
- dev_queue_xmit(skb);
-
- return 0;
-}
-
-/*
- * Statistics
- */
-static struct net_device_stats *bpq_get_stats(struct device *dev)
-{
- struct bpqdev *bpq;
-
- bpq = (struct bpqdev *)dev->priv;
-
- return &bpq->stats;
-}
-
-/*
- * Set AX.25 callsign
- */
-static int bpq_set_mac_address(struct device *dev, void *addr)
-{
- struct sockaddr *sa = (struct sockaddr *)addr;
-
- memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
-
- return 0;
-}
-
-/* Ioctl commands
- *
- * SIOCSBPQETHOPT reserved for enhancements
- * SIOCSBPQETHADDR set the destination and accepted
- * source ethernet address (broadcast
- * or multicast: accept all)
- */
-static int bpq_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
-{
- int err;
- struct bpq_ethaddr *ethaddr = (struct bpq_ethaddr *)ifr->ifr_data;
- struct bpqdev *bpq = dev->priv;
- struct bpq_req req;
-
- if (!suser())
- return -EPERM;
-
- if (bpq == NULL) /* woops! */
- return -ENODEV;
-
- switch (cmd) {
- case SIOCSBPQETHOPT:
- if ((err = verify_area(VERIFY_WRITE, ifr->ifr_data, sizeof(struct bpq_req))) != 0)
- return err;
- copy_from_user(&req, ifr->ifr_data, sizeof(struct bpq_req));
- switch (req.cmd) {
- case SIOCGBPQETHPARAM:
- case SIOCSBPQETHPARAM:
- default:
- return -EINVAL;
- }
-
- break;
-
- case SIOCSBPQETHADDR:
- if ((err = verify_area(VERIFY_READ, ethaddr, sizeof(struct bpq_ethaddr))) != 0)
- return err;
- copy_from_user(bpq->dest_addr, ethaddr->destination, ETH_ALEN);
- copy_from_user(bpq->acpt_addr, ethaddr->accept, ETH_ALEN);
- break;
-
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-/*
- * open/close a device
- */
-static int bpq_open(struct device *dev)
-{
- if (bpq_check_devices(dev))
- return -ENODEV; /* oops, it's gone */
-
- dev->tbusy = 0;
- dev->start = 1;
-
- MOD_INC_USE_COUNT;
-
- return 0;
-}
-
-static int bpq_close(struct device *dev)
-{
- dev->tbusy = 1;
- dev->start = 0;
-
- MOD_DEC_USE_COUNT;
-
- return 0;
-}
-
-/*
- * currently unused
- */
-static int bpq_dev_init(struct device *dev)
-{
- return 0;
-}
-
-
-/* ------------------------------------------------------------------------ */
-
-
-/*
- * Proc filesystem
- */
-static char * bpq_print_ethaddr(unsigned char *e)
-{
- static char buf[18];
-
- sprintf(buf, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
- e[0], e[1], e[2], e[3], e[4], e[5]);
-
- return buf;
-}
-
-int bpq_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
-{
- struct bpqdev *bpqdev;
- int len = 0;
- off_t pos = 0;
- off_t begin = 0;
-
- cli();
-
- len += sprintf(buffer, "dev ether destination accept from\n");
-
- for (bpqdev = bpq_devices; bpqdev != NULL; bpqdev = bpqdev->next) {
- len += sprintf(buffer + len, "%-5s %-10s %s ",
- bpqdev->axdev.name, bpqdev->ethname,
- bpq_print_ethaddr(bpqdev->dest_addr));
-
- len += sprintf(buffer + len, "%s\n",
- (bpqdev->acpt_addr[0] & 0x01) ? "*" : bpq_print_ethaddr(bpqdev->acpt_addr));
-
- pos = begin + len;
-
- if (pos < offset) {
- len = 0;
- begin = pos;
- }
-
- if (pos > offset + length)
- break;
- }
-
- sti();
-
- *start = buffer + (offset - begin);
- len -= (offset - begin);
-
- if (len > length) len = length;
-
- return len;
-}
-
-
-/* ------------------------------------------------------------------------ */
-
-
-/*
- * Setup a new device.
- */
-static int bpq_new_device(struct device *dev)
-{
- int k;
- unsigned char *buf;
- struct bpqdev *bpq, *bpq2;
-
- if ((bpq = kmalloc(sizeof(struct bpqdev), GFP_KERNEL)) == NULL)
- return -ENOMEM;
-
- memset(bpq, 0, sizeof(struct bpqdev));
-
- bpq->ethdev = dev;
-
- bpq->ethname[sizeof(bpq->ethname)-1] = '\0';
- strncpy(bpq->ethname, dev->name, sizeof(bpq->ethname)-1);
-
- memcpy(bpq->dest_addr, bcast_addr, sizeof(bpq_eth_addr));
- memcpy(bpq->acpt_addr, bcast_addr, sizeof(bpq_eth_addr));
-
- dev = &bpq->axdev;
- buf = kmalloc(14, GFP_KERNEL);
-
- for (k = 0; k < MAXBPQDEV; k++) {
- struct device *odev;
-
- sprintf(buf, "bpq%d", k);
-
- if ((odev = dev_get(buf)) == NULL || bpq_check_devices(odev))
- break;
- }
-
- if (k == MAXBPQDEV) {
- kfree(bpq);
- return -ENODEV;
- }
-
- dev->priv = (void *)bpq; /* pointer back */
- dev->name = buf;
- dev->init = bpq_dev_init;
-
- if (register_netdev(dev) != 0) {
- kfree(bpq);
- return -EIO;
- }
-
- dev_init_buffers(dev);
-
- dev->hard_start_xmit = bpq_xmit;
- dev->open = bpq_open;
- dev->stop = bpq_close;
- dev->set_mac_address = bpq_set_mac_address;
- dev->get_stats = bpq_get_stats;
- dev->do_ioctl = bpq_ioctl;
-
- memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN);
- memcpy(dev->dev_addr, ax25_defaddr, AX25_ADDR_LEN);
-
- dev->flags = 0;
-
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
- dev->hard_header = ax25_encapsulate;
- dev->rebuild_header = ax25_rebuild_header;
-#endif
-
- dev->type = ARPHRD_AX25;
- dev->hard_header_len = AX25_MAX_HEADER_LEN + AX25_BPQ_HEADER_LEN;
- dev->mtu = AX25_DEF_PACLEN;
- dev->addr_len = AX25_ADDR_LEN;
-
- cli();
-
- if (bpq_devices == NULL) {
- bpq_devices = bpq;
- } else {
- for (bpq2 = bpq_devices; bpq2->next != NULL; bpq2 = bpq2->next);
- bpq2->next = bpq;
- }
-
- sti();
-
- return 0;
-}
-
-
-/*
- * Handle device status changes.
- */
-static int bpq_device_event(struct notifier_block *this,unsigned long event, void *ptr)
-{
- struct device *dev = (struct device *)ptr;
-
- if (!dev_is_ethdev(dev))
- return NOTIFY_DONE;
-
- bpq_check_devices(NULL);
-
- switch (event) {
- case NETDEV_UP: /* new ethernet device -> new BPQ interface */
- if (bpq_get_ax25_dev(dev) == NULL)
- bpq_new_device(dev);
- break;
-
- case NETDEV_DOWN: /* ethernet device closed -> close BPQ interface */
- if ((dev = bpq_get_ax25_dev(dev)) != NULL)
- dev_close(dev);
- break;
-
- default:
- break;
- }
-
- return NOTIFY_DONE;
-}
-
-
-/* ------------------------------------------------------------------------ */
-
-/*
- * Initialize driver. To be called from af_ax25 if not compiled as a
- * module
- */
-__initfunc(int bpq_init(void))
-{
- struct device *dev;
-
- bpq_packet_type.type = htons(ETH_P_BPQ);
- dev_add_pack(&bpq_packet_type);
-
- register_netdevice_notifier(&bpq_dev_notifier);
-
- printk(KERN_INFO "AX.25 ethernet driver version 0.01\n");
-
-#ifdef CONFIG_PROC_FS
- proc_net_register(&(struct proc_dir_entry) {
- PROC_NET_AX25_BPQETHER, 8, "bpqether",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, &proc_net_inode_operations,
- bpq_get_info
- });
-#endif
-
- for (dev = dev_base; dev != NULL; dev = dev->next) {
- if (dev_is_ethdev(dev))
- bpq_new_device(dev);
- }
-
- return 0;
-}
-
-#ifdef MODULE
-EXPORT_NO_SYMBOLS;
-
-MODULE_AUTHOR("Joerg Reuter DL1BKE <jreuter@lykos.oche.de>");
-MODULE_DESCRIPTION("Transmit and receive AX.25 packets over Ethernet");
-
-int init_module(void)
-{
- return bpq_init();
-}
-
-void cleanup_module(void)
-{
- struct bpqdev *bpq;
-
- dev_remove_pack(&bpq_packet_type);
-
- unregister_netdevice_notifier(&bpq_dev_notifier);
-
-#ifdef CONFIG_PROC_FS
- proc_net_unregister(PROC_NET_AX25_BPQETHER);
-#endif
-
- for (bpq = bpq_devices; bpq != NULL; bpq = bpq->next)
- unregister_netdev(&bpq->axdev);
-}
-#endif
diff --git a/drivers/net/de600.c b/drivers/net/de600.c
index f73939830..2bdddc546 100644
--- a/drivers/net/de600.c
+++ b/drivers/net/de600.c
@@ -39,8 +39,8 @@ static const char *version =
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
**************************************************************/
-/* Add another "; SLOW_DOWN_IO" here if your adapter won't work OK: */
-#define DE600_SLOW_DOWN SLOW_DOWN_IO; SLOW_DOWN_IO; SLOW_DOWN_IO
+/* Add more time here if your adapter won't work OK: */
+#define DE600_SLOW_DOWN udelay(delay_time)
/*
* If you still have trouble reading/writing to the adapter,
@@ -104,6 +104,7 @@ static const char *version =
#include <asm/system.h>
#include <linux/errno.h>
#include <linux/init.h>
+#include <linux/delay.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
@@ -113,6 +114,9 @@ static const char *version =
static unsigned int de600_debug = DE600_DEBUG;
MODULE_PARM(de600_debug, "i");
+static unsigned int delay_time = 10;
+MODULE_PARM(delay_time, "i");
+
#ifdef FAKE_SMALL_MAX
static unsigned long de600_rspace(struct sock *sk);
#include <net/sock.h>
diff --git a/drivers/net/e2100.c b/drivers/net/e2100.c
index 3c2288f6a..62558807a 100644
--- a/drivers/net/e2100.c
+++ b/drivers/net/e2100.c
@@ -44,6 +44,7 @@ static const char *version =
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
+#include <linux/delay.h>
#include <asm/io.h>
#include <asm/system.h>
@@ -150,7 +151,7 @@ __initfunc(int e21_probe1(struct device *dev, int ioaddr))
/* Verify by making certain that there is a 8390 at there. */
outb(E8390_NODMA + E8390_STOP, ioaddr);
- SLOW_DOWN_IO;
+ udelay(1); /* we want to delay one I/O cycle - which is 2MHz */
status = inb(ioaddr);
if (status != 0x21 && status != 0x23)
return ENODEV;
diff --git a/drivers/net/eepro.c b/drivers/net/eepro.c
index bd568c2ab..1b1ac98d2 100644
--- a/drivers/net/eepro.c
+++ b/drivers/net/eepro.c
@@ -102,6 +102,7 @@ static const char *version =
#include <asm/dma.h>
#include <linux/errno.h>
#include <linux/init.h>
+#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
@@ -652,8 +653,8 @@ eepro_open(struct device *dev)
outb(SEL_RESET_CMD, ioaddr);
/* We are supposed to wait for 2 us after a SEL_RESET */
- SLOW_DOWN_IO;
- SLOW_DOWN_IO;
+
+ udelay(2);
lp->tx_start = lp->tx_end = XMT_LOWER_LIMIT << 8; /* or = RCV_RAM */
lp->tx_last = 0;
@@ -695,8 +696,7 @@ eepro_send_packet(struct sk_buff *skb, struct device *dev)
/* Try to restart the adaptor. */
outb(SEL_RESET_CMD, ioaddr);
/* We are supposed to wait for 2 us after a SEL_RESET */
- SLOW_DOWN_IO;
- SLOW_DOWN_IO;
+ udelay(2);
/* Do I also need to flush the transmit buffers here? YES? */
lp->tx_start = lp->tx_end = rcv_ram;
@@ -824,9 +824,9 @@ eepro_close(struct device *dev)
/* Update the statistics here. What statistics? */
/* We are supposed to wait for 200 us after a RESET */
- SLOW_DOWN_IO;
- SLOW_DOWN_IO; /* May not be enough? */
+ udelay(200);
+
MOD_DEC_USE_COUNT;
return 0;
}
@@ -933,8 +933,7 @@ set_multicast_list(struct device *dev)
/* Acknowledge that the MC setup is done */
do { /* We should be doing this in the eepro_interrupt()! */
- SLOW_DOWN_IO;
- SLOW_DOWN_IO;
+ udelay(2);
if (inb(ioaddr + STATUS_REG) & 0x08)
{
i = inb(ioaddr);
@@ -962,7 +961,7 @@ set_multicast_list(struct device *dev)
/* IMPORTANT - the 82595 will be set to Bank 0 after the eeprom is read */
/* The delay between EEPROM clock transitions. */
-#define eeprom_delay() { int _i = 40; while (--_i > 0) { __SLOW_DOWN_IO; }}
+#define eeprom_delay() { udelay(40); }
#define EE_READ_CMD (6 << 6)
int
diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c
index 0f30de74c..4f1243b4e 100644
--- a/drivers/net/eepro100.c
+++ b/drivers/net/eepro100.c
@@ -61,6 +61,7 @@ static int max_interrupt_work = 20;
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/bios32.h>
+#include <linux/delay.h>
#include <asm/processor.h> /* Processor type for cache alignment. */
#include <asm/bitops.h>
#include <asm/io.h>
diff --git a/drivers/net/eexpress.h b/drivers/net/eexpress.h
index ff42bdd0e..28b431268 100644
--- a/drivers/net/eexpress.h
+++ b/drivers/net/eexpress.h
@@ -37,7 +37,7 @@
#define ASIC_RST 0x40
#define i586_RST 0x80
-#define eeprom_delay() { int _i = 40; while (--_i>0) { __SLOW_DOWN_IO; }}
+#define eeprom_delay() { udelay(40); }
/*
* i82586 Memory Configuration
diff --git a/drivers/net/eql.c b/drivers/net/eql.c
index 386708670..685b1f850 100644
--- a/drivers/net/eql.c
+++ b/drivers/net/eql.c
@@ -329,7 +329,7 @@ static int eql_close(struct device *dev)
static int eql_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
{
- if(!suser() && cmd!=EQL_GETMASTRCFG && cmd!=EQL_GETSLAVECFG)
+ if(cmd!=EQL_GETMASTRCFG && cmd!=EQL_GETSLAVECFG && !suser())
return -EPERM;
switch (cmd)
{
diff --git a/drivers/net/hdlcdrv.c b/drivers/net/hdlcdrv.c
index 89f7229e7..e69de29bb 100644
--- a/drivers/net/hdlcdrv.c
+++ b/drivers/net/hdlcdrv.c
@@ -1,1024 +0,0 @@
-/*****************************************************************************/
-
-/*
- * hdlcdrv.c -- HDLC packet radio network driver.
- *
- * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Please note that the GPL allows you to use the driver, NOT the radio.
- * In order to use the radio, you need a license from the communications
- * authority of your country.
- *
- * The driver was derived from Donald Beckers skeleton.c
- * Written 1993-94 by Donald Becker.
- *
- * History:
- * 0.1 21.09.96 Started
- * 18.10.96 Changed to new user space access routines
- * (copy_{to,from}_user)
- * 0.2 21.11.96 various small changes
- * 0.3 03.03.97 fixed (hopefully) IP not working with ax.25 as a module
- * 0.4 16.04.97 init code/data tagged
- * 0.5 30.07.97 made HDLC buffers bigger (solves a problem with the
- * soundmodem driver)
- */
-
-/*****************************************************************************/
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/net.h>
-#include <linux/in.h>
-#include <linux/if.h>
-#include <linux/malloc.h>
-#include <linux/errno.h>
-#include <asm/bitops.h>
-
-#include <linux/netdevice.h>
-#include <linux/if_arp.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/hdlcdrv.h>
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
-/* prototypes for ax25_encapsulate and ax25_rebuild_header */
-#include <net/ax25.h>
-#endif /* CONFIG_AX25 || CONFIG_AX25_MODULE */
-
-/* make genksyms happy */
-#include <linux/ip.h>
-#include <linux/udp.h>
-#include <linux/tcp.h>
-
-/* --------------------------------------------------------------------- */
-
-/*
- * currently this module is supposed to support both module styles, i.e.
- * the old one present up to about 2.1.9, and the new one functioning
- * starting with 2.1.21. The reason is I have a kit allowing to compile
- * this module also under 2.0.x which was requested by several people.
- * This will go in 2.2
- */
-#include <linux/version.h>
-
-#if LINUX_VERSION_CODE >= 0x20100
-#include <asm/uaccess.h>
-#else
-#include <asm/segment.h>
-#include <linux/mm.h>
-
-#undef put_user
-#undef get_user
-
-#define put_user(x,ptr) ({ __put_user((unsigned long)(x),(ptr),sizeof(*(ptr))); 0; })
-#define get_user(x,ptr) ({ x = ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr)))); 0; })
-
-extern inline int copy_from_user(void *to, const void *from, unsigned long n)
-{
- int i = verify_area(VERIFY_READ, from, n);
- if (i)
- return i;
- memcpy_fromfs(to, from, n);
- return 0;
-}
-
-extern inline int copy_to_user(void *to, const void *from, unsigned long n)
-{
- int i = verify_area(VERIFY_WRITE, to, n);
- if (i)
- return i;
- memcpy_tofs(to, from, n);
- return 0;
-}
-#endif
-
-/* --------------------------------------------------------------------- */
-
-#if LINUX_VERSION_CODE < 0x20115
-extern __inline__ void dev_init_buffers(struct device *dev)
-{
- int i;
- for(i=0;i<DEV_NUMBUFFS;i++)
- {
- skb_queue_head_init(&dev->buffs[i]);
- }
-}
-#endif
-
-/* --------------------------------------------------------------------- */
-
-#if LINUX_VERSION_CODE >= 0x20123
-#include <linux/init.h>
-#else
-#define __init
-#define __initdata
-#define __initfunc(x) x
-#endif
-
-/* --------------------------------------------------------------------- */
-
-#if LINUX_VERSION_CODE < 0x20125
-#define test_and_set_bit set_bit
-#define test_and_clear_bit clear_bit
-#endif
-
-/* --------------------------------------------------------------------- */
-
-/*
- * The name of the card. Is used for messages and in the requests for
- * io regions, irqs and dma channels
- */
-
-static char ax25_bcast[7] =
-{'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, '0' << 1};
-static char ax25_test[7] =
-{'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1, '1' << 1};
-
-/* --------------------------------------------------------------------- */
-
-#define KISS_VERBOSE
-
-/* --------------------------------------------------------------------- */
-
-#define PARAM_TXDELAY 1
-#define PARAM_PERSIST 2
-#define PARAM_SLOTTIME 3
-#define PARAM_TXTAIL 4
-#define PARAM_FULLDUP 5
-#define PARAM_HARDWARE 6
-#define PARAM_RETURN 255
-
-/* --------------------------------------------------------------------- */
-
-#define min(a, b) (((a) < (b)) ? (a) : (b))
-#define max(a, b) (((a) > (b)) ? (a) : (b))
-
-/* --------------------------------------------------------------------- */
-/*
- * the CRC routines are stolen from WAMPES
- * by Dieter Deyke
- */
-
-static const unsigned short crc_ccitt_table[] = {
- 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
- 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
- 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
- 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
- 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
- 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
- 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
- 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
- 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
- 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
- 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
- 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
- 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
- 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
- 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
- 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
- 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
- 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
- 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
- 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
- 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
- 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
- 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
- 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
- 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
- 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
- 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
- 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
- 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
- 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
- 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
- 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
-};
-
-/*---------------------------------------------------------------------------*/
-
-static inline void append_crc_ccitt(unsigned char *buffer, int len)
-{
- unsigned int crc = 0xffff;
-
- for (;len>0;len--)
- crc = (crc >> 8) ^ crc_ccitt_table[(crc ^ *buffer++) & 0xff];
- crc ^= 0xffff;
- *buffer++ = crc;
- *buffer++ = crc >> 8;
-}
-
-/*---------------------------------------------------------------------------*/
-
-static inline int check_crc_ccitt(const unsigned char *buf, int cnt)
-{
- unsigned int crc = 0xffff;
-
- for (; cnt > 0; cnt--)
- crc = (crc >> 8) ^ crc_ccitt_table[(crc ^ *buf++) & 0xff];
- return (crc & 0xffff) == 0xf0b8;
-}
-
-/*---------------------------------------------------------------------------*/
-
-#if 0
-static int calc_crc_ccitt(const unsigned char *buf, int cnt)
-{
- unsigned int crc = 0xffff;
-
- for (; cnt > 0; cnt--)
- crc = (crc >> 8) ^ crc_ccitt_table[(crc ^ *buf++) & 0xff];
- crc ^= 0xffff;
- return (crc & 0xffff);
-}
-#endif
-
-/* ---------------------------------------------------------------------- */
-
-#define tenms_to_2flags(s,tenms) ((tenms * s->par.bitrate) / 100 / 16)
-
-/* ---------------------------------------------------------------------- */
-/*
- * The HDLC routines
- */
-
-static int hdlc_rx_add_bytes(struct hdlcdrv_state *s, unsigned int bits,
- int num)
-{
- int added = 0;
-
- while (s->hdlcrx.rx_state && num >= 8) {
- if (s->hdlcrx.len >= sizeof(s->hdlcrx.buffer)) {
- s->hdlcrx.rx_state = 0;
- return 0;
- }
- *s->hdlcrx.bp++ = bits >> (32-num);
- s->hdlcrx.len++;
- num -= 8;
- added += 8;
- }
- return added;
-}
-
-static void hdlc_rx_flag(struct device *dev, struct hdlcdrv_state *s)
-{
- struct sk_buff *skb;
- int pkt_len;
- unsigned char *cp;
-
- if (s->hdlcrx.len < 4)
- return;
- if (!check_crc_ccitt(s->hdlcrx.buffer, s->hdlcrx.len))
- return;
- pkt_len = s->hdlcrx.len - 2 + 1; /* KISS kludge */
- if (!(skb = dev_alloc_skb(pkt_len))) {
- printk("%s: memory squeeze, dropping packet\n",
- s->ifname);
- s->stats.rx_dropped++;
- return;
- }
- skb->dev = dev;
- cp = skb_put(skb, pkt_len);
- *cp++ = 0; /* KISS kludge */
- memcpy(cp, s->hdlcrx.buffer, pkt_len - 1);
- skb->protocol = htons(ETH_P_AX25);
- skb->mac.raw = skb->data;
- netif_rx(skb);
- s->stats.rx_packets++;
-}
-
-void hdlcdrv_receiver(struct device *dev, struct hdlcdrv_state *s)
-{
- int i;
- unsigned int mask1, mask2, mask3, mask4, mask5, mask6, word;
-
- if (!s || s->magic != HDLCDRV_MAGIC)
- return;
- if (test_and_set_bit(0, &s->hdlcrx.in_hdlc_rx))
- return;
-
- while (!hdlcdrv_hbuf_empty(&s->hdlcrx.hbuf)) {
- word = hdlcdrv_hbuf_get(&s->hdlcrx.hbuf);
-
-#ifdef HDLCDRV_DEBUG
- hdlcdrv_add_bitbuffer_word(&s->bitbuf_hdlc, word);
-#endif /* HDLCDRV_DEBUG */
- s->hdlcrx.bitstream >>= 16;
- s->hdlcrx.bitstream |= word << 16;
- s->hdlcrx.bitbuf >>= 16;
- s->hdlcrx.bitbuf |= word << 16;
- s->hdlcrx.numbits += 16;
- for(i = 15, mask1 = 0x1fc00, mask2 = 0x1fe00, mask3 = 0x0fc00,
- mask4 = 0x1f800, mask5 = 0xf800, mask6 = 0xffff;
- i >= 0;
- i--, mask1 <<= 1, mask2 <<= 1, mask3 <<= 1, mask4 <<= 1,
- mask5 <<= 1, mask6 = (mask6 << 1) | 1) {
- if ((s->hdlcrx.bitstream & mask1) == mask1)
- s->hdlcrx.rx_state = 0; /* abort received */
- else if ((s->hdlcrx.bitstream & mask2) == mask3) {
- /* flag received */
- if (s->hdlcrx.rx_state) {
- hdlc_rx_add_bytes(s, s->hdlcrx.bitbuf
- << (8+i),
- s->hdlcrx.numbits
- -8-i);
- hdlc_rx_flag(dev, s);
- }
- s->hdlcrx.len = 0;
- s->hdlcrx.bp = s->hdlcrx.buffer;
- s->hdlcrx.rx_state = 1;
- s->hdlcrx.numbits = i;
- } else if ((s->hdlcrx.bitstream & mask4) == mask5) {
- /* stuffed bit */
- s->hdlcrx.numbits--;
- s->hdlcrx.bitbuf = (s->hdlcrx.bitbuf & (~mask6)) |
- ((s->hdlcrx.bitbuf & mask6) << 1);
- }
- }
- s->hdlcrx.numbits -= hdlc_rx_add_bytes(s, s->hdlcrx.bitbuf,
- s->hdlcrx.numbits);
- }
- clear_bit(0, &s->hdlcrx.in_hdlc_rx);
-}
-
-/* ---------------------------------------------------------------------- */
-
-static void inline do_kiss_params(struct hdlcdrv_state *s,
- unsigned char *data, unsigned long len)
-{
-
-#ifdef KISS_VERBOSE
-#define PKP(a,b) printk(KERN_INFO "%s: channel params: " a "\n", s->ifname, b)
-#else /* KISS_VERBOSE */
-#define PKP(a,b)
-#endif /* KISS_VERBOSE */
-
- if (len < 2)
- return;
- switch(data[0]) {
- case PARAM_TXDELAY:
- s->ch_params.tx_delay = data[1];
- PKP("TX delay = %ums", 10 * s->ch_params.tx_delay);
- break;
- case PARAM_PERSIST:
- s->ch_params.ppersist = data[1];
- PKP("p persistence = %u", s->ch_params.ppersist);
- break;
- case PARAM_SLOTTIME:
- s->ch_params.slottime = data[1];
- PKP("slot time = %ums", s->ch_params.slottime);
- break;
- case PARAM_TXTAIL:
- s->ch_params.tx_tail = data[1];
- PKP("TX tail = %ums", s->ch_params.tx_tail);
- break;
- case PARAM_FULLDUP:
- s->ch_params.fulldup = !!data[1];
- PKP("%s duplex", s->ch_params.fulldup ? "full" : "half");
- break;
- default:
- break;
- }
-#undef PKP
-}
-
-/* ---------------------------------------------------------------------- */
-
-void hdlcdrv_transmitter(struct device *dev, struct hdlcdrv_state *s)
-{
- unsigned int mask1, mask2, mask3;
- int i;
- struct sk_buff *skb;
- int pkt_len;
-
- if (!s || s->magic != HDLCDRV_MAGIC)
- return;
- if (test_and_set_bit(0, &s->hdlctx.in_hdlc_tx))
- return;
- for (;;) {
- if (s->hdlctx.numbits >= 16) {
- if (hdlcdrv_hbuf_full(&s->hdlctx.hbuf)) {
- clear_bit(0, &s->hdlctx.in_hdlc_tx);
- return;
- }
- hdlcdrv_hbuf_put(&s->hdlctx.hbuf, s->hdlctx.bitbuf);
- s->hdlctx.bitbuf >>= 16;
- s->hdlctx.numbits -= 16;
- }
- switch (s->hdlctx.tx_state) {
- default:
- clear_bit(0, &s->hdlctx.in_hdlc_tx);
- return;
- case 0:
- case 1:
- if (s->hdlctx.numflags) {
- s->hdlctx.numflags--;
- s->hdlctx.bitbuf |=
- 0x7e7e << s->hdlctx.numbits;
- s->hdlctx.numbits += 16;
- break;
- }
- if (s->hdlctx.tx_state == 1) {
- clear_bit(0, &s->hdlctx.in_hdlc_tx);
- return;
- }
- if (!(skb = skb_dequeue(&s->send_queue))) {
- int flgs = tenms_to_2flags
- (s, s->ch_params.tx_tail);
- if (flgs < 2)
- flgs = 2;
- s->hdlctx.tx_state = 1;
- s->hdlctx.numflags = flgs;
- break;
- }
- if (skb->data[0] != 0) {
- do_kiss_params(s, skb->data, skb->len);
- dev_kfree_skb(skb, FREE_WRITE);
- break;
- }
- pkt_len = skb->len-1; /* strip KISS byte */
- if (pkt_len >= HDLCDRV_MAXFLEN || pkt_len < 2) {
- s->hdlctx.tx_state = 0;
- s->hdlctx.numflags = 1;
- dev_kfree_skb(skb, FREE_WRITE);
- break;
- }
- memcpy(s->hdlctx.buffer, skb->data+1, pkt_len);
- dev_kfree_skb(skb, FREE_WRITE);
- s->hdlctx.bp = s->hdlctx.buffer;
- append_crc_ccitt(s->hdlctx.buffer, pkt_len);
- s->hdlctx.len = pkt_len+2; /* the appended CRC */
- s->hdlctx.tx_state = 2;
- s->hdlctx.bitstream = 0;
- s->stats.tx_packets++;
- break;
- case 2:
- if (!s->hdlctx.len) {
- s->hdlctx.tx_state = 0;
- s->hdlctx.numflags = 1;
- break;
- }
- s->hdlctx.len--;
- s->hdlctx.bitbuf |= *s->hdlctx.bp <<
- s->hdlctx.numbits;
- s->hdlctx.bitstream >>= 8;
- s->hdlctx.bitstream |= (*s->hdlctx.bp++) << 16;
- mask1 = 0x1f000;
- mask2 = 0x10000;
- mask3 = 0xffffffff >> (31-s->hdlctx.numbits);
- s->hdlctx.numbits += 8;
- for(i = 0; i < 8; i++, mask1 <<= 1, mask2 <<= 1,
- mask3 = (mask3 << 1) | 1) {
- if ((s->hdlctx.bitstream & mask1) != mask1)
- continue;
- s->hdlctx.bitstream &= ~mask2;
- s->hdlctx.bitbuf =
- (s->hdlctx.bitbuf & mask3) |
- ((s->hdlctx.bitbuf &
- (~mask3)) << 1);
- s->hdlctx.numbits++;
- mask3 = (mask3 << 1) | 1;
- }
- break;
- }
- }
-}
-
-/* ---------------------------------------------------------------------- */
-
-static void start_tx(struct device *dev, struct hdlcdrv_state *s)
-{
- s->hdlctx.tx_state = 0;
- s->hdlctx.numflags = tenms_to_2flags(s, s->ch_params.tx_delay);
- s->hdlctx.bitbuf = s->hdlctx.bitstream = s->hdlctx.numbits = 0;
- hdlcdrv_transmitter(dev, s);
- s->hdlctx.ptt = 1;
- s->ptt_keyed++;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static unsigned short random_seed;
-
-static inline unsigned short random_num(void)
-{
- random_seed = 28629 * random_seed + 157;
- return random_seed;
-}
-
-/* ---------------------------------------------------------------------- */
-
-void hdlcdrv_arbitrate(struct device *dev, struct hdlcdrv_state *s)
-{
- if (!s || s->magic != HDLCDRV_MAGIC || s->hdlctx.ptt ||
- skb_queue_empty(&s->send_queue))
- return;
- if (s->ch_params.fulldup) {
- start_tx(dev, s);
- return;
- }
- if (s->hdlcrx.dcd) {
- s->hdlctx.slotcnt = s->ch_params.slottime;
- return;
- }
- if ((--s->hdlctx.slotcnt) > 0)
- return;
- s->hdlctx.slotcnt = s->ch_params.slottime;
- if ((random_num() % 256) > s->ch_params.ppersist)
- return;
- start_tx(dev, s);
-}
-
-/* --------------------------------------------------------------------- */
-/*
- * ===================== network driver interface =========================
- */
-
-static inline int hdlcdrv_paranoia_check(struct device *dev,
- const char *routine)
-{
- if (!dev || !dev->priv ||
- ((struct hdlcdrv_state *)dev->priv)->magic != HDLCDRV_MAGIC) {
- printk(KERN_ERR "hdlcdrv: bad magic number for hdlcdrv_state "
- "struct in routine %s\n", routine);
- return 1;
- }
- return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int hdlcdrv_send_packet(struct sk_buff *skb, struct device *dev)
-{
- struct hdlcdrv_state *sm;
-
- if (hdlcdrv_paranoia_check(dev, "hdlcdrv_send_packet"))
- return 0;
- sm = (struct hdlcdrv_state *)dev->priv;
- skb_queue_tail(&sm->send_queue, skb);
- dev->trans_start = jiffies;
- return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int hdlcdrv_set_mac_address(struct device *dev, void *addr)
-{
- struct sockaddr *sa = (struct sockaddr *)addr;
-
- /* addr is an AX.25 shifted ASCII mac address */
- memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
- return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-#if LINUX_VERSION_CODE >= 0x20119
-static struct net_device_stats *hdlcdrv_get_stats(struct device *dev)
-#else
-static struct enet_statistics *hdlcdrv_get_stats(struct device *dev)
-#endif
-{
- struct hdlcdrv_state *sm;
-
- if (hdlcdrv_paranoia_check(dev, "hdlcdrv_get_stats"))
- return NULL;
- sm = (struct hdlcdrv_state *)dev->priv;
- /*
- * Get the current statistics. This may be called with the
- * card open or closed.
- */
- return &sm->stats;
-}
-
-/* --------------------------------------------------------------------- */
-/*
- * Open/initialize the board. This is called (in the current kernel)
- * sometime after booting when the 'ifconfig' program is run.
- *
- * This routine should set everything up anew at each open, even
- * registers that "should" only need to be set once at boot, so that
- * there is non-reboot way to recover if something goes wrong.
- */
-
-static int hdlcdrv_open(struct device *dev)
-{
- struct hdlcdrv_state *s;
- int i;
-
- if (hdlcdrv_paranoia_check(dev, "hdlcdrv_open"))
- return -EINVAL;
- s = (struct hdlcdrv_state *)dev->priv;
-
- if (dev->start)
- return 0;
- if (!s->ops || !s->ops->open)
- return -ENODEV;
-
- dev->start = 1;
- /*
- * initialise some variables
- */
- s->hdlcrx.hbuf.rd = s->hdlcrx.hbuf.wr = 0;
- s->hdlcrx.in_hdlc_rx = 0;
- s->hdlcrx.rx_state = 0;
-
- s->hdlctx.hbuf.rd = s->hdlctx.hbuf.wr = 0;
- s->hdlctx.in_hdlc_tx = 0;
- s->hdlctx.tx_state = 1;
- s->hdlctx.numflags = 0;
- s->hdlctx.bitstream = s->hdlctx.bitbuf = s->hdlctx.numbits = 0;
- s->hdlctx.ptt = 0;
- s->hdlctx.slotcnt = s->ch_params.slottime;
- s->hdlctx.calibrate = 0;
-
- i = s->ops->open(dev);
- if (i) {
- dev->start = 0;
- return i;
- }
-
- dev->tbusy = 0;
- dev->interrupt = 0;
-
- return 0;
-}
-
-/* --------------------------------------------------------------------- */
-/*
- * The inverse routine to hdlcdrv_open().
- */
-
-static int hdlcdrv_close(struct device *dev)
-{
- struct hdlcdrv_state *s;
- struct sk_buff *skb;
- int i = 0;
-
- if (hdlcdrv_paranoia_check(dev, "hdlcdrv_close"))
- return -EINVAL;
- s = (struct hdlcdrv_state *)dev->priv;
-
- if (!dev->start)
- return 0;
- dev->start = 0;
- dev->tbusy = 1;
-
- if (s->ops && s->ops->close)
- i = s->ops->close(dev);
- /* Free any buffers left in the hardware transmit queue */
- while ((skb = skb_dequeue(&s->send_queue)))
- dev_kfree_skb(skb, FREE_WRITE);
- return i;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int hdlcdrv_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
-{
- struct hdlcdrv_state *s;
- struct hdlcdrv_ioctl bi;
-
- if (hdlcdrv_paranoia_check(dev, "hdlcdrv_ioctl"))
- return -EINVAL;
- s = (struct hdlcdrv_state *)dev->priv;
-
- if (cmd != SIOCDEVPRIVATE) {
- if (s->ops && s->ops->ioctl)
- return s->ops->ioctl(dev, ifr, &bi, cmd);
- return -ENOIOCTLCMD;
- }
- if (copy_from_user(&bi, ifr->ifr_data, sizeof(bi)))
- return -EFAULT;
-
- switch (bi.cmd) {
- default:
- if (s->ops && s->ops->ioctl)
- return s->ops->ioctl(dev, ifr, &bi, cmd);
- return -ENOIOCTLCMD;
-
- case HDLCDRVCTL_GETCHANNELPAR:
- bi.data.cp.tx_delay = s->ch_params.tx_delay;
- bi.data.cp.tx_tail = s->ch_params.tx_tail;
- bi.data.cp.slottime = s->ch_params.slottime;
- bi.data.cp.ppersist = s->ch_params.ppersist;
- bi.data.cp.fulldup = s->ch_params.fulldup;
- break;
-
- case HDLCDRVCTL_SETCHANNELPAR:
- if (!suser())
- return -EACCES;
- s->ch_params.tx_delay = bi.data.cp.tx_delay;
- s->ch_params.tx_tail = bi.data.cp.tx_tail;
- s->ch_params.slottime = bi.data.cp.slottime;
- s->ch_params.ppersist = bi.data.cp.ppersist;
- s->ch_params.fulldup = bi.data.cp.fulldup;
- s->hdlctx.slotcnt = 1;
- return 0;
-
- case HDLCDRVCTL_GETMODEMPAR:
- bi.data.mp.iobase = dev->base_addr;
- bi.data.mp.irq = dev->irq;
- bi.data.mp.dma = dev->dma;
- bi.data.mp.dma2 = s->ptt_out.dma2;
- bi.data.mp.seriobase = s->ptt_out.seriobase;
- bi.data.mp.pariobase = s->ptt_out.pariobase;
- bi.data.mp.midiiobase = s->ptt_out.midiiobase;
- break;
-
- case HDLCDRVCTL_SETMODEMPAR:
- if ((!suser()) || dev->start)
- return -EACCES;
- dev->base_addr = bi.data.mp.iobase;
- dev->irq = bi.data.mp.irq;
- dev->dma = bi.data.mp.dma;
- s->ptt_out.dma2 = bi.data.mp.dma2;
- s->ptt_out.seriobase = bi.data.mp.seriobase;
- s->ptt_out.pariobase = bi.data.mp.pariobase;
- s->ptt_out.midiiobase = bi.data.mp.midiiobase;
- return 0;
-
- case HDLCDRVCTL_GETSTAT:
- bi.data.cs.ptt = hdlcdrv_ptt(s);
- bi.data.cs.dcd = s->hdlcrx.dcd;
- bi.data.cs.ptt_keyed = s->ptt_keyed;
- bi.data.cs.tx_packets = s->stats.tx_packets;
- bi.data.cs.tx_errors = s->stats.tx_errors;
- bi.data.cs.rx_packets = s->stats.rx_packets;
- bi.data.cs.rx_errors = s->stats.rx_errors;
- break;
-
- case HDLCDRVCTL_OLDGETSTAT:
- bi.data.ocs.ptt = hdlcdrv_ptt(s);
- bi.data.ocs.dcd = s->hdlcrx.dcd;
- bi.data.ocs.ptt_keyed = s->ptt_keyed;
-#if LINUX_VERSION_CODE < 0x20100
- bi.data.ocs.stats = s->stats;
-#endif
- break;
-
- case HDLCDRVCTL_CALIBRATE:
- s->hdlctx.calibrate = bi.data.calibrate * s->par.bitrate / 16;
- return 0;
-
- case HDLCDRVCTL_GETSAMPLES:
-#ifndef HDLCDRV_DEBUG
- return -EPERM;
-#else /* HDLCDRV_DEBUG */
- if (s->bitbuf_channel.rd == s->bitbuf_channel.wr)
- return -EAGAIN;
- bi.data.bits =
- s->bitbuf_channel.buffer[s->bitbuf_channel.rd];
- s->bitbuf_channel.rd = (s->bitbuf_channel.rd+1) %
- sizeof(s->bitbuf_channel.buffer);
- break;
-#endif /* HDLCDRV_DEBUG */
-
- case HDLCDRVCTL_GETBITS:
-#ifndef HDLCDRV_DEBUG
- return -EPERM;
-#else /* HDLCDRV_DEBUG */
- if (s->bitbuf_hdlc.rd == s->bitbuf_hdlc.wr)
- return -EAGAIN;
- bi.data.bits =
- s->bitbuf_hdlc.buffer[s->bitbuf_hdlc.rd];
- s->bitbuf_hdlc.rd = (s->bitbuf_hdlc.rd+1) %
- sizeof(s->bitbuf_hdlc.buffer);
- break;
-#endif /* HDLCDRV_DEBUG */
-
- case HDLCDRVCTL_DRIVERNAME:
- if (s->ops && s->ops->drvname) {
- strncpy(bi.data.drivername, s->ops->drvname,
- sizeof(bi.data.drivername));
- break;
- }
- bi.data.drivername[0] = '\0';
- break;
-
- }
- if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi)))
- return -EFAULT;
- return 0;
-
-}
-
-/* --------------------------------------------------------------------- */
-
-/*
- * Check for a network adaptor of this type, and return '0' if one exists.
- * If dev->base_addr == 0, probe all likely locations.
- * If dev->base_addr == 1, always return failure.
- * If dev->base_addr == 2, allocate space for the device and return success
- * (detachable devices only).
- */
-static int hdlcdrv_probe(struct device *dev)
-{
- const struct hdlcdrv_channel_params dflt_ch_params = {
- 20, 2, 10, 40, 0
- };
- struct hdlcdrv_state *s;
-
- if (!dev)
- return -ENXIO;
- /*
- * not a real probe! only initialize data structures
- */
- s = (struct hdlcdrv_state *)dev->priv;
- /*
- * initialize the hdlcdrv_state struct
- */
- s->ch_params = dflt_ch_params;
- s->ptt_keyed = 0;
-
- s->hdlcrx.hbuf.rd = s->hdlcrx.hbuf.wr = 0;
- s->hdlcrx.in_hdlc_rx = 0;
- s->hdlcrx.rx_state = 0;
-
- s->hdlctx.hbuf.rd = s->hdlctx.hbuf.wr = 0;
- s->hdlctx.in_hdlc_tx = 0;
- s->hdlctx.tx_state = 1;
- s->hdlctx.numflags = 0;
- s->hdlctx.bitstream = s->hdlctx.bitbuf = s->hdlctx.numbits = 0;
- s->hdlctx.ptt = 0;
- s->hdlctx.slotcnt = s->ch_params.slottime;
- s->hdlctx.calibrate = 0;
-
-#ifdef HDLCDRV_DEBUG
- s->bitbuf_channel.rd = s->bitbuf_channel.wr = 0;
- s->bitbuf_channel.shreg = 0x80;
-
- s->bitbuf_hdlc.rd = s->bitbuf_hdlc.wr = 0;
- s->bitbuf_hdlc.shreg = 0x80;
-#endif /* HDLCDRV_DEBUG */
-
- /*
- * initialize the device struct
- */
- dev->open = hdlcdrv_open;
- dev->stop = hdlcdrv_close;
- dev->do_ioctl = hdlcdrv_ioctl;
- dev->hard_start_xmit = hdlcdrv_send_packet;
- dev->get_stats = hdlcdrv_get_stats;
-
- /* Fill in the fields of the device structure */
-
- dev_init_buffers(dev);
-
- skb_queue_head_init(&s->send_queue);
-
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
- dev->hard_header = ax25_encapsulate;
- dev->rebuild_header = ax25_rebuild_header;
-#else /* CONFIG_AX25 || CONFIG_AX25_MODULE */
- dev->hard_header = NULL;
- dev->rebuild_header = NULL;
-#endif /* CONFIG_AX25 || CONFIG_AX25_MODULE */
- dev->set_mac_address = hdlcdrv_set_mac_address;
-
- dev->type = ARPHRD_AX25; /* AF_AX25 device */
- dev->hard_header_len = 73; /* We do digipeaters now */
- dev->mtu = 1500; /* eth_mtu is the default */
- dev->addr_len = 7; /* sizeof an ax.25 address */
- memcpy(dev->broadcast, ax25_bcast, 7);
- memcpy(dev->dev_addr, ax25_test, 7);
-
- /* New style flags */
- dev->flags = 0;
-
- return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-int hdlcdrv_register_hdlcdrv(struct device *dev, const struct hdlcdrv_ops *ops,
- unsigned int privsize, char *ifname,
- unsigned int baseaddr, unsigned int irq,
- unsigned int dma)
-{
- struct hdlcdrv_state *s;
-
- if (!dev || !ops)
- return -EACCES;
- if (privsize < sizeof(struct hdlcdrv_state))
- privsize = sizeof(struct hdlcdrv_state);
- memset(dev, 0, sizeof(struct device));
- if (!(s = dev->priv = kmalloc(privsize, GFP_KERNEL)))
- return -ENOMEM;
- /*
- * initialize part of the hdlcdrv_state struct
- */
- memset(s, 0, privsize);
- s->magic = HDLCDRV_MAGIC;
- strncpy(s->ifname, ifname, sizeof(s->ifname));
- s->ops = ops;
- /*
- * initialize part of the device struct
- */
- dev->name = s->ifname;
- dev->if_port = 0;
- dev->init = hdlcdrv_probe;
- dev->start = 0;
- dev->tbusy = 1;
- dev->base_addr = baseaddr;
- dev->irq = irq;
- dev->dma = dma;
- if (register_netdev(dev)) {
- printk(KERN_WARNING "hdlcdrv: cannot register net "
- "device %s\n", s->ifname);
- kfree(dev->priv);
- return -ENXIO;
- }
- MOD_INC_USE_COUNT;
- return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-int hdlcdrv_unregister_hdlcdrv(struct device *dev)
-{
- struct hdlcdrv_state *s;
-
- if (!dev)
- return -EINVAL;
- if (!(s = (struct hdlcdrv_state *)dev->priv))
- return -EINVAL;
- if (s->magic != HDLCDRV_MAGIC)
- return -EINVAL;
- if (dev->start && s->ops->close)
- s->ops->close(dev);
- unregister_netdev(dev);
- kfree(s);
- MOD_DEC_USE_COUNT;
- return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-#if LINUX_VERSION_CODE >= 0x20115
-
-EXPORT_SYMBOL(hdlcdrv_receiver);
-EXPORT_SYMBOL(hdlcdrv_transmitter);
-EXPORT_SYMBOL(hdlcdrv_arbitrate);
-EXPORT_SYMBOL(hdlcdrv_register_hdlcdrv);
-EXPORT_SYMBOL(hdlcdrv_unregister_hdlcdrv);
-
-#else
-
-static struct symbol_table hdlcdrv_syms = {
-#include <linux/symtab_begin.h>
- X(hdlcdrv_receiver),
- X(hdlcdrv_transmitter),
- X(hdlcdrv_arbitrate),
- X(hdlcdrv_register_hdlcdrv),
- X(hdlcdrv_unregister_hdlcdrv),
-#include <linux/symtab_end.h>
-};
-
-#endif
-
-/* --------------------------------------------------------------------- */
-
-#ifdef MODULE
-
-#if LINUX_VERSION_CODE >= 0x20115
-
-MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");
-MODULE_DESCRIPTION("Packet Radio network interface HDLC encoder/decoder");
-
-#endif
-
-/* --------------------------------------------------------------------- */
-
-__initfunc(int init_module(void))
-{
- printk(KERN_INFO "hdlcdrv: (C) 1996 Thomas Sailer HB9JNX/AE4WA\n");
- printk(KERN_INFO "hdlcdrv: version 0.5 compiled " __TIME__ " " __DATE__ "\n");
-#if LINUX_VERSION_CODE < 0x20115
- register_symtab(&hdlcdrv_syms);
-#endif
- return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-void cleanup_module(void)
-{
- printk(KERN_INFO "hdlcdrv: cleanup\n");
-}
-
-#endif /* MODULE */
-/* --------------------------------------------------------------------- */
diff --git a/drivers/net/hp-plus.c b/drivers/net/hp-plus.c
index c7f0a5e5d..0952b8ae0 100644
--- a/drivers/net/hp-plus.c
+++ b/drivers/net/hp-plus.c
@@ -31,6 +31,7 @@ static const char *version =
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
+#include <linux/delay.h>
#include <asm/system.h>
#include <asm/io.h>
@@ -266,7 +267,7 @@ hpp_open(struct device *dev)
/* Reset the 8390 and HP chip. */
option_reg = inw(ioaddr + HPP_OPTION);
outw(option_reg & ~(NICReset + ChipReset), ioaddr + HPP_OPTION);
- SLOW_DOWN_IO; SLOW_DOWN_IO;
+ udelay(5);
/* Unreset the board and enable interrupts. */
outw(option_reg | (EnableIRQ + NICReset + ChipReset), ioaddr + HPP_OPTION);
@@ -307,12 +308,11 @@ hpp_reset_8390(struct device *dev)
outw(option_reg & ~(NICReset + ChipReset), ioaddr + HPP_OPTION);
/* Pause a few cycles for the hardware reset to take place. */
- SLOW_DOWN_IO;
- SLOW_DOWN_IO;
+ udelay(5);
ei_status.txing = 0;
outw(option_reg | (EnableIRQ + NICReset + ChipReset), ioaddr + HPP_OPTION);
- SLOW_DOWN_IO; SLOW_DOWN_IO;
+ udelay(5);
if ((inb_p(ioaddr+NIC_OFFSET+EN0_ISR) & ENISR_RESET) == 0)
diff --git a/drivers/net/hp.c b/drivers/net/hp.c
index c31f97842..156ed5f14 100644
--- a/drivers/net/hp.c
+++ b/drivers/net/hp.c
@@ -233,11 +233,10 @@ hp_reset_8390(struct device *dev)
outb_p(0x00, hp_base + HP_CONFIGURE);
ei_status.txing = 0;
/* Pause just a few cycles for the hardware reset to take place. */
- SLOW_DOWN_IO;
- SLOW_DOWN_IO;
+ udelay(5);
outb_p(saved_config, hp_base + HP_CONFIGURE);
- SLOW_DOWN_IO; SLOW_DOWN_IO;
+ udelay(5);
if ((inb_p(hp_base+NIC_OFFSET+EN0_ISR) & ENISR_RESET) == 0)
printk("%s: hp_reset_8390() did not complete.\n", dev->name);
diff --git a/drivers/net/mkiss.c b/drivers/net/mkiss.c
index 562a27681..e69de29bb 100644
--- a/drivers/net/mkiss.c
+++ b/drivers/net/mkiss.c
@@ -1,1134 +0,0 @@
-/*
- * MKISS Driver
- *
- * This module:
- * This module is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
- * This module implements the AX.25 protocol for kernel-based
- * devices like TTYs. It interfaces between a raw TTY, and the
- * kernel's AX.25 protocol layers, just like slip.c.
- * AX.25 needs to be seperated from slip.c while slip.c is no
- * longer a static kernel device since it is a module.
- * This method clears the way to implement other kiss protocols
- * like mkiss smack g8bpq ..... so far only mkiss is implemented.
- *
- * Hans Alblas <hans@esrac.ele.tue.nl>
- *
- * History
- * Jonathan (G4KLX) Fixed to match Linux networking changes - 2.1.15.
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <asm/system.h>
-#include <asm/segment.h>
-#include <asm/bitops.h>
-#include <asm/uaccess.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/in.h>
-#include <linux/inet.h>
-#include <linux/tty.h>
-#include <linux/errno.h>
-#include <linux/netdevice.h>
-#include <linux/major.h>
-#include <linux/init.h>
-
-#include <linux/timer.h>
-
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/if_arp.h>
-
-#include <net/ax25.h>
-
-#include "mkiss.h"
-
-#ifdef CONFIG_INET
-#include <linux/ip.h>
-#include <linux/tcp.h>
-#endif
-
-#ifdef MODULE
-#define AX25_VERSION "AX25-MODULAR-NET3.019-NEWTTY"
-#define min(a,b) (a < b ? a : b)
-#else
-#define AX25_VERSION "AX25-NET3.019-NEWTTY"
-#endif
-
-#define NR_MKISS 4
-#define MKISS_SERIAL_TYPE_NORMAL 1
-
-struct mkiss_channel {
- int magic; /* magic word */
- int init; /* channel exists? */
- struct tty_struct *tty; /* link to tty control structure */
-};
-
-typedef struct ax25_ctrl {
- char if_name[8]; /* "ax0\0" .. "ax99999\0" */
- struct ax_disp ctrl; /* */
- struct device dev; /* the device */
-} ax25_ctrl_t;
-
-static ax25_ctrl_t **ax25_ctrls = NULL;
-
-int ax25_maxdev = AX25_MAXDEV; /* Can be overridden with insmod! */
-
-static struct tty_ldisc ax_ldisc;
-static struct tty_driver mkiss_driver;
-static int mkiss_refcount;
-static struct tty_struct *mkiss_table[NR_MKISS];
-static struct termios *mkiss_termios[NR_MKISS];
-static struct termios *mkiss_termios_locked[NR_MKISS];
-struct mkiss_channel MKISS_Info[NR_MKISS];
-
-static int ax25_init(struct device *);
-static int mkiss_init(void);
-static int mkiss_write(struct tty_struct *, int, const unsigned char *, int);
-static int kiss_esc(unsigned char *, unsigned char *, int);
-static void kiss_unesc(struct ax_disp *, unsigned char);
-
-/* Find a free channel, and link in this `tty' line. */
-static inline struct ax_disp *ax_alloc(void)
-{
- ax25_ctrl_t *axp;
- int i;
-
- if (ax25_ctrls == NULL) /* Master array missing ! */
- return NULL;
-
- for (i = 0; i < ax25_maxdev; i++) {
- axp = ax25_ctrls[i];
-
- /* Not allocated ? */
- if (axp == NULL)
- break;
-
- /* Not in use ? */
- if (!test_and_set_bit(AXF_INUSE, &axp->ctrl.flags))
- break;
- }
-
- /* Sorry, too many, all slots in use */
- if (i >= ax25_maxdev)
- return NULL;
-
- /* If no channels are available, allocate one */
- if (axp == NULL && (ax25_ctrls[i] = kmalloc(sizeof(ax25_ctrl_t), GFP_KERNEL)) != NULL) {
- axp = ax25_ctrls[i];
- memset(axp, 0, sizeof(ax25_ctrl_t));
-
- /* Initialize channel control data */
- set_bit(AXF_INUSE, &axp->ctrl.flags);
- sprintf(axp->if_name, "ax%d", i++);
- axp->ctrl.tty = NULL;
- axp->dev.name = axp->if_name;
- axp->dev.base_addr = i;
- axp->dev.priv = (void *)&axp->ctrl;
- axp->dev.next = NULL;
- axp->dev.init = ax25_init;
- }
-
- if (axp != NULL) {
- /*
- * register device so that it can be ifconfig'ed
- * ax25_init() will be called as a side-effect
- * SIDE-EFFECT WARNING: ax25_init() CLEARS axp->ctrl !
- */
- if (register_netdev(&axp->dev) == 0) {
- /* (Re-)Set the INUSE bit. Very Important! */
- set_bit(AXF_INUSE, &axp->ctrl.flags);
- axp->ctrl.dev = &axp->dev;
- axp->dev.priv = (void *)&axp->ctrl;
-
- return &axp->ctrl;
- } else {
- clear_bit(AXF_INUSE,&axp->ctrl.flags);
- printk(KERN_ERR "mkiss: ax_alloc() - register_netdev() failure.\n");
- }
- }
-
- return NULL;
-}
-
-/* Free an AX25 channel. */
-static inline void ax_free(struct ax_disp *ax)
-{
- /* Free all AX25 frame buffers. */
- if (ax->rbuff)
- kfree(ax->rbuff);
- ax->rbuff = NULL;
- if (ax->xbuff)
- kfree(ax->xbuff);
- ax->xbuff = NULL;
- if (!test_and_clear_bit(AXF_INUSE, &ax->flags))
- printk(KERN_ERR "mkiss: %s: ax_free for already free unit.\n", ax->dev->name);
-}
-
-static void ax_changedmtu(struct ax_disp *ax)
-{
- struct device *dev = ax->dev;
- unsigned char *xbuff, *rbuff, *oxbuff, *orbuff;
- int len;
- unsigned long flags;
-
- len = dev->mtu * 2;
-
- /*
- * allow for arrival of larger UDP packets, even if we say not to
- * also fixes a bug in which SunOS sends 512-byte packets even with
- * an MSS of 128
- */
- if (len < 576 * 2)
- len = 576 * 2;
-
- xbuff = kmalloc(len + 4, GFP_ATOMIC);
- rbuff = kmalloc(len + 4, GFP_ATOMIC);
-
- if (xbuff == NULL || rbuff == NULL) {
- printk(KERN_ERR "mkiss: %s: unable to grow ax25 buffers, MTU change cancelled.\n",
- ax->dev->name);
- dev->mtu = ax->mtu;
- if (xbuff != NULL)
- kfree(xbuff);
- if (rbuff != NULL)
- kfree(rbuff);
- return;
- }
-
- save_flags(flags);
- cli();
-
- oxbuff = ax->xbuff;
- ax->xbuff = xbuff;
- orbuff = ax->rbuff;
- ax->rbuff = rbuff;
-
- if (ax->xleft) {
- if (ax->xleft <= len) {
- memcpy(ax->xbuff, ax->xhead, ax->xleft);
- } else {
- ax->xleft = 0;
- ax->tx_dropped++;
- }
- }
-
- ax->xhead = ax->xbuff;
-
- if (ax->rcount) {
- if (ax->rcount <= len) {
- memcpy(ax->rbuff, orbuff, ax->rcount);
- } else {
- ax->rcount = 0;
- ax->rx_over_errors++;
- set_bit(AXF_ERROR, &ax->flags);
- }
- }
-
- ax->mtu = dev->mtu + 73;
- ax->buffsize = len;
-
- restore_flags(flags);
-
- if (oxbuff != NULL)
- kfree(oxbuff);
- if (orbuff != NULL)
- kfree(orbuff);
-}
-
-
-/* Set the "sending" flag. This must be atomic, hence the ASM. */
-static inline void ax_lock(struct ax_disp *ax)
-{
- if (test_and_set_bit(0, (void *)&ax->dev->tbusy))
- printk(KERN_ERR "mkiss: %s: trying to lock already locked device!\n", ax->dev->name);
-}
-
-
-/* Clear the "sending" flag. This must be atomic, hence the ASM. */
-static inline void ax_unlock(struct ax_disp *ax)
-{
- if (!test_and_clear_bit(0, (void *)&ax->dev->tbusy))
- printk(KERN_ERR "mkiss: %s: trying to unlock already unlocked device!\n", ax->dev->name);
-}
-
-/* Send one completely decapsulated AX.25 packet to the AX.25 layer. */
-static void ax_bump(struct ax_disp *ax)
-{
- struct ax_disp *tmp_ax;
- struct sk_buff *skb;
- struct mkiss_channel *mkiss;
- int count;
-
- tmp_ax = ax;
-
- if (ax->rbuff[0] > 0x0f) {
- if (ax->mkiss != NULL) {
- mkiss= ax->mkiss->tty->driver_data;
- if (mkiss->magic == MKISS_DRIVER_MAGIC)
- tmp_ax = ax->mkiss;
- }
- }
-
- count = ax->rcount;
-
- if ((skb = dev_alloc_skb(count)) == NULL) {
- printk(KERN_ERR "mkiss: %s: memory squeeze, dropping packet.\n", ax->dev->name);
- ax->rx_dropped++;
- return;
- }
-
- skb->dev = tmp_ax->dev;
- memcpy(skb_put(skb,count), ax->rbuff, count);
- skb->mac.raw = skb->data;
- skb->protocol = htons(ETH_P_AX25);
- netif_rx(skb);
- tmp_ax->rx_packets++;
-}
-
-/* Encapsulate one AX.25 packet and stuff into a TTY queue. */
-static void ax_encaps(struct ax_disp *ax, unsigned char *icp, int len)
-{
- unsigned char *p;
- int actual, count;
- struct mkiss_channel *mkiss = ax->tty->driver_data;
-
- if (ax->mtu != ax->dev->mtu + 73) /* Someone has been ifconfigging */
- ax_changedmtu(ax);
-
- if (len > ax->mtu) { /* Sigh, shouldn't occur BUT ... */
- len = ax->mtu;
- printk(KERN_ERR "mkiss: %s: truncating oversized transmit packet!\n", ax->dev->name);
- ax->tx_dropped++;
- ax_unlock(ax);
- return;
- }
-
- p = icp;
-
- if (mkiss->magic != MKISS_DRIVER_MAGIC) {
- count = kiss_esc(p, (unsigned char *)ax->xbuff, len);
- ax->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
- actual = ax->tty->driver.write(ax->tty, 0, ax->xbuff, count);
- ax->tx_packets++;
- ax->dev->trans_start = jiffies;
- ax->xleft = count - actual;
- ax->xhead = ax->xbuff + actual;
- } else {
- count = kiss_esc(p, (unsigned char *) ax->mkiss->xbuff, len);
- ax->mkiss->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
- actual = ax->mkiss->tty->driver.write(ax->mkiss->tty, 0, ax->mkiss->xbuff, count);
- ax->tx_packets++;
- ax->mkiss->dev->trans_start = jiffies;
- ax->mkiss->xleft = count - actual;
- ax->mkiss->xhead = ax->mkiss->xbuff + actual;
- }
-}
-
-/*
- * Called by the driver when there's room for more data. If we have
- * more packets to send, we send them here.
- */
-static void ax25_write_wakeup(struct tty_struct *tty)
-{
- int actual;
- struct ax_disp *ax = (struct ax_disp *)tty->disc_data;
- struct mkiss_channel *mkiss;
-
- /* First make sure we're connected. */
- if (ax == NULL || ax->magic != AX25_MAGIC || !ax->dev->start)
- return;
- if (ax->xleft <= 0) {
- /* Now serial buffer is almost free & we can start
- * transmission of another packet
- */
- tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
-
- if (ax->mkiss != NULL) {
- mkiss= ax->mkiss->tty->driver_data;
- if (mkiss->magic == MKISS_DRIVER_MAGIC)
- ax_unlock(ax->mkiss);
- }
-
- ax_unlock(ax);
- mark_bh(NET_BH);
- return;
- }
-
- actual = tty->driver.write(tty, 0, ax->xhead, ax->xleft);
- ax->xleft -= actual;
- ax->xhead += actual;
-}
-
-/* Encapsulate an AX.25 packet and kick it into a TTY queue. */
-static int ax_xmit(struct sk_buff *skb, struct device *dev)
-{
- struct ax_disp *ax = (struct ax_disp*)dev->priv;
- struct mkiss_channel *mkiss = ax->tty->driver_data;
- struct ax_disp *tmp_ax;
-
- tmp_ax = NULL;
-
- if (mkiss->magic == MKISS_DRIVER_MAGIC) {
- if (skb->data[0] < 0x10)
- skb->data[0] = skb->data[0] + 0x10;
- tmp_ax = ax->mkiss;
- }
-
- if (!dev->start) {
- printk(KERN_ERR "mkiss: %s: xmit call when iface is down\n", dev->name);
- return 1;
- }
-
- if (tmp_ax != NULL)
- if (tmp_ax->dev->tbusy)
- return 1;
-
- if (tmp_ax != NULL)
- if (dev->tbusy) {
- printk(KERN_ERR "mkiss: dev busy while serial dev is free\n");
- ax_unlock(ax);
- }
-
- if (dev->tbusy) {
- /*
- * May be we must check transmitter timeout here ?
- * 14 Oct 1994 Dmitry Gorodchanin.
- */
- if (jiffies - dev->trans_start < 20 * HZ) {
- /* 20 sec timeout not reached */
- return 1;
- }
-
- printk(KERN_ERR "mkiss: %s: transmit timed out, %s?\n", dev->name,
- (ax->tty->driver.chars_in_buffer(ax->tty) || ax->xleft) ?
- "bad line quality" : "driver error");
-
- ax->xleft = 0;
- ax->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
- ax_unlock(ax);
- }
-
- /* We were not busy, so we are now... :-) */
- if (skb != NULL) {
- ax_lock(ax);
- if (tmp_ax != NULL)
- ax_lock(tmp_ax);
- ax_encaps(ax, skb->data, skb->len);
- kfree_skb(skb, FREE_WRITE);
- }
-
- return 0;
-}
-
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
-
-/* Return the frame type ID */
-static int ax_header(struct sk_buff *skb, struct device *dev, unsigned short type,
- void *daddr, void *saddr, unsigned len)
-{
-#ifdef CONFIG_INET
- if (type != htons(ETH_P_AX25))
- return ax25_encapsulate(skb, dev, type, daddr, saddr, len);
-#endif
- return 0;
-}
-
-
-static int ax_rebuild_header(struct sk_buff *skb)
-{
-#ifdef CONFIG_INET
- return ax25_rebuild_header(skb);
-#else
- return 0;
-#endif
-}
-
-#endif /* CONFIG_{AX25,AX25_MODULE} */
-
-/* Open the low-level part of the AX25 channel. Easy! */
-static int ax_open(struct device *dev)
-{
- struct ax_disp *ax = (struct ax_disp*)dev->priv;
- unsigned long len;
-
- if (ax->tty == NULL)
- return -ENODEV;
-
- /*
- * Allocate the frame buffers:
- *
- * rbuff Receive buffer.
- * xbuff Transmit buffer.
- * cbuff Temporary compression buffer.
- */
- len = dev->mtu * 2;
-
- /*
- * allow for arrival of larger UDP packets, even if we say not to
- * also fixes a bug in which SunOS sends 512-byte packets even with
- * an MSS of 128
- */
- if (len < 576 * 2)
- len = 576 * 2;
-
- if ((ax->rbuff = kmalloc(len + 4, GFP_KERNEL)) == NULL)
- goto norbuff;
-
- if ((ax->xbuff = kmalloc(len + 4, GFP_KERNEL)) == NULL)
- goto noxbuff;
-
- ax->mtu = dev->mtu + 73;
- ax->buffsize = len;
- ax->rcount = 0;
- ax->xleft = 0;
-
- ax->flags &= (1 << AXF_INUSE); /* Clear ESCAPE & ERROR flags */
- dev->tbusy = 0;
- dev->start = 1;
-
- return 0;
-
- /* Cleanup */
- kfree(ax->xbuff);
-
-noxbuff:
- kfree(ax->rbuff);
-
-norbuff:
- return -ENOMEM;
-}
-
-
-/* Close the low-level part of the AX25 channel. Easy! */
-static int ax_close(struct device *dev)
-{
- struct ax_disp *ax = (struct ax_disp*)dev->priv;
-
- if (ax->tty == NULL)
- return -EBUSY;
-
- ax->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
-
- dev->tbusy = 1;
- dev->start = 0;
-
- return 0;
-}
-
-static int ax25_receive_room(struct tty_struct *tty)
-{
- return 65536; /* We can handle an infinite amount of data. :-) */
-}
-
-/*
- * Handle the 'receiver data ready' interrupt.
- * This function is called by the 'tty_io' module in the kernel when
- * a block of data has been received, which can now be decapsulated
- * and sent on to the AX.25 layer for further processing.
- */
-static void ax25_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count)
-{
- struct ax_disp *ax = (struct ax_disp *)tty->disc_data;
-
- if (ax == NULL || ax->magic != AX25_MAGIC || !ax->dev->start)
- return;
-
- /*
- * Argh! mtu change time! - costs us the packet part received
- * at the change
- */
- if (ax->mtu != ax->dev->mtu + 73)
- ax_changedmtu(ax);
-
- /* Read the characters out of the buffer */
- while (count--) {
- if (fp != NULL && *fp++) {
- if (!test_and_set_bit(AXF_ERROR, &ax->flags))
- ax->rx_errors++;
- cp++;
- continue;
- }
-
- kiss_unesc(ax, *cp++);
- }
-}
-
-static int ax25_open(struct tty_struct *tty)
-{
- struct ax_disp *ax = (struct ax_disp *)tty->disc_data;
- struct ax_disp *tmp_ax;
- struct mkiss_channel *mkiss;
- int err, cnt;
-
- /* First make sure we're not already connected. */
- if (ax && ax->magic == AX25_MAGIC)
- return -EEXIST;
-
- /* OK. Find a free AX25 channel to use. */
- if ((ax = ax_alloc()) == NULL)
- return -ENFILE;
-
- ax->tty = tty;
- tty->disc_data = ax;
-
- ax->mkiss = NULL;
- tmp_ax = NULL;
-
- if (tty->driver.flush_buffer)
- tty->driver.flush_buffer(tty);
- if (tty->ldisc.flush_buffer)
- tty->ldisc.flush_buffer(tty);
-
- /* Restore default settings */
- ax->dev->type = ARPHRD_AX25;
-
- /* Perform the low-level AX25 initialization. */
- if ((err = ax_open(ax->dev)))
- return err;
-
- mkiss= ax->tty->driver_data;
-
- if (mkiss->magic == MKISS_DRIVER_MAGIC) {
- for (cnt = 1; cnt < ax25_maxdev; cnt++) {
- if (ax25_ctrls[cnt]) {
- if (ax25_ctrls[cnt]->dev.start) {
- if (ax == &ax25_ctrls[cnt]->ctrl) {
- cnt--;
- tmp_ax = &ax25_ctrls[cnt]->ctrl;
- break;
- }
- }
- }
- }
- }
-
- if (tmp_ax != NULL) {
- ax->mkiss = tmp_ax;
- tmp_ax->mkiss = ax;
- }
-
- MOD_INC_USE_COUNT;
-
- /* Done. We have linked the TTY line to a channel. */
- return ax->dev->base_addr;
-}
-
-static void ax25_close(struct tty_struct *tty)
-{
- struct ax_disp *ax = (struct ax_disp *)tty->disc_data;
- int mkiss ;
-
- /* First make sure we're connected. */
- if (ax == NULL || ax->magic != AX25_MAGIC)
- return;
-
- mkiss = ax->mode;
- if (ax->dev->flags & IFF_UP)
- {
- dev_lock_wait();
- dev_close(ax->dev);
- dev_unlock_list();
- }
-
- tty->disc_data = 0;
- ax->tty = NULL;
-
- /* VSV = very important to remove timers */
- ax_free(ax);
- unregister_netdev(ax->dev);
-
- MOD_DEC_USE_COUNT;
-}
-
-
-static struct net_device_stats *ax_get_stats(struct device *dev)
-{
- static struct net_device_stats stats;
- struct ax_disp *ax = (struct ax_disp*)dev->priv;
-
- memset(&stats, 0, sizeof(struct net_device_stats));
-
- stats.rx_packets = ax->rx_packets;
- stats.tx_packets = ax->tx_packets;
- stats.rx_dropped = ax->rx_dropped;
- stats.tx_dropped = ax->tx_dropped;
- stats.tx_errors = ax->tx_errors;
- stats.rx_errors = ax->rx_errors;
- stats.rx_over_errors = ax->rx_over_errors;
-
- return &stats;
-}
-
-
-/************************************************************************
- * STANDARD ENCAPSULATION *
- ************************************************************************/
-
-int kiss_esc(unsigned char *s, unsigned char *d, int len)
-{
- unsigned char *ptr = d;
- unsigned char c;
-
- /*
- * Send an initial END character to flush out any
- * data that may have accumulated in the receiver
- * due to line noise.
- */
-
- *ptr++ = END;
-
- while (len-- > 0) {
- switch (c = *s++) {
- case END:
- *ptr++ = ESC;
- *ptr++ = ESC_END;
- break;
- case ESC:
- *ptr++ = ESC;
- *ptr++ = ESC_ESC;
- break;
- default:
- *ptr++ = c;
- break;
- }
- }
-
- *ptr++ = END;
-
- return ptr - d;
-}
-
-static void kiss_unesc(struct ax_disp *ax, unsigned char s)
-{
- switch (s) {
- case END:
- /* drop keeptest bit = VSV */
- if (test_bit(AXF_KEEPTEST, &ax->flags))
- clear_bit(AXF_KEEPTEST, &ax->flags);
-
- if (!test_and_clear_bit(AXF_ERROR, &ax->flags) && (ax->rcount > 2))
- ax_bump(ax);
-
- clear_bit(AXF_ESCAPE, &ax->flags);
- ax->rcount = 0;
- return;
-
- case ESC:
- set_bit(AXF_ESCAPE, &ax->flags);
- return;
- case ESC_ESC:
- if (test_and_clear_bit(AXF_ESCAPE, &ax->flags))
- s = ESC;
- break;
- case ESC_END:
- if (test_and_clear_bit(AXF_ESCAPE, &ax->flags))
- s = END;
- break;
- }
-
- if (!test_bit(AXF_ERROR, &ax->flags)) {
- if (ax->rcount < ax->buffsize) {
- ax->rbuff[ax->rcount++] = s;
- return;
- }
-
- ax->rx_over_errors++;
- set_bit(AXF_ERROR, &ax->flags);
- }
-}
-
-
-int ax_set_mac_address(struct device *dev, void *addr)
-{
- int err;
-
- if ((err = verify_area(VERIFY_READ, addr, AX25_ADDR_LEN)) != 0)
- return err;
-
- /* addr is an AX.25 shifted ASCII mac address */
- copy_from_user(dev->dev_addr, addr, AX25_ADDR_LEN);
-
- return 0;
-}
-
-static int ax_set_dev_mac_address(struct device *dev, void *addr)
-{
- struct sockaddr *sa = addr;
-
- memcpy(dev->dev_addr, sa->sa_data, AX25_ADDR_LEN);
-
- return 0;
-}
-
-
-/* Perform I/O control on an active ax25 channel. */
-static int ax25_disp_ioctl(struct tty_struct *tty, void *file, int cmd, void *arg)
-{
- struct ax_disp *ax = (struct ax_disp *)tty->disc_data;
- int err;
- unsigned int tmp;
-
- /* First make sure we're connected. */
- if (ax == NULL || ax->magic != AX25_MAGIC)
- return -EINVAL;
-
- switch (cmd) {
- case SIOCGIFNAME:
- if ((err = verify_area(VERIFY_WRITE, arg, strlen(ax->dev->name) + 1)) != 0)
- return err;
- copy_to_user(arg, ax->dev->name, strlen(ax->dev->name) + 1);
- return 0;
-
- case SIOCGIFENCAP:
- if ((err = verify_area(VERIFY_WRITE, arg, sizeof(int))) != 0)
- return err;
- put_user(4, (int *)arg);
- return 0;
-
- case SIOCSIFENCAP:
- if ((err = verify_area(VERIFY_READ, arg, sizeof(int))) != 0)
- return err;
- get_user(tmp, (int *)arg);
- ax->mode = tmp;
- ax->dev->addr_len = AX25_ADDR_LEN; /* sizeof an AX.25 addr */
- ax->dev->hard_header_len = AX25_KISS_HEADER_LEN + AX25_MAX_HEADER_LEN + 3;
- ax->dev->type = ARPHRD_AX25;
- return 0;
-
- case SIOCSIFHWADDR:
- return ax_set_mac_address(ax->dev, arg);
-
- default:
- return -ENOIOCTLCMD;
- }
-}
-
-static int ax_open_dev(struct device *dev)
-{
- struct ax_disp *ax = (struct ax_disp*)dev->priv;
-
- if (ax->tty==NULL)
- return -ENODEV;
-
- return 0;
-}
-
-/* Initialize AX25 control device -- register AX25 line discipline */
-__initfunc(int mkiss_init_ctrl_dev(void))
-{
- int status;
-
- if (ax25_maxdev < 4) ax25_maxdev = 4; /* Sanity */
-
- if ((ax25_ctrls = kmalloc(sizeof(void*) * ax25_maxdev, GFP_KERNEL)) == NULL) {
- printk(KERN_ERR "mkiss: Can't allocate ax25_ctrls[] array ! No mkiss available\n");
- return -ENOMEM;
- }
-
- /* Clear the pointer array, we allocate devices when we need them */
- memset(ax25_ctrls, 0, sizeof(void*) * ax25_maxdev); /* Pointers */
-
- /* Fill in our line protocol discipline, and register it */
- memset(&ax_ldisc, 0, sizeof(ax_ldisc));
- ax_ldisc.magic = TTY_LDISC_MAGIC;
- ax_ldisc.name = "mkiss";
- ax_ldisc.flags = 0;
- ax_ldisc.open = ax25_open;
- ax_ldisc.close = ax25_close;
- ax_ldisc.read = NULL;
- ax_ldisc.write = NULL;
- ax_ldisc.ioctl = (int (*)(struct tty_struct *, struct file *, unsigned int, unsigned long))ax25_disp_ioctl;
- ax_ldisc.poll = NULL;
-
- ax_ldisc.receive_buf = ax25_receive_buf;
- ax_ldisc.receive_room = ax25_receive_room;
- ax_ldisc.write_wakeup = ax25_write_wakeup;
-
- if ((status = tty_register_ldisc(N_AX25, &ax_ldisc)) != 0)
- printk(KERN_ERR "mkiss: can't register line discipline (err = %d)\n", status);
-
- mkiss_init();
-
-#ifdef MODULE
- return status;
-#else
- /*
- * Return "not found", so that dev_init() will unlink
- * the placeholder device entry for us.
- */
- return ENODEV;
-#endif
-}
-
-
-/* Initialize the driver. Called by network startup. */
-
-static int ax25_init(struct device *dev)
-{
- struct ax_disp *ax = (struct ax_disp*)dev->priv;
-
- static char ax25_bcast[AX25_ADDR_LEN] =
- {'Q'<<1,'S'<<1,'T'<<1,' '<<1,' '<<1,' '<<1,'0'<<1};
- static char ax25_test[AX25_ADDR_LEN] =
- {'L'<<1,'I'<<1,'N'<<1,'U'<<1,'X'<<1,' '<<1,'1'<<1};
-
- if (ax == NULL) /* Allocation failed ?? */
- return -ENODEV;
-
- /* Set up the "AX25 Control Block". (And clear statistics) */
- memset(ax, 0, sizeof (struct ax_disp));
- ax->magic = AX25_MAGIC;
- ax->dev = dev;
-
- /* Finish setting up the DEVICE info. */
- dev->mtu = AX_MTU;
- dev->hard_start_xmit = ax_xmit;
- dev->open = ax_open_dev;
- dev->stop = ax_close;
- dev->get_stats = ax_get_stats;
-#ifdef HAVE_SET_MAC_ADDR
- dev->set_mac_address = ax_set_dev_mac_address;
-#endif
- dev->hard_header_len = 0;
- dev->addr_len = 0;
- dev->type = ARPHRD_AX25;
- dev->tx_queue_len = 10;
-
- memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN);
- memcpy(dev->dev_addr, ax25_test, AX25_ADDR_LEN);
-
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
- dev->hard_header = ax_header;
- dev->rebuild_header = ax_rebuild_header;
-#endif
-
- dev_init_buffers(dev);
-
- /* New-style flags. */
- dev->flags = 0;
-
- return 0;
-}
-
-static int mkiss_open(struct tty_struct *tty, struct file *filp)
-{
- struct mkiss_channel *mkiss;
- int chan;
-
- chan = MINOR(tty->device) - tty->driver.minor_start;
-
- if (chan < 0 || chan >= NR_MKISS)
- return -ENODEV;
-
- mkiss = &MKISS_Info[chan];
-
- mkiss->magic = MKISS_DRIVER_MAGIC;
- mkiss->init = 1;
- mkiss->tty = tty;
-
- tty->driver_data = mkiss;
-
- tty->termios->c_iflag = IGNBRK | IGNPAR;
- tty->termios->c_cflag = B9600 | CS8 | CLOCAL;
- tty->termios->c_cflag &= ~CBAUD;
-
- return 0;
-}
-
-static void mkiss_close(struct tty_struct *tty, struct file * filp)
-{
- struct mkiss_channel *mkiss = tty->driver_data;
-
- if (mkiss == NULL || mkiss->magic != MKISS_DRIVER_MAGIC)
- return;
-
- mkiss->tty = NULL;
- mkiss->init = 0;
- tty->stopped = 0;
-}
-
-static int mkiss_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count)
-{
- return 0;
-}
-
-static int mkiss_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
-{
- /* Ignore serial ioctl's */
- switch (cmd) {
- case TCSBRK:
- case TIOCMGET:
- case TIOCMBIS:
- case TIOCMBIC:
- case TIOCMSET:
- case TCSETS:
- case TCSETSF: /* should flush first, but... */
- case TCSETSW: /* should wait until flush, but... */
- return 0;
- default:
- return -ENOIOCTLCMD;
- }
-}
-
-
-static void mkiss_dummy(struct tty_struct *tty)
-{
- struct mkiss_channel *mkiss = tty->driver_data;
-
- if (tty == NULL)
- return;
-
- if (mkiss == NULL)
- return;
-}
-
-static void mkiss_dummy2(struct tty_struct *tty, unsigned char ch)
-{
- struct mkiss_channel *mkiss = tty->driver_data;
-
- if (tty == NULL)
- return;
-
- if (mkiss == NULL)
- return;
-}
-
-
-static int mkiss_write_room(struct tty_struct * tty)
-{
- struct mkiss_channel *mkiss = tty->driver_data;
-
- if (tty == NULL)
- return 0;
-
- if (mkiss == NULL)
- return 0;
-
- return 65536; /* We can handle an infinite amount of data. :-) */
-}
-
-
-static int mkiss_chars_in_buffer(struct tty_struct *tty)
-{
- struct mkiss_channel *mkiss = tty->driver_data;
-
- if (tty == NULL)
- return 0;
-
- if (mkiss == NULL)
- return 0;
-
- return 0;
-}
-
-
-static void mkiss_set_termios(struct tty_struct *tty, struct termios *old_termios)
-{
- /* we don't do termios */
-}
-
-/* ******************************************************************** */
-/* * Init MKISS driver * */
-/* ******************************************************************** */
-
-__initfunc(static int mkiss_init(void))
-{
- memset(&mkiss_driver, 0, sizeof(struct tty_driver));
-
- mkiss_driver.magic = MKISS_DRIVER_MAGIC;
- mkiss_driver.name = "mkiss";
- mkiss_driver.major = MKISS_MAJOR;
- mkiss_driver.minor_start = 0;
- mkiss_driver.num = NR_MKISS;
- mkiss_driver.type = TTY_DRIVER_TYPE_SERIAL;
- mkiss_driver.subtype = MKISS_SERIAL_TYPE_NORMAL; /* not needed */
-
- mkiss_driver.init_termios = tty_std_termios;
- mkiss_driver.init_termios.c_iflag = IGNBRK | IGNPAR;
- mkiss_driver.init_termios.c_cflag = B9600 | CS8 | CLOCAL;
-
- mkiss_driver.flags = TTY_DRIVER_REAL_RAW;
- mkiss_driver.refcount = &mkiss_refcount;
- mkiss_driver.table = mkiss_table;
- mkiss_driver.termios = (struct termios **)mkiss_termios;
- mkiss_driver.termios_locked = (struct termios **)mkiss_termios_locked;
-
- mkiss_driver.ioctl = mkiss_ioctl;
- mkiss_driver.open = mkiss_open;
- mkiss_driver.close = mkiss_close;
- mkiss_driver.write = mkiss_write;
- mkiss_driver.write_room = mkiss_write_room;
- mkiss_driver.chars_in_buffer = mkiss_chars_in_buffer;
- mkiss_driver.set_termios = mkiss_set_termios;
-
- /* some unused functions */
- mkiss_driver.flush_buffer = mkiss_dummy;
- mkiss_driver.throttle = mkiss_dummy;
- mkiss_driver.unthrottle = mkiss_dummy;
- mkiss_driver.stop = mkiss_dummy;
- mkiss_driver.start = mkiss_dummy;
- mkiss_driver.hangup = mkiss_dummy;
- mkiss_driver.flush_chars = mkiss_dummy;
- mkiss_driver.put_char = mkiss_dummy2;
-
- if (tty_register_driver(&mkiss_driver)) {
- printk(KERN_ERR "mkiss: couldn't register Mkiss device\n");
- return -EIO;
- }
-
- printk(KERN_INFO "AX.25 Multikiss device enabled\n");
-
- return 0;
-}
-
-#ifdef MODULE
-EXPORT_NO_SYMBOLS;
-
-MODULE_PARM(ax25_maxdev, "i");
-MODULE_PARM_DESC(ax25_maxdev, "number of MKISS devices");
-
-MODULE_AUTHOR("Hans Albas PE1AYX <hans@esrac.ele.tue.nl>");
-MODULE_DESCRIPTION("KISS driver for AX.25 over TTYs");
-
-int init_module(void)
-{
- return mkiss_init_ctrl_dev();
-}
-
-void cleanup_module(void)
-{
- int i;
-
- if (ax25_ctrls != NULL) {
- for (i = 0; i < ax25_maxdev; i++) {
- if (ax25_ctrls[i]) {
- /*
- * VSV = if dev->start==0, then device
- * unregistred while close proc.
- */
- if (ax25_ctrls[i]->dev.start)
- unregister_netdev(&(ax25_ctrls[i]->dev));
-
- kfree(ax25_ctrls[i]);
- ax25_ctrls[i] = NULL;
- }
- }
-
- kfree(ax25_ctrls);
- ax25_ctrls = NULL;
- }
-
- if ((i = tty_register_ldisc(N_AX25, NULL)))
- printk(KERN_ERR "mkiss: can't unregister line discipline (err = %d)\n", i);
-
- if (tty_unregister_driver(&mkiss_driver)) /* remove devive */
- printk(KERN_ERR "mkiss: can't unregister MKISS device\n");
-}
-
-#endif /* MODULE */
diff --git a/drivers/net/mkiss.h b/drivers/net/mkiss.h
index 0e32aa82b..e69de29bb 100644
--- a/drivers/net/mkiss.h
+++ b/drivers/net/mkiss.h
@@ -1,56 +0,0 @@
-/****************************************************************************
- * Defines for the Multi-KISS driver.
- ****************************************************************************/
-
-#define AX25_MAXDEV 16 /* MAX number of AX25 channels;
- This can be overridden with
- insmod -oax25_maxdev=nnn */
-#define AX_MTU 236
-
-/* SLIP/KISS protocol characters. */
-#define END 0300 /* indicates end of frame */
-#define ESC 0333 /* indicates byte stuffing */
-#define ESC_END 0334 /* ESC ESC_END means END 'data' */
-#define ESC_ESC 0335 /* ESC ESC_ESC means ESC 'data' */
-
-struct ax_disp {
- int magic;
-
- /* Various fields. */
- struct tty_struct *tty; /* ptr to TTY structure */
- struct device *dev; /* easy for intr handling */
- struct ax_disp *mkiss; /* mkiss txport if mkiss channel*/
-
- /* These are pointers to the malloc()ed frame buffers. */
- unsigned char *rbuff; /* receiver buffer */
- int rcount; /* received chars counter */
- unsigned char *xbuff; /* transmitter buffer */
- unsigned char *xhead; /* pointer to next byte to XMIT */
- int xleft; /* bytes left in XMIT queue */
-
- /* SLIP interface statistics. */
- unsigned long rx_packets; /* inbound frames counter */
- unsigned long tx_packets; /* outbound frames counter */
- unsigned long rx_errors; /* Parity, etc. errors */
- unsigned long tx_errors; /* Planned stuff */
- unsigned long rx_dropped; /* No memory for skb */
- unsigned long tx_dropped; /* When MTU change */
- unsigned long rx_over_errors; /* Frame bigger then SLIP buf. */
-
- /* Detailed SLIP statistics. */
- int mtu; /* Our mtu (to spot changes!) */
- int buffsize; /* Max buffers sizes */
-
-
- unsigned char flags; /* Flag values/ mode etc */
-#define AXF_INUSE 0 /* Channel in use */
-#define AXF_ESCAPE 1 /* ESC received */
-#define AXF_ERROR 2 /* Parity, etc. error */
-#define AXF_KEEPTEST 3 /* Keepalive test flag */
-#define AXF_OUTWAIT 4 /* is outpacket was flag */
-
- int mode;
-};
-
-#define AX25_MAGIC 0x5316
-#define MKISS_DRIVER_MAGIC 1215
diff --git a/drivers/net/ne.c b/drivers/net/ne.c
index 04cc02961..efbfc54e4 100644
--- a/drivers/net/ne.c
+++ b/drivers/net/ne.c
@@ -665,9 +665,7 @@ ne_block_output(struct device *dev, int count,
outb_p(0x00, nic_base + EN0_RSARHI);
outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
/* Make certain that the dummy read has occurred. */
- SLOW_DOWN_IO;
- SLOW_DOWN_IO;
- SLOW_DOWN_IO;
+ udelay(6);
#endif
outb_p(ENISR_RDC, nic_base + EN0_ISR);
diff --git a/drivers/net/net_init.c b/drivers/net/net_init.c
index ae57553a3..5a9c1cc3b 100644
--- a/drivers/net/net_init.c
+++ b/drivers/net/net_init.c
@@ -38,8 +38,8 @@
#include <linux/trdevice.h>
#include <linux/if_arp.h>
#include <linux/fddidevice.h>
-#include <linux/net_alias.h>
#include <linux/if_ltalk.h>
+#include <linux/rtnetlink.h>
/* The network devices currently exist only in the socket namespace, so these
entries are unused. The only ones that make sense are
@@ -112,7 +112,7 @@ init_etherdev(struct device *dev, int sizeof_priv)
new_device = 1;
}
- found: /* From the double loop above. */
+found: /* From the double loop above. */
if (dev->name &&
((dev->name[0] == '\0') || (dev->name[0] == ' '))) {
@@ -126,14 +126,9 @@ init_etherdev(struct device *dev, int sizeof_priv)
ether_setup(dev); /* Hmmm, should this be called here? */
- if (new_device) {
- /* Append the device to the device queue. */
- struct device **old_devp = &dev_base;
- while ((*old_devp)->next)
- old_devp = & (*old_devp)->next;
- (*old_devp)->next = dev;
- dev->next = 0;
- }
+ if (new_device)
+ register_netdevice(dev);
+
return dev;
}
@@ -173,8 +168,6 @@ void ether_setup(struct device *dev)
int i;
/* Fill in the fields of the device structure with ethernet-generic values.
This should be in a common file instead of per-driver. */
-
- dev_init_buffers(dev);
/* register boot-defined "eth" devices */
if (dev->name && (strncmp(dev->name, "eth", 3) == 0)) {
@@ -195,6 +188,7 @@ void ether_setup(struct device *dev)
dev->set_mac_address = eth_mac_addr;
dev->hard_header_cache = eth_header_cache;
dev->header_cache_update= eth_header_cache_update;
+ dev->hard_header_parse = eth_header_parse;
dev->type = ARPHRD_ETHER;
dev->hard_header_len = ETH_HLEN;
@@ -206,11 +200,8 @@ void ether_setup(struct device *dev)
/* New-style flags. */
dev->flags = IFF_BROADCAST|IFF_MULTICAST;
- dev->family = AF_INET;
- dev->pa_addr = 0;
- dev->pa_brdaddr = 0;
- dev->pa_mask = 0;
- dev->pa_alen = 4;
+
+ dev_init_buffers(dev);
}
#ifdef CONFIG_FDDI
@@ -222,8 +213,6 @@ void fddi_setup(struct device *dev)
* This should be in a common file instead of per-driver.
*/
- dev_init_buffers(dev);
-
dev->change_mtu = fddi_change_mtu;
dev->hard_header = fddi_header;
dev->rebuild_header = fddi_rebuild_header;
@@ -238,11 +227,9 @@ void fddi_setup(struct device *dev)
/* New-style flags */
dev->flags = IFF_BROADCAST | IFF_MULTICAST;
- dev->family = AF_INET;
- dev->pa_addr = 0;
- dev->pa_brdaddr = 0;
- dev->pa_mask = 0;
- dev->pa_alen = 4;
+
+ dev_init_buffers(dev);
+
return;
}
@@ -264,8 +251,6 @@ static int ltalk_mac_addr(struct device *dev, void *addr)
void ltalk_setup(struct device *dev)
{
/* Fill in the fields of the device structure with localtalk-generic values. */
-
- dev_init_buffers(dev);
dev->change_mtu = ltalk_change_mtu;
dev->hard_header = NULL;
@@ -283,11 +268,8 @@ void ltalk_setup(struct device *dev)
dev->broadcast[0] = 0xFF;
dev->flags = IFF_BROADCAST|IFF_MULTICAST|IFF_NOARP;
- dev->family = AF_APPLETALK;
- dev->pa_addr = 0;
- dev->pa_brdaddr = 0;
- dev->pa_mask = 0;
- dev->pa_alen = 1;
+
+ dev_init_buffers(dev);
}
#endif
@@ -309,134 +291,61 @@ int ether_config(struct device *dev, struct ifmap *map)
return 0;
}
-int register_netdev(struct device *dev)
+static int etherdev_get_index(struct device *dev)
{
- struct device *d = dev_base;
- unsigned long flags;
int i=MAX_ETH_CARDS;
- save_flags(flags);
- cli();
-
- if (dev) {
- if (dev->name &&
- ((dev->name[0] == '\0') || (dev->name[0] == ' '))) {
- for (i = 0; i < MAX_ETH_CARDS; ++i)
- if (ethdev_index[i] == NULL) {
- sprintf(dev->name, "eth%d", i);
- printk("loading device '%s'...\n", dev->name);
- ethdev_index[i] = dev;
- break;
- }
- }
-
- if (dev->init) {
- sti(); /* device probes assume interrupts enabled */
- if (dev->init(dev) != 0) {
- if (i < MAX_ETH_CARDS) ethdev_index[i] = NULL;
- restore_flags(flags);
- return -EIO;
- }
- cli();
- }
-
- /* Add device to end of chain */
- if (dev_base) {
- while (d->next)
- d = d->next;
- d->next = dev;
+ for (i = 0; i < MAX_ETH_CARDS; ++i) {
+ if (ethdev_index[i] == NULL) {
+ sprintf(dev->name, "eth%d", i);
+ printk("loading device '%s'...\n", dev->name);
+ ethdev_index[i] = dev;
+ return i;
}
- else
- dev_base = dev;
- dev->next = NULL;
- dev->ifindex = dev_new_index();
}
- restore_flags(flags);
- return 0;
+ return -1;
}
-void unregister_netdev(struct device *dev)
+static void etherdev_put_index(struct device *dev)
{
- struct device *d = dev_base;
- unsigned long flags;
int i;
-
- save_flags(flags);
- cli();
-
- if (dev == NULL)
- {
- printk("was NULL\n");
- restore_flags(flags);
- return;
- }
- /* else */
- if (dev->start)
- printk("ERROR '%s' busy and not MOD_IN_USE.\n", dev->name);
-
- /*
- * must jump over main_device+aliases
- * avoid alias devices unregistration so that only
- * net_alias module manages them
- */
-#ifdef CONFIG_NET_ALIAS
- if (dev_base == dev)
- dev_base = net_alias_nextdev(dev);
- else
- {
- while(d && (net_alias_nextdev(d) != dev)) /* skip aliases */
- d = net_alias_nextdev(d);
-
- if (d && (net_alias_nextdev(d) == dev))
- {
- /*
- * Critical: Bypass by consider devices as blocks (maindev+aliases)
- */
- net_alias_nextdev_set(d, net_alias_nextdev(dev));
- }
-#else
- if (dev_base == dev)
- dev_base = dev->next;
- else
- {
- while (d && (d->next != dev))
- d = d->next;
-
- if (d && (d->next == dev))
- {
- d->next = dev->next;
- }
-#endif
- else
- {
- printk("unregister_netdev: '%s' not found\n", dev->name);
- restore_flags(flags);
- return;
- }
- }
- for (i = 0; i < MAX_ETH_CARDS; ++i)
- {
- if (ethdev_index[i] == dev)
- {
+ for (i = 0; i < MAX_ETH_CARDS; ++i) {
+ if (ethdev_index[i] == dev) {
ethdev_index[i] = NULL;
break;
}
}
+}
+
+int register_netdev(struct device *dev)
+{
+ int i=-1;
- restore_flags(flags);
+ rtnl_lock();
- /*
- * You can i.e use a interfaces in a route though it is not up.
- * We call close_dev (which is changed: it will down a device even if
- * dev->flags==0 (but it will not call dev->stop if IFF_UP
- * is not set).
- * This will call notifier_call_chain(&netdev_chain, NETDEV_DOWN, dev),
- * dev_mc_discard(dev), ....
- */
-
- dev_close(dev);
+ if (dev->name &&
+ (dev->name[0] == '\0' || dev->name[0] == ' '))
+ i = etherdev_get_index(dev);
+
+ if (register_netdevice(dev)) {
+ if (i >= 0)
+ etherdev_put_index(dev);
+ rtnl_unlock();
+ return -EIO;
+ }
+ rtnl_unlock();
+ return 0;
+}
+
+void unregister_netdev(struct device *dev)
+{
+ rtnl_lock();
+ unregister_netdevice(dev);
+ etherdev_put_index(dev);
+ rtnl_unlock();
}
+
#ifdef CONFIG_TR
/* The list of used and available "tr" slots */
#define MAX_TR_CARDS 16
@@ -488,15 +397,6 @@ trfound: /* From the double loop above. */
break;
}
- if (new_device) {
- /* Append the device to the device queue. */
- struct device **old_devp = &dev_base;
-
- while ((*old_devp)->next)
- old_devp = & (*old_devp)->next;
- (*old_devp)->next = dev;
- dev->next = 0;
- }
dev->hard_header = tr_header;
dev->rebuild_header = tr_rebuild_header;
@@ -511,11 +411,9 @@ trfound: /* From the double loop above. */
/* New-style flags. */
dev->flags = IFF_BROADCAST;
- dev->family = AF_INET;
- dev->pa_addr = 0;
- dev->pa_brdaddr = 0;
- dev->pa_mask = 0;
- dev->pa_alen = 4;
+
+ if (new_device)
+ register_netdevice(dev);
return dev;
}
@@ -553,99 +451,21 @@ void tr_freedev(struct device *dev)
int register_trdev(struct device *dev)
{
- unsigned long flags;
-
dev_init_buffers(dev);
- save_flags(flags);
-
- if (dev && dev->init) {
- sti(); /* device probes assume interrupts enabled */
- if (dev->init(dev) != 0) {
- unregister_trdev(dev);
- restore_flags(flags);
- return -EIO;
- }
- cli();
-
+ if (dev->init && dev->init(dev) != 0) {
+ unregister_trdev(dev);
+ return -EIO;
}
- restore_flags(flags);
return 0;
}
void unregister_trdev(struct device *dev)
{
- struct device *d = dev_base;
- unsigned long flags;
-
- save_flags(flags);
- cli();
-
- if (dev == NULL)
- {
- printk("was NULL\n");
- restore_flags(flags);
- return;
- }
- /* else */
- if (dev->start)
- printk("ERROR '%s' busy and not MOD_IN_USE.\n", dev->name);
-
- /*
- * must jump over main_device+aliases
- * avoid alias devices unregistration so that only
- * net_alias module manages them
- */
-#ifdef CONFIG_NET_ALIAS
- if (dev_base == dev)
- dev_base = net_alias_nextdev(dev);
- else
- {
- while(d && (net_alias_nextdev(d) != dev)) /* skip aliases */
- d = net_alias_nextdev(d);
-
- if (d && (net_alias_nextdev(d) == dev))
- {
- /*
- * Critical: Bypass by consider devices as blocks (maindev+aliases)
- */
- net_alias_nextdev_set(d, net_alias_nextdev(dev));
- }
-#else
- if (dev_base == dev)
- dev_base = dev->next;
- else
- {
- while (d && (d->next != dev))
- d = d->next;
-
- if (d && (d->next == dev))
- {
- d->next = dev->next;
- }
-#endif
- else
- {
- printk("unregister_trdev: '%s' not found\n", dev->name);
- restore_flags(flags);
- return;
- }
- }
-
+ rtnl_lock();
+ unregister_netdevice(dev);
+ rtnl_unlock();
tr_freedev(dev);
-
- restore_flags(flags);
-
- /*
- * You can i.e use a interfaces in a route though it is not up.
- * We call close_dev (which is changed: it will down a device even if
- * dev->flags==0 (but it will not call dev->stop if IFF_UP
- * is not set).
- * This will call notifier_call_chain(&netdev_chain, NETDEV_DOWN, dev),
- * dev_mc_discard(dev), ....
- */
-
- dev_close(dev);
}
#endif
@@ -655,6 +475,5 @@ void unregister_trdev(struct device *dev)
* compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c net_init.c"
* version-control: t
* kept-new-versions: 5
- * tab-width: 4
* End:
*/
diff --git a/drivers/net/pi2.c b/drivers/net/pi2.c
index 3eb3a9223..e69de29bb 100644
--- a/drivers/net/pi2.c
+++ b/drivers/net/pi2.c
@@ -1,1677 +0,0 @@
-/*
- pi2.c: Driver for the Ottawa Amateur Radio Club PI and PI2 interface.
- Copyright (c) 1994 David Perry
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License version 2, as
- published by the Free Software Foundation.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software Foundation,
- Inc., 675 Mass Ave, Cambridge MA 02139, USA.
-
- The file skeleton.c by Donald Becker was used as a starting point
- for this driver.
-
- Revision History
-
- April 6, 1994 (dp) Created
- version 0.0 ALPHA
- April 10, 1994 (dp) Included cleanup, suggestions from J. P. Morrison.
- version 0.1 ALPHA
- April 13, 1994 (dp) Included address probing from JPM, autoirq
- version 0.2 ALPHA
- April 14, 1994 (ac) Sketched in the NET3 changes.
- April 17, 1994 (dp) Finished the NET3 changes. Used init_etherdev()
- instead of kmalloc() to ensure that DMA buffers will
- reside under the 16 meg line.
- version 0.4 ALPHA
- April 18, 1994 (dp) Now using the kernel provided sk_buff handling functions.
- Fixed a nasty problem with DMA.
- version 0.5 ALPHA
- June 6, 1994 (ac) Fixed to match the buffer locking changes. Added a hack to
- fix a funny I see (search for HACK) and fixed the calls in
- init() so it doesn't migrate module based ethernet cards up
- to eth2 Took out the old module ideas as they are no longer
- relevant to the PI driver.
- July 16, 1994 (dp) Fixed the B channel rx overrun problem ac referred to
- above. Also added a bit of a hack to improve the maximum
- baud rate on the B channel (Search for STUFF2). Included
- ioctl stuff from John Paul Morrison. version 0.6 ALPHA
- Feb 9, 1995 (dp) Updated for 1.1.90 kernel
- version 0.7 ALPHA
- Apr 6, 1995 (ac) Tweaks for NET3 pre snapshot 002 AX.25
- April 23, 1995 (dp) Fixed ioctl so it works properly with piconfig program
- when changing the baud rate or clock mode.
- version 0.8 ALPHA
- July 17, 1995 (ac) Finally polishing of AX25.030+ support
- Oct 29, 1995 (ac) A couple of minor fixes before this, and this release changes
- to the proper set_mac_address semantics which will break
- a few programs I suspect.
- Aug 18, 1996 (jsn) Converted to be used as a module.
- Dec 13, 1996 (jsn) Fixed to match Linux networking changes.
-*/
-
-/* The following #define invokes a hack that will improve performance (baud)
- for the B port. The up side is it makes 9600 baud work ok on the B port.
- It may do 38400, depending on the host. The down side is it burns up
- CPU cycles with ints locked for up to 1 character time, at the beginning
- of each transmitted packet. If this causes you to lose sleep, #undefine it.
-*/
-
-/*#define STUFF2 1*/
-
-/* The default configuration */
-#define PI_DMA 3
-
-#define DEF_A_SPEED 0 /* 0 means external clock */
-#define DEF_A_TXDELAY 15 /* 15 mS transmit delay */
-#define DEF_A_PERSIST 128 /* 50% persistence */
-#define DEF_A_SLOTIME 15 /* 15 mS slot time */
-#define DEF_A_SQUELDELAY 1 /* 1 mS squelch delay - allows fcs and flag */
-#define DEF_A_CLOCKMODE 0 /* clock mode - 0 is normal */
-
-#define DEF_B_SPEED 1200 /* 1200 baud */
-#define DEF_B_TXDELAY 40 /* 400 mS */
-#define DEF_B_PERSIST 128 /* 50% */
-#define DEF_B_SLOTIME 30 /* 300 mS */
-#define DEF_B_SQUELDELAY 3 /* 30 mS */
-#define DEF_B_CLOCKMODE 0 /* Normal clock mode */
-
-/* The following #define is only really required for the PI card, not
- the PI2 - but it's safer to leave it in. */
-#define REALLY_SLOW_IO 1
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ptrace.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/malloc.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <asm/system.h>
-#include <asm/bitops.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <asm/uaccess.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/timer.h>
-#include <linux/if_arp.h>
-#include <linux/pi2.h>
-#include <linux/init.h>
-#include "z8530.h"
-#include <net/ax25.h>
-
-struct mbuf {
- struct mbuf *next;
- int cnt;
- char data[0];
-};
-
-/*
- * The actual devices we will use
- */
-
-/*
- * PI device declarations.
- */
-
-static int pi0_preprobe(struct device *dev){return 0;} /* Dummy probe function */
-static struct device pi0a = { "pi0a", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, pi0_preprobe };
-static struct device pi0b = { "pi0b", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, pi0_preprobe };
-
-
-/* The number of low I/O ports used by the card. */
-#define PI_TOTAL_SIZE 8
-
-
-/* Index to functions, as function prototypes. */
-
-static int pi_probe(struct device *dev, int card_type);
-static int pi_open(struct device *dev);
-static int pi_send_packet(struct sk_buff *skb, struct device *dev);
-static void pi_interrupt(int reg_ptr, void *dev_id, struct pt_regs *regs);
-static int pi_close(struct device *dev);
-static int pi_ioctl(struct device *dev, struct ifreq *ifr, int cmd);
-static struct net_device_stats *pi_get_stats(struct device *dev);
-static void rts(struct pi_local *lp, int x);
-static void b_rxint(struct device *dev, struct pi_local *lp);
-static void b_txint(struct pi_local *lp);
-static void b_exint(struct pi_local *lp);
-static void a_rxint(struct device *dev, struct pi_local *lp);
-static void a_txint(struct pi_local *lp);
-static void a_exint(struct pi_local *lp);
-static char *get_dma_buffer(unsigned long *mem_ptr);
-static int valid_dma_page(unsigned long addr, unsigned long dev_buffsize);
-
-static char ax25_bcast[7] =
-{'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, '0' << 1};
-static char ax25_test[7] =
-{'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1, '1' << 1};
-
-static int ext2_secrm_seed = 152; /* Random generator base */
-
-extern inline unsigned char random(void)
-{
- return (unsigned char) (ext2_secrm_seed = ext2_secrm_seed
- * 69069l + 1);
-}
-
-extern inline void wrtscc(int cbase, int ctl, int sccreg, int val)
-{
- /* assume caller disables interrupts! */
- outb_p(0, cbase + DMAEN); /* Disable DMA while we touch the scc */
- outb_p(sccreg, ctl); /* Select register */
- outb_p(val, ctl); /* Output value */
- outb_p(1, cbase + DMAEN); /* Enable DMA */
-}
-
-extern inline int rdscc(int cbase, int ctl, int sccreg)
-{
- int retval;
-
- /* assume caller disables interrupts! */
- outb_p(0, cbase + DMAEN); /* Disable DMA while we touch the scc */
- outb_p(sccreg, ctl); /* Select register */
- retval = inb_p(ctl);
- outb_p(1, cbase + DMAEN); /* Enable DMA */
- return retval;
-}
-
-static void switchbuffers(struct pi_local *lp)
-{
- if (lp->rcvbuf == lp->rxdmabuf1)
- lp->rcvbuf = lp->rxdmabuf2;
- else
- lp->rcvbuf = lp->rxdmabuf1;
-}
-
-static void hardware_send_packet(struct pi_local *lp, struct sk_buff *skb)
-{
- char kickflag;
- unsigned long flags;
-
- lp->stats.tx_packets++;
-
- save_flags(flags);
- cli();
- kickflag = (skb_peek(&lp->sndq) == NULL) && (lp->sndbuf == NULL);
- restore_flags(flags);
-
- skb_queue_tail(&lp->sndq, skb);
- if (kickflag)
- {
- /* simulate interrupt to xmit */
- switch (lp->base & 2)
- {
- case 2:
- a_txint(lp); /* process interrupt */
- break;
- case 0:
- save_flags(flags);
- cli();
- if (lp->tstate == IDLE)
- b_txint(lp);
- restore_flags(flags);
- break;
- }
- }
-}
-
-static void setup_rx_dma(struct pi_local *lp)
-{
- unsigned long flags;
- int cmd;
- unsigned long dma_abs;
- unsigned dmachan;
-
- save_flags(flags);
- cli();
-
- dma_abs = (unsigned long) (lp->rcvbuf->data);
- dmachan = lp->dmachan;
- cmd = lp->base + CTL;
-
- if(!valid_dma_page(dma_abs, DMA_BUFF_SIZE + sizeof(struct mbuf)))
- panic("PI: RX buffer violates DMA boundary!");
-
- /* Get ready for RX DMA */
- wrtscc(lp->cardbase, cmd, R1, WT_FN_RDYFN | WT_RDY_RT | INT_ERR_Rx | EXT_INT_ENAB);
-
- disable_dma(dmachan);
- clear_dma_ff(dmachan);
-
- /* Set DMA mode register to single transfers, incrementing address,
- * auto init, writes
- */
- set_dma_mode(dmachan, DMA_MODE_READ | 0x10);
- set_dma_addr(dmachan, dma_abs);
- set_dma_count(dmachan, lp->bufsiz);
- enable_dma(dmachan);
-
- /* If a packet is already coming in, this line is supposed to
- avoid receiving a partial packet.
- */
- wrtscc(lp->cardbase, cmd, R0, RES_Rx_CRC);
-
- /* Enable RX dma */
- wrtscc(lp->cardbase, cmd, R1,
- WT_RDY_ENAB | WT_FN_RDYFN | WT_RDY_RT | INT_ERR_Rx | EXT_INT_ENAB);
-
- restore_flags(flags);
-}
-
-static void setup_tx_dma(struct pi_local *lp, int length)
-{
- unsigned long dma_abs;
- unsigned long flags;
- unsigned long dmachan;
-
- save_flags(flags);
- cli();
-
- dmachan = lp->dmachan;
- dma_abs = (unsigned long) (lp->txdmabuf);
-
- if(!valid_dma_page(dma_abs, DMA_BUFF_SIZE + sizeof(struct mbuf)))
- panic("PI: TX buffer violates DMA boundary!");
-
- disable_dma(dmachan);
- /* Set DMA mode register to single transfers, incrementing address,
- * no auto init, reads
- */
- set_dma_mode(dmachan, DMA_MODE_WRITE);
- clear_dma_ff(dmachan);
- set_dma_addr(dmachan, dma_abs);
- /* output byte count */
- set_dma_count(dmachan, length);
-
- restore_flags(flags);
-}
-
-static void tdelay(struct pi_local *lp, int time)
-{
- int port;
- unsigned int t1;
- unsigned char sc;
-
- if (lp->base & 2) { /* If A channel */
- sc = SC1;
- t1 = time;
- port = lp->cardbase + TMR1;
- } else {
- sc = SC2;
- t1 = 10 * time; /* 10s of milliseconds for the B channel */
- port = lp->cardbase + TMR2;
- wrtscc(lp->cardbase, lp->base + CTL, R1, INT_ALL_Rx | EXT_INT_ENAB);
- }
-
- /* Setup timer sc */
- outb_p(sc | LSB_MSB | MODE0, lp->cardbase + TMRCMD);
-
- /* times 2 to make millisecs */
- outb_p((t1 << 1) & 0xFF, port);
- outb_p((t1 >> 7) & 0xFF, port);
-
- /* Enable correct int for timeout */
- wrtscc(lp->cardbase, lp->base + CTL, R15, CTSIE);
- wrtscc(lp->cardbase, lp->base + CTL, R0, RES_EXT_INT);
-}
-
-static void a_txint(struct pi_local *lp)
-{
- int cmd;
- unsigned long flags;
-
- save_flags(flags);
- cli();
-
- cmd = CTL + lp->base;
-
- switch (lp->tstate) {
- case IDLE:
- /* Transmitter idle. Find a frame for transmission */
- if ((lp->sndbuf = skb_dequeue(&lp->sndq)) == NULL) {
- rts(lp, OFF);
- restore_flags(flags);
- return;
- }
- /* If a buffer to send, we drop thru here */
- case DEFER:
- /* we may have deferred prev xmit attempt */
- /* Check DCD - debounce it
- * See Intel Microcommunications Handbook, p2-308
- */
- wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
- wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
- if ((rdscc(lp->cardbase, cmd, R0) & DCD) != 0) {
- lp->tstate = DEFER;
- tdelay(lp, 100);
- /* defer until DCD transition or timeout */
- wrtscc(lp->cardbase, cmd, R15, CTSIE | DCDIE);
- restore_flags(flags);
- return;
- }
- if (random() > lp->persist) {
- lp->tstate = DEFER;
- tdelay(lp, lp->slotime);
- restore_flags(flags);
- return;
- }
- /* Assert RTS early minimize collision window */
- wrtscc(lp->cardbase, cmd, R5, TxCRC_ENAB | RTS | Tx8);
- rts(lp, ON); /* Transmitter on */
- lp->tstate = ST_TXDELAY;
- tdelay(lp, lp->txdelay);
- restore_flags(flags);
- return;
- default:
- break;
- } /* end switch(lp->state) */
-
- restore_flags(flags);
-} /*a_txint */
-
-static void a_exint(struct pi_local *lp)
-{
- unsigned long flags;
- int cmd;
- char st;
- int length;
-
- save_flags(flags);
- cli(); /* disable interrupts */
-
- st = rdscc(lp->cardbase, lp->base + CTL, R0); /* Fetch status */
-
- /* reset external status latch */
- wrtscc(lp->cardbase, CTL + lp->base, R0, RES_EXT_INT);
- cmd = lp->base + CTL;
-
- if ((lp->rstate >= ACTIVE) && (st & BRK_ABRT)) {
- setup_rx_dma(lp);
- lp->rstate = ACTIVE;
- }
- switch (lp->tstate) {
- case ACTIVE:
- kfree_skb(lp->sndbuf, FREE_WRITE);
- lp->sndbuf = NULL;
- lp->tstate = FLAGOUT;
- tdelay(lp, lp->squeldelay);
- break;
- case FLAGOUT:
- if ((lp->sndbuf = skb_dequeue(&lp->sndq)) == NULL) {
- /* Nothing to send - return to receive mode */
- lp->tstate = IDLE;
- rts(lp, OFF);
- restore_flags(flags);
- return;
- }
- /* NOTE - fall through if more to send */
- case ST_TXDELAY:
- /* Disable DMA chan */
- disable_dma(lp->dmachan);
-
- /* Set up for TX dma */
- wrtscc(lp->cardbase, cmd, R1, WT_FN_RDYFN | EXT_INT_ENAB);
-
-
- /* Get all chars */
- /* Strip KISS control byte */
- length = lp->sndbuf->len - 1;
- memcpy(lp->txdmabuf, &lp->sndbuf->data[1], length);
-
-
- /* Setup DMA controller for tx */
- setup_tx_dma(lp, length);
-
- /* select transmit interrupts to enable */
- /* Allow DMA on chan */
- enable_dma(lp->dmachan);
-
- /* reset CRC, Txint pend*/
- wrtscc(lp->cardbase, cmd, R0, RES_Tx_CRC | RES_Tx_P);
-
- /* allow Underrun int only */
- wrtscc(lp->cardbase, cmd, R15, TxUIE);
-
- /* Enable TX DMA */
- wrtscc(lp->cardbase, cmd, R1, WT_RDY_ENAB | WT_FN_RDYFN | EXT_INT_ENAB);
-
- /* Send CRC on underrun */
- wrtscc(lp->cardbase, cmd, R0, RES_EOM_L);
-
-
- /* packet going out now */
- lp->tstate = ACTIVE;
- break;
- case DEFER:
- /* we have deferred prev xmit attempt
- * See Intel Microcommunications Handbook, p2-308
- */
- wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
- wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
- if ((rdscc(lp->cardbase, cmd, R0) & DCD) != 0) {
- lp->tstate = DEFER;
- tdelay(lp, 100);
- /* Defer until dcd transition or 100mS timeout */
- wrtscc(lp->cardbase, CTL + lp->base, R15, CTSIE | DCDIE);
- restore_flags(flags);
- return;
- }
- if (random() > lp->persist) {
- lp->tstate = DEFER;
- tdelay(lp, lp->slotime);
- restore_flags(flags);
- return;
- }
- /* Assert RTS early minimize collision window */
- wrtscc(lp->cardbase, cmd, R5, TxCRC_ENAB | RTS | Tx8);
- rts(lp, ON); /* Transmitter on */
- lp->tstate = ST_TXDELAY;
- tdelay(lp, lp->txdelay);
- restore_flags(flags);
- return;
- } /* switch(lp->tstate) */
-
- restore_flags(flags);
-} /* a_exint() */
-
-/* Receive interrupt handler for the A channel
- */
-static void a_rxint(struct device *dev, struct pi_local *lp)
-{
- unsigned long flags;
- int cmd;
- int bytecount;
- char rse;
- struct sk_buff *skb;
- int sksize, pkt_len;
- struct mbuf *cur_buf;
- unsigned char *cfix;
-
- save_flags(flags);
- cli(); /* disable interrupts */
- cmd = lp->base + CTL;
-
- rse = rdscc(lp->cardbase, cmd, R1); /* Get special condition bits from R1 */
- if (rse & Rx_OVR)
- lp->rstate = RXERROR;
-
- if (rse & END_FR) {
- /* If end of frame */
- /* figure length of frame from 8237 */
- clear_dma_ff(lp->dmachan);
- bytecount = lp->bufsiz - get_dma_residue(lp->dmachan);
-
- if ((rse & CRC_ERR) || (lp->rstate > ACTIVE) || (bytecount < 10)) {
- if ((bytecount >= 10) && (rse & CRC_ERR)) {
- lp->stats.rx_crc_errors++;
- }
- if (lp->rstate == RXERROR) {
- lp->stats.rx_errors++;
- lp->stats.rx_over_errors++;
- }
- /* Reset buffer pointers */
- lp->rstate = ACTIVE;
- setup_rx_dma(lp);
- } else {
- /* Here we have a valid frame */
- /* Toss 2 crc bytes , add one for KISS */
- pkt_len = lp->rcvbuf->cnt = bytecount - 2 + 1;
-
- /* Get buffer for next frame */
- cur_buf = lp->rcvbuf;
- switchbuffers(lp);
- setup_rx_dma(lp);
-
-
- /* Malloc up new buffer. */
- sksize = pkt_len;
-
- skb = dev_alloc_skb(sksize);
- if (skb == NULL) {
- printk(KERN_ERR "PI: %s: Memory squeeze, dropping packet.\n", dev->name);
- lp->stats.rx_dropped++;
- restore_flags(flags);
- return;
- }
- skb->dev = dev;
-
- /* KISS kludge - prefix with a 0 byte */
- cfix=skb_put(skb,pkt_len);
- *cfix++=0;
- /* 'skb->data' points to the start of sk_buff data area. */
- memcpy(cfix, (char *) cur_buf->data,
- pkt_len - 1);
- skb->protocol=htons(ETH_P_AX25);
- skb->mac.raw=skb->data;
- netif_rx(skb);
- lp->stats.rx_packets++;
- } /* end good frame */
- } /* end EOF check */
- wrtscc(lp->cardbase, lp->base + CTL, R0, ERR_RES); /* error reset */
- restore_flags(flags);
-}
-
-static void b_rxint(struct device *dev, struct pi_local *lp)
-{
- unsigned long flags;
- int cmd;
- char rse;
- struct sk_buff *skb;
- int sksize;
- int pkt_len;
- unsigned char *cfix;
-
- save_flags(flags);
- cli(); /* disable interrupts */
- cmd = CTL + lp->base;
-
- rse = rdscc(lp->cardbase, cmd, R1); /* get status byte from R1 */
-
- if ((rdscc(lp->cardbase, cmd, R0)) & Rx_CH_AV) {
- /* there is a char to be stored
- * read special condition bits before reading the data char
- */
- if (rse & Rx_OVR) {
- /* Rx overrun - toss buffer */
- /* reset buffer pointers */
- lp->rcp = lp->rcvbuf->data;
- lp->rcvbuf->cnt = 0;
-
- lp->rstate = RXERROR; /* set error flag */
- lp->stats.rx_errors++;
- lp->stats.rx_over_errors++;
- } else if (lp->rcvbuf->cnt >= lp->bufsiz) {
- /* Too large -- toss buffer */
- /* reset buffer pointers */
- lp->rcp = lp->rcvbuf->data;
- lp->rcvbuf->cnt = 0;
- lp->rstate = TOOBIG;/* when set, chars are not stored */
- }
- /* ok, we can store the received character now */
- if (lp->rstate == ACTIVE) { /* If no errors... */
- *lp->rcp++ = rdscc(lp->cardbase, cmd, R8); /* char to rcv buff */
- lp->rcvbuf->cnt++; /* bump count */
- } else {
- /* got to empty FIFO */
- (void) rdscc(lp->cardbase, cmd, R8);
- wrtscc(lp->cardbase, cmd, R0, ERR_RES); /* reset err latch */
- lp->rstate = ACTIVE;
- }
- }
- if (rse & END_FR) {
- /* END OF FRAME -- Make sure Rx was active */
- if (lp->rcvbuf->cnt > 0) {
- if ((rse & CRC_ERR) || (lp->rstate > ACTIVE) || (lp->rcvbuf->cnt < 10)) {
- if ((lp->rcvbuf->cnt >= 10) && (rse & CRC_ERR)) {
- lp->stats.rx_crc_errors++;
- }
- lp->rcp = lp->rcvbuf->data;
- lp->rcvbuf->cnt = 0;
- } else {
- /* Here we have a valid frame */
- pkt_len = lp->rcvbuf->cnt -= 2; /* Toss 2 crc bytes */
- pkt_len += 1; /* Make room for KISS control byte */
-
- /* Malloc up new buffer. */
- sksize = pkt_len;
- skb = dev_alloc_skb(sksize);
- if (skb == NULL) {
- printk(KERN_ERR "PI: %s: Memory squeeze, dropping packet.\n", dev->name);
- lp->stats.rx_dropped++;
- restore_flags(flags);
- return;
- }
- skb->dev = dev;
-
- /* KISS kludge - prefix with a 0 byte */
- cfix=skb_put(skb,pkt_len);
- *cfix++=0;
- /* 'skb->data' points to the start of sk_buff data area. */
- memcpy(cfix, lp->rcvbuf->data, pkt_len - 1);
- skb->protocol=ntohs(ETH_P_AX25);
- skb->mac.raw=skb->data;
- netif_rx(skb);
- lp->stats.rx_packets++;
- /* packet queued - initialize buffer for next frame */
- lp->rcp = lp->rcvbuf->data;
- lp->rcvbuf->cnt = 0;
-
- } /* end good frame queued */
- } /* end check for active receive upon EOF */
- lp->rstate = ACTIVE; /* and clear error status */
- } /* end EOF check */
- restore_flags(flags);
-}
-
-
-static void b_txint(struct pi_local *lp)
-{
- unsigned long flags;
- int cmd;
- unsigned char c;
-
- save_flags(flags);
- cli();
- cmd = CTL + lp->base;
-
- switch (lp->tstate) {
- case CRCOUT:
- lp->tstate = FLAGOUT;
- tdelay(lp, lp->squeldelay);
- restore_flags(flags);
- return;
- case IDLE:
- /* Transmitter idle. Find a frame for transmission */
- if ((lp->sndbuf = skb_dequeue(&lp->sndq)) == NULL) {
- /* Nothing to send - return to receive mode
- * Tx OFF now - flag should have gone
- */
- rts(lp, OFF);
-
- restore_flags(flags);
- return;
- }
- lp->txptr = lp->sndbuf->data;
- lp->txptr++; /* Ignore KISS control byte */
- lp->txcnt = (int) lp->sndbuf->len - 1;
- /* If a buffer to send, we drop thru here */
- case DEFER: /* we may have deferred prev xmit attempt */
- /* Check DCD - debounce it */
- /* See Intel Microcommunications Handbook, p2-308 */
- wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
- wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
- if ((rdscc(lp->cardbase, cmd, R0) & DCD) != 0) {
- lp->tstate = DEFER;
- tdelay(lp, 100);
- /* defer until DCD transition or timeout */
- wrtscc(lp->cardbase, cmd, R15, CTSIE | DCDIE);
- restore_flags(flags);
- return;
- }
- if (random() > lp->persist) {
- lp->tstate = DEFER;
- tdelay(lp, lp->slotime);
- restore_flags(flags);
- return;
- }
- rts(lp, ON); /* Transmitter on */
- lp->tstate = ST_TXDELAY;
- tdelay(lp, lp->txdelay);
- restore_flags(flags);
- return;
-
- case ACTIVE:
- /* Here we are actively sending a frame */
- if (lp->txcnt--) {
- c = *lp->txptr++;
- /* next char is gone */
- wrtscc(lp->cardbase, cmd, R8, c);
- /* stuffing a char satisfies Interrupt condition */
- } else {
- /* No more to send */
- kfree_skb(lp->sndbuf, FREE_WRITE);
- lp->sndbuf = NULL;
- if ((rdscc(lp->cardbase, cmd, R0) & 0x40)) {
- /* Did we underrun? */
- /* unexpected underrun */
- lp->stats.tx_errors++;
- lp->stats.tx_fifo_errors++;
- wrtscc(lp->cardbase, cmd, R0, SEND_ABORT);
- lp->tstate = FLAGOUT;
- tdelay(lp, lp->squeldelay);
- restore_flags(flags);
- return;
- }
- lp->tstate = UNDERRUN; /* Now we expect to underrun */
- /* Send flags on underrun */
- if (lp->speed) { /* If internally clocked */
- wrtscc(lp->cardbase, cmd, R10, CRCPS | NRZI);
- } else {
- wrtscc(lp->cardbase, cmd, R10, CRCPS);
- }
- wrtscc(lp->cardbase, cmd, R0, RES_Tx_P); /* reset Tx Int Pend */
- }
- restore_flags(flags);
- return; /* back to wait for interrupt */
- } /* end switch */
- restore_flags(flags);
-}
-
-/* Pi SIO External/Status interrupts (for the B channel)
- * This can be caused by a receiver abort, or a Tx UNDERRUN/EOM.
- * Receiver automatically goes to Hunt on an abort.
- *
- * If the Tx Underrun interrupt hits, change state and
- * issue a reset command for it, and return.
- */
-static void b_exint(struct pi_local *lp)
-{
- unsigned long flags;
- char st;
- int cmd;
- char c;
-
- cmd = CTL + lp->base;
- save_flags(flags);
- cli(); /* disable interrupts */
- st = rdscc(lp->cardbase, cmd, R0); /* Fetch status */
- /* reset external status latch */
- wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
-
-
- switch (lp->tstate) {
- case ACTIVE: /* Unexpected underrun */
- kfree_skb(lp->sndbuf, FREE_WRITE);
- lp->sndbuf = NULL;
- wrtscc(lp->cardbase, cmd, R0, SEND_ABORT);
- lp->tstate = FLAGOUT;
- lp->stats.tx_errors++;
- lp->stats.tx_fifo_errors++;
- tdelay(lp, lp->squeldelay);
- restore_flags(flags);
- return;
- case UNDERRUN:
- lp->tstate = CRCOUT;
- restore_flags(flags);
- return;
- case FLAGOUT:
- /* Find a frame for transmission */
- if ((lp->sndbuf = skb_dequeue(&lp->sndq)) == NULL) {
- /* Nothing to send - return to receive mode
- * Tx OFF now - flag should have gone
- */
- rts(lp, OFF);
- lp->tstate = IDLE;
- restore_flags(flags);
- return;
- }
- lp->txptr = lp->sndbuf->data;
- lp->txptr++; /* Ignore KISS control byte */
- lp->txcnt = (int) lp->sndbuf->len - 1;
- /* Get first char to send */
- lp->txcnt--;
- c = *lp->txptr++;
- wrtscc(lp->cardbase, cmd, R0, RES_Tx_CRC); /* reset for next frame */
-
- /* Send abort on underrun */
- if (lp->speed) { /* If internally clocked */
- wrtscc(lp->cardbase, cmd, R10, CRCPS | NRZI | ABUNDER);
- } else {
- wrtscc(lp->cardbase, cmd, R10, CRCPS | ABUNDER);
- }
-
- wrtscc(lp->cardbase, cmd, R8, c); /* First char out now */
- wrtscc(lp->cardbase, cmd, R0, RES_EOM_L); /* Reset end of message latch */
-
-#ifdef STUFF2
- /* stuff an extra one if we can */
- if (lp->txcnt) {
- lp->txcnt--;
- c = *lp->txptr++;
- /* Wait for tx buffer empty */
- while((rdscc(lp->cardbase, cmd, R0) & 0x04) == 0)
- ;
- wrtscc(lp->cardbase, cmd, R8, c);
- }
-#endif
-
- /* select transmit interrupts to enable */
-
- wrtscc(lp->cardbase, cmd, R15, TxUIE); /* allow Underrun int only */
- wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
- wrtscc(lp->cardbase, cmd, R1, TxINT_ENAB | EXT_INT_ENAB); /* Tx/Ext ints */
-
- lp->tstate = ACTIVE; /* char going out now */
- restore_flags(flags);
- return;
-
- case DEFER:
- /* Check DCD - debounce it
- * See Intel Microcommunications Handbook, p2-308
- */
- wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
- wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
- if ((rdscc(lp->cardbase, cmd, R0) & DCD) != 0) {
- lp->tstate = DEFER;
- tdelay(lp, 100);
- /* defer until DCD transition or timeout */
- wrtscc(lp->cardbase, cmd, R15, CTSIE | DCDIE);
- restore_flags(flags);
- return;
- }
- if (random() > lp->persist) {
- lp->tstate = DEFER;
- tdelay(lp, lp->slotime);
- restore_flags(flags);
- return;
- }
- rts(lp, ON); /* Transmitter on */
- lp->tstate = ST_TXDELAY;
- tdelay(lp, lp->txdelay);
- restore_flags(flags);
- return;
-
- case ST_TXDELAY:
-
- /* Get first char to send */
- lp->txcnt--;
- c = *lp->txptr++;
- wrtscc(lp->cardbase, cmd, R0, RES_Tx_CRC); /* reset for next frame */
-
- /* Send abort on underrun */
- if (lp->speed) { /* If internally clocked */
- wrtscc(lp->cardbase, cmd, R10, CRCPS | NRZI | ABUNDER);
- } else {
- wrtscc(lp->cardbase, cmd, R10, CRCPS | ABUNDER);
- }
-
- wrtscc(lp->cardbase, cmd, R8, c); /* First char out now */
- wrtscc(lp->cardbase, cmd, R0, RES_EOM_L); /* Reset end of message latch */
-
-#ifdef STUFF2
- /* stuff an extra one if we can */
- if (lp->txcnt) {
- lp->txcnt--;
- c = *lp->txptr++;
- /* Wait for tx buffer empty */
- while((rdscc(lp->cardbase, cmd, R0) & 0x04) == 0)
- ;
- wrtscc(lp->cardbase, cmd, R8, c);
- }
-#endif
-
- /* select transmit interrupts to enable */
-
- wrtscc(lp->cardbase, cmd, R15, TxUIE); /* allow Underrun int only */
- wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
- /* Tx/Extern ints on */
- wrtscc(lp->cardbase, cmd, R1, TxINT_ENAB | EXT_INT_ENAB);
-
- lp->tstate = ACTIVE; /* char going out now */
- restore_flags(flags);
- return;
- }
-
- /* Receive Mode only
- * This triggers when hunt mode is entered, & since an ABORT
- * automatically enters hunt mode, we use that to clean up
- * any waiting garbage
- */
- if ((lp->rstate == ACTIVE) && (st & BRK_ABRT)) {
- (void) rdscc(lp->cardbase, cmd, R8);
- (void) rdscc(lp->cardbase, cmd, R8);
- (void) rdscc(lp->cardbase, cmd, R8);
- lp->rcp = lp->rcvbuf->data;
- lp->rcvbuf->cnt = 0; /* rewind on DCD transition */
- }
- restore_flags(flags);
-}
-
-/* Probe for a PI card. */
-/* This routine also initializes the timer chip */
-
-__initfunc(static int hw_probe(int ioaddr))
-{
- int time = 1000; /* Number of milliseconds for test */
- unsigned long start_time, end_time;
-
- int base, tmr0, tmr1, tmrcmd;
- int a = 1;
- int b = 1;
-
- base = ioaddr & 0x3f0;
- tmr0 = TMR0 + base;
- tmr1 = TMR1 + base;
- tmrcmd = TMRCMD + base;
-
- /* Set up counter chip timer 0 for 500 uS period square wave */
- /* assuming a 3.68 mhz clock for now */
- outb_p(SC0 | LSB_MSB | MODE3, tmrcmd);
- outb_p(922 & 0xFF, tmr0);
- outb_p(922 >> 8, tmr0);
-
- /* Setup timer control word for timer 1*/
- outb_p(SC1 | LSB_MSB | MODE0, tmrcmd);
- outb_p((time << 1) & 0xFF, tmr1);
- outb_p((time >> 7) & 0XFF, tmr1);
-
- /* wait until counter reg is loaded */
- do {
- /* Latch count for reading */
- outb_p(SC1, tmrcmd);
- a = inb_p(tmr1);
- b = inb_p(tmr1);
- } while (b == 0);
- start_time = jiffies;
- while (b != 0) {
- /* Latch count for reading */
- outb_p(SC1, tmrcmd);
- a = inb_p(tmr1);
- b = inb_p(tmr1);
- end_time = jiffies;
- /* Don't wait forever - there may be no card here */
- if ((end_time - start_time) > 200)
- return 0; /* No card found */
- }
- end_time = jiffies;
- /* 87 jiffies, for a 3.68 mhz clock, half that for a double speed clock */
- if ((end_time - start_time) > 65) {
- return (1); /* PI card found */
- } else {
- /* Faster crystal - tmr0 needs adjusting */
- /* Set up counter chip */
- /* 500 uS square wave */
- outb_p(SC0 | LSB_MSB | MODE3, tmrcmd);
- outb_p(1844 & 0xFF, tmr0);
- outb_p(1844 >> 8, tmr0);
- return (2); /* PI2 card found */
- }
-}
-
-static void rts(struct pi_local *lp, int x)
-{
- int tc;
- long br;
- int cmd;
- int dummy;
-
- /* assumes interrupts are off */
- cmd = CTL + lp->base;
-
- /* Reprogram BRG and turn on transmitter to send flags */
- if (x == ON) { /* Turn Tx ON and Receive OFF */
- /* Exints off first to avoid abort int */
- wrtscc(lp->cardbase, cmd, R15, 0);
- wrtscc(lp->cardbase, cmd, R3, Rx8); /* Rx off */
- lp->rstate = IDLE;
- if (cmd & 2) { /* if channel a */
- /* Set up for TX dma */
- wrtscc(lp->cardbase, cmd, R1, WT_FN_RDYFN | EXT_INT_ENAB);
- } else {
- wrtscc(lp->cardbase, cmd, R1, 0); /* No interrupts */
- }
-
- if (!lp->clockmode) {
- if (lp->speed) { /* if internally clocked */
- br = lp->speed; /* get desired speed */
- tc = (lp->xtal / br) - 2; /* calc 1X BRG divisor */
- wrtscc(lp->cardbase, cmd, R12, tc & 0xFF); /* lower byte */
- wrtscc(lp->cardbase, cmd, R13, (tc >> 8) & 0xFF); /* upper byte */
- }
- }
- wrtscc(lp->cardbase, cmd, R5, TxCRC_ENAB | RTS | TxENAB | Tx8 | DTR);
- /* Transmitter now on */
- } else { /* Tx OFF and Rx ON */
- lp->tstate = IDLE;
- wrtscc(lp->cardbase, cmd, R5, Tx8 | DTR); /* TX off */
-
- if (!lp->clockmode) {
- if (lp->speed) { /* if internally clocked */
- /* Reprogram BRG for 32x clock for receive DPLL */
- /* BRG off, keep Pclk source */
- wrtscc(lp->cardbase, cmd, R14, BRSRC);
- br = lp->speed; /* get desired speed */
- /* calc 32X BRG divisor */
- tc = ((lp->xtal / 32) / br) - 2;
- wrtscc(lp->cardbase, cmd, R12, tc & 0xFF); /* lower byte */
- wrtscc(lp->cardbase, cmd, R13, (tc >> 8) & 0xFF); /* upper byte */
- /* SEARCH mode, BRG source */
- wrtscc(lp->cardbase, cmd, R14, BRSRC | SEARCH);
- /* Enable the BRG */
- wrtscc(lp->cardbase, cmd, R14, BRSRC | BRENABL);
- }
- }
- /* Flush rx fifo */
- wrtscc(lp->cardbase, cmd, R3, Rx8); /* Make sure rx is off */
- wrtscc(lp->cardbase, cmd, R0, ERR_RES); /* reset err latch */
- dummy = rdscc(lp->cardbase, cmd, R1); /* get status byte from R1 */
- (void) rdscc(lp->cardbase, cmd, R8);
- (void) rdscc(lp->cardbase, cmd, R8);
-
- (void) rdscc(lp->cardbase, cmd, R8);
-
- /* Now, turn on the receiver and hunt for a flag */
- wrtscc(lp->cardbase, cmd, R3, RxENABLE | Rx8);
- lp->rstate = ACTIVE; /* Normal state */
-
- if (cmd & 2) { /* if channel a */
- setup_rx_dma(lp);
- } else {
- /* reset buffer pointers */
- lp->rcp = lp->rcvbuf->data;
- lp->rcvbuf->cnt = 0;
- wrtscc(lp->cardbase, cmd, R1, (INT_ALL_Rx | EXT_INT_ENAB));
- }
- wrtscc(lp->cardbase, cmd, R15, BRKIE); /* allow ABORT int */
- }
-}
-
-static void scc_init(struct device *dev)
-{
- unsigned long flags;
- struct pi_local *lp = (struct pi_local *) dev->priv;
-
- int tc;
- long br;
- register int cmd;
-
- /* Initialize 8530 channel for SDLC operation */
-
- cmd = CTL + lp->base;
- save_flags(flags);
- cli();
-
- switch (cmd & CHANA) {
- case CHANA:
- wrtscc(lp->cardbase, cmd, R9, CHRA); /* Reset channel A */
- wrtscc(lp->cardbase, cmd, R2, 0xff); /* Initialize interrupt vector */
- break;
- default:
- wrtscc(lp->cardbase, cmd, R9, CHRB); /* Reset channel B */
- break;
- }
-
- /* Deselect all Rx and Tx interrupts */
- wrtscc(lp->cardbase, cmd, R1, 0);
-
- /* Turn off external interrupts (like CTS/CD) */
- wrtscc(lp->cardbase, cmd, R15, 0);
-
- /* X1 clock, SDLC mode */
- wrtscc(lp->cardbase, cmd, R4, SDLC | X1CLK);
-
- /* Tx/Rx parameters */
- if (lp->speed) { /* Use internal clocking */
- wrtscc(lp->cardbase, cmd, R10, CRCPS | NRZI);
- if (!lp->clockmode)
- /* Tx Clk from BRG. Rcv Clk from DPLL, TRxC pin outputs DPLL */
- wrtscc(lp->cardbase, cmd, R11, TCBR | RCDPLL | TRxCDP | TRxCOI);
- else
- /* Tx Clk from DPLL, Rcv Clk from DPLL, TRxC Outputs BRG */
- wrtscc(lp->cardbase, cmd, R11, TCDPLL | RCDPLL | TRxCBR | TRxCOI);
- } else { /* Use external clocking */
- wrtscc(lp->cardbase, cmd, R10, CRCPS);
- /* Tx Clk from Trxcl. Rcv Clk from Rtxcl, TRxC pin is input */
- wrtscc(lp->cardbase, cmd, R11, TCTRxCP);
- }
-
- /* Null out SDLC start address */
- wrtscc(lp->cardbase, cmd, R6, 0);
-
- /* SDLC flag */
- wrtscc(lp->cardbase, cmd, R7, FLAG);
-
- /* Set up the Transmitter but don't enable it
- * DTR, 8 bit TX chars only
- */
- wrtscc(lp->cardbase, cmd, R5, Tx8 | DTR);
-
- /* Receiver initial setup */
- wrtscc(lp->cardbase, cmd, R3, Rx8); /* 8 bits/char */
-
- /* Setting up BRG now - turn it off first */
- wrtscc(lp->cardbase, cmd, R14, BRSRC); /* BRG off, keep Pclk source */
-
- /* set the 32x time constant for the BRG in Receive mode */
-
- if (lp->speed) {
- br = lp->speed; /* get desired speed */
- tc = ((lp->xtal / 32) / br) - 2; /* calc 32X BRG divisor */
- } else {
- tc = 14;
- }
-
- wrtscc(lp->cardbase, cmd, R12, tc & 0xFF); /* lower byte */
- wrtscc(lp->cardbase, cmd, R13, (tc >> 8) & 0xFF); /* upper byte */
-
- /* Following subroutine sets up and ENABLES the receiver */
- rts(lp, OFF); /* TX OFF and RX ON */
-
- if (lp->speed) {
- /* DPLL frm BRG, BRG src PCLK */
- wrtscc(lp->cardbase, cmd, R14, BRSRC | SSBR);
- } else {
- /* DPLL frm rtxc,BRG src PCLK */
- wrtscc(lp->cardbase, cmd, R14, BRSRC | SSRTxC);
- }
- wrtscc(lp->cardbase, cmd, R14, BRSRC | SEARCH); /* SEARCH mode, keep BRG src */
- wrtscc(lp->cardbase, cmd, R14, BRSRC | BRENABL); /* Enable the BRG */
-
- if (!(cmd & 2)) /* if channel b */
- wrtscc(lp->cardbase, cmd, R1, (INT_ALL_Rx | EXT_INT_ENAB));
-
- wrtscc(lp->cardbase, cmd, R15, BRKIE); /* ABORT int */
-
- /* Now, turn on the receiver and hunt for a flag */
- wrtscc(lp->cardbase, cmd, R3, RxENABLE | RxCRC_ENAB | Rx8);
-
- restore_flags(flags);
-}
-
-static void chipset_init(struct device *dev)
-{
- int cardbase;
- unsigned long flags;
-
- cardbase = dev->base_addr & 0x3f0;
-
- save_flags(flags);
- cli();
- wrtscc(cardbase, dev->base_addr + CTL, R9, FHWRES); /* Hardware reset */
- /* Disable interrupts with master interrupt ctrl reg */
- wrtscc(cardbase, dev->base_addr + CTL, R9, 0);
- restore_flags(flags);
-
-}
-
-
-__initfunc(int pi_init(void))
-{
- int *port;
- int ioaddr = 0;
- int card_type = 0;
- int ports[] = {0x380, 0x300, 0x320, 0x340, 0x360, 0x3a0, 0};
-
- printk(KERN_INFO "PI: V0.8 ALPHA April 23 1995 David Perry (dp@hydra.carleton.ca)\n");
-
- /* Only one card supported for now */
- for (port = &ports[0]; *port && !card_type; port++) {
- ioaddr = *port;
-
- if (check_region(ioaddr, PI_TOTAL_SIZE) == 0) {
- printk(KERN_INFO "PI: Probing for card at address %#3x\n",ioaddr);
- card_type = hw_probe(ioaddr);
- }
- }
-
- switch (card_type) {
- case 1:
- printk(KERN_INFO "PI: Found a PI card at address %#3x\n", ioaddr);
- break;
- case 2:
- printk(KERN_INFO "PI: Found a PI2 card at address %#3x\n", ioaddr);
- break;
- default:
- printk(KERN_ERR "PI: ERROR: No card found\n");
- return -EIO;
- }
-
- /* Link a couple of device structures into the chain */
- /* For the A port */
- /* Allocate space for 4 buffers even though we only need 3,
- because one of them may cross a DMA page boundary and
- be rejected by get_dma_buffer().
- */
- register_netdev(&pi0a);
-
- pi0a.priv = kmalloc(sizeof(struct pi_local) + (DMA_BUFF_SIZE + sizeof(struct mbuf)) * 4, GFP_KERNEL | GFP_DMA);
-
- pi0a.dma = PI_DMA;
- pi0a.base_addr = ioaddr + 2;
- pi0a.irq = 0;
-
- /* And the B port */
- register_netdev(&pi0b);
- pi0b.base_addr = ioaddr;
- pi0b.irq = 0;
-
- pi0b.priv = kmalloc(sizeof(struct pi_local) + (DMA_BUFF_SIZE + sizeof(struct mbuf)) * 4, GFP_KERNEL | GFP_DMA);
-
- /* Now initialize them */
- pi_probe(&pi0a, card_type);
- pi_probe(&pi0b, card_type);
-
- pi0b.irq = pi0a.irq; /* IRQ is shared */
-
- return 0;
-}
-
-static int valid_dma_page(unsigned long addr, unsigned long dev_buffsize)
-{
- if (((addr & 0xffff) + dev_buffsize) <= 0x10000)
- return 1;
- else
- return 0;
-}
-
-static int pi_set_mac_address(struct device *dev, void *addr)
-{
- struct sockaddr *sa = (struct sockaddr *)addr;
- memcpy(dev->dev_addr, sa->sa_data, dev->addr_len); /* addr is an AX.25 shifted ASCII */
- return 0; /* mac address */
-}
-
-/* Allocate a buffer which does not cross a DMA page boundary */
-static char *
-get_dma_buffer(unsigned long *mem_ptr)
-{
- char *ret;
-
- ret = (char *)*mem_ptr;
-
- if(!valid_dma_page(*mem_ptr, DMA_BUFF_SIZE + sizeof(struct mbuf))){
- *mem_ptr += (DMA_BUFF_SIZE + sizeof(struct mbuf));
- ret = (char *)*mem_ptr;
- }
- *mem_ptr += (DMA_BUFF_SIZE + sizeof(struct mbuf));
- return (ret);
-}
-
-static int pi_probe(struct device *dev, int card_type)
-{
- short ioaddr;
- struct pi_local *lp;
- unsigned long flags;
- unsigned long mem_ptr;
-
- ioaddr = dev->base_addr;
-
- /* Initialize the device structure. */
- /* Must be done before chipset_init */
- /* Make certain the data structures used by the PI2 are aligned. */
- dev->priv = (void *) (((int) dev->priv + 7) & ~7);
- lp = (struct pi_local *) dev->priv;
-
- memset(dev->priv, 0, sizeof(struct pi_local));
-
- /* Allocate some buffers which do not cross DMA page boundaries */
- mem_ptr = (unsigned long) dev->priv + sizeof(struct pi_local);
- lp->txdmabuf = get_dma_buffer(&mem_ptr);
- lp->rxdmabuf1 = (struct mbuf *) get_dma_buffer(&mem_ptr);
- lp->rxdmabuf2 = (struct mbuf *) get_dma_buffer(&mem_ptr);
-
- /* Initialize rx buffer */
- lp->rcvbuf = lp->rxdmabuf1;
- lp->rcp = lp->rcvbuf->data;
- lp->rcvbuf->cnt = 0;
-
- /* Initialize the transmit queue head structure */
- skb_queue_head_init(&lp->sndq);
-
- /* These need to be initialized before scc_init is called. */
- if (card_type == 1)
- lp->xtal = (unsigned long) SINGLE / 2;
- else
- lp->xtal = (unsigned long) DOUBLE / 2;
- lp->base = dev->base_addr;
- lp->cardbase = dev->base_addr & 0x3f0;
- if (dev->base_addr & CHANA) {
- lp->speed = DEF_A_SPEED;
- /* default channel access Params */
- lp->txdelay = DEF_A_TXDELAY;
- lp->persist = DEF_A_PERSIST;
- lp->slotime = DEF_A_SLOTIME;
- lp->squeldelay = DEF_A_SQUELDELAY;
- lp->clockmode = DEF_A_CLOCKMODE;
-
- } else {
- lp->speed = DEF_B_SPEED;
- /* default channel access Params */
- lp->txdelay = DEF_B_TXDELAY;
- lp->persist = DEF_B_PERSIST;
- lp->slotime = DEF_B_SLOTIME;
- lp->squeldelay = DEF_B_SQUELDELAY;
- lp->clockmode = DEF_B_CLOCKMODE;
- }
- lp->bufsiz = DMA_BUFF_SIZE;
- lp->tstate = IDLE;
-
- chipset_init(dev);
-
- if (dev->base_addr & CHANA) { /* Do these things only for the A port */
- /* Note that a single IRQ services 2 devices (A and B channels) */
-
- lp->dmachan = dev->dma;
- if (lp->dmachan < 1 || lp->dmachan > 3)
- printk(KERN_ERR "PI: DMA channel %d out of range\n", lp->dmachan);
-
- /* chipset_init() was already called */
-
- if (dev->irq < 2) {
- autoirq_setup(0);
- save_flags(flags);
- cli();
- wrtscc(lp->cardbase, CTL + lp->base, R1, EXT_INT_ENAB);
- /* enable PI card interrupts */
- wrtscc(lp->cardbase, CTL + lp->base, R9, MIE | NV);
- restore_flags(flags);
- /* request a timer interrupt for 1 mS hence */
- tdelay(lp, 1);
- /* 20 "jiffies" should be plenty of time... */
- dev->irq = autoirq_report(20);
- if (!dev->irq) {
- printk(KERN_ERR "PI: Failed to detect IRQ line.\n");
- }
- save_flags(flags);
- cli();
- wrtscc(lp->cardbase, dev->base_addr + CTL, R9, FHWRES); /* Hardware reset */
- /* Disable interrupts with master interrupt ctrl reg */
- wrtscc(lp->cardbase, dev->base_addr + CTL, R9, 0);
- restore_flags(flags);
- }
-
- printk(KERN_INFO "PI: Autodetected IRQ %d, assuming DMA %d.\n",
- dev->irq, dev->dma);
-
- /* This board has jumpered interrupts. Snarf the interrupt vector
- now. There is no point in waiting since no other device can use
- the interrupt, and this marks the 'irqaction' as busy. */
- {
- int irqval = request_irq(dev->irq, &pi_interrupt,0, "pi2", dev);
- if (irqval) {
- printk(KERN_ERR "PI: unable to get IRQ %d (irqval=%d).\n",
- dev->irq, irqval);
- return EAGAIN;
- }
- }
-
- /* Grab the region */
- request_region(ioaddr & 0x3f0, PI_TOTAL_SIZE, "pi2" );
-
-
- } /* Only for A port */
- dev->open = pi_open;
- dev->stop = pi_close;
- dev->do_ioctl = pi_ioctl;
- dev->hard_start_xmit = pi_send_packet;
- dev->get_stats = pi_get_stats;
-
- /* Fill in the fields of the device structure */
-
- dev_init_buffers(dev);
-
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
- dev->hard_header = ax25_encapsulate;
- dev->rebuild_header = ax25_rebuild_header;
-#endif
-
- dev->set_mac_address = pi_set_mac_address;
-
- dev->type = ARPHRD_AX25; /* AF_AX25 device */
- dev->hard_header_len = 73; /* We do digipeaters now */
- dev->mtu = 1500; /* eth_mtu is the default */
- dev->addr_len = 7; /* sizeof an ax.25 address */
- memcpy(dev->broadcast, ax25_bcast, 7);
- memcpy(dev->dev_addr, ax25_test, 7);
-
- /* New-style flags. */
- dev->flags = 0;
- return 0;
-}
-
-/* Open/initialize the board. This is called (in the current kernel)
- sometime after booting when the 'ifconfig' program is run.
-
- This routine should set everything up anew at each open, even
- registers that "should" only need to be set once at boot, so that
- there is non-reboot way to recover if something goes wrong.
- */
-static int pi_open(struct device *dev)
-{
- unsigned long flags;
- static first_time = 1;
-
- struct pi_local *lp = (struct pi_local *) dev->priv;
-
- if (dev->base_addr & 2) { /* if A channel */
- if (first_time) {
- if (request_dma(dev->dma,"pi2")) {
- free_irq(dev->irq, dev);
- return -EAGAIN;
- }
- }
- /* Reset the hardware here. */
- chipset_init(dev);
- }
- lp->tstate = IDLE;
-
- if (dev->base_addr & 2) { /* if A channel */
- scc_init(dev); /* Called once for each channel */
- scc_init(dev->next);
- }
- /* master interrupt enable */
- save_flags(flags);
- cli();
- wrtscc(lp->cardbase, CTL + lp->base, R9, MIE | NV);
- restore_flags(flags);
-
- lp->open_time = jiffies;
-
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
- first_time = 0;
-
- MOD_INC_USE_COUNT;
-
- return 0;
-}
-
-static int pi_send_packet(struct sk_buff *skb, struct device *dev)
-{
- struct pi_local *lp = (struct pi_local *) dev->priv;
-
- hardware_send_packet(lp, skb);
- dev->trans_start = jiffies;
-
- return 0;
-}
-
-/* The typical workload of the driver:
- Handle the network interface interrupts. */
-static void pi_interrupt(int reg_ptr, void *dev_id, struct pt_regs *regs)
-{
-/* int irq = -(((struct pt_regs *) reg_ptr)->orig_eax + 2);*/
- struct pi_local *lp;
- int st;
- unsigned long flags;
-
-/* dev_b = dev_a->next; Relies on the order defined in Space.c */
-
-#if 0
- if (dev_a == NULL) {
- printk(KERN_ERR "PI: pi_interrupt(): irq %d for unknown device.\n", irq);
- return;
- }
-#endif
- /* Read interrupt status register (only valid from channel A)
- * Process all pending interrupts in while loop
- */
- lp = (struct pi_local *) pi0a.priv; /* Assume channel A */
- while ((st = rdscc(lp->cardbase, pi0a.base_addr | CHANA | CTL, R3)) != 0) {
- if (st & CHBTxIP) {
- /* Channel B Transmit Int Pending */
- lp = (struct pi_local *) pi0b.priv;
- b_txint(lp);
- } else if (st & CHARxIP) {
- /* Channel A Rcv Interrupt Pending */
- lp = (struct pi_local *) pi0a.priv;
- a_rxint(&pi0a, lp);
- } else if (st & CHATxIP) {
- /* Channel A Transmit Int Pending */
- lp = (struct pi_local *) pi0a.priv;
- a_txint(lp);
- } else if (st & CHAEXT) {
- /* Channel A External Status Int */
- lp = (struct pi_local *) pi0a.priv;
- a_exint(lp);
- } else if (st & CHBRxIP) {
- /* Channel B Rcv Interrupt Pending */
- lp = (struct pi_local *) pi0b.priv;
- b_rxint(&pi0b, lp);
- } else if (st & CHBEXT) {
- /* Channel B External Status Int */
- lp = (struct pi_local *) pi0b.priv;
- b_exint(lp);
- }
- /* Reset highest interrupt under service */
- save_flags(flags);
- cli();
- wrtscc(lp->cardbase, lp->base + CTL, R0, RES_H_IUS);
- restore_flags(flags);
- } /* End of while loop on int processing */
- return;
-}
-
-/* The inverse routine to pi_open(). */
-static int pi_close(struct device *dev)
-{
- unsigned long flags;
- struct pi_local *lp;
- struct sk_buff *ptr;
-
- save_flags(flags);
- cli();
-
- lp = (struct pi_local *) dev->priv;
- ptr = NULL;
-
- chipset_init(dev); /* reset the scc */
- disable_dma(lp->dmachan);
-
- lp->open_time = 0;
-
- dev->tbusy = 1;
- dev->start = 0;
-
- /* Free any buffers left in the hardware transmit queue */
- while ((ptr = skb_dequeue(&lp->sndq)) != NULL)
- kfree_skb(ptr, FREE_WRITE);
-
- restore_flags(flags);
-
- MOD_DEC_USE_COUNT;
-
- return 0;
-}
-
-static int pi_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
-{
- unsigned long flags;
- struct pi_req rq;
- struct pi_local *lp = (struct pi_local *) dev->priv;
-
- int ret = verify_area(VERIFY_WRITE, ifr->ifr_data, sizeof(struct pi_req));
- if (ret)
- return ret;
-
- if(cmd!=SIOCDEVPRIVATE)
- return -EINVAL;
-
- copy_from_user(&rq, ifr->ifr_data, sizeof(struct pi_req));
-
- switch (rq.cmd) {
- case SIOCSPIPARAM:
-
- if (!suser())
- return -EPERM;
- save_flags(flags);
- cli();
- lp->txdelay = rq.txdelay;
- lp->persist = rq.persist;
- lp->slotime = rq.slotime;
- lp->squeldelay = rq.squeldelay;
- lp->clockmode = rq.clockmode;
- lp->speed = rq.speed;
- pi_open(&pi0a); /* both channels get reset %%% */
- restore_flags(flags);
- ret = 0;
- break;
-
- case SIOCSPIDMA:
-
- if (!suser())
- return -EPERM;
- ret = 0;
- if (dev->base_addr & 2) { /* if A channel */
- if (rq.dmachan < 1 || rq.dmachan > 3)
- return -EINVAL;
- save_flags(flags);
- cli();
- pi_close(dev);
- free_dma(lp->dmachan);
- dev->dma = lp->dmachan = rq.dmachan;
- if (request_dma(lp->dmachan,"pi2"))
- ret = -EAGAIN;
- pi_open(dev);
- restore_flags(flags);
- }
- break;
-
- case SIOCSPIIRQ:
- ret = -EINVAL; /* add this later */
- break;
-
- case SIOCGPIPARAM:
- case SIOCGPIDMA:
- case SIOCGPIIRQ:
-
- rq.speed = lp->speed;
- rq.txdelay = lp->txdelay;
- rq.persist = lp->persist;
- rq.slotime = lp->slotime;
- rq.squeldelay = lp->squeldelay;
- rq.clockmode = lp->clockmode;
- rq.dmachan = lp->dmachan;
- rq.irq = dev->irq;
- copy_to_user(ifr->ifr_data, &rq, sizeof(struct pi_req));
- ret = 0;
- break;
-
- default:
- ret = -EINVAL;
- }
- return ret;
-}
-
-/* Get the current statistics. This may be called with the card open or
- closed. */
-static struct net_device_stats *pi_get_stats(struct device *dev)
-{
- struct pi_local *lp = (struct pi_local *) dev->priv;
-
- return &lp->stats;
-}
-
-#ifdef MODULE
-EXPORT_NO_SYMBOLS;
-
-MODULE_AUTHOR("David Perry <dp@hydra.carleton.ca>");
-MODULE_DESCRIPTION("AX.25 driver for the Ottawa PI and PI/2 HDLC cards");
-
-int init_module(void)
-{
- return pi_init();
-}
-
-void cleanup_module(void)
-{
- free_irq(pi0a.irq, &pi0a); /* IRQs and IO Ports are shared */
- release_region(pi0a.base_addr & 0x3f0, PI_TOTAL_SIZE);
-
- kfree(pi0a.priv);
- pi0a.priv = NULL;
- unregister_netdev(&pi0a);
-
- kfree(pi0b.priv);
- pi0b.priv = NULL;
- unregister_netdev(&pi0b);
-}
-#endif
diff --git a/drivers/net/plip.c b/drivers/net/plip.c
index 17c85a9ba..1774de0bb 100644
--- a/drivers/net/plip.c
+++ b/drivers/net/plip.c
@@ -1,5 +1,3 @@
-#warning This wont work until we merge the networking changes
-#if 0
/* $Id: plip.c,v 1.3.6.2 1997/04/16 15:07:56 phil Exp $ */
/* PLIP: A parallel port "network" driver for Linux. */
/* This driver is for parallel port with 5-bit cable (LapLink (R) cable). */
@@ -1238,4 +1236,3 @@ plip_init(void))
* compile-command: "gcc -DMODULE -DMODVERSIONS -D__KERNEL__ -Wall -Wstrict-prototypes -O2 -g -fomit-frame-pointer -pipe -m486 -c plip.c"
* End:
*/
-#endif
diff --git a/drivers/net/ppp.c b/drivers/net/ppp.c
index 3c86a779f..cb977abde 100644
--- a/drivers/net/ppp.c
+++ b/drivers/net/ppp.c
@@ -83,6 +83,7 @@
#include <linux/if_ether.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
+#include <linux/rtnetlink.h>
#include <linux/inet.h>
#include <linux/ioctl.h>
#include <linux/init.h>
@@ -682,10 +683,12 @@ ppp_release (struct ppp *ppp)
if (tty != NULL && tty->disc_data == ppp)
tty->disc_data = NULL; /* Break the tty->ppp link */
+ rtnl_lock();
/* Strong layering violation. */
- if (dev && dev->flags & IFF_UP) {
- dev_close (dev); /* close the device properly */
- }
+ if (dev && dev->flags & IFF_UP) {
+ dev_close (dev); /* close the device properly */
+ }
+ rtnl_unlock();
ppp_free_buf (ppp->rbuf);
ppp_free_buf (ppp->wbuf);
@@ -3017,8 +3020,8 @@ ppp_dev_xmit (sk_buff *skb, struct device *dev)
*/
if (!ppp->inuse) {
dev_kfree_skb (skb, FREE_WRITE);
- printk("I am dying to know, are you still alive?\n");
-#ifdef main_got_it_is_something
+ printk(KERN_WARNING "ppp: I am dying to know, are you still alive?\n");
+#if 0
dev_close (dev);
#endif
return 0;
diff --git a/drivers/net/pt.c b/drivers/net/pt.c
index 11bef1d6f..e69de29bb 100644
--- a/drivers/net/pt.c
+++ b/drivers/net/pt.c
@@ -1,1778 +0,0 @@
-#undef PT_DEBUG 1
-/*
- * pt.c: Linux device driver for the Gracilis PackeTwin.
- * Copyright (c) 1995 Craig Small VK2XLZ (vk2xlz@vk2xlz.ampr.org.)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2, as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 675 Mass Ave, Cambridge MA 02139, USA.
- *
- * This driver is largely based upon the PI driver by David Perry.
- *
- * Revision History
- * 23/02/95 cs Started again on driver, last one scrapped
- * 27/02/95 cs Program works, we have chan A only. Tx stays on
- * 28/02/95 cs Fix Tx problem (& TxUIE instead of | )
- * Fix Chan B Tx timer problem, used TMR2 instead of TMR1
- * 03/03/95 cs Painfully found out (after 3 days) SERIAL_CFG is write only
- * created image of it and DMA_CFG
- * 21/06/95 cs Upgraded to suit PI driver 0.8 ALPHA
- * 22/08/95 cs Changed it all around to make it like pi driver
- * 23/08/95 cs It now works, got caught again by TMR2 and we must have
- * auto-enables for daughter boards.
- * 07/10/95 cs Fixed for 1.3.30 (hopefully)
- * 26/11/95 cs Fixed for 1.3.43, ala 29/10 for pi2.c by ac
- * 21/12/95 cs Got rid of those nasty warnings when compiling, for 1.3.48
- * 08/08/96 jsn Convert to use as a module. Removed send_kiss, empty_scc and
- * pt_loopback functions - they were unused.
- * 13/12/96 jsn Fixed to match Linux networking changes.
- */
-
-/*
- * default configuration of the PackeTwin,
- * ie What Craig uses his PT for.
- */
-#define PT_DMA 3
-
-#define DEF_A_SPEED 4800 /* 4800 baud */
-#define DEF_A_TXDELAY 350 /* 350 mS */
-#define DEF_A_PERSIST 64 /* 25% persistence */
-#define DEF_A_SLOTIME 10 /* 10 mS */
-#define DEF_A_SQUELDELAY 30 /* 30 mS */
-#define DEF_A_CLOCKMODE 0 /* Normal clock mode */
-#define DEF_A_NRZI 1 /* NRZI mode */
-
-#define DEF_B_SPEED 0 /* 0 means external clock */
-#define DEF_B_TXDELAY 250 /* 250 mS */
-#define DEF_B_PERSIST 64 /* 25% */
-#define DEF_B_SLOTIME 10 /* 10 mS */
-#define DEF_B_SQUELDELAY 30 /* 30 mS */
-#define DEF_B_CLOCKMODE 0 /* Normal clock mode ?!? */
-#define DEF_B_NRZI 1 /* NRZI mode */
-
-
-#define PARAM_TXDELAY 1
-#define PARAM_PERSIST 2
-#define PARAM_SLOTTIME 3
-#define PARAM_FULLDUP 5
-#define PARAM_HARDWARE 6
-#define PARAM_RETURN 255
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ptrace.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/malloc.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <asm/system.h>
-#include <asm/bitops.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <asm/uaccess.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/timer.h>
-#include <linux/if_arp.h>
-#include <linux/pt.h>
-#include <linux/init.h>
-#include "z8530.h"
-#include <net/ax25.h>
-
-struct mbuf {
- struct mbuf *next;
- int cnt;
- char data[0];
-};
-
-/*
- * The actual PT devices we will use
- */
-static int pt0_preprobe(struct device *dev) {return 0;} /* Dummy probe function */
-static struct device pt0a = { "pt0a", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, pt0_preprobe };
-static struct device pt0b = { "pt0b", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, pt0_preprobe };
-
-/* Ok, they shouldn't be here, but both channels share them */
-/* The Images of the Serial and DMA config registers */
-static unsigned char pt_sercfg = 0;
-static unsigned char pt_dmacfg = 0;
-
-/* The number of IO ports used by the card */
-#define PT_TOTAL_SIZE 16
-
-/* Index to functions, as function prototypes. */
-
-static int pt_probe(struct device *dev);
-static int pt_open(struct device *dev);
-static int pt_send_packet(struct sk_buff *skb, struct device *dev);
-static void pt_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static int pt_close(struct device *dev);
-static int pt_ioctl(struct device *dev, struct ifreq *ifr, int cmd);
-static struct net_device_stats *pt_get_stats(struct device *dev);
-static void pt_rts(struct pt_local *lp, int x);
-static void pt_rxisr(struct device *dev);
-static void pt_txisr(struct pt_local *lp);
-static void pt_exisr(struct pt_local *lp);
-static void pt_tmrisr(struct pt_local *lp);
-static char *get_dma_buffer(unsigned long *mem_ptr);
-static int valid_dma_page(unsigned long addr, unsigned long dev_buffsize);
-static int hw_probe(int ioaddr);
-static void tdelay(struct pt_local *lp, int time);
-static void chipset_init(struct device *dev);
-
-static char ax25_bcast[7] =
-{'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, '0' << 1};
-static char ax25_test[7] =
-{'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1, '1' << 1};
-
-
-
-static int ext2_secrm_seed = 152;
-
-static inline unsigned char random(void)
-{
- return (unsigned char) (ext2_secrm_seed = ext2_secrm_seed * 60691 + 1);
-}
-
-static inline void wrtscc(int cbase, int ctl, int sccreg, unsigned char val)
-{
- outb_p(sccreg, ctl); /* Select register */
- outb_p(val, ctl); /* Output value */
-}
-
-static inline unsigned char rdscc(int cbase, int ctl, int sccreg)
-{
- unsigned char retval;
-
- outb_p(sccreg, ctl); /* Select register */
- retval = inb_p(ctl);
- return retval;
-}
-
-static void switchbuffers(struct pt_local *lp)
-{
- if (lp->rcvbuf == lp->rxdmabuf1)
- lp->rcvbuf = lp->rxdmabuf2;
- else
- lp->rcvbuf = lp->rxdmabuf1;
-}
-
-static void hardware_send_packet(struct pt_local *lp, struct sk_buff *skb)
-{
- char kickflag;
- unsigned long flags;
- char *ptr;
- struct device *dev;
-
- /* First, let's see if this packet is actually a KISS packet */
- ptr = skb->data;
- if (ptr[0] != 0 && skb->len >= 2)
- {
-#ifdef PT_DEBUG
- printk(KERN_DEBUG "PT: Rx KISS... Control = %d, value = %d.\n", ptr[0], (skb->len > 1? ptr[1] : -1));
-#endif
- /* Kludge to get device */
- if ((struct pt_local*)(&pt0b.priv) == lp)
- dev = &pt0b;
- else
- dev = &pt0a;
- switch(ptr[0])
- {
-
- case PARAM_TXDELAY:
- /*TxDelay is in 10mS increments */
- lp->txdelay = ptr[1] * 10;
- break;
- case PARAM_PERSIST:
- lp->persist = ptr[1];
- break;
- case PARAM_SLOTTIME:
- lp->slotime = ptr[1];
- break;
- case PARAM_FULLDUP:
- /* Yeah right, you wish! Fullduplex is a little while to
- * go folks, but this is how you fire it up
- */
- break;
- /* Perhaps we should have txtail here?? */
- } /*switch */
- return;
- }
-
- lp->stats.tx_packets++;
- lp->stats.tx_bytes+=skb->len;
- save_flags(flags);
- cli();
- kickflag = (skb_peek(&lp->sndq) == NULL) && (lp->sndbuf == NULL);
- restore_flags(flags);
-
-#ifdef PT_DEBUG
- printk(KERN_DEBUG "PT: hardware_send_packet(): kickflag = %d (%d).\n", kickflag, lp->base & CHANA);
-#endif
- skb_queue_tail(&lp->sndq, skb);
- if (kickflag)
- {
- /* Simulate interrupt to transmit */
- if (lp->dmachan)
- pt_txisr(lp);
- else
- {
- save_flags(flags);
- cli();
- if (lp->tstate == IDLE)
- pt_txisr(lp);
- restore_flags(flags);
- }
- }
-} /* hardware_send_packet() */
-
-static void setup_rx_dma(struct pt_local *lp)
-{
- unsigned long flags;
- int cmd;
- unsigned long dma_abs;
- unsigned char dmachan;
-
- save_flags(flags);
- cli();
-
- dma_abs = (unsigned long) (lp->rcvbuf->data);
- dmachan = lp->dmachan;
- cmd = lp->base + CTL;
-
- if(!valid_dma_page(dma_abs, DMA_BUFF_SIZE + sizeof(struct mbuf)))
- panic("PI: RX buffer violates DMA boundary!");
-
- /* Get ready for RX DMA */
- wrtscc(lp->cardbase, cmd, R1, WT_FN_RDYFN | WT_RDY_RT | INT_ERR_Rx | EXT_INT_ENAB);
-
- disable_dma(dmachan);
- clear_dma_ff(dmachan);
-
- /*
- * Set DMA mode register to single transfers, incrementing address,
- * auto init, writes
- */
-
- set_dma_mode(dmachan, DMA_MODE_READ | 0x10);
- set_dma_addr(dmachan, dma_abs);
- set_dma_count(dmachan, lp->bufsiz);
- enable_dma(dmachan);
-
- /*
- * If a packet is already coming in, this line is supposed to
- * avoid receiving a partial packet.
- */
-
- wrtscc(lp->cardbase, cmd, R0, RES_Rx_CRC);
-
- /* Enable RX dma */
- wrtscc(lp->cardbase, cmd, R1,
- WT_RDY_ENAB | WT_FN_RDYFN | WT_RDY_RT | INT_ERR_Rx | EXT_INT_ENAB);
-
- restore_flags(flags);
-}
-
-static void setup_tx_dma(struct pt_local *lp, int length)
-{
- unsigned long dma_abs;
- unsigned long flags;
- unsigned long dmachan;
-
- save_flags(flags);
- cli();
-
- dmachan = lp->dmachan;
- dma_abs = (unsigned long) (lp->txdmabuf);
-
- if(!valid_dma_page(dma_abs, DMA_BUFF_SIZE + sizeof(struct mbuf)))
- panic("PT: TX buffer violates DMA boundary!");
-
- disable_dma(dmachan);
- /* Set DMA mode register to single transfers, incrementing address,
- * no auto init, reads
- */
- set_dma_mode(dmachan, DMA_MODE_WRITE);
- clear_dma_ff(dmachan);
- set_dma_addr(dmachan, dma_abs);
- /* output byte count */
- set_dma_count(dmachan, length);
-
- restore_flags(flags);
-}
-
-/*
- * This sets up all the registers in the SCC for the given channel
- * based upon tsync_hwint()
- */
-static void scc_init(struct device *dev)
-{
- unsigned long flags;
- struct pt_local *lp = (struct pt_local*) dev->priv;
- register int cmd = lp->base + CTL;
- int tc, br;
-
-#ifdef PT_DEBUG
- printk(KERN_DEBUG "PT: scc_init(): (%d).\n", lp->base & CHANA);
-#endif
- save_flags(flags);
- cli();
-
- /* We may put something here to enable_escc */
-
- if (cmd & CHANA)
- {
- wrtscc(lp->cardbase, cmd, R9, CHRA); /* Reset channel A */
- wrtscc(lp->cardbase, cmd, R2, 0xff); /* Initialise interrupt vector */
- }
- else
- wrtscc(lp->cardbase, cmd, R9, CHRB); /* Reset channel B */
-
- /* Deselect all Rx and Tx interrupts */
- wrtscc(lp->cardbase, cmd, R1, 0);
-
- /* Turn off external interrupts (like CTS/CD) */
- wrtscc(lp->cardbase, cmd, R15, 0);
-
- /* X1 clock, SDLC mode */
- wrtscc(lp->cardbase, cmd, R4, SDLC | X1CLK);
-
- /* Preset CRC and set mode */
- if (lp->nrzi)
- /* Preset Tx CRC, put into NRZI mode */
- wrtscc(lp->cardbase, cmd, R10, CRCPS | NRZI);
- else
- /* Preset Tx CRC, put into NRZ mode */
- wrtscc(lp->cardbase, cmd, R10, CRCPS);
-
- /* Tx/Rx parameters */
- if (lp->speed) /* Use internal clocking */
- /* Tx Clk from BRG. Rx Clk form DPLL, TRxC pin outputs DPLL */
- wrtscc(lp->cardbase, cmd, R11, TCBR | RCDPLL | TRxCDP | TRxCOI);
- else /* Use external clocking */
- {
- /* Tx Clk from TRxCL. Rx Clk from RTxCL, TRxC pin if input */
- wrtscc(lp->cardbase, cmd, R11, TCTRxCP | RCRTxCP | TRxCBR);
- wrtscc(lp->cardbase,cmd, R14, 0); /* wiz1 */
- }
-
- /* Null out SDLC start address */
- wrtscc(lp->cardbase, cmd, R6, 0);
-
- /* SDLC flag */
- wrtscc(lp->cardbase, cmd, R7, FLAG);
-
- /* Setup Tx but don't enable it */
- wrtscc(lp->cardbase, cmd, R5, Tx8 | DTR);
-
- /* Setup Rx */
- wrtscc(lp->cardbase, cmd, R3, AUTO_ENAB | Rx8);
-
- /* Setup the BRG, turn it off first */
- wrtscc(lp->cardbase, cmd, R14, BRSRC);
-
- /* set the 32x time constant for the BRG in Rx mode */
- if (lp->speed)
- {
- br = lp->speed;
- tc = ((lp->xtal / 32) / (br * 2)) - 2;
- wrtscc(lp->cardbase, cmd, R12, tc & 0xff); /* lower byte */
- wrtscc(lp->cardbase, cmd, R13, (tc >> 8) & 0xff); /* upper byte */
- }
-
- /* Turn transmitter off, to setup stuff */
- pt_rts(lp, OFF);
-
- /* External clocking */
- if (lp->speed)
- {
- /* DPLL frm BRG, BRG src PCLK */
- wrtscc(lp->cardbase, cmd, R14, BRSRC | SSBR);
- wrtscc(lp->cardbase, cmd, R14, BRSRC | SEARCH); /* SEARCH mode, keep BRG src */
- wrtscc(lp->cardbase, cmd, R14, BRSRC | BRENABL); /* Enable the BRG */
-
- /* Turn off external clock port */
- if (lp->base & CHANA)
- outb_p( (pt_sercfg &= ~PT_EXTCLKA), (lp->cardbase + SERIAL_CFG) );
- else
- outb_p( (pt_sercfg &= ~PT_EXTCLKB), (lp->cardbase + SERIAL_CFG) );
- }
- else
- {
- /* DPLL frm rtxc,BRG src PCLK */
- /* Turn on external clock port */
- if (lp->base & CHANA)
- outb_p( (pt_sercfg |= PT_EXTCLKA), (lp->cardbase + SERIAL_CFG) );
- else
- outb_p( (pt_sercfg |= PT_EXTCLKB), (lp->cardbase + SERIAL_CFG) );
- }
-
- if (!lp->dmachan)
- wrtscc(lp->cardbase, cmd, R1, (INT_ALL_Rx | EXT_INT_ENAB));
-
- wrtscc(lp->cardbase, cmd, R15, BRKIE); /* ABORT int */
-
- /* Turn on the DTR to tell modem we're alive */
- if (lp->base & CHANA)
- outb_p( (pt_sercfg |= PT_DTRA_ON), (lp->cardbase + SERIAL_CFG) );
- else
- outb_p( (pt_sercfg |= PT_DTRB_ON), (lp->cardbase + SERIAL_CFG) );
-
- /* Now, turn on the receiver and hunt for a flag */
- wrtscc(lp->cardbase, cmd, R3, RxENABLE | RxCRC_ENAB | AUTO_ENAB | Rx8 );
-
- restore_flags(flags);
-
-} /* scc_init() */
-
-/* Resets the given channel and whole SCC if both channels off */
-static void chipset_init(struct device *dev)
-{
-
- struct pt_local *lp = (struct pt_local*) dev->priv;
-#ifdef PT_DEBUG
- printk(KERN_DEBUG "PT: chipset_init(): pt0a tstate = %d.\n", ((struct pt_local*)pt0a.priv)->tstate);
- printk(KERN_DEBUG "PT: chipset_init(): pt0b tstate = %d.\n", ((struct pt_local*)pt0b.priv)->tstate);
-#endif
- /* Reset SCC if both channels are to be canned */
- if ( ((lp->base & CHANA) && !(pt_sercfg & PT_DTRB_ON)) ||
- (!(lp->base & CHANA) && !(pt_sercfg & PT_DTRA_ON)) )
- {
- wrtscc(lp->cardbase, lp->base + CTL, R9, FHWRES);
- /* Reset int and dma registers */
- outb_p((pt_sercfg = 0), lp->cardbase + SERIAL_CFG);
- outb_p((pt_dmacfg = 0), lp->cardbase + DMA_CFG);
-#ifdef PT_DEBUG
- printk(KERN_DEBUG "PT: chipset_init() Resetting SCC, called by ch (%d).\n", lp->base & CHANA);
-#endif
- }
- /* Reset individual channel */
- if (lp->base & CHANA) {
- wrtscc(lp->cardbase, lp->base + CTL, R9, MIE | DLC | NV | CHRA);
- outb_p( (pt_sercfg &= ~PT_DTRA_ON), lp->cardbase + SERIAL_CFG);
- } else {
- wrtscc(lp->cardbase, lp->base + CTL, R9, MIE | DLC | NV | CHRB);
- outb_p( (pt_sercfg &= ~PT_DTRB_ON), lp->cardbase + SERIAL_CFG);
- }
-} /* chipset_init() */
-
-
-
-__initfunc(int pt_init(void))
-{
- int *port;
- int ioaddr = 0;
- int card_type = 0;
- int ports[] =
- { 0x230, 0x240, 0x250, 0x260, 0x270, 0x280, 0x290, 0x2a0,
- 0x2b0, 0x300, 0x330, 0x3f0, 0};
-
- printk(KERN_INFO "PT: 0.41 ALPHA 07 October 1995 Craig Small (csmall@small.dropbear.id.au)\n");
-
- for (port = &ports[0]; *port && !card_type; port++) {
- ioaddr = *port;
-
- if (check_region(ioaddr, PT_TOTAL_SIZE) == 0) {
- printk(KERN_INFO "PT: Probing for card at address %#3x\n", ioaddr);
- card_type = hw_probe(ioaddr);
- }
- }
- if (card_type) {
- printk(KERN_INFO "PT: Found a PT at address %#3x\n",ioaddr);
- } else {
- printk(KERN_ERR "PT: ERROR: No card found.\n");
- return -EIO;
- }
-
- /*
- * Link a couple of device structures into the chain
- *
- * For the A port
- * Allocate space for 4 buffers even though we only need 3,
- * because one of them may cross a DMA page boundary and
- * be rejected by get_dma_buffer().
- */
- register_netdev(&pt0a);
-
- pt0a.priv= kmalloc(sizeof(struct pt_local) + (DMA_BUFF_SIZE + sizeof(struct mbuf)) * 4, GFP_KERNEL | GFP_DMA);
-
- pt0a.dma = 0; /* wizzer - no dma yet */
- pt0a.base_addr = ioaddr + CHANA;
- pt0a.irq = 0;
-
- /* And B port */
- register_netdev(&pt0b);
-
- pt0b.priv= kmalloc(sizeof(struct pt_local) + (DMA_BUFF_SIZE + sizeof(struct mbuf)) * 4, GFP_KERNEL | GFP_DMA);
-
- pt0b.base_addr = ioaddr + CHANB;
- pt0b.irq = 0;
-
- /* Now initialise them */
- pt_probe(&pt0a);
- pt_probe(&pt0b);
-
- pt0b.irq = pt0a.irq; /* IRQ is shared */
-
- return 0;
-} /* pt_init() */
-
-/*
- * Probe for PT card. Also initialises the timers
- */
-__initfunc(static int hw_probe(int ioaddr))
-{
- int time = 1000; /* Number of milliseconds to test */
- int a = 1;
- int b = 1;
- unsigned long start_time, end_time;
-
- inb_p(ioaddr + TMR1CLR);
- inb_p(ioaddr + TMR2CLR);
-
- /* Timer counter channel 0, 1mS period */
- outb_p(SC0 | LSB_MSB | MODE3, ioaddr + TMRCMD);
- outb_p(0x00, ioaddr + TMR0);
- outb_p(0x18, ioaddr + TMR0);
-
- /* Setup timer control word for timer 1 */
- outb_p(SC1 | LSB_MSB | MODE0, ioaddr + TMRCMD);
- outb_p((time << 1) & 0xff, ioaddr + TMR1);
- outb_p((time >> 7) & 0xff, ioaddr + TMR1);
-
- /* wait until counter reg is loaded */
- do {
- /* Latch count for reading */
- outb_p(SC1, ioaddr + TMRCMD);
- a = inb_p(ioaddr + TMR1);
- b = inb_p(ioaddr + TMR1);
- } while (b == 0);
- start_time = jiffies;
- while(b != 0)
- {
- /* Latch count for reading */
- outb_p(SC1, ioaddr + TMRCMD);
- a = inb_p(ioaddr + TMR1);
- b = inb_p(ioaddr + TMR1);
- end_time = jiffies;
- /* Don't wait forever - there may be no card here */
- if ((end_time - start_time) > 200)
- {
- inb_p(ioaddr + TMR1CLR);
- return 0;
- }
- }
-
- /* Now fix the timers up for general operation */
-
- /* Clear the timers */
- inb_p(ioaddr + TMR1CLR);
- inb_p(ioaddr + TMR2CLR);
-
- outb_p(SC1 | LSB_MSB | MODE0, ioaddr + TMRCMD);
- inb_p(ioaddr + TMR1CLR);
-
- outb_p(SC2 | LSB_MSB | MODE0, ioaddr + TMRCMD);
- /* Should this be tmr1 or tmr2? wiz3*/
- inb_p(ioaddr + TMR1CLR);
-
- return 1;
-} /* hw_probe() */
-
-
-static void pt_rts(struct pt_local *lp, int x)
-{
- int tc;
- long br;
- int cmd = lp->base + CTL;
-#ifdef PT_DEBUG
- printk(KERN_DEBUG "PT: pt_rts(): Transmitter status will be %d (%d).\n", x, lp->base & CHANA);
-#endif
- if (x == ON) {
- /* Ex ints off to avoid int */
- wrtscc(lp->cardbase, cmd, R15, 0);
- wrtscc(lp->cardbase, cmd, R3, AUTO_ENAB | Rx8); /* Rx off */
- lp->rstate = IDLE;
-
- if(lp->dmachan)
- {
- /* Setup for Tx DMA */
- wrtscc(lp->cardbase, cmd, R1, WT_FN_RDYFN | EXT_INT_ENAB);
- } else {
- /* No interrupts */
- wrtscc(lp->cardbase, cmd, R1, 0);
- }
-
- if (!lp->clockmode)
- {
- if (lp->speed)
- {
- br = lp->speed;
- tc = (lp->xtal / (br * 2)) - 2;
- wrtscc(lp->cardbase, cmd, R12, tc & 0xff);
- wrtscc(lp->cardbase, cmd, R13, (tc >> 8) & 0xff);
- }
- }
- /* Turn on Tx by raising RTS */
- wrtscc(lp->cardbase, cmd, R5, TxCRC_ENAB | RTS | TxENAB | Tx8 | DTR);
- /* Transmitter on now */
- } else { /* turning off Tx */
- lp->tstate = IDLE;
-
- /* Turn off Tx by dropping RTS */
- wrtscc(lp->cardbase, cmd, R5, Tx8 | DTR);
- if (!lp->clockmode)
- {
- if (lp->speed) /* internally clocked */
- {
- /* Reprogram BRG from 32x clock for Rx DPLL */
- /* BRG off, keep PClk source */
- wrtscc(lp->cardbase, cmd, R14, BRSRC);
- br = lp->speed;
- tc = ((lp->xtal / 32) / (br * 2)) - 2;
- wrtscc(lp->cardbase, cmd, R12, tc & 0xff);
- wrtscc(lp->cardbase, cmd, R13, (tc >> 8) & 0xff);
-
- /* SEARCH mode, BRG source */
- wrtscc(lp->cardbase, cmd, R14, BRSRC | SEARCH);
- /* Enable the BRG */
- wrtscc(lp->cardbase, cmd, R14, BRSRC | BRENABL);
- }
- }
- /* Flush Rx fifo */
- /* Turn Rx off */
- wrtscc(lp->cardbase, cmd, R3, AUTO_ENAB | Rx8);
-
- /* Reset error latch */
- wrtscc(lp->cardbase, cmd, R0, ERR_RES);
-
- /* get status byte from R1 */
- (void) rdscc(lp->cardbase, cmd, R1);
-
- /* Read and dump data in queue */
- (void) rdscc(lp->cardbase, cmd, R8);
- (void) rdscc(lp->cardbase, cmd, R8);
- (void) rdscc(lp->cardbase, cmd, R8);
-
- /* Now, turn on Rx and hunt for a flag */
- wrtscc(lp->cardbase, cmd, R3, RxENABLE | AUTO_ENAB | Rx8 );
-
- lp->rstate = ACTIVE;
-
- if (lp->dmachan)
- {
- setup_rx_dma(lp);
- } else {
- /* Reset buffer pointers */
- lp->rcp = lp->rcvbuf->data;
- lp->rcvbuf->cnt = 0;
- /* Allow aborts to interrupt us */
- wrtscc(lp->cardbase, cmd, R1, INT_ALL_Rx | EXT_INT_ENAB);
-
- }
- wrtscc(lp->cardbase, cmd, R15, BRKIE );
- }
-} /* pt_rts() */
-
-
-static int valid_dma_page(unsigned long addr, unsigned long dev_bufsize)
-{
- if (((addr & 0xffff) + dev_bufsize) <= 0x10000)
- return 1;
- else
- return 0;
-}
-
-static int pt_set_mac_address(struct device *dev, void *addr)
-{
- struct sockaddr *sa = (struct sockaddr *)addr;
- memcpy(dev->dev_addr, sa->sa_data, dev->addr_len); /* addr is an AX.25 shifted ASCII */
- return 0; /* mac address */
-}
-
-
-/* Allocate a buffer which does not cross a DMA page boundary */
-static char * get_dma_buffer(unsigned long *mem_ptr)
-{
- char *ret;
-
- ret = (char *) *mem_ptr;
-
- if (!valid_dma_page(*mem_ptr, DMA_BUFF_SIZE + sizeof(struct mbuf))) {
- *mem_ptr += (DMA_BUFF_SIZE + sizeof(struct mbuf));
- ret = (char *) *mem_ptr;
- }
- *mem_ptr += (DMA_BUFF_SIZE + sizeof(struct mbuf));
- return (ret);
-} /* get_dma_buffer() */
-
-
-/*
- * Sets up all the structures for the PT device
- */
-static int pt_probe(struct device *dev)
-{
- short ioaddr;
- struct pt_local *lp;
- unsigned long flags;
- unsigned long mem_ptr;
-
- ioaddr = dev->base_addr;
-
- /*
- * Initialise the device structure.
- * Must be done before chipset_init()
- * Make sure data structures used by the PT are aligned
- */
- dev->priv = (void *) (((int) dev->priv + 7) & ~7);
- lp = (struct pt_local*) dev->priv;
-
- memset(dev->priv, 0, sizeof(struct pt_local));
-
- /* Allocate some buffers which do not cross DMA boundaries */
- mem_ptr = (unsigned long) dev->priv + sizeof(struct pt_local);
- lp->txdmabuf = get_dma_buffer(&mem_ptr);
- lp->rxdmabuf1 = (struct mbuf *) get_dma_buffer(&mem_ptr);
- lp->rxdmabuf2 = (struct mbuf *) get_dma_buffer(&mem_ptr);
-
- /* Initialise the Rx buffer */
- lp->rcvbuf = lp->rxdmabuf1;
- lp->rcp = lp->rcvbuf->data;
- lp->rcvbuf->cnt = 0;
-
- /* Initialise the transmit queue head structure */
- skb_queue_head_init(&lp->sndq);
-
- lp->base = dev->base_addr;
- lp->cardbase = dev->base_addr & 0x3f0;
-
- /* These need to be initialised before scc_init() is called.
- */
- lp->xtal = XTAL;
-
- if (dev->base_addr & CHANA) {
- lp->speed = DEF_A_SPEED;
- lp->txdelay = DEF_A_TXDELAY;
- lp->persist = DEF_A_PERSIST;
- lp->slotime = DEF_A_SLOTIME;
- lp->squeldelay = DEF_A_SQUELDELAY;
- lp->clockmode = DEF_A_CLOCKMODE;
- lp->nrzi = DEF_A_NRZI;
- } else {
- lp->speed = DEF_B_SPEED;
- lp->txdelay = DEF_B_TXDELAY;
- lp->persist = DEF_B_PERSIST;
- lp->slotime = DEF_B_SLOTIME;
- lp->squeldelay = DEF_B_SQUELDELAY;
- lp->clockmode = DEF_B_CLOCKMODE;
- lp->nrzi = DEF_B_NRZI;
- }
- lp->bufsiz = DMA_BUFF_SIZE;
- lp->tstate = IDLE;
-
- chipset_init(dev);
-
- if (dev->base_addr & CHANA) {
- /* Note that a single IRQ services 2 devices (A and B channels)
- */
-
- /*
- * We disable the dma for a while, we have to get ints working
- * properly first!!
- */
- lp->dmachan = 0;
-
- if (dev->irq < 2) {
- autoirq_setup(0);
-
- /* Turn on PT interrupts */
- save_flags(flags);
- cli();
- outb_p( pt_sercfg |= PT_EI, lp->cardbase + INT_CFG);
- restore_flags(flags);
-
- /* Set a timer interrupt */
- tdelay(lp, 1);
- dev->irq = autoirq_report(20);
-
- /* Turn off PT interrupts */
- save_flags(flags);
- cli();
- outb_p( (pt_sercfg &= ~ PT_EI), lp->cardbase + INT_CFG);
- restore_flags(flags);
-
- if (!dev->irq) {
- printk(KERN_ERR "PT: ERROR: Failed to detect IRQ line, assuming IRQ7.\n");
- }
- }
-
- printk(KERN_INFO "PT: Autodetected IRQ %d, assuming DMA %d\n", dev->irq, dev->dma);
-
- /* This board has jumpered interrupts. Snarf the interrupt vector
- * now. There is no point in waiting since no other device can use
- * the interrupt, and this marks the 'irqaction' as busy.
- */
- {
- int irqval = request_irq(dev->irq, &pt_interrupt,0, "pt", dev);
- if (irqval) {
- printk(KERN_ERR "PT: ERROR: Unable to get IRQ %d (irqval = %d).\n",
- dev->irq, irqval);
- return EAGAIN;
- }
- }
-
- /* Grab the region */
- request_region(ioaddr & 0x3f0, PT_TOTAL_SIZE, "pt" );
- } /* A port */
- dev->open = pt_open;
- dev->stop = pt_close;
- dev->do_ioctl = pt_ioctl;
- dev->hard_start_xmit = pt_send_packet;
- dev->get_stats = pt_get_stats;
-
- /* Fill in the fields of the device structure */
- dev_init_buffers(dev);
-
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
- dev->hard_header = ax25_encapsulate;
- dev->rebuild_header = ax25_rebuild_header;
-#endif
-
- dev->set_mac_address = pt_set_mac_address;
-
- dev->type = ARPHRD_AX25; /* AF_AX25 device */
- dev->hard_header_len = 73; /* We do digipeaters now */
- dev->mtu = 1500; /* eth_mtu is default */
- dev->addr_len = 7; /* sizeof an ax.25 address */
- memcpy(dev->broadcast, ax25_bcast, 7);
- memcpy(dev->dev_addr, ax25_test, 7);
-
- /* New style flags */
- dev->flags = 0;
-
- return 0;
-} /* pt_probe() */
-
-
-/* Open/initialise the board. This is called (in the current kernel)
- * sometime after booting when the 'ifconfig' program is run.
- *
- * This routine should set everything up anew at each open, even
- * registers that 'should' only be set once at boot, so that there is
- * a non-reboot way to recover if something goes wrong.
- * derived from last half of tsync_attach()
- */
-static int pt_open(struct device *dev)
-{
- unsigned long flags;
- struct pt_local *lp = dev->priv;
- static first_time = 1;
-
- if (dev->base_addr & CHANA)
- {
- if (first_time)
- {
- if (request_dma(dev->dma, "pt"))
- {
- free_irq(dev->irq, dev);
- return -EAGAIN;
- }
- }
-
- /* Reset hardware */
- chipset_init(dev);
- }
- lp->tstate = IDLE;
-
- if (dev->base_addr & CHANA)
- {
- scc_init(dev);
- scc_init(dev->next);
- }
- /* Save a copy of register RR0 for comparing with later on */
- /* We always put 0 in zero count */
- lp->saved_RR0 = rdscc(lp->cardbase, lp->base + CTL, R0) & ~ZCOUNT;
-
- /* master interrupt enable */
- save_flags(flags);
- cli();
- wrtscc(lp->cardbase, lp->base + CTL, R9, MIE | NV);
- outb_p( pt_sercfg |= PT_EI, lp->cardbase + INT_CFG);
- restore_flags(flags);
-
- lp->open_time = jiffies;
-
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
- first_time = 0;
-
- MOD_INC_USE_COUNT;
-
- return 0;
-} /* pt_open() */
-
-static int pt_send_packet(struct sk_buff *skb, struct device *dev)
-{
- struct pt_local *lp = (struct pt_local *) dev->priv;
-
-#ifdef PT_DEBUG
- printk(KERN_DEBUG "PT: pt_send_packet(): (%d)\n", lp->base & CHANA);
-#endif
- hardware_send_packet(lp, skb);
- dev->trans_start = jiffies;
-
- return 0;
-}
-
-
-
-/* The inverse routine to pt_open() */
-static int pt_close(struct device *dev)
-{
- unsigned long flags;
- struct pt_local *lp = dev->priv;
- struct sk_buff *ptr = NULL;
- int cmd;
-
- cmd = lp->base + CTL;
-
- save_flags(flags);
- cli();
-
- /* Reset SCC or channel */
- chipset_init(dev);
- disable_dma(lp->dmachan);
-
- lp->open_time = 0;
- dev->tbusy = 1;
- dev->start = 0;
-
- /* Free any buffers left in the hardware transmit queue */
- while ((ptr = skb_dequeue(&lp->sndq)) != NULL)
- kfree_skb(ptr, FREE_WRITE);
-
- restore_flags(flags);
-
-#ifdef PT_DEBUG
- printk(KERN_DEBUG "PT: pt_close(): Closing down channel (%d).\n", lp->base & CHANA);
-#endif
-
- MOD_DEC_USE_COUNT;
-
- return 0;
-} /* pt_close() */
-
-
-static int pt_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
-{
- unsigned long flags;
- struct pt_req rq;
- struct pt_local *lp = (struct pt_local *) dev->priv;
-
- int ret = verify_area(VERIFY_WRITE, ifr->ifr_data, sizeof(struct pt_req));
- if (ret)
- return ret;
-
- if (cmd != SIOCDEVPRIVATE)
- return -EINVAL;
-
- copy_from_user(&rq, ifr->ifr_data, sizeof(struct pt_req));
-
- switch (rq.cmd) {
- case SIOCSPIPARAM:
-
- if (!suser())
- return -EPERM;
- save_flags(flags);
- cli();
- lp->txdelay = rq.txdelay;
- lp->persist = rq.persist;
- lp->slotime = rq.slotime;
- lp->squeldelay = rq.squeldelay;
- lp->clockmode = rq.clockmode;
- lp->speed = rq.speed;
- pt_open(&pt0a);
- restore_flags(flags);
- ret = 0;
- break;
-
- case SIOCSPIDMA:
-
- if (!suser())
- return -EPERM;
- ret = 0;
- if (dev->base_addr & CHANA) { /* if A channel */
- if (rq.dmachan < 1 || rq.dmachan > 3)
- return -EINVAL;
- save_flags(flags);
- cli();
- pt_close(dev);
- free_dma(lp->dmachan);
- dev->dma = lp->dmachan = rq.dmachan;
- if (request_dma(lp->dmachan,"pt"))
- ret = -EAGAIN;
- pt_open(dev);
- restore_flags(flags);
- }
- break;
-
- case SIOCSPIIRQ:
- ret = -EINVAL; /* add this later */
- break;
-
- case SIOCGPIPARAM:
- case SIOCGPIDMA:
- case SIOCGPIIRQ:
-
- rq.speed = lp->speed;
- rq.txdelay = lp->txdelay;
- rq.persist = lp->persist;
- rq.slotime = lp->slotime;
- rq.squeldelay = lp->squeldelay;
- rq.clockmode = lp->clockmode;
- rq.dmachan = lp->dmachan;
- rq.irq = dev->irq;
- copy_to_user(ifr->ifr_data, &rq, sizeof(struct pt_req));
- ret = 0;
- break;
-
- default:
- ret = -EINVAL;
- }
- return ret;
-}
-
-/*
- * Get the current statistics.
- * This may be called with the card open or closed.
- */
-
-static struct net_device_stats *pt_get_stats(struct device *dev)
-{
- struct pt_local *lp = (struct pt_local *) dev->priv;
- return &lp->stats;
-}
-
-
-/*
- * Local variables:
- * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c skeleton.c"
- * version-control: t
- * kept-new-versions: 5
- * tab-width: 4
- * End:
- */
-
-
-static void tdelay(struct pt_local *lp, int time)
-{
- /* For some reason, we turn off the Tx interrupts here! */
- if (!lp->dmachan)
- wrtscc(lp->cardbase, lp->base + CTL, R1, INT_ALL_Rx | EXT_INT_ENAB);
-
- if (lp->base & CHANA)
- {
- outb_p(time & 0xff, lp->cardbase + TMR1);
- outb_p((time >> 8)&0xff, lp->cardbase + TMR1);
- }
- else
- {
- outb_p(time & 0xff, lp->cardbase + TMR2);
- outb_p((time >> 8)&0xff, lp->cardbase + TMR2);
- }
-} /* tdelay */
-
-
-static void pt_txisr(struct pt_local *lp)
-{
- unsigned long flags;
- int cmd;
- unsigned char c;
-
- save_flags(flags);
- cli();
- cmd = lp->base + CTL;
-
-#ifdef PT_DEBUG
- printk(KERN_DEBUG "PT: pt_txisr(): tstate = %d (%d).\n", lp->tstate, lp->base & CHANA);
-#endif
-
- switch (lp->tstate)
- {
- case CRCOUT:
- lp->tstate = FLAGOUT;
- tdelay(lp, lp->squeldelay);
- restore_flags(flags);
- return;
-
- case IDLE:
- /* Transmitter idle. Find a frame for transmission */
- if ((lp->sndbuf = skb_dequeue(&lp->sndq)) == NULL)
- {
- /* Nothing to send - return to receive mode
- * Tx off now - flag should have gone
- */
- pt_rts(lp, OFF);
-
- restore_flags(flags);
- return;
- }
- if (!lp->dmachan)
- {
- lp->txptr = lp->sndbuf->data;
- lp->txptr++; /* Ignore KISS control byte */
- lp->txcnt = (int) lp->sndbuf->len - 1;
- }
- /* If a buffer to send, drop though here */
-
- case DEFER:
- /* Check DCD - debounce it */
- /* See Intel Microcommunications Handbook p2-308 */
- wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
- wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
- if ((rdscc(lp->cardbase, cmd, R0) & DCD) != 0)
- {
- lp->tstate = DEFER;
- tdelay(lp, 100);
- /* DEFER until DCD transition or timeout */
- wrtscc(lp->cardbase, cmd, R15, DCDIE);
- restore_flags(flags);
- return;
- }
- if (random() > lp->persist)
- {
- lp->tstate = DEFER;
- tdelay(lp, lp->slotime);
- restore_flags(flags);
- return;
- }
- pt_rts(lp, ON); /* Tx on */
- if (lp->dmachan)
- wrtscc(lp->cardbase, cmd, R5, TxCRC_ENAB | RTS | Tx8);
- lp->tstate = ST_TXDELAY;
- tdelay(lp, lp->txdelay);
- restore_flags(flags);
- return;
-
- case ACTIVE:
- /* Here we are actively sending a frame */
- if (lp->txcnt--)
- {
- /* XLZ - checkout Gracilis PT code to see if the while
- * loop is better or not.
- */
- c = *lp->txptr++;
- /* next char is gone */
- wrtscc(lp->cardbase, cmd, R8, c);
- /* stuffing a char satisfies interrupt condition */
- } else {
- /* No more to send */
- kfree_skb(lp->sndbuf, FREE_WRITE);
- lp->sndbuf = NULL;
- if ((rdscc(lp->cardbase, cmd, R0) & TxEOM))
- {
- /* Did we underrun */
- lp->stats.tx_errors++;
- lp->stats.tx_fifo_errors++;
- wrtscc(lp->cardbase, cmd, R0, SEND_ABORT);
- lp->tstate = FLAGOUT;
- tdelay(lp, lp->squeldelay);
- restore_flags(flags);
- return;
- }
- lp->tstate = UNDERRUN;
- /* Send flags on underrun */
- if (lp->nrzi)
- {
- wrtscc(lp->cardbase, cmd, R10, CRCPS | NRZI);
- } else {
- wrtscc(lp->cardbase, cmd, R10, CRCPS | NRZ);
- }
- /* Reset Tx interrupt pending */
- wrtscc(lp->cardbase, cmd, R0, RES_Tx_P);
- }
- restore_flags(flags);
- return;
- default:
- printk(KERN_ERR "PT: pt_txisr(): Invalid tstate (%d) for chan %s.\n", lp->tstate, (cmd & CHANA? "A": "B") );
- pt_rts(lp, OFF);
- lp->tstate = IDLE;
- break;
- } /*switch */
- restore_flags(flags);
-}
-
-static void pt_rxisr(struct device *dev)
-{
- struct pt_local *lp = (struct pt_local*) dev->priv;
- int cmd = lp->base + CTL;
- int bytecount;
- unsigned long flags;
- char rse;
- struct sk_buff *skb;
- int sksize, pkt_len;
- struct mbuf *cur_buf = NULL;
- unsigned char *cfix;
-
- save_flags(flags);
- cli();
-
- /* Get status byte from R1 */
- rse = rdscc(lp->cardbase, cmd, R1);
-
-#ifdef PT_DEBUG
- printk(KERN_DEBUG "PT: pt_rxisr(): R1 = %#3x. (%d)\n", rse, lp->base & CHANA);
-#endif
-
- if (lp->dmachan && (rse & Rx_OVR))
- lp->rstate = RXERROR;
-
- if (rdscc(lp->cardbase, cmd, R0) & Rx_CH_AV && !lp->dmachan)
- {
- /* There is a char to be stored
- * Read special condition bits before reading the data char
- */
- if (rse & Rx_OVR)
- {
- /* Rx overrun - toss buffer */
- /* wind back the pointers */
- lp->rcp = lp->rcvbuf->data;
- lp->rcvbuf->cnt = 0;
- lp->rstate = RXERROR;
- lp->stats.rx_errors++;
- lp->stats.rx_fifo_errors++;
- } else if (lp->rcvbuf->cnt >= lp->bufsiz)
- {
- /* Too large packet
- * wind back Rx buffer pointers
- */
- lp->rcp = lp->rcvbuf->data;
- lp->rcvbuf->cnt = 0;
- lp->rstate = TOOBIG;
- }
- /* ok, we can store the Rx char if no errors */
- if (lp->rstate == ACTIVE)
- {
- *lp->rcp++ = rdscc(lp->cardbase, cmd, R8);
- lp->rcvbuf->cnt++;
- } else {
- /* we got an error, dump the FIFO */
- (void) rdscc(lp->cardbase, cmd, R8);
- (void) rdscc(lp->cardbase, cmd, R8);
- (void) rdscc(lp->cardbase, cmd, R8);
-
- /* Reset error latch */
- wrtscc(lp->cardbase, cmd, R0, ERR_RES);
- lp->rstate = ACTIVE;
-
- /* Resync the SCC */
- wrtscc(lp->cardbase, cmd, R3, RxENABLE | ENT_HM | AUTO_ENAB | Rx8);
-
- }
- }
-
- if (rse & END_FR)
- {
-#ifdef PT_DEBUG
- printk(KERN_DEBUG "PT: pt_rxisr() Got end of a %u byte frame.\n", lp->rcvbuf->cnt);
-#endif
- if (lp->dmachan)
- {
- clear_dma_ff(lp->dmachan);
- bytecount = lp->bufsiz - get_dma_residue(lp->dmachan);
- } else {
- bytecount = lp->rcvbuf->cnt;
- }
-
- /* END OF FRAME - Make sure Rx was active */
- if (lp->rcvbuf->cnt > 0 || lp->dmachan)
- {
- if ((rse & CRC_ERR) || (lp->rstate > ACTIVE) || (bytecount < 10))
- {
- if ((bytecount >= 10) && (rse & CRC_ERR))
- {
- lp->stats.rx_crc_errors++;
- }
- if (lp->dmachan)
- {
- if (lp->rstate == RXERROR)
- {
- lp->stats.rx_errors++;
- lp->stats.rx_over_errors++;
- }
- lp->rstate = ACTIVE;
- setup_rx_dma(lp);
- } else {
- /* wind back Rx buffer pointers */
- lp->rcp = lp->rcvbuf->data;
- lp->rcvbuf->cnt = 0;
-
- /* Re-sync the SCC */
- wrtscc(lp->cardbase, cmd, R3, RxENABLE | ENT_HM | AUTO_ENAB | Rx8);
-
- }
-#ifdef PT_DEBUG
- printk(KERN_DEBUG "PT: pt_rxisr() %s error.\n", (rse & CRC_ERR)? "CRC" : "state");
-#endif
- } else {
- /* We have a valid frame */
- if (lp->dmachan)
- {
- pkt_len = lp->rcvbuf->cnt = bytecount - 2 +1;
- /* Get buffer for next frame */
- cur_buf = lp->rcvbuf;
- switchbuffers(lp);
- setup_rx_dma(lp);
- } else {
- pkt_len = lp->rcvbuf->cnt -= 2; /* Toss 2 CRC bytes */
- pkt_len += 1; /* make room for KISS control byte */
- }
-
- /* Malloc up new buffer */
- sksize = pkt_len;
- skb = dev_alloc_skb(sksize);
- if (skb == NULL)
- {
- printk(KERN_ERR "PT: %s: Memory squeeze, dropping packet.\n", dev->name);
- lp->stats.rx_dropped++;
- restore_flags(flags);
- return;
- }
- skb->dev = dev;
-
- /* KISS kludge = prefix with a 0 byte */
- cfix=skb_put(skb,pkt_len);
- *cfix++=0;
- /* skb->data points to the start of sk_buff area */
- if (lp->dmachan)
- memcpy(cfix, (char*)cur_buf->data, pkt_len - 1);
- else
- memcpy(cfix, lp->rcvbuf->data, pkt_len - 1);
- skb->protocol = ntohs(ETH_P_AX25);
- skb->mac.raw=skb->data;
- lp->stats.rx_bytes+=skb->len;
- netif_rx(skb);
- lp->stats.rx_packets++;
- if (!lp->dmachan)
- {
- /* packet queued - wind back buffer for next frame */
- lp->rcp = lp->rcvbuf->data;
- lp->rcvbuf->cnt = 0;
- }
- } /* good frame */
- } /* check active Rx */
- /* Clear error status */
- lp->rstate = ACTIVE;
- /* Reset error latch */
- } /* end EOF check */
- wrtscc(lp->cardbase, cmd, R0, ERR_RES);
- restore_flags(flags);
-} /* pt_rxisr() */
-
-/*
- * This handles the two timer interrupts.
- * This is a real bugger, cause you have to rip it out of the pi's
- * external status code. They use the CTS line or something.
- */
-static void pt_tmrisr(struct pt_local *lp)
-{
- unsigned long flags;
-
-#ifdef PT_DEBUG
- printk(KERN_DEBUG "PT: pt_tmrisr(): tstate = %d (%d).\n", lp->tstate, lp->base & CHANA);
-#endif
-
- save_flags(flags);
- cli();
-
-
- switch (lp->tstate)
- {
- /* Most of this stuff is in pt_exisr() */
- case FLAGOUT:
- case ST_TXDELAY:
- case DEFER:
-/* case ACTIVE:
- case UNDERRUN:*/
- pt_exisr(lp);
- break;
-
- default:
- if (lp->base & CHANA)
- printk(KERN_ERR "PT: pt_tmrisr(): Invalid tstate %d for Channel A\n", lp->tstate);
- else
- printk(KERN_ERR "PT: pt_tmrisr(): Invalid tstate %d for Channel B\n", lp->tstate);
- break;
- } /* end switch */
- restore_flags(flags);
-} /* pt_tmrisr() */
-
-
-/*
- * This routine is called by the kernel when there is an interrupt for the
- * PT.
- */
-static void pt_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- /* It's a tad dodgy here, but we assume pt0a until proven otherwise */
- struct device *dev = &pt0a;
- struct pt_local *lp = dev->priv;
- unsigned char intreg;
- unsigned char st;
- register int cbase = dev->base_addr & 0x3f0;
- unsigned long flags;
-
- /* Read the PT's interrupt register, this is not the SCC one! */
- intreg = inb_p(cbase + INT_REG);
- while(( intreg & 0x07) != 0x07) {
- /* Read interrupt register pending from Channel A */
- while ((st = rdscc(cbase, cbase + CHANA + CTL, R3)) != 0)
- {
- /* Read interrupt vector from R2, channel B */
-#ifdef PT_DEBUG
- printk(KERN_DEBUG "PT: pt_interrupt(): R3 = %#3x", st);
-#endif
-/* st = rdscc(lp->cardbase, cbase + CHANB + CTL, R2) & 0x0e;*/
-#ifdef PT_DEBUG
- printk(KERN_DEBUG "PI: R2 = %#3x.\n", st);
-#endif
- if (st & CHARxIP) {
- /* Channel A Rx */
- lp = (struct pt_local*)pt0a.priv;
- pt_rxisr(&pt0a);
- } else if (st & CHATxIP) {
- /* Channel A Tx */
- lp = (struct pt_local*)pt0a.priv;
- pt_txisr(lp);
- } else if (st & CHAEXT) {
- /* Channel A External Status */
- lp = (struct pt_local*)pt0a.priv;
- pt_exisr(lp);
- } else if (st & CHBRxIP) {
- /* Channel B Rx */
- lp= (struct pt_local*)pt0b.priv;
- pt_rxisr(&pt0b);
- } else if (st & CHBTxIP) {
- /* Channel B Tx */
- lp = (struct pt_local*)pt0b.priv;
- pt_txisr(lp);
- } else if (st & CHBEXT) {
- /* Channel B External Status */
- lp = (struct pt_local*)pt0b.priv;
- pt_exisr(lp);
- }
- /* Reset highest interrupt under service */
- save_flags(flags);
- cli();
- wrtscc(lp->cardbase, lp->base + CTL, R0, RES_H_IUS);
- restore_flags(flags);
- } /* end of SCC ints */
-
- if (!(intreg & PT_TMR1_MSK))
- {
- /* Clear timer 1 */
- inb_p(cbase + TMR1CLR);
-
- pt_tmrisr( (struct pt_local*)pt0a.priv);
- }
-
- if (!(intreg & PT_TMR2_MSK))
- {
- /* Clear timer 2 */
- inb_p(cbase + TMR2CLR);
-
- pt_tmrisr( (struct pt_local*)pt0b.priv);
- }
-
- /* Get the next PT interrupt vector */
- intreg = inb_p(cbase + INT_REG);
- } /* while (intreg) */
-} /* pt_interrupt() */
-
-
-static void pt_exisr(struct pt_local *lp)
-{
- unsigned long flags;
- int cmd = lp->base + CTL;
- unsigned char st;
- char c;
- int length;
-
- save_flags(flags);
- cli();
-
- /* Get external status */
- st = rdscc(lp->cardbase, cmd, R0);
-
-#ifdef PT_DEBUG
- printk(KERN_DEBUG "PT: exisr(): R0 = %#3x tstate = %d (%d).\n", st, lp->tstate, lp->base & CHANA);
-#endif
- /* Reset external status latch */
- wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
-
- if ((lp->rstate >= ACTIVE) && (st & BRK_ABRT) && lp->dmachan)
- {
- setup_rx_dma(lp);
- lp->rstate = ACTIVE;
- }
-
- switch (lp->tstate)
- {
- case ACTIVE: /* Unexpected underrun */
-#ifdef PT_DEBUG
- printk(KERN_DEBUG "PT: exisr(): unexpected underrun detected.\n");
-#endif
- kfree_skb(lp->sndbuf, FREE_WRITE);
- lp->sndbuf = NULL;
- if (!lp->dmachan)
- {
- wrtscc(lp->cardbase, cmd, R0, SEND_ABORT);
- lp->stats.tx_errors++;
- lp->stats.tx_fifo_errors++;
- }
- lp->tstate = FLAGOUT;
- tdelay(lp, lp->squeldelay);
- restore_flags(flags);
- return;
- case UNDERRUN:
- lp->tstate = CRCOUT;
- restore_flags(flags);
- return;
- case FLAGOUT:
- /* squeldelay has timed out */
- /* Find a frame for transmission */
- if ((lp->sndbuf = skb_dequeue(&lp->sndq)) == NULL)
- {
- /* Nothing to send - return to Rx mode */
- pt_rts(lp, OFF);
- lp->tstate = IDLE;
- restore_flags(flags);
- return;
- }
- if (!lp->dmachan)
- {
- lp->txptr = lp->sndbuf->data;
- lp->txptr++; /* Ignore KISS control byte */
- lp->txcnt = (int) lp->sndbuf->len - 1;
- }
- /* Fall through if we have a packet */
-
- case ST_TXDELAY:
- if (lp->dmachan)
- {
- /* Disable DMA chan */
- disable_dma(lp->dmachan);
-
- /* Set up for TX dma */
- wrtscc(lp->cardbase, cmd, R1, WT_FN_RDYFN | EXT_INT_ENAB);
-
- length = lp->sndbuf->len - 1;
- memcpy(lp->txdmabuf, &lp->sndbuf->data[1], length);
-
- /* Setup DMA controller for Tx */
- setup_tx_dma(lp, length);
-
- enable_dma(lp->dmachan);
-
- /* Reset CRC, Txint pending */
- wrtscc(lp->cardbase, cmd, R0, RES_Tx_CRC | RES_Tx_P);
-
- /* Allow underrun only */
- wrtscc(lp->cardbase, cmd, R15, TxUIE);
-
- /* Enable TX DMA */
- wrtscc(lp->cardbase, cmd, R1, WT_RDY_ENAB | WT_FN_RDYFN | EXT_INT_ENAB);
-
- /* Send CRC on underrun */
- wrtscc(lp->cardbase, cmd, R0, RES_EOM_L);
-
- lp->tstate = ACTIVE;
- break;
- }
- /* Get first char to send */
- lp->txcnt--;
- c = *lp->txptr++;
- /* Reset CRC for next frame */
- wrtscc(lp->cardbase, cmd, R0, RES_Tx_CRC);
-
- /* send abort on underrun */
- if (lp->nrzi)
- {
- wrtscc(lp->cardbase, cmd, R10, CRCPS | NRZI | ABUNDER);
- } else {
- wrtscc(lp->cardbase, cmd, R10, CRCPS | NRZ | ABUNDER);
- }
- /* send first char */
- wrtscc(lp->cardbase, cmd, R8, c);
-
- /* Reset end of message latch */
- wrtscc(lp->cardbase, cmd, R0, RES_EOM_L);
-
- /* stuff an extra one in */
-/* while ((rdscc(lp->cardbase, cmd, R0) & Tx_BUF_EMP) && lp->txcnt)
- {
- lp->txcnt--;
- c = *lp->txptr++;
- wrtscc(lp->cardbase, cmd, R8, c);
- }*/
-
- /* select Tx interrupts to enable */
- /* Allow underrun int only */
- wrtscc(lp->cardbase, cmd, R15, TxUIE);
-
- /* Reset external interrupts */
- wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
-
- /* Tx and Rx ints enabled */
- wrtscc(lp->cardbase, cmd, R1, TxINT_ENAB | EXT_INT_ENAB);
-
- lp->tstate = ACTIVE;
- restore_flags(flags);
- return;
-
- /* slotime has timed out */
- case DEFER:
- /* Check DCD - debounce it
- * see Intel Microcommunications Handbook, p2-308
- */
- wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
- wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
- if ((rdscc(lp->cardbase, cmd, R0) & DCD) != 0)
- {
- lp->tstate = DEFER;
- tdelay(lp, 100);
- /* DEFER until DCD transition or timeout */
- wrtscc(lp->cardbase, cmd, R15, DCDIE);
- restore_flags(flags);
- return;
- }
- if (random() > lp->persist)
- {
- lp->tstate = DEFER;
- tdelay(lp, lp->slotime);
- restore_flags(flags);
- return;
- }
- if (lp->dmachan)
- wrtscc(lp->cardbase, cmd, R5, TxCRC_ENAB | RTS | Tx8);
- pt_rts(lp, ON); /* Tx on */
- lp->tstate = ST_TXDELAY;
- tdelay(lp, lp->txdelay);
- restore_flags(flags);
- return;
-
- /* Only for int driven parts */
- if (lp->dmachan)
- {
- restore_flags(flags);
- return;
- }
-
- } /* end switch */
- /*
- * Rx mode only
- * This triggers when hunt mode is entered, & since an ABORT
- * automatically enters hunt mode, we use that to clean up
- * any waiting garbage
- */
- if ((lp->rstate == ACTIVE) && (st & BRK_ABRT) )
- {
-#ifdef PT_DEBUG
- printk(KERN_DEBUG "PT: exisr(): abort detected.\n");
-#endif
- /* read and dump all of SCC Rx FIFO */
- (void) rdscc(lp->cardbase, cmd, R8);
- (void) rdscc(lp->cardbase, cmd, R8);
- (void) rdscc(lp->cardbase, cmd, R8);
-
- lp->rcp = lp->rcvbuf->data;
- lp->rcvbuf->cnt = 0;
-
- /* Re-sync the SCC */
- wrtscc(lp->cardbase, cmd, R3, RxENABLE | ENT_HM | AUTO_ENAB | Rx8);
-
- }
-
- /* Check for DCD transitions */
- if ( (st & DCD) != (lp->saved_RR0 & DCD))
- {
-#ifdef PT_DEBUG
- printk(KERN_DEBUG "PT: pt_exisr(): DCD is now %s.\n", (st & DCD)? "ON" : "OFF" );
-#endif
- if (st & DCD)
- {
- /* Check that we don't already have some data */
- if (lp->rcvbuf->cnt > 0)
- {
-#ifdef PT_DEBUG
- printk(KERN_DEBUG "PT: pt_exisr() dumping %u bytes from buffer.\n", lp->rcvbuf->cnt);
-#endif
- /* wind back buffers */
- lp->rcp = lp->rcvbuf->data;
- lp->rcvbuf->cnt = 0;
- }
- } else { /* DCD off */
-
- /* read and dump al SCC FIFO */
- (void)rdscc(lp->cardbase, cmd, R8);
- (void)rdscc(lp->cardbase, cmd, R8);
- (void)rdscc(lp->cardbase, cmd, R8);
-
- /* wind back buffers */
- lp->rcp = lp->rcvbuf->data;
- lp->rcvbuf->cnt = 0;
-
- /* Re-sync the SCC */
- wrtscc(lp->cardbase, cmd, R3, RxENABLE | ENT_HM | AUTO_ENAB | Rx8);
- }
-
- }
- /* Update the saved version of register RR) */
- lp->saved_RR0 = st &~ ZCOUNT;
- restore_flags(flags);
-
-} /* pt_exisr() */
-
-#ifdef MODULE
-EXPORT_NO_SYMBOLS;
-
-MODULE_AUTHOR("Craig Small VK2XLZ <vk2xlz@vk2xlz.ampr.org>");
-MODULE_DESCRIPTION("AX.25 driver for the Gracillis PacketTwin HDLC card");
-
-int init_module(void)
-{
- return pt_init();
-}
-
-void cleanup_module(void)
-{
- free_irq(pt0a.irq, &pt0a); /* IRQs and IO Ports are shared */
- release_region(pt0a.base_addr & 0x3f0, PT_TOTAL_SIZE);
-
- kfree(pt0a.priv);
- pt0a.priv = NULL;
- unregister_netdev(&pt0a);
-
- kfree(pt0b.priv);
- pt0b.priv = NULL;
- unregister_netdev(&pt0b);
-}
-#endif
diff --git a/drivers/net/scc.c b/drivers/net/scc.c
index 63362ac70..e69de29bb 100644
--- a/drivers/net/scc.c
+++ b/drivers/net/scc.c
@@ -1,2245 +0,0 @@
-#define RCS_ID "$Id: scc.c,v 1.69 1997/04/06 19:22:45 jreuter Exp jreuter $"
-
-#define VERSION "3.0"
-#define BANNER "Z8530 SCC driver version "VERSION".dl1bke (experimental) by DL1BKE\n"
-
-/*
- * Please use z8530drv-utils-3.0 with this version.
- * ------------------
- */
-
-/*
- ********************************************************************
- * SCC.C - Linux driver for Z8530 based HDLC cards for AX.25 *
- ********************************************************************
-
-
- ********************************************************************
-
- Copyright (c) 1993, 1997 Joerg Reuter DL1BKE
-
- portions (c) 1993 Guido ten Dolle PE1NNZ
-
- ********************************************************************
-
- The driver and the programs in the archive are UNDER CONSTRUCTION.
- The code is likely to fail, and so your kernel could --- even
- a whole network.
-
- This driver is intended for Amateur Radio use. If you are running it
- for commercial purposes, please drop me a note. I am nosy...
-
- ...BUT:
-
- ! You m u s t recognize the appropriate legislations of your country !
- ! before you connect a radio to the SCC board and start to transmit or !
- ! receive. The GPL allows you to use the d r i v e r, NOT the RADIO! !
-
- For non-Amateur-Radio use please note that you might need a special
- allowance/licence from the designer of the SCC Board and/or the
- MODEM.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the (modified) GNU General Public License
- delivered with the Linux kernel source.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should find a copy of the GNU General Public License in
- /usr/src/linux/COPYING;
-
- ********************************************************************
-
-
- Incomplete history of z8530drv:
- -------------------------------
-
- 940913 - started to write the driver, rescued most of my own
- code (and Hans Alblas' memory buffer pool concept) from
- an earlier project "sccdrv" which was initiated by
- Guido ten Dolle. Not much of the old driver survived,
- though. The first version I put my hands on was sccdrv1.3
- from August 1993. The memory buffer pool concept
- appeared in an unauthorized sccdrv version (1.5) from
- August 1994.
-
- 950131 - changed copyright notice to GPL without limitations.
-
- .
- . <SNIP>
- .
-
- 961005 - New semester, new driver...
-
- * KISS TNC emulator removed (TTY driver)
- * Source moved to drivers/net/
- * Includes Z8530 defines from drivers/net/z8530.h
- * Uses sk_buffer memory management
- * Reduced overhead of /proc/net/z8530drv output
- * Streamlined quite a lot things
- * Invents brand new bugs... ;-)
-
- The move to version number 3.0 reflects theses changes.
- You can use 'kissbridge' if you need a KISS TNC emulator.
-
- 961213 - Fixed for Linux networking changes. (G4KLX)
- 970108 - Fixed the remaining problems.
- 970402 - Hopefully fixed the problems with the new *_timer()
- routines, added calibration code.
-
- Thanks to all who contributed to this driver with ideas and bug
- reports!
-
- NB -- if you find errors, change something, please let me know
- first before you distribute it... And please don't touch
- the version number. Just replace my callsign in
- "v3.0.dl1bke" with your own. Just to avoid confusion...
-
- If you want to add your modification to the linux distribution
- please (!) contact me first.
-
- New versions of the driver will be announced on the linux-hams
- mailing list on vger.rutgers.edu. To subscribe send an e-mail
- to majordomo@vger.rutgers.edu with the following line in
- the body of the mail:
-
- subscribe linux-hams
-
- The content of the "Subject" field will be ignored.
-
- vy 73,
- Joerg Reuter ampr-net: dl1bke@db0pra.ampr.org
- AX-25 : DL1BKE @ DB0ACH.#NRW.DEU.EU
- Internet: jreuter@lykos.oche.de
-*/
-
-/* ----------------------------------------------------------------------- */
-
-#undef SCC_DELAY /* perhaps your ISA bus is a *bit* too fast? */
-#undef SCC_LDELAY 1 /* slow it even a bit more down */
-#undef DONT_CHECK /* don't look if the SCCs you specified are available */
-
-#define MAXSCC 4 /* number of max. supported chips */
-#define BUFSIZE 384 /* must not exceed 4096 */
-#define MAXQUEUE 8 /* number of buffers we queue ourself */
-#undef DISABLE_ALL_INTS /* use cli()/sti() in ISR instead of */
- /* enable_irq()/disable_irq() */
-#undef SCC_DEBUG
-
-#define DEFAULT_CLOCK 4915200 /* default pclock if nothing is specified */
-
-/* ----------------------------------------------------------------------- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/string.h>
-#include <linux/in.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
-#include <linux/malloc.h>
-#include <linux/delay.h>
-
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/if_ether.h>
-#include <linux/if_arp.h>
-#include <linux/socket.h>
-#include <linux/init.h>
-
-#include <linux/scc.h>
-#include "z8530.h"
-
-#include <net/ax25.h>
-#include <asm/irq.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/bitops.h>
-
-#include <linux/kernel.h>
-#include <linux/proc_fs.h>
-
-#ifdef MODULE
-int init_module(void);
-void cleanup_module(void);
-#endif
-
-int scc_init(void);
-
-static void t_dwait(unsigned long);
-static void t_txdelay(unsigned long);
-static void t_tail(unsigned long);
-static void t_busy(unsigned long);
-static void t_maxkeyup(unsigned long);
-static void t_idle(unsigned long);
-static void scc_tx_done(struct scc_channel *);
-static void scc_start_tx_timer(struct scc_channel *, void (*)(unsigned long), unsigned long);
-static void scc_start_maxkeyup(struct scc_channel *);
-static void scc_start_defer(struct scc_channel *);
-
-static void z8530_init(void);
-
-static void init_channel(struct scc_channel *scc);
-static void scc_key_trx (struct scc_channel *scc, char tx);
-static void scc_isr(int irq, void *dev_id, struct pt_regs *regs);
-static void scc_init_timer(struct scc_channel *scc);
-
-static int scc_net_setup(struct scc_channel *scc, unsigned char *name);
-static int scc_net_init(struct device *dev);
-static int scc_net_open(struct device *dev);
-static int scc_net_close(struct device *dev);
-static void scc_net_rx(struct scc_channel *scc, struct sk_buff *skb);
-static int scc_net_tx(struct sk_buff *skb, struct device *dev);
-static int scc_net_ioctl(struct device *dev, struct ifreq *ifr, int cmd);
-static int scc_net_set_mac_address(struct device *dev, void *addr);
-static int scc_net_header(struct sk_buff *skb, struct device *dev, unsigned short type, void *daddr, void *saddr, unsigned len);
-static struct net_device_stats * scc_net_get_stats(struct device *dev);
-
-static unsigned char *SCC_DriverName = "scc";
-
-static struct irqflags { unsigned char used : 1; } Ivec[16];
-
-static struct scc_channel SCC_Info[2 * MAXSCC]; /* information per channel */
-
-static struct scc_ctrl {
- io_port chan_A;
- io_port chan_B;
- int irq;
-} SCC_ctrl[MAXSCC+1];
-
-static unsigned char Driver_Initialized = 0;
-static int Nchips = 0;
-static io_port Vector_Latch = 0;
-
-MODULE_AUTHOR("Joerg Reuter <jreuter@lykos.oche.de>");
-MODULE_DESCRIPTION("Network Device Driver for Z8530 based HDLC cards for Amateur Packet Radio");
-MODULE_SUPPORTED_DEVICE("scc");
-
-/* ******************************************************************** */
-/* * Port Access Functions * */
-/* ******************************************************************** */
-
-/* These provide interrupt save 2-step access to the Z8530 registers */
-
-extern __inline__ unsigned char InReg(io_port port, unsigned char reg)
-{
- unsigned long flags;
- unsigned char r;
-
- save_flags(flags);
- cli();
-#ifdef SCC_LDELAY
- Outb(port, reg);
- udelay(SCC_LDELAY);
- r=Inb(port);
- udelay(SCC_LDELAY);
-#else
- Outb(port, reg);
- r=Inb(port);
-#endif
- restore_flags(flags);
- return r;
-}
-
-extern __inline__ void OutReg(io_port port, unsigned char reg, unsigned char val)
-{
- unsigned long flags;
-
- save_flags(flags);
- cli();
-#ifdef SCC_LDELAY
- Outb(port, reg); udelay(SCC_LDELAY);
- Outb(port, val); udelay(SCC_LDELAY);
-#else
- Outb(port, reg);
- Outb(port, val);
-#endif
- restore_flags(flags);
-}
-
-extern __inline__ void wr(struct scc_channel *scc, unsigned char reg,
- unsigned char val)
-{
- OutReg(scc->ctrl, reg, (scc->wreg[reg] = val));
-}
-
-extern __inline__ void or(struct scc_channel *scc, unsigned char reg, unsigned char val)
-{
- OutReg(scc->ctrl, reg, (scc->wreg[reg] |= val));
-}
-
-extern __inline__ void cl(struct scc_channel *scc, unsigned char reg, unsigned char val)
-{
- OutReg(scc->ctrl, reg, (scc->wreg[reg] &= ~val));
-}
-
-#ifdef DISABLE_ALL_INTS
-extern __inline__ void scc_cli(int irq)
-{ cli(); }
-extern __inline__ void scc_sti(int irq)
-{ sti(); }
-#else
-static __inline__ void scc_cli(int irq)
-{ disable_irq(irq); }
-static __inline__ void scc_sti(int irq)
-{ enable_irq(irq); }
-#endif
-
-/* ******************************************************************** */
-/* * Some useful macros * */
-/* ******************************************************************** */
-
-
-extern __inline__ void scc_lock_dev(struct scc_channel *scc)
-{
- scc->dev->tbusy = 1;
-}
-
-extern __inline__ void scc_unlock_dev(struct scc_channel *scc)
-{
- scc->dev->tbusy = 0;
-}
-
-extern __inline__ void scc_discard_buffers(struct scc_channel *scc)
-{
- unsigned long flags;
-
- save_flags(flags);
- cli();
-
- if (scc->tx_buff != NULL)
- {
- dev_kfree_skb(scc->tx_buff, FREE_WRITE);
- scc->tx_buff = NULL;
- }
-
- while (skb_queue_len(&scc->tx_queue))
- dev_kfree_skb(skb_dequeue(&scc->tx_queue), FREE_WRITE);
-
- restore_flags(flags);
-}
-
-
-
-/* ******************************************************************** */
-/* * Interrupt Service Routines * */
-/* ******************************************************************** */
-
-
-/* ----> subroutines for the interrupt handlers <---- */
-
-extern __inline__ void scc_notify(struct scc_channel *scc, int event)
-{
- struct sk_buff *skb;
- char *bp;
-
- if (scc->kiss.fulldup != KISS_DUPLEX_OPTIMA)
- return;
-
- skb = dev_alloc_skb(2);
- if (skb != NULL)
- {
- bp = skb_put(skb, 2);
- *bp++ = PARAM_HWEVENT;
- *bp++ = event;
- scc_net_rx(scc, skb);
- } else
- scc->stat.nospace++;
-}
-
-extern __inline__ void flush_rx_FIFO(struct scc_channel *scc)
-{
- int k;
-
- for (k=0; k<3; k++)
- Inb(scc->data);
-
- if(scc->rx_buff != NULL) /* did we receive something? */
- {
- scc->stat.rxerrs++; /* then count it as an error */
- kfree_skb(scc->rx_buff, FREE_READ);
- scc->rx_buff = NULL;
- }
-}
-
-
-/* ----> four different interrupt handlers for Tx, Rx, changing of */
-/* DCD/CTS and Rx/Tx errors */
-
-/* Transmitter interrupt handler */
-extern __inline__ void scc_txint(struct scc_channel *scc)
-{
- struct sk_buff *skb;
-
- scc->stat.txints++;
- skb = scc->tx_buff;
-
- /* send first octet */
-
- if (skb == NULL)
- {
- skb = skb_dequeue(&scc->tx_queue);
- scc->tx_buff = skb;
- scc_unlock_dev(scc);
-
- if (skb == NULL)
- {
- scc_tx_done(scc);
- Outb(scc->ctrl, RES_Tx_P);
- return;
- }
-
- if (skb->len == 0) /* Paranoia... */
- {
- dev_kfree_skb(skb, FREE_WRITE);
- scc->tx_buff = NULL;
- scc_tx_done(scc);
- Outb(scc->ctrl, RES_Tx_P);
- return;
- }
-
- scc->stat.tx_state = TXS_ACTIVE;
-
- OutReg(scc->ctrl, R0, RES_Tx_CRC);
- /* reset CRC generator */
- or(scc,R10,ABUNDER); /* re-install underrun protection */
- Outb(scc->data,*skb->data); /* send byte */
- skb_pull(skb, 1);
-
- if (!scc->enhanced) /* reset EOM latch */
- Outb(scc->ctrl,RES_EOM_L);
- return;
- }
-
- /* End Of Frame... */
-
- if (skb->len == 0)
- {
- Outb(scc->ctrl, RES_Tx_P); /* reset pending int */
- cl(scc, R10, ABUNDER); /* send CRC */
- dev_kfree_skb(skb, FREE_WRITE);
- scc->tx_buff = NULL;
- scc->stat.tx_state = TXS_NEWFRAME; /* next frame... */
- return;
- }
-
- /* send octet */
-
- Outb(scc->data,*skb->data);
- skb_pull(skb, 1);
-}
-
-
-/* External/Status interrupt handler */
-extern __inline__ void scc_exint(struct scc_channel *scc)
-{
- unsigned char status,changes,chg_and_stat;
-
- scc->stat.exints++;
-
- status = InReg(scc->ctrl,R0);
- changes = status ^ scc->status;
- chg_and_stat = changes & status;
-
- /* ABORT: generated whenever DCD drops while receiving */
-
- if (chg_and_stat & BRK_ABRT) /* Received an ABORT */
- flush_rx_FIFO(scc);
-
-
- /* DCD: on = start to receive packet, off = ABORT condition */
- /* (a successfully received packet generates a special condition int) */
-
- if(changes & DCD) /* DCD input changed state */
- {
- if(status & DCD) /* DCD is now ON */
- {
- if (scc->modem.clocksrc != CLK_EXTERNAL)
- OutReg(scc->ctrl,R14,SEARCH|scc->wreg[R14]); /* DPLL: enter search mode */
-
- or(scc,R3,ENT_HM|RxENABLE); /* enable the receiver, hunt mode */
- } else { /* DCD is now OFF */
- cl(scc,R3,ENT_HM|RxENABLE); /* disable the receiver */
- flush_rx_FIFO(scc);
- }
-
- if (!scc->kiss.softdcd)
- scc_notify(scc, (status & DCD)? HWEV_DCD_ON:HWEV_DCD_OFF);
- }
-
- /* HUNT: software DCD; on = waiting for SYNC, off = receiving frame */
-
- if (changes & SYNC_HUNT)
- {
- if (scc->kiss.softdcd)
- scc_notify(scc, (status & SYNC_HUNT)? HWEV_DCD_OFF:HWEV_DCD_ON);
- else
- cl(scc,R15,SYNCIE); /* oops, we were too lazy to disable this? */
- }
-
-#ifdef notdef
- /* CTS: use external TxDelay (what's that good for?!)
- * Anyway: If we _could_ use it (BayCom USCC uses CTS for
- * own purposes) we _should_ use the "autoenable" feature
- * of the Z8530 and not this interrupt...
- */
-
- if (chg_and_stat & CTS) /* CTS is now ON */
- {
- if (scc->kiss.txdelay == 0) /* zero TXDELAY = wait for CTS */
- scc_start_tx_timer(scc, t_txdelay, 0);
- }
-#endif
-
- if (scc->stat.tx_state == TXS_ACTIVE && (status & TxEOM))
- {
- scc->stat.tx_under++; /* oops, an underrun! count 'em */
- Outb(scc->ctrl, RES_EXT_INT); /* reset ext/status interrupts */
-
- if (scc->tx_buff != NULL)
- {
- dev_kfree_skb(scc->tx_buff, FREE_WRITE);
- scc->tx_buff = NULL;
- }
-
- or(scc,R10,ABUNDER);
- scc_start_tx_timer(scc, t_txdelay, 0); /* restart transmission */
- }
-
- scc->status = status;
- Outb(scc->ctrl,RES_EXT_INT);
-}
-
-
-/* Receiver interrupt handler */
-extern __inline__ void scc_rxint(struct scc_channel *scc)
-{
- struct sk_buff *skb;
-
- scc->stat.rxints++;
-
- if((scc->wreg[5] & RTS) && scc->kiss.fulldup == KISS_DUPLEX_HALF)
- {
- Inb(scc->data); /* discard char */
- or(scc,R3,ENT_HM); /* enter hunt mode for next flag */
- return;
- }
-
- skb = scc->rx_buff;
-
- if (skb == NULL)
- {
- skb = dev_alloc_skb(scc->stat.bufsize);
- if (skb == NULL)
- {
- scc->dev_stat.rx_dropped++;
- scc->stat.nospace++;
- Inb(scc->data);
- or(scc, R3, ENT_HM);
- return;
- }
-
- scc->rx_buff = skb;
- *(skb_put(skb, 1)) = 0; /* KISS data */
- }
-
- if (skb->len >= scc->stat.bufsize)
- {
-#ifdef notdef
- printk(KERN_DEBUG "z8530drv: oops, scc_rxint() received huge frame...\n");
-#endif
- kfree_skb(skb, FREE_READ);
- scc->rx_buff = NULL;
- Inb(scc->data);
- or(scc, R3, ENT_HM);
- return;
- }
-
- *(skb_put(skb, 1)) = Inb(scc->data);
-}
-
-
-/* Receive Special Condition interrupt handler */
-extern __inline__ void scc_spint(struct scc_channel *scc)
-{
- unsigned char status;
- struct sk_buff *skb;
-
- scc->stat.spints++;
-
- status = InReg(scc->ctrl,R1); /* read receiver status */
-
- Inb(scc->data); /* throw away Rx byte */
- skb = scc->rx_buff;
-
- if(status & Rx_OVR) /* receiver overrun */
- {
- scc->stat.rx_over++; /* count them */
- or(scc,R3,ENT_HM); /* enter hunt mode for next flag */
-
- if (skb != NULL)
- kfree_skb(skb, FREE_READ);
- scc->rx_buff = NULL;
- }
-
- if(status & END_FR && skb != NULL) /* end of frame */
- {
- /* CRC okay, frame ends on 8 bit boundary and received something ? */
-
- if (!(status & CRC_ERR) && (status & 0xe) == RES8 && skb->len > 0)
- {
- /* ignore last received byte (first of the CRC bytes) */
- skb_trim(skb, skb->len-1);
- scc_net_rx(scc, skb);
- scc->rx_buff = NULL;
- scc->stat.rxframes++;
- } else { /* a bad frame */
- kfree_skb(skb, FREE_READ);
- scc->rx_buff = NULL;
- scc->stat.rxerrs++;
- }
- }
-
- Outb(scc->ctrl,ERR_RES);
-}
-
-
-/* ----> interrupt service routine for the Z8530 <---- */
-
-static void scc_isr_dispatch(struct scc_channel *scc, int vector)
-{
- switch (vector & VECTOR_MASK)
- {
- case TXINT: scc_txint(scc); break;
- case EXINT: scc_exint(scc); break;
- case RXINT: scc_rxint(scc); break;
- case SPINT: scc_spint(scc); break;
- }
-}
-
-/* If the card has a latch for the interrupt vector (like the PA0HZP card)
- use it to get the number of the chip that generated the int.
- If not: poll all defined chips.
- */
-
-#define SCC_IRQTIMEOUT 30000
-
-static void scc_isr(int irq, void *dev_id, struct pt_regs *regs)
-{
- unsigned char vector;
- struct scc_channel *scc;
- struct scc_ctrl *ctrl;
- int k;
-
- scc_cli(irq);
-
- if (Vector_Latch)
- {
- for(k=0; k < SCC_IRQTIMEOUT; k++)
- {
- Outb(Vector_Latch, 0); /* Generate INTACK */
-
- /* Read the vector */
- if((vector=Inb(Vector_Latch)) >= 16 * Nchips) break;
- if (vector & 0x01) break;
-
- scc=&SCC_Info[vector >> 3 ^ 0x01];
- if (!scc->dev) break;
-
- scc_isr_dispatch(scc, vector);
-
- OutReg(scc->ctrl,R0,RES_H_IUS); /* Reset Highest IUS */
- }
- scc_sti(irq);
-
- if (k == SCC_IRQTIMEOUT)
- printk(KERN_WARNING "z8530drv: endless loop in scc_isr()?\n");
-
- return;
- }
-
- /* Find the SCC generating the interrupt by polling all attached SCCs
- * reading RR3A (the interrupt pending register)
- */
-
- ctrl = SCC_ctrl;
- while (ctrl->chan_A)
- {
- if (ctrl->irq != irq)
- {
- ctrl++;
- continue;
- }
-
- scc = NULL;
- for (k = 0; InReg(ctrl->chan_A,R3) && k < SCC_IRQTIMEOUT; k++)
- {
- vector=InReg(ctrl->chan_B,R2); /* Read the vector */
- if (vector & 0x01) break;
-
- scc = &SCC_Info[vector >> 3 ^ 0x01];
- if (!scc->dev) break;
-
- scc_isr_dispatch(scc, vector);
- }
-
- if (k == SCC_IRQTIMEOUT)
- {
- printk(KERN_WARNING "z8530drv: endless loop in scc_isr()?!\n");
- break;
- }
-
- /* This looks wierd and it is. At least the BayCom USCC doesn't
- * use the Interrupt Daisy Chain, thus we'll have to start
- * all over again to be sure not to miss an interrupt from
- * (any of) the other chip(s)...
- * Honestly, the situation *is* braindamaged...
- */
-
- if (scc != NULL)
- {
- OutReg(scc->ctrl,R0,RES_H_IUS);
- ctrl = SCC_ctrl;
- } else
- ctrl++;
- }
-
- scc_sti(irq);
-}
-
-
-
-/* ******************************************************************** */
-/* * Init Channel */
-/* ******************************************************************** */
-
-
-/* ----> set SCC channel speed <---- */
-
-extern __inline__ void set_brg(struct scc_channel *scc, unsigned int tc)
-{
- cl(scc,R14,BRENABL); /* disable baudrate generator */
- wr(scc,R12,tc & 255); /* brg rate LOW */
- wr(scc,R13,tc >> 8); /* brg rate HIGH */
- or(scc,R14,BRENABL); /* enable baudrate generator */
-}
-
-extern __inline__ void set_speed(struct scc_channel *scc)
-{
- disable_irq(scc->irq);
-
- if (scc->modem.speed > 0) /* paranoia... */
- set_brg(scc, (unsigned) (scc->clock / (scc->modem.speed * 64)) - 2);
-
- enable_irq(scc->irq);
-}
-
-
-/* ----> initialize a SCC channel <---- */
-
-extern __inline__ void init_brg(struct scc_channel *scc)
-{
- wr(scc, R14, BRSRC); /* BRG source = PCLK */
- OutReg(scc->ctrl, R14, SSBR|scc->wreg[R14]); /* DPLL source = BRG */
- OutReg(scc->ctrl, R14, SNRZI|scc->wreg[R14]); /* DPLL NRZI mode */
-}
-
-/*
- * Initialization according to the Z8530 manual (SGS-Thomson's version):
- *
- * 1. Modes and constants
- *
- * WR9 11000000 chip reset
- * WR4 XXXXXXXX Tx/Rx control, async or sync mode
- * WR1 0XX00X00 select W/REQ (optional)
- * WR2 XXXXXXXX program interrupt vector
- * WR3 XXXXXXX0 select Rx control
- * WR5 XXXX0XXX select Tx control
- * WR6 XXXXXXXX sync character
- * WR7 XXXXXXXX sync character
- * WR9 000X0XXX select interrupt control
- * WR10 XXXXXXXX miscellaneous control (optional)
- * WR11 XXXXXXXX clock control
- * WR12 XXXXXXXX time constant lower byte (optional)
- * WR13 XXXXXXXX time constant upper byte (optional)
- * WR14 XXXXXXX0 miscellaneous control
- * WR14 XXXSSSSS commands (optional)
- *
- * 2. Enables
- *
- * WR14 000SSSS1 baud rate enable
- * WR3 SSSSSSS1 Rx enable
- * WR5 SSSS1SSS Tx enable
- * WR0 10000000 reset Tx CRG (optional)
- * WR1 XSS00S00 DMA enable (optional)
- *
- * 3. Interrupt status
- *
- * WR15 XXXXXXXX enable external/status
- * WR0 00010000 reset external status
- * WR0 00010000 reset external status twice
- * WR1 SSSXXSXX enable Rx, Tx and Ext/status
- * WR9 000SXSSS enable master interrupt enable
- *
- * 1 = set to one, 0 = reset to zero
- * X = user defined, S = same as previous init
- *
- *
- * Note that the implementation differs in some points from above scheme.
- *
- */
-
-static void init_channel(struct scc_channel *scc)
-{
- del_timer(&scc->tx_t);
- del_timer(&scc->tx_wdog);
-
- disable_irq(scc->irq);
-
- wr(scc,R4,X1CLK|SDLC); /* *1 clock, SDLC mode */
- wr(scc,R1,0); /* no W/REQ operation */
- wr(scc,R3,Rx8|RxCRC_ENAB); /* RX 8 bits/char, CRC, disabled */
- wr(scc,R5,Tx8|DTR|TxCRC_ENAB); /* TX 8 bits/char, disabled, DTR */
- wr(scc,R6,0); /* SDLC address zero (not used) */
- wr(scc,R7,FLAG); /* SDLC flag value */
- wr(scc,R9,VIS); /* vector includes status */
- wr(scc,R10,(scc->modem.nrz? NRZ : NRZI)|CRCPS|ABUNDER); /* abort on underrun, preset CRC generator, NRZ(I) */
- wr(scc,R14, 0);
-
-
-/* set clock sources:
-
- CLK_DPLL: normal halfduplex operation
-
- RxClk: use DPLL
- TxClk: use DPLL
- TRxC mode DPLL output
-
- CLK_EXTERNAL: external clocking (G3RUH or DF9IC modem)
-
- BayCom: others:
-
- TxClk = pin RTxC TxClk = pin TRxC
- RxClk = pin TRxC RxClk = pin RTxC
-
-
- CLK_DIVIDER:
- RxClk = use DPLL
- TxClk = pin RTxC
-
- BayCom: others:
- pin TRxC = DPLL pin TRxC = BRG
- (RxClk * 1) (RxClk * 32)
-*/
-
-
- switch(scc->modem.clocksrc)
- {
- case CLK_DPLL:
- wr(scc, R11, RCDPLL|TCDPLL|TRxCOI|TRxCDP);
- init_brg(scc);
- break;
-
- case CLK_DIVIDER:
- wr(scc, R11, ((scc->brand & BAYCOM)? TRxCDP : TRxCBR) | RCDPLL|TCRTxCP|TRxCOI);
- init_brg(scc);
- break;
-
- case CLK_EXTERNAL:
- wr(scc, R11, (scc->brand & BAYCOM)? RCTRxCP|TCRTxCP : RCRTxCP|TCTRxCP);
- OutReg(scc->ctrl, R14, DISDPLL);
- break;
-
- }
-
- set_speed(scc); /* set baudrate */
-
- if(scc->enhanced)
- {
- or(scc,R15,SHDLCE|FIFOE); /* enable FIFO, SDLC/HDLC Enhancements (From now R7 is R7') */
- wr(scc,R7,AUTOEOM);
- }
-
- if((InReg(scc->ctrl,R0)) & DCD) /* DCD is now ON */
- {
- if (scc->modem.clocksrc != CLK_EXTERNAL)
- or(scc,R14, SEARCH);
-
- or(scc,R3,ENT_HM|RxENABLE); /* enable the receiver, hunt mode */
- }
-
- /* enable ABORT, DCD & SYNC/HUNT interrupts */
-
- wr(scc,R15, BRKIE|TxUIE|DCDIE);
- if (scc->kiss.softdcd)
- or(scc,R15, SYNCIE);
-
- Outb(scc->ctrl,RES_EXT_INT); /* reset ext/status interrupts */
- Outb(scc->ctrl,RES_EXT_INT); /* must be done twice */
-
- or(scc,R1,INT_ALL_Rx|TxINT_ENAB|EXT_INT_ENAB); /* enable interrupts */
-
- scc->status = InReg(scc->ctrl,R0); /* read initial status */
-
- or(scc,R9,MIE); /* master interrupt enable */
-
- scc_init_timer(scc);
-
- enable_irq(scc->irq);
-}
-
-
-
-
-/* ******************************************************************** */
-/* * SCC timer functions * */
-/* ******************************************************************** */
-
-
-/* ----> scc_key_trx sets the time constant for the baudrate
- generator and keys the transmitter <---- */
-
-static void scc_key_trx(struct scc_channel *scc, char tx)
-{
- unsigned int time_const;
-
- if (scc->brand & PRIMUS)
- Outb(scc->ctrl + 4, scc->option | (tx? 0x80 : 0));
-
- if (scc->modem.speed < 300)
- scc->modem.speed = 1200;
-
- time_const = (unsigned) (scc->clock / (scc->modem.speed * (tx? 2:64))) - 2;
-
- disable_irq(scc->irq);
-
- if (tx)
- {
- or(scc, R1, TxINT_ENAB); /* t_maxkeyup may have reset these */
- or(scc, R15, TxUIE);
- }
-
- if (scc->modem.clocksrc == CLK_DPLL)
- { /* force simplex operation */
- if (tx)
- {
- cl(scc, R3, RxENABLE|ENT_HM); /* switch off receiver */
- cl(scc, R15, DCDIE); /* No DCD changes, please */
- set_brg(scc, time_const); /* reprogram baudrate generator */
-
- /* DPLL -> Rx clk, BRG -> Tx CLK, TRxC mode output, TRxC = BRG */
- wr(scc, R11, RCDPLL|TCBR|TRxCOI|TRxCBR);
-
- or(scc,R5,RTS|TxENAB); /* set the RTS line and enable TX */
- } else {
- cl(scc,R5,RTS|TxENAB);
-
- set_brg(scc, time_const); /* reprogram baudrate generator */
-
- /* DPLL -> Rx clk, DPLL -> Tx CLK, TRxC mode output, TRxC = DPLL */
- wr(scc, R11, RCDPLL|TCDPLL|TRxCOI|TRxCDP);
-
- or(scc,R3,RxENABLE|ENT_HM);
- or(scc,R15, DCDIE);
- }
- } else {
- if (tx)
- {
- if (scc->kiss.fulldup == KISS_DUPLEX_HALF)
- {
- cl(scc, R3, RxENABLE);
- cl(scc, R15, DCDIE);
- }
-
-
- or(scc,R5,RTS|TxENAB); /* enable tx */
- } else {
- cl(scc,R5,RTS|TxENAB); /* disable tx */
-
- if (scc->kiss.fulldup == KISS_DUPLEX_HALF)
- {
- or(scc, R3, RxENABLE|ENT_HM);
- or(scc, R15, DCDIE);
- }
- }
- }
-
- enable_irq(scc->irq);
-}
-
-
-/* ----> SCC timer interrupt handler and friends. <---- */
-
-static void scc_start_tx_timer(struct scc_channel *scc, void (*handler)(unsigned long), unsigned long when)
-{
- unsigned long flags;
-
-
- save_flags(flags);
- cli();
-
- del_timer(&scc->tx_t);
-
- if (when == 0)
- {
- handler((unsigned long) scc);
- } else
- if (when != TIMER_OFF)
- {
- scc->tx_t.data = (unsigned long) scc;
- scc->tx_t.function = handler;
- scc->tx_t.expires = jiffies + (when*HZ)/100;
- add_timer(&scc->tx_t);
- }
-
- restore_flags(flags);
-}
-
-static void scc_start_defer(struct scc_channel *scc)
-{
- unsigned long flags;
-
- save_flags(flags);
- cli();
-
- del_timer(&scc->tx_wdog);
-
- if (scc->kiss.maxdefer != 0 && scc->kiss.maxdefer != TIMER_OFF)
- {
- scc->tx_wdog.data = (unsigned long) scc;
- scc->tx_wdog.function = t_busy;
- scc->tx_wdog.expires = jiffies + HZ*scc->kiss.maxdefer;
- add_timer(&scc->tx_wdog);
- }
- restore_flags(flags);
-}
-
-static void scc_start_maxkeyup(struct scc_channel *scc)
-{
- unsigned long flags;
-
- save_flags(flags);
- cli();
-
- del_timer(&scc->tx_wdog);
-
- if (scc->kiss.maxkeyup != 0 && scc->kiss.maxkeyup != TIMER_OFF)
- {
- scc->tx_wdog.data = (unsigned long) scc;
- scc->tx_wdog.function = t_maxkeyup;
- scc->tx_wdog.expires = jiffies + HZ*scc->kiss.maxkeyup;
- add_timer(&scc->tx_wdog);
- }
-
- restore_flags(flags);
-}
-
-/*
- * This is called from scc_txint() when there are no more frames to send.
- * Not exactly a timer function, but it is a close friend of the family...
- */
-
-static void scc_tx_done(struct scc_channel *scc)
-{
- /*
- * trx remains keyed in fulldup mode 2 until t_idle expires.
- */
-
- switch (scc->kiss.fulldup)
- {
- case KISS_DUPLEX_LINK:
- scc->stat.tx_state = TXS_IDLE2;
- if (scc->kiss.idletime != TIMER_OFF)
- scc_start_tx_timer(scc, t_idle, scc->kiss.idletime*100);
- break;
- case KISS_DUPLEX_OPTIMA:
- scc_notify(scc, HWEV_ALL_SENT);
- break;
- default:
- scc->stat.tx_state = TXS_BUSY;
- scc_start_tx_timer(scc, t_tail, scc->kiss.tailtime);
- }
-
- scc_unlock_dev(scc);
-}
-
-
-static unsigned char Rand = 17;
-
-extern __inline__ int is_grouped(struct scc_channel *scc)
-{
- int k;
- struct scc_channel *scc2;
- unsigned char grp1, grp2;
-
- grp1 = scc->kiss.group;
-
- for (k = 0; k < (Nchips * 2); k++)
- {
- scc2 = &SCC_Info[k];
- grp2 = scc2->kiss.group;
-
- if (scc2 == scc || !(scc2->dev && grp2))
- continue;
-
- if ((grp1 & 0x3f) == (grp2 & 0x3f))
- {
- if ( (grp1 & TXGROUP) && (scc2->wreg[R5] & RTS) )
- return 1;
-
- if ( (grp1 & RXGROUP) && (scc2->status & DCD) )
- return 1;
- }
- }
- return 0;
-}
-
-/* DWAIT and SLOTTIME expired
- *
- * fulldup == 0: DCD is active or Rand > P-persistence: start t_busy timer
- * else key trx and start txdelay
- * fulldup == 1: key trx and start txdelay
- * fulldup == 2: mintime expired, reset status or key trx and start txdelay
- */
-
-static void t_dwait(unsigned long channel)
-{
- struct scc_channel *scc = (struct scc_channel *) channel;
-
- if (scc->stat.tx_state == TXS_WAIT) /* maxkeyup or idle timeout */
- {
- if (skb_queue_len(&scc->tx_queue) == 0) /* nothing to send */
- {
- scc->stat.tx_state = TXS_IDLE;
- scc_unlock_dev(scc); /* t_maxkeyup locked it. */
- return;
- }
-
- scc->stat.tx_state = TXS_BUSY;
- }
-
- if (scc->kiss.fulldup == KISS_DUPLEX_HALF)
- {
- Rand = Rand * 17 + 31;
-
- if ( (scc->kiss.softdcd? !(scc->status & SYNC_HUNT):(scc->status & DCD)) || (scc->kiss.persist) < Rand || (scc->kiss.group && is_grouped(scc)) )
- {
- scc_start_defer(scc);
- scc_start_tx_timer(scc, t_dwait, scc->kiss.slottime);
- return ;
- }
- }
-
- if ( !(scc->wreg[R5] & RTS) )
- {
- scc_key_trx(scc, TX_ON);
- scc_start_tx_timer(scc, t_txdelay, scc->kiss.txdelay);
- } else {
- scc_start_tx_timer(scc, t_txdelay, 0);
- }
-}
-
-
-/* TXDELAY expired
- *
- * kick transmission by a fake scc_txint(scc), start 'maxkeyup' watchdog.
- */
-
-static void t_txdelay(unsigned long channel)
-{
- struct scc_channel *scc = (struct scc_channel *) channel;
-
- scc_start_maxkeyup(scc);
-
- if (scc->tx_buff == NULL)
- {
- disable_irq(scc->irq);
- scc_txint(scc);
- enable_irq(scc->irq);
- }
-}
-
-
-/* TAILTIME expired
- *
- * switch off transmitter. If we were stopped by Maxkeyup restart
- * transmission after 'mintime' seconds
- */
-
-static void t_tail(unsigned long channel)
-{
- struct scc_channel *scc = (struct scc_channel *) channel;
- unsigned long flags;
-
- save_flags(flags);
- cli();
-
- del_timer(&scc->tx_wdog);
- scc_key_trx(scc, TX_OFF);
-
- restore_flags(flags);
-
- if (scc->stat.tx_state == TXS_TIMEOUT) /* we had a timeout? */
- {
- scc->stat.tx_state = TXS_WAIT;
-
- if (scc->kiss.mintime != TIMER_OFF) /* try it again */
- scc_start_tx_timer(scc, t_dwait, scc->kiss.mintime*100);
- else
- scc_start_tx_timer(scc, t_dwait, 0);
- return;
- }
-
- scc->stat.tx_state = TXS_IDLE;
- scc_unlock_dev(scc);
-}
-
-
-/* BUSY timeout
- *
- * throw away send buffers if DCD remains active too long.
- */
-
-static void t_busy(unsigned long channel)
-{
- struct scc_channel *scc = (struct scc_channel *) channel;
-
- del_timer(&scc->tx_t);
- scc_lock_dev(scc);
-
- scc_discard_buffers(scc);
-
- scc->stat.txerrs++;
- scc->stat.tx_state = TXS_IDLE;
-
- scc_unlock_dev(scc);
-}
-
-/* MAXKEYUP timeout
- *
- * this is our watchdog.
- */
-
-static void t_maxkeyup(unsigned long channel)
-{
- struct scc_channel *scc = (struct scc_channel *) channel;
- unsigned long flags;
-
- save_flags(flags);
- cli();
-
- /*
- * let things settle down before we start to
- * accept new data.
- */
-
- scc_lock_dev(scc);
- scc_discard_buffers(scc);
-
- del_timer(&scc->tx_t);
-
- cl(scc, R1, TxINT_ENAB); /* force an ABORT, but don't */
- cl(scc, R15, TxUIE); /* count it. */
- OutReg(scc->ctrl, R0, RES_Tx_P);
-
- restore_flags(flags);
-
- scc->stat.txerrs++;
- scc->stat.tx_state = TXS_TIMEOUT;
- scc_start_tx_timer(scc, t_tail, scc->kiss.tailtime);
-}
-
-/* IDLE timeout
- *
- * in fulldup mode 2 it keys down the transmitter after 'idle' seconds
- * of inactivity. We will not restart transmission before 'mintime'
- * expires.
- */
-
-static void t_idle(unsigned long channel)
-{
- struct scc_channel *scc = (struct scc_channel *) channel;
-
- del_timer(&scc->tx_wdog);
-
- scc_key_trx(scc, TX_OFF);
-
- if (scc->kiss.mintime != TIMER_OFF)
- scc_start_tx_timer(scc, t_dwait, scc->kiss.mintime*100);
- scc->stat.tx_state = TXS_WAIT;
-}
-
-static void scc_init_timer(struct scc_channel *scc)
-{
- unsigned long flags;
-
- save_flags(flags);
- cli();
-
- scc->stat.tx_state = TXS_IDLE;
-
- restore_flags(flags);
-}
-
-
-/* ******************************************************************** */
-/* * Set/get L1 parameters * */
-/* ******************************************************************** */
-
-
-/*
- * this will set the "hardware" parameters through KISS commands or ioctl()
- */
-
-#define CAST(x) (unsigned long)(x)
-
-static unsigned int scc_set_param(struct scc_channel *scc, unsigned int cmd, unsigned int arg)
-{
- int dcd;
-
- switch (cmd)
- {
- case PARAM_TXDELAY: scc->kiss.txdelay=arg; break;
- case PARAM_PERSIST: scc->kiss.persist=arg; break;
- case PARAM_SLOTTIME: scc->kiss.slottime=arg; break;
- case PARAM_TXTAIL: scc->kiss.tailtime=arg; break;
- case PARAM_FULLDUP: scc->kiss.fulldup=arg; break;
- case PARAM_DTR: break; /* does someone need this? */
- case PARAM_GROUP: scc->kiss.group=arg; break;
- case PARAM_IDLE: scc->kiss.idletime=arg; break;
- case PARAM_MIN: scc->kiss.mintime=arg; break;
- case PARAM_MAXKEY: scc->kiss.maxkeyup=arg; break;
- case PARAM_WAIT: scc->kiss.waittime=arg; break;
- case PARAM_MAXDEFER: scc->kiss.maxdefer=arg; break;
- case PARAM_TX: scc->kiss.tx_inhibit=arg; break;
-
- case PARAM_SOFTDCD:
- scc->kiss.softdcd=arg;
- if (arg)
- or(scc, R15, SYNCIE);
- else
- cl(scc, R15, SYNCIE);
- break;
-
- case PARAM_SPEED:
- if (arg < 256)
- scc->modem.speed=arg*100;
- else
- scc->modem.speed=arg;
-
- if (scc->stat.tx_state == 0) /* only switch baudrate on rx... ;-) */
- set_speed(scc);
- break;
-
- case PARAM_RTS:
- if ( !(scc->wreg[R5] & RTS) )
- {
- if (arg != TX_OFF)
- scc_key_trx(scc, TX_ON);
- scc_start_tx_timer(scc, t_txdelay, scc->kiss.txdelay);
- } else {
- if (arg == TX_OFF)
- {
- scc->stat.tx_state = TXS_BUSY;
- scc_start_tx_timer(scc, t_tail, scc->kiss.tailtime);
- }
- }
- break;
-
- case PARAM_HWEVENT:
- dcd = (scc->kiss.softdcd? !(scc->status & SYNC_HUNT):(scc->status & DCD));
- scc_notify(scc, dcd? HWEV_DCD_ON:HWEV_DCD_OFF);
- break;
-
- default: return -EINVAL;
- }
-
- return 0;
-}
-
-
-
-static unsigned long scc_get_param(struct scc_channel *scc, unsigned int cmd)
-{
- switch (cmd)
- {
- case PARAM_TXDELAY: return CAST(scc->kiss.txdelay);
- case PARAM_PERSIST: return CAST(scc->kiss.persist);
- case PARAM_SLOTTIME: return CAST(scc->kiss.slottime);
- case PARAM_TXTAIL: return CAST(scc->kiss.tailtime);
- case PARAM_FULLDUP: return CAST(scc->kiss.fulldup);
- case PARAM_SOFTDCD: return CAST(scc->kiss.softdcd);
- case PARAM_DTR: return CAST((scc->wreg[R5] & DTR)? 1:0);
- case PARAM_RTS: return CAST((scc->wreg[R5] & RTS)? 1:0);
- case PARAM_SPEED: return CAST(scc->modem.speed);
- case PARAM_GROUP: return CAST(scc->kiss.group);
- case PARAM_IDLE: return CAST(scc->kiss.idletime);
- case PARAM_MIN: return CAST(scc->kiss.mintime);
- case PARAM_MAXKEY: return CAST(scc->kiss.maxkeyup);
- case PARAM_WAIT: return CAST(scc->kiss.waittime);
- case PARAM_MAXDEFER: return CAST(scc->kiss.maxdefer);
- case PARAM_TX: return CAST(scc->kiss.tx_inhibit);
- default: return NO_SUCH_PARAM;
- }
-
-}
-
-#undef CAST
-#undef SVAL
-
-/* ******************************************************************* */
-/* * Send calibration pattern * */
-/* ******************************************************************* */
-
-static void scc_stop_calibrate(unsigned long channel)
-{
- struct scc_channel *scc = (struct scc_channel *) channel;
- unsigned long flags;
-
- save_flags(flags);
- cli();
-
- del_timer(&scc->tx_wdog);
- scc_key_trx(scc, TX_OFF);
- wr(scc, R6, 0);
- wr(scc, R7, FLAG);
- Outb(scc->ctrl,RES_EXT_INT); /* reset ext/status interrupts */
- Outb(scc->ctrl,RES_EXT_INT);
-
- scc_unlock_dev(scc);
-
- restore_flags(flags);
-}
-
-
-static void
-scc_start_calibrate(struct scc_channel *scc, int duration, unsigned char pattern)
-{
- unsigned long flags;
-
- save_flags(flags);
- cli();
-
- scc_lock_dev(scc);
- scc_discard_buffers(scc);
-
- del_timer(&scc->tx_wdog);
-
- scc->tx_wdog.data = (unsigned long) scc;
- scc->tx_wdog.function = scc_stop_calibrate;
- scc->tx_wdog.expires = jiffies + HZ*scc->kiss.maxkeyup;
- add_timer(&scc->tx_wdog);
-
- wr(scc, R6, 0);
- wr(scc, R7, pattern);
-
- /*
- * Don't know if this works.
- * Damn, where is my Z8530 programming manual...?
- */
-
- Outb(scc->ctrl,RES_EXT_INT); /* reset ext/status interrupts */
- Outb(scc->ctrl,RES_EXT_INT);
-
- scc_key_trx(scc, TX_ON);
-
- restore_flags(flags);
-}
-
-/* ******************************************************************* */
-/* * Init channel structures, special HW, etc... * */
-/* ******************************************************************* */
-
-/*
- * Reset the Z8530s and setup special hardware
- */
-
-static void z8530_init(void)
-{
- struct scc_channel *scc;
- int chip, k;
- unsigned long flags;
- char *flag;
-
-
- printk(KERN_INFO "Init Z8530 driver: %u channels, IRQ", Nchips*2);
-
- flag=" ";
- for (k = 0; k < 16; k++)
- if (Ivec[k].used)
- {
- printk("%s%d", flag, k);
- flag=",";
- }
- printk("\n");
-
-
- /* reset and pre-init all chips in the system */
- for (chip = 0; chip < Nchips; chip++)
- {
- scc=&SCC_Info[2*chip];
- if (!scc->ctrl) continue;
-
- /* Special SCC cards */
-
- if(scc->brand & EAGLE) /* this is an EAGLE card */
- Outb(scc->special,0x08); /* enable interrupt on the board */
-
- if(scc->brand & (PC100 | PRIMUS)) /* this is a PC100/PRIMUS card */
- Outb(scc->special,scc->option); /* set the MODEM mode (0x22) */
-
-
- /* Reset and pre-init Z8530 */
-
- save_flags(flags);
- cli();
-
- Outb(scc->ctrl, 0);
- OutReg(scc->ctrl,R9,FHWRES); /* force hardware reset */
- udelay(100); /* give it 'a bit' more time than required */
- wr(scc, R2, chip*16); /* interrupt vector */
- wr(scc, R9, VIS); /* vector includes status */
-
- restore_flags(flags);
- }
-
-
- Driver_Initialized = 1;
-}
-
-/*
- * Allocate device structure, err, instance, and register driver
- */
-
-static int scc_net_setup(struct scc_channel *scc, unsigned char *name)
-{
- unsigned char *buf;
- struct device *dev;
-
- if (dev_get(name) != NULL)
- {
- printk(KERN_INFO "Z8530drv: device %s already exists.\n", name);
- return -EEXIST;
- }
-
- if ((scc->dev = (struct device *) kmalloc(sizeof(struct device), GFP_KERNEL)) == NULL)
- return -ENOMEM;
-
- dev = scc->dev;
- memset(dev, 0, sizeof(struct device));
-
- buf = (unsigned char *) kmalloc(10, GFP_KERNEL);
- strcpy(buf, name);
-
- dev->priv = (void *) scc;
- dev->name = buf;
- dev->init = scc_net_init;
-
- if (register_netdev(dev) != 0)
- {
- kfree(dev);
- return -EIO;
- }
-
- return 0;
-}
-
-
-
-/* ******************************************************************** */
-/* * Network driver methods * */
-/* ******************************************************************** */
-
-static unsigned char ax25_bcast[AX25_ADDR_LEN] =
-{'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, '0' << 1};
-static unsigned char ax25_nocall[AX25_ADDR_LEN] =
-{'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1, '1' << 1};
-
-/* ----> Initialize device <----- */
-
-static int scc_net_init(struct device *dev)
-{
- dev_init_buffers(dev);
-
- dev->tx_queue_len = 16; /* should be enough... */
-
- dev->open = scc_net_open;
- dev->stop = scc_net_close;
-
- dev->hard_start_xmit = scc_net_tx;
- dev->hard_header = scc_net_header;
- dev->rebuild_header = ax25_rebuild_header;
- dev->set_mac_address = scc_net_set_mac_address;
- dev->get_stats = scc_net_get_stats;
- dev->do_ioctl = scc_net_ioctl;
-
- memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN);
- memcpy(dev->dev_addr, ax25_nocall, AX25_ADDR_LEN);
-
- dev->flags = 0;
-
- dev->type = ARPHRD_AX25;
- dev->hard_header_len = AX25_MAX_HEADER_LEN + AX25_BPQ_HEADER_LEN;
- dev->mtu = AX25_DEF_PACLEN;
- dev->addr_len = AX25_ADDR_LEN;
-
- return 0;
-}
-
-/* ----> open network device <---- */
-
-static int scc_net_open(struct device *dev)
-{
- struct scc_channel *scc = (struct scc_channel *) dev->priv;
-
- if (scc == NULL || scc->magic != SCC_MAGIC)
- return -ENODEV;
-
- if (!scc->init)
- return -EINVAL;
-
- MOD_INC_USE_COUNT;
-
- scc->tx_buff = NULL;
- skb_queue_head_init(&scc->tx_queue);
-
- init_channel(scc);
-
- dev->tbusy = 0;
- dev->start = 1;
-
- return 0;
-}
-
-/* ----> close network device <---- */
-
-static int scc_net_close(struct device *dev)
-{
- struct scc_channel *scc = (struct scc_channel *) dev->priv;
- unsigned long flags;
-
- if (scc == NULL || scc->magic != SCC_MAGIC)
- return -ENODEV;
-
- MOD_DEC_USE_COUNT;
-
- save_flags(flags);
- cli();
-
- Outb(scc->ctrl,0); /* Make sure pointer is written */
- wr(scc,R1,0); /* disable interrupts */
- wr(scc,R3,0);
-
- del_timer(&scc->tx_t);
- del_timer(&scc->tx_wdog);
-
- restore_flags(flags);
-
- scc_discard_buffers(scc);
-
- dev->tbusy = 1;
- dev->start = 0;
-
- return 0;
-}
-
-/* ----> receive frame, called from scc_rxint() <---- */
-
-static void scc_net_rx(struct scc_channel *scc, struct sk_buff *skb)
-{
- if (skb->len == 0)
- {
- kfree_skb(skb, FREE_READ);
- return;
- }
-
- scc->dev_stat.rx_packets++;
-
- skb->dev = scc->dev;
- skb->protocol = htons(ETH_P_AX25);
- skb->mac.raw = skb->data;
-
- netif_rx(skb);
- return;
-}
-
-/* ----> transmit frame <---- */
-
-static int scc_net_tx(struct sk_buff *skb, struct device *dev)
-{
- struct scc_channel *scc = (struct scc_channel *) dev->priv;
- unsigned long flags;
- char kisscmd;
-
- if (scc == NULL || scc->magic != SCC_MAGIC || dev->tbusy)
- {
- dev_kfree_skb(skb, FREE_WRITE);
- return 0;
- }
-
- if (skb->len > scc->stat.bufsize || skb->len < 2)
- {
- scc->dev_stat.tx_dropped++; /* bogus frame */
- dev_kfree_skb(skb, FREE_WRITE);
- return 0;
- }
-
- scc->dev_stat.tx_packets++;
- scc->stat.txframes++;
-
- kisscmd = *skb->data & 0x1f;
- skb_pull(skb, 1);
-
- if (kisscmd)
- {
- scc_set_param(scc, kisscmd, *skb->data);
- dev_kfree_skb(skb, FREE_WRITE);
- return 0;
- }
-
- save_flags(flags);
- cli();
-
- if (skb_queue_len(&scc->tx_queue) >= MAXQUEUE-1)
- {
- struct sk_buff *skb_del;
- skb_del = __skb_dequeue(&scc->tx_queue);
- dev_kfree_skb(skb_del, FREE_WRITE);
- }
- __skb_queue_tail(&scc->tx_queue, skb);
-
- dev->trans_start = jiffies;
-
- /*
- * Start transmission if the trx state is idle or
- * t_idle hasn't expired yet. Use dwait/persistance/slottime
- * algorithm for normal halfduplex operation.
- */
-
- if(scc->stat.tx_state == TXS_IDLE || scc->stat.tx_state == TXS_IDLE2)
- {
- scc->stat.tx_state = TXS_BUSY;
- if (scc->kiss.fulldup == KISS_DUPLEX_HALF)
- scc_start_tx_timer(scc, t_dwait, scc->kiss.waittime);
- else
- scc_start_tx_timer(scc, t_dwait, 0);
- }
-
- restore_flags(flags);
-
- return 0;
-}
-
-/* ----> ioctl functions <---- */
-
-/*
- * SIOCSCCCFG - configure driver arg: (struct scc_hw_config *) arg
- * SIOCSCCINI - initialize driver arg: ---
- * SIOCSCCCHANINI - initialize channel arg: (struct scc_modem *) arg
- * SIOCSCCSMEM - set memory arg: (struct scc_mem_config *) arg
- * SIOCSCCGKISS - get level 1 parameter arg: (struct scc_kiss_cmd *) arg
- * SIOCSCCSKISS - set level 1 parameter arg: (struct scc_kiss_cmd *) arg
- * SIOCSCCGSTAT - get driver status arg: (struct scc_stat *) arg
- * SIOCSCCCAL - send calib. pattern arg: (struct scc_calibrate *) arg
- */
-
-static int scc_net_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
-{
- struct scc_kiss_cmd kiss_cmd;
- struct scc_mem_config memcfg;
- struct scc_hw_config hwcfg;
- struct scc_calibrate cal;
- int chan;
- unsigned char device_name[10];
- void *arg;
- struct scc_channel *scc;
-
- scc = (struct scc_channel *) dev->priv;
- if (scc == NULL || scc->magic != SCC_MAGIC)
- return -EINVAL;
-
- arg = (void *) ifr->ifr_data;
-
- if (!Driver_Initialized)
- {
- if (cmd == SIOCSCCCFG)
- {
- int found = 1;
-
- if (!suser()) return -EPERM;
- if (!arg) return -EFAULT;
-
- if (Nchips >= MAXSCC)
- return -EINVAL;
-
- if (copy_from_user(&hwcfg, arg, sizeof(hwcfg)))
- return -EFAULT;
-
- if (hwcfg.irq == 2) hwcfg.irq = 9;
-
- if (!Ivec[hwcfg.irq].used && hwcfg.irq)
- {
- if (request_irq(hwcfg.irq, scc_isr, SA_INTERRUPT, "AX.25 SCC", NULL))
- printk(KERN_WARNING "z8530drv: warning, cannot get IRQ %d\n", hwcfg.irq);
- else
- Ivec[hwcfg.irq].used = 1;
- }
-
- if (hwcfg.vector_latch)
- Vector_Latch = hwcfg.vector_latch;
-
- if (hwcfg.clock == 0)
- hwcfg.clock = DEFAULT_CLOCK;
-
-#ifndef DONT_CHECK
- disable_irq(hwcfg.irq);
-
- check_region(scc->ctrl, 1);
- Outb(hwcfg.ctrl_a, 0);
- udelay(5);
- OutReg(hwcfg.ctrl_a,R13,0x55); /* is this chip really there? */
- udelay(5);
-
- if (InReg(hwcfg.ctrl_a,R13) != 0x55)
- found = 0;
-
- enable_irq(hwcfg.irq);
-#endif
-
- if (found)
- {
- SCC_Info[2*Nchips ].ctrl = hwcfg.ctrl_a;
- SCC_Info[2*Nchips ].data = hwcfg.data_a;
- SCC_Info[2*Nchips ].irq = hwcfg.irq;
- SCC_Info[2*Nchips+1].ctrl = hwcfg.ctrl_b;
- SCC_Info[2*Nchips+1].data = hwcfg.data_b;
- SCC_Info[2*Nchips+1].irq = hwcfg.irq;
-
- SCC_ctrl[Nchips].chan_A = hwcfg.ctrl_a;
- SCC_ctrl[Nchips].chan_B = hwcfg.ctrl_b;
- SCC_ctrl[Nchips].irq = hwcfg.irq;
- }
-
-
- for (chan = 0; chan < 2; chan++)
- {
- sprintf(device_name, "%s%i", SCC_DriverName, 2*Nchips+chan);
-
- SCC_Info[2*Nchips+chan].special = hwcfg.special;
- SCC_Info[2*Nchips+chan].clock = hwcfg.clock;
- SCC_Info[2*Nchips+chan].brand = hwcfg.brand;
- SCC_Info[2*Nchips+chan].option = hwcfg.option;
- SCC_Info[2*Nchips+chan].enhanced = hwcfg.escc;
-
-#ifdef DONT_CHECK
- printk(KERN_INFO "%s: data port = 0x%3.3x control port = 0x%3.3x\n",
- device_name,
- SCC_Info[2*Nchips+chan].data,
- SCC_Info[2*Nchips+chan].ctrl);
-
-#else
- printk(KERN_INFO "%s: data port = 0x%3.3lx control port = 0x%3.3lx -- %s\n",
- device_name,
- chan? hwcfg.data_b : hwcfg.data_a,
- chan? hwcfg.ctrl_b : hwcfg.ctrl_a,
- found? "found" : "missing");
-#endif
-
- if (found)
- {
- request_region(SCC_Info[2*Nchips+chan].ctrl, 1, "scc ctrl");
- request_region(SCC_Info[2*Nchips+chan].data, 1, "scc data");
- if (Nchips+chan != 0)
- scc_net_setup(&SCC_Info[2*Nchips+chan], device_name);
- }
- }
-
- if (found) Nchips++;
-
- return 0;
- }
-
- if (cmd == SIOCSCCINI)
- {
- if (!suser())
- return -EPERM;
-
- if (Nchips == 0)
- return -EINVAL;
-
- z8530_init();
- return 0;
- }
-
- return -EINVAL; /* confuse the user */
- }
-
- if (!scc->init)
- {
- if (cmd == SIOCSCCCHANINI)
- {
- if (!suser()) return -EPERM;
- if (!arg) return -EINVAL;
-
- scc->stat.bufsize = BUFSIZE;
-
- if (copy_from_user(&scc->modem, arg, sizeof(struct scc_modem)))
- return -EINVAL;
-
- /* default KISS Params */
-
- if (scc->modem.speed < 4800)
- {
- scc->kiss.txdelay = 36; /* 360 ms */
- scc->kiss.persist = 42; /* 25% persistence */ /* was 25 */
- scc->kiss.slottime = 16; /* 160 ms */
- scc->kiss.tailtime = 4; /* minimal reasonable value */
- scc->kiss.fulldup = 0; /* CSMA */
- scc->kiss.waittime = 50; /* 500 ms */
- scc->kiss.maxkeyup = 10; /* 10 s */
- scc->kiss.mintime = 3; /* 3 s */
- scc->kiss.idletime = 30; /* 30 s */
- scc->kiss.maxdefer = 120; /* 2 min */
- scc->kiss.softdcd = 0; /* hardware dcd */
- } else {
- scc->kiss.txdelay = 10; /* 100 ms */
- scc->kiss.persist = 64; /* 25% persistence */ /* was 25 */
- scc->kiss.slottime = 8; /* 160 ms */
- scc->kiss.tailtime = 1; /* minimal reasonable value */
- scc->kiss.fulldup = 0; /* CSMA */
- scc->kiss.waittime = 50; /* 500 ms */
- scc->kiss.maxkeyup = 7; /* 7 s */
- scc->kiss.mintime = 3; /* 3 s */
- scc->kiss.idletime = 30; /* 30 s */
- scc->kiss.maxdefer = 120; /* 2 min */
- scc->kiss.softdcd = 0; /* hardware dcd */
- }
-
- scc->tx_buff = NULL;
- skb_queue_head_init(&scc->tx_queue);
- scc->init = 1;
-
- return 0;
- }
-
- return -EINVAL;
- }
-
- switch(cmd)
- {
- case SIOCSCCRESERVED:
- return -ENOIOCTLCMD;
-
- case SIOCSCCSMEM:
- if (!suser()) return -EPERM;
- if (!arg || copy_from_user(&memcfg, arg, sizeof(memcfg)))
- return -EINVAL;
- scc->stat.bufsize = memcfg.bufsize;
- return 0;
-
- case SIOCSCCGSTAT:
- if (!arg || copy_to_user(arg, &scc->stat, sizeof(scc->stat)))
- return -EINVAL;
- return 0;
-
- case SIOCSCCGKISS:
- if (!arg || copy_from_user(&kiss_cmd, arg, sizeof(kiss_cmd)))
- return -EINVAL;
- kiss_cmd.param = scc_get_param(scc, kiss_cmd.command);
- if (copy_to_user(arg, &kiss_cmd, sizeof(kiss_cmd)))
- return -EINVAL;
- return 0;
-
- case SIOCSCCSKISS:
- if (!suser()) return -EPERM;
- if (!arg || copy_from_user(&kiss_cmd, arg, sizeof(kiss_cmd)))
- return -EINVAL;
- return scc_set_param(scc, kiss_cmd.command, kiss_cmd.param);
-
- case SIOCSCCCAL:
- if (!suser()) return -EPERM;
- if (!arg || copy_from_user(&cal, arg, sizeof(cal)))
- return -EINVAL;
-
- scc_start_calibrate(scc, cal.time, cal.pattern);
- return 0;
-
- default:
- return -ENOIOCTLCMD;
-
- }
-
- return -EINVAL;
-}
-
-/* ----> set interface callsign <---- */
-
-static int scc_net_set_mac_address(struct device *dev, void *addr)
-{
- struct sockaddr *sa = (struct sockaddr *) addr;
- memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
- return 0;
-}
-
-/* ----> "hard" header <---- */
-
-static int scc_net_header(struct sk_buff *skb, struct device *dev,
- unsigned short type, void *daddr, void *saddr, unsigned len)
-{
- return ax25_encapsulate(skb, dev, type, daddr, saddr, len);
-}
-
-/* ----> get statistics <---- */
-
-static struct net_device_stats *scc_net_get_stats(struct device *dev)
-{
- struct scc_channel *scc = (struct scc_channel *) dev->priv;
-
- if (scc == NULL || scc->magic != SCC_MAGIC)
- return NULL;
-
- scc->dev_stat.rx_errors = scc->stat.rxerrs + scc->stat.rx_over;
- scc->dev_stat.tx_errors = scc->stat.txerrs + scc->stat.tx_under;
- scc->dev_stat.rx_fifo_errors = scc->stat.rx_over;
- scc->dev_stat.tx_fifo_errors = scc->stat.tx_under;
-
- return &scc->dev_stat;
-}
-
-/* ******************************************************************** */
-/* * dump statistics to /proc/net/z8530drv * */
-/* ******************************************************************** */
-
-
-static int scc_net_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
-{
- struct scc_channel *scc;
- struct scc_kiss *kiss;
- struct scc_stat *stat;
- int len = 0;
- off_t pos = 0;
- off_t begin = 0;
- int k;
-
- len += sprintf(buffer, "z8530drv-"VERSION"\n");
-
- if (!Driver_Initialized)
- {
- len += sprintf(buffer+len, "not initialized\n");
- goto done;
- }
-
- if (!Nchips)
- {
- len += sprintf(buffer+len, "chips missing\n");
- goto done;
- }
-
- for (k = 0; k < Nchips*2; k++)
- {
- scc = &SCC_Info[k];
- stat = &scc->stat;
- kiss = &scc->kiss;
-
- if (!scc->init)
- continue;
-
- /* dev data ctrl irq clock brand enh vector special option
- * baud nrz clocksrc softdcd bufsize
- * rxints txints exints spints
- * rcvd rxerrs over / xmit txerrs under / nospace bufsize
- * txd pers slot tail ful wait min maxk idl defr txof grp
- * W ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
- * R ## ## XX ## ## ## ## ## XX ## ## ## ## ## ## ##
- */
-
- len += sprintf(buffer+len, "%s\t%3.3lx %3.3lx %d %lu %2.2x %d %3.3lx %3.3lx %d\n",
- scc->dev->name,
- scc->data, scc->ctrl, scc->irq, scc->clock, scc->brand,
- scc->enhanced, Vector_Latch, scc->special,
- scc->option);
- len += sprintf(buffer+len, "\t%lu %d %d %d %d\n",
- scc->modem.speed, scc->modem.nrz,
- scc->modem.clocksrc, kiss->softdcd,
- stat->bufsize);
- len += sprintf(buffer+len, "\t%lu %lu %lu %lu\n",
- stat->rxints, stat->txints, stat->exints, stat->spints);
- len += sprintf(buffer+len, "\t%lu %lu %d / %lu %lu %d / %d %d\n",
- stat->rxframes, stat->rxerrs, stat->rx_over,
- stat->txframes, stat->txerrs, stat->tx_under,
- stat->nospace, stat->tx_state);
-
-#define K(x) kiss->x
- len += sprintf(buffer+len, "\t%d %d %d %d %d %d %d %d %d %d %d %d\n",
- K(txdelay), K(persist), K(slottime), K(tailtime),
- K(fulldup), K(waittime), K(mintime), K(maxkeyup),
- K(idletime), K(maxdefer), K(tx_inhibit), K(group));
-#undef K
-#ifdef SCC_DEBUG
- {
- int reg;
-
- len += sprintf(buffer+len, "\tW ");
- for (reg = 0; reg < 16; reg++)
- len += sprintf(buffer+len, "%2.2x ", scc->wreg[reg]);
- len += sprintf(buffer+len, "\n");
-
- len += sprintf(buffer+len, "\tR %2.2x %2.2x XX ", InReg(scc->ctrl,R0), InReg(scc->ctrl,R1));
- for (reg = 3; reg < 8; reg++)
- len += sprintf(buffer+len, "%2.2x ", InReg(scc->ctrl, reg));
- len += sprintf(buffer+len, "XX ");
- for (reg = 9; reg < 16; reg++)
- len += sprintf(buffer+len, "%2.2x ", InReg(scc->ctrl, reg));
- len += sprintf(buffer+len, "\n");
- }
-#endif
- len += sprintf(buffer+len, "\n");
-
- pos = begin + len;
-
- if (pos < offset) {
- len = 0;
- begin = pos;
- }
-
- if (pos > offset + length)
- break;
- }
-
-done:
-
- *start = buffer + (offset - begin);
- len -= (offset - begin);
-
- if (len > length) len = length;
-
- return len;
-}
-
-#ifdef CONFIG_PROC_FS
-
-struct proc_dir_entry scc_proc_dir_entry =
-{
- PROC_NET_Z8530, 8, "z8530drv", S_IFREG | S_IRUGO, 1, 0, 0, 0,
- &proc_net_inode_operations, scc_net_get_info
-};
-
-#define scc_net_procfs_init() proc_net_register(&scc_proc_dir_entry);
-#define scc_net_procfs_remove() proc_net_unregister(PROC_NET_Z8530);
-#else
-#define scc_net_procfs_init()
-#define scc_net_procfs_remove()
-#endif
-
-
-/* ******************************************************************** */
-/* * Init SCC driver * */
-/* ******************************************************************** */
-
-__initfunc(int scc_init (void))
-{
- int chip, chan, k, result;
- char devname[10];
-
- printk(KERN_INFO BANNER);
-
- memset(&SCC_ctrl, 0, sizeof(SCC_ctrl));
-
- /* pre-init channel information */
-
- for (chip = 0; chip < MAXSCC; chip++)
- {
- memset((char *) &SCC_Info[2*chip ], 0, sizeof(struct scc_channel));
- memset((char *) &SCC_Info[2*chip+1], 0, sizeof(struct scc_channel));
-
- for (chan = 0; chan < 2; chan++)
- SCC_Info[2*chip+chan].magic = SCC_MAGIC;
- }
-
- for (k = 0; k < 16; k++) Ivec[k].used = 0;
-
- sprintf(devname,"%s0", SCC_DriverName);
-
- result = scc_net_setup(SCC_Info, devname);
- if (result)
- {
- printk(KERN_ERR "z8530drv: cannot initialize module\n");
- return result;
- }
-
- scc_net_procfs_init();
-
- return 0;
-}
-
-/* ******************************************************************** */
-/* * Module support * */
-/* ******************************************************************** */
-
-
-#ifdef MODULE
-int init_module(void)
-{
- int result = 0;
-
- result = scc_init();
-
- if (result == 0)
- printk(KERN_INFO "Copyright 1993,1997 Joerg Reuter DL1BKE (jreuter@lykos.tng.oche.de)\n");
-
- return result;
-}
-
-void cleanup_module(void)
-{
- long flags;
- io_port ctrl;
- int k;
- struct scc_channel *scc;
-
- save_flags(flags);
- cli();
-
- if (Nchips == 0)
- unregister_netdev(SCC_Info[0].dev);
-
- for (k = 0; k < Nchips; k++)
- if ( (ctrl = SCC_ctrl[k].chan_A) )
- {
- Outb(ctrl, 0);
- OutReg(ctrl,R9,FHWRES); /* force hardware reset */
- udelay(50);
- }
-
- for (k = 0; k < Nchips*2; k++)
- {
- scc = &SCC_Info[k];
- if (scc)
- {
- release_region(scc->ctrl, 1);
- release_region(scc->data, 1);
- if (scc->dev)
- {
- unregister_netdev(scc->dev);
- kfree(scc->dev);
- }
- }
- }
-
- for (k=0; k < 16 ; k++)
- if (Ivec[k].used) free_irq(k, NULL);
-
- restore_flags(flags);
-
- scc_net_procfs_remove();
-}
-#endif
diff --git a/drivers/net/slip.c b/drivers/net/slip.c
index 76b0aec81..9493fe371 100644
--- a/drivers/net/slip.c
+++ b/drivers/net/slip.c
@@ -68,6 +68,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
+#include <linux/rtnetlink.h>
#include <linux/if_arp.h>
#include <linux/if_slip.h>
#include <linux/init.h>
@@ -733,6 +734,7 @@ slip_close(struct tty_struct *tty)
return;
}
+ rtnl_lock();
if (sl->dev->flags & IFF_UP)
{
/* STRONG layering violation! --ANK */
@@ -749,6 +751,8 @@ slip_close(struct tty_struct *tty)
(void)del_timer (&sl->outfill_timer);
#endif
sl_free(sl);
+ unregister_netdevice(sl->dev);
+ rtnl_unlock();
MOD_DEC_USE_COUNT;
}
diff --git a/drivers/net/soundmodem/.cvsignore b/drivers/net/soundmodem/.cvsignore
index 1f1dff45f..e69de29bb 100644
--- a/drivers/net/soundmodem/.cvsignore
+++ b/drivers/net/soundmodem/.cvsignore
@@ -1,3 +0,0 @@
-.depend
-sm_tbl_*.h
-gentbl
diff --git a/drivers/net/soundmodem/Makefile b/drivers/net/soundmodem/Makefile
index 381eb35cd..e69de29bb 100644
--- a/drivers/net/soundmodem/Makefile
+++ b/drivers/net/soundmodem/Makefile
@@ -1,60 +0,0 @@
-#
-# Makefile for the soundmodem device driver.
-#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
-# Note 2! The CFLAGS definitions are now inherited from the
-# parent makes..
-#
-
-O_TARGET := soundmodem.o
-
-O_OBJS := sm.o
-ifeq ($(CONFIG_SOUNDMODEM_SBC),y)
-O_OBJS += sm_sbc.o
-endif
-ifeq ($(CONFIG_SOUNDMODEM_WSS),y)
-O_OBJS += sm_wss.o
-endif
-ifeq ($(CONFIG_SOUNDMODEM_AFSK1200),y)
-O_OBJS += sm_afsk1200.o
-endif
-ifeq ($(CONFIG_SOUNDMODEM_AFSK2400_7),y)
-O_OBJS += sm_afsk2400_7.o
-endif
-ifeq ($(CONFIG_SOUNDMODEM_AFSK2400_8),y)
-O_OBJS += sm_afsk2400_8.o
-endif
-ifeq ($(CONFIG_SOUNDMODEM_AFSK2666),y)
-O_OBJS += sm_afsk2666.o
-endif
-ifeq ($(CONFIG_SOUNDMODEM_HAPN4800),y)
-O_OBJS += sm_hapn4800.o
-endif
-ifeq ($(CONFIG_SOUNDMODEM_PSK4800),y)
-O_OBJS += sm_psk4800.o
-endif
-ifeq ($(CONFIG_SOUNDMODEM_FSK9600),y)
-O_OBJS += sm_fsk9600.o
-endif
-
-M_OBJS := $(O_TARGET)
-
-all: all_targets
-.PHONY: all
-
-gentbl: gentbl.c
- $(HOSTCC) $< -o $@ -lm
-
-TBLHDR := sm_tbl_afsk1200.h sm_tbl_afsk2400_8.h
-TBLHDR += sm_tbl_afsk2666.h sm_tbl_psk4800.h
-TBLHDR += sm_tbl_hapn4800.h sm_tbl_fsk9600.h
-
-$(TBLHDR): gentbl
- ./gentbl
-
-fastdep: $(TBLHDR)
-
-include $(TOPDIR)/Rules.make
diff --git a/drivers/net/soundmodem/gentbl.c b/drivers/net/soundmodem/gentbl.c
index c35d0e466..e69de29bb 100644
--- a/drivers/net/soundmodem/gentbl.c
+++ b/drivers/net/soundmodem/gentbl.c
@@ -1,676 +0,0 @@
-/*****************************************************************************/
-
-/*
- * gentbl.c -- soundcard radio modem driver table generator.
- *
- * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Please note that the GPL allows you to use the driver, NOT the radio.
- * In order to use the radio, you need a license from the communications
- * authority of your country.
- *
- */
-
-#include <stdio.h>
-#include <math.h>
-#include <string.h>
-
-/* -------------------------------------------------------------------- */
-
-static void gentbl_offscostab(FILE *f, unsigned int nbits)
-{
- int i;
-
- fprintf(f, "\n/*\n * small cosine table in U8 format\n */\n"
- "#define OFFSCOSTABBITS %u\n"
- "#define OFFSCOSTABSIZE (1<<OFFSCOSTABBITS)\n\n",
- nbits);
- fprintf(f, "static unsigned char offscostab[OFFSCOSTABSIZE] = {\n\t");
- for (i = 0; i < (1<<nbits); i++) {
- fprintf(f, "%4u", (int)
- (128+127.0*cos(i*2.0*M_PI/(1<<nbits))));
- if (i < (1<<nbits)-1)
- fprintf(f, "%s", (i & 7) == 7 ? ",\n\t" : ",");
- }
- fprintf(f, "\n};\n\n"
- "#define OFFSCOS(x) offscostab[((x)>>%d)&0x%x]\n\n",
- 16-nbits, (1<<nbits)-1);
-}
-
-/* -------------------------------------------------------------------- */
-
-static void gentbl_costab(FILE *f, unsigned int nbits)
-{
- int i;
-
- fprintf(f, "\n/*\n * more accurate cosine table\n */\n\n"
- "static const short costab[%d] = {", (1<<nbits));
- for (i = 0; i < (1<<nbits); i++) {
- if (!(i & 7))
- fprintf(f, "\n\t");
- fprintf(f, "%6d", (int)(32767.0*cos(i*2.0*M_PI/(1<<nbits))));
- if (i != ((1<<nbits)-1))
- fprintf(f, ", ");
- }
- fprintf(f, "\n};\n\n#define COS(x) costab[((x)>>%d)&0x%x]\n"
- "#define SIN(x) COS((x)+0xc000)\n\n", 16-nbits,
- (1<<nbits)-1);
-}
-
-/* -------------------------------------------------------------------- */
-
-#define AFSK12_SAMPLE_RATE 9600
-#define AFSK12_TX_FREQ_LO 1200
-#define AFSK12_TX_FREQ_HI 2200
-#define AFSK12_CORRLEN 8
-
-static void gentbl_afsk1200(FILE *f)
-{
- int i, v, sum;
-
-#define ARGLO(x) 2.0*M_PI*(double)x*(double)AFSK12_TX_FREQ_LO/(double)AFSK12_SAMPLE_RATE
-#define ARGHI(x) 2.0*M_PI*(double)x*(double)AFSK12_TX_FREQ_HI/(double)AFSK12_SAMPLE_RATE
-
- fprintf(f, "\n/*\n * afsk1200 specific tables\n */\n"
- "#define AFSK12_SAMPLE_RATE %u\n"
- "#define AFSK12_TX_FREQ_LO %u\n"
- "#define AFSK12_TX_FREQ_HI %u\n"
- "#define AFSK12_CORRLEN %u\n\n",
- AFSK12_SAMPLE_RATE, AFSK12_TX_FREQ_LO,
- AFSK12_TX_FREQ_HI, AFSK12_CORRLEN);
- fprintf(f, "static const int afsk12_tx_lo_i[] = {\n\t");
- for(sum = i = 0; i < AFSK12_CORRLEN; i++) {
- sum += (v = 127.0*cos(ARGLO(i)));
- fprintf(f, " %4i%c", v, (i < AFSK12_CORRLEN-1) ? ',' : ' ');
- }
- fprintf(f, "\n};\n#define SUM_AFSK12_TX_LO_I %d\n\n"
- "static const int afsk12_tx_lo_q[] = {\n\t", sum);
- for(sum = i = 0; i < AFSK12_CORRLEN; i++) {
- sum += (v = 127.0*sin(ARGLO(i)));
- fprintf(f, " %4i%c", v, (i < AFSK12_CORRLEN-1) ? ',' : ' ');
- }
- fprintf(f, "\n};\n#define SUM_AFSK12_TX_LO_Q %d\n\n"
- "static const int afsk12_tx_hi_i[] = {\n\t", sum);
- for(sum = i = 0; i < AFSK12_CORRLEN; i++) {
- sum += (v = 127.0*cos(ARGHI(i)));
- fprintf(f, " %4i%c", v, (i < AFSK12_CORRLEN-1) ? ',' : ' ');
- }
- fprintf(f, "\n};\n#define SUM_AFSK12_TX_HI_I %d\n\n"
- "static const int afsk12_tx_hi_q[] = {\n\t", sum);
- for(sum = i = 0; i < AFSK12_CORRLEN; i++) {
- sum += (v = 127.0*sin(ARGHI(i)));
- fprintf(f, " %4i%c", v, (i < AFSK12_CORRLEN-1) ? ',' : ' ');
- }
- fprintf(f, "\n};\n#define SUM_AFSK12_TX_HI_Q %d\n\n", sum);
-#undef ARGLO
-#undef ARGHI
-}
-
-/* -------------------------------------------------------------------- */
-
-static const float fsk96_tx_coeff_4[32] = {
- -0.001152, 0.000554, 0.002698, 0.002753,
- -0.002033, -0.008861, -0.008002, 0.006607,
- 0.023727, 0.018905, -0.018056, -0.057957,
- -0.044368, 0.055683, 0.207667, 0.322048,
- 0.322048, 0.207667, 0.055683, -0.044368,
- -0.057957, -0.018056, 0.018905, 0.023727,
- 0.006607, -0.008002, -0.008861, -0.002033,
- 0.002753, 0.002698, 0.000554, -0.001152
-};
-
-static const float fsk96_tx_coeff_5[40] = {
- -0.001009, -0.000048, 0.001376, 0.002547,
- 0.002061, -0.001103, -0.005795, -0.008170,
- -0.004017, 0.006924, 0.018225, 0.019238,
- 0.002925, -0.025777, -0.048064, -0.039683,
- 0.013760, 0.104144, 0.200355, 0.262346,
- 0.262346, 0.200355, 0.104144, 0.013760,
- -0.039683, -0.048064, -0.025777, 0.002925,
- 0.019238, 0.018225, 0.006924, -0.004017,
- -0.008170, -0.005795, -0.001103, 0.002061,
- 0.002547, 0.001376, -0.000048, -0.001009
-};
-
-#define HAMMING(x) (0.54-0.46*cos(2*M_PI*(x)));
-
-static float hamming(float x)
-{
- return 0.54-0.46*cos(2*M_PI*x);
-}
-
-static float sinc(float x)
-{
- if (x == 0)
- return 1;
- x *= M_PI;
- return sin(x)/x;
-}
-
-static void gentbl_fsk9600(FILE *f)
-{
- int i, j, k, l, m;
- float s;
- float c[44];
- float min, max;
-
- fprintf(f, "\n/*\n * fsk9600 specific tables\n */\n");
- min = max = 0;
- memset(c, 0, sizeof(c));
-#if 0
- memcpy(c+2, fsk96_tx_coeff_4, sizeof(fsk96_tx_coeff_4));
-#else
- for (i = 0; i < 29; i++)
- c[3+i] = sinc(1.2*((i-14.0)/4.0))*hamming(i/28.0)/3.5;
-#endif
- fprintf(f, "static unsigned char fsk96_txfilt_4[] = {\n\t");
- for (i = 0; i < 4; i++) {
- for (j = 0; j < 256; j++) {
- for (k = 1, s = 0, l = i; k < 256; k <<= 1) {
- if (j & k) {
- for (m = 0; m < 4; m++, l++)
- s += c[l];
- } else {
- for (m = 0; m < 4; m++, l++)
- s -= c[l];
- }
- }
- s *= 0.75;
- if (s > max)
- max = s;
- if (s < min)
- min = s;
- fprintf(f, "%4d", (int)(128+127*s));
- if (i < 3 || j < 255)
- fprintf(f, ",%s", (j & 7) == 7
- ? "\n\t" : "");
- }
- }
- fprintf(stderr, "fsk9600: txfilt4: min = %f; max = %f\n", min, max);
- fprintf(f, "\n};\n\n");
- min = max = 0;
- memset(c, 0, sizeof(c));
-#if 0
- memcpy(c+2, fsk96_tx_coeff_5, sizeof(fsk96_tx_coeff_5));
-#else
- for (i = 0; i < 36; i++)
- c[4+i] = sinc(1.2*((i-17.5)/5.0))*hamming(i/35.0)/4.5;
-#endif
- fprintf(f, "static unsigned char fsk96_txfilt_5[] = {\n\t");
- for (i = 0; i < 5; i++) {
- for (j = 0; j < 256; j++) {
- for (k = 1, s = 0, l = i; k < 256; k <<= 1) {
- if (j & k) {
- for (m = 0; m < 5; m++, l++)
- s += c[l];
- } else {
- for (m = 0; m < 5; m++, l++)
- s -= c[l];
- }
- }
- s *= 0.75;
- if (s > max)
- max = s;
- if (s < min)
- min = s;
- fprintf(f, "%4d", (int)(128+127*s));
- if (i < 4 || j < 255)
- fprintf(f, ",%s", (j & 7) == 7
- ? "\n\t" : "");
- }
- }
- fprintf(stderr, "fsk9600: txfilt5: min = %f; max = %f\n", min, max);
- fprintf(f, "\n};\n\n");
-}
-
-/* -------------------------------------------------------------------- */
-
-#define AFSK26_SAMPLERATE 16000
-
-#define AFSK26_NUMCAR 2
-#define AFSK26_FIRSTCAR 2000
-#define AFSK26_MSK_LEN 6
-#define AFSK26_RXOVER 2
-
-#define AFSK26_DEMCORRLEN (2*AFSK26_MSK_LEN)
-
-#define AFSK26_WINDOW(x) ((1-cos(2.0*M_PI*(x)))/2.0)
-
-#define AFSK26_AMPL(x) (((x)?1.0:0.7))
-
-#undef AFSK26_AMPL
-#define AFSK26_AMPL(x) 1
-
-static void gentbl_afsk2666(FILE *f)
-{
- int i, j, k, l, o, v, sumi, sumq;
- float window[AFSK26_DEMCORRLEN*AFSK26_RXOVER];
- int cfreq[AFSK26_NUMCAR];
-
- fprintf(f, "\n/*\n * afsk2666 specific tables\n */\n"
- "#define AFSK26_DEMCORRLEN %d\n"
- "#define AFSK26_SAMPLERATE %d\n\n", AFSK26_DEMCORRLEN,
- AFSK26_SAMPLERATE);
- fprintf(f, "static const unsigned int afsk26_carfreq[%d] = { ",
- AFSK26_NUMCAR);
- for (i = 0; i < AFSK26_NUMCAR; i++) {
- cfreq[i] = 0x10000*AFSK26_FIRSTCAR/AFSK26_SAMPLERATE+
- 0x10000*i/AFSK26_MSK_LEN/2;
- fprintf(f, "0x%x", cfreq[i]);
- if (i < AFSK26_NUMCAR-1)
- fprintf(f, ", ");
- }
- fprintf(f, " };\n\n");
- for (i = 0; i < AFSK26_DEMCORRLEN*AFSK26_RXOVER; i++)
- window[i] = AFSK26_WINDOW(((float)i)/(AFSK26_DEMCORRLEN*
- AFSK26_RXOVER)) * 127.0;
- fprintf(f, "\nstatic const struct {\n\t"
- "int i[%d];\n\tint q[%d];\n} afsk26_dem_tables[%d][%d] = {\n",
- AFSK26_DEMCORRLEN, AFSK26_DEMCORRLEN, AFSK26_RXOVER, AFSK26_NUMCAR);
- for (o = AFSK26_RXOVER-1; o >= 0; o--) {
- fprintf(f, "\t{\n");
- for (i = 0; i < AFSK26_NUMCAR; i++) {
- j = cfreq[i];
- fprintf(f, "\t\t{{ ");
- for (l = AFSK26_DEMCORRLEN-1, k = (j * o)/AFSK26_RXOVER, sumi = 0; l >= 0;
- l--, k = (k+j)&0xffffu) {
- sumi += (v = AFSK26_AMPL(i)*window[l*AFSK26_RXOVER+o]*
- cos(M_PI*k/32768.0));
- fprintf(f, "%6d%s", v, l ? ", " : " }, { ");
- }
- for (l = AFSK26_DEMCORRLEN-1, k = (j * o)/AFSK26_RXOVER, sumq = 0; l >= 0;
- l--, k = (k+j)&0xffffu) {
- sumq += (v = AFSK26_AMPL(i)*window[l*AFSK26_RXOVER+o]*
- sin(M_PI*k/32768.0));
- fprintf(f, "%6d%s", v, l ? ", " : " }}");
- }
- if (i < 1)
- fprintf(f, ",");
- fprintf(f, "\n#define AFSK26_DEM_SUM_I_%d_%d %d\n"
- "#define AFSK26_DEM_SUM_Q_%d_%d %d\n",
- AFSK26_RXOVER-1-o, i, sumi, AFSK26_RXOVER-1-o, i, sumq);
- }
- fprintf(f, "\t}%s\n", o ? "," : "");
- }
- fprintf(f, "};\n\n");
-}
-
-/* -------------------------------------------------------------------- */
-
-#define ATAN_TABLEN 1024
-
-static void gentbl_atantab(FILE *f)
-{
- int i;
- short x;
-
- fprintf(f, "\n/*\n"
- " * arctan table (indexed by i/q; should really be indexed by i/(i+q)\n"
- " */\n""#define ATAN_TABLEN %d\n\n"
- "static const unsigned short atan_tab[ATAN_TABLEN+2] = {",
- ATAN_TABLEN);
- for (i = 0; i <= ATAN_TABLEN; i++) {
- if (!(i & 7))
- fprintf(f, "\n\t");
- x = atan(i / (float)ATAN_TABLEN) / M_PI * 0x8000;
- fprintf(f, "%6d, ", x);
- }
- fprintf(f, "%6d\n};\n\n", x);
-
-}
-
-/* -------------------------------------------------------------------- */
-
-#define PSK48_TXF_OVERSAMPLING 5
-#define PSK48_TXF_NUMSAMPLES 16
-#define PSK48_RXF_LEN 64
-
-static const float psk48_tx_coeff[80] = {
- -0.000379, -0.000640, -0.000000, 0.000772,
- 0.000543, -0.000629, -0.001187, -0.000000,
- 0.001634, 0.001183, -0.001382, -0.002603,
- -0.000000, 0.003481, 0.002472, -0.002828,
- -0.005215, -0.000000, 0.006705, 0.004678,
- -0.005269, -0.009584, -0.000000, 0.012065,
- 0.008360, -0.009375, -0.017028, -0.000000,
- 0.021603, 0.015123, -0.017229, -0.032012,
- -0.000000, 0.043774, 0.032544, -0.040365,
- -0.084963, -0.000000, 0.201161, 0.374060,
- 0.374060, 0.201161, -0.000000, -0.084963,
- -0.040365, 0.032544, 0.043774, -0.000000,
- -0.032012, -0.017229, 0.015123, 0.021603,
- -0.000000, -0.017028, -0.009375, 0.008360,
- 0.012065, -0.000000, -0.009584, -0.005269,
- 0.004678, 0.006705, -0.000000, -0.005215,
- -0.002828, 0.002472, 0.003481, -0.000000,
- -0.002603, -0.001382, 0.001183, 0.001634,
- -0.000000, -0.001187, -0.000629, 0.000543,
- 0.000772, -0.000000, -0.000640, -0.000379
-};
-
-static const float psk48_rx_coeff[PSK48_RXF_LEN] = {
- -0.000219, 0.000360, 0.000873, 0.001080,
- 0.000747, -0.000192, -0.001466, -0.002436,
- -0.002328, -0.000699, 0.002101, 0.004809,
- 0.005696, 0.003492, -0.001633, -0.007660,
- -0.011316, -0.009627, -0.001780, 0.009712,
- 0.019426, 0.021199, 0.011342, -0.008583,
- -0.030955, -0.044093, -0.036634, -0.002651,
- 0.054742, 0.123101, 0.184198, 0.220219,
- 0.220219, 0.184198, 0.123101, 0.054742,
- -0.002651, -0.036634, -0.044093, -0.030955,
- -0.008583, 0.011342, 0.021199, 0.019426,
- 0.009712, -0.001780, -0.009627, -0.011316,
- -0.007660, -0.001633, 0.003492, 0.005696,
- 0.004809, 0.002101, -0.000699, -0.002328,
- -0.002436, -0.001466, -0.000192, 0.000747,
- 0.001080, 0.000873, 0.000360, -0.000219
-};
-
-static void gentbl_psk4800(FILE *f)
-{
- int i, j, k;
- short x;
-
- fprintf(f, "\n/*\n * psk4800 specific tables\n */\n"
- "#define PSK48_TXF_OVERSAMPLING %d\n"
- "#define PSK48_TXF_NUMSAMPLES %d\n\n"
- "#define PSK48_SAMPLERATE 8000\n"
- "#define PSK48_CAR_FREQ 2000\n"
- "#define PSK48_PSK_LEN 5\n"
- "#define PSK48_RXF_LEN %u\n"
- "#define PSK48_PHASEINC (0x10000*PSK48_CAR_FREQ/PSK48_SAMPLERATE)\n"
- "#define PSK48_SPHASEINC (0x10000/(2*PSK48_PSK_LEN))\n\n"
- "static const short psk48_tx_table[PSK48_TXF_OVERSAMPLING*"
- "PSK48_TXF_NUMSAMPLES*8*2] = {",
- PSK48_TXF_OVERSAMPLING, PSK48_TXF_NUMSAMPLES, PSK48_RXF_LEN);
- for (i = 0; i < PSK48_TXF_OVERSAMPLING; i++) {
- for (j = 0; j < PSK48_TXF_NUMSAMPLES; j++) {
- fprintf(f, "\n\t");
- for (k = 0; k < 8; k++) {
- x = 32767.0 * cos(k*M_PI/4.0) *
- psk48_tx_coeff[j * PSK48_TXF_OVERSAMPLING + i];
- fprintf(f, "%6d, ", x);
- }
- fprintf(f, "\n\t");
- for (k = 0; k < 8; k++) {
- x = 32767.0 * sin(k*M_PI/4.0) *
- psk48_tx_coeff[j * PSK48_TXF_OVERSAMPLING + i];
- fprintf(f, "%6d", x);
- if (k != 7 || j != PSK48_TXF_NUMSAMPLES-1 ||
- i != PSK48_TXF_OVERSAMPLING-1)
- fprintf(f, ", ");
- }
- }
- }
- fprintf(f, "\n};\n\n");
-
- fprintf(f, "static const short psk48_rx_coeff[PSK48_RXF_LEN] = {\n\t");
- for (i = 0; i < PSK48_RXF_LEN; i++) {
- fprintf(f, "%6d", (int)(psk48_rx_coeff[i]*32767.0));
- if (i < PSK48_RXF_LEN-1)
- fprintf(f, ",%s", (i & 7) == 7 ? "\n\t" : "");
- }
- fprintf(f, "\n};\n\n");
-}
-
-/* -------------------------------------------------------------------- */
-
-static void gentbl_hapn4800(FILE *f)
-{
- int i, j, k, l;
- float s;
- float c[40];
- float min, max;
-
- fprintf(f, "\n/*\n * hapn4800 specific tables\n */\n\n");
- /*
- * firstly generate tables for the FM transmitter modulator
- */
- min = max = 0;
- memset(c, 0, sizeof(c));
- for (i = 0; i < 24; i++)
- c[8+i] = sinc(1.5*((i-11.5)/8.0))*hamming(i/23.0)/2.4;
- for (i = 0; i < 24; i++)
- c[i] -= c[i+8];
- fprintf(f, "static unsigned char hapn48_txfilt_8[] = {\n\t");
- for (i = 0; i < 8; i++) {
- for (j = 0; j < 16; j++) {
- for (k = 1, s = 0, l = i; k < 16; k <<= 1, l += 8) {
- if (j & k)
- s += c[l];
- else
- s -= c[l];
- }
- if (s > max)
- max = s;
- if (s < min)
- min = s;
- fprintf(f, "%4d", (int)(128+127*s));
- if (i < 7 || j < 15)
- fprintf(f, ",%s", (j & 7) == 7
- ? "\n\t" : "");
- }
- }
- fprintf(stderr, "hapn4800: txfilt8: min = %f; max = %f\n", min, max);
- fprintf(f, "\n};\n\n");
- min = max = 0;
- memset(c, 0, sizeof(c));
- for (i = 0; i < 30; i++)
- c[10+i] = sinc(1.5*((i-14.5)/10.0))*hamming(i/29.0)/2.4;
- for (i = 0; i < 30; i++)
- c[i] -= c[i+10];
- fprintf(f, "static unsigned char hapn48_txfilt_10[] = {\n\t");
- for (i = 0; i < 10; i++) {
- for (j = 0; j < 16; j++) {
- for (k = 1, s = 0, l = i; k < 16; k <<= 1, l += 10) {
- if (j & k)
- s += c[l];
- else
- s -= c[l];
- }
- if (s > max)
- max = s;
- if (s < min)
- min = s;
- fprintf(f, "%4d", (int)(128+127*s));
- if (i < 9 || j < 15)
- fprintf(f, ",%s", (j & 7) == 7
- ? "\n\t" : "");
- }
- }
- fprintf(stderr, "hapn4800: txfilt10: min = %f; max = %f\n", min, max);
- fprintf(f, "\n};\n\n");
- /*
- * secondly generate tables for the PM transmitter modulator
- */
- min = max = 0;
- memset(c, 0, sizeof(c));
- for (i = 0; i < 25; i++)
- c[i] = sinc(1.4*((i-12.0)/8.0))*hamming(i/24.0)/6.3;
- for (i = 0; i < 25; i++)
- for (j = 1; j < 8; j++)
- c[i] += c[i+j];
- fprintf(f, "static unsigned char hapn48_txfilt_pm8[] = {\n\t");
- for (i = 0; i < 8; i++) {
- for (j = 0; j < 16; j++) {
- for (k = 1, s = 0, l = i; k < 16; k <<= 1, l += 8) {
- if (j & k)
- s += c[l];
- else
- s -= c[l];
- }
- if (s > max)
- max = s;
- if (s < min)
- min = s;
- fprintf(f, "%4d", (int)(128+127*s));
- if (i < 7 || j < 15)
- fprintf(f, ",%s", (j & 7) == 7
- ? "\n\t" : "");
- }
- }
- fprintf(stderr, "hapn4800: txfiltpm8: min = %f; max = %f\n", min, max);
- fprintf(f, "\n};\n\n");
- min = max = 0;
- memset(c, 0, sizeof(c));
- for (i = 0; i < 31; i++)
- c[10+i] = sinc(1.4*((i-15.0)/10.0))*hamming(i/30.0)/7.9;
- for (i = 0; i < 31; i++)
- for (j = 1; j < 10; j++)
- c[i] += c[i+j];
- fprintf(f, "static unsigned char hapn48_txfilt_pm10[] = {\n\t");
- for (i = 0; i < 10; i++) {
- for (j = 0; j < 16; j++) {
- for (k = 1, s = 0, l = i; k < 16; k <<= 1, l += 10) {
- if (j & k)
- s += c[l];
- else
- s -= c[l];
- }
- if (s > max)
- max = s;
- if (s < min)
- min = s;
- fprintf(f, "%4d", (int)(128+127*s));
- if (i < 9 || j < 15)
- fprintf(f, ",%s", (j & 7) == 7
- ? "\n\t" : "");
- }
- }
- fprintf(stderr, "hapn4800: txfiltpm10: min = %f; max = %f\n", min, max);
- fprintf(f, "\n};\n\n");
-
-}
-
-/* -------------------------------------------------------------------- */
-
-#define AFSK24_SAMPLERATE 16000
-#define AFSK24_CORRLEN 14
-
-static void gentbl_afsk2400(FILE *f, float tcm3105clk)
-{
- int i, sum, v;
-
- fprintf(f, "\n/*\n * afsk2400 specific tables (tcm3105 clk %7fHz)\n */\n"
- "#define AFSK24_TX_FREQ_LO %d\n"
- "#define AFSK24_TX_FREQ_HI %d\n"
- "#define AFSK24_BITPLL_INC %d\n"
- "#define AFSK24_SAMPLERATE %d\n\n", tcm3105clk,
- (int)(tcm3105clk/3694.0), (int)(tcm3105clk/2015.0),
- 0x10000*2400/AFSK24_SAMPLERATE, AFSK24_SAMPLERATE);
-
-#define ARGLO(x) 2.0*M_PI*(double)x*(tcm3105clk/3694.0)/(double)AFSK24_SAMPLERATE
-#define ARGHI(x) 2.0*M_PI*(double)x*(tcm3105clk/2015.0)/(double)AFSK24_SAMPLERATE
-#define WINDOW(x) hamming((float)(x)/(AFSK24_CORRLEN-1.0))
-
- fprintf(f, "static const int afsk24_tx_lo_i[] = {\n\t");
- for(sum = i = 0; i < AFSK24_CORRLEN; i++) {
- sum += (v = 127.0*cos(ARGLO(i))*WINDOW(i));
- fprintf(f, " %4i%c", v, (i < AFSK24_CORRLEN-1) ? ',' : ' ');
- }
- fprintf(f, "\n};\n#define SUM_AFSK24_TX_LO_I %d\n\n"
- "static const int afsk24_tx_lo_q[] = {\n\t", sum);
- for(sum = i = 0; i < AFSK24_CORRLEN; i++) {
- sum += (v = 127.0*sin(ARGLO(i))*WINDOW(i));
- fprintf(f, " %4i%c", v, (i < AFSK24_CORRLEN-1) ? ',' : ' ');
- }
- fprintf(f, "\n};\n#define SUM_AFSK24_TX_LO_Q %d\n\n"
- "static const int afsk24_tx_hi_i[] = {\n\t", sum);
- for(sum = i = 0; i < AFSK24_CORRLEN; i++) {
- sum += (v = 127.0*cos(ARGHI(i))*WINDOW(i));
- fprintf(f, " %4i%c", v, (i < AFSK24_CORRLEN-1) ? ',' : ' ');
- }
- fprintf(f, "\n};\n#define SUM_AFSK24_TX_HI_I %d\n\n"
- "static const int afsk24_tx_hi_q[] = {\n\t", sum);
- for(sum = i = 0; i < AFSK24_CORRLEN; i++) {
- sum += (v = 127.0*sin(ARGHI(i))*WINDOW(i));
- fprintf(f, " %4i%c", v, (i < AFSK24_CORRLEN-1) ? ',' : ' ');
- }
- fprintf(f, "\n};\n#define SUM_AFSK24_TX_HI_Q %d\n\n", sum);
-#undef ARGLO
-#undef ARGHI
-#undef WINDOW
-}
-
-/* -------------------------------------------------------------------- */
-
-static char *progname;
-
-static void gentbl_banner(FILE *f)
-{
- fprintf(f, "/*\n * THIS FILE IS GENERATED AUTOMATICALLY BY %s, "
- "DO NOT EDIT!\n */\n\n", progname);
-}
-
-/* -------------------------------------------------------------------- */
-
-void main(int argc, char *argv[])
-{
- FILE *f;
-
- progname = argv[0];
- if (!(f = fopen("sm_tbl_afsk1200.h", "w")))
- exit(1);
- gentbl_banner(f);
- gentbl_offscostab(f, 6);
- gentbl_costab(f, 6);
- gentbl_afsk1200(f);
- fclose(f);
- if (!(f = fopen("sm_tbl_afsk2666.h", "w")))
- exit(1);
- gentbl_banner(f);
- gentbl_offscostab(f, 6);
- gentbl_costab(f, 6);
- gentbl_afsk2666(f);
- fclose(f);
- if (!(f = fopen("sm_tbl_psk4800.h", "w")))
- exit(1);
- gentbl_banner(f);
- gentbl_psk4800(f);
- gentbl_costab(f, 8);
- gentbl_atantab(f);
- fclose(f);
- if (!(f = fopen("sm_tbl_hapn4800.h", "w")))
- exit(1);
- gentbl_banner(f);
- gentbl_hapn4800(f);
- fclose(f);
- if (!(f = fopen("sm_tbl_fsk9600.h", "w")))
- exit(1);
- gentbl_banner(f);
- gentbl_fsk9600(f);
- fclose(f);
- if (!(f = fopen("sm_tbl_afsk2400_8.h", "w")))
- exit(1);
- gentbl_banner(f);
- gentbl_offscostab(f, 6);
- gentbl_costab(f, 6);
- gentbl_afsk2400(f, 8000000);
- fclose(f);
- if (!(f = fopen("sm_tbl_afsk2400_7.h", "w")))
- exit(1);
- gentbl_banner(f);
- gentbl_offscostab(f, 6);
- gentbl_costab(f, 6);
- gentbl_afsk2400(f, 7372800);
- fclose(f);
- exit(0);
-}
-
-
-/* -------------------------------------------------------------------- */
diff --git a/drivers/net/soundmodem/sm.c b/drivers/net/soundmodem/sm.c
index 171aecfc7..e69de29bb 100644
--- a/drivers/net/soundmodem/sm.c
+++ b/drivers/net/soundmodem/sm.c
@@ -1,898 +0,0 @@
-/*****************************************************************************/
-
-/*
- * sm.c -- soundcard radio modem driver.
- *
- * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Please note that the GPL allows you to use the driver, NOT the radio.
- * In order to use the radio, you need a license from the communications
- * authority of your country.
- *
- *
- * Command line options (insmod command line)
- *
- * mode mode string; eg. "wss:afsk1200"
- * iobase base address of the soundcard; common values are 0x220 for sbc,
- * 0x530 for wss
- * irq interrupt number; common values are 7 or 5 for sbc, 11 for wss
- * dma dma number; common values are 0 or 1
- *
- *
- * History:
- * 0.1 21.09.96 Started
- * 18.10.96 Changed to new user space access routines (copy_{to,from}_user)
- * 0.4 21.01.97 Separately compileable soundcard/modem modules
- * 0.5 03.03.97 fixed LPT probing (check_lpt result was interpreted the wrong way round)
- * 0.6 16.04.97 init code/data tagged
- * 0.7 30.07.97 fixed halfduplex interrupt handlers/hotfix for CS423X
- */
-
-/*****************************************************************************/
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/ptrace.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/ioport.h>
-#include <linux/net.h>
-#include <linux/in.h>
-#include <linux/string.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/bitops.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include "sm.h"
-
-/* --------------------------------------------------------------------- */
-
-/*
- * currently this module is supposed to support both module styles, i.e.
- * the old one present up to about 2.1.9, and the new one functioning
- * starting with 2.1.21. The reason is I have a kit allowing to compile
- * this module also under 2.0.x which was requested by several people.
- * This will go in 2.2
- */
-#include <linux/version.h>
-
-#if LINUX_VERSION_CODE >= 0x20100
-#include <asm/uaccess.h>
-#else
-#include <asm/segment.h>
-#include <linux/mm.h>
-
-#undef put_user
-#undef get_user
-
-#define put_user(x,ptr) ({ __put_user((unsigned long)(x),(ptr),sizeof(*(ptr))); 0; })
-#define get_user(x,ptr) ({ x = ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr)))); 0; })
-
-extern inline int copy_from_user(void *to, const void *from, unsigned long n)
-{
- int i = verify_area(VERIFY_READ, from, n);
- if (i)
- return i;
- memcpy_fromfs(to, from, n);
- return 0;
-}
-
-extern inline int copy_to_user(void *to, const void *from, unsigned long n)
-{
- int i = verify_area(VERIFY_WRITE, to, n);
- if (i)
- return i;
- memcpy_tofs(to, from, n);
- return 0;
-}
-#endif
-
-#if LINUX_VERSION_CODE >= 0x20123
-#include <linux/init.h>
-#else
-#define __init
-#define __initdata
-#define __initfunc(x) x
-#endif
-
-/* --------------------------------------------------------------------- */
-
-/*static*/ const char sm_drvname[] = "soundmodem";
-static const char sm_drvinfo[] = KERN_INFO "soundmodem: (C) 1996-1997 Thomas Sailer, HB9JNX/AE4WA\n"
-KERN_INFO "soundmodem: version 0.7 compiled " __TIME__ " " __DATE__ "\n";
-
-/* --------------------------------------------------------------------- */
-
-/*static*/ const struct modem_tx_info *sm_modem_tx_table[] = {
-#ifdef CONFIG_SOUNDMODEM_AFSK1200
- &sm_afsk1200_tx,
-#endif /* CONFIG_SOUNDMODEM_AFSK1200 */
-#ifdef CONFIG_SOUNDMODEM_AFSK2400_7
- &sm_afsk2400_7_tx,
-#endif /* CONFIG_SOUNDMODEM_AFSK2400_7 */
-#ifdef CONFIG_SOUNDMODEM_AFSK2400_8
- &sm_afsk2400_8_tx,
-#endif /* CONFIG_SOUNDMODEM_AFSK2400_8 */
-#ifdef CONFIG_SOUNDMODEM_AFSK2666
- &sm_afsk2666_tx,
-#endif /* CONFIG_SOUNDMODEM_AFSK2666 */
-#ifdef CONFIG_SOUNDMODEM_PSK4800
- &sm_psk4800_tx,
-#endif /* CONFIG_SOUNDMODEM_PSK4800 */
-#ifdef CONFIG_SOUNDMODEM_HAPN4800
- &sm_hapn4800_8_tx,
- &sm_hapn4800_10_tx,
- &sm_hapn4800_pm8_tx,
- &sm_hapn4800_pm10_tx,
-#endif /* CONFIG_SOUNDMODEM_HAPN4800 */
-#ifdef CONFIG_SOUNDMODEM_FSK9600
- &sm_fsk9600_4_tx,
- &sm_fsk9600_5_tx,
-#endif /* CONFIG_SOUNDMODEM_FSK9600 */
- NULL
-};
-
-/*static*/ const struct modem_rx_info *sm_modem_rx_table[] = {
-#ifdef CONFIG_SOUNDMODEM_AFSK1200
- &sm_afsk1200_rx,
-#endif /* CONFIG_SOUNDMODEM_AFSK1200 */
-#ifdef CONFIG_SOUNDMODEM_AFSK2400_7
- &sm_afsk2400_7_rx,
-#endif /* CONFIG_SOUNDMODEM_AFSK2400_7 */
-#ifdef CONFIG_SOUNDMODEM_AFSK2400_8
- &sm_afsk2400_8_rx,
-#endif /* CONFIG_SOUNDMODEM_AFSK2400_8 */
-#ifdef CONFIG_SOUNDMODEM_AFSK2666
- &sm_afsk2666_rx,
-#endif /* CONFIG_SOUNDMODEM_AFSK2666 */
-#ifdef CONFIG_SOUNDMODEM_PSK4800
- &sm_psk4800_rx,
-#endif /* CONFIG_SOUNDMODEM_PSK4800 */
-#ifdef CONFIG_SOUNDMODEM_HAPN4800
- &sm_hapn4800_8_rx,
- &sm_hapn4800_10_rx,
- &sm_hapn4800_pm8_rx,
- &sm_hapn4800_pm10_rx,
-#endif /* CONFIG_SOUNDMODEM_HAPN4800 */
-#ifdef CONFIG_SOUNDMODEM_FSK9600
- &sm_fsk9600_4_rx,
- &sm_fsk9600_5_rx,
-#endif /* CONFIG_SOUNDMODEM_FSK9600 */
- NULL
-};
-
-static const struct hardware_info *sm_hardware_table[] = {
-#ifdef CONFIG_SOUNDMODEM_SBC
- &sm_hw_sbc,
- &sm_hw_sbcfdx,
-#endif /* CONFIG_SOUNDMODEM_SBC */
-#ifdef CONFIG_SOUNDMODEM_WSS
- &sm_hw_wss,
- &sm_hw_wssfdx,
-#endif /* CONFIG_SOUNDMODEM_WSS */
- NULL
-};
-
-/* --------------------------------------------------------------------- */
-
-#define NR_PORTS 4
-
-/* --------------------------------------------------------------------- */
-
-static struct device sm_device[NR_PORTS];
-
-static struct {
- char *mode;
- int iobase, irq, dma, dma2, seriobase, pariobase, midiiobase;
-} sm_ports[NR_PORTS] = {
- { NULL, -1, 0, 0, 0, -1, -1, -1 },
-};
-
-/* --------------------------------------------------------------------- */
-
-#define UART_RBR(iobase) (iobase+0)
-#define UART_THR(iobase) (iobase+0)
-#define UART_IER(iobase) (iobase+1)
-#define UART_IIR(iobase) (iobase+2)
-#define UART_FCR(iobase) (iobase+2)
-#define UART_LCR(iobase) (iobase+3)
-#define UART_MCR(iobase) (iobase+4)
-#define UART_LSR(iobase) (iobase+5)
-#define UART_MSR(iobase) (iobase+6)
-#define UART_SCR(iobase) (iobase+7)
-#define UART_DLL(iobase) (iobase+0)
-#define UART_DLM(iobase) (iobase+1)
-
-#define SER_EXTENT 8
-
-#define LPT_DATA(iobase) (iobase+0)
-#define LPT_STATUS(iobase) (iobase+1)
-#define LPT_CONTROL(iobase) (iobase+2)
-#define LPT_IRQ_ENABLE 0x10
-
-#define LPT_EXTENT 3
-
-#define MIDI_DATA(iobase) (iobase)
-#define MIDI_STATUS(iobase) (iobase+1)
-#define MIDI_READ_FULL 0x80 /* attention: negative logic!! */
-#define MIDI_WRITE_EMPTY 0x40 /* attention: negative logic!! */
-
-#define MIDI_EXTENT 2
-
-/* ---------------------------------------------------------------------- */
-
-#define PARAM_TXDELAY 1
-#define PARAM_PERSIST 2
-#define PARAM_SLOTTIME 3
-#define PARAM_TXTAIL 4
-#define PARAM_FULLDUP 5
-#define PARAM_HARDWARE 6
-#define PARAM_RETURN 255
-
-#define SP_SER 1
-#define SP_PAR 2
-#define SP_MIDI 4
-
-/* --------------------------------------------------------------------- */
-/*
- * ===================== port checking routines ========================
- */
-
-/*
- * returns 0 if ok and != 0 on error;
- * the same behaviour as par96_check_lpt in baycom.c
- */
-
-/*
- * returns 0 if ok and != 0 on error;
- * the same behaviour as par96_check_lpt in baycom.c
- */
-
-static int check_lpt(unsigned int iobase)
-{
- unsigned char b1,b2;
- int i;
-
- if (iobase <= 0 || iobase > 0x1000-LPT_EXTENT)
- return 0;
- if (check_region(iobase, LPT_EXTENT))
- return 0;
- b1 = inb(LPT_DATA(iobase));
- b2 = inb(LPT_CONTROL(iobase));
- outb(0xaa, LPT_DATA(iobase));
- i = inb(LPT_DATA(iobase)) == 0xaa;
- outb(0x55, LPT_DATA(iobase));
- i &= inb(LPT_DATA(iobase)) == 0x55;
- outb(0x0a, LPT_CONTROL(iobase));
- i &= (inb(LPT_CONTROL(iobase)) & 0xf) == 0x0a;
- outb(0x05, LPT_CONTROL(iobase));
- i &= (inb(LPT_CONTROL(iobase)) & 0xf) == 0x05;
- outb(b1, LPT_DATA(iobase));
- outb(b2, LPT_CONTROL(iobase));
- return !i;
-}
-
-/* --------------------------------------------------------------------- */
-
-enum uart { c_uart_unknown, c_uart_8250,
- c_uart_16450, c_uart_16550, c_uart_16550A};
-static const char *uart_str[] =
- { "unknown", "8250", "16450", "16550", "16550A" };
-
-static enum uart check_uart(unsigned int iobase)
-{
- unsigned char b1,b2,b3;
- enum uart u;
- enum uart uart_tab[] =
- { c_uart_16450, c_uart_unknown, c_uart_16550, c_uart_16550A };
-
- if (iobase <= 0 || iobase > 0x1000-SER_EXTENT)
- return c_uart_unknown;
- if (check_region(iobase, SER_EXTENT))
- return c_uart_unknown;
- b1 = inb(UART_MCR(iobase));
- outb(b1 | 0x10, UART_MCR(iobase)); /* loopback mode */
- b2 = inb(UART_MSR(iobase));
- outb(0x1a, UART_MCR(iobase));
- b3 = inb(UART_MSR(iobase)) & 0xf0;
- outb(b1, UART_MCR(iobase)); /* restore old values */
- outb(b2, UART_MSR(iobase));
- if (b3 != 0x90)
- return c_uart_unknown;
- inb(UART_RBR(iobase));
- inb(UART_RBR(iobase));
- outb(0x01, UART_FCR(iobase)); /* enable FIFOs */
- u = uart_tab[(inb(UART_IIR(iobase)) >> 6) & 3];
- if (u == c_uart_16450) {
- outb(0x5a, UART_SCR(iobase));
- b1 = inb(UART_SCR(iobase));
- outb(0xa5, UART_SCR(iobase));
- b2 = inb(UART_SCR(iobase));
- if ((b1 != 0x5a) || (b2 != 0xa5))
- u = c_uart_8250;
- }
- return u;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int check_midi(unsigned int iobase)
-{
- unsigned long timeout;
- unsigned long flags;
- unsigned char b;
-
- if (iobase <= 0 || iobase > 0x1000-MIDI_EXTENT)
- return 0;
- if (check_region(iobase, MIDI_EXTENT))
- return 0;
- timeout = jiffies + (HZ / 100);
- while (inb(MIDI_STATUS(iobase)) & MIDI_WRITE_EMPTY)
- if ((signed)(jiffies - timeout) > 0)
- return 0;
- save_flags(flags);
- cli();
- outb(0xff, MIDI_DATA(iobase));
- b = inb(MIDI_STATUS(iobase));
- restore_flags(flags);
- if (!(b & MIDI_WRITE_EMPTY))
- return 0;
- while (inb(MIDI_STATUS(iobase)) & MIDI_WRITE_EMPTY)
- if ((signed)(jiffies - timeout) > 0)
- return 0;
- return 1;
-}
-
-/* --------------------------------------------------------------------- */
-
-void sm_output_status(struct sm_state *sm)
-{
- int invert_dcd = 0;
- int invert_ptt = 0;
-
- int ptt = /*hdlcdrv_ptt(&sm->hdrv)*/(sm->dma.ptt_cnt > 0) ^ invert_ptt;
- int dcd = (!!sm->hdrv.hdlcrx.dcd) ^ invert_dcd;
-
- if (sm->hdrv.ptt_out.flags & SP_SER) {
- outb(dcd | (ptt << 1), UART_MCR(sm->hdrv.ptt_out.seriobase));
- outb(0x40 & (-ptt), UART_LCR(sm->hdrv.ptt_out.seriobase));
- }
- if (sm->hdrv.ptt_out.flags & SP_PAR) {
- outb(ptt | (dcd << 1), LPT_DATA(sm->hdrv.ptt_out.pariobase));
- }
- if (sm->hdrv.ptt_out.flags & SP_MIDI && hdlcdrv_ptt(&sm->hdrv)) {
- outb(0, MIDI_DATA(sm->hdrv.ptt_out.midiiobase));
- }
-}
-
-/* --------------------------------------------------------------------- */
-
-static void sm_output_open(struct sm_state *sm)
-{
- enum uart u = c_uart_unknown;
-
- sm->hdrv.ptt_out.flags = 0;
- if (sm->hdrv.ptt_out.seriobase > 0 &&
- sm->hdrv.ptt_out.seriobase <= 0x1000-SER_EXTENT &&
- ((u = check_uart(sm->hdrv.ptt_out.seriobase))) != c_uart_unknown) {
- sm->hdrv.ptt_out.flags |= SP_SER;
- request_region(sm->hdrv.ptt_out.seriobase, SER_EXTENT, "sm ser ptt");
- outb(0, UART_IER(sm->hdrv.ptt_out.seriobase));
- /* 5 bits, 1 stop, no parity, no break, Div latch access */
- outb(0x80, UART_LCR(sm->hdrv.ptt_out.seriobase));
- outb(0, UART_DLM(sm->hdrv.ptt_out.seriobase));
- outb(1, UART_DLL(sm->hdrv.ptt_out.seriobase)); /* as fast as possible */
- /* LCR and MCR set by output_status */
- }
- if (sm->hdrv.ptt_out.pariobase > 0 &&
- sm->hdrv.ptt_out.pariobase <= 0x1000-LPT_EXTENT &&
- !check_lpt(sm->hdrv.ptt_out.pariobase)) {
- sm->hdrv.ptt_out.flags |= SP_PAR;
- request_region(sm->hdrv.ptt_out.pariobase, LPT_EXTENT, "sm par ptt");
- }
- if (sm->hdrv.ptt_out.midiiobase > 0 &&
- sm->hdrv.ptt_out.midiiobase <= 0x1000-MIDI_EXTENT &&
- check_midi(sm->hdrv.ptt_out.midiiobase)) {
- sm->hdrv.ptt_out.flags |= SP_MIDI;
- request_region(sm->hdrv.ptt_out.midiiobase, MIDI_EXTENT,
- "sm midi ptt");
- }
- sm_output_status(sm);
-
- printk(KERN_INFO "%s: ptt output:", sm_drvname);
- if (sm->hdrv.ptt_out.flags & SP_SER)
- printk(" serial interface at 0x%x, uart %s", sm->hdrv.ptt_out.seriobase,
- uart_str[u]);
- if (sm->hdrv.ptt_out.flags & SP_PAR)
- printk(" parallel interface at 0x%x", sm->hdrv.ptt_out.pariobase);
- if (sm->hdrv.ptt_out.flags & SP_MIDI)
- printk(" mpu401 (midi) interface at 0x%x", sm->hdrv.ptt_out.midiiobase);
- if (!sm->hdrv.ptt_out.flags)
- printk(" none");
- printk("\n");
-}
-
-/* --------------------------------------------------------------------- */
-
-static void sm_output_close(struct sm_state *sm)
-{
- /* release regions used for PTT output */
- sm->hdrv.hdlctx.ptt = sm->hdrv.hdlctx.calibrate = 0;
- sm_output_status(sm);
- if (sm->hdrv.ptt_out.flags & SP_SER)
- release_region(sm->hdrv.ptt_out.seriobase, SER_EXTENT);
- if (sm->hdrv.ptt_out.flags & SP_PAR)
- release_region(sm->hdrv.ptt_out.pariobase, LPT_EXTENT);
- if (sm->hdrv.ptt_out.flags & SP_MIDI)
- release_region(sm->hdrv.ptt_out.midiiobase, MIDI_EXTENT);
- sm->hdrv.ptt_out.flags = 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int sm_open(struct device *dev);
-static int sm_close(struct device *dev);
-static int sm_ioctl(struct device *dev, struct ifreq *ifr,
- struct hdlcdrv_ioctl *hi, int cmd);
-
-/* --------------------------------------------------------------------- */
-
-static const struct hdlcdrv_ops sm_ops = {
- sm_drvname, sm_drvinfo, sm_open, sm_close, sm_ioctl
-};
-
-/* --------------------------------------------------------------------- */
-
-static int sm_open(struct device *dev)
-{
- struct sm_state *sm;
- int err;
-
- if (!dev || !dev->priv ||
- ((struct sm_state *)dev->priv)->hdrv.magic != HDLCDRV_MAGIC) {
- printk(KERN_ERR "sm_open: invalid device struct\n");
- return -EINVAL;
- }
- sm = (struct sm_state *)dev->priv;
-
- if (!sm->mode_tx || !sm->mode_rx || !sm->hwdrv || !sm->hwdrv->open)
- return -ENODEV;
- sm->hdrv.par.bitrate = sm->mode_rx->bitrate;
- err = sm->hwdrv->open(dev, sm);
- if (err)
- return err;
- sm_output_open(sm);
- MOD_INC_USE_COUNT;
- printk(KERN_INFO "%s: %s mode %s.%s at iobase 0x%lx irq %u dma %u dma2 %u\n",
- sm_drvname, sm->hwdrv->hw_name, sm->mode_tx->name,
- sm->mode_rx->name, dev->base_addr, dev->irq, dev->dma, sm->hdrv.ptt_out.dma2);
- return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int sm_close(struct device *dev)
-{
- struct sm_state *sm;
- int err = -ENODEV;
-
- if (!dev || !dev->priv ||
- ((struct sm_state *)dev->priv)->hdrv.magic != HDLCDRV_MAGIC) {
- printk(KERN_ERR "sm_close: invalid device struct\n");
- return -EINVAL;
- }
- sm = (struct sm_state *)dev->priv;
-
-
- if (sm->hwdrv && sm->hwdrv->close)
- err = sm->hwdrv && sm->hwdrv->close(dev, sm);
- sm_output_close(sm);
- MOD_DEC_USE_COUNT;
- printk(KERN_INFO "%s: close %s at iobase 0x%lx irq %u dma %u\n",
- sm_drvname, sm->hwdrv->hw_name, dev->base_addr, dev->irq, dev->dma);
- return err;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int sethw(struct device *dev, struct sm_state *sm, char *mode)
-{
- char *cp = strchr(mode, ':');
- const struct hardware_info **hwp = sm_hardware_table;
-
- if (!cp)
- cp = mode;
- else {
- *cp++ = '\0';
- while (hwp && (*hwp) && (*hwp)->hw_name && strcmp((*hwp)->hw_name, mode))
- hwp++;
- if (!hwp || !*hwp || !(*hwp)->hw_name)
- return -EINVAL;
- if ((*hwp)->loc_storage > sizeof(sm->hw)) {
- printk(KERN_ERR "%s: insufficient storage for hw driver %s (%d)\n",
- sm_drvname, (*hwp)->hw_name, (*hwp)->loc_storage);
- return -EINVAL;
- }
- sm->hwdrv = *hwp;
- }
- if (!*cp)
- return 0;
- if (sm->hwdrv && sm->hwdrv->sethw)
- return sm->hwdrv->sethw(dev, sm, cp);
- return -EINVAL;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int sm_ioctl(struct device *dev, struct ifreq *ifr,
- struct hdlcdrv_ioctl *hi, int cmd)
-{
- struct sm_state *sm;
- struct sm_ioctl bi;
- unsigned long flags;
- unsigned int newdiagmode;
- unsigned int newdiagflags;
- char *cp;
- const struct modem_tx_info **mtp = sm_modem_tx_table;
- const struct modem_rx_info **mrp = sm_modem_rx_table;
- const struct hardware_info **hwp = sm_hardware_table;
-
- if (!dev || !dev->priv ||
- ((struct sm_state *)dev->priv)->hdrv.magic != HDLCDRV_MAGIC) {
- printk(KERN_ERR "sm_ioctl: invalid device struct\n");
- return -EINVAL;
- }
- sm = (struct sm_state *)dev->priv;
-
- if (cmd != SIOCDEVPRIVATE) {
- if (!sm->hwdrv || !sm->hwdrv->ioctl)
- return sm->hwdrv->ioctl(dev, sm, ifr, hi, cmd);
- return -ENOIOCTLCMD;
- }
- switch (hi->cmd) {
- default:
- if (sm->hwdrv && sm->hwdrv->ioctl)
- return sm->hwdrv->ioctl(dev, sm, ifr, hi, cmd);
- return -ENOIOCTLCMD;
-
- case HDLCDRVCTL_GETMODE:
- cp = hi->data.modename;
- if (sm->hwdrv && sm->hwdrv->hw_name)
- cp += sprintf(cp, "%s:", sm->hwdrv->hw_name);
- else
- cp += sprintf(cp, "<unspec>:");
- if (sm->mode_tx && sm->mode_tx->name)
- cp += sprintf(cp, "%s", sm->mode_tx->name);
- else
- cp += sprintf(cp, "<unspec>");
- if (!sm->mode_rx || !sm->mode_rx ||
- strcmp(sm->mode_rx->name, sm->mode_tx->name)) {
- if (sm->mode_rx && sm->mode_rx->name)
- cp += sprintf(cp, ",%s", sm->mode_rx->name);
- else
- cp += sprintf(cp, ",<unspec>");
- }
- if (copy_to_user(ifr->ifr_data, hi, sizeof(*hi)))
- return -EFAULT;
- return 0;
-
- case HDLCDRVCTL_SETMODE:
- if (!suser() || dev->start)
- return -EACCES;
- hi->data.modename[sizeof(hi->data.modename)-1] = '\0';
- return sethw(dev, sm, hi->data.modename);
-
- case HDLCDRVCTL_MODELIST:
- cp = hi->data.modename;
- while (*hwp) {
- if ((*hwp)->hw_name)
- cp += sprintf("%s:,", (*hwp)->hw_name);
- hwp++;
- }
- while (*mtp) {
- if ((*mtp)->name)
- cp += sprintf(">%s,", (*mtp)->name);
- mtp++;
- }
- while (*mrp) {
- if ((*mrp)->name)
- cp += sprintf("<%s,", (*mrp)->name);
- mrp++;
- }
- cp[-1] = '\0';
- if (copy_to_user(ifr->ifr_data, hi, sizeof(*hi)))
- return -EFAULT;
- return 0;
-
-#ifdef SM_DEBUG
- case SMCTL_GETDEBUG:
- if (copy_from_user(&bi, ifr->ifr_data, sizeof(bi)))
- return -EFAULT;
- bi.data.dbg.int_rate = sm->debug_vals.last_intcnt;
- bi.data.dbg.mod_cycles = sm->debug_vals.mod_cyc;
- bi.data.dbg.demod_cycles = sm->debug_vals.demod_cyc;
- bi.data.dbg.dma_residue = sm->debug_vals.dma_residue;
- sm->debug_vals.mod_cyc = sm->debug_vals.demod_cyc =
- sm->debug_vals.dma_residue = 0;
- if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi)))
- return -EFAULT;
- return 0;
-#endif /* SM_DEBUG */
-
- case SMCTL_DIAGNOSE:
- if (copy_from_user(&bi, ifr->ifr_data, sizeof(bi)))
- return -EFAULT;
- newdiagmode = bi.data.diag.mode;
- newdiagflags = bi.data.diag.flags;
- if (newdiagmode > SM_DIAGMODE_CONSTELLATION)
- return -EINVAL;
- bi.data.diag.mode = sm->diag.mode;
- bi.data.diag.flags = sm->diag.flags;
- bi.data.diag.samplesperbit = sm->mode_rx->sperbit;
- if (sm->diag.mode != newdiagmode) {
- save_flags(flags);
- cli();
- sm->diag.ptr = -1;
- sm->diag.flags = newdiagflags & ~SM_DIAGFLAG_VALID;
- sm->diag.mode = newdiagmode;
- restore_flags(flags);
- if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi)))
- return -EFAULT;
- return 0;
- }
- if (sm->diag.ptr < 0 || sm->diag.mode == SM_DIAGMODE_OFF) {
- if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi)))
- return -EFAULT;
- return 0;
- }
- if (bi.data.diag.datalen > DIAGDATALEN)
- bi.data.diag.datalen = DIAGDATALEN;
- if (sm->diag.ptr < bi.data.diag.datalen) {
- if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi)))
- return -EFAULT;
- return 0;
- }
- if (copy_to_user(bi.data.diag.data, sm->diag.data,
- bi.data.diag.datalen * sizeof(short)))
- return -EFAULT;
- bi.data.diag.flags |= SM_DIAGFLAG_VALID;
- save_flags(flags);
- cli();
- sm->diag.ptr = -1;
- sm->diag.flags = newdiagflags & ~SM_DIAGFLAG_VALID;
- sm->diag.mode = newdiagmode;
- restore_flags(flags);
- if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi)))
- return -EFAULT;
- return 0;
- }
-}
-
-/* --------------------------------------------------------------------- */
-
-#ifdef __i386__
-
-int sm_x86_capability = 0;
-
-__initfunc(static void i386_capability(void))
-{
- unsigned long flags;
- unsigned long fl1;
- union {
- struct {
- unsigned int ebx, edx, ecx;
- } r;
- unsigned char s[13];
- } id;
- unsigned int eax;
-
- save_flags(flags);
- flags |= 0x200000;
- restore_flags(flags);
- save_flags(flags);
- fl1 = flags;
- flags &= ~0x200000;
- restore_flags(flags);
- save_flags(flags);
- if (!(fl1 & 0x200000) || (flags & 0x200000)) {
- printk(KERN_WARNING "%s: cpu does not support CPUID\n", sm_drvname);
- return;
- }
- __asm__ ("cpuid" : "=a" (eax), "=b" (id.r.ebx), "=c" (id.r.ecx), "=d" (id.r.edx) :
- "0" (0));
- id.s[12] = 0;
- if (eax < 1) {
- printk(KERN_WARNING "%s: cpu (vendor string %s) does not support capability "
- "list\n", sm_drvname, id.s);
- return;
- }
- printk(KERN_INFO "%s: cpu: vendor string %s ", sm_drvname, id.s);
- __asm__ ("cpuid" : "=a" (eax), "=d" (sm_x86_capability) : "0" (1) : "ebx", "ecx");
- printk("fam %d mdl %d step %d cap 0x%x\n", (eax >> 8) & 15, (eax >> 4) & 15,
- eax & 15, sm_x86_capability);
-}
-#endif /* __i386__ */
-
-/* --------------------------------------------------------------------- */
-
-#ifdef MODULE
-__initfunc(static int sm_init(void))
-#else /* MODULE */
-__initfunc(int sm_init(void))
-#endif /* MODULE */
-{
- int i, j, found = 0;
- char set_hw = 1;
- struct sm_state *sm;
- char ifname[HDLCDRV_IFNAMELEN];
-
- printk(sm_drvinfo);
-#ifdef __i386__
- i386_capability();
-#endif /* __i386__ */
- /*
- * register net devices
- */
- for (i = 0; i < NR_PORTS; i++) {
- struct device *dev = sm_device+i;
- sprintf(ifname, "sm%d", i);
-
- if (!sm_ports[i].mode)
- set_hw = 0;
- if (!set_hw)
- sm_ports[i].iobase = sm_ports[i].irq = 0;
- j = hdlcdrv_register_hdlcdrv(dev, &sm_ops, sizeof(struct sm_state),
- ifname, sm_ports[i].iobase,
- sm_ports[i].irq, sm_ports[i].dma);
- if (!j) {
- sm = (struct sm_state *)dev->priv;
- sm->hdrv.ptt_out.dma2 = sm_ports[i].dma2;
- sm->hdrv.ptt_out.seriobase = sm_ports[i].seriobase;
- sm->hdrv.ptt_out.pariobase = sm_ports[i].pariobase;
- sm->hdrv.ptt_out.midiiobase = sm_ports[i].midiiobase;
- if (set_hw && sethw(dev, sm, sm_ports[i].mode))
- set_hw = 0;
- found++;
- } else {
- printk(KERN_WARNING "%s: cannot register net device\n",
- sm_drvname);
- }
- }
- if (!found)
- return -ENXIO;
- return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-#ifdef MODULE
-
-/*
- * command line settable parameters
- */
-static char *mode = NULL;
-static int iobase = -1;
-static int irq = -1;
-static int dma = -1;
-static int dma2 = -1;
-static int serio = 0;
-static int pario = 0;
-static int midiio = 0;
-
-#if LINUX_VERSION_CODE >= 0x20115
-
-MODULE_PARM(mode, "s");
-MODULE_PARM_DESC(mode, "soundmodem operating mode; eg. sbc:afsk1200 or wss:fsk9600");
-MODULE_PARM(iobase, "i");
-MODULE_PARM_DESC(iobase, "soundmodem base address");
-MODULE_PARM(irq, "i");
-MODULE_PARM_DESC(irq, "soundmodem interrupt");
-MODULE_PARM(dma, "i");
-MODULE_PARM_DESC(dma, "soundmodem dma channel");
-MODULE_PARM(dma2, "i");
-MODULE_PARM_DESC(dma2, "soundmodem 2nd dma channel; full duplex only");
-MODULE_PARM(serio, "i");
-MODULE_PARM_DESC(serio, "soundmodem PTT output on serial port");
-MODULE_PARM(pario, "i");
-MODULE_PARM_DESC(pario, "soundmodem PTT output on parallel port");
-MODULE_PARM(midiio, "i");
-MODULE_PARM_DESC(midiio, "soundmodem PTT output on midi port");
-
-MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");
-MODULE_DESCRIPTION("Soundcard amateur radio modem driver");
-
-#endif
-
-__initfunc(int init_module(void))
-{
- if (mode) {
- if (iobase == -1)
- iobase = (!strncmp(mode, "sbc", 3)) ? 0x220 : 0x530;
- if (irq == -1)
- irq = (!strncmp(mode, "sbc", 3)) ? 5 : 11;
- if (dma == -1)
- dma = 1;
- }
- sm_ports[0].mode = mode;
- sm_ports[0].iobase = iobase;
- sm_ports[0].irq = irq;
- sm_ports[0].dma = dma;
- sm_ports[0].dma2 = dma2;
- sm_ports[0].seriobase = serio;
- sm_ports[0].pariobase = pario;
- sm_ports[0].midiiobase = midiio;
- sm_ports[1].mode = NULL;
-
- return sm_init();
-}
-
-/* --------------------------------------------------------------------- */
-
-void cleanup_module(void)
-{
- int i;
-
- printk(KERN_INFO "sm: cleanup_module called\n");
-
- for(i = 0; i < NR_PORTS; i++) {
- struct device *dev = sm_device+i;
- struct sm_state *sm = (struct sm_state *)dev->priv;
-
- if (sm) {
- if (sm->hdrv.magic != HDLCDRV_MAGIC)
- printk(KERN_ERR "sm: invalid magic in "
- "cleanup_module\n");
- else
- hdlcdrv_unregister_hdlcdrv(dev);
- }
- }
-}
-
-#else /* MODULE */
-/* --------------------------------------------------------------------- */
-/*
- * format: sm=io,irq,dma[,dma2[,serio[,pario]]],mode
- * mode: hw:modem
- * hw: sbc, wss, wssfdx
- * modem: afsk1200, fsk9600
- */
-
-__initfunc(void sm_setup(char *str, int *ints))
-{
- int i;
-
- for (i = 0; (i < NR_PORTS) && (sm_ports[i].mode); i++);
- if ((i >= NR_PORTS) || (ints[0] < 3)) {
- printk(KERN_INFO "%s: too many or invalid interface "
- "specifications\n", sm_drvname);
- return;
- }
- sm_ports[i].mode = str;
- sm_ports[i].iobase = ints[1];
- sm_ports[i].irq = ints[2];
- sm_ports[i].dma = ints[3];
- sm_ports[i].dma2 = (ints[0] >= 4) ? ints[4] : 0;
- sm_ports[i].seriobase = (ints[0] >= 5) ? ints[5] : 0;
- sm_ports[i].pariobase = (ints[0] >= 6) ? ints[6] : 0;
- sm_ports[i].midiiobase = (ints[0] >= 7) ? ints[7] : 0;
- if (i < NR_PORTS-1)
- sm_ports[i+1].mode = NULL;
-}
-
-#endif /* MODULE */
-/* --------------------------------------------------------------------- */
diff --git a/drivers/net/soundmodem/sm.h b/drivers/net/soundmodem/sm.h
index 25bbc8ba9..e69de29bb 100644
--- a/drivers/net/soundmodem/sm.h
+++ b/drivers/net/soundmodem/sm.h
@@ -1,382 +0,0 @@
-/*****************************************************************************/
-
-/*
- * sm.h -- soundcard radio modem driver internal header.
- *
- * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Please note that the GPL allows you to use the driver, NOT the radio.
- * In order to use the radio, you need a license from the communications
- * authority of your country.
- *
- */
-
-#ifndef _SM_H
-#define _SM_H
-
-/* ---------------------------------------------------------------------- */
-
-#include <linux/hdlcdrv.h>
-#include <linux/soundmodem.h>
-
-#define SM_DEBUG
-
-/* ---------------------------------------------------------------------- */
-/*
- * Information that need to be kept for each board.
- */
-
-struct sm_state {
- struct hdlcdrv_state hdrv;
-
- const struct modem_tx_info *mode_tx;
- const struct modem_rx_info *mode_rx;
-
- const struct hardware_info *hwdrv;
-
- /*
- * Hardware (soundcard) access routines state
- */
- struct {
- void *ibuf;
- unsigned int ifragsz;
- unsigned int ifragptr;
- unsigned int i16bit;
- void *obuf;
- unsigned int ofragsz;
- unsigned int ofragptr;
- unsigned int o16bit;
- int ptt_cnt;
- } dma;
-
- union {
- long hw[32/sizeof(long)];
- } hw;
-
- /*
- * state of the modem code
- */
- union {
- long m[32/sizeof(long)];
- } m;
- union {
- long d[256/sizeof(long)];
- } d;
-
-#define DIAGDATALEN 64
- struct diag_data {
- unsigned int mode;
- unsigned int flags;
- volatile int ptr;
- short data[DIAGDATALEN];
- } diag;
-
-
-#ifdef SM_DEBUG
- struct debug_vals {
- unsigned long last_jiffies;
- unsigned cur_intcnt;
- unsigned last_intcnt;
- unsigned mod_cyc;
- unsigned demod_cyc;
- unsigned dma_residue;
- } debug_vals;
-#endif /* SM_DEBUG */
-};
-
-/* ---------------------------------------------------------------------- */
-/*
- * Mode definition structure
- */
-
-struct modem_tx_info {
- const char *name;
- unsigned int loc_storage;
- int srate;
- int bitrate;
- void (*modulator_u8)(struct sm_state *, unsigned char *, unsigned int);
- void (*modulator_s16)(struct sm_state *, short *, unsigned int);
- void (*init)(struct sm_state *);
-};
-
-struct modem_rx_info {
- const char *name;
- unsigned int loc_storage;
- int srate;
- int bitrate;
- unsigned int overlap;
- unsigned int sperbit;
- void (*demodulator_u8)(struct sm_state *, const unsigned char *, unsigned int);
- void (*demodulator_s16)(struct sm_state *, const short *, unsigned int);
- void (*init)(struct sm_state *);
-};
-
-/* ---------------------------------------------------------------------- */
-/*
- * Soundcard driver definition structure
- */
-
-struct hardware_info {
- char *hw_name; /* used for request_{region,irq,dma} */
- unsigned int loc_storage;
- /*
- * mode specific open/close
- */
- int (*open)(struct device *, struct sm_state *);
- int (*close)(struct device *, struct sm_state *);
- int (*ioctl)(struct device *, struct sm_state *, struct ifreq *,
- struct hdlcdrv_ioctl *, int);
- int (*sethw)(struct device *, struct sm_state *, char *);
-};
-
-/* --------------------------------------------------------------------- */
-
-#define min(a, b) (((a) < (b)) ? (a) : (b))
-#define max(a, b) (((a) > (b)) ? (a) : (b))
-
-/* --------------------------------------------------------------------- */
-
-extern const char sm_drvname[];
-extern const char sm_drvinfo[];
-
-/* --------------------------------------------------------------------- */
-/*
- * ===================== diagnostics stuff ===============================
- */
-
-extern inline void diag_trigger(struct sm_state *sm)
-{
- if (sm->diag.ptr < 0)
- if (!(sm->diag.flags & SM_DIAGFLAG_DCDGATE) || sm->hdrv.hdlcrx.dcd)
- sm->diag.ptr = 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-#define SHRT_MAX ((short)(((unsigned short)(~0U))>>1))
-#define SHRT_MIN (-SHRT_MAX-1)
-
-extern inline void diag_add(struct sm_state *sm, int valinp, int valdemod)
-{
- int val;
-
- if ((sm->diag.mode != SM_DIAGMODE_INPUT &&
- sm->diag.mode != SM_DIAGMODE_DEMOD) ||
- sm->diag.ptr >= DIAGDATALEN || sm->diag.ptr < 0)
- return;
- val = (sm->diag.mode == SM_DIAGMODE_DEMOD) ? valdemod : valinp;
- /* clip */
- if (val > SHRT_MAX)
- val = SHRT_MAX;
- if (val < SHRT_MIN)
- val = SHRT_MIN;
- sm->diag.data[sm->diag.ptr++] = val;
-}
-
-/* --------------------------------------------------------------------- */
-
-extern inline void diag_add_one(struct sm_state *sm, int val)
-{
- if ((sm->diag.mode != SM_DIAGMODE_INPUT &&
- sm->diag.mode != SM_DIAGMODE_DEMOD) ||
- sm->diag.ptr >= DIAGDATALEN || sm->diag.ptr < 0)
- return;
- /* clip */
- if (val > SHRT_MAX)
- val = SHRT_MAX;
- if (val < SHRT_MIN)
- val = SHRT_MIN;
- sm->diag.data[sm->diag.ptr++] = val;
-}
-
-/* --------------------------------------------------------------------- */
-
-static inline void diag_add_constellation(struct sm_state *sm, int vali, int valq)
-{
- if ((sm->diag.mode != SM_DIAGMODE_CONSTELLATION) ||
- sm->diag.ptr >= DIAGDATALEN-1 || sm->diag.ptr < 0)
- return;
- /* clip */
- if (vali > SHRT_MAX)
- vali = SHRT_MAX;
- if (vali < SHRT_MIN)
- vali = SHRT_MIN;
- if (valq > SHRT_MAX)
- valq = SHRT_MAX;
- if (valq < SHRT_MIN)
- valq = SHRT_MIN;
- sm->diag.data[sm->diag.ptr++] = vali;
- sm->diag.data[sm->diag.ptr++] = valq;
-}
-
-/* --------------------------------------------------------------------- */
-/*
- * ===================== utility functions ===============================
- */
-
-extern inline unsigned int hweight32(unsigned int w)
- __attribute__ ((unused));
-extern inline unsigned int hweight16(unsigned short w)
- __attribute__ ((unused));
-extern inline unsigned int hweight8(unsigned char w)
- __attribute__ ((unused));
-
-extern inline unsigned int hweight32(unsigned int w)
-{
- unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555);
- res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
- res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F);
- res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF);
- return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF);
-}
-
-extern inline unsigned int hweight16(unsigned short w)
-{
- unsigned short res = (w & 0x5555) + ((w >> 1) & 0x5555);
- res = (res & 0x3333) + ((res >> 2) & 0x3333);
- res = (res & 0x0F0F) + ((res >> 4) & 0x0F0F);
- return (res & 0x00FF) + ((res >> 8) & 0x00FF);
-}
-
-extern inline unsigned int hweight8(unsigned char w)
-{
- unsigned short res = (w & 0x55) + ((w >> 1) & 0x55);
- res = (res & 0x33) + ((res >> 2) & 0x33);
- return (res & 0x0F) + ((res >> 4) & 0x0F);
-}
-
-extern inline unsigned int gcd(unsigned int x, unsigned int y)
- __attribute__ ((unused));
-extern inline unsigned int lcm(unsigned int x, unsigned int y)
- __attribute__ ((unused));
-
-extern inline unsigned int gcd(unsigned int x, unsigned int y)
-{
- for (;;) {
- if (!x)
- return y;
- if (!y)
- return x;
- if (x > y)
- x %= y;
- else
- y %= x;
- }
-}
-
-extern inline unsigned int lcm(unsigned int x, unsigned int y)
-{
- return x * y / gcd(x, y);
-}
-
-/* --------------------------------------------------------------------- */
-/*
- * ===================== profiling =======================================
- */
-
-
-#ifdef __i386__
-
-extern int sm_x86_capability;
-
-#define HAS_RDTSC (sm_x86_capability & 0x10)
-
-/*
- * only do 32bit cycle counter arithmetic; we hope we won't overflow :-)
- * in fact, overflowing modems would require over 2THz clock speeds :-)
- */
-
-#define time_exec(var,cmd) \
-({ \
- if (HAS_RDTSC) { \
- unsigned int cnt1, cnt2, cnt3; \
- __asm__(".byte 0x0f,0x31" : "=a" (cnt1), "=d" (cnt3)); \
- cmd; \
- __asm__(".byte 0x0f,0x31" : "=a" (cnt2), "=d" (cnt3)); \
- var = cnt2-cnt1; \
- } else { \
- cmd; \
- } \
-})
-
-#else /* __i386__ */
-
-#define time_exec(var,cmd) cmd
-
-#endif /* __i386__ */
-
-/* --------------------------------------------------------------------- */
-
-extern const struct modem_tx_info sm_afsk1200_tx;
-extern const struct modem_tx_info sm_afsk2400_7_tx;
-extern const struct modem_tx_info sm_afsk2400_8_tx;
-extern const struct modem_tx_info sm_afsk2666_tx;
-extern const struct modem_tx_info sm_psk4800_tx;
-extern const struct modem_tx_info sm_hapn4800_8_tx;
-extern const struct modem_tx_info sm_hapn4800_10_tx;
-extern const struct modem_tx_info sm_hapn4800_pm8_tx;
-extern const struct modem_tx_info sm_hapn4800_pm10_tx;
-extern const struct modem_tx_info sm_fsk9600_4_tx;
-extern const struct modem_tx_info sm_fsk9600_5_tx;
-
-extern const struct modem_rx_info sm_afsk1200_rx;
-extern const struct modem_rx_info sm_afsk2400_7_rx;
-extern const struct modem_rx_info sm_afsk2400_8_rx;
-extern const struct modem_rx_info sm_afsk2666_rx;
-extern const struct modem_rx_info sm_psk4800_rx;
-extern const struct modem_rx_info sm_hapn4800_8_rx;
-extern const struct modem_rx_info sm_hapn4800_10_rx;
-extern const struct modem_rx_info sm_hapn4800_pm8_rx;
-extern const struct modem_rx_info sm_hapn4800_pm10_rx;
-extern const struct modem_rx_info sm_fsk9600_4_rx;
-extern const struct modem_rx_info sm_fsk9600_5_rx;
-
-extern const struct hardware_info sm_hw_sbc;
-extern const struct hardware_info sm_hw_sbcfdx;
-extern const struct hardware_info sm_hw_wss;
-extern const struct hardware_info sm_hw_wssfdx;
-
-extern const struct modem_tx_info *sm_modem_tx_table[];
-extern const struct modem_rx_info *sm_modem_rx_table[];
-extern const struct hardware_info *sm_hardware_table[];
-
-/* --------------------------------------------------------------------- */
-
-void sm_output_status(struct sm_state *sm);
-/*void sm_output_open(struct sm_state *sm);*/
-/*void sm_output_close(struct sm_state *sm);*/
-
-/* --------------------------------------------------------------------- */
-
-extern void inline sm_int_freq(struct sm_state *sm)
-{
-#ifdef SM_DEBUG
- unsigned long cur_jiffies = jiffies;
- /*
- * measure the interrupt frequency
- */
- sm->debug_vals.cur_intcnt++;
- if ((cur_jiffies - sm->debug_vals.last_jiffies) >= HZ) {
- sm->debug_vals.last_jiffies = cur_jiffies;
- sm->debug_vals.last_intcnt = sm->debug_vals.cur_intcnt;
- sm->debug_vals.cur_intcnt = 0;
- }
-#endif /* SM_DEBUG */
-}
-
-/* --------------------------------------------------------------------- */
-#endif /* _SM_H */
diff --git a/drivers/net/soundmodem/sm_afsk1200.c b/drivers/net/soundmodem/sm_afsk1200.c
index 64b20a57c..e69de29bb 100644
--- a/drivers/net/soundmodem/sm_afsk1200.c
+++ b/drivers/net/soundmodem/sm_afsk1200.c
@@ -1,272 +0,0 @@
-/*****************************************************************************/
-
-/*
- * sm_afsk1200.c -- soundcard radio modem driver, 1200 baud AFSK modem
- *
- * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Please note that the GPL allows you to use the driver, NOT the radio.
- * In order to use the radio, you need a license from the communications
- * authority of your country.
- *
- */
-
-#include "sm.h"
-#include "sm_tbl_afsk1200.h"
-
-/* --------------------------------------------------------------------- */
-
-struct demod_state_afsk12 {
- unsigned int shreg;
- unsigned int bit_pll;
- unsigned char last_sample;
- unsigned int dcd_shreg;
- int dcd_sum0, dcd_sum1, dcd_sum2;
- unsigned int dcd_time;
- unsigned char last_rxbit;
-};
-
-struct mod_state_afsk12 {
- unsigned int shreg;
- unsigned char tx_bit;
- unsigned int bit_pll;
- unsigned int dds_inc;
- unsigned int txphase;
-};
-
-/* --------------------------------------------------------------------- */
-
-static const int dds_inc[2] = {
- AFSK12_TX_FREQ_LO*0x10000/AFSK12_SAMPLE_RATE,
- AFSK12_TX_FREQ_HI*0x10000/AFSK12_SAMPLE_RATE
-};
-
-static void modulator_1200_u8(struct sm_state *sm, unsigned char *buf,
- unsigned int buflen)
-{
- struct mod_state_afsk12 *st = (struct mod_state_afsk12 *)(&sm->m);
-
- for (; buflen > 0; buflen--) {
- if (!((st->txphase++) & 7)) {
- if (st->shreg <= 1)
- st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
- st->tx_bit = (st->tx_bit ^ (!(st->shreg & 1))) & 1;
- st->shreg >>= 1;
- }
- st->dds_inc = dds_inc[st->tx_bit & 1];
- *buf++ = OFFSCOS(st->bit_pll);
- st->bit_pll += st->dds_inc;
- }
-}
-
-/* --------------------------------------------------------------------- */
-
-static void modulator_1200_s16(struct sm_state *sm, short *buf, unsigned int buflen)
-{
- struct mod_state_afsk12 *st = (struct mod_state_afsk12 *)(&sm->m);
-
- for (; buflen > 0; buflen--) {
- if (!((st->txphase++) & 7)) {
- if (st->shreg <= 1)
- st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
- st->tx_bit = (st->tx_bit ^ (!(st->shreg & 1))) & 1;
- st->shreg >>= 1;
- }
- st->dds_inc = dds_inc[st->tx_bit & 1];
- *buf++ = COS(st->bit_pll);
- st->bit_pll += st->dds_inc;
- }
-}
-
-/* --------------------------------------------------------------------- */
-
-extern __inline__ int convolution8_u8(const unsigned char *st, const int *coeff, int csum)
-{
- int sum = -0x80 * csum;
-
- sum += (st[0] * coeff[0]);
- sum += (st[-1] * coeff[1]);
- sum += (st[-2] * coeff[2]);
- sum += (st[-3] * coeff[3]);
- sum += (st[-4] * coeff[4]);
- sum += (st[-5] * coeff[5]);
- sum += (st[-6] * coeff[6]);
- sum += (st[-7] * coeff[7]);
-
- sum >>= 7;
- return sum * sum;
-}
-
-extern __inline__ int convolution8_s16(const short *st, const int *coeff, int csum)
-{
- int sum = 0;
-
- sum += (st[0] * coeff[0]);
- sum += (st[-1] * coeff[1]);
- sum += (st[-2] * coeff[2]);
- sum += (st[-3] * coeff[3]);
- sum += (st[-4] * coeff[4]);
- sum += (st[-5] * coeff[5]);
- sum += (st[-6] * coeff[6]);
- sum += (st[-7] * coeff[7]);
-
- sum >>= 15;
- return sum * sum;
-}
-
-extern __inline__ int do_filter_1200_u8(const unsigned char *buf)
-{
- int sum = convolution8_u8(buf, afsk12_tx_lo_i, SUM_AFSK12_TX_LO_I);
- sum += convolution8_u8(buf, afsk12_tx_lo_q, SUM_AFSK12_TX_LO_Q);
- sum -= convolution8_u8(buf, afsk12_tx_hi_i, SUM_AFSK12_TX_HI_I);
- sum -= convolution8_u8(buf, afsk12_tx_hi_q, SUM_AFSK12_TX_HI_Q);
- return sum;
-}
-
-extern __inline__ int do_filter_1200_s16(const short *buf)
-{
- int sum = convolution8_s16(buf, afsk12_tx_lo_i, SUM_AFSK12_TX_LO_I);
- sum += convolution8_s16(buf, afsk12_tx_lo_q, SUM_AFSK12_TX_LO_Q);
- sum -= convolution8_s16(buf, afsk12_tx_hi_i, SUM_AFSK12_TX_HI_I);
- sum -= convolution8_s16(buf, afsk12_tx_hi_q, SUM_AFSK12_TX_HI_Q);
- return sum;
-}
-
-/* --------------------------------------------------------------------- */
-
-static const int pll_corr[2] = { -0x1000, 0x1000 };
-
-static void demodulator_1200_u8(struct sm_state *sm, const unsigned char *buf, unsigned int buflen)
-{
- struct demod_state_afsk12 *st = (struct demod_state_afsk12 *)(&sm->d);
- int j;
- int sum;
- unsigned char newsample;
-
- for (; buflen > 0; buflen--, buf++) {
- sum = do_filter_1200_u8(buf);
- st->dcd_shreg <<= 1;
- st->bit_pll += 0x2000;
- newsample = (sum > 0);
- if (st->last_sample ^ newsample) {
- st->last_sample = newsample;
- st->dcd_shreg |= 1;
- st->bit_pll += pll_corr
- [st->bit_pll < 0x9000];
- j = 4 * hweight8(st->dcd_shreg & 0x38)
- - hweight16(st->dcd_shreg & 0x7c0);
- st->dcd_sum0 += j;
- }
- hdlcdrv_channelbit(&sm->hdrv, st->last_sample);
- if ((--st->dcd_time) <= 0) {
- hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 +
- st->dcd_sum1 +
- st->dcd_sum2) < 0);
- st->dcd_sum2 = st->dcd_sum1;
- st->dcd_sum1 = st->dcd_sum0;
- st->dcd_sum0 = 2; /* slight bias */
- st->dcd_time = 120;
- }
- if (st->bit_pll >= 0x10000) {
- st->bit_pll &= 0xffff;
- st->shreg >>= 1;
- st->shreg |= (!(st->last_rxbit ^
- st->last_sample)) << 16;
- st->last_rxbit = st->last_sample;
- diag_trigger(sm);
- if (st->shreg & 1) {
- hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1);
- st->shreg = 0x10000;
- }
- }
- diag_add(sm, (((int)*buf)-0x80) << 8, sum);
- }
-}
-
-/* --------------------------------------------------------------------- */
-
-static void demodulator_1200_s16(struct sm_state *sm, const short *buf, unsigned int buflen)
-{
- struct demod_state_afsk12 *st = (struct demod_state_afsk12 *)(&sm->d);
- int j;
- int sum;
- unsigned char newsample;
-
- for (; buflen > 0; buflen--, buf++) {
- sum = do_filter_1200_s16(buf);
- st->dcd_shreg <<= 1;
- st->bit_pll += 0x2000;
- newsample = (sum > 0);
- if (st->last_sample ^ newsample) {
- st->last_sample = newsample;
- st->dcd_shreg |= 1;
- st->bit_pll += pll_corr
- [st->bit_pll < 0x9000];
- j = 4 * hweight8(st->dcd_shreg & 0x38)
- - hweight16(st->dcd_shreg & 0x7c0);
- st->dcd_sum0 += j;
- }
- hdlcdrv_channelbit(&sm->hdrv, st->last_sample);
- if ((--st->dcd_time) <= 0) {
- hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 +
- st->dcd_sum1 +
- st->dcd_sum2) < 0);
- st->dcd_sum2 = st->dcd_sum1;
- st->dcd_sum1 = st->dcd_sum0;
- st->dcd_sum0 = 2; /* slight bias */
- st->dcd_time = 120;
- }
- if (st->bit_pll >= 0x10000) {
- st->bit_pll &= 0xffff;
- st->shreg >>= 1;
- st->shreg |= (!(st->last_rxbit ^
- st->last_sample)) << 16;
- st->last_rxbit = st->last_sample;
- diag_trigger(sm);
- if (st->shreg & 1) {
- hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1);
- st->shreg = 0x10000;
- }
- }
- diag_add(sm, *buf, sum);
- }
-}
-
-/* --------------------------------------------------------------------- */
-
-static void demod_init_1200(struct sm_state *sm)
-{
- struct demod_state_afsk12 *st = (struct demod_state_afsk12 *)(&sm->d);
-
- st->dcd_time = 120;
- st->dcd_sum0 = 2;
-}
-
-/* --------------------------------------------------------------------- */
-
-const struct modem_tx_info sm_afsk1200_tx = {
- "afsk1200", sizeof(struct mod_state_afsk12),
- AFSK12_SAMPLE_RATE, 1200, modulator_1200_u8, modulator_1200_s16, NULL
-};
-
-const struct modem_rx_info sm_afsk1200_rx = {
- "afsk1200", sizeof(struct demod_state_afsk12),
- AFSK12_SAMPLE_RATE, 1200, 8, AFSK12_SAMPLE_RATE/1200,
- demodulator_1200_u8, demodulator_1200_s16, demod_init_1200
-};
-
-/* --------------------------------------------------------------------- */
diff --git a/drivers/net/soundmodem/sm_afsk2400_7.c b/drivers/net/soundmodem/sm_afsk2400_7.c
index d217936ab..e69de29bb 100644
--- a/drivers/net/soundmodem/sm_afsk2400_7.c
+++ b/drivers/net/soundmodem/sm_afsk2400_7.c
@@ -1,296 +0,0 @@
-/*****************************************************************************/
-
-/*
- * sm_afsk2400_7.c -- soundcard radio modem driver, 2400 baud AFSK modem
- *
- * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Please note that the GPL allows you to use the driver, NOT the radio.
- * In order to use the radio, you need a license from the communications
- * authority of your country.
- *
- */
-
-/*
- * This driver is intended to be compatible with TCM3105 modems
- * overclocked to 7.3728MHz. The mark and space frequencies therefore
- * lie at 3658 and 1996 Hz.
- * Note that I do _not_ recommend the building of such links, I provide
- * this only for the users who live in the coverage area of such
- * a "legacy" link.
- */
-
-#include "sm.h"
-#include "sm_tbl_afsk2400_7.h"
-
-/* --------------------------------------------------------------------- */
-
-struct demod_state_afsk24 {
- unsigned int shreg;
- unsigned int bit_pll;
- unsigned char last_sample;
- unsigned int dcd_shreg;
- int dcd_sum0, dcd_sum1, dcd_sum2;
- unsigned int dcd_time;
- unsigned char last_rxbit;
-};
-
-struct mod_state_afsk24 {
- unsigned int shreg;
- unsigned char tx_bit;
- unsigned int bit_pll;
- unsigned int tx_seq;
- unsigned int phinc;
-};
-
-/* --------------------------------------------------------------------- */
-
-static const int dds_inc[2] = { AFSK24_TX_FREQ_LO*0x10000/AFSK24_SAMPLERATE,
- AFSK24_TX_FREQ_HI*0x10000/AFSK24_SAMPLERATE };
-
-static void modulator_2400_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen)
-{
- struct mod_state_afsk24 *st = (struct mod_state_afsk24 *)(&sm->m);
-
- for (; buflen > 0; buflen--, buf++) {
- if (st->tx_seq < 0x5555) {
- if (st->shreg <= 1)
- st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
- st->tx_bit = (st->tx_bit ^ (!(st->shreg & 1))) & 1;
- st->shreg >>= 1;
- st->phinc = dds_inc[st->tx_bit & 1];
- }
- st->tx_seq += 0x5555;
- st->tx_seq &= 0xffff;
- *buf = OFFSCOS(st->bit_pll);
- st->bit_pll += st->phinc;
- }
-}
-
-/* --------------------------------------------------------------------- */
-
-static void modulator_2400_s16(struct sm_state *sm, short *buf, unsigned int buflen)
-{
- struct mod_state_afsk24 *st = (struct mod_state_afsk24 *)(&sm->m);
-
- for (; buflen > 0; buflen--, buf++) {
- if (st->tx_seq < 0x5555) {
- if (st->shreg <= 1)
- st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
- st->tx_bit = (st->tx_bit ^ (!(st->shreg & 1))) & 1;
- st->shreg >>= 1;
- st->phinc = dds_inc[st->tx_bit & 1];
- }
- st->tx_seq += 0x5555;
- st->tx_seq &= 0xffff;
- *buf = COS(st->bit_pll);
- st->bit_pll += st->phinc;
- }
-}
-
-/* --------------------------------------------------------------------- */
-
-extern __inline__ int convolution14_u8(const unsigned char *st, const int *coeff, int csum)
-{
- int sum = -0x80 * csum;
-
- sum += (st[0] * coeff[0]);
- sum += (st[-1] * coeff[1]);
- sum += (st[-2] * coeff[2]);
- sum += (st[-3] * coeff[3]);
- sum += (st[-4] * coeff[4]);
- sum += (st[-5] * coeff[5]);
- sum += (st[-6] * coeff[6]);
- sum += (st[-7] * coeff[7]);
- sum += (st[-8] * coeff[8]);
- sum += (st[-9] * coeff[9]);
- sum += (st[-10] * coeff[10]);
- sum += (st[-11] * coeff[11]);
- sum += (st[-12] * coeff[12]);
- sum += (st[-13] * coeff[13]);
-
- sum >>= 7;
- return sum * sum;
-}
-
-extern __inline__ int convolution14_s16(const short *st, const int *coeff, int csum)
-{
- int sum = 0;
-
- sum += (st[0] * coeff[0]);
- sum += (st[-1] * coeff[1]);
- sum += (st[-2] * coeff[2]);
- sum += (st[-3] * coeff[3]);
- sum += (st[-4] * coeff[4]);
- sum += (st[-5] * coeff[5]);
- sum += (st[-6] * coeff[6]);
- sum += (st[-7] * coeff[7]);
- sum += (st[-8] * coeff[8]);
- sum += (st[-9] * coeff[9]);
- sum += (st[-10] * coeff[10]);
- sum += (st[-11] * coeff[11]);
- sum += (st[-12] * coeff[12]);
- sum += (st[-13] * coeff[13]);
-
- sum >>= 15;
- return sum * sum;
-}
-
-extern __inline__ int do_filter_2400_u8(const unsigned char *buf)
-{
- int sum = convolution14_u8(buf, afsk24_tx_lo_i, SUM_AFSK24_TX_LO_I);
- sum += convolution14_u8(buf, afsk24_tx_lo_q, SUM_AFSK24_TX_LO_Q);
- sum -= convolution14_u8(buf, afsk24_tx_hi_i, SUM_AFSK24_TX_HI_I);
- sum -= convolution14_u8(buf, afsk24_tx_hi_q, SUM_AFSK24_TX_HI_Q);
- return sum;
-}
-
-extern __inline__ int do_filter_2400_s16(const short *buf)
-{
- int sum = convolution14_s16(buf, afsk24_tx_lo_i, SUM_AFSK24_TX_LO_I);
- sum += convolution14_s16(buf, afsk24_tx_lo_q, SUM_AFSK24_TX_LO_Q);
- sum -= convolution14_s16(buf, afsk24_tx_hi_i, SUM_AFSK24_TX_HI_I);
- sum -= convolution14_s16(buf, afsk24_tx_hi_q, SUM_AFSK24_TX_HI_Q);
- return sum;
-}
-
-/* --------------------------------------------------------------------- */
-
-static void demodulator_2400_u8(struct sm_state *sm, const unsigned char *buf, unsigned int buflen)
-{
- struct demod_state_afsk24 *st = (struct demod_state_afsk24 *)(&sm->d);
- int j;
- int sum;
- unsigned char newsample;
-
- for (; buflen > 0; buflen--, buf++) {
- sum = do_filter_2400_u8(buf);
- st->dcd_shreg <<= 1;
- st->bit_pll += AFSK24_BITPLL_INC;
- newsample = (sum > 0);
- if (st->last_sample ^ newsample) {
- st->last_sample = newsample;
- st->dcd_shreg |= 1;
- if (st->bit_pll < (0x8000+AFSK24_BITPLL_INC/2))
- st->bit_pll += AFSK24_BITPLL_INC/2;
- else
- st->bit_pll -= AFSK24_BITPLL_INC/2;
- j = /* 2 * */ hweight8(st->dcd_shreg & 0x1c)
- - hweight16(st->dcd_shreg & 0x1e0);
- st->dcd_sum0 += j;
- }
- hdlcdrv_channelbit(&sm->hdrv, st->last_sample);
- if ((--st->dcd_time) <= 0) {
- hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 +
- st->dcd_sum1 +
- st->dcd_sum2) < 0);
- st->dcd_sum2 = st->dcd_sum1;
- st->dcd_sum1 = st->dcd_sum0;
- st->dcd_sum0 = 2; /* slight bias */
- st->dcd_time = 120;
- }
- if (st->bit_pll >= 0x10000) {
- st->bit_pll &= 0xffff;
- st->shreg >>= 1;
- st->shreg |= (!(st->last_rxbit ^
- st->last_sample)) << 16;
- st->last_rxbit = st->last_sample;
- diag_trigger(sm);
- if (st->shreg & 1) {
- hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1);
- st->shreg = 0x10000;
- }
- }
- diag_add(sm, (((int)*buf)-0x80) << 8, sum);
- }
-}
-
-/* --------------------------------------------------------------------- */
-
-static void demodulator_2400_s16(struct sm_state *sm, const short *buf, unsigned int buflen)
-{
- struct demod_state_afsk24 *st = (struct demod_state_afsk24 *)(&sm->d);
- int j;
- int sum;
- unsigned char newsample;
-
- for (; buflen > 0; buflen--, buf++) {
- sum = do_filter_2400_s16(buf);
- st->dcd_shreg <<= 1;
- st->bit_pll += AFSK24_BITPLL_INC;
- newsample = (sum > 0);
- if (st->last_sample ^ newsample) {
- st->last_sample = newsample;
- st->dcd_shreg |= 1;
- if (st->bit_pll < (0x8000+AFSK24_BITPLL_INC/2))
- st->bit_pll += AFSK24_BITPLL_INC/2;
- else
- st->bit_pll -= AFSK24_BITPLL_INC/2;
- j = /* 2 * */ hweight8(st->dcd_shreg & 0x1c)
- - hweight16(st->dcd_shreg & 0x1e0);
- st->dcd_sum0 += j;
- }
- hdlcdrv_channelbit(&sm->hdrv, st->last_sample);
- if ((--st->dcd_time) <= 0) {
- hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 +
- st->dcd_sum1 +
- st->dcd_sum2) < 0);
- st->dcd_sum2 = st->dcd_sum1;
- st->dcd_sum1 = st->dcd_sum0;
- st->dcd_sum0 = 2; /* slight bias */
- st->dcd_time = 120;
- }
- if (st->bit_pll >= 0x10000) {
- st->bit_pll &= 0xffff;
- st->shreg >>= 1;
- st->shreg |= (!(st->last_rxbit ^
- st->last_sample)) << 16;
- st->last_rxbit = st->last_sample;
- diag_trigger(sm);
- if (st->shreg & 1) {
- hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1);
- st->shreg = 0x10000;
- }
- }
- diag_add(sm, *buf, sum);
- }
-}
-
-/* --------------------------------------------------------------------- */
-
-static void demod_init_2400(struct sm_state *sm)
-{
- struct demod_state_afsk24 *st = (struct demod_state_afsk24 *)(&sm->d);
-
- st->dcd_time = 120;
- st->dcd_sum0 = 2;
-}
-
-/* --------------------------------------------------------------------- */
-
-const struct modem_tx_info sm_afsk2400_7_tx = {
- "afsk2400_7", sizeof(struct mod_state_afsk24), AFSK24_SAMPLERATE, 2400,
- modulator_2400_u8, modulator_2400_s16, NULL
-};
-
-const struct modem_rx_info sm_afsk2400_7_rx = {
- "afsk2400_7", sizeof(struct demod_state_afsk24),
- AFSK24_SAMPLERATE, 2400, 14, AFSK24_SAMPLERATE/2400,
- demodulator_2400_u8, demodulator_2400_s16, demod_init_2400
-};
-
-/* --------------------------------------------------------------------- */
diff --git a/drivers/net/soundmodem/sm_afsk2400_8.c b/drivers/net/soundmodem/sm_afsk2400_8.c
index 23d233746..e69de29bb 100644
--- a/drivers/net/soundmodem/sm_afsk2400_8.c
+++ b/drivers/net/soundmodem/sm_afsk2400_8.c
@@ -1,296 +0,0 @@
-/*****************************************************************************/
-
-/*
- * sm_afsk2400_8.c -- soundcard radio modem driver, 2400 baud AFSK modem
- *
- * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Please note that the GPL allows you to use the driver, NOT the radio.
- * In order to use the radio, you need a license from the communications
- * authority of your country.
- *
- */
-
-/*
- * This driver is intended to be compatible with TCM3105 modems
- * overclocked to 8MHz. The mark and space frequencies therefore
- * lie at 3970 and 2165 Hz.
- * Note that I do _not_ recommend the building of such links, I provide
- * this only for the users who live in the coverage area of such
- * a "legacy" link.
- */
-
-#include "sm.h"
-#include "sm_tbl_afsk2400_8.h"
-
-/* --------------------------------------------------------------------- */
-
-struct demod_state_afsk24 {
- unsigned int shreg;
- unsigned int bit_pll;
- unsigned char last_sample;
- unsigned int dcd_shreg;
- int dcd_sum0, dcd_sum1, dcd_sum2;
- unsigned int dcd_time;
- unsigned char last_rxbit;
-};
-
-struct mod_state_afsk24 {
- unsigned int shreg;
- unsigned char tx_bit;
- unsigned int bit_pll;
- unsigned int tx_seq;
- unsigned int phinc;
-};
-
-/* --------------------------------------------------------------------- */
-
-static const int dds_inc[2] = { AFSK24_TX_FREQ_LO*0x10000/AFSK24_SAMPLERATE,
- AFSK24_TX_FREQ_HI*0x10000/AFSK24_SAMPLERATE };
-
-static void modulator_2400_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen)
-{
- struct mod_state_afsk24 *st = (struct mod_state_afsk24 *)(&sm->m);
-
- for (; buflen > 0; buflen--, buf++) {
- if (st->tx_seq < 0x5555) {
- if (st->shreg <= 1)
- st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
- st->tx_bit = (st->tx_bit ^ (!(st->shreg & 1))) & 1;
- st->shreg >>= 1;
- st->phinc = dds_inc[st->tx_bit & 1];
- }
- st->tx_seq += 0x5555;
- st->tx_seq &= 0xffff;
- *buf = OFFSCOS(st->bit_pll);
- st->bit_pll += st->phinc;
- }
-}
-
-/* --------------------------------------------------------------------- */
-
-static void modulator_2400_s16(struct sm_state *sm, short *buf, unsigned int buflen)
-{
- struct mod_state_afsk24 *st = (struct mod_state_afsk24 *)(&sm->m);
-
- for (; buflen > 0; buflen--, buf++) {
- if (st->tx_seq < 0x5555) {
- if (st->shreg <= 1)
- st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
- st->tx_bit = (st->tx_bit ^ (!(st->shreg & 1))) & 1;
- st->shreg >>= 1;
- st->phinc = dds_inc[st->tx_bit & 1];
- }
- st->tx_seq += 0x5555;
- st->tx_seq &= 0xffff;
- *buf = COS(st->bit_pll);
- st->bit_pll += st->phinc;
- }
-}
-
-/* --------------------------------------------------------------------- */
-
-extern __inline__ int convolution14_u8(const unsigned char *st, const int *coeff, int csum)
-{
- int sum = -0x80 * csum;
-
- sum += (st[0] * coeff[0]);
- sum += (st[-1] * coeff[1]);
- sum += (st[-2] * coeff[2]);
- sum += (st[-3] * coeff[3]);
- sum += (st[-4] * coeff[4]);
- sum += (st[-5] * coeff[5]);
- sum += (st[-6] * coeff[6]);
- sum += (st[-7] * coeff[7]);
- sum += (st[-8] * coeff[8]);
- sum += (st[-9] * coeff[9]);
- sum += (st[-10] * coeff[10]);
- sum += (st[-11] * coeff[11]);
- sum += (st[-12] * coeff[12]);
- sum += (st[-13] * coeff[13]);
-
- sum >>= 7;
- return sum * sum;
-}
-
-extern __inline__ int convolution14_s16(const short *st, const int *coeff, int csum)
-{
- int sum = 0;
-
- sum += (st[0] * coeff[0]);
- sum += (st[-1] * coeff[1]);
- sum += (st[-2] * coeff[2]);
- sum += (st[-3] * coeff[3]);
- sum += (st[-4] * coeff[4]);
- sum += (st[-5] * coeff[5]);
- sum += (st[-6] * coeff[6]);
- sum += (st[-7] * coeff[7]);
- sum += (st[-8] * coeff[8]);
- sum += (st[-9] * coeff[9]);
- sum += (st[-10] * coeff[10]);
- sum += (st[-11] * coeff[11]);
- sum += (st[-12] * coeff[12]);
- sum += (st[-13] * coeff[13]);
-
- sum >>= 15;
- return sum * sum;
-}
-
-extern __inline__ int do_filter_2400_u8(const unsigned char *buf)
-{
- int sum = convolution14_u8(buf, afsk24_tx_lo_i, SUM_AFSK24_TX_LO_I);
- sum += convolution14_u8(buf, afsk24_tx_lo_q, SUM_AFSK24_TX_LO_Q);
- sum -= convolution14_u8(buf, afsk24_tx_hi_i, SUM_AFSK24_TX_HI_I);
- sum -= convolution14_u8(buf, afsk24_tx_hi_q, SUM_AFSK24_TX_HI_Q);
- return sum;
-}
-
-extern __inline__ int do_filter_2400_s16(const short *buf)
-{
- int sum = convolution14_s16(buf, afsk24_tx_lo_i, SUM_AFSK24_TX_LO_I);
- sum += convolution14_s16(buf, afsk24_tx_lo_q, SUM_AFSK24_TX_LO_Q);
- sum -= convolution14_s16(buf, afsk24_tx_hi_i, SUM_AFSK24_TX_HI_I);
- sum -= convolution14_s16(buf, afsk24_tx_hi_q, SUM_AFSK24_TX_HI_Q);
- return sum;
-}
-
-/* --------------------------------------------------------------------- */
-
-static void demodulator_2400_u8(struct sm_state *sm, const unsigned char *buf, unsigned int buflen)
-{
- struct demod_state_afsk24 *st = (struct demod_state_afsk24 *)(&sm->d);
- int j;
- int sum;
- unsigned char newsample;
-
- for (; buflen > 0; buflen--, buf++) {
- sum = do_filter_2400_u8(buf);
- st->dcd_shreg <<= 1;
- st->bit_pll += AFSK24_BITPLL_INC;
- newsample = (sum > 0);
- if (st->last_sample ^ newsample) {
- st->last_sample = newsample;
- st->dcd_shreg |= 1;
- if (st->bit_pll < (0x8000+AFSK24_BITPLL_INC/2))
- st->bit_pll += AFSK24_BITPLL_INC/2;
- else
- st->bit_pll -= AFSK24_BITPLL_INC/2;
- j = /* 2 * */ hweight8(st->dcd_shreg & 0x1c)
- - hweight16(st->dcd_shreg & 0x1e0);
- st->dcd_sum0 += j;
- }
- hdlcdrv_channelbit(&sm->hdrv, st->last_sample);
- if ((--st->dcd_time) <= 0) {
- hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 +
- st->dcd_sum1 +
- st->dcd_sum2) < 0);
- st->dcd_sum2 = st->dcd_sum1;
- st->dcd_sum1 = st->dcd_sum0;
- st->dcd_sum0 = 2; /* slight bias */
- st->dcd_time = 120;
- }
- if (st->bit_pll >= 0x10000) {
- st->bit_pll &= 0xffff;
- st->shreg >>= 1;
- st->shreg |= (!(st->last_rxbit ^
- st->last_sample)) << 16;
- st->last_rxbit = st->last_sample;
- diag_trigger(sm);
- if (st->shreg & 1) {
- hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1);
- st->shreg = 0x10000;
- }
- }
- diag_add(sm, (((int)*buf)-0x80) << 8, sum);
- }
-}
-
-/* --------------------------------------------------------------------- */
-
-static void demodulator_2400_s16(struct sm_state *sm, const short *buf, unsigned int buflen)
-{
- struct demod_state_afsk24 *st = (struct demod_state_afsk24 *)(&sm->d);
- int j;
- int sum;
- unsigned char newsample;
-
- for (; buflen > 0; buflen--, buf++) {
- sum = do_filter_2400_s16(buf);
- st->dcd_shreg <<= 1;
- st->bit_pll += AFSK24_BITPLL_INC;
- newsample = (sum > 0);
- if (st->last_sample ^ newsample) {
- st->last_sample = newsample;
- st->dcd_shreg |= 1;
- if (st->bit_pll < (0x8000+AFSK24_BITPLL_INC/2))
- st->bit_pll += AFSK24_BITPLL_INC/2;
- else
- st->bit_pll -= AFSK24_BITPLL_INC/2;
- j = /* 2 * */ hweight8(st->dcd_shreg & 0x1c)
- - hweight16(st->dcd_shreg & 0x1e0);
- st->dcd_sum0 += j;
- }
- hdlcdrv_channelbit(&sm->hdrv, st->last_sample);
- if ((--st->dcd_time) <= 0) {
- hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 +
- st->dcd_sum1 +
- st->dcd_sum2) < 0);
- st->dcd_sum2 = st->dcd_sum1;
- st->dcd_sum1 = st->dcd_sum0;
- st->dcd_sum0 = 2; /* slight bias */
- st->dcd_time = 120;
- }
- if (st->bit_pll >= 0x10000) {
- st->bit_pll &= 0xffff;
- st->shreg >>= 1;
- st->shreg |= (!(st->last_rxbit ^
- st->last_sample)) << 16;
- st->last_rxbit = st->last_sample;
- diag_trigger(sm);
- if (st->shreg & 1) {
- hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1);
- st->shreg = 0x10000;
- }
- }
- diag_add(sm, *buf, sum);
- }
-}
-
-/* --------------------------------------------------------------------- */
-
-static void demod_init_2400(struct sm_state *sm)
-{
- struct demod_state_afsk24 *st = (struct demod_state_afsk24 *)(&sm->d);
-
- st->dcd_time = 120;
- st->dcd_sum0 = 2;
-}
-
-/* --------------------------------------------------------------------- */
-
-const struct modem_tx_info sm_afsk2400_8_tx = {
- "afsk2400_8", sizeof(struct mod_state_afsk24), AFSK24_SAMPLERATE, 2400,
- modulator_2400_u8, modulator_2400_s16, NULL
-};
-
-const struct modem_rx_info sm_afsk2400_8_rx = {
- "afsk2400_8", sizeof(struct demod_state_afsk24),
- AFSK24_SAMPLERATE, 2400, 14, AFSK24_SAMPLERATE/2400,
- demodulator_2400_u8, demodulator_2400_s16, demod_init_2400
-};
-
-/* --------------------------------------------------------------------- */
diff --git a/drivers/net/soundmodem/sm_fsk9600.c b/drivers/net/soundmodem/sm_fsk9600.c
index bc2fb53b1..e69de29bb 100644
--- a/drivers/net/soundmodem/sm_fsk9600.c
+++ b/drivers/net/soundmodem/sm_fsk9600.c
@@ -1,391 +0,0 @@
-/*****************************************************************************/
-
-/*
- * sm_fsk9600.c -- soundcard radio modem driver,
- * 9600 baud G3RUH compatible FSK modem
- *
- * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Please note that the GPL allows you to use the driver, NOT the radio.
- * In order to use the radio, you need a license from the communications
- * authority of your country.
- *
- */
-
-#include "sm.h"
-#include "sm_tbl_fsk9600.h"
-
-/* --------------------------------------------------------------------- */
-
-struct demod_state_fsk96 {
- unsigned int shreg;
- unsigned long descram;
- unsigned int bit_pll;
- unsigned char last_sample;
- unsigned int dcd_shreg;
- int dcd_sum0, dcd_sum1, dcd_sum2;
- unsigned int dcd_time;
-};
-
-struct mod_state_fsk96 {
- unsigned int shreg;
- unsigned long scram;
- unsigned char tx_bit;
- unsigned char *txtbl;
- unsigned int txphase;
-};
-
-/* --------------------------------------------------------------------- */
-
-#define DESCRAM_TAP1 0x20000
-#define DESCRAM_TAP2 0x01000
-#define DESCRAM_TAP3 0x00001
-
-#define DESCRAM_TAPSH1 17
-#define DESCRAM_TAPSH2 12
-#define DESCRAM_TAPSH3 0
-
-#define SCRAM_TAP1 0x20000 /* X^17 */
-#define SCRAM_TAPN 0x00021 /* X^0+X^5 */
-
-/* --------------------------------------------------------------------- */
-
-static void modulator_9600_4_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen)
-{
- struct mod_state_fsk96 *st = (struct mod_state_fsk96 *)(&sm->m);
-
- for (; buflen > 0; buflen--) {
- if (!st->txphase++) {
- if (st->shreg <= 1)
- st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
- st->scram = (st->scram << 1) | (st->scram & 1);
- st->scram ^= !(st->shreg & 1);
- st->shreg >>= 1;
- if (st->scram & (SCRAM_TAP1 << 1))
- st->scram ^= SCRAM_TAPN << 1;
- st->tx_bit = (st->tx_bit << 1) | (!!(st->scram & (SCRAM_TAP1 << 2)));
- st->txtbl = fsk96_txfilt_4 + (st->tx_bit & 0xff);
- }
- if (st->txphase >= 4)
- st->txphase = 0;
- *buf++ = *st->txtbl;
- st->txtbl += 0x100;
- }
-}
-
-/* --------------------------------------------------------------------- */
-
-static void modulator_9600_4_s16(struct sm_state *sm, short *buf, unsigned int buflen)
-{
- struct mod_state_fsk96 *st = (struct mod_state_fsk96 *)(&sm->m);
-
- for (; buflen > 0; buflen--) {
- if (!st->txphase++) {
- if (st->shreg <= 1)
- st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
- st->scram = (st->scram << 1) | (st->scram & 1);
- st->scram ^= !(st->shreg & 1);
- st->shreg >>= 1;
- if (st->scram & (SCRAM_TAP1 << 1))
- st->scram ^= SCRAM_TAPN << 1;
- st->tx_bit = (st->tx_bit << 1) | (!!(st->scram & (SCRAM_TAP1 << 2)));
- st->txtbl = fsk96_txfilt_4 + (st->tx_bit & 0xff);
- }
- if (st->txphase >= 4)
- st->txphase = 0;
- *buf++ = ((*st->txtbl)-0x80) << 8;
- st->txtbl += 0x100;
- }
-}
-
-/* --------------------------------------------------------------------- */
-
-static void demodulator_9600_4_u8(struct sm_state *sm, const unsigned char *buf, unsigned int buflen)
-{
- struct demod_state_fsk96 *st = (struct demod_state_fsk96 *)(&sm->d);
- static const int pll_corr[2] = { -0x1000, 0x1000 };
- unsigned char curbit;
- unsigned int descx;
-
- for (; buflen > 0; buflen--, buf++) {
- st->dcd_shreg <<= 1;
- st->bit_pll += 0x4000;
- curbit = (*buf >= 0x80);
- if (st->last_sample ^ curbit) {
- st->dcd_shreg |= 1;
- st->bit_pll += pll_corr[st->bit_pll < 0xa000];
- st->dcd_sum0 += 8 * hweight8(st->dcd_shreg & 0x0c) -
- !!(st->dcd_shreg & 0x10);
- }
- st->last_sample = curbit;
- hdlcdrv_channelbit(&sm->hdrv, st->last_sample);
- if ((--st->dcd_time) <= 0) {
- hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 +
- st->dcd_sum1 +
- st->dcd_sum2) < 0);
- st->dcd_sum2 = st->dcd_sum1;
- st->dcd_sum1 = st->dcd_sum0;
- st->dcd_sum0 = 2; /* slight bias */
- st->dcd_time = 240;
- }
- if (st->bit_pll >= 0x10000) {
- st->bit_pll &= 0xffff;
- st->descram = (st->descram << 1) | curbit;
- descx = st->descram ^ (st->descram >> 1);
- descx ^= ((descx >> DESCRAM_TAPSH1) ^
- (descx >> DESCRAM_TAPSH2));
- st->shreg >>= 1;
- st->shreg |= (!(descx & 1)) << 16;
- if (st->shreg & 1) {
- hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1);
- st->shreg = 0x10000;
- }
- diag_trigger(sm);
- }
- diag_add_one(sm, ((short)(*buf - 0x80)) << 8);
- }
-}
-
-/* --------------------------------------------------------------------- */
-
-static void demodulator_9600_4_s16(struct sm_state *sm, const short *buf, unsigned int buflen)
-{
- struct demod_state_fsk96 *st = (struct demod_state_fsk96 *)(&sm->d);
- static const int pll_corr[2] = { -0x1000, 0x1000 };
- unsigned char curbit;
- unsigned int descx;
-
- for (; buflen > 0; buflen--, buf++) {
- st->dcd_shreg <<= 1;
- st->bit_pll += 0x4000;
- curbit = (*buf >= 0);
- if (st->last_sample ^ curbit) {
- st->dcd_shreg |= 1;
- st->bit_pll += pll_corr[st->bit_pll < 0xa000];
- st->dcd_sum0 += 8 * hweight8(st->dcd_shreg & 0x0c) -
- !!(st->dcd_shreg & 0x10);
- }
- st->last_sample = curbit;
- hdlcdrv_channelbit(&sm->hdrv, st->last_sample);
- if ((--st->dcd_time) <= 0) {
- hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 +
- st->dcd_sum1 +
- st->dcd_sum2) < 0);
- st->dcd_sum2 = st->dcd_sum1;
- st->dcd_sum1 = st->dcd_sum0;
- st->dcd_sum0 = 2; /* slight bias */
- st->dcd_time = 240;
- }
- if (st->bit_pll >= 0x10000) {
- st->bit_pll &= 0xffff;
- st->descram = (st->descram << 1) | curbit;
- descx = st->descram ^ (st->descram >> 1);
- descx ^= ((descx >> DESCRAM_TAPSH1) ^
- (descx >> DESCRAM_TAPSH2));
- st->shreg >>= 1;
- st->shreg |= (!(descx & 1)) << 16;
- if (st->shreg & 1) {
- hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1);
- st->shreg = 0x10000;
- }
- diag_trigger(sm);
- }
- diag_add_one(sm, *buf);
- }
-}
-
-/* --------------------------------------------------------------------- */
-
-static void modulator_9600_5_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen)
-{
- struct mod_state_fsk96 *st = (struct mod_state_fsk96 *)(&sm->m);
-
- for (; buflen > 0; buflen--) {
- if (!st->txphase++) {
- if (st->shreg <= 1)
- st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
- st->scram = (st->scram << 1) | (st->scram & 1);
- st->scram ^= !(st->shreg & 1);
- st->shreg >>= 1;
- if (st->scram & (SCRAM_TAP1 << 1))
- st->scram ^= SCRAM_TAPN << 1;
- st->tx_bit = (st->tx_bit << 1) | (!!(st->scram & (SCRAM_TAP1 << 2)));
- st->txtbl = fsk96_txfilt_5 + (st->tx_bit & 0xff);
- }
- if (st->txphase >= 5)
- st->txphase = 0;
- *buf++ = *st->txtbl;
- st->txtbl += 0x100;
- }
-}
-
-/* --------------------------------------------------------------------- */
-
-static void modulator_9600_5_s16(struct sm_state *sm, short *buf, unsigned int buflen)
-{
- struct mod_state_fsk96 *st = (struct mod_state_fsk96 *)(&sm->m);
-
- for (; buflen > 0; buflen--) {
- if (!st->txphase++) {
- if (st->shreg <= 1)
- st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
- st->scram = (st->scram << 1) | (st->scram & 1);
- st->scram ^= !(st->shreg & 1);
- st->shreg >>= 1;
- if (st->scram & (SCRAM_TAP1 << 1))
- st->scram ^= SCRAM_TAPN << 1;
- st->tx_bit = (st->tx_bit << 1) | (!!(st->scram & (SCRAM_TAP1 << 2)));
- st->txtbl = fsk96_txfilt_5 + (st->tx_bit & 0xff);
- }
- if (st->txphase >= 5)
- st->txphase = 0;
- *buf++ = ((*st->txtbl)-0x80)<<8;
- st->txtbl += 0x100;
- }
-}
-
-/* --------------------------------------------------------------------- */
-
-static void demodulator_9600_5_u8(struct sm_state *sm, const unsigned char *buf, unsigned int buflen)
-{
- struct demod_state_fsk96 *st = (struct demod_state_fsk96 *)(&sm->d);
- static const int pll_corr[2] = { -0x1000, 0x1000 };
- unsigned char curbit;
- unsigned int descx;
-
- for (; buflen > 0; buflen--, buf++) {
- st->dcd_shreg <<= 1;
- st->bit_pll += 0x3333;
- curbit = (*buf >= 0x80);
- if (st->last_sample ^ curbit) {
- st->dcd_shreg |= 1;
- st->bit_pll += pll_corr[st->bit_pll < 0x9999];
- st->dcd_sum0 += 16 * hweight8(st->dcd_shreg & 0x0c) -
- hweight8(st->dcd_shreg & 0x70);
- }
- st->last_sample = curbit;
- hdlcdrv_channelbit(&sm->hdrv, st->last_sample);
- if ((--st->dcd_time) <= 0) {
- hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 +
- st->dcd_sum1 +
- st->dcd_sum2) < 0);
- st->dcd_sum2 = st->dcd_sum1;
- st->dcd_sum1 = st->dcd_sum0;
- st->dcd_sum0 = 2; /* slight bias */
- st->dcd_time = 240;
- }
- if (st->bit_pll >= 0x10000) {
- st->bit_pll &= 0xffff;
- st->descram = (st->descram << 1) | curbit;
- descx = st->descram ^ (st->descram >> 1);
- descx ^= ((descx >> DESCRAM_TAPSH1) ^
- (descx >> DESCRAM_TAPSH2));
- st->shreg >>= 1;
- st->shreg |= (!(descx & 1)) << 16;
- if (st->shreg & 1) {
- hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1);
- st->shreg = 0x10000;
- }
- diag_trigger(sm);
- }
- diag_add_one(sm, ((short)(*buf - 0x80)) << 8);
- }
-}
-
-/* --------------------------------------------------------------------- */
-
-static void demodulator_9600_5_s16(struct sm_state *sm, const short *buf, unsigned int buflen)
-{
- struct demod_state_fsk96 *st = (struct demod_state_fsk96 *)(&sm->d);
- static const int pll_corr[2] = { -0x1000, 0x1000 };
- unsigned char curbit;
- unsigned int descx;
-
- for (; buflen > 0; buflen--, buf++) {
- st->dcd_shreg <<= 1;
- st->bit_pll += 0x3333;
- curbit = (*buf >= 0);
- if (st->last_sample ^ curbit) {
- st->dcd_shreg |= 1;
- st->bit_pll += pll_corr[st->bit_pll < 0x9999];
- st->dcd_sum0 += 16 * hweight8(st->dcd_shreg & 0x0c) -
- hweight8(st->dcd_shreg & 0x70);
- }
- st->last_sample = curbit;
- hdlcdrv_channelbit(&sm->hdrv, st->last_sample);
- if ((--st->dcd_time) <= 0) {
- hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 +
- st->dcd_sum1 +
- st->dcd_sum2) < 0);
- st->dcd_sum2 = st->dcd_sum1;
- st->dcd_sum1 = st->dcd_sum0;
- st->dcd_sum0 = 2; /* slight bias */
- st->dcd_time = 240;
- }
- if (st->bit_pll >= 0x10000) {
- st->bit_pll &= 0xffff;
- st->descram = (st->descram << 1) | curbit;
- descx = st->descram ^ (st->descram >> 1);
- descx ^= ((descx >> DESCRAM_TAPSH1) ^
- (descx >> DESCRAM_TAPSH2));
- st->shreg >>= 1;
- st->shreg |= (!(descx & 1)) << 16;
- if (st->shreg & 1) {
- hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1);
- st->shreg = 0x10000;
- }
- diag_trigger(sm);
- }
- diag_add_one(sm, *buf);
- }
-}
-
-/* --------------------------------------------------------------------- */
-
-static void demod_init_9600(struct sm_state *sm)
-{
- struct demod_state_fsk96 *st = (struct demod_state_fsk96 *)(&sm->d);
-
- st->dcd_time = 240;
- st->dcd_sum0 = 2;
-}
-
-/* --------------------------------------------------------------------- */
-
-const struct modem_tx_info sm_fsk9600_4_tx = {
- "fsk9600", sizeof(struct mod_state_fsk96), 38400, 9600,
- modulator_9600_4_u8, modulator_9600_4_s16, NULL
-};
-
-const struct modem_rx_info sm_fsk9600_4_rx = {
- "fsk9600", sizeof(struct demod_state_fsk96), 38400, 9600, 1, 4,
- demodulator_9600_4_u8, demodulator_9600_4_s16, demod_init_9600
-};
-
-/* --------------------------------------------------------------------- */
-
-const struct modem_tx_info sm_fsk9600_5_tx = {
- "fsk9600", sizeof(struct mod_state_fsk96), 48000, 9600,
- modulator_9600_5_u8, modulator_9600_5_s16, NULL
-};
-
-const struct modem_rx_info sm_fsk9600_5_rx = {
- "fsk9600", sizeof(struct demod_state_fsk96), 48000, 9600, 1, 5,
- demodulator_9600_5_u8, demodulator_9600_5_s16, demod_init_9600
-};
-
-/* --------------------------------------------------------------------- */
diff --git a/drivers/net/soundmodem/sm_hapn4800.c b/drivers/net/soundmodem/sm_hapn4800.c
index f6babcd9d..e69de29bb 100644
--- a/drivers/net/soundmodem/sm_hapn4800.c
+++ b/drivers/net/soundmodem/sm_hapn4800.c
@@ -1,560 +0,0 @@
-/*****************************************************************************/
-
-/*
- * sm_hapn4800.c -- soundcard radio modem driver, 4800 baud HAPN modem
- *
- * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Please note that the GPL allows you to use the driver, NOT the radio.
- * In order to use the radio, you need a license from the communications
- * authority of your country.
- *
- *
- * This module implements a (hopefully) HAPN (Hamilton Area Packet
- * Network) compatible 4800 baud modem.
- * The HAPN modem uses kind of "duobinary signalling" (not really,
- * duobinary signalling gives ... 0 0 -1 0 1 0 0 ... at the sampling
- * instants, whereas HAPN signalling gives ... 0 0 -1 1 0 0 ..., see
- * Proakis, Digital Communications).
- * The code is untested. It is compatible with itself (i.e. it can decode
- * the packets it sent), but I could not test if it is compatible with
- * any "real" HAPN modem, since noone uses it in my region of the world.
- * Feedback therefore welcome.
- */
-
-#include "sm.h"
-#include "sm_tbl_hapn4800.h"
-
-/* --------------------------------------------------------------------- */
-
-struct demod_state_hapn48 {
- unsigned int shreg;
- unsigned int bit_pll;
- unsigned char last_bit;
- unsigned char last_bit2;
- unsigned int dcd_shreg;
- int dcd_sum0, dcd_sum1, dcd_sum2;
- unsigned int dcd_time;
- int lvlhi, lvllo;
-};
-
-struct mod_state_hapn48 {
- unsigned int shreg;
- unsigned char tx_bit;
- unsigned int tx_seq;
- const unsigned char *tbl;
-};
-
-/* --------------------------------------------------------------------- */
-
-static void modulator_hapn4800_10_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen)
-{
- struct mod_state_hapn48 *st = (struct mod_state_hapn48 *)(&sm->m);
-
- for (; buflen > 0; buflen--, buf++) {
- if (!st->tx_seq++) {
- if (st->shreg <= 1)
- st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
- st->tx_bit = ((st->tx_bit << 1) |
- (st->tx_bit & 1));
- st->tx_bit ^= (!(st->shreg & 1));
- st->shreg >>= 1;
- st->tbl = hapn48_txfilt_10 + (st->tx_bit & 0xf);
- }
- if (st->tx_seq >= 10)
- st->tx_seq = 0;
- *buf = *st->tbl;
- st->tbl += 0x10;
- }
-}
-
-/* --------------------------------------------------------------------- */
-
-static void modulator_hapn4800_10_s16(struct sm_state *sm, short *buf, unsigned int buflen)
-{
- struct mod_state_hapn48 *st = (struct mod_state_hapn48 *)(&sm->m);
-
- for (; buflen > 0; buflen--, buf++) {
- if (!st->tx_seq++) {
- if (st->shreg <= 1)
- st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
- st->tx_bit = ((st->tx_bit << 1) |
- (st->tx_bit & 1));
- st->tx_bit ^= (!(st->shreg & 1));
- st->shreg >>= 1;
- st->tbl = hapn48_txfilt_10 + (st->tx_bit & 0xf);
- }
- if (st->tx_seq >= 10)
- st->tx_seq = 0;
- *buf = ((*st->tbl)-0x80)<<8;
- st->tbl += 0x10;
- }
-}
-
-/* --------------------------------------------------------------------- */
-
-static void modulator_hapn4800_8_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen)
-{
- struct mod_state_hapn48 *st = (struct mod_state_hapn48 *)(&sm->m);
-
- for (; buflen > 0; buflen--, buf++) {
- if (!st->tx_seq++) {
- if (st->shreg <= 1)
- st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
- st->tx_bit = (st->tx_bit << 1) | (st->tx_bit & 1);
- st->tx_bit ^= !(st->shreg & 1);
- st->shreg >>= 1;
- st->tbl = hapn48_txfilt_8 + (st->tx_bit & 0xf);
- }
- if (st->tx_seq >= 8)
- st->tx_seq = 0;
- *buf = *st->tbl;
- st->tbl += 0x10;
- }
-}
-
-/* --------------------------------------------------------------------- */
-
-static void modulator_hapn4800_8_s16(struct sm_state *sm, short *buf, unsigned int buflen)
-{
- struct mod_state_hapn48 *st = (struct mod_state_hapn48 *)(&sm->m);
-
- for (; buflen > 0; buflen--, buf++) {
- if (!st->tx_seq++) {
- if (st->shreg <= 1)
- st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
- st->tx_bit = (st->tx_bit << 1) | (st->tx_bit & 1);
- st->tx_bit ^= !(st->shreg & 1);
- st->shreg >>= 1;
- st->tbl = hapn48_txfilt_8 + (st->tx_bit & 0xf);
- }
- if (st->tx_seq >= 8)
- st->tx_seq = 0;
- *buf = ((*st->tbl)-0x80)<<8;
- st->tbl += 0x10;
- }
-}
-
-/* --------------------------------------------------------------------- */
-
-static void modulator_hapn4800_pm10_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen)
-{
- struct mod_state_hapn48 *st = (struct mod_state_hapn48 *)(&sm->m);
-
- for (; buflen > 0; buflen--, buf++) {
- if (!st->tx_seq++) {
- if (st->shreg <= 1)
- st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
- st->tx_bit = ((st->tx_bit << 1) |
- (st->tx_bit & 1));
- st->tx_bit ^= (!(st->shreg & 1));
- st->shreg >>= 1;
- st->tbl = hapn48_txfilt_pm10 + (st->tx_bit & 0xf);
- }
- if (st->tx_seq >= 10)
- st->tx_seq = 0;
- *buf = *st->tbl;
- st->tbl += 0x10;
- }
-}
-
-/* --------------------------------------------------------------------- */
-
-static void modulator_hapn4800_pm10_s16(struct sm_state *sm, short *buf, unsigned int buflen)
-{
- struct mod_state_hapn48 *st = (struct mod_state_hapn48 *)(&sm->m);
-
- for (; buflen > 0; buflen--, buf++) {
- if (!st->tx_seq++) {
- if (st->shreg <= 1)
- st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
- st->tx_bit = ((st->tx_bit << 1) |
- (st->tx_bit & 1));
- st->tx_bit ^= (!(st->shreg & 1));
- st->shreg >>= 1;
- st->tbl = hapn48_txfilt_pm10 + (st->tx_bit & 0xf);
- }
- if (st->tx_seq >= 10)
- st->tx_seq = 0;
- *buf = ((*st->tbl)-0x80)<<8;
- st->tbl += 0x10;
- }
-}
-
-/* --------------------------------------------------------------------- */
-
-static void modulator_hapn4800_pm8_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen)
-{
- struct mod_state_hapn48 *st = (struct mod_state_hapn48 *)(&sm->m);
-
- for (; buflen > 0; buflen--, buf++) {
- if (!st->tx_seq++) {
- if (st->shreg <= 1)
- st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
- st->tx_bit = (st->tx_bit << 1) | (st->tx_bit & 1);
- st->tx_bit ^= !(st->shreg & 1);
- st->shreg >>= 1;
- st->tbl = hapn48_txfilt_pm8 + (st->tx_bit & 0xf);
- }
- if (st->tx_seq >= 8)
- st->tx_seq = 0;
- *buf = *st->tbl;
- st->tbl += 0x10;
- }
-}
-
-/* --------------------------------------------------------------------- */
-
-static void modulator_hapn4800_pm8_s16(struct sm_state *sm, short *buf, unsigned int buflen)
-{
- struct mod_state_hapn48 *st = (struct mod_state_hapn48 *)(&sm->m);
-
- for (; buflen > 0; buflen--, buf++) {
- if (!st->tx_seq++) {
- if (st->shreg <= 1)
- st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
- st->tx_bit = (st->tx_bit << 1) | (st->tx_bit & 1);
- st->tx_bit ^= !(st->shreg & 1);
- st->shreg >>= 1;
- st->tbl = hapn48_txfilt_pm8 + (st->tx_bit & 0xf);
- }
- if (st->tx_seq >= 8)
- st->tx_seq = 0;
- *buf = ((*st->tbl)-0x80)<<8;
- st->tbl += 0x10;
- }
-}
-
-/* --------------------------------------------------------------------- */
-
-static void demodulator_hapn4800_10_u8(struct sm_state *sm, const unsigned char *buf, unsigned int buflen)
-{
- struct demod_state_hapn48 *st = (struct demod_state_hapn48 *)(&sm->d);
- static const int pll_corr[2] = { -0x800, 0x800 };
- int curst, cursync;
- int inv;
-
- for (; buflen > 0; buflen--, buf++) {
- inv = ((int)(buf[-2])-0x80) << 8;
- st->lvlhi = (st->lvlhi * 65309) >> 16; /* decay */
- st->lvllo = (st->lvllo * 65309) >> 16; /* decay */
- if (inv > st->lvlhi)
- st->lvlhi = inv;
- if (inv < st->lvllo)
- st->lvllo = inv;
- if (buflen & 1)
- st->dcd_shreg <<= 1;
- st->bit_pll += 0x199a;
- curst = cursync = 0;
- if (inv > st->lvlhi >> 1) {
- curst = 1;
- cursync = (buf[-2] > buf[-1] && buf[-2] > buf[-3] &&
- buf[-2] > buf[-0] && buf[-2] > buf[-4]);
- } else if (inv < st->lvllo >> 1) {
- curst = -1;
- cursync = (buf[-2] < buf[-1] && buf[-2] < buf[-3] &&
- buf[-2] < buf[-0] && buf[-2] < buf[-4]);
- }
- if (cursync) {
- st->dcd_shreg |= cursync;
- st->bit_pll += pll_corr[((st->bit_pll - 0x8000u) & 0xffffu) < 0x8ccdu];
- st->dcd_sum0 += 16 * hweight32(st->dcd_shreg & 0x18c6318c) -
- hweight32(st->dcd_shreg & 0xe739ce70);
- }
- hdlcdrv_channelbit(&sm->hdrv, cursync);
- if ((--st->dcd_time) <= 0) {
- hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 +
- st->dcd_sum1 +
- st->dcd_sum2) < 0);
- st->dcd_sum2 = st->dcd_sum1;
- st->dcd_sum1 = st->dcd_sum0;
- st->dcd_sum0 = 2; /* slight bias */
- st->dcd_time = 240;
- }
- if (st->bit_pll >= 0x10000) {
- st->bit_pll &= 0xffff;
- st->last_bit2 = st->last_bit;
- if (curst < 0)
- st->last_bit = 0;
- else if (curst > 0)
- st->last_bit = 1;
- st->shreg >>= 1;
- st->shreg |= ((st->last_bit ^ st->last_bit2 ^ 1) & 1) << 16;
- if (st->shreg & 1) {
- hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1);
- st->shreg = 0x10000;
- }
- diag_trigger(sm);
- }
- diag_add_one(sm, inv);
- }
-}
-
-/* --------------------------------------------------------------------- */
-
-static void demodulator_hapn4800_10_s16(struct sm_state *sm, const short *buf, unsigned int buflen)
-{
- struct demod_state_hapn48 *st = (struct demod_state_hapn48 *)(&sm->d);
- static const int pll_corr[2] = { -0x800, 0x800 };
- int curst, cursync;
- int inv;
-
- for (; buflen > 0; buflen--, buf++) {
- inv = buf[-2];
- st->lvlhi = (st->lvlhi * 65309) >> 16; /* decay */
- st->lvllo = (st->lvllo * 65309) >> 16; /* decay */
- if (inv > st->lvlhi)
- st->lvlhi = inv;
- if (inv < st->lvllo)
- st->lvllo = inv;
- if (buflen & 1)
- st->dcd_shreg <<= 1;
- st->bit_pll += 0x199a;
- curst = cursync = 0;
- if (inv > st->lvlhi >> 1) {
- curst = 1;
- cursync = (buf[-2] > buf[-1] && buf[-2] > buf[-3] &&
- buf[-2] > buf[-0] && buf[-2] > buf[-4]);
- } else if (inv < st->lvllo >> 1) {
- curst = -1;
- cursync = (buf[-2] < buf[-1] && buf[-2] < buf[-3] &&
- buf[-2] < buf[-0] && buf[-2] < buf[-4]);
- }
- if (cursync) {
- st->dcd_shreg |= cursync;
- st->bit_pll += pll_corr[((st->bit_pll - 0x8000u) & 0xffffu) < 0x8ccdu];
- st->dcd_sum0 += 16 * hweight32(st->dcd_shreg & 0x18c6318c) -
- hweight32(st->dcd_shreg & 0xe739ce70);
- }
- hdlcdrv_channelbit(&sm->hdrv, cursync);
- if ((--st->dcd_time) <= 0) {
- hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 +
- st->dcd_sum1 +
- st->dcd_sum2) < 0);
- st->dcd_sum2 = st->dcd_sum1;
- st->dcd_sum1 = st->dcd_sum0;
- st->dcd_sum0 = 2; /* slight bias */
- st->dcd_time = 240;
- }
- if (st->bit_pll >= 0x10000) {
- st->bit_pll &= 0xffff;
- st->last_bit2 = st->last_bit;
- if (curst < 0)
- st->last_bit = 0;
- else if (curst > 0)
- st->last_bit = 1;
- st->shreg >>= 1;
- st->shreg |= ((st->last_bit ^ st->last_bit2 ^ 1) & 1) << 16;
- if (st->shreg & 1) {
- hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1);
- st->shreg = 0x10000;
- }
- diag_trigger(sm);
- }
- diag_add_one(sm, inv);
- }
-}
-
-/* --------------------------------------------------------------------- */
-
-static void demodulator_hapn4800_8_u8(struct sm_state *sm, const unsigned char *buf, unsigned int buflen)
-{
- struct demod_state_hapn48 *st = (struct demod_state_hapn48 *)(&sm->d);
- static const int pll_corr[2] = { -0x800, 0x800 };
- int curst, cursync;
- int inv;
-
- for (; buflen > 0; buflen--, buf++) {
- inv = ((int)(buf[-2])-0x80) << 8;
- st->lvlhi = (st->lvlhi * 65309) >> 16; /* decay */
- st->lvllo = (st->lvllo * 65309) >> 16; /* decay */
- if (inv > st->lvlhi)
- st->lvlhi = inv;
- if (inv < st->lvllo)
- st->lvllo = inv;
- if (buflen & 1)
- st->dcd_shreg <<= 1;
- st->bit_pll += 0x2000;
- curst = cursync = 0;
- if (inv > st->lvlhi >> 1) {
- curst = 1;
- cursync = (buf[-2] > buf[-1] && buf[-2] > buf[-3] &&
- buf[-2] > buf[-0] && buf[-2] > buf[-4]);
- } else if (inv < st->lvllo >> 1) {
- curst = -1;
- cursync = (buf[-2] < buf[-1] && buf[-2] < buf[-3] &&
- buf[-2] < buf[-0] && buf[-2] < buf[-4]);
- }
- if (cursync) {
- st->dcd_shreg |= cursync;
- st->bit_pll += pll_corr[((st->bit_pll - 0x8000u) & 0xffffu) < 0x9000u];
- st->dcd_sum0 += 16 * hweight32(st->dcd_shreg & 0x44444444) -
- hweight32(st->dcd_shreg & 0xbbbbbbbb);
- }
- hdlcdrv_channelbit(&sm->hdrv, cursync);
- if ((--st->dcd_time) <= 0) {
- hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 +
- st->dcd_sum1 +
- st->dcd_sum2) < 0);
- st->dcd_sum2 = st->dcd_sum1;
- st->dcd_sum1 = st->dcd_sum0;
- st->dcd_sum0 = 2; /* slight bias */
- st->dcd_time = 240;
- }
- if (st->bit_pll >= 0x10000) {
- st->bit_pll &= 0xffff;
- st->last_bit2 = st->last_bit;
- if (curst < 0)
- st->last_bit = 0;
- else if (curst > 0)
- st->last_bit = 1;
- st->shreg >>= 1;
- st->shreg |= ((st->last_bit ^ st->last_bit2 ^ 1) & 1) << 16;
- if (st->shreg & 1) {
- hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1);
- st->shreg = 0x10000;
- }
- diag_trigger(sm);
- }
- diag_add_one(sm, inv);
- }
-}
-
-/* --------------------------------------------------------------------- */
-
-static void demodulator_hapn4800_8_s16(struct sm_state *sm, const short *buf, unsigned int buflen)
-{
- struct demod_state_hapn48 *st = (struct demod_state_hapn48 *)(&sm->d);
- static const int pll_corr[2] = { -0x800, 0x800 };
- int curst, cursync;
- int inv;
-
- for (; buflen > 0; buflen--, buf++) {
- inv = buf[-2];
- st->lvlhi = (st->lvlhi * 65309) >> 16; /* decay */
- st->lvllo = (st->lvllo * 65309) >> 16; /* decay */
- if (inv > st->lvlhi)
- st->lvlhi = inv;
- if (inv < st->lvllo)
- st->lvllo = inv;
- if (buflen & 1)
- st->dcd_shreg <<= 1;
- st->bit_pll += 0x2000;
- curst = cursync = 0;
- if (inv > st->lvlhi >> 1) {
- curst = 1;
- cursync = (buf[-2] > buf[-1] && buf[-2] > buf[-3] &&
- buf[-2] > buf[-0] && buf[-2] > buf[-4]);
- } else if (inv < st->lvllo >> 1) {
- curst = -1;
- cursync = (buf[-2] < buf[-1] && buf[-2] < buf[-3] &&
- buf[-2] < buf[-0] && buf[-2] < buf[-4]);
- }
- if (cursync) {
- st->dcd_shreg |= cursync;
- st->bit_pll += pll_corr[((st->bit_pll - 0x8000u) & 0xffffu) < 0x9000u];
- st->dcd_sum0 += 16 * hweight32(st->dcd_shreg & 0x44444444) -
- hweight32(st->dcd_shreg & 0xbbbbbbbb);
- }
- hdlcdrv_channelbit(&sm->hdrv, cursync);
- if ((--st->dcd_time) <= 0) {
- hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 +
- st->dcd_sum1 +
- st->dcd_sum2) < 0);
- st->dcd_sum2 = st->dcd_sum1;
- st->dcd_sum1 = st->dcd_sum0;
- st->dcd_sum0 = 2; /* slight bias */
- st->dcd_time = 240;
- }
- if (st->bit_pll >= 0x10000) {
- st->bit_pll &= 0xffff;
- st->last_bit2 = st->last_bit;
- if (curst < 0)
- st->last_bit = 0;
- else if (curst > 0)
- st->last_bit = 1;
- st->shreg >>= 1;
- st->shreg |= ((st->last_bit ^ st->last_bit2 ^ 1) & 1) << 16;
- if (st->shreg & 1) {
- hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1);
- st->shreg = 0x10000;
- }
- diag_trigger(sm);
- }
- diag_add_one(sm, inv);
- }
-}
-
-/* --------------------------------------------------------------------- */
-
-static void demod_init_hapn4800(struct sm_state *sm)
-{
- struct demod_state_hapn48 *st = (struct demod_state_hapn48 *)(&sm->d);
-
- st->dcd_time = 120;
- st->dcd_sum0 = 2;
-}
-
-/* --------------------------------------------------------------------- */
-
-const struct modem_tx_info sm_hapn4800_8_tx = {
- "hapn4800", sizeof(struct mod_state_hapn48), 38400, 4800,
- modulator_hapn4800_8_u8, modulator_hapn4800_8_s16, NULL
-};
-
-const struct modem_rx_info sm_hapn4800_8_rx = {
- "hapn4800", sizeof(struct demod_state_hapn48), 38400, 4800, 5, 8,
- demodulator_hapn4800_8_u8, demodulator_hapn4800_8_s16, demod_init_hapn4800
-};
-
-/* --------------------------------------------------------------------- */
-
-const struct modem_tx_info sm_hapn4800_10_tx = {
- "hapn4800", sizeof(struct mod_state_hapn48), 48000, 4800,
- modulator_hapn4800_10_u8, modulator_hapn4800_10_s16, NULL
-};
-
-const struct modem_rx_info sm_hapn4800_10_rx = {
- "hapn4800", sizeof(struct demod_state_hapn48), 48000, 4800, 5, 10,
- demodulator_hapn4800_10_u8, demodulator_hapn4800_10_s16, demod_init_hapn4800
-};
-
-/* --------------------------------------------------------------------- */
-
-const struct modem_tx_info sm_hapn4800_pm8_tx = {
- "hapn4800pm", sizeof(struct mod_state_hapn48), 38400, 4800,
- modulator_hapn4800_pm8_u8, modulator_hapn4800_pm8_s16, NULL
-};
-
-const struct modem_rx_info sm_hapn4800_pm8_rx = {
- "hapn4800pm", sizeof(struct demod_state_hapn48), 38400, 4800, 5, 8,
- demodulator_hapn4800_8_u8, demodulator_hapn4800_8_s16, demod_init_hapn4800
-};
-
-/* --------------------------------------------------------------------- */
-
-const struct modem_tx_info sm_hapn4800_pm10_tx = {
- "hapn4800pm", sizeof(struct mod_state_hapn48), 48000, 4800,
- modulator_hapn4800_pm10_u8, modulator_hapn4800_pm10_s16, NULL
-};
-
-const struct modem_rx_info sm_hapn4800_pm10_rx = {
- "hapn4800pm", sizeof(struct demod_state_hapn48), 48000, 4800, 5, 10,
- demodulator_hapn4800_10_u8, demodulator_hapn4800_10_s16, demod_init_hapn4800
-};
-
-/* --------------------------------------------------------------------- */
diff --git a/drivers/net/soundmodem/sm_sbc.c b/drivers/net/soundmodem/sm_sbc.c
index bbef05a5d..e69de29bb 100644
--- a/drivers/net/soundmodem/sm_sbc.c
+++ b/drivers/net/soundmodem/sm_sbc.c
@@ -1,941 +0,0 @@
-/*****************************************************************************/
-
-/*
- * sm_sbc.c -- soundcard radio modem driver soundblaster hardware driver
- *
- * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Please note that the GPL allows you to use the driver, NOT the radio.
- * In order to use the radio, you need a license from the communications
- * authority of your country.
- *
- */
-
-#include <linux/ptrace.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <linux/ioport.h>
-#include <linux/soundmodem.h>
-#include "sm.h"
-#include "smdma.h"
-
-/* --------------------------------------------------------------------- */
-
-/*
- * currently this module is supposed to support both module styles, i.e.
- * the old one present up to about 2.1.9, and the new one functioning
- * starting with 2.1.21. The reason is I have a kit allowing to compile
- * this module also under 2.0.x which was requested by several people.
- * This will go in 2.2
- */
-#include <linux/version.h>
-
-#if LINUX_VERSION_CODE >= 0x20100
-#include <asm/uaccess.h>
-#else
-#include <asm/segment.h>
-#include <linux/mm.h>
-
-#undef put_user
-#undef get_user
-
-#define put_user(x,ptr) ({ __put_user((unsigned long)(x),(ptr),sizeof(*(ptr))); 0; })
-#define get_user(x,ptr) ({ x = ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr)))); 0; })
-
-extern inline int copy_from_user(void *to, const void *from, unsigned long n)
-{
- int i = verify_area(VERIFY_READ, from, n);
- if (i)
- return i;
- memcpy_fromfs(to, from, n);
- return 0;
-}
-
-extern inline int copy_to_user(void *to, const void *from, unsigned long n)
-{
- int i = verify_area(VERIFY_WRITE, to, n);
- if (i)
- return i;
- memcpy_tofs(to, from, n);
- return 0;
-}
-#endif
-
-/* --------------------------------------------------------------------- */
-
-struct sc_state_sbc {
- unsigned char revhi, revlo;
- unsigned char fmt[2];
- unsigned int sr[2];
-};
-
-#define SCSTATE ((struct sc_state_sbc *)(&sm->hw))
-
-/* --------------------------------------------------------------------- */
-/*
- * the sbc converter's registers
- */
-#define DSP_RESET(iobase) (iobase+0x6)
-#define DSP_READ_DATA(iobase) (iobase+0xa)
-#define DSP_WRITE_DATA(iobase) (iobase+0xc)
-#define DSP_WRITE_STATUS(iobase) (iobase+0xc)
-#define DSP_DATA_AVAIL(iobase) (iobase+0xe)
-#define DSP_MIXER_ADDR(iobase) (iobase+0x4)
-#define DSP_MIXER_DATA(iobase) (iobase+0x5)
-#define DSP_INTACK_16BIT(iobase) (iobase+0xf)
-#define SBC_EXTENT 16
-
-/* --------------------------------------------------------------------- */
-/*
- * SBC commands
- */
-#define SBC_OUTPUT 0x14
-#define SBC_INPUT 0x24
-#define SBC_BLOCKSIZE 0x48
-#define SBC_HI_OUTPUT 0x91
-#define SBC_HI_INPUT 0x99
-#define SBC_LO_OUTPUT_AUTOINIT 0x1c
-#define SBC_LO_INPUT_AUTOINIT 0x2c
-#define SBC_HI_OUTPUT_AUTOINIT 0x90
-#define SBC_HI_INPUT_AUTOINIT 0x98
-#define SBC_IMMED_INT 0xf2
-#define SBC_GET_REVISION 0xe1
-#define ESS_GET_REVISION 0xe7
-#define SBC_SPEAKER_ON 0xd1
-#define SBC_SPEAKER_OFF 0xd3
-#define SBC_DMA_ON 0xd0
-#define SBC_DMA_OFF 0xd4
-#define SBC_SAMPLE_RATE 0x40
-#define SBC_SAMPLE_RATE_OUT 0x41
-#define SBC_SAMPLE_RATE_IN 0x42
-#define SBC_MONO_8BIT 0xa0
-#define SBC_MONO_16BIT 0xa4
-#define SBC_STEREO_8BIT 0xa8
-#define SBC_STEREO_16BIT 0xac
-
-#define SBC4_OUT8_AI 0xc6
-#define SBC4_IN8_AI 0xce
-#define SBC4_MODE_UNS_MONO 0x00
-#define SBC4_MODE_SIGN_MONO 0x10
-
-#define SBC4_OUT16_AI 0xb6
-#define SBC4_IN16_AI 0xbe
-
-/* --------------------------------------------------------------------- */
-
-static int inline reset_dsp(struct device *dev)
-{
- int i;
-
- outb(1, DSP_RESET(dev->base_addr));
- for (i = 0; i < 0x100; i++)
- SLOW_DOWN_IO;
- outb(0, DSP_RESET(dev->base_addr));
- for (i = 0; i < 0xffff; i++)
- if (inb(DSP_DATA_AVAIL(dev->base_addr)) & 0x80)
- if (inb(DSP_READ_DATA(dev->base_addr)) == 0xaa)
- return 1;
- return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static void inline write_dsp(struct device *dev, unsigned char data)
-{
- int i;
-
- for (i = 0; i < 0xffff; i++)
- if (!(inb(DSP_WRITE_STATUS(dev->base_addr)) & 0x80)) {
- outb(data, DSP_WRITE_DATA(dev->base_addr));
- return;
- }
-}
-
-/* --------------------------------------------------------------------- */
-
-static int inline read_dsp(struct device *dev, unsigned char *data)
-{
- int i;
-
- if (!data)
- return 0;
- for (i = 0; i < 0xffff; i++)
- if (inb(DSP_DATA_AVAIL(dev->base_addr)) & 0x80) {
- *data = inb(DSP_READ_DATA(dev->base_addr));
- return 1;
- }
- return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int config_resources(struct device *dev, struct sm_state *sm, int fdx)
-{
- unsigned char irqreg = 0, dmareg = 0, realirq, realdma;
- unsigned long flags;
-
- switch (dev->irq) {
- case 2:
- case 9:
- irqreg |= 0x01;
- break;
-
- case 5:
- irqreg |= 0x02;
- break;
-
- case 7:
- irqreg |= 0x04;
- break;
-
- case 10:
- irqreg |= 0x08;
- break;
-
- default:
- return -ENODEV;
- }
-
- switch (dev->dma) {
- case 0:
- dmareg |= 0x01;
- break;
-
- case 1:
- dmareg |= 0x02;
- break;
-
- case 3:
- dmareg |= 0x08;
- break;
-
- default:
- return -ENODEV;
- }
-
- if (fdx) {
- switch (sm->hdrv.ptt_out.dma2) {
- case 5:
- dmareg |= 0x20;
- break;
-
- case 6:
- dmareg |= 0x40;
- break;
-
- case 7:
- dmareg |= 0x80;
- break;
-
- default:
- return -ENODEV;
- }
- }
- save_flags(flags);
- cli();
- outb(0x80, DSP_MIXER_ADDR(dev->base_addr));
- outb(irqreg, DSP_MIXER_DATA(dev->base_addr));
- realirq = inb(DSP_MIXER_DATA(dev->base_addr));
- outb(0x81, DSP_MIXER_ADDR(dev->base_addr));
- outb(dmareg, DSP_MIXER_DATA(dev->base_addr));
- realdma = inb(DSP_MIXER_DATA(dev->base_addr));
- restore_flags(flags);
- if ((~realirq) & irqreg || (~realdma) & dmareg) {
- printk(KERN_ERR "%s: sbc resource registers cannot be set; PnP device "
- "and IRQ/DMA specified wrongly?\n", sm_drvname);
- return -EINVAL;
- }
- return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static void inline sbc_int_ack_8bit(struct device *dev)
-{
- inb(DSP_DATA_AVAIL(dev->base_addr));
-}
-
-/* --------------------------------------------------------------------- */
-
-static void inline sbc_int_ack_16bit(struct device *dev)
-{
- inb(DSP_INTACK_16BIT(dev->base_addr));
-}
-
-/* --------------------------------------------------------------------- */
-
-static void setup_dma_dsp(struct device *dev, struct sm_state *sm, int send)
-{
- unsigned long flags;
- static const unsigned char sbcmode[2][2] = {
- { SBC_LO_INPUT_AUTOINIT, SBC_LO_OUTPUT_AUTOINIT },
- { SBC_HI_INPUT_AUTOINIT, SBC_HI_OUTPUT_AUTOINIT }
- };
- static const unsigned char sbc4mode[2] = { SBC4_IN8_AI, SBC4_OUT8_AI };
- static const unsigned char sbcskr[2] = { SBC_SPEAKER_OFF, SBC_SPEAKER_ON };
- unsigned int nsamps;
-
- send = !!send;
- if (!reset_dsp(dev)) {
- printk(KERN_ERR "%s: sbc: cannot reset sb dsp\n", sm_drvname);
- return;
- }
- save_flags(flags);
- cli();
- sbc_int_ack_8bit(dev);
- write_dsp(dev, SBC_SAMPLE_RATE); /* set sampling rate */
- write_dsp(dev, SCSTATE->fmt[send]);
- write_dsp(dev, sbcskr[send]);
- nsamps = dma_setup(sm, send, dev->dma) - 1;
- sbc_int_ack_8bit(dev);
- if (SCSTATE->revhi >= 4) {
- write_dsp(dev, sbc4mode[send]);
- write_dsp(dev, SBC4_MODE_UNS_MONO);
- write_dsp(dev, nsamps & 0xff);
- write_dsp(dev, nsamps >> 8);
- } else {
- write_dsp(dev, SBC_BLOCKSIZE);
- write_dsp(dev, nsamps & 0xff);
- write_dsp(dev, nsamps >> 8);
- write_dsp(dev, sbcmode[SCSTATE->fmt[send] >= 180][send]);
- /* hispeed mode if sample rate > 13kHz */
- }
- restore_flags(flags);
-}
-
-/* --------------------------------------------------------------------- */
-
-static void sbc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- struct device *dev = (struct device *)dev_id;
- struct sm_state *sm = (struct sm_state *)dev->priv;
- unsigned int curfrag;
-
- if (!dev || !sm || sm->hdrv.magic != HDLCDRV_MAGIC)
- return;
- cli();
- sbc_int_ack_8bit(dev);
- disable_dma(dev->dma);
- clear_dma_ff(dev->dma);
- dma_ptr(sm, sm->dma.ptt_cnt > 0, dev->dma, &curfrag);
- enable_dma(dev->dma);
- sm_int_freq(sm);
- sti();
- if (sm->dma.ptt_cnt <= 0) {
- dma_receive(sm, curfrag);
- hdlcdrv_arbitrate(dev, &sm->hdrv);
- if (hdlcdrv_ptt(&sm->hdrv)) {
- /* starting to transmit */
- disable_dma(dev->dma);
- hdlcdrv_transmitter(dev, &sm->hdrv); /* prefill HDLC buffer */
- dma_start_transmit(sm);
- setup_dma_dsp(dev, sm, 1);
- dma_transmit(sm);
- }
- } else if (dma_end_transmit(sm, curfrag)) {
- /* stopping transmission */
- disable_dma(dev->dma);
- sti();
- dma_init_receive(sm);
- setup_dma_dsp(dev, sm, 0);
- } else
- dma_transmit(sm);
- sm_output_status(sm);
- hdlcdrv_transmitter(dev, &sm->hdrv);
- hdlcdrv_receiver(dev, &sm->hdrv);
-
-}
-
-/* --------------------------------------------------------------------- */
-
-static int sbc_open(struct device *dev, struct sm_state *sm)
-{
- int err;
- unsigned int dmasz, u;
-
- if (sizeof(sm->m) < sizeof(struct sc_state_sbc)) {
- printk(KERN_ERR "sm sbc: sbc state too big: %d > %d\n",
- sizeof(struct sc_state_sbc), sizeof(sm->m));
- return -ENODEV;
- }
- if (!dev || !sm)
- return -ENXIO;
- if (dev->base_addr <= 0 || dev->base_addr > 0x1000-SBC_EXTENT ||
- dev->irq < 2 || dev->irq > 15 || dev->dma > 3)
- return -ENXIO;
- if (check_region(dev->base_addr, SBC_EXTENT))
- return -EACCES;
- /*
- * check if a card is available
- */
- if (!reset_dsp(dev)) {
- printk(KERN_ERR "%s: sbc: no card at io address 0x%lx\n",
- sm_drvname, dev->base_addr);
- return -ENODEV;
- }
- write_dsp(dev, SBC_GET_REVISION);
- if (!read_dsp(dev, &SCSTATE->revhi) ||
- !read_dsp(dev, &SCSTATE->revlo))
- return -ENODEV;
- printk(KERN_INFO "%s: SoundBlaster DSP revision %d.%d\n", sm_drvname,
- SCSTATE->revhi, SCSTATE->revlo);
- if (SCSTATE->revhi < 2) {
- printk(KERN_ERR "%s: your card is an antiquity, at least DSP "
- "rev 2.00 required\n", sm_drvname);
- return -ENODEV;
- }
- if (SCSTATE->revhi < 3 &&
- (SCSTATE->fmt[0] >= 180 || SCSTATE->fmt[1] >= 180)) {
- printk(KERN_ERR "%s: sbc io 0x%lx: DSP rev %d.%02d too "
- "old, at least 3.00 required\n", sm_drvname,
- dev->base_addr, SCSTATE->revhi, SCSTATE->revlo);
- return -ENODEV;
- }
- if (SCSTATE->revhi >= 4 &&
- (err = config_resources(dev, sm, 0))) {
- printk(KERN_ERR "%s: invalid IRQ and/or DMA specified\n", sm_drvname);
- return err;
- }
- /*
- * initialize some variables
- */
- dma_init_receive(sm);
- dmasz = (NUM_FRAGMENTS + 1) * sm->dma.ifragsz;
- u = NUM_FRAGMENTS * sm->dma.ofragsz;
- if (u > dmasz)
- dmasz = u;
- if (!(sm->dma.ibuf = sm->dma.obuf = kmalloc(dmasz, GFP_KERNEL | GFP_DMA)))
- return -ENOMEM;
- dma_init_transmit(sm);
- dma_init_receive(sm);
-
- memset(&sm->m, 0, sizeof(sm->m));
- memset(&sm->d, 0, sizeof(sm->d));
- if (sm->mode_tx->init)
- sm->mode_tx->init(sm);
- if (sm->mode_rx->init)
- sm->mode_rx->init(sm);
-
- if (request_dma(dev->dma, sm->hwdrv->hw_name)) {
- kfree_s(sm->dma.obuf, dmasz);
- return -EBUSY;
- }
- if (request_irq(dev->irq, sbc_interrupt, SA_INTERRUPT,
- sm->hwdrv->hw_name, dev)) {
- free_dma(dev->dma);
- kfree_s(sm->dma.obuf, dmasz);
- return -EBUSY;
- }
- request_region(dev->base_addr, SBC_EXTENT, sm->hwdrv->hw_name);
- setup_dma_dsp(dev, sm, 0);
- return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int sbc_close(struct device *dev, struct sm_state *sm)
-{
- if (!dev || !sm)
- return -EINVAL;
- /*
- * disable interrupts
- */
- disable_dma(dev->dma);
- reset_dsp(dev);
- free_irq(dev->irq, dev);
- free_dma(dev->dma);
- release_region(dev->base_addr, SBC_EXTENT);
- kfree(sm->dma.obuf);
- return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int sbc_sethw(struct device *dev, struct sm_state *sm, char *mode)
-{
- char *cp = strchr(mode, '.');
- const struct modem_tx_info **mtp = sm_modem_tx_table;
- const struct modem_rx_info **mrp;
-
- if (!strcmp(mode, "off")) {
- sm->mode_tx = NULL;
- sm->mode_rx = NULL;
- return 0;
- }
- if (cp)
- *cp++ = '\0';
- else
- cp = mode;
- for (; *mtp; mtp++) {
- if ((*mtp)->loc_storage > sizeof(sm->m)) {
- printk(KERN_ERR "%s: insufficient storage for modulator %s (%d)\n",
- sm_drvname, (*mtp)->name, (*mtp)->loc_storage);
- continue;
- }
- if (!(*mtp)->name || strcmp((*mtp)->name, mode))
- continue;
- if ((*mtp)->srate < 5000 || (*mtp)->srate > 44100)
- continue;
- if (!(*mtp)->modulator_u8)
- continue;
- for (mrp = sm_modem_rx_table; *mrp; mrp++) {
- if ((*mrp)->loc_storage > sizeof(sm->d)) {
- printk(KERN_ERR "%s: insufficient storage for demodulator %s (%d)\n",
- sm_drvname, (*mrp)->name, (*mrp)->loc_storage);
- continue;
- }
- if (!(*mrp)->demodulator_u8)
- continue;
- if ((*mrp)->name && !strcmp((*mrp)->name, cp) &&
- (*mrp)->srate >= 5000 && (*mrp)->srate <= 44100) {
- sm->mode_tx = *mtp;
- sm->mode_rx = *mrp;
- SCSTATE->fmt[0] = 256-((1000000L+sm->mode_rx->srate/2)/
- sm->mode_rx->srate);
- SCSTATE->fmt[1] = 256-((1000000L+sm->mode_tx->srate/2)/
- sm->mode_tx->srate);
- sm->dma.ifragsz = (sm->mode_rx->srate + 50)/100;
- sm->dma.ofragsz = (sm->mode_tx->srate + 50)/100;
- if (sm->dma.ifragsz < sm->mode_rx->overlap)
- sm->dma.ifragsz = sm->mode_rx->overlap;
- sm->dma.i16bit = sm->dma.o16bit = 0;
- return 0;
- }
- }
- }
- return -EINVAL;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int sbc_ioctl(struct device *dev, struct sm_state *sm, struct ifreq *ifr,
- struct hdlcdrv_ioctl *hi, int cmd)
-{
- struct sm_ioctl bi;
- unsigned long flags;
- int i;
-
- if (cmd != SIOCDEVPRIVATE)
- return -ENOIOCTLCMD;
-
- if (hi->cmd == HDLCDRVCTL_MODEMPARMASK)
- return HDLCDRV_PARMASK_IOBASE | HDLCDRV_PARMASK_IRQ |
- HDLCDRV_PARMASK_DMA | HDLCDRV_PARMASK_SERIOBASE |
- HDLCDRV_PARMASK_PARIOBASE | HDLCDRV_PARMASK_MIDIIOBASE;
-
- if (copy_from_user(&bi, ifr->ifr_data, sizeof(bi)))
- return -EFAULT;
-
- switch (bi.cmd) {
- default:
- return -ENOIOCTLCMD;
-
- case SMCTL_GETMIXER:
- i = 0;
- bi.data.mix.sample_rate = sm->mode_rx->srate;
- bi.data.mix.bit_rate = sm->hdrv.par.bitrate;
- bi.data.mix.mixer_type = SM_MIXER_INVALID;
- switch (SCSTATE->revhi) {
- case 2:
- bi.data.mix.mixer_type = SM_MIXER_CT1335;
- break;
- case 3:
- bi.data.mix.mixer_type = SM_MIXER_CT1345;
- break;
- case 4:
- bi.data.mix.mixer_type = SM_MIXER_CT1745;
- break;
- }
- if (bi.data.mix.mixer_type != SM_MIXER_INVALID &&
- bi.data.mix.reg < 0x80) {
- save_flags(flags);
- cli();
- outb(bi.data.mix.reg, DSP_MIXER_ADDR(dev->base_addr));
- bi.data.mix.data = inb(DSP_MIXER_DATA(dev->base_addr));
- restore_flags(flags);
- i = 1;
- }
- if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi)))
- return -EFAULT;
- return i;
-
- case SMCTL_SETMIXER:
- if (!suser())
- return -EACCES;
- switch (SCSTATE->revhi) {
- case 2:
- if (bi.data.mix.mixer_type != SM_MIXER_CT1335)
- return -EINVAL;
- break;
- case 3:
- if (bi.data.mix.mixer_type != SM_MIXER_CT1345)
- return -EINVAL;
- break;
- case 4:
- if (bi.data.mix.mixer_type != SM_MIXER_CT1745)
- return -EINVAL;
- break;
- default:
- return -ENODEV;
- }
- if (bi.data.mix.reg >= 0x80)
- return -EACCES;
- save_flags(flags);
- cli();
- outb(bi.data.mix.reg, DSP_MIXER_ADDR(dev->base_addr));
- outb(bi.data.mix.data, DSP_MIXER_DATA(dev->base_addr));
- restore_flags(flags);
- return 0;
-
- }
- if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi)))
- return -EFAULT;
- return 0;
-
-}
-
-/* --------------------------------------------------------------------- */
-
-const struct hardware_info sm_hw_sbc = {
- "sbc", sizeof(struct sc_state_sbc),
- sbc_open, sbc_close, sbc_ioctl, sbc_sethw
-};
-
-/* --------------------------------------------------------------------- */
-
-static void setup_dma_fdx_dsp(struct device *dev, struct sm_state *sm)
-{
- unsigned long flags;
- unsigned int isamps, osamps;
-
- if (!reset_dsp(dev)) {
- printk(KERN_ERR "%s: sbc: cannot reset sb dsp\n", sm_drvname);
- return;
- }
- save_flags(flags);
- cli();
- sbc_int_ack_8bit(dev);
- sbc_int_ack_16bit(dev);
- /* should eventually change to set rates individually by SBC_SAMPLE_RATE_{IN/OUT} */
- write_dsp(dev, SBC_SAMPLE_RATE_IN);
- write_dsp(dev, SCSTATE->sr[0] >> 8);
- write_dsp(dev, SCSTATE->sr[0] & 0xff);
- write_dsp(dev, SBC_SAMPLE_RATE_OUT);
- write_dsp(dev, SCSTATE->sr[1] >> 8);
- write_dsp(dev, SCSTATE->sr[1] & 0xff);
- write_dsp(dev, SBC_SPEAKER_ON);
- if (sm->dma.o16bit) {
- /*
- * DMA channel 1 (8bit) does input (capture),
- * DMA channel 2 (16bit) does output (playback)
- */
- isamps = dma_setup(sm, 0, dev->dma) - 1;
- osamps = dma_setup(sm, 1, sm->hdrv.ptt_out.dma2) - 1;
- sbc_int_ack_8bit(dev);
- sbc_int_ack_16bit(dev);
- write_dsp(dev, SBC4_IN8_AI);
- write_dsp(dev, SBC4_MODE_UNS_MONO);
- write_dsp(dev, isamps & 0xff);
- write_dsp(dev, isamps >> 8);
- write_dsp(dev, SBC4_OUT16_AI);
- write_dsp(dev, SBC4_MODE_SIGN_MONO);
- write_dsp(dev, osamps & 0xff);
- write_dsp(dev, osamps >> 8);
- } else {
- /*
- * DMA channel 1 (8bit) does output (playback),
- * DMA channel 2 (16bit) does input (capture)
- */
- isamps = dma_setup(sm, 0, sm->hdrv.ptt_out.dma2) - 1;
- osamps = dma_setup(sm, 1, dev->dma) - 1;
- sbc_int_ack_8bit(dev);
- sbc_int_ack_16bit(dev);
- write_dsp(dev, SBC4_OUT8_AI);
- write_dsp(dev, SBC4_MODE_UNS_MONO);
- write_dsp(dev, osamps & 0xff);
- write_dsp(dev, osamps >> 8);
- write_dsp(dev, SBC4_IN16_AI);
- write_dsp(dev, SBC4_MODE_SIGN_MONO);
- write_dsp(dev, isamps & 0xff);
- write_dsp(dev, isamps >> 8);
- }
- dma_init_receive(sm);
- dma_init_transmit(sm);
- restore_flags(flags);
-}
-
-/* --------------------------------------------------------------------- */
-
-static void sbcfdx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- struct device *dev = (struct device *)dev_id;
- struct sm_state *sm = (struct sm_state *)dev->priv;
- unsigned char intsrc, pbint = 0, captint = 0;
- unsigned int ocfrag, icfrag;
- unsigned long flags;
-
- if (!dev || !sm || sm->hdrv.magic != HDLCDRV_MAGIC)
- return;
- save_flags(flags);
- cli();
- outb(0x82, DSP_MIXER_ADDR(dev->base_addr));
- intsrc = inb(DSP_MIXER_DATA(dev->base_addr));
- if (intsrc & 0x01) {
- sbc_int_ack_8bit(dev);
- if (sm->dma.o16bit) {
- captint = 1;
- disable_dma(dev->dma);
- clear_dma_ff(dev->dma);
- dma_ptr(sm, 0, dev->dma, &icfrag);
- enable_dma(dev->dma);
- } else {
- pbint = 1;
- disable_dma(dev->dma);
- clear_dma_ff(dev->dma);
- dma_ptr(sm, 1, dev->dma, &ocfrag);
- enable_dma(dev->dma);
- }
- }
- if (intsrc & 0x02) {
- sbc_int_ack_16bit(dev);
- if (sm->dma.o16bit) {
- pbint = 1;
- disable_dma(sm->hdrv.ptt_out.dma2);
- clear_dma_ff(sm->hdrv.ptt_out.dma2);
- dma_ptr(sm, 1, sm->hdrv.ptt_out.dma2, &ocfrag);
- enable_dma(sm->hdrv.ptt_out.dma2);
- } else {
- captint = 1;
- disable_dma(sm->hdrv.ptt_out.dma2);
- clear_dma_ff(sm->hdrv.ptt_out.dma2);
- dma_ptr(sm, 0, sm->hdrv.ptt_out.dma2, &icfrag);
- enable_dma(sm->hdrv.ptt_out.dma2);
- }
- }
- restore_flags(flags);
- sm_int_freq(sm);
- sti();
- if (pbint) {
- if (dma_end_transmit(sm, ocfrag))
- dma_clear_transmit(sm);
- dma_transmit(sm);
- }
- if (captint) {
- dma_receive(sm, icfrag);
- hdlcdrv_arbitrate(dev, &sm->hdrv);
- }
- sm_output_status(sm);
- hdlcdrv_transmitter(dev, &sm->hdrv);
- hdlcdrv_receiver(dev, &sm->hdrv);
-}
-
-/* --------------------------------------------------------------------- */
-
-static int sbcfdx_open(struct device *dev, struct sm_state *sm)
-{
- int err;
-
- if (sizeof(sm->m) < sizeof(struct sc_state_sbc)) {
- printk(KERN_ERR "sm sbc: sbc state too big: %d > %d\n",
- sizeof(struct sc_state_sbc), sizeof(sm->m));
- return -ENODEV;
- }
- if (!dev || !sm)
- return -ENXIO;
- if (dev->base_addr <= 0 || dev->base_addr > 0x1000-SBC_EXTENT ||
- dev->irq < 2 || dev->irq > 15 || dev->dma > 3)
- return -ENXIO;
- if (check_region(dev->base_addr, SBC_EXTENT))
- return -EACCES;
- /*
- * check if a card is available
- */
- if (!reset_dsp(dev)) {
- printk(KERN_ERR "%s: sbc: no card at io address 0x%lx\n",
- sm_drvname, dev->base_addr);
- return -ENODEV;
- }
- write_dsp(dev, SBC_GET_REVISION);
- if (!read_dsp(dev, &SCSTATE->revhi) ||
- !read_dsp(dev, &SCSTATE->revlo))
- return -ENODEV;
- printk(KERN_INFO "%s: SoundBlaster DSP revision %d.%d\n", sm_drvname,
- SCSTATE->revhi, SCSTATE->revlo);
- if (SCSTATE->revhi < 4) {
- printk(KERN_ERR "%s: at least DSP rev 4.00 required\n", sm_drvname);
- return -ENODEV;
- }
- if ((err = config_resources(dev, sm, 1))) {
- printk(KERN_ERR "%s: invalid IRQ and/or DMA specified\n", sm_drvname);
- return err;
- }
- /*
- * initialize some variables
- */
- if (!(sm->dma.ibuf = kmalloc(sm->dma.ifragsz * (NUM_FRAGMENTS+1), GFP_KERNEL | GFP_DMA)))
- return -ENOMEM;
- if (!(sm->dma.obuf = kmalloc(sm->dma.ofragsz * NUM_FRAGMENTS, GFP_KERNEL | GFP_DMA))) {
- kfree(sm->dma.ibuf);
- return -ENOMEM;
- }
- dma_init_transmit(sm);
- dma_init_receive(sm);
-
- memset(&sm->m, 0, sizeof(sm->m));
- memset(&sm->d, 0, sizeof(sm->d));
- if (sm->mode_tx->init)
- sm->mode_tx->init(sm);
- if (sm->mode_rx->init)
- sm->mode_rx->init(sm);
-
- if (request_dma(dev->dma, sm->hwdrv->hw_name)) {
- kfree(sm->dma.ibuf);
- kfree(sm->dma.obuf);
- return -EBUSY;
- }
- if (request_dma(sm->hdrv.ptt_out.dma2, sm->hwdrv->hw_name)) {
- kfree(sm->dma.ibuf);
- kfree(sm->dma.obuf);
- free_dma(dev->dma);
- return -EBUSY;
- }
- if (request_irq(dev->irq, sbcfdx_interrupt, SA_INTERRUPT,
- sm->hwdrv->hw_name, dev)) {
- kfree(sm->dma.ibuf);
- kfree(sm->dma.obuf);
- free_dma(dev->dma);
- free_dma(sm->hdrv.ptt_out.dma2);
- return -EBUSY;
- }
- request_region(dev->base_addr, SBC_EXTENT, sm->hwdrv->hw_name);
- setup_dma_fdx_dsp(dev, sm);
- return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int sbcfdx_close(struct device *dev, struct sm_state *sm)
-{
- if (!dev || !sm)
- return -EINVAL;
- /*
- * disable interrupts
- */
- disable_dma(dev->dma);
- disable_dma(sm->hdrv.ptt_out.dma2);
- reset_dsp(dev);
- free_irq(dev->irq, dev);
- free_dma(dev->dma);
- free_dma(sm->hdrv.ptt_out.dma2);
- release_region(dev->base_addr, SBC_EXTENT);
- kfree(sm->dma.ibuf);
- kfree(sm->dma.obuf);
- return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int sbcfdx_sethw(struct device *dev, struct sm_state *sm, char *mode)
-{
- char *cp = strchr(mode, '.');
- const struct modem_tx_info **mtp = sm_modem_tx_table;
- const struct modem_rx_info **mrp;
-
- if (!strcmp(mode, "off")) {
- sm->mode_tx = NULL;
- sm->mode_rx = NULL;
- return 0;
- }
- if (cp)
- *cp++ = '\0';
- else
- cp = mode;
- for (; *mtp; mtp++) {
- if ((*mtp)->loc_storage > sizeof(sm->m)) {
- printk(KERN_ERR "%s: insufficient storage for modulator %s (%d)\n",
- sm_drvname, (*mtp)->name, (*mtp)->loc_storage);
- continue;
- }
- if (!(*mtp)->name || strcmp((*mtp)->name, mode))
- continue;
- if ((*mtp)->srate < 5000 || (*mtp)->srate > 44100)
- continue;
- for (mrp = sm_modem_rx_table; *mrp; mrp++) {
- if ((*mrp)->loc_storage > sizeof(sm->d)) {
- printk(KERN_ERR "%s: insufficient storage for demodulator %s (%d)\n",
- sm_drvname, (*mrp)->name, (*mrp)->loc_storage);
- continue;
- }
- if ((*mrp)->name && !strcmp((*mrp)->name, cp) &&
- (*mtp)->srate >= 5000 && (*mtp)->srate <= 44100 &&
- (*mrp)->srate == (*mtp)->srate) {
- sm->mode_tx = *mtp;
- sm->mode_rx = *mrp;
- SCSTATE->sr[0] = sm->mode_rx->srate;
- SCSTATE->sr[1] = sm->mode_tx->srate;
- sm->dma.ifragsz = (sm->mode_rx->srate + 50)/100;
- sm->dma.ofragsz = (sm->mode_tx->srate + 50)/100;
- if (sm->dma.ifragsz < sm->mode_rx->overlap)
- sm->dma.ifragsz = sm->mode_rx->overlap;
- if (sm->mode_rx->demodulator_s16 && sm->mode_tx->modulator_u8) {
- sm->dma.i16bit = 1;
- sm->dma.o16bit = 0;
- sm->dma.ifragsz <<= 1;
- } else if (sm->mode_rx->demodulator_u8 && sm->mode_tx->modulator_s16) {
- sm->dma.i16bit = 0;
- sm->dma.o16bit = 1;
- sm->dma.ofragsz <<= 1;
- } else {
- printk(KERN_INFO "%s: mode %s or %s unusable\n", sm_drvname,
- sm->mode_rx->name, sm->mode_tx->name);
- sm->mode_tx = NULL;
- sm->mode_rx = NULL;
- return -EINVAL;
- }
- return 0;
- }
- }
- }
- return -EINVAL;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int sbcfdx_ioctl(struct device *dev, struct sm_state *sm, struct ifreq *ifr,
- struct hdlcdrv_ioctl *hi, int cmd)
-{
- if (cmd != SIOCDEVPRIVATE)
- return -ENOIOCTLCMD;
-
- if (hi->cmd == HDLCDRVCTL_MODEMPARMASK)
- return HDLCDRV_PARMASK_IOBASE | HDLCDRV_PARMASK_IRQ |
- HDLCDRV_PARMASK_DMA | HDLCDRV_PARMASK_DMA2 | HDLCDRV_PARMASK_SERIOBASE |
- HDLCDRV_PARMASK_PARIOBASE | HDLCDRV_PARMASK_MIDIIOBASE;
-
- return sbc_ioctl(dev, sm, ifr, hi, cmd);
-}
-
-/* --------------------------------------------------------------------- */
-
-const struct hardware_info sm_hw_sbcfdx = {
- "sbcfdx", sizeof(struct sc_state_sbc),
- sbcfdx_open, sbcfdx_close, sbcfdx_ioctl, sbcfdx_sethw
-};
-
-/* --------------------------------------------------------------------- */
diff --git a/drivers/net/soundmodem/sm_wss.c b/drivers/net/soundmodem/sm_wss.c
index a089544d2..e69de29bb 100644
--- a/drivers/net/soundmodem/sm_wss.c
+++ b/drivers/net/soundmodem/sm_wss.c
@@ -1,965 +0,0 @@
-/*****************************************************************************/
-
-/*
- * sm_wss.c -- soundcard radio modem driver, WSS (half duplex) driver
- *
- * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Please note that the GPL allows you to use the driver, NOT the radio.
- * In order to use the radio, you need a license from the communications
- * authority of your country.
- *
- */
-
-#include <linux/ptrace.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <linux/ioport.h>
-#include <linux/soundmodem.h>
-#include "sm.h"
-#include "smdma.h"
-
-/* --------------------------------------------------------------------- */
-
-/*
- * currently this module is supposed to support both module styles, i.e.
- * the old one present up to about 2.1.9, and the new one functioning
- * starting with 2.1.21. The reason is I have a kit allowing to compile
- * this module also under 2.0.x which was requested by several people.
- * This will go in 2.2
- */
-#include <linux/version.h>
-
-#if LINUX_VERSION_CODE >= 0x20100
-#include <asm/uaccess.h>
-#else
-#include <asm/segment.h>
-#include <linux/mm.h>
-
-#undef put_user
-#undef get_user
-
-#define put_user(x,ptr) ({ __put_user((unsigned long)(x),(ptr),sizeof(*(ptr))); 0; })
-#define get_user(x,ptr) ({ x = ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr)))); 0; })
-
-extern inline int copy_from_user(void *to, const void *from, unsigned long n)
-{
- int i = verify_area(VERIFY_READ, from, n);
- if (i)
- return i;
- memcpy_fromfs(to, from, n);
- return 0;
-}
-
-extern inline int copy_to_user(void *to, const void *from, unsigned long n)
-{
- int i = verify_area(VERIFY_WRITE, to, n);
- if (i)
- return i;
- memcpy_tofs(to, from, n);
- return 0;
-}
-#endif
-
-/* --------------------------------------------------------------------- */
-
-struct sc_state_wss {
- unsigned char revwss, revid, revv, revcid;
- unsigned char fmt[2];
- unsigned char crystal;
-};
-
-#define SCSTATE ((struct sc_state_wss *)(&sm->hw))
-
-/* --------------------------------------------------------------------- */
-
-#define WSS_CONFIG(iobase) (iobase+0)
-#define WSS_STATUS(iobase) (iobase+3)
-#define WSS_CODEC_IA(iobase) (iobase+4)
-#define WSS_CODEC_ID(iobase) (iobase+5)
-#define WSS_CODEC_STATUS(iobase) (iobase+6)
-#define WSS_CODEC_DATA(iobase) (iobase+7)
-
-#define WSS_EXTENT 8
-
-#define CS423X_HOTFIX
-
-/* --------------------------------------------------------------------- */
-
-static void write_codec(struct device *dev, unsigned char idx,
- unsigned char data)
-{
- int timeout = 900000;
-
- /* wait until codec ready */
- while (timeout > 0 && inb(WSS_CODEC_IA(dev->base_addr)) & 0x80)
- timeout--;
- outb(idx, WSS_CODEC_IA(dev->base_addr));
- outb(data, WSS_CODEC_ID(dev->base_addr));
-}
-
-
-/* --------------------------------------------------------------------- */
-
-static unsigned char read_codec(struct device *dev, unsigned char idx)
-{
- int timeout = 900000;
-
- /* wait until codec ready */
- while (timeout > 0 && inb(WSS_CODEC_IA(dev->base_addr)) & 0x80)
- timeout--;
- outb(idx & 0x1f, WSS_CODEC_IA(dev->base_addr));
- return inb(WSS_CODEC_ID(dev->base_addr));
-}
-
-/* --------------------------------------------------------------------- */
-
-extern void inline wss_ack_int(struct device *dev)
-{
- outb(0, WSS_CODEC_STATUS(dev->base_addr));
-}
-
-/* --------------------------------------------------------------------- */
-
-static int wss_srate_tab[16] = {
- 8000, 5510, 16000, 11025, 27420, 18900, 32000, 22050,
- -1, 37800, -1, 44100, 48000, 33075, 9600, 6620
-};
-
-static int wss_srate_index(int srate)
-{
- int i;
-
- for (i = 0; i < (sizeof(wss_srate_tab)/sizeof(wss_srate_tab[0])); i++)
- if (srate == wss_srate_tab[i] && wss_srate_tab[i] > 0)
- return i;
- return -1;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int wss_set_codec_fmt(struct device *dev, struct sm_state *sm, unsigned char fmt,
- unsigned char fmt2, char fdx, char fullcalib)
-{
- unsigned long time;
- unsigned long flags;
-
- save_flags(flags);
- cli();
- /* Clock and data format register */
- write_codec(dev, 0x48, fmt);
- if (SCSTATE->crystal) {
- write_codec(dev, 0x5c, fmt2 & 0xf0);
- /* MCE and interface config reg */
- write_codec(dev, 0x49, (fdx ? 0 : 0x4) | (fullcalib ? 0x18 : 0));
- } else
- /* MCE and interface config reg */
- write_codec(dev, 0x49, fdx ? 0x8 : 0xc);
- outb(0xb, WSS_CODEC_IA(dev->base_addr)); /* leave MCE */
- if (SCSTATE->crystal && !fullcalib)
- return 0;
- /*
- * wait for ACI start
- */
- time = 1000;
- while (!(read_codec(dev, 0x0b) & 0x20))
- if (!(--time)) {
- printk(KERN_WARNING "%s: ad1848 auto calibration timed out (1)\n",
- sm_drvname);
- restore_flags(flags);
- return -1;
- }
- /*
- * wait for ACI end
- */
- sti();
- time = jiffies + HZ/4;
- while ((read_codec(dev, 0x0b) & 0x20) && ((signed)(jiffies - time) < 0));
- restore_flags(flags);
- if ((signed)(jiffies - time) >= 0) {
- printk(KERN_WARNING "%s: ad1848 auto calibration timed out (2)\n",
- sm_drvname);
- return -1;
- }
- return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int wss_init_codec(struct device *dev, struct sm_state *sm, char fdx,
- unsigned char src_l, unsigned char src_r,
- int igain_l, int igain_r,
- int ogain_l, int ogain_r)
-{
- unsigned char tmp, reg0, reg1, reg6, reg7;
- static const signed char irqtab[16] =
- { -1, -1, 0x10, -1, -1, -1, -1, 0x08, -1, 0x10, 0x18, 0x20, -1, -1,
- -1, -1 };
- static const signed char dmatab[4] = { 1, 2, -1, 3 };
-
- tmp = inb(WSS_STATUS(dev->base_addr));
- if ((tmp & 0x3f) != 0x04 && (tmp & 0x3f) != 0x00 &&
- (tmp & 0x3f) != 0x0f) {
- printk(KERN_WARNING "sm: WSS card id register not found, "
- "address 0x%lx, ID register 0x%02x\n",
- dev->base_addr, (int)tmp);
- /* return -1; */
- SCSTATE->revwss = 0;
- } else {
- if ((tmp & 0x80) && ((dev->dma == 0) ||
- ((dev->irq >= 8) && (dev->irq != 9)))) {
- printk(KERN_ERR "%s: WSS: DMA0 and/or IRQ8..IRQ15 "
- "(except IRQ9) cannot be used on an 8bit "
- "card\n", sm_drvname);
- return -1;
- }
- if (dev->irq > 15 || irqtab[dev->irq] == -1) {
- printk(KERN_ERR "%s: WSS: invalid interrupt %d\n",
- sm_drvname, (int)dev->irq);
- return -1;
- }
- if (dev->dma > 3 || dmatab[dev->dma] == -1) {
- printk(KERN_ERR "%s: WSS: invalid dma channel %d\n",
- sm_drvname, (int)dev->dma);
- return -1;
- }
- tmp = irqtab[dev->irq] | dmatab[dev->dma];
- /* irq probe */
- outb((tmp & 0x38) | 0x40, WSS_CONFIG(dev->base_addr));
- if (!(inb(WSS_STATUS(dev->base_addr)) & 0x40)) {
- outb(0, WSS_CONFIG(dev->base_addr));
- printk(KERN_ERR "%s: WSS: IRQ%d is not free!\n",
- sm_drvname, dev->irq);
- }
- outb(tmp, WSS_CONFIG(dev->base_addr));
- SCSTATE->revwss = inb(WSS_STATUS(dev->base_addr)) & 0x3f;
- }
- /*
- * initialize the codec
- */
- if (igain_l < 0)
- igain_l = 0;
- if (igain_r < 0)
- igain_r = 0;
- if (ogain_l > 0)
- ogain_l = 0;
- if (ogain_r > 0)
- ogain_r = 0;
- reg0 = (src_l << 6) & 0xc0;
- reg1 = (src_r << 6) & 0xc0;
- if (reg0 == 0x80 && igain_l >= 20) {
- reg0 |= 0x20;
- igain_l -= 20;
- }
- if (reg1 == 0x80 && igain_r >= 20) {
- reg1 |= 0x20;
- igain_r -= 20;
- }
- if (igain_l > 23)
- igain_l = 23;
- if (igain_r > 23)
- igain_r = 23;
- reg0 |= igain_l * 2 / 3;
- reg1 |= igain_r * 2 / 3;
- reg6 = (ogain_l < -95) ? 0x80 : (ogain_l * (-2) / 3);
- reg7 = (ogain_r < -95) ? 0x80 : (ogain_r * (-2) / 3);
- write_codec(dev, 9, 0);
- write_codec(dev, 0, 0x45);
- if (read_codec(dev, 0) != 0x45)
- goto codec_err;
- write_codec(dev, 0, 0xaa);
- if (read_codec(dev, 0) != 0xaa)
- goto codec_err;
- write_codec(dev, 12, 0x40); /* enable MODE2 */
- write_codec(dev, 16, 0);
- write_codec(dev, 0, 0x45);
- SCSTATE->crystal = (read_codec(dev, 16) != 0x45);
- write_codec(dev, 0, 0xaa);
- SCSTATE->crystal &= (read_codec(dev, 16) != 0xaa);
- if (SCSTATE->crystal) {
- SCSTATE->revcid = read_codec(dev, 0x19);
- SCSTATE->revv = (SCSTATE->revcid >> 5) & 7;
- SCSTATE->revcid &= 7;
- write_codec(dev, 0x10, 0x80); /* maximum output level */
- write_codec(dev, 0x11, 0x02); /* xtal enable and no HPF */
- write_codec(dev, 0x12, 0x80); /* left line input control */
- write_codec(dev, 0x13, 0x80); /* right line input control */
- write_codec(dev, 0x16, 0); /* disable alternative freq sel */
- write_codec(dev, 0x1a, 0xe0); /* mono IO disable */
- write_codec(dev, 0x1b, 0x00); /* left out no att */
- write_codec(dev, 0x1d, 0x00); /* right out no att */
- }
-
- if (wss_set_codec_fmt(dev, sm, SCSTATE->fmt[0], SCSTATE->fmt[0], fdx, 1))
- goto codec_err;
-
- write_codec(dev, 0, reg0); /* left input control */
- write_codec(dev, 1, reg1); /* right input control */
- write_codec(dev, 2, 0x80); /* left aux#1 input control */
- write_codec(dev, 3, 0x80); /* right aux#1 input control */
- write_codec(dev, 4, 0x80); /* left aux#2 input control */
- write_codec(dev, 5, 0x80); /* right aux#2 input control */
- write_codec(dev, 6, reg6); /* left dac control */
- write_codec(dev, 7, reg7); /* right dac control */
- write_codec(dev, 0xa, 0x2); /* pin control register */
- write_codec(dev, 0xd, 0x0); /* digital mix control */
- SCSTATE->revid = read_codec(dev, 0xc) & 0xf;
- /*
- * print revisions
- */
- if (SCSTATE->crystal)
- printk(KERN_INFO "%s: Crystal CODEC ID %d, Chip revision %d, "
- " Chip ID %d\n", sm_drvname, (int)SCSTATE->revid,
- (int)SCSTATE->revv, (int)SCSTATE->revcid);
- else
- printk(KERN_INFO "%s: WSS revision %d, CODEC revision %d\n",
- sm_drvname, (int)SCSTATE->revwss,
- (int)SCSTATE->revid);
- return 0;
- codec_err:
- outb(0, WSS_CONFIG(dev->base_addr));
- printk(KERN_ERR "%s: no WSS soundcard found at address 0x%lx\n",
- sm_drvname, dev->base_addr);
- return -1;
-}
-
-/* --------------------------------------------------------------------- */
-
-static void setup_dma_wss(struct device *dev, struct sm_state *sm, int send)
-{
- unsigned long flags;
- static const unsigned char codecmode[2] = { 0x0e, 0x0d };
- unsigned char oldcodecmode;
- long abrt;
- unsigned char fmt;
- unsigned int numsamps;
-
- send = !!send;
- fmt = SCSTATE->fmt[send];
- save_flags(flags);
- cli();
- /*
- * perform the final DMA sequence to disable the codec request
- */
- oldcodecmode = read_codec(dev, 9);
- write_codec(dev, 9, 0xc); /* disable codec */
- wss_ack_int(dev);
- if (read_codec(dev, 11) & 0x10) {
- dma_setup(sm, oldcodecmode & 1, dev->dma);
- abrt = 0;
- while ((read_codec(dev, 11) & 0x10) || ((++abrt) >= 0x10000));
- }
-#ifdef CS423X_HOTFIX
- if (read_codec(dev, 0x8) != fmt || SCSTATE->crystal)
- wss_set_codec_fmt(dev, sm, fmt, fmt, 0, 0);
-#else /* CS423X_HOTFIX */
- if (read_codec(dev, 0x8) != fmt)
- wss_set_codec_fmt(dev, sm, fmt, fmt, 0, 0);
-#endif /* CS423X_HOTFIX */
- numsamps = dma_setup(sm, send, dev->dma) - 1;
- write_codec(dev, 15, numsamps & 0xff);
- write_codec(dev, 14, numsamps >> 8);
- write_codec(dev, 9, codecmode[send]);
- restore_flags(flags);
-}
-
-/* --------------------------------------------------------------------- */
-
-static void wss_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- struct device *dev = (struct device *)dev_id;
- struct sm_state *sm = (struct sm_state *)dev->priv;
- unsigned int curfrag;
- unsigned int nums;
-
- if (!dev || !sm || !sm->mode_rx || !sm->mode_tx ||
- sm->hdrv.magic != HDLCDRV_MAGIC)
- return;
- cli();
- wss_ack_int(dev);
- disable_dma(dev->dma);
- clear_dma_ff(dev->dma);
- nums = dma_ptr(sm, sm->dma.ptt_cnt > 0, dev->dma, &curfrag) - 1;
- write_codec(dev, 15, nums & 0xff);
- write_codec(dev, 14, nums >> 8);
- enable_dma(dev->dma);
- sm_int_freq(sm);
- sti();
- if (sm->dma.ptt_cnt <= 0) {
- dma_receive(sm, curfrag);
- hdlcdrv_arbitrate(dev, &sm->hdrv);
- if (hdlcdrv_ptt(&sm->hdrv)) {
- /* starting to transmit */
- disable_dma(dev->dma);
- hdlcdrv_transmitter(dev, &sm->hdrv); /* prefill HDLC buffer */
- dma_start_transmit(sm);
- setup_dma_wss(dev, sm, 1);
- dma_transmit(sm);
- }
- } else if (dma_end_transmit(sm, curfrag)) {
- /* stopping transmission */
- disable_dma(dev->dma);
- dma_init_receive(sm);
- setup_dma_wss(dev, sm, 0);
- } else
- dma_transmit(sm);
- sm_output_status(sm);
- hdlcdrv_transmitter(dev, &sm->hdrv);
- hdlcdrv_receiver(dev, &sm->hdrv);
-}
-
-/* --------------------------------------------------------------------- */
-
-static int wss_open(struct device *dev, struct sm_state *sm)
-{
- unsigned int dmasz, u;
-
- if (sizeof(sm->m) < sizeof(struct sc_state_wss)) {
- printk(KERN_ERR "sm wss: wss state too big: %d > %d\n",
- sizeof(struct sc_state_wss), sizeof(sm->m));
- return -ENODEV;
- }
- if (!dev || !sm || !sm->mode_rx || !sm->mode_tx)
- return -ENXIO;
- if (dev->base_addr <= 0 || dev->base_addr > 0x1000-WSS_EXTENT ||
- dev->irq < 2 || dev->irq > 15 || dev->dma > 3)
- return -ENXIO;
- if (check_region(dev->base_addr, WSS_EXTENT))
- return -EACCES;
- /*
- * check if a card is available
- */
- if (wss_init_codec(dev, sm, 0, 1, 1, 0, 0, -45, -45))
- return -ENODEV;
- /*
- * initialize some variables
- */
- dma_init_receive(sm);
- dmasz = (NUM_FRAGMENTS + 1) * sm->dma.ifragsz;
- u = NUM_FRAGMENTS * sm->dma.ofragsz;
- if (u > dmasz)
- dmasz = u;
- if (!(sm->dma.ibuf = sm->dma.obuf = kmalloc(dmasz, GFP_KERNEL | GFP_DMA)))
- return -ENOMEM;
- dma_init_transmit(sm);
- dma_init_receive(sm);
-
- memset(&sm->m, 0, sizeof(sm->m));
- memset(&sm->d, 0, sizeof(sm->d));
- if (sm->mode_tx->init)
- sm->mode_tx->init(sm);
- if (sm->mode_rx->init)
- sm->mode_rx->init(sm);
-
- if (request_dma(dev->dma, sm->hwdrv->hw_name)) {
- kfree_s(sm->dma.obuf, dmasz);
- return -EBUSY;
- }
- if (request_irq(dev->irq, wss_interrupt, SA_INTERRUPT,
- sm->hwdrv->hw_name, dev)) {
- free_dma(dev->dma);
- kfree_s(sm->dma.obuf, dmasz);
- return -EBUSY;
- }
- request_region(dev->base_addr, WSS_EXTENT, sm->hwdrv->hw_name);
- setup_dma_wss(dev, sm, 0);
- return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int wss_close(struct device *dev, struct sm_state *sm)
-{
- if (!dev || !sm)
- return -EINVAL;
- /*
- * disable interrupts
- */
- disable_dma(dev->dma);
- write_codec(dev, 9, 0xc); /* disable codec */
- free_irq(dev->irq, dev);
- free_dma(dev->dma);
- release_region(dev->base_addr, WSS_EXTENT);
- kfree(sm->dma.obuf);
- return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int wss_sethw(struct device *dev, struct sm_state *sm, char *mode)
-{
- char *cp = strchr(mode, '.');
- const struct modem_tx_info **mtp = sm_modem_tx_table;
- const struct modem_rx_info **mrp;
- int i, j;
-
- if (!strcmp(mode, "off")) {
- sm->mode_tx = NULL;
- sm->mode_rx = NULL;
- return 0;
- }
- if (cp)
- *cp++ = '\0';
- else
- cp = mode;
- for (; *mtp; mtp++) {
- if ((*mtp)->loc_storage > sizeof(sm->m)) {
- printk(KERN_ERR "%s: insufficient storage for modulator %s (%d)\n",
- sm_drvname, (*mtp)->name, (*mtp)->loc_storage);
- continue;
- }
- if (!(*mtp)->name || strcmp((*mtp)->name, mode))
- continue;
- if ((i = wss_srate_index((*mtp)->srate)) < 0)
- continue;
- for (mrp = sm_modem_rx_table; *mrp; mrp++) {
- if ((*mrp)->loc_storage > sizeof(sm->d)) {
- printk(KERN_ERR "%s: insufficient storage for demodulator %s (%d)\n",
- sm_drvname, (*mrp)->name, (*mrp)->loc_storage);
- continue;
- }
- if ((*mrp)->name && !strcmp((*mrp)->name, cp) &&
- ((j = wss_srate_index((*mrp)->srate)) >= 0)) {
- sm->mode_tx = *mtp;
- sm->mode_rx = *mrp;
- SCSTATE->fmt[0] = j;
- SCSTATE->fmt[1] = i;
- sm->dma.ifragsz = (sm->mode_rx->srate + 50)/100;
- sm->dma.ofragsz = (sm->mode_tx->srate + 50)/100;
- if (sm->dma.ifragsz < sm->mode_rx->overlap)
- sm->dma.ifragsz = sm->mode_rx->overlap;
- /* prefer same data format if possible to minimize switching times */
- sm->dma.i16bit = sm->dma.o16bit = 2;
- if (sm->mode_rx->srate == sm->mode_tx->srate) {
- if (sm->mode_rx->demodulator_s16 && sm->mode_tx->modulator_s16)
- sm->dma.i16bit = sm->dma.o16bit = 1;
- else if (sm->mode_rx->demodulator_u8 && sm->mode_tx->modulator_u8)
- sm->dma.i16bit = sm->dma.o16bit = 0;
- }
- if (sm->dma.i16bit == 2) {
- if (sm->mode_rx->demodulator_s16)
- sm->dma.i16bit = 1;
- else if (sm->mode_rx->demodulator_u8)
- sm->dma.i16bit = 0;
- }
- if (sm->dma.o16bit == 2) {
- if (sm->mode_tx->modulator_s16)
- sm->dma.o16bit = 1;
- else if (sm->mode_tx->modulator_u8)
- sm->dma.o16bit = 0;
- }
- if (sm->dma.i16bit == 2 || sm->dma.o16bit == 2) {
- printk(KERN_INFO "%s: mode %s or %s unusable\n", sm_drvname,
- sm->mode_rx->name, sm->mode_tx->name);
- sm->mode_tx = NULL;
- sm->mode_rx = NULL;
- return -EINVAL;
- }
-#ifdef __BIG_ENDIAN
- /* big endian 16bit only works on crystal cards... */
- if (sm->dma.i16bit) {
- SCSTATE->fmt[0] |= 0xc0;
- sm->dma.ifragsz <<= 1;
- }
- if (sm->dma.o16bit) {
- SCSTATE->fmt[1] |= 0xc0;
- sm->dma.ofragsz <<= 1;
- }
-#else /* __BIG_ENDIAN */
- if (sm->dma.i16bit) {
- SCSTATE->fmt[0] |= 0x40;
- sm->dma.ifragsz <<= 1;
- }
- if (sm->dma.o16bit) {
- SCSTATE->fmt[1] |= 0x40;
- sm->dma.ofragsz <<= 1;
- }
-#endif /* __BIG_ENDIAN */
- return 0;
- }
- }
- }
- return -EINVAL;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int wss_ioctl(struct device *dev, struct sm_state *sm, struct ifreq *ifr,
- struct hdlcdrv_ioctl *hi, int cmd)
-{
- struct sm_ioctl bi;
- int i;
-
- if (cmd != SIOCDEVPRIVATE)
- return -ENOIOCTLCMD;
-
- if (hi->cmd == HDLCDRVCTL_MODEMPARMASK)
- return HDLCDRV_PARMASK_IOBASE | HDLCDRV_PARMASK_IRQ |
- HDLCDRV_PARMASK_DMA | HDLCDRV_PARMASK_SERIOBASE |
- HDLCDRV_PARMASK_PARIOBASE | HDLCDRV_PARMASK_MIDIIOBASE;
-
- if (copy_from_user(&bi, ifr->ifr_data, sizeof(bi)))
- return -EFAULT;
-
- switch (bi.cmd) {
- default:
- return -ENOIOCTLCMD;
-
- case SMCTL_GETMIXER:
- i = 0;
- bi.data.mix.sample_rate = sm->mode_rx->srate;
- bi.data.mix.bit_rate = sm->hdrv.par.bitrate;
- bi.data.mix.mixer_type = SCSTATE->crystal ?
- SM_MIXER_CRYSTAL : SM_MIXER_AD1848;
- if (((SCSTATE->crystal ? 0x2c0c20fflu: 0x20fflu)
- >> bi.data.mix.reg) & 1) {
- bi.data.mix.data = read_codec(dev, bi.data.mix.reg);
- i = 1;
- }
- if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi)))
- return -EFAULT;
- return i;
-
- case SMCTL_SETMIXER:
- if (!suser())
- return -EACCES;
- if ((bi.data.mix.mixer_type != SM_MIXER_CRYSTAL ||
- !SCSTATE->crystal) &&
- (bi.data.mix.mixer_type != SM_MIXER_AD1848 ||
- bi.data.mix.reg >= 0x10))
- return -EINVAL;
- if (!((0x2c0c20fflu >> bi.data.mix.reg) & 1))
- return -EACCES;
- write_codec(dev, bi.data.mix.reg, bi.data.mix.data);
- return 0;
-
- }
- if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi)))
- return -EFAULT;
- return 0;
-
-}
-
-/* --------------------------------------------------------------------- */
-
-const struct hardware_info sm_hw_wss = {
- "wss", sizeof(struct sc_state_wss),
- wss_open, wss_close, wss_ioctl, wss_sethw
-};
-
-/* --------------------------------------------------------------------- */
-
-static void setup_fdx_dma_wss(struct device *dev, struct sm_state *sm)
-{
- unsigned long flags;
- unsigned char oldcodecmode, codecdma;
- long abrt;
- unsigned int osamps, isamps;
-
- save_flags(flags);
- cli();
- /*
- * perform the final DMA sequence to disable the codec request
- */
- oldcodecmode = read_codec(dev, 9);
- write_codec(dev, 9, 0); /* disable codec DMA */
- wss_ack_int(dev);
- if ((codecdma = read_codec(dev, 11)) & 0x10) {
- dma_setup(sm, 1, dev->dma);
- dma_setup(sm, 0, sm->hdrv.ptt_out.dma2);
- abrt = 0;
- while (((codecdma = read_codec(dev, 11)) & 0x10) || ((++abrt) >= 0x10000));
- }
- wss_set_codec_fmt(dev, sm, SCSTATE->fmt[1], SCSTATE->fmt[0], 1, 1);
- osamps = dma_setup(sm, 1, dev->dma) - 1;
- isamps = dma_setup(sm, 0, sm->hdrv.ptt_out.dma2) - 1;
- write_codec(dev, 15, osamps & 0xff);
- write_codec(dev, 14, osamps >> 8);
- if (SCSTATE->crystal) {
- write_codec(dev, 31, isamps & 0xff);
- write_codec(dev, 30, isamps >> 8);
- }
- write_codec(dev, 9, 3);
- restore_flags(flags);
-}
-
-/* --------------------------------------------------------------------- */
-
-static void wssfdx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- struct device *dev = (struct device *)dev_id;
- struct sm_state *sm = (struct sm_state *)dev->priv;
- unsigned long flags;
- unsigned char cry_int_src;
- unsigned icfrag, ocfrag, isamps, osamps;
-
- if (!dev || !sm || !sm->mode_rx || !sm->mode_tx ||
- sm->hdrv.magic != HDLCDRV_MAGIC)
- return;
- save_flags(flags);
- cli();
- if (SCSTATE->crystal) {
- /* Crystal has an essentially different interrupt handler! */
- cry_int_src = read_codec(dev, 0x18);
- wss_ack_int(dev);
- if (cry_int_src & 0x10) { /* playback interrupt */
- disable_dma(dev->dma);
- clear_dma_ff(dev->dma);
- osamps = dma_ptr(sm, 1, dev->dma, &ocfrag)-1;
- write_codec(dev, 15, osamps & 0xff);
- write_codec(dev, 14, osamps >> 8);
- enable_dma(dev->dma);
- }
- if (cry_int_src & 0x20) { /* capture interrupt */
- disable_dma(sm->hdrv.ptt_out.dma2);
- clear_dma_ff(sm->hdrv.ptt_out.dma2);
- isamps = dma_ptr(sm, 0, sm->hdrv.ptt_out.dma2, &icfrag)-1;
- write_codec(dev, 31, isamps & 0xff);
- write_codec(dev, 30, isamps >> 8);
- enable_dma(sm->hdrv.ptt_out.dma2);
- }
- restore_flags(flags);
- sm_int_freq(sm);
- sti();
- if (cry_int_src & 0x10) {
- if (dma_end_transmit(sm, ocfrag))
- dma_clear_transmit(sm);
- dma_transmit(sm);
- }
- if (cry_int_src & 0x20) {
- dma_receive(sm, icfrag);
- hdlcdrv_arbitrate(dev, &sm->hdrv);
- }
- sm_output_status(sm);
- hdlcdrv_transmitter(dev, &sm->hdrv);
- hdlcdrv_receiver(dev, &sm->hdrv);
- return;
- }
- wss_ack_int(dev);
- disable_dma(dev->dma);
- disable_dma(sm->hdrv.ptt_out.dma2);
- clear_dma_ff(dev->dma);
- clear_dma_ff(sm->hdrv.ptt_out.dma2);
- osamps = dma_ptr(sm, 1, dev->dma, &ocfrag)-1;
- isamps = dma_ptr(sm, 0, sm->hdrv.ptt_out.dma2, &icfrag)-1;
- write_codec(dev, 15, osamps & 0xff);
- write_codec(dev, 14, osamps >> 8);
- if (SCSTATE->crystal) {
- write_codec(dev, 31, isamps & 0xff);
- write_codec(dev, 30, isamps >> 8);
- }
- enable_dma(dev->dma);
- enable_dma(sm->hdrv.ptt_out.dma2);
- restore_flags(flags);
- sm_int_freq(sm);
- sti();
- if (dma_end_transmit(sm, ocfrag))
- dma_clear_transmit(sm);
- dma_transmit(sm);
- dma_receive(sm, icfrag);
- hdlcdrv_arbitrate(dev, &sm->hdrv);
- sm_output_status(sm);
- hdlcdrv_transmitter(dev, &sm->hdrv);
- hdlcdrv_receiver(dev, &sm->hdrv);
-}
-
-/* --------------------------------------------------------------------- */
-
-static int wssfdx_open(struct device *dev, struct sm_state *sm)
-{
- if (!dev || !sm || !sm->mode_rx || !sm->mode_tx)
- return -ENXIO;
- if (dev->base_addr <= 0 || dev->base_addr > 0x1000-WSS_EXTENT ||
- dev->irq < 2 || dev->irq > 15 || dev->dma > 3)
- return -ENXIO;
- if (check_region(dev->base_addr, WSS_EXTENT))
- return -EACCES;
- /*
- * check if a card is available
- */
- if (wss_init_codec(dev, sm, 1, 1, 1, 0, 0, -45, -45))
- return -ENODEV;
- /*
- * initialize some variables
- */
- if (!(sm->dma.ibuf = kmalloc(sm->dma.ifragsz * (NUM_FRAGMENTS+1), GFP_KERNEL | GFP_DMA)))
- return -ENOMEM;
- if (!(sm->dma.obuf = kmalloc(sm->dma.ofragsz * NUM_FRAGMENTS, GFP_KERNEL | GFP_DMA))) {
- kfree(sm->dma.ibuf);
- return -ENOMEM;
- }
- dma_init_transmit(sm);
- dma_init_receive(sm);
-
- memset(&sm->m, 0, sizeof(sm->m));
- memset(&sm->d, 0, sizeof(sm->d));
- if (sm->mode_tx->init)
- sm->mode_tx->init(sm);
- if (sm->mode_rx->init)
- sm->mode_rx->init(sm);
-
- if (request_dma(dev->dma, sm->hwdrv->hw_name)) {
- kfree(sm->dma.ibuf);
- kfree(sm->dma.obuf);
- return -EBUSY;
- }
- if (request_dma(sm->hdrv.ptt_out.dma2, sm->hwdrv->hw_name)) {
- kfree(sm->dma.ibuf);
- kfree(sm->dma.obuf);
- free_dma(dev->dma);
- return -EBUSY;
- }
- if (request_irq(dev->irq, wssfdx_interrupt, SA_INTERRUPT,
- sm->hwdrv->hw_name, dev)) {
- kfree(sm->dma.ibuf);
- kfree(sm->dma.obuf);
- free_dma(dev->dma);
- free_dma(sm->hdrv.ptt_out.dma2);
- return -EBUSY;
- }
- request_region(dev->base_addr, WSS_EXTENT, sm->hwdrv->hw_name);
- setup_fdx_dma_wss(dev, sm);
- return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int wssfdx_close(struct device *dev, struct sm_state *sm)
-{
- if (!dev || !sm)
- return -EINVAL;
- /*
- * disable interrupts
- */
- disable_dma(dev->dma);
- disable_dma(sm->hdrv.ptt_out.dma2);
- write_codec(dev, 9, 0xc); /* disable codec */
- free_irq(dev->irq, dev);
- free_dma(dev->dma);
- free_dma(sm->hdrv.ptt_out.dma2);
- release_region(dev->base_addr, WSS_EXTENT);
- kfree(sm->dma.ibuf);
- kfree(sm->dma.obuf);
- return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int wssfdx_sethw(struct device *dev, struct sm_state *sm, char *mode)
-{
- char *cp = strchr(mode, '.');
- const struct modem_tx_info **mtp = sm_modem_tx_table;
- const struct modem_rx_info **mrp;
- int i;
-
- if (!strcmp(mode, "off")) {
- sm->mode_tx = NULL;
- sm->mode_rx = NULL;
- return 0;
- }
- if (cp)
- *cp++ = '\0';
- else
- cp = mode;
- for (; *mtp; mtp++) {
- if ((*mtp)->loc_storage > sizeof(sm->m)) {
- printk(KERN_ERR "%s: insufficient storage for modulator %s (%d)\n",
- sm_drvname, (*mtp)->name, (*mtp)->loc_storage);
- continue;
- }
- if (!(*mtp)->name || strcmp((*mtp)->name, mode))
- continue;
- if ((i = wss_srate_index((*mtp)->srate)) < 0)
- continue;
- for (mrp = sm_modem_rx_table; *mrp; mrp++) {
- if ((*mrp)->loc_storage > sizeof(sm->d)) {
- printk(KERN_ERR "%s: insufficient storage for demodulator %s (%d)\n",
- sm_drvname, (*mrp)->name, (*mrp)->loc_storage);
- continue;
- }
- if ((*mrp)->name && !strcmp((*mrp)->name, cp) &&
- (*mtp)->srate == (*mrp)->srate) {
- sm->mode_tx = *mtp;
- sm->mode_rx = *mrp;
- SCSTATE->fmt[0] = SCSTATE->fmt[1] = i;
- sm->dma.ifragsz = sm->dma.ofragsz = (sm->mode_rx->srate + 50)/100;
- if (sm->dma.ifragsz < sm->mode_rx->overlap)
- sm->dma.ifragsz = sm->mode_rx->overlap;
- sm->dma.i16bit = sm->dma.o16bit = 2;
- if (sm->mode_rx->demodulator_s16) {
- sm->dma.i16bit = 1;
- sm->dma.ifragsz <<= 1;
-#ifdef __BIG_ENDIAN /* big endian 16bit only works on crystal cards... */
- SCSTATE->fmt[0] |= 0xc0;
-#else /* __BIG_ENDIAN */
- SCSTATE->fmt[0] |= 0x40;
-#endif /* __BIG_ENDIAN */
- } else if (sm->mode_rx->demodulator_u8)
- sm->dma.i16bit = 0;
- if (sm->mode_tx->modulator_s16) {
- sm->dma.o16bit = 1;
- sm->dma.ofragsz <<= 1;
-#ifdef __BIG_ENDIAN /* big endian 16bit only works on crystal cards... */
- SCSTATE->fmt[1] |= 0xc0;
-#else /* __BIG_ENDIAN */
- SCSTATE->fmt[1] |= 0x40;
-#endif /* __BIG_ENDIAN */
- } else if (sm->mode_tx->modulator_u8)
- sm->dma.o16bit = 0;
- if (sm->dma.i16bit == 2 || sm->dma.o16bit == 2) {
- printk(KERN_INFO "%s: mode %s or %s unusable\n", sm_drvname,
- sm->mode_rx->name, sm->mode_tx->name);
- sm->mode_tx = NULL;
- sm->mode_rx = NULL;
- return -EINVAL;
- }
- return 0;
- }
- }
- }
- return -EINVAL;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int wssfdx_ioctl(struct device *dev, struct sm_state *sm, struct ifreq *ifr,
- struct hdlcdrv_ioctl *hi, int cmd)
-{
- if (cmd != SIOCDEVPRIVATE)
- return -ENOIOCTLCMD;
-
- if (hi->cmd == HDLCDRVCTL_MODEMPARMASK)
- return HDLCDRV_PARMASK_IOBASE | HDLCDRV_PARMASK_IRQ |
- HDLCDRV_PARMASK_DMA | HDLCDRV_PARMASK_DMA2 |
- HDLCDRV_PARMASK_SERIOBASE | HDLCDRV_PARMASK_PARIOBASE |
- HDLCDRV_PARMASK_MIDIIOBASE;
-
- return wss_ioctl(dev, sm, ifr, hi, cmd);
-}
-
-/* --------------------------------------------------------------------- */
-
-const struct hardware_info sm_hw_wssfdx = {
- "wssfdx", sizeof(struct sc_state_wss),
- wssfdx_open, wssfdx_close, wssfdx_ioctl, wssfdx_sethw
-};
-
-/* --------------------------------------------------------------------- */
-
-#undef SCSTATE
diff --git a/drivers/net/soundmodem/smdma.h b/drivers/net/soundmodem/smdma.h
index 44e457a7a..e69de29bb 100644
--- a/drivers/net/soundmodem/smdma.h
+++ b/drivers/net/soundmodem/smdma.h
@@ -1,217 +0,0 @@
-/*****************************************************************************/
-
-/*
- * smdma.h -- soundcard radio modem driver dma buffer routines.
- *
- * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Please note that the GPL allows you to use the driver, NOT the radio.
- * In order to use the radio, you need a license from the communications
- * authority of your country.
- *
- */
-
-#ifndef _SMDMA_H
-#define _SMDMA_H
-
-/* ---------------------------------------------------------------------- */
-
-#include "sm.h"
-
-/* ---------------------------------------------------------------------- */
-
-#define DMA_MODE_AUTOINIT 0x10
-#define NUM_FRAGMENTS 4
-
-/*
- * NOTE: make sure that hdlcdrv_hdlcbuffer contains enough space
- * for the modulator to fill the whole DMA buffer without underrun
- * at the highest possible baud rate, otherwise the TX state machine will
- * not work correctly. That is (9k6 FSK): HDLCDRV_HDLCBUFFER > 6*NUM_FRAGMENTS
- */
-
-/* --------------------------------------------------------------------- */
-/*
- * ===================== DMA buffer management ===========================
- */
-
-/*
- * returns the number of samples per fragment
- */
-extern __inline__ unsigned int dma_setup(struct sm_state *sm, int send, unsigned int dmanr)
-{
- if (send) {
- disable_dma(dmanr);
- clear_dma_ff(dmanr);
- set_dma_mode(dmanr, DMA_MODE_WRITE | DMA_MODE_AUTOINIT);
- set_dma_addr(dmanr, virt_to_bus(sm->dma.obuf));
- set_dma_count(dmanr, sm->dma.ofragsz * NUM_FRAGMENTS);
- enable_dma(dmanr);
- if (sm->dma.o16bit)
- return sm->dma.ofragsz/2;
- return sm->dma.ofragsz;
- } else {
- disable_dma(dmanr);
- clear_dma_ff(dmanr);
- set_dma_mode(dmanr, DMA_MODE_READ | DMA_MODE_AUTOINIT);
- set_dma_addr(dmanr, virt_to_bus(sm->dma.ibuf));
- set_dma_count(dmanr, sm->dma.ifragsz * NUM_FRAGMENTS);
- enable_dma(dmanr);
- if (sm->dma.i16bit)
- return sm->dma.ifragsz/2;
- return sm->dma.ifragsz;
- }
-}
-
-/* --------------------------------------------------------------------- */
-
-extern __inline__ unsigned int dma_ptr(struct sm_state *sm, int send, unsigned int dmanr,
- unsigned int *curfrag)
-{
- unsigned int dmaptr, sz, frg, offs;
-
- dmaptr = get_dma_residue(dmanr);
- if (send) {
- sz = sm->dma.ofragsz * NUM_FRAGMENTS;
- if (dmaptr == 0 || dmaptr > sz)
- dmaptr = sz;
- dmaptr--;
- frg = dmaptr / sm->dma.ofragsz;
- offs = (dmaptr % sm->dma.ofragsz) + 1;
- *curfrag = NUM_FRAGMENTS - 1 - frg;
-#ifdef SM_DEBUG
- if (!sm->debug_vals.dma_residue || offs < sm->debug_vals.dma_residue)
- sm->debug_vals.dma_residue = offs;
-#endif /* SM_DEBUG */
- if (sm->dma.o16bit)
- return offs/2;
- return offs;
- } else {
- sz = sm->dma.ifragsz * NUM_FRAGMENTS;
- if (dmaptr == 0 || dmaptr > sz)
- dmaptr = sz;
- dmaptr--;
- frg = dmaptr / sm->dma.ifragsz;
- offs = (dmaptr % sm->dma.ifragsz) + 1;
- *curfrag = NUM_FRAGMENTS - 1 - frg;
-#ifdef SM_DEBUG
- if (!sm->debug_vals.dma_residue || offs < sm->debug_vals.dma_residue)
- sm->debug_vals.dma_residue = offs;
-#endif /* SM_DEBUG */
- if (sm->dma.i16bit)
- return offs/2;
- return offs;
- }
-}
-
-/* --------------------------------------------------------------------- */
-
-extern __inline__ int dma_end_transmit(struct sm_state *sm, unsigned int curfrag)
-{
- unsigned int diff = (NUM_FRAGMENTS + curfrag - sm->dma.ofragptr) % NUM_FRAGMENTS;
-
- sm->dma.ofragptr = curfrag;
- if (sm->dma.ptt_cnt <= 0) {
- sm->dma.ptt_cnt = 0;
- return 0;
- }
- sm->dma.ptt_cnt -= diff;
- if (sm->dma.ptt_cnt <= 0) {
- sm->dma.ptt_cnt = 0;
- return -1;
- }
- return 0;
-}
-
-extern __inline__ void dma_transmit(struct sm_state *sm)
-{
- void *p;
-
- while (sm->dma.ptt_cnt < NUM_FRAGMENTS && hdlcdrv_ptt(&sm->hdrv)) {
- p = (unsigned char *)sm->dma.obuf + sm->dma.ofragsz *
- ((sm->dma.ofragptr + sm->dma.ptt_cnt) % NUM_FRAGMENTS);
- if (sm->dma.o16bit) {
- time_exec(sm->debug_vals.mod_cyc,
- sm->mode_tx->modulator_s16(sm, p, sm->dma.ofragsz/2));
- } else {
- time_exec(sm->debug_vals.mod_cyc,
- sm->mode_tx->modulator_u8(sm, p, sm->dma.ofragsz));
- }
- sm->dma.ptt_cnt++;
- }
-}
-
-extern __inline__ void dma_init_transmit(struct sm_state *sm)
-{
- sm->dma.ofragptr = 0;
- sm->dma.ptt_cnt = 0;
-}
-
-extern __inline__ void dma_start_transmit(struct sm_state *sm)
-{
- sm->dma.ofragptr = 0;
- if (sm->dma.o16bit) {
- time_exec(sm->debug_vals.mod_cyc,
- sm->mode_tx->modulator_s16(sm, sm->dma.obuf, sm->dma.ofragsz/2));
- } else {
- time_exec(sm->debug_vals.mod_cyc,
- sm->mode_tx->modulator_u8(sm, sm->dma.obuf, sm->dma.ofragsz));
- }
- sm->dma.ptt_cnt = 1;
-}
-
-extern __inline__ void dma_clear_transmit(struct sm_state *sm)
-{
- sm->dma.ptt_cnt = 0;
- memset(sm->dma.obuf, (sm->dma.o16bit) ? 0 : 0x80, sm->dma.ofragsz * NUM_FRAGMENTS);
-}
-
-/* --------------------------------------------------------------------- */
-
-extern __inline__ void dma_receive(struct sm_state *sm, unsigned int curfrag)
-{
- void *p;
-
- while (sm->dma.ifragptr != curfrag) {
- if (sm->dma.ifragptr)
- p = (unsigned char *)sm->dma.ibuf +
- sm->dma.ifragsz * sm->dma.ifragptr;
- else {
- p = (unsigned char *)sm->dma.ibuf + NUM_FRAGMENTS * sm->dma.ifragsz;
- memcpy(p, sm->dma.ibuf, sm->dma.ifragsz);
- }
- if (sm->dma.o16bit) {
- time_exec(sm->debug_vals.demod_cyc,
- sm->mode_rx->demodulator_s16(sm, p, sm->dma.ifragsz/2));
- } else {
- time_exec(sm->debug_vals.demod_cyc,
- sm->mode_rx->demodulator_u8(sm, p, sm->dma.ifragsz));
- }
- sm->dma.ifragptr = (sm->dma.ifragptr + 1) % NUM_FRAGMENTS;
- }
-}
-
-extern __inline__ void dma_init_receive(struct sm_state *sm)
-{
- sm->dma.ifragptr = 0;
-}
-
-/* --------------------------------------------------------------------- */
-#endif /* _SMDMA_H */
-
-
-
diff --git a/drivers/net/strip.c b/drivers/net/strip.c
index 6d927ab4e..ce5595dfa 100644
--- a/drivers/net/strip.c
+++ b/drivers/net/strip.c
@@ -1,5 +1,3 @@
-#warning "will not compile until the networking is merged"
-#if 0
/*
* Copyright 1996 The Board of Trustees of The Leland Stanford
* Junior University. All Rights Reserved.
@@ -2782,4 +2780,3 @@ void cleanup_module(void)
printk(KERN_INFO "STRIP: Module Unloaded\n");
}
#endif /* MODULE */
-#endif
diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c
index 46b6bd7e7..5aed7585a 100644
--- a/drivers/net/tlan.c
+++ b/drivers/net/tlan.c
@@ -244,12 +244,11 @@ extern int init_module(void)
priv->nextDevice = TLanDevices;
TLanDevices = dev;
TLanDevicesInstalled++;
- printk("TLAN: %s irq=%2d io=%04x, %s\n", dev->name, (int) irq, io_base, TLan
-DeviceList[dl_ix].deviceName );
+ printk("TLAN: %s irq=%2d io=%04x, %s\n", dev->name, (int) irq, io_base, TLanDeviceList[dl_ix].deviceName );
}
}
- // printk( "TLAN: Found %d device(s).\n", TLanDevicesInstalled );
+ /* printk( "TLAN: Found %d device(s).\n", TLanDevicesInstalled ); */
return ( ( TLanDevicesInstalled >= 0 ) ? 0 : -ENODEV );
@@ -399,8 +398,7 @@ extern int tlan_probe( struct device *dev )
*
**************************************************************/
-int TLan_PciProbe( u8 *pci_bus, u8 *pci_dfn, u8 *pci_irq, u8 *pci_rev, u32 *pci_
-io_base, u32 *dl_ix )
+int TLan_PciProbe( u8 *pci_bus, u8 *pci_dfn, u8 *pci_irq, u8 *pci_rev, u32 *pci_io_base, u32 *dl_ix )
{
static int dl_index = 0;
static int pci_index = 0;
@@ -438,10 +436,8 @@ io_base, u32 *dl_ix )
pcibios_read_config_byte ( *pci_bus, *pci_dfn, PCI_REVISION_ID, pci_rev);
pcibios_read_config_byte ( *pci_bus, *pci_dfn, PCI_INTERRUPT_LINE, pci_irq);
pcibios_read_config_word ( *pci_bus, *pci_dfn, PCI_COMMAND, &pci_command);
- pcibios_read_config_dword( *pci_bus, *pci_dfn, PCI_BASE_ADDRESS_0, pci_io_ba
-se);
- pcibios_read_config_byte ( *pci_bus, *pci_dfn, PCI_LATENCY_TIMER, &pci_laten
-cy);
+ pcibios_read_config_dword( *pci_bus, *pci_dfn, PCI_BASE_ADDRESS_0, pci_io_base);
+ pcibios_read_config_byte ( *pci_bus, *pci_dfn, PCI_LATENCY_TIMER, &pci_latency);
if (pci_latency < 0x10) {
pcibios_write_config_byte( *pci_bus, *pci_dfn, PCI_LATENCY_TIMER, 0xff);
@@ -452,8 +448,7 @@ cy);
pcibios_read_config_dword( *pci_bus, *pci_dfn, reg, pci_io_base);
if ((pci_command & PCI_COMMAND_IO) && (*pci_io_base & 0x3)) {
*pci_io_base &= PCI_BASE_ADDRESS_IO_MASK;
- TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN: IO mapping is available at %x.\n", *pc
-i_io_base);
+ TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN: IO mapping is available at %x.\n", *pci_io_base);
break;
} else {
*pci_io_base = 0;
@@ -592,11 +587,9 @@ int TLan_Open( struct device *dev )
TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv;
priv->tlanRev = TLan_DioRead8( dev->base_addr, TLAN_DEF_REVISION );
- err = request_irq( dev->irq, TLan_HandleInterrupt, SA_SHIRQ, TLanSignature, dev
- );
+ err = request_irq( dev->irq, TLan_HandleInterrupt, SA_SHIRQ, TLanSignature, dev);
if ( err ) {
- printk( "TLAN: Cannot open %s because IRQ %d is already in use.\n", dev->name
-, dev->irq );
+ printk( "TLAN: Cannot open %s because IRQ %d is already in use.\n", dev->name , dev->irq );
return -EAGAIN;
}
@@ -631,8 +624,7 @@ int TLan_Open( struct device *dev )
outl( TLAN_HC_GO | TLAN_HC_RT, dev->base_addr + TLAN_HOST_CMD );
}
- TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN: Device %s opened. Revision = %x\n", dev->na
-me, priv->tlanRev );
+ TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN: Device %s opened. Revision = %x\n", dev->name, priv->tlanRev );
return 0;
@@ -677,8 +669,7 @@ int TLan_StartTx( struct sk_buff *skb, struct device *dev )
tail_list = priv->txList + priv->txTail;
if ( tail_list->cStat != TLAN_CSTAT_UNUSED ) {
- TLAN_DBG( TLAN_DEBUG_TX, "TLAN TRANSMIT: %s is busy (Head=%d Tail=%d)\n", dev
-->name, priv->txHead, priv->txTail );
+ TLAN_DBG( TLAN_DEBUG_TX, "TLAN TRANSMIT: %s is busy (Head=%d Tail=%d)\n", dev->name, priv->txHead, priv->txTail );
dev->tbusy = 1;
priv->txBusyCount++;
return 1;
@@ -698,22 +689,19 @@ int TLan_StartTx( struct sk_buff *skb, struct device *dev )
tail_list->buffer[1].count = 0;
tail_list->buffer[1].address = 0;
}
- // are we transferring?
+ /* are we transferring? */
cli();
tail_list->cStat = TLAN_CSTAT_READY;
if ( ! priv->txInProgress ) {
priv->txInProgress = 1;
outw( 0x4, dev->base_addr + TLAN_HOST_INT );
- TLAN_DBG( TLAN_DEBUG_TX, "TLAN TRANSMIT: Starting TX on buffer %d\n", priv->t
-xTail );
+ TLAN_DBG( TLAN_DEBUG_TX, "TLAN TRANSMIT: Starting TX on buffer %d\n", priv->txTail );
outl( virt_to_bus( tail_list ), dev->base_addr + TLAN_CH_PARM );
outl( TLAN_HC_GO | TLAN_HC_ACK, dev->base_addr + TLAN_HOST_CMD );
} else {
- TLAN_DBG( TLAN_DEBUG_TX, "TLAN TRANSMIT: Adding buffer %d to TX channel\n", p
-riv->txTail );
+ TLAN_DBG( TLAN_DEBUG_TX, "TLAN TRANSMIT: Adding buffer %d to TX channel\n", priv->txTail );
if ( priv->txTail == 0 )
- ( priv->txList + ( TLAN_NUM_TX_LISTS - 1 ) )->forward = virt_to_bus( tail_lis
-t );
+ ( priv->txList + ( TLAN_NUM_TX_LISTS - 1 ) )->forward = virt_to_bus( tail_list );
else
( priv->txList + ( priv->txTail - 1 ) )->forward = virt_to_bus( tail_list );
}
@@ -764,14 +752,13 @@ void TLan_HandleInterrupt(int irq, void *dev_id, struct pt_regs *regs)
dev = (struct device *) dev_id;
if ( dev->interrupt )
- printk( "TLAN: Re-entering interrupt handler for %s: %d.\n" , dev->name, dev
-->interrupt );
+ printk( "TLAN: Re-entering interrupt handler for %s: %d.\n" , dev->name, dev->interrupt );
dev->interrupt++;
cli();
host_int = inw( dev->base_addr + TLAN_HOST_INT );
- outw( host_int, dev->base_addr + TLAN_HOST_INT ); // Deactivate Ints
+ outw( host_int, dev->base_addr + TLAN_HOST_INT ); /* Deactivate Ints */
type = ( host_int & TLAN_HI_IT_MASK ) >> 2;
@@ -852,10 +839,8 @@ struct net_device_stats *TLan_GetStats( struct device *dev )
/* Should only read stats if open ? */
TLan_ReadAndClearStats( dev, TLAN_RECORD );
- TLAN_DBG( TLAN_DEBUG_RX, "TLAN RECEIVE: %s EOC count = %d\n", dev->name, priv-
->rxEocCount );
- TLAN_DBG( TLAN_DEBUG_TX, "TLAN TRANSMIT: %s Busy count = %d\n", dev->name, pri
-v->txBusyCount );
+ TLAN_DBG( TLAN_DEBUG_RX, "TLAN RECEIVE: %s EOC count = %d\n", dev->name, priv->rxEocCount );
+ TLAN_DBG( TLAN_DEBUG_TX, "TLAN TRANSMIT: %s Busy count = %d\n", dev->name, priv->txBusyCount );
if ( debug & TLAN_DEBUG_GNRL ) {
TLan_PrintDio( dev->base_addr );
TLan_PhyPrint( dev );
@@ -971,7 +956,7 @@ void TLan_SetMulticastList( struct device *dev )
u32 TLan_HandleInvalid( struct device *dev, u16 host_int )
{
host_int = 0;
- // printk( "TLAN: Invalid interrupt on %s.\n", dev->name );
+ /* printk( "TLAN: Invalid interrupt on %s.\n", dev->name ); */
return 0;
} /* TLan_HandleInvalid */
@@ -1008,8 +993,7 @@ u32 TLan_HandleTxEOF( struct device *dev, u16 host_int )
TLanList *head_list;
u32 ack = 1;
- TLAN_DBG( TLAN_DEBUG_TX, "TLAN TRANSMIT: Handling TX EOF (Head=%d Tail=%d)\n",
- priv->txHead, priv->txTail );
+ TLAN_DBG( TLAN_DEBUG_TX, "TLAN TRANSMIT: Handling TX EOF (Head=%d Tail=%d)\n", priv->txHead, priv->txTail );
host_int = 0;
head_list = priv->txList + priv->txHead;
if ( head_list->cStat & TLAN_CSTAT_EOC )
@@ -1017,7 +1001,7 @@ u32 TLan_HandleTxEOF( struct device *dev, u16 host_int )
if ( ! head_list->cStat & TLAN_CSTAT_FRM_CMP ) {
printk( "TLAN: Received interrupt for uncompleted TX frame.\n" );
}
- // printk( "Ack %d CSTAT=%hx\n", priv->txHead, head_list->cStat );
+ /* printk( "Ack %d CSTAT=%hx\n", priv->txHead, head_list->cStat ); */
#if LINUX_KERNEL_VERSION > 0x20100
priv->stats->tx_bytes += head_list->frameSize;
@@ -1029,8 +1013,7 @@ u32 TLan_HandleTxEOF( struct device *dev, u16 host_int )
if ( priv->txHead >= TLAN_NUM_TX_LISTS )
priv->txHead = 0;
if ( eoc ) {
- TLAN_DBG( TLAN_DEBUG_TX, "TLAN TRANSMIT: Handling TX EOC (Head=%d Tail=%d)\n"
-, priv->txHead, priv->txTail );
+ TLAN_DBG( TLAN_DEBUG_TX, "TLAN TRANSMIT: Handling TX EOC (Head=%d Tail=%d)\n", priv->txHead, priv->txTail );
head_list = priv->txList + priv->txHead;
if ( ( head_list->cStat & TLAN_CSTAT_READY ) == TLAN_CSTAT_READY ) {
outl( virt_to_bus( head_list ), dev->base_addr + TLAN_CH_PARM );
@@ -1042,14 +1025,14 @@ u32 TLan_HandleTxEOF( struct device *dev, u16 host_int )
TLan_DioWrite8( dev->base_addr, TLAN_LED_REG, TLAN_LED_LINK | TLAN_LED_ACT );
if ( priv->phyFlags & TLAN_PHY_ACTIVITY ) {
if ( priv->timerSetAt == 0 ) {
- // printk("TxEOF Starting timer...\n");
+ /* printk("TxEOF Starting timer...\n"); */
priv->timerSetAt = jiffies;
priv->timer.expires = jiffies + TLAN_TIMER_ACT_DELAY;
priv->timerType = TLAN_TIMER_ACT;
add_timer( &priv->timer );
} else if ( priv->timerType == TLAN_TIMER_ACT ) {
priv->timerSetAt = jiffies;
- // printk("TxEOF continuing timer...\n");
+ /* printk("TxEOF continuing timer...\n"); */
}
}
@@ -1125,8 +1108,7 @@ u32 TLan_HandleRxEOF( struct device *dev, u16 host_int )
TLanList *tail_list;
void *t;
- TLAN_DBG( TLAN_DEBUG_RX, "TLAN RECEIVE: Handling RX EOF (Head=%d Tail=%d)\n",
-priv->rxHead, priv->rxTail );
+ TLAN_DBG( TLAN_DEBUG_RX, "TLAN RECEIVE: Handling RX EOF (Head=%d Tail=%d)\n", priv->rxHead, priv->rxTail );
host_int = 0;
head_list = priv->rxList + priv->rxHead;
tail_list = priv->rxList + priv->rxTail;
@@ -1143,7 +1125,7 @@ priv->rxHead, priv->rxTail );
skb->dev = dev;
skb_reserve( skb, 2 );
t = (void *) skb_put( skb, head_list->frameSize );
- // printk( " %hd %p %p\n", head_list->frameSize, skb->data, t );
+ /* printk( " %hd %p %p\n", head_list->frameSize, skb->data, t ); */
#if LINUX_KERNEL_VERSION > 0x20100
priv->stats->rx_bytes += head_list->frameSize;
@@ -1165,8 +1147,7 @@ priv->rxHead, priv->rxTail );
if ( priv->rxTail >= TLAN_NUM_RX_LISTS )
priv->rxTail = 0;
if ( eoc ) {
- TLAN_DBG( TLAN_DEBUG_RX, "TLAN RECEIVE: Handling RX EOC (Head=%d Tail=%d)\n",
- priv->rxHead, priv->rxTail );
+ TLAN_DBG( TLAN_DEBUG_RX, "TLAN RECEIVE: Handling RX EOC (Head=%d Tail=%d)\n", priv->rxHead, priv->rxTail );
head_list = priv->rxList + priv->rxHead;
outl( virt_to_bus( head_list ), dev->base_addr + TLAN_CH_PARM );
ack |= TLAN_HC_GO | TLAN_HC_RT;
@@ -1175,13 +1156,13 @@ priv->rxHead, priv->rxTail );
TLan_DioWrite8( dev->base_addr, TLAN_LED_REG, TLAN_LED_LINK | TLAN_LED_ACT );
if ( priv->phyFlags & TLAN_PHY_ACTIVITY ) {
if ( priv->timerSetAt == 0 ) {
- // printk("RxEOF Starting timer...\n");
+ /* printk("RxEOF Starting timer...\n"); */
priv->timerSetAt = jiffies;
priv->timer.expires = jiffies + TLAN_TIMER_ACT_DELAY;
priv->timerType = TLAN_TIMER_ACT;
add_timer( &priv->timer );
} else if ( priv->timerType == TLAN_TIMER_ACT ) {
- // printk("RxEOF tarting continuing timer...\n");
+ /* printk("RxEOF tarting continuing timer...\n"); */
priv->timerSetAt = jiffies;
}
}
@@ -1250,8 +1231,7 @@ u32 TLan_HandleTxEOC( struct device *dev, u16 host_int )
host_int = 0;
if ( priv->tlanRev < 0x30 ) {
- TLAN_DBG( TLAN_DEBUG_TX, "TLAN TRANSMIT: Handling TX EOC (Head=%d Tail=%d) --
- IRQ\n", priv->txHead, priv->txTail );
+ TLAN_DBG( TLAN_DEBUG_TX, "TLAN TRANSMIT: Handling TX EOC (Head=%d Tail=%d) -- IRQ\n", priv->txHead, priv->txTail );
head_list = priv->txList + priv->txHead;
if ( ( head_list->cStat & TLAN_CSTAT_READY ) == TLAN_CSTAT_READY ) {
outl( virt_to_bus( head_list ), dev->base_addr + TLAN_CH_PARM );
@@ -1312,7 +1292,7 @@ u32 TLan_HandleStatusCheck( struct device *dev, u16 host_int )
priv->timerType = TLAN_TIMER_LINK;
add_timer( &priv->timer );
} else {
- //printk( " RX GO---->\n" );
+ /*printk( " RX GO---->\n" ); */
outl( virt_to_bus( priv->rxList ), dev->base_addr + TLAN_CH_PARM );
outl( TLAN_HC_GO | TLAN_HC_RT, dev->base_addr + TLAN_HOST_CMD );
}
@@ -1328,8 +1308,7 @@ u32 TLan_HandleStatusCheck( struct device *dev, u16 host_int )
TLan_PhyPrint( dev );
}
}
- TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN: Status Check! %s Net_Sts=%x\n", dev->name,
-(unsigned) net_sts );
+ TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN: Status Check! %s Net_Sts=%x\n", dev->name, (unsigned) net_sts );
}
return ack;
@@ -1367,8 +1346,7 @@ u32 TLan_HandleRxEOC( struct device *dev, u16 host_int )
host_int = 0;
if ( priv->tlanRev < 0x30 ) {
- TLAN_DBG( TLAN_DEBUG_RX, "TLAN RECEIVE: Handling RX EOC (Head=%d Tail=%d) --
-IRQ\n", priv->rxHead, priv->rxTail );
+ TLAN_DBG( TLAN_DEBUG_RX, "TLAN RECEIVE: Handling RX EOC (Head=%d Tail=%d) -- IRQ\n", priv->rxHead, priv->rxTail );
head_list = priv->rxList + priv->rxHead;
outl( virt_to_bus( head_list ), dev->base_addr + TLAN_CH_PARM );
ack |= TLAN_HC_GO | TLAN_HC_RT;
@@ -1427,8 +1405,7 @@ void TLan_Timer( unsigned long data )
u16 gen_sts;
TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv;
- // printk( "TLAN: %s Entered Timer, type = %d\n", dev->name, priv->timerType )
-;
+ /* printk( "TLAN: %s Entered Timer, type = %d\n", dev->name, priv->timerType ); */
switch ( priv->timerType ) {
case TLAN_TIMER_LINK:
@@ -1497,8 +1474,7 @@ void TLan_ResetLists( struct device *dev )
for ( i = 0; i < TLAN_NUM_TX_LISTS; i++ ) {
list = priv->txList + i;
list->cStat = TLAN_CSTAT_UNUSED;
- list->buffer[0].address = virt_to_bus( priv->txBuffer + ( i * TLAN_MAX_FRAME_S
-IZE ) );
+ list->buffer[0].address = virt_to_bus( priv->txBuffer + ( i * TLAN_MAX_FRAME_SIZE ) );
list->buffer[2].count = 0;
list->buffer[2].address = 0;
}
@@ -1510,8 +1486,7 @@ IZE ) );
list->cStat = TLAN_CSTAT_READY;
list->frameSize = TLAN_MAX_FRAME_SIZE;
list->buffer[0].count = TLAN_MAX_FRAME_SIZE | TLAN_LAST_BUFFER;
- list->buffer[0].address = virt_to_bus( priv->rxBuffer + ( i * TLAN_MAX_FRAME_S
-IZE ) );
+ list->buffer[0].address = virt_to_bus( priv->rxBuffer + ( i * TLAN_MAX_FRAME_SIZE ) );
list->buffer[1].count = 0;
list->buffer[1].address = 0;
if ( i < TLAN_NUM_RX_LISTS - 1 )
@@ -1544,8 +1519,7 @@ void TLan_PrintDio( u16 io_base )
u32 data0, data1;
int i;
- printk( "TLAN: Contents of internal registers for io base 0x%04hx.\n", io_bas
-e );
+ printk( "TLAN: Contents of internal registers for io base 0x%04hx.\n", io_base );
printk( "TLAN: Off. +0 +4\n" );
for ( i = 0; i < 0x4C; i+= 8 ) {
data0 = TLan_DioRead32( io_base, i );
@@ -1583,10 +1557,9 @@ void TLan_PrintList( TLanList *list, char *type, int num)
printk( "TLAN: Forward = 0x%08x\n", list->forward );
printk( "TLAN: CSTAT = 0x%04hx\n", list->cStat );
printk( "TLAN: Frame Size = 0x%04hx\n", list->frameSize );
- // for ( i = 0; i < 10; i++ ) {
+ /* for ( i = 0; i < 10; i++ ) { */
for ( i = 0; i < 2; i++ ) {
- printk( "TLAN: Buffer[%d].count, addr = 0x%08x, 0x%08x\n", i, list->buffe
-r[i].count, list->buffer[i].address );
+ printk( "TLAN: Buffer[%d].count, addr = 0x%08x, 0x%08x\n", i, list->buffer[i].count, list->buffer[i].address );
}
} /* TLan_PrintList */
@@ -1695,41 +1668,41 @@ int TLan_Reset( struct device *dev )
u32 data;
u8 data8;
-// 1. Assert reset bit.
+/* 1. Assert reset bit. */
data = inl(dev->base_addr + TLAN_HOST_CMD);
data |= TLAN_HC_AD_RST;
outl(data, dev->base_addr + TLAN_HOST_CMD);
-// 2. Turn off interrupts. ( Probably isn't necessary )
+/* 2. Turn off interrupts. ( Probably isn't necessary ) */
data = inl(dev->base_addr + TLAN_HOST_CMD);
data |= TLAN_HC_INT_OFF;
outl(data, dev->base_addr + TLAN_HOST_CMD);
-// 3. Clear AREGs and HASHs.
+/* 3. Clear AREGs and HASHs. */
for ( i = TLAN_AREG_0; i <= TLAN_HASH_2; i += 4 ) {
TLan_DioWrite32( dev->base_addr, (u16) i, 0 );
}
-// 4. Setup NetConfig register.
+/* 4. Setup NetConfig register. */
data = TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN | TLAN_NET_CFG_PHY_EN;
TLan_DioWrite16( dev->base_addr, TLAN_NET_CONFIG, (u16) data );
-// 5. Load Ld_Tmr and Ld_Thr in HOST_CMD.
+/* 5. Load Ld_Tmr and Ld_Thr in HOST_CMD. */
outl( TLAN_HC_LD_TMR | 0x0, dev->base_addr + TLAN_HOST_CMD );
outl( TLAN_HC_LD_THR | 0x1, dev->base_addr + TLAN_HOST_CMD );
-// 6. Unreset the MII by setting NMRST (in NetSio) to 1.
+/* 6. Unreset the MII by setting NMRST (in NetSio) to 1. */
outw( TLAN_NET_SIO, dev->base_addr + TLAN_DIO_ADR );
addr = dev->base_addr + TLAN_DIO_DATA + TLAN_NET_SIO;
TLan_SetBit( TLAN_NET_SIO_NMRST, addr );
-// 7. Setup the remaining registers.
+/* 7. Setup the remaining registers. */
if ( priv->tlanRev >= 0x30 ) {
data8 = TLAN_ID_TX_EOC | TLAN_ID_RX_EOC;
@@ -1947,17 +1920,18 @@ void TLan_PhySelect( struct device *dev )
u16 vendor;
u16 device;
- priv->phyCheck = &TLan_PhyNop; // Make sure these aren't ever NULL
+ priv->phyCheck = &TLan_PhyNop; /* Make sure these aren't ever NULL */
priv->phyService = &TLan_PhyNop;
vendor = TLanDeviceList[priv->pciEntry].vendorId;
device = TLanDeviceList[priv->pciEntry].deviceId;
- // This is a bit uglier than I'd like, but the 0xF130 device must
- // NOT be assigned a valid PHY as it uses an unmanaged, bit-rate
- // PHY. It is simplest just to use another goto, rather than
- // nesting the two for loops in the if statement.
-
+ /*
+ * This is a bit uglier than I'd like, but the 0xF130 device must
+ * NOT be assigned a valid PHY as it uses an unmanaged, bit-rate
+ * PHY. It is simplest just to use another goto, rather than
+ * nesting the two for loops in the if statement.
+ */
if ( ( vendor == PCI_VENDOR_ID_COMPAQ ) &&
( device == PCI_DEVICE_ID_NETFLEX_3P ) ) {
entry = 0;
@@ -2085,8 +2059,7 @@ int TLan_PhyInternalCheck( struct device *dev )
TLan_MiiReadReg( io, phy, MII_GEN_CTL, &gen_ctl );
if ( gen_ctl & MII_GC_PDOWN ) {
TLan_MiiSync( io );
- TLan_MiiWriteReg( io, phy, MII_GEN_CTL, MII_GC_PDOWN | MII_GC_LOOPBK | MII_GC_
-ISOLATE );
+ TLan_MiiWriteReg( io, phy, MII_GEN_CTL, MII_GC_PDOWN | MII_GC_LOOPBK | MII_GC_ISOLATE );
TLan_MiiWriteReg( io, phy, MII_GEN_CTL, MII_GC_LOOPBK );
udelay(50000);
TLan_MiiWriteReg( io, phy, MII_GEN_CTL, MII_GC_RESET | MII_GC_LOOPBK );
@@ -2097,8 +2070,8 @@ ISOLATE );
while ( value & MII_GC_RESET )
TLan_MiiReadReg( io, phy, MII_GEN_CTL, &value );
- // TLan_MiiWriteReg( io, phy, MII_GEN_CTL, MII_GC_LOOPBK | MII_GC_DUPLEX );
- // TLan_MiiWriteReg( io, phy, MII_GEN_CTL, MII_GC_DUPLEX );
+ /* TLan_MiiWriteReg( io, phy, MII_GEN_CTL, MII_GC_LOOPBK | MII_GC_DUPLEX ); */
+ /* TLan_MiiWriteReg( io, phy, MII_GEN_CTL, MII_GC_DUPLEX ); */
TLan_MiiWriteReg( io, phy, MII_GEN_CTL, 0 );
udelay(500000);
@@ -2110,9 +2083,9 @@ ISOLATE );
value &= ~TLAN_TC_AUISEL;
TLan_MiiWriteReg( io, phy, TLAN_TLPHY_CTL, value );
- // Read Possible Latched Link Status
+ /* Read Possible Latched Link Status */
TLan_MiiReadReg( io, phy, MII_GEN_STS, &value );
- // Read Real Link Status
+ /* Read Real Link Status */
TLan_MiiReadReg( io, phy, MII_GEN_STS, &value );
if ( ( value & MII_GS_LINK ) || aui ) {
priv->phyOnline = 1;
@@ -2122,7 +2095,7 @@ ISOLATE );
TLan_DioWrite8( io, TLAN_LED_REG, 0 );
}
- // Enable Interrupts
+ /* Enable Interrupts */
TLan_MiiReadReg( io, phy, TLAN_TLPHY_CTL, &value );
value |= TLAN_TC_INTEN;
TLan_MiiWriteReg( io, phy, TLAN_TLPHY_CTL, value );
@@ -2223,11 +2196,9 @@ static int TLan_PhyDp83840aCheck( struct device *dev )
TLan_MiiReadReg( io, phy, MII_GEN_CTL, &gen_ctl );
if ( gen_ctl & MII_GC_PDOWN ) {
TLan_MiiSync( io );
- TLan_MiiWriteReg( io, phy, MII_GEN_CTL, MII_GC_PDOWN | MII_GC_LOOPBK | MII_GC_
-ISOLATE );
+ TLan_MiiWriteReg( io, phy, MII_GEN_CTL, MII_GC_PDOWN | MII_GC_LOOPBK | MII_GC_ISOLATE );
TLan_MiiWriteReg( io, phy, MII_GEN_CTL, MII_GC_LOOPBK );
- for ( i = 0; i < 500000; i++ )
- SLOW_DOWN_IO;
+ udelay(500000);
TLan_MiiWriteReg( io, phy, MII_GEN_CTL, MII_GC_RESET | MII_GC_LOOPBK );
TLan_MiiSync( io );
}
@@ -2236,8 +2207,8 @@ ISOLATE );
while ( value & MII_GC_RESET )
TLan_MiiReadReg( io, phy, MII_GEN_CTL, &value );
- // TLan_MiiWriteReg( io, phy, MII_GEN_CTL, MII_GC_LOOPBK | MII_GC_DUPLEX );
- // TLan_MiiWriteReg( io, phy, MII_GEN_CTL, MII_GC_DUPLEX );
+ /* TLan_MiiWriteReg( io, phy, MII_GEN_CTL, MII_GC_LOOPBK | MII_GC_DUPLEX ); */
+ /* TLan_MiiWriteReg( io, phy, MII_GEN_CTL, MII_GC_DUPLEX ); */
TLan_MiiWriteReg( io, phy, MII_GEN_CTL, 0 );
TLan_MiiReadReg( io, phy, MII_AN_ADV, &value );
value &= ~0x0140;
@@ -2245,13 +2216,11 @@ ISOLATE );
TLan_MiiWriteReg( io, phy, MII_GEN_CTL, 0x1000 );
TLan_MiiWriteReg( io, phy, MII_GEN_CTL, 0x1200 );
- for ( i = 0; i < 50000; i++ )
- SLOW_DOWN_IO;
-
-/*
- // Read Possible Latched Link Status
+ udelay(50000);
+#if 0
+ /* Read Possible Latched Link Status */
TLan_MiiReadReg( io, phy, MII_GEN_STS, &value );
- // Read Real Link Status
+ /* Read Real Link Status */
TLan_MiiReadReg( io, phy, MII_GEN_STS, &value );
if ( value & MII_GS_LINK ) {
priv->phyOnline = 1;
@@ -2261,15 +2230,15 @@ ISOLATE );
TLan_DioWrite8( io, TLAN_LED_REG, 0 );
}
- // Enable Interrupts
+ /* Enable Interrupts */
TLan_MiiReadReg( io, phy, TLAN_TLPHY_CTL, &value );
value |= TLAN_TC_INTEN;
TLan_MiiWriteReg( io, phy, TLAN_TLPHY_CTL, value );
-*/
+#endif
sio = TLan_DioRead8( dev->base_addr, TLAN_NET_SIO );
sio &= ~TLAN_NET_SIO_MINTEN;
TLan_DioWrite8( dev->base_addr, TLAN_NET_SIO, sio );
-// priv->phyOnline = 1;
+/* priv->phyOnline = 1; */
return 0;
@@ -2592,7 +2561,7 @@ int TLan_EeSendByte( u16 io_base, u8 data, int stop )
outw( TLAN_NET_SIO, io_base + TLAN_DIO_ADR );
sio = io_base + TLAN_DIO_DATA + TLAN_NET_SIO;
- // Assume clock is low, tx is enabled;
+ /* Assume clock is low, tx is enabled; */
for ( place = 0x80; place != 0; place >>= 1 ) {
if ( place & data )
TLan_SetBit( TLAN_NET_SIO_EDATA, sio );
@@ -2608,8 +2577,7 @@ int TLan_EeSendByte( u16 io_base, u8 data, int stop )
TLan_SetBit( TLAN_NET_SIO_ETXEN, sio );
if ( ( ! err ) && stop ) {
- TLan_ClearBit( TLAN_NET_SIO_EDATA, sio ); // STOP, raise data while clock is h
-igh
+ TLan_ClearBit( TLAN_NET_SIO_EDATA, sio ); /* STOP, raise data while clock is high */
TLan_SetBit( TLAN_NET_SIO_ECLOK, sio );
TLan_SetBit( TLAN_NET_SIO_EDATA, sio );
}
@@ -2654,7 +2622,7 @@ void TLan_EeReceiveByte( u16 io_base, u8 *data, int stop )
sio = io_base + TLAN_DIO_DATA + TLAN_NET_SIO;
*data = 0;
- // Assume clock is low, tx is enabled;
+ /* Assume clock is low, tx is enabled; */
TLan_ClearBit( TLAN_NET_SIO_ETXEN, sio );
for ( place = 0x80; place; place >>= 1 ) {
TLan_SetBit( TLAN_NET_SIO_ECLOK, sio );
@@ -2665,15 +2633,14 @@ void TLan_EeReceiveByte( u16 io_base, u8 *data, int stop )
TLan_SetBit( TLAN_NET_SIO_ETXEN, sio );
if ( ! stop ) {
- TLan_ClearBit( TLAN_NET_SIO_EDATA, sio ); // Ack = 0
+ TLan_ClearBit( TLAN_NET_SIO_EDATA, sio ); /* Ack = 0 */
TLan_SetBit( TLAN_NET_SIO_ECLOK, sio );
TLan_ClearBit( TLAN_NET_SIO_ECLOK, sio );
} else {
- TLan_SetBit( TLAN_NET_SIO_EDATA, sio ); // No ack = 1 (?)
+ TLan_SetBit( TLAN_NET_SIO_EDATA, sio ); /* No ack = 1 (?) */
TLan_SetBit( TLAN_NET_SIO_ECLOK, sio );
TLan_ClearBit( TLAN_NET_SIO_ECLOK, sio );
- TLan_ClearBit( TLAN_NET_SIO_EDATA, sio ); // STOP, raise data while clock is h
-igh
+ TLan_ClearBit( TLAN_NET_SIO_EDATA, sio ); /* STOP, raise data while clock is high */
TLan_SetBit( TLAN_NET_SIO_ECLOK, sio );
TLan_SetBit( TLAN_NET_SIO_EDATA, sio );
}
diff --git a/drivers/net/tlan.h b/drivers/net/tlan.h
index c4f6d6c5e..94613d3a6 100644
--- a/drivers/net/tlan.h
+++ b/drivers/net/tlan.h
@@ -483,26 +483,19 @@ inline u32 xor( u32 a, u32 b )
{
return ( ( a && ! b ) || ( ! a && b ) );
}
-#define XOR8( a, b, c, d, e, f, g, h ) xor( a, xor( b, xor( c, xor( d, xor( e, x
-or( f, xor( g, h ) ) ) ) ) ) )
+#define XOR8( a, b, c, d, e, f, g, h ) xor( a, xor( b, xor( c, xor( d, xor( e, xor( f, xor( g, h ) ) ) ) ) ) )
#define DA( a, bit ) ( ( (u8) a[bit/8] ) & ( (u8) ( 1 << bit%8 ) ) )
inline u32 TLan_HashFunc( u8 *a )
{
u32 hash;
- hash = XOR8( DA(a,0), DA(a, 6), DA(a,12), DA(a,18), DA(a,24), DA(a,30), DA(a,3
-6), DA(a,42) );
- hash |= XOR8( DA(a,1), DA(a, 7), DA(a,13), DA(a,19), DA(a,25), DA(a,31), DA(a,3
-7), DA(a,43) ) << 1;
- hash |= XOR8( DA(a,2), DA(a, 8), DA(a,14), DA(a,20), DA(a,26), DA(a,32), DA(a,3
-8), DA(a,44) ) << 2;
- hash |= XOR8( DA(a,3), DA(a, 9), DA(a,15), DA(a,21), DA(a,27), DA(a,33), DA(a,3
-9), DA(a,45) ) << 3;
- hash |= XOR8( DA(a,4), DA(a,10), DA(a,16), DA(a,22), DA(a,28), DA(a,34), DA(a,4
-0), DA(a,46) ) << 4;
- hash |= XOR8( DA(a,5), DA(a,11), DA(a,17), DA(a,23), DA(a,29), DA(a,35), DA(a,4
-1), DA(a,47) ) << 5;
+ hash = XOR8( DA(a,0), DA(a, 6), DA(a,12), DA(a,18), DA(a,24), DA(a,30), DA(a,36), DA(a,42) );
+ hash |= XOR8( DA(a,1), DA(a, 7), DA(a,13), DA(a,19), DA(a,25), DA(a,31), DA(a,37), DA(a,43) ) << 1;
+ hash |= XOR8( DA(a,2), DA(a, 8), DA(a,14), DA(a,20), DA(a,26), DA(a,32), DA(a,38), DA(a,44) ) << 2;
+ hash |= XOR8( DA(a,3), DA(a, 9), DA(a,15), DA(a,21), DA(a,27), DA(a,33), DA(a,39), DA(a,45) ) << 3;
+ hash |= XOR8( DA(a,4), DA(a,10), DA(a,16), DA(a,22), DA(a,28), DA(a,34), DA(a,40), DA(a,46) ) << 4;
+ hash |= XOR8( DA(a,5), DA(a,11), DA(a,17), DA(a,23), DA(a,29), DA(a,35), DA(a,41), DA(a,47) ) << 5;
return hash;
diff --git a/drivers/net/z8530.h b/drivers/net/z8530.h
index 3d4a918d7..e69de29bb 100644
--- a/drivers/net/z8530.h
+++ b/drivers/net/z8530.h
@@ -1,243 +0,0 @@
-
-/* 8530 Serial Communications Controller Register definitions */
-#define FLAG 0x7e
-
-/* Write Register 0 */
-#define R0 0 /* Register selects */
-#define R1 1
-#define R2 2
-#define R3 3
-#define R4 4
-#define R5 5
-#define R6 6
-#define R7 7
-#define R8 8
-#define R9 9
-#define R10 10
-#define R11 11
-#define R12 12
-#define R13 13
-#define R14 14
-#define R15 15
-
-#define NULLCODE 0 /* Null Code */
-#define POINT_HIGH 0x8 /* Select upper half of registers */
-#define RES_EXT_INT 0x10 /* Reset Ext. Status Interrupts */
-#define SEND_ABORT 0x18 /* HDLC Abort */
-#define RES_RxINT_FC 0x20 /* Reset RxINT on First Character */
-#define RES_Tx_P 0x28 /* Reset TxINT Pending */
-#define ERR_RES 0x30 /* Error Reset */
-#define RES_H_IUS 0x38 /* Reset highest IUS */
-
-#define RES_Rx_CRC 0x40 /* Reset Rx CRC Checker */
-#define RES_Tx_CRC 0x80 /* Reset Tx CRC Checker */
-#define RES_EOM_L 0xC0 /* Reset EOM latch */
-
-/* Write Register 1 */
-
-#define EXT_INT_ENAB 0x1 /* Ext Int Enable */
-#define TxINT_ENAB 0x2 /* Tx Int Enable */
-#define PAR_SPEC 0x4 /* Parity is special condition */
-
-#define RxINT_DISAB 0 /* Rx Int Disable */
-#define RxINT_FCERR 0x8 /* Rx Int on First Character Only or Error */
-#define INT_ALL_Rx 0x10 /* Int on all Rx Characters or error */
-#define INT_ERR_Rx 0x18 /* Int on error only */
-
-#define WT_RDY_RT 0x20 /* Wait/Ready on R/T */
-#define WT_FN_RDYFN 0x40 /* Wait/FN/Ready FN */
-#define WT_RDY_ENAB 0x80 /* Wait/Ready Enable */
-
-/* Write Register #2 (Interrupt Vector) */
-
-/* Write Register 3 */
-
-#define RxENABLE 0x1 /* Rx Enable */
-#define SYNC_L_INH 0x2 /* Sync Character Load Inhibit */
-#define ADD_SM 0x4 /* Address Search Mode (SDLC) */
-#define RxCRC_ENAB 0x8 /* Rx CRC Enable */
-#define ENT_HM 0x10 /* Enter Hunt Mode */
-#define AUTO_ENAB 0x20 /* Auto Enables */
-#define Rx5 0x0 /* Rx 5 Bits/Character */
-#define Rx7 0x40 /* Rx 7 Bits/Character */
-#define Rx6 0x80 /* Rx 6 Bits/Character */
-#define Rx8 0xc0 /* Rx 8 Bits/Character */
-
-/* Write Register 4 */
-
-#define PAR_ENA 0x1 /* Parity Enable */
-#define PAR_EVEN 0x2 /* Parity Even/Odd* */
-
-#define SYNC_ENAB 0 /* Sync Modes Enable */
-#define SB1 0x4 /* 1 stop bit/char */
-#define SB15 0x8 /* 1.5 stop bits/char */
-#define SB2 0xc /* 2 stop bits/char */
-
-#define MONSYNC 0 /* 8 Bit Sync character */
-#define BISYNC 0x10 /* 16 bit sync character */
-#define SDLC 0x20 /* SDLC Mode (01111110 Sync Flag) */
-#define EXTSYNC 0x30 /* External Sync Mode */
-
-#define X1CLK 0x0 /* x1 clock mode */
-#define X16CLK 0x40 /* x16 clock mode */
-#define X32CLK 0x80 /* x32 clock mode */
-#define X64CLK 0xC0 /* x64 clock mode */
-
-/* Write Register 5 */
-
-#define TxCRC_ENAB 0x1 /* Tx CRC Enable */
-#define RTS 0x2 /* RTS */
-#define SDLC_CRC 0x4 /* SDLC/CRC-16 */
-#define TxENAB 0x8 /* Tx Enable */
-#define SND_BRK 0x10 /* Send Break */
-#define Tx5 0x0 /* Tx 5 bits (or less)/character */
-#define Tx7 0x20 /* Tx 7 bits/character */
-#define Tx6 0x40 /* Tx 6 bits/character */
-#define Tx8 0x60 /* Tx 8 bits/character */
-#define DTR 0x80 /* DTR */
-
-/* Write Register 6 (Sync bits 0-7/SDLC Address Field) */
-
-/* Write Register 7 (Sync bits 8-15/SDLC 01111110) */
-
-/* Write Register 8 (transmit buffer) */
-
-/* Write Register 9 (Master interrupt control) */
-#define VIS 1 /* Vector Includes Status */
-#define NV 2 /* No Vector */
-#define DLC 4 /* Disable Lower Chain */
-#define MIE 8 /* Master Interrupt Enable */
-#define STATHI 0x10 /* Status high */
-#define NORESET 0 /* No reset on write to R9 */
-#define CHRB 0x40 /* Reset channel B */
-#define CHRA 0x80 /* Reset channel A */
-#define FHWRES 0xc0 /* Force hardware reset */
-
-/* Write Register 10 (misc control bits) */
-#define BIT6 1 /* 6 bit/8bit sync */
-#define LOOPMODE 2 /* SDLC Loop mode */
-#define ABUNDER 4 /* Abort/flag on SDLC xmit underrun */
-#define MARKIDLE 8 /* Mark/flag on idle */
-#define GAOP 0x10 /* Go active on poll */
-#define NRZ 0 /* NRZ mode */
-#define NRZI 0x20 /* NRZI mode */
-#define FM1 0x40 /* FM1 (transition = 1) */
-#define FM0 0x60 /* FM0 (transition = 0) */
-#define CRCPS 0x80 /* CRC Preset I/O */
-
-/* Write Register 11 (Clock Mode control) */
-#define TRxCXT 0 /* TRxC = Xtal output */
-#define TRxCTC 1 /* TRxC = Transmit clock */
-#define TRxCBR 2 /* TRxC = BR Generator Output */
-#define TRxCDP 3 /* TRxC = DPLL output */
-#define TRxCOI 4 /* TRxC O/I */
-#define TCRTxCP 0 /* Transmit clock = RTxC pin */
-#define TCTRxCP 8 /* Transmit clock = TRxC pin */
-#define TCBR 0x10 /* Transmit clock = BR Generator output */
-#define TCDPLL 0x18 /* Transmit clock = DPLL output */
-#define RCRTxCP 0 /* Receive clock = RTxC pin */
-#define RCTRxCP 0x20 /* Receive clock = TRxC pin */
-#define RCBR 0x40 /* Receive clock = BR Generator output */
-#define RCDPLL 0x60 /* Receive clock = DPLL output */
-#define RTxCX 0x80 /* RTxC Xtal/No Xtal */
-
-/* Write Register 12 (lower byte of baud rate generator time constant) */
-
-/* Write Register 13 (upper byte of baud rate generator time constant) */
-
-/* Write Register 14 (Misc control bits) */
-#define BRENABL 1 /* Baud rate generator enable */
-#define BRSRC 2 /* Baud rate generator source */
-#define DTRREQ 4 /* DTR/Request function */
-#define AUTOECHO 8 /* Auto Echo */
-#define LOOPBAK 0x10 /* Local loopback */
-#define SEARCH 0x20 /* Enter search mode */
-#define RMC 0x40 /* Reset missing clock */
-#define DISDPLL 0x60 /* Disable DPLL */
-#define SSBR 0x80 /* Set DPLL source = BR generator */
-#define SSRTxC 0xa0 /* Set DPLL source = RTxC */
-#define SFMM 0xc0 /* Set FM mode */
-#define SNRZI 0xe0 /* Set NRZI mode */
-
-/* Write Register 15 (external/status interrupt control) */
-#define ZCIE 2 /* Zero count IE */
-#define DCDIE 8 /* DCD IE */
-#define SYNCIE 0x10 /* Sync/hunt IE */
-#define CTSIE 0x20 /* CTS IE */
-#define TxUIE 0x40 /* Tx Underrun/EOM IE */
-#define BRKIE 0x80 /* Break/Abort IE */
-
-
-/* Read Register 0 */
-#define Rx_CH_AV 0x1 /* Rx Character Available */
-#define ZCOUNT 0x2 /* Zero count */
-#define Tx_BUF_EMP 0x4 /* Tx Buffer empty */
-#define DCD 0x8 /* DCD */
-#define SYNC_HUNT 0x10 /* Sync/hunt */
-#define CTS 0x20 /* CTS */
-#define TxEOM 0x40 /* Tx underrun */
-#define BRK_ABRT 0x80 /* Break/Abort */
-
-/* Read Register 1 */
-#define ALL_SNT 0x1 /* All sent */
-/* Residue Data for 8 Rx bits/char programmed */
-#define RES3 0x8 /* 0/3 */
-#define RES4 0x4 /* 0/4 */
-#define RES5 0xc /* 0/5 */
-#define RES6 0x2 /* 0/6 */
-#define RES7 0xa /* 0/7 */
-#define RES8 0x6 /* 0/8 */
-#define RES18 0xe /* 1/8 */
-#define RES28 0x0 /* 2/8 */
-/* Special Rx Condition Interrupts */
-#define PAR_ERR 0x10 /* Parity error */
-#define Rx_OVR 0x20 /* Rx Overrun Error */
-#define CRC_ERR 0x40 /* CRC/Framing Error */
-#define END_FR 0x80 /* End of Frame (SDLC) */
-
-/* Read Register 2 (channel b only) - Interrupt vector */
-
-/* Read Register 3 (interrupt pending register) ch a only */
-#define CHBEXT 0x1 /* Channel B Ext/Stat IP */
-#define CHBTxIP 0x2 /* Channel B Tx IP */
-#define CHBRxIP 0x4 /* Channel B Rx IP */
-#define CHAEXT 0x8 /* Channel A Ext/Stat IP */
-#define CHATxIP 0x10 /* Channel A Tx IP */
-#define CHARxIP 0x20 /* Channel A Rx IP */
-
-/* Read Register 8 (receive data register) */
-
-/* Read Register 10 (misc status bits) */
-#define ONLOOP 2 /* On loop */
-#define LOOPSEND 0x10 /* Loop sending */
-#define CLK2MIS 0x40 /* Two clocks missing */
-#define CLK1MIS 0x80 /* One clock missing */
-
-/* Read Register 12 (lower byte of baud rate generator constant) */
-
-/* Read Register 13 (upper byte of baud rate generator constant) */
-
-/* Read Register 15 (value of WR 15) */
-
-/* 8580/85180/85280 Enhanced SCC register definitions */
-
-/* Write Register 7' (SDLC/HDLC Programmable Enhancements) */
-#define AUTOTXF 0x01 /* Auto Tx Flag */
-#define AUTOEOM 0x02 /* Auto EOM Latch Reset */
-#define AUTORTS 0x04 /* Auto RTS */
-#define TXDNRZI 0x08 /* TxD Pulled High in SDLC NRZI mode */
-#define FASTDTR 0x10 /* Fast DTR/REQ Mode */
-#define CRCCBCR 0x20 /* CRC Check Bytes Completely Received */
-#define EXTRDEN 0x40 /* Extended Read Enabled */
-
-/* Write Register 15 (external/status interrupt control) */
-#define SHDLCE 1 /* SDLC/HDLC Enhancements Enable */
-#define FIFOE 4 /* FIFO Enable */
-
-/* Read Register 6 (frame status FIFO) */
-#define BCLSB 0xff /* LSB of 14 bits count */
-
-/* Read Register 7 (frame status FIFO) */
-#define BCMSB 0x3f /* MSB of 14 bits count */
-#define FDA 0x40 /* FIFO Data Available Status */
-#define FOY 0x80 /* FIFO Overflow Status */
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index a6966ad95..c39083b24 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -60,9 +60,11 @@ struct pci_dev_info dev_info[] = {
DEVICE( NCR, NCR_53C895, "53c895"),
DEVICE( NCR, NCR_53C885, "53c885"),
DEVICE( NCR, NCR_53C875, "53c875"),
+ DEVICE( NCR, NCR_53C876, "53c876"),
DEVICE( ATI, ATI_68800, "68800AX"),
DEVICE( ATI, ATI_215CT222, "215CT222"),
DEVICE( ATI, ATI_210888CX, "210888CX"),
+ DEVICE( ATI, ATI_215GB, "Mach64 GB"),
DEVICE( ATI, ATI_215GP, "Mach64 GP (Rage Pro)"),
DEVICE( ATI, ATI_215GT, "Mach64 GT (Rage II)"),
DEVICE( ATI, ATI_215GTB, "Mach64 GT (Rage II)"),
@@ -72,7 +74,9 @@ struct pci_dev_info dev_info[] = {
DEVICE( VLSI, VLSI_82C593, "82C593-FC1"),
DEVICE( VLSI, VLSI_82C594, "82C594-AFC2"),
DEVICE( VLSI, VLSI_82C597, "82C597-AFC2"),
- DEVICE( VLSI, VLSI_VAS96011, "VAS96011 PowerPC"),
+ DEVICE( VLSI, VLSI_82C541, "82C541 Lynx"),
+ DEVICE( VLSI, VLSI_82C543, "82C543 Lynx ISA"),
+ DEVICE( VLSI, VLSI_VAS96011, "VAS96011 (Golden Gate II)"),
DEVICE( ADL, ADL_2301, "2301"),
DEVICE( NS, NS_87415, "87415"),
DEVICE( NS, NS_87410, "87410"),
@@ -108,6 +112,7 @@ struct pci_dev_info dev_info[] = {
DEVICE( CIRRUS, CIRRUS_7543, "CL 7543"),
DEVICE( CIRRUS, CIRRUS_7541, "CL 7541"),
DEVICE( IBM, IBM_FIRE_CORAL, "Fire Coral"),
+ DEVICE( IBM, IBM_TR, "Token Ring"),
DEVICE( IBM, IBM_82G2675, "82G2675"),
DEVICE( IBM, IBM_82351, "82351"),
DEVICE( WD, WD_7197, "WD 7197"),
@@ -116,6 +121,7 @@ struct pci_dev_info dev_info[] = {
DEVICE( TRIDENT, TRIDENT_9420, "TG 9420"),
DEVICE( TRIDENT, TRIDENT_9440, "TG 9440"),
DEVICE( TRIDENT, TRIDENT_9660, "TG 9660"),
+ DEVICE( TRIDENT, TRIDENT_9750, "Image 975"),
DEVICE( AI, AI_M1435, "M1435"),
DEVICE( MATROX, MATROX_MGA_2, "Atlas PX2085"),
DEVICE( MATROX, MATROX_MIL, "Millennium"),
@@ -127,6 +133,7 @@ struct pci_dev_info dev_info[] = {
DEVICE( CT, CT_65550, "65550"),
DEVICE( CT, CT_65554, "65554"),
DEVICE( MIRO, MIRO_36050, "ZR36050"),
+ DEVICE( NEC, NEC_PCX2, "PowerVR PCX2"),
DEVICE( FD, FD_36C70, "TMC-18C30"),
DEVICE( SI, SI_6201, "6201"),
DEVICE( SI, SI_6202, "6202"),
@@ -139,6 +146,7 @@ struct pci_dev_info dev_info[] = {
DEVICE( SI, SI_5511, "85C5511"),
DEVICE( SI, SI_5513, "85C5513"),
DEVICE( SI, SI_5571, "5571"),
+ DEVICE( SI, SI_5597, "5597"),
DEVICE( SI, SI_7001, "7001"),
DEVICE( HP, HP_J2585A, "J2585A"),
DEVICE( HP, HP_J2585B, "J2585B (Lassen)"),
@@ -149,12 +157,17 @@ struct pci_dev_info dev_info[] = {
DEVICE( OPTI, OPTI_82C557, "82C557"),
DEVICE( OPTI, OPTI_82C558, "82C558"),
DEVICE( OPTI, OPTI_82C621, "82C621"),
+ DEVICE( OPTI, OPTI_82C700, "82C700"),
+ DEVICE( OPTI, OPTI_82C701, "82C701 FireStar Plus"),
+ DEVICE( OPTI, OPTI_82C814, "82C814 Firebridge 1"),
DEVICE( OPTI, OPTI_82C822, "82C822"),
DEVICE( SGS, SGS_2000, "STG 2000X"),
DEVICE( SGS, SGS_1764, "STG 1764X"),
DEVICE( BUSLOGIC, BUSLOGIC_MULTIMASTER_NC, "MultiMaster NC"),
DEVICE( BUSLOGIC, BUSLOGIC_MULTIMASTER, "MultiMaster"),
DEVICE( BUSLOGIC, BUSLOGIC_FLASHPOINT, "FlashPoint"),
+ DEVICE( TI, TI_TVP4010, "TVP4010 Permedia"),
+ DEVICE( TI, TI_TVP4020, "TVP4020 Permedia 2"),
DEVICE( TI, TI_PCI1130, "PCI1130"),
DEVICE( TI, TI_PCI1131, "PCI1131"),
DEVICE( OAK, OAK_OTI107, "OTI107"),
@@ -162,7 +175,7 @@ struct pci_dev_info dev_info[] = {
DEVICE( MOTOROLA, MOTOROLA_MPC105,"MPC105 Eagle"),
DEVICE( MOTOROLA, MOTOROLA_MPC106,"MPC106 Grackle"),
DEVICE( MOTOROLA, MOTOROLA_RAVEN, "Raven"),
- DEVICE( PROMISE, PROMISE_IDE_UDMA,"IDE Ultra DMA/33"),
+ DEVICE( PROMISE, PROMISE_20246, "IDE UltraDMA/33"),
DEVICE( PROMISE, PROMISE_5300, "DC5030"),
DEVICE( N9, N9_I128, "Imagine 128"),
DEVICE( N9, N9_I128_2, "Imagine 128v2"),
@@ -229,9 +242,11 @@ struct pci_dev_info dev_info[] = {
DEVICE( AL, AL_M4803, "M4803"),
DEVICE( AL, AL_M5219, "M5219"),
DEVICE( AL, AL_M5229, "M5229 TXpro"),
+ DEVICE( SURECOM, SURECOM_NE34, "NE-34PCI LAN"),
DEVICE( NEOMAGIC, NEOMAGIC_MAGICGRAPH_NM2070, "Magicgraph NM2070"),
DEVICE( NEOMAGIC, NEOMAGIC_MAGICGRAPH_128V, "MagicGraph 128V"),
DEVICE( NEOMAGIC, NEOMAGIC_MAGICGRAPH_128ZV, "MagicGraph 128ZV"),
+ DEVICE( NEOMAGIC, NEOMAGIC_MAGICGRAPH_NM2160, "MagicGraph NM2160"),
DEVICE( ASP, ASP_ABP940, "ABP940"),
DEVICE( ASP, ASP_ABP940U, "ABP940U"),
DEVICE( CERN, CERN_SPSB_PMC, "STAR/RD24 SCI-PCI (PMC)"),
@@ -301,6 +316,7 @@ struct pci_dev_info dev_info[] = {
DEVICE( ALLIANCE, ALLIANCE_PROMOTIO, "Promotion-6410"),
DEVICE( ALLIANCE, ALLIANCE_PROVIDEO, "Provideo"),
DEVICE( ALLIANCE, ALLIANCE_AT24, "AT24"),
+ DEVICE( ALLIANCE, ALLIANCE_AT3D, "AT3D"),
DEVICE( VMIC, VMIC_VME, "VMIVME-7587"),
DEVICE( DIGI, DIGI_RIGHTSWITCH, "RightSwitch SE-6"),
DEVICE( MUTECH, MUTECH_MV1000, "MV-1000"),
@@ -311,9 +327,11 @@ struct pci_dev_info dev_info[] = {
DEVICE( ZEITNET, ZEITNET_1225, "1225"),
DEVICE( OMEGA, OMEGA_82C092G, "82C092G"),
BRIDGE( GALILEO, GALILEO_GT64011, "GT64011", 0x00),
+ DEVICE( LITEON, LITEON_LNE100TX,"LNE100TX"),
DEVICE( NP, NP_PCI_FDDI, "NP-PCI"),
DEVICE( SPECIALIX, SPECIALIX_XIO, "XIO/SIO host"),
DEVICE( SPECIALIX, SPECIALIX_RIO, "RIO host"),
+ DEVICE( AURAVISION, AURAVISION_VXP524,"VXP524"),
DEVICE( IKON, IKON_10115, "10115 Greensheet"),
DEVICE( IKON, IKON_10117, "10117 Greensheet"),
DEVICE( ZORAN, ZORAN_36057, "ZR36057"),
@@ -337,7 +355,7 @@ struct pci_dev_info dev_info[] = {
DEVICE( OPTIBASE, OPTIBASE_VQUEST,"VideoQuest"),
DEVICE( ENSONIQ, ENSONIQ_AUDIOPCI,"AudioPCI"),
DEVICE( PICTUREL, PICTUREL_PCIVST,"PCIVST"),
- DEVICE( NVIDIA, NVIDIA_RIVA128, "Riva 128"),
+ DEVICE( NVIDIA_SGS, NVIDIA_SGS_RIVA128, "Riva 128"),
DEVICE( SYMPHONY, SYMPHONY_101, "82C101"),
DEVICE( TEKRAM, TEKRAM_DC290, "DC-290"),
DEVICE( 3DLABS, 3DLABS_300SX, "GLINT 300SX"),
@@ -391,11 +409,14 @@ struct pci_dev_info dev_info[] = {
DEVICE( INTEL, INTEL_82371AB, "82371AB PIIX4 IDE"),
DEVICE( INTEL, INTEL_82371AB_2,"82371AB PIIX4 USB"),
DEVICE( INTEL, INTEL_82371AB_3,"82371AB PIIX4 ACPI"),
+ DEVICE( INTEL, INTEL_82443LX_0,"440LX - 82443LX PAC Host"),
+ DEVICE( INTEL, INTEL_82443LX_1,"440LX - 82443LX PAC AGP"),
DEVICE( INTEL, INTEL_P6, "Orion P6"),
DEVICE( INTEL, INTEL_82450GX, "82450GX Orion P6"),
DEVICE( KTI, KTI_ET32P2, "ET32P2"),
DEVICE( ADAPTEC, ADAPTEC_7850, "AIC-7850"),
DEVICE( ADAPTEC, ADAPTEC_7855, "AIC-7855"),
+ DEVICE( ADAPTEC, ADAPTEC_5800, "AIC-5800"),
DEVICE( ADAPTEC, ADAPTEC_7860, "AIC-7860"),
DEVICE( ADAPTEC, ADAPTEC_7861, "AIC-7861"),
DEVICE( ADAPTEC, ADAPTEC_7870, "AIC-7870"),
@@ -403,6 +424,7 @@ struct pci_dev_info dev_info[] = {
DEVICE( ADAPTEC, ADAPTEC_7872, "AIC-7872"),
DEVICE( ADAPTEC, ADAPTEC_7873, "AIC-7873"),
DEVICE( ADAPTEC, ADAPTEC_7874, "AIC-7874"),
+ DEVICE( ADAPTEC, ADAPTEC_7895, "AIC-7895U"),
DEVICE( ADAPTEC, ADAPTEC_7880, "AIC-7880U"),
DEVICE( ADAPTEC, ADAPTEC_7881, "AIC-7881U"),
DEVICE( ADAPTEC, ADAPTEC_7882, "AIC-7882U"),
@@ -611,7 +633,7 @@ const char *pci_strvendor(unsigned int vendor)
case PCI_VENDOR_ID_NCR: return "NCR";
case PCI_VENDOR_ID_ATI: return "ATI";
case PCI_VENDOR_ID_VLSI: return "VLSI";
- case PCI_VENDOR_ID_ADL: return "Advance Logic";
+ case PCI_VENDOR_ID_ADL: return "Avance Logic";
case PCI_VENDOR_ID_NS: return "NS";
case PCI_VENDOR_ID_TSENG: return "Tseng'Lab";
case PCI_VENDOR_ID_WEITEK: return "Weitek";
@@ -662,9 +684,11 @@ const char *pci_strvendor(unsigned int vendor)
case PCI_VENDOR_ID_SMC: return "SMC";
case PCI_VENDOR_ID_AL: return "Acer Labs";
case PCI_VENDOR_ID_MITSUBISHI: return "Mitsubishi";
+ case PCI_VENDOR_ID_SURECOM: return "Surecom";
case PCI_VENDOR_ID_NEOMAGIC: return "Neomagic";
case PCI_VENDOR_ID_ASP: return "Advanced System Products";
case PCI_VENDOR_ID_CERN: return "CERN";
+ case PCI_VENDOR_ID_NVIDIA: return "NVidia";
case PCI_VENDOR_ID_IMS: return "IMS";
case PCI_VENDOR_ID_TEKRAM2: return "Tekram";
case PCI_VENDOR_ID_TUNDRA: return "Tundra";
@@ -690,8 +714,10 @@ const char *pci_strvendor(unsigned int vendor)
case PCI_VENDOR_ID_ZEITNET: return "ZeitNet";
case PCI_VENDOR_ID_OMEGA: return "Omega Micro";
case PCI_VENDOR_ID_GALILEO: return "Galileo Technology";
+ case PCI_VENDOR_ID_LITEON: return "LiteOn";
case PCI_VENDOR_ID_NP: return "Network Peripherals";
case PCI_VENDOR_ID_SPECIALIX: return "Specialix";
+ case PCI_VENDOR_ID_AURAVISION: return "Auravision";
case PCI_VENDOR_ID_IKON: return "Ikon";
case PCI_VENDOR_ID_ZORAN: return "Zoran";
case PCI_VENDOR_ID_COMPEX: return "Compex";
@@ -702,7 +728,7 @@ const char *pci_strvendor(unsigned int vendor)
case PCI_VENDOR_ID_OPTIBASE: return "Optibase";
case PCI_VENDOR_ID_ENSONIQ: return "Ensoniq";
case PCI_VENDOR_ID_PICTUREL: return "Picture Elements";
- case PCI_VENDOR_ID_NVIDIA: return "NVidia/SGS Thomson";
+ case PCI_VENDOR_ID_NVIDIA_SGS: return "NVidia/SGS Thomson";
case PCI_VENDOR_ID_SYMPHONY: return "Symphony";
case PCI_VENDOR_ID_TEKRAM: return "Tekram";
case PCI_VENDOR_ID_3DLABS: return "3Dlabs";
diff --git a/drivers/pnp/parport_probe.c b/drivers/pnp/parport_probe.c
index 70aebe874..836d1aa66 100644
--- a/drivers/pnp/parport_probe.c
+++ b/drivers/pnp/parport_probe.c
@@ -1,4 +1,4 @@
-/* $Id: parport_probe.c,v 1.1.2.9 1997/03/29 21:08:16 phil Exp $
+/* $Id: parport_probe.c,v 1.3 1997/10/19 18:18:46 phil Exp $
* Parallel port device probing code
*
* Authors: Carsten Gross, carsten@sol.wohnheim.uni-ulm.de
@@ -28,9 +28,9 @@ static inline int read_nibble(struct parport *port)
{
unsigned char i;
i = parport_read_status(port)>>3;
- i&=~8;
- if ( ( i & 0x10) == 0) i|=8;
- return(i & 0x0f);
+ i &= ~8;
+ if ((i & 0x10) == 0) i |= 8;
+ return (i & 0x0f);
}
static void read_terminate(struct parport *port) {
@@ -44,7 +44,6 @@ static void read_terminate(struct parport *port) {
parport_wait_peripheral(port, 0x80, 0x80);
/* no timeout possible, Autofeed low, SelectIN high */
parport_write_control(port, (parport_read_control(port) & ~2) | 8);
- return;
}
static long read_polled(struct parport *port, char *buf,
@@ -94,7 +93,6 @@ static void wakeup(void *ref)
return;
wake_up(&wait_q);
- return;
}
int parport_probe(struct parport *port, char *buffer, int len)
@@ -221,9 +219,11 @@ static void parse_data(struct parport *port, char *str)
static void pretty_print(struct parport *port)
{
- printk(KERN_INFO "%s: %s", port->name, classes[port->probe_info.class].descr);
+ printk(KERN_INFO "%s: %s", port->name,
+ classes[port->probe_info.class].descr);
if (port->probe_info.class) {
- printk(", %s (%s)", port->probe_info.model, port->probe_info.mfr);
+ printk(", %s %s", port->probe_info.mfr,
+ port->probe_info.model);
}
printk("\n");
}
@@ -267,12 +267,16 @@ void parport_probe_one(struct parport *port)
int init_module(void)
{
struct parport *p;
+ MOD_INC_USE_COUNT;
for (p = parport_enumerate(); p; p = p->next)
parport_probe_one(p);
+ parport_probe_hook = &parport_probe_one;
+ MOD_DEC_USE_COUNT;
return 0;
}
void cleanup_module(void)
{
+ parport_probe_hook = NULL;
}
#endif
diff --git a/drivers/scsi/BusLogic.h b/drivers/scsi/BusLogic.h
index 87e44e758..6f62e04b0 100644
--- a/drivers/scsi/BusLogic.h
+++ b/drivers/scsi/BusLogic.h
@@ -1526,15 +1526,11 @@ void BusLogic_StartMailboxCommand(BusLogic_HostAdapter_T *HostAdapter)
static inline void BusLogic_Delay(int Seconds)
{
+ int Milliseconds = 1000 * Seconds;
unsigned long ProcessorFlags;
save_flags(ProcessorFlags);
sti();
- while (--Seconds >= 0) {
- int i = 1000;
- do {
- udelay(1000);
- } while (--i);
- }
+ while (--Milliseconds >= 0) udelay(1000);
restore_flags(ProcessorFlags);
}
diff --git a/drivers/scsi/Config.in b/drivers/scsi/Config.in
index ac6d3bb6e..969ef7831 100644
--- a/drivers/scsi/Config.in
+++ b/drivers/scsi/Config.in
@@ -85,7 +85,7 @@ fi
if [ "$CONFIG_MCA" = "y" ]; then
dep_tristate 'IBMMCA SCSI support' CONFIG_SCSI_IBMMCA $CONFIG_SCSI
if [ "$CONFIG_SCSI_IBMMCA" != "n" ]; then
- bool ' reset SCSI-devices while booting' SCSI_IBMMCA_DEV_RESET
+ bool ' reset SCSI-devices while booting' CONFIG_SCSI_IBMMCA_DEV_RESET
fi
fi
if [ "$CONFIG_PARPORT" != "n" ]; then
diff --git a/drivers/scsi/aic7xxx.c b/drivers/scsi/aic7xxx.c
index 5551cbad8..051dedaac 100644
--- a/drivers/scsi/aic7xxx.c
+++ b/drivers/scsi/aic7xxx.c
@@ -147,6 +147,8 @@ struct proc_dir_entry proc_scsi_aic7xxx = {
#define ALL_TARGETS -1
#define ALL_CHANNELS '\0'
#define ALL_LUNS -1
+#define MAX_TARGETS 16
+#define MAX_LUNS 8
#ifndef TRUE
# define TRUE 1
#endif
@@ -301,7 +303,7 @@ struct proc_dir_entry proc_scsi_aic7xxx = {
#ifdef AIC7XXX_TAGGED_QUEUEING_BY_DEVICE
typedef struct
{
- char tag_commands[16]; /* Allow for wide/twin channel adapters. */
+ unsigned char tag_commands[16]; /* Allow for wide/twin channel adapters. */
} adapter_tag_info_t;
/*
@@ -871,7 +873,7 @@ struct aic7xxx_host {
long r_total; /* total reads */
long r_total512; /* 512 byte blocks read */
long r_bins[10]; /* binned reads */
- } stats[2][16][8]; /* channel, target, lun */
+ } stats[MAX_TARGETS][MAX_LUNS]; /* [(channel << 3)|target][lun] */
#endif /* AIC7XXX_PROC_STATS */
};
@@ -969,6 +971,7 @@ static int aic7xxx_verbose = 0; /* verbose messages */
* IO, we'll use them then.
*
***************************************************************************/
+
static inline unsigned char
aic_inb(struct aic7xxx_host *p, long port)
{
@@ -992,15 +995,24 @@ aic_outsb(struct aic7xxx_host *p, long port, unsigned char *valp, size_t size)
{
if (p->maddr != NULL)
{
+#ifdef __alpha__
+ int i;
+
+ for (i=0; i < size; i++)
+ {
+ p->maddr[port] = valp[i];
+ }
+#else
__asm __volatile("
cld;
1: lodsb;
movb %%al,(%0);
loop 1b" :
:
- "r" ((p)->maddr + (port)),
- "S" ((valp)), "c" ((size)) :
+ "r" (p->maddr + port),
+ "S" (valp), "c" (size) :
"%esi", "%ecx", "%eax");
+#endif
}
else
{
@@ -1439,7 +1451,7 @@ aic7xxx_scsirate(struct aic7xxx_host *p, unsigned char *scsirate,
* If the offset is 0, then the device is requesting asynchronous
* transfers.
*/
- if ((*period >= aic7xxx_syncrates[i].period) && *offset != 0)
+ if ((*period <= aic7xxx_syncrates[i - 1].period) && *offset != 0)
{
for (i = 0; i < num_aic7xxx_syncrates; i++)
{
@@ -1970,21 +1982,46 @@ aic7xxx_done(struct aic7xxx_host *p, struct aic7xxx_scb *scb)
if ((scb->flags & (SCB_MSGOUT_WDTR | SCB_MSGOUT_SDTR)) != 0)
{
unsigned short mask;
+ int message_error = FALSE;
mask = 0x01 << TARGET_INDEX(scb->cmd);
+
+ /*
+ * Check to see if we get an invalid message or a message error
+ * after failing to negotiate a wide or sync transfer message.
+ */
+ if ((scb->flags & SCB_SENSE) &&
+ ((scb->cmd->sense_buffer[12] == 0x43) || /* INVALID_MESSAGE */
+ (scb->cmd->sense_buffer[12] == 0x49))) /* MESSAGE_ERROR */
+ {
+ message_error = TRUE;
+ }
+
if (scb->flags & SCB_MSGOUT_WDTR)
{
p->wdtr_pending &= ~mask;
+ if (message_error)
+ {
+ p->needwdtr &= ~mask;
+ p->needwdtr_copy &= ~mask;
+ }
}
if (scb->flags & SCB_MSGOUT_SDTR)
{
p->sdtr_pending &= ~mask;
+ if (message_error)
+ {
+ p->needsdtr &= ~mask;
+ p->needsdtr_copy &= ~mask;
+ }
}
}
aic7xxx_free_scb(p, scb);
aic7xxx_queue_cmd_complete(p, cmd);
#ifdef AIC7XXX_PROC_STATS
+ if ( (cmd->cmnd[0] != TEST_UNIT_READY) &&
+ (cmd->cmnd[0] != INQUIRY) )
{
int actual;
@@ -2000,7 +2037,7 @@ aic7xxx_done(struct aic7xxx_host *p, struct aic7xxx_scb *scb)
long *ptr;
int x;
- sp = &p->stats[cmd->channel & 0x01][cmd->target & 0x0F][cmd->lun & 0x07];
+ sp = &p->stats[TARGET_INDEX(cmd)][cmd->lun & 0x7];
sp->xfers++;
if (cmd->request.cmd == WRITE)
@@ -3088,6 +3125,8 @@ aic7xxx_handle_seqint(struct aic7xxx_host *p, unsigned char intstat)
}
else
{
+ int send_reject = FALSE;
+
/*
* Send our own WDTR in reply.
*/
@@ -3110,14 +3149,25 @@ aic7xxx_handle_seqint(struct aic7xxx_host *p, unsigned char intstat)
{
bus_width = BUS_8_BIT;
scratch &= 0x7F; /* XXX - FreeBSD doesn't do this. */
+ send_reject = TRUE;
}
break;
default:
break;
}
- aic7xxx_construct_wdtr(p, /* start byte */ 0, bus_width);
- outb(SEND_MSG, p->base + RETURN_1);
+ if (send_reject)
+ {
+ outb(SEND_REJ, p->base + RETURN_1);
+ printk(KERN_WARNING "scsi%d: Target %d, channel %c, initiating "
+ "wide negotiation on a narrow bus - rejecting!",
+ p->host_no, target, channel);
+ }
+ else
+ {
+ aic7xxx_construct_wdtr(p, /* start byte */ 0, bus_width);
+ outb(SEND_MSG, p->base + RETURN_1);
+ }
}
p->needwdtr &= ~target_mask;
outb(scratch, p->base + TARG_SCRATCH + scratch_offset);
@@ -4062,7 +4112,7 @@ aic7xxx_device_queue_depth(struct aic7xxx_host *p, Scsi_Device *device)
#ifndef AIC7XXX_TAGGED_QUEUEING_BY_DEVICE
device->queue_depth = default_depth;
#else
- if (p->instance > NUMBER(aic7xxx_tag_info))
+ if (p->instance >= NUMBER(aic7xxx_tag_info))
{
device->queue_depth = default_depth;
}
@@ -5022,7 +5072,7 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p)
scbq_init(&p->scb_data->free_scbs);
scbq_init(&p->waiting_scbs);
- for (i = 0; i <= NUMBER(p->device_status); i++)
+ for (i = 0; i < NUMBER(p->device_status); i++)
{
p->device_status[i].commands_sent = 0;
p->device_status[i].flags = 0;
@@ -5305,8 +5355,17 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p)
*/
outb(p->qcntmask, p->base + QCNTMASK);
- outb(p->qfullcount, p->base + FIFODEPTH);
- outb(0, p->base + CMDOUTCNT);
+ /*
+ * Set FIFO depth and command out count. These are only used when
+ * paging is enabled and should not be touched for AIC-7770 based
+ * adapters; FIFODEPTH and CMDOUTCNT overlay SCSICONF and SCSICONF+1
+ * which are used to control termination.
+ */
+ if (p->flags & PAGE_ENABLED)
+ {
+ outb(p->qfullcount, p->base + FIFODEPTH);
+ outb(0, p->base + CMDOUTCNT);
+ }
/*
* We don't have any waiting selections or disconnected SCBs.
@@ -5537,7 +5596,6 @@ load_seeprom (struct aic7xxx_host *p, unsigned char *sxfrctl1)
{
case AIC_7770: /* None of these adapters have seeproms. */
case AIC_7771:
- case AIC_7850:
case AIC_7855:
break;
@@ -5545,6 +5603,7 @@ load_seeprom (struct aic7xxx_host *p, unsigned char *sxfrctl1)
have_seeprom = read_284x_seeprom(p, (struct seeprom_config *) scarray);
break;
+ case AIC_7850: /* The 2910B is a 7850 with a seeprom. */
case AIC_7861:
case AIC_7870:
case AIC_7871:
@@ -5654,7 +5713,11 @@ load_seeprom (struct aic7xxx_host *p, unsigned char *sxfrctl1)
scsi_conf = (p->scsi_id & 0x7);
if (sc->adapter_control & CFSPARITY)
scsi_conf |= ENSPCHK;
- if (sc->adapter_control & CFRESETB)
+ /*
+ * The 7850 controllers with a seeprom, do not honor the CFRESETB
+ * flag in the seeprom. Assume that we want to reset the SCSI bus.
+ */
+ if ((sc->adapter_control & CFRESETB) || (p->chip_class == AIC_7850))
scsi_conf |= RESET_SCSI;
if ((p->chip_class == AIC_786x) || (p->chip_class == AIC_788x))
@@ -5721,7 +5784,7 @@ aic7xxx_detect(Scsi_Host_Template *template)
* a NULL entry to indicate that no prior hosts have
* been found/registered for that IRQ.
*/
- for (i = 0; i <= NUMBER(aic7xxx_boards); i++)
+ for (i = 0; i < NUMBER(aic7xxx_boards); i++)
{
aic7xxx_boards[i] = NULL;
}
@@ -5787,6 +5850,14 @@ aic7xxx_detect(Scsi_Host_Template *template)
hcntrl = inb(base + HCNTRL) & IRQMS; /* Default */
outb(hcntrl | PAUSE, base + HCNTRL);
+ p = aic7xxx_alloc(template, base, 0, chip_type, 0, NULL);
+ if (p == NULL)
+ {
+ printk(KERN_WARNING "aic7xxx: Unable to allocate device space.\n");
+ continue;
+ }
+ aic7xxx_chip_reset(p);
+
irq = inb(INTDEF + base) & 0x0F;
switch (irq)
{
@@ -5800,19 +5871,14 @@ aic7xxx_detect(Scsi_Host_Template *template)
default:
printk(KERN_WARNING "aic7xxx: Host adapter uses unsupported IRQ "
- "level, ignoring.\n");
+ "level %d, ignoring.\n", irq);
irq = 0;
+ aic7xxx_free(p);
break;
}
if (irq != 0)
{
- p = aic7xxx_alloc(template, base, 0, chip_type, 0, NULL);
- if (p == NULL)
- {
- printk(KERN_WARNING "aic7xxx: Unable to allocate device space.\n");
- continue;
- }
p->irq = irq & 0x0F;
p->chip_class = AIC_777x;
#ifdef AIC7XXX_PAGE_ENABLE
@@ -5823,7 +5889,6 @@ aic7xxx_detect(Scsi_Host_Template *template)
{
p->flags |= EXTENDED_TRANSLATION;
}
- aic7xxx_chip_reset(p);
switch (p->chip_type)
{
@@ -5985,7 +6050,6 @@ aic7xxx_detect(Scsi_Host_Template *template)
flags = 0;
switch (aic7xxx_pci_devices[i].chip_type)
{
- case AIC_7850:
case AIC_7855:
flags |= USE_DEFAULTS;
break;
@@ -6887,7 +6951,7 @@ aic7xxx_reset(Scsi_Cmnd *cmd, unsigned int flags)
scb = (p->scb_data->scb_array[aic7xxx_position(cmd)]);
base = p->base;
channel = cmd->channel ? 'B': 'A';
- tindex = (cmd->channel << 4) | cmd->target;
+ tindex = TARGET_INDEX(cmd);
#ifdef 0 /* AIC7XXX_DEBUG_ABORT */
if (scb != NULL)
@@ -7128,4 +7192,3 @@ Scsi_Host_Template driver_template = AIC7XXX;
* tab-width: 8
* End:
*/
-
diff --git a/drivers/scsi/aic7xxx/aic7xxx.reg b/drivers/scsi/aic7xxx/aic7xxx.reg
index d3486e078..ac8549b34 100644
--- a/drivers/scsi/aic7xxx/aic7xxx.reg
+++ b/drivers/scsi/aic7xxx/aic7xxx.reg
@@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: aic7xxx.reg,v 1.2 1997/08/30 02:17:28 ralf Exp $
+ * $Id: aic7xxx.reg,v 1.3 1997/12/15 12:47:28 ralf Exp $
*/
/*
@@ -1079,10 +1079,26 @@ scratch_ram {
CUR_SCBID {
size 1
}
+ ARG_1 {
+ size 1
+ mask SEND_MSG 0x80
+ mask SEND_SENSE 0x40
+ mask SEND_REJ 0x20
+ alias RETURN_1
+ }
/*
* Running count of commands placed in
* the QOUTFIFO. This is cleared by the
* kernel driver every FIFODEPTH commands.
+ *
+ * NOTE: These scratch RAM registers are overlaying SCSICONF
+ * and SCSICONF2 and are only used on cards that are
+ * capable of SCB paging. Currently, only the PCI
+ * controllers can do this, which is good because the
+ * AIC-7770 based controllers use the SCSICONF register
+ * to control termination. In other words, do not
+ * destroy the contents of SCSICONF and SCSICONF2 for
+ * AIC-7770 based controllers.
*/
CMDOUTCNT {
size 1
@@ -1094,13 +1110,6 @@ scratch_ram {
FIFODEPTH {
size 1
}
- ARG_1 {
- size 1
- mask SEND_MSG 0x80
- mask SEND_SENSE 0x40
- mask SEND_REJ 0x20
- alias RETURN_1
- }
/*
* These are reserved registers in the card's scratch ram. Some of
* the values are specified in the AHA2742 technical reference manual
@@ -1111,6 +1120,11 @@ scratch_ram {
size 1
bit RESET_SCSI 0x40
}
+ SCSICONF2 {
+ address 0x05b
+ size 1
+ bit RESET_SCSI 0x40
+ }
HOSTCONF {
address 0x05d
size 1
diff --git a/drivers/scsi/aic7xxx_proc.c b/drivers/scsi/aic7xxx_proc.c
index dee247534..8ad2cfb03 100644
--- a/drivers/scsi/aic7xxx_proc.c
+++ b/drivers/scsi/aic7xxx_proc.c
@@ -21,13 +21,15 @@
* o Modified from the EATA-DMA /proc support.
* o Additional support for device block statistics provided by
* Matthew Jacob.
+ * o Correction of overflow by Heinz Mauelshagen
+ * o Adittional corrections by Doug Ledford
*
* Dean W. Gehnert, deang@teleport.com, 05/01/96
*
* $Id: aic7xxx_proc.c,v 4.1 1997/06/97 08:23:42 deang Exp $
*-M*************************************************************************/
-#define BLS buffer + len + size
+#define BLS (&aic7xxx_buffer[size])
#define HDRB \
" < 512 512-1K 1-2K 2-4K 4-8K 8-16K 16-32K 32-64K 64-128K >128K"
@@ -49,6 +51,13 @@ proc_debug(const char *fmt, ...)
# define proc_debug(fmt, args...)
#endif /* PROC_DEBUG */
+static int aic7xxx_buffer_size = 0;
+static char *aic7xxx_buffer = NULL;
+static const char *bus_names[] = { "Single", "Twin", "Wide" };
+static const char *chip_names[] = { "AIC-777x", "AIC-785x", "AIC-786x",
+ "AIC-787x", "AIC-788x" };
+
+
/*+F*************************************************************************
* Function:
* aic7xxx_set_info
@@ -63,6 +72,7 @@ aic7xxx_set_info(char *buffer, int length, struct Scsi_Host *HBAptr)
return (-ENOSYS); /* Currently this is a no-op */
}
+
/*+F*************************************************************************
* Function:
* aic7xxx_proc_info
@@ -71,20 +81,18 @@ aic7xxx_set_info(char *buffer, int length, struct Scsi_Host *HBAptr)
* Return information to handle /proc support for the driver.
*-F*************************************************************************/
int
-aic7xxx_proc_info(char *buffer, char **start, off_t offset, int length,
- int hostno, int inout)
+aic7xxx_proc_info ( char *buffer, char **start, off_t offset, int length,
+ int hostno, int inout)
{
struct Scsi_Host *HBAptr;
struct aic7xxx_host *p;
- int i;
- int found = FALSE;
- int size = 0;
- int len = 0;
- off_t begin = 0;
- off_t pos = 0;
- static char *bus_names[] = { "Single", "Twin", "Wide" };
- static char *chip_names[] = { "AIC-777x", "AIC-785x", "AIC-786x",
- "AIC-787x", "AIC-788x" };
+ int found = FALSE;
+ int size = 0;
+ unsigned char i;
+#ifdef AIC7XXX_PROC_STATS
+ struct aic7xxx_xferstats *sp;
+ unsigned char target, lun;
+#endif
HBAptr = NULL;
for (i=0; i < NUMBER(aic7xxx_boards); i++)
@@ -118,9 +126,15 @@ aic7xxx_proc_info(char *buffer, char **start, off_t offset, int length,
if (HBAptr == NULL)
{
- size += sprintf(BLS, "Can't find adapter for host number %d\n", hostno);
- len += size; pos = begin + len; size = 0;
- goto stop_output;
+ size += sprintf(buffer, "Can't find adapter for host number %d\n", hostno);
+ if (size > length)
+ {
+ return (size);
+ }
+ else
+ {
+ return (length);
+ }
}
if (inout == TRUE) /* Has data been written to the file? */
@@ -130,21 +144,49 @@ aic7xxx_proc_info(char *buffer, char **start, off_t offset, int length,
p = (struct aic7xxx_host *) HBAptr->hostdata;
+ /*
+ * It takes roughly 1K of space to hold all relevant card info, not
+ * counting any proc stats, so we start out with a 1.5k buffer size and
+ * if proc_stats is defined, then we sweep the stats structure to see
+ * how many drives we will be printing out for and add 384 bytes per
+ * device with active stats.
+ */
+
+ size = 1536;
+#ifdef AIC7XXX_PROC_STATS
+ for (target = 0; target < MAX_TARGETS; target++)
+ {
+ for (lun = 0; lun < MAX_LUNS; lun++)
+ {
+ if (p->stats[target][lun].xfers != 0)
+ size += 384;
+ }
+ }
+#endif
+ if (aic7xxx_buffer_size != size)
+ {
+ if (aic7xxx_buffer != NULL)
+ {
+ kfree(aic7xxx_buffer);
+ aic7xxx_buffer_size = 0;
+ }
+ aic7xxx_buffer = kmalloc(size, GFP_KERNEL);
+ }
+ if (aic7xxx_buffer == NULL)
+ {
+ size = sprintf(buffer, "AIC7xxx - kmalloc error at line %d\n",
+ __LINE__);
+ return size;
+ }
+ aic7xxx_buffer_size = size;
+
+ size = 0;
size += sprintf(BLS, "Adaptec AIC7xxx driver version: ");
size += sprintf(BLS, "%s/", rcs_version(AIC7XXX_C_VERSION));
size += sprintf(BLS, "%s", rcs_version(AIC7XXX_H_VERSION));
#if 0
size += sprintf(BLS, "%s\n", rcs_version(AIC7XXX_SEQ_VER));
#endif
- if (size > 512)
- printk(KERN_CRIT "aic7xxx: possible overflow at first position\n");
- len += size; pos = begin + len; size = 0;
- if (pos < offset)
- {
- begin = pos;
- len = 0;
- }
-
size += sprintf(BLS, "\n");
size += sprintf(BLS, "Compile Options:\n");
#ifdef AIC7XXX_RESET_DELAY
@@ -168,30 +210,19 @@ aic7xxx_proc_info(char *buffer, char **start, off_t offset, int length,
#else
size += sprintf(BLS, " AIC7XXX_PROC_STATS : Disabled\n");
#endif
- if (size > 512)
- printk(KERN_CRIT "aic7xxx: possible overflow at second position\n");
- len += size; pos = begin + len; size = 0;
- if (pos < offset)
- {
- begin = pos;
- len = 0;
- }
- else if (pos >= offset + length)
- goto stop_output;
-
size += sprintf(BLS, "\n");
size += sprintf(BLS, "Adapter Configuration:\n");
- size += sprintf(BLS, " SCSI Adapter: %s\n",
+ size += sprintf(BLS, " SCSI Adapter: %s\n",
board_names[p->chip_type]);
- size += sprintf(BLS, " (%s chipset)\n",
+ size += sprintf(BLS, " (%s chipset)\n",
chip_names[p->chip_class]);
- size += sprintf(BLS, " Host Bus: %s\n", bus_names[p->bus_type]);
- size += sprintf(BLS, " Base IO: %#.4x\n", p->base);
- size += sprintf(BLS, " Base IO Memory: 0x%x\n", p->mbase);
- size += sprintf(BLS, " IRQ: %d\n", HBAptr->irq);
- size += sprintf(BLS, " SCBs: Used %d, HW %d, Page %d\n",
+ size += sprintf(BLS, " Host Bus: %s\n", bus_names[p->bus_type]);
+ size += sprintf(BLS, " Base IO: %#.4x\n", p->base);
+ size += sprintf(BLS, " Base IO Memory: 0x%x\n", p->mbase);
+ size += sprintf(BLS, " IRQ: %d\n", HBAptr->irq);
+ size += sprintf(BLS, " SCBs: Used %d, HW %d, Page %d\n",
p->scb_data->numscbs, p->scb_data->maxhscbs, p->scb_data->maxscbs);
- size += sprintf(BLS, " Interrupts: %d", p->isr_count);
+ size += sprintf(BLS, " Interrupts: %d", p->isr_count);
if (p->chip_class == AIC_777x)
{
size += sprintf(BLS, " %s\n",
@@ -201,102 +232,81 @@ aic7xxx_proc_info(char *buffer, char **start, off_t offset, int length,
{
size += sprintf(BLS, "\n");
}
- size += sprintf(BLS, " Serial EEPROM: %s\n",
+ size += sprintf(BLS, " Serial EEPROM: %s\n",
(p->flags & HAVE_SEEPROM) ? "True" : "False");
- size += sprintf(BLS, " Extended Translation: %sabled\n",
+ size += sprintf(BLS, " Extended Translation: %sabled\n",
(p->flags & EXTENDED_TRANSLATION) ? "En" : "Dis");
- size += sprintf(BLS, " SCSI Bus Reset: %sabled\n",
+ size += sprintf(BLS, " SCSI Bus Reset: %sabled\n",
aic7xxx_no_reset ? "Dis" : "En");
- size += sprintf(BLS, " Ultra SCSI: %sabled\n",
+ size += sprintf(BLS, " Ultra SCSI: %sabled\n",
(p->flags & ULTRA_ENABLED) ? "En" : "Dis");
- size += sprintf(BLS, " Target Disconnect: %sabled\n",
- p->discenable ? "En" : "Dis");
- if (size > 512)
- printk(KERN_CRIT "aic7xxx: possible overflow at third position\n");
- len += size; pos = begin + len; size = 0;
- if (pos < offset)
- {
- begin = pos;
- len = 0;
- }
- else if (pos >= offset + length)
- goto stop_output;
-
+ size += sprintf(BLS, "Disconnect Enable Flags: 0x%x\n", p->discenable);
+
#ifdef AIC7XXX_PROC_STATS
+ size += sprintf(BLS, "\n");
+ size += sprintf(BLS, "Statistics:\n");
+ for (target = 0; target < MAX_TARGETS; target++)
{
- struct aic7xxx_xferstats *sp;
- int channel, target, lun;
-
- /*
- * XXX: Need to fix this to avoid overflow...
- * Fixed - gordo.
- */
- size += sprintf(BLS, "\n");
- size += sprintf(BLS, "Statistics:\n");
- for (channel = 0; channel < 2; channel++)
+ for (lun = 0; lun < MAX_LUNS; lun++)
{
- for (target = 0; target < 16; target++)
+ sp = &p->stats[target][lun];
+ if (sp->xfers == 0)
{
- for (lun = 0; lun < 8; lun++)
- {
- sp = &p->stats[channel][target][lun];
- if (sp->xfers == 0)
- {
- continue;
- }
- size += sprintf(BLS, "CHAN#%c (TGT %d LUN %d):\n",
- 'A' + channel, target, lun);
- size += sprintf(BLS, "nxfers %ld (%ld read;%ld written)\n",
- sp->xfers, sp->r_total, sp->w_total);
- size += sprintf(BLS, "blks(512) rd=%ld; blks(512) wr=%ld\n",
- sp->r_total512, sp->w_total512);
- size += sprintf(BLS, "%s\n", HDRB);
- size += sprintf(BLS, " Reads:");
- size += sprintf(BLS, "%6ld %6ld %6ld %6ld ", sp->r_bins[0],
- sp->r_bins[1], sp->r_bins[2], sp->r_bins[3]);
- size += sprintf(BLS, "%6ld %6ld %6ld %6ld ", sp->r_bins[4],
- sp->r_bins[5], sp->r_bins[6], sp->r_bins[7]);
- size += sprintf(BLS, "%6ld %6ld\n", sp->r_bins[8],
- sp->r_bins[9]);
- size += sprintf(BLS, "Writes:");
- size += sprintf(BLS, "%6ld %6ld %6ld %6ld ", sp->w_bins[0],
- sp->w_bins[1], sp->w_bins[2], sp->w_bins[3]);
- size += sprintf(BLS, "%6ld %6ld %6ld %6ld ", sp->w_bins[4],
- sp->w_bins[5], sp->w_bins[6], sp->w_bins[7]);
- size += sprintf(BLS, "%6ld %6ld\n", sp->w_bins[8],
- sp->w_bins[9]);
- size += sprintf(BLS, "\n");
- }
- if (size > 512)
- printk(KERN_CRIT "aic7xxx: possible overflow at loop %d:%d\n", target, lun);
- len += size; pos = begin + len; size = 0;
- if (pos < offset)
- {
- begin = pos;
- len = 0;
- }
- else if (pos >= offset + length)
- goto stop_output;
+ continue;
}
+ if (p->bus_type == AIC_TWIN)
+ {
+ size += sprintf(BLS, "CHAN#%c (TGT %d LUN %d):\n",
+ 'A' + (target >> 3), (target & 0x7), lun);
+ }
+ else
+ {
+ size += sprintf(BLS, "CHAN#%c (TGT %d LUN %d):\n",
+ 'A', target, lun);
+ }
+ size += sprintf(BLS, "nxfers %ld (%ld read;%ld written)\n",
+ sp->xfers, sp->r_total, sp->w_total);
+ size += sprintf(BLS, "blks(512) rd=%ld; blks(512) wr=%ld\n",
+ sp->r_total512, sp->w_total512);
+ size += sprintf(BLS, "%s\n", HDRB);
+ size += sprintf(BLS, " Reads:");
+ for (i = 0; i < NUMBER(sp->r_bins); i++)
+ {
+ size += sprintf(BLS, "%6ld ", sp->r_bins[i]);
+ }
+ size += sprintf(BLS, "\n");
+ size += sprintf(BLS, "Writes:");
+ for (i = 0; i < NUMBER(sp->w_bins); i++)
+ {
+ size += sprintf(BLS, "%6ld ", sp->w_bins[i]);
+ }
+ size += sprintf(BLS, "\n\n");
}
}
#endif /* AIC7XXX_PROC_STATS */
-stop_output:
- proc_debug("2pos: %ld offset: %ld len: %d\n", pos, offset, len);
- *start = buffer + (offset - begin); /* Start of wanted data */
- len -= (offset - begin); /* Start slop */
- if (len < 0)
+ if (size >= aic7xxx_buffer_size)
{
- len = 0; /* off end of file */
+ printk(KERN_WARNING "aic7xxx: Overflow in aic7xxx_proc.c\n");
}
- else if (len > length)
+
+ if (offset > size - 1)
{
- len = length; /* Ending slop */
+ kfree(aic7xxx_buffer);
+ aic7xxx_buffer = NULL;
+ aic7xxx_buffer_size = length = 0;
+ *start = NULL;
}
- proc_debug("3pos: %ld offset: %ld len: %d\n", pos, offset, len);
-
- return (len);
+ else
+ {
+ *start = &aic7xxx_buffer[offset]; /* Start of wanted data */
+ if (size - offset < length)
+ {
+ length = size - offset;
+ }
+ }
+
+ return (length);
}
/*
diff --git a/drivers/scsi/aic7xxx_reg.h b/drivers/scsi/aic7xxx_reg.h
index 8fbf84fa6..855a20441 100644
--- a/drivers/scsi/aic7xxx_reg.h
+++ b/drivers/scsi/aic7xxx_reg.h
@@ -30,6 +30,13 @@
#define ACTNEGEN 0x02
#define STPWEN 0x01
+#define SCSISIGI 0x03
+#define ATNI 0x10
+#define SELI 0x08
+#define BSYI 0x04
+#define REQI 0x02
+#define ACKI 0x01
+
#define SCSISIGO 0x03
#define CDO 0x80
#define IOO 0x40
@@ -40,13 +47,6 @@
#define REQO 0x02
#define ACKO 0x01
-#define SCSISIGI 0x03
-#define ATNI 0x10
-#define SELI 0x08
-#define BSYI 0x04
-#define REQI 0x02
-#define ACKI 0x01
-
#define SCSIRATE 0x04
#define WIDEXFER 0x80
#define SXFR 0x70
@@ -252,24 +252,26 @@
#define CUR_SCBID 0x58
-#define CMDOUTCNT 0x59
+#define ARG_1 0x59
+#define RETURN_1 0x59
+#define SEND_MSG 0x80
+#define SEND_SENSE 0x40
+#define SEND_REJ 0x20
#define SCSICONF 0x5a
-#define RESET_SCSI 0x40
-#define FIFODEPTH 0x5a
+#define CMDOUTCNT 0x5a
-#define ARG_1 0x5b
-#define RETURN_1 0x5b
-#define SEND_MSG 0x80
-#define SEND_SENSE 0x40
-#define SEND_REJ 0x20
+#define SCSICONF2 0x5b
+#define RESET_SCSI 0x40
+
+#define FIFODEPTH 0x5b
#define HOSTCONF 0x5d
#define HA_274_BIOSCTRL 0x5f
-#define BIOSMODE 0x30
#define BIOSDISABLED 0x30
+#define BIOSMODE 0x30
#define CHANNEL_B_PRIMARY 0x08
#define SEQCTL 0x60
@@ -313,16 +315,16 @@
#define STACK 0x6f
-#define BCTL 0x84
-#define ACE 0x08
-#define ENABLE 0x01
-
#define DSCOMMAND 0x84
#define CACHETHEN 0x80
#define DPARCKEN 0x40
#define MPARCKEN 0x20
#define EXTREQLCK 0x10
+#define BCTL 0x84
+#define ACE 0x08
+#define ENABLE 0x01
+
#define BUSTIME 0x85
#define BOFF 0xf0
#define BON 0x0f
@@ -372,18 +374,18 @@
#define BAD_PHASE 0x01
#define SEQINT 0x01
-#define CLRINT 0x92
-#define CLRBRKADRINT 0x08
-#define CLRSCSIINT 0x04
-#define CLRCMDINT 0x02
-#define CLRSEQINT 0x01
-
#define ERROR 0x92
#define PARERR 0x08
#define ILLOPCODE 0x04
#define ILLSADDR 0x02
#define ILLHADDR 0x01
+#define CLRINT 0x92
+#define CLRBRKADRINT 0x08
+#define CLRSCSIINT 0x04
+#define CLRCMDINT 0x02
+#define CLRSEQINT 0x01
+
#define DFCNTRL 0x93
#define DFSTATUS 0x94
@@ -408,6 +410,8 @@
#define QOUTCNT 0x9e
+#define SCB_BASE 0xa0
+
#define SCB_CONTROL 0xa0
#define MK_MESSAGE 0x80
#define DISCENB 0x40
@@ -417,8 +421,6 @@
#define DISCONNECTED 0x04
#define SCB_TAG_TYPE 0x03
-#define SCB_BASE 0xa0
-
#define SCB_TCL 0xa1
#define TID 0xf0
#define SELBUSB 0x08
@@ -464,10 +466,10 @@
#define DI_2840 0x01
-#define BUS_8_BIT 0x00
-#define MAX_OFFSET_8BIT 0x0f
-#define BUS_16_BIT 0x01
#define MAX_OFFSET_16BIT 0x08
+#define BUS_8_BIT 0x00
#define SCB_LIST_NULL 0xff
#define SG_SIZEOF 0x08
+#define MAX_OFFSET_8BIT 0x0f
#define BUS_32_BIT 0x02
+#define BUS_16_BIT 0x01
diff --git a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c
index 1bd283a45..2600f7397 100644
--- a/drivers/scsi/ibmmca.c
+++ b/drivers/scsi/ibmmca.c
@@ -199,11 +199,10 @@
5) Magneto-Optical drives and medium-changers are also recognized, now.
Therefore, we have a completely gapfree recognition of all SCSI-
device-types, that are known by Linux up to kernel 2.1.31.
- 6) The flag SCSI_IBMMCA_DEV_RESET has been inserted. If it is set within
- the configuration, each connected SCSI-device will get a reset command
- during boottime. This can be necessary for some special SCSI-devices.
- This flag should be included in Config.in.
- (See also the new Config.in file.)
+ 6) The flag CONFIG_SCSI_IBMMCA_DEV_RESET has been inserted. If it is set
+ within the configuration, each connected SCSI-device will get a reset
+ command during boottime. This can be necessary for some special
+ SCSI-devices. (See also the new Config.in file.)
Probable next improvement: bad disk handler.
- Michael Lang
@@ -1164,7 +1163,7 @@ static void check_devices (struct Scsi_Host *shpnt)
if (device_exists (shpnt, ldn, &ld[ldn].block_length,
&ld[ldn].device_type))
{
-#ifdef SCSI_IBMMCA_DEV_RESET
+#ifdef CONFIG_SCSI_IBMMCA_DEV_RESET
int ticks;
printk("(resetting)");
ticks = IM_RESET_DELAY*HZ;
diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
index 0971ce954..93711a0d2 100644
--- a/drivers/scsi/scsi_ioctl.c
+++ b/drivers/scsi/scsi_ioctl.c
@@ -397,7 +397,7 @@ int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg)
*/
int kernel_scsi_ioctl (Scsi_Device *dev, int cmd, void *arg) {
- unsigned long oldfs;
+ mm_segment_t oldfs;
int tmp;
oldfs = get_fs();
set_fs(get_ds());
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 12a8f3723..2504b30a5 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -31,7 +31,6 @@
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/cdrom.h>
-#include <linux/ucdrom.h>
#include <linux/interrupt.h>
#include <linux/config.h>
#include <asm/system.h>
@@ -90,7 +89,6 @@ static struct cdrom_device_ops sr_dops = {
sr_open, /* open */
sr_release, /* release */
sr_drive_status, /* drive status */
- sr_disk_status, /* disc status */
sr_media_change, /* media changed */
sr_tray_move, /* tray move */
sr_lock_door, /* lock door */
@@ -102,7 +100,8 @@ static struct cdrom_device_ops sr_dops = {
sr_audio_ioctl, /* audio ioctl */
sr_dev_ioctl, /* device-specific ioctl */
CDC_CLOSE_TRAY | CDC_OPEN_TRAY| CDC_LOCK | CDC_SELECT_SPEED |
- CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO,
+ CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO |
+ CDC_RESET | CDC_IOCTLS | CDC_DRIVE_STATUS,
0
};
@@ -1022,6 +1021,7 @@ static int sr_init()
void sr_finish()
{
int i;
+ char name[6];
blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
blk_size[MAJOR_NR] = sr_sizes;
@@ -1052,7 +1052,10 @@ void sr_finish()
scsi_CDs[i].cdi.dev = MKDEV(MAJOR_NR,i);
scsi_CDs[i].cdi.mask = 0;
get_capabilities(i);
- register_cdrom(&scsi_CDs[i].cdi, "sr");
+
+ sprintf(name, "sr%d", i);
+ strcpy(scsi_CDs[i].cdi.name, name);
+ register_cdrom(&scsi_CDs[i].cdi);
}
diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c
index 628d39c3e..265c7d04f 100644
--- a/drivers/scsi/sr_ioctl.c
+++ b/drivers/scsi/sr_ioctl.c
@@ -12,7 +12,6 @@
#include <scsi/scsi_ioctl.h>
#include <linux/cdrom.h>
-#include <linux/ucdrom.h>
#include "sr.h"
#if 0
@@ -729,7 +728,7 @@ int sr_dev_ioctl(struct cdrom_device_info *cdi,
return -ENOMEM;
lba = (((msf.cdmsf_min0 * CD_SECS) + msf.cdmsf_sec0)
- * CD_FRAMES + msf.cdmsf_frame0) - CD_BLOCK_OFFSET;
+ * CD_FRAMES + msf.cdmsf_frame0) - CD_MSF_OFFSET;
if (lba < 0 || lba >= scsi_CDs[target].capacity)
return -EINVAL;
@@ -757,7 +756,7 @@ int sr_dev_ioctl(struct cdrom_device_info *cdi,
lba = ra.addr.lba;
else
lba = (((ra.addr.msf.minute * CD_SECS) + ra.addr.msf.second)
- * CD_FRAMES + ra.addr.msf.frame) - CD_BLOCK_OFFSET;
+ * CD_FRAMES + ra.addr.msf.frame) - CD_MSF_OFFSET;
if (lba < 0 || lba >= scsi_CDs[target].capacity)
return -EINVAL;
diff --git a/drivers/scsi/sr_vendor.c b/drivers/scsi/sr_vendor.c
index 82d5ba7d8..7fec8fea1 100644
--- a/drivers/scsi/sr_vendor.c
+++ b/drivers/scsi/sr_vendor.c
@@ -44,7 +44,6 @@
#include <scsi/scsi_ioctl.h>
#include <linux/cdrom.h>
-#include <linux/ucdrom.h>
#include "sr.h"
#if 0
@@ -231,7 +230,7 @@ int sr_cd_check(struct cdrom_device_info *cdi)
frame = BCD_TO_BIN(buffer[3]);
sector = min*CD_SECS*CD_FRAMES + sec*CD_FRAMES + frame;
if (sector)
- sector -= CD_BLOCK_OFFSET;
+ sector -= CD_MSF_OFFSET;
break;
case VENDOR_HP_4020:
diff --git a/drivers/sgi/char/sgicons.c b/drivers/sgi/char/sgicons.c
index fb937679b..746ac93b4 100644
--- a/drivers/sgi/char/sgicons.c
+++ b/drivers/sgi/char/sgicons.c
@@ -159,6 +159,11 @@ void set_vesa_blanking(const unsigned long arg) { }
void vesa_powerdown(void) { }
void set_palette (void) { }
+__initfunc(int con_is_present())
+{
+ return 1;
+}
+
extern unsigned long video_mem_base, video_screen_size, video_mem_term;
__initfunc(unsigned long con_type_init(unsigned long start_mem, const char **name))
diff --git a/drivers/sgi/char/sgiserial.c b/drivers/sgi/char/sgiserial.c
index 025f41e69..c8d4d7e54 100644
--- a/drivers/sgi/char/sgiserial.c
+++ b/drivers/sgi/char/sgiserial.c
@@ -1601,7 +1601,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
if (!(info->flags & ZILOG_CALLOUT_ACTIVE) &&
!(info->flags & ZILOG_CLOSING) && do_clocal)
break;
- if (current->signal & ~current->blocked) {
+ if (signal_pending(current)) {
retval = -ERESTARTSYS;
break;
}
diff --git a/drivers/sgi/char/shmiq.c b/drivers/sgi/char/shmiq.c
index 27365ae57..37a8b9bf9 100644
--- a/drivers/sgi/char/shmiq.c
+++ b/drivers/sgi/char/shmiq.c
@@ -47,6 +47,7 @@
#include <linux/sched.h>
#include <linux/file.h>
#include <linux/interrupt.h>
+#include <linux/poll.h>
#include <linux/vmalloc.h>
#include <linux/wait.h>
#include <linux/major.h>
diff --git a/drivers/sgi/char/usema.c b/drivers/sgi/char/usema.c
index 31a71d5aa..dfef772eb 100644
--- a/drivers/sgi/char/usema.c
+++ b/drivers/sgi/char/usema.c
@@ -27,6 +27,7 @@
#include <linux/sched.h>
#include <linux/file.h>
#include <linux/major.h>
+#include <linux/poll.h>
#include <linux/string.h>
#include <linux/dcache.h>
#include <linux/mm.h>
@@ -64,7 +65,7 @@ sgi_usemaclone_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
struct irix_usema *usema = file->private_data;
int retval;
- printk("[%s:%d] wants ioctl 0x%xd (arg 0x%lx)",
+ printk("[%s:%ld] wants ioctl 0x%xd (arg 0x%lx)",
current->comm, current->pid, cmd, arg);
switch(cmd) {
@@ -76,7 +77,7 @@ sgi_usemaclone_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
usattach_t *attach = (usattach_t *)arg;
retval = verify_area(VERIFY_READ, attach, sizeof(usattach_t));
if (retval) {
- printk("[%s:%d] sgi_usema_ioctl(UIOCATTACHSEMA): "
+ printk("[%s:%ld] sgi_usema_ioctl(UIOCATTACHSEMA): "
"verify_area failure",
current->comm, current->pid);
return retval;
@@ -84,7 +85,8 @@ sgi_usemaclone_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
if (usema == 0)
return -EINVAL;
- printk("UIOCATTACHSEMA: attaching usema %p to process %d\n", usema, current->pid);
+ printk("UIOCATTACHSEMA: attaching usema %p to process %ld\n",
+ usema, current->pid);
/* XXX what is attach->us_handle for? */
return sgi_usema_attach(attach, usema);
break;
@@ -97,12 +99,12 @@ sgi_usemaclone_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
retval = verify_area(VERIFY_READ, attach, sizeof(usattach_t));
if (retval) {
- printk("[%s:%d] sgi_usema_ioctl(UIOC*BLOCK): "
+ printk("[%s:%ld] sgi_usema_ioctl(UIOC*BLOCK): "
"verify_area failure",
current->comm, current->pid);
return retval;
}
- printk("UIOC*BLOCK: putting process %d to sleep on usema %p",
+ printk("UIOC*BLOCK: putting process %ld to sleep on usema %p",
current->pid, usema);
if (cmd == UIOCNOIBLOCK)
interruptible_sleep_on(&usema->proc_list);
@@ -117,13 +119,13 @@ sgi_usemaclone_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
retval = verify_area(VERIFY_READ, attach, sizeof(usattach_t));
if (retval) {
- printk("[%s:%d] sgi_usema_ioctl(UIOC*BLOCK): "
+ printk("[%s:%ld] sgi_usema_ioctl(UIOC*BLOCK): "
"verify_area failure",
current->comm, current->pid);
return retval;
}
- printk("[%s:%d] releasing usema %p",
+ printk("[%s:%ld] releasing usema %p",
current->comm, current->pid, usema);
wake_up(&usema->proc_list);
return 0;
@@ -137,7 +139,8 @@ sgi_usemaclone_poll(struct file *filp, poll_table *wait)
{
struct irix_usema *usema = filp->private_data;
- printk("[%s:%d] wants to poll usema %p", current->comm, current->pid, usema);
+ printk("[%s:%ld] wants to poll usema %p",
+ current->comm, current->pid, usema);
return 0;
}
@@ -186,6 +189,7 @@ static struct miscdevice dev_usemaclone = {
void
usema_init(void)
{
- printk("usemaclone misc device registered (minor: %d)\n", SGI_USEMACLONE);
+ printk("usemaclone misc device registered (minor: %d)\n",
+ SGI_USEMACLONE);
misc_register(&dev_usemaclone);
}
diff --git a/drivers/sound/Config.in b/drivers/sound/Config.in
index 310bf01bf..80b8bd37e 100644
--- a/drivers/sound/Config.in
+++ b/drivers/sound/Config.in
@@ -1,27 +1,156 @@
-#
-# Sound driver configuration
-#
-#--------
-# There is another confic script which is compatible with rest of
-# the kernel. It can be activated by running 'make mkscript' in this
-# directory. Please note that this is an _experimental_ feature which
-# doesn't work with all cards (PSS, SM Wave, AudioTriX Pro, Maui).
-#--------
-#
-$MAKE -C drivers/sound config || exit 1
+dep_tristate 'ProAudioSpectrum 16 support' CONFIG_PAS $CONFIG_SOUND
+dep_tristate '100% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support' CONFIG_SB $CONFIG_SOUND
+dep_tristate 'Generic OPL2/OPL3 FM synthesizer support' CONFIG_ADLIB $CONFIG_SOUND
+dep_tristate 'Gravis Ultrasound support' CONFIG_GUS $CONFIG_SOUND
+if [ "$CONFIG_GUS" != "n" ]; then
+ bool '16 bit sampling option of GUS (_NOT_ GUS MAX)' CONFIG_GUS16
+ bool 'GUS MAX support' CONFIG_GUSMAX
+fi
+dep_tristate 'MPU-401 support (NOT for SB16)' CONFIG_MPU401 $CONFIG_SOUND
+dep_tristate 'PSS (ECHO-ADI2111) support' CONFIG_PSS $CONFIG_SOUND
+dep_tristate 'Microsoft Sound System support' CONFIG_MSS $CONFIG_SOUND
+dep_tristate 'Ensoniq SoundScape support' CONFIG_SSCAPE $CONFIG_SOUND
+dep_tristate 'MediaTrix AudioTrix Pro support' CONFIG_TRIX $CONFIG_SOUND
+dep_tristate 'Support for OPTi MAD16 and/or Mozart based cards' CONFIG_MAD16 $CONFIG_SOUND
+dep_tristate 'Support for Crystal CS4232 based (PnP) cards' CONFIG_CS4232 $CONFIG_SOUND
+dep_tristate 'Support for Turtle Beach Wave Front (Maui, Tropez) synthesizers' CONFIG_MAUI $CONFIG_SOUND
+dep_tristate 'Yamaha OPL3-SA1 audio controller' CONFIG_OPL3SA1 $CONFIG_SOUND
+dep_tristate 'SoftOSS software wave table engine' CONFIG_SOFTOSS $CONFIG_SOUND
+dep_tristate 'FM synthesizer (YM3812/OPL-3) support' CONFIG_YM3812 $CONFIG_SOUND
+
+if [ "$CONFIG_AEDSP16" = "y" -o "$CONFIG_AEDSP16" = "m" ]; then
+ hex 'I/O base for Audio Excel DSP 16 220 or 240' AEDSP16_BASE 220
+fi
+
+if [ "$CONFIG_SB" = "y" -o "$CONFIG_SB" = "m" ]; then
+ hex 'I/O base for SB Check from manual of the card' SBC_BASE 220
+ int 'Sound Blaster IRQ Check from manual of the card' SBC_IRQ 7
+ int 'Sound Blaster DMA 0, 1 or 3' SBC_DMA 1
+ int 'Sound Blaster 16 bit DMA (SB16, Jazz16, SMW) 5, 6 or 7 (use 1 for 8 bit cards)' SB_DMA2 5
+ hex 'MPU401 I/O base of SB16, Jazz16 and ES1688 Check from manual of the card' SB_MPU_BASE 330
+ comment 'MPU401 IRQ is only required with Jazz16, SM Wave and ESS1688.'
+ comment 'Enter -1 to the following question if you have something else such as SB16/32.'
+ int 'SB MPU401 IRQ (Jazz16, SM Wave and ES1688) Check from manual of the card' SB_MPU_IRQ -1
+fi
+
+if [ "$CONFIG_PAS" = "y" -o "$CONFIG_PAS" = "m" ]; then
+ int 'PAS16 IRQ 3, 4, 5, 7, 9, 10, 11, 12, 14 or 15' PAS_IRQ 10
+ int 'PAS16 DMA 0, 1, 3, 5, 6 or 7' PAS_DMA 3
+fi
+
+if [ "$CONFIG_GUS" = "y" -o "$CONFIG_GUS" = "m" ]; then
+ hex 'I/O base for GUS 210, 220, 230, 240, 250 or 260' GUS_BASE 220
+ int 'GUS IRQ 3, 5, 7, 9, 11, 12 or 15' GUS_IRQ 15
+ int 'GUS DMA 1, 3, 5, 6 or 7' GUS_DMA 6
+ int 'Second DMA channel for GUS 1, 3, 5, 6 or 7' GUS_DMA2 -1
+fi
+
+if [ "$CONFIG_GUS16" = "y" ]; then
+ hex 'I/O base for the 16 bit daughtercard of GUS 530, 604, E80 or F40' GUS16_BASE 530
+ int 'GUS 16 bit daughtercard IRQ 3, 4, 5, 7, or 9' GUS16_IRQ 7
+ int 'GUS DMA 0, 1 or 3' GUS16_DMA 3
+fi
+
+if [ "$CONFIG_MPU401" = "y" -o "$CONFIG_MPU401" = "m" ]; then
+ hex 'I/O base for MPU401 Check from manual of the card' MPU_BASE 330
+ int 'MPU401 IRQ Check from manual of the card' MPU_IRQ 9
+fi
+
+if [ "$CONFIG_MAUI" = "y" -o "$CONFIG_MAUI" = "M" ]; then
+ comment 'ERROR! You have to use old sound configuration method with Maui.'
+ hex 'I/O base for Maui 210, 230, 260, 290, 300, 320, 338 or 330' MAUI_BASE 330
+ int 'Maui IRQ 5, 9, 12 or 15' MAUI_IRQ 9
+fi
+
+if [ "$CONFIG_UART6850" = "y" -o "$CONFIG_UART6850" = "m" ]; then
+ hex 'I/O base for UART 6850 MIDI port (Unknown)' U6850_BASE 0
+ int 'UART6850 IRQ (Unknown)' U6850_IRQ -1
+fi
+
+if [ "$CONFIG_PSS" = "y" -o "$CONFIG_PSS" = "y" ]; then
+ comment 'ERROR! You have to use old sound configuration method with PSS cards.'
+ hex 'PSS I/O base 220 or 240' PSS_BASE 220
+ hex 'PSS audio I/O base 530, 604, E80 or F40' PSS_MSS_BASE 530
+ int 'PSS audio IRQ 7, 9, 10 or 11' PSS_MSS_IRQ 11
+ int 'PSS audio DMA 0, 1 or 3' PSS_MSS_DMA 3
+ hex 'PSS MIDI I/O base ' PSS_MPU_BASE 330
+ int 'PSS MIDI IRQ 3, 4, 5, 7 or 9' PSS_MPU_IRQ 9
+fi
+
+if [ "$CONFIG_MSS" = "y" -o "$CONFIG_MSS" = "m" ]; then
+ hex 'MSS/WSS I/O base 530, 604, E80 or F40' MSS_BASE 530
+ int 'MSS/WSS IRQ 7, 9, 10 or 11' MSS_IRQ 11
+ int 'MSS/WSS DMA 0, 1 or 3' MSS_DMA 3
+ int 'MSS/WSS second DMA (if possible) 0, 1 or 3' MSS_DMA2 -1
+fi
+if [ "$CONFIG_SSCAPE" = "y" -o "$CONFIG_SSCAPE" = "m" ]; then
+ hex 'SoundScape MIDI I/O base 320, 330, 340 or 350' SSCAPE_BASE 330
+ int 'SoundScape MIDI IRQ ' SSCAPE_IRQ 9
+ int 'SoundScape initialization DMA 0, 1 or 3' SSCAPE_DMA 3
+ hex 'SoundScape audio I/O base 534, 608, E84 or F44' SSCAPE_MSS_BASE 534
+ int 'SoundScape audio IRQ 7, 9, 10 or 11' SSCAPE_MSS_IRQ 11
+fi
+
+if [ "$CONFIG_TRIX" = "y" -o "$CONFIG_TRIX" = "m" ]; then
+ comment 'ERROR! You have to use old sound configuration method with OPL3-SA1.'
+ hex 'OPL3-SA1 audio I/O base 530, 604, E80 or F40' TRIX_BASE 530
+ int 'OPL3-SA1 audio IRQ 7, 9, 10 or 11' TRIX_IRQ 11
+ int 'OPL3-SA1 audio DMA 0, 1 or 3' TRIX_DMA 0
+ int 'OPL3-SA1 second (duplex) DMA 0, 1 or 3' TRIX_DMA2 3
+ hex 'OPL3-SA1 MIDI I/O base 330, 370, 3B0 or 3F0' TRIX_MPU_BASE 330
+ int 'OPL3-SA1 MIDI IRQ 3, 4, 5, 7 or 9' TRIX_MPU_IRQ 9
+ hex 'OPL3-SA1 SB I/O base 220, 210, 230, 240, 250, 260 or 270' TRIX_SB_BASE 220
+ int 'OPL3-SA1 SB IRQ 3, 4, 5 or 7' TRIX_SB_IRQ 7
+ int 'OPL3-SA1 SB DMA 1 or 3' TRIX_SB_DMA 1
+fi
+
+if [ "$CONFIG_OPL3SA1" = "y" -o "$CONFIG_OPL3SA1" = "m" ]; then
+ hex 'OPL3-SA1 audio I/O base 530, 604, E80 or F40' OPL3SA1_BASE 530
+ int 'OPL3-SA1 audio IRQ 7, 9, 10 or 11' OPL3SA1_IRQ 11
+ int 'OPL3-SA1 audio DMA 0, 1 or 3' OPL3SA1_DMA 0
+ int 'OPL3-SA1 second (duplex) DMA 0, 1 or 3' OPL3SA1_DMA2 3
+ hex 'OPL3-SA1 MIDI I/O base 330, 370, 3B0 or 3F0' OPL3SA1_MPU_BASE 330
+ int 'OPL3-SA1 MIDI IRQ 3, 4, 5, 7 or 9' OPL3SA1_MPU_IRQ 9
+fi
+
+if [ "$CONFIG_CS4232" = "y" -o "$CONFIG_CS4232" = "m" ]; then
+ hex 'CS4232 audio I/O base 530, 604, E80 or F40' CS4232_BASE 530
+ int 'CS4232 audio IRQ 5, 7, 9, 11, 12 or 15' CS4232_IRQ 11
+ int 'CS4232 audio DMA 0, 1 or 3' CS4232_DMA 0
+ int 'CS4232 second (duplex) DMA 0, 1 or 3' CS4232_DMA2 3
+ hex 'CS4232 MIDI I/O base 330, 370, 3B0 or 3F0' CS4232_MPU_BASE 330
+ int 'CS4232 MIDI IRQ 5, 7, 9, 11, 12 or 15' CS4232_MPU_IRQ 9
+fi
+
+if [ "$CONFIG_MAD16" = "y" -o "$CONFIG_MAD16" = "m" ]; then
+ hex 'MAD16 audio I/O base 530, 604, E80 or F40' MAD16_BASE 530
+ int 'MAD16 audio IRQ 7, 9, 10 or 11' MAD16_IRQ 11
+ int 'MAD16 audio DMA 0, 1 or 3' MAD16_DMA 3
+ int 'MAD16 second (duplex) DMA 0, 1 or 3' MAD16_DMA2 0
+ hex 'MAD16 MIDI I/O base 300, 310, 320 or 330 (0 disables)' MAD16_MPU_BASE 330
+ int 'MAD16 MIDI IRQ 5, 7, 9 or 10' MAD16_MPU_IRQ 9
+fi
+
+if [ "$CONFIG_SOFTOSS" = "y" -o "$CONFIG_SOFTOSS" = "m" ]; then
+ int 'Sampling rate for SoftOSS 8000 to 48000' SOFTOSS_RATE 22050
+ int 'Max # of concurrent voices for SoftOSS 4 to 32' SOFTOSS_VOICES 32
+fi
+
+#
+$MAKE -C drivers/sound kernelconfig || exit 1
bool 'Additional low level drivers' CONFIG_LOWLEVEL_SOUND
if [ "$CONFIG_LOWLEVEL_SOUND" = "y" ]; then
- bool 'ACI mixer (miroPCM12)' CONFIG_ACI_MIXER
- bool 'AWE32 synth' CONFIG_AWE32_SYNTH
+ dep_tristate 'ACI mixer (miroPCM12)' CONFIG_ACI_MIXER $CONFIG_SOUND
+ dep_tristate 'AWE32 synth' CONFIG_AWE32_SYNTH $CONFIG_SOUND
bool 'Gallant Audio Cards (SC-6000 and SC-6600 based)' CONFIG_AEDSP16
if [ "$CONFIG_AEDSP16" = "y" ]; then
comment 'SC-6600 Audio Cards have no jumper switches at all'
bool 'SC-6600 based audio cards (new Audio Excel DSP 16)' CONFIG_SC6600
- if [ "$CONFIG_SB" = "y" -a "$CONFIG_AEDSP16_MSS" != "y" ]; then
+ if [ "$CONFIG_SB" = "y" -o "$CONFIG_SB" = "m" -a "$CONFIG_AEDSP16_MSS" != "y" ]; then
bool 'Audio Excel DSP 16 (SBPro emulation)' CONFIG_AEDSP16_SBPRO
if [ "$CONFIG_AEDSP16_SBPRO" = "y" ]; then
comment 'Audio Excel DSP 16 [Sound Blaster Pro]'
@@ -33,7 +162,7 @@ if [ "$CONFIG_LOWLEVEL_SOUND" = "y" ]; then
fi
fi
- if [ "$CONFIG_MSS" = "y" -a "$CONFIG_AEDSP16_SBPRO" != "y" ]; then
+ if [ "$CONFIG_MSS" = "y" -o "$CONFIG_MSS" = "m" -a "$CONFIG_AEDSP16_SBPRO" != "y" ]; then
bool 'Audio Excel DSP 16 (MSS emulation)' CONFIG_AEDSP16_MSS
if [ "$CONFIG_AEDSP16_MSS" = "y" ]; then
comment 'Audio Excel DSP 16 [Microsoft Sound System]'
@@ -44,7 +173,7 @@ if [ "$CONFIG_LOWLEVEL_SOUND" = "y" ]; then
fi
fi
- if [ "$CONFIG_MPU401" = "y" ]; then
+ if [ "$CONFIG_MPU401" = "y" -o "$CONFIG_MPU401" = "m" ]; then
bool 'Audio Excel DSP 16 (MPU401 emulation)' CONFIG_AEDSP16_MPU401
if [ "$CONFIG_AEDSP16_MPU401" = "y" ]; then
comment 'Audio Excel DSP 16 [MPU-401]'
@@ -67,3 +196,4 @@ if [ "$CONFIG_LOWLEVEL_SOUND" = "y" ]; then
fi
fi
+
diff --git a/drivers/sound/Makefile b/drivers/sound/Makefile
index e90ba9a03..fb81925b2 100644
--- a/drivers/sound/Makefile
+++ b/drivers/sound/Makefile
@@ -34,8 +34,8 @@ kernelconfig:
else
ifeq (.defines,$(wildcard .defines))
-#include .defines
-include .objects
+include .defines
+#include .objects
endif
TARGET_OS=linux
@@ -66,25 +66,20 @@ ifeq ($(CONFIG_MIDI),y)
LX_OBJS += midi_synth.o
endif
-ifeq ($(CONFIG_MIDI),y)
- L_OBJS += midibuf.o
- LX_OBJS += midi_synth.o
-endif
-
#ifeq ($(CONFIG_AUDIO),y)
#L_OBJS += dmabuf.o
#endif
ifeq ($(CONFIG_YM3812),y)
-LX_OBJS += opl3.o
+LX_OBJS += adlib_card.o opl3.o
else
ifeq ($(CONFIG_YM3812),m)
- MX_OBJS += opl3.o
+ MX_OBJS += adlib_card.o opl3.o
endif
endif
ifeq ($(CONFIG_PAS),y)
-L_OBJS += pas2_card.c pas2_midi.c pas2_mixer.c pas2_pcm.c
+L_OBJS += pas2.o
else
ifeq ($(CONFIG_PAS),m)
M_OBJS += pas2.o
@@ -92,7 +87,7 @@ else
endif
ifeq ($(CONFIG_GUS),y)
-L_OBJS += gus_card.c gus_midi.c gus_vol.c gus_wave.c ics2101.c
+L_OBJS += gus.o
else
ifeq ($(CONFIG_GUS),m)
M_OBJS += gus.o
@@ -105,14 +100,15 @@ LX_OBJS += sb_card.o uart401.o
else
ifeq ($(CONFIG_SB),m)
M_OBJS += sb.o
- MX_OBJS += sb_card.o uart401.o
+ MX_OBJS += uart401.o
+ MIX_OBJS += sb_card.o
endif
endif
-ifeq ($(CONFIG_ADLIB),y)
+ifeq ($(CONFIG_MSS),y)
LX_OBJS += ad1848.o
else
- ifeq ($(CONFIG_ADLIB),m)
+ ifeq ($(CONFIG_MSS),m)
MX_OBJS += ad1848.o
endif
endif
@@ -130,6 +126,14 @@ LX_OBJS += mpu401.o
else
ifeq ($(CONFIG_MPU401),m)
MX_OBJS += mpu401.o
+ else
+ ifeq ($(CONFIG_MPU_EMU),y)
+ LX_OBJS += mpu401.o
+ else
+ ifeq ($(CONFIG_MPU_EMU),m)
+ MX_OBJS += mpu401.o
+ endif
+ endif
endif
endif
@@ -205,6 +209,16 @@ else
endif
endif
+ifeq ($(CONFIG_OPL3SA1),y)
+L_OBJS += opl3sa.o
+LX_OBJS += ad1848.o
+else
+ ifeq ($(CONFIG_OPL3SA1),m)
+ M_OBJS += opl3sa.o
+ MX_OBJS += ad1848.o
+ endif
+endif
+
include $(TOPDIR)/Rules.make
softoss2.o: softoss.o softoss_rs.o
@@ -248,4 +262,13 @@ setup:
mkscript:
+config: configure
+ @$(MAKE) setup
+ @./configure > local.h
+ @echo \#define SOUND_CONFIG_DATE \"`date`\" >> local.h
+ @echo \#define SOUND_CONFIG_BY \"`whoami`\" >> local.h
+# @echo \#define SOUND_CONFIG_HOST \"`hostname`\" >> local.h 2>/dev/null
+# @echo \#define SOUND_CONFIG_DOMAIN \"`hostname -d`\" >> local.h 2>/dev/null
+ @echo \#define SOUND_UNAME_A \"`uname -a`\" >> local.h
+
endif
diff --git a/drivers/sound/Readme b/drivers/sound/Readme
index 113ad9130..9fb851c5f 100644
--- a/drivers/sound/Readme
+++ b/drivers/sound/Readme
@@ -2,7 +2,7 @@ OSS/Free version 3.8 release notes
----------------------------------
Most up to date information about this driver is available from
-http://www.4front-tech.com/ossfree.
+http://www.opensound.com/ossfree.
@@ -11,7 +11,7 @@ sites). It gives instructions about using sound with Linux. It's bit out of
date but still very useful. Information about bug fixes and such things
is available from the web page (see above).
-Please check http://www.4front-tech.com/pguide for more info about programming
+Please check http://www.opensound.com/pguide for more info about programming
with OSS API.
====================================================
@@ -20,7 +20,7 @@ with OSS API.
Packages "snd-util-3.8.tar.gz" and "snd-data-0.1.tar.Z"
contain useful utilities to be used with this driver.
-See http://www.4front-tech.com/ossfree/getting.html for
+See http://www.opensound.com/ossfree/getting.html for
download instructions.
If you are looking for the installation instructions, please
@@ -31,7 +31,7 @@ Supported soundcards
See Readme.cards.
-Please check http://www.4front-tech.com/ossfree if you don't find
+Please check http://www.opensound.com/ossfree if you don't find
your soundcard there.
Contributors
@@ -86,7 +86,7 @@ changed or what you have planned to do. Also ensure you are using the
very latest (development) version of OSS/Free since the change may already be
implemented there. In general it's major waste of time to try to improve
several months old version. Information about the latest version can be found
-from http://www.4front-tech.com/ossfree. In general there is no point in
+from http://www.opensound.com/ossfree. In general there is no point in
sending me patches relative to production kernels.
Sponsors etc.
@@ -123,7 +123,7 @@ If you have some problems
=========================
Read the sound HOWTO (sunsite.unc.edu:/pub/Linux/docs/...?).
-Also look at the home page (http://www.4front-tech.com/ossfree). It may
+Also look at the home page (http://www.opensound.com/ossfree). It may
contain info about some recent bug fixes.
It's likely that you have some problems when trying to use the sound driver
@@ -177,8 +177,8 @@ Best regards,
Hannu
Hannu Savolainen
-hannu@4front-tech.com
-(Please check http://www.4front-tech.com/ossfree before mailing me).
+hannu@opensound.com
+(Please check http://www.opensound.com/ossfree before mailing me).
Snail mail: Hannu Savolainen
Hiekkalaiturintie 3 A 8
diff --git a/drivers/sound/Readme.cards b/drivers/sound/Readme.cards
index 79bbe464b..dff774546 100644
--- a/drivers/sound/Readme.cards
+++ b/drivers/sound/Readme.cards
@@ -4,7 +4,7 @@ Configuring version 3.8 (for Linux) with some most common soundcards
This document describes configuring soundcards with freeware version of
Open Sound Systems (OSS/Free). Information about the commercial version
(OSS/Linux) and it's configuration is available from
-http://www.4front-tech.com/linux.html. Information presented here is
+http://www.opensound.com/linux.html. Information presented here is
not valid for OSS/Linux.
If you are unsure about how to configure OSS/Free
@@ -15,7 +15,7 @@ you can use the information included in soundon.log when configuring OSS/Free.
IMPORTANT! This document covers only cards that were "known" when
this driver version was released. Please look at
- http://www.4front-tech.com/ossfree for info about
+ http://www.opensound.com/ossfree for info about
cards introduced recently.
The following covers mainly the "old" configuration
@@ -115,7 +115,7 @@ ancestors which are covered by this document.
Cards that are not (fully) supported by this driver
===================================================
-See http://www.4front-tech.com/ossfree for information about soundcards
+See http://www.opensound.com/ossfree for information about soundcards
to be supported in future.
@@ -174,7 +174,7 @@ support for PnP cards. There are bugs in setting DMA channels in earlier
versions of isapnptools so at least version 1.6 is required with soundcards.
Yet another way to use PnP cards is to use (commercial) OSS/Linux drivers.
-See http://www.4front-tech.com/linux.html for more info. This is the way
+See http://www.opensound.com/linux.html for more info. This is the way
you probably like to do it if you don't waste hours of time in recompiling
kernel and the required tools.
@@ -1231,7 +1231,7 @@ distributed driver (diffs) for the card.
Writing a driver for a new card is not possible if there are no
programming information available about the card. If you don't
find your new card from this file, look from the home page
-(http://www.4front-tech.com/ossfree). Then please contact
+(http://www.opensound.com/ossfree). Then please contact
manufacturer of the card and ask if they have (or are willing to)
released technical details of the card. Do this before contacting me. I
can only answer 'no' if there are no programming information available.
@@ -1252,7 +1252,7 @@ of this driver (see http://www.4Front-tech.com/oss.html for more info).
There are some common audio chipsets that are not supported yet. For example
Sierra Aria and IBM Mwave. It's possible that these architectures
get some support in future but I can't make any promises. Just look
-at the home page (http://www.4front-tech.com/ossfree/new_cards.html)
+at the home page (http://www.opensound.com/ossfree/new_cards.html)
for latest info.
Information about unsupported soundcards and chipsets is welcome as well
@@ -1261,10 +1261,10 @@ as free copies of soundcards, SDKs and operating systems.
If you have any corrections and/or comments, please contact me.
Hannu Savolainen
-hannu@4front-tech.com
+hannu@opensound.com
-Personal home page: http://personal.eunet.fi/pp/voxware/hannu.html
-www home page of OSS/Free: http://www.4front-tech.com/ossfree
+Personal home page: http://www.compusonic.fi/~hannu
+www home page of OSS/Free: http://www.opensound.com/ossfree
www home page of commercial OSS
-(Open Sound System) drivers: http://www.4front-tech.com/oss.html
+(Open Sound System) drivers: http://www.opensound.com/oss.html
diff --git a/drivers/sound/Readme.linux b/drivers/sound/Readme.linux
index 103470869..b3fa3a833 100644
--- a/drivers/sound/Readme.linux
+++ b/drivers/sound/Readme.linux
@@ -67,10 +67,10 @@ Readme.cards for info about configuring the driver with your card. Also
check for possible boot (insmod) time error messages in /var/adm/messages.
- Other messages or problems
-Please check http://www.4front-tech.com/ossfree for more info.
+Please check http://www.opensound.com/ossfree for more info.
Hannu Savolainen
-hannu@4front-tech.com
+hannu@opensound.com
----------------- cut here ------------------------------
SURPRISE SURPRISE!!!
diff --git a/drivers/sound/audio.c b/drivers/sound/audio.c
index 24bbaa0e0..3ccdc5892 100644
--- a/drivers/sound/audio.c
+++ b/drivers/sound/audio.c
@@ -304,6 +304,9 @@ audio_read(int dev, struct fileinfo *file, char *buf, int count)
if (dev_nblock[dev] && buf_no == -EAGAIN)
return p;
+ if (p > 0) /* Avoid throwing away data */
+ return p; /* Return it instead */
+
return buf_no;
}
if (l > c)
@@ -958,6 +961,34 @@ dma_ioctl(int dev, unsigned int cmd, caddr_t arg)
}
break;
+ case SNDCTL_DSP_GETODELAY:
+ {
+ int count;
+ unsigned long flags;
+ struct dma_buffparms *dmap = dmap_out;
+
+ if (!(audio_devs[dev]->open_mode & OPEN_WRITE))
+ return -EINVAL;
+ if (!(dmap->flags & DMA_ALLOC_DONE))
+ return (*(int *) arg = 0);
+
+ save_flags (flags);
+ cli ();
+ /* Compute number of bytes that have been played */
+ count = DMAbuf_get_buffer_pointer (dev, dmap, DMODE_OUTPUT);
+ if (count < dmap->fragment_size && dmap->qhead != 0)
+ count += dmap->bytes_in_use; /* Pointer wrap not handled yet */
+ count += dmap->byte_counter;
+
+ /* Substract current count from the number of bytes written by app */
+ count = dmap->user_counter - count;
+ if (count < 0)
+ count = 0;
+ restore_flags (flags);
+
+ return (*(int *) arg = count);
+ }
+ break;
case SNDCTL_DSP_POST:
;
diff --git a/drivers/sound/configure.c b/drivers/sound/configure.c
index aea32b388..e00ca26f5 100644
--- a/drivers/sound/configure.c
+++ b/drivers/sound/configure.c
@@ -1132,8 +1132,8 @@ ask_parameters(void)
ask_int_choice(B(OPT_CS4232), "CS4232_BASE",
"CS4232 audio I/O base",
FMT_HEX,
- 0x530,
- "530, 604, E80 or F40");
+ 0x534,
+ "534, 608, E84 or F44");
ask_int_choice(B(OPT_CS4232), "CS4232_IRQ",
"CS4232 audio IRQ",
diff --git a/drivers/sound/dmabuf.c b/drivers/sound/dmabuf.c
index 609831377..ab5164ee4 100644
--- a/drivers/sound/dmabuf.c
+++ b/drivers/sound/dmabuf.c
@@ -13,6 +13,7 @@
#include <linux/config.h>
#define BE_CONSERVATIVE
+#define SAMPLE_ROUNDUP 0
#include "sound_config.h"
@@ -269,7 +270,7 @@ dma_reset_output(int dev)
audio_devs[dev]->dmap_out->flags |= DMA_SYNCING;
audio_devs[dev]->dmap_out->underrun_count = 0;
- if (!(current->signal & ~current->blocked)
+ if (!signal_pending(current)
&& audio_devs[dev]->dmap_out->qlen
&& audio_devs[dev]->dmap_out->underrun_count == 0)
{
@@ -408,7 +409,7 @@ DMAbuf_sync(int dev)
audio_devs[dev]->dmap_out->flags |= DMA_SYNCING;
audio_devs[dev]->dmap_out->underrun_count = 0;
- while (!(current->signal & ~current->blocked)
+ while (!signal_pending(current)
&& n++ <= audio_devs[dev]->dmap_out->nbufs
&& audio_devs[dev]->dmap_out->qlen
&& audio_devs[dev]->dmap_out->underrun_count == 0)
@@ -448,7 +449,7 @@ DMAbuf_sync(int dev)
cli();
if (audio_devs[dev]->d->local_qlen) /* Device has hidden buffers */
{
- while (!((current->signal & ~current->blocked))
+ while (!signal_pending(current)
&& audio_devs[dev]->d->local_qlen(dev))
{
@@ -488,7 +489,7 @@ DMAbuf_release(int dev, int mode)
if (audio_devs[dev]->open_mode & OPEN_WRITE)
if (!(audio_devs[dev]->dmap_in->mapping_flags & DMA_MAP_MAPPED))
- if (!((current->signal & ~current->blocked))
+ if (!signal_pending(current)
&& (audio_devs[dev]->dmap_out->dma_mode == DMODE_OUTPUT))
{
DMAbuf_sync(dev);
@@ -835,7 +836,7 @@ output_sleep(int dev, int dontblock)
tmout = 20 * HZ;
}
- if ((current->signal & ~current->blocked))
+ if (signal_pending(current))
return -EIO;
@@ -860,7 +861,7 @@ output_sleep(int dev, int dontblock)
printk("Sound: DMA (output) timed out - IRQ/DRQ config error?\n");
;
dma_reset_output(dev);
- } else if ((current->signal & ~current->blocked))
+ } else if (signal_pending(current))
{
err = -EINTR;
}
@@ -896,7 +897,7 @@ find_output_space(int dev, char **buf, int *size)
active_offs += dmap->byte_counter;
#endif
- offs = (dmap->user_counter % dmap->bytes_in_use) & ~3;
+ offs = (dmap->user_counter % dmap->bytes_in_use) & ~SAMPLE_ROUNDUP;
if (offs < 0 || offs >= dmap->bytes_in_use)
{
printk("OSS: Got unexpected offs %ld. Giving up.\n", offs);
@@ -920,10 +921,10 @@ find_output_space(int dev, char **buf, int *size)
{
len = (maxfrags * dmap->fragment_size) - occupied_bytes;
}
- *size = len & ~3;
+ *size = len & ~SAMPLE_ROUNDUP;
restore_flags(flags);
- return (len > 0);
+ return (*size > 0);
}
int
@@ -1539,10 +1540,11 @@ DMAbuf_deinit(int dev)
{
/* This routine is called when driver is being unloaded */
#ifdef RUNTIME_DMA_ALLOC
- sound_free_dmap (dev, audio_devs[dev]->dmap_out,
- audio_devs[dev]->dmap_out->dma);
+ if (audio_devs[dev])
+ sound_free_dmap (dev, audio_devs[dev]->dmap_out,
+ audio_devs[dev]->dmap_out->dma);
- if (audio_devs[dev]->flags & DMA_DUPLEX)
+ if (audio_devs[dev] && audio_devs[dev]->flags & DMA_DUPLEX)
sound_free_dmap (dev, audio_devs[dev]->dmap_in,
audio_devs[dev]->dmap_in->dma);
#endif
diff --git a/drivers/sound/dmasound.c b/drivers/sound/dmasound.c
index e7768f07f..0d4c73c1f 100644
--- a/drivers/sound/dmasound.c
+++ b/drivers/sound/dmasound.c
@@ -657,7 +657,7 @@ struct sound_queue
static struct sound_queue sq;
#define sq_block_address(i) (sq.buffers[i])
-#define SIGNAL_RECEIVED (current->signal & ~current->blocked)
+#define SIGNAL_RECEIVED (signal_pending(current))
#define NON_BLOCKING(open_mode) (open_mode & O_NONBLOCK)
#define ONE_SECOND HZ /* in jiffies (100ths of a second) */
#define NO_TIME_LIMIT 0xffffffff
diff --git a/drivers/sound/lowlevel/awe_wave.c b/drivers/sound/lowlevel/awe_wave.c
index 196882423..8ac02d490 100644
--- a/drivers/sound/lowlevel/awe_wave.c
+++ b/drivers/sound/lowlevel/awe_wave.c
@@ -551,16 +551,20 @@ int attach_awe(void)
INIT_TABLE(samples, max_samples, AWE_MAX_SAMPLES, awe_sample_list);
INIT_TABLE(infos, max_infos, AWE_MAX_INFOS, awe_voice_list);
- if (my_dev=sound_alloc_synthdev())
+ my_dev = sound_alloc_synthdev();
+ if (my_dev == -1) {
+ my_free(voices);
+ my_free(channels);
printk(KERN_WARNING "AWE32 Error: too many synthesizers\n");
- else {
- voice_alloc = &awe_operations.alloc;
- voice_alloc->max_voice = awe_max_voices;
- synth_devs[my_dev] = &awe_operations;
+ return 0;
}
+ voice_alloc = &awe_operations.alloc;
+ voice_alloc->max_voice = awe_max_voices;
+ synth_devs[my_dev] = &awe_operations;
+
#ifdef CONFIG_AWE32_MIXER
- if (my_mixerdev=sound_alloc_mixerdev()) {
+ if ((my_mixerdev=sound_alloc_mixerdev())==-1) {
mixer_devs[my_mixerdev] = &awe_mixer_operations;
}
#endif
diff --git a/drivers/sound/mad16.c b/drivers/sound/mad16.c
index f1f6559c4..bffc6ef17 100644
--- a/drivers/sound/mad16.c
+++ b/drivers/sound/mad16.c
@@ -795,6 +795,18 @@ int cddma = 3;
int opl4 = 0;
int joystick = 0;
+MODULE_PARM(io,"i");
+MODULE_PARM(dma,"i");
+MODULE_PARM(dma16,"i");
+MODULE_PARM(irq,"i");
+MODULE_PARM(cdtype,"i");
+MODULE_PARM(cdirq,"i");
+MODULE_PARM(cdport,"i");
+MODULE_PARM(cddma,"i");
+MODULE_PARM(opl4,"i");
+MODULE_PARM(joystick,"i");
+
+
static int found_mpu;
diff --git a/drivers/sound/maui.c b/drivers/sound/maui.c
index 37f4966b6..83d489d52 100644
--- a/drivers/sound/maui.c
+++ b/drivers/sound/maui.c
@@ -96,7 +96,7 @@ maui_wait(int mask)
}
maui_sleep_flag.opts &= ~WK_SLEEP;
};
- if ((current->signal & ~current->blocked))
+ if (signal_pending(current))
{
return 0;
}
diff --git a/drivers/sound/midi_synth.c b/drivers/sound/midi_synth.c
index 3885a650b..b123473cc 100644
--- a/drivers/sound/midi_synth.c
+++ b/drivers/sound/midi_synth.c
@@ -498,15 +498,15 @@ midi_synth_load_patch(int dev, int format, const char *addr,
return 0;
if (format != SYSEX_PATCH)
- {
- printk("MIDI Error: Invalid patch format (key) 0x%x\n", format);
+ {
+/* printk("MIDI Error: Invalid patch format (key) 0x%x\n", format);*/
return -EINVAL;
- }
+ }
if (count < hdr_size)
- {
- printk("MIDI Error: Patch header too short\n");
- return -EINVAL;
- }
+ {
+/* printk("MIDI Error: Patch header too short\n");*/
+ return -EINVAL;
+ }
count -= hdr_size;
/*
@@ -514,74 +514,73 @@ midi_synth_load_patch(int dev, int format, const char *addr,
* been transferred already.
*/
- copy_from_user(&((char *) &sysex)[offs], &(addr)[offs], hdr_size - offs);
-
- if (count < sysex.len)
- {
- printk("MIDI Warning: Sysex record too short (%d<%d)\n", count, (int) sysex.len);
- sysex.len = count;
- }
- left = sysex.len;
- src_offs = 0;
+ if(copy_from_user(&((char *) &sysex)[offs], &(addr)[offs], hdr_size - offs))
+ return -EFAULT;
+
+ if (count < sysex.len)
+ {
+/* printk(KERN_WARNING "MIDI Warning: Sysex record too short (%d<%d)\n", count, (int) sysex.len);*/
+ sysex.len = count;
+ }
+ left = sysex.len;
+ src_offs = 0;
sysex_sleep_flag.opts = WK_NONE;
- for (i = 0; i < left && !(current->signal & ~current->blocked); i++)
- {
- unsigned char data;
-
- get_user(*(unsigned char *) &data, (unsigned char *) &((addr)[hdr_size + i]));
-
- eox_seen = (i > 0 && data & 0x80); /* End of sysex */
-
- if (eox_seen && data != 0xf7)
- data = 0xf7;
-
- if (i == 0)
- {
- if (data != 0xf0)
- {
- printk("Error: Sysex start missing\n");
- return -EINVAL;
- }
- }
- while (!midi_devs[orig_dev]->outputc(orig_dev, (unsigned char) (data & 0xff)) &&
- !(current->signal & ~current->blocked))
-
- {
- unsigned long tlimit;
-
- if (1)
- current->timeout = tlimit = jiffies + (1);
- else
- tlimit = (unsigned long) -1;
- sysex_sleep_flag.opts = WK_SLEEP;
- interruptible_sleep_on(&sysex_sleeper);
- if (!(sysex_sleep_flag.opts & WK_WAKEUP))
- {
- if (jiffies >= tlimit)
- sysex_sleep_flag.opts |= WK_TIMEOUT;
- }
- sysex_sleep_flag.opts &= ~WK_SLEEP;
- }; /* Wait for timeout */
-
- if (!first_byte && data & 0x80)
- return 0;
- first_byte = 0;
- }
+ for (i = 0; i < left && !signal_pending(current); i++)
+ {
+ unsigned char data;
+
+ get_user(*(unsigned char *) &data, (unsigned char *) &((addr)[hdr_size + i]));
+
+ eox_seen = (i > 0 && data & 0x80); /* End of sysex */
+
+ if (eox_seen && data != 0xf7)
+ data = 0xf7;
+
+ if (i == 0)
+ {
+ if (data != 0xf0)
+ {
+ printk(KERN_WARNING "midi_synth: Sysex start missing\n");
+ return -EINVAL;
+ }
+ }
+ while (!midi_devs[orig_dev]->outputc(orig_dev, (unsigned char) (data & 0xff)) &&
+ !signal_pending(current))
+
+ {
+ unsigned long tlimit;
+
+ if (1)
+ current->timeout = tlimit = jiffies + (1);
+ else
+ tlimit = (unsigned long) -1;
+ sysex_sleep_flag.opts = WK_SLEEP;
+ interruptible_sleep_on(&sysex_sleeper);
+ if (!(sysex_sleep_flag.opts & WK_WAKEUP))
+ {
+ if (jiffies >= tlimit)
+ sysex_sleep_flag.opts |= WK_TIMEOUT;
+ }
+ sysex_sleep_flag.opts &= ~WK_SLEEP;
+ }; /* Wait for timeout */
+
+ if (!first_byte && data & 0x80)
+ return 0;
+ first_byte = 0;
+ }
if (!eox_seen)
midi_outc(orig_dev, 0xf7);
return 0;
}
-
-void
-midi_synth_panning(int dev, int channel, int pressure)
+
+void midi_synth_panning(int dev, int channel, int pressure)
{
}
-
-void
-midi_synth_aftertouch(int dev, int channel, int pressure)
+
+void midi_synth_aftertouch(int dev, int channel, int pressure)
{
int orig_dev = synth_devs[dev]->midi_dev;
int msg, chn;
diff --git a/drivers/sound/midibuf.c b/drivers/sound/midibuf.c
index ad2f5780a..fb6534191 100644
--- a/drivers/sound/midibuf.c
+++ b/drivers/sound/midibuf.c
@@ -93,7 +93,7 @@ drain_midi_queue(int dev)
*/
if (midi_devs[dev]->buffer_status != NULL)
- while (!(current->signal & ~current->blocked) &&
+ while (!signal_pending(current) &&
midi_devs[dev]->buffer_status(dev))
{
@@ -283,7 +283,7 @@ MIDIbuf_release(int dev, struct fileinfo *file)
* devices
*/
- while (!(current->signal & ~current->blocked) &&
+ while (!signal_pending(current) &&
DATA_AVAIL(midi_out_buf[dev]))
{
@@ -364,7 +364,7 @@ MIDIbuf_write(int dev, struct fileinfo *file, const char *buf, int count)
}
midi_sleep_flag[dev].opts &= ~WK_SLEEP;
};
- if ((current->signal & ~current->blocked))
+ if (signal_pending(current))
{
restore_flags(flags);
return -EINTR;
@@ -421,7 +421,7 @@ MIDIbuf_read(int dev, struct fileinfo *file, char *buf, int count)
}
input_sleep_flag[dev].opts &= ~WK_SLEEP;
};
- if ((current->signal & ~current->blocked))
+ if (signal_pending(current))
c = -EINTR; /*
* The user is getting restless
*/
diff --git a/drivers/sound/mpu401.c b/drivers/sound/mpu401.c
index f504a5d9d..cf00dc9e4 100644
--- a/drivers/sound/mpu401.c
+++ b/drivers/sound/mpu401.c
@@ -1844,14 +1844,5 @@ void cleanup_module(void)
SOUND_LOCK_END;
}
-#else
-
-void
-export_mpu401_syms(void)
-{
- register_symtab(&mpu401_syms);
-}
-
-
#endif
#endif
diff --git a/drivers/sound/pss.c b/drivers/sound/pss.c
index 2a9080a8f..50c06e6d0 100644
--- a/drivers/sound/pss.c
+++ b/drivers/sound/pss.c
@@ -116,17 +116,15 @@ probe_pss(struct address_info *hw_config)
if (devc->base != 0x230 && devc->base != 0x250) /* Some cards use these */
return 0;
- if (check_region(devc->base, 16))
- {
- printk("PSS: I/O port conflict\n");
- return 0;
- }
+ if (check_region(devc->base, 16)) {
+ printk(KERN_ERR "PSS: I/O port conflict\n");
+ return 0;
+ }
id = inw(REG(PSS_ID));
- if ((id >> 8) != 'E')
- {
- /* printk( "No PSS signature detected at 0x%x (0x%x)\n", devc->base, id); */
- return 0;
- }
+ if ((id >> 8) != 'E') {
+ printk(KERN_ERR "No PSS signature detected at 0x%x (0x%x)\n", devc->base, id);
+ return 0;
+ }
return 1;
}
@@ -855,14 +853,28 @@ unload_pss_mss(struct address_info *hw_config)
#ifdef MODULE
-int io = -1;
-int irq = -1;
-int dma = -1;
+int pss_io = 0x220;
+
+int mss_io = 0x530;
+int mss_irq = 11;
+int mss_dma = 1;
-int pssmpu, pssmss;
-struct address_info cfg;
+int mpu_io = 0x330;
+int mpu_irq = -1;
+
+struct address_info cfgpss = { 0 /* pss_io */, 0, -1, -1 };
+struct address_info cfgmpu = { 0 /* mpu_io */, 0 /* mpu_irq */, 0, -1 };
+struct address_info cfgmss = { 0 /* mss_io */, 0 /* mss_irq */, 0 /* mss_dma */, -1 };
+
+MODULE_PARM(pss_io, "i");
+MODULE_PARM(mss_io, "i");
+MODULE_PARM(mss_irq, "i");
+MODULE_PARM(mss_dma, "i");
+MODULE_PARM(mpu_io, "i");
+MODULE_PARM(mpu_irq, "i");
static int fw_load = 0;
+static int pssmpu = 0, pssmss = 0;
/*
* Load a PSS sound card module
@@ -871,34 +883,39 @@ static int fw_load = 0;
int
init_module(void)
{
- if (io == -1 || irq == -1 || dma == -1)
- {
+#if 0
+ if (pss_io == -1 || irq == -1 || dma == -1) {
printk("pss: dma, irq and io must be set.\n");
return -EINVAL;
- }
- cfg.io_base = io;
- cfg.irq = irq;
+ }
+#endif
+ cfgpss.io_base = pss_io;
- if (!pss_synth)
- {
- fw_load = 1;
- pss_synthLen = mod_firmware_load("/etc/sound/pss_synth", (void *) &pss_synth);
- }
- if (probe_pss(&cfg))
+ cfgmss.io_base = mss_io;
+ cfgmss.irq = mss_irq;
+ cfgmss.dma = mss_dma;
+
+ cfgmpu.io_base = mpu_io;
+ cfgmpu.irq = mpu_irq;
+
+ if (!pss_synth) {
+ fw_load = 1;
+ pss_synthLen = mod_firmware_load("/etc/sound/pss_synth", (void *) &pss_synth);
+ }
+ if (!probe_pss(&cfgpss))
return -ENODEV;
+ attach_pss(&cfgpss);
/*
* Attach stuff
*/
- if (probe_pss_mpu(&cfg))
- {
- pssmpu = 1;
- attach_pss_mpu(&cfg);
- }
- if (probe_pss_mss(&cfg))
- {
- pssmss = 1;
- attach_pss_mss(&cfg);
- }
+ if (probe_pss_mpu(&cfgmpu)) {
+ pssmpu = 1;
+ attach_pss_mpu(&cfgmpu);
+ }
+ if (probe_pss_mss(&cfgmss)) {
+ pssmss = 1;
+ attach_pss_mss(&cfgmss);
+ }
SOUND_LOCK;
return 0;
}
@@ -909,10 +926,10 @@ cleanup_module(void)
if (fw_load && pss_synth)
kfree(pss_synth);
if (pssmss)
- unload_pss_mss(&cfg);
+ unload_pss_mss(&cfgmss);
if (pssmpu)
- unload_pss_mpu(&cfg);
- unload_pss(&cfg);
+ unload_pss_mpu(&cfgmpu);
+ unload_pss(&cfgpss);
SOUND_LOCK_END;
}
#endif
diff --git a/drivers/sound/sequencer.c b/drivers/sound/sequencer.c
index 8995e0072..fe18beea9 100644
--- a/drivers/sound/sequencer.c
+++ b/drivers/sound/sequencer.c
@@ -1219,7 +1219,7 @@ seq_drain_midi_queues(void)
n = 1;
- while (!(current->signal & ~current->blocked) && n)
+ while (!signal_pending(current) && n)
{
n = 0;
@@ -1271,7 +1271,7 @@ sequencer_release(int dev, struct fileinfo *file)
if (mode != OPEN_READ && !(file->flags & (O_NONBLOCK) ?
1 : 0))
- while (!(current->signal & ~current->blocked) && qlen > 0)
+ while (!signal_pending(current) && qlen > 0)
{
seq_sync();
@@ -1335,7 +1335,7 @@ seq_sync(void)
{
unsigned long flags;
- if (qlen && !seq_playing && !(current->signal & ~current->blocked))
+ if (qlen && !seq_playing && !signal_pending(current))
seq_startplay();
save_flags(flags);
@@ -1563,7 +1563,7 @@ sequencer_ioctl(int dev, struct fileinfo *file,
if (mode == OPEN_READ)
return 0;
- while (qlen > 0 && !(current->signal & ~current->blocked))
+ while (qlen > 0 && !signal_pending(current))
seq_sync();
if (qlen)
return -EINTR;
diff --git a/drivers/sound/sound_firmware.c b/drivers/sound/sound_firmware.c
index 4dedda0d9..c7c8091c2 100644
--- a/drivers/sound/sound_firmware.c
+++ b/drivers/sound/sound_firmware.c
@@ -49,7 +49,7 @@ static int do_mod_firmware_load(const char *fn, char **fp)
int mod_firmware_load(const char *fn, char **fp)
{
int r;
- unsigned long fs = get_fs();
+ mm_segment_t fs = get_fs();
set_fs(get_ds());
r = do_mod_firmware_load(fn, fp);
diff --git a/drivers/sound/soundvers.h b/drivers/sound/soundvers.h
index b3a8356c2..e9084d2f4 100644
--- a/drivers/sound/soundvers.h
+++ b/drivers/sound/soundvers.h
@@ -1,2 +1,2 @@
-#define SOUND_VERSION_STRING "3.8s-971110"
+#define SOUND_VERSION_STRING "3.8s2++-971130"
#define SOUND_INTERNAL_VERSION 0x030804
diff --git a/drivers/sound/uart401.c b/drivers/sound/uart401.c
index 22e4fe8f9..63bfd9211 100644
--- a/drivers/sound/uart401.c
+++ b/drivers/sound/uart401.c
@@ -452,8 +452,7 @@ unload_uart401(struct address_info *hw_config)
if (!devc->share_irq)
snd_release_irq(devc->irq);
- /* Free device too !! - AC FIXME: CHECK THIS IS RIGHT */
- if (devc)
+ if (!devc)
vfree(devc);
sound_unload_mididev(hw_config->slots[4]);
}