diff options
author | asami <asami@FreeBSD.org> | 1996-10-30 22:41:46 +0000 |
---|---|---|
committer | asami <asami@FreeBSD.org> | 1996-10-30 22:41:46 +0000 |
commit | 95ac832055c11e8031e18bcc9759b2d12b654e9b (patch) | |
tree | 37f74d6fdf54e31c6c6d69a11d50e299cd0a1118 /sys | |
parent | e1b78916a4b8d96475ebaa0033860c706702fe49 (diff) | |
download | FreeBSD-src-95ac832055c11e8031e18bcc9759b2d12b654e9b.zip FreeBSD-src-95ac832055c11e8031e18bcc9759b2d12b654e9b.tar.gz |
More merge and update.
(1) deleted #if 0
pc98/pc98/mse.c
(2) hold per-unit I/O ports in ed_softc
pc98/pc98/if_ed.c
pc98/pc98/if_ed98.h
(3) merge more files by segregating changes into headers.
new file (moved from pc98/pc98):
i386/isa/aic_98.h
deleted:
well, it's already in the commit message so I won't repeat the
long list here ;)
Submitted by: The FreeBSD(98) Development Team
Diffstat (limited to 'sys')
114 files changed, 1166 insertions, 28780 deletions
diff --git a/sys/amd64/amd64/prof_machdep.c b/sys/amd64/amd64/prof_machdep.c index 62c8df5..a8603cb 100644 --- a/sys/amd64/amd64/prof_machdep.c +++ b/sys/amd64/amd64/prof_machdep.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: prof_machdep.c,v 1.2 1996/04/08 16:41:06 wollman Exp $ + * $Id: prof_machdep.c,v 1.3 1996/10/17 19:32:10 bde Exp $ */ #ifdef GUPROF @@ -40,7 +40,11 @@ #include <machine/profile.h> #endif +#ifdef PC98 +#include <pc98/pc98/pc98.h> +#else #include <i386/isa/isa.h> +#endif #include <i386/isa/timerreg.h> #ifdef GUPROF diff --git a/sys/amd64/amd64/vm_machdep.c b/sys/amd64/amd64/vm_machdep.c index 44b799d..62ff784 100644 --- a/sys/amd64/amd64/vm_machdep.c +++ b/sys/amd64/amd64/vm_machdep.c @@ -38,7 +38,7 @@ * * from: @(#)vm_machdep.c 7.3 (Berkeley) 5/13/91 * Utah $Hdr: vm_machdep.c 1.16.1.1 89/06/23$ - * $Id: vm_machdep.c,v 1.69 1996/09/28 22:37:43 dyson Exp $ + * $Id: vm_machdep.c,v 1.70 1996/10/15 03:16:33 dyson Exp $ */ #include "npx.h" @@ -66,7 +66,11 @@ #include <sys/user.h> +#ifdef PC98 +#include <pc98/pc98/pc98.h> +#else #include <i386/isa/isa.h> +#endif #ifdef BOUNCE_BUFFERS static vm_offset_t @@ -90,7 +94,11 @@ static int bounceallocarraysize; static unsigned *bounceallocarray; static int bouncefree; +#if defined(PC98) && defined (EPSON_BOUNCEDMA) +#define SIXTEENMEG (3840*4096) /* 15MB boundary */ +#else #define SIXTEENMEG (4096*4096) +#endif #define MAXBKVA 1024 int maxbkva = MAXBKVA*PAGE_SIZE; @@ -748,7 +756,7 @@ cpu_reset() { * to do the reset here would then end up in no man's land. */ -#ifndef BROKEN_KEYBOARD_RESET +#if !defined(BROKEN_KEYBOARD_RESET) && !defined(PC98) outb(IO_KBD + 4, 0xFE); DELAY(500000); /* wait 0.5 sec to see if that did it */ printf("Keyboard reset did not work, attempting CPU shutdown\n"); @@ -761,6 +769,12 @@ cpu_reset() { /* "good night, sweet prince .... <THUNK!>" */ invltlb(); /* NOTREACHED */ +#ifdef PC98 + asm(" cli "); + outb(0x37, 0x0f); /* SHUT 0 = 0 */ + outb(0x37, 0x0b); /* SHUT 1 = 0 */ + outb(0xf0, 0x00); /* reset port */ +#endif while(1); } diff --git a/sys/amd64/include/clock.h b/sys/amd64/include/clock.h index f20902f..0f3427f 100644 --- a/sys/amd64/include/clock.h +++ b/sys/amd64/include/clock.h @@ -3,7 +3,7 @@ * Garrett Wollman, September 1994. * This file is in the public domain. * - * $Id: clock.h,v 1.19 1996/10/17 17:31:25 bde Exp $ + * $Id: clock.h,v 1.20 1996/10/25 13:01:08 bde Exp $ */ #ifndef _MACHINE_CLOCK_H_ @@ -65,7 +65,11 @@ int sysbeep __P((int pitch, int period)); #ifdef CLOCK_HAIR +#ifdef PC98 +#include <pc98/pc98/pc98.h> /* XXX */ +#else #include <i386/isa/isa.h> /* XXX */ +#endif #include <i386/isa/timerreg.h> /* XXX */ static __inline u_int diff --git a/sys/amd64/isa/timerreg.h b/sys/amd64/isa/timerreg.h index 5742f66..16fbc0b 100644 --- a/sys/amd64/isa/timerreg.h +++ b/sys/amd64/isa/timerreg.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: Header: timerreg.h,v 1.2 93/02/28 15:08:58 mccanne Exp - * $Id$ + * $Id: timerreg.h,v 1.2 1993/10/16 13:46:26 rgrimes Exp $ */ /* @@ -59,6 +59,7 @@ * in undefined behavior (but hopefully not fry the chip). * Reading in this manner has no side effects. * + * [IBM-PC] * The outputs of the three timers are connected as follows: * * timer 0 -> irq 0 @@ -67,15 +68,31 @@ * * Timer 0 is used to call hardclock. * Timer 2 is used to generate console beeps. + * + * [PC-9801] + * The outputs of the three timers are connected as follows: + * + * timer 0 -> irq 0 + * timer 1 -> speaker (via keyboard controller) + * timer 2 -> RS232C + * + * Timer 0 is used to call hardclock. + * Timer 1 is used to generate console beeps. */ /* * Macros for specifying values to be written into a mode register. */ #define TIMER_CNTR0 (IO_TIMER1 + 0) /* timer 0 counter port */ +#ifdef PC98 +#define TIMER_CNTR1 0x3fdb /* timer 1 counter port */ +#define TIMER_CNTR2 (IO_TIMER1 + 4) /* timer 2 counter port */ +#define TIMER_MODE (IO_TIMER1 + 6) /* timer mode port */ +#else #define TIMER_CNTR1 (IO_TIMER1 + 1) /* timer 1 counter port */ #define TIMER_CNTR2 (IO_TIMER1 + 2) /* timer 2 counter port */ #define TIMER_MODE (IO_TIMER1 + 3) /* timer mode port */ +#endif #define TIMER_SEL0 0x00 /* select counter 0 */ #define TIMER_SEL1 0x40 /* select counter 1 */ #define TIMER_SEL2 0x80 /* select counter 2 */ diff --git a/sys/amd64/isa/vector.S b/sys/amd64/isa/vector.S index 94691f5..0283c2a 100644 --- a/sys/amd64/isa/vector.S +++ b/sys/amd64/isa/vector.S @@ -1,12 +1,26 @@ /* * from: vector.s, 386BSD 0.1 unknown origin - * $Id: vector.s,v 1.19 1996/04/11 21:18:47 bde Exp $ + * $Id: vector.s,v 1.20 1996/05/31 01:08:08 peter Exp $ + */ + +/* + * modified for PC98 by Kakefuda */ #include "opt_auto_eoi.h" #include <i386/isa/icu.h> +#ifdef PC98 +#include <pc98/pc98/pc98.h> +#else #include <i386/isa/isa.h> +#endif + +#ifdef PC98 +#define ICU_IMR_OFFSET 2 /* IO_ICU{1,2} + 2 */ +#else +#define ICU_IMR_OFFSET 1 /* IO_ICU{1,2} + 1 */ +#endif #define ICU_EOI 0x20 /* XXX - define elsewhere */ @@ -168,7 +182,7 @@ IDTVEC(vec_name) ; \ movb _imen + IRQ_BYTE(irq_num),%al ; \ orb $IRQ_BIT(irq_num),%al ; \ movb %al,_imen + IRQ_BYTE(irq_num) ; \ - outb %al,$icu+1 ; \ + outb %al,$icu+ICU_IMR_OFFSET ; \ enable_icus ; \ incl _cnt+V_INTR ; /* tally interrupts */ \ movl _cpl,%eax ; \ @@ -190,7 +204,7 @@ __CONCAT(Xresume,irq_num): ; \ movb _imen + IRQ_BYTE(irq_num),%al ; \ andb $~IRQ_BIT(irq_num),%al ; \ movb %al,_imen + IRQ_BYTE(irq_num) ; \ - outb %al,$icu+1 ; \ + outb %al,$icu+ICU_IMR_OFFSET ; \ sti ; /* XXX _doreti repeats the cli/sti */ \ MEXITCOUNT ; \ /* We could usually avoid the following jmp by inlining some of */ \ diff --git a/sys/amd64/isa/vector.s b/sys/amd64/isa/vector.s index 94691f5..0283c2a 100644 --- a/sys/amd64/isa/vector.s +++ b/sys/amd64/isa/vector.s @@ -1,12 +1,26 @@ /* * from: vector.s, 386BSD 0.1 unknown origin - * $Id: vector.s,v 1.19 1996/04/11 21:18:47 bde Exp $ + * $Id: vector.s,v 1.20 1996/05/31 01:08:08 peter Exp $ + */ + +/* + * modified for PC98 by Kakefuda */ #include "opt_auto_eoi.h" #include <i386/isa/icu.h> +#ifdef PC98 +#include <pc98/pc98/pc98.h> +#else #include <i386/isa/isa.h> +#endif + +#ifdef PC98 +#define ICU_IMR_OFFSET 2 /* IO_ICU{1,2} + 2 */ +#else +#define ICU_IMR_OFFSET 1 /* IO_ICU{1,2} + 1 */ +#endif #define ICU_EOI 0x20 /* XXX - define elsewhere */ @@ -168,7 +182,7 @@ IDTVEC(vec_name) ; \ movb _imen + IRQ_BYTE(irq_num),%al ; \ orb $IRQ_BIT(irq_num),%al ; \ movb %al,_imen + IRQ_BYTE(irq_num) ; \ - outb %al,$icu+1 ; \ + outb %al,$icu+ICU_IMR_OFFSET ; \ enable_icus ; \ incl _cnt+V_INTR ; /* tally interrupts */ \ movl _cpl,%eax ; \ @@ -190,7 +204,7 @@ __CONCAT(Xresume,irq_num): ; \ movb _imen + IRQ_BYTE(irq_num),%al ; \ andb $~IRQ_BIT(irq_num),%al ; \ movb %al,_imen + IRQ_BYTE(irq_num) ; \ - outb %al,$icu+1 ; \ + outb %al,$icu+ICU_IMR_OFFSET ; \ sti ; /* XXX _doreti repeats the cli/sti */ \ MEXITCOUNT ; \ /* We could usually avoid the following jmp by inlining some of */ \ diff --git a/sys/amd64/pci/pci_bus.c b/sys/amd64/pci/pci_bus.c index 4232069..903214c 100644 --- a/sys/amd64/pci/pci_bus.c +++ b/sys/amd64/pci/pci_bus.c @@ -1,6 +1,6 @@ /************************************************************************** ** -** $Id: pcibus.c,v 1.25 1996/06/13 21:50:41 se Exp $ +** $Id: pcibus.c,v 1.26 1996/06/18 01:22:28 bde Exp $ ** ** pci bus subroutines for i386 architecture. ** @@ -151,7 +151,11 @@ DATA_SET (pcibus_set, i386pci); #define CONF1_ENABLE_RES1 0x80000000ul #define CONF2_ENABLE_PORT 0x0cf8 +#ifdef PC98 +#define CONF2_FORWARD_PORT 0x0cf9 +#else #define CONF2_FORWARD_PORT 0x0cfa +#endif #define CONF2_ENABLE_CHK 0x0e #define CONF2_ENABLE_RES 0x0e diff --git a/sys/amd64/pci/pci_cfgreg.c b/sys/amd64/pci/pci_cfgreg.c index 4232069..903214c 100644 --- a/sys/amd64/pci/pci_cfgreg.c +++ b/sys/amd64/pci/pci_cfgreg.c @@ -1,6 +1,6 @@ /************************************************************************** ** -** $Id: pcibus.c,v 1.25 1996/06/13 21:50:41 se Exp $ +** $Id: pcibus.c,v 1.26 1996/06/18 01:22:28 bde Exp $ ** ** pci bus subroutines for i386 architecture. ** @@ -151,7 +151,11 @@ DATA_SET (pcibus_set, i386pci); #define CONF1_ENABLE_RES1 0x80000000ul #define CONF2_ENABLE_PORT 0x0cf8 +#ifdef PC98 +#define CONF2_FORWARD_PORT 0x0cf9 +#else #define CONF2_FORWARD_PORT 0x0cfa +#endif #define CONF2_ENABLE_CHK 0x0e #define CONF2_ENABLE_RES 0x0e diff --git a/sys/conf/files.pc98 b/sys/conf/files.pc98 index fef4b97..08f74ae 100644 --- a/sys/conf/files.pc98 +++ b/sys/conf/files.pc98 @@ -3,7 +3,7 @@ # # modified for PC-9801 # -# $Id: files.pc98,v 1.7 1996/09/12 11:09:18 asami Exp $ +# $Id: files.pc98,v 1.8 1996/10/23 07:24:49 asami Exp $ # aic7xxx_asm optional ahc device-driver \ dependency "$S/dev/aic7xxx/aic7xxx_asm.c" \ @@ -43,7 +43,7 @@ i386/i386/db_disasm.c optional ddb i386/i386/db_interface.c optional ddb i386/i386/db_trace.c optional ddb i386/i386/i386-gdbstub.c optional ddb -pc98/i386/exception.s standard +i386/i386/exception.s standard i386/i386/identcpu.c standard i386/i386/in_cksum.c optional inet # locore.s needs to be handled in Makefile to put it first. Otherwise it's @@ -62,7 +62,7 @@ i386/i386/swtch.s standard i386/i386/sys_machdep.c standard pc98/i386/trap.c standard pc98/i386/userconfig.c optional userconfig -pc98/i386/vm_machdep.c standard +i386/i386/vm_machdep.c standard i386/ibcs2/ibcs2_fcntl.c optional ibcs2 i386/ibcs2/ibcs2_stat.c optional ibcs2 i386/ibcs2/ibcs2_ipc.c optional ibcs2 @@ -89,7 +89,7 @@ pc98/pc98/bs/bshw.c optional bs device-driver pc98/pc98/bs/bsif.c optional bs device-driver pc98/pc98/sbic55.c optional sbic device-driver #i386/pc98/aha1542.c optional aha device-driver -pc98/pc98/aic6360.c optional aic device-driver +i386/isa/aic6360.c optional aic device-driver pc98/pc98/b004.c optional bqu device-driver i386/pc98/bt742a.c optional bt device-driver i386/pc98/bt5xx-445.c optional bt device-driver @@ -130,8 +130,8 @@ pc98/pc98/mse.c optional mse device-driver pc98/isa/ncr5380.c optional nca device-driver pc98/pc98/npx.c optional npx device-driver pc98/pc98/pcaudio.c optional pca device-driver -pc98/pc98/matcd/matcd.c optional matcd device-driver -pc98/pc98/pcibus.c optional pci device-driver +i386/isa/matcd/matcd.c optional matcd device-driver +i386/isa/pcibus.c optional pci device-driver i386/isa/pcicx.c optional ze device-driver i386/isa/pcicx.c optional zp device-driver pc98/isa/pcvt/pcvt_drv.c optional vt device-driver @@ -140,11 +140,11 @@ pc98/isa/pcvt/pcvt_kbd.c optional vt device-driver pc98/isa/pcvt/pcvt_out.c optional vt device-driver pc98/isa/pcvt/pcvt_sup.c optional vt device-driver pc98/isa/pcvt/pcvt_vtf.c optional vt device-driver -pc98/pc98/prof_machdep.c optional profiling-routine +i386/isa/prof_machdep.c optional profiling-routine pc98/pc98/psm.c optional psm device-driver pc98/isa/qcam.c optional qcam device-driver pc98/isa/qcamio.c optional qcam device-driver -pc98/pc98/random_machdep.c standard +i386/isa/random_machdep.c standard pc98/isa/rc.c optional rc device-driver i386/isa/scd.c optional scd device-driver pc98/isa/seagate.c optional sea device-driver @@ -152,51 +152,51 @@ pc98/isa/si.c optional si device-driver pc98/isa/si_code.c optional si device-driver pc98/pc98/sio.c optional sio device-driver pc98/pc98/sound/pcm86.c optional pcm device-driver -pc98/pc98/sound/dev_table.c optional snd device-driver +i386/isa/sound/dev_table.c optional snd device-driver pc98/pc98/sound/soundcard.c optional snd device-driver pc98/pc98/sound/sound_switch.c optional snd device-driver -pc98/pc98/sound/audio.c optional snd device-driver -pc98/pc98/sound/dmabuf.c optional snd device-driver -pc98/pc98/sound/sys_timer.c optional snd device-driver -pc98/pc98/sound/sequencer.c optional snd device-driver -pc98/pc98/sound/patmgr.c optional snd device-driver -pc98/pc98/sound/adlib_card.c optional opl device-driver +i386/isa/sound/audio.c optional snd device-driver +i386/isa/sound/dmabuf.c optional snd device-driver +i386/isa/sound/sys_timer.c optional snd device-driver +i386/isa/sound/sequencer.c optional snd device-driver +i386/isa/sound/patmgr.c optional snd device-driver +i386/isa/sound/adlib_card.c optional opl device-driver pc98/pc98/sound/opl3.c optional opl device-driver -pc98/pc98/sound/gus_card.c optional gus device-driver -pc98/pc98/sound/gus_midi.c optional gus device-driver -pc98/pc98/sound/gus_vol.c optional gus device-driver -pc98/pc98/sound/gus_wave.c optional gus device-driver -pc98/pc98/sound/ics2101.c optional gus device-driver -pc98/pc98/sound/sound_timer.c optional gus device-driver -pc98/pc98/sound/midi_synth.c optional gus device-driver -pc98/pc98/sound/midibuf.c optional gus device-driver +i386/isa/sound/gus_card.c optional gus device-driver +i386/isa/sound/gus_midi.c optional gus device-driver +i386/isa/sound/gus_vol.c optional gus device-driver +i386/isa/sound/gus_wave.c optional gus device-driver +i386/isa/sound/ics2101.c optional gus device-driver +i386/isa/sound/sound_timer.c optional gus device-driver +i386/isa/sound/midi_synth.c optional gus device-driver +i386/isa/sound/midibuf.c optional gus device-driver pc98/pc98/sound/ad1848.c optional gusxvi device-driver pc98/pc98/sound/ad1848.c optional gus device-driver pc98/pc98/sound/ad1848.c optional mss device-driver -pc98/pc98/sound/midi_synth.c optional mss device-driver -pc98/pc98/sound/midibuf.c optional mss device-driver -pc98/pc98/sound/mpu401.c optional mpu device-driver -pc98/pc98/sound/midi_synth.c optional mpu device-driver -pc98/pc98/sound/midibuf.c optional mpu device-driver -pc98/pc98/sound/pas2_card.c optional pas device-driver -pc98/pc98/sound/pas2_midi.c optional pas device-driver -pc98/pc98/sound/pas2_mixer.c optional pas device-driver +i386/isa/sound/midi_synth.c optional mss device-driver +i386/isa/sound/midibuf.c optional mss device-driver +i386/isa/sound/mpu401.c optional mpu device-driver +i386/isa/sound/midi_synth.c optional mpu device-driver +i386/isa/sound/midibuf.c optional mpu device-driver +i386/isa/sound/pas2_card.c optional pas device-driver +i386/isa/sound/pas2_midi.c optional pas device-driver +i386/isa/sound/pas2_mixer.c optional pas device-driver pc98/pc98/sound/pas2_pcm.c optional pas device-driver -pc98/pc98/sound/midi_synth.c optional pas device-driver -pc98/pc98/sound/midibuf.c optional pas device-driver -pc98/pc98/sound/sb_card.c optional sb device-driver +i386/isa/sound/midi_synth.c optional pas device-driver +i386/isa/sound/midibuf.c optional pas device-driver +i386/isa/sound/sb_card.c optional sb device-driver pc98/pc98/sound/sb_dsp.c optional sb device-driver -pc98/pc98/sound/sb_midi.c optional sb device-driver -pc98/pc98/sound/sb_mixer.c optional sb device-driver -pc98/pc98/sound/midi_synth.c optional sb device-driver -pc98/pc98/sound/midibuf.c optional sb device-driver +i386/isa/sound/sb_midi.c optional sb device-driver +i386/isa/sound/sb_mixer.c optional sb device-driver +i386/isa/sound/midi_synth.c optional sb device-driver +i386/isa/sound/midibuf.c optional sb device-driver pc98/pc98/sound/sb16_dsp.c optional sbxvi device-driver pc98/pc98/sound/sb16_midi.c optional sbmidi device-driver -pc98/pc98/sound/uart6850.c optional uart device-driver -pc98/pc98/sound/midi_synth.c optional uart device-driver -pc98/pc98/sound/midibuf.c optional uart device-driver -pc98/pc98/sound/trix.c optional trix device-driver -pc98/pc98/sound/sscape.c optional sscape device-driver +i386/isa/sound/uart6850.c optional uart device-driver +i386/isa/sound/midi_synth.c optional uart device-driver +i386/isa/sound/midibuf.c optional uart device-driver +i386/isa/sound/trix.c optional trix device-driver +i386/isa/sound/sscape.c optional sscape device-driver pc98/isa/spigot.c optional spigot device-driver pc98/pc98/spkr.c optional speaker device-driver pc98/isa/stallion.c optional stl device-driver @@ -205,7 +205,7 @@ pc98/isa/tw.c optional tw device-driver pc98/isa/ultra14f.c optional uha device-driver pc98/pc98/wd.c optional wdc device-driver pc98/pc98/wd.c optional wd device-driver -pc98/pc98/atapi.c optional atapi device-driver +i386/isa/atapi.c optional atapi device-driver pc98/pc98/wcd.c optional wcd device-driver pc98/isa/wd7000.c optional wds device-driver pc98/pc98/wt.c optional wt device-driver diff --git a/sys/conf/options.pc98 b/sys/conf/options.pc98 index 3f3edc68..106083c 100644 --- a/sys/conf/options.pc98 +++ b/sys/conf/options.pc98 @@ -1,4 +1,4 @@ -# $Id: options.pc98,v 1.6 1996/10/23 07:24:55 asami Exp $ +# $Id: options.pc98,v 1.7 1996/10/29 08:36:14 asami Exp $ BOUNCEPAGES opt_bounce.h USER_LDT MATH_EMULATE opt_math_emulate.h @@ -29,6 +29,8 @@ XSERVER opt_pcvt.h AHC_TAGENABLE opt_aic7xxx.h AHC_SCBPAGING_ENABLE opt_aic7xxx.h +AHC_FORCE_PIO opt_aic7xxx.h +AHC_SHARE_SCBS opt_aic7xxx.h CLK_CALIBRATION_LOOP opt_clock.h CLK_USE_I8254_CALIBRATION opt_clock.h diff --git a/sys/dev/kbd/kbdtables.h b/sys/dev/kbd/kbdtables.h index 1c832cb..9f69ee4 100644 --- a/sys/dev/kbd/kbdtables.h +++ b/sys/dev/kbd/kbdtables.h @@ -25,11 +25,150 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: kbdtables.h,v 1.30 1995/12/10 13:38:53 phk Exp $ + * $Id: kbdtables.h,v 1.31 1996/01/25 16:37:20 ache Exp $ */ #define SET8 0x80 /* set eight bit on */ +#ifdef PC98 +/* PC-9801 keymap by kuribo@isl.melco.co.jp */ +static keymap_t key_map = { 0x80, /* PC98 keymap */ +/* alt + * scan cntrl alt alt cntrl + * code base shift cntrl shift alt shift cntrl shift spcl flgs + * --------------------------------------------------------------------------- + */ +/* sc=00 */ 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, DBG, 0x1B, 0x02, 0x00, +/* sc=01 */ '1', '!', '!', '!', '1', '!', '!', '!', 0x00, 0x00, +/* sc=02 */ '2', '\"', 0x1A, 0x1A, '2', '@', 0x00, 0x00, 0x00, 0x00, +/* sc=03 */ '3', '#', 0x1B, 0x1B, '3', '#', 0x1B, 0x1B, 0x00, 0x00, +/* sc=04 */ '4', '$', 0x1C, 0x1C, '4', '$', 0x1C, 0x1C, 0x00, 0x00, +/* sc=05 */ '5', '%', 0x1D, 0x1D, '5', '%', 0x1D, 0x1D, 0x00, 0x00, +/* sc=06 */ '6', '&', 0x1E, 0x1E, '6', '^', 0x1E, 0x1E, 0x00, 0x00, +/* sc=07 */ '7', '\'', 0x1F, 0x1F, '7', '&', '&', '&', 0x00, 0x00, +/* sc=08 */ '8', '(', 0x7F, 0x7F, '8', '*', 0x08, 0x08, 0x00, 0x00, +/* sc=09 */ '9', ')', '9', '9', '9', '(', '(', '(', 0x00, 0x00, +/* sc=0a */ '0', NOP, '0', '0', '0', ')', ')', ')', 0x40, 0x00, +/* sc=0b */ '-', '=', '-', '-', '-', '_', 0x1F, 0x1F, 0x00, 0x00, +/* sc=0c */ '^', '`', 0x1E, 0x1E, '=', '+', '+', '+', 0x00, 0x00, +/* sc=0d */ '\\', '|', 0x1C, 0x1C, '\\', '|', 0x1C, 0x1C, 0x00, 0x00, +/* sc=0e */ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, +/* sc=0f */ '\t', '\t', '\t', '\t', '\t', '\t', '\t', '\t', 0x00, 0x00, +/* sc=10 */ 'q', 'Q', 0x11, 0x11, 'q', 'Q', 0x11, 0x11, 0x00, 0x01, +/* sc=11 */ 'w', 'W', 0x17, 0x17, 'w', 'W', 0x17, 0x17, 0x00, 0x01, +/* sc=12 */ 'e', 'E', 0x05, 0x05, 'e', 'E', 0x05, 0x05, 0x00, 0x01, +/* sc=13 */ 'r', 'R', 0x12, 0x12, 'r', 'R', 0x12, 0x12, 0x00, 0x01, +/* sc=14 */ 't', 'T', 0x14, 0x14, 't', 'T', 0x14, 0x14, 0x00, 0x01, +/* sc=15 */ 'y', 'Y', 0x19, 0x19, 'y', 'Y', 0x19, 0x19, 0x00, 0x01, +/* sc=16 */ 'u', 'U', 0x15, 0x15, 'u', 'U', 0x15, 0x15, 0x00, 0x01, +/* sc=17 */ 'i', 'I', 0x09, 0x09, 'i', 'I', 0x09, 0x09, 0x00, 0x01, +/* sc=18 */ 'o', 'O', 0x0F, 0x0F, 'o', 'O', 0x0F, 0x0F, 0x00, 0x01, +/* sc=19 */ 'p', 'P', 0x10, 0x10, 'p', 'P', 0x10, 0x10, 0x00, 0x01, +/* sc=1a */ '@', '~', 0x00, 0x00, '[', '{', 0x1B, 0x1B, 0x00, 0x00, +/* sc=1b */ '[', '{', 0x1B, 0x1B, ']', '}', 0x1D, 0x1D, 0x00, 0x00, +/* sc=1c */ '\r', '\r', '\n', '\n', '\r', '\r', '\n', '\n', 0x00, 0x00, +/* sc=1d */ 'a', 'A', 0x01, 0x01, 'a', 'A', 0x01, 0x01, 0x00, 0x01, +/* sc=1e */ 's', 'S', 0x13, 0x13, 's', 'S', 0x13, 0x13, 0x00, 0x01, +/* sc=1f */ 'd', 'D', 0x04, 0x04, 'd', 'D', 0x04, 0x04, 0x00, 0x01, +/* sc=20 */ 'f', 'F', 0x06, 0x06, 'f', 'F', 0x06, 0x06, 0x00, 0x01, +/* sc=21 */ 'g', 'G', 0x07, 0x07, 'g', 'G', 0x07, 0x07, 0x00, 0x01, +/* sc=22 */ 'h', 'H', 0x08, 0x08, 'h', 'H', 0x08, 0x08, 0x00, 0x01, +/* sc=23 */ 'j', 'J', '\n', '\n', 'j', 'J', '\n', '\n', 0x00, 0x01, +/* sc=24 */ 'k', 'K', 0x0B, 0x0B, 'k', 'K', 0x0B, 0x0B, 0x00, 0x01, +/* sc=25 */ 'l', 'L', 0x0C, 0x0C, 'l', 'L', 0x0C, 0x0C, 0x00, 0x01, +/* sc=26 */ ';', '+', ';', ';', ';', ':', ';', ';', 0x00, 0x00, +/* sc=27 */ ':', '*', ':', ':', '\'', '\"', '\'', '\'', 0x00, 0x00, +/* sc=28 */ ']', '}', 0x1D, 0x1D, '`', '~', '~', '~', 0x00, 0x00, +/* sc=29 */ 'z', 'Z', 0x1A, 0x1A, 'z', 'Z', 0x1A, 0x1A, 0x00, 0x01, +/* sc=2a */ 'x', 'X', 0x18, 0x18, 'x', 'X', 0x18, 0x18, 0x00, 0x01, +/* sc=2b */ 'c', 'C', 0x03, 0x03, 'c', 'C', 0x03, 0x03, 0x00, 0x01, +/* sc=2c */ 'v', 'V', 0x16, 0x16, 'v', 'V', 0x16, 0x16, 0x00, 0x01, +/* sc=2d */ 'b', 'B', 0x02, 0x02, 'b', 'B', 0x02, 0x02, 0x00, 0x01, +/* sc=2e */ 'n', 'N', 0x0E, 0x0E, 'n', 'N', 0x0E, 0x0E, 0x00, 0x01, +/* sc=2f */ 'm', 'M', '\r', '\r', 'm', 'M', '\r', '\r', 0x00, 0x01, +/* sc=30 */ ',', '<', '<', '<', ',', '<', '<', '<', 0x00, 0x00, +/* sc=31 */ '.', '>', '>', '>', '.', '>', '>', '>', 0x00, 0x00, +/* sc=32 */ '/', '?', 0x7F, 0x7F, '/', '?', 0x7F, 0x7F, 0x00, 0x00, +/* sc=33 */ NOP, '_', 0x1F, 0x1F, '\\', '|', 0x1C, 0x1C, 0x80, 0x00, +/* sc=34 */ ' ', ' ', 0x00, 0x00, ' ', ' ', 0x00, 0x00, 0x00, 0x00, +/* sc=35 */ 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x00, 0x00, +/* sc=36 */ F(51), F(51), F(51), F(51), F(51), F(51), F(51), F(51), 0xFF, 0x00, +/* sc=37 */ F(59), F(59), F(59), F(59), F(59), F(59), F(59), F(59), 0xFF, 0x00, +/* sc=38 */ F(60), F(60), F(60), F(60), F(60), F(60), F(60), F(60), 0xFF, 0x00, +/* sc=39 */ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, RBT, RBT, 0x03, 0x02, +/* sc=3a */ F(50), F(50), F(50), F(50), F(50), F(50), F(50), F(50), 0xFF, 0x00, +/* sc=3b */ F(53), F(53), F(53), F(53), F(53), F(53), F(53), F(53), 0xFF, 0x00, +/* sc=3c */ F(55), F(55), F(55), F(55), F(55), F(55), F(55), F(55), 0xFF, 0x00, +/* sc=3d */ F(58), F(58), F(58), F(58), F(58), F(58), F(58), F(58), 0xFF, 0x00, +/* sc=3e */ F(49), F(49), F(49), F(49), F(49), F(49), F(49), F(49), 0xFF, 0x00, +/* sc=3f */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=40 */ '-', '-', '-', '-', '-', '-', '-', '-', 0x00, 0x00, +/* sc=41 */ '/', '/', '/', '/', '/', '/', '/', '/', 0x00, 0x00, +/* sc=42 */ '7', '7', '7', '7', '7', '7', '7', '7', 0x00, 0x00, +/* sc=43 */ '8', '8', '8', '8', '8', '8', '8', '8', 0x00, 0x00, +/* sc=44 */ '9', '9', '9', '9', '9', '9', '9', '9', 0x00, 0x00, +/* sc=45 */ '*', '*', '*', '*', '*', '*', '*', '*', 0x00, 0x00, +/* sc=46 */ '4', '4', '4', '4', '4', '4', '4', '4', 0x00, 0x00, +/* sc=47 */ '5', '5', '5', '5', '5', '5', '5', '5', 0x00, 0x00, +/* sc=48 */ '6', '6', '6', '6', '6', '6', '6', '6', 0x00, 0x00, +/* sc=49 */ '+', '+', '+', '+', '+', '+', '+', '+', 0x00, 0x00, +/* sc=4a */ '1', '1', '1', '1', '1', '1', '1', '1', 0x00, 0x00, +/* sc=4b */ '2', '2', '2', '2', '2', '2', '2', '2', 0x00, 0x00, +/* sc=4c */ '3', '3', '3', '3', '3', '3', '3', '3', 0x00, 0x00, +/* sc=4d */ '=', '=', '=', '=', '=', '=', '=', '=', 0x00, 0x00, +/* sc=4e */ '0', '0', '0', '0', '0', '0', '0', '0', 0x00, 0x00, +/* sc=4f */ ',', ',', ',', ',', ',', ',', ',', ',', 0x00, 0x00, +/* sc=50 */ '.', '.', '.', '.', '.', '.', '.', '.', 0x00, 0x00, +/* sc=51 */ 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x00, 0x00, +/* sc=52 */ F(11), F(23), F(35), F(47), S(11), S(11), S(11), S(11), 0xFF, 0x00, +/* sc=53 */ F(12), F(24), F(36), F(48), S(12), S(12), S(12), S(12), 0xFF, 0x00, +/* sc=54 */ SLK, SLK, SLK, SLK, SLK, SLK, SLK, SLK, 0xFF, 0x00, +/* sc=55 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=56 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=57 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=58 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=59 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=5a */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=5b */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=5c */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=5d */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=5e */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=5f */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=60 */ F(57), F(57), F(57), F(57), F(57), F(57), F(57), F(57), 0xFF, 0x00, +/* sc=61 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=62 */ F( 1), F(13), F(25), F(37), S( 1), S( 1), S( 1), S( 1), 0xFF, 0x00, +/* sc=63 */ F( 2), F(14), F(26), F(38), S( 2), S( 2), S( 2), S( 2), 0xFF, 0x00, +/* sc=64 */ F( 3), F(15), F(27), F(39), S( 3), S( 3), S( 3), S( 3), 0xFF, 0x00, +/* sc=65 */ F( 4), F(16), F(28), F(40), S( 4), S( 4), S( 4), S( 4), 0xFF, 0x00, +/* sc=66 */ F( 5), F(17), F(29), F(41), S( 5), S( 5), S( 5), S( 5), 0xFF, 0x00, +/* sc=67 */ F( 6), F(18), F(30), F(42), S( 6), S( 6), S( 6), S( 6), 0xFF, 0x00, +/* sc=68 */ F( 7), F(19), F(31), F(43), S( 7), S( 7), S( 7), S( 7), 0xFF, 0x00, +/* sc=69 */ F( 8), F(20), F(32), F(44), S( 8), S( 8), S( 8), S( 8), 0xFF, 0x00, +/* sc=6a */ F( 9), F(21), F(33), F(45), S( 9), S( 9), S( 9), S( 9), 0xFF, 0x00, +/* sc=6b */ F(10), F(22), F(34), F(46), S(10), S(10), S(10), S(10), 0xFF, 0x00, +/* sc=6c */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=6d */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=6e */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=6f */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=70 */ LSH, LSH, LSH, LSH, LSH, LSH, LSH, LSH, 0xFF, 0x00, +/* sc=71 */ CLK, CLK, CLK, CLK, CLK, CLK, CLK, CLK, 0xFF, 0x00, +/* sc=72 */ LALT, LALT, LALT, LALT, LALT, LALT, LALT, LALT, 0xFF, 0x00, +/* sc=73 */ LALT, LALT, LALT, LALT, LALT, LALT, LALT, LALT, 0xFF, 0x00, +/* sc=74 */ LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, 0xFF, 0x00, +/* sc=75 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=76 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=77 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=78 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=79 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=7a */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=7b */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=7c */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=7d */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=7e */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=7f */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +}; +#endif + #ifdef DKKEYMAP static keymap_t key_map = { 0x6C, /* DK iso8859 keymap */ /* alt @@ -750,7 +889,7 @@ static keymap_t key_map = { 0xEC, /* keys number */ #endif -#if !defined(DKKEYMAP) && !defined(UKKEYMAP) && !defined(GRKEYMAP) && !defined(SWKEYMAP) && !defined(RUKEYMAP) +#if !defined(DKKEYMAP) && !defined(UKKEYMAP) && !defined(GRKEYMAP) && !defined(SWKEYMAP) && !defined(RUKEYMAP) && !defined(PC98) static keymap_t key_map = { 0x6C, /* US iso8859 keymap */ /* alt * scan cntrl alt alt cntrl diff --git a/sys/i386/i386/vm_machdep.c b/sys/i386/i386/vm_machdep.c index 44b799d..62ff784 100644 --- a/sys/i386/i386/vm_machdep.c +++ b/sys/i386/i386/vm_machdep.c @@ -38,7 +38,7 @@ * * from: @(#)vm_machdep.c 7.3 (Berkeley) 5/13/91 * Utah $Hdr: vm_machdep.c 1.16.1.1 89/06/23$ - * $Id: vm_machdep.c,v 1.69 1996/09/28 22:37:43 dyson Exp $ + * $Id: vm_machdep.c,v 1.70 1996/10/15 03:16:33 dyson Exp $ */ #include "npx.h" @@ -66,7 +66,11 @@ #include <sys/user.h> +#ifdef PC98 +#include <pc98/pc98/pc98.h> +#else #include <i386/isa/isa.h> +#endif #ifdef BOUNCE_BUFFERS static vm_offset_t @@ -90,7 +94,11 @@ static int bounceallocarraysize; static unsigned *bounceallocarray; static int bouncefree; +#if defined(PC98) && defined (EPSON_BOUNCEDMA) +#define SIXTEENMEG (3840*4096) /* 15MB boundary */ +#else #define SIXTEENMEG (4096*4096) +#endif #define MAXBKVA 1024 int maxbkva = MAXBKVA*PAGE_SIZE; @@ -748,7 +756,7 @@ cpu_reset() { * to do the reset here would then end up in no man's land. */ -#ifndef BROKEN_KEYBOARD_RESET +#if !defined(BROKEN_KEYBOARD_RESET) && !defined(PC98) outb(IO_KBD + 4, 0xFE); DELAY(500000); /* wait 0.5 sec to see if that did it */ printf("Keyboard reset did not work, attempting CPU shutdown\n"); @@ -761,6 +769,12 @@ cpu_reset() { /* "good night, sweet prince .... <THUNK!>" */ invltlb(); /* NOTREACHED */ +#ifdef PC98 + asm(" cli "); + outb(0x37, 0x0f); /* SHUT 0 = 0 */ + outb(0x37, 0x0b); /* SHUT 1 = 0 */ + outb(0xf0, 0x00); /* reset port */ +#endif while(1); } diff --git a/sys/i386/include/clock.h b/sys/i386/include/clock.h index f20902f..0f3427f 100644 --- a/sys/i386/include/clock.h +++ b/sys/i386/include/clock.h @@ -3,7 +3,7 @@ * Garrett Wollman, September 1994. * This file is in the public domain. * - * $Id: clock.h,v 1.19 1996/10/17 17:31:25 bde Exp $ + * $Id: clock.h,v 1.20 1996/10/25 13:01:08 bde Exp $ */ #ifndef _MACHINE_CLOCK_H_ @@ -65,7 +65,11 @@ int sysbeep __P((int pitch, int period)); #ifdef CLOCK_HAIR +#ifdef PC98 +#include <pc98/pc98/pc98.h> /* XXX */ +#else #include <i386/isa/isa.h> /* XXX */ +#endif #include <i386/isa/timerreg.h> /* XXX */ static __inline u_int diff --git a/sys/i386/isa/aic6360.c b/sys/i386/isa/aic6360.c index d9de4a6..46129e7 100644 --- a/sys/i386/isa/aic6360.c +++ b/sys/i386/isa/aic6360.c @@ -31,7 +31,7 @@ */ /* - * $Id: aic6360.c,v 1.22 1996/09/06 23:07:07 phk Exp $ + * $Id: aic6360.c,v 1.23 1996/10/15 19:22:04 bde Exp $ * * Acknowledgements: Many of the algorithms used in this driver are * inspired by the work of Julian Elischer (julian@tfs.com) and @@ -48,6 +48,10 @@ */ /* + * PC-9801-100/AHA-1030P support by URATA S. + */ + +/* * A few customizable items: */ @@ -183,6 +187,9 @@ #define ST_MASK 0x3e /* bit 0,6,7 is reserved */ /* AIC6360 definitions */ +#ifdef PC98 +#include <i386/isa/aic_98.h> +#else #define SCSISEQ (iobase + 0x00) /* SCSI sequence control */ #define SXFRCTL0 (iobase + 0x01) /* SCSI transfer control 0 */ #define SXFRCTL1 (iobase + 0x02) /* SCSI transfer control 1 */ @@ -222,6 +229,7 @@ #define STACK (iobase + 0x1d) /* Stack */ #define TEST (iobase + 0x1e) /* Test register */ #define ID (iobase + 0x1f) /* ID register */ +#endif #define IDSTRING "(C)1991ADAPTECAIC6360 " @@ -609,6 +617,9 @@ static struct aic_data { /* One of these per adapter */ u_char imess[AIC_MAX_MSG_LEN + 1]; u_char *imp; /* Message pointer (for multibyte messages) */ u_char imlen; +#ifdef PC98 + int *aicport; /* I/O port information */ +#endif } *aicdata[NAIC]; #define AIC_SHOWACBS 0x01 @@ -723,6 +734,15 @@ aicprobe(dev) bzero(aic, sizeof(struct aic_data)); aicdata[unit] = aic; aic->iobase = dev->id_iobase; +#ifdef PC98 + if (AIC_TYPE98(dev->id_flags) == AIC98_100) { + /* PC-9801-100 */ + aic->aicport = aicport_100; + } else { + /* generic card */ + aic->aicport = aicport_generic; + } +#endif if (aic_find(aic) != 0) { aicdata[unit] = NULL; @@ -730,6 +750,11 @@ aicprobe(dev) return 0; } aicunit++; + +#ifdef PC98 + if (AIC_TYPE98(dev->id_flags) == AIC98_100) + return 0x40; +#endif return 0x20; } diff --git a/sys/pc98/pc98/aic_98.h b/sys/i386/isa/aic_98.h index 8a31101..8a31101 100644 --- a/sys/pc98/pc98/aic_98.h +++ b/sys/i386/isa/aic_98.h diff --git a/sys/i386/isa/atapi.c b/sys/i386/isa/atapi.c index 8fde197..2445dcb 100644 --- a/sys/i386/isa/atapi.c +++ b/sys/i386/isa/atapi.c @@ -358,7 +358,12 @@ static struct atapi_params *atapi_probe (int port, int unit) { struct atapi_params *ap; char tb [DEV_BSIZE]; +#ifdef PC98 + int cnt; + outb(0x432,unit%2); + print(("unit = %d,select %d\n",unit,unit%2)); +#endif /* Wait for controller not busy. */ outb (port + AR_DRIVE, unit ? ARD_DRIVE1 : ARD_DRIVE0); if (atapi_wait (port, 0) < 0) { @@ -368,8 +373,20 @@ static struct atapi_params *atapi_probe (int port, int unit) } /* Issue ATAPI IDENTIFY command. */ +#ifdef PC98 + outb (port + AR_DRIVE, unit/2 ? ARD_DRIVE1 : ARD_DRIVE0); + + /* Wait for DRQ deassert. */ + for (cnt=2000; cnt>0; --cnt) + if (! (inb (0x640 + AR_STATUS) & ARS_DRQ)) + break; + + outb (port + AR_COMMAND, ATAPIC_IDENTIFY); + DELAY(500); +#else outb (port + AR_DRIVE, unit ? ARD_DRIVE1 : ARD_DRIVE0); outb (port + AR_COMMAND, ATAPIC_IDENTIFY); +#endif /* Check that device is present. */ if (inb (port + AR_STATUS) == 0xff) { @@ -550,7 +567,13 @@ int atapi_start_cmd (struct atapi *ata, struct atapicmd *ac) ac->result.error = 0; ac->result.status = 0; +#ifdef PC98 + outb(0x432,(ac->unit)%2); + print(("(ac->unit) = %d,select %d (2) \n",(ac->unit),(ac->unit)%2)); + outb (ata->port + AR_DRIVE, (ac->unit)/2 ? ARD_DRIVE1 : ARD_DRIVE0); +#else outb (ata->port + AR_DRIVE, ac->unit ? ARD_DRIVE1 : ARD_DRIVE0); +#endif if (atapi_wait (ata->port, 0) < 0) { printf ("atapi%d.%d: controller not ready for cmd\n", ata->ctrlr, ac->unit); @@ -632,6 +655,11 @@ int atapi_intr (int ctrlr) struct atapi *ata = atapitab + ctrlr; struct atapicmd *ac = ata->queue; +#ifdef PC98 + outb(0x432,(ac->unit)%2); + print(("atapi_intr:(ac->unit)= %d,select %d\n",ac->unit,(ac->unit)%2)); +#endif + if (! ac) { printf ("atapi%d: stray interrupt\n", ata->ctrlr); return (0); diff --git a/sys/i386/isa/atapi.h b/sys/i386/isa/atapi.h index d43241b..5ff3d34 100644 --- a/sys/i386/isa/atapi.h +++ b/sys/i386/isa/atapi.h @@ -17,6 +17,18 @@ /* * Disk Controller ATAPI register definitions. */ +#ifdef PC98 +#define AR_DATA 0x0 /* RW - data register (16 bits) */ +#define AR_ERROR 0x2 /* R - error register */ +#define AR_FEATURES 0x2 /* W - features */ +#define AR_IREASON 0x4 /* RW - interrupt reason */ +#define AR_TAG 0x6 /* - reserved for SAM TAG byte */ +#define AR_CNTLO 0x8 /* RW - byte count, low byte */ +#define AR_CNTHI 0xa /* RW - byte count, high byte */ +#define AR_DRIVE 0xc /* RW - drive select */ +#define AR_COMMAND 0xe /* W - command register */ +#define AR_STATUS 0xe /* R - immediate status */ +#else #define AR_DATA 0x0 /* RW - data register (16 bits) */ #define AR_ERROR 0x1 /* R - error register */ #define AR_FEATURES 0x1 /* W - features */ @@ -27,6 +39,7 @@ #define AR_DRIVE 0x6 /* RW - drive select */ #define AR_COMMAND 0x7 /* W - command register */ #define AR_STATUS 0x7 /* R - immediate status */ +#endif /* * Status register bits diff --git a/sys/i386/isa/icu.s b/sys/i386/isa/icu.s index 1107c13..567daf1 100644 --- a/sys/i386/isa/icu.s +++ b/sys/i386/isa/icu.s @@ -36,7 +36,7 @@ * * @(#)icu.s 7.2 (Berkeley) 5/21/91 * - * $Id: icu.s,v 1.24 1996/03/12 05:44:25 nate Exp $ + * $Id: icu.s,v 1.25 1996/05/31 01:08:07 peter Exp $ */ /* @@ -278,6 +278,7 @@ vec0: MEXITCOUNT jmp _Xintr0 /* XXX might need _Xfastintr0 */ +#ifndef PC98 ALIGN_TEXT vec8: popl %eax @@ -287,6 +288,7 @@ vec8: cli MEXITCOUNT jmp _Xintr8 /* XXX might need _Xfastintr8 */ +#endif #define BUILD_VEC(irq_num) \ ALIGN_TEXT ; \ @@ -301,6 +303,9 @@ __CONCAT(vec,irq_num): ; \ BUILD_VEC(5) BUILD_VEC(6) BUILD_VEC(7) +#ifdef PC98 + BUILD_VEC(8) +#endif BUILD_VEC(9) BUILD_VEC(10) BUILD_VEC(11) diff --git a/sys/i386/isa/kbdtables.h b/sys/i386/isa/kbdtables.h index 1c832cb..9f69ee4 100644 --- a/sys/i386/isa/kbdtables.h +++ b/sys/i386/isa/kbdtables.h @@ -25,11 +25,150 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: kbdtables.h,v 1.30 1995/12/10 13:38:53 phk Exp $ + * $Id: kbdtables.h,v 1.31 1996/01/25 16:37:20 ache Exp $ */ #define SET8 0x80 /* set eight bit on */ +#ifdef PC98 +/* PC-9801 keymap by kuribo@isl.melco.co.jp */ +static keymap_t key_map = { 0x80, /* PC98 keymap */ +/* alt + * scan cntrl alt alt cntrl + * code base shift cntrl shift alt shift cntrl shift spcl flgs + * --------------------------------------------------------------------------- + */ +/* sc=00 */ 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, DBG, 0x1B, 0x02, 0x00, +/* sc=01 */ '1', '!', '!', '!', '1', '!', '!', '!', 0x00, 0x00, +/* sc=02 */ '2', '\"', 0x1A, 0x1A, '2', '@', 0x00, 0x00, 0x00, 0x00, +/* sc=03 */ '3', '#', 0x1B, 0x1B, '3', '#', 0x1B, 0x1B, 0x00, 0x00, +/* sc=04 */ '4', '$', 0x1C, 0x1C, '4', '$', 0x1C, 0x1C, 0x00, 0x00, +/* sc=05 */ '5', '%', 0x1D, 0x1D, '5', '%', 0x1D, 0x1D, 0x00, 0x00, +/* sc=06 */ '6', '&', 0x1E, 0x1E, '6', '^', 0x1E, 0x1E, 0x00, 0x00, +/* sc=07 */ '7', '\'', 0x1F, 0x1F, '7', '&', '&', '&', 0x00, 0x00, +/* sc=08 */ '8', '(', 0x7F, 0x7F, '8', '*', 0x08, 0x08, 0x00, 0x00, +/* sc=09 */ '9', ')', '9', '9', '9', '(', '(', '(', 0x00, 0x00, +/* sc=0a */ '0', NOP, '0', '0', '0', ')', ')', ')', 0x40, 0x00, +/* sc=0b */ '-', '=', '-', '-', '-', '_', 0x1F, 0x1F, 0x00, 0x00, +/* sc=0c */ '^', '`', 0x1E, 0x1E, '=', '+', '+', '+', 0x00, 0x00, +/* sc=0d */ '\\', '|', 0x1C, 0x1C, '\\', '|', 0x1C, 0x1C, 0x00, 0x00, +/* sc=0e */ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, +/* sc=0f */ '\t', '\t', '\t', '\t', '\t', '\t', '\t', '\t', 0x00, 0x00, +/* sc=10 */ 'q', 'Q', 0x11, 0x11, 'q', 'Q', 0x11, 0x11, 0x00, 0x01, +/* sc=11 */ 'w', 'W', 0x17, 0x17, 'w', 'W', 0x17, 0x17, 0x00, 0x01, +/* sc=12 */ 'e', 'E', 0x05, 0x05, 'e', 'E', 0x05, 0x05, 0x00, 0x01, +/* sc=13 */ 'r', 'R', 0x12, 0x12, 'r', 'R', 0x12, 0x12, 0x00, 0x01, +/* sc=14 */ 't', 'T', 0x14, 0x14, 't', 'T', 0x14, 0x14, 0x00, 0x01, +/* sc=15 */ 'y', 'Y', 0x19, 0x19, 'y', 'Y', 0x19, 0x19, 0x00, 0x01, +/* sc=16 */ 'u', 'U', 0x15, 0x15, 'u', 'U', 0x15, 0x15, 0x00, 0x01, +/* sc=17 */ 'i', 'I', 0x09, 0x09, 'i', 'I', 0x09, 0x09, 0x00, 0x01, +/* sc=18 */ 'o', 'O', 0x0F, 0x0F, 'o', 'O', 0x0F, 0x0F, 0x00, 0x01, +/* sc=19 */ 'p', 'P', 0x10, 0x10, 'p', 'P', 0x10, 0x10, 0x00, 0x01, +/* sc=1a */ '@', '~', 0x00, 0x00, '[', '{', 0x1B, 0x1B, 0x00, 0x00, +/* sc=1b */ '[', '{', 0x1B, 0x1B, ']', '}', 0x1D, 0x1D, 0x00, 0x00, +/* sc=1c */ '\r', '\r', '\n', '\n', '\r', '\r', '\n', '\n', 0x00, 0x00, +/* sc=1d */ 'a', 'A', 0x01, 0x01, 'a', 'A', 0x01, 0x01, 0x00, 0x01, +/* sc=1e */ 's', 'S', 0x13, 0x13, 's', 'S', 0x13, 0x13, 0x00, 0x01, +/* sc=1f */ 'd', 'D', 0x04, 0x04, 'd', 'D', 0x04, 0x04, 0x00, 0x01, +/* sc=20 */ 'f', 'F', 0x06, 0x06, 'f', 'F', 0x06, 0x06, 0x00, 0x01, +/* sc=21 */ 'g', 'G', 0x07, 0x07, 'g', 'G', 0x07, 0x07, 0x00, 0x01, +/* sc=22 */ 'h', 'H', 0x08, 0x08, 'h', 'H', 0x08, 0x08, 0x00, 0x01, +/* sc=23 */ 'j', 'J', '\n', '\n', 'j', 'J', '\n', '\n', 0x00, 0x01, +/* sc=24 */ 'k', 'K', 0x0B, 0x0B, 'k', 'K', 0x0B, 0x0B, 0x00, 0x01, +/* sc=25 */ 'l', 'L', 0x0C, 0x0C, 'l', 'L', 0x0C, 0x0C, 0x00, 0x01, +/* sc=26 */ ';', '+', ';', ';', ';', ':', ';', ';', 0x00, 0x00, +/* sc=27 */ ':', '*', ':', ':', '\'', '\"', '\'', '\'', 0x00, 0x00, +/* sc=28 */ ']', '}', 0x1D, 0x1D, '`', '~', '~', '~', 0x00, 0x00, +/* sc=29 */ 'z', 'Z', 0x1A, 0x1A, 'z', 'Z', 0x1A, 0x1A, 0x00, 0x01, +/* sc=2a */ 'x', 'X', 0x18, 0x18, 'x', 'X', 0x18, 0x18, 0x00, 0x01, +/* sc=2b */ 'c', 'C', 0x03, 0x03, 'c', 'C', 0x03, 0x03, 0x00, 0x01, +/* sc=2c */ 'v', 'V', 0x16, 0x16, 'v', 'V', 0x16, 0x16, 0x00, 0x01, +/* sc=2d */ 'b', 'B', 0x02, 0x02, 'b', 'B', 0x02, 0x02, 0x00, 0x01, +/* sc=2e */ 'n', 'N', 0x0E, 0x0E, 'n', 'N', 0x0E, 0x0E, 0x00, 0x01, +/* sc=2f */ 'm', 'M', '\r', '\r', 'm', 'M', '\r', '\r', 0x00, 0x01, +/* sc=30 */ ',', '<', '<', '<', ',', '<', '<', '<', 0x00, 0x00, +/* sc=31 */ '.', '>', '>', '>', '.', '>', '>', '>', 0x00, 0x00, +/* sc=32 */ '/', '?', 0x7F, 0x7F, '/', '?', 0x7F, 0x7F, 0x00, 0x00, +/* sc=33 */ NOP, '_', 0x1F, 0x1F, '\\', '|', 0x1C, 0x1C, 0x80, 0x00, +/* sc=34 */ ' ', ' ', 0x00, 0x00, ' ', ' ', 0x00, 0x00, 0x00, 0x00, +/* sc=35 */ 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x00, 0x00, +/* sc=36 */ F(51), F(51), F(51), F(51), F(51), F(51), F(51), F(51), 0xFF, 0x00, +/* sc=37 */ F(59), F(59), F(59), F(59), F(59), F(59), F(59), F(59), 0xFF, 0x00, +/* sc=38 */ F(60), F(60), F(60), F(60), F(60), F(60), F(60), F(60), 0xFF, 0x00, +/* sc=39 */ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, RBT, RBT, 0x03, 0x02, +/* sc=3a */ F(50), F(50), F(50), F(50), F(50), F(50), F(50), F(50), 0xFF, 0x00, +/* sc=3b */ F(53), F(53), F(53), F(53), F(53), F(53), F(53), F(53), 0xFF, 0x00, +/* sc=3c */ F(55), F(55), F(55), F(55), F(55), F(55), F(55), F(55), 0xFF, 0x00, +/* sc=3d */ F(58), F(58), F(58), F(58), F(58), F(58), F(58), F(58), 0xFF, 0x00, +/* sc=3e */ F(49), F(49), F(49), F(49), F(49), F(49), F(49), F(49), 0xFF, 0x00, +/* sc=3f */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=40 */ '-', '-', '-', '-', '-', '-', '-', '-', 0x00, 0x00, +/* sc=41 */ '/', '/', '/', '/', '/', '/', '/', '/', 0x00, 0x00, +/* sc=42 */ '7', '7', '7', '7', '7', '7', '7', '7', 0x00, 0x00, +/* sc=43 */ '8', '8', '8', '8', '8', '8', '8', '8', 0x00, 0x00, +/* sc=44 */ '9', '9', '9', '9', '9', '9', '9', '9', 0x00, 0x00, +/* sc=45 */ '*', '*', '*', '*', '*', '*', '*', '*', 0x00, 0x00, +/* sc=46 */ '4', '4', '4', '4', '4', '4', '4', '4', 0x00, 0x00, +/* sc=47 */ '5', '5', '5', '5', '5', '5', '5', '5', 0x00, 0x00, +/* sc=48 */ '6', '6', '6', '6', '6', '6', '6', '6', 0x00, 0x00, +/* sc=49 */ '+', '+', '+', '+', '+', '+', '+', '+', 0x00, 0x00, +/* sc=4a */ '1', '1', '1', '1', '1', '1', '1', '1', 0x00, 0x00, +/* sc=4b */ '2', '2', '2', '2', '2', '2', '2', '2', 0x00, 0x00, +/* sc=4c */ '3', '3', '3', '3', '3', '3', '3', '3', 0x00, 0x00, +/* sc=4d */ '=', '=', '=', '=', '=', '=', '=', '=', 0x00, 0x00, +/* sc=4e */ '0', '0', '0', '0', '0', '0', '0', '0', 0x00, 0x00, +/* sc=4f */ ',', ',', ',', ',', ',', ',', ',', ',', 0x00, 0x00, +/* sc=50 */ '.', '.', '.', '.', '.', '.', '.', '.', 0x00, 0x00, +/* sc=51 */ 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x00, 0x00, +/* sc=52 */ F(11), F(23), F(35), F(47), S(11), S(11), S(11), S(11), 0xFF, 0x00, +/* sc=53 */ F(12), F(24), F(36), F(48), S(12), S(12), S(12), S(12), 0xFF, 0x00, +/* sc=54 */ SLK, SLK, SLK, SLK, SLK, SLK, SLK, SLK, 0xFF, 0x00, +/* sc=55 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=56 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=57 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=58 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=59 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=5a */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=5b */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=5c */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=5d */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=5e */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=5f */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=60 */ F(57), F(57), F(57), F(57), F(57), F(57), F(57), F(57), 0xFF, 0x00, +/* sc=61 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=62 */ F( 1), F(13), F(25), F(37), S( 1), S( 1), S( 1), S( 1), 0xFF, 0x00, +/* sc=63 */ F( 2), F(14), F(26), F(38), S( 2), S( 2), S( 2), S( 2), 0xFF, 0x00, +/* sc=64 */ F( 3), F(15), F(27), F(39), S( 3), S( 3), S( 3), S( 3), 0xFF, 0x00, +/* sc=65 */ F( 4), F(16), F(28), F(40), S( 4), S( 4), S( 4), S( 4), 0xFF, 0x00, +/* sc=66 */ F( 5), F(17), F(29), F(41), S( 5), S( 5), S( 5), S( 5), 0xFF, 0x00, +/* sc=67 */ F( 6), F(18), F(30), F(42), S( 6), S( 6), S( 6), S( 6), 0xFF, 0x00, +/* sc=68 */ F( 7), F(19), F(31), F(43), S( 7), S( 7), S( 7), S( 7), 0xFF, 0x00, +/* sc=69 */ F( 8), F(20), F(32), F(44), S( 8), S( 8), S( 8), S( 8), 0xFF, 0x00, +/* sc=6a */ F( 9), F(21), F(33), F(45), S( 9), S( 9), S( 9), S( 9), 0xFF, 0x00, +/* sc=6b */ F(10), F(22), F(34), F(46), S(10), S(10), S(10), S(10), 0xFF, 0x00, +/* sc=6c */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=6d */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=6e */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=6f */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=70 */ LSH, LSH, LSH, LSH, LSH, LSH, LSH, LSH, 0xFF, 0x00, +/* sc=71 */ CLK, CLK, CLK, CLK, CLK, CLK, CLK, CLK, 0xFF, 0x00, +/* sc=72 */ LALT, LALT, LALT, LALT, LALT, LALT, LALT, LALT, 0xFF, 0x00, +/* sc=73 */ LALT, LALT, LALT, LALT, LALT, LALT, LALT, LALT, 0xFF, 0x00, +/* sc=74 */ LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, 0xFF, 0x00, +/* sc=75 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=76 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=77 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=78 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=79 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=7a */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=7b */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=7c */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=7d */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=7e */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=7f */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +}; +#endif + #ifdef DKKEYMAP static keymap_t key_map = { 0x6C, /* DK iso8859 keymap */ /* alt @@ -750,7 +889,7 @@ static keymap_t key_map = { 0xEC, /* keys number */ #endif -#if !defined(DKKEYMAP) && !defined(UKKEYMAP) && !defined(GRKEYMAP) && !defined(SWKEYMAP) && !defined(RUKEYMAP) +#if !defined(DKKEYMAP) && !defined(UKKEYMAP) && !defined(GRKEYMAP) && !defined(SWKEYMAP) && !defined(RUKEYMAP) && !defined(PC98) static keymap_t key_map = { 0x6C, /* US iso8859 keymap */ /* alt * scan cntrl alt alt cntrl diff --git a/sys/i386/isa/matcd/creative.h b/sys/i386/isa/matcd/creative.h index 0877a78..72a12ad 100644 --- a/sys/i386/isa/matcd/creative.h +++ b/sys/i386/isa/matcd/creative.h @@ -98,13 +98,20 @@ See matcd.c for Edit History #define CMD 0 /*Write - commands*/ #define DATA 0 /*Read - data/status from drive*/ +#ifdef PC98 +#define PHASE 0x100 /*Write - switch between data/status*/ +#define STATUS 0x100 /*Read - bus status */ +#define RESET 0x200 /*Write - reset all attached drives*/ +#define ALTDATA 0x200 /*<20>Read - data on non Creative bds.*/ +#define SELECT 0x300 /*Write - drive select*/ +#else /* !PC98 */ #define PHASE 1 /*Write - switch between data/status*/ #define STATUS 1 /*Read - bus status*/ #define RESET 2 /*Write - reset all attached drives*/ /*Any value written will reset*/ #define ALTDATA 2 /*<20>Read - data on non Creative bds.*/ #define SELECT 3 /*Write - drive select*/ - +#endif /*PC98*/ /* Creative PHASE port bit assignments */ diff --git a/sys/i386/isa/matcd/options.h b/sys/i386/isa/matcd/options.h index af0db68..3fde880 100644 --- a/sys/i386/isa/matcd/options.h +++ b/sys/i386/isa/matcd/options.h @@ -184,6 +184,16 @@ #ifdef AUTOHUNT static int port_hints[]={ +#ifdef PC98 + 0x30d2, + 0x30d0, + 0x30d4, + 0x30d6, + 0x30d8, + 0x30da, + 0x30dc, + 0x30de, +#else /* IBM-PC */ 0x230, /*SB Pro & SB16*/ 0x240, /*SB Pro & SB16*/ 0x250, /*Creative omniCD standalone boards*/ @@ -205,6 +215,7 @@ static int port_hints[]={ 0x670, /*IBM*/ 0x690, /*IBM*/ #endif /*0*/ +#endif /* PC98 */ -1}; /*use. Table MUST end with -1*/ #endif /*AUTOHUNT*/ diff --git a/sys/i386/isa/pcibus.c b/sys/i386/isa/pcibus.c index 4232069..903214c 100644 --- a/sys/i386/isa/pcibus.c +++ b/sys/i386/isa/pcibus.c @@ -1,6 +1,6 @@ /************************************************************************** ** -** $Id: pcibus.c,v 1.25 1996/06/13 21:50:41 se Exp $ +** $Id: pcibus.c,v 1.26 1996/06/18 01:22:28 bde Exp $ ** ** pci bus subroutines for i386 architecture. ** @@ -151,7 +151,11 @@ DATA_SET (pcibus_set, i386pci); #define CONF1_ENABLE_RES1 0x80000000ul #define CONF2_ENABLE_PORT 0x0cf8 +#ifdef PC98 +#define CONF2_FORWARD_PORT 0x0cf9 +#else #define CONF2_FORWARD_PORT 0x0cfa +#endif #define CONF2_ENABLE_CHK 0x0e #define CONF2_ENABLE_RES 0x0e diff --git a/sys/i386/isa/prof_machdep.c b/sys/i386/isa/prof_machdep.c index 62c8df5..a8603cb 100644 --- a/sys/i386/isa/prof_machdep.c +++ b/sys/i386/isa/prof_machdep.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: prof_machdep.c,v 1.2 1996/04/08 16:41:06 wollman Exp $ + * $Id: prof_machdep.c,v 1.3 1996/10/17 19:32:10 bde Exp $ */ #ifdef GUPROF @@ -40,7 +40,11 @@ #include <machine/profile.h> #endif +#ifdef PC98 +#include <pc98/pc98/pc98.h> +#else #include <i386/isa/isa.h> +#endif #include <i386/isa/timerreg.h> #ifdef GUPROF diff --git a/sys/i386/isa/random_machdep.c b/sys/i386/isa/random_machdep.c index 227b707..7a13baf 100644 --- a/sys/i386/isa/random_machdep.c +++ b/sys/i386/isa/random_machdep.c @@ -1,7 +1,7 @@ /* * random_machdep.c -- A strong random number generator * - * $Id: random_machdep.c,v 1.11 1996/09/27 13:25:13 peter Exp $ + * $Id: random_machdep.c,v 1.12 1996/10/09 19:47:32 bde Exp $ * * Version 0.95, last modified 18-Oct-95 * @@ -51,7 +51,11 @@ #include <machine/random.h> #include <i386/isa/icu.h> +#ifdef PC98 +#include <pc98/pc98/pc98.h> +#else #include <i386/isa/isa.h> +#endif #include <i386/isa/timerreg.h> #define MAX_BLKDEV 4 diff --git a/sys/i386/isa/sound/dev_table.h b/sys/i386/isa/sound/dev_table.h index 402538c..5269f63 100644 --- a/sys/i386/isa/sound/dev_table.h +++ b/sys/i386/isa/sound/dev_table.h @@ -302,6 +302,11 @@ struct sound_timer_operations { {SNDCARD_TRXPRO_SB, "AudioTriX (SB mode)", attach_trix_sb, probe_trix_sb}, {SNDCARD_TRXPRO_MPU, "AudioTriX MIDI", attach_trix_mpu, probe_trix_mpu}, #endif +#ifdef PC98 +#ifndef EXCLUDE_PCM86 + {SNDCARD_PCM86, "PC-9801-86/73", attach_pcm86, probe_pcm86}, +#endif +#endif {0, "*?*", NULL, NULL} }; @@ -384,6 +389,11 @@ struct sound_timer_operations { #ifndef EXCLUDE_YM3812 {SNDCARD_ADLIB, {FM_MONO, 0, 0}, SND_DEFAULT_ENABLE}, #endif +#ifdef PC98 +#ifndef EXCLUDE_PCM86 + {SNDCARD_PCM86, {0, 0, 0}, SND_DEFAULT_ENABLE}, +#endif +#endif {0, {0}, 0} }; diff --git a/sys/i386/isa/sound/local.h b/sys/i386/isa/sound/local.h index e80b780..c243e4b 100644 --- a/sys/i386/isa/sound/local.h +++ b/sys/i386/isa/sound/local.h @@ -92,6 +92,14 @@ #define EXCLUDE_UART6850 #endif +#ifdef PC98 +#include "pcm.h" +#if NPCM == 0 && !defined(EXCLUDE_PCM86) +#define EXCLUDE_PCM86 +#endif +#endif + + /* nothing but a sequencer (Adlib/OPL) ? */ #if NGUS == 0 && NSB == 0 && NSBMIDI == 0 && NPAS == 0 && NMPU == 0 && \ NUART == 0 && NMSS == 0 @@ -99,9 +107,11 @@ #define EXCLUDE_MIDI #endif #ifndef EXCLUDE_AUDIO +#if !defined(PC98) || defined(EXCLUDE_PCM86) && defined(EXCLUDE_MSS) #define EXCLUDE_AUDIO #endif #endif +#endif /* nothing but a Midi (MPU/UART) ? */ #if NGUS == 0 && NSB == 0 && NSBMIDI == 0 && NPAS == 0 && NOPL == 0 && \ @@ -111,6 +121,8 @@ #define EXCLUDE_SEQUENCER #endif #ifndef EXCLUDE_AUDIO +#if !defined(PC98) || defined(EXCLUDE_PCM86) && defined(EXCLUDE_MSS) #define EXCLUDE_AUDIO #endif #endif +#endif diff --git a/sys/i386/isa/sound/sound_calls.h b/sys/i386/isa/sound/sound_calls.h index bfe2f44..d52da0b 100644 --- a/sys/i386/isa/sound/sound_calls.h +++ b/sys/i386/isa/sound/sound_calls.h @@ -249,6 +249,12 @@ int pss_ioctl (int dev, struct fileinfo *file, int pss_lseek (int dev, struct fileinfo *file, off_t offset, int orig); long pss_init(long mem_start); +#ifdef PC98 +/* From pcm86.c */ +int probe_pcm86(struct address_info *hw_config); +long attach_pcm86(long mem_start, struct address_info *hw_config); +#endif PC98 + /* From aedsp16.c */ int InitAEDSP16_SBPRO(struct address_info *hw_config); int InitAEDSP16_MSS(struct address_info *hw_config); diff --git a/sys/i386/isa/sound/sound_config.h b/sys/i386/isa/sound/sound_config.h index daafcbe..2330fa9 100644 --- a/sys/i386/isa/sound/sound_config.h +++ b/sys/i386/isa/sound/sound_config.h @@ -79,24 +79,44 @@ If your card has nonstandard I/O address or IRQ number, change defines for the following settings in your kernel Makefile */ #ifndef SBC_BASE +#ifdef PC98 +#define SBC_BASE 0x20d2 /* 0x20d2 is the factory default. */ +#else #define SBC_BASE 0x220 /* 0x220 is the factory default. */ #endif +#endif #ifndef SBC_IRQ +#ifdef PC98 +#define SBC_IRQ 10 /* IQR10 is not the factory default on PC9821. */ +#else #define SBC_IRQ 7 /* IQR7 is the factory default. */ #endif +#endif #ifndef SBC_DMA +#ifdef PC98 +#define SBC_DMA 3 +#else #define SBC_DMA 1 #endif +#endif #ifndef SB16_DMA +#ifdef PC98 +#define SB16_DMA 3 +#else #define SB16_DMA 6 #endif +#endif #ifndef SB16MIDI_BASE +#ifdef PC98 +#define SB16MIDI_BASE 0x80d2 +#else #define SB16MIDI_BASE 0x300 #endif +#endif #ifndef PAS_BASE #define PAS_BASE 0x388 @@ -248,7 +268,11 @@ If your card has nonstandard I/O address or IRQ number, change defines #define DMA_AUTOINIT 0x10 +#ifdef PC98 +#define FM_MONO 0x28d2 /* This is the I/O address used by AdLib */ +#else #define FM_MONO 0x388 /* This is the I/O address used by AdLib */ +#endif /* SEQ_MAX_QUEUE is the maximum number of sequencer events buffered by the driver. (There is no need to alter this) */ diff --git a/sys/i386/isa/timerreg.h b/sys/i386/isa/timerreg.h index 5742f66..16fbc0b 100644 --- a/sys/i386/isa/timerreg.h +++ b/sys/i386/isa/timerreg.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: Header: timerreg.h,v 1.2 93/02/28 15:08:58 mccanne Exp - * $Id$ + * $Id: timerreg.h,v 1.2 1993/10/16 13:46:26 rgrimes Exp $ */ /* @@ -59,6 +59,7 @@ * in undefined behavior (but hopefully not fry the chip). * Reading in this manner has no side effects. * + * [IBM-PC] * The outputs of the three timers are connected as follows: * * timer 0 -> irq 0 @@ -67,15 +68,31 @@ * * Timer 0 is used to call hardclock. * Timer 2 is used to generate console beeps. + * + * [PC-9801] + * The outputs of the three timers are connected as follows: + * + * timer 0 -> irq 0 + * timer 1 -> speaker (via keyboard controller) + * timer 2 -> RS232C + * + * Timer 0 is used to call hardclock. + * Timer 1 is used to generate console beeps. */ /* * Macros for specifying values to be written into a mode register. */ #define TIMER_CNTR0 (IO_TIMER1 + 0) /* timer 0 counter port */ +#ifdef PC98 +#define TIMER_CNTR1 0x3fdb /* timer 1 counter port */ +#define TIMER_CNTR2 (IO_TIMER1 + 4) /* timer 2 counter port */ +#define TIMER_MODE (IO_TIMER1 + 6) /* timer mode port */ +#else #define TIMER_CNTR1 (IO_TIMER1 + 1) /* timer 1 counter port */ #define TIMER_CNTR2 (IO_TIMER1 + 2) /* timer 2 counter port */ #define TIMER_MODE (IO_TIMER1 + 3) /* timer mode port */ +#endif #define TIMER_SEL0 0x00 /* select counter 0 */ #define TIMER_SEL1 0x40 /* select counter 1 */ #define TIMER_SEL2 0x80 /* select counter 2 */ diff --git a/sys/i386/isa/vector.s b/sys/i386/isa/vector.s index 94691f5..0283c2a 100644 --- a/sys/i386/isa/vector.s +++ b/sys/i386/isa/vector.s @@ -1,12 +1,26 @@ /* * from: vector.s, 386BSD 0.1 unknown origin - * $Id: vector.s,v 1.19 1996/04/11 21:18:47 bde Exp $ + * $Id: vector.s,v 1.20 1996/05/31 01:08:08 peter Exp $ + */ + +/* + * modified for PC98 by Kakefuda */ #include "opt_auto_eoi.h" #include <i386/isa/icu.h> +#ifdef PC98 +#include <pc98/pc98/pc98.h> +#else #include <i386/isa/isa.h> +#endif + +#ifdef PC98 +#define ICU_IMR_OFFSET 2 /* IO_ICU{1,2} + 2 */ +#else +#define ICU_IMR_OFFSET 1 /* IO_ICU{1,2} + 1 */ +#endif #define ICU_EOI 0x20 /* XXX - define elsewhere */ @@ -168,7 +182,7 @@ IDTVEC(vec_name) ; \ movb _imen + IRQ_BYTE(irq_num),%al ; \ orb $IRQ_BIT(irq_num),%al ; \ movb %al,_imen + IRQ_BYTE(irq_num) ; \ - outb %al,$icu+1 ; \ + outb %al,$icu+ICU_IMR_OFFSET ; \ enable_icus ; \ incl _cnt+V_INTR ; /* tally interrupts */ \ movl _cpl,%eax ; \ @@ -190,7 +204,7 @@ __CONCAT(Xresume,irq_num): ; \ movb _imen + IRQ_BYTE(irq_num),%al ; \ andb $~IRQ_BIT(irq_num),%al ; \ movb %al,_imen + IRQ_BYTE(irq_num) ; \ - outb %al,$icu+1 ; \ + outb %al,$icu+ICU_IMR_OFFSET ; \ sti ; /* XXX _doreti repeats the cli/sti */ \ MEXITCOUNT ; \ /* We could usually avoid the following jmp by inlining some of */ \ diff --git a/sys/i386/pci/pci_bus.c b/sys/i386/pci/pci_bus.c index 4232069..903214c 100644 --- a/sys/i386/pci/pci_bus.c +++ b/sys/i386/pci/pci_bus.c @@ -1,6 +1,6 @@ /************************************************************************** ** -** $Id: pcibus.c,v 1.25 1996/06/13 21:50:41 se Exp $ +** $Id: pcibus.c,v 1.26 1996/06/18 01:22:28 bde Exp $ ** ** pci bus subroutines for i386 architecture. ** @@ -151,7 +151,11 @@ DATA_SET (pcibus_set, i386pci); #define CONF1_ENABLE_RES1 0x80000000ul #define CONF2_ENABLE_PORT 0x0cf8 +#ifdef PC98 +#define CONF2_FORWARD_PORT 0x0cf9 +#else #define CONF2_FORWARD_PORT 0x0cfa +#endif #define CONF2_ENABLE_CHK 0x0e #define CONF2_ENABLE_RES 0x0e diff --git a/sys/i386/pci/pci_cfgreg.c b/sys/i386/pci/pci_cfgreg.c index 4232069..903214c 100644 --- a/sys/i386/pci/pci_cfgreg.c +++ b/sys/i386/pci/pci_cfgreg.c @@ -1,6 +1,6 @@ /************************************************************************** ** -** $Id: pcibus.c,v 1.25 1996/06/13 21:50:41 se Exp $ +** $Id: pcibus.c,v 1.26 1996/06/18 01:22:28 bde Exp $ ** ** pci bus subroutines for i386 architecture. ** @@ -151,7 +151,11 @@ DATA_SET (pcibus_set, i386pci); #define CONF1_ENABLE_RES1 0x80000000ul #define CONF2_ENABLE_PORT 0x0cf8 +#ifdef PC98 +#define CONF2_FORWARD_PORT 0x0cf9 +#else #define CONF2_FORWARD_PORT 0x0cfa +#endif #define CONF2_ENABLE_CHK 0x0e #define CONF2_ENABLE_RES 0x0e diff --git a/sys/i386/pci/pci_pir.c b/sys/i386/pci/pci_pir.c index 4232069..903214c 100644 --- a/sys/i386/pci/pci_pir.c +++ b/sys/i386/pci/pci_pir.c @@ -1,6 +1,6 @@ /************************************************************************** ** -** $Id: pcibus.c,v 1.25 1996/06/13 21:50:41 se Exp $ +** $Id: pcibus.c,v 1.26 1996/06/18 01:22:28 bde Exp $ ** ** pci bus subroutines for i386 architecture. ** @@ -151,7 +151,11 @@ DATA_SET (pcibus_set, i386pci); #define CONF1_ENABLE_RES1 0x80000000ul #define CONF2_ENABLE_PORT 0x0cf8 +#ifdef PC98 +#define CONF2_FORWARD_PORT 0x0cf9 +#else #define CONF2_FORWARD_PORT 0x0cfa +#endif #define CONF2_ENABLE_CHK 0x0e #define CONF2_ENABLE_RES 0x0e diff --git a/sys/isa/kbdtables.h b/sys/isa/kbdtables.h index 1c832cb..9f69ee4 100644 --- a/sys/isa/kbdtables.h +++ b/sys/isa/kbdtables.h @@ -25,11 +25,150 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: kbdtables.h,v 1.30 1995/12/10 13:38:53 phk Exp $ + * $Id: kbdtables.h,v 1.31 1996/01/25 16:37:20 ache Exp $ */ #define SET8 0x80 /* set eight bit on */ +#ifdef PC98 +/* PC-9801 keymap by kuribo@isl.melco.co.jp */ +static keymap_t key_map = { 0x80, /* PC98 keymap */ +/* alt + * scan cntrl alt alt cntrl + * code base shift cntrl shift alt shift cntrl shift spcl flgs + * --------------------------------------------------------------------------- + */ +/* sc=00 */ 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, DBG, 0x1B, 0x02, 0x00, +/* sc=01 */ '1', '!', '!', '!', '1', '!', '!', '!', 0x00, 0x00, +/* sc=02 */ '2', '\"', 0x1A, 0x1A, '2', '@', 0x00, 0x00, 0x00, 0x00, +/* sc=03 */ '3', '#', 0x1B, 0x1B, '3', '#', 0x1B, 0x1B, 0x00, 0x00, +/* sc=04 */ '4', '$', 0x1C, 0x1C, '4', '$', 0x1C, 0x1C, 0x00, 0x00, +/* sc=05 */ '5', '%', 0x1D, 0x1D, '5', '%', 0x1D, 0x1D, 0x00, 0x00, +/* sc=06 */ '6', '&', 0x1E, 0x1E, '6', '^', 0x1E, 0x1E, 0x00, 0x00, +/* sc=07 */ '7', '\'', 0x1F, 0x1F, '7', '&', '&', '&', 0x00, 0x00, +/* sc=08 */ '8', '(', 0x7F, 0x7F, '8', '*', 0x08, 0x08, 0x00, 0x00, +/* sc=09 */ '9', ')', '9', '9', '9', '(', '(', '(', 0x00, 0x00, +/* sc=0a */ '0', NOP, '0', '0', '0', ')', ')', ')', 0x40, 0x00, +/* sc=0b */ '-', '=', '-', '-', '-', '_', 0x1F, 0x1F, 0x00, 0x00, +/* sc=0c */ '^', '`', 0x1E, 0x1E, '=', '+', '+', '+', 0x00, 0x00, +/* sc=0d */ '\\', '|', 0x1C, 0x1C, '\\', '|', 0x1C, 0x1C, 0x00, 0x00, +/* sc=0e */ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, +/* sc=0f */ '\t', '\t', '\t', '\t', '\t', '\t', '\t', '\t', 0x00, 0x00, +/* sc=10 */ 'q', 'Q', 0x11, 0x11, 'q', 'Q', 0x11, 0x11, 0x00, 0x01, +/* sc=11 */ 'w', 'W', 0x17, 0x17, 'w', 'W', 0x17, 0x17, 0x00, 0x01, +/* sc=12 */ 'e', 'E', 0x05, 0x05, 'e', 'E', 0x05, 0x05, 0x00, 0x01, +/* sc=13 */ 'r', 'R', 0x12, 0x12, 'r', 'R', 0x12, 0x12, 0x00, 0x01, +/* sc=14 */ 't', 'T', 0x14, 0x14, 't', 'T', 0x14, 0x14, 0x00, 0x01, +/* sc=15 */ 'y', 'Y', 0x19, 0x19, 'y', 'Y', 0x19, 0x19, 0x00, 0x01, +/* sc=16 */ 'u', 'U', 0x15, 0x15, 'u', 'U', 0x15, 0x15, 0x00, 0x01, +/* sc=17 */ 'i', 'I', 0x09, 0x09, 'i', 'I', 0x09, 0x09, 0x00, 0x01, +/* sc=18 */ 'o', 'O', 0x0F, 0x0F, 'o', 'O', 0x0F, 0x0F, 0x00, 0x01, +/* sc=19 */ 'p', 'P', 0x10, 0x10, 'p', 'P', 0x10, 0x10, 0x00, 0x01, +/* sc=1a */ '@', '~', 0x00, 0x00, '[', '{', 0x1B, 0x1B, 0x00, 0x00, +/* sc=1b */ '[', '{', 0x1B, 0x1B, ']', '}', 0x1D, 0x1D, 0x00, 0x00, +/* sc=1c */ '\r', '\r', '\n', '\n', '\r', '\r', '\n', '\n', 0x00, 0x00, +/* sc=1d */ 'a', 'A', 0x01, 0x01, 'a', 'A', 0x01, 0x01, 0x00, 0x01, +/* sc=1e */ 's', 'S', 0x13, 0x13, 's', 'S', 0x13, 0x13, 0x00, 0x01, +/* sc=1f */ 'd', 'D', 0x04, 0x04, 'd', 'D', 0x04, 0x04, 0x00, 0x01, +/* sc=20 */ 'f', 'F', 0x06, 0x06, 'f', 'F', 0x06, 0x06, 0x00, 0x01, +/* sc=21 */ 'g', 'G', 0x07, 0x07, 'g', 'G', 0x07, 0x07, 0x00, 0x01, +/* sc=22 */ 'h', 'H', 0x08, 0x08, 'h', 'H', 0x08, 0x08, 0x00, 0x01, +/* sc=23 */ 'j', 'J', '\n', '\n', 'j', 'J', '\n', '\n', 0x00, 0x01, +/* sc=24 */ 'k', 'K', 0x0B, 0x0B, 'k', 'K', 0x0B, 0x0B, 0x00, 0x01, +/* sc=25 */ 'l', 'L', 0x0C, 0x0C, 'l', 'L', 0x0C, 0x0C, 0x00, 0x01, +/* sc=26 */ ';', '+', ';', ';', ';', ':', ';', ';', 0x00, 0x00, +/* sc=27 */ ':', '*', ':', ':', '\'', '\"', '\'', '\'', 0x00, 0x00, +/* sc=28 */ ']', '}', 0x1D, 0x1D, '`', '~', '~', '~', 0x00, 0x00, +/* sc=29 */ 'z', 'Z', 0x1A, 0x1A, 'z', 'Z', 0x1A, 0x1A, 0x00, 0x01, +/* sc=2a */ 'x', 'X', 0x18, 0x18, 'x', 'X', 0x18, 0x18, 0x00, 0x01, +/* sc=2b */ 'c', 'C', 0x03, 0x03, 'c', 'C', 0x03, 0x03, 0x00, 0x01, +/* sc=2c */ 'v', 'V', 0x16, 0x16, 'v', 'V', 0x16, 0x16, 0x00, 0x01, +/* sc=2d */ 'b', 'B', 0x02, 0x02, 'b', 'B', 0x02, 0x02, 0x00, 0x01, +/* sc=2e */ 'n', 'N', 0x0E, 0x0E, 'n', 'N', 0x0E, 0x0E, 0x00, 0x01, +/* sc=2f */ 'm', 'M', '\r', '\r', 'm', 'M', '\r', '\r', 0x00, 0x01, +/* sc=30 */ ',', '<', '<', '<', ',', '<', '<', '<', 0x00, 0x00, +/* sc=31 */ '.', '>', '>', '>', '.', '>', '>', '>', 0x00, 0x00, +/* sc=32 */ '/', '?', 0x7F, 0x7F, '/', '?', 0x7F, 0x7F, 0x00, 0x00, +/* sc=33 */ NOP, '_', 0x1F, 0x1F, '\\', '|', 0x1C, 0x1C, 0x80, 0x00, +/* sc=34 */ ' ', ' ', 0x00, 0x00, ' ', ' ', 0x00, 0x00, 0x00, 0x00, +/* sc=35 */ 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x00, 0x00, +/* sc=36 */ F(51), F(51), F(51), F(51), F(51), F(51), F(51), F(51), 0xFF, 0x00, +/* sc=37 */ F(59), F(59), F(59), F(59), F(59), F(59), F(59), F(59), 0xFF, 0x00, +/* sc=38 */ F(60), F(60), F(60), F(60), F(60), F(60), F(60), F(60), 0xFF, 0x00, +/* sc=39 */ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, RBT, RBT, 0x03, 0x02, +/* sc=3a */ F(50), F(50), F(50), F(50), F(50), F(50), F(50), F(50), 0xFF, 0x00, +/* sc=3b */ F(53), F(53), F(53), F(53), F(53), F(53), F(53), F(53), 0xFF, 0x00, +/* sc=3c */ F(55), F(55), F(55), F(55), F(55), F(55), F(55), F(55), 0xFF, 0x00, +/* sc=3d */ F(58), F(58), F(58), F(58), F(58), F(58), F(58), F(58), 0xFF, 0x00, +/* sc=3e */ F(49), F(49), F(49), F(49), F(49), F(49), F(49), F(49), 0xFF, 0x00, +/* sc=3f */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=40 */ '-', '-', '-', '-', '-', '-', '-', '-', 0x00, 0x00, +/* sc=41 */ '/', '/', '/', '/', '/', '/', '/', '/', 0x00, 0x00, +/* sc=42 */ '7', '7', '7', '7', '7', '7', '7', '7', 0x00, 0x00, +/* sc=43 */ '8', '8', '8', '8', '8', '8', '8', '8', 0x00, 0x00, +/* sc=44 */ '9', '9', '9', '9', '9', '9', '9', '9', 0x00, 0x00, +/* sc=45 */ '*', '*', '*', '*', '*', '*', '*', '*', 0x00, 0x00, +/* sc=46 */ '4', '4', '4', '4', '4', '4', '4', '4', 0x00, 0x00, +/* sc=47 */ '5', '5', '5', '5', '5', '5', '5', '5', 0x00, 0x00, +/* sc=48 */ '6', '6', '6', '6', '6', '6', '6', '6', 0x00, 0x00, +/* sc=49 */ '+', '+', '+', '+', '+', '+', '+', '+', 0x00, 0x00, +/* sc=4a */ '1', '1', '1', '1', '1', '1', '1', '1', 0x00, 0x00, +/* sc=4b */ '2', '2', '2', '2', '2', '2', '2', '2', 0x00, 0x00, +/* sc=4c */ '3', '3', '3', '3', '3', '3', '3', '3', 0x00, 0x00, +/* sc=4d */ '=', '=', '=', '=', '=', '=', '=', '=', 0x00, 0x00, +/* sc=4e */ '0', '0', '0', '0', '0', '0', '0', '0', 0x00, 0x00, +/* sc=4f */ ',', ',', ',', ',', ',', ',', ',', ',', 0x00, 0x00, +/* sc=50 */ '.', '.', '.', '.', '.', '.', '.', '.', 0x00, 0x00, +/* sc=51 */ 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x00, 0x00, +/* sc=52 */ F(11), F(23), F(35), F(47), S(11), S(11), S(11), S(11), 0xFF, 0x00, +/* sc=53 */ F(12), F(24), F(36), F(48), S(12), S(12), S(12), S(12), 0xFF, 0x00, +/* sc=54 */ SLK, SLK, SLK, SLK, SLK, SLK, SLK, SLK, 0xFF, 0x00, +/* sc=55 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=56 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=57 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=58 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=59 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=5a */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=5b */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=5c */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=5d */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=5e */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=5f */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=60 */ F(57), F(57), F(57), F(57), F(57), F(57), F(57), F(57), 0xFF, 0x00, +/* sc=61 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=62 */ F( 1), F(13), F(25), F(37), S( 1), S( 1), S( 1), S( 1), 0xFF, 0x00, +/* sc=63 */ F( 2), F(14), F(26), F(38), S( 2), S( 2), S( 2), S( 2), 0xFF, 0x00, +/* sc=64 */ F( 3), F(15), F(27), F(39), S( 3), S( 3), S( 3), S( 3), 0xFF, 0x00, +/* sc=65 */ F( 4), F(16), F(28), F(40), S( 4), S( 4), S( 4), S( 4), 0xFF, 0x00, +/* sc=66 */ F( 5), F(17), F(29), F(41), S( 5), S( 5), S( 5), S( 5), 0xFF, 0x00, +/* sc=67 */ F( 6), F(18), F(30), F(42), S( 6), S( 6), S( 6), S( 6), 0xFF, 0x00, +/* sc=68 */ F( 7), F(19), F(31), F(43), S( 7), S( 7), S( 7), S( 7), 0xFF, 0x00, +/* sc=69 */ F( 8), F(20), F(32), F(44), S( 8), S( 8), S( 8), S( 8), 0xFF, 0x00, +/* sc=6a */ F( 9), F(21), F(33), F(45), S( 9), S( 9), S( 9), S( 9), 0xFF, 0x00, +/* sc=6b */ F(10), F(22), F(34), F(46), S(10), S(10), S(10), S(10), 0xFF, 0x00, +/* sc=6c */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=6d */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=6e */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=6f */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=70 */ LSH, LSH, LSH, LSH, LSH, LSH, LSH, LSH, 0xFF, 0x00, +/* sc=71 */ CLK, CLK, CLK, CLK, CLK, CLK, CLK, CLK, 0xFF, 0x00, +/* sc=72 */ LALT, LALT, LALT, LALT, LALT, LALT, LALT, LALT, 0xFF, 0x00, +/* sc=73 */ LALT, LALT, LALT, LALT, LALT, LALT, LALT, LALT, 0xFF, 0x00, +/* sc=74 */ LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, 0xFF, 0x00, +/* sc=75 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=76 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=77 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=78 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=79 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=7a */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=7b */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=7c */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=7d */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=7e */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +/* sc=7f */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, +}; +#endif + #ifdef DKKEYMAP static keymap_t key_map = { 0x6C, /* DK iso8859 keymap */ /* alt @@ -750,7 +889,7 @@ static keymap_t key_map = { 0xEC, /* keys number */ #endif -#if !defined(DKKEYMAP) && !defined(UKKEYMAP) && !defined(GRKEYMAP) && !defined(SWKEYMAP) && !defined(RUKEYMAP) +#if !defined(DKKEYMAP) && !defined(UKKEYMAP) && !defined(GRKEYMAP) && !defined(SWKEYMAP) && !defined(RUKEYMAP) && !defined(PC98) static keymap_t key_map = { 0x6C, /* US iso8859 keymap */ /* alt * scan cntrl alt alt cntrl diff --git a/sys/isa/timerreg.h b/sys/isa/timerreg.h index 5742f66..16fbc0b 100644 --- a/sys/isa/timerreg.h +++ b/sys/isa/timerreg.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: Header: timerreg.h,v 1.2 93/02/28 15:08:58 mccanne Exp - * $Id$ + * $Id: timerreg.h,v 1.2 1993/10/16 13:46:26 rgrimes Exp $ */ /* @@ -59,6 +59,7 @@ * in undefined behavior (but hopefully not fry the chip). * Reading in this manner has no side effects. * + * [IBM-PC] * The outputs of the three timers are connected as follows: * * timer 0 -> irq 0 @@ -67,15 +68,31 @@ * * Timer 0 is used to call hardclock. * Timer 2 is used to generate console beeps. + * + * [PC-9801] + * The outputs of the three timers are connected as follows: + * + * timer 0 -> irq 0 + * timer 1 -> speaker (via keyboard controller) + * timer 2 -> RS232C + * + * Timer 0 is used to call hardclock. + * Timer 1 is used to generate console beeps. */ /* * Macros for specifying values to be written into a mode register. */ #define TIMER_CNTR0 (IO_TIMER1 + 0) /* timer 0 counter port */ +#ifdef PC98 +#define TIMER_CNTR1 0x3fdb /* timer 1 counter port */ +#define TIMER_CNTR2 (IO_TIMER1 + 4) /* timer 2 counter port */ +#define TIMER_MODE (IO_TIMER1 + 6) /* timer mode port */ +#else #define TIMER_CNTR1 (IO_TIMER1 + 1) /* timer 1 counter port */ #define TIMER_CNTR2 (IO_TIMER1 + 2) /* timer 2 counter port */ #define TIMER_MODE (IO_TIMER1 + 3) /* timer mode port */ +#endif #define TIMER_SEL0 0x00 /* select counter 0 */ #define TIMER_SEL1 0x40 /* select counter 1 */ #define TIMER_SEL2 0x80 /* select counter 2 */ diff --git a/sys/kern/kern_random.c b/sys/kern/kern_random.c index 227b707..7a13baf 100644 --- a/sys/kern/kern_random.c +++ b/sys/kern/kern_random.c @@ -1,7 +1,7 @@ /* * random_machdep.c -- A strong random number generator * - * $Id: random_machdep.c,v 1.11 1996/09/27 13:25:13 peter Exp $ + * $Id: random_machdep.c,v 1.12 1996/10/09 19:47:32 bde Exp $ * * Version 0.95, last modified 18-Oct-95 * @@ -51,7 +51,11 @@ #include <machine/random.h> #include <i386/isa/icu.h> +#ifdef PC98 +#include <pc98/pc98/pc98.h> +#else #include <i386/isa/isa.h> +#endif #include <i386/isa/timerreg.h> #define MAX_BLKDEV 4 diff --git a/sys/pc98/cbus/cbus.h b/sys/pc98/cbus/cbus.h index 84c77b4..6a369f7 100644 --- a/sys/pc98/cbus/cbus.h +++ b/sys/pc98/cbus/cbus.h @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)isa.h 5.7 (Berkeley) 5/9/91 - * $Id: pc98.h,v 1.5 1996/10/09 21:46:34 asami Exp $ + * $Id: pc98.h,v 1.6 1996/10/23 07:25:22 asami Exp $ */ #ifndef _PC98_PC98_PC98_H_ @@ -73,7 +73,7 @@ #define IO_NMI 0x050 /* NMI Control */ #define IO_WAIT 0x05F /* WAIT 0.6 us */ #define IO_GDC1 0x060 /* 7220 GDC Text Control */ -#define IO_TIMER 0x071 /* 8253C Timer */ +#define IO_TIMER1 0x071 /* 8253C Timer */ #define IO_SASI 0x080 /* SASI Hard Disk Controller */ #define IO_FD1 0x090 /* 765A 1MB FDC */ #define IO_GDC2 0x0a0 /* 7220 GDC Graphic Control */ diff --git a/sys/pc98/cbus/clock.c b/sys/pc98/cbus/clock.c index 3e9faf9..0ba9a65 100644 --- a/sys/pc98/cbus/clock.c +++ b/sys/pc98/cbus/clock.c @@ -34,7 +34,11 @@ * SUCH DAMAGE. * * from: @(#)clock.c 7.2 (Berkeley) 5/12/91 - * $Id: clock.c,v 1.8 1996/10/23 07:25:13 asami Exp $ + * $Id: clock.c,v 1.9 1996/10/29 08:36:19 asami Exp $ + */ + +/* + * Routines to handle clock hardware. */ /* @@ -48,10 +52,6 @@ * modified for PC98 by Kakefuda */ -/* - * Primitive clock interrupt routines. - */ - #include "opt_clock.h" #include "opt_cpu.h" @@ -72,13 +72,12 @@ #ifdef PC98 #include <pc98/pc98/pc98.h> #include <i386/isa/isa_device.h> -#include <pc98/pc98/timerreg.h> #else #include <i386/isa/isa.h> #include <i386/isa/isa_device.h> #include <i386/isa/rtc.h> -#include <i386/isa/timerreg.h> #endif +#include <i386/isa/timerreg.h> /* * 32-bit time_t's can't reach leap years before 1904 or after 2036, so we @@ -109,52 +108,49 @@ int adjkerntz; /* local offset from GMT in seconds */ int disable_rtc_set; /* disable resettodr() if != 0 */ -int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */ - u_int idelayed; #if defined(I586_CPU) || defined(I686_CPU) -u_int i586_ctr_bias; +u_int i586_ctr_bias; u_int i586_ctr_comultiplier; u_int i586_ctr_freq; u_int i586_ctr_multiplier; -long long i586_last_tick; -unsigned long i586_avg_tick; #endif int statclock_disable; u_int stat_imask = SWI_CLOCK_MASK; #ifdef TIMER_FREQ -static u_int timer_freq = TIMER_FREQ; +u_int timer_freq = TIMER_FREQ; #else #ifdef PC98 #ifndef AUTO_CLOCK #ifndef PC98_8M -static u_int timer_freq = 2457600; +u_int timer_freq = 2457600; #else /* !PC98_8M */ -static u_int timer_freq = 1996800; +u_int timer_freq = 1996800; #endif /* PC98_8M */ #else /* AUTO_CLOCK */ -static u_int timer_freq = 2457600; +u_int timer_freq = 2457600; #endif /* AUTO_CLOCK */ #else /* IBM-PC */ -static u_int timer_freq = 1193182; +u_int timer_freq = 1193182; #endif /* PC98 */ #endif -int timer0_max_count; -u_int timer0_overflow_threshold; -u_int timer0_prescaler_count; +int timer0_max_count; +u_int timer0_overflow_threshold; +u_int timer0_prescaler_count; +int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */ static int beeping = 0; static u_int clk_imask = HWI_MASK | SWI_MASK; static const u_char daysinmonth[] = {31,28,31,30,31,30,31,31,30,31,30,31}; -static u_int hardclock_max_count; +static u_int hardclock_max_count; /* * XXX new_function and timer_func should not handle clockframes, but * timer_func currently needs to hold hardclock to handle the * timer0_state == 0 case. We should use register_intr()/unregister_intr() * to switch between clkintr() and a slightly different timerintr(). */ -static void (*new_function) __P((struct clockframe *frame)); -static u_int new_rate; +static void (*new_function) __P((struct clockframe *frame)); +static u_int new_rate; #ifndef PC98 static u_char rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF; static u_char rtc_statusb = RTCSB_24HR | RTCSB_PINTR; @@ -171,7 +167,7 @@ static u_char timer0_state; static u_char timer1_state; #endif static u_char timer2_state; -static void (*timer_func) __P((struct clockframe *frame)) = hardclock; +static void (*timer_func) __P((struct clockframe *frame)) = hardclock; int rtc_inb __P((void)); #if defined(I586_CPU) || defined(I686_CPU) @@ -437,7 +433,7 @@ getit(void) disable_intr(); /* Select timer0 and latch counter value. */ - outb(TIMER_MODE, TIMER_SEL0); + outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH); low = inb(TIMER_CNTR0); high = inb(TIMER_CNTR0); @@ -625,7 +621,7 @@ calibrate_clocks(void) u_int count, prev_count, tot_count; int sec, start_sec, timeout; - printf("Calibrating clock(s) relative to mc146818A clock...\n"); + printf("Calibrating clock(s) relative to mc146818A clock ... "); if (!(rtcin(RTC_STATUSD) & RTCSD_PWR)) goto fail; timeout = 100000000; @@ -782,7 +778,7 @@ startrtclock() if (delta < timer_freq / 100) { #ifndef CLK_USE_I8254_CALIBRATION if (bootverbose) - printf( + printf( "CLK_USE_I8254_CALIBRATION not specified - using default frequency\n"); freq = timer_freq; #endif @@ -802,7 +798,7 @@ startrtclock() #ifndef CLK_USE_I586_CALIBRATION if (i586_ctr_freq != 0) { if (bootverbose) - printf( + printf( "CLK_USE_I586_CALIBRATION not specified - using old calibration method\n"); i586_ctr_freq = 0; } @@ -1114,10 +1110,8 @@ cpu_initclocks() /* * Finish setting up anti-jitter measures. */ - if (i586_ctr_freq != 0) { - i586_last_tick = rdtsc(); - i586_ctr_bias = i586_last_tick; - } + if (i586_ctr_freq != 0) + i586_ctr_bias = rdtsc(); #endif #ifndef PC98 diff --git a/sys/pc98/cbus/pcrtc.c b/sys/pc98/cbus/pcrtc.c index 3e9faf9..0ba9a65 100644 --- a/sys/pc98/cbus/pcrtc.c +++ b/sys/pc98/cbus/pcrtc.c @@ -34,7 +34,11 @@ * SUCH DAMAGE. * * from: @(#)clock.c 7.2 (Berkeley) 5/12/91 - * $Id: clock.c,v 1.8 1996/10/23 07:25:13 asami Exp $ + * $Id: clock.c,v 1.9 1996/10/29 08:36:19 asami Exp $ + */ + +/* + * Routines to handle clock hardware. */ /* @@ -48,10 +52,6 @@ * modified for PC98 by Kakefuda */ -/* - * Primitive clock interrupt routines. - */ - #include "opt_clock.h" #include "opt_cpu.h" @@ -72,13 +72,12 @@ #ifdef PC98 #include <pc98/pc98/pc98.h> #include <i386/isa/isa_device.h> -#include <pc98/pc98/timerreg.h> #else #include <i386/isa/isa.h> #include <i386/isa/isa_device.h> #include <i386/isa/rtc.h> -#include <i386/isa/timerreg.h> #endif +#include <i386/isa/timerreg.h> /* * 32-bit time_t's can't reach leap years before 1904 or after 2036, so we @@ -109,52 +108,49 @@ int adjkerntz; /* local offset from GMT in seconds */ int disable_rtc_set; /* disable resettodr() if != 0 */ -int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */ - u_int idelayed; #if defined(I586_CPU) || defined(I686_CPU) -u_int i586_ctr_bias; +u_int i586_ctr_bias; u_int i586_ctr_comultiplier; u_int i586_ctr_freq; u_int i586_ctr_multiplier; -long long i586_last_tick; -unsigned long i586_avg_tick; #endif int statclock_disable; u_int stat_imask = SWI_CLOCK_MASK; #ifdef TIMER_FREQ -static u_int timer_freq = TIMER_FREQ; +u_int timer_freq = TIMER_FREQ; #else #ifdef PC98 #ifndef AUTO_CLOCK #ifndef PC98_8M -static u_int timer_freq = 2457600; +u_int timer_freq = 2457600; #else /* !PC98_8M */ -static u_int timer_freq = 1996800; +u_int timer_freq = 1996800; #endif /* PC98_8M */ #else /* AUTO_CLOCK */ -static u_int timer_freq = 2457600; +u_int timer_freq = 2457600; #endif /* AUTO_CLOCK */ #else /* IBM-PC */ -static u_int timer_freq = 1193182; +u_int timer_freq = 1193182; #endif /* PC98 */ #endif -int timer0_max_count; -u_int timer0_overflow_threshold; -u_int timer0_prescaler_count; +int timer0_max_count; +u_int timer0_overflow_threshold; +u_int timer0_prescaler_count; +int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */ static int beeping = 0; static u_int clk_imask = HWI_MASK | SWI_MASK; static const u_char daysinmonth[] = {31,28,31,30,31,30,31,31,30,31,30,31}; -static u_int hardclock_max_count; +static u_int hardclock_max_count; /* * XXX new_function and timer_func should not handle clockframes, but * timer_func currently needs to hold hardclock to handle the * timer0_state == 0 case. We should use register_intr()/unregister_intr() * to switch between clkintr() and a slightly different timerintr(). */ -static void (*new_function) __P((struct clockframe *frame)); -static u_int new_rate; +static void (*new_function) __P((struct clockframe *frame)); +static u_int new_rate; #ifndef PC98 static u_char rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF; static u_char rtc_statusb = RTCSB_24HR | RTCSB_PINTR; @@ -171,7 +167,7 @@ static u_char timer0_state; static u_char timer1_state; #endif static u_char timer2_state; -static void (*timer_func) __P((struct clockframe *frame)) = hardclock; +static void (*timer_func) __P((struct clockframe *frame)) = hardclock; int rtc_inb __P((void)); #if defined(I586_CPU) || defined(I686_CPU) @@ -437,7 +433,7 @@ getit(void) disable_intr(); /* Select timer0 and latch counter value. */ - outb(TIMER_MODE, TIMER_SEL0); + outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH); low = inb(TIMER_CNTR0); high = inb(TIMER_CNTR0); @@ -625,7 +621,7 @@ calibrate_clocks(void) u_int count, prev_count, tot_count; int sec, start_sec, timeout; - printf("Calibrating clock(s) relative to mc146818A clock...\n"); + printf("Calibrating clock(s) relative to mc146818A clock ... "); if (!(rtcin(RTC_STATUSD) & RTCSD_PWR)) goto fail; timeout = 100000000; @@ -782,7 +778,7 @@ startrtclock() if (delta < timer_freq / 100) { #ifndef CLK_USE_I8254_CALIBRATION if (bootverbose) - printf( + printf( "CLK_USE_I8254_CALIBRATION not specified - using default frequency\n"); freq = timer_freq; #endif @@ -802,7 +798,7 @@ startrtclock() #ifndef CLK_USE_I586_CALIBRATION if (i586_ctr_freq != 0) { if (bootverbose) - printf( + printf( "CLK_USE_I586_CALIBRATION not specified - using old calibration method\n"); i586_ctr_freq = 0; } @@ -1114,10 +1110,8 @@ cpu_initclocks() /* * Finish setting up anti-jitter measures. */ - if (i586_ctr_freq != 0) { - i586_last_tick = rdtsc(); - i586_ctr_bias = i586_last_tick; - } + if (i586_ctr_freq != 0) + i586_ctr_bias = rdtsc(); #endif #ifndef PC98 diff --git a/sys/pc98/conf/GENERIC b/sys/pc98/conf/GENERIC index 5bd1821..320aaa2 100644 --- a/sys/pc98/conf/GENERIC +++ b/sys/pc98/conf/GENERIC @@ -11,7 +11,7 @@ # device lines is present in the ./LINT configuration file. If you are # in doubt as to the purpose or necessity of a line, check first in LINT. # -# $Id: GENERIC98,v 1.6 1996/10/09 21:45:41 asami Exp $ +# $Id: GENERIC98,v 1.7 1996/10/23 07:24:45 asami Exp $ # GENERIC98 -- Generic PC98 machine with WD/SBIC55 disks @@ -100,6 +100,9 @@ device wcd0 #IDE CD-ROM # for any number of installed devices. controller ncr0 controller ahc0 +options "AHC_FORCE_PIO" # Some motherboards choke on MemI/O, + # so use PIO in the ahc driver in the + # generic kernel. controller sbic0 at isa? port "IO_SCSI" bio irq 5 drq 3 vector sbicintr # sbic55.c.new diff --git a/sys/pc98/conf/GENERIC98 b/sys/pc98/conf/GENERIC98 index 5bd1821..320aaa2 100644 --- a/sys/pc98/conf/GENERIC98 +++ b/sys/pc98/conf/GENERIC98 @@ -11,7 +11,7 @@ # device lines is present in the ./LINT configuration file. If you are # in doubt as to the purpose or necessity of a line, check first in LINT. # -# $Id: GENERIC98,v 1.6 1996/10/09 21:45:41 asami Exp $ +# $Id: GENERIC98,v 1.7 1996/10/23 07:24:45 asami Exp $ # GENERIC98 -- Generic PC98 machine with WD/SBIC55 disks @@ -100,6 +100,9 @@ device wcd0 #IDE CD-ROM # for any number of installed devices. controller ncr0 controller ahc0 +options "AHC_FORCE_PIO" # Some motherboards choke on MemI/O, + # so use PIO in the ahc driver in the + # generic kernel. controller sbic0 at isa? port "IO_SCSI" bio irq 5 drq 3 vector sbicintr # sbic55.c.new diff --git a/sys/pc98/conf/files.pc98 b/sys/pc98/conf/files.pc98 index fef4b97..08f74ae 100644 --- a/sys/pc98/conf/files.pc98 +++ b/sys/pc98/conf/files.pc98 @@ -3,7 +3,7 @@ # # modified for PC-9801 # -# $Id: files.pc98,v 1.7 1996/09/12 11:09:18 asami Exp $ +# $Id: files.pc98,v 1.8 1996/10/23 07:24:49 asami Exp $ # aic7xxx_asm optional ahc device-driver \ dependency "$S/dev/aic7xxx/aic7xxx_asm.c" \ @@ -43,7 +43,7 @@ i386/i386/db_disasm.c optional ddb i386/i386/db_interface.c optional ddb i386/i386/db_trace.c optional ddb i386/i386/i386-gdbstub.c optional ddb -pc98/i386/exception.s standard +i386/i386/exception.s standard i386/i386/identcpu.c standard i386/i386/in_cksum.c optional inet # locore.s needs to be handled in Makefile to put it first. Otherwise it's @@ -62,7 +62,7 @@ i386/i386/swtch.s standard i386/i386/sys_machdep.c standard pc98/i386/trap.c standard pc98/i386/userconfig.c optional userconfig -pc98/i386/vm_machdep.c standard +i386/i386/vm_machdep.c standard i386/ibcs2/ibcs2_fcntl.c optional ibcs2 i386/ibcs2/ibcs2_stat.c optional ibcs2 i386/ibcs2/ibcs2_ipc.c optional ibcs2 @@ -89,7 +89,7 @@ pc98/pc98/bs/bshw.c optional bs device-driver pc98/pc98/bs/bsif.c optional bs device-driver pc98/pc98/sbic55.c optional sbic device-driver #i386/pc98/aha1542.c optional aha device-driver -pc98/pc98/aic6360.c optional aic device-driver +i386/isa/aic6360.c optional aic device-driver pc98/pc98/b004.c optional bqu device-driver i386/pc98/bt742a.c optional bt device-driver i386/pc98/bt5xx-445.c optional bt device-driver @@ -130,8 +130,8 @@ pc98/pc98/mse.c optional mse device-driver pc98/isa/ncr5380.c optional nca device-driver pc98/pc98/npx.c optional npx device-driver pc98/pc98/pcaudio.c optional pca device-driver -pc98/pc98/matcd/matcd.c optional matcd device-driver -pc98/pc98/pcibus.c optional pci device-driver +i386/isa/matcd/matcd.c optional matcd device-driver +i386/isa/pcibus.c optional pci device-driver i386/isa/pcicx.c optional ze device-driver i386/isa/pcicx.c optional zp device-driver pc98/isa/pcvt/pcvt_drv.c optional vt device-driver @@ -140,11 +140,11 @@ pc98/isa/pcvt/pcvt_kbd.c optional vt device-driver pc98/isa/pcvt/pcvt_out.c optional vt device-driver pc98/isa/pcvt/pcvt_sup.c optional vt device-driver pc98/isa/pcvt/pcvt_vtf.c optional vt device-driver -pc98/pc98/prof_machdep.c optional profiling-routine +i386/isa/prof_machdep.c optional profiling-routine pc98/pc98/psm.c optional psm device-driver pc98/isa/qcam.c optional qcam device-driver pc98/isa/qcamio.c optional qcam device-driver -pc98/pc98/random_machdep.c standard +i386/isa/random_machdep.c standard pc98/isa/rc.c optional rc device-driver i386/isa/scd.c optional scd device-driver pc98/isa/seagate.c optional sea device-driver @@ -152,51 +152,51 @@ pc98/isa/si.c optional si device-driver pc98/isa/si_code.c optional si device-driver pc98/pc98/sio.c optional sio device-driver pc98/pc98/sound/pcm86.c optional pcm device-driver -pc98/pc98/sound/dev_table.c optional snd device-driver +i386/isa/sound/dev_table.c optional snd device-driver pc98/pc98/sound/soundcard.c optional snd device-driver pc98/pc98/sound/sound_switch.c optional snd device-driver -pc98/pc98/sound/audio.c optional snd device-driver -pc98/pc98/sound/dmabuf.c optional snd device-driver -pc98/pc98/sound/sys_timer.c optional snd device-driver -pc98/pc98/sound/sequencer.c optional snd device-driver -pc98/pc98/sound/patmgr.c optional snd device-driver -pc98/pc98/sound/adlib_card.c optional opl device-driver +i386/isa/sound/audio.c optional snd device-driver +i386/isa/sound/dmabuf.c optional snd device-driver +i386/isa/sound/sys_timer.c optional snd device-driver +i386/isa/sound/sequencer.c optional snd device-driver +i386/isa/sound/patmgr.c optional snd device-driver +i386/isa/sound/adlib_card.c optional opl device-driver pc98/pc98/sound/opl3.c optional opl device-driver -pc98/pc98/sound/gus_card.c optional gus device-driver -pc98/pc98/sound/gus_midi.c optional gus device-driver -pc98/pc98/sound/gus_vol.c optional gus device-driver -pc98/pc98/sound/gus_wave.c optional gus device-driver -pc98/pc98/sound/ics2101.c optional gus device-driver -pc98/pc98/sound/sound_timer.c optional gus device-driver -pc98/pc98/sound/midi_synth.c optional gus device-driver -pc98/pc98/sound/midibuf.c optional gus device-driver +i386/isa/sound/gus_card.c optional gus device-driver +i386/isa/sound/gus_midi.c optional gus device-driver +i386/isa/sound/gus_vol.c optional gus device-driver +i386/isa/sound/gus_wave.c optional gus device-driver +i386/isa/sound/ics2101.c optional gus device-driver +i386/isa/sound/sound_timer.c optional gus device-driver +i386/isa/sound/midi_synth.c optional gus device-driver +i386/isa/sound/midibuf.c optional gus device-driver pc98/pc98/sound/ad1848.c optional gusxvi device-driver pc98/pc98/sound/ad1848.c optional gus device-driver pc98/pc98/sound/ad1848.c optional mss device-driver -pc98/pc98/sound/midi_synth.c optional mss device-driver -pc98/pc98/sound/midibuf.c optional mss device-driver -pc98/pc98/sound/mpu401.c optional mpu device-driver -pc98/pc98/sound/midi_synth.c optional mpu device-driver -pc98/pc98/sound/midibuf.c optional mpu device-driver -pc98/pc98/sound/pas2_card.c optional pas device-driver -pc98/pc98/sound/pas2_midi.c optional pas device-driver -pc98/pc98/sound/pas2_mixer.c optional pas device-driver +i386/isa/sound/midi_synth.c optional mss device-driver +i386/isa/sound/midibuf.c optional mss device-driver +i386/isa/sound/mpu401.c optional mpu device-driver +i386/isa/sound/midi_synth.c optional mpu device-driver +i386/isa/sound/midibuf.c optional mpu device-driver +i386/isa/sound/pas2_card.c optional pas device-driver +i386/isa/sound/pas2_midi.c optional pas device-driver +i386/isa/sound/pas2_mixer.c optional pas device-driver pc98/pc98/sound/pas2_pcm.c optional pas device-driver -pc98/pc98/sound/midi_synth.c optional pas device-driver -pc98/pc98/sound/midibuf.c optional pas device-driver -pc98/pc98/sound/sb_card.c optional sb device-driver +i386/isa/sound/midi_synth.c optional pas device-driver +i386/isa/sound/midibuf.c optional pas device-driver +i386/isa/sound/sb_card.c optional sb device-driver pc98/pc98/sound/sb_dsp.c optional sb device-driver -pc98/pc98/sound/sb_midi.c optional sb device-driver -pc98/pc98/sound/sb_mixer.c optional sb device-driver -pc98/pc98/sound/midi_synth.c optional sb device-driver -pc98/pc98/sound/midibuf.c optional sb device-driver +i386/isa/sound/sb_midi.c optional sb device-driver +i386/isa/sound/sb_mixer.c optional sb device-driver +i386/isa/sound/midi_synth.c optional sb device-driver +i386/isa/sound/midibuf.c optional sb device-driver pc98/pc98/sound/sb16_dsp.c optional sbxvi device-driver pc98/pc98/sound/sb16_midi.c optional sbmidi device-driver -pc98/pc98/sound/uart6850.c optional uart device-driver -pc98/pc98/sound/midi_synth.c optional uart device-driver -pc98/pc98/sound/midibuf.c optional uart device-driver -pc98/pc98/sound/trix.c optional trix device-driver -pc98/pc98/sound/sscape.c optional sscape device-driver +i386/isa/sound/uart6850.c optional uart device-driver +i386/isa/sound/midi_synth.c optional uart device-driver +i386/isa/sound/midibuf.c optional uart device-driver +i386/isa/sound/trix.c optional trix device-driver +i386/isa/sound/sscape.c optional sscape device-driver pc98/isa/spigot.c optional spigot device-driver pc98/pc98/spkr.c optional speaker device-driver pc98/isa/stallion.c optional stl device-driver @@ -205,7 +205,7 @@ pc98/isa/tw.c optional tw device-driver pc98/isa/ultra14f.c optional uha device-driver pc98/pc98/wd.c optional wdc device-driver pc98/pc98/wd.c optional wd device-driver -pc98/pc98/atapi.c optional atapi device-driver +i386/isa/atapi.c optional atapi device-driver pc98/pc98/wcd.c optional wcd device-driver pc98/isa/wd7000.c optional wds device-driver pc98/pc98/wt.c optional wt device-driver diff --git a/sys/pc98/conf/options.pc98 b/sys/pc98/conf/options.pc98 index 3f3edc68..106083c 100644 --- a/sys/pc98/conf/options.pc98 +++ b/sys/pc98/conf/options.pc98 @@ -1,4 +1,4 @@ -# $Id: options.pc98,v 1.6 1996/10/23 07:24:55 asami Exp $ +# $Id: options.pc98,v 1.7 1996/10/29 08:36:14 asami Exp $ BOUNCEPAGES opt_bounce.h USER_LDT MATH_EMULATE opt_math_emulate.h @@ -29,6 +29,8 @@ XSERVER opt_pcvt.h AHC_TAGENABLE opt_aic7xxx.h AHC_SCBPAGING_ENABLE opt_aic7xxx.h +AHC_FORCE_PIO opt_aic7xxx.h +AHC_SHARE_SCBS opt_aic7xxx.h CLK_CALIBRATION_LOOP opt_clock.h CLK_USE_I8254_CALIBRATION opt_clock.h diff --git a/sys/pc98/i386/exception.s b/sys/pc98/i386/exception.s deleted file mode 100644 index b2bfa93..0000000 --- a/sys/pc98/i386/exception.s +++ /dev/null @@ -1,279 +0,0 @@ -/*- - * Copyright (c) 1990 The Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Id: exception.s,v 1.1.1.1 1996/06/14 10:04:41 asami Exp $ - */ - -#include "npx.h" /* NNPX */ -#include "assym.s" /* system defines */ -#include <sys/errno.h> /* error return codes */ -#include <machine/spl.h> /* SWI_AST_MASK ... */ -#include <machine/psl.h> /* PSL_I */ -#include <machine/trap.h> /* trap codes */ -#include <sys/syscall.h> /* syscall numbers */ -#include <machine/asmacros.h> /* miscellaneous macros */ -#include <sys/cdefs.h> /* CPP macros */ - -#define KDSEL 0x10 /* kernel data selector */ -#define SEL_RPL_MASK 0x0003 -#define TRAPF_CS_OFF (13 * 4) - - .text - -/*****************************************************************************/ -/* Trap handling */ -/*****************************************************************************/ -/* - * Trap and fault vector routines - */ -#define IDTVEC(name) ALIGN_TEXT; .globl __CONCAT(_X,name); __CONCAT(_X,name): -#define TRAP(a) pushl $(a) ; jmp _alltraps - -/* - * XXX - debugger traps are now interrupt gates so at least bdb doesn't lose - * control. The sti's give the standard losing behaviour for ddb and kgdb. - */ -#ifdef BDE_DEBUGGER -#define BDBTRAP(name) \ - ss ; \ - cmpb $0,_bdb_exists ; \ - je 1f ; \ - testb $SEL_RPL_MASK,4(%esp) ; \ - jne 1f ; \ - ss ; \ - .globl __CONCAT(__CONCAT(bdb_,name),_ljmp); \ -__CONCAT(__CONCAT(bdb_,name),_ljmp): \ - ljmp $0,$0 ; \ -1: -#else -#define BDBTRAP(name) -#endif - -#define BPTTRAP(a) testl $PSL_I,4+8(%esp) ; je 1f ; sti ; 1: ; TRAP(a) - -MCOUNT_LABEL(user) -MCOUNT_LABEL(btrap) - -IDTVEC(div) - pushl $0; TRAP(T_DIVIDE) -IDTVEC(dbg) - BDBTRAP(dbg) - pushl $0; BPTTRAP(T_TRCTRAP) -IDTVEC(nmi) - pushl $0; TRAP(T_NMI) -IDTVEC(bpt) - BDBTRAP(bpt) - pushl $0; BPTTRAP(T_BPTFLT) -IDTVEC(ofl) - pushl $0; TRAP(T_OFLOW) -IDTVEC(bnd) - pushl $0; TRAP(T_BOUND) -IDTVEC(ill) - pushl $0; TRAP(T_PRIVINFLT) -IDTVEC(dna) - pushl $0; TRAP(T_DNA) -IDTVEC(fpusegm) - pushl $0; TRAP(T_FPOPFLT) -IDTVEC(tss) - TRAP(T_TSSFLT) -IDTVEC(missing) - TRAP(T_SEGNPFLT) -IDTVEC(stk) - TRAP(T_STKFLT) -IDTVEC(prot) - TRAP(T_PROTFLT) -IDTVEC(page) - TRAP(T_PAGEFLT) -IDTVEC(mchk) - pushl $0; TRAP(T_MCHK) -IDTVEC(rsvd) - pushl $0; TRAP(T_RESERVED) -IDTVEC(fpu) -#if NNPX > 0 - /* - * Handle like an interrupt (except for accounting) so that we can - * call npxintr to clear the error. It would be better to handle - * npx interrupts as traps. This used to be difficult for nested - * interrupts, but now it is fairly easy - mask nested ones the - * same as SWI_AST's. - */ - pushl $0 /* dummy error code */ - pushl $0 /* dummy trap type */ - pushal - pushl %ds - pushl %es /* now the stack frame is a trap frame */ - movl $KDSEL,%eax - movl %ax,%ds - movl %ax,%es - FAKE_MCOUNT(12*4(%esp)) - movl _cpl,%eax - pushl %eax - pushl $0 /* dummy unit to finish building intr frame */ - incl _cnt+V_TRAP - orl $SWI_AST_MASK,%eax - movl %eax,_cpl - call _npxintr - incb _intr_nesting_level - MEXITCOUNT - jmp _doreti -#else /* NNPX > 0 */ - pushl $0; TRAP(T_ARITHTRAP) -#endif /* NNPX > 0 */ -IDTVEC(align) - TRAP(T_ALIGNFLT) - - SUPERALIGN_TEXT - .globl _alltraps -_alltraps: - pushal - pushl %ds - pushl %es -alltraps_with_regs_pushed: - movl $KDSEL,%eax - movl %ax,%ds - movl %ax,%es - FAKE_MCOUNT(12*4(%esp)) -calltrap: - FAKE_MCOUNT(_btrap) /* init "from" _btrap -> calltrap */ - incl _cnt+V_TRAP - orl $SWI_AST_MASK,_cpl - call _trap - - /* - * There was no place to save the cpl so we have to recover it - * indirectly. For traps from user mode it was 0, and for traps - * from kernel mode Oring SWI_AST_MASK into it didn't change it. - */ - subl %eax,%eax - testb $SEL_RPL_MASK,TRAPF_CS_OFF(%esp) - jne 1f - movl _cpl,%eax -1: - /* - * Return via _doreti to handle ASTs. Have to change trap frame - * to interrupt frame. - */ - pushl %eax - subl $4,%esp - incb _intr_nesting_level - MEXITCOUNT - jmp _doreti - -/* - * Call gate entry for syscall. - * The intersegment call has been set up to specify one dummy parameter. - * This leaves a place to put eflags so that the call frame can be - * converted to a trap frame. Note that the eflags is (semi-)bogusly - * pushed into (what will be) tf_err and then copied later into the - * final spot. It has to be done this way because esp can't be just - * temporarily altered for the pushfl - an interrupt might come in - * and clobber the saved cs/eip. - */ - SUPERALIGN_TEXT -IDTVEC(syscall) - pushfl /* save eflags in tf_err for now */ - subl $4,%esp /* skip over tf_trapno */ - pushal - pushl %ds - pushl %es - movl $KDSEL,%eax /* switch to kernel segments */ - movl %ax,%ds - movl %ax,%es - movl TF_ERR(%esp),%eax /* copy saved eflags to final spot */ - movl %eax,TF_EFLAGS(%esp) - movl $7,TF_ERR(%esp) /* sizeof "lcall 7,0" */ - FAKE_MCOUNT(12*4(%esp)) - incl _cnt+V_SYSCALL - movl $SWI_AST_MASK,_cpl - call _syscall - /* - * Return via _doreti to handle ASTs. - */ - pushl $0 /* cpl to restore */ - subl $4,%esp - movb $1,_intr_nesting_level - MEXITCOUNT - jmp _doreti - -/* - * Call gate entry for Linux/NetBSD syscall (int 0x80) - */ - SUPERALIGN_TEXT -IDTVEC(int0x80_syscall) - subl $8,%esp /* skip over tf_trapno and tf_err */ - pushal - pushl %ds - pushl %es - movl $KDSEL,%eax /* switch to kernel segments */ - movl %ax,%ds - movl %ax,%es - movl $2,TF_ERR(%esp) /* sizeof "int 0x80" */ - FAKE_MCOUNT(12*4(%esp)) - incl _cnt+V_SYSCALL - movl $SWI_AST_MASK,_cpl - call _syscall - /* - * Return via _doreti to handle ASTs. - */ - pushl $0 /* cpl to restore */ - subl $4,%esp - movb $1,_intr_nesting_level - MEXITCOUNT - jmp _doreti - -/* - * Include what was once config+isa-dependent code. - * XXX it should be in a stand-alone file. It's still icu-dependent and - * belongs in i386/isa. - */ -#ifdef PC98 -#include "pc98/pc98/vector.s" -#else -#include "i386/isa/vector.s" -#endif - -/* - * Include what was once icu-dependent code. - * XXX it should be merged into this file (also move the definition of - * imen to vector.s or isa.c). - * Before including it, set up a normal asm environment so that vector.s - * doesn't have to know that stuff is included after it. - */ - .data - ALIGN_DATA - .text - SUPERALIGN_TEXT -#ifdef PC98 -#include "pc98/pc98/icu.s" -#else -#include "i386/isa/icu.s" -#endif diff --git a/sys/pc98/i386/microtime.s b/sys/pc98/i386/microtime.s index 8cd7f44..146f748 100644 --- a/sys/pc98/i386/microtime.s +++ b/sys/pc98/i386/microtime.s @@ -32,22 +32,20 @@ * SUCH DAMAGE. * * from: Steve McCanne's microtime code - * $Id: microtime.s,v 1.4 1996/09/07 02:13:34 asami Exp $ + * $Id: microtime.s,v 1.5 1996/10/09 19:47:38 bde Exp $ */ #include "opt_cpu.h" #include <machine/asmacros.h> -#include <machine/clock.h> #include <i386/isa/icu.h> #ifdef PC98 #include <pc98/pc98/pc98.h> -#include <pc98/pc98/timerreg.h> #else #include <i386/isa/isa.h> -#include <i386/isa/timerreg.h> #endif +#include <i386/isa/timerreg.h> ENTRY(microtime) diff --git a/sys/pc98/i386/userconfig.c b/sys/pc98/i386/userconfig.c index ba5da41..55ead7a 100644 --- a/sys/pc98/i386/userconfig.c +++ b/sys/pc98/i386/userconfig.c @@ -46,7 +46,7 @@ ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ** - ** $Id: userconfig.c,v 1.8 1996/10/23 07:25:04 asami Exp $ + ** $Id: userconfig.c,v 1.9 1996/10/29 08:36:17 asami Exp $ **/ /** @@ -244,7 +244,7 @@ static DEV_INFO device_info[] = { {"aha", "Adaptec 154x SCSI controller", 0, CLS_STORAGE}, {"uha", "Ultrastor 14F/24F/34F SCSI controller",0, CLS_STORAGE}, {"aic", "Adaptec 152x SCSI and compatible sound cards", 0, CLS_STORAGE}, -{"nca", "ProAudio Spectrum SCSI and comaptibles", 0, CLS_STORAGE}, +{"nca", "ProAudio Spectrum SCSI and compatibles", 0, CLS_STORAGE}, {"sea", "Seagate ST01/ST02 SCSI and compatibles", 0, CLS_STORAGE}, {"wds", "Western Digitial WD7000 SCSI controller", 0, CLS_STORAGE}, {"ncr", "NCR 53C810 SCSI controller", FLG_FIXED, CLS_STORAGE}, @@ -2247,7 +2247,7 @@ visuserconfig(void) * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: userconfig.c,v 1.8 1996/10/23 07:25:04 asami Exp $ + * $Id: userconfig.c,v 1.9 1996/10/29 08:36:17 asami Exp $ */ #include "scbus.h" diff --git a/sys/pc98/i386/vm_machdep.c b/sys/pc98/i386/vm_machdep.c deleted file mode 100644 index 4e1581c..0000000 --- a/sys/pc98/i386/vm_machdep.c +++ /dev/null @@ -1,864 +0,0 @@ -/*- - * Copyright (c) 1982, 1986 The Regents of the University of California. - * Copyright (c) 1989, 1990 William Jolitz - * Copyright (c) 1994 John Dyson - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * the Systems Programming Group of the University of Utah Computer - * Science Department, and William Jolitz. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: @(#)vm_machdep.c 7.3 (Berkeley) 5/13/91 - * Utah $Hdr: vm_machdep.c 1.16.1.1 89/06/23$ - * $Id: vm_machdep.c,v 1.5 1996/10/09 21:46:03 asami Exp $ - */ - -#include "npx.h" -#include "opt_bounce.h" - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/proc.h> -#include <sys/malloc.h> -#include <sys/buf.h> -#include <sys/vnode.h> -#include <sys/vmmeter.h> - -#include <machine/clock.h> -#include <machine/md_var.h> - -#include <vm/vm.h> -#include <vm/vm_param.h> -#include <vm/vm_prot.h> -#include <vm/lock.h> -#include <vm/vm_kern.h> -#include <vm/vm_page.h> -#include <vm/vm_map.h> -#include <vm/vm_extern.h> - -#include <sys/user.h> - -#ifdef PC98 -#include <pc98/pc98/pc98.h> -#include <pc98/pc98/epsonio.h> -#else -#include <i386/isa/isa.h> -#endif - -#ifdef BOUNCE_BUFFERS -static vm_offset_t - vm_bounce_kva __P((int size, int waitok)); -static void vm_bounce_kva_free __P((vm_offset_t addr, vm_offset_t size, - int now)); -static vm_offset_t - vm_bounce_page_find __P((int count)); -static void vm_bounce_page_free __P((vm_offset_t pa, int count)); - -static volatile int kvasfreecnt; - -caddr_t bouncememory; -int bouncepages; -static int bpwait; -static vm_offset_t *bouncepa; -static int bmwait, bmfreeing; - -#define BITS_IN_UNSIGNED (8*sizeof(unsigned)) -static int bounceallocarraysize; -static unsigned *bounceallocarray; -static int bouncefree; - -#if defined(PC98) && defined (EPSON_BOUNCEDMA) -#define SIXTEENMEG (3840*4096) /* 15MB boundary */ -#else -#define SIXTEENMEG (4096*4096) -#endif -#define MAXBKVA 1024 -int maxbkva = MAXBKVA*PAGE_SIZE; - -/* special list that can be used at interrupt time for eventual kva free */ -static struct kvasfree { - vm_offset_t addr; - vm_offset_t size; -} kvaf[MAXBKVA]; - -/* - * get bounce buffer pages (count physically contiguous) - * (only 1 inplemented now) - */ -static vm_offset_t -vm_bounce_page_find(count) - int count; -{ - int bit; - int s,i; - - if (count != 1) - panic("vm_bounce_page_find -- no support for > 1 page yet!!!"); - - s = splbio(); -retry: - for (i = 0; i < bounceallocarraysize; i++) { - if (bounceallocarray[i] != 0xffffffff) { - bit = ffs(~bounceallocarray[i]); - if (bit) { - bounceallocarray[i] |= 1 << (bit - 1) ; - bouncefree -= count; - splx(s); - return bouncepa[(i * BITS_IN_UNSIGNED + (bit - 1))]; - } - } - } - bpwait = 1; - tsleep((caddr_t) &bounceallocarray, PRIBIO, "bncwai", 0); - goto retry; -} - -static void -vm_bounce_kva_free(addr, size, now) - vm_offset_t addr; - vm_offset_t size; - int now; -{ - int s = splbio(); - kvaf[kvasfreecnt].addr = addr; - kvaf[kvasfreecnt].size = size; - ++kvasfreecnt; - if( now) { - /* - * this will do wakeups - */ - vm_bounce_kva(0,0); - } else { - if (bmwait) { - /* - * if anyone is waiting on the bounce-map, then wakeup - */ - wakeup((caddr_t) io_map); - bmwait = 0; - } - } - splx(s); -} - -/* - * free count bounce buffer pages - */ -static void -vm_bounce_page_free(pa, count) - vm_offset_t pa; - int count; -{ - int allocindex; - int index; - int bit; - - if (count != 1) - panic("vm_bounce_page_free -- no support for > 1 page yet!!!"); - - for(index=0;index<bouncepages;index++) { - if( pa == bouncepa[index]) - break; - } - - if( index == bouncepages) - panic("vm_bounce_page_free: invalid bounce buffer"); - - allocindex = index / BITS_IN_UNSIGNED; - bit = index % BITS_IN_UNSIGNED; - - bounceallocarray[allocindex] &= ~(1 << bit); - - bouncefree += count; - if (bpwait) { - bpwait = 0; - wakeup((caddr_t) &bounceallocarray); - } -} - -/* - * allocate count bounce buffer kva pages - */ -static vm_offset_t -vm_bounce_kva(size, waitok) - int size; - int waitok; -{ - int i; - vm_offset_t kva = 0; - vm_offset_t off; - int s = splbio(); -more: - if (!bmfreeing && kvasfreecnt) { - bmfreeing = 1; - for (i = 0; i < kvasfreecnt; i++) { - for(off=0;off<kvaf[i].size;off+=PAGE_SIZE) { - pmap_kremove( kvaf[i].addr + off); - } - kmem_free_wakeup(io_map, kvaf[i].addr, - kvaf[i].size); - } - kvasfreecnt = 0; - bmfreeing = 0; - if( bmwait) { - bmwait = 0; - wakeup( (caddr_t) io_map); - } - } - - if( size == 0) { - splx(s); - return 0; - } - - if ((kva = kmem_alloc_pageable(io_map, size)) == 0) { - if( !waitok) { - splx(s); - return 0; - } - bmwait = 1; - tsleep((caddr_t) io_map, PRIBIO, "bmwait", 0); - goto more; - } - splx(s); - return kva; -} - -/* - * same as vm_bounce_kva -- but really allocate (but takes pages as arg) - */ -vm_offset_t -vm_bounce_kva_alloc(count) -int count; -{ - int i; - vm_offset_t kva; - vm_offset_t pa; - if( bouncepages == 0) { - kva = (vm_offset_t) malloc(count*PAGE_SIZE, M_TEMP, M_WAITOK); - return kva; - } - kva = vm_bounce_kva(count*PAGE_SIZE, 1); - for(i=0;i<count;i++) { - pa = vm_bounce_page_find(1); - pmap_kenter(kva + i * PAGE_SIZE, pa); - } - return kva; -} - -/* - * same as vm_bounce_kva_free -- but really free - */ -void -vm_bounce_kva_alloc_free(kva, count) - vm_offset_t kva; - int count; -{ - int i; - vm_offset_t pa; - if( bouncepages == 0) { - free((caddr_t) kva, M_TEMP); - return; - } - for(i = 0; i < count; i++) { - pa = pmap_kextract(kva + i * PAGE_SIZE); - vm_bounce_page_free(pa, 1); - } - vm_bounce_kva_free(kva, count*PAGE_SIZE, 0); -} - -/* - * do the things necessary to the struct buf to implement - * bounce buffers... inserted before the disk sort - */ -void -vm_bounce_alloc(bp) - struct buf *bp; -{ - int countvmpg; - vm_offset_t vastart, vaend; - vm_offset_t vapstart, vapend; - vm_offset_t va, kva; - vm_offset_t pa; - int dobounceflag = 0; - int i; - - if (bouncepages == 0) - return; - - if (bp->b_flags & B_BOUNCE) { - printf("vm_bounce_alloc: called recursively???\n"); - return; - } - - if (bp->b_bufsize < bp->b_bcount) { - printf( - "vm_bounce_alloc: b_bufsize(0x%lx) < b_bcount(0x%lx) !!\n", - bp->b_bufsize, bp->b_bcount); - panic("vm_bounce_alloc"); - } - -/* - * This is not really necessary - * if( bp->b_bufsize != bp->b_bcount) { - * printf("size: %d, count: %d\n", bp->b_bufsize, bp->b_bcount); - * } - */ - - - vastart = (vm_offset_t) bp->b_data; - vaend = (vm_offset_t) bp->b_data + bp->b_bufsize; - - vapstart = trunc_page(vastart); - vapend = round_page(vaend); - countvmpg = (vapend - vapstart) / PAGE_SIZE; - -/* - * if any page is above 16MB, then go into bounce-buffer mode - */ - va = vapstart; - for (i = 0; i < countvmpg; i++) { - pa = pmap_kextract(va); - if (pa >= SIXTEENMEG) - ++dobounceflag; - if( pa == 0) - panic("vm_bounce_alloc: Unmapped page"); - va += PAGE_SIZE; - } - if (dobounceflag == 0) - return; - - if (bouncepages < dobounceflag) - panic("Not enough bounce buffers!!!"); - -/* - * allocate a replacement kva for b_addr - */ - kva = vm_bounce_kva(countvmpg*PAGE_SIZE, 1); -#if 0 - printf("%s: vapstart: %x, vapend: %x, countvmpg: %d, kva: %x ", - (bp->b_flags & B_READ) ? "read":"write", - vapstart, vapend, countvmpg, kva); -#endif - va = vapstart; - for (i = 0; i < countvmpg; i++) { - pa = pmap_kextract(va); - if (pa >= SIXTEENMEG) { - /* - * allocate a replacement page - */ - vm_offset_t bpa = vm_bounce_page_find(1); - pmap_kenter(kva + (PAGE_SIZE * i), bpa); -#if 0 - printf("r(%d): (%x,%x,%x) ", i, va, pa, bpa); -#endif - /* - * if we are writing, the copy the data into the page - */ - if ((bp->b_flags & B_READ) == 0) { - bcopy((caddr_t) va, (caddr_t) kva + (PAGE_SIZE * i), PAGE_SIZE); - } - } else { - /* - * use original page - */ - pmap_kenter(kva + (PAGE_SIZE * i), pa); - } - va += PAGE_SIZE; - } - -/* - * flag the buffer as being bounced - */ - bp->b_flags |= B_BOUNCE; -/* - * save the original buffer kva - */ - bp->b_savekva = bp->b_data; -/* - * put our new kva into the buffer (offset by original offset) - */ - bp->b_data = (caddr_t) (((vm_offset_t) kva) | - ((vm_offset_t) bp->b_savekva & PAGE_MASK)); -#if 0 - printf("b_savekva: %x, newva: %x\n", bp->b_savekva, bp->b_data); -#endif - return; -} - -/* - * hook into biodone to free bounce buffer - */ -void -vm_bounce_free(bp) - struct buf *bp; -{ - int i; - vm_offset_t origkva, bouncekva, bouncekvaend; - -/* - * if this isn't a bounced buffer, then just return - */ - if ((bp->b_flags & B_BOUNCE) == 0) - return; - -/* - * This check is not necessary - * if (bp->b_bufsize != bp->b_bcount) { - * printf("vm_bounce_free: b_bufsize=%d, b_bcount=%d\n", - * bp->b_bufsize, bp->b_bcount); - * } - */ - - origkva = (vm_offset_t) bp->b_savekva; - bouncekva = (vm_offset_t) bp->b_data; -/* - printf("free: %d ", bp->b_bufsize); -*/ - -/* - * check every page in the kva space for b_addr - */ - for (i = 0; i < bp->b_bufsize; ) { - vm_offset_t mybouncepa; - vm_offset_t copycount; - - copycount = round_page(bouncekva + 1) - bouncekva; - mybouncepa = pmap_kextract(trunc_page(bouncekva)); - -/* - * if this is a bounced pa, then process as one - */ - if ( mybouncepa != pmap_kextract( trunc_page( origkva))) { - vm_offset_t tocopy = copycount; - if (i + tocopy > bp->b_bufsize) - tocopy = bp->b_bufsize - i; -/* - * if this is a read, then copy from bounce buffer into original buffer - */ - if (bp->b_flags & B_READ) - bcopy((caddr_t) bouncekva, (caddr_t) origkva, tocopy); -/* - * free the bounce allocation - */ - -/* - printf("(kva: %x, pa: %x)", bouncekva, mybouncepa); -*/ - vm_bounce_page_free(mybouncepa, 1); - } - - origkva += copycount; - bouncekva += copycount; - i += copycount; - } - -/* - printf("\n"); -*/ -/* - * add the old kva into the "to free" list - */ - - bouncekva= trunc_page((vm_offset_t) bp->b_data); - bouncekvaend= round_page((vm_offset_t)bp->b_data + bp->b_bufsize); - -/* - printf("freeva: %d\n", (bouncekvaend - bouncekva) / PAGE_SIZE); -*/ - vm_bounce_kva_free( bouncekva, (bouncekvaend - bouncekva), 0); - bp->b_data = bp->b_savekva; - bp->b_savekva = 0; - bp->b_flags &= ~B_BOUNCE; - - return; -} - - -/* - * init the bounce buffer system - */ -void -vm_bounce_init() -{ - int i; - - kvasfreecnt = 0; - - if (bouncepages == 0) - return; - - bounceallocarraysize = (bouncepages + BITS_IN_UNSIGNED - 1) / BITS_IN_UNSIGNED; - bounceallocarray = malloc(bounceallocarraysize * sizeof(unsigned), M_TEMP, M_NOWAIT); - - if (!bounceallocarray) - panic("Cannot allocate bounce resource array"); - - bouncepa = malloc(bouncepages * sizeof(vm_offset_t), M_TEMP, M_NOWAIT); - if (!bouncepa) - panic("Cannot allocate physical memory array"); - - for(i=0;i<bounceallocarraysize;i++) { - bounceallocarray[i] = 0xffffffff; - } - - for(i=0;i<bouncepages;i++) { - vm_offset_t pa; - if( (pa = pmap_kextract((vm_offset_t) bouncememory + i * PAGE_SIZE)) >= SIXTEENMEG) - panic("bounce memory out of range"); - if( pa == 0) - panic("bounce memory not resident"); - bouncepa[i] = pa; - bounceallocarray[i/(8*sizeof(int))] &= ~(1<<(i%(8*sizeof(int)))); - } - bouncefree = bouncepages; - -} -#endif /* BOUNCE_BUFFERS */ - -/* - * quick version of vm_fault - */ -void -vm_fault_quick(v, prot) - caddr_t v; - int prot; -{ - if (prot & VM_PROT_WRITE) - subyte(v, fubyte(v)); - else - fubyte(v); -} - -/* - * Finish a fork operation, with process p2 nearly set up. - * Copy and update the kernel stack and pcb, making the child - * ready to run, and marking it so that it can return differently - * than the parent. Returns 1 in the child process, 0 in the parent. - * We currently double-map the user area so that the stack is at the same - * address in each process; in the future we will probably relocate - * the frame pointers on the stack after copying. - */ -int -cpu_fork(p1, p2) - register struct proc *p1, *p2; -{ - struct pcb *pcb2 = &p2->p_addr->u_pcb; - int sp, offset; - volatile int retval; - - /* - * Copy pcb and stack from proc p1 to p2. - * We do this as cheaply as possible, copying only the active - * part of the stack. The stack and pcb need to agree; - * this is tricky, as the final pcb is constructed by savectx, - * but its frame isn't yet on the stack when the stack is copied. - * This should be done differently, with a single call - * that copies and updates the pcb+stack, - * replacing the bcopy and savectx. - */ - - __asm __volatile("movl %%esp,%0" : "=r" (sp)); - offset = sp - (int)kstack; - - retval = 1; /* return 1 in child */ - bcopy((caddr_t)kstack + offset, (caddr_t)p2->p_addr + offset, - (unsigned) ctob(UPAGES) - offset); - p2->p_md.md_regs = p1->p_md.md_regs; - - *pcb2 = p1->p_addr->u_pcb; - pcb2->pcb_cr3 = vtophys(p2->p_vmspace->vm_pmap.pm_pdir); - - retval = 0; /* return 0 in parent */ - savectx(pcb2); - return (retval); -} - -void -cpu_exit(p) - register struct proc *p; -{ -#ifdef USER_LDT - struct pcb *pcb; -#endif - -#if NNPX > 0 - npxexit(p); -#endif /* NNPX */ -#ifdef USER_LDT - pcb = &p->p_addr->u_pcb; - if (pcb->pcb_ldt != 0) { - if (pcb == curpcb) - lldt(GSEL(GUSERLDT_SEL, SEL_KPL)); - kmem_free(kernel_map, (vm_offset_t)pcb->pcb_ldt, - pcb->pcb_ldt_len * sizeof(union descriptor)); - pcb->pcb_ldt_len = (int)pcb->pcb_ldt = 0; - } -#endif - cnt.v_swtch++; - cpu_switch(p); - panic("cpu_exit"); -} - -void -cpu_wait(p) - struct proc *p; -{ - /* drop per-process resources */ - pmap_dispose_proc(p); - vmspace_free(p->p_vmspace); -} - -/* - * Dump the machine specific header information at the start of a core dump. - */ -int -cpu_coredump(p, vp, cred) - struct proc *p; - struct vnode *vp; - struct ucred *cred; -{ - - return (vn_rdwr(UIO_WRITE, vp, (caddr_t) p->p_addr, ctob(UPAGES), - (off_t)0, UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *)NULL, - p)); -} - -#ifdef notyet -static void -setredzone(pte, vaddr) - u_short *pte; - caddr_t vaddr; -{ -/* eventually do this by setting up an expand-down stack segment - for ss0: selector, allowing stack access down to top of u. - this means though that protection violations need to be handled - thru a double fault exception that must do an integral task - switch to a known good context, within which a dump can be - taken. a sensible scheme might be to save the initial context - used by sched (that has physical memory mapped 1:1 at bottom) - and take the dump while still in mapped mode */ -} -#endif - -/* - * Convert kernel VA to physical address - */ -u_long -kvtop(void *addr) -{ - vm_offset_t va; - - va = pmap_kextract((vm_offset_t)addr); - if (va == 0) - panic("kvtop: zero page frame"); - return((int)va); -} - -/* - * Map an IO request into kernel virtual address space. - * - * All requests are (re)mapped into kernel VA space. - * Notice that we use b_bufsize for the size of the buffer - * to be mapped. b_bcount might be modified by the driver. - */ -void -vmapbuf(bp) - register struct buf *bp; -{ - register caddr_t addr, v, kva; - vm_offset_t pa; - - if ((bp->b_flags & B_PHYS) == 0) - panic("vmapbuf"); - - for (v = bp->b_saveaddr, addr = (caddr_t)trunc_page(bp->b_data); - addr < bp->b_data + bp->b_bufsize; - addr += PAGE_SIZE, v += PAGE_SIZE) { - /* - * Do the vm_fault if needed; do the copy-on-write thing - * when reading stuff off device into memory. - */ - vm_fault_quick(addr, - (bp->b_flags&B_READ)?(VM_PROT_READ|VM_PROT_WRITE):VM_PROT_READ); - pa = trunc_page(pmap_kextract((vm_offset_t) addr)); - if (pa == 0) - panic("vmapbuf: page not present"); - vm_page_hold(PHYS_TO_VM_PAGE(pa)); - pmap_kenter((vm_offset_t) v, pa); - } - - kva = bp->b_saveaddr; - bp->b_saveaddr = bp->b_data; - bp->b_data = kva + (((vm_offset_t) bp->b_data) & PAGE_MASK); -} - -/* - * Free the io map PTEs associated with this IO operation. - * We also invalidate the TLB entries and restore the original b_addr. - */ -void -vunmapbuf(bp) - register struct buf *bp; -{ - register caddr_t addr; - vm_offset_t pa; - - if ((bp->b_flags & B_PHYS) == 0) - panic("vunmapbuf"); - - for (addr = (caddr_t)trunc_page(bp->b_data); - addr < bp->b_data + bp->b_bufsize; - addr += PAGE_SIZE) { - pa = trunc_page(pmap_kextract((vm_offset_t) addr)); - pmap_kremove((vm_offset_t) addr); - vm_page_unhold(PHYS_TO_VM_PAGE(pa)); - } - - bp->b_data = bp->b_saveaddr; -} - -/* - * Force reset the processor by invalidating the entire address space! - */ -void -cpu_reset() { -#ifdef PC98 - asm(" cli "); - outb(0x37, 0x0f); /* SHUT 0 = 0 */ - outb(0x37, 0x0b); /* SHUT 1 = 0 */ - if ((pc98_machine_type & M_EPSON_PC98) - && (epson_machine_id == 0x20 /*note A*/)) { - epson_outb(0xc17, epson_inb(0xc17) | 0x40); - /* reset port for NOTE_A */ - } - outb(0xf0, 0x00); /* reset port */ -#else /* IBM-PC */ - - /* - * Attempt to do a CPU reset via the keyboard controller, - * do not turn of the GateA20, as any machine that fails - * to do the reset here would then end up in no man's land. - */ - -#ifndef BROKEN_KEYBOARD_RESET - outb(IO_KBD + 4, 0xFE); - DELAY(500000); /* wait 0.5 sec to see if that did it */ - printf("Keyboard reset did not work, attempting CPU shutdown\n"); - DELAY(1000000); /* wait 1 sec for printf to complete */ -#endif - - /* force a shutdown by unmapping entire address space ! */ - bzero((caddr_t) PTD, PAGE_SIZE); - - /* "good night, sweet prince .... <THUNK!>" */ - invltlb(); -#endif - /* NOTREACHED */ - while(1); -} - -/* - * Grow the user stack to allow for 'sp'. This version grows the stack in - * chunks of SGROWSIZ. - */ -int -grow(p, sp) - struct proc *p; - u_int sp; -{ - unsigned int nss; - caddr_t v; - struct vmspace *vm = p->p_vmspace; - - if ((caddr_t)sp <= vm->vm_maxsaddr || (unsigned)sp >= (unsigned)USRSTACK) - return (1); - - nss = roundup(USRSTACK - (unsigned)sp, PAGE_SIZE); - - if (nss > p->p_rlimit[RLIMIT_STACK].rlim_cur) - return (0); - - if (vm->vm_ssize && roundup(vm->vm_ssize << PAGE_SHIFT, - SGROWSIZ) < nss) { - int grow_amount; - /* - * If necessary, grow the VM that the stack occupies - * to allow for the rlimit. This allows us to not have - * to allocate all of the VM up-front in execve (which - * is expensive). - * Grow the VM by the amount requested rounded up to - * the nearest SGROWSIZ to provide for some hysteresis. - */ - grow_amount = roundup((nss - (vm->vm_ssize << PAGE_SHIFT)), SGROWSIZ); - v = (char *)USRSTACK - roundup(vm->vm_ssize << PAGE_SHIFT, - SGROWSIZ) - grow_amount; - /* - * If there isn't enough room to extend by SGROWSIZ, then - * just extend to the maximum size - */ - if (v < vm->vm_maxsaddr) { - v = vm->vm_maxsaddr; - grow_amount = MAXSSIZ - (vm->vm_ssize << PAGE_SHIFT); - } - if ((grow_amount == 0) || (vm_map_find(&vm->vm_map, NULL, 0, (vm_offset_t *)&v, - grow_amount, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0) != KERN_SUCCESS)) { - return (0); - } - vm->vm_ssize += grow_amount >> PAGE_SHIFT; - } - - return (1); -} - -/* - * prototype routine to implement the pre-zeroed page mechanism - * this routine is called from the idle loop. - */ -int -vm_page_zero_idle() { - vm_page_t m; - static int free_rover = 0; - if ((cnt.v_free_count > cnt.v_interrupt_free_min) && - (m = vm_page_list_find(PQ_FREE, free_rover))) { - --(*vm_page_queues[m->queue].lcnt); - TAILQ_REMOVE(vm_page_queues[m->queue].pl, m, pageq); - enable_intr(); - pmap_zero_page(VM_PAGE_TO_PHYS(m)); - disable_intr(); - m->queue = PQ_ZERO + m->pc; - ++(*vm_page_queues[m->queue].lcnt); - TAILQ_INSERT_HEAD(vm_page_queues[m->queue].pl, m, pageq); - free_rover = (free_rover + PQ_PRIME3) & PQ_L2_MASK; - ++vm_page_zero_count; - return 1; - } - return 0; -} diff --git a/sys/pc98/pc98/aic6360.c b/sys/pc98/pc98/aic6360.c deleted file mode 100644 index cbec0c0..0000000 --- a/sys/pc98/pc98/aic6360.c +++ /dev/null @@ -1,2436 +0,0 @@ -/* - * Copyright (c) 1994 Charles Hannum. - * Copyright (c) 1994 Jarle Greipsland - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Jarle Greipsland - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * $Id: aic6360.c,v 1.4 1996/09/10 09:37:43 asami Exp $ - * - * Acknowledgements: Many of the algorithms used in this driver are - * inspired by the work of Julian Elischer (julian@tfs.com) and - * Charles Hannum (mycroft@duality.gnu.ai.mit.edu). Thanks a million! - * - * Converted from NetBSD to FreeBSD by Jim Babb - */ - -/* TODO list: - * 1) Get the DMA stuff working. - * 2) Get the iov/uio stuff working. Is this a good thing ??? - * 3) Get the synch stuff working. - * 4) Rewrite it to use malloc for the acb structs instead of static alloc.? - */ - -/* - * PC-9801-100/AHA-1030P support by URATA S. - */ - -/* - * A few customizable items: - */ - -/* The SCSI ID of the host adapter/computer */ -#ifndef AIC_SCSI_HOSTID -#define AIC_SCSI_HOSTID 7 -#endif - -/* Use doubleword transfers to/from SCSI chip. Note: This requires - * motherboard support. Basicly, some motherboard chipsets are able to - * split a 32 bit I/O operation into two 16 bit I/O operations, - * transparently to the processor. This speeds up some things, notably long - * data transfers. - */ -#define AIC_USE_DWORDS 0 - -/* Allow disconnects? Was mainly used in an early phase of the driver when - * the message system was very flaky. Should go away soon. - */ -#define AIC_ALLOW_DISCONNECT 1 - -/* Synchronous data transfers? (does not work yet!) XXX */ -#define AIC_USE_SYNCHRONOUS 0 /* Enable/disable (1/0) */ -#define AIC_SYNC_PERIOD 200 -#define AIC_SYNC_REQ_ACK_OFS 8 - -/* Max attempts made to transmit a message */ -#define AIC_MSG_MAX_ATTEMPT 3 /* Not used now XXX */ - -/* Use DMA (else we do programmed I/O using string instructions) (not yet!)*/ -#define AIC_USE_EISA_DMA 0 -#define AIC_USE_ISA_DMA 0 - -/* How to behave on the (E)ISA bus when/if DMAing (on<<4) + off in us */ -#define EISA_BRST_TIM ((15<<4) + 1) /* 15us on, 1us off */ - -/* Some spin loop parameters (essentially how long to wait some places) - * The problem(?) is that sometimes we expect either to be able to transmit a - * byte or to get a new one from the SCSI bus pretty soon. In order to avoid - * returning from the interrupt just to get yanked back for the next byte we - * may spin in the interrupt routine waiting for this byte to come. How long? - * This is really (SCSI) device and processor dependent. Tuneable, I guess. - */ -#define AIC_MSGI_SPIN 1 /* Will spinwait upto ?ms for a new msg byte */ -#define AIC_MSGO_SPIN 1 - -/* Include debug functions? At the end of this file there are a bunch of - * functions that will print out various information regarding queued SCSI - * commands, driver state and chip contents. You can call them from the - * kernel debugger. If you set AIC_DEBUG to 0 they are not included (the - * kernel uses less memory) but you lose the debugging facilities. - */ -#define AIC_DEBUG 0 - -/* End of customizable parameters */ - -#if AIC_USE_EISA_DMA || AIC_USE_ISA_DMA -#error "I said not yet! Start paying attention... grumble" -#endif - -#include "opt_ddb.h" -#include "aic.h" - -#include <sys/types.h> -#include <sys/param.h> -#include <sys/kernel.h> -#include <sys/systm.h> -#include <sys/errno.h> -#include <sys/ioctl.h> -#include <sys/malloc.h> -#include <sys/buf.h> -#include <sys/proc.h> -#include <sys/queue.h> -#include <scsi/scsi_all.h> -#include <scsi/scsiconf.h> - -#include <machine/clock.h> -#include <i386/isa/isa_device.h> - -#include <sys/kernel.h> - -/* Definitions, most of them has turned out to be unneccesary, but here they - * are anyway. - */ - -/* - * Generic SCSI messages. For now we reject most of them. - */ -/* Messages (1 byte) */ /* I/T M(andatory) or (O)ptional */ -#define MSG_CMDCOMPLETE 0x00 /* M/M */ -#define MSG_EXTENDED 0x01 /* O/O */ -#define MSG_SAVEDATAPOINTER 0x02 /* O/O */ -#define MSG_RESTOREPOINTERS 0x03 /* O/O */ -#define MSG_DISCONNECT 0x04 /* O/O */ -#define MSG_INITIATOR_DET_ERR 0x05 /* M/M */ -#define MSG_ABORT 0x06 /* O/M */ -#define MSG_MESSAGE_REJECT 0x07 /* M/M */ -#define MSG_NOOP 0x08 /* M/M */ -#define MSG_PARITY_ERR 0x09 /* M/M */ -#define MSG_LINK_CMD_COMPLETE 0x0a /* O/O */ -#define MSG_LINK_CMD_COMPLETEF 0x0b /* O/O */ -#define MSG_BUS_DEV_RESET 0x0c /* O/M */ -#define MSG_ABORT_TAG 0x0d /* O/O */ -#define MSG_CLEAR_QUEUE 0x0e /* O/O */ -#define MSG_INIT_RECOVERY 0x0f /* O/O */ -#define MSG_REL_RECOVERY 0x10 /* O/O */ -#define MSG_TERM_IO_PROC 0x11 /* O/O */ - -/* Messages (2 byte) */ -#define MSG_SIMPLE_Q_TAG 0x20 /* O/O */ -#define MSG_HEAD_OF_Q_TAG 0x21 /* O/O */ -#define MSG_ORDERED_Q_TAG 0x22 /* O/O */ -#define MSG_IGN_WIDE_RESIDUE 0x23 /* O/O */ - -/* Identify message */ -#define MSG_IDENTIFY(lun) ((AIC_ALLOW_DISCONNECT ? 0xc0 : 0x80)|((lun) & 0x7)) -#define MSG_ISIDENT(m) ((m) & 0x80) - -/* Extended messages (opcode) */ -#define MSG_EXT_SDTR 0x01 - -/* SCSI Status codes */ -#define ST_GOOD 0x00 -#define ST_CHKCOND 0x02 -#define ST_CONDMET 0x04 -#define ST_BUSY 0x08 -#define ST_INTERMED 0x10 -#define ST_INTERMED_CONDMET 0x14 -#define ST_RESERVATION_CONFLICT 0x18 -#define ST_CMD_TERM 0x22 -#define ST_QUEUE_FULL 0x28 - -#define ST_MASK 0x3e /* bit 0,6,7 is reserved */ - -/* AIC6360 definitions */ -#ifdef PC98 -#include <pc98/pc98/aic_98.h> -#else -#define SCSISEQ (iobase + 0x00) /* SCSI sequence control */ -#define SXFRCTL0 (iobase + 0x01) /* SCSI transfer control 0 */ -#define SXFRCTL1 (iobase + 0x02) /* SCSI transfer control 1 */ -#define SCSISIGI (iobase + 0x03) /* SCSI signal in */ -#define SCSISIGO (iobase + 0x03) /* SCSI signal out */ -#define SCSIRATE (iobase + 0x04) /* SCSI rate control */ -#define SCSIID (iobase + 0x05) /* SCSI ID */ -#define SELID (iobase + 0x05) /* Selection/Reselection ID */ -#define SCSIDAT (iobase + 0x06) /* SCSI Latched Data */ -#define SCSIBUS (iobase + 0x07) /* SCSI Data Bus*/ -#define STCNT0 (iobase + 0x08) /* SCSI transfer count */ -#define STCNT1 (iobase + 0x09) -#define STCNT2 (iobase + 0x0a) -#define CLRSINT0 (iobase + 0x0b) /* Clear SCSI interrupts 0 */ -#define SSTAT0 (iobase + 0x0b) /* SCSI interrupt status 0 */ -#define CLRSINT1 (iobase + 0x0c) /* Clear SCSI interrupts 1 */ -#define SSTAT1 (iobase + 0x0c) /* SCSI status 1 */ -#define SSTAT2 (iobase + 0x0d) /* SCSI status 2 */ -#define SCSITEST (iobase + 0x0e) /* SCSI test control */ -#define SSTAT3 (iobase + 0x0e) /* SCSI status 3 */ -#define CLRSERR (iobase + 0x0f) /* Clear SCSI errors */ -#define SSTAT4 (iobase + 0x0f) /* SCSI status 4 */ -#define SIMODE0 (iobase + 0x10) /* SCSI interrupt mode 0 */ -#define SIMODE1 (iobase + 0x11) /* SCSI interrupt mode 1 */ -#define DMACNTRL0 (iobase + 0x12) /* DMA control 0 */ -#define DMACNTRL1 (iobase + 0x13) /* DMA control 1 */ -#define DMASTAT (iobase + 0x14) /* DMA status */ -#define FIFOSTAT (iobase + 0x15) /* FIFO status */ -#define DMADATA (iobase + 0x16) /* DMA data */ -#define DMADATAL (iobase + 0x16) /* DMA data low byte */ -#define DMADATAH (iobase + 0x17) /* DMA data high byte */ -#define BRSTCNTRL (iobase + 0x18) /* Burst Control */ -#define DMADATALONG (iobase + 0x18) -#define PORTA (iobase + 0x1a) /* Port A */ -#define PORTB (iobase + 0x1b) /* Port B */ -#define REV (iobase + 0x1c) /* Revision (001 for 6360) */ -#define STACK (iobase + 0x1d) /* Stack */ -#define TEST (iobase + 0x1e) /* Test register */ -#define ID (iobase + 0x1f) /* ID register */ -#endif - -#define IDSTRING "(C)1991ADAPTECAIC6360 " - -/* What all the bits do */ - -/* SCSISEQ */ -#define TEMODEO 0x80 -#define ENSELO 0x40 -#define ENSELI 0x20 -#define ENRESELI 0x10 -#define ENAUTOATNO 0x08 -#define ENAUTOATNI 0x04 -#define ENAUTOATNP 0x02 -#define SCSIRSTO 0x01 - -/* SXFRCTL0 */ -#define SCSIEN 0x80 -#define DMAEN 0x40 -#define CHEN 0x20 -#define CLRSTCNT 0x10 -#define SPIOEN 0x08 -#define CLRCH 0x02 - -/* SXFRCTL1 */ -#define BITBUCKET 0x80 -#define SWRAPEN 0x40 -#define ENSPCHK 0x20 -#define STIMESEL1 0x10 -#define STIMESEL0 0x08 -#define STIMO_256ms 0x00 -#define STIMO_128ms 0x08 -#define STIMO_64ms 0x10 -#define STIMO_32ms 0x18 -#define ENSTIMER 0x04 -#define BYTEALIGN 0x02 - -/* SCSISIGI */ -#define CDI 0x80 -#define IOI 0x40 -#define MSGI 0x20 -#define ATNI 0x10 -#define SELI 0x08 -#define BSYI 0x04 -#define REQI 0x02 -#define ACKI 0x01 - -/* Important! The 3 most significant bits of this register, in initiator mode, - * represents the "expected" SCSI bus phase and can be used to trigger phase - * mismatch and phase change interrupts. But more important: If there is a - * phase mismatch the chip will not transfer any data! This is actually a nice - * feature as it gives us a bit more control over what is happening when we are - * bursting data (in) through the FIFOs and the phase suddenly changes from - * DATA IN to STATUS or MESSAGE IN. The transfer will stop and wait for the - * proper phase to be set in this register instead of dumping the bits into the - * FIFOs. - */ -/* SCSISIGO */ -#define CDO 0x80 -#define CDEXP (CDO) -#define IOO 0x40 -#define IOEXP (IOO) -#define MSGO 0x20 -#define MSGEXP (MSGO) -#define ATNO 0x10 -#define SELO 0x08 -#define BSYO 0x04 -#define REQO 0x02 -#define ACKO 0x01 - -/* Information transfer phases */ -#define PH_DOUT (0) -#define PH_DIN (IOI) -#define PH_CMD (CDI) -#define PH_STAT (CDI|IOI) -#define PH_MSGO (MSGI|CDI) -#define PH_MSGI (MSGI|CDI|IOI) - -#define PH_MASK 0xe0 - -/* Some pseudo phases for getphase()*/ -#define PH_BUSFREE 0x100 /* (Re)Selection no longer valid */ -#define PH_INVALID 0x101 /* (Re)Selection valid, but no REQ yet */ -#define PH_PSBIT 0x100 /* "pseudo" bit */ - -/* SCSIRATE */ -#define SXFR2 0x40 -#define SXFR1 0x20 -#define SXFR0 0x10 -#define SOFS3 0x08 -#define SOFS2 0x04 -#define SOFS1 0x02 -#define SOFS0 0x01 - -/* SCSI ID */ -#define OID2 0x40 -#define OID1 0x20 -#define OID0 0x10 -#define OID_S 4 /* shift value */ -#define TID2 0x04 -#define TID1 0x02 -#define TID0 0x01 -#define SCSI_ID_MASK 0x7 - -/* SCSI selection/reselection ID (both target *and* initiator) */ -#define SELID7 0x80 -#define SELID6 0x40 -#define SELID5 0x20 -#define SELID4 0x10 -#define SELID3 0x08 -#define SELID2 0x04 -#define SELID1 0x02 -#define SELID0 0x01 - -/* CLRSINT0 Clears what? (interrupt and/or status bit) */ -#define SETSDONE 0x80 -#define CLRSELDO 0x40 /* I */ -#define CLRSELDI 0x20 /* I+ */ -#define CLRSELINGO 0x10 /* I */ -#define CLRSWRAP 0x08 /* I+S */ -#define CLRSDONE 0x04 /* I+S */ -#define CLRSPIORDY 0x02 /* I */ -#define CLRDMADONE 0x01 /* I */ - -/* SSTAT0 Howto clear */ -#define TARGET 0x80 -#define SELDO 0x40 /* Selfclearing */ -#define SELDI 0x20 /* Selfclearing when CLRSELDI is set */ -#define SELINGO 0x10 /* Selfclearing */ -#define SWRAP 0x08 /* CLRSWAP */ -#define SDONE 0x04 /* Not used in initiator mode */ -#define SPIORDY 0x02 /* Selfclearing (op on SCSIDAT) */ -#define DMADONE 0x01 /* Selfclearing (all FIFOs empty & T/C */ - -/* CLRSINT1 Clears what? */ -#define CLRSELTIMO 0x80 /* I+S */ -#define CLRATNO 0x40 -#define CLRSCSIRSTI 0x20 /* I+S */ -#define CLRBUSFREE 0x08 /* I+S */ -#define CLRSCSIPERR 0x04 /* I+S */ -#define CLRPHASECHG 0x02 /* I+S */ -#define CLRREQINIT 0x01 /* I+S */ - -/* SSTAT1 How to clear? When set?*/ -#define SELTO 0x80 /* C select out timeout */ -#define ATNTARG 0x40 /* Not used in initiator mode */ -#define SCSIRSTI 0x20 /* C RST asserted */ -#define PHASEMIS 0x10 /* Selfclearing */ -#define BUSFREE 0x08 /* C bus free condition */ -#define SCSIPERR 0x04 /* C parity error on inbound data */ -#define PHASECHG 0x02 /* C phase in SCSISIGI doesn't match */ -#define REQINIT 0x01 /* C or ACK asserting edge of REQ */ - -/* SSTAT2 */ -#define SOFFSET 0x20 -#define SEMPTY 0x10 -#define SFULL 0x08 -#define SFCNT2 0x04 -#define SFCNT1 0x02 -#define SFCNT0 0x01 - -/* SCSITEST */ -#define SCTESTU 0x08 -#define SCTESTD 0x04 -#define STCTEST 0x01 - -/* SSTAT3 */ -#define SCSICNT3 0x80 -#define SCSICNT2 0x40 -#define SCSICNT1 0x20 -#define SCSICNT0 0x10 -#define OFFCNT3 0x08 -#define OFFCNT2 0x04 -#define OFFCNT1 0x02 -#define OFFCNT0 0x01 - -/* CLRSERR */ -#define CLRSYNCERR 0x04 -#define CLRFWERR 0x02 -#define CLRFRERR 0x01 - -/* SSTAT4 */ -#define SYNCERR 0x04 -#define FWERR 0x02 -#define FRERR 0x01 - -/* SIMODE0 */ -#define ENSELDO 0x40 -#define ENSELDI 0x20 -#define ENSELINGO 0x10 -#define ENSWRAP 0x08 -#define ENSDONE 0x04 -#define ENSPIORDY 0x02 -#define ENDMADONE 0x01 - -/* SIMODE1 */ -#define ENSELTIMO 0x80 -#define ENATNTARG 0x40 -#define ENSCSIRST 0x20 -#define ENPHASEMIS 0x10 -#define ENBUSFREE 0x08 -#define ENSCSIPERR 0x04 -#define ENPHASECHG 0x02 -#define ENREQINIT 0x01 - -/* DMACNTRL0 */ -#define ENDMA 0x80 -#define B8MODE 0x40 -#define DMA 0x20 -#define DWORDPIO 0x10 -#define WRITE 0x08 -#define INTEN 0x04 -#define RSTFIFO 0x02 -#define SWINT 0x01 - -/* DMACNTRL1 */ -#define PWRDWN 0x80 -#define ENSTK32 0x40 -#define STK4 0x10 -#define STK3 0x08 -#define STK2 0x04 -#define STK1 0x02 -#define STK0 0x01 - -/* DMASTAT */ -#define ATDONE 0x80 -#define WORDRDY 0x40 -#define INTSTAT 0x20 -#define DFIFOFULL 0x10 -#define DFIFOEMP 0x08 -#define DFIFOHF 0x04 -#define DWORDRDY 0x02 - -/* BRSTCNTRL */ -#define BON3 0x80 -#define BON2 0x40 -#define BON1 0x20 -#define BON0 0x10 -#define BOFF3 0x08 -#define BOFF2 0x04 -#define BOFF1 0x02 -#define BOFF0 0x01 - -/* TEST */ -#define BOFFTMR 0x40 -#define BONTMR 0x20 -#define STCNTH 0x10 -#define STCNTM 0x08 -#define STCNTL 0x04 -#define SCSIBLK 0x02 -#define DMABLK 0x01 - - -#define orreg(reg, val) outb((reg), inb(reg)| (val)) -#define andreg(reg, val) outb((reg), inb(reg)& (val)) -#define nandreg(reg, val) outb((reg), inb(reg)&~(val)) - - - -#ifdef DDB -#define fatal_if_no_DDB() -#else -#define fatal_if_no_DDB() panic("panic for historical reasons") -#endif - -typedef u_long physaddr; - -struct aic_dma_seg { - physaddr addr; - long len; -}; - -#define DELAYCOUNT 16 - -#define FUDGE(X) ((X)>>1) /* get 1 ms spincount */ -#define MINIFUDGE(X) ((X)>>4) /* get (approx) 125us spincount */ -#define AIC_NSEG 16 -#define NUM_CONCURRENT 7 /* Only one per target for now */ - -/* - * ACB. Holds additional information for each SCSI command Comments: We - * need a separate scsi command block because we may need to overwrite it - * with a request sense command. Basicly, we refrain from fiddling with - * the scsi_xfer struct (except do the expected updating of return values). - * We'll generally update: xs->{flags,resid,error,sense,status} and - * occasionally xs->retries. - */ - -struct acb { - TAILQ_ENTRY(acb) chain; - struct scsi_xfer *xs; /* SCSI xfer ctrl block from above */ - int flags; /* Status */ -#define ACB_FREE 0x00 -#define ACB_ACTIVE 0x01 -#define ACB_DONE 0x04 -#define ACB_CHKSENSE 0x08 -/* struct aic_dma_seg dma[AIC_NSEG]; */ /* Physical addresses+len */ - struct scsi_generic cmd; /* SCSI command block */ - int clen; - char *daddr; /* Saved data pointer */ - int dleft; /* Residue */ - int stat; /* SCSI status byte */ -}; - -/* - * Some info about each (possible) target on the SCSI bus. This should - * probably have been a "per target+lunit" structure, but we'll leave it at - * this for now. Is there a way to reliably hook it up to sc->fordriver?? - */ -struct aic_tinfo { - int cmds; /* #commands processed */ - int dconns; /* #disconnects */ - int touts; /* #timeouts */ - int perrs; /* #parity errors */ - int senses; /* #request sense commands sent */ - ushort lubusy; /* What local units/subr. are busy? */ - u_char flags; -#define NEED_TO_RESET 0x01 /* Should send a BUS_DEV_RESET */ -#define DO_NEGOTIATE 0x02 /* (Re)Negotiate synchronous options */ -#define TARGET_BUSY 0x04 /* Target is busy, i.e. cmd in progress */ - u_char persgst; /* Period suggestion */ - u_char offsgst; /* Offset suggestion */ - u_char syncdata; /* True negotiated synch parameters */ -}; - -/* Register a linenumber (for debugging) */ -#if AIC_DEBUG -#define LOGLINE(p) \ - do { \ - p->history[p->hp] = __LINE__; \ - p->hp = ++p->hp % AIC_HSIZE; \ - } while (0) -#else -#define LOGLINE(p) -#endif - -static struct aic_data { /* One of these per adapter */ - u_short iobase; /* Base I/O port */ - struct scsi_link sc_link; /* prototype for subdevs */ - int aic_int; /* IRQ on the EISA bus */ - int aic_dma; /* DRQ on the EISA bus */ - /* Lists of command blocks */ - TAILQ_HEAD(acb_list, acb) free_list, ready_list, nexus_list; - struct acb *nexus; /* current command */ - /* Command blocks and target info */ - struct acb acb[NUM_CONCURRENT]; - struct aic_tinfo tinfo[8]; - /* Data about the current nexus (updated for every cmd switch) */ - u_char *dp; /* Current data pointer */ - int dleft; /* Data left to transfer */ - /* Adapter state */ - short phase; /* Copy of what bus phase we are in */ - short prevphase; /* Copy of what bus phase we were in */ - short state; /* State applicable to the adapter */ -#define AIC_IDLE 0x01 -#define AIC_TMP_UNAVAIL 0x02 /* Don't accept SCSI commands */ -#define AIC_SELECTING 0x03 /* SCSI command is arbiting */ -#define AIC_RESELECTED 0x04 /* Has been reselected */ -#define AIC_HASNEXUS 0x05 /* Actively using the SCSI bus */ -#define AIC_CLEANING 0x06 - short flags; -#define AIC_DROP_MSGI 0x01 /* Discard all msgs (parity err detected) */ -#define AIC_DOINGDMA 0x02 /* The FIFO data path is active! */ -#define AIC_BUSFREE_OK 0x04 /* Bus free phase is OK. */ -#define AIC_SYNCHNEGO 0x08 /* Synch negotiation in progress. */ -#define AIC_BLOCKED 0x10 /* Don't schedule new scsi bus operations */ - /* Debugging stuff */ -#define AIC_HSIZE 8 - short history[AIC_HSIZE]; /* Store line numbers here. */ - short hp; - u_char progress; /* Set if interrupt has achieved progress */ - /* Message stuff */ - u_char msgpriq; /* One or more messages to send (encoded) */ - u_char msgout; /* What message is on its way out? */ -#define SEND_DEV_RESET 0x01 -#define SEND_PARITY_ERROR 0x02 -#define SEND_ABORT 0x04 -#define SEND_REJECT 0x08 -#define SEND_INIT_DET_ERR 0x10 -#define SEND_IDENTIFY 0x20 -#define SEND_SDTR 0x40 -#define AIC_MAX_MSG_LEN 8 - u_char omess[AIC_MAX_MSG_LEN]; /* Scratch area for messages */ - u_char *omp; /* Message pointer (for multibyte messages) */ - u_char omlen; - u_char imess[AIC_MAX_MSG_LEN + 1]; - u_char *imp; /* Message pointer (for multibyte messages) */ - u_char imlen; -#ifdef PC98 - int *aicport; /* I/O port information */ -#endif -} *aicdata[NAIC]; - -#define AIC_SHOWACBS 0x01 -#define AIC_SHOWINTS 0x02 -#define AIC_SHOWCMDS 0x04 -#define AIC_SHOWMISC 0x08 -#define AIC_SHOWTRAC 0x10 -#define AIC_SHOWSTART 0x20 -static int aic_debug = 0; /* AIC_SHOWSTART|AIC_SHOWMISC|AIC_SHOWTRAC; */ - -#if AIC_DEBUG -#define AIC_ACBS(str) do {if (aic_debug & AIC_SHOWACBS) printf str;} while (0) -#define AIC_MISC(str) do {if (aic_debug & AIC_SHOWMISC) printf str;} while (0) -#define AIC_INTS(str) do {if (aic_debug & AIC_SHOWINTS) printf str;} while (0) -#define AIC_TRACE(str) do {if (aic_debug & AIC_SHOWTRAC) printf str;} while (0) -#define AIC_CMDS(str) do {if (aic_debug & AIC_SHOWCMDS) printf str;} while (0) -#define AIC_START(str) do {if (aic_debug & AIC_SHOWSTART) printf str;}while (0) -#else -#define AIC_ACBS(str) -#define AIC_MISC(str) -#define AIC_INTS(str) -#define AIC_TRACE(str) -#define AIC_CMDS(str) -#define AIC_START(str) -#endif - -static int aicprobe __P((struct isa_device *)); -static int aicattach __P((struct isa_device *)); -static void aic_minphys __P((struct buf *)); -static u_int32_t aic_adapter_info __P((int)); -static void aic_init __P((struct aic_data *)); -static int aic_find __P((struct aic_data *)); -static void aic_done __P((struct acb *)); -static void aic_dataout __P((struct aic_data *aic)); -static void aic_datain __P((struct aic_data *aic)); -static int32_t aic_scsi_cmd __P((struct scsi_xfer *)); -static int aic_poll __P((struct aic_data *aic, struct acb *)); -void aic_add_timeout __P((struct acb *, int)); -void aic_remove_timeout __P((struct acb *)); -static void aic6360_reset __P((struct aic_data *aic)); -static u_short aicphase __P((struct aic_data *aic)); -static void aic_msgin __P((struct aic_data *aic)); -static void aic_msgout __P((struct aic_data *aic)); -static timeout_t aic_timeout; -static void aic_sched __P((struct aic_data *)); -static void aic_scsi_reset __P((struct aic_data *)); -#if AIC_DEBUG -void aic_print_active_acb __P((void)); -void aic_dump6360 __P((void)); -void aic_dump_driver __P((void)); -#endif - -/* Linkup to the rest of the kernel */ -struct isa_driver aicdriver = { - aicprobe, aicattach, "aic" -}; - -static int aicunit = 0; - -static struct scsi_adapter aic_switch = { - aic_scsi_cmd, - aic_minphys, - 0, - 0, - aic_adapter_info, - "aic" - ,0 , 0 -}; - -static struct scsi_device aic_dev = { - NULL, /* Use default error handler */ - NULL, /* have a queue, served by this */ - NULL, /* have no async handler */ - NULL, /* Use default 'done' routine */ - "aic", - 0 -}; - - -/* - * INITIALIZATION ROUTINES (probe, attach ++) - */ - -/* - * aicprobe: probe for AIC6360 SCSI-controller - * returns non-zero value if a controller is found. - */ -static int -aicprobe(dev) - struct isa_device *dev; -{ - int unit = aicunit; - struct aic_data *aic; - - if (unit >= NAIC) { - printf("aic%d: unit number too high\n", unit); - return 0; - } - dev->id_unit = unit; - /* - * Allocate a storage area for us - */ - if (aicdata[unit]) { - printf("aic%d: memory already allocated\n", unit); - return 0; - } - aic = malloc(sizeof(struct aic_data), M_TEMP, M_NOWAIT); - if (!aic) { - printf("aic%d: cannot malloc!\n", unit); - return 0; - } - bzero(aic, sizeof(struct aic_data)); - aicdata[unit] = aic; - aic->iobase = dev->id_iobase; -#ifdef PC98 - if (AIC_TYPE98(dev->id_flags) == AIC98_100) { - /* PC-9801-100 */ - aic->aicport = aicport_100; - } else { - /* generic card */ - aic->aicport = aicport_generic; - } -#endif - - if (aic_find(aic) != 0) { - aicdata[unit] = NULL; - free(aic, M_TEMP); - return 0; - } - aicunit++; -#ifdef PC98 - return 0x40; -#else - return 0x20; -#endif -} - -/* Do the real search-for-device. - * Prerequisite: aic->iobase should be set to the proper value - */ -static int -aic_find(aic) - struct aic_data *aic; -{ - u_short iobase = aic->iobase; - char chip_id[sizeof(IDSTRING)]; /* For chips that support it */ - int i; - - /* Remove aic6360 from possible powerdown mode */ - outb(DMACNTRL0, 0); - - /* Thanks to mark@aggregate.com for the new method for detecting - * whether the chip is present or not. Bonus: may also work for - * the AIC-6260! - */ - AIC_TRACE(("aic: probing for aic-chip at port 0x%x\n",(int)iobase)); - /* - * Linux also init's the stack to 1-16 and then clears it, - * 6260's don't appear to have an ID reg - mpg - */ - /* Push the sequence 0,1,..,15 on the stack */ -#define STSIZE 16 - outb(DMACNTRL1, 0); /* Reset stack pointer */ - for (i = 0; i < STSIZE; i++) - outb(STACK, i); - - /* See if we can pull out the same sequence */ - outb(DMACNTRL1, 0); - for (i = 0; i < STSIZE && inb(STACK) == i; i++) - ; - if (i != STSIZE) { - AIC_START(("STACK futzed at %d.\n", i)); - return ENXIO; - } - - /* See if we can pull the id string out of the ID register, - * now only used for informational purposes. - */ - bzero(chip_id, sizeof(chip_id)); - insb(ID, chip_id, sizeof(IDSTRING)-1); - AIC_START(("AIC found at 0x%x ", (int)aic->iobase)); - AIC_START(("ID: %s ",chip_id)); - AIC_START(("chip revision %d\n",(int)inb(REV))); - return 0; -} - - -/* - * Attach the AIC6360, fill out some high and low level data structures - */ -static int -aicattach(dev) - struct isa_device *dev; -{ - int unit = dev->id_unit; - struct aic_data *aic = aicdata[unit]; - struct scsibus_data *scbus; - - AIC_TRACE(("aicattach\n")); - aic->state = 0; - aic_scsi_reset(aic); - aic_init(aic); /* Init chip and driver */ - - /* - * Fill in the prototype scsi_link - */ - aic->sc_link.adapter_unit = unit; - aic->sc_link.adapter_targ = AIC_SCSI_HOSTID; - aic->sc_link.adapter_softc = aic; - aic->sc_link.adapter = &aic_switch; - aic->sc_link.device = &aic_dev; - - /* - * Prepare the scsibus_data area for the upperlevel - * scsi code. - */ - scbus = scsi_alloc_bus(); - if(!scbus) - return 0; - scbus->adapter_link = &aic->sc_link; - - /* - * ask the adapter what subunits are present - */ - scsi_attachdevs(scbus); - - return 1; -} - - -/* Initialize AIC6360 chip itself - * The following conditions should hold: - * aicprobe should have succeeded, i.e. the iobase address in aic_data must - * be valid. - */ -static void -aic6360_reset(aic) - struct aic_data *aic; -{ - u_short iobase = aic->iobase; - - outb(SCSITEST, 0); /* Doc. recommends to clear these two */ - outb(TEST, 0); /* registers before operations commence */ - - /* Reset SCSI-FIFO and abort any transfers */ - outb(SXFRCTL0, CHEN|CLRCH|CLRSTCNT); - - /* Reset DMA-FIFO */ - outb(DMACNTRL0, RSTFIFO); - outb(DMACNTRL1, 0); - - outb(SCSISEQ, 0); /* Disable all selection features */ - outb(SXFRCTL1, 0); - - outb(SIMODE0, 0x00); /* Disable some interrupts */ - outb(CLRSINT0, 0x7f); /* Clear a slew of interrupts */ - - outb(SIMODE1, 0x00); /* Disable some more interrupts */ - outb(CLRSINT1, 0xef); /* Clear another slew of interrupts */ - - outb(SCSIRATE, 0); /* Disable synchronous transfers */ - - outb(CLRSERR, 0x07); /* Haven't seen ant errors (yet) */ - - outb(SCSIID, AIC_SCSI_HOSTID << OID_S); /* Set our SCSI-ID */ - outb(BRSTCNTRL, EISA_BRST_TIM); -} - -/* Pull the SCSI RST line for 500 us */ -static void -aic_scsi_reset(aic) - struct aic_data *aic; -{ - u_short iobase = aic->iobase; - - outb(SCSISEQ, SCSIRSTO); - DELAY(500); - outb(SCSISEQ, 0); - DELAY(50); -} - -/* - * Initialize aic SCSI driver, also (conditonally) reset the SCSI bus. - * The reinitialization is still buggy (e.g. on SCSI resets). - */ -static void -aic_init(aic) - struct aic_data *aic; -{ - u_short iobase = aic->iobase; - struct acb *acb; - int r; - - /* Reset the SCSI-bus itself */ - aic_scsi_reset(aic); - - aic6360_reset(aic); /* Clean up our own hardware */ - -/*XXX*/ /* If not the first time (probably a reset condition), - * we should clean queues with active commands - */ - if (aic->state == 0) { /* First time through */ - TAILQ_INIT(&aic->ready_list); - TAILQ_INIT(&aic->nexus_list); - TAILQ_INIT(&aic->free_list); - aic->nexus = 0; - acb = aic->acb; - bzero(acb, sizeof(aic->acb)); - for (r = 0; r < sizeof(aic->acb) / sizeof(*acb); r++) { - TAILQ_INSERT_TAIL(&aic->free_list, acb, chain); - acb++; - } - bzero(&aic->tinfo, sizeof(aic->tinfo)); - } else { - aic->state = AIC_CLEANING; - if (aic->nexus != NULL) { - aic->nexus->xs->error = XS_DRIVER_STUFFUP; - untimeout(aic_timeout, (caddr_t)aic->nexus); - aic_done(aic->nexus); - } - aic->nexus = NULL; - while (acb = aic->nexus_list.tqh_first) { - acb->xs->error = XS_DRIVER_STUFFUP; - untimeout(aic_timeout, (caddr_t)acb); - aic_done(acb); - } - } - - aic->phase = aic->prevphase = PH_INVALID; - aic->hp = 0; - for (r = 0; r < 7; r++) { - struct aic_tinfo *tp = &aic->tinfo[r]; - tp->flags = AIC_USE_SYNCHRONOUS ? DO_NEGOTIATE : 0; - tp->flags |= NEED_TO_RESET; - tp->persgst = AIC_SYNC_PERIOD; - tp->offsgst = AIC_SYNC_REQ_ACK_OFS; - tp->syncdata = 0; - } - aic->state = AIC_IDLE; - outb(DMACNTRL0, INTEN); - return; -} - -/* - * DRIVER FUNCTIONS CALLABLE FROM HIGHER LEVEL DRIVERS - */ - -/* - * Expected sequence: - * 1) Command inserted into ready list - * 2) Command selected for execution - * 3) Command won arbitration and has selected target device - * 4) Send message out (identify message, eventually also sync.negotiations) - * 5) Send command - * 5a) Receive disconnect message, disconnect. - * 5b) Reselected by target - * 5c) Receive identify message from target. - * 6) Send or receive data - * 7) Receive status - * 8) Receive message (command complete etc.) - * 9) If status == SCSI_CHECK construct a synthetic request sense SCSI cmd. - * Repeat 2-8 (no disconnects please...) - */ - -/* - * Start a SCSI-command - * This function is called by the higher level SCSI-driver to queue/run - * SCSI-commands. - */ -static int32_t -aic_scsi_cmd(xs) - struct scsi_xfer *xs; -{ - struct scsi_link *sc = xs->sc_link; - struct aic_data *aic; - struct acb *acb; - int s = 0; - int flags; - - aic = (struct aic_data *)sc->adapter_softc; - SC_DEBUG(sc, SDEV_DB2, ("aic_scsi_cmd\n")); - AIC_TRACE(("aic_scsi_cmd\n")); - AIC_MISC(("[0x%x, %d]->%d ", (int)xs->cmd->opcode, xs->cmdlen, - sc->target)); - - flags = xs->flags; - - /* Get a aic command block */ - if (!(flags & SCSI_NOMASK)) { - /* Critical region */ - s = splbio(); - acb = aic->free_list.tqh_first; - if (acb) { - TAILQ_REMOVE(&aic->free_list, acb, chain); - } - splx(s); - } else { - acb = aic->free_list.tqh_first; - if (acb) { - TAILQ_REMOVE(&aic->free_list, acb, chain); - } - } - - if (acb == NULL) { - xs->error = XS_DRIVER_STUFFUP; - AIC_MISC(("TRY_AGAIN_LATER")); - return TRY_AGAIN_LATER; - } - - /* Initialize acb */ - acb->flags = ACB_ACTIVE; - acb->xs = xs; - bcopy(xs->cmd, &acb->cmd, xs->cmdlen); - acb->clen = xs->cmdlen; - acb->daddr = xs->data; - acb->dleft = xs->datalen; - acb->stat = 0; - - if (!(flags & SCSI_NOMASK)) - s = splbio(); - - TAILQ_INSERT_TAIL(&aic->ready_list, acb, chain); - timeout(aic_timeout, (caddr_t)acb, (xs->timeout*hz)/1000); - - if (aic->state == AIC_IDLE) - aic_sched(aic); - - if (!(flags & SCSI_NOMASK)) { /* Almost done. Wait outside */ - splx(s); - AIC_MISC(("SUCCESSFULLY_QUEUED")); - return SUCCESSFULLY_QUEUED; - } - - /* Not allowed to use interrupts, use polling instead */ - return aic_poll(aic, acb); -} - -/* - * Adjust transfer size in buffer structure - */ -static void -aic_minphys(bp) - struct buf *bp; -{ - - AIC_TRACE(("aic_minphys\n")); - if (bp->b_bcount > (AIC_NSEG << PAGE_SHIFT)) - bp->b_bcount = (AIC_NSEG << PAGE_SHIFT); -} - - -static u_int32_t -aic_adapter_info(unit) - int unit; -{ - - AIC_TRACE(("aic_adapter_info\n")); - return (2); /* One outstanding command per target */ -} - -/* - * Used when interrupt driven I/O isn't allowed, e.g. during boot. - */ -static int -aic_poll(aic, acb) - struct aic_data *aic; - struct acb *acb; -{ - register u_short iobase = aic->iobase; - struct scsi_xfer *xs = acb->xs; - int count = xs->timeout * 10; - - AIC_TRACE(("aic_poll\n")); - while (count) { - if (inb(DMASTAT) & INTSTAT) - aicintr(xs->sc_link->adapter_unit); - if (xs->flags & ITSDONE) - break; - DELAY(100); - count--; - } - if (count == 0) { - AIC_MISC(("aic_poll: timeout")); - aic_timeout((caddr_t)acb); - } - if (xs->error) - return HAD_ERROR; - return COMPLETE; -} - -/* LOW LEVEL SCSI UTILITIES */ - -/* Determine the SCSI bus phase, return either a real SCSI bus phase or some - * pseudo phase we use to detect certain exceptions. This one is a bit tricky. - * The bits we peek at: - * CDI, MSGI and DI is the 3 SCSI signals determining the bus phase. - * These should be qualified by REQI high and ACKI low. - * Also peek at SSTAT0[SELDO|SELDI] to detect a passing BUSFREE condition. - * No longer detect SCSI RESET or PERR here. They are tested for separately - * in the interrupt handler. - * Note: If an exception occur at some critical time during the phase - * determination we'll most likely return something wildly erronous.... - */ -static inline u_short -aicphase(aic) - struct aic_data *aic; -{ - register u_short iobase = aic->iobase; - register u_char sstat0, sstat1, scsisig; - - sstat1 = inb(SSTAT1); /* Look for REQINIT (REQ asserted) */ - scsisig = inb(SCSISIGI); /* Get the SCSI bus signals */ - sstat0 = inb(SSTAT0); /* Get the selection valid status bits */ - - if (!(inb(SSTAT0) & (SELDO|SELDI))) /* Selection became invalid? */ - return PH_BUSFREE; - - /* Selection is still valid */ - if (!(sstat1 & REQINIT)) /* REQ not asserted ? */ - return PH_INVALID; - - /* REQ is asserted, (and ACK is not) */ - return scsisig & PH_MASK; -} - - -/* Schedule a scsi operation. This has now been pulled out of the interrupt - * handler so that we may call it from aic_scsi_cmd and aic_done. This may - * save us an unecessary interrupt just to get things going. Should only be - * called when state == AIC_IDLE and at bio pl. - */ -static void -aic_sched(aic) - register struct aic_data *aic; -{ - struct scsi_link *sc; - struct acb *acb; - u_short iobase = aic->iobase; - int t; - u_char simode0, simode1, scsiseq; - - AIC_TRACE(("aic_sched\n")); - simode0 = ENSELDI; - simode1 = ENSCSIRST|ENSCSIPERR|ENREQINIT; - scsiseq = ENRESELI; - /* - * Find first acb in rdy queue that is for a target/lunit - * combinations that is not busy. - */ - outb(CLRSINT1, CLRSELTIMO|CLRBUSFREE|CLRSCSIPERR); - for (acb = aic->ready_list.tqh_first; acb; acb = acb->chain.tqe_next) { - sc = acb->xs->sc_link; - t = sc->target; - if (!(aic->tinfo[t].lubusy & (1 << sc->lun))) { - TAILQ_REMOVE(&aic->ready_list, acb, chain); - aic->nexus = acb; - aic->state = AIC_SELECTING; - /* - * Start selection process. Always enable - * reselections. Note: we don't have a nexus yet, so - * cannot set aic->state = AIC_HASNEXUS. - */ - simode0 = ENSELDI|ENSELDO; - simode1 = ENSCSIRST|ENSCSIPERR| - ENREQINIT|ENSELTIMO; - scsiseq = ENRESELI|ENSELO|ENAUTOATNO; - outb(SCSIID, AIC_SCSI_HOSTID << OID_S | t); - outb(SXFRCTL1, STIMO_256ms|ENSTIMER); - outb(CLRSINT0, CLRSELDO); - break; - } -#if AIC_DEBUG - else - AIC_MISC(("%d:%d busy\n", t, sc->lun)); -#endif - } - AIC_MISC(("%sselecting\n",scsiseq&ENSELO?"":"re")); - outb(SIMODE0, simode0); - outb(SIMODE1, simode1); - outb(SCSISEQ, scsiseq); -} - - -/* - * POST PROCESSING OF SCSI_CMD (usually current) - */ -static void -aic_done(acb) - struct acb *acb; -{ - struct scsi_xfer *xs = acb->xs; - struct scsi_link *sc = xs->sc_link; - struct aic_data *aic = (struct aic_data *)sc->adapter_softc; - - AIC_TRACE(("aic_done ")); - - /* - * Now, if we've come here with no error code, i.e. we've kept the - * initial XS_NOERROR, and the status code signals that we should - * check sense, we'll need to set up a request sense cmd block and - * push the command back into the ready queue *before* any other - * commands for this target/lunit, else we lose the sense info. - * We don't support chk sense conditions for the request sense cmd. - */ - if (xs->error == XS_NOERROR && !(acb->flags & ACB_CHKSENSE)) { - if ((acb->stat & ST_MASK)==SCSI_CHECK) { - struct scsi_sense *ss = (void *)&acb->cmd; - AIC_MISC(("requesting sense ")); - /* First, save the return values */ - xs->resid = acb->dleft; - xs->status = acb->stat; - /* Next, setup a request sense command block */ - bzero(ss, sizeof(*ss)); - ss->op_code = REQUEST_SENSE; - ss->byte2 = sc->lun << 5; - ss->length = sizeof(struct scsi_sense_data); - acb->clen = sizeof(*ss); - acb->daddr = (char *)&xs->sense; - acb->dleft = sizeof(struct scsi_sense_data); - acb->flags = ACB_ACTIVE|ACB_CHKSENSE; - TAILQ_INSERT_HEAD(&aic->ready_list, acb, chain); - aic->tinfo[sc->target].lubusy &= ~(1<<sc->lun); - aic->tinfo[sc->target].senses++; - if (aic->nexus == acb) { - aic->nexus = NULL; - aic->state = AIC_IDLE; - aic_sched(aic); - } - return; - } - } - - if (xs->flags & SCSI_ERR_OK) { - xs->resid = 0; - xs->error = XS_NOERROR; - } else if (xs->error == XS_NOERROR && (acb->flags & ACB_CHKSENSE)) { - xs->error = XS_SENSE; - } else { - xs->resid = acb->dleft; - } - xs->flags |= ITSDONE; - -#if AIC_DEBUG - if (aic_debug & AIC_SHOWMISC) { - printf("err=0x%02x ",xs->error); - if (xs->error == XS_SENSE) - printf("sense=%2x\n", xs->sense.error_code); - } - if ((xs->resid || xs->error > XS_SENSE) && aic_debug & AIC_SHOWMISC) { - if (xs->resid) - printf("aic_done: resid=%d\n", xs->resid); - if (xs->error) - printf("aic_done: error=%d\n", xs->error); - } -#endif - - /* - * Remove the ACB from whatever queue it's on. We have to do a bit of - * a hack to figure out which queue it's on. Note that it is *not* - * necessary to cdr down the ready queue, but we must cdr down the - * nexus queue and see if it's there, so we can mark the unit as no - * longer busy. This code is sickening, but it works. - */ - if (acb == aic->nexus) { - aic->state = AIC_IDLE; - aic->tinfo[sc->target].lubusy &= ~(1<<sc->lun); - aic_sched(aic); - } else if (aic->ready_list.tqh_last == &acb->chain.tqe_next) { - TAILQ_REMOVE(&aic->ready_list, acb, chain); - } else { - register struct acb *acb2; - for (acb2 = aic->nexus_list.tqh_first; acb2; - acb2 = acb2->chain.tqe_next) - if (acb2 == acb) { - TAILQ_REMOVE(&aic->nexus_list, acb, chain); - aic->tinfo[sc->target].lubusy &= ~(1<<sc->lun); - /* XXXX Should we call aic_sched() here? */ - break; - } - if (acb2) - ; - else if (acb->chain.tqe_next) { - TAILQ_REMOVE(&aic->ready_list, acb, chain); - } else { - printf("aic%d: can't find matching acb\n", - xs->sc_link->adapter_unit); - Debugger("aic6360"); - fatal_if_no_DDB(); - } - } - /* Put it on the free list. */ - acb->flags = ACB_FREE; - TAILQ_INSERT_HEAD(&aic->free_list, acb, chain); - - aic->tinfo[sc->target].cmds++; - scsi_done(xs); - return; -} - -/* - * INTERRUPT/PROTOCOL ENGINE - */ - -/* The message system: - * This is a revamped message system that now should easier accomodate new - * messages, if necessary. - * Currently we accept these messages: - * IDENTIFY (when reselecting) - * COMMAND COMPLETE # (expect bus free after messages marked #) - * NOOP - * MESSAGE REJECT - * SYNCHRONOUS DATA TRANSFER REQUEST - * SAVE DATA POINTER - * RESTORE POINTERS - * DISCONNECT # - * - * We may send these messages in prioritized order: - * BUS DEVICE RESET # if SCSI_RESET & xs->flags (or in weird sits.) - * MESSAGE PARITY ERROR par. err. during MSGI - * MESSAGE REJECT If we get a message we don't know how to handle - * ABORT # send on errors - * INITIATOR DETECTED ERROR also on errors (SCSI2) (during info xfer) - * IDENTIFY At the start of each transfer - * SYNCHRONOUS DATA TRANSFER REQUEST if appropriate - * NOOP if nothing else fits the bill ... - */ - -#define aic_sched_msgout(m) \ - do { \ - orreg(SCSISIGO, ATNO); \ - aic->msgpriq |= (m); \ - } while (0) - -#define IS1BYTEMSG(m) (((m) != 1 && (m) < 0x20) || (m) >= 0x80) -#define IS2BYTEMSG(m) (((m) & 0xf0) == 0x20) -#define ISEXTMSG(m) ((m) == 1) -/* Precondition: - * The SCSI bus is already in the MSGI phase and there is a message byte - * on the bus, along with an asserted REQ signal. - */ -static void -aic_msgin(aic) - register struct aic_data *aic; -{ - register u_short iobase = aic->iobase; - int spincount, extlen; - u_char sstat1; - - AIC_TRACE(("aic_msgin ")); - outb(SCSISIGO, PH_MSGI); - /* Prepare for a new message. A message should (according to the SCSI - * standard) be transmitted in one single message_in phase. - * If we have been in some other phase, then this is a new message. - */ - if (aic->prevphase != PH_MSGI) { - aic->flags &= ~AIC_DROP_MSGI; - aic->imlen = 0; - } - /* - * Read a whole message but the last byte. If we shall reject the - * message, we shall have to do it, by asserting ATNO, during the - * message transfer phase itself. - */ - for (;;) { - sstat1 = inb(SSTAT1); - /* If parity errors just dump everything on the floor, also - * a parity error automatically sets ATNO - */ - if (sstat1 & SCSIPERR) { - aic_sched_msgout(SEND_PARITY_ERROR); - aic->flags |= AIC_DROP_MSGI; - } - /* - * If we're going to reject the message, don't bother storing - * the incoming bytes. But still, we need to ACK them. - */ - if (!(aic->flags & AIC_DROP_MSGI)) { - /* Get next message byte */ - aic->imess[aic->imlen] = inb(SCSIDAT); - /* - * This testing is suboptimal, but most messages will - * be of the one byte variety, so it should not effect - * performance significantly. - */ - if (IS1BYTEMSG(aic->imess[0])) - break; - if (IS2BYTEMSG(aic->imess[0]) && aic->imlen == 1) - break; - if (ISEXTMSG(aic->imess[0]) && aic->imlen > 0) { - if (aic->imlen == AIC_MAX_MSG_LEN) { - aic->flags |= AIC_DROP_MSGI; - aic_sched_msgout(SEND_REJECT); - } - extlen = aic->imess[1] ? aic->imess[1] : 256; - if (aic->imlen == extlen + 2) - break; /* Got it all */ - } - } - /* If we reach this spot we're either: - * a) in the middle of a multi-byte message or - * b) we're dropping bytes - */ - outb(SXFRCTL0, CHEN|SPIOEN); - inb(SCSIDAT); /* Really read it (ACK it, that is) */ - outb(SXFRCTL0, CHEN); - aic->imlen++; - - /* - * We expect the bytes in a multibyte message to arrive - * relatively close in time, a few microseconds apart. - * Therefore we will spinwait for some small amount of time - * waiting for the next byte. - */ - spincount = DELAYCOUNT * AIC_MSGI_SPIN; - LOGLINE(aic); - while (spincount-- && !((sstat1 = inb(SSTAT1)) & REQINIT)) - ; - if (spincount == -1 || sstat1 & (PHASEMIS|BUSFREE)) - return; - } - /* Now we should have a complete message (1 byte, 2 byte and moderately - * long extended messages). We only handle extended messages which - * total length is shorter than AIC_MAX_MSG_LEN. Longer messages will - * be amputated. (Return XS_BOBBITT ?) - */ - if (aic->state == AIC_HASNEXUS) { - struct acb *acb = aic->nexus; - struct aic_tinfo *ti = &aic->tinfo[acb->xs->sc_link->target]; - int offs, per, rate; - - outb(SIMODE1, ENSCSIRST|ENPHASEMIS|ENBUSFREE|ENSCSIPERR); - switch (aic->imess[0]) { - case MSG_CMDCOMPLETE: - if (!acb) { - aic_sched_msgout(SEND_ABORT); - printf("aic: CMDCOMPLETE but no command?\n"); - break; - } - if (aic->dleft < 0) { - struct scsi_link *sc = acb->xs->sc_link; - printf("aic: %d extra bytes from %d:%d\n", - -aic->dleft, sc->target, sc->lun); - acb->dleft = 0; - } - acb->xs->resid = acb->dleft = aic->dleft; - aic->flags |= AIC_BUSFREE_OK; - untimeout(aic_timeout, (caddr_t)acb); - aic_done(acb); - break; - case MSG_MESSAGE_REJECT: - if (aic_debug & AIC_SHOWMISC) - printf("aic: our msg rejected by target\n"); - if (aic->flags & AIC_SYNCHNEGO) { - ti->syncdata = 0; - ti->persgst = ti->offsgst = 0; - aic->flags &= ~AIC_SYNCHNEGO; - ti->flags &= ~DO_NEGOTIATE; - } - /* Not all targets understand INITIATOR_DETECTED_ERR */ - if (aic->msgout == SEND_INIT_DET_ERR) - aic_sched_msgout(SEND_ABORT); - break; - case MSG_NOOP: /* Will do! Immediately, sir!*/ - break; /* Hah, that was easy! */ - case MSG_DISCONNECT: - if (!acb) { - aic_sched_msgout(SEND_ABORT); - printf("aic: nothing to DISCONNECT\n"); - break; - } - ti->dconns++; - TAILQ_INSERT_HEAD(&aic->nexus_list, acb, chain); - acb = aic->nexus = NULL; - aic->state = AIC_IDLE; - aic->flags |= AIC_BUSFREE_OK; - break; - case MSG_SAVEDATAPOINTER: - if (!acb) { - aic_sched_msgout(SEND_ABORT); - printf("aic: no DATAPOINTERs to save\n"); - break; - } - acb->dleft = aic->dleft; - acb->daddr = aic->dp; - break; - case MSG_RESTOREPOINTERS: - if (!acb) { - aic_sched_msgout(SEND_ABORT); - printf("aic: no DATAPOINTERs to restore\n"); - break; - } - aic->dp = acb->daddr; - aic->dleft = acb->dleft; - break; - case MSG_EXTENDED: - switch (aic->imess[2]) { - case MSG_EXT_SDTR: - per = aic->imess[3] * 4; - rate = (per + 49 - 100)/50; - offs = aic->imess[4]; - if (offs == 0) - ti->syncdata = 0; - else if (rate > 7) { - /* Too slow for aic6360. Do asynch - * instead. Renegotiate the deal. - */ - ti->persgst = 0; - ti->offsgst = 0; - aic_sched_msgout(SEND_SDTR); - } else { - rate = rate<<4 | offs; - ti->syncdata = rate; - } - break; - default: /* Extended messages we don't handle */ - aic_sched_msgout(SEND_REJECT); - break; - } - break; - default: - aic_sched_msgout(SEND_REJECT); - break; - } - } else if (aic->state == AIC_RESELECTED) { - struct scsi_link *sc; - struct acb *acb; - u_char selid, lunit; - /* - * Which target is reselecting us? (The ID bit really) - */ - selid = inb(SELID) & ~(1<<AIC_SCSI_HOSTID); - if (MSG_ISIDENT(aic->imess[0])) { /* Identify? */ - AIC_MISC(("searching ")); - /* Search wait queue for disconnected cmd - * The list should be short, so I haven't bothered with - * any more sophisticated structures than a simple - * singly linked list. - */ - lunit = aic->imess[0] & 0x07; - for (acb = aic->nexus_list.tqh_first; acb; - acb = acb->chain.tqe_next) { - sc = acb->xs->sc_link; - if (sc->lun == lunit && - selid == (1<<sc->target)) { - TAILQ_REMOVE(&aic->nexus_list, acb, - chain); - break; - } - } - if (!acb) { /* Invalid reselection! */ - aic_sched_msgout(SEND_ABORT); - printf("aic: invalid reselect (idbit=0x%2x)\n", - selid); - } else { /* Reestablish nexus */ - /* Setup driver data structures and - * do an implicit RESTORE POINTERS - */ - aic->nexus = acb; - aic->dp = acb->daddr; - aic->dleft = acb->dleft; - aic->tinfo[sc->target].lubusy |= (1<<sc->lun); - outb(SCSIRATE,aic->tinfo[sc->target].syncdata); - AIC_MISC(("... found acb")); - aic->state = AIC_HASNEXUS; - } - } else { - printf("aic: bogus reselect (no IDENTIFY) %0x2x\n", - selid); - aic_sched_msgout(SEND_DEV_RESET); - } - } else { /* Neither AIC_HASNEXUS nor AIC_RESELECTED! */ - printf("aic: unexpected message in; will send DEV_RESET\n"); - aic_sched_msgout(SEND_DEV_RESET); - } - /* Must not forget to ACK the last message byte ... */ - outb(SXFRCTL0, CHEN|SPIOEN); - inb(SCSIDAT); - outb(SXFRCTL0, CHEN); - outb(SIMODE1, ENSCSIRST|ENBUSFREE|ENSCSIPERR|ENREQINIT); -} - - -/* The message out (and in) stuff is a bit complicated: - * If the target requests another message (sequence) without - * having changed phase in between it really asks for a - * retransmit, probably due to parity error(s). - * The following messages can be sent: - * IDENTIFY @ These 3 stems from scsi command activity - * BUS_DEV_RESET @ - * IDENTIFY + SDTR @ - * MESSAGE_REJECT if MSGI doesn't make sense - * MESSAGE_PARITY_ERROR if MSGI spots a parity error - * NOOP if asked for a message and there's nothing to send - */ -static void -aic_msgout(aic) - register struct aic_data *aic; -{ - register u_short iobase = aic->iobase; - struct aic_tinfo *ti; - struct acb *acb; - - /* First determine what to send. If we haven't seen a - * phasechange this is a retransmission request. - */ - outb(SCSISIGO, PH_MSGO); - if (aic->prevphase != PH_MSGO) { /* NOT a retransmit */ - /* Pick up highest priority message */ - aic->msgout = aic->msgpriq & -aic->msgpriq; /* What message? */ - aic->omlen = 1; /* "Default" message len */ - switch (aic->msgout) { - case SEND_SDTR: /* Also implies an IDENTIFY message */ - acb = aic->nexus; - ti = &aic->tinfo[acb->xs->sc_link->target]; - aic->omess[1] = MSG_EXTENDED; - aic->omess[2] = 3; - aic->omess[3] = MSG_EXT_SDTR; - aic->omess[4] = ti->persgst >> 2; - aic->omess[5] = ti->offsgst; - aic->omlen = 6; - /* Fallthrough! */ - case SEND_IDENTIFY: - if (aic->state != AIC_HASNEXUS) { - printf("aic at line %d: no nexus", __LINE__); - Debugger("aic6360"); - fatal_if_no_DDB(); - } - acb = aic->nexus; - aic->omess[0] = MSG_IDENTIFY(acb->xs->sc_link->lun); - break; - case SEND_DEV_RESET: - aic->omess[0] = MSG_BUS_DEV_RESET; - aic->flags |= AIC_BUSFREE_OK; - break; - case SEND_PARITY_ERROR: - aic->omess[0] = MSG_PARITY_ERR; - break; - case SEND_ABORT: - aic->omess[0] = MSG_ABORT; - aic->flags |= AIC_BUSFREE_OK; - break; - case SEND_INIT_DET_ERR: - aic->omess[0] = MSG_INITIATOR_DET_ERR; - break; - case SEND_REJECT: - aic->omess[0] = MSG_MESSAGE_REJECT; - break; - default: - aic->omess[0] = MSG_NOOP; - break; - } - aic->omp = aic->omess; - } else if (aic->omp == &aic->omess[aic->omlen]) { - /* Have sent the message at least once, this is a retransmit. - */ - AIC_MISC(("retransmitting ")); - if (aic->omlen > 1) - outb(SCSISIGO, PH_MSGO|ATNO); - } - /* else, we're in the middle of a multi-byte message */ - outb(SXFRCTL0, CHEN|SPIOEN); - outb(DMACNTRL0, INTEN|RSTFIFO); - outb(SIMODE1, ENSCSIRST|ENBUSFREE|ENSCSIPERR|ENREQINIT); - do { - LOGLINE(aic); - do { - aic->phase = aicphase(aic); - } while (aic->phase == PH_INVALID); - if (aic->phase != PH_MSGO) - /* Target left MSGO, possibly to reject our - * message - */ - break; - /* Clear ATN before last byte */ - if (aic->omp == &aic->omess[aic->omlen-1]) - outb(CLRSINT1, CLRATNO); - outb(SCSIDAT, *aic->omp++); /* Send MSG */ - LOGLINE(aic); - while (inb(SCSISIGI) & ACKO) - ; - } while (aic->omp != &aic->omess[aic->omlen]); - aic->progress = aic->omp != aic->omess; - /* We get here in two ways: - * a) phase != MSGO. Target is probably going to reject our message - * b) aic->omp == &aic->omess[aic->omlen], i.e. the message has been - * transmitted correctly and accepted by the target. - */ - if (aic->phase == PH_MSGO) { /* Message accepted by target! */ - aic->msgpriq &= ~aic->msgout; - aic->msgout = 0; - } - outb(SXFRCTL0, CHEN); /* Disable SPIO */ - outb(SIMODE0, 0); /* Setup interrupts before leaving */ - outb(SIMODE1, ENSCSIRST|ENBUSFREE|ENSCSIPERR|ENREQINIT); - /* Enabled ints: SCSIPERR, SCSIRSTI (unexpected) - * REQINIT (expected) BUSFREE (possibly expected) - */ -} - -/* aic_dataout: perform a data transfer using the FIFO datapath in the aic6360 - * Precondition: The SCSI bus should be in the DOUT phase, with REQ asserted - * and ACK deasserted (i.e. waiting for a data byte) - * This new revision has been optimized (I tried) to make the common case fast, - * and the rarer cases (as a result) somewhat more comlex - */ -static void -aic_dataout(aic) - register struct aic_data *aic; -{ - register u_short iobase = aic->iobase; - register u_char dmastat; - int amount, olddleft = aic->dleft; -#define DOUTAMOUNT 128 /* Full FIFO */ - - /* Enable DATA OUT transfers */ - outb(SCSISIGO, PH_DOUT); - outb(CLRSINT1, CLRPHASECHG); - /* Clear FIFOs and counters */ - outb(SXFRCTL0, CHEN|CLRSTCNT|CLRCH); - outb(DMACNTRL0, WRITE|INTEN|RSTFIFO); - /* Enable FIFOs */ - outb(SXFRCTL0, SCSIEN|DMAEN|CHEN); - outb(DMACNTRL0, ENDMA|DWORDPIO|WRITE|INTEN); - - /* Setup to detect: - * PHASEMIS & PHASECHG: target has left the DOUT phase - * SCSIRST: something just pulled the RST line. - * BUSFREE: target has unexpectedly left the DOUT phase - */ - outb(SIMODE1, ENPHASEMIS|ENSCSIRST|ENBUSFREE|ENPHASECHG); - - /* I have tried to make the main loop as tight as possible. This - * means that some of the code following the loop is a bit more - * complex than otherwise. - */ - while (aic->dleft) { - int xfer; - - LOGLINE(aic); - - for (;;) { - dmastat = inb(DMASTAT); - if (dmastat & DFIFOEMP) - break; - if (dmastat & INTSTAT) - goto phasechange; - } - - xfer = min(DOUTAMOUNT, aic->dleft); - -#if AIC_USE_DWORDS - if (xfer >= 12) { - outsl(DMADATALONG, aic->dp, xfer/4); - aic->dleft -= xfer & ~3; - aic->dp += xfer & ~3; - xfer &= 3; - } -#else - if (xfer >= 8) { - outsw(DMADATA, aic->dp, xfer/2); - aic->dleft -= xfer & ~1; - aic->dp += xfer & ~1; - xfer &= 1; - } -#endif - - if (xfer) { - outb(DMACNTRL0, ENDMA|B8MODE|INTEN); - outsb(DMADATA, aic->dp, xfer); - aic->dleft -= xfer; - aic->dp += xfer; - outb(DMACNTRL0, ENDMA|DWORDPIO|INTEN); - } - } - - /* See the bytes off chip */ - for (;;) { - dmastat = inb(DMASTAT); - if ((dmastat & DFIFOEMP) && (inb(SSTAT2) & SEMPTY)) - break; - if (dmastat & INTSTAT) - goto phasechange; - } - -phasechange: - /* We now have the data off chip. */ - outb(SXFRCTL0, CHEN); - - if (dmastat & INTSTAT) { /* Some sort of phasechange */ - register u_char sstat2; - /* Stop transfers, do some accounting */ - amount = inb(FIFOSTAT); - sstat2 = inb(SSTAT2); - if ((sstat2 & 7) == 0) - amount += sstat2 & SFULL ? 8 : 0; - else - amount += sstat2 & 7; - aic->dleft += amount; - aic->dp -= amount; - AIC_MISC(("+%d ", amount)); - } - - outb(DMACNTRL0, RSTFIFO|INTEN); - LOGLINE(aic); - while (inb(SXFRCTL0) & SCSIEN) - ; - outb(SIMODE1, ENSCSIRST|ENBUSFREE|ENSCSIPERR|ENREQINIT); - /* Enabled ints: BUSFREE, SCSIPERR, SCSIRSTI (unexpected) - * REQINIT (expected) - */ - aic->progress = olddleft != aic->dleft; - return; -} - -/* aic_datain: perform data transfers using the FIFO datapath in the aic6360 - * Precondition: The SCSI bus should be in the DIN phase, with REQ asserted - * and ACK deasserted (i.e. at least one byte is ready). - * For now, uses a pretty dumb algorithm, hangs around until all data has been - * transferred. This, is OK for fast targets, but not so smart for slow - * targets which don't disconnect or for huge transfers. - */ -static void -aic_datain(aic) - register struct aic_data *aic; -{ - register u_short iobase = aic->iobase; - register u_char dmastat; - int olddleft = aic->dleft; -#define DINAMOUNT 128 /* Default amount of data to transfer */ - - /* Enable DATA IN transfers */ - outb(SCSISIGO, PH_DIN); - outb(CLRSINT1, CLRPHASECHG); - /* Clear FIFOs and counters */ - outb(SXFRCTL0, CHEN|CLRSTCNT|CLRCH); - outb(DMACNTRL0, INTEN|RSTFIFO); - /* Enable FIFOs */ - outb(SXFRCTL0, SCSIEN|DMAEN|CHEN); - outb(DMACNTRL0, ENDMA|DWORDPIO|INTEN); - - outb(SIMODE1, ENSCSIRST|ENPHASEMIS|ENBUSFREE|ENPHASECHG); - - /* We leave this loop if one or more of the following is true: - * a) phase != PH_DIN && FIFOs are empty - * b) SCSIRSTI is set (a reset has occurred) or busfree is detected. - */ - while (aic->dleft) { - int done = 0; - int xfer; - - LOGLINE(aic); - - /* Wait for fifo half full or phase mismatch */ - for (;;) { - dmastat = inb(DMASTAT); - if (dmastat & (DFIFOFULL|INTSTAT)) - break; - } - - if (dmastat & DFIFOFULL) - xfer = DINAMOUNT; - else { - while ((inb(SSTAT2) & SEMPTY) == 0) - ; - xfer = inb(FIFOSTAT); - done = 1; - } - - xfer = min(xfer, aic->dleft); - -#if AIC_USE_DWORDS - if (xfer >= 12) { - insl(DMADATALONG, aic->dp, xfer/4); - aic->dleft -= xfer & ~3; - aic->dp += xfer & ~3; - xfer &= 3; - } -#else - if (xfer >= 8) { - insw(DMADATA, aic->dp, xfer/2); - aic->dleft -= xfer & ~1; - aic->dp += xfer & ~1; - xfer &= 1; - } -#endif - - if (xfer) { - outb(DMACNTRL0, ENDMA|B8MODE|INTEN); - insb(DMADATA, aic->dp, xfer); - aic->dleft -= xfer; - aic->dp += xfer; - outb(DMACNTRL0, ENDMA|DWORDPIO|INTEN); - } - - if (done) - break; - } - -#if 0 - if (aic->dleft) - printf("residual of %d\n", aic->dleft); -#endif - - aic->progress = olddleft != aic->dleft; - /* Some SCSI-devices are rude enough to transfer more data than what - * was requested, e.g. 2048 bytes from a CD-ROM instead of the - * requested 512. Test for progress, i.e. real transfers. If no real - * transfers have been performed (acb->dleft is probably already zero) - * and the FIFO is not empty, waste some bytes.... - */ - if (!aic->progress) { - int extra = 0; - LOGLINE(aic); - - for (;;) { - dmastat = inb(DMASTAT); - if (dmastat & DFIFOEMP) - break; - (void) inb(DMADATA); /* Throw it away */ - extra++; - } - - AIC_MISC(("aic: %d extra bytes from %d:%d\n", extra, - acb->xs->sc_link->target, acb->xs->sc_link->lun)); - aic->progress = extra; - } - - /* Stop the FIFO data path */ - outb(SXFRCTL0, CHEN); - - outb(DMACNTRL0, RSTFIFO|INTEN); - /* Come back when REQ is set again */ - outb(SIMODE1, ENSCSIRST|ENBUSFREE|ENSCSIPERR|ENREQINIT); - LOGLINE(aic); -} - - -/* - * This is the workhorse routine of the driver. - * Deficiencies (for now): - * 1) always uses programmed I/O - * 2) doesn't support synchronous transfers properly (yet) - */ - -void -aicintr(int unit) -{ - struct aic_data *aic = aicdata[unit]; - register struct acb *acb; - register struct scsi_link *sc; - register u_short iobase = aic->iobase; - struct aic_tinfo *ti; - u_char sstat0, sstat1, sstat2, sxfrctl0; - - - LOGLINE(aic); - /* Clear INTEN. This is important if we're running with edge - * triggered interrupts as we don't guarantee that all interrupts will - * be served during one single invocation of this routine, i.e. we may - * need another edge. - */ - outb(DMACNTRL0, 0); - AIC_TRACE(("aicintr\n")); - - /* - * 1st check for abnormal conditions, such as reset or parity errors - */ - sstat1 = inb(SSTAT1); - AIC_MISC(("s1:0x%02x ", sstat1)); - if (sstat1 & (SCSIRSTI|SCSIPERR)) { - if (sstat1 & SCSIRSTI) { - printf("aic: reset in -- reinitializing....\n"); - aic_init(aic); /* Restart everything */ - LOGLINE(aic); - outb(DMACNTRL0, INTEN); - return; - } else { - printf("aic: SCSI bus parity error\n"); - outb(CLRSINT1, CLRSCSIPERR); - if (aic->prevphase == PH_MSGI) - aic_sched_msgout(SEND_PARITY_ERROR); - else - aic_sched_msgout(SEND_INIT_DET_ERR); - } - } - - /* - * If we're not already busy doing something test for the following - * conditions: - * 1) We have been reselected by something - * 2) We have selected something successfully - * 3) Our selection process has timed out - * 4) This is really a bus free interrupt just to get a new command - * going? - * 5) Spurious interrupt? - */ - sstat0 = inb(SSTAT0); - AIC_MISC(("s0:0x%02x ", sstat0)); - if (aic->state != AIC_HASNEXUS) { /* No nexus yet */ - if (sstat0 & SELDI) { - LOGLINE(aic); - /* We have been reselected. Things to do: - * a) If we're trying to select something ourselves - * back off the current command. - * b) "Wait" for a message in phase (IDENTIFY) - * c) Call aic_msgin() to get the identify message and - * retrieve the disconnected command from the wait - * queue. - */ - AIC_MISC(("reselect ")); - /* If we're trying to select a target ourselves, - * push our command back into the rdy list. - */ - if (aic->state == AIC_SELECTING) { - AIC_MISC(("backoff selector ")); - TAILQ_INSERT_HEAD(&aic->ready_list, aic->nexus, - chain); - aic->nexus = NULL; - } - aic->state = AIC_RESELECTED; - /* Clear interrupts, disable future selection stuff - * including select interrupts and timeouts - */ - outb(CLRSINT0, CLRSELDI); - outb(SCSISEQ, 0); - outb(SIMODE0, 0); - /* Setup chip so we may detect spurious busfree - * conditions later. - */ - outb(CLRSINT1, CLRBUSFREE); - outb(SIMODE1, ENSCSIRST|ENBUSFREE| - ENSCSIPERR|ENREQINIT); - /* Now, we're expecting an IDENTIFY message. */ - aic->phase = aicphase(aic); - if (aic->phase & PH_PSBIT) { - LOGLINE(aic); - outb(DMACNTRL0, INTEN); - return; /* Come back when REQ is set */ - } - if (aic->phase == PH_MSGI) - aic_msgin(aic); /* Handle identify message */ - else { - /* Things are seriously fucked up. - * Pull the brakes, i.e. RST - */ - printf("aic at line %d: target didn't identify\n", __LINE__); - Debugger("aic6360"); - fatal_if_no_DDB(); - aic_init(aic); - return; - } - if (aic->state != AIC_HASNEXUS) {/* IDENTIFY fail?! */ - printf("aic at line %d: identify failed\n", - __LINE__); - aic_init(aic); - return; - } else { - outb(SIMODE1, - ENSCSIRST|ENBUSFREE|ENSCSIPERR|ENREQINIT); - /* Fallthrough to HASNEXUS part of aicintr */ - } - } else if (sstat0 & SELDO) { - LOGLINE(aic); - /* We have selected a target. Things to do: - * a) Determine what message(s) to send. - * b) Verify that we're still selecting the target. - * c) Mark device as busy. - */ - acb = aic->nexus; - if (!acb) { - printf("aic at line %d: missing acb", __LINE__); - Debugger("aic6360"); - fatal_if_no_DDB(); - } - sc = acb->xs->sc_link; - ti = &aic->tinfo[sc->target]; - if (acb->xs->flags & SCSI_RESET) - aic->msgpriq = SEND_DEV_RESET; - else if (ti->flags & DO_NEGOTIATE) - aic->msgpriq = SEND_IDENTIFY|SEND_SDTR; - else - aic->msgpriq = SEND_IDENTIFY; - /* Setup chip to enable later testing for busfree - * conditions - */ - outb(CLRSINT1, CLRBUSFREE); - outb(SCSISEQ, 0); /* Stop selection stuff */ - nandreg(SIMODE0, ENSELDO); /* No more selectout ints */ - sstat0 = inb(SSTAT0); - if (sstat0 & SELDO) { /* Still selected!? */ - outb(SIMODE0, 0); - outb(SIMODE1, ENSCSIRST|ENSCSIPERR| - ENBUSFREE|ENREQINIT); - aic->state = AIC_HASNEXUS; - aic->flags = 0; - aic->prevphase = PH_INVALID; - aic->dp = acb->daddr; - aic->dleft = acb->dleft; - ti->lubusy |= (1<<sc->lun); - AIC_MISC(("select ok ")); - } else { - /* Has seen busfree since selection, i.e. - * a "spurious" selection. Shouldn't happen. - */ - printf("aic: unexpected busfree\n"); - acb->xs->error = XS_DRIVER_STUFFUP; - untimeout(aic_timeout, (caddr_t)acb); - aic_done(acb); - } - LOGLINE(aic); - outb(DMACNTRL0, INTEN); - return; - } else if (sstat1 & SELTO) { - /* Selection timed out. What to do: - * Disable selections out and fail the command with - * code XS_TIMEOUT. - */ - acb = aic->nexus; - if (!acb) { - printf("aic at line %d: missing acb", __LINE__); - Debugger("aic6360"); - fatal_if_no_DDB(); - } - outb(SCSISEQ, ENRESELI|ENAUTOATNP); - outb(SXFRCTL1, 0); - outb(CLRSINT1, CLRSELTIMO); - aic->state = AIC_IDLE; - acb->xs->error = XS_TIMEOUT; - untimeout(aic_timeout, (caddr_t)acb); - aic_done(acb); - LOGLINE(aic); - outb(DMACNTRL0, INTEN); - return; - } else { - /* Assume a bus free interrupt. What to do: - * Start selecting. - */ - if (aic->state == AIC_IDLE) - aic_sched(aic); -#if AIC_DEBUG - else - AIC_MISC(("Extra aic6360 interrupt.")); -#endif - LOGLINE(aic); - outb(DMACNTRL0, INTEN); - return; - } - } - /* Driver is now in state AIC_HASNEXUS, i.e. we have a current command - * working the SCSI bus. - */ - acb = aic->nexus; - if (aic->state != AIC_HASNEXUS || acb == NULL) { - printf("aic: no nexus!!\n"); - Debugger("aic6360"); - fatal_if_no_DDB(); - } - - /* What sort of transfer does the bus signal? */ - aic->phase = aicphase(aic); - if (!(aic->phase & PH_PSBIT)) /* not a pseudo phase */ - outb(SCSISIGO, aic->phase); - outb(CLRSINT1, CLRPHASECHG); - /* These interrupts are enabled by default: - * SCSIRSTI, SCSIPERR, BUSFREE, REQINIT - */ - switch (aic->phase) { - case PH_MSGO: - LOGLINE(aic); - if (aic_debug & AIC_SHOWMISC) - printf("PH_MSGO "); - aic_msgout(aic); - aic->prevphase = PH_MSGO; - /* Setup interrupts before leaving */ - outb(SIMODE0, 0); - outb(SIMODE1, ENSCSIRST|ENBUSFREE|ENSCSIPERR|ENREQINIT); - /* Enabled ints: SCSIPERR, SCSIRSTI (unexpected) - * REQINIT (expected) BUSFREE (possibly expected) - */ - break; - case PH_CMD: /* CMD phase & REQ asserted */ - LOGLINE(aic); - if (aic_debug & AIC_SHOWMISC) - printf("PH_CMD 0x%02x (%d) ", - acb->cmd.opcode, acb->clen); - outb(SCSISIGO, PH_CMD); - /* Use FIFO for CMDs. Assumes that no cmd > 128 bytes. OK? */ - /* Clear hostFIFO and enable EISA-hostFIFO transfers */ - outb(DMACNTRL0, WRITE|RSTFIFO|INTEN); /* 3(4) */ - /* Clear scsiFIFO and enable SCSI-interface - & hostFIFO-scsiFIFO transfers */ - outb(SXFRCTL0, CHEN|CLRCH|CLRSTCNT); /* 4 */ - outb(SXFRCTL0, SCSIEN|DMAEN|CHEN); /* 5 */ - outb(DMACNTRL0, ENDMA|WRITE|INTEN); /* 3+6 */ - /* What (polled) interrupts to enable */ - outb(SIMODE1, ENPHASEMIS|ENSCSIRST|ENBUSFREE|ENSCSIPERR); - /* DFIFOEMP is set, FIFO (128 byte) is always big enough */ - outsw(DMADATA, (short *)&acb->cmd, acb->clen>>1); - - /* Wait for SCSI FIFO to drain */ - LOGLINE(aic); - do { - sstat2 = inb(SSTAT2); - } while (!(sstat2 & SEMPTY) && !(inb(DMASTAT) & INTSTAT)); - if (!(inb(SSTAT2) & SEMPTY)) { - printf("aic at line %d: SCSI-FIFO didn't drain\n", - __LINE__); - Debugger("aic6360"); - fatal_if_no_DDB(); - acb->xs->error = XS_DRIVER_STUFFUP; - untimeout(aic_timeout, (caddr_t)acb); - aic_done(acb); - aic_init(aic); - return; - } - outb(SXFRCTL0, CHEN); /* Clear SCSIEN & DMAEN */ - outb(SIMODE0, 0); - outb(SIMODE1, ENSCSIRST|ENBUSFREE|ENSCSIPERR); - LOGLINE(aic); - do { - sxfrctl0 = inb(SXFRCTL0); - } while (sxfrctl0 & SCSIEN && !(inb(DMASTAT) & INTSTAT)); - if (sxfrctl0 & SCSIEN) { - printf("aic at line %d: scsi xfer never finished\n", - __LINE__); - Debugger("aic6360"); - fatal_if_no_DDB(); - acb->xs->error = XS_DRIVER_STUFFUP; - untimeout(aic_timeout, (caddr_t)acb); - aic_done(acb); - aic_init(aic); - return; - } - outb(SIMODE1, ENSCSIRST|ENBUSFREE|ENSCSIPERR|ENREQINIT); - /* Enabled ints: BUSFREE, SCSIPERR, SCSIRSTI (unexpected) - * REQINIT (expected) - */ - aic->prevphase = PH_CMD; - break; - case PH_DOUT: - LOGLINE(aic); - AIC_MISC(("PH_DOUT [%d] ",aic->dleft)); - aic_dataout(aic); - aic->prevphase = PH_DOUT; - break; - case PH_MSGI: - LOGLINE(aic); - if (aic_debug & AIC_SHOWMISC) - printf("PH_MSGI "); - aic_msgin(aic); - outb(SIMODE1, ENSCSIRST|ENBUSFREE|ENSCSIPERR|ENREQINIT); - aic->prevphase = PH_MSGI; - break; - case PH_DIN: - LOGLINE(aic); - if (aic_debug & AIC_SHOWMISC) - printf("PH_DIN "); - aic_datain(aic); - aic->prevphase = PH_DIN; - break; - case PH_STAT: - LOGLINE(aic); - if (aic_debug & AIC_SHOWMISC) - printf("PH_STAT "); - outb(SCSISIGO, PH_STAT); - outb(SXFRCTL0, CHEN|SPIOEN); - outb(DMACNTRL0, RSTFIFO|INTEN); - outb(SIMODE1, ENSCSIRST|ENPHASEMIS|ENBUSFREE|ENSCSIPERR); - acb->stat = inb(SCSIDAT); - outb(SXFRCTL0, CHEN); - if (aic_debug & AIC_SHOWMISC) - printf("0x%02x ", acb->stat); - outb(SIMODE1, ENSCSIRST|ENBUSFREE|ENSCSIPERR|ENREQINIT); - aic->prevphase = PH_STAT; - break; - case PH_INVALID: - LOGLINE(aic); - break; - case PH_BUSFREE: - LOGLINE(aic); - if (aic->flags & AIC_BUSFREE_OK) { /*It's fun the 1st time.. */ - aic->flags &= ~AIC_BUSFREE_OK; - } else { - printf("aic at line %d: unexpected busfree phase\n", - __LINE__); - Debugger("aic6360"); - fatal_if_no_DDB(); - } - break; - default: - printf("aic at line %d: bogus bus phase\n", __LINE__); - Debugger("aic6360"); - fatal_if_no_DDB(); - break; - } - LOGLINE(aic); - outb(DMACNTRL0, INTEN); - return; -} - -static void -aic_timeout(void *arg1) { - int s = splbio(); - struct acb *acb = (struct acb *)arg1; - int unit; - struct aic_data *aic; - - unit = acb->xs->sc_link->adapter_unit; - aic = aicdata[unit]; - sc_print_addr(acb->xs->sc_link); - acb->xs->error = XS_TIMEOUT; - printf("timed out\n"); - - aic_done(acb); - splx(s); -} - -#if AIC_DEBUG -/* - * The following functions are mostly used for debugging purposes, either - * directly called from the driver or from the kernel debugger. - */ - -void -aic_show_scsi_cmd(acb) - struct acb *acb; -{ - u_char *b = (u_char *)&acb->cmd; - struct scsi_link *sc = acb->xs->sc_link; - int i; - - sc_print_addr(sc); - if (!(acb->xs->flags & SCSI_RESET)) { - for (i = 0; i < acb->clen; i++) { - if (i) - printf(","); - printf("%x", b[i]); - } - printf("\n"); - } else - printf("RESET\n"); -} - -void -aic_print_acb(acb) - struct acb *acb; -{ - - printf("acb@%x xs=%x flags=%x", acb, acb->xs, acb->flags); - printf(" daddr=%x dleft=%d stat=%x\n", - (long)acb->daddr, acb->dleft, acb->stat); - aic_show_scsi_cmd(acb); -} - -void -aic_print_active_acb() -{ - struct acb *acb; - struct aic_data *aic = aicdata[0]; - - printf("ready list:\n"); - for (acb = aic->ready_list.tqh_first; acb; acb = acb->chain.tqe_next) - aic_print_acb(acb); - printf("nexus:\n"); - if (aic->nexus) - aic_print_acb(aic->nexus); - printf("nexus list:\n"); - for (acb = aic->nexus_list.tqh_first; acb; acb = acb->chain.tqe_next) - aic_print_acb(acb); -} - -void -aic_dump6360() -{ - u_short iobase = 0x340; - - printf("aic6360: SCSISEQ=%x SXFRCTL0=%x SXFRCTL1=%x SCSISIGI=%x\n", - inb(SCSISEQ), inb(SXFRCTL0), inb(SXFRCTL1), inb(SCSISIGI)); - printf(" SSTAT0=%x SSTAT1=%x SSTAT2=%x SSTAT3=%x SSTAT4=%x\n", - inb(SSTAT0), inb(SSTAT1), inb(SSTAT2), inb(SSTAT3), inb(SSTAT4)); - printf(" SIMODE0=%x SIMODE1=%x DMACNTRL0=%x DMACNTRL1=%x DMASTAT=%x\n", - inb(SIMODE0), inb(SIMODE1), inb(DMACNTRL0), inb(DMACNTRL1), - inb(DMASTAT)); - printf(" FIFOSTAT=%d SCSIBUS=0x%x\n", - inb(FIFOSTAT), inb(SCSIBUS)); -} - -void -aic_dump_driver() -{ - struct aic_data *aic = aicdata[0]; - struct aic_tinfo *ti; - int i; - - printf("nexus=%x phase=%x prevphase=%x\n", aic->nexus, aic->phase, - aic->prevphase); - printf("state=%x msgin=%x msgpriq=%x msgout=%x imlen=%d omlen=%d\n", - aic->state, aic->imess[0], aic->msgpriq, aic->msgout, aic->imlen, - aic->omlen); - printf("history:"); - i = aic->hp; - do { - printf(" %d", aic->history[i]); - i = (i + 1) % AIC_HSIZE; - } while (i != aic->hp); - printf("*\n"); - for (i = 0; i < 7; i++) { - ti = &aic->tinfo[i]; - printf("tinfo%d: %d cmds %d disconnects %d timeouts", - i, ti->cmds, ti->dconns, ti->touts); - printf(" %d senses flags=%x\n", ti->senses, ti->flags); - } -} -#endif diff --git a/sys/pc98/pc98/atapi.c b/sys/pc98/pc98/atapi.c deleted file mode 100644 index dc5e1c7..0000000 --- a/sys/pc98/pc98/atapi.c +++ /dev/null @@ -1,1074 +0,0 @@ -/* - * Device-independent level for ATAPI drivers. - * - * Copyright (C) 1995 Cronyx Ltd. - * Author Serge Vakulenko, <vak@cronyx.ru> - * - * This software is distributed with NO WARRANTIES, not even the implied - * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Authors grant any other persons or organisations permission to use - * or modify this software as long as this message is kept with the software, - * all derivative works or modified versions. - * - * Version 1.9, Mon Oct 9 22:34:47 MSK 1995 - */ - -/* - * The ATAPI level is implemented as a machine-dependent layer - * between the device driver and the IDE controller. - * All the machine- and controller dependency is isolated inside - * the ATAPI level, while all the device dependency is located - * in the device subdriver. - * - * It seems that an ATAPI bus will became popular for medium-speed - * storage devices such as CD-ROMs, magneto-optical disks, tape streamers etc. - * - * To ease the development of new ATAPI drivers, the subdriver - * interface was designed to be as simple as possible. - * - * Three routines are available for the subdriver to access the device: - * - * struct atapires atapi_request_wait (ata, unit, cmd, a1, a2, a3, a4, a5, - * a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, addr, count); - * struct atapi *ata; -- atapi controller descriptor - * int unit; -- device unit number on the IDE bus - * u_char cmd; -- ATAPI command code - * u_char a1..a15; -- ATAPI command arguments - * char *addr; -- address of the data buffer for i/o - * int count; -- data length, >0 for read ops, <0 for write ops - * - * The atapi_request_wait() function puts the op in the queue of ATAPI - * commands for the IDE controller, starts the controller, the waits for - * operation to be completed (using tsleep). - * The function should be called from the user phase only (open(), close(), - * ioctl() etc). - * Ata and unit args are the values which the subdriver gets from the ATAPI - * level via attach() call. - * Buffer pointed to by *addr should be placed in core memory, static - * or dynamic, but not in stack. - * The function returns the error code structure, which consists of: - * - atapi driver code value - * - controller status port value - * - controller error port value - * - * struct atapires atapi_request_immediate (ata, unit, cmd, a1, a2, a3, - * a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, - * addr, count); - * - * The atapi_request_immediate() function is similar to atapi_request_wait(), - * but it does not use interrupts for performing the request. - * It should be used during an attach phase to get parameters from the device. - * - * void atapi_request_callback (ata, unit, cmd, a1, a2, a3, a4, a5, - * a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, - * addr, count, done, x, y); - * struct atapi *ata; -- atapi controller descriptor - * int unit; -- device unit number on the IDE bus - * u_char cmd; -- ATAPI command code - * u_char a1..a15; -- ATAPI command arguments - * char *addr; -- address of the data buffer for i/o - * int count; -- data length, >0 for read ops, <0 for write ops - * void (*done)(); -- function to call when op finished - * void *x, *y; -- arguments for done() function - * - * The atapi_request_callback() function puts the op in the queue of ATAPI - * commands for the IDE controller, starts the controller, then returns. - * When the operation finishes, then the callback function done() - * will be called on the interrupt level. - * The function is designed to be callable from the interrupt phase. - * The done() functions is called with the following arguments: - * (void) (*done) (x, y, count, errcode) - * void *x, *y; -- arguments from the atapi_request_callback() - * int count; -- the data residual count - * struct atapires errcode; -- error code structure, see above - * - * The new driver could be added in three steps: - * 1. Add entries for the new driver to bdevsw and cdevsw tables in conf.c. - * You will need to make at least three routines: open(), close(), - * strategy() and possibly ioctl(). - * 2. Make attach() routine, which should allocate all the needed data - * structures and print the device description string (see wcdattach()). - * 3. Add an appropriate case to the switch in atapi_attach() routine, - * call attach() routine of the new driver here. Add the appropriate - * #include line at the top of attach.c. - * That's all! - * - * Use #define DEBUG in atapi.c to enable tracing of all i/o operations - * on the IDE bus. - */ -#undef DEBUG - -#include "wdc.h" -#include "opt_atapi.h" - -#ifndef ATAPI_MODULE -# include "wcd.h" -/* # include "wmt.h" -- add your driver here */ -/* # include "wmd.h" -- add your driver here */ -#endif - -#if NWDC > 0 && defined (ATAPI) - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/proc.h> -#include <sys/malloc.h> - -#include <machine/clock.h> -#include <machine/cpufunc.h> - -#ifdef ATAPI_MODULE -# define ATAPI_STATIC -#endif - -#ifdef PC98 -#include <pc98/pc98/atapi.h> -#else -#include <i386/isa/atapi.h> -#endif - -#ifndef ATAPI_STATIC -/* this code is compiled as part of the kernel if options ATAPI */ -/* - * In the case of loadable ATAPI driver we need to store - * the probe info for delayed attaching. - */ -struct atapidrv atapi_drvtab[4]; -int atapi_ndrv; -struct atapi *atapi_tab; - -int atapi_attach (int ctlr, int unit, int port) -{ - atapi_drvtab[atapi_ndrv].ctlr = ctlr; - atapi_drvtab[atapi_ndrv].unit = unit; - atapi_drvtab[atapi_ndrv].port = port; - atapi_drvtab[atapi_ndrv].attached = 0; - ++atapi_ndrv; - return (1); -} -#else /* ATAPI_STATIC */ -/* this code is compiled part of the module */ - -#ifdef DEBUG -# define print(s) printf s -#else -# define print(s) {/*void*/} -#endif - -/* - * ATAPI packet command phase. - */ -#define PHASE_CMDOUT (ARS_DRQ | ARI_CMD) -#define PHASE_DATAIN (ARS_DRQ | ARI_IN) -#define PHASE_DATAOUT ARS_DRQ -#define PHASE_COMPLETED (ARI_IN | ARI_CMD) -#define PHASE_ABORTED 0 /* nonstandard - for NEC 260 */ - -struct atapi atapitab[NWDC]; - -static struct atapi_params *atapi_probe (int port, int unit); -static int atapi_wait (int port, u_char bits_wanted); -static void atapi_send_cmd (struct atapi *ata, struct atapicmd *ac); -static int atapi_io (struct atapi *ata, struct atapicmd *ac); -static int atapi_start_cmd (struct atapi *ata, struct atapicmd *ac); -static int atapi_wait_cmd (struct atapi *ata, struct atapicmd *ac); - -extern int wdstart (int ctrlr); -extern int wcdattach(struct atapi*, int, struct atapi_params*, int); - -/* - * Probe the ATAPI device at IDE controller `ctlr', drive `unit'. - * Called at splbio(). - */ -#ifdef ATAPI_MODULE -static -#endif -int atapi_attach (int ctlr, int unit, int port) -{ - struct atapi *ata = atapitab + ctlr; - struct atapi_params *ap; - char buf [sizeof(ap->model) + 1]; - char revbuf [sizeof(ap->revision) + 1]; - struct atapicmd *ac; - - print (("atapi%d.%d at 0x%x: attach called\n", ctlr, unit, port)); - ap = atapi_probe (port, unit); - if (! ap) - return (0); - - bcopy (ap->model, buf, sizeof(buf)-1); - buf[sizeof(buf)-1] = 0; - - bcopy (ap->revision, revbuf, sizeof(revbuf)-1); - revbuf[sizeof(revbuf)-1] = 0; - - printf ("wdc%d: unit %d (atapi): <%s/%s>", ctlr, unit, buf, revbuf); - - /* device is removable */ - if (ap->removable) - printf (", removable"); - - /* packet command size */ - switch (ap->cmdsz) { - case AT_PSIZE_12: break; - case AT_PSIZE_16: printf (", cmd16"); ata->cmd16 = 1; break; - default: printf (", cmd%d", ap->cmdsz); - } - - /* DRQ type */ - switch (ap->drqtype) { - case AT_DRQT_MPROC: ata->slow = 1; break; - case AT_DRQT_INTR: printf (", intr"); ata->intrcmd = 1; break; - case AT_DRQT_ACCEL: printf (", accel"); break; - default: printf (", drq%d", ap->drqtype); - } - - /* overlap operation supported */ - if (ap->ovlapflag) - printf (", ovlap"); - - /* interleaved DMA supported */ - if (ap->idmaflag) - printf (", idma"); - /* DMA supported */ - else if (ap->dmaflag) - printf (", dma"); - - /* IORDY can be disabled */ - if (ap->iordydis) - printf (", iordis"); - /* IORDY supported */ - else if (ap->iordyflag) - printf (", iordy"); - - printf ("\n"); - - ata->port = port; - ata->ctrlr = ctlr; - ata->attached[unit] = 0; -#ifdef DEBUG - ata->debug = 1; -#else - ata->debug = 0; -#endif - /* Initialize free queue. */ - ata->cmdrq[15].next = 0; - for (ac = ata->cmdrq+14; ac >= ata->cmdrq; --ac) - ac->next = ac+1; - ata->free = ata->cmdrq; - - if (ap->proto != AT_PROTO_ATAPI) { - printf ("wdc%d: unit %d: unknown ATAPI protocol=%d\n", - ctlr, unit, ap->proto); - free (ap, M_TEMP); - return (0); - } -#ifdef ATAPI_MODULE - ata->params[unit] = ap; - return (1); -#else - switch (ap->devtype) { - default: - /* unknown ATAPI device */ - printf ("wdc%d: unit %d: unknown ATAPI type=%d\n", - ctlr, unit, ap->devtype); - break; - - case AT_TYPE_DIRECT: /* direct-access */ - case AT_TYPE_CDROM: /* CD-ROM device */ -#if NWCD > 0 - /* ATAPI CD-ROM */ - if (wcdattach (ata, unit, ap, ata->debug) < 0) - break; - /* Device attached successfully. */ - ata->attached[unit] = 1; - return (1); -#else - printf ("wdc%d: ATAPI CD-ROMs not configured\n", ctlr); - break; -#endif - - case AT_TYPE_TAPE: /* streaming tape (QIC-121 model) */ -#if NWMT > 0 - /* Add your driver here */ -#else - printf ("wdc%d: ATAPI streaming tapes not supported yet\n", ctlr); -#endif - break; - - case AT_TYPE_OPTICAL: /* optical disk */ -#if NWMD > 0 - /* Add your driver here */ -#else - printf ("wdc%d: ATAPI optical disks not supported yet\n", ctlr); -#endif - break; - } - /* Attach failed. */ - free (ap, M_TEMP); - return (0); -#endif /* ATAPI_MODULE */ -} - -static char *cmdname (u_char cmd) -{ - static char buf[8]; - - switch (cmd) { - case 0x00: return ("TEST_UNIT_READY"); - case 0x03: return ("REQUEST_SENSE"); - case 0x1b: return ("START_STOP"); - case 0x1e: return ("PREVENT_ALLOW"); - case 0x25: return ("READ_CAPACITY"); - case 0x28: return ("READ_BIG"); - case 0x43: return ("READ_TOC"); - case 0x42: return ("READ_SUBCHANNEL"); - case 0x55: return ("MODE_SELECT_BIG"); - case 0x5a: return ("MODE_SENSE"); - case 0xb4: return ("PLAY_CD"); - case 0x47: return ("PLAY_MSF"); - case 0x4b: return ("PAUSE"); - case 0x48: return ("PLAY_TRACK"); - case 0xa5: return ("PLAY_BIG"); - } - sprintf (buf, "[0x%x]", cmd); - return (buf); -} - -static void bswap (char *buf, int len) -{ - u_short *p = (u_short*) (buf + len); - while (--p >= (u_short*) buf) - *p = ntohs (*p); -} - -static void btrim (char *buf, int len) -{ - char *p; - - /* Remove the trailing spaces. */ - for (p=buf; p<buf+len; ++p) - if (! *p) - *p = ' '; - for (p=buf+len-1; p>=buf && *p==' '; --p) - *p = 0; -} - -/* - * Issue IDENTIFY command to ATAPI drive to ask it what it is. - */ -static struct atapi_params *atapi_probe (int port, int unit) -{ - struct atapi_params *ap; - char tb [DEV_BSIZE]; - int cnt; - -#ifdef PC98 - outb(0x432,unit%2); - print(("unit = %d,select %d\n",unit,unit%2)); -#endif - /* Wait for controller not busy. */ - outb (port + AR_DRIVE, unit ? ARD_DRIVE1 : ARD_DRIVE0); - if (atapi_wait (port, 0) < 0) { - print (("atapiX.%d at 0x%x: controller busy, status=%b\n", - unit, port, inb (port + AR_STATUS), ARS_BITS)); - return (0); - } - - /* Issue ATAPI IDENTIFY command. */ -#ifdef PC98 - outb (port + AR_DRIVE, unit/2 ? ARD_DRIVE1 : ARD_DRIVE0); - - /* Wait for DRQ deassert. */ - for (cnt=2000; cnt>0; --cnt) - if (! (inb (0x640 + AR_STATUS) & ARS_DRQ)) - break; - - outb (port + AR_COMMAND, ATAPIC_IDENTIFY); - DELAY(500); -#else - outb (port + AR_DRIVE, unit ? ARD_DRIVE1 : ARD_DRIVE0); - outb (port + AR_COMMAND, ATAPIC_IDENTIFY); -#endif - - /* Check that device is present. */ - if (inb (port + AR_STATUS) == 0xff) { - print (("atapiX.%d at 0x%x: no device\n", unit, port)); - if (unit == 1) - /* Select unit 0. */ - outb (port + AR_DRIVE, ARD_DRIVE0); - return (0); - } - - /* Wait for data ready. */ - if (atapi_wait (port, ARS_DRQ) != 0) { - print (("atapiX.%d at 0x%x: identify not ready, status=%b\n", - unit, port, inb (port + AR_STATUS), ARS_BITS)); - if (unit == 1) - /* Select unit 0. */ - outb (port + AR_DRIVE, ARD_DRIVE0); - return (0); - } - - /* Obtain parameters. */ - insw (port + AR_DATA, tb, sizeof(tb) / sizeof(short)); - - ap = malloc (sizeof *ap, M_TEMP, M_NOWAIT); - if (! ap) - return (0); - bcopy (tb, ap, sizeof *ap); - - /* - * Shuffle string byte order. - * Mitsumi and NEC drives don't need this. - */ - if (! ((ap->model[0] == 'N' && ap->model[1] == 'E') || - (ap->model[0] == 'F' && ap->model[1] == 'X'))) - bswap (ap->model, sizeof(ap->model)); - bswap (ap->serial, sizeof(ap->serial)); - bswap (ap->revision, sizeof(ap->revision)); - - /* Clean up the model name, serial and revision numbers. */ - btrim (ap->model, sizeof(ap->model)); - btrim (ap->serial, sizeof(ap->serial)); - btrim (ap->revision, sizeof(ap->revision)); - return (ap); -} - -/* - * Wait uninterruptibly until controller is not busy and certain - * status bits are set. - * The wait is usually short unless it is for the controller to process - * an entire critical command. - * Return 1 for (possibly stale) controller errors, -1 for timeout errors, - * or 0 for no errors. - */ -static int atapi_wait (int port, u_char bits_wanted) -{ - int cnt; - u_char s; - - /* Wait 5 sec for BUSY deassert. */ - for (cnt=500000; cnt>0; --cnt) { - s = inb (port + AR_STATUS); - if (! (s & ARS_BSY)) - break; - DELAY (10); - } - if (cnt <= 0) - return (-1); - if (! bits_wanted) - return (s & ARS_CHECK); - - /* Wait 50 msec for bits wanted. */ - for (cnt=5000; cnt>0; --cnt) { - s = inb (port + AR_STATUS); - if ((s & bits_wanted) == bits_wanted) - return (s & ARS_CHECK); - DELAY (10); - } - return (-1); -} - -void atapi_debug (struct atapi *ata, int on) -{ - ata->debug = on; -} - -static struct atapicmd *atapi_alloc (struct atapi *ata) -{ - struct atapicmd *ac; - - while (! ata->free) - tsleep ((caddr_t)ata, PRIBIO, "atacmd", 0); - ac = ata->free; - ata->free = ac->next; - ac->busy = 1; - return (ac); -} - -static void atapi_free (struct atapi *ata, struct atapicmd *ac) -{ - if (! ata->free) - wakeup ((caddr_t)&ata); - ac->busy = 0; - ac->next = ata->free; - ata->free = ac; -} - -/* - * Add new command request to the end of the queue. - */ -static void atapi_enqueue (struct atapi *ata, struct atapicmd *ac) -{ - ac->next = 0; - if (ata->tail) - ata->tail->next = ac; - else - ata->queue = ac; - ata->tail = ac; -} - -static void atapi_done (struct atapi *ata) -{ - struct atapicmd *ac = ata->queue; - - if (! ac) - return; /* cannot happen */ - - ata->queue = ac->next; - if (! ata->queue) - ata->tail = 0; - - if (ac->callback) { - (*ac->callback) (ac->cbarg1, ac->cbarg2, ac->count, ac->result); - atapi_free (ata, ac); - } else - wakeup ((caddr_t)ac); -} - -/* - * Start new packet op. Called from wdstart(). - * Return 1 if op started, and we are waiting for interrupt. - * Return 0 when idle. - */ -int atapi_start (int ctrlr) -{ - struct atapi *ata = atapitab + ctrlr; - struct atapicmd *ac; -again: - ac = ata->queue; - if (! ac) - return (0); - - /* Start packet command. */ - if (atapi_start_cmd (ata, ac) < 0) { - atapi_done (ata); - goto again; - } - - if (ata->intrcmd) - /* Wait for interrupt before sending packet command */ - return (1); - - /* Wait for DRQ. */ - if (atapi_wait_cmd (ata, ac) < 0) { - atapi_done (ata); - goto again; - } - - /* Send packet command. */ - atapi_send_cmd (ata, ac); - return (1); -} - -/* - * Start new packet op. Returns -1 on errors. - */ -int atapi_start_cmd (struct atapi *ata, struct atapicmd *ac) -{ - ac->result.error = 0; - ac->result.status = 0; - -#ifdef PC98 - outb(0x432,(ac->unit)%2); - print(("(ac->unit) = %d,select %d (2) \n",(ac->unit),(ac->unit)%2)); - outb (ata->port + AR_DRIVE, (ac->unit)/2 ? ARD_DRIVE1 : ARD_DRIVE0); -#else - outb (ata->port + AR_DRIVE, ac->unit ? ARD_DRIVE1 : ARD_DRIVE0); -#endif - if (atapi_wait (ata->port, 0) < 0) { - printf ("atapi%d.%d: controller not ready for cmd\n", - ata->ctrlr, ac->unit); - ac->result.code = RES_NOTRDY; - return (-1); - } - - /* Set up the controller registers. */ - outb (ata->port + AR_FEATURES, 0); - outb (ata->port + AR_IREASON, 0); - outb (ata->port + AR_TAG, 0); - outb (ata->port + AR_CNTLO, ac->count & 0xff); - outb (ata->port + AR_CNTHI, ac->count >> 8); - outb (ata->port + AR_COMMAND, ATAPIC_PACKET); - - if (ata->debug) - printf ("atapi%d.%d: start\n", ata->ctrlr, ac->unit); - return (0); -} - -/* - * Wait for DRQ before sending packet cmd. Returns -1 on errors. - */ -int atapi_wait_cmd (struct atapi *ata, struct atapicmd *ac) -{ - /* Wait for DRQ from 50 usec to 3 msec for slow devices */ - int cnt = ata->intrcmd ? 10000 : ata->slow ? 3000 : 50; - int ireason = 0, phase = 0; - - /* Wait for command phase. */ - for (; cnt>0; cnt-=10) { - ireason = inb (ata->port + AR_IREASON); - ac->result.status = inb (ata->port + AR_STATUS); - phase = (ireason & (ARI_CMD | ARI_IN)) | - (ac->result.status & ARS_DRQ); - if (phase == PHASE_CMDOUT) - break; - DELAY (10); - } - - if (phase != PHASE_CMDOUT) { - ac->result.code = RES_NODRQ; - ac->result.error = inb (ata->port + AR_ERROR); - printf ("atapi%d.%d: invalid command phase, ireason=0x%x, status=%b, error=%b\n", - ata->ctrlr, ac->unit, ireason, - ac->result.status, ARS_BITS, - ac->result.error, AER_BITS); - return (-1); - } - return (0); -} - -/* - * Send packet cmd. - */ -void atapi_send_cmd (struct atapi *ata, struct atapicmd *ac) -{ - outsw (ata->port + AR_DATA, ac->cmd, ata->cmd16 ? 8 : 6); - if (ata->debug) - printf ("atapi%d.%d: send cmd %s %x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x\n", - ata->ctrlr, ac->unit, cmdname (ac->cmd[0]), ac->cmd[0], - ac->cmd[1], ac->cmd[2], ac->cmd[3], ac->cmd[4], - ac->cmd[5], ac->cmd[6], ac->cmd[7], ac->cmd[8], - ac->cmd[9], ac->cmd[10], ac->cmd[11], ac->cmd[12], - ac->cmd[13], ac->cmd[14], ac->cmd[15]); -} - -/* - * Interrupt routine for the controller. Called from wdintr(). - * Finish the started op, wakeup wait-type commands, - * run callbacks for callback-type commands, then return. - * Do not start new op here, it will be done by wdstart, - * which is called just after us. - * Return 1 if op continues, and we are waiting for new interrupt. - * Return 0 when idle. - */ -int atapi_intr (int ctrlr) -{ - struct atapi *ata = atapitab + ctrlr; - struct atapicmd *ac = ata->queue; - -#ifdef PC98 - outb(0x432,(ac->unit)%2); - print(("atapi_intr:(ac->unit)= %d,select %d\n",ac->unit,(ac->unit)%2)); -#endif - - if (! ac) { - printf ("atapi%d: stray interrupt\n", ata->ctrlr); - return (0); - } - if (atapi_io (ata, ac) > 0) - return (1); - atapi_done (ata); - return (0); -} - -/* - * Process the i/o phase, transferring the command/data to/from the device. - * Return 1 if op continues, and we are waiting for new interrupt. - * Return 0 when idle. - */ -int atapi_io (struct atapi *ata, struct atapicmd *ac) -{ - u_char ireason; - u_short len, i; - - if (atapi_wait (ata->port, 0) < 0) { - ac->result.status = inb (ata->port + AR_STATUS); - ac->result.error = inb (ata->port + AR_ERROR); - ac->result.code = RES_NOTRDY; - printf ("atapi%d.%d: controller not ready, status=%b, error=%b\n", - ata->ctrlr, ac->unit, ac->result.status, ARS_BITS, - ac->result.error, AER_BITS); - return (0); - } - - ac->result.status = inb (ata->port + AR_STATUS); - ac->result.error = inb (ata->port + AR_ERROR); - len = inb (ata->port + AR_CNTLO); - len |= inb (ata->port + AR_CNTHI) << 8; - ireason = inb (ata->port + AR_IREASON); - - if (ata->debug) { - printf ("atapi%d.%d: intr ireason=0x%x, len=%d, status=%b, error=%b\n", - ata->ctrlr, ac->unit, ireason, len, - ac->result.status, ARS_BITS, - ac->result.error, AER_BITS); - } - switch ((ireason & (ARI_CMD | ARI_IN)) | (ac->result.status & ARS_DRQ)) { - default: - printf ("atapi%d.%d: unknown phase\n", ata->ctrlr, ac->unit); - ac->result.code = RES_ERR; - break; - - case PHASE_CMDOUT: - /* Send packet command. */ - if (! (ac->result.status & ARS_DRQ)) { - printf ("atapi%d.%d: no cmd drq\n", - ata->ctrlr, ac->unit); - ac->result.code = RES_NODRQ; - break; - } - atapi_send_cmd (ata, ac); - return (1); - - case PHASE_DATAOUT: - /* Write data */ - if (ac->count > 0) { - printf ("atapi%d.%d: invalid data direction\n", - ata->ctrlr, ac->unit); - ac->result.code = RES_INVDIR; - break; - } - if (-ac->count < len) { - print (("atapi%d.%d: send data underrun, %d bytes left\n", - ata->ctrlr, ac->unit, -ac->count)); - ac->result.code = RES_UNDERRUN; - outsw (ata->port + AR_DATA, ac->addr, - -ac->count / sizeof(short)); - for (i= -ac->count; i<len; i+=sizeof(short)) - outw (ata->port + AR_DATA, 0); - } else - outsw (ata->port + AR_DATA, ac->addr, - len / sizeof(short)); - ac->addr += len; - ac->count += len; - return (1); - - case PHASE_DATAIN: - /* Read data */ - if (ac->count < 0) { - printf ("atapi%d.%d: invalid data direction\n", - ata->ctrlr, ac->unit); - ac->result.code = RES_INVDIR; - break; - } - if (ac->count < len) { - print (("atapi%d.%d: recv data overrun, %d bytes left\n", - ata->ctrlr, ac->unit, ac->count)); - ac->result.code = RES_OVERRUN; - insw (ata->port + AR_DATA, ac->addr, - ac->count / sizeof(short)); - for (i=ac->count; i<len; i+=sizeof(short)) - inw (ata->port + AR_DATA); - } else - insw (ata->port + AR_DATA, ac->addr, - len / sizeof(short)); - ac->addr += len; - ac->count -= len; - return (1); - - case PHASE_ABORTED: - case PHASE_COMPLETED: - if (ac->result.status & (ARS_CHECK | ARS_DF)) - ac->result.code = RES_ERR; - else if (ac->count < 0) { - print (("atapi%d.%d: send data overrun, %d bytes left\n", - ata->ctrlr, ac->unit, -ac->count)); - ac->result.code = RES_OVERRUN; - } else if (ac->count > 0) { - print (("atapi%d.%d: recv data underrun, %d bytes left\n", - ata->ctrlr, ac->unit, ac->count)); - ac->result.code = RES_UNDERRUN; - bzero (ac->addr, ac->count); - } else - ac->result.code = RES_OK; - break; - } - return (0); -} - -/* - * Queue new packet request, then call wdstart(). - * Called on splbio(). - */ -void atapi_request_callback (struct atapi *ata, int unit, - u_char cmd, u_char a1, u_char a2, u_char a3, u_char a4, - u_char a5, u_char a6, u_char a7, u_char a8, u_char a9, - u_char a10, u_char a11, u_char a12, u_char a13, u_char a14, u_char a15, - char *addr, int count, atapi_callback_t *done, void *x, void *y) -{ - struct atapicmd *ac; - - ac = atapi_alloc (ata); - ac->cmd[0] = cmd; ac->cmd[1] = a1; - ac->cmd[2] = a2; ac->cmd[3] = a3; - ac->cmd[4] = a4; ac->cmd[5] = a5; - ac->cmd[6] = a6; ac->cmd[7] = a7; - ac->cmd[8] = a8; ac->cmd[9] = a9; - ac->cmd[10] = a10; ac->cmd[11] = a11; - ac->cmd[12] = a12; ac->cmd[13] = a13; - ac->cmd[14] = a14; ac->cmd[15] = a15; - ac->unit = unit; - ac->addr = addr; - ac->count = count; - ac->callback = done; - ac->cbarg1 = x; - ac->cbarg2 = y; - - if (ata->debug) - printf ("atapi%d.%d: req cb %x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x len=%d\n", - ata->ctrlr, ac->unit, ac->cmd[0], ac->cmd[1], - ac->cmd[2], ac->cmd[3], ac->cmd[4], ac->cmd[5], - ac->cmd[6], ac->cmd[7], ac->cmd[8], ac->cmd[9], - ac->cmd[10], ac->cmd[11], ac->cmd[12], - ac->cmd[13], ac->cmd[14], ac->cmd[15], count); - atapi_enqueue (ata, ac); - wdstart (ata->ctrlr); -} - -/* - * Queue new packet request, then call wdstart(). - * Wait until the request is finished. - * Called on spl0(). - * Return atapi error. - * Buffer pointed to by *addr should be placed in core memory, not in stack! - */ -struct atapires atapi_request_wait (struct atapi *ata, int unit, - u_char cmd, u_char a1, u_char a2, u_char a3, u_char a4, - u_char a5, u_char a6, u_char a7, u_char a8, u_char a9, - u_char a10, u_char a11, u_char a12, u_char a13, u_char a14, u_char a15, - char *addr, int count) -{ - struct atapicmd *ac; - int x = splbio (); - struct atapires result; - - ac = atapi_alloc (ata); - ac->cmd[0] = cmd; ac->cmd[1] = a1; - ac->cmd[2] = a2; ac->cmd[3] = a3; - ac->cmd[4] = a4; ac->cmd[5] = a5; - ac->cmd[6] = a6; ac->cmd[7] = a7; - ac->cmd[8] = a8; ac->cmd[9] = a9; - ac->cmd[10] = a10; ac->cmd[11] = a11; - ac->cmd[12] = a12; ac->cmd[13] = a13; - ac->cmd[14] = a14; ac->cmd[15] = a15; - ac->unit = unit; - ac->addr = addr; - ac->count = count; - ac->callback = 0; - ac->cbarg1 = 0; - ac->cbarg2 = 0; - - if (ata->debug) - printf ("atapi%d.%d: req w %x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x len=%d\n", - ata->ctrlr, ac->unit, ac->cmd[0], ac->cmd[1], - ac->cmd[2], ac->cmd[3], ac->cmd[4], ac->cmd[5], - ac->cmd[6], ac->cmd[7], ac->cmd[8], ac->cmd[9], - ac->cmd[10], ac->cmd[11], ac->cmd[12], - ac->cmd[13], ac->cmd[14], ac->cmd[15], count); - atapi_enqueue (ata, ac); - wdstart (ata->ctrlr); - tsleep ((caddr_t)ac, PRIBIO, "atareq", 0); - - result = ac->result; - atapi_free (ata, ac); - splx (x); - return (result); -} - -/* - * Perform a packet command on the device. - * Should be called on splbio(). - * Return atapi error. - */ -struct atapires atapi_request_immediate (struct atapi *ata, int unit, - u_char cmd, u_char a1, u_char a2, u_char a3, u_char a4, - u_char a5, u_char a6, u_char a7, u_char a8, u_char a9, - u_char a10, u_char a11, u_char a12, u_char a13, u_char a14, u_char a15, - char *addr, int count) -{ - struct atapicmd cmdbuf, *ac = &cmdbuf; - int cnt; - - ac->cmd[0] = cmd; ac->cmd[1] = a1; - ac->cmd[2] = a2; ac->cmd[3] = a3; - ac->cmd[4] = a4; ac->cmd[5] = a5; - ac->cmd[6] = a6; ac->cmd[7] = a7; - ac->cmd[8] = a8; ac->cmd[9] = a9; - ac->cmd[10] = a10; ac->cmd[11] = a11; - ac->cmd[12] = a12; ac->cmd[13] = a13; - ac->cmd[14] = a14; ac->cmd[15] = a15; - ac->unit = unit; - ac->addr = addr; - ac->count = count; - ac->callback = 0; - ac->cbarg1 = 0; - ac->cbarg2 = 0; - - if (ata->debug) - printf ("atapi%d.%d: req im %x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x len=%d\n", - ata->ctrlr, ac->unit, ac->cmd[0], ac->cmd[1], - ac->cmd[2], ac->cmd[3], ac->cmd[4], ac->cmd[5], - ac->cmd[6], ac->cmd[7], ac->cmd[8], ac->cmd[9], - ac->cmd[10], ac->cmd[11], ac->cmd[12], - ac->cmd[13], ac->cmd[14], ac->cmd[15], count); - - /* Start packet command, wait for DRQ. */ - if (atapi_start_cmd (ata, ac) >= 0 && atapi_wait_cmd (ata, ac) >= 0) { - /* Send packet command. */ - atapi_send_cmd (ata, ac); - - /* Wait for data i/o phase. */ - for (cnt=20000; cnt>0; --cnt) - if (((inb (ata->port + AR_IREASON) & (ARI_CMD | ARI_IN)) | - (inb (ata->port + AR_STATUS) & ARS_DRQ)) != PHASE_CMDOUT) - break; - - /* Do all needed i/o. */ - while (atapi_io (ata, ac)) - /* Wait for DRQ deassert. */ - for (cnt=2000; cnt>0; --cnt) - if (! (inb (ata->port + AR_STATUS) & ARS_DRQ)) - break; - } - return (ac->result); -} -#endif /* ATAPI_STATIC */ - -#if defined (ATAPI_MODULE) || !defined(ATAPI_STATIC) -int (*atapi_start_ptr) (int ctrlr); -int (*atapi_intr_ptr) (int ctrlr); -void (*atapi_debug_ptr) (struct atapi *ata, int on); -struct atapires (*atapi_request_wait_ptr) (struct atapi *ata, int unit, - u_char cmd, u_char a1, u_char a2, u_char a3, u_char a4, - u_char a5, u_char a6, u_char a7, u_char a8, u_char a9, - u_char a10, u_char a11, u_char a12, u_char a13, u_char a14, u_char a15, - char *addr, int count); -void (*atapi_request_callback_ptr) (struct atapi *ata, int unit, - u_char cmd, u_char a1, u_char a2, u_char a3, u_char a4, - u_char a5, u_char a6, u_char a7, u_char a8, u_char a9, - u_char a10, u_char a11, u_char a12, u_char a13, u_char a14, u_char a15, - char *addr, int count, atapi_callback_t *done, void *x, void *y); -struct atapires (*atapi_request_immediate_ptr) (struct atapi *ata, int unit, - u_char cmd, u_char a1, u_char a2, u_char a3, u_char a4, - u_char a5, u_char a6, u_char a7, u_char a8, u_char a9, - u_char a10, u_char a11, u_char a12, u_char a13, u_char a14, u_char a15, - char *addr, int count); -#endif - -#ifdef ATAPI_MODULE -/* - * ATAPI loadable driver stubs. - */ -#include <sys/exec.h> -#include <sys/conf.h> -#include <sys/sysent.h> -#include <sys/lkm.h> - -extern int atapi_lock (int ctlr); -/* - * XXX "ioconf.h" is not included by <sys/conf.h> for lkms, so we need this - * misplaced declaration. - */ -extern void wdintr (int); - -/* - * Construct lkm_misc structure (see lkm.h). - */ -MOD_MISC(atapi); - -int atapi_locked; - -int atapi_lock (int ctlr) -{ - atapi_locked = 1; - wakeup (&atapi_locked); - return (1); -} - -/* - * Function called when loading the driver. - */ -static int atapi_load (struct lkm_table *lkmtp, int cmd) -{ - struct atapidrv *d; - int n, x; - - /* - * Probe all free IDE units, searching for ATAPI drives. - */ - n = 0; - for (d=atapi_drvtab; d<atapi_drvtab+atapi_ndrv && d->port; ++d) { - /* Lock the controller. */ - x = splbio (); - atapi_locked = 0; - atapi_start_ptr = atapi_lock; - wdstart (d->ctlr); - while (! atapi_locked) - tsleep (&atapi_locked, PRIBIO, "atach", 0); - - /* Probe the drive. */ - if (atapi_attach (d->ctlr, d->unit, d->port)) { - d->attached = 1; - ++n; - } - - /* Unlock the controller. */ - atapi_start_ptr = 0; - wdintr (d->ctlr); - splx (x); - } - if (! n) - return ENXIO; - atapi_start_ptr = atapi_start; - atapi_intr_ptr = atapi_intr; - atapi_debug_ptr = atapi_debug; - atapi_request_wait_ptr = atapi_request_wait; - atapi_request_callback_ptr = atapi_request_callback; - atapi_request_immediate_ptr = atapi_request_immediate; - atapi_tab = atapitab; - return 0; -} - -/* - * Function called when unloading the driver. - */ -static int atapi_unload (struct lkm_table *lkmtp, int cmd) -{ - struct atapi *ata; - int u; - - for (ata=atapi_tab; ata<atapi_tab+2; ++ata) - if (ata->port) - for (u=0; u<2; ++u) - if (ata->attached[u]) - return EBUSY; - for (ata=atapi_tab; ata<atapi_tab+2; ++ata) - if (ata->port) - for (u=0; u<2; ++u) - if (ata->params[u]) { - free (ata->params[u], M_TEMP); - ata->params[u] = 0; - } - atapi_start_ptr = 0; - atapi_intr_ptr = 0; - atapi_debug_ptr = 0; - atapi_request_wait_ptr = 0; - atapi_request_callback_ptr = 0; - atapi_request_immediate_ptr = 0; - atapi_tab = 0; - return 0; -} - -/* - * Dispatcher function for the module (load/unload/stat). - */ -int atapi_mod (struct lkm_table *lkmtp, int cmd, int ver) -{ - DISPATCH (lkmtp, cmd, ver, atapi_load, atapi_unload, lkm_nullcmd); -} -#endif /* ATAPI_MODULE */ - -#endif /* NWDC && ATAPI */ diff --git a/sys/pc98/pc98/atapi.h b/sys/pc98/pc98/atapi.h index d43241b..5ff3d34 100644 --- a/sys/pc98/pc98/atapi.h +++ b/sys/pc98/pc98/atapi.h @@ -17,6 +17,18 @@ /* * Disk Controller ATAPI register definitions. */ +#ifdef PC98 +#define AR_DATA 0x0 /* RW - data register (16 bits) */ +#define AR_ERROR 0x2 /* R - error register */ +#define AR_FEATURES 0x2 /* W - features */ +#define AR_IREASON 0x4 /* RW - interrupt reason */ +#define AR_TAG 0x6 /* - reserved for SAM TAG byte */ +#define AR_CNTLO 0x8 /* RW - byte count, low byte */ +#define AR_CNTHI 0xa /* RW - byte count, high byte */ +#define AR_DRIVE 0xc /* RW - drive select */ +#define AR_COMMAND 0xe /* W - command register */ +#define AR_STATUS 0xe /* R - immediate status */ +#else #define AR_DATA 0x0 /* RW - data register (16 bits) */ #define AR_ERROR 0x1 /* R - error register */ #define AR_FEATURES 0x1 /* W - features */ @@ -27,6 +39,7 @@ #define AR_DRIVE 0x6 /* RW - drive select */ #define AR_COMMAND 0x7 /* W - command register */ #define AR_STATUS 0x7 /* R - immediate status */ +#endif /* * Status register bits diff --git a/sys/pc98/pc98/clock.c b/sys/pc98/pc98/clock.c index 3e9faf9..0ba9a65 100644 --- a/sys/pc98/pc98/clock.c +++ b/sys/pc98/pc98/clock.c @@ -34,7 +34,11 @@ * SUCH DAMAGE. * * from: @(#)clock.c 7.2 (Berkeley) 5/12/91 - * $Id: clock.c,v 1.8 1996/10/23 07:25:13 asami Exp $ + * $Id: clock.c,v 1.9 1996/10/29 08:36:19 asami Exp $ + */ + +/* + * Routines to handle clock hardware. */ /* @@ -48,10 +52,6 @@ * modified for PC98 by Kakefuda */ -/* - * Primitive clock interrupt routines. - */ - #include "opt_clock.h" #include "opt_cpu.h" @@ -72,13 +72,12 @@ #ifdef PC98 #include <pc98/pc98/pc98.h> #include <i386/isa/isa_device.h> -#include <pc98/pc98/timerreg.h> #else #include <i386/isa/isa.h> #include <i386/isa/isa_device.h> #include <i386/isa/rtc.h> -#include <i386/isa/timerreg.h> #endif +#include <i386/isa/timerreg.h> /* * 32-bit time_t's can't reach leap years before 1904 or after 2036, so we @@ -109,52 +108,49 @@ int adjkerntz; /* local offset from GMT in seconds */ int disable_rtc_set; /* disable resettodr() if != 0 */ -int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */ - u_int idelayed; #if defined(I586_CPU) || defined(I686_CPU) -u_int i586_ctr_bias; +u_int i586_ctr_bias; u_int i586_ctr_comultiplier; u_int i586_ctr_freq; u_int i586_ctr_multiplier; -long long i586_last_tick; -unsigned long i586_avg_tick; #endif int statclock_disable; u_int stat_imask = SWI_CLOCK_MASK; #ifdef TIMER_FREQ -static u_int timer_freq = TIMER_FREQ; +u_int timer_freq = TIMER_FREQ; #else #ifdef PC98 #ifndef AUTO_CLOCK #ifndef PC98_8M -static u_int timer_freq = 2457600; +u_int timer_freq = 2457600; #else /* !PC98_8M */ -static u_int timer_freq = 1996800; +u_int timer_freq = 1996800; #endif /* PC98_8M */ #else /* AUTO_CLOCK */ -static u_int timer_freq = 2457600; +u_int timer_freq = 2457600; #endif /* AUTO_CLOCK */ #else /* IBM-PC */ -static u_int timer_freq = 1193182; +u_int timer_freq = 1193182; #endif /* PC98 */ #endif -int timer0_max_count; -u_int timer0_overflow_threshold; -u_int timer0_prescaler_count; +int timer0_max_count; +u_int timer0_overflow_threshold; +u_int timer0_prescaler_count; +int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */ static int beeping = 0; static u_int clk_imask = HWI_MASK | SWI_MASK; static const u_char daysinmonth[] = {31,28,31,30,31,30,31,31,30,31,30,31}; -static u_int hardclock_max_count; +static u_int hardclock_max_count; /* * XXX new_function and timer_func should not handle clockframes, but * timer_func currently needs to hold hardclock to handle the * timer0_state == 0 case. We should use register_intr()/unregister_intr() * to switch between clkintr() and a slightly different timerintr(). */ -static void (*new_function) __P((struct clockframe *frame)); -static u_int new_rate; +static void (*new_function) __P((struct clockframe *frame)); +static u_int new_rate; #ifndef PC98 static u_char rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF; static u_char rtc_statusb = RTCSB_24HR | RTCSB_PINTR; @@ -171,7 +167,7 @@ static u_char timer0_state; static u_char timer1_state; #endif static u_char timer2_state; -static void (*timer_func) __P((struct clockframe *frame)) = hardclock; +static void (*timer_func) __P((struct clockframe *frame)) = hardclock; int rtc_inb __P((void)); #if defined(I586_CPU) || defined(I686_CPU) @@ -437,7 +433,7 @@ getit(void) disable_intr(); /* Select timer0 and latch counter value. */ - outb(TIMER_MODE, TIMER_SEL0); + outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH); low = inb(TIMER_CNTR0); high = inb(TIMER_CNTR0); @@ -625,7 +621,7 @@ calibrate_clocks(void) u_int count, prev_count, tot_count; int sec, start_sec, timeout; - printf("Calibrating clock(s) relative to mc146818A clock...\n"); + printf("Calibrating clock(s) relative to mc146818A clock ... "); if (!(rtcin(RTC_STATUSD) & RTCSD_PWR)) goto fail; timeout = 100000000; @@ -782,7 +778,7 @@ startrtclock() if (delta < timer_freq / 100) { #ifndef CLK_USE_I8254_CALIBRATION if (bootverbose) - printf( + printf( "CLK_USE_I8254_CALIBRATION not specified - using default frequency\n"); freq = timer_freq; #endif @@ -802,7 +798,7 @@ startrtclock() #ifndef CLK_USE_I586_CALIBRATION if (i586_ctr_freq != 0) { if (bootverbose) - printf( + printf( "CLK_USE_I586_CALIBRATION not specified - using old calibration method\n"); i586_ctr_freq = 0; } @@ -1114,10 +1110,8 @@ cpu_initclocks() /* * Finish setting up anti-jitter measures. */ - if (i586_ctr_freq != 0) { - i586_last_tick = rdtsc(); - i586_ctr_bias = i586_last_tick; - } + if (i586_ctr_freq != 0) + i586_ctr_bias = rdtsc(); #endif #ifndef PC98 diff --git a/sys/pc98/pc98/icu.s b/sys/pc98/pc98/icu.s deleted file mode 100644 index 567daf1..0000000 --- a/sys/pc98/pc98/icu.s +++ /dev/null @@ -1,357 +0,0 @@ -/*- - * Copyright (c) 1989, 1990 William F. Jolitz. - * Copyright (c) 1990 The Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * William Jolitz. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)icu.s 7.2 (Berkeley) 5/21/91 - * - * $Id: icu.s,v 1.25 1996/05/31 01:08:07 peter Exp $ - */ - -/* - * AT/386 - * Vector interrupt control section - */ - -/* - * XXX this file should be named ipl.s. All spls are now soft and the - * only thing related to the hardware icu is that the h/w interrupt - * numbers are used without translation in the masks. - */ - - .data - .globl _cpl -_cpl: .long HWI_MASK | SWI_MASK /* current priority (all off) */ - .globl _imen -_imen: .long HWI_MASK /* interrupt mask enable (all h/w off) */ - .globl _tty_imask -_tty_imask: .long 0 - .globl _bio_imask -_bio_imask: .long 0 - .globl _net_imask -_net_imask: .long 0 - .globl _ipending -_ipending: .long 0 - .globl _netisr -_netisr: .long 0 /* set with bits for which queue to service */ - .globl _netisrs -_netisrs: - .long dummynetisr, dummynetisr, dummynetisr, dummynetisr - .long dummynetisr, dummynetisr, dummynetisr, dummynetisr - .long dummynetisr, dummynetisr, dummynetisr, dummynetisr - .long dummynetisr, dummynetisr, dummynetisr, dummynetisr - .long dummynetisr, dummynetisr, dummynetisr, dummynetisr - .long dummynetisr, dummynetisr, dummynetisr, dummynetisr - .long dummynetisr, dummynetisr, dummynetisr, dummynetisr - .long dummynetisr, dummynetisr, dummynetisr, dummynetisr -vec: - .long vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7 - .long vec8, vec9, vec10, vec11, vec12, vec13, vec14, vec15 - - .text - -/* - * Handle return from interrupts, traps and syscalls. - */ - SUPERALIGN_TEXT -_doreti: - FAKE_MCOUNT(_bintr) /* init "from" _bintr -> _doreti */ - addl $4,%esp /* discard unit number */ - popl %eax /* cpl to restore */ -doreti_next: - /* - * Check for pending HWIs and SWIs atomically with restoring cpl - * and exiting. The check has to be atomic with exiting to stop - * (ipending & ~cpl) changing from zero to nonzero while we're - * looking at it (this wouldn't be fatal but it would increase - * interrupt latency). Restoring cpl has to be atomic with exiting - * so that the stack cannot pile up (the nesting level of interrupt - * handlers is limited by the number of bits in cpl). - */ - movl %eax,%ecx - notl %ecx - cli - andl _ipending,%ecx - jne doreti_unpend -doreti_exit: - movl %eax,_cpl - decb _intr_nesting_level - MEXITCOUNT - .globl doreti_popl_es -doreti_popl_es: - popl %es - .globl doreti_popl_ds -doreti_popl_ds: - popl %ds - popal - addl $8,%esp - .globl doreti_iret -doreti_iret: - iret - - ALIGN_TEXT - .globl doreti_iret_fault -doreti_iret_fault: - subl $8,%esp - pushal - pushl %ds - .globl doreti_popl_ds_fault -doreti_popl_ds_fault: - pushl %es - .globl doreti_popl_es_fault -doreti_popl_es_fault: - movl $0,4+4+32+4(%esp) /* XXX should be the error code */ - movl $T_PROTFLT,4+4+32+0(%esp) - jmp alltraps_with_regs_pushed - - ALIGN_TEXT -doreti_unpend: - /* - * Enabling interrupts is safe because we haven't restored cpl yet. - * The locking from the "btrl" test is probably no longer necessary. - * We won't miss any new pending interrupts because we will check - * for them again. - */ - sti - bsfl %ecx,%ecx /* slow, but not worth optimizing */ - btrl %ecx,_ipending - jnc doreti_next /* some intr cleared memory copy */ - movl ihandlers(,%ecx,4),%edx - testl %edx,%edx - je doreti_next /* "can't happen" */ - cmpl $NHWI,%ecx - jae doreti_swi - cli - movl %eax,_cpl - MEXITCOUNT - jmp %edx - - ALIGN_TEXT -doreti_swi: - pushl %eax - /* - * The SWI_AST handler has to run at cpl = SWI_AST_MASK and the - * SWI_CLOCK handler at cpl = SWI_CLOCK_MASK, so we have to restore - * all the h/w bits in cpl now and have to worry about stack growth. - * The worst case is currently (30 Jan 1994) 2 SWI handlers nested - * in dying interrupt frames and about 12 HWIs nested in active - * interrupt frames. There are only 4 different SWIs and the HWI - * and SWI masks limit the nesting further. - */ - orl imasks(,%ecx,4),%eax - movl %eax,_cpl - call %edx - popl %eax - jmp doreti_next - - ALIGN_TEXT -swi_ast: - addl $8,%esp /* discard raddr & cpl to get trap frame */ - testb $SEL_RPL_MASK,TRAPF_CS_OFF(%esp) - je swi_ast_phantom - movl $T_ASTFLT,(2+8+0)*4(%esp) - call _trap - subl %eax,%eax /* recover cpl */ - jmp doreti_next - - ALIGN_TEXT -swi_ast_phantom: - /* - * These happen when there is an interrupt in a trap handler before - * ASTs can be masked or in an lcall handler before they can be - * masked or after they are unmasked. They could be avoided for - * trap entries by using interrupt gates, and for lcall exits by - * using by using cli, but they are unavoidable for lcall entries. - */ - cli - orl $SWI_AST_PENDING,_ipending - subl %eax,%eax - jmp doreti_exit /* SWI_AST is highest so we must be done */ - -/* - * Interrupt priority mechanism - * -- soft splXX masks with group mechanism (cpl) - * -- h/w masks for currently active or unused interrupts (imen) - * -- ipending = active interrupts currently masked by cpl - */ - -ENTRY(splz) - /* - * The caller has restored cpl and checked that (ipending & ~cpl) - * is nonzero. We have to repeat the check since if there is an - * interrupt while we're looking, _doreti processing for the - * interrupt will handle all the unmasked pending interrupts - * because we restored early. We're repeating the calculation - * of (ipending & ~cpl) anyway so that the caller doesn't have - * to pass it, so this only costs one "jne". "bsfl %ecx,%ecx" - * is undefined when %ecx is 0 so we can't rely on the secondary - * btrl tests. - */ - movl _cpl,%eax -splz_next: - /* - * We don't need any locking here. (ipending & ~cpl) cannot grow - * while we're looking at it - any interrupt will shrink it to 0. - */ - movl %eax,%ecx - notl %ecx - andl _ipending,%ecx - jne splz_unpend - ret - - ALIGN_TEXT -splz_unpend: - bsfl %ecx,%ecx - btrl %ecx,_ipending - jnc splz_next - movl ihandlers(,%ecx,4),%edx - testl %edx,%edx - je splz_next /* "can't happen" */ - cmpl $NHWI,%ecx - jae splz_swi - /* - * We would prefer to call the intr handler directly here but that - * doesn't work for badly behaved handlers that want the interrupt - * frame. Also, there's a problem determining the unit number. - * We should change the interface so that the unit number is not - * determined at config time. - */ - jmp *vec(,%ecx,4) - - ALIGN_TEXT -splz_swi: - cmpl $SWI_AST,%ecx - je splz_next /* "can't happen" */ - pushl %eax - orl imasks(,%ecx,4),%eax - movl %eax,_cpl - call %edx - popl %eax - movl %eax,_cpl - jmp splz_next - -/* - * Fake clock interrupt(s) so that they appear to come from our caller instead - * of from here, so that system profiling works. - * XXX do this more generally (for all vectors; look up the C entry point). - * XXX frame bogusness stops us from just jumping to the C entry point. - */ - ALIGN_TEXT -vec0: - popl %eax /* return address */ - pushfl -#define KCSEL 8 - pushl $KCSEL - pushl %eax - cli - MEXITCOUNT - jmp _Xintr0 /* XXX might need _Xfastintr0 */ - -#ifndef PC98 - ALIGN_TEXT -vec8: - popl %eax - pushfl - pushl $KCSEL - pushl %eax - cli - MEXITCOUNT - jmp _Xintr8 /* XXX might need _Xfastintr8 */ -#endif - -#define BUILD_VEC(irq_num) \ - ALIGN_TEXT ; \ -__CONCAT(vec,irq_num): ; \ - int $ICU_OFFSET + (irq_num) ; \ - ret - - BUILD_VEC(1) - BUILD_VEC(2) - BUILD_VEC(3) - BUILD_VEC(4) - BUILD_VEC(5) - BUILD_VEC(6) - BUILD_VEC(7) -#ifdef PC98 - BUILD_VEC(8) -#endif - BUILD_VEC(9) - BUILD_VEC(10) - BUILD_VEC(11) - BUILD_VEC(12) - BUILD_VEC(13) - BUILD_VEC(14) - BUILD_VEC(15) - - ALIGN_TEXT -swi_net: - MCOUNT - bsfl _netisr,%eax - je swi_net_done -swi_net_more: - btrl %eax,_netisr - jnc swi_net_next - call *_netisrs(,%eax,4) -swi_net_next: - bsfl _netisr,%eax - jne swi_net_more -swi_net_done: - ret - - ALIGN_TEXT -dummynetisr: - MCOUNT - ret - -/* - * XXX there should be a registration function to put the handler for the - * attached driver directly in ihandlers. Then this function will go away. - */ - ALIGN_TEXT -swi_tty: - MCOUNT -#include "cy.h" -#if NCY > 0 - call _cypoll -#endif -#include "rc.h" -#if NRC > 0 - call _rcpoll -#endif -#include "sio.h" -#if NSIO > 0 - jmp _siopoll -#else - ret -#endif diff --git a/sys/pc98/pc98/if_ed.c b/sys/pc98/pc98/if_ed.c index 6b7bf2f..9e1d45b 100644 --- a/sys/pc98/pc98/if_ed.c +++ b/sys/pc98/pc98/if_ed.c @@ -24,7 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: if_ed.c,v 1.9 1996/10/23 07:25:17 asami Exp $ + * $Id: if_ed.c,v 1.10 1996/10/29 08:36:20 asami Exp $ */ /* @@ -106,7 +106,17 @@ #include <i386/isa/if_edreg.h> #ifdef PC98 -#include <pc98/pc98/if_ed98.h> +/* register offsets */ +struct pc98_edregister { + u_int *port; + u_int ioskip; + u_int nic_offset; + u_int asic_offset; + u_int data; + u_int reset; + u_int pc_misc; + u_int pc_reset; +}; #endif /* @@ -160,12 +170,16 @@ struct ed_softc { u_char next_packet; /* pointer to next unread RX packet */ struct ifmib_iso_8802_3 mibdata; /* stuff for network mgmt */ #ifdef PC98 - int unit; + struct pc98_edregister edreg; /* I/O port register offset info */ #endif }; static struct ed_softc ed_softc[NED]; +#ifdef PC98 +#include <pc98/pc98/if_ed98.h> +#endif + static int ed_attach __P((struct ed_softc *, int, int)); static int ed_attach_isa __P((struct isa_device *)); @@ -421,10 +435,6 @@ ed_probe(isa_dev) { int nports; -#ifdef PC98 - ed_softc[isa_dev->id_unit].unit = isa_dev->id_unit; -#endif - #if NCRD > 0 /* * If PC-Card probe required, then register driver with @@ -443,7 +453,7 @@ ed_probe(isa_dev) if ((ED_TYPE98(isa_dev->id_flags) == ED_TYPE98_GENERIC) || (ED_TYPE98(isa_dev->id_flags) == ED_TYPE98_LPC)) { ed_softc[isa_dev->id_unit].type = ED_TYPE98_LPC; - pc98_set_register(isa_dev, isa_dev->id_unit, ED_TYPE98_LPC); + pc98_set_register(isa_dev, ED_TYPE98_LPC); nports = ed_probe_Novell(isa_dev); if (nports) return (nports); @@ -454,7 +464,7 @@ ed_probe(isa_dev) * Allied Telesis CenterCom LA-98-T */ ed_softc[isa_dev->id_unit].type = ED_TYPE98_GENERIC; - pc98_set_register(isa_dev, isa_dev->id_unit, ED_TYPE98_GENERIC); + pc98_set_register(isa_dev, ED_TYPE98_GENERIC); if (ED_TYPE98(isa_dev->id_flags) == ED_TYPE98_GENERIC) { #endif @@ -478,7 +488,7 @@ ed_probe(isa_dev) if ((ED_TYPE98(isa_dev->id_flags) == ED_TYPE98_GENERIC) || (ED_TYPE98(isa_dev->id_flags) == ED_TYPE98_SIC)) { ed_softc[isa_dev->id_unit].type = ED_TYPE98_SIC; - pc98_set_register(isa_dev, isa_dev->id_unit, ED_TYPE98_SIC); + pc98_set_register(isa_dev, ED_TYPE98_SIC); nports = ed_probe_SIC98(isa_dev); if (nports) return (nports); @@ -492,7 +502,7 @@ ed_probe(isa_dev) (ED_TYPE98(isa_dev->id_flags) == ED_TYPE98_BDN)) { /* LD-BDN */ ed_softc[isa_dev->id_unit].type = ED_TYPE98_BDN; - pc98_set_register(isa_dev, isa_dev->id_unit, ED_TYPE98_BDN); + pc98_set_register(isa_dev, ED_TYPE98_BDN); nports = ed_probe_Novell(isa_dev); if (nports) return (nports); @@ -506,7 +516,7 @@ ed_probe(isa_dev) (ED_TYPE98(isa_dev->id_flags) == ED_TYPE98_LGY)) { /* LGY-98 */ ed_softc[isa_dev->id_unit].type = ED_TYPE98_LGY; - pc98_set_register(isa_dev, isa_dev->id_unit, ED_TYPE98_LGY); + pc98_set_register(isa_dev, ED_TYPE98_LGY); nports = ed_probe_Novell(isa_dev); if (nports) return (nports); @@ -520,7 +530,7 @@ ed_probe(isa_dev) (ED_TYPE98(isa_dev->id_flags) == ED_TYPE98_ICM)) { /* ICM */ ed_softc[isa_dev->id_unit].type = ED_TYPE98_ICM; - pc98_set_register(isa_dev, isa_dev->id_unit, ED_TYPE98_ICM); + pc98_set_register(isa_dev, ED_TYPE98_ICM); nports = ed_probe_Novell(isa_dev); if (nports) return (nports); @@ -534,7 +544,7 @@ ed_probe(isa_dev) (ED_TYPE98(isa_dev->id_flags) == ED_TYPE98_EGY)) { /* EGY-98 */ ed_softc[isa_dev->id_unit].type = ED_TYPE98_EGY; - pc98_set_register(isa_dev, isa_dev->id_unit, ED_TYPE98_EGY); + pc98_set_register(isa_dev, ED_TYPE98_EGY); nports = ed_probe_Novell(isa_dev); if (nports) return (nports); @@ -547,7 +557,7 @@ ed_probe(isa_dev) (ED_TYPE98(isa_dev->id_flags) == ED_TYPE98_LA98)) { /* LA-98 */ ed_softc[isa_dev->id_unit].type = ED_TYPE98_LA98; - pc98_set_register(isa_dev, isa_dev->id_unit, ED_TYPE98_LA98); + pc98_set_register(isa_dev, ED_TYPE98_LA98); nports = ed_probe_Novell(isa_dev); if (nports) return (nports); @@ -560,7 +570,7 @@ ed_probe(isa_dev) (ED_TYPE98(isa_dev->id_flags) == ED_TYPE98_108)) { /* PC-9801-108 */ ed_softc[isa_dev->id_unit].type = ED_TYPE98_108; - pc98_set_register(isa_dev, isa_dev->id_unit, ED_TYPE98_108); + pc98_set_register(isa_dev, ED_TYPE98_108); nports = ed_probe_Novell(isa_dev); if (nports) return (nports); @@ -573,7 +583,7 @@ ed_probe(isa_dev) (ED_TYPE98(isa_dev->id_flags) == ED_TYPE98_CNET98EL)) { /* C-NET(98)E/L */ ed_softc[isa_dev->id_unit].type = ED_TYPE98_CNET98EL; - pc98_set_register(isa_dev, isa_dev->id_unit, ED_TYPE98_CNET98EL); + pc98_set_register(isa_dev, ED_TYPE98_CNET98EL); nports = ed_probe_CNET98EL(isa_dev); if (nports) return (nports); @@ -586,7 +596,7 @@ ed_probe(isa_dev) (ED_TYPE98(isa_dev->id_flags) == ED_TYPE98_CNET98)) { /* C-NET(98) */ ed_softc[isa_dev->id_unit].type = ED_TYPE98_CNET98; - pc98_set_register(isa_dev, isa_dev->id_unit, ED_TYPE98_CNET98); + pc98_set_register(isa_dev, ED_TYPE98_CNET98); nports = ed_probe_CNET98(isa_dev); if (nports) return (nports); @@ -628,10 +638,6 @@ ed_probe_generic8390(sc) struct ed_softc *sc; { #ifdef PC98 - int unit = sc->unit; -#endif - -#ifdef PC98 if (sc->type == ED_TYPE98_LPC) { if ((inb(sc->nic_addr + ED_P0_CR) & (ED_CR_RD2 | ED_CR_TXP | ED_CR_STA | ED_CR_STP)) != @@ -1036,9 +1042,6 @@ ed_probe_3Com(isa_dev) int i; u_int memsize; u_char isa16bit; -#ifdef PC98 - int unit = isa_dev->id_unit; -#endif sc->asic_addr = isa_dev->id_iobase + ED_3COM_ASIC_OFFSET; sc->nic_addr = isa_dev->id_iobase + ED_3COM_NIC_OFFSET; @@ -1359,7 +1362,6 @@ ed_probe_Novell_generic(sc, port, unit, flags) if (sc->type == ED_TYPE98_LPC) LPCT_1d0_OFF(); #endif - DELAY(5000); /* @@ -1592,7 +1594,7 @@ ed_probe_Novell(isa_dev) } #if NCRD > 0 - + /* * Probe framework for pccards. Replicates the standard framework, * minus the pccard driver registration and ignores the ether address @@ -1653,9 +1655,7 @@ ed_probe_HP_pclanp(isa_dev) u_char irq; /* board configured IRQ */ char test_pattern[ED_HPP_TEST_SIZE]; /* read/write areas for */ char test_buffer[ED_HPP_TEST_SIZE]; /* probing card */ -#ifdef PC98 - int unit = isa_dev->id_unit; -#endif + /* Fill in basic information */ sc->asic_addr = isa_dev->id_iobase + ED_HPP_ASIC_OFFSET; @@ -2503,9 +2503,6 @@ ed_stop(sc) struct ed_softc *sc; { int n = 5000; -#ifdef PC98 - int unit = sc->unit; -#endif if (sc->gone) return; @@ -2550,9 +2547,6 @@ ed_init(xsc) struct ed_softc *sc = xsc; struct ifnet *ifp = &sc->arpcom.ac_if; int i, s; -#ifdef PC98 - int unit = sc->unit; -#endif if (sc->gone) return; @@ -2655,7 +2649,7 @@ ed_init(xsc) */ #ifdef PC98 for (i = 0; i < ETHER_ADDR_LEN; ++i) - outb(sc->nic_addr + ED_P1_PAR0 + i * pc98_io_skip[unit], + outb(sc->nic_addr + ED_P1_PAR0 + i * sc->edreg.ioskip, sc->arpcom.ac_enaddr[i]); #else for (i = 0; i < ETHER_ADDR_LEN; ++i) @@ -2713,9 +2707,6 @@ ed_xmit(sc) { struct ifnet *ifp = (struct ifnet *)sc; unsigned short len; -#ifdef PC98 - int unit = sc->unit; -#endif if (sc->gone) return; @@ -2930,9 +2921,6 @@ ed_rint(sc) u_short len; struct ed_ring packet_hdr; char *packet_ptr; -#ifdef PC98 - int unit = sc->unit; -#endif if (sc->gone) return; @@ -3056,9 +3044,6 @@ edintr_sc(sc) { struct ifnet *ifp = (struct ifnet *)sc; u_char isr; -#ifdef PC98 - int unit = sc->unit; -#endif if (sc->gone) return; @@ -3548,10 +3533,6 @@ ed_pio_readmem(sc, src, dst, amount) unsigned char *dst; unsigned short amount; { -#ifdef PC98 - int unit = sc->unit; -#endif - /* HP cards need special handling */ if (sc->vendor == ED_VENDOR_HP && sc->type == ED_TYPE_HP_PCLANPLUS) { ed_hpp_readmem(sc, src, dst, amount); @@ -3603,9 +3584,6 @@ ed_pio_writemem(sc, src, dst, len) unsigned short len; { int maxwait = 200; /* about 240us */ -#ifdef PC98 - int unit = sc->unit; -#endif if (sc->vendor == ED_VENDOR_NOVELL) { @@ -3711,9 +3689,6 @@ ed_pio_write_mbufs(sc, m, dst) unsigned short total_len, dma_len; struct mbuf *mp; int maxwait = 200; /* about 240us */ -#ifdef PC98 - int unit = sc->unit; -#endif /* HP PC Lan+ cards need special handling */ if ((sc->vendor == ED_VENDOR_HP) && @@ -3977,9 +3952,6 @@ ed_hpp_write_mbufs(struct ed_softc *sc, struct mbuf *m, int dst) volatile u_short * const d = (volatile u_short *) sc->hpp_mem_start; int use_32bit_accesses = !(sc->hpp_id & ED_HPP_ID_16_BIT_ACCESS); -#ifdef PC98 - int unit = sc->unit; -#endif /* select page 0 registers */ outb(sc->nic_addr + ED_P0_CR, sc->cr_proto | ED_CR_STA); @@ -4095,9 +4067,6 @@ ed_setrcr(sc) { struct ifnet *ifp = (struct ifnet *)sc; int i; -#ifdef PC98 - int unit = sc->unit; -#endif /* set page 1 registers */ outb(sc->nic_addr + ED_P0_CR, sc->cr_proto | ED_CR_PAGE_1 | ED_CR_STP); @@ -4109,7 +4078,7 @@ ed_setrcr(sc) */ #ifdef PC98 for (i = 0; i < 8; i++) - outb(sc->nic_addr + ED_P1_MAR0 + i * pc98_io_skip[unit], 0xff); + outb(sc->nic_addr + ED_P1_MAR0 + i * sc->edreg.ioskip, 0xff); #else for (i = 0; i < 8; i++) outb(sc->nic_addr + ED_P1_MAR0 + i, 0xff); @@ -4139,7 +4108,7 @@ ed_setrcr(sc) */ #ifdef PC98 for (i = 0; i < 8; i++) - outb(sc->nic_addr + ED_P1_MAR0 + i * pc98_io_skip[unit], + outb(sc->nic_addr + ED_P1_MAR0 + i * sc->edreg.ioskip, ((u_char *) mcaf)[i]); #else for (i = 0; i < 8; i++) @@ -4155,12 +4124,12 @@ ed_setrcr(sc) * Initialize multicast address hashing registers to * not accept multicasts. */ -#ifndef PC98 +#ifdef PC98 for (i = 0; i < 8; ++i) - outb(sc->nic_addr + ED_P1_MAR0 + i, 0x00); + outb(sc->nic_addr + ED_P1_MAR0 + i * sc->edreg.ioskip, 0x00); #else for (i = 0; i < 8; ++i) - outb(sc->nic_addr + ED_P1_MAR0 + i * pc98_io_skip[unit], 0x00); + outb(sc->nic_addr + ED_P1_MAR0 + i, 0x00); #endif /* Set page 0 registers */ diff --git a/sys/pc98/pc98/if_ed98.h b/sys/pc98/pc98/if_ed98.h index 9924e36..476d574 100644 --- a/sys/pc98/pc98/if_ed98.h +++ b/sys/pc98/pc98/if_ed98.h @@ -36,8 +36,7 @@ #error Why you include if_ed98.h? #endif -static void pc98_set_register __P((struct isa_device *dev, - int unit, int type)); +static void pc98_set_register __P((struct isa_device *dev, int type)); /* * Vendor types @@ -50,11 +49,11 @@ static void pc98_set_register __P((struct isa_device *dev, #ifdef ED_NOVELL_NIC_OFFSET #undef ED_NOVELL_NIC_OFFSET #endif -#define ED_NOVELL_NIC_OFFSET ed_novell_nic_offset[unit] +#define ED_NOVELL_NIC_OFFSET sc->edreg.nic_offset #ifdef ED_NOVELL_ASIC_OFFSET #undef ED_NOVELL_ASIC_OFFSET #endif -#define ED_NOVELL_ASIC_OFFSET ed_novell_asic_offset[unit] +#define ED_NOVELL_ASIC_OFFSET sc->edreg.asic_offset /* * Remote DMA data register; for reading or writing to the NIC mem @@ -63,7 +62,7 @@ static void pc98_set_register __P((struct isa_device *dev, #ifdef ED_NOVELL_DATA #undef ED_NOVELL_DATA #endif -#define ED_NOVELL_DATA ed_novell_data[unit] +#define ED_NOVELL_DATA sc->edreg.data /* * Reset register; reading from this register causes a board reset @@ -71,7 +70,7 @@ static void pc98_set_register __P((struct isa_device *dev, #ifdef ED_NOVELL_RESET #undef ED_NOVELL_RESET #endif -#define ED_NOVELL_RESET ed_novell_reset[unit] +#define ED_NOVELL_RESET sc->edreg.reset /* * Card type @@ -113,152 +112,152 @@ static void pc98_set_register __P((struct isa_device *dev, * Page 0 register offsets */ #undef ED_P0_CR -#define ED_P0_CR edp[unit][0x00] +#define ED_P0_CR sc->edreg.port[0x00] #undef ED_P0_CLDA0 -#define ED_P0_CLDA0 edp[unit][0x01] +#define ED_P0_CLDA0 sc->edreg.port[0x01] #undef ED_P0_PSTART -#define ED_P0_PSTART edp[unit][0x01] +#define ED_P0_PSTART sc->edreg.port[0x01] #undef ED_P0_CLDA1 -#define ED_P0_CLDA1 edp[unit][0x02] +#define ED_P0_CLDA1 sc->edreg.port[0x02] #undef ED_P0_PSTOP -#define ED_P0_PSTOP edp[unit][0x02] +#define ED_P0_PSTOP sc->edreg.port[0x02] #undef ED_P0_BNRY -#define ED_P0_BNRY edp[unit][0x03] +#define ED_P0_BNRY sc->edreg.port[0x03] #undef ED_P0_TSR -#define ED_P0_TSR edp[unit][0x04] +#define ED_P0_TSR sc->edreg.port[0x04] #undef ED_P0_TPSR -#define ED_P0_TPSR edp[unit][0x04] +#define ED_P0_TPSR sc->edreg.port[0x04] #undef ED_P0_NCR -#define ED_P0_NCR edp[unit][0x05] +#define ED_P0_NCR sc->edreg.port[0x05] #undef ED_P0_TBCR0 -#define ED_P0_TBCR0 edp[unit][0x05] +#define ED_P0_TBCR0 sc->edreg.port[0x05] #undef ED_P0_FIFO -#define ED_P0_FIFO edp[unit][0x06] +#define ED_P0_FIFO sc->edreg.port[0x06] #undef ED_P0_TBCR1 -#define ED_P0_TBCR1 edp[unit][0x06] +#define ED_P0_TBCR1 sc->edreg.port[0x06] #undef ED_P0_ISR -#define ED_P0_ISR edp[unit][0x07] +#define ED_P0_ISR sc->edreg.port[0x07] #undef ED_P0_CRDA0 -#define ED_P0_CRDA0 edp[unit][0x08] +#define ED_P0_CRDA0 sc->edreg.port[0x08] #undef ED_P0_RSAR0 -#define ED_P0_RSAR0 edp[unit][0x08] +#define ED_P0_RSAR0 sc->edreg.port[0x08] #undef ED_P0_CRDA1 -#define ED_P0_CRDA1 edp[unit][0x09] +#define ED_P0_CRDA1 sc->edreg.port[0x09] #undef ED_P0_RSAR1 -#define ED_P0_RSAR1 edp[unit][0x09] +#define ED_P0_RSAR1 sc->edreg.port[0x09] #undef ED_P0_RBCR0 -#define ED_P0_RBCR0 edp[unit][0x0a] +#define ED_P0_RBCR0 sc->edreg.port[0x0a] #undef ED_P0_RBCR1 -#define ED_P0_RBCR1 edp[unit][0x0b] +#define ED_P0_RBCR1 sc->edreg.port[0x0b] #undef ED_P0_RSR -#define ED_P0_RSR edp[unit][0x0c] +#define ED_P0_RSR sc->edreg.port[0x0c] #undef ED_P0_RCR -#define ED_P0_RCR edp[unit][0x0c] +#define ED_P0_RCR sc->edreg.port[0x0c] #undef ED_P0_CNTR0 -#define ED_P0_CNTR0 edp[unit][0x0d] +#define ED_P0_CNTR0 sc->edreg.port[0x0d] #undef ED_P0_TCR -#define ED_P0_TCR edp[unit][0x0d] +#define ED_P0_TCR sc->edreg.port[0x0d] #undef ED_P0_CNTR1 -#define ED_P0_CNTR1 edp[unit][0x0e] +#define ED_P0_CNTR1 sc->edreg.port[0x0e] #undef ED_P0_DCR -#define ED_P0_DCR edp[unit][0x0e] +#define ED_P0_DCR sc->edreg.port[0x0e] #undef ED_P0_CNTR2 -#define ED_P0_CNTR2 edp[unit][0x0f] +#define ED_P0_CNTR2 sc->edreg.port[0x0f] #undef ED_P0_IMR -#define ED_P0_IMR edp[unit][0x0f] +#define ED_P0_IMR sc->edreg.port[0x0f] /* * Page 1 register offsets */ #undef ED_P1_CR -#define ED_P1_CR edp[unit][0x00] +#define ED_P1_CR sc->edreg.port[0x00] #undef ED_P1_PAR0 -#define ED_P1_PAR0 edp[unit][0x01] +#define ED_P1_PAR0 sc->edreg.port[0x01] #undef ED_P1_PAR1 -#define ED_P1_PAR1 edp[unit][0x02] +#define ED_P1_PAR1 sc->edreg.port[0x02] #undef ED_P1_PAR2 -#define ED_P1_PAR2 edp[unit][0x03] +#define ED_P1_PAR2 sc->edreg.port[0x03] #undef ED_P1_PAR3 -#define ED_P1_PAR3 edp[unit][0x04] +#define ED_P1_PAR3 sc->edreg.port[0x04] #undef ED_P1_PAR4 -#define ED_P1_PAR4 edp[unit][0x05] +#define ED_P1_PAR4 sc->edreg.port[0x05] #undef ED_P1_PAR5 -#define ED_P1_PAR5 edp[unit][0x06] +#define ED_P1_PAR5 sc->edreg.port[0x06] #undef ED_P1_CURR -#define ED_P1_CURR edp[unit][0x07] +#define ED_P1_CURR sc->edreg.port[0x07] #undef ED_P1_MAR0 -#define ED_P1_MAR0 edp[unit][0x08] +#define ED_P1_MAR0 sc->edreg.port[0x08] #undef ED_P1_MAR1 -#define ED_P1_MAR1 edp[unit][0x09] +#define ED_P1_MAR1 sc->edreg.port[0x09] #undef ED_P1_MAR2 -#define ED_P1_MAR2 edp[unit][0x0a] +#define ED_P1_MAR2 sc->edreg.port[0x0a] #undef ED_P1_MAR3 -#define ED_P1_MAR3 edp[unit][0x0b] +#define ED_P1_MAR3 sc->edreg.port[0x0b] #undef ED_P1_MAR4 -#define ED_P1_MAR4 edp[unit][0x0c] +#define ED_P1_MAR4 sc->edreg.port[0x0c] #undef ED_P1_MAR5 -#define ED_P1_MAR5 edp[unit][0x0d] +#define ED_P1_MAR5 sc->edreg.port[0x0d] #undef ED_P1_MAR6 -#define ED_P1_MAR6 edp[unit][0x0e] +#define ED_P1_MAR6 sc->edreg.port[0x0e] #undef ED_P1_MAR7 -#define ED_P1_MAR7 edp[unit][0x0f] +#define ED_P1_MAR7 sc->edreg.port[0x0f] /* * Page 2 register offsets */ #undef ED_P2_CR -#define ED_P2_CR edp[unit][0x00] +#define ED_P2_CR sc->edreg.port[0x00] #undef ED_P2_PSTART -#define ED_P2_PSTART edp[unit][0x01] +#define ED_P2_PSTART sc->edreg.port[0x01] #undef ED_P2_CLDA0 -#define ED_P2_CLDA0 edp[unit][0x01] +#define ED_P2_CLDA0 sc->edreg.port[0x01] #undef ED_P2_PSTOP -#define ED_P2_PSTOP edp[unit][0x02] +#define ED_P2_PSTOP sc->edreg.port[0x02] #undef ED_P2_CLDA1 -#define ED_P2_CLDA1 edp[unit][0x02] +#define ED_P2_CLDA1 sc->edreg.port[0x02] #undef ED_P2_RNPP -#define ED_P2_RNPP edp[unit][0x03] +#define ED_P2_RNPP sc->edreg.port[0x03] #undef ED_P2_TPSR -#define ED_P2_TPSR edp[unit][0x04] +#define ED_P2_TPSR sc->edreg.port[0x04] #undef ED_P2_LNPP -#define ED_P2_LNPP edp[unit][0x05] +#define ED_P2_LNPP sc->edreg.port[0x05] #undef ED_P2_ACU -#define ED_P2_ACU edp[unit][0x06] +#define ED_P2_ACU sc->edreg.port[0x06] #undef ED_P2_ACL -#define ED_P2_ACL edp[unit][0x07] +#define ED_P2_ACL sc->edreg.port[0x07] #undef ED_P2_RCR -#define ED_P2_RCR edp[unit][0x0c] +#define ED_P2_RCR sc->edreg.port[0x0c] #undef ED_P2_TCR -#define ED_P2_TCR edp[unit][0x0d] +#define ED_P2_TCR sc->edreg.port[0x0d] #undef ED_P2_DCR -#define ED_P2_DCR edp[unit][0x0e] +#define ED_P2_DCR sc->edreg.port[0x0e] #undef ED_P2_IMR -#define ED_P2_IMR edp[unit][0x0f] +#define ED_P2_IMR sc->edreg.port[0x0f] /* PCCARD */ #ifdef ED_PC_MISC #undef ED_PC_MISC #endif -#define ED_PC_MISC ed_pc_misc[unit] +#define ED_PC_MISC sc->edreg.pc_misc #ifdef ED_PC_RESET #undef ED_PC_RESET #endif -#define ED_PC_RESET ed_pc_reset[unit] +#define ED_PC_RESET sc->edreg.pc_reset /* LPC-T support */ #define LPCT_1d0_ON() \ @@ -336,19 +335,6 @@ static void pc98_set_register __P((struct isa_device *dev, */ #define ED_CNET98EL_ISR 0x05 - - -/* register offsets */ -static unsigned int *edp[NED]; -static unsigned int pc98_io_skip[NED]; -static int ed_novell_nic_offset[NED]; -static int ed_novell_asic_offset[NED]; -static int ed_novell_data[NED]; -static int ed_novell_reset[NED]; -static int ed_pc_misc[NED]; -static int ed_pc_reset[NED]; - - /* NE2000, LGY-98, ICM, LPC-T, C-NET(98)E/L */ static unsigned int edp_generic[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 @@ -391,14 +377,15 @@ static unsigned int edp_cnet98[16] = { }; -static void pc98_set_register(struct isa_device *dev, int unit, int type) +static void pc98_set_register(struct isa_device *dev, int type) { + struct ed_softc *sc = &ed_softc[dev->id_unit]; int adj; switch (type) { case ED_TYPE98_GENERIC: - edp[unit] = edp_generic; - pc98_io_skip[unit] = 1; + sc->edreg.port = edp_generic; + sc->edreg.ioskip = 1; ED_NOVELL_NIC_OFFSET = 0x0000; ED_NOVELL_ASIC_OFFSET = 0x0010; ED_NOVELL_DATA = 0x0000; @@ -408,8 +395,8 @@ static void pc98_set_register(struct isa_device *dev, int unit, int type) break; case ED_TYPE98_LGY: - edp[unit] = edp_generic; - pc98_io_skip[unit] = 1; + sc->edreg.port = edp_generic; + sc->edreg.ioskip = 1; ED_NOVELL_NIC_OFFSET = 0x0000; ED_NOVELL_ASIC_OFFSET = 0x0200; ED_NOVELL_DATA = 0x0000; @@ -419,8 +406,8 @@ static void pc98_set_register(struct isa_device *dev, int unit, int type) break; case ED_TYPE98_EGY: - edp[unit] = edp_egy98; - pc98_io_skip[unit] = 2; + sc->edreg.port = edp_egy98; + sc->edreg.ioskip = 2; ED_NOVELL_NIC_OFFSET = 0; ED_NOVELL_ASIC_OFFSET = 0x0200; ED_NOVELL_DATA = 0x0000; @@ -430,8 +417,8 @@ static void pc98_set_register(struct isa_device *dev, int unit, int type) break; case ED_TYPE98_ICM: - edp[unit] = edp_generic; - pc98_io_skip[unit] = 1; + sc->edreg.port = edp_generic; + sc->edreg.ioskip = 1; ED_NOVELL_NIC_OFFSET = 0; ED_NOVELL_ASIC_OFFSET = 0x0100; ED_NOVELL_DATA = 0x0000; @@ -441,8 +428,8 @@ static void pc98_set_register(struct isa_device *dev, int unit, int type) break; case ED_TYPE98_BDN: - edp[unit] = edp_bdn98; - pc98_io_skip[unit] = 0x1000; + sc->edreg.port = edp_bdn98; + sc->edreg.ioskip = 0x1000; ED_NOVELL_NIC_OFFSET = 0x0000; ED_NOVELL_ASIC_OFFSET = 0x0100; ED_NOVELL_DATA = 0; @@ -452,8 +439,8 @@ static void pc98_set_register(struct isa_device *dev, int unit, int type) break; case ED_TYPE98_SIC: - edp[unit] = edp_sic98; - pc98_io_skip[unit] = 0x200; + sc->edreg.port = edp_sic98; + sc->edreg.ioskip = 0x200; ED_NOVELL_NIC_OFFSET = 0x0000; ED_NOVELL_ASIC_OFFSET = 0x2000; ED_NOVELL_DATA = 0x00; /* dummy */ @@ -463,8 +450,8 @@ static void pc98_set_register(struct isa_device *dev, int unit, int type) break; case ED_TYPE98_LPC: - edp[unit] = edp_generic; - pc98_io_skip[unit] = 0x1; + sc->edreg.port = edp_generic; + sc->edreg.ioskip = 0x1; ED_NOVELL_NIC_OFFSET = 0x0000; ED_NOVELL_ASIC_OFFSET = 0x0100; ED_NOVELL_DATA = 0x0000; @@ -474,8 +461,8 @@ static void pc98_set_register(struct isa_device *dev, int unit, int type) break; case ED_TYPE98_108: - edp[unit] = edp_nec108; - pc98_io_skip[unit] = 2; + sc->edreg.port = edp_nec108; + sc->edreg.ioskip = 2; adj = (dev->id_iobase & 0xf000) / 2; ED_NOVELL_NIC_OFFSET = 0; ED_NOVELL_ASIC_OFFSET = (0x888 | adj) - dev->id_iobase; @@ -486,8 +473,8 @@ static void pc98_set_register(struct isa_device *dev, int unit, int type) break; case ED_TYPE98_LA98: - edp[unit] = edp_la98; - pc98_io_skip[unit] = 0x1000; + sc->edreg.port = edp_la98; + sc->edreg.ioskip = 0x1000; ED_NOVELL_NIC_OFFSET = 0; ED_NOVELL_ASIC_OFFSET = 0x100; ED_NOVELL_DATA = 0x0000; @@ -497,8 +484,8 @@ static void pc98_set_register(struct isa_device *dev, int unit, int type) break; case ED_TYPE98_CNET98EL: - edp[unit] = edp_generic; - pc98_io_skip[unit] = 1; + sc->edreg.port = edp_generic; + sc->edreg.ioskip = 1; ED_NOVELL_NIC_OFFSET = 0; ED_NOVELL_ASIC_OFFSET = 0x0400; ED_NOVELL_DATA = 0x000e; @@ -507,8 +494,8 @@ static void pc98_set_register(struct isa_device *dev, int unit, int type) break; case ED_TYPE98_CNET98: - edp[unit] = edp_cnet98; - pc98_io_skip[unit] = 2; + sc->edreg.port = edp_cnet98; + sc->edreg.ioskip = 2; ED_NOVELL_NIC_OFFSET = 0; ED_NOVELL_ASIC_OFFSET = 0x0400; ED_NOVELL_DATA = 0x000e; diff --git a/sys/pc98/pc98/if_fe.c b/sys/pc98/pc98/if_fe.c index 856b1c5..bfc8229 100644 --- a/sys/pc98/pc98/if_fe.c +++ b/sys/pc98/pc98/if_fe.c @@ -21,7 +21,7 @@ */ /* - * $Id: if_fe.c,v 1.8 1996/09/12 11:09:48 asami Exp $ + * $Id: if_fe.c,v 1.9 1996/10/09 21:46:25 asami Exp $ * * Device driver for Fujitsu MB86960A/MB86965A based Ethernet cards. * To be used with FreeBSD 2.x @@ -242,8 +242,8 @@ static struct fe_softc { #define sc_enaddr arpcom.ac_enaddr /* Standard driver entry points. These can be static. */ -static int fe_probe ( DEVICE * ); -static int fe_attach ( DEVICE * ); +static int fe_probe ( struct isa_device * ); +static int fe_attach ( struct isa_device * ); static void fe_init ( int ); static int fe_ioctl ( struct ifnet *, int, caddr_t ); static void fe_start ( struct ifnet * ); diff --git a/sys/pc98/pc98/kbd.h b/sys/pc98/pc98/kbd.h index 8a963e4..a4fcc74 100644 --- a/sys/pc98/pc98/kbd.h +++ b/sys/pc98/pc98/kbd.h @@ -1,9 +1,15 @@ /* * Keyboard definitions + * from: unknown origin, 386BSD 0.1 + * $Id: kbd.h,v 1.4 1995/05/30 08:02:38 rgrimes Exp $ */ -#ifndef _PC98_PC98_KBD_H_ -#define _PC98_PC98_KBD_H_ 1 +#ifndef _I386_ISA_KBD_H_ +#define _I386_ISA_KBD_H_ 1 + +/* Reference: IBM AT Technical Reference Manual, + * pp. 1-38 to 1-43, 4-3 to 4-22 + */ /* commands and responses */ #define KBC_RESET 0xFF /* Reset the keyboard */ @@ -12,4 +18,4 @@ #define KBR_RESEND 0xFE /* Keyboard needs resend of command */ #define KBR_ACK 0xFA /* Keyboard did receive command */ #define KBR_RSTDONE 0xAA /* Keyboard reset complete */ -#endif /* _PC98_PC98_KBD_H_ */ +#endif /* _I386_ISA_KBD_H_ */ diff --git a/sys/pc98/pc98/kbdtables.h b/sys/pc98/pc98/kbdtables.h deleted file mode 100644 index 4a822a9..0000000 --- a/sys/pc98/pc98/kbdtables.h +++ /dev/null @@ -1,1039 +0,0 @@ -/*- - * Copyright (c) 1992-1994 Sen Schmidt - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software withough specific prior written permission - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $Id: kbdtables.h,v 1.1.1.1 1996/06/14 10:04:44 asami Exp $ - */ - -#define SET8 0x80 /* set eight bit on */ - -/* - * modified for PC98 by kuribo@isl.melco.co.jp - */ - -#ifdef PC98 /* PC98 keyboard truetype by kuribo */ -static keymap_t key_map = { 0x80, /* PC98 keymap */ -/* alt - * scan cntrl alt alt cntrl - * code base shift cntrl shift alt shift cntrl shift spcl flgs - * --------------------------------------------------------------------------- - */ -/* sc=00 */ 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, DBG, 0x1B, 0x02, 0x00, -/* sc=01 */ '1', '!', '!', '!', '1', '!', '!', '!', 0x00, 0x00, -/* sc=02 */ '2', '\"', 0x1A, 0x1A, '2', '@', 0x00, 0x00, 0x00, 0x00, -/* sc=03 */ '3', '#', 0x1B, 0x1B, '3', '#', 0x1B, 0x1B, 0x00, 0x00, -/* sc=04 */ '4', '$', 0x1C, 0x1C, '4', '$', 0x1C, 0x1C, 0x00, 0x00, -/* sc=05 */ '5', '%', 0x1D, 0x1D, '5', '%', 0x1D, 0x1D, 0x00, 0x00, -/* sc=06 */ '6', '&', 0x1E, 0x1E, '6', '^', 0x1E, 0x1E, 0x00, 0x00, -/* sc=07 */ '7', '\'', 0x1F, 0x1F, '7', '&', '&', '&', 0x00, 0x00, -/* sc=08 */ '8', '(', 0x7F, 0x7F, '8', '*', 0x08, 0x08, 0x00, 0x00, -/* sc=09 */ '9', ')', '9', '9', '9', '(', '(', '(', 0x00, 0x00, -/* sc=0a */ '0', NOP, '0', '0', '0', ')', ')', ')', 0x40, 0x00, -/* sc=0b */ '-', '=', '-', '-', '-', '_', 0x1F, 0x1F, 0x00, 0x00, -/* sc=0c */ '^', '`', 0x1E, 0x1E, '=', '+', '+', '+', 0x00, 0x00, -/* sc=0d */ '\\', '|', 0x1C, 0x1C, '\\', '|', 0x1C, 0x1C, 0x00, 0x00, -/* sc=0e */ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, -/* sc=0f */ '\t', '\t', '\t', '\t', '\t', '\t', '\t', '\t', 0x00, 0x00, -/* sc=10 */ 'q', 'Q', 0x11, 0x11, 'q', 'Q', 0x11, 0x11, 0x00, 0x01, -/* sc=11 */ 'w', 'W', 0x17, 0x17, 'w', 'W', 0x17, 0x17, 0x00, 0x01, -/* sc=12 */ 'e', 'E', 0x05, 0x05, 'e', 'E', 0x05, 0x05, 0x00, 0x01, -/* sc=13 */ 'r', 'R', 0x12, 0x12, 'r', 'R', 0x12, 0x12, 0x00, 0x01, -/* sc=14 */ 't', 'T', 0x14, 0x14, 't', 'T', 0x14, 0x14, 0x00, 0x01, -/* sc=15 */ 'y', 'Y', 0x19, 0x19, 'y', 'Y', 0x19, 0x19, 0x00, 0x01, -/* sc=16 */ 'u', 'U', 0x15, 0x15, 'u', 'U', 0x15, 0x15, 0x00, 0x01, -/* sc=17 */ 'i', 'I', 0x09, 0x09, 'i', 'I', 0x09, 0x09, 0x00, 0x01, -/* sc=18 */ 'o', 'O', 0x0F, 0x0F, 'o', 'O', 0x0F, 0x0F, 0x00, 0x01, -/* sc=19 */ 'p', 'P', 0x10, 0x10, 'p', 'P', 0x10, 0x10, 0x00, 0x01, -/* sc=1a */ '@', '~', 0x00, 0x00, '[', '{', 0x1B, 0x1B, 0x00, 0x00, -/* sc=1b */ '[', '{', 0x1B, 0x1B, ']', '}', 0x1D, 0x1D, 0x00, 0x00, -/* sc=1c */ '\r', '\r', '\n', '\n', '\r', '\r', '\n', '\n', 0x00, 0x00, -/* sc=1d */ 'a', 'A', 0x01, 0x01, 'a', 'A', 0x01, 0x01, 0x00, 0x01, -/* sc=1e */ 's', 'S', 0x13, 0x13, 's', 'S', 0x13, 0x13, 0x00, 0x01, -/* sc=1f */ 'd', 'D', 0x04, 0x04, 'd', 'D', 0x04, 0x04, 0x00, 0x01, -/* sc=20 */ 'f', 'F', 0x06, 0x06, 'f', 'F', 0x06, 0x06, 0x00, 0x01, -/* sc=21 */ 'g', 'G', 0x07, 0x07, 'g', 'G', 0x07, 0x07, 0x00, 0x01, -/* sc=22 */ 'h', 'H', 0x08, 0x08, 'h', 'H', 0x08, 0x08, 0x00, 0x01, -/* sc=23 */ 'j', 'J', '\n', '\n', 'j', 'J', '\n', '\n', 0x00, 0x01, -/* sc=24 */ 'k', 'K', 0x0B, 0x0B, 'k', 'K', 0x0B, 0x0B, 0x00, 0x01, -/* sc=25 */ 'l', 'L', 0x0C, 0x0C, 'l', 'L', 0x0C, 0x0C, 0x00, 0x01, -/* sc=26 */ ';', '+', ';', ';', ';', ':', ';', ';', 0x00, 0x00, -/* sc=27 */ ':', '*', ':', ':', '\'', '\"', '\'', '\'', 0x00, 0x00, -/* sc=28 */ ']', '}', 0x1D, 0x1D, '`', '~', '~', '~', 0x00, 0x00, -/* sc=29 */ 'z', 'Z', 0x1A, 0x1A, 'z', 'Z', 0x1A, 0x1A, 0x00, 0x01, -/* sc=2a */ 'x', 'X', 0x18, 0x18, 'x', 'X', 0x18, 0x18, 0x00, 0x01, -/* sc=2b */ 'c', 'C', 0x03, 0x03, 'c', 'C', 0x03, 0x03, 0x00, 0x01, -/* sc=2c */ 'v', 'V', 0x16, 0x16, 'v', 'V', 0x16, 0x16, 0x00, 0x01, -/* sc=2d */ 'b', 'B', 0x02, 0x02, 'b', 'B', 0x02, 0x02, 0x00, 0x01, -/* sc=2e */ 'n', 'N', 0x0E, 0x0E, 'n', 'N', 0x0E, 0x0E, 0x00, 0x01, -/* sc=2f */ 'm', 'M', '\r', '\r', 'm', 'M', '\r', '\r', 0x00, 0x01, -/* sc=30 */ ',', '<', '<', '<', ',', '<', '<', '<', 0x00, 0x00, -/* sc=31 */ '.', '>', '>', '>', '.', '>', '>', '>', 0x00, 0x00, -/* sc=32 */ '/', '?', 0x7F, 0x7F, '/', '?', 0x7F, 0x7F, 0x00, 0x00, -/* sc=33 */ NOP, '_', 0x1F, 0x1F, '\\', '|', 0x1C, 0x1C, 0x80, 0x00, -/* sc=34 */ ' ', ' ', 0x00, 0x00, ' ', ' ', 0x00, 0x00, 0x00, 0x00, -/* sc=35 */ 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x00, 0x00, -/* sc=36 */ F(51), F(51), F(51), F(51), F(51), F(51), F(51), F(51), 0xFF, 0x00, -/* sc=37 */ F(59), F(59), F(59), F(59), F(59), F(59), F(59), F(59), 0xFF, 0x00, -/* sc=38 */ F(60), F(60), F(60), F(60), F(60), F(60), F(60), F(60), 0xFF, 0x00, -/* sc=39 */ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, RBT, RBT, 0x00, 0x00, -/* sc=3a */ F(50), F(50), F(50), F(50), F(50), F(50), F(50), F(50), 0xFF, 0x00, -/* sc=3b */ F(53), F(53), F(53), F(53), F(53), F(53), F(53), F(53), 0xFF, 0x00, -/* sc=3c */ F(55), F(55), F(55), F(55), F(55), F(55), F(55), F(55), 0xFF, 0x00, -/* sc=3d */ F(58), F(58), F(58), F(58), F(58), F(58), F(58), F(58), 0xFF, 0x00, -/* sc=3e */ F(49), F(49), F(49), F(49), F(49), F(49), F(49), F(49), 0xFF, 0x00, -/* sc=3f */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=40 */ '-', '-', '-', '-', '-', '-', '-', '-', 0x00, 0x00, -/* sc=41 */ '/', '/', '/', '/', '/', '/', '/', '/', 0x00, 0x00, -/* sc=42 */ '7', '7', '7', '7', '7', '7', '7', '7', 0x00, 0x00, -/* sc=43 */ '8', '8', '8', '8', '8', '8', '8', '8', 0x00, 0x00, -/* sc=44 */ '9', '9', '9', '9', '9', '9', '9', '9', 0x00, 0x00, -/* sc=45 */ '*', '*', '*', '*', '*', '*', '*', '*', 0x00, 0x00, -/* sc=46 */ '4', '4', '4', '4', '4', '4', '4', '4', 0x00, 0x00, -/* sc=47 */ '5', '5', '5', '5', '5', '5', '5', '5', 0x00, 0x00, -/* sc=48 */ '6', '6', '6', '6', '6', '6', '6', '6', 0x00, 0x00, -/* sc=49 */ '+', '+', '+', '+', '+', '+', '+', '+', 0x00, 0x00, -/* sc=4a */ '1', '1', '1', '1', '1', '1', '1', '1', 0x00, 0x00, -/* sc=4b */ '2', '2', '2', '2', '2', '2', '2', '2', 0x00, 0x00, -/* sc=4c */ '3', '3', '3', '3', '3', '3', '3', '3', 0x00, 0x00, -/* sc=4d */ '=', '=', '=', '=', '=', '=', '=', '=', 0x00, 0x00, -/* sc=4e */ '0', '0', '0', '0', '0', '0', '0', '0', 0x00, 0x00, -/* sc=4f */ ',', ',', ',', ',', ',', ',', ',', ',', 0x00, 0x00, -/* sc=50 */ '.', '.', '.', '.', '.', '.', '.', '.', 0x00, 0x00, -/* sc=51 */ 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x00, 0x00, -/* sc=52 */ F(11), F(23), F(35), F(47), S(11), S(11), S(11), S(11), 0xFF, 0x00, -/* sc=53 */ F(12), F(24), F(36), F(48), S(12), S(12), S(12), S(12), 0xFF, 0x00, -/* sc=54 */ SLK, SLK, SLK, SLK, SLK, SLK, SLK, SLK, 0xFF, 0x00, -/* sc=55 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=56 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=57 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=58 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=59 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=5a */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=5b */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=5c */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=5d */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=5e */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=5f */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=60 */ F(57), F(57), F(57), F(57), F(57), F(57), F(57), F(57), 0xFF, 0x00, -/* sc=61 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=62 */ F( 1), F(13), F(25), F(37), S( 1), S( 1), S( 1), S( 1), 0xFF, 0x00, -/* sc=63 */ F( 2), F(14), F(26), F(38), S( 2), S( 2), S( 2), S( 2), 0xFF, 0x00, -/* sc=64 */ F( 3), F(15), F(27), F(39), S( 3), S( 3), S( 3), S( 3), 0xFF, 0x00, -/* sc=65 */ F( 4), F(16), F(28), F(40), S( 4), S( 4), S( 4), S( 4), 0xFF, 0x00, -/* sc=66 */ F( 5), F(17), F(29), F(41), S( 5), S( 5), S( 5), S( 5), 0xFF, 0x00, -/* sc=67 */ F( 6), F(18), F(30), F(42), S( 6), S( 6), S( 6), S( 6), 0xFF, 0x00, -/* sc=68 */ F( 7), F(19), F(31), F(43), S( 7), S( 7), S( 7), S( 7), 0xFF, 0x00, -/* sc=69 */ F( 8), F(20), F(32), F(44), S( 8), S( 8), S( 8), S( 8), 0xFF, 0x00, -/* sc=6a */ F( 9), F(21), F(33), F(45), S( 9), S( 9), S( 9), S( 9), 0xFF, 0x00, -/* sc=6b */ F(10), F(22), F(34), F(46), S(10), S(10), S(10), S(10), 0xFF, 0x00, -/* sc=6c */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=6d */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=6e */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=6f */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=70 */ LSH, LSH, LSH, LSH, LSH, LSH, LSH, LSH, 0xFF, 0x00, -/* sc=71 */ CLK, CLK, CLK, CLK, CLK, CLK, CLK, CLK, 0xFF, 0x00, -/* sc=72 */ LALT, LALT, LALT, LALT, LALT, LALT, LALT, LALT, 0xFF, 0x00, -/* sc=73 */ LALT, LALT, LALT, LALT, LALT, LALT, LALT, LALT, 0xFF, 0x00, -/* sc=74 */ LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, 0xFF, 0x00, -/* sc=75 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=76 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=77 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=78 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=79 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=7a */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=7b */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=7c */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=7d */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=7e */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=7f */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -}; -#endif - -#ifdef DKKEYMAP -static keymap_t key_map = { 0x6C, /* DK iso8859 keymap */ -/* alt - * scan cntrl alt alt cntrl - * code base shift cntrl shift alt shift cntrl shift spcl flgs - * --------------------------------------------------------------------------- - */ -/* sc=00 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=01 */ 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, DBG, 0x1B, 0x02, 0x00, -/* sc=02 */ '1', '!', NOP, NOP, '1', '!', NOP, NOP, 0x33, 0x00, -/* sc=03 */ '2', '"', 0x00, 0x00, '@', '@', 0x00, 0x00, 0x00, 0x00, -/* sc=04 */ '3', '#', NOP, NOP, 0x9E, '#', NOP, NOP, 0x33, 0x00, -/* sc=05 */ '4', 0xA4, NOP, NOP, '$', 0xA4, NOP, NOP, 0x33, 0x00, -/* sc=06 */ '5', '%', NOP, NOP, '5', '%', NOP, NOP, 0x33, 0x00, -/* sc=07 */ '6', '&', NOP, NOP, '6', '&', NOP, NOP, 0x33, 0x00, -/* sc=08 */ '7', '/', NOP, NOP, '{', '/', NOP, NOP, 0x33, 0x00, -/* sc=09 */ '8', '(', 0x1B, 0x1B, '[', '(', 0x1B, 0x1B, 0x00, 0x00, -/* sc=0a */ '9', ')', 0x1D, 0x1D, ']', ')', 0x1D, 0x1D, 0x00, 0x00, -/* sc=0b */ '0', '=', NOP, NOP, '}', '=', NOP, NOP, 0x33, 0x00, -/* sc=0c */ '+', '?', NOP, NOP, '+', '?', NOP, NOP, 0x33, 0x00, -/* sc=0d */ '\'', '`', NOP, NOP, '|', '`', NOP, NOP, 0x33, 0x00, -/* sc=0e */ 0x08, 0x08, 0x7F, 0x7F, 0x08, 0x08, 0x7F, 0x7F, 0x00, 0x00, -/* sc=0f */ 0x09, BTAB, NOP, NOP, 0x09, BTAB, NOP, NOP, 0x77, 0x00, -/* sc=10 */ 'q', 'Q', 0x11, 0x11, 'q', 'Q', 0x11, 0x11, 0x00, 0x01, -/* sc=11 */ 'w', 'W', 0x17, 0x17, 'w', 'W', 0x17, 0x17, 0x00, 0x01, -/* sc=12 */ 'e', 'E', 0x05, 0x05, 'e', 'E', 0x05, 0x05, 0x00, 0x01, -/* sc=13 */ 'r', 'R', 0x12, 0x12, 'r', 'R', 0x12, 0x12, 0x00, 0x01, -/* sc=14 */ 't', 'T', 0x14, 0x14, 't', 'T', 0x14, 0x14, 0x00, 0x01, -/* sc=15 */ 'y', 'Y', 0x19, 0x19, 'y', 'Y', 0x19, 0x19, 0x00, 0x01, -/* sc=16 */ 'u', 'U', 0x15, 0x15, 'u', 'U', 0x15, 0x15, 0x00, 0x01, -/* sc=17 */ 'i', 'I', 0x09, 0x09, 'i', 'I', 0x09, 0x09, 0x00, 0x01, -/* sc=18 */ 'o', 'O', 0x0F, 0x0F, 'o', 'O', 0x0F, 0x0F, 0x00, 0x01, -/* sc=19 */ 'p', 'P', 0x10, 0x10, 'p', 'P', 0x10, 0x10, 0x00, 0x01, -/* sc=1a */ 0xE5, 0xC5, NOP, NOP, 0x86, 0x8F, NOP, NOP, 0x33, 0x01, -/* sc=1b */ '"', '^', 0x1E, 0x1E, '~', '^', 0x1E, 0x1E, 0x00, 0x00, -/* sc=1c */ 0x0D, 0x0D, 0x0A, 0x0A, 0x0D, 0x0D, 0x0A, 0x0A, 0x00, 0x00, -/* sc=1d */ LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, 0xFF, 0x00, -/* sc=1e */ 'a', 'A', 0x01, 0x01, 'a', 'A', 0x01, 0x01, 0x00, 0x01, -/* sc=1f */ 's', 'S', 0x13, 0x13, 's', 'S', 0x13, 0x13, 0x00, 0x01, -/* sc=20 */ 'd', 'D', 0x04, 0x04, 'd', 'D', 0x04, 0x04, 0x00, 0x01, -/* sc=21 */ 'f', 'F', 0x06, 0x06, 'f', 'F', 0x06, 0x06, 0x00, 0x01, -/* sc=22 */ 'g', 'G', 0x07, 0x07, 'g', 'G', 0x07, 0x07, 0x00, 0x01, -/* sc=23 */ 'h', 'H', 0x08, 0x08, 'h', 'H', 0x08, 0x08, 0x00, 0x01, -/* sc=24 */ 'j', 'J', 0x0A, 0x0A, 'j', 'J', 0x0A, 0x0A, 0x00, 0x01, -/* sc=25 */ 'k', 'K', 0x0B, 0x0B, 'k', 'K', 0x0B, 0x0B, 0x00, 0x01, -/* sc=26 */ 'l', 'L', 0x0C, 0x0C, 'l', 'L', 0x0C, 0x0C, 0x00, 0x01, -/* sc=27 */ 0xE6, 0xC6, NOP, NOP, 0x91, 0x92, NOP, NOP, 0x33, 0x01, -/* sc=28 */ 0xF8, 0xD8, NOP, NOP, 0x9B, 0x9D, NOP, NOP, 0x33, 0x01, -/* sc=29 */ 0xBD, 0xA7, NOP, NOP, 0xBD, 0xA7, NOP, NOP, 0x33, 0x00, -/* sc=2a */ LSH, LSH, LSH, LSH, LSH, LSH, LSH, LSH, 0xFF, 0x00, -/* sc=2b */ '\'', '*', NOP, NOP, '\'', '*', NOP, NOP, 0x33, 0x00, -/* sc=2c */ 'z', 'Z', 0x1A, 0x1A, 'z', 'Z', 0x1A, 0x1A, 0x00, 0x01, -/* sc=2d */ 'x', 'X', 0x18, 0x18, 'x', 'X', 0x18, 0x18, 0x00, 0x01, -/* sc=2e */ 'c', 'C', 0x03, 0x03, 'c', 'C', 0x03, 0x03, 0x00, 0x01, -/* sc=2f */ 'v', 'V', 0x16, 0x16, 'v', 'V', 0x16, 0x16, 0x00, 0x01, -/* sc=30 */ 'b', 'B', 0x02, 0x02, 'b', 'B', 0x02, 0x02, 0x00, 0x01, -/* sc=31 */ 'n', 'N', 0x0E, 0x0E, 'n', 'N', 0x0E, 0x0E, 0x00, 0x01, -/* sc=32 */ 'm', 'M', 0x0D, 0x0D, 'm', 'M', 0x0D, 0x0D, 0x00, 0x01, -/* sc=33 */ ',', ';', NOP, NOP, ',', ';', NOP, NOP, 0x33, 0x00, -/* sc=34 */ '.', ':', NOP, NOP, '.', ':', NOP, NOP, 0x33, 0x00, -/* sc=35 */ '-', '_', 0x1F, 0x1F, '-', '_', 0x1F, 0x1F, 0x00, 0x00, -/* sc=36 */ RSH, RSH, RSH, RSH, RSH, RSH, RSH, RSH, 0xFF, 0x00, -/* sc=37 */ '*', '*', '*', '*', '*', '*', '*', '*', 0x00, 0x00, -/* sc=38 */ LALT, LALT, LALT, LALT, LALT, LALT, LALT, LALT, 0xFF, 0x00, -/* sc=39 */ ' ', ' ', 0x00, ' ', ' ', ' ', SUSP, ' ', 0x02, 0x00, -/* sc=3a */ CLK, CLK, CLK, CLK, CLK, CLK, CLK, CLK, 0xFF, 0x00, -/* sc=3b */ F( 1), F(13), F(25), F(37), S( 1), S(11), S( 1), S(11), 0xFF, 0x00, -/* sc=3c */ F( 2), F(14), F(26), F(38), S( 2), S(12), S( 2), S(12), 0xFF, 0x00, -/* sc=3d */ F( 3), F(15), F(27), F(39), S( 3), S(13), S( 3), S(13), 0xFF, 0x00, -/* sc=3e */ F( 4), F(16), F(28), F(40), S( 4), S(14), S( 4), S(14), 0xFF, 0x00, -/* sc=3f */ F( 5), F(17), F(29), F(41), S( 5), S(15), S( 5), S(15), 0xFF, 0x00, -/* sc=40 */ F( 6), F(18), F(30), F(42), S( 6), S(16), S( 6), S(16), 0xFF, 0x00, -/* sc=41 */ F( 7), F(19), F(31), F(43), S( 7), S( 7), S( 7), S( 7), 0xFF, 0x00, -/* sc=42 */ F( 8), F(20), F(32), F(44), S( 8), S( 8), S( 8), S( 8), 0xFF, 0x00, -/* sc=43 */ F( 9), F(21), F(33), F(45), S( 9), S( 9), S( 9), S( 9), 0xFF, 0x00, -/* sc=44 */ F(10), F(22), F(34), F(46), S(10), S(10), S(10), S(10), 0xFF, 0x00, -/* sc=45 */ NLK, NLK, NLK, NLK, NLK, NLK, NLK, NLK, 0xFF, 0x00, -/* sc=46 */ SLK, SLK, SLK, SLK, SLK, SLK, SLK, SLK, 0xFF, 0x00, -/* sc=47 */ F(49), '7', '7', '7', '7', '7', '7', '7', 0x80, 0x02, -/* sc=48 */ F(50), '8', '8', '8', '8', '8', '8', '8', 0x80, 0x02, -/* sc=49 */ F(51), '9', '9', '9', '9', '9', '9', '9', 0x80, 0x02, -/* sc=4a */ F(52), '-', '-', '-', '-', '-', '-', '-', 0x80, 0x02, -/* sc=4b */ F(53), '4', '4', '4', '4', '4', '4', '4', 0x80, 0x02, -/* sc=4c */ F(54), '5', '5', '5', '5', '5', '5', '5', 0x80, 0x02, -/* sc=4d */ F(55), '6', '6', '6', '6', '6', '6', '6', 0x80, 0x02, -/* sc=4e */ F(56), '+', '+', '+', '+', '+', '+', '+', 0x80, 0x02, -/* sc=4f */ F(57), '1', '1', '1', '1', '1', '1', '1', 0x80, 0x02, -/* sc=50 */ F(58), '2', '2', '2', '2', '2', '2', '2', 0x80, 0x02, -/* sc=51 */ F(59), '3', '3', '3', '3', '3', '3', '3', 0x80, 0x02, -/* sc=52 */ F(60), '0', '0', '0', '0', '0', '0', '0', 0x80, 0x02, -/* sc=53 */ 0x7F, '.', '.', '.', '.', '.', RBT, RBT, 0x03, 0x02, -/* sc=54 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=55 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=56 */ '<', '>', 0x1C, 0x1C, '\\', '>', 0x1C, 0x1C, 0x00, 0x00, -/* sc=57 */ F(11), F(23), F(35), F(47), S(11), S(11), S(11), S(11), 0xFF, 0x00, -/* sc=58 */ F(12), F(24), F(36), F(48), S(12), S(12), S(12), S(12), 0xFF, 0x00, -/* sc=59 */ 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x00, 0x02, -/* sc=5a */ RCTR, RCTR, RCTR, RCTR, RCTR, RCTR, RCTR, RCTR, 0xFF, 0x00, -/* sc=5b */ '/', '/', '/', '/', '/', '/', '/', '/', 0x00, 0x00, -/* sc=5c */ NEXT, NOP, DBG, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=5d */ RALT, RALT, RALT, RALT, RALT, RALT, RALT, RALT, 0xFF, 0x00, -/* sc=5e */ F(49), F(49), F(49), F(49), F(49), F(49), F(49), F(49), 0xFF, 0x00, -/* sc=5f */ F(50), F(50), F(50), F(50), F(50), F(50), F(50), F(50), 0xFF, 0x00, -/* sc=60 */ F(51), F(51), F(51), F(51), F(51), F(51), F(51), F(51), 0xFF, 0x00, -/* sc=61 */ F(53), F(53), F(53), F(53), F(53), F(53), F(53), F(53), 0xFF, 0x00, -/* sc=62 */ F(55), F(55), F(55), F(55), F(55), F(55), F(55), F(55), 0xFF, 0x00, -/* sc=63 */ F(57), F(57), F(57), F(57), F(57), F(57), F(57), F(57), 0xFF, 0x00, -/* sc=64 */ F(58), F(58), F(58), F(58), F(58), F(58), F(58), F(58), 0xFF, 0x00, -/* sc=65 */ F(59), F(59), F(59), F(59), F(59), F(59), F(59), F(59), 0xFF, 0x00, -/* sc=66 */ F(60), F(60), F(60), F(60), F(60), F(60), F(60), F(60), 0xFF, 0x00, -/* sc=67 */ F(61), F(61), F(61), F(61), F(61), F(61), RBT, F(61), 0xFF, 0x00, -/* sc=68 */ SLK, SLK, SLK, SLK, SLK, SLK, SLK, SLK, 0xFF, 0x00, -/* sc=69 */ F(62), F(62), F(62), F(62), F(62), F(62), F(62), F(62), 0xFF, 0x00, -/* sc=6a */ F(63), F(63), F(63), F(63), F(63), F(63), F(63), F(63), 0xFF, 0x00, -/* sc=6b */ F(64), F(64), F(64), F(64), F(64), F(64), F(64), F(64), 0xFF, 0x00, -}; -#endif - -#ifdef UKKEYMAP -static keymap_t key_map = { 0x6C, /* uk iso8859 keymap */ -/* alt - * scan cntrl alt alt cntrl - * code base shift cntrl shift alt shift cntrl shift spcl flgs - * --------------------------------------------------------------------------- - */ -/* sc=00 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=01 */ 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, DBG, 0x1B, 0x02, 0x00, -/* sc=02 */ '1', '!', NOP, NOP, '`', '`', NOP, NOP, 0x33, 0x00, -/* sc=03 */ '2', '"', 0x00, 0x00, '@', '@', 0x00, 0x00, 0x00, 0x00, -/* sc=04 */ '3', 0xA3, NOP, NOP, '#', '#', NOP, NOP, 0x33, 0x00, -/* sc=05 */ '4', '$', NOP, NOP, '4', '$', NOP, NOP, 0x33, 0x00, -/* sc=06 */ '5', '%', NOP, NOP, '5', '%', NOP, NOP, 0x33, 0x00, -/* sc=07 */ '6', '^', 0x1E, 0x1E, '^', '^', 0x1E, 0x1E, 0x00, 0x00, -/* sc=08 */ '7', '&', NOP, NOP, '[', '[', 0x1B, 0x1B, 0x30, 0x00, -/* sc=09 */ '8', '*', NOP, NOP, '8', '*', NOP, NOP, 0x33, 0x00, -/* sc=0a */ '9', '(', NOP, NOP, ']', ']', 0x1D, 0x1D, 0x30, 0x00, -/* sc=0b */ '0', ')', NOP, NOP, '{', '{', NOP, NOP, 0x33, 0x00, -/* sc=0c */ '-', '_', 0x1F, 0x1F, '|', '|', 0x1F, 0x1F, 0x00, 0x00, -/* sc=0d */ '=', '+', NOP, NOP, '}', '}', NOP, NOP, 0x33, 0x00, -/* sc=0e */ 0x08, 0x08, 0x7F, 0x7F, 0x08, 0x08, 0x7F, 0x7F, 0x00, 0x00, -/* sc=0f */ 0x09, BTAB, NOP, NOP, 0x09, BTAB, NOP, NOP, 0x77, 0x00, -/* sc=10 */ 'q', 'Q', 0x11, 0x11, 'q', 'Q', 0x11, 0x11, 0x00, 0x01, -/* sc=11 */ 'w', 'W', 0x17, 0x17, 'w', 'W', 0x17, 0x17, 0x00, 0x01, -/* sc=12 */ 'e', 'E', 0x05, 0x05, 'e', 'E', 0x05, 0x05, 0x00, 0x01, -/* sc=13 */ 'r', 'R', 0x12, 0x12, 'r', 'R', 0x12, 0x12, 0x00, 0x01, -/* sc=14 */ 't', 'T', 0x14, 0x14, 't', 'T', 0x14, 0x14, 0x00, 0x01, -/* sc=15 */ 'y', 'Y', 0x19, 0x19, 'y', 'Y', 0x19, 0x19, 0x00, 0x01, -/* sc=16 */ 'u', 'U', 0x15, 0x15, 'u', 'U', 0x15, 0x15, 0x00, 0x01, -/* sc=17 */ 'i', 'I', 0x09, 0x09, 'i', 'I', 0x09, 0x09, 0x00, 0x01, -/* sc=18 */ 'o', 'O', 0x0F, 0x0F, 'o', 'O', 0x0F, 0x0F, 0x00, 0x01, -/* sc=19 */ 'p', 'P', 0x10, 0x10, 'p', 'P', 0x10, 0x10, 0x00, 0x01, -/* sc=1a */ '[', '{', 0x1B, 0x1B, '[', '{', 0x1B, 0x1B, 0x00, 0x00, -/* sc=1b */ ']', '}', 0x1D, 0x1D, ']', '}', 0x1D, 0x1D, 0x00, 0x00, -/* sc=1c */ 0x0D, 0x0D, 0x0A, 0x0A, 0x0D, 0x0D, 0x0A, 0x0A, 0x00, 0x00, -/* sc=1d */ LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, 0xFF, 0x00, -/* sc=1e */ 'a', 'A', 0x01, 0x01, 'a', 'A', 0x01, 0x01, 0x00, 0x01, -/* sc=1f */ 's', 'S', 0x13, 0x13, 's', 'S', 0x13, 0x13, 0x00, 0x01, -/* sc=20 */ 'd', 'D', 0x04, 0x04, 'd', 'D', 0x04, 0x04, 0x00, 0x01, -/* sc=21 */ 'f', 'F', 0x06, 0x06, 'f', 'F', 0x06, 0x06, 0x00, 0x01, -/* sc=22 */ 'g', 'G', 0x07, 0x07, 'g', 'G', 0x07, 0x07, 0x00, 0x01, -/* sc=23 */ 'h', 'H', 0x08, 0x08, 'h', 'H', 0x08, 0x08, 0x00, 0x01, -/* sc=24 */ 'j', 'J', 0x0A, 0x0A, 'j', 'J', 0x0A, 0x0A, 0x00, 0x01, -/* sc=25 */ 'k', 'K', 0x0B, 0x0B, 'k', 'K', 0x0B, 0x0B, 0x00, 0x01, -/* sc=26 */ 'l', 'L', 0x0C, 0x0C, 'l', 'L', 0x0C, 0x0C, 0x00, 0x01, -/* sc=27 */ ';', ':', NOP, NOP, ';', ':', NOP, NOP, 0x33, 0x00, -/* sc=28 */ '\'', '@', 0x00, 0x00, '\'', '@', 0x00, 0x00, 0x00, 0x00, -/* sc=29 */ '\\', '|', 0x1C, 0x1C, '\\', '\\', 0x1C, 0x1C, 0x00, 0x00, -/* sc=2a */ LSH, LSH, LSH, LSH, LSH, LSH, LSH, LSH, 0xFF, 0x00, -/* sc=2b */ '#', '~', NOP, NOP, '~', '~', NOP, NOP, 0x33, 0x00, -/* sc=2c */ 'z', 'Z', 0x1A, 0x1A, 'z', 'Z', 0x1A, 0x1A, 0x00, 0x01, -/* sc=2d */ 'x', 'X', 0x18, 0x18, 'x', 'X', 0x18, 0x18, 0x00, 0x01, -/* sc=2e */ 'c', 'C', 0x03, 0x03, 'c', 'C', 0x03, 0x03, 0x00, 0x01, -/* sc=2f */ 'v', 'V', 0x16, 0x16, 'v', 'V', 0x16, 0x16, 0x00, 0x01, -/* sc=30 */ 'b', 'B', 0x02, 0x02, 'b', 'B', 0x02, 0x02, 0x00, 0x01, -/* sc=31 */ 'n', 'N', 0x0E, 0x0E, 'n', 'N', 0x0E, 0x0E, 0x00, 0x01, -/* sc=32 */ 'm', 'M', 0x0D, 0x0D, 'm', 'M', 0x0D, 0x0D, 0x00, 0x01, -/* sc=33 */ ',', '<', NOP, NOP, ',', '<', NOP, NOP, 0x33, 0x00, -/* sc=34 */ '.', '>', NOP, NOP, '.', '>', NOP, NOP, 0x33, 0x00, -/* sc=35 */ '/', '?', NOP, NOP, '/', '?', NOP, NOP, 0x33, 0x00, -/* sc=36 */ RSH, RSH, RSH, RSH, RSH, RSH, RSH, RSH, 0xFF, 0x00, -/* sc=37 */ '*', '*', 0x0A, 0x0A, '*', '*', 0x0A, 0x0A, 0x33, 0x00, -/* sc=38 */ LALT, LALT, LALT, LALT, LALT, LALT, LALT, LALT, 0xFF, 0x00, -/* sc=39 */ ' ', ' ', 0x00, ' ', ' ', ' ', SUSP, ' ', 0x02, 0x00, -/* sc=3a */ CLK, CLK, CLK, CLK, CLK, CLK, CLK, CLK, 0xFF, 0x00, -/* sc=3b */ F( 1), F(13), F(25), F(37), S( 1), S(11), S( 1), S(11), 0xFF, 0x00, -/* sc=3c */ F( 2), F(14), F(26), F(38), S( 2), S(12), S( 2), S(12), 0xFF, 0x00, -/* sc=3d */ F( 3), F(15), F(27), F(39), S( 3), S(13), S( 3), S(13), 0xFF, 0x00, -/* sc=3e */ F( 4), F(16), F(28), F(40), S( 4), S(14), S( 4), S(14), 0xFF, 0x00, -/* sc=3f */ F( 5), F(17), F(29), F(41), S( 5), S(15), S( 5), S(15), 0xFF, 0x00, -/* sc=40 */ F( 6), F(18), F(30), F(42), S( 6), S(16), S( 6), S(16), 0xFF, 0x00, -/* sc=41 */ F( 7), F(19), F(31), F(43), S( 7), S( 7), S( 7), S( 7), 0xFF, 0x00, -/* sc=42 */ F( 8), F(20), F(32), F(44), S( 8), S( 8), S( 8), S( 8), 0xFF, 0x00, -/* sc=43 */ F( 9), F(21), F(33), F(45), S( 9), S( 9), S( 9), S( 9), 0xFF, 0x00, -/* sc=44 */ F(10), F(22), F(34), F(46), S(10), S(10), S(10), S(10), 0xFF, 0x00, -/* sc=45 */ NLK, NLK, 0x13, 0x13, NLK, NLK, 0x13, 0x13, 0xCC, 0x00, -/* sc=46 */ SLK, SLK, 0x7F, 0x7F, SLK, SLK, 0x7F, 0x7F, 0xCC, 0x00, -/* sc=47 */ F(49), '7', '7', '7', '7', '7', '7', '7', 0x80, 0x02, -/* sc=48 */ F(50), '8', '8', '8', '8', '8', '8', '8', 0x80, 0x02, -/* sc=49 */ F(51), '9', '9', '9', '9', '9', '9', '9', 0x80, 0x02, -/* sc=4a */ F(52), '-', 0x1F, 0x1F, '-', '-', '-', '-', 0x80, 0x02, -/* sc=4b */ F(53), '4', '4', '4', '4', '4', '4', '4', 0x80, 0x02, -/* sc=4c */ F(54), '5', '5', '5', '5', '5', '5', '5', 0x80, 0x02, -/* sc=4d */ F(55), '6', 0x1E, 0x1E, '6', '6', '6', '6', 0x80, 0x02, -/* sc=4e */ F(56), '+', '+', '+', '+', '+', '+', '+', 0x80, 0x02, -/* sc=4f */ F(57), '1', '1', '1', '1', '1', '1', '1', 0x80, 0x02, -/* sc=50 */ F(58), '2', '2', '2', '2', '2', '2', '2', 0x80, 0x02, -/* sc=51 */ F(59), '3', '3', '3', '3', '3', '3', '3', 0x80, 0x02, -/* sc=52 */ F(60), '0', '0', '0', '0', '0', '0', '0', 0x80, 0x02, -/* sc=53 */ 0x7F, '.', '.', '.', '.', '.', RBT, RBT, 0x03, 0x02, -/* sc=54 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=55 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=56 */ '\\', '|', 0x1C, 0x1C, '\\', '|', 0x1C, 0x1C, 0x00, 0x00, -/* sc=57 */ F(11), F(23), F(35), F(47), S(11), S(11), S(11), S(11), 0xFF, 0x00, -/* sc=58 */ F(12), F(24), F(36), F(48), S(12), S(12), S(12), S(12), 0xFF, 0x00, -/* sc=59 */ 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0xFF, 0x02, -/* sc=5a */ RCTR, RCTR, RCTR, RCTR, RCTR, RCTR, RCTR, RCTR, 0xFF, 0x00, -/* sc=5b */ '/', '/', '/', '/', '/', '/', '/', '/', 0x00, 0x02, -/* sc=5c */ NEXT, NOP, DBG, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=5d */ RALT, RALT, RALT, RALT, RALT, RALT, RALT, RALT, 0xFF, 0x00, -/* sc=5e */ F(49), F(49), F(49), F(49), F(49), F(49), F(49), F(49), 0xFF, 0x00, -/* sc=5f */ F(50), F(50), F(50), F(50), F(50), F(50), F(50), F(50), 0xFF, 0x00, -/* sc=60 */ F(51), F(51), F(51), F(51), F(51), F(51), F(51), F(51), 0xFF, 0x00, -/* sc=61 */ F(53), F(53), F(53), F(53), F(53), F(53), F(53), F(53), 0xFF, 0x00, -/* sc=62 */ F(55), F(55), F(55), F(55), F(55), F(55), F(55), F(55), 0xFF, 0x00, -/* sc=63 */ F(57), F(57), F(57), F(57), F(57), F(57), F(57), F(57), 0xFF, 0x00, -/* sc=64 */ F(58), F(58), F(58), F(58), F(58), F(58), F(58), F(58), 0xFF, 0x00, -/* sc=65 */ F(59), F(59), F(59), F(59), F(59), F(59), F(59), F(59), 0xFF, 0x00, -/* sc=66 */ F(60), F(60), F(60), F(60), F(60), F(60), F(60), F(60), 0xFF, 0x00, -/* sc=67 */ F(61), F(61), F(61), F(61), F(61), F(61), RBT, F(61), 0xFF, 0x00, -/* sc=68 */ SLK, SLK, SLK, SLK, SLK, SLK, SLK, SLK, 0xFF, 0x00, -/* sc=69 */ F(62), F(62), F(62), F(62), F(62), F(62), F(62), F(62), 0xFF, 0x00, -/* sc=6a */ F(63), F(63), F(63), F(63), F(63), F(63), F(63), F(63), 0xFF, 0x00, -/* sc=6b */ F(64), F(64), F(64), F(64), F(64), F(64), F(64), F(64), 0xFF, 0x00, -}; -#endif - -#ifdef GRKEYMAP -static keymap_t key_map = { 0x6C, /* german iso8859 keymap */ -/* alt - * scan cntrl alt alt cntrl - * code base shift cntrl shift alt shift cntrl shift spcl flgs - * --------------------------------------------------------------------------- - */ -/* sc=00 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=01 */ 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, DBG, 0x1B, 0x02, 0x00, -/* sc=02 */ '1', '!', NOP, NOP, '`', '`', NOP, NOP, 0x33, 0x00, -/* sc=03 */ '2', '"', 0x00, 0x00, '@', '@', 0x00, 0x00, 0x00, 0x00, -/* sc=04 */ '3', 0xA7, NOP, NOP, '#', '#', NOP, NOP, 0x33, 0x00, -/* sc=05 */ '4', '$', NOP, NOP, '4', '$', NOP, NOP, 0x33, 0x00, -/* sc=06 */ '5', '%', NOP, NOP, '5', '%', NOP, NOP, 0x33, 0x00, -/* sc=07 */ '6', '&', 0x1E, 0x1E, '^', '^', 0x1E, 0x1E, 0x00, 0x00, -/* sc=08 */ '7', '/', 0x1B, 0x1B, '[', '[', 0x1B, 0x1B, 0x00, 0x00, -/* sc=09 */ '8', '(', NOP, NOP, '8', '(', NOP, NOP, 0x33, 0x00, -/* sc=0a */ '9', ')', 0x1D, 0x1D, ']', ']', 0x1D, 0x1D, 0x00, 0x00, -/* sc=0b */ '0', '=', NOP, NOP, '{', '{', NOP, NOP, 0x33, 0x00, -/* sc=0c */ 0xDF, '?', NOP, NOP, '|', '|', NOP, NOP, 0x33, 0x00, -/* sc=0d */ 0x92, 0x93, NOP, NOP, '\'', '`', NOP, NOP, 0x33, 0x00, -/* sc=0e */ 0x08, 0x08, 0x7F, 0x7F, 0x08, 0x08, 0x7F, 0x7F, 0x00, 0x00, -/* sc=0f */ 0x09, BTAB, NOP, NOP, 0x09, BTAB, NOP, NOP, 0x77, 0x00, -/* sc=10 */ 'q', 'Q', 0x11, 0x11, 'q', 'Q', 0x11, 0x11, 0x00, 0x01, -/* sc=11 */ 'w', 'W', 0x17, 0x17, 'w', 'W', 0x17, 0x17, 0x00, 0x01, -/* sc=12 */ 'e', 'E', 0x05, 0x05, 'e', 'E', 0x05, 0x05, 0x00, 0x01, -/* sc=13 */ 'r', 'R', 0x12, 0x12, 'r', 'R', 0x12, 0x12, 0x00, 0x01, -/* sc=14 */ 't', 'T', 0x14, 0x14, 't', 'T', 0x14, 0x14, 0x00, 0x01, -/* sc=15 */ 'z', 'Z', 0x1A, 0x1A, 'z', 'Z', 0x1A, 0x1A, 0x00, 0x01, -/* sc=16 */ 'u', 'U', 0x15, 0x15, 'u', 'U', 0x15, 0x15, 0x00, 0x01, -/* sc=17 */ 'i', 'I', 0x09, 0x09, 'i', 'I', 0x09, 0x09, 0x00, 0x01, -/* sc=18 */ 'o', 'O', 0x0F, 0x0F, 'o', 'O', 0x0F, 0x0F, 0x00, 0x01, -/* sc=19 */ 'p', 'P', 0x10, 0x10, 'p', 'P', 0x10, 0x10, 0x00, 0x01, -/* sc=1a */ 0xFC, 0xDC, 0x1B, 0x1B, '[', '{', 0x1B, 0x1B, 0x00, 0x01, -/* sc=1b */ '+', '*', 0x1D, 0x1D, ']', '}', 0x1D, 0x1D, 0x00, 0x00, -/* sc=1c */ 0x0D, 0x0D, 0x0A, 0x0A, 0x0D, 0x0D, 0x0A, 0x0A, 0x00, 0x00, -/* sc=1d */ LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, 0xFF, 0x00, -/* sc=1e */ 'a', 'A', 0x01, 0x01, 'a', 'A', 0x01, 0x01, 0x00, 0x01, -/* sc=1f */ 's', 'S', 0x13, 0x13, 's', 'S', 0x13, 0x13, 0x00, 0x01, -/* sc=20 */ 'd', 'D', 0x04, 0x04, 'd', 'D', 0x04, 0x04, 0x00, 0x01, -/* sc=21 */ 'f', 'F', 0x06, 0x06, 'f', 'F', 0x06, 0x06, 0x00, 0x01, -/* sc=22 */ 'g', 'G', 0x07, 0x07, 'g', 'G', 0x07, 0x07, 0x00, 0x01, -/* sc=23 */ 'h', 'H', 0x08, 0x08, 'h', 'H', 0x08, 0x08, 0x00, 0x01, -/* sc=24 */ 'j', 'J', 0x0A, 0x0A, 'j', 'J', 0x0A, 0x0A, 0x00, 0x01, -/* sc=25 */ 'k', 'K', 0x0B, 0x0B, 'k', 'K', 0x0B, 0x0B, 0x00, 0x01, -/* sc=26 */ 'l', 'L', 0x0C, 0x0C, 'l', 'L', 0x0C, 0x0C, 0x00, 0x01, -/* sc=27 */ 0xF6, 0xD6, NOP, NOP, 0xF6, 0xD6, NOP, NOP, 0x33, 0x01, -/* sc=28 */ 0xE4, 0xC4, NOP, NOP, 0xE4, 0xC4, NOP, NOP, 0x33, 0x01, -/* sc=29 */ '<', '>', 0x1C, 0x1C, '\\', '|', 0x1C, 0x1C, 0x00, 0x00, -/* sc=2a */ LSH, LSH, LSH, LSH, LSH, LSH, LSH, LSH, 0xFF, 0x00, -/* sc=2b */ '#', '^', 0x1E, 0x1E, '`', '~', 0x1E, 0x1E, 0x00, 0x00, -/* sc=2c */ 'y', 'Y', 0x19, 0x19, 'y', 'Y', 0x19, 0x19, 0x00, 0x01, -/* sc=2d */ 'x', 'X', 0x18, 0x18, 'x', 'X', 0x18, 0x18, 0x00, 0x01, -/* sc=2e */ 'c', 'C', 0x03, 0x03, 'c', 'C', 0x03, 0x03, 0x00, 0x01, -/* sc=2f */ 'v', 'V', 0x16, 0x16, 'v', 'V', 0x16, 0x16, 0x00, 0x01, -/* sc=30 */ 'b', 'B', 0x02, 0x02, 'b', 'B', 0x02, 0x02, 0x00, 0x01, -/* sc=31 */ 'n', 'N', 0x0E, 0x0E, 'n', 'N', 0x0E, 0x0E, 0x00, 0x01, -/* sc=32 */ 'm', 'M', 0x0D, 0x0D, 'm', 'M', 0x0D, 0x0D, 0x00, 0x01, -/* sc=33 */ ',', ';', NOP, NOP, ',', ';', NOP, NOP, 0x33, 0x00, -/* sc=34 */ '.', ':', NOP, NOP, '.', ':', NOP, NOP, 0x33, 0x00, -/* sc=35 */ '-', '_', 0x1F, 0x1F, '-', '_', 0x1F, 0x1F, 0x00, 0x00, -/* sc=36 */ RSH, RSH, RSH, RSH, RSH, RSH, RSH, RSH, 0xFF, 0x00, -/* sc=37 */ '*', '*', 0x0A, 0x0A, '*', '*', 0x0A, 0x0A, 0x33, 0x00, -/* sc=38 */ LALT, LALT, LALT, LALT, LALT, LALT, LALT, LALT, 0xFF, 0x00, -/* sc=39 */ ' ', ' ', 0x00, ' ', ' ', ' ', SUSP, ' ', 0x02, 0x00, -/* sc=3a */ CLK, CLK, CLK, CLK, CLK, CLK, CLK, CLK, 0xFF, 0x00, -/* sc=3b */ F( 1), F(13), F(25), F(37), S( 1), S(11), S( 1), S(11), 0xFF, 0x00, -/* sc=3c */ F( 2), F(14), F(26), F(38), S( 2), S(12), S( 2), S(12), 0xFF, 0x00, -/* sc=3d */ F( 3), F(15), F(27), F(39), S( 3), S(13), S( 3), S(13), 0xFF, 0x00, -/* sc=3e */ F( 4), F(16), F(28), F(40), S( 4), S(14), S( 4), S(14), 0xFF, 0x00, -/* sc=3f */ F( 5), F(17), F(29), F(41), S( 5), S(15), S( 5), S(15), 0xFF, 0x00, -/* sc=40 */ F( 6), F(18), F(30), F(42), S( 6), S(16), S( 6), S(16), 0xFF, 0x00, -/* sc=41 */ F( 7), F(19), F(31), F(43), S( 7), S( 7), S( 7), S( 7), 0xFF, 0x00, -/* sc=42 */ F( 8), F(20), F(32), F(44), S( 8), S( 8), S( 8), S( 8), 0xFF, 0x00, -/* sc=43 */ F( 9), F(21), F(33), F(45), S( 9), S( 9), S( 9), S( 9), 0xFF, 0x00, -/* sc=44 */ F(10), F(22), F(34), F(46), S(10), S(10), S(10), S(10), 0xFF, 0x00, -/* sc=45 */ NLK, NLK, 0x13, 0x13, NLK, NLK, 0x13, 0x13, 0xCC, 0x00, -/* sc=46 */ SLK, SLK, 0x7F, 0x7F, SLK, SLK, 0x7F, 0x7F, 0xCC, 0x00, -/* sc=47 */ F(49), '7', '7', '7', '7', '7', '7', '7', 0x80, 0x02, -/* sc=48 */ F(50), '8', '8', '8', '8', '8', '8', '8', 0x80, 0x02, -/* sc=49 */ F(51), '9', '9', '9', '9', '9', '9', '9', 0x80, 0x02, -/* sc=4a */ F(52), '-', 0x1F, 0x1F, '-', '-', '-', '-', 0x80, 0x02, -/* sc=4b */ F(53), '4', '4', '4', '4', '4', '4', '4', 0x80, 0x02, -/* sc=4c */ F(54), '5', '5', '5', '5', '5', '5', '5', 0x80, 0x02, -/* sc=4d */ F(55), '6', 0x1E, 0x1E, '6', '6', '6', '6', 0x80, 0x02, -/* sc=4e */ F(56), '+', '+', '+', '+', '+', '+', '+', 0x80, 0x02, -/* sc=4f */ F(57), '1', '1', '1', '1', '1', '1', '1', 0x80, 0x02, -/* sc=50 */ F(58), '2', '2', '2', '2', '2', '2', '2', 0x80, 0x02, -/* sc=51 */ F(59), '3', '3', '3', '3', '3', '3', '3', 0x80, 0x02, -/* sc=52 */ F(60), '0', '0', '0', '0', '0', '0', '0', 0x80, 0x02, -/* sc=53 */ 0x7F, '.', '.', '.', '.', '.', RBT, RBT, 0x03, 0x02, -/* sc=54 */ 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00, 0x00, -/* sc=55 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=56 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=57 */ F(11), F(23), F(35), F(47), S(11), S(11), S(11), S(11), 0xFF, 0x00, -/* sc=58 */ F(12), F(24), F(36), F(48), S(12), S(12), S(12), S(12), 0xFF, 0x00, -/* sc=59 */ 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0xFF, 0x02, -/* sc=5a */ RCTR, RCTR, RCTR, RCTR, RCTR, RCTR, RCTR, RCTR, 0xFF, 0x00, -/* sc=5b */ '/', '/', '/', '/', '/', '/', '/', '/', 0x00, 0x02, -/* sc=5c */ NEXT, NOP, DBG, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=5d */ RALT, RALT, RALT, RALT, RALT, RALT, RALT, RALT, 0xFF, 0x00, -/* sc=5e */ F(49), F(49), F(49), F(49), F(49), F(49), F(49), F(49), 0xFF, 0x00, -/* sc=5f */ F(50), F(50), F(50), F(50), F(50), F(50), F(50), F(50), 0xFF, 0x00, -/* sc=60 */ F(51), F(51), F(51), F(51), F(51), F(51), F(51), F(51), 0xFF, 0x00, -/* sc=61 */ F(53), F(53), F(53), F(53), F(53), F(53), F(53), F(53), 0xFF, 0x00, -/* sc=62 */ F(55), F(55), F(55), F(55), F(55), F(55), F(55), F(55), 0xFF, 0x00, -/* sc=63 */ F(57), F(57), F(57), F(57), F(57), F(57), F(57), F(57), 0xFF, 0x00, -/* sc=64 */ F(58), F(58), F(58), F(58), F(58), F(58), F(58), F(58), 0xFF, 0x00, -/* sc=65 */ F(59), F(59), F(59), F(59), F(59), F(59), F(59), F(59), 0xFF, 0x00, -/* sc=66 */ F(60), F(60), F(60), F(60), F(60), F(60), F(60), F(60), 0xFF, 0x00, -/* sc=67 */ F(61), F(61), F(61), F(61), F(61), F(61), RBT, F(61), 0xFF, 0x00, -/* sc=68 */ SLK, SLK, SLK, SLK, SLK, SLK, SLK, SLK, 0xFF, 0x00, -/* sc=69 */ F(62), F(62), F(62), F(62), F(62), F(62), F(62), F(62), 0xFF, 0x00, -/* sc=6a */ F(63), F(63), F(63), F(63), F(63), F(63), F(63), F(63), 0xFF, 0x00, -/* sc=6b */ F(64), F(64), F(64), F(64), F(64), F(64), F(64), F(64), 0xFF, 0x00, -}; -#endif - -#ifdef SWKEYMAP -static keymap_t key_map = { 0x6C, /* swedish iso8859 keymap */ -/* alt - * scan cntrl alt alt cntrl - * code base shift cntrl shift alt shift cntrl shift spcl flgs - * --------------------------------------------------------------------------- - */ -/* sc=00 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=01 */ 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, DBG, 0x1B, 0x02, 0x00, -/* sc=02 */ '1', '!', NOP, NOP, NOP, NOP, NOP, NOP, 0x3F, 0x00, -/* sc=03 */ '2', '"', 0x00, 0x00, '@', '@', 0x00, 0x00, 0x00, 0x00, -/* sc=04 */ '3', '#', NOP, NOP, 0xA3, NOP, NOP, NOP, 0x37, 0x00, -/* sc=05 */ '4', '$', NOP, NOP, 0xA4, NOP, NOP, NOP, 0x37, 0x00, -/* sc=06 */ '5', '%', NOP, NOP, NOP, NOP, NOP, NOP, 0x3F, 0x00, -/* sc=07 */ '6', '&', NOP, NOP, NOP, NOP, NOP, NOP, 0x3F, 0x00, -/* sc=08 */ '7', '/', NOP, NOP, '{', NOP, NOP, NOP, 0x37, 0x00, -/* sc=09 */ '8', '(', NOP, NOP, '[', NOP, NOP, NOP, 0x37, 0x00, -/* sc=0a */ '9', ')', NOP, NOP, ']', NOP, NOP, NOP, 0x37, 0x00, -/* sc=0b */ '0', '=', NOP, NOP, '}', NOP, NOP, NOP, 0x37, 0x00, -/* sc=0c */ '+', '?', NOP, NOP, '\\', NOP, 0x1C, NOP, 0x35, 0x00, -/* sc=0d */ 0x180, '`', NOP, NOP, NOP, NOP, NOP, NOP, 0x3F, 0x00, -/* sc=0e */ 0x08, 0x08, 0x7F, 0x7F, 0x08, 0x08, 0x7F, 0x7F, 0x00, 0x00, -/* sc=0f */ 0x09, BTAB, NOP, NOP, 0x09, BTAB, NOP, NOP, 0x77, 0x00, -/* sc=10 */ 'q', 'Q', 0x11, 0x11, 'q', 'Q', 0x11, 0x11, 0x00, 0x01, -/* sc=11 */ 'w', 'W', 0x17, 0x17, 'w', 'W', 0x17, 0x17, 0x00, 0x01, -/* sc=12 */ 'e', 'E', 0x05, 0x05, 'e', 'E', 0x05, 0x05, 0x00, 0x01, -/* sc=13 */ 'r', 'R', 0x12, 0x12, 'r', 'R', 0x12, 0x12, 0x00, 0x01, -/* sc=14 */ 't', 'T', 0x14, 0x14, 't', 'T', 0x14, 0x14, 0x00, 0x01, -/* sc=15 */ 'y', 'Y', 0x19, 0x19, 'y', 'Y', 0x19, 0x19, 0x00, 0x01, -/* sc=16 */ 'u', 'U', 0x15, 0x15, 'u', 'U', 0x15, 0x15, 0x00, 0x01, -/* sc=17 */ 'i', 'I', 0x09, 0x09, 'i', 'I', 0x09, 0x09, 0x00, 0x01, -/* sc=18 */ 'o', 'O', 0x0F, 0x0F, 'o', 'O', 0x0F, 0x0F, 0x00, 0x01, -/* sc=19 */ 'p', 'P', 0x10, 0x10, 'p', 'P', 0x10, 0x10, 0x00, 0x01, -/* sc=1a */ 0xE5, 0xC5, NOP, NOP, '}', ']', NOP, NOP, 0x33, 0x01, -/* sc=1b */ 0xA8, '^', NOP, NOP, '~', NOP, NOP, NOP, 0x37, 0x00, -/* sc=1c */ 0x0D, 0x0D, 0x0A, 0x0A, 0x0D, 0x0D, 0x0A, 0x0A, 0x00, 0x00, -/* sc=1d */ LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, 0xFF, 0x00, -/* sc=1e */ 'a', 'A', 0x01, 0x01, 'a', 'A', 0x01, 0x01, 0x00, 0x01, -/* sc=1f */ 's', 'S', 0x13, 0x13, 's', 'S', 0x13, 0x13, 0x00, 0x01, -/* sc=20 */ 'd', 'D', 0x04, 0x04, 'd', 'D', 0x04, 0x04, 0x00, 0x01, -/* sc=21 */ 'f', 'F', 0x06, 0x06, 'f', 'F', 0x06, 0x06, 0x00, 0x01, -/* sc=22 */ 'g', 'G', 0x07, 0x07, 'g', 'G', 0x07, 0x07, 0x00, 0x01, -/* sc=23 */ 'h', 'H', 0x08, 0x08, 'h', 'H', 0x08, 0x08, 0x00, 0x01, -/* sc=24 */ 'j', 'J', 0x0A, 0x0A, 'j', 'J', 0x0A, 0x0A, 0x00, 0x01, -/* sc=25 */ 'k', 'K', 0x0B, 0x0B, 'k', 'K', 0x0B, 0x0B, 0x00, 0x01, -/* sc=26 */ 'l', 'L', 0x0C, 0x0C, 'l', 'L', 0x0C, 0x0C, 0x00, 0x01, -/* sc=27 */ 0xF6, 0xD6, NOP, NOP, '|', '\\', NOP, NOP, 0x33, 0x01, -/* sc=28 */ 0xE4, 0xC4, NOP, NOP, '{', '[', NOP, NOP, 0x33, 0x01, -/* sc=29 */ 0xA7, 0xBD, NOP, NOP, '\\', '|', NOP, NOP, 0x33, 0x00, -/* sc=2a */ LSH, LSH, LSH, LSH, LSH, LSH, LSH, LSH, 0xFF, 0x00, -/* sc=2b */ '\'', '*', NOP, NOP, NOP, NOP, NOP, NOP, 0x3F, 0x00, -/* sc=2c */ 'z', 'Z', 0x1A, 0x1A, 'z', 'Z', 0x1A, 0x1A, 0x00, 0x01, -/* sc=2d */ 'x', 'X', 0x18, 0x18, 'x', 'X', 0x18, 0x18, 0x00, 0x01, -/* sc=2e */ 'c', 'C', 0x03, 0x03, 'c', 'C', 0x03, 0x03, 0x00, 0x01, -/* sc=2f */ 'v', 'V', 0x16, 0x16, 'v', 'V', 0x16, 0x16, 0x00, 0x01, -/* sc=30 */ 'b', 'B', 0x02, 0x02, 'b', 'B', 0x02, 0x02, 0x00, 0x01, -/* sc=31 */ 'n', 'N', 0x0E, 0x0E, 'n', 'N', 0x0E, 0x0E, 0x00, 0x01, -/* sc=32 */ 'm', 'M', 0x0D, 0x0D, 'm', 'M', 0x0D, 0x0D, 0x00, 0x01, -/* sc=33 */ ',', ';', NOP, NOP, NOP, '<', NOP, NOP, 0x3B, 0x00, -/* sc=34 */ '.', ':', NOP, NOP, NOP, '>', NOP, NOP, 0x3B, 0x00, -/* sc=35 */ '-', '_', 0x1F, NOP, '/', '?', NOP, NOP, 0x13, 0x00, -/* sc=36 */ RSH, RSH, RSH, RSH, RSH, RSH, RSH, RSH, 0xFF, 0x00, -/* sc=37 */ '*', '*', 0x0A, 0x0A, '*', '*', 0x0A, 0x0A, 0x33, 0x00, -/* sc=38 */ LALT, LALT, LALT, LALT, LALT, LALT, LALT, LALT, 0xFF, 0x00, -/* sc=39 */ ' ', ' ', 0x00, ' ', ' ', ' ', SUSP, ' ', 0x02, 0x00, -/* sc=3a */ CLK, CLK, CLK, CLK, CLK, CLK, CLK, CLK, 0xFF, 0x00, -/* sc=3b */ F( 1), F(13), F(25), F(37), S( 1), S(11), S( 1), S(11), 0xFF, 0x00, -/* sc=3c */ F( 2), F(14), F(26), F(38), S( 2), S(12), S( 2), S(12), 0xFF, 0x00, -/* sc=3d */ F( 3), F(15), F(27), F(39), S( 3), S(13), S( 3), S(13), 0xFF, 0x00, -/* sc=3e */ F( 4), F(16), F(28), F(40), S( 4), S(14), S( 4), S(14), 0xFF, 0x00, -/* sc=3f */ F( 5), F(17), F(29), F(41), S( 5), S(15), S( 5), S(15), 0xFF, 0x00, -/* sc=40 */ F( 6), F(18), F(30), F(42), S( 6), S(16), S( 6), S(16), 0xFF, 0x00, -/* sc=41 */ F( 7), F(19), F(31), F(43), S( 7), S( 7), S( 7), S( 7), 0xFF, 0x00, -/* sc=42 */ F( 8), F(20), F(32), F(44), S( 8), S( 8), S( 8), S( 8), 0xFF, 0x00, -/* sc=43 */ F( 9), F(21), F(33), F(45), S( 9), S( 9), S( 9), S( 9), 0xFF, 0x00, -/* sc=44 */ F(10), F(22), F(34), F(46), S(10), S(10), S(10), S(10), 0xFF, 0x00, -/* sc=45 */ NLK, NLK, 0x13, 0x13, NLK, NLK, 0x13, 0x13, 0xCC, 0x00, -/* sc=46 */ SLK, SLK, 0x7F, 0x7F, SLK, SLK, 0x7F, 0x7F, 0xCC, 0x00, -/* sc=47 */ F(49), '7', '7', '7', '7', '7', '7', '7', 0x80, 0x02, -/* sc=48 */ F(50), '8', '8', '8', '8', '8', '8', '8', 0x80, 0x02, -/* sc=49 */ F(51), '9', '9', '9', '9', '9', '9', '9', 0x80, 0x02, -/* sc=4a */ F(52), '-', 0x1F, 0x1F, '-', '-', '-', '-', 0x80, 0x02, -/* sc=4b */ F(53), '4', '4', '4', '4', '4', '4', '4', 0x80, 0x02, -/* sc=4c */ F(54), '5', '5', '5', '5', '5', '5', '5', 0x80, 0x02, -/* sc=4d */ F(55), '6', 0x1E, 0x1E, '6', '6', '6', '6', 0x80, 0x02, -/* sc=4e */ F(56), '+', '+', '+', '+', '+', '+', '+', 0x80, 0x02, -/* sc=4f */ F(57), '1', '1', '1', '1', '1', '1', '1', 0x80, 0x02, -/* sc=50 */ F(58), '2', '2', '2', '2', '2', '2', '2', 0x80, 0x02, -/* sc=51 */ F(59), '3', '3', '3', '3', '3', '3', '3', 0x80, 0x02, -/* sc=52 */ F(60), '0', '0', '0', '0', '0', '0', '0', 0x80, 0x02, -/* sc=53 */ 0x7F, '.', '.', '.', '.', '.', RBT, RBT, 0x03, 0x02, -/* sc=54 */ 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00, 0x00, -/* sc=55 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=56 */ '<', '>', NOP, NOP, '|', NOP, NOP, NOP, 0x37, 0x00, -/* sc=57 */ F(11), F(23), F(35), F(47), S(11), S(11), S(11), S(11), 0xFF, 0x00, -/* sc=58 */ F(12), F(24), F(36), F(48), S(12), S(12), S(12), S(12), 0xFF, 0x00, -/* sc=59 */ 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0xFF, 0x02, -/* sc=5a */ RCTR, RCTR, RCTR, RCTR, RCTR, RCTR, RCTR, RCTR, 0xFF, 0x00, -/* sc=5b */ '/', '/', '/', '/', '/', '/', '/', '/', 0x00, 0x02, -/* sc=5c */ NEXT, NOP, DBG, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=5d */ RALT, RALT, RALT, RALT, RALT, RALT, RALT, RALT, 0xFF, 0x00, -/* sc=5e */ F(49), F(49), F(49), F(49), F(49), F(49), F(49), F(49), 0xFF, 0x00, -/* sc=5f */ F(50), F(50), F(50), F(50), F(50), F(50), F(50), F(50), 0xFF, 0x00, -/* sc=60 */ F(51), F(51), F(51), F(51), F(51), F(51), F(51), F(51), 0xFF, 0x00, -/* sc=61 */ F(53), F(53), F(53), F(53), F(53), F(53), F(53), F(53), 0xFF, 0x00, -/* sc=62 */ F(55), F(55), F(55), F(55), F(55), F(55), F(55), F(55), 0xFF, 0x00, -/* sc=63 */ F(57), F(57), F(57), F(57), F(57), F(57), F(57), F(57), 0xFF, 0x00, -/* sc=64 */ F(58), F(58), F(58), F(58), F(58), F(58), F(58), F(58), 0xFF, 0x00, -/* sc=65 */ F(59), F(59), F(59), F(59), F(59), F(59), F(59), F(59), 0xFF, 0x00, -/* sc=66 */ F(60), F(60), F(60), F(60), F(60), F(60), F(60), F(60), 0xFF, 0x00, -/* sc=67 */ F(61), F(61), F(61), F(61), F(61), F(61), RBT, F(61), 0xFF, 0x00, -/* sc=68 */ SLK, SLK, SLK, SLK, SLK, SLK, SLK, SLK, 0xFF, 0x00, -/* sc=69 */ F(62), F(62), F(62), F(62), F(62), F(62), F(62), F(62), 0xFF, 0x00, -/* sc=6a */ F(63), F(63), F(63), F(63), F(63), F(63), F(63), F(63), 0xFF, 0x00, -/* sc=6b */ F(64), F(64), F(64), F(64), F(64), F(64), F(64), F(64), 0xFF, 0x00, -}; -#endif - -#ifdef RUKEYMAP -static keymap_t key_map = { 0xEC, /* keys number */ -/* alt - * scan cntrl alt alt cntrl - * code base shift cntrl shift alt shift cntrl shift spcl flgs - * ------------------------------------------------------------------------------------------- - */ -/* sc=00 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=01 */ 0x1B, 0x1B, NOP, NOP, SET8|0x1B, SET8|0x1B, DBG, NOP, 0x33, 0x00, -/* sc=02 */ '1', '!', NOP, NOP, SET8|'1', SET8|'!', NOP, NOP, 0x33, 0x00, -/* sc=03 */ '2', '@', 0x00, 0x00, SET8|'2', SET8|'@', SET8|0x00, SET8|0x00, 0x00, 0x00, -/* sc=04 */ '3', '#', NOP, NOP, SET8|'3', SET8|'#', NOP, NOP, 0x33, 0x00, -/* sc=05 */ '4', '$', NOP, NOP, SET8|'4', SET8|'$', NOP, NOP, 0x33, 0x00, -/* sc=06 */ '5', '%', NOP, NOP, SET8|'5', SET8|'%', NOP, NOP, 0x33, 0x00, -/* sc=07 */ '6', '^', 0x1E, 0x1E, SET8|'6', SET8|'^', SET8|0x1E, SET8|0x1E, 0x00, 0x00, -/* sc=08 */ '7', '&', NOP, NOP, SET8|'7', SET8|'&', NOP, NOP, 0x33, 0x00, -/* sc=09 */ '8', '*', NOP, NOP, SET8|'8', SET8|'*', NOP, NOP, 0x33, 0x00, -/* sc=0a */ '9', '(', NOP, NOP, SET8|'9', SET8|'(', NOP, NOP, 0x33, 0x00, -/* sc=0b */ '0', ')', NOP, NOP, SET8|'0', SET8|')', NOP, NOP, 0x33, 0x00, -/* sc=0c */ '-', '_', 0x1F, 0x1F, SET8|'-', SET8|'_', SET8|0x1F, SET8|0x1F, 0x00, 0x00, -/* sc=0d */ '=', '+', NOP, NOP, SET8|'=', SET8|'+', NOP, NOP, 0x33, 0x00, -/* sc=0e */ 0x08, 0x08, 0x7F, 0x7F, SET8|0x08, SET8|0x08, SET8|0x7F, SET8|0x7F, 0x00, 0x00, -/* sc=0f */ 0x09, BTAB, NOP, NOP, SET8|0x09, BTAB, NOP, NOP, 0x77, 0x00, -/* sc=10 */ 'q', 'Q', 0x11, 0x11, SET8|'q', SET8|'Q', SET8|0x11, SET8|0x11, 0x00, 0x01, -/* sc=11 */ 'w', 'W', 0x17, 0x17, SET8|'w', SET8|'W', SET8|0x17, SET8|0x17, 0x00, 0x01, -/* sc=12 */ 'e', 'E', 0x05, 0x05, SET8|'e', SET8|'E', SET8|0x05, SET8|0x05, 0x00, 0x01, -/* sc=13 */ 'r', 'R', 0x12, 0x12, SET8|'r', SET8|'R', SET8|0x12, SET8|0x12, 0x00, 0x01, -/* sc=14 */ 't', 'T', 0x14, 0x14, SET8|'t', SET8|'T', SET8|0x14, SET8|0x14, 0x00, 0x01, -/* sc=15 */ 'y', 'Y', 0x19, 0x19, SET8|'y', SET8|'Y', SET8|0x19, SET8|0x19, 0x00, 0x01, -/* sc=16 */ 'u', 'U', 0x15, 0x15, SET8|'u', SET8|'U', SET8|0x15, SET8|0x15, 0x00, 0x01, -/* sc=17 */ 'i', 'I', 0x09, 0x09, SET8|'i', SET8|'I', SET8|0x09, SET8|0x09, 0x00, 0x01, -/* sc=18 */ 'o', 'O', 0x0F, 0x0F, SET8|'o', SET8|'O', SET8|0x0F, SET8|0x0F, 0x00, 0x01, -/* sc=19 */ 'p', 'P', 0x10, 0x10, SET8|'p', SET8|'P', SET8|0x10, SET8|0x10, 0x00, 0x01, -/* sc=1a */ '[', '{', 0x1B, 0x1B, SET8|'[', SET8|'{', SET8|0x1B, SET8|0x1B, 0x00, 0x00, -/* sc=1b */ ']', '}', 0x1D, 0x1D, SET8|']', SET8|'}', SET8|0x1D, SET8|0x1D, 0x00, 0x00, -/* sc=1c */ 0x0D, 0x0D, 0x0A, 0x0A, SET8|0x0D, SET8|0x0D, SET8|0x0A, SET8|0x0A, 0x00, 0x00, -/* sc=1d */ LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, 0xFF, 0x00, -/* sc=1e */ 'a', 'A', 0x01, 0x01, SET8|'a', SET8|'A', SET8|0x01, SET8|0x01, 0x00, 0x01, -/* sc=1f */ 's', 'S', 0x13, 0x13, SET8|'s', SET8|'S', SET8|0x13, SET8|0x13, 0x00, 0x01, -/* sc=20 */ 'd', 'D', 0x04, 0x04, SET8|'d', SET8|'D', SET8|0x04, SET8|0x04, 0x00, 0x01, -/* sc=21 */ 'f', 'F', 0x06, 0x06, SET8|'f', SET8|'F', SET8|0x06, SET8|0x06, 0x00, 0x01, -/* sc=22 */ 'g', 'G', 0x07, 0x07, SET8|'g', SET8|'G', SET8|0x07, SET8|0x07, 0x00, 0x01, -/* sc=23 */ 'h', 'H', 0x08, 0x08, SET8|'h', SET8|'H', SET8|0x08, SET8|0x08, 0x00, 0x01, -/* sc=24 */ 'j', 'J', 0x0A, 0x0A, SET8|'j', SET8|'J', SET8|0x0A, SET8|0x0A, 0x00, 0x01, -/* sc=25 */ 'k', 'K', 0x0B, 0x0B, SET8|'k', SET8|'K', SET8|0x0B, SET8|0x0B, 0x00, 0x01, -/* sc=26 */ 'l', 'L', 0x0C, 0x0C, SET8|'l', SET8|'L', SET8|0x0C, SET8|0x0C, 0x00, 0x01, -/* sc=27 */ ';', ':', NOP, NOP, SET8|';', SET8|':', NOP, NOP, 0x33, 0x00, -/* sc=28 */ '\'', '"', NOP, NOP, SET8|'\'', SET8|'"', NOP, NOP, 0x33, 0x00, -/* sc=29 */ '`', '~', NOP, NOP, SET8|'`', SET8|'~', NOP, NOP, 0x33, 0x00, -/* sc=2a */ LSH, LSH, LSH, LSH, LSH, LSH, LSH, LSH, 0xFF, 0x00, -/* sc=2b */ '\\', '|', 0x1C, 0x1C, SET8|'\\', SET8|'|', SET8|0x1C, SET8|0x1C, 0x00, 0x00, -/* sc=2c */ 'z', 'Z', 0x1A, 0x1A, SET8|'z', SET8|'Z', SET8|0x1A, SET8|0x1A, 0x00, 0x01, -/* sc=2d */ 'x', 'X', 0x18, 0x18, SET8|'x', SET8|'X', SET8|0x18, SET8|0x18, 0x00, 0x01, -/* sc=2e */ 'c', 'C', 0x03, 0x03, SET8|'c', SET8|'C', SET8|0x03, SET8|0x03, 0x00, 0x01, -/* sc=2f */ 'v', 'V', 0x16, 0x16, SET8|'v', SET8|'V', SET8|0x16, SET8|0x16, 0x00, 0x01, -/* sc=30 */ 'b', 'B', 0x02, 0x02, SET8|'b', SET8|'B', SET8|0x02, SET8|0x02, 0x00, 0x01, -/* sc=31 */ 'n', 'N', 0x0E, 0x0E, SET8|'n', SET8|'N', SET8|0x0E, SET8|0x0E, 0x00, 0x01, -/* sc=32 */ 'm', 'M', 0x0D, 0x0D, SET8|'m', SET8|'M', SET8|0x0D, SET8|0x0D, 0x00, 0x01, -/* sc=33 */ ',', '<', NOP, NOP, SET8|',', SET8|'<', NOP, NOP, 0x33, 0x00, -/* sc=34 */ '.', '>', NOP, NOP, SET8|'.', SET8|'>', NOP, NOP, 0x33, 0x00, -/* sc=35 */ '/', '?', NOP, NOP, SET8|'/', SET8|'?', NOP, NOP, 0x33, 0x00, -/* sc=36 */ RSH, RSH, RSH, RSH, RSH, RSH, RSH, RSH, 0xFF, 0x00, -/* sc=37 */ '*', '*', 0x0A, 0x0A, SET8|'*', SET8|'*', SET8|0x0A, SET8|0x0A, 0x00, 0x00, -/* sc=38 */ LALT, LALT, LALT, LALT, LALT, LALT, LALT, LALT, 0xFF, 0x00, -/* sc=39 */ ' ', ' ', 0x00, ' ', SET8|' ', SET8|' ', SET8|' ', SET8|' ', 0x00, 0x00, -/* sc=3a */ ALK, CLK, CLK, CLK, CLK, CLK, CLK, CLK, 0xFF, 0x00, -/* sc=3b */ F( 1), F(13), F(25), F(37), S( 1), S(11), S( 1), S(11), 0xFF, 0x00, -/* sc=3c */ F( 2), F(14), F(26), F(38), S( 2), S(12), S( 2), S(12), 0xFF, 0x00, -/* sc=3d */ F( 3), F(15), F(27), F(39), S( 3), S(13), S( 3), S(13), 0xFF, 0x00, -/* sc=3e */ F( 4), F(16), F(28), F(40), S( 4), S(14), S( 4), S(14), 0xFF, 0x00, -/* sc=3f */ F( 5), F(17), F(29), F(41), S( 5), S(15), S( 5), S(15), 0xFF, 0x00, -/* sc=40 */ F( 6), F(18), F(30), F(42), S( 6), S(16), S( 6), S(16), 0xFF, 0x00, -/* sc=41 */ F( 7), F(19), F(31), F(43), S( 7), S( 7), S( 7), S( 7), 0xFF, 0x00, -/* sc=42 */ F( 8), F(20), F(32), F(44), S( 8), S( 8), S( 8), S( 8), 0xFF, 0x00, -/* sc=43 */ F( 9), F(21), F(33), F(45), S( 9), S( 9), S( 9), S( 9), 0xFF, 0x00, -/* sc=44 */ F(10), F(22), F(34), F(46), S(10), S(10), S(10), S(10), 0xFF, 0x00, -/* sc=45 */ NLK, NLK, NLK, NLK, NLK, NLK, NLK, NLK, 0xFF, 0x00, -/* sc=46 */ SLK, SLK, SLK, SLK, SLK, SLK, SLK, SLK, 0xFF, 0x00, -/* sc=47 */ F(49), '7', '7', '7', SET8|'7', SET8|'7', SET8|'7', SET8|'7', 0x80, 0x02, -/* sc=48 */ F(50), '8', '8', '8', SET8|'8', SET8|'8', SET8|'8', SET8|'8', 0x80, 0x02, -/* sc=49 */ F(51), '9', '9', '9', SET8|'9', SET8|'9', SET8|'9', SET8|'9', 0x80, 0x02, -/* sc=4a */ F(52), '-', '-', '-', SET8|'-', SET8|'-', SET8|'-', SET8|'-', 0x80, 0x02, -/* sc=4b */ F(53), '4', '4', '4', SET8|'4', SET8|'4', SET8|'4', SET8|'4', 0x80, 0x02, -/* sc=4c */ F(54), '5', '5', '5', SET8|'5', SET8|'5', SET8|'5', SET8|'5', 0x80, 0x02, -/* sc=4d */ F(55), '6', '6', '6', SET8|'6', SET8|'6', SET8|'6', SET8|'6', 0x80, 0x02, -/* sc=4e */ F(56), '+', '+', '+', SET8|'+', SET8|'+', SET8|'+', SET8|'+', 0x80, 0x02, -/* sc=4f */ F(57), '1', '1', '1', SET8|'1', SET8|'1', SET8|'1', SET8|'1', 0x80, 0x02, -/* sc=50 */ F(58), '2', '2', '2', SET8|'2', SET8|'2', SET8|'2', SET8|'2', 0x80, 0x02, -/* sc=51 */ F(59), '3', '3', '3', SET8|'3', SET8|'3', SET8|'3', SET8|'3', 0x80, 0x02, -/* sc=52 */ F(60), '0', '0', '0', SET8|'0', SET8|'0', SET8|'0', SET8|'0', 0x80, 0x02, -/* sc=53 */ 0x7F, '.', '.', '.', SET8|'.', SET8|'.', RBT, RBT, 0x03, 0x02, -/* sc=54 */ ALK, ALK, ALK, ALK, ALK, ALK, ALK, ALK, 0xFF, 0x00, -/* sc=55 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=56 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=57 */ F(11), F(23), F(35), F(47), S(11), S(11), S(11), S(11), 0xFF, 0x00, -/* sc=58 */ F(12), F(24), F(36), F(48), S(12), S(12), S(12), S(12), 0xFF, 0x00, -/* sc=59 */ 0x0D, 0x0D, 0x0A, 0x0A, SET8|0x0D, SET8|0x0D, SET8|0x0A, SET8|0x0A, 0x00, 0x00, -/* sc=5a */ RCTR, RCTR, RCTR, RCTR, RCTR, RCTR, RCTR, RCTR, 0xFF, 0x00, -/* sc=5b */ '/', '/', NOP, NOP, SET8|'/', SET8|'/', NOP, NOP, 0x33, 0x00, -/* sc=5c */ NEXT, NOP, DBG, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=5d */ RALT, RALT, RALT, RALT, RALT, RALT, RALT, RALT, 0xFF, 0x00, -/* sc=5e */ F(49), F(49), F(49), F(49), F(49), F(49), F(49), F(49), 0xFF, 0x00, -/* sc=5f */ F(50), F(50), F(50), F(50), F(50), F(50), F(50), F(50), 0xFF, 0x00, -/* sc=60 */ F(51), F(51), F(51), F(51), F(51), F(51), F(51), F(51), 0xFF, 0x00, -/* sc=61 */ F(53), F(53), F(53), F(53), F(53), F(53), F(53), F(53), 0xFF, 0x00, -/* sc=62 */ F(55), F(55), F(55), F(55), F(55), F(55), F(55), F(55), 0xFF, 0x00, -/* sc=63 */ F(57), F(57), F(57), F(57), F(57), F(57), F(57), F(57), 0xFF, 0x00, -/* sc=64 */ F(58), F(58), F(58), F(58), F(58), F(58), F(58), F(58), 0xFF, 0x00, -/* sc=65 */ F(59), F(59), F(59), F(59), F(59), F(59), F(59), F(59), 0xFF, 0x00, -/* sc=66 */ F(60), F(60), F(60), F(60), F(60), F(60), F(60), F(60), 0xFF, 0x00, -/* sc=67 */ F(61), F(61), F(61), F(61), F(61), F(61), RBT, F(61), 0xFF, 0x00, -/* sc=68 */ SLK, SLK, SLK, SLK, SLK, SLK, SLK, SLK, 0xFF, 0x00, -/* sc=69 */ F(62), F(62), F(62), F(62), F(62), F(62), F(62), F(62), 0xFF, 0x00, -/* sc=6a */ F(63), F(63), F(63), F(63), F(63), F(63), F(63), F(63), 0xFF, 0x00, -/* sc=6b */ F(64), F(64), F(64), F(64), F(64), F(64), F(64), F(64), 0xFF, 0x00, -/* sc=6c */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=6d */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=6e */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=6f */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=70 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=71 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=72 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=73 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=74 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=75 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=76 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=77 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=78 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=79 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=7a */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=7b */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=7c */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=7d */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=7e */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=7f */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* extended (ALTGR LOCK keys) */ -/* sc=00 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=01 */ 0x1B, 0x1B, NOP, NOP, SET8|0x1B, SET8|0x1B, DBG, NOP, 0x33, 0x00, -/* sc=02 */ '!', '1', NOP, NOP, SET8|'1', SET8|'!', NOP, NOP, 0x33, 0x00, -/* sc=03 */ '"', '2', 0x00, 0x00, SET8|'2', SET8|'@', SET8|0x00, SET8|0x00, 0x00, 0x00, -/* sc=04 */ '\'', '3', NOP, NOP, SET8|'3', SET8|'#', NOP, NOP, 0x33, 0x00, -/* sc=05 */ '*', '4', NOP, NOP, SET8|'4', SET8|'$', NOP, NOP, 0x33, 0x00, -/* sc=06 */ ':', '5', NOP, NOP, SET8|'5', SET8|'%', NOP, NOP, 0x33, 0x00, -/* sc=07 */ ',', '6', 0x1E, 0x1E, SET8|'6', SET8|'^', SET8|0x1E, SET8|0x1E, 0x00, 0x00, -/* sc=08 */ '.', '7', NOP, NOP, SET8|'7', SET8|'&', NOP, NOP, 0x33, 0x00, -/* sc=09 */ ';', '8', NOP, NOP, SET8|'8', SET8|'*', NOP, NOP, 0x33, 0x00, -/* sc=0a */ '(', '9', NOP, NOP, SET8|'9', SET8|'(', NOP, NOP, 0x33, 0x00, -/* sc=0b */ ')', '0', NOP, NOP, SET8|'0', SET8|')', NOP, NOP, 0x33, 0x00, -/* sc=0c */ '-', '_', 0x1F, 0x1F, SET8|'-', SET8|'_', SET8|0x1F, SET8|0x1F, 0x00, 0x00, -/* sc=0d */ '=', '+', NOP, NOP, SET8|'=', SET8|'+', NOP, NOP, 0x33, 0x00, -/* sc=0e */ 0x08, 0x08, 0x7F, 0x7F, SET8|0x08, SET8|0x08, SET8|0x7F, SET8|0x7F, 0x00, 0x00, -/* sc=0f */ 0x09, BTAB, NOP, NOP, SET8|0x09, BTAB, NOP, NOP, 0x77, 0x00, -/* sc=10 */ 0xca, 0xea, 0x11, 0x11, SET8|'q', SET8|'Q', SET8|0x11, SET8|0x11, 0x00, 0x01, -/* sc=11 */ 0xc3, 0xe3, 0x17, 0x17, SET8|'w', SET8|'W', SET8|0x17, SET8|0x17, 0x00, 0x01, -/* sc=12 */ 0xd5, 0xf5, 0x05, 0x05, SET8|'e', SET8|'E', SET8|0x05, SET8|0x05, 0x00, 0x01, -/* sc=13 */ 0xcb, 0xeb, 0x12, 0x12, SET8|'r', SET8|'R', SET8|0x12, SET8|0x12, 0x00, 0x01, -/* sc=14 */ 0xc5, 0xe5, 0x14, 0x14, SET8|'t', SET8|'T', SET8|0x14, SET8|0x14, 0x00, 0x01, -/* sc=15 */ 0xce, 0xee, 0x19, 0x19, SET8|'y', SET8|'Y', SET8|0x19, SET8|0x19, 0x00, 0x01, -/* sc=16 */ 0xc7, 0xe7, 0x15, 0x15, SET8|'u', SET8|'U', SET8|0x15, SET8|0x15, 0x00, 0x01, -/* sc=17 */ 0xdb, 0xfb, 0x09, 0x09, SET8|'i', SET8|'I', SET8|0x09, SET8|0x09, 0x00, 0x01, -/* sc=18 */ 0xdd, 0xfd, 0x0F, 0x0F, SET8|'o', SET8|'O', SET8|0x0F, SET8|0x0F, 0x00, 0x01, -/* sc=19 */ 0xda, 0xfa, 0x10, 0x10, SET8|'p', SET8|'P', SET8|0x10, SET8|0x10, 0x00, 0x01, -/* sc=1a */ 0xc8, 0xe8, 0x1B, 0x1B, SET8|'[', SET8|'{', SET8|0x1B, SET8|0x1B, 0x00, 0x01, -/* sc=1b */ 0xdf, 0xff, 0x1D, 0x1D, SET8|']', SET8|'}', SET8|0x1D, SET8|0x1D, 0x00, 0x01, -/* sc=1c */ 0x0D, 0x0D, 0x0A, 0x0A, SET8|0x0D, SET8|0x0D, SET8|0x0A, SET8|0x0A, 0x00, 0x00, -/* sc=1d */ LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, 0xFF, 0x00, -/* sc=1e */ 0xc6, 0xe6, 0x01, 0x01, SET8|'a', SET8|'A', SET8|0x01, SET8|0x01, 0x00, 0x01, -/* sc=1f */ 0xd9, 0xf9, 0x13, 0x13, SET8|'s', SET8|'S', SET8|0x13, SET8|0x13, 0x00, 0x01, -/* sc=20 */ 0xd7, 0xf7, 0x04, 0x04, SET8|'d', SET8|'D', SET8|0x04, SET8|0x04, 0x00, 0x01, -/* sc=21 */ 0xc1, 0xe1, 0x06, 0x06, SET8|'f', SET8|'F', SET8|0x06, SET8|0x06, 0x00, 0x01, -/* sc=22 */ 0xd0, 0xf0, 0x07, 0x07, SET8|'g', SET8|'G', SET8|0x07, SET8|0x07, 0x00, 0x01, -/* sc=23 */ 0xd2, 0xf2, 0x08, 0x08, SET8|'h', SET8|'H', SET8|0x08, SET8|0x08, 0x00, 0x01, -/* sc=24 */ 0xcf, 0xef, 0x0A, 0x0A, SET8|'j', SET8|'J', SET8|0x0A, SET8|0x0A, 0x00, 0x01, -/* sc=25 */ 0xcc, 0xec, 0x0B, 0x0B, SET8|'k', SET8|'K', SET8|0x0B, SET8|0x0B, 0x00, 0x01, -/* sc=26 */ 0xc4, 0xe4, 0x0C, 0x0C, SET8|'l', SET8|'L', SET8|0x0C, SET8|0x0C, 0x00, 0x01, -/* sc=27 */ 0xd6, 0xf6, NOP, NOP, SET8|';', SET8|':', NOP, NOP, 0x33, 0x01, -/* sc=28 */ 0xdc, 0xfc, NOP, NOP, SET8|'\'', SET8|'"', NOP, NOP, 0x33, 0x01, -/* sc=29 */ 0xa3, 0xb3, NOP, NOP, SET8|'`', SET8|'~', NOP, NOP, 0x33, 0x01, -/* sc=2a */ LSH, LSH, LSH, LSH, LSH, LSH, LSH, LSH, 0xFF, 0x00, -/* sc=2b */ '\\', '|', 0x1C, 0x1C, SET8|'\\', SET8|'|', SET8|0x1C, SET8|0x1C, 0x00, 0x00, -/* sc=2c */ 0xd1, 0xf1, 0x1A, 0x1A, SET8|'z', SET8|'Z', SET8|0x1A, SET8|0x1A, 0x00, 0x01, -/* sc=2d */ 0xde, 0xfe, 0x18, 0x18, SET8|'x', SET8|'X', SET8|0x18, SET8|0x18, 0x00, 0x01, -/* sc=2e */ 0xd3, 0xf3, 0x03, 0x03, SET8|'c', SET8|'C', SET8|0x03, SET8|0x03, 0x00, 0x01, -/* sc=2f */ 0xcd, 0xed, 0x16, 0x16, SET8|'v', SET8|'V', SET8|0x16, SET8|0x16, 0x00, 0x01, -/* sc=30 */ 0xc9, 0xe9, 0x02, 0x02, SET8|'b', SET8|'B', SET8|0x02, SET8|0x02, 0x00, 0x01, -/* sc=31 */ 0xd4, 0xf4, 0x0E, 0x0E, SET8|'n', SET8|'N', SET8|0x0E, SET8|0x0E, 0x00, 0x01, -/* sc=32 */ 0xd8, 0xf8, 0x0D, 0x0D, SET8|'m', SET8|'M', SET8|0x0D, SET8|0x0D, 0x00, 0x01, -/* sc=33 */ 0xc2, 0xe2, NOP, NOP, SET8|',', SET8|'<', NOP, NOP, 0x33, 0x01, -/* sc=34 */ 0xc0, 0xe0, NOP, NOP, SET8|'.', SET8|'>', NOP, NOP, 0x33, 0x01, -/* sc=35 */ '/', '?', NOP, NOP, SET8|'/', SET8|'?', NOP, NOP, 0x33, 0x00, -/* sc=36 */ RSH, RSH, RSH, RSH, RSH, RSH, RSH, RSH, 0xFF, 0x00, -/* sc=37 */ '*', '*', 0x0A, 0x0A, SET8|'*', SET8|'*', SET8|0x0A, SET8|0x0A, 0x00, 0x00, -/* sc=38 */ LALT, LALT, LALT, LALT, LALT, LALT, LALT, LALT, 0xFF, 0x00, -/* sc=39 */ ' ', ' ', 0x00, ' ', SET8|' ', SET8|' ', SET8|' ', SET8|' ', 0x00, 0x00, -/* sc=3a */ ALK, CLK, CLK, CLK, CLK, CLK, CLK, CLK, 0xFF, 0x00, -/* sc=3b */ F( 1), F(13), F(25), F(37), S( 1), S(11), S( 1), S(11), 0xFF, 0x00, -/* sc=3c */ F( 2), F(14), F(26), F(38), S( 2), S(12), S( 2), S(12), 0xFF, 0x00, -/* sc=3d */ F( 3), F(15), F(27), F(39), S( 3), S(13), S( 3), S(13), 0xFF, 0x00, -/* sc=3e */ F( 4), F(16), F(28), F(40), S( 4), S(14), S( 4), S(14), 0xFF, 0x00, -/* sc=3f */ F( 5), F(17), F(29), F(41), S( 5), S(15), S( 5), S(15), 0xFF, 0x00, -/* sc=40 */ F( 6), F(18), F(30), F(42), S( 6), S(16), S( 6), S(16), 0xFF, 0x00, -/* sc=41 */ F( 7), F(19), F(31), F(43), S( 7), S( 7), S( 7), S( 7), 0xFF, 0x00, -/* sc=42 */ F( 8), F(20), F(32), F(44), S( 8), S( 8), S( 8), S( 8), 0xFF, 0x00, -/* sc=43 */ F( 9), F(21), F(33), F(45), S( 9), S( 9), S( 9), S( 9), 0xFF, 0x00, -/* sc=44 */ F(10), F(22), F(34), F(46), S(10), S(10), S(10), S(10), 0xFF, 0x00, -/* sc=45 */ NLK, NLK, NLK, NLK, NLK, NLK, NLK, NLK, 0xFF, 0x00, -/* sc=46 */ SLK, SLK, SLK, SLK, SLK, SLK, SLK, SLK, 0xFF, 0x00, -/* sc=47 */ F(49), '7', '7', '7', SET8|'7', SET8|'7', SET8|'7', SET8|'7', 0x80, 0x02, -/* sc=48 */ F(50), '8', '8', '8', SET8|'8', SET8|'8', SET8|'8', SET8|'8', 0x80, 0x02, -/* sc=49 */ F(51), '9', '9', '9', SET8|'9', SET8|'9', SET8|'9', SET8|'9', 0x80, 0x02, -/* sc=4a */ F(52), '-', '-', '-', SET8|'-', SET8|'-', SET8|'-', SET8|'-', 0x80, 0x02, -/* sc=4b */ F(53), '4', '4', '4', SET8|'4', SET8|'4', SET8|'4', SET8|'4', 0x80, 0x02, -/* sc=4c */ F(54), '5', '5', '5', SET8|'5', SET8|'5', SET8|'5', SET8|'5', 0x80, 0x02, -/* sc=4d */ F(55), '6', '6', '6', SET8|'6', SET8|'6', SET8|'6', SET8|'6', 0x80, 0x02, -/* sc=4e */ F(56), '+', '+', '+', SET8|'+', SET8|'+', SET8|'+', SET8|'+', 0x80, 0x02, -/* sc=4f */ F(57), '1', '1', '1', SET8|'1', SET8|'1', SET8|'1', SET8|'1', 0x80, 0x02, -/* sc=50 */ F(58), '2', '2', '2', SET8|'2', SET8|'2', SET8|'2', SET8|'2', 0x80, 0x02, -/* sc=51 */ F(59), '3', '3', '3', SET8|'3', SET8|'3', SET8|'3', SET8|'3', 0x80, 0x02, -/* sc=52 */ F(60), '0', '0', '0', SET8|'0', SET8|'0', SET8|'0', SET8|'0', 0x80, 0x02, -/* sc=53 */ 0x7F, '.', '.', '.', SET8|'.', SET8|'.', RBT, RBT, 0x03, 0x02, -/* sc=54 */ ALK, ALK, ALK, ALK, ALK, ALK, ALK, ALK, 0xFF, 0x00, -/* sc=55 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=56 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=57 */ F(11), F(23), F(35), F(47), S(11), S(11), S(11), S(11), 0xFF, 0x00, -/* sc=58 */ F(12), F(24), F(36), F(48), S(12), S(12), S(12), S(12), 0xFF, 0x00, -/* sc=59 */ 0x0D, 0x0D, 0x0A, 0x0A, SET8|0x0D, SET8|0x0D, SET8|0x0A, SET8|0x0A, 0x00, 0x00, -/* sc=5a */ RCTR, RCTR, RCTR, RCTR, RCTR, RCTR, RCTR, RCTR, 0xFF, 0x00, -/* sc=5b */ '/', '/', NOP, NOP, SET8|'/', SET8|'/', NOP, NOP, 0x33, 0x00, -/* sc=5c */ NEXT, NOP, DBG, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=5d */ RALT, RALT, RALT, RALT, RALT, RALT, RALT, RALT, 0xFF, 0x00, -/* sc=5e */ F(49), F(49), F(49), F(49), F(49), F(49), F(49), F(49), 0xFF, 0x00, -/* sc=5f */ F(50), F(50), F(50), F(50), F(50), F(50), F(50), F(50), 0xFF, 0x00, -/* sc=60 */ F(51), F(51), F(51), F(51), F(51), F(51), F(51), F(51), 0xFF, 0x00, -/* sc=61 */ F(53), F(53), F(53), F(53), F(53), F(53), F(53), F(53), 0xFF, 0x00, -/* sc=62 */ F(55), F(55), F(55), F(55), F(55), F(55), F(55), F(55), 0xFF, 0x00, -/* sc=63 */ F(57), F(57), F(57), F(57), F(57), F(57), F(57), F(57), 0xFF, 0x00, -/* sc=64 */ F(58), F(58), F(58), F(58), F(58), F(58), F(58), F(58), 0xFF, 0x00, -/* sc=65 */ F(59), F(59), F(59), F(59), F(59), F(59), F(59), F(59), 0xFF, 0x00, -/* sc=66 */ F(60), F(60), F(60), F(60), F(60), F(60), F(60), F(60), 0xFF, 0x00, -/* sc=67 */ F(61), F(61), F(61), F(61), F(61), F(61), RBT, F(61), 0xFF, 0x00, -/* sc=68 */ SLK, SLK, SLK, SLK, SLK, SLK, SLK, SLK, 0xFF, 0x00, -/* sc=69 */ F(62), F(62), F(62), F(62), F(62), F(62), F(62), F(62), 0xFF, 0x00, -/* sc=6a */ F(63), F(63), F(63), F(63), F(63), F(63), F(63), F(63), 0xFF, 0x00, -/* sc=6b */ F(64), F(64), F(64), F(64), F(64), F(64), F(64), F(64), 0xFF, 0x00, -}; - -#endif - -#if !defined(DKKEYMAP) && !defined(UKKEYMAP) && !defined(GRKEYMAP) && !defined(SWKEYMAP) && !defined(RUKEYMAP) && !defined(PC98) -static keymap_t key_map = { 0x6C, /* US iso8859 keymap */ -/* alt - * scan cntrl alt alt cntrl - * code base shift cntrl shift alt shift cntrl shift spcl flgs - * --------------------------------------------------------------------------- - */ -/* sc=00 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=01 */ 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, DBG, 0x1B, 0x02, 0x00, -/* sc=02 */ '1', '!', NOP, NOP, '1', '!', NOP, NOP, 0x33, 0x00, -/* sc=03 */ '2', '@', 0x00, 0x00, '2', '@', 0x00, 0x00, 0x00, 0x00, -/* sc=04 */ '3', '#', NOP, NOP, '3', '#', NOP, NOP, 0x33, 0x00, -/* sc=05 */ '4', '$', NOP, NOP, '4', '$', NOP, NOP, 0x33, 0x00, -/* sc=06 */ '5', '%', NOP, NOP, '5', '%', NOP, NOP, 0x33, 0x00, -/* sc=07 */ '6', '^', 0x1E, 0x1E, '6', '^', 0x1E, 0x1E, 0x00, 0x00, -/* sc=08 */ '7', '&', NOP, NOP, '7', '&', NOP, NOP, 0x33, 0x00, -/* sc=09 */ '8', '*', NOP, NOP, '8', '*', NOP, NOP, 0x33, 0x00, -/* sc=0a */ '9', '(', NOP, NOP, '9', '(', NOP, NOP, 0x33, 0x00, -/* sc=0b */ '0', ')', NOP, NOP, '0', ')', NOP, NOP, 0x33, 0x00, -/* sc=0c */ '-', '_', 0x1F, 0x1F, '-', '_', 0x1F, 0x1F, 0x00, 0x00, -/* sc=0d */ '=', '+', NOP, NOP, '=', '+', NOP, NOP, 0x33, 0x00, -/* sc=0e */ 0x08, 0x08, 0x7F, 0x7F, 0x08, 0x08, 0x7F, 0x7F, 0x00, 0x00, -/* sc=0f */ 0x09, BTAB, NOP, NOP, 0x09, BTAB, NOP, NOP, 0x77, 0x00, -/* sc=10 */ 'q', 'Q', 0x11, 0x11, 'q', 'Q', 0x11, 0x11, 0x00, 0x01, -/* sc=11 */ 'w', 'W', 0x17, 0x17, 'w', 'W', 0x17, 0x17, 0x00, 0x01, -/* sc=12 */ 'e', 'E', 0x05, 0x05, 'e', 'E', 0x05, 0x05, 0x00, 0x01, -/* sc=13 */ 'r', 'R', 0x12, 0x12, 'r', 'R', 0x12, 0x12, 0x00, 0x01, -/* sc=14 */ 't', 'T', 0x14, 0x14, 't', 'T', 0x14, 0x14, 0x00, 0x01, -/* sc=15 */ 'y', 'Y', 0x19, 0x19, 'y', 'Y', 0x19, 0x19, 0x00, 0x01, -/* sc=16 */ 'u', 'U', 0x15, 0x15, 'u', 'U', 0x15, 0x15, 0x00, 0x01, -/* sc=17 */ 'i', 'I', 0x09, 0x09, 'i', 'I', 0x09, 0x09, 0x00, 0x01, -/* sc=18 */ 'o', 'O', 0x0F, 0x0F, 'o', 'O', 0x0F, 0x0F, 0x00, 0x01, -/* sc=19 */ 'p', 'P', 0x10, 0x10, 'p', 'P', 0x10, 0x10, 0x00, 0x01, -/* sc=1a */ '[', '{', 0x1B, 0x1B, '[', '{', 0x1B, 0x1B, 0x00, 0x00, -/* sc=1b */ ']', '}', 0x1D, 0x1D, ']', '}', 0x1D, 0x1D, 0x00, 0x00, -/* sc=1c */ 0x0D, 0x0D, 0x0A, 0x0A, 0x0D, 0x0D, 0x0A, 0x0A, 0x00, 0x00, -/* sc=1d */ LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, 0xFF, 0x00, -/* sc=1e */ 'a', 'A', 0x01, 0x01, 'a', 'A', 0x01, 0x01, 0x00, 0x01, -/* sc=1f */ 's', 'S', 0x13, 0x13, 's', 'S', 0x13, 0x13, 0x00, 0x01, -/* sc=20 */ 'd', 'D', 0x04, 0x04, 'd', 'D', 0x04, 0x04, 0x00, 0x01, -/* sc=21 */ 'f', 'F', 0x06, 0x06, 'f', 'F', 0x06, 0x06, 0x00, 0x01, -/* sc=22 */ 'g', 'G', 0x07, 0x07, 'g', 'G', 0x07, 0x07, 0x00, 0x01, -/* sc=23 */ 'h', 'H', 0x08, 0x08, 'h', 'H', 0x08, 0x08, 0x00, 0x01, -/* sc=24 */ 'j', 'J', 0x0A, 0x0A, 'j', 'J', 0x0A, 0x0A, 0x00, 0x01, -/* sc=25 */ 'k', 'K', 0x0B, 0x0B, 'k', 'K', 0x0B, 0x0B, 0x00, 0x01, -/* sc=26 */ 'l', 'L', 0x0C, 0x0C, 'l', 'L', 0x0C, 0x0C, 0x00, 0x01, -/* sc=27 */ ';', ':', NOP, NOP, ';', ':', NOP, NOP, 0x33, 0x00, -/* sc=28 */ '\'', '"', NOP, NOP, '\'', '"', NOP, NOP, 0x33, 0x00, -/* sc=29 */ '`', '~', NOP, NOP, '`', '~', NOP, NOP, 0x33, 0x00, -/* sc=2a */ LSH, LSH, LSH, LSH, LSH, LSH, LSH, LSH, 0xFF, 0x00, -/* sc=2b */ '\\', '|', 0x1C, 0x1C, '\\', '|', 0x1C, 0x1C, 0x00, 0x00, -/* sc=2c */ 'z', 'Z', 0x1A, 0x1A, 'z', 'Z', 0x1A, 0x1A, 0x00, 0x01, -/* sc=2d */ 'x', 'X', 0x18, 0x18, 'x', 'X', 0x18, 0x18, 0x00, 0x01, -/* sc=2e */ 'c', 'C', 0x03, 0x03, 'c', 'C', 0x03, 0x03, 0x00, 0x01, -/* sc=2f */ 'v', 'V', 0x16, 0x16, 'v', 'V', 0x16, 0x16, 0x00, 0x01, -/* sc=30 */ 'b', 'B', 0x02, 0x02, 'b', 'B', 0x02, 0x02, 0x00, 0x01, -/* sc=31 */ 'n', 'N', 0x0E, 0x0E, 'n', 'N', 0x0E, 0x0E, 0x00, 0x01, -/* sc=32 */ 'm', 'M', 0x0D, 0x0D, 'm', 'M', 0x0D, 0x0D, 0x00, 0x01, -/* sc=33 */ ',', '<', NOP, NOP, ',', '<', NOP, NOP, 0x33, 0x00, -/* sc=34 */ '.', '>', NOP, NOP, '.', '>', NOP, NOP, 0x33, 0x00, -/* sc=35 */ '/', '?', NOP, NOP, '/', '?', NOP, NOP, 0x33, 0x00, -/* sc=36 */ RSH, RSH, RSH, RSH, RSH, RSH, RSH, RSH, 0xFF, 0x00, -/* sc=37 */ '*', '*', 0x0A, 0x0A, '*', '*', 0x0A, 0x0A, 0x33, 0x00, -/* sc=38 */ LALT, LALT, LALT, LALT, LALT, LALT, LALT, LALT, 0xFF, 0x00, -/* sc=39 */ ' ', ' ', 0x00, ' ', ' ', ' ', SUSP, ' ', 0x02, 0x00, -/* sc=3a */ CLK, CLK, CLK, CLK, CLK, CLK, CLK, CLK, 0xFF, 0x00, -/* sc=3b */ F( 1), F(13), F(25), F(37), S( 1), S(11), S( 1), S(11), 0xFF, 0x00, -/* sc=3c */ F( 2), F(14), F(26), F(38), S( 2), S(12), S( 2), S(12), 0xFF, 0x00, -/* sc=3d */ F( 3), F(15), F(27), F(39), S( 3), S(13), S( 3), S(13), 0xFF, 0x00, -/* sc=3e */ F( 4), F(16), F(28), F(40), S( 4), S(14), S( 4), S(14), 0xFF, 0x00, -/* sc=3f */ F( 5), F(17), F(29), F(41), S( 5), S(15), S( 5), S(15), 0xFF, 0x00, -/* sc=40 */ F( 6), F(18), F(30), F(42), S( 6), S(16), S( 6), S(16), 0xFF, 0x00, -/* sc=41 */ F( 7), F(19), F(31), F(43), S( 7), S( 7), S( 7), S( 7), 0xFF, 0x00, -/* sc=42 */ F( 8), F(20), F(32), F(44), S( 8), S( 8), S( 8), S( 8), 0xFF, 0x00, -/* sc=43 */ F( 9), F(21), F(33), F(45), S( 9), S( 9), S( 9), S( 9), 0xFF, 0x00, -/* sc=44 */ F(10), F(22), F(34), F(46), S(10), S(10), S(10), S(10), 0xFF, 0x00, -/* sc=45 */ NLK, NLK, NLK, NLK, NLK, NLK, NLK, NLK, 0xFF, 0x00, -/* sc=46 */ SLK, SLK, SLK, SLK, SLK, SLK, SLK, SLK, 0xFF, 0x00, -/* sc=47 */ F(49), '7', '7', '7', '7', '7', '7', '7', 0x80, 0x02, -/* sc=48 */ F(50), '8', '8', '8', '8', '8', '8', '8', 0x80, 0x02, -/* sc=49 */ F(51), '9', '9', '9', '9', '9', '9', '9', 0x80, 0x02, -/* sc=4a */ F(52), '-', '-', '-', '-', '-', '-', '-', 0x80, 0x02, -/* sc=4b */ F(53), '4', '4', '4', '4', '4', '4', '4', 0x80, 0x02, -/* sc=4c */ F(54), '5', '5', '5', '5', '5', '5', '5', 0x80, 0x02, -/* sc=4d */ F(55), '6', '6', '6', '6', '6', '6', '6', 0x80, 0x02, -/* sc=4e */ F(56), '+', '+', '+', '+', '+', '+', '+', 0x80, 0x02, -/* sc=4f */ F(57), '1', '1', '1', '1', '1', '1', '1', 0x80, 0x02, -/* sc=50 */ F(58), '2', '2', '2', '2', '2', '2', '2', 0x80, 0x02, -/* sc=51 */ F(59), '3', '3', '3', '3', '3', '3', '3', 0x80, 0x02, -/* sc=52 */ F(60), '0', '0', '0', '0', '0', '0', '0', 0x80, 0x02, -/* sc=53 */ 0x7F, '.', '.', '.', '.', '.', RBT, RBT, 0x03, 0x02, -/* sc=54 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=55 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=56 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=57 */ F(11), F(23), F(35), F(47), S(11), S(11), S(11), S(11), 0xFF, 0x00, -/* sc=58 */ F(12), F(24), F(36), F(48), S(12), S(12), S(12), S(12), 0xFF, 0x00, -/* sc=59 */ 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x00, 0x00, -/* sc=5a */ RCTR, RCTR, RCTR, RCTR, RCTR, RCTR, RCTR, RCTR, 0xFF, 0x00, -/* sc=5b */ '/', '/', '/', '/', '/', '/', '/', '/', 0x00, 0x00, -/* sc=5c */ NEXT, NOP, DBG, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, -/* sc=5d */ RALT, RALT, RALT, RALT, RALT, RALT, RALT, RALT, 0xFF, 0x00, -/* sc=5e */ F(49), F(49), F(49), F(49), F(49), F(49), F(49), F(49), 0xFF, 0x00, -/* sc=5f */ F(50), F(50), F(50), F(50), F(50), F(50), F(50), F(50), 0xFF, 0x00, -/* sc=60 */ F(51), F(51), F(51), F(51), F(51), F(51), F(51), F(51), 0xFF, 0x00, -/* sc=61 */ F(53), F(53), F(53), F(53), F(53), F(53), F(53), F(53), 0xFF, 0x00, -/* sc=62 */ F(55), F(55), F(55), F(55), F(55), F(55), F(55), F(55), 0xFF, 0x00, -/* sc=63 */ F(57), F(57), F(57), F(57), F(57), F(57), F(57), F(57), 0xFF, 0x00, -/* sc=64 */ F(58), F(58), F(58), F(58), F(58), F(58), F(58), F(58), 0xFF, 0x00, -/* sc=65 */ F(59), F(59), F(59), F(59), F(59), F(59), F(59), F(59), 0xFF, 0x00, -/* sc=66 */ F(60), F(60), F(60), F(60), F(60), F(60), F(60), F(60), 0xFF, 0x00, -/* sc=67 */ F(61), F(61), F(61), F(61), F(61), F(61), RBT, F(61), 0xFF, 0x00, -/* sc=68 */ SLK, SLK, SLK, SLK, SLK, SLK, SLK, SLK, 0xFF, 0x00, -/* sc=69 */ F(62), F(62), F(62), F(62), F(62), F(62), F(62), F(62), 0xFF, 0x00, -/* sc=6a */ F(63), F(63), F(63), F(63), F(63), F(63), F(63), F(63), 0xFF, 0x00, -/* sc=6b */ F(64), F(64), F(64), F(64), F(64), F(64), F(64), F(64), 0xFF, 0x00, -}; - -#endif - -static fkeytab_t fkey_tab[96] = { -/* 01-04 */ {"\033[M", 3}, {"\033[N", 3}, {"\033[O", 3}, {"\033[P", 3}, -/* 05-08 */ {"\033[Q", 3}, {"\033[R", 3}, {"\033[S", 3}, {"\033[T", 3}, -/* 09-12 */ {"\033[U", 3}, {"\033[V", 3}, {"\033[W", 3}, {"\033[X", 3}, -/* 13-16 */ {"\033[Y", 3}, {"\033[Z", 3}, {"\033[a", 3}, {"\033[b", 3}, -/* 17-20 */ {"\033[c", 3}, {"\033[d", 3}, {"\033[e", 3}, {"\033[f", 3}, -/* 21-24 */ {"\033[g", 3}, {"\033[h", 3}, {"\033[i", 3}, {"\033[j", 3}, -/* 25-28 */ {"\033[k", 3}, {"\033[l", 3}, {"\033[m", 3}, {"\033[n", 3}, -/* 29-32 */ {"\033[o", 3}, {"\033[p", 3}, {"\033[q", 3}, {"\033[r", 3}, -/* 33-36 */ {"\033[s", 3}, {"\033[t", 3}, {"\033[u", 3}, {"\033[v", 3}, -/* 37-40 */ {"\033[w", 3}, {"\033[x", 3}, {"\033[y", 3}, {"\033[z", 3}, -/* 41-44 */ {"\033[@", 3}, {"\033[[", 3}, {"\033[\\",3}, {"\033[]", 3}, -/* 45-48 */ {"\033[^", 3}, {"\033[_", 3}, {"\033[`", 3}, {"\033[{", 3}, -/* 49-52 */ {"\033[H", 3}, {"\033[A", 3}, {"\033[I", 3}, {"-" , 1}, -/* 53-56 */ {"\033[D", 3}, {"\033[E", 3}, {"\033[C", 3}, {"+" , 1}, -/* 57-60 */ {"\033[F", 3}, {"\033[B", 3}, {"\033[G", 3}, {"\033[L", 3}, -/* 61-64 */ {"\177", 1}, {"\033[J", 3}, {"\033[~", 3}, {"\033[}", 3}, -/* 65-68 */ {"", 0} , {"", 0} , {"", 0} , {"", 0} , -/* 69-72 */ {"", 0} , {"", 0} , {"", 0} , {"", 0} , -/* 73-76 */ {"", 0} , {"", 0} , {"", 0} , {"", 0} , -/* 77-80 */ {"", 0} , {"", 0} , {"", 0} , {"", 0} , -/* 81-84 */ {"", 0} , {"", 0} , {"", 0} , {"", 0} , -/* 85-88 */ {"", 0} , {"", 0} , {"", 0} , {"", 0} , -/* 89-92 */ {"", 0} , {"", 0} , {"", 0} , {"", 0} , -/* 93-96 */ {"", 0} , {"", 0} , {"", 0} , {"", 0} -}; diff --git a/sys/pc98/pc98/matcd/TODO b/sys/pc98/pc98/matcd/TODO deleted file mode 100644 index 138f470..0000000 --- a/sys/pc98/pc98/matcd/TODO +++ /dev/null @@ -1,42 +0,0 @@ -Things to do for the matcd driver 4-Jul-95 - -1. Someone wants to switch all drivers from disklabel and - its assorted mechanisms over to disk slicing and its mechanisms, - but I was unable to find any useful documentation on how to - implement the changes for a read-only, single-partition, - removable (ie, partition can change size) device. - So this will have to wait until after 2.1. - -2. Support for reading R-W subcodes while playing audio. This would be - useful if you have any CD+G or CD+MIDI discs, but the demand for this - is pretty low, unless you like Karaoke. Someone will also have to - write a CD+G viewer for X. The code for the driver to add this is - pretty minor but there aren't any precedents on how to handle the - data transfer to the application. - -3. Support for reading the ISBN and UPC labels. The ioctl structures - for these appear to be defined but no other driver seems to do this. - -4. Multi-session support. There are two forms of this; what - Philips defined and what Kodak uses. This will be quite - complicated and will probably require changes in the filesystem - layer. The drive support for Kodak multi-session is known to work. - -5. Multiple data tracks. My vision here was to add an ioctl - that caused a track offset to be inserted into block requests, - effectively shifting the base to the specified track. Very - easy to add but not a big deal since I have only two discs - in my collection that have multiple data tracks and I mastered - one of them. - -6. A curses-based CD-Player app (ie, not X). I will probably do this - mainly for its value as a debugging tool. It was pretty annoying - not finding a single application that actually issued all the - defined ioctls, let alone any new ones. - -If you feel the urge to work on one or more of these remaining items, -please contact the author first at bsdmail@nemesis.lonestar.org -to make sure the work hasn't already been done or started. - - Frank Durda IV - diff --git a/sys/pc98/pc98/matcd/creative.h b/sys/pc98/pc98/matcd/creative.h deleted file mode 100644 index 72a12ad..0000000 --- a/sys/pc98/pc98/matcd/creative.h +++ /dev/null @@ -1,142 +0,0 @@ -/*creative.h------------------------------------------------------------------- - - Matsushita(Panasonic) / Creative CD-ROM Driver (matcd) - Authored by Frank Durda IV - - Copyright 1994, 1995 Frank Durda IV. All rights reserved. - "FDIV" is a trademark of Frank Durda IV. - - - Redistribution and use in source and binary forms, with or - without modification, are permitted provided that the following - conditions are met: - 1. Redistributions of source code must retain the above copyright - notice positioned at the very beginning of this file without - modification, all copyright strings, all related programming - codes that display the copyright strings, this list of - conditions and the following disclaimer. - 2. Redistributions in binary form must contain all copyright strings - and related programming code that display the copyright strings. - 3. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - 4. All advertising materials mentioning features or use of this - software must display the following acknowledgement: - "The Matsushita/Panasonic CD-ROM driver was developed - by Frank Durda IV for use with "FreeBSD" and similar - operating systems." - "Similar operating systems" includes mainly non-profit oriented - systems for research and education, including but not restricted - to "NetBSD", "386BSD", and "Mach" (by CMU). The wording of the - acknowledgement (in electronic form or printed text) may not be - changed without permission from the author. - 5. Absolutely no warranty of function, fitness or purpose is made - by the author Frank Durda IV. - 6. Neither the name of the author nor the name "FreeBSD" may - be used to endorse or promote products derived from this software - without specific prior written permission. - (The author can be reached at bsdmail@nemesis.lonestar.org) - 7. The product containing this software must meet all of these - conditions even if it is unsupported, not a complete system - and/or does not contain compiled code. - 8. These conditions will be in force for the full life of the - copyright. - 9. If all the above conditions are met, modifications to other - parts of this file may be freely made, although any person - or persons making changes do not receive the right to add their - name or names to the copyright strings and notices in this - software. Persons making changes are encouraged to insert edit - history in matcd.c and to put your name and details of the - change there. - 10. You must have prior written permission from the author to - deviate from these terms. - - Vendors who produce product(s) containing this code are encouraged - (but not required) to provide copies of the finished product(s) to - the author and to correspond with the author about development - activity relating to this code. Donations of development hardware - and/or software are also welcome. (This is one of the faster ways - to get a driver developed for a device.) - - THIS SOFTWARE IS PROVIDED BY THE DEVELOPER(S) ``AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE DEVELOPER(S) BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - ------No changes are allowed above this line------------------------------------ - -See matcd.c for Edit History - - These are the I/O port mapping offsets and bit assignments used - by Creative Labs in their implementation of the host interface for - the Matsushita CD-ROM drive. These may be different in the adapter - cards (including sound cards) made by other vendors. - It is unknown if the Creative interface is based on a reference design - provided by Matsushita (other interface vendors would similar or - identical if this was the case). - - The drive is actually capable of some things that the Creative - interface doesn't implement, such as DMA and interrupts. - - See matcd.h for defines related to the Matsushita drive itself. -*/ - - -/* Creative Labs (and compatible) I/O port mapping offsets -*/ - -#define NUMPORTS 4 /*Four ports are decoded by the i/f*/ - -#define CMD 0 /*Write - commands*/ -#define DATA 0 /*Read - data/status from drive*/ -#ifdef PC98 -#define PHASE 0x100 /*Write - switch between data/status*/ -#define STATUS 0x100 /*Read - bus status */ -#define RESET 0x200 /*Write - reset all attached drives*/ -#define ALTDATA 0x200 /*<20>Read - data on non Creative bds.*/ -#define SELECT 0x300 /*Write - drive select*/ -#else /* !PC98 */ -#define PHASE 1 /*Write - switch between data/status*/ -#define STATUS 1 /*Read - bus status*/ -#define RESET 2 /*Write - reset all attached drives*/ - /*Any value written will reset*/ -#define ALTDATA 2 /*<20>Read - data on non Creative bds.*/ -#define SELECT 3 /*Write - drive select*/ -#endif /*PC98*/ - -/* Creative PHASE port bit assignments -*/ - -#define PHASENA 1 /*Access data bytes instead of status*/ - - -/* Creative STATUS port register bits -*/ - -#define DTEN 2 /*When low, in data xfer phase*/ -#define STEN 4 /*When low, in status phase*/ -#define TEST 1 /*Function is unknown*/ - - -/* Creative drive SELECT port bit assignments - Note that in the Creative interface, DS0==Bit 1 and - DS1==Bit 0 (DS is Drive Select). -*/ - -#define CRDRIVE0 0x00 -#define CRDRIVE1 0x02 -#define CRDRIVE2 0x01 -#define CRDRIVE3 0x03 - -/*End of creative.h*/ - - diff --git a/sys/pc98/pc98/matcd/matcd.c b/sys/pc98/pc98/matcd/matcd.c deleted file mode 100644 index a8b1eb4..0000000 --- a/sys/pc98/pc98/matcd/matcd.c +++ /dev/null @@ -1,2670 +0,0 @@ -/*matcd.c-------------------------------------------------------------------- - - Matsushita(Panasonic) / Creative CD-ROM Driver (matcd) - Authored by Frank Durda IV - - Copyright 1994, 1995 Frank Durda IV. All rights reserved. - "FDIV" is a trademark of Frank Durda IV. - - - Redistribution and use in source and binary forms, with or - without modification, are permitted provided that the following - conditions are met: - 1. Redistributions of source code must retain the above copyright - notice positioned at the very beginning of this file without - modification, all copyright strings, all related programming - codes that display the copyright strings, this list of - conditions and the following disclaimer. - 2. Redistributions in binary form must contain all copyright strings - and related programming code that display the copyright strings. - 3. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - 4. All advertising materials mentioning features or use of this - software must display the following acknowledgement: - "The Matsushita/Panasonic CD-ROM driver was developed - by Frank Durda IV for use with "FreeBSD" and similar - operating systems." - "Similar operating systems" includes mainly non-profit oriented - systems for research and education, including but not restricted - to "NetBSD", "386BSD", and "Mach" (by CMU). The wording of the - acknowledgement (in electronic form or printed text) may not be - changed without permission from the author. - 5. Absolutely no warranty of function, fitness or purpose is made - by the author Frank Durda IV. - 6. Neither the name of the author nor the name "FreeBSD" may - be used to endorse or promote products derived from this software - without specific prior written permission. - (The author can be reached at bsdmail@nemesis.lonestar.org) - 7. The product containing this software must meet all of these - conditions even if it is unsupported, not a complete system - and/or does not contain compiled code. - 8. These conditions will be in force for the full life of the - copyright. - 9. If all the above conditions are met, modifications to other - parts of this file may be freely made, although any person - or persons making changes do not receive the right to add their - name or names to the copyright strings and notices in this - software. Persons making changes are encouraged to insert edit - history in matcd.c and to put your name and details of the - change there. - 10. You must have prior written permission from the author to - deviate from these terms. - - Vendors who produce product(s) containing this code are encouraged - (but not required) to provide copies of the finished product(s) to - the author and to correspond with the author about development - activity relating to this code. Donations of development hardware - and/or software are also welcome. (This is one of the faster ways - to get a driver developed for a device.) - - THIS SOFTWARE IS PROVIDED BY THE DEVELOPER(S) ``AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE DEVELOPER(S) BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - ------------------------------------------------------------------------------ -Dedicated to: My family, my Grandfather, - and Max, my Golden Retriever - -Thanks to: Jordon Hubbard (jkh) for getting me ramped-up to 2.x system - quickly enough to make the 2.1 release. He put up with - plenty of silly questions and might get the post of - ambassador some day. - -and The people who donated equipment and other material to make - development of this driver possible. Donations and - sponsors for projects are appreciated. - - ------No changes are allowed above this line------------------------------------ - -Edit History - (should be in sync with any source control log entries) - - Never seen one of these before? Ok, here is how it works. - Every time you change the code, you increment the edit number, - that number over there in the <%d> and in the (%d) in the - version string. You never set this number lower than it is. - Near, or preferably on lines that change, insert the edit - number. If there is a number there already, you can replace it - with a newer one. This makes searches for code changes very fast. - - In the edit history, start with the edit number, and a good - description of what changes were made. Then follow it with - the date, your name and an EMAIL address where you can be reached. - - Please follow this practice; it helps leave understandable code in - your wake. - - FYI, you have major and minor release codes. Major releases numbered - 1 thru n. Major feature additions should get a new major release - number. Minor releases start with a null and then letters - A thru Z. So 3A(456) is Major release 3, Minor release 1, - Edit 456 (in Microsoft-ese that would be 03.01.456), and 5(731) - is Major release 5, Minor release 0, Edit 731. Typically only the - author will change the major and minor release codes in small - projects. - - EDIT edit Edit HISTORY history History - -<1> This initial version is to get basic filesystem I/O working - using the SoundBlaster 16 interface. The stand-alone adapter - card doesn't work yet. - December 1994 Frank Durda IV bsdmail@nemesis.lonestar.org - -<2> Corrections to resolve a race condition when multiple drives - on the same controller was active. Fixed drive 1 & 2 swap - problem. See selectdrive(). - 21-Jan-95 Frank Durda IV bsdmail@nemesis.lonestar.org - -<3> Added automatic probing and support for all Creative Labs sound - cards with the Creative/Panasonic interface and the stand-alone - interface adapters. See AUTOHUNT and FULLCONFIG conditionals - for more information. - 21-Jan-95 Frank Durda IV bsdmail@nemesis.lonestar.org - -<4> Rebundled debug conditionals. - 14-Feb-95 Frank Durda IV bsdmail@nemesis.lonestar.org - -<5> Changes needed to work on FreeBSD 2.1. Also added draincmd - since some conditions cause the drive to produce surprise data. - See setmode and draincmd - 19-Feb-95 Frank Durda IV bsdmail@nemesis.lonestar.org - -<6> Got rid of some redundant error code by creating chk_error(). - Also built a nice generic bus-lock function. - 20-Feb-95 Frank Durda IV bsdmail@nemesis.lonestar.org - -<7> Improved comments, general structuring. - Fixed a problem with disc eject not working if LOCKDRIVE was set. - Apparently the drive will reject an EJECT command if the drive - is LOCKED. - 21-Feb-95 Frank Durda IV bsdmail@nemesis.lonestar.org - -Edit number code marking begins here - earlier edits were during development. - -<8> Final device name selected and actually made to compile under - >2.0. For newer systems, it is "matcd", for older it is "mat". - 24-Feb-95 Frank Durda IV bsdmail@nemesis.lonestar.org - -<9> Added some additional disk-related ioctl functions that didn't - make it into earlier versions. - 26-Feb-95 Frank Durda IV bsdmail@nemesis.lonestar.org - -<10> Updated some conditionals so the code will compile under - 1.1.5.1, although this is not the supported platform. - Also found that some other devices probe code was changing the - settings for the port 0x302 debug board, so added code to set it - to a sane state before we use it. - 26-Feb-95 Frank Durda IV bsdmail@nemesis.lonestar.org - -<11> The Copyright and Use statement has been replaced in all files - with a new version. - 1-Mar-95 Frank Durda IV bsdmail@nemesis.lonestar.org - -<12> Added ioctls having to do with audio volume, routing and playback - speed. Also added some code I think is for dynamic loading. - 12-Mar-95 Frank Durda IV bsdmail@nemesis.lonestar.org - -<13> Added ioctls to return TOC headers and entries. - 19-Mar-95 Frank Durda IV bsdmail@nemesis.lonestar.org - -<14> More ioctls to finish out general audio support and some clean-up. - Also fixed a bug in open where CD label information would not - always be cleared after a disc change. - - Added a check to block attempts to resume audio if already playing. - The resulting sound is a cross between Kryten and Max Headroom. - But, if you *want* this "feature", enable #define KRYTEN - in options.h. - - So it is not BSD-ish enough, eh? What, too many comments? :-) - 21-Mar-95 Frank Durda IV bsdmail@nemesis.lonestar.org - -<15> LOCKDRIVE has been modified so that a new series of minor - numbers are created. When these are opened, the selected - drive will have its door locked and the device must be completely - closed to unlock the media. The EJECT ioctl will be refused - when the drive is locked this way. This is useful for - servers and other places where the media needs to remain in the - drive. Bit 7 of the minor number controls locking. - - As of this edit, the code compiles with no warnings with -Wall set. - 22-Mar-95 Frank Durda IV bsdmail@nemesis.lonestar.org - -<16> Added a new check in the probe code that looks for the drive - interface being in an idle state after issuing a reset. If this - isn't the case, then the device at this location isn't a - Matsushita CD-ROM drive. This will prevent hangs in draincmd later. - Added the tray close ioctl. This required modifications to open - to allow the character devices to be "partially" opened so that - the close ioctl could be issued when the open would otherwise fail. - Close also delays slightly after completing because the drive - doesn't update its disc and media status instantly. - Also created the capability ioctl that lets an application find out - up front what things a drive can do. - Fixed a global spelling error. - Changed matcddriver structure to simply say "matcd". The original - string "matcd interface " broke the kernel -c boot mechanism. - Updated the #includes in response to a complaint in first release. - Updated and tested conditionals so that driver will still compile - under FreeBSD 1.1.5.1 as well as 2.0 and early 2.1. - 4-Apr-95 Frank Durda IV bsdmail@nemesis.lonestar.org - -<17> The function matcd_toc_entries which is executed in response to - the CDIOREADTOCENTRYS ioctl didn't cope with programs that only - requested part of the TOC. This change is based on code submitted - by Doug Robson (dfr@render.com). - (This change was introduced out of order and exists in FreeBSD - 2.0.5 without the version stamp being updated. I.N.M.F.) - 1-Jun-95 Frank Durda IV bsdmail@nemesis.lonestar.org - -<18> While working on the TEAC CD-ROM driver (teaccd) that is reusing - chunks of code from this driver, I discovered several functions, - arrays and other things that should have been declared 'static'. - These changes are necessary if the TEAC CD-ROM driver is to be - present at the same time as matcd. - Also fixed the residual buss vs bus symbols and strings. - There are no functional code changes in this edit. - 2-May-95 Frank Durda IV bsdmail@nemesis.lonestar.org - -<19> Creative has changed the Status port slightly in their - sound boards based on the Vibra-16 (and probably the Vibra-16S) - chipset. This change masks some unused bits that were formally - on all the time and are doing different things in this design. - The changes are transparent to all other supported boards. - 20-Jun-95 Frank Durda IV bsdmail@nemesis.lonestar.org - -<20> Code was added to detect non-Creative (SoundBlaster) host - interfaces, and the driver will switch to code compatible with the - detected host interface. This should add support for MediaVision, - IBM, Reveal, and other compatible adapters with split - data/status-ports. This code allows a mix of SoundBlaster (Type 0) - and non-SoundBlaster (Type 1) boards in the same system with no - special configuration. - - I also updated the attach code to display the interface type and - changed the host interface probe messages to reflect the "c" for - controller in controller-specific messages as the existing messages - were confusing when a second card was in place . The kernel -c - tables have been updated accordingly, so you now have a matcdc%d - controller to change settings on. - 24-Jun-95 Frank Durda IV bsdmail@nemesis.lonestar.org - -<21> Added interface handling code in two of those "this should not - happen" routines, draincmd and get_stat. Since these routines are - called by functions during probing that may not know what type - interface is out there, the code assumes that a given adapter is - both a type 0 and a type 1 adapter at the same time. Plus, - this code gets executed once in a very long time so the cost of - assuming both host adapter types is not significant. - 4-Jul-95 Frank Durda IV bsdmail@nemesis.lonestar.org - -<22> Four external interface prototypes were altered by someone else. - I believe these changes are for making GCC and/or the linker shut-up - when building some other part of the system since matcd already - compiles -Wall with no warnings... - 8-Sep-95 Frank Durda IV bsdmail@nemesis.lonestar.org - -<23> This change implements the ioctls for preventing media removal - and allowing media removal. - Currently, these calls will work according to the following rules: - No "l" devs opened Any "l" dev open - CDALLOW accepted always rejected always - CDPREVENT accepted always accepted always - - One refinement might be to allow CDALLOW/CDPREVENT to always - work if UID 0 issued the ioctl, but that will wait for later. - - I also made a change to the information that the toc_entry code - returns so that xcdplayer won't malfunction. (It would not play - the last track on a non-mixed mode audio CD.) Unlike cdplayer, - xcdplayer asks for track information one track at a time, and - calls for information on the lead-out track by its official - number (0xaa), rather than referring to the "after last" (n+1) track - as cdplayer does. Anyway, this change should make both players - happy. - 16-Sep-95 Frank Durda IV bsdmail@nemesis.lonestar.org - -<24> In Edit 15 when the extra devs were created for selective locking, - the door locking was broken if a non-locking dev on the drive is - closed. The problem was caused by not tracking locked devs and - non-locking devs as being different partitions. The change is to - simply use the locking dev bit to flag a set of shadow partitions - when it comes to lock operations. All other operations treat the - locked and unlocked partitions as being identical. - 18-Sep-95 Frank Durda IV bsdmail@nemesis.lonestar.org - -<25> During work on Edit 23, I noted that on slow and very busy systems, - sometimes the driver would go to sleep forever. The problem appears - to have been a race condition caused by doing separate timeout/sleep - calls without using SPL first. The change here is to use tsleep - which provides the equivalent of timeout/sleep timeout/tsleep if the - last paremeter is tsleep is set to the time value that would have been - given to timeout. - I also fixed some duplicate location strings in the tsleep calls. - 24-Sep-95 Frank Durda IV bsdmail@nemesis.lonestar.org - -<26> Moved a function declaration that generated two warnings with - the FULLCONFIG/FULLDRIVER conditionals disabled. - Updated the igot function so that it correctly reports limited - functions when a sub-set driver is compiled. - Eliminated FULLCONFIG conditional and now set controller counts - based on the NMATCD #define produced by the config process. - Also, disable the audio-related ioctls based on the BOOTMFS - conditional to help make the boot floppy kernel smaller. - 18-Oct-95 Frank Durda IV bsdmail@nemesis.lonestar.org - -<27> Incorporated changes needed to move the cdevsw and bdevsw - entries into the drivers (including this one). Also - include a quick first pass cut at DEVFS suppport. - ----------------------------------------------------------------------------*/ - -/*Match this format: Version_dc(d)__dd-mmm-yy */ -static char MATCDVERSION[]="Version 1(26) 18-Oct-95"; - -/* The following strings may not be changed*/ -static char MATCDCOPYRIGHT[] = "Matsushita CD-ROM driver, Copr. 1994,1995 Frank Durda IV"; -/* The proceeding strings may not be changed*/ - -/* $Id: matcd.c,v 1.4 1996/09/03 10:24:08 asami Exp $ */ - -/*--------------------------------------------------------------------------- - Include declarations ----------------------------------------------------------------------------*/ - -#include "matcd.h" -#include <sys/param.h> -#include <sys/systm.h> - -#include <sys/buf.h> -#include <sys/dkbad.h> -#include <sys/cdio.h> -#include <sys/disklabel.h> -#include <sys/file.h> -#include <sys/ioctl.h> -#include <sys/proc.h> - -#ifdef PC98 -#include "pc98/pc98/matcd/options.h" /*Conditional compile options - and probe port hints*/ -#include "i386/isa/matcd/matcddrv.h" /*Drive-related defs & strings*/ -#include "pc98/pc98/matcd/creative.h" /*Host interface related defs*/ -#else -#include "i386/isa/matcd/options.h" /*Conditional compile options - and probe port hints*/ -#include "i386/isa/matcd/matcddrv.h" /*Drive-related defs & strings*/ -#include "i386/isa/matcd/creative.h" /*Host interface related defs*/ -#endif - -#include <sys/conf.h> -#include <sys/kernel.h> -#ifdef DEVFS -#include <sys/devfsext.h> -#endif /*DEVFS*/ - -/*--------------------------------------------------------------------------- - Defines and structures ----------------------------------------------------------------------------*/ - -#define DRIVESPERC 4 /*This is a constant*/ -#define TOTALDRIVES NUMCTRLRS*DRIVESPERC /*Max possible drives*/ - -#define TICKRES 10 /*Our coarse timer resolution*/ -#define ISABUSKHZ 8330 /*Number of IN/OUT ISA/sec*/ -#define MAXTRKS 101 /*Maximum possible tracks*/ - -#define RAW_DEVICE 46 /*<16>Dev number for raw device*/ - - -#define MATCDBLK 2048 /*Standard block size*/ -#define MATCDRBLK 2352 /*Raw and/or DA block size*/ -#define MATCD_RETRYS 5 /*Number of retries for read ops*/ -#define MATCD_READ_1 0x80 /*Read state machine defines*/ -#define MATCD_READ_2 0x90 /*Read state machine defines*/ - -struct matcd_volinfo { - unsigned char type; /*00 CD-DA or CD-ROM - 10 CD-I - 20 XA */ - unsigned char trk_low; /*Normally 1*/ - unsigned char trk_high; /*Highest track number*/ - unsigned char vol_msf[3]; /*Size of disc in min/sec/frame*/ -}; - - -struct matcd_mbx { - short controller; - short ldrive; - short partition; - short port; - short iftype; /*<20>Host interface type*/ - short retry; - short nblk; - int sz; - u_long skip; - struct buf *bp; - int p_offset; - short count; -}; - -static struct matcd_data { - short drivemode; /*Last state drive was set to*/ - short flags; - short status; /*Last audio-related function*/ - int blksize; - u_long disksize; - short iobase; - short iftype; /*<20>Host interface type*/ - struct disklabel dlabel; - unsigned int partflags[MAXPARTITIONS]; - unsigned int openflags; - struct matcd_volinfo volinfo; - struct matcd_mbx mbx; - u_char patch[2]; /*<12>Last known audio routing*/ - u_char volume[2]; /*<12>Last known volume setting*/ -#ifdef DEVFS - void *ra_devfs_token; /* handle for devfs entry */ - void *rc_devfs_token; - void *a_devfs_token; - void *c_devfs_token; - void *rla_devfs_token; - void *rlc_devfs_token; - void *la_devfs_token; - void *lc_devfs_token; -#endif DEVFS -} matcd_data[TOTALDRIVES]; - - -/* Bit equates for matcd_data.flags*/ - -#define MATCDINIT 0x0001 /*Probe ran on host adapter*/ -#define MATCDLABEL 0x0004 /*Valid TOC exists*/ -#define MATCDLOCK 0x0008 /*<15>Drive door is locked*/ -#define MATCDWARN 0x0020 /*Have reported an open disc change*/ - - -/* Bit equates for matcd_data.partflags*/ - -#define MATCDOPEN 0x0001 -#define MATCDREADRAW 0x0002 - - -/* Error classes returned by chk_error()*/ - -#define ERR_RETRY 1 /*A retry might recover this*/ -#define ERR_INIT 2 /*A retry certainly will get this*/ -#define ERR_FATAL 3 /*This cannot be recovered from*/ - - -static struct buf_queue_head request_head[NUMCTRLRS]; /*<18>A queue for each host interface*/ -static int nextcontroller=0; /*<18>Number of interface units found*/ -static int drivepresent=0; /*<18>Don't change this - see license*/ -static int iftype; /*<20>Probe/Attach i.f. type relay*/ - -static unsigned char if_state[4]={0,0,0,0}; /*<18>State of the host I/F and bus*/ - -/* Flags in the if_state array -*/ - -#define BUSBUSY 0x01 /*<18>Bus is already busy*/ - - -struct matcd_read2 { - unsigned char start_msf[3]; - unsigned char end_msf[3]; -}; - - -/* This mystery structure is supposed to make dynamic driver - loading possible. -*/ - - -/*--------------------------------------------------------------------------- - These macros take apart the minor number and yield the - partition, drive on controller, and controller. - This must match the settings in /dev/MAKEDEV. ----------------------------------------------------------------------------*/ - -#define matcd_partition(dev) ((minor(dev)) & 0x07) -#define matcd_ldrive(dev) (((minor(dev)) & 0x78) >> 3) -#define matcd_cdrive(dev) (((minor(dev)) & 0x18) >> 3) -#define matcd_controller(dev) (((minor(dev)) & 0x60) >> 5) -#ifdef LOCKDRIVE -#define matcd_lockable(dev) (((minor(dev)) & 0x80) >> 5) -#endif /*LOCKDRIVE*/ - - - - -/*--------------------------------------------------------------------------- - Entry points and other connections to/from kernel - see also conf.h - --- not any more :) ----------------------------------------------------------------------------*/ - -static int matcd_probe(struct isa_device *dev); -static int matcd_attach(struct isa_device *dev); -struct isa_driver matcddriver={matcd_probe, matcd_attach, - "matcdc"}; - - -static d_open_t matcdopen; -static d_close_t matcdclose; -static d_ioctl_t matcdioctl; -static d_psize_t matcdsize; -static d_strategy_t matcdstrategy; - -#define CDEV_MAJOR 46 -#define BDEV_MAJOR 17 - -static struct cdevsw matcd_cdevsw; -static struct bdevsw matcd_bdevsw = - { matcdopen, matcdclose, matcdstrategy, matcdioctl, /*17*/ - nodump, matcdsize, 0, "matcd", - &matcd_cdevsw, -1 }; - -/*--------------------------------------------------------------------------- - Internal function declarations ----------------------------------------------------------------------------*/ - -static void matcd_drvinit(void *unused); -static void matcd_start(int controller); -static void zero_cmd(char *); -static void matcd_pread(int port, int count, unsigned char * data); -static int matcd_fastcmd(int port,int ldrive,int cdrive, - unsigned char * cp); -static void matcd_slowcmd(int port,int ldrive,int cdrive, - unsigned char * cp); -static void matcd_blockread(int state); -static void selectdrive(int port,int drive); -static void doreset(int port,int cdrive); -static int doprobe(int port,int cdrive); -static void lockbus(int controller, int ldrive); -static void unlockbus(int controller, int ldrive); -static int matcd_volinfo(int ldrive); -static void draincmd(int port,int cdrive,int ldrive); -static int get_error(int port, int ldrive, int cdrive); -static int chk_error(int errnum); -static int msf_to_blk(unsigned char * cd); -#ifdef FULLDRIVER -static int matcd_playtracks(int ldrive, int cdrive, int controller, - struct ioc_play_track *pt); -static int matcd_playmsf(int ldrive, int cdrive, int controller, - struct ioc_play_msf *pt); -static int matcd_pause(int ldrive, int cdrive, int controller, - int action); -static int matcd_stop(int ldrive, int cdrive, int controller); -static int matcd_level(int ldrive, int cdrive, int controller, - struct ioc_vol * volume, int action); -static int matcd_patch(int ldrive, int cdrive, int controller, - struct ioc_patch * routing); -static int matcd_route(int ldrive, int cdrive, int controller, - int command); -static int matcd_pitch(int ldrive, int cdrive, int controller, - struct ioc_pitch * speed); -#endif /*FULLDRIVER*/ -static int matcd_toc_header(int ldrive, int cdrive, int controller, - struct ioc_toc_header * toc); -static int matcd_toc_entries(int ldrive, int cdrive, - int controller, - struct ioc_read_toc_entry *ioc_entry); -static int matcd_read_subq(int ldrive, int cdrive, int controller, - struct ioc_read_subchannel * sqp); -static int matcd_igot(struct ioc_capability * sqp); -static int waitforit(int timelimit, int state, int port, - char * where); -static int get_stat(int port, int ldrive); -static int media_chk(struct matcd_data *cd,int errnum, - int ldrive,int test); -static int matcd_eject(int ldrive, int cdrive, int controller); -static int matcd_doorclose(int ldrive, int cdrive, int controller); -static int matcd_dlock(int ldrive, int cdrive, - int controller, int action); -static int docmd(char * cmd, int ldrive, int cdrive, - int controller, int port); - - -/*--------------------------------------------------------------------------- - matcdopen - Open the device - - This routine actually gets called every time anybody opens - any partition on a drive. But the first call is the one that - does all the work. - -<15> If LOCKDRIVE is enabled, additional minor number devices allow -<15> the drive to be locked while being accessed. ----------------------------------------------------------------------------*/ -int matcdopen(dev_t dev, int flags, int fmt, - struct proc *p) -{ - int cdrive,ldrive,partition,controller,lock; - struct matcd_data *cd; - int i,z,port; - unsigned char cmd[MAXCMDSIZ]; - - ldrive=matcd_ldrive(dev); - cdrive=matcd_cdrive(dev); - partition=matcd_partition(dev); - controller=matcd_controller(dev); - lock=matcd_lockable(dev); - cd= &matcd_data[ldrive]; - port=cd->iobase; /*and port#*/ - - if (ldrive >= TOTALDRIVES) return(ENXIO); - - -#ifdef DEBUGOPEN - printf("matcd%d: Open: dev %x partition %x controller %x flags %x cdrive %x\n", - ldrive,(int)dev,partition,controller,cd->flags, - matcd_cdrive(dev)); -#endif /*DEBUGOPEN*/ - - if (!(cd->flags & MATCDINIT)) { /*Did probe find this drive*/ - return(ENXIO); - } - - if (!(cd->flags & MATCDLABEL) && - cd->openflags) { /*Has drive completely closed?*/ - return(ENXIO); /*No, all partitions must close*/ - } - - -/* Now, test to see if the media is ready -*/ - - lockbus(controller,ldrive); - zero_cmd(cmd); - cmd[0]=NOP; /*Test drive*/ - matcd_slowcmd(port,ldrive,cdrive,cmd); - i=waitforit(10*TICKRES,DTEN,port,"matopen"); - z=get_stat(port,ldrive); /*Read status byte*/ -#ifdef DEBUGOPEN - printf("matcd%d Result of NOP is %x %x\n",ldrive,i,z); -#endif /*DEBUGOPEN*/ - if ((z & MATCD_ST_DSKIN)==0) { /*Is there a disc in the drive?*/ -#ifdef DEBUGOPEN - printf("matcd%d: No Disc in open\n",ldrive); -#endif /*DEBUGOPEN*/ - unlockbus(controller, ldrive); /*Release bus lock*/ - cd->flags &= ~MATCDLABEL; /*<16>Mark label as invalid*/ - if (major(dev)==RAW_DEVICE) { /*<16>Is the char device?*/ - return(0); /*<16>Allow Semi open*/ - } - else { - return(ENXIO); /*<16>Normally blow off*/ - } - } - if (z & MATCD_ST_ERROR) { /*Was there an error*/ - i=get_error(port,ldrive,cdrive);/*Find out what it was*/ -#ifdef DEBUGOPEN - printf("matcd%d NOP Error was %x\n",ldrive,i); -#endif /*DEBUGOPEN*/ - if (cd->openflags) { /*Any parts open?*/ - if (media_chk(cd,i,ldrive,0)) { /*<14>Was it a disc chg?*/ -#ifdef DEBUGOPEN - printf("matcd%d: Disc change detected i %x z %x\n", - ldrive,i,z); -#endif /*DEBUGOPEN*/ - unlockbus(controller, ldrive); /*Release bus lock*/ - return(ENOTTY); - } - - } else { - media_chk(cd,i,ldrive,1);/*<14>Was it a disc chg?*/ - /*<14>Clear volume info*/ - } - } - unlockbus(controller, ldrive); /*Release bus lock*/ - -/* Here we fill in the disklabel structure although most is - hardcoded. -*/ - - if ((cd->flags & MATCDLABEL)==0) { - bzero(&cd->dlabel,sizeof(struct disklabel)); - - -/* Now we query the drive for the actual size of the media. - This is where we find out of there is any media or if the - media isn't a Mode 1 or Mode 2/XA disc. - See version information about Mode 2/XA support. -*/ - lockbus(controller,ldrive); - i=matcdsize(dev); - unlockbus(controller, ldrive); /*Release bus lock*/ -#ifdef DEBUGOPEN - printf("matcd%d: Bus unlocked in open\n",ldrive); -#endif /*DEBUGOPEN*/ - if (i < 0) { - printf("matcd%d: Could not read the disc size\n",ldrive); - return(ENXIO); - } /*matcdsize filled in rest of dlabel*/ - -/* Based on the results, fill in the variable entries in the disklabel -*/ - cd->dlabel.d_secsize=cd->blksize; - cd->dlabel.d_ncylinders=(cd->disksize/100)+1; - cd->dlabel.d_secperunit=cd->disksize; - cd->dlabel.d_partitions[0].p_size=cd->disksize; - cd->dlabel.d_checksum=dkcksum(&cd->dlabel); - - -/* Now fill in the hardcoded section -*/ - /*123456789012345678*/ - strncpy(cd->dlabel.d_typename,"Matsushita CDR ",16); - strncpy(cd->dlabel.d_packname,"(c) 1994, fdiv ",16); - cd->dlabel.d_magic=DISKMAGIC; - cd->dlabel.d_magic2=DISKMAGIC; - cd->dlabel.d_nsectors=100; - cd->dlabel.d_secpercyl=100; - cd->dlabel.d_ntracks=1; - cd->dlabel.d_interleave=1; - cd->dlabel.d_rpm=300; - cd->dlabel.d_npartitions=1; /*See note below*/ - cd->dlabel.d_partitions[0].p_offset=0; - cd->dlabel.d_partitions[0].p_fstype=9; - cd->dlabel.d_flags=D_REMOVABLE; - -/* I originally considered allowing the partition match tracks or - sessions on the media, but since you are allowed up to 99 - tracks in the RedBook world, this would not fit in with the - BSD fixed partition count scheme. So ioctls will be used to shift - the track to be accessed into partition 1. -*/ - - cd->flags |= MATCDLABEL; /*Mark drive as having TOC*/ - } - -#ifdef DEBUGOPEN - printf("matcd%d open2: partition=%d disksize=%d blksize=%x flags=%x\n", - ldrive,partition,(int)cd->disksize,cd->blksize,cd->flags); -#endif /*DEBUGOPEN*/ - -#ifdef LOCKDRIVE - if (cd->openflags==0 && lock) { - zero_cmd(cmd); - cmd[0]=LOCK; /*Lock drive*/ - cmd[1]=1; - docmd(cmd,ldrive,cdrive,controller,port);/*<15>Issue cmd*/ - cd->flags |= MATCDLOCK; /*<15>Drive is now locked*/ - } -#endif /*LOCKDRIVE*/ - cd->openflags |= (1<<(partition+lock));/*<24>Mark partition open*/ - - if (partition==RAW_PART || - (partition < cd->dlabel.d_npartitions && - cd->dlabel.d_partitions[partition].p_fstype != FS_UNUSED)) { - cd->partflags[partition] |= MATCDOPEN; - if (partition == RAW_PART) { - cd->partflags[partition] |= MATCDREADRAW; - } -#ifdef DEBUGOPEN - printf("matcd%d: Open is complete - openflags %x\n", - ldrive,cd->openflags); -#endif /*DEBUGOPEN*/ - return(0); - } -#ifdef DEBUGOPEN - printf("matcd%d: Open FAILED\n",ldrive); -#endif /*DEBUGOPEN*/ - return(ENXIO); -} - - -/*--------------------------------------------------------------------------- - matcdclose - Close the device - - Close may not do much other than clear some driver settings. - Note that audio playback will continue. - -<15> If you define LOCKDRIVE, and the drive has been opened using -<15> one of the locking minor numbers, code in close will unlock -<15> the drive. ----------------------------------------------------------------------------*/ - -int matcdclose(dev_t dev, int flags, int fmt, - struct proc *p) -{ - int ldrive,cdrive,port,partition,controller,lock; - struct matcd_data *cd; -#ifdef LOCKDRIVE - unsigned char cmd[MAXCMDSIZ]; -#endif /*LOCKDRIVE*/ - - ldrive=matcd_ldrive(dev); - cdrive=matcd_cdrive(dev); - lock=matcd_lockable(dev); - cd=matcd_data+ldrive; - port=cd->iobase; /*and port#*/ - - if (ldrive >= TOTALDRIVES) - return(ENXIO); - - partition = matcd_partition(dev); - controller=matcd_controller(dev); -#ifdef DEBUGOPEN - printf("matcd%d: Close partition=%d flags %x openflags %x partflags %x\n", - ldrive,partition,cd->flags,cd->openflags, - cd->partflags[partition]); -#endif /*DEBUGOPEN*/ - - if (!(cd->flags & MATCDINIT)) - return(ENXIO); - - cd->partflags[partition] &= ~(MATCDOPEN|MATCDREADRAW); - cd->openflags &= ~(1<<(partition+lock)); - if (cd->openflags==0) { /*<24>Really last close?*/ -#ifdef LOCKDRIVE - if (cd->flags & MATCDLOCK) { /*<24>Was drive locked?*/ - zero_cmd(cmd); /*Yes, so unlock it*/ - cmd[0]=LOCK; /*Unlock drive*/ - docmd(cmd,ldrive,cdrive,controller,port); - } -#endif /*LOCKDRIVE*/ - cd->flags &= ~(MATCDWARN|MATCDLOCK); - /*<15>Clear warning flag*/ - } - return(0); -} - - -/*--------------------------------------------------------------------------- - matcdstrategy - Accepts I/O requests from kernel for processing - - This routine accepts a read request block pointer (historically - but somewhat inaccurately called *bp for buffer pointer). - Various sanity checks are performed on the request. - When we are happy with the request and the state of the device, - the request is added to the queue of requests for the interface - that the drive is connected to. We support multiple interfaces - so there are multiple queues. Once the request is added, we - call the matcd_start routine to start the device in case it isn't - doing something already. All I/O including ioctl requests - rely on the current request starting the next one before exiting. ----------------------------------------------------------------------------*/ - -void matcdstrategy(struct buf *bp) -{ - struct matcd_data *cd; - int s; - int ldrive,controller; - - ldrive=matcd_ldrive(bp->b_dev); - controller=matcd_controller(bp->b_dev); - cd= &matcd_data[ldrive]; - -#ifdef DEBUGIO - printf("matcd%d: Strategy: buf=0x%lx, block#=%ld bcount=%ld\n", - ldrive,(unsigned long)bp,bp->b_blkno,bp->b_bcount); -#endif /*DEBUGIO*/ - - - if (ldrive >= TOTALDRIVES || bp->b_blkno < 0) { - printf("matcd%d: Bogus parameters received - kernel may be corrupted\n",ldrive); - bp->b_error=EINVAL; - goto bad; - } - - if (!(cd->flags & MATCDLABEL)) { - bp->b_error = EIO; - goto bad; - } - - if (!(bp->b_flags & B_READ)) { - bp->b_error = EROFS; - goto bad; - } - - if (bp->b_bcount==0) /*Request is zero-length - all done*/ - goto done; - - if (matcd_partition(bp->b_dev) != RAW_PART) { - if (bounds_check_with_label(bp,&cd->dlabel,1) <= 0) { - goto done; - } - } else { - bp->b_pblkno=bp->b_blkno; - bp->b_resid=0; - } - - s=splbio(); /*Make sure we don't get intr'ed*/ - tqdisksort(&request_head[controller], bp);/*Add new request (bp) to queue (dp - and sort the requests in a way that - may not be ideal for CD-ROM media*/ - - - matcd_start(controller); /*Ok, with our newly sorted queue, - see if we can start an I/O operation - right now*/ - splx(s); /*Return priorities to normal*/ - return; /*All done*/ - -bad: bp->b_flags |= B_ERROR; /*Request bad in some way*/ -done: bp->b_resid = bp->b_bcount; /*Show amount of data un read*/ - biodone(bp); /*Signal we have done all we plan to*/ - return; -} - - -/*--------------------------------------------------------------------------- - matcd_start - Pull a request from the queue and consider doing it. ----------------------------------------------------------------------------*/ - -static void matcd_start(int controller) -{ - struct matcd_data *cd; - struct buf *bp; - struct partition *p; - int part,ldrive; - - bp = TAILQ_FIRST(&request_head[controller]); - if (bp == NULL) { /*Nothing on read queue to do?*/ - wakeup((caddr_t)&matcd_data->status); /*Wakeup any blocked*/ - return; /* opens, ioctls, etc*/ - } - - ldrive=matcd_ldrive(bp->b_dev); /*Get logical drive#*/ - cd=&matcd_data[ldrive]; /*Get pointer to data for this drive*/ -#ifdef DEBUGIO - printf("matcd%d: In start controller %d\n",ldrive,controller); -#endif /*DEBUGIO*/ - - if (if_state[controller] & BUSBUSY) { -#ifdef DEBUGIO - printf("matcd%d: Dropping thread in start, controller %d\n", - ldrive,controller); -#endif /*DEBUGIO*/ - return; - } - -/* Ok, the controller is idle (not necessarily the drive) and so - get the command to do and issue it -*/ - - TAILQ_REMOVE(&request_head[controller], bp, b_act); - - part=matcd_partition(bp->b_dev); - p=cd->dlabel.d_partitions + part; - - if_state[controller] |= BUSBUSY;/*<18>Mark bus as busy*/ - cd->mbx.ldrive=ldrive; /*Save current logical drive*/ - cd->mbx.controller=controller; /*and controller*/ - cd->mbx.partition=part; /*and partition (2048 vs 2532)*/ - cd->mbx.port=cd->iobase; /*and port#*/ - cd->mbx.iftype=cd->iftype; /*<20>interface type*/ - cd->mbx.retry=MATCD_RETRYS; /*and the retry count*/ - cd->mbx.bp=bp; /*and the bp*/ - cd->mbx.p_offset=p->p_offset; /*and where the data will go*/ - matcd_blockread(MATCD_READ_1+ldrive); /*Actually start the read*/ - return; /*Dropping thread. matcd_blockread - must have scheduled a timeout or - we will go to sleep forever*/ -} - - -/*--------------------------------------------------------------------------- - matcdioctl - Process things that aren't block reads - - In this driver, ioctls are used mainly to change - the mode the drive is running in, play audio and other - things that don't fit into the block read scheme of things. ----------------------------------------------------------------------------*/ - -int matcdioctl(dev_t dev, int command, caddr_t addr, - int flags, struct proc *p) -{ - struct matcd_data *cd; - int ldrive,cdrive,partition; - int port, controller; -#ifdef DEBUGIOCTL - int i; -#endif /*DEBUGIOCTL*/ - - ldrive=matcd_ldrive(dev); - cdrive=matcd_cdrive(dev); - partition=matcd_partition(dev); - controller=ldrive>>2; - cd = &matcd_data[ldrive]; - port=cd->iobase; - -#ifdef DEBUGIOCTL - printf("matcd%d: ioctl %x cdrive %x parms ",ldrive,command,cdrive); - for (i=0;i<10;i++) { - printf("%02x ",(unsigned int)addr[i]); - } - printf(" flags %x\n",cd->flags); -#endif /*DEBUGIOCTL*/ - - if (command==CDIOCCLOSE) /*<16>Allow close if door open*/ - return(matcd_doorclose(ldrive, cdrive, controller)); - - if (!(cd->flags & MATCDLABEL)) /*Did we read TOC OK?*/ - return(EIO); /*<16>then drive really isn't ready*/ - - switch(command) { - case DIOCSBAD: - return(EINVAL); - - case DIOCGDINFO: - *(struct disklabel *) addr = cd->dlabel; - return(0); - - case DIOCGPART: - ((struct partinfo *) addr)->disklab=&cd->dlabel; - ((struct partinfo *) addr)->part= - &cd->dlabel.d_partitions[matcd_partition(dev)]; - return(0); - - case DIOCWDINFO: - case DIOCSDINFO: - if ((flags & FWRITE) == 0) { - return(EBADF); - } - else { - return setdisklabel(&cd->dlabel, - (struct disklabel *) addr, 0); - } - case DIOCWLABEL: - return(EBADF); - - case CDIOCEJECT: - return(matcd_eject(ldrive, cdrive, controller)); - - case CDIOCALLOW: - return(matcd_dlock(ldrive, cdrive, - controller,0)); - - case CDIOCPREVENT: - return(matcd_dlock(ldrive, cdrive, - controller, MATCDLOCK)); - -#ifdef FULLDRIVER - case CDIOCPLAYTRACKS: - return(matcd_playtracks(ldrive, cdrive, controller, - (struct ioc_play_track *) addr)); - - case CDIOCPLAYMSF: - return(matcd_playmsf(ldrive, cdrive, controller, - (struct ioc_play_msf *) addr)); - - case CDIOCRESUME: - return(matcd_pause(ldrive, cdrive, controller,RESUME)); - - case CDIOCPAUSE: - return(matcd_pause(ldrive, cdrive, controller,0)); - - case CDIOCSTOP: - return(matcd_stop(ldrive, cdrive, controller)); - - case CDIOCGETVOL: - case CDIOCSETVOL: - return(matcd_level(ldrive, cdrive, controller, - (struct ioc_vol *) addr, command)); - - case CDIOCSETMONO: /*<12>This drive can't do mono*/ - return(EINVAL); /*<12>but it looks like it should*/ - - /*<12>SRC OUT SRC OUT*/ - case CDIOCSETSTEREO: /*<12>0 -> L 1 -> R*/ - case CDIOCSETMUTE: /*<12>0 -> NULL 1 -> NULL*/ - case CDIOCSETLEFT: /*<12>0 -> L&R 1 -> NULL*/ - case CDIOCSETRIGHT: /*<12>0 -> NULL 1 -> L&R*/ - /*<12>Adjust audio routing*/ - return(matcd_route(ldrive, cdrive, controller, - command)); - - case CDIOCSETPATCH: /*<12>Allow precise routing*/ - return(matcd_patch(ldrive, cdrive, controller, - (struct ioc_patch *) addr)); - - case CDIOCPITCH: /*<12>Adjust playback speed*/ - return(matcd_pitch(ldrive, cdrive, controller, - (struct ioc_pitch *) addr)); - - case CDIOCSTART: /*<12>Only reason this isn't*/ - return(EINVAL); /*<12>implemented is I can't find out*/ - /*<12>what it should do!*/ -#endif /*FULLDRIVER*/ - - case CDIOREADTOCHEADER: - return(matcd_toc_header(ldrive, cdrive, controller, - (struct ioc_toc_header *) addr)); - - case CDIOREADTOCENTRYS: - return(matcd_toc_entries(ldrive, cdrive, controller, - (struct ioc_read_toc_entry *) addr)); - - case CDIOCREADSUBCHANNEL: - return(matcd_read_subq(ldrive, cdrive, controller, - (struct ioc_read_subchannel *) addr)); - - case CDIOCCAPABILITY: /*<16>Request drive/driver capability*/ - return(matcd_igot((struct ioc_capability *) addr)); - - case CDIOCRESET: /*<12>There is no way to hard reset*/ - return(EINVAL); /*<12>just one drive*/ - - default: - return(ENOTTY); - } -} - -/*--------------------------------------------------------------------------- - matcdsize - Reports how many blocks exist on the disc. ----------------------------------------------------------------------------*/ - -int matcdsize(dev_t dev) -{ - int size,blksize; - int ldrive,part; - struct matcd_data *cd; - - ldrive=matcd_ldrive(dev); - part=matcd_partition(dev); - if (part==RAW_PART) - blksize=MATCDRBLK; /*2352*/ - else - blksize=MATCDBLK; /*2048*/ - - cd = &matcd_data[ldrive]; - - if (matcd_volinfo(ldrive) >= 0) { - cd->blksize=blksize; - size=msf_to_blk((char * )&cd->volinfo.vol_msf); - - cd->disksize=size*(blksize/DEV_BSIZE); -#ifdef DEBUGOPEN - printf("matcd%d: Media size %d\n",ldrive,size); -#endif /*DEBUGOPEN*/ - return(0); - } - return(-1); -} - -/*--------------------------------------------------------------------------- - matcd_probe - Search for host interface/adapters - - The probe routine hunts for the first drive on the interface since - there is no way to locate just the adapter. It also resets the - entire drive chain while it is there. matcd_attach() takes care of - the rest of the initialization. - - The probe routine can be compiled two ways. In AUTOHUNT mode, - the kernel config file can say "port?" and we will check all ports - listed in the port_hint array (see above). - - Without AUTOHUNT set, the config file must list a specific port - address to check. - - Note that specifying the explicit addresses makes boot-up a lot - faster. - - The probe will locate Panasonic/Creative interface on the following - Creative adapter boards: - #1330A Sound Blaster PRO - #1730 Sound Blaster 16 - #1740 Sound Blaster 16 (cost reduced) - #2230 Sound Blaster 16 (cost reduced) - #2770 Sound Blaster 16 Value (cost reduced) - #1810 omniCD upgrade kit adapter card (stand-alone CD) - #3100 PhoneBlaster SB16 + Sierra 14.4K modem combo - Creative releases a newer and cheaper-to-make Sound Blaster - board every few months, so by the original release date of this - software, there are probably 8 different board models called - Sound Blaster 16. These include "Vibra", "Value", etc. - - Please report additional part numbers and board descriptions - and new port numbers that work to the author. - ----------------------------------------------------------------------------*/ - -static int -matcd_probe(struct isa_device *dev) -{ - int i,cdrive; - unsigned char y; - int port = dev->id_iobase; /*Take port hint from config file*/ - - cdrive=nextcontroller; /*Controller defined by pass for now*/ - if (nextcontroller==NUMCTRLRS) { - printf("matcdc%d: - Too many interfaces specified in config\n", - nextcontroller); - return(0); - } - if (nextcontroller==0) { /*Very first time to be called*/ - for (i=0; i<TOTALDRIVES; i++) { - matcd_data[i].drivemode=MODE_UNKNOWN; - matcd_data[i].flags=0; - } - } - - i=nextcontroller*DRIVESPERC; /*Precompute controller offset*/ - for (y=0; y<DRIVESPERC; y++) { - matcd_data[i+y].flags=0; - } - -#ifdef DEBUGPROBE - printf("matcdc%d: In probe i %d y %d port %x\n", - nextcontroller,i,y,port); -#endif /*DEBUGPROBE*/ -#ifdef AUTOHUNT -#ifdef DEBUGPROBE - printf("matcd%d: size of port_hints %d\n", - nextcontroller,sizeof(port_hints)); -#endif /*DEBUGPROBE*/ - if (port==-1) { - for(i=0;i<(sizeof(port_hints)/sizeof(short));i++) { - port=port_hints[i]; -#ifdef DEBUGPROBE - printf("matcdc%d: Port hint %x\n",nextcontroller,port); -#endif /*DEBUGPROBE*/ - if (port==-1) { - dev->id_iobase=-1; /*Put port ? back*/ - return(0);/*Nothing left to try*/ - } - if (port!=0) { /*Untested port found*/ - dev->id_iobase=port; - port_hints[i]=0;/*Don't use that port again*/ - if (doprobe(port,cdrive)==0) return(NUMPORTS); - } - } - dev->id_iobase=-1; /*Put port ? back as it was*/ - return(0); /*Interface not found*/ - - } else { /*Config specified a port*/ - i=0; /*so eliminate it from the hint list*/ - for(i=0;;i++) { /*or we might try to assign it again*/ - if (port_hints[i]== -1) break; /*End of list*/ - if (port_hints[i]==port) { - port_hints[i]=0; /*Clear duplicate*/ - break; - } - } - if (doprobe(port,cdrive)==0) return(NUMPORTS); - else return(0); - } -#else /*AUTOHUNT*/ - if (port==-1) { - printf("matcdc%d: AUTOHUNT disabled but port? specified in config\n", - nextcontroller); - return(0); - } - if (doprobe(port,cdrive)==0) return(NUMPORTS); - else return(0); -#endif /*AUTOHUNT*/ -} - -/*--------------------------------------------------------------------------- - doprobe - Common probe code that actually checks the ports we - have decided to test. - -<20> Edit 20 changes adds code to determine if the host interface - is one that behaves like the Creative SoundBlaster cards, - or whether the host interface like those used by some boards - made by Media Vision and a version known as Lasermate. ----------------------------------------------------------------------------*/ - -int doprobe(int port,int cdrive) -{ - unsigned char cmd[MAXCMDSIZ]; - int i; - -#ifdef RESETONBOOT - doreset(port,cdrive); /*Reset what might be our device*/ -#endif /*RESETONBOOT*/ - outb(port+PHASE,0); /*<16>Guarantee status phase*/ - zero_cmd(cmd); - cmd[0]=NOP; /*A reasonably harmless command. - This command will fail after - power-up or after reset. That's OK*/ -#ifdef RESETONBOOT - if (((inb(port+STATUS) & (DTEN|STEN)) != (DTEN|STEN)) || - (inb(port+DATA) != 0xff)) - return(-1); /*<20>Something detected but it isn't - the device we wanted*/ -#endif /*RESETONBOOT*/ - if (matcd_fastcmd(port,0,0,cmd)==0) {/*Issue command*/ - outb(port+PHASE,1); /*<20>Switch to Creative Data phase*/ - i=inb(port+CMD); /*<20>Read a byte in data phase*/ - outb(port+PHASE,0); /*<20>Switch to Creative Status phase*/ - if ((inb(port+STATUS) & (DTEN|STEN)) - == (DTEN|STEN)) { /*<20>Drive went idle*/ - iftype=1; /*<20>It is not a Creative interface.*/ - } else { /*<20>Status byte still available*/ - iftype=0; - inb(port+CMD); /*<20>Read status byte*/ - } -#ifdef DEBUGPROBE - printf("matcdc%d: Probe found something\n",nextcontroller); -#endif /*DEBUGPROBE*/ -/*------Don't change anything below this line - see license -----------------*/ - if (drivepresent==0) { /*Don't change*/ - printf("matcd - Matsushita (Panasonic) CD-ROM Driver by FDIV, %s\n", - /*Don't change*/ - MATCDVERSION); /*Don't change*/ - drivepresent++; /*Don't change*/ - if (drivepresent==0) /*Don't change - make LINT happy*/ - printf("%s\n",MATCDCOPYRIGHT); /*Don't change*/ - } /*Don't change*/ -/*------Don't change anything above this line - see license -----------------*/ - return(0); /*Drive 0 detected*/ - } -#ifdef DEBUGPROBE - printf("matcdc%d: Probe DID NOT find something\n",nextcontroller); -#endif /*DEBUGPROBE*/ - return(1); -} - - -/*--------------------------------------------------------------------------- - matcd_attach - Locates drives on the adapters that were located. - If we got here, we located an interface and at least one - drive. Now we figure out how many drives are under that - interface. The Panasonic interface is too simple to call - it a controller, but in the existing PDP model, that is - what it would be. ----------------------------------------------------------------------------*/ - -static int -matcd_attach(struct isa_device *dev) -{ - int i; - unsigned int z,cdrive; - unsigned char cmd[MAXCMDSIZ]; - unsigned char data[12]; - struct matcd_data *cd; - int port = dev->id_iobase; /*Take port ID selected in probe()*/ - -#ifdef DEBUGPROBE - printf("matcdc: Attach dev %x id_unit %d\n", - (unsigned int)dev,dev->id_unit); -#endif /*DEBUGPROBE*/ - printf("matcdc%d Host interface type %d\n", - nextcontroller,iftype); - TAILQ_INIT(&request_head[nextcontroller]); - for (cdrive=0; cdrive<4; cdrive++) { /*We're hunting drives...*/ - zero_cmd(cmd); - cmd[0]=NOP; /*A reasonably harmless command. - This command will fail after - power-up or after reset. It's OK*/ - i=cdrive+(DRIVESPERC*nextcontroller); - if (matcd_fastcmd(port,i,cdrive,cmd)==0) { /*Issue cmd*/ - z=get_stat(port,cdrive);/*Read status byte*/ - if ((z & MATCD_ST_ERROR)) { /*If there was an error, - we must ask for error info - or subsequent cmds fail*/ - zero_cmd(cmd); - cmd[0]=READERROR; /*Inquire*/ - matcd_fastcmd(port,i,cdrive,cmd); - matcd_pread(port,8,data);/*Read data returned*/ - z=get_stat(port,i);/*Read status byte*/ -#ifdef DEBUGPROBE - printf("matcd%d: Status byte %x ",i,z); -#endif /*DEBUGPROBE*/ - } - zero_cmd(cmd); - cmd[0]=READID; /*Get drive ID*/ - matcd_fastcmd(port,i,cdrive,cmd); - matcd_pread(port,10,data);/*Read Drive Parm*/ - get_stat(port,i); /*Read and toss status byte*/ - data[10]=0; /*Build ASCIZ string*/ - printf("matcd%d: [%s] ",i,data); - cd=&matcd_data[i]; - cd->flags |= MATCDINIT; - cd->iobase=dev->id_iobase; - cd->iftype=iftype; - cd->openflags=0; - cd->volume[0]=cd->volume[1]=DEFVOL; - /*<12>Match volume drive resets to*/ - cd->patch[0]=0x01; /*<12>Channel 0 to Left*/ - cd->patch[1]=0x02; /*<12>Channel 1 to Right*/ - cd->status=CD_AS_NO_STATUS; - for (i=0; i<MAXPARTITIONS; i++) { - cd->partflags[i]=0; - } -#ifdef DEVFS - cd->ra_devfs_token = devfs_add_devswf(&matcd_cdevsw, - dkmakeminor(i, 0, 0), DV_CHR, - UID_ROOT, GID_OPERATOR, 0640, "rmatcd%da", i); - cd->rc_devfs_token = devfs_add_devswf(&matcd_cdevsw, - dkmakeminor(i, 0, RAW_PART), DV_CHR, - UID_ROOT, GID_OPERATOR, 0640, "rmatcd%dc", i); - cd->a_devfs_token = devfs_add_devswf(&matcd_bdevsw, - dkmakeminor(i, 0, 0), DV_BLK, - UID_ROOT, GID_OPERATOR, 0640, "matcd%da", i); - cd->c_devfs_token = devfs_add_devswf(&matcd_bdevsw, - dkmakeminor(i, 0, RAW_PART), DV_BLK, - UID_ROOT, GID_OPERATOR, 0640, "matcd%dc", i); - cd->rla_devfs_token = devfs_add_devswf(&matcd_cdevsw, - 0x80 | dkmakeminor(i, 0, 0), DV_CHR, - UID_ROOT, GID_OPERATOR, 0640, "rmatcd%dla", i); - cd->rlc_devfs_token = devfs_add_devswf(&matcd_cdevsw, - 0x80 | dkmakeminor(i, 0, RAW_PART), DV_CHR, - UID_ROOT, GID_OPERATOR, 0640, "rmatcd%dc", i); - cd->la_devfs_token = devfs_add_devswf(&matcd_bdevsw, - 0x80 | dkmakeminor(i, 0, 0), DV_BLK, - UID_ROOT, GID_OPERATOR, 0640, "matcd%dla", i); - cd->lc_devfs_token = devfs_add_devswf(&matcd_bdevsw, - 0x80 | dkmakeminor(i, 0, RAW_PART), DV_BLK, - UID_ROOT, GID_OPERATOR, 0640, "matcd%dlc", i); -#endif - } - } - nextcontroller++; /*Bump ctlr assign to next number*/ - printf("\n"); /*End line of drive reports*/ - - return(1); -} - - -/*--------------------------------------------------------------------------- - zero_cmd - Initialize command buffer ----------------------------------------------------------------------------*/ - -void zero_cmd(char * lcmd) -{ - int i; - - for (i=0; i<MAXCMDSIZ; lcmd[i++]=0); - return; -} - - -/*--------------------------------------------------------------------------- - doreset - Resets all the drives connected to a interface ----------------------------------------------------------------------------*/ - -void doreset(int port,int cdrive) -{ - register int i,z; - outb(port+RESET,0); /*Reset what might be our device*/ - /*Although this ensures a known - state, it does close the drive - door (if open) and aborts any - audio playback in progress. */ - for (i=0;i<(125*ISABUSKHZ);i++){/*DELAY 500msec minimum. Worst - case is door open and none or - unreadable media */ - z=inb(port+CMD); /*This makes the loop run at a - known speed. This value is ok - for 8.33MHz bus*/ - } - for (i=0;i<4;i++) { - matcd_data[(cdrive*4)+i].drivemode=MODE_UNKNOWN; - } - return; -} - - -/*--------------------------------------------------------------------------- - matcd_fastcmd - Send a command to a drive - - This routine executed commands that return instantly (or reasonably - quick), such as RESET, NOP, READ ERROR, etc. The only difference - between it and handling for slower commands, is the slower commands - will invoke a timeout/sleep if they don't get an instant response. - - Fastcmd is mainly used in probe(), attach() and error related - functions. Every attempt should be made to NOT use this - function for any command that might be executed when the system - is up. ----------------------------------------------------------------------------*/ - -int matcd_fastcmd(int port,int ldrive,int cdrive,unsigned char * cp) -{ - unsigned int i; - unsigned char z; - int level; -#ifdef DEBUGCMD - unsigned char *cx; -#endif /*DEBUGCMD*/ - - - - draincmd(port,cdrive,ldrive); /*Make sure bus is really idle*/ -#ifdef DEBUGCMD - cx=cp; - printf("matcd%d: Fast Send port %x sel %d command %x %x %x %x %x %x %x\n", - ldrive,port,cdrive,cx[0],cx[1],cx[2],cx[3],cx[4],cx[5],cx[6]); -#endif /*DEBUGCMD*/ - selectdrive(port,cdrive); /*Enable the desired target drive*/ - level=splhigh(); /*----------------------------------------*/ - for (i=0; i<7; i++) { /*The seven bytes of the command*/ - outb(port+CMD,*cp++); /*must be sent within 10msec or*/ - } /*the drive will ignore the cmd*/ - splx(level); /*------------------------------------------------*/ - -/* Now we wait a maximum of 240msec for a response. - Only in a few rare cases does it take this long. - If it is longer, the command should probably be slept on - rather than increasing the timing value -*/ - - for (i=0; i<(60*ISABUSKHZ); i++) { - z = (inb(port+STATUS)) & (DTEN|STEN); - if (z != (DTEN|STEN)) break; - } - -/* We are now either in a data or status phase, OR we timed-out.*/ - - if (z == (DTEN|STEN)) { -#ifdef DEBUGCMD - printf("matcd%d: Command time-out\n",ldrive); -#endif /*DEBUGCMD*/ - return(-1); - } - if (z != DTEN) { - return(1); - } - return(0); -} - - -/*--------------------------------------------------------------------------- - matcd_slowcmd - Issue a command to the drive - - This routine is for commands that might take a long time, such - as a read or seek. The caller must determine if the command - completes instantly or schedule a poll later on. ----------------------------------------------------------------------------*/ - -void matcd_slowcmd(int port,int ldrive,int cdrive,unsigned char * cp) -{ - unsigned int i; - int level,size; -#ifdef DEBUGCMD - unsigned char *cx; -#endif /*DEBUGCMD*/ - - - draincmd(port,cdrive,ldrive); /*Make sure bus is really idle*/ - -#ifdef DEBUGCMD - cx=cp; - printf("matcd%d: Slow Send port %x sel %d command %x %x %x %x %x %x %x\n", - ldrive,port,cdrive,cx[0],cx[1],cx[2],cx[3],cx[4],cx[5],cx[6]); -#endif /*DEBUGCMD*/ - selectdrive(port,cdrive); /*Enable the desired target drive*/ - if (*cp==ABORT) size=1; - else size=7; - level=splhigh(); /*----------------------------------------*/ - for (i=0; i<size; i++) { /*The seven bytes of the command*/ - outb(port+CMD,*cp++); /*must be sent within 10msec or*/ - } /*the drive will ignore the cmd*/ - splx(level); /*------------------------------------------------*/ - return; -} - - -/*--------------------------------------------------------------------------- - draincmd - Makes certain the bus is idle and throws away - any residual data from the drive if there is any. - Called as preface to most commands. - Added in Edit 5. - - This was added because switching drive modes causes - the drive to emit buffers that were meant to be sent - to the D-to-A to be sent to the host. See setmode. ----------------------------------------------------------------------------*/ -void draincmd(int port,int cdrive,int ldrive) -{ - int i,z; - - i=inb(port+STATUS); - if ((i & (DTEN|STEN)) == (DTEN|STEN)) return; - - printf("matcd%d: in draincmd: bus not idle %x - trying to fix\n", - ldrive,inb(port+STATUS)); - if ((i & (DTEN|STEN)) == STEN) { -#ifdef DEBUGCMD - printf("matcd%d: Data present READING - ",ldrive); -#endif /*DEBUGCMD*/ - i=0; - outb(port+PHASE,1); /*<16>Enable data read*/ - while ((inb(port+STATUS) & (DTEN|STEN)) == STEN) { - inb(port+DATA); /*<21>Ok for Creative*/ - inb(port+ALTDATA); /*<21>Ok for others*/ - i++; - } - outb(port+PHASE,0); -#ifdef DEBUGCMD - printf("%d bytes read\n",i); -#endif /*DEBUGCMD*/ - } -#ifdef DEBUGCMD - printf("matcd%d: Now read status: ",ldrive); -#endif /*DEBUGCMD*/ - i=get_stat(port,ldrive); /*Read status byte*/ - z=inb(port+STATUS); /*Read bus status*/ -#ifdef DEBUGCMD - printf("Data byte %x and status is now %x\n",i,z); -#endif /*DEBUGCMD*/ - if ((z & (DTEN|STEN)) != (DTEN|STEN)) { - printf("matcd%d: Bus not idle %x - resetting\n", - cdrive,inb(port+STATUS)); - doreset(port,cdrive); - } - return; -} - - -/*--------------------------------------------------------------------------- - selectdrive - Swaps drive select bits - - On Creative SB/SB16/stand-alone adapters, possibly to make them - hard to reverse engineer, the drive select signals are swapped. ----------------------------------------------------------------------------*/ - -void selectdrive(int port,int drive) -{ - switch(drive) { - case 0: /*0x00 -> 0x00*/ - outb(port+SELECT,CRDRIVE0); - break; - case 1: /*0x01 -> 0x02*/ - outb(port+SELECT,CRDRIVE1); - break; - case 2: /*0x02 -> 0x01*/ - outb(port+SELECT,CRDRIVE2); - break; - case 3: /*0x03 -> 0x03*/ - outb(port+SELECT,CRDRIVE3); - break; - } - return; -} - - -/*--------------------------------------------------------------------------- - matcd_pread - Read small blocks of control data from a drive ----------------------------------------------------------------------------*/ - -void matcd_pread(int port, int count, unsigned char * data) -{ - int i; - - for (i=0; i<count; i++) { - *data++ = inb(port+CMD); - } - return; -} - - -/*--------------------------------------------------------------------------- - matcd_setmode - Configures disc to run in the desired data mode - - This routine assumes the drive is already idle. - -NOTE - Undocumented action of hardware: If you change (or reaffirm) data - modes with MODESELECT + BLOCKPARAM immediately after a command was - issued that aborted a DA play operation, the drive will unexpectedly - return 2532 bytes of data in a data phase on the first or second - subsequent command. - - Original Symptom: drive will refuse to go idle after reading data - and status expected for a command. State mechanics for this are - not fully understood. ----------------------------------------------------------------------------*/ - -static int -matcd_setmode(int ldrive, int mode) -{ - struct matcd_data *cd; - int retries; - int i,port,cdrive; - unsigned char cmd[MAXCMDSIZ]; - - cd = matcd_data + ldrive; - retries=3; - cdrive=ldrive&0x03; - port=cd->iobase; - if (cd->drivemode==mode) { - return(0); /*Drive already set*/ - } - -/* The drive is not in the right mode, so we need to set it. -*/ - - zero_cmd(cmd); - cmd[0]=MODESELECT; /*Set drive transfer modes*/ -/* cmd[1]=BLOCKPARAM; BLOCKPARAM==0*/ - cmd[2]=mode; - switch(mode) { - case MODE_DATA: - cmd[3]=0x08; /*2048 bytes*/ - break; - case MODE_USER: - cmd[3]=0x09; /*2352 bytes*/ - cmd[4]=0x30; - break; - case MODE_DA: - cmd[3]=0x09; /*2352 bytes*/ - cmd[4]=0x30; - break; - } - i=0; - while(retries-- > 0) { - i=matcd_fastcmd(port,ldrive,cdrive,cmd); - get_stat(port,ldrive); /*Read and toss status byte*/ - if (i==0) { - cd->drivemode=mode; /*Set new mode*/ - return(i); - } - get_error(port,ldrive,cdrive); - } - cd->drivemode=MODE_UNKNOWN; /*We failed*/ - return(i); -} - - -/*--------------------------------------------------------------------------- - matcd_volinfo - Read information from disc Table of Contents ----------------------------------------------------------------------------*/ - -static int matcd_volinfo(int ldrive) -{ - struct matcd_data *cd; - int port,i; - int z,cdrive; - int retry; - unsigned char cmd[MAXCMDSIZ]; - unsigned char data[12]; - - retry=10; /*<16>This may take a long time*/ - cd = &matcd_data[ldrive]; - cdrive=ldrive&0x03; - port=cd->iobase; - -#ifdef DEBUGOPEN - printf("matcd%d: In volinfo, port %x\n",ldrive,port); -#endif /*DEBUGOPEN*/ - - while(retry>0) { - zero_cmd(cmd); - cmd[0]=READDINFO; /*Read Disc Info*/ - matcd_slowcmd(port,ldrive,cdrive,cmd); - i=waitforit(10*TICKRES,DTEN,port,"matvinf"); - if (i) { /*THIS SHOULD NOT HAPPEN*/ - z=get_stat(port,ldrive);/*Read status byte*/ - printf("matcd%d: command failed, status %x\n", - ldrive,z); - return(-1); - } - matcd_pread(port, 6, data); /*Read data returned*/ - z=get_stat(port,ldrive);/*Read status byte*/ -#ifdef DEBUGOPEN - printf("matcd%d: Data got was %x %x %x %x %x %x ",ldrive, - data[0],data[1],data[2], data[3],data[4],data[5]); - printf("status byte %x\n",z); -#endif /*DEBUGOPEN*/ - if ((z & MATCD_ST_ERROR)==0) - break; /*No Error*/ - -/* If media change or other error, you have to read error data or - the drive will reject subsequent commands. -*/ - - if (chk_error(get_error(port, ldrive, cdrive))==ERR_FATAL) { -#ifdef DEBUGOPEN - printf("matcd%d: command failed, status %x\n", - ldrive,z); -#endif /*DEBUGOPEN*/ - return(-1); - } - tsleep((caddr_t)&nextcontroller, PRIBIO, "matvi2", hz); - if ((--retry)==0) return(-1); -#ifdef DEBUGOPEN - printf("matcd%d: Retrying",ldrive); -#endif /*DEBUGOPEN*/ - } -#ifdef DEBUGOPEN - printf("matcd%d: Status port %x \n",ldrive,inb(port+STATUS)); -#endif /*DEBUGOPEN*/ - - cd->volinfo.type=data[0]; - cd->volinfo.trk_high=data[2]; - cd->volinfo.trk_low=data[1]; - cd->volinfo.vol_msf[0]=data[3]; - cd->volinfo.vol_msf[1]=data[4]; - cd->volinfo.vol_msf[2]=data[5]; - - if (cd->volinfo.trk_low + cd->volinfo.trk_high) { - cd->flags |= MATCDLABEL; - return(0); - } - return(-1); -} - - -/*--------------------------------------------------------------------------- - blk_to_msf - Convert block numbers into CD disk block ids ----------------------------------------------------------------------------*/ - -static void blk_to_msf(int blk, unsigned char *msf) -{ - blk=blk+150; /*2 seconds skip required to - reach ISO data*/ - msf[0]=blk/4500; - blk=blk%4500; - msf[1]=blk/75; - msf[2]=blk%75; - return; -} - - -/*--------------------------------------------------------------------------- - msf_to_blk - Convert CD disk block ids into block numbers ----------------------------------------------------------------------------*/ - -static int msf_to_blk(unsigned char * cd) -{ - return(((cd[0]*60) /*Convert MSF to*/ - +cd[1])*75 /*Blocks minus 2*/ - +cd[2]-150); /*seconds*/ -} - - -/*--------------------------------------------------------------------------- - matcd_blockread - Performs actual background disc I/O operations - - This routine is handed the block number to read, issues the - command to the drive, waits for it to complete, reads the - data or error, retries if needed, and returns the results - to the host. ----------------------------------------------------------------------------*/ - -static void matcd_blockread(int state) -{ - struct matcd_mbx *mbx; - int ldrive,cdrive; - int port, controller; - short iftype; - struct buf *bp; - struct matcd_data *cd; - int i; - struct matcd_read2 rbuf; - int blknum; - caddr_t addr; - int status; - int errtyp; - int phase; - unsigned char cmd[MAXCMDSIZ]; - - mbx = &matcd_data[state & 0x0f].mbx; - ldrive=mbx->ldrive; /*ldrive is logical drive #*/ - cdrive=ldrive & 0x03; /*cdrive is drive # on a controller*/ - port=mbx->port; /*port is base port for i/f*/ - iftype=mbx->iftype; - bp= mbx->bp; - cd=&matcd_data[ldrive]; - controller = cd->mbx.controller; - -#ifdef DEBUGIO - printf("matcd%d: Show state %x cdrive %d partition %d\n", - ldrive,state,cdrive,mbx->partition); -#endif /*DEBUGIO*/ - -loop: -#ifdef DEBUGIO - printf("matcd%d: Top dp %x\n",ldrive,(unsigned int)dp); -#endif /*DEBUGIO*/ - switch (state & 0xf0) { - case MATCD_READ_1: -#ifdef DEBUGIO - printf("matcd%d: State 1 cd->flags %x\n",ldrive,cd->flags); -#endif /*DEBUGIO*/ - /* to check for raw/cooked mode */ - if (cd->partflags[mbx->partition] & MATCDREADRAW) { - mbx->sz = MATCDRBLK; - i=matcd_setmode(ldrive, MODE_DA); -#ifdef DEBUGIO - printf("matcd%d: Set MODE_DA result %d\n",ldrive,i); -#endif /*DEBUGIO*/ - } else { - mbx->sz = cd->blksize; - i=matcd_setmode(ldrive, MODE_DATA); -#ifdef DEBUGIO - printf("matcd%d: Set MODE_DATA result %d\n",ldrive,i); -#endif /*DEBUGIO*/ - } - /*for first block*/ -#ifdef DEBUGIO - printf("matcd%d: A mbx %x bp %x b_bcount %x sz %x\n", - ldrive,(unsigned int)mbx,(unsigned int)bp, - (unsigned int)bp->b_bcount,mbx->sz); -#endif /*DEBUGIO*/ - mbx->nblk = (bp->b_bcount + (mbx->sz-1)) / mbx->sz; - mbx->skip=0; -nextblock: -#ifdef DEBUGIO - printf("matcd%d: at Nextblock b_blkno %d\n", - ldrive,(unsigned int)bp->b_blkno); -#endif /*DEBUGIO*/ - - blknum=(bp->b_blkno / (mbx->sz/DEV_BSIZE)) - + mbx->p_offset + mbx->skip/mbx->sz; - - blk_to_msf(blknum,rbuf.start_msf); - - zero_cmd(cmd); - cmd[0]=READ; /*Get drive ID*/ - cmd[1]=rbuf.start_msf[0]; - cmd[2]=rbuf.start_msf[1]; - cmd[3]=rbuf.start_msf[2]; - cmd[6]=1; /*Xfer only one block*/ - matcd_slowcmd(port,ldrive,cdrive,cmd); - -/* Now that we have issued the command, check immediately to - see if data is ready. The drive has read-ahead caching, so - it is possible the data is already in the drive buffer. - - If the data is not ready, schedule a wakeup and later on this - code will run again to see if the data is ready then. -*/ - - case MATCD_READ_2: - state=MATCD_READ_2+ldrive; - phase = (inb(port+STATUS)) & (DTEN|STEN); -#ifdef DEBUGIO - printf("matcd%d: In state 2 status %x ",ldrive,phase); -#endif /*DEBUGIO*/ - switch(phase) { - case (DTEN|STEN): /*DTEN==H STEN==H*/ -#ifdef DEBUGIO - printf("matcd%d: Sleeping\n",ldrive); -#endif /*DEBUGIO*/ - timeout((timeout_func_t)matcd_blockread, - (caddr_t)MATCD_READ_2+ldrive,hz/100); - return; - - - case STEN: /*DTEN=L STEN=H*/ - case 0: /*DTEN=L STEN=L*/ -#ifdef DEBUGIO - printf("matcd%d: Data Phase\n",ldrive); -#endif /*DEBUGIO*/ - addr=bp->b_un.b_addr + mbx->skip; -#ifdef DEBUGIO - printf("matcd%d: Xfer Addr %x size %x", - ldrive,(unsigned int)addr,mbx->sz); - i=0; /*<20>Reset read count*/ -#endif /*DEBUGIO*/ - if (iftype==0) { /*<20>Creative host I/F*/ - outb(port+PHASE,1); /*Enable data read*/ - while((inb(port+STATUS) & - (DTEN|STEN))==STEN) { - *addr++=inb(port+DATA); -#ifdef DEBUGIO - i++; -#endif /*DEBUGIO*/ - } - outb(port+PHASE,0); /*Disable read*/ - } else { /*<20>Not Creative interface*/ - while((inb(port+STATUS) & - (DTEN|STEN))==STEN) { - *addr++=inb(port+ALTDATA); -#ifdef DEBUGIO - i++; -#endif /*DEBUGIO*/ - } - } -#ifdef DEBUGIO - printf("matcd%d: Read %d bytes\n",ldrive,i); -#endif /*DEBUGIO*/ - - -/* Now, wait for the Status phase to arrive. This will also - tell us if any went wrong with the request. -*/ - while((inb(port+STATUS)&(DTEN|STEN)) != DTEN); - status=get_stat(port,ldrive); /*Read status byte*/ -#ifdef DEBUGIO - printf("matcd%d: Status port %x byte %x ", - ldrive,i,status); -#endif /*DEBUGIO*/ - if (status & MATCD_ST_ERROR) { - i=get_error(port,ldrive,cdrive); - printf("matcd%d: %s while reading block %d [Soft]\n", - ldrive,matcderrors[i],(int)bp->b_blkno); - media_chk(cd,i,ldrive,0);/*<14>was wrong place*/ - } - - if (--mbx->nblk > 0) { - mbx->skip += mbx->sz; - goto nextblock; /*Oooooh, you flunk the course*/ - } - bp->b_resid=0; - biodone(bp); /*Signal transfer complete*/ - - unlockbus(ldrive>>2, ldrive); /*Release bus lock*/ - matcd_start(controller);/*See if other drives have work*/ - return; - -/* Here we skipped the data phase and went directly to status. - This indicates a hard error. -*/ - - case DTEN: /*DTEN=H STEN=L*/ - status=get_stat(port,ldrive); /*Read status byte*/ -#ifdef DEBUGIO - printf("matcd%d: error, status was %x\n", - ldrive,status); -#endif /*DEBUGIO*/ - -/* Ok, we need more details, so read error. This is needed to issue - any further commands anyway -*/ - - errtyp=get_error(port,ldrive,cdrive); - printf("matcd%d: %s while reading block %d\n", - ldrive,matcderrors[errtyp],(int)bp->b_blkno); - - if (media_chk(cd,errtyp,ldrive,0)==0) { - errtyp=chk_error(errtyp); - if (errtyp==ERR_RETRY) {/*<14>We can retry*/ - /*<14>this error but the drive*/ - /*<14>probably has already*/ - if (mbx->retry-- > 0 ) { - state=MATCD_READ_1+ldrive; -#ifdef DEBUGIO - printf("matcd%d: Attempting retry\n", - ldrive); -#endif /*DEBUGIO*/ - goto loop; - } - } - } -/*<14> The other error types are either something very bad or the media -<14> has been removed by the user. In both cases there is no retry -<14> for this call. We will invalidate the label in both cases. -*/ - bp->b_flags |= B_ERROR; - bp->b_resid = bp->b_bcount; - biodone(bp); - unlockbus(ldrive>>2, ldrive); - matcd_start(controller); - return; - } - } -} - - -/*--------------------------------------------------------------------------- - docmd - Get the bus, do the command, wait for completion, - attempt retries, give up the bus. - For commands that do not return data. ----------------------------------------------------------------------------*/ - -int docmd(char * cmd, int ldrive, int cdrive, int controller, int port) -{ - int retries,i,z; - - lockbus(controller, ldrive); /*Request bus*/ - retries=3; - while(retries-- > 0) { - matcd_slowcmd(port,ldrive,cdrive,cmd); - i=waitforit(80*TICKRES,DTEN,port,"matcmd"); - z=get_stat(port,ldrive);/*Read status byte*/ - if ((z & MATCD_ST_ERROR)==0) break; - i=chk_error(get_error(port,ldrive,cdrive)); - if (i!=ERR_INIT) { - unlockbus(controller, ldrive); /*Release bus*/ - return(EFAULT); - } - } - unlockbus(controller, ldrive); /*Release bus*/ - return(i); -} - - -/*--------------------------------------------------------------------------- - get_error - Read the error that aborted a command. - Created in Edit 6 ----------------------------------------------------------------------------*/ - -int get_error(int port, int ldrive, int cdrive) -{ - int status,errnum; - unsigned char cmd1[MAXCMDSIZ]; - unsigned char data[12]; - - zero_cmd(cmd1); - cmd1[0]=READERROR; /*Enquire*/ - matcd_fastcmd(port,ldrive,cdrive,cmd1); - matcd_pread(port, 8, data); /*Read data returned*/ - errnum=data[2]; /*Caller wants it classified*/ - status=get_stat(port,ldrive); /*Read status byte*/ - -#ifdef DEBUGCMD - printf("matcd%d: Chkerror found %x on command %x addrval %x statusdata %x statusport %x\n", - ldrive,errnum,data[1],data[0],status,inb(port+STATUS)); -#endif /*DEBUGCMD*/ - return(errnum); -} - - -/*--------------------------------------------------------------------------- - chk_error - Classify the error that the drive reported - Created in Edit 6 ----------------------------------------------------------------------------*/ - -int chk_error(int errnum) -{ - switch(errnum) { -/* These are errors we can attempt a retry for, although the drive - has already done so. -*/ - case UNRECV_ERROR: - case SEEK_ERROR: - case TRACK_ERROR: - case FOCUS_ERROR: - case CLV_ERROR: - case DATA_ERROR: - case MODE_ERROR: /*<16>Make this retryable*/ - return(ERR_RETRY); - -/* These errors usually indicate the user took the media from the - drive while the dev was open. We will invalidate the unit - until it closes when we see this. -*/ - case NOT_READY: - case MEDIA_CHANGED: - case DISC_OUT: - case HARD_RESET: - return (ERR_INIT); - -/* These errors indicate the system is confused about the drive - or media, and point to bugs in the driver or OS. These errors - cannot be retried since you will always get the same error. -*/ - - case RAM_ERROR: - case DIAG_ERROR: - case CDB_ERROR: - case END_ADDRESS: - case ILLEGAL_REQ: - case ADDRESS_ERROR: - default: - return (ERR_FATAL); - } -} - - -/*--------------------------------------------------------------------------- - get_stat - Reads status byte - - This routine should be totally unnecessary, performing the - task with a single line of in-line code. However in special - cases, the drives return blocks of data that are not associated - with the command in question. This appears to be at least one - firmware error and the rest of the driver makes an effort to avoid - triggering the fault. However, reading and throwing this - bogus data is faster and less destructive than resetting all - the drives on a given controller, plus it leaves the other drives - unaffected. ----------------------------------------------------------------------------*/ - -int get_stat(int port,int ldrive) -{ - int status,busstat; - - status=inb(port+DATA); /*Read status byte, last step of cmd*/ - busstat=inb(port+STATUS); /*<16>Get bus status - should be 0xff*/ - while ((busstat & (DTEN|STEN)) != (DTEN|STEN)) { - printf("matcd%d: get_stat: After reading status byte, bus didn't go idle %x %x %x\n",ldrive,status,busstat,port); - if (( busstat & (DTEN|STEN)) == STEN) { - int k; - k=0; -#ifdef DEBUGCMD - printf("matcd%d: DATA PRESENT!!!! DISCARDING\n",ldrive); -#endif /*DEBUGCMD*/ - outb(port+PHASE,1); /*Enable data read*/ - while ((inb(port+STATUS) & (DTEN|STEN)) == STEN) { - inb(port+DATA); - inb(port+ALTDATA); -/* printf("%2x ",inb(port+DATA));*/ - k++; - } - outb(port+PHASE,0); -#ifdef DEBUGCMD - printf("\nmatcd%d: BYTES READ IN DATA was %d\n", - ldrive,k); -#endif /*DEBUGCMD*/ - } - status=inb(port+DATA); /*Read the status byte again*/ -#ifdef DEBUGCMD - printf("matcd%d: Next status byte is %x\n",ldrive,status); -#endif /*DEBUGCMD*/ - busstat=inb(port+STATUS); - } - return(status); -} - - -/*--------------------------------------------------------------------------- - waitforit - Waits for a command started by slowcmd to complete. ----------------------------------------------------------------------------*/ - -int waitforit(int timelimit, int state, int port, char * where) -{ - int i,j; - - j=i=0; -#ifdef DEBUGCMD - printf("matcd: waitforit port %x timelimit %x hz %x\n", - port,timelimit,hz); -#endif /*DEBUGCMD*/ - while (i<timelimit) { - j=inb(port+STATUS) & (STEN|DTEN); /*Read status*/ - if (j!=(STEN|DTEN)) break; - tsleep((caddr_t)&nextcontroller, PRIBIO, where, hz/100); - i++; - } -#ifdef DEBUGCMD - printf("matcd: Count was %d\n",i); -#endif /*DEBUGCMD*/ - if (j==state) return(0); /*Command complete*/ -#ifdef DEBUGCMD - printf("matcd: Timeout!"); -#endif /*DEBUGCMD*/ - return(1); /*Timeout occurred*/ -} - - -/*--------------------------------------------------------------------------- - lockbus - Wait for the bus on the requested driver interface - to go idle and acquire it. - Created in Edit 6 ----------------------------------------------------------------------------*/ - -void lockbus(int controller, int ldrive) -{ - while ((if_state[controller] & BUSBUSY)) { -#ifdef DEBUGSLEEP - printf("matcd%d: Can't do it now - going to sleep\n", - ldrive); -#endif /*DEBUGSLEEP*/ - tsleep((caddr_t)&matcd_data->status, PRIBIO, - "matlck", 0); - } - if_state[controller] |= BUSBUSY; /*<18>It's ours NOW*/ -#ifdef DEBUGSLEEP - printf("matcd%d: BUS locked in lockbus\n",ldrive); -#endif /*DEBUGSLEEP*/ -} - - -/*--------------------------------------------------------------------------- - unlockbus - Release the host interface bus we already have so - someone else can use it. - Created in Edit 6 ----------------------------------------------------------------------------*/ - -void unlockbus(int controller, int ldrive) -{ - if_state[controller] &= ~BUSBUSY; -#ifdef DEBUGSLEEP - printf("matcd%d: bus unlocked\n",ldrive); -#endif /*DEBUGSLEEP*/ - wakeup((caddr_t)&matcd_data->status); /*Wakeup other users*/ - matcd_start(controller); /*Wake up any block I/O*/ -} - - -/*--------------------------------------------------------------------------- - media_chk - Checks error for types related to media - changes. ----------------------------------------------------------------------------*/ - -int media_chk(struct matcd_data *cd,int errnum,int ldrive,int test) -{ - if (errnum==NOT_READY || - errnum==MEDIA_CHANGED || - errnum==HARD_RESET || - errnum==DISC_OUT) { - cd->flags &= ~MATCDLABEL; /*Mark label as invalid*/ - if (test==0) { /*<14>Do warn by default*/ - - if ((cd->flags & MATCDWARN)==0) {/*<14>Msg already?*/ - printf("matcd%d: Media changed - Further I/O aborted until device closed\n",ldrive); - cd->flags |= MATCDWARN; - } - } - return(1); - } - if (errnum==MODE_ERROR) /*<16>Maybe the setting is*/ - cd->drivemode=MODE_UNKNOWN; /*<16>wrong so force a reset*/ - return(0); -} - - -/*--------------------------------------------------------------------------- - matcd_eject - Open drive tray ----------------------------------------------------------------------------*/ - -int matcd_eject(int ldrive, int cdrive, int controller) -{ - int i,port; - struct matcd_data *cd; - unsigned char cmd[MAXCMDSIZ]; - - cd=&matcd_data[ldrive]; - port=cd->iobase; /*Get I/O port base*/ - -#ifdef LOCKDRIVE - if (cd->flags & MATCDLOCK) { /*<15>Drive was locked via open*/ - return(EINVAL); /*<15>so don't allow the eject*/ - } -#endif /*LOCKDRIVE*/ - zero_cmd(cmd); /*Initialize command buffer*/ - cmd[0]=LOCK; /*Unlock drive*/ - i=docmd(cmd,ldrive,cdrive,controller,port); /*Issue command*/ - cmd[0]=DOOROPEN; /*Open Door*/ - i=docmd(cmd,ldrive,cdrive,controller,port); /*Issue command*/ - cd->flags &= ~(MATCDLABEL|MATCDLOCK); /*<15>Mark vol info invalid*/ - return(i); /*Return result we got*/ -} - - -/*--------------------------------------------------------------------------- - matcd_doorclose - Close drive tray -<16> Added in Edit 16 ----------------------------------------------------------------------------*/ - -int matcd_doorclose(int ldrive, int cdrive, int controller) -{ - int i,port; - struct matcd_data *cd; - unsigned char cmd[MAXCMDSIZ]; - - cd=&matcd_data[ldrive]; - port=cd->iobase; /*Get I/O port base*/ - - zero_cmd(cmd); /*Initialize command buffer*/ - cmd[0]=DOORCLOSE; /*Open Door*/ - i=docmd(cmd,ldrive,cdrive,controller,port); /*Issue command*/ - cd->flags &= ~(MATCDLABEL|MATCDLOCK); /*Mark vol info invalid*/ - tsleep((caddr_t)&nextcontroller, PRIBIO, "matclos", hz); - return(i); /*Return result we got*/ -} - - -/*--------------------------------------------------------------------------- -<23> matcd_dlock - Honor/Reject drive tray requests ----------------------------------------------------------------------------*/ - -int matcd_dlock(int ldrive, int cdrive, int controller, int action) -{ - int i,port; - struct matcd_data *cd; - unsigned char cmd[MAXCMDSIZ]; - - cd=&matcd_data[ldrive]; - port=cd->iobase; /*<23>Get I/O port base*/ - - zero_cmd(cmd); /*<23>Initialize command buffer*/ - cmd[0]=LOCK; /*<23>Unlock drive*/ - - if (action) { /*<23>They want to lock the door?*/ - cd->flags |= MATCDLOCK; /*<23>Remember we did this*/ - cmd[1]=1; /*<23>Lock Door command*/ - } else { - cd->flags &= ~MATCDLOCK;/*<23>Remember we did this*/ - /*<23>Unlock Door command*/ - } - i=docmd(cmd,ldrive,cdrive,controller,port); /*<23>Issue command*/ - return(i); /*<23>Return result we got*/ -} - - -/*--------------------------------------------------------------------------- - matcd_toc_header - Return Table of Contents header to caller -<13> New for Edit 13 ----------------------------------------------------------------------------*/ - -static int matcd_toc_header(int ldrive, int cdrive, int controller, - struct ioc_toc_header * toc) -{ - struct matcd_data *cd; - - cd=&matcd_data[ldrive]; - if ((cd->flags & MATCDLABEL)==0) - return(EIO); /*Refuse after chg error*/ - - toc->len=msf_to_blk(cd->volinfo.vol_msf); /*In frames*/ - toc->starting_track=cd->volinfo.trk_low; /*1*/ - toc->ending_track=cd->volinfo.trk_high; /*Last track*/ - - return(0); - -} - - -/*--------------------------------------------------------------------------- - matcd_toc_entries - Read all of the TOC entries - - These entries are cached by the drive, but it might be worth - the space investment to have the driver cache these as well. - For a disc with 40 tracks, it means 41 command calls to get - this information from the drive. -<13> New for Edit 13 ----------------------------------------------------------------------------*/ - -static int matcd_toc_entries(int ldrive, int cdrive, int controller, - struct ioc_read_toc_entry * ioc_entry) -{ - struct matcd_data *cd; - struct cd_toc_entry entries[MAXTRKS]; - struct cd_toc_entry *from; - struct cd_toc_entry *to; - int len,trk,i,z,port; - unsigned char cmd[MAXCMDSIZ]; - unsigned char data[5]; - - cd=&matcd_data[ldrive]; - port=cd->iobase; - - if ((cd->flags & MATCDLABEL)==0) - return(EIO); /*Refuse after chg error*/ - - zero_cmd(cmd); - cmd[0]=READTOC; - - for(trk=cd->volinfo.trk_low-1; trk<cd->volinfo.trk_high; trk++) { - cmd[2]=trk+1; - lockbus(controller, ldrive); /*Request bus*/ - matcd_slowcmd(port,ldrive,cdrive,cmd); - i=waitforit(10*TICKRES,DTEN,port,"mats1"); - matcd_pread(port, 8, data); /*Read data returned*/ - z=get_stat(port,ldrive); /*Read status byte*/ - if ((z & MATCD_ST_ERROR)) { /*Something went wrong*/ - i=get_error(port, ldrive, cdrive); - unlockbus(controller, ldrive); /*Release bus*/ - return(EIO); - } - unlockbus(controller, ldrive); /*Release bus*/ - -#ifdef DEBUGIOCTL - printf("Track %d addr/ctrl %x m %x s %x f %x\n",data[2], - data[1],data[4],data[5],data[6]); -#endif /*DEBUGIOCTL*/ - - entries[trk].control=data[1]; /*Track type*/ - entries[trk].addr_type=ioc_entry->address_format;/*Type*/ - entries[trk].track=data[2]; /*Track #, can be Out of Order*/ - if (ioc_entry->address_format == CD_MSF_FORMAT) { - entries[trk].addr.msf.unused=0; - entries[trk].addr.msf.minute=data[4]; /*Min*/ - entries[trk].addr.msf.second=data[5]; /*Sec*/ - entries[trk].addr.msf.frame=data[6]; /*Frame*/ - } - } - entries[trk].control=data[2]; /*Copy from last valid track*/ - entries[trk].track=0xaa; /*<23>Lead-out*/ - entries[trk].addr.msf.unused=0; /*Fill*/ - entries[trk].addr.msf.minute=cd->volinfo.vol_msf[0]; - entries[trk].addr.msf.second=cd->volinfo.vol_msf[1]; - entries[trk].addr.msf.frame=cd->volinfo.vol_msf[2]; - trk++; /*Bump to include leadout track*/ - - -/* Now that we have read all the data from the drive, copy the - array from the kernel address space into the user address space -*/ - - len=ioc_entry->data_len; - i=ioc_entry->starting_track; /*<23>What did they want?*/ - if (i==0xaa) i=trk-1; /*<23>Give them lead-out info*/ - else i=ioc_entry->starting_track - 1; /*<23>start where they asked*/ - from = &entries[i]; - to = ioc_entry->data; - - while (i < trk && len >= sizeof(struct cd_toc_entry)) { - if (copyout(from,to,sizeof(struct cd_toc_entry)) - != 0) { - return (EFAULT); - } - i++; - len -= sizeof(struct cd_toc_entry); - from++; - to++; - } - return(0); - -} - -/*--------------------------------------------------------------------------- - matcd_subq - Read the Sub-Q packet - (where are we?) - - This call gives a snapshot state of where the optical - pick-up is when the command is issued. -<14> New for Edit 14 ----------------------------------------------------------------------------*/ - -static int matcd_read_subq(int ldrive, int cdrive, int controller, - struct ioc_read_subchannel * sqp) -{ - struct matcd_data *cd; - int i,z,port; - unsigned char cmd[MAXCMDSIZ]; - unsigned char data[12]; - struct cd_sub_channel_info subq; /*Build result here*/ - - cd=&matcd_data[ldrive]; - port=cd->iobase; - - if ((cd->flags & MATCDLABEL)==0) - return(EIO); /*Refuse after chg error*/ - -/* We only support the ioctl functions we could get information - on, so test for the things we can do -*/ - - if (sqp->data_format!=CD_CURRENT_POSITION || - sqp->address_format!=CD_MSF_FORMAT) { - return(EINVAL); - } - - zero_cmd(cmd); - cmd[0]=READSUBQ; - lockbus(controller, ldrive); /*Request bus*/ - matcd_slowcmd(port,ldrive,cdrive,cmd); - -/* While we wait, fill in the hard-coded entries of the table*/ - - subq.what.position.data_format=CD_MSF_FORMAT; - subq.what.position.absaddr.msf.unused=0; - subq.what.position.reladdr.msf.unused=0; - - i=waitforit(10*TICKRES,DTEN,port,"mats2"); - matcd_pread(port, 11, data); /*Read data returned*/ - z=get_stat(port,ldrive); /*Read status byte*/ - if ((z & MATCD_ST_ERROR)) { /*Something went wrong*/ - i=get_error(port, ldrive, cdrive); - unlockbus(controller, ldrive); /*Release bus*/ - return(EIO); - } - unlockbus(controller, ldrive); /*Release bus*/ - -#ifdef DEBUGIOCTL - printf("Subq track %d index %d adr/ctl %x abs %d:%2d:%2d rel %d:%2d:%2d UPC %x\n", - data[2],data[3],data[1],data[4],data[5],data[6], - data[7],data[8],data[9],data[10]); -#endif /*DEBUGIOCTL*/ - - if (z & MATCD_ST_AUDIOBSY) { /*Drive playing or paused*/ - if (cd->status==CD_AS_PLAY_PAUSED) { /*Have we issued*/ - i=cd->status; /*a pause command?*/ - } else { - i=CD_AS_PLAY_IN_PROGRESS;/*No, we really are playing*/ - } - } else { - if (cd->status==CD_AS_PLAY_IN_PROGRESS) {/*It was playing*/ - i=CD_AS_PLAY_COMPLETED; /*so it finished*/ - } else { /*Any other status reported*/ - i=cd->status; /*as we get it*/ - } - } - - subq.header.audio_status=cd->status=i; /*Store status we selected*/ - - subq.what.position.track_number=data[2]; - subq.what.position.index_number=data[3]; - - subq.what.position.absaddr.msf.minute=data[4]; - subq.what.position.absaddr.msf.second=data[5]; - subq.what.position.absaddr.msf.frame=data[6]; - - subq.what.position.reladdr.msf.minute=data[7]; - subq.what.position.reladdr.msf.second=data[8]; - subq.what.position.reladdr.msf.frame=data[9]; - -/* Ok, now copy our nicely-built structure from the kernel address - space into the user address space (we hope) -*/ - - if (copyout(&subq, sqp->data, - min(sizeof(struct cd_sub_channel_info), sqp->data_len))!=0) { - return(EFAULT); - } - return(0); -} - -/*--------------------------------------------------------------------------- - matcd_igot - Like the song, report the capabilities that the - drive/driver has available. - - This call returns a structure of flags indicating what - functions are available so that the application can offer - only the functions the drive is actually capable of. -<16> New for Edit 16 ----------------------------------------------------------------------------*/ - -static int matcd_igot(struct ioc_capability * sqp) -{ - -#ifdef FULLDRIVER - sqp->play_function=(CDDOPLAYTRK | /*Can play trks/indx*/ - CDDOPLAYMSF | /*Can play msf to msf*/ - CDDOPAUSE | /*Can pause playback*/ - CDDORESUME | /*Can resume playback*/ - CDDOSTOP | /*Can stop playback*/ - CDDOPITCH); /*Can change play pitch*/ - - sqp->routing_function=(CDREADVOLUME | /*Can read volume*/ - CDSETVOLUME | /*Can set volume*/ - CDSETSTEREO | /*Can select stereo play*/ - CDSETLEFT | /*Can select left-only*/ - CDSETRIGHT | /*Can select right-only*/ - CDSETMUTE | /*Can mute audio*/ - CDSETPATCH); /*Direct patch settings*/ -#else /*FULLDRIVER*/ - sqp->play_function=0; /*No audio capability*/ - sqp->routing_function=0; /*No audio capability*/ -#endif /*FULLDRIVER*/ - - sqp->special_function=(CDDOEJECT | /*Door can be opened*/ - CDDOCLOSE | /*Door can be closed*/ - CDDOLOCK | /*Door can be locked*/ - CDREADSUBQ | /*Can read subchannel*/ - CDREADENTRIES | /*Can read TOC entries*/ - CDREADHEADER); /*Can read TOC*/ - return(0); -} - - -#ifdef FULLDRIVER -#include "i386/isa/matcd/audio.c" /*<15>ioctls related to - audio are here*/ -#endif /*FULLDRIVER*/ - - -static matcd_devsw_installed = 0; - -static void -matcd_drvinit(void *unused) -{ - - if( ! matcd_devsw_installed ) { - bdevsw_add_generic(BDEV_MAJOR,CDEV_MAJOR, &matcd_bdevsw); - matcd_devsw_installed = 1; - } -} - -SYSINIT(matcddev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,matcd_drvinit,NULL) - - -/*End of matcd.c*/ - diff --git a/sys/pc98/pc98/matcd/options.h b/sys/pc98/pc98/matcd/options.h deleted file mode 100644 index 62d2e2b..0000000 --- a/sys/pc98/pc98/matcd/options.h +++ /dev/null @@ -1,283 +0,0 @@ -/*options.h-------------------------------------------------------------------- - - Matsushita(Panasonic) / Creative CD-ROM Driver (matcd) - Authored by Frank Durda IV - - Copyright 1994, 1995 Frank Durda IV. All rights reserved. - "FDIV" is a trademark of Frank Durda IV. - - - Redistribution and use in source and binary forms, with or - without modification, are permitted provided that the following - conditions are met: - 1. Redistributions of source code must retain the above copyright - notice positioned at the very beginning of this file without - modification, all copyright strings, all related programming - codes that display the copyright strings, this list of - conditions and the following disclaimer. - 2. Redistributions in binary form must contain all copyright strings - and related programming code that display the copyright strings. - 3. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - 4. All advertising materials mentioning features or use of this - software must display the following acknowledgement: - "The Matsushita/Panasonic CD-ROM driver was developed - by Frank Durda IV for use with "FreeBSD" and similar - operating systems." - "Similar operating systems" includes mainly non-profit oriented - systems for research and education, including but not restricted - to "NetBSD", "386BSD", and "Mach" (by CMU). The wording of the - acknowledgement (in electronic form or printed text) may not be - changed without permission from the author. - 5. Absolutely no warranty of function, fitness or purpose is made - by the author Frank Durda IV. - 6. Neither the name of the author nor the name "FreeBSD" may - be used to endorse or promote products derived from this software - without specific prior written permission. - (The author can be reached at bsdmail@nemesis.lonestar.org) - 7. The product containing this software must meet all of these - conditions even if it is unsupported, not a complete system - and/or does not contain compiled code. - 8. These conditions will be in force for the full life of the - copyright. - 9. If all the above conditions are met, modifications to other - parts of this file may be freely made, although any person - or persons making changes do not receive the right to add their - name or names to the copyright strings and notices in this - software. Persons making changes are encouraged to insert edit - history in matcd.c and to put your name and details of the - change there. - 10. You must have prior written permission from the author to - deviate from these terms. - - Vendors who produce product(s) containing this code are encouraged - (but not required) to provide copies of the finished product(s) to - the author and to correspond with the author about development - activity relating to this code. Donations of development hardware - and/or software are also welcome. (This is one of the faster ways - to get a driver developed for a device.) - - THIS SOFTWARE IS PROVIDED BY THE DEVELOPER(S) ``AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE DEVELOPER(S) BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - ------No changes are allowed above this line------------------------------------ ------------------------------------------------------------------------------ - Conditional compilation flags - change to suit your system ----------------------------------------------------------------------------*/ - -/* AUTOHUNT Adds extra code that allows the driver to search - for interface cards rather than having to hard-code - the locations in the kernel conf file. - Leaving AUTOHUNT enabled is the recommended setting. -*/ - -#define AUTOHUNT - - -/* NUMCTRLRS Configures support for between one and four - host interfaces, for up to 16 drives. - The number of entries in the kernel config - file is used by default, but this may be changed - to a specific value if desired. - - Leaving NUMCTRLRS based on NMATCD is the - recommended setting. -*/ - -#if NMATCD >= 4 -#define NUMCTRLRS 4 /*Limit driver to four host interfaces*/ -#else /*NMATCD*/ -#define NUMCTRLRS NMATCD -#endif /*NMATCD*/ - - -/* FULLDRIVER If not set, the audio, non-data functions and - some error recovery functions are eliminated from - the compiled driver. The resulting driver will be - smaller and may help a kernel fit on a boot floppy. - Leaving FULLDRIVER enabled is the recommended setting. -*/ - -#ifndef BOOTMFS -#define FULLDRIVER -#endif /*BOOTMFS*/ - - -/* RESETONBOOT causes the driver to reset the drive(s) to be - reset during probing. This causes any audio - playback to be aborted and the drives will close - their trays if they are open. - Leaving RESETONBOOT enabled is the recommended setting. -*/ - -#define RESETONBOOT - - -/*<15> LOCKDRIVE If enabled, when a drive is opened using a -<15> minor number greater than 127, the drive door is -<15> locked. The drive door remains locked until all -<23> partitions on the drive are closed. The EJECT, -<23> ALLOW and PREVENT ioctls are refused when this locking -<23> mechanism is active. -<15> The additional code size is small so enabling -<15> LOCKDRIVE is the recommended setting. -*/ - -#define LOCKDRIVE - - -/*<14> KRYTEN This enables a bug that someone might consider -<14> to be a feature. If KRYTEN is enabled and you are -<14> playing audio and you issue the resume-play ioctl, -<14> the audio will stutter, playing the same quarter -<14> of a second or so of audio several times before -<14> resuming normally. Resuming from a pause acts -<14> normally regardless of the setting of this flag. -<14> Leaving KRYTEN disabled is the recommended setting. -<14>*/ - -/*#define KRYTEN*/ - - -/*--------------------------------------------------------------------------- - This structure contains the hints for where we should look for the - host adapter. If you want to change where we search or reduce the - places we search to avoid confusing some other device, either - specify explicit addresses in the kernel config file (preferred) - or change this array. - - If the kernel config file has multiple ? entries, the probe routines - will use this table multiple times and will eliminate each failed - entry that probe tries. - - WARNING: The number of controller entries for this driver in config - must be less than or equal to the number of hints if hints are used. - - If you add entries to the table, add them immediately before - the -1 end-of-table marker. The values already present are - the ones used by Creative Labs boards and those of a few - other vendors. - - Each additional entry increases the boot time by four seconds, - and can increase the chance of accessing some other device. - Therefore, the list should be kept to a minimum. Once the - devices have been correctly located, the kernel should be - configured so that it looks only at the correct location from - that point on. - - Be sure to search devices located below 0x3ff BEFORE scanning - higher locations. Some boards don't decode all I/O address lines, - so 0x230 and 0x630 appear identical. ----------------------------------------------------------------------------*/ - -#ifdef AUTOHUNT -static int port_hints[]={ -#ifdef PC98 - 0x30d2, - 0x30d0, - 0x30d4, - 0x30d6, - 0x30d8, - 0x30da, - 0x30dc, - 0x30de, -#else - 0x230, /*SB Pro & SB16*/ - 0x240, /*SB Pro & SB16*/ - 0x250, /*Creative omniCD standalone boards*/ - 0x260, /*Creative omniCD standalone boards*/ - 0x340, /*Laser Mate*/ - 0x360, /*Laser Mate*/ - 0x630, /*IBM*/ -#if 0 -/* These locations are alternate settings for LaserMate and IBM - boards, but they usually conflict with network and SCSI cards. - I recommend against probing these randomly. -*/ - 0x310, /*Laser Mate*/ - 0x320, /*Laser Mate*/ - 0x330, /*Laser Mate*/ - 0x350, /*Laser Mate*/ - 0x370, /*Laser Mate*/ - 0x650, /*IBM*/ - 0x670, /*IBM*/ - 0x690, /*IBM*/ -#endif /*0*/ -#endif - -1}; /*use. Table MUST end with -1*/ -#endif /*AUTOHUNT*/ - - -/*--------------------------------------------------------------------------- - Debugging flags - Turn these on only if you are looking at a - problem. ----------------------------------------------------------------------------*/ - -/* DEBUGOPEN If enabled, debug messages for open and close - operations. -*/ - -/*#define DEBUGOPEN*/ - - -/* DEBUGIO If enabled, reports on calls to strategy, start - and other I/O related functions. -*/ - -/*#define DEBUGIO*/ - - -/* DEBUGQUEUE If enabled, shows activity on disk request queues. - Warning - This debug is VERY VERY NOISY and will - loop endlessly if queues are not null terminated - as they should be. -*/ - -/*#define DEBUGQUEUE*/ - - -/* DEBUGCMD If enabled, shows the actual commands being issued - to the CD-ROM drives. -*/ - -/*#define DEBUGCMD*/ - - -/* DEBUGSLEEP If enabled, reports on timeouts, wakeups, dropped - threads, etc. -*/ - -/*#define DEBUGSLEEP*/ - - -/* DEBUGIOCTL If enabled, reports on the various ioctl-related - calls and operations. You might have to enable - DEBUGCMD as well to get enough debugging information. -*/ - -/*#define DEBUGIOCTL*/ - - -/* DEBUGPROBE If enabled, reports on the process of locating - adapters and drives. The debugging in matcdprobe() - and matcdattach() routines is enabled with this - flag. -*/ - -/*#define DEBUGPROBE*/ - - -/*End of options.h*/ - diff --git a/sys/pc98/pc98/mse.c b/sys/pc98/pc98/mse.c index 871a564..9ffaafc 100644 --- a/sys/pc98/pc98/mse.c +++ b/sys/pc98/pc98/mse.c @@ -11,7 +11,7 @@ * this software for any purpose. It is provided "as is" * without express or implied warranty. * - * $Id: mse.c,v 1.4 1996/09/07 02:13:57 asami Exp $ + * $Id: mse.c,v 1.5 1996/09/10 09:38:15 asami Exp $ */ /* * Driver for the Logitech and ATI Inport Bus mice for use with 386bsd and @@ -662,17 +662,7 @@ mse_probe98m(idp) /* initialize */ outb(msport + INT, INT_DISABLE); /* INT disable */ outb(msport + HC, HC_NO_CLEAR); /* HC = 0 */ -#if 0 - if (inb(msport + PORT_C) & 0x80 != 0) { - return (0); - } -#endif outb(msport + HC, HC_CLEAR); /* HC = 1 */ -#if 0 - if (inb(msport + PORT_C) & 0x80 == 0) { - return (0); - } -#endif return (1); } diff --git a/sys/pc98/pc98/pc98.h b/sys/pc98/pc98/pc98.h index 84c77b4..6a369f7 100644 --- a/sys/pc98/pc98/pc98.h +++ b/sys/pc98/pc98/pc98.h @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)isa.h 5.7 (Berkeley) 5/9/91 - * $Id: pc98.h,v 1.5 1996/10/09 21:46:34 asami Exp $ + * $Id: pc98.h,v 1.6 1996/10/23 07:25:22 asami Exp $ */ #ifndef _PC98_PC98_PC98_H_ @@ -73,7 +73,7 @@ #define IO_NMI 0x050 /* NMI Control */ #define IO_WAIT 0x05F /* WAIT 0.6 us */ #define IO_GDC1 0x060 /* 7220 GDC Text Control */ -#define IO_TIMER 0x071 /* 8253C Timer */ +#define IO_TIMER1 0x071 /* 8253C Timer */ #define IO_SASI 0x080 /* SASI Hard Disk Controller */ #define IO_FD1 0x090 /* 765A 1MB FDC */ #define IO_GDC2 0x0a0 /* 7220 GDC Graphic Control */ diff --git a/sys/pc98/pc98/pcaudio.c b/sys/pc98/pc98/pcaudio.c index 10d5232..2b5c4c7 100644 --- a/sys/pc98/pc98/pcaudio.c +++ b/sys/pc98/pc98/pcaudio.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: pcaudio.c,v 1.5 1996/09/10 09:38:24 asami Exp $ + * $Id: pcaudio.c,v 1.6 1996/10/09 21:46:40 asami Exp $ */ #include "pca.h" @@ -35,8 +35,7 @@ #include <sys/systm.h> #include <sys/conf.h> #include <sys/uio.h> -#include <sys/ioctl.h> -#include <sys/file.h> +#include <sys/fcntl.h> #include <sys/proc.h> #include <sys/kernel.h> @@ -45,18 +44,14 @@ #ifdef PC98 #include <pc98/pc98/pc98.h> -#include <i386/isa/isa_device.h> -#include <pc98/pc98/timerreg.h> - -#include <pc98/pc98/sound/ulaw.h> #else #include <i386/isa/isa.h> +#endif #include <i386/isa/isa_device.h> #include <i386/isa/timerreg.h> #define DSP_ULAW_NOT_WANTED #include <i386/isa/sound/ulaw.h> -#endif #ifdef DEVFS #include <sys/devfsext.h> @@ -97,7 +92,7 @@ static void *pcac_devfs_token; static int pca_sleep = 0; static int pca_initialized = 0; -void pcaintr(struct clockframe *frame); +static void pcaintr(struct clockframe *frame); static int pcaprobe(struct isa_device *dvp); static int pcaattach(struct isa_device *dvp); @@ -121,7 +116,8 @@ static void pca_continue __P((void)); static void pca_init __P((void)); static void pca_pause __P((void)); -static inline void conv(const void *table, void *buff, unsigned long n) +static inline void +conv(const void *table, void *buff, unsigned long n) { __asm__("1:\tmovb (%2), %3\n" "\txlatb\n" @@ -152,7 +148,7 @@ pca_volume(int volume) static void -pca_init() +pca_init(void) { pca_status.open = 0; pca_status.queries = 0; @@ -233,7 +229,7 @@ pca_stop(void) static void -pca_pause() +pca_pause(void) { int x = splhigh(); @@ -249,7 +245,7 @@ pca_pause() static void -pca_continue() +pca_continue(void) { int x = splhigh(); @@ -313,7 +309,7 @@ pcaattach(struct isa_device *dvp) } -static int +static int pcaopen(dev_t dev, int flags, int fmt, struct proc *p) { /* audioctl device can always be opened */ @@ -341,7 +337,7 @@ pcaopen(dev_t dev, int flags, int fmt, struct proc *p) } -static int +static int pcaclose(dev_t dev, int flags, int fmt, struct proc *p) { /* audioctl device can always be closed */ @@ -357,7 +353,7 @@ pcaclose(dev_t dev, int flags, int fmt, struct proc *p) } -static int +static int pcawrite(dev_t dev, struct uio *uio, int flag) { int count, error, which, x; @@ -403,7 +399,7 @@ pcawrite(dev_t dev, struct uio *uio, int flag) } -static int +static int pcaioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p) { audio_info_t *auptr; @@ -467,7 +463,7 @@ pcaioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p) } -void +static void pcaintr(struct clockframe *frame) { if (pca_status.index < pca_status.in_use[pca_status.current]) { @@ -510,7 +506,7 @@ pcaintr(struct clockframe *frame) } -int +static int pcaselect(dev_t dev, int rw, struct proc *p) { int s = spltty(); diff --git a/sys/pc98/pc98/pcibus.c b/sys/pc98/pc98/pcibus.c deleted file mode 100644 index 2e922e9..0000000 --- a/sys/pc98/pc98/pcibus.c +++ /dev/null @@ -1,526 +0,0 @@ -/************************************************************************** -** -** $Id: pcibus.c,v 1.3 1996/09/03 10:23:51 asami Exp $ -** -** pci bus subroutines for i386 architecture. -** -** FreeBSD -** -**------------------------------------------------------------------------- -** -** Copyright (c) 1994 Wolfgang Stanglmeier. All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** 2. Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. -** 3. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -** -*************************************************************************** -*/ - -#include "vector.h" - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> - -#include <i386/isa/icu.h> -#include <i386/isa/isa_device.h> - -#include <pci/pcivar.h> -#include <pci/pcireg.h> -#include <pci/pcibus.h> - -/*----------------------------------------------------------------- -** -** The following functions are provided by the pci bios. -** They are used only by the pci configuration. -** -** pcibus_setup(): -** Probes for a pci system. -** Sets pci_maxdevice and pci_mechanism. -** -** pcibus_tag(): -** Creates a handle for pci configuration space access. -** This handle is given to the read/write functions. -** -** pcibus_ftag(): -** Creates a modified handle. -** -** pcibus_read(): -** Read a long word from the pci configuration space. -** Requires a tag (from pcitag) and the register -** number (should be a long word alligned one). -** -** pcibus_write(): -** Writes a long word to the pci configuration space. -** Requires a tag (from pcitag), the register number -** (should be a long word alligned one), and a value. -** -** pcibus_regirq(): -** Register an interupt handler for a pci device. -** Requires a tag (from pcitag), the register number -** (should be a long word alligned one), and a value. -** -**----------------------------------------------------------------- -*/ - -static int -pcibus_check (void); - -static void -pcibus_setup (void); - -static pcici_t -pcibus_tag (u_char bus, u_char device, u_char func); - -static pcici_t -pcibus_ftag (pcici_t tag, u_char func); - -static u_long -pcibus_read (pcici_t tag, u_long reg); - -static void -pcibus_write (pcici_t tag, u_long reg, u_long data); - -static int -pcibus_ihandler_attach (int irq, inthand2_t *func, int arg, unsigned* maskptr); - -static int -pcibus_ihandler_detach (int irq, inthand2_t *func); - -static int -pcibus_imask_include (int irq, unsigned* maskptr); - -static int -pcibus_imask_exclude (int irq, unsigned* maskptr); - -static struct pcibus i386pci = { - "pci", - pcibus_setup, - pcibus_tag, - pcibus_ftag, - pcibus_read, - pcibus_write, - ICU_LEN, - pcibus_ihandler_attach, - pcibus_ihandler_detach, - pcibus_imask_include, - pcibus_imask_exclude, -}; - -/* -** Announce structure to generic driver -*/ - -DATA_SET (pcibus_set, i386pci); - -/*-------------------------------------------------------------------- -** -** Determine configuration mode -** -**-------------------------------------------------------------------- -*/ - - -#define CONF1_ADDR_PORT 0x0cf8 -#define CONF1_DATA_PORT 0x0cfc - -#define CONF1_ENABLE 0x80000000ul -#define CONF1_ENABLE_CHK 0x80000000ul -#define CONF1_ENABLE_MSK 0x7ff00000ul -#define CONF1_ENABLE_CHK1 0xff000001ul -#define CONF1_ENABLE_MSK1 0x80000001ul -#define CONF1_ENABLE_RES1 0x80000000ul - -#define CONF2_ENABLE_PORT 0x0cf8 -#ifdef PC98 -#define CONF2_FORWARD_PORT 0x0cf9 -#else -#define CONF2_FORWARD_PORT 0x0cfa -#endif - -#define CONF2_ENABLE_CHK 0x0e -#define CONF2_ENABLE_RES 0x0e - -static int -pcibus_check (void) -{ - u_char device; - - if (bootverbose) printf ("pcibus_check:\tdevice "); - - for (device = 0; device < pci_maxdevice; device++) { - unsigned long id; - if (bootverbose) - printf ("%d ", device); - id = pcibus_read (pcibus_tag (0,device,0), 0); - if (id && id != 0xfffffffful) { - if (bootverbose) printf ("is there (id=%08lx)\n", id); - return 1; - } - } - if (bootverbose) - printf ("-- nothing found\n"); - return 0; -} - -static void -pcibus_setup (void) -{ - unsigned long mode1res,oldval1; - unsigned char mode2res,oldval2; - - oldval1 = inl (CONF1_ADDR_PORT); - - if (bootverbose) { - printf ("pcibus_setup(1):\tmode 1 addr port (0x0cf8) is 0x%08lx\n", oldval1); - } - - /*--------------------------------------- - ** Assume configuration mechanism 1 for now ... - **--------------------------------------- - */ - - if ((oldval1 & CONF1_ENABLE_MSK) == 0) { - - pci_mechanism = 1; - pci_maxdevice = 32; - - outl (CONF1_ADDR_PORT, CONF1_ENABLE_CHK); - outb (CONF1_ADDR_PORT +3, 0); - mode1res = inl (CONF1_ADDR_PORT); - outl (CONF1_ADDR_PORT, oldval1); - - if (bootverbose) - printf ("pcibus_setup(1a):\tmode1res=0x%08lx (0x%08lx)\n", - mode1res, CONF1_ENABLE_CHK); - - if (mode1res) { - if (pcibus_check()) - return; - }; - - outl (CONF1_ADDR_PORT, CONF1_ENABLE_CHK1); - mode1res = inl(CONF1_ADDR_PORT); - outl (CONF1_ADDR_PORT, oldval1); - - if (bootverbose) - printf ("pcibus_setup(1b):\tmode1res=0x%08lx (0x%08lx)\n", - mode1res, CONF1_ENABLE_CHK1); - - if ((mode1res & CONF1_ENABLE_MSK1) == CONF1_ENABLE_RES1) { - if (pcibus_check()) - return; - }; - } - - /*--------------------------------------- - ** Try configuration mechanism 2 ... - **--------------------------------------- - */ - - oldval2 = inb (CONF2_ENABLE_PORT); - - if (bootverbose) { - printf ("pcibus_setup(2):\tmode 2 enable port (0x0cf8) is 0x%02x\n", oldval2); - } - - if ((oldval2 & 0xf0) == 0) { - - pci_mechanism = 2; - pci_maxdevice = 16; - - outb (CONF2_ENABLE_PORT, CONF2_ENABLE_CHK); - mode2res = inb(CONF2_ENABLE_PORT); - outb (CONF2_ENABLE_PORT, oldval2); - - if (bootverbose) - printf ("pcibus_setup(2a):\tmode2res=0x%02x (0x%02x)\n", - mode2res, CONF2_ENABLE_CHK); - - if (mode2res == CONF2_ENABLE_RES) { - if (bootverbose) - printf ("pcibus_setup(2a):\tnow trying mechanism 2\n"); - - if (pcibus_check()) - return; - } - } - - /*--------------------------------------- - ** No PCI bus host bridge found - **--------------------------------------- - */ - - pci_mechanism = 0; - pci_maxdevice = 0; -} - -/*-------------------------------------------------------------------- -** -** Build a pcitag from bus, device and function number -** -**-------------------------------------------------------------------- -*/ - -static pcici_t -pcibus_tag (unsigned char bus, unsigned char device, unsigned char func) -{ - pcici_t tag; - - tag.cfg1 = 0; - if (func >= 8) return tag; - - switch (pci_mechanism) { - - case 1: - if (device < 32) { - tag.cfg1 = CONF1_ENABLE - | (((u_long) bus ) << 16ul) - | (((u_long) device) << 11ul) - | (((u_long) func ) << 8ul); - } - break; - case 2: - if (device < 16) { - tag.cfg2.port = 0xc000 | (device << 8ul); - tag.cfg2.enable = 0xf0 | (func << 1ul); - tag.cfg2.forward = bus; - } - break; - }; - return tag; -} - -static pcici_t -pcibus_ftag (pcici_t tag, u_char func) -{ - switch (pci_mechanism) { - - case 1: - tag.cfg1 &= ~0x700ul; - tag.cfg1 |= (((u_long) func) << 8ul); - break; - case 2: - tag.cfg2.enable = 0xf0 | (func << 1ul); - break; - }; - return tag; -} - -/*-------------------------------------------------------------------- -** -** Read register from configuration space. -** -**-------------------------------------------------------------------- -*/ - -static u_long -pcibus_read (pcici_t tag, u_long reg) -{ - u_long addr, data = 0; - - if (!tag.cfg1) return (0xfffffffful); - - switch (pci_mechanism) { - - case 1: - addr = tag.cfg1 | (reg & 0xfc); -#ifdef PCI_DEBUG - printf ("pci_conf_read(1): addr=%x ", addr); -#endif - outl (CONF1_ADDR_PORT, addr); - data = inl (CONF1_DATA_PORT); - outl (CONF1_ADDR_PORT, 0 ); - break; - - case 2: - addr = tag.cfg2.port | (reg & 0xfc); -#ifdef PCI_DEBUG - printf ("pci_conf_read(2): addr=%x ", addr); -#endif - outb (CONF2_ENABLE_PORT , tag.cfg2.enable ); - outb (CONF2_FORWARD_PORT, tag.cfg2.forward); - - data = inl ((u_short) addr); - - outb (CONF2_ENABLE_PORT, 0); - outb (CONF2_FORWARD_PORT, 0); - break; - }; - -#ifdef PCI_DEBUG - printf ("data=%x\n", data); -#endif - - return (data); -} - -/*-------------------------------------------------------------------- -** -** Write register into configuration space. -** -**-------------------------------------------------------------------- -*/ - -static void -pcibus_write (pcici_t tag, u_long reg, u_long data) -{ - u_long addr; - - if (!tag.cfg1) return; - - switch (pci_mechanism) { - - case 1: - addr = tag.cfg1 | (reg & 0xfc); -#ifdef PCI_DEBUG - printf ("pci_conf_write(1): addr=%x data=%x\n", - addr, data); -#endif - outl (CONF1_ADDR_PORT, addr); - outl (CONF1_DATA_PORT, data); - outl (CONF1_ADDR_PORT, 0 ); - break; - - case 2: - addr = tag.cfg2.port | (reg & 0xfc); -#ifdef PCI_DEBUG - printf ("pci_conf_write(2): addr=%x data=%x\n", - addr, data); -#endif - outb (CONF2_ENABLE_PORT, tag.cfg2.enable); - outb (CONF2_FORWARD_PORT, tag.cfg2.forward); - - outl ((u_short) addr, data); - - outb (CONF2_ENABLE_PORT, 0); - outb (CONF2_FORWARD_PORT, 0); - break; - }; -} - -/*----------------------------------------------------------------------- -** -** Register an interupt handler for a pci device. -** -**----------------------------------------------------------------------- -*/ - -static int -pcibus_ihandler_attach (int irq, inthand2_t *func, int arg, unsigned * maskptr) -{ - char buf[16]; - char *cp; - int free_id, id, result; - - sprintf(buf, "pci irq%d", irq); - for (cp = intrnames, free_id = 0, id = 0; id < NR_DEVICES; id++) { - if (strcmp(cp, buf) == 0) - break; - if (free_id <= 0 && strcmp(cp, "pci irqnn") == 0) - free_id = id; - while (*cp++ != '\0') - ; - } - if (id == NR_DEVICES) { - id = free_id; - if (id == 0) { - /* - * All pci irq counters are in use, perhaps because - * config is old so there aren't any. Abuse the - * clk0 counter. - */ - printf ( - "pcibus_ihandler_attach: counting pci irq%d's as clk0 irqs\n", - irq); - } - } - result = register_intr( - irq, /* isa irq */ - id, /* device id */ - 0, /* flags? */ - func, /* handler */ - maskptr, /* mask pointer */ - arg); /* handler arg */ - - if (result) { - printf ("@@@ pcibus_ihandler_attach: result=%d\n", result); - return (result); - }; - update_intr_masks(); - - INTREN ((1ul<<irq)); - return (0); -} - -static int -pcibus_ihandler_detach (int irq, inthand2_t *func) -{ - int result; - - INTRDIS ((1ul<<irq)); - - result = unregister_intr (irq, func); - - if (result) - printf ("@@@ pcibus_ihandler_detach: result=%d\n", result); - - update_intr_masks(); - - return (result); -} - -static int -pcibus_imask_include (int irq, unsigned* maskptr) -{ - unsigned mask; - - if (!maskptr) return (0); - - mask = 1ul << irq; - - if (*maskptr & mask) - return (-1); - - INTRMASK (*maskptr, mask); - update_intr_masks(); - - return (0); -} - -static int -pcibus_imask_exclude (int irq, unsigned* maskptr) -{ - unsigned mask; - - if (!maskptr) return (0); - - mask = 1ul << irq; - - if (! (*maskptr & mask)) - return (-1); - - *maskptr &= ~mask; - update_intr_masks(); - - return (0); -} diff --git a/sys/pc98/pc98/prof_machdep.c b/sys/pc98/pc98/prof_machdep.c deleted file mode 100644 index 50e7c3b..0000000 --- a/sys/pc98/pc98/prof_machdep.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * NEED A COPYRIGHT NOPTICE HERE - * - * $Id: prof_machdep.c,v 1.2 1996/04/08 16:41:06 wollman Exp $ - */ -#include <sys/param.h> -#include <sys/systm.h> -#include <machine/clock.h> -#ifdef PC98 -#include <pc98/pc98/pc98.h> -#include <pc98/pc98/timerreg.h> -#else -#include <i386/isa/isa.h> -#include <i386/isa/timerreg.h> -#endif - -#ifdef GUPROF -extern u_int cputime __P((void)); -#endif - -#ifdef __GNUC__ -asm(" -GM_STATE = 0 -GMON_PROF_OFF = 3 - - .text - .align 4,0x90 - .globl __mcount -__mcount: - # - # Check that we are profiling. Do it early for speed. - # - cmpl $GMON_PROF_OFF,__gmonparam+GM_STATE - je Lmcount_exit - # - # __mcount is the same as mcount except the caller hasn't changed - # the stack except to call here, so the caller's raddr is above - # our raddr. - # - movl 4(%esp),%edx - jmp Lgot_frompc - - .align 4,0x90 - .globl mcount -mcount: - cmpl $GMON_PROF_OFF,__gmonparam+GM_STATE - je Lmcount_exit - # - # The caller's stack frame has already been built, so %ebp is - # the caller's frame pointer. The caller's raddr is in the - # caller's frame following the caller's caller's frame pointer. - # - movl 4(%ebp),%edx -Lgot_frompc: - # - # Our raddr is the caller's pc. - # - movl (%esp),%eax - - pushf - pushl %eax - pushl %edx - cli - call _mcount - addl $8,%esp - popf -Lmcount_exit: - ret -"); -#else /* !__GNUC__ */ -#error -#endif /* __GNUC__ */ - -#ifdef GUPROF -/* - * mexitcount saves the return register(s), loads selfpc and calls - * mexitcount(selfpc) to do the work. Someday it should be in a machine - * dependent file together with cputime(), __mcount and mcount. cputime() - * can't just be put in machdep.c because it has to be compiled without -pg. - */ -#ifdef __GNUC__ -asm(" - .text -# -# Dummy label to be seen when gprof -u hides mexitcount. -# - .align 4,0x90 - .globl __mexitcount -__mexitcount: - nop - -GMON_PROF_HIRES = 4 - - .align 4,0x90 - .globl mexitcount -mexitcount: - cmpl $GMON_PROF_HIRES,__gmonparam+GM_STATE - jne Lmexitcount_exit - pushl %edx - pushl %eax - movl 8(%esp),%eax - pushf - pushl %eax - cli - call _mexitcount - addl $4,%esp - popf - popl %eax - popl %edx -Lmexitcount_exit: - ret -"); -#else /* !__GNUC__ */ -#error -#endif /* __GNUC__ */ - -/* - * Return the time elapsed since the last call. The units are machine- - * dependent. - */ -u_int -cputime() -{ - u_int count; - u_int delta; - u_char low; - static u_int prev_count; - - /* - * Read the current value of the 8254 timer counter 0. - */ - outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH); - low = inb(TIMER_CNTR0); - count = low | (inb(TIMER_CNTR0) << 8); - - /* - * The timer counts down from TIMER_CNTR0_MAX to 0 and then resets. - * While profiling is enabled, this routine is called at least twice - * per timer reset (for mcounting and mexitcounting hardclock()), - * so at most one reset has occurred since the last call, and one - * has occurred iff the current count is larger than the previous - * count. This allows counter underflow to be detected faster - * than in microtime(). - */ - delta = prev_count - count; - prev_count = count; - if ((int) delta <= 0) - return (delta + timer0_max_count); - return (delta); -} -#else /* not GUPROF */ -#ifdef __GNUC__ -asm(" - .text - .align 4,0x90 - .globl mexitcount -mexitcount: - ret -"); -#else /* !__GNUC__ */ -#error -#endif /* __GNUC__ */ -#endif /* GUPROF */ diff --git a/sys/pc98/pc98/random_machdep.c b/sys/pc98/pc98/random_machdep.c deleted file mode 100644 index 13ced6f..0000000 --- a/sys/pc98/pc98/random_machdep.c +++ /dev/null @@ -1,520 +0,0 @@ -/* - * random_machdep.c -- A strong random number generator - * - * $Id: random_machdep.c,v 1.7 1996/10/09 21:46:41 asami Exp $ - * - * Version 0.95, last modified 18-Oct-95 - * - * Copyright Theodore Ts'o, 1994, 1995. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, and the entire permission notice in its entirety, - * including the disclaimer of warranties. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * ALTERNATIVELY, this product may be distributed under the terms of - * the GNU Public License, in which case the provisions of the GPL are - * required INSTEAD OF the above restrictions. (This clause is - * necessary due to a potential bad interaction between the GPL and - * the restrictions contained in a BSD-style copyright.) - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * modified for PC-9801 by KATO T. of Nagoya University - */ - -#include "opt_cpu.h" - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/select.h> -#include <sys/fcntl.h> - -#include <machine/clock.h> -#include <machine/random.h> - -#include <i386/isa/icu.h> -#ifdef PC98 -#include <pc98/pc98/pc98.h> -#include <pc98/pc98/timerreg.h> -#else -#include <i386/isa/isa.h> -#include <i386/isa/timerreg.h> -#endif - -#define MAX_BLKDEV 4 - -/* - * The pool is stirred with a primitive polynomial of degree 128 - * over GF(2), namely x^128 + x^99 + x^59 + x^31 + x^9 + x^7 + 1. - * For a pool of size 64, try x^64+x^62+x^38+x^10+x^6+x+1. - */ -#define POOLWORDS 128 /* Power of 2 - note that this is 32-bit words */ -#define POOLBITS (POOLWORDS*32) - -#if POOLWORDS == 128 -#define TAP1 99 /* The polynomial taps */ -#define TAP2 59 -#define TAP3 31 -#define TAP4 9 -#define TAP5 7 -#elif POOLWORDS == 64 -#define TAP1 62 /* The polynomial taps */ -#define TAP2 38 -#define TAP3 10 -#define TAP4 6 -#define TAP5 1 -#else -#error No primitive polynomial available for chosen POOLWORDS -#endif - -#define WRITEBUFFER 512 /* size in bytes */ - -/* There is actually only one of these, globally. */ -struct random_bucket { - u_int add_ptr; - u_int entropy_count; - int input_rotate; - u_int32_t *pool; - struct selinfo rsel; -}; - -/* There is one of these per entropy source */ -struct timer_rand_state { - u_long last_time; - int last_delta; - int nbits; -}; - -static struct random_bucket random_state; -static u_int32_t random_pool[POOLWORDS]; -static struct timer_rand_state keyboard_timer_state; -static struct timer_rand_state extract_timer_state; -static struct timer_rand_state irq_timer_state[ICU_LEN]; -#ifdef notyet -static struct timer_rand_state blkdev_timer_state[MAX_BLKDEV]; -#endif -static struct wait_queue *random_wait; - -inthand2_t *sec_intr_handler[ICU_LEN]; -int sec_intr_unit[ICU_LEN]; - -#ifndef MIN -#define MIN(a,b) (((a) < (b)) ? (a) : (b)) -#endif - -void -rand_initialize(void) -{ - random_state.add_ptr = 0; - random_state.entropy_count = 0; - random_state.pool = random_pool; - random_wait = NULL; - random_state.rsel.si_flags = 0; - random_state.rsel.si_pid = 0; -} - -/* - * This function adds an int into the entropy "pool". It does not - * update the entropy estimate. The caller must do this if appropriate. - * - * The pool is stirred with a primitive polynomial of degree 128 - * over GF(2), namely x^128 + x^99 + x^59 + x^31 + x^9 + x^7 + 1. - * For a pool of size 64, try x^64+x^62+x^38+x^10+x^6+x+1. - * - * We rotate the input word by a changing number of bits, to help - * assure that all bits in the entropy get toggled. Otherwise, if we - * consistently feed the entropy pool small numbers (like ticks and - * scancodes, for example), the upper bits of the entropy pool don't - * get affected. --- TYT, 10/11/95 - */ -static inline void -add_entropy_word(struct random_bucket *r, const u_int32_t input) -{ - u_int i; - u_int32_t w; - - w = (input << r->input_rotate) | (input >> (32 - r->input_rotate)); - i = r->add_ptr = (r->add_ptr - 1) & (POOLWORDS-1); - if (i) - r->input_rotate = (r->input_rotate + 7) & 31; - else - /* - * At the beginning of the pool, add an extra 7 bits - * rotation, so that successive passes spread the - * input bits across the pool evenly. - */ - r->input_rotate = (r->input_rotate + 14) & 31; - - /* XOR in the various taps */ - w ^= r->pool[(i+TAP1)&(POOLWORDS-1)]; - w ^= r->pool[(i+TAP2)&(POOLWORDS-1)]; - w ^= r->pool[(i+TAP3)&(POOLWORDS-1)]; - w ^= r->pool[(i+TAP4)&(POOLWORDS-1)]; - w ^= r->pool[(i+TAP5)&(POOLWORDS-1)]; - w ^= r->pool[i]; - /* Rotate w left 1 bit (stolen from SHA) and store */ - r->pool[i] = (w << 1) | (w >> 31); -} - -/* - * This function adds entropy to the entropy "pool" by using timing - * delays. It uses the timer_rand_state structure to make an estimate - * of how any bits of entropy this call has added to the pool. - * - * The number "num" is also added to the pool - it should somehow describe - * the type of event which just happened. This is currently 0-255 for - * keyboard scan codes, and 256 upwards for interrupts. - * On the i386, this is assumed to be at most 16 bits, and the high bits - * are used for a high-resolution timer. - */ -static void -add_timer_randomness(struct random_bucket *r, struct timer_rand_state *state, - u_int num) -{ - int delta, delta2; - u_int nbits; - u_int32_t time; - -#if defined(I586_CPU) || defined(I686_CPU) - if (i586_ctr_freq != 0) { - num ^= (u_int32_t) rdtsc() << 16; - r->entropy_count += 2; - } else { -#endif - disable_intr(); - outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH); - num ^= inb(TIMER_CNTR0) << 16; - num ^= inb(TIMER_CNTR0) << 24; - enable_intr(); - r->entropy_count += 2; -#if defined(I586_CPU) || defined(I686_CPU) - } -#endif - - time = ticks; - - add_entropy_word(r, (u_int32_t) num); - add_entropy_word(r, time); - - /* - * Calculate number of bits of randomness we probably - * added. We take into account the first and second order - * deltas in order to make our estimate. - */ - delta = time - state->last_time; - state->last_time = time; - - delta2 = delta - state->last_delta; - state->last_delta = delta; - - if (delta < 0) delta = -delta; - if (delta2 < 0) delta2 = -delta2; - delta = MIN(delta, delta2) >> 1; - for (nbits = 0; delta; nbits++) - delta >>= 1; - - r->entropy_count += nbits; - - /* Prevent overflow */ - if (r->entropy_count > POOLBITS) - r->entropy_count = POOLBITS; - - if (r->entropy_count >= 8) - selwakeup(&random_state.rsel); -} - -void -add_keyboard_randomness(u_char scancode) -{ - add_timer_randomness(&random_state, &keyboard_timer_state, scancode); -} - -void -add_interrupt_randomness(int irq) -{ - (sec_intr_handler[irq])(sec_intr_unit[irq]); - add_timer_randomness(&random_state, &irq_timer_state[irq], irq); -} - -#ifdef notused -void -add_blkdev_randomness(int major) -{ - if (major >= MAX_BLKDEV) - return; - - add_timer_randomness(&random_state, &blkdev_timer_state[major], - 0x200+major); -} -#endif /* notused */ - -/* - * MD5 transform algorithm, taken from code written by Colin Plumb, - * and put into the public domain - * - * QUESTION: Replace this with SHA, which as generally received better - * reviews from the cryptographic community? - */ - -/* The four core functions - F1 is optimized somewhat */ - -/* #define F1(x, y, z) (x & y | ~x & z) */ -#define F1(x, y, z) (z ^ (x & (y ^ z))) -#define F2(x, y, z) F1(z, x, y) -#define F3(x, y, z) (x ^ y ^ z) -#define F4(x, y, z) (y ^ (x | ~z)) - -/* This is the central step in the MD5 algorithm. */ -#define MD5STEP(f, w, x, y, z, data, s) \ - ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x ) - -/* - * The core of the MD5 algorithm, this alters an existing MD5 hash to - * reflect the addition of 16 longwords of new data. MD5Update blocks - * the data and converts bytes into longwords for this routine. - */ -static void -MD5Transform(u_int32_t buf[4], - u_int32_t const in[16]) -{ - u_int32_t a, b, c, d; - - a = buf[0]; - b = buf[1]; - c = buf[2]; - d = buf[3]; - - MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478, 7); - MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12); - MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17); - MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22); - MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf, 7); - MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12); - MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17); - MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22); - MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8, 7); - MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12); - MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17); - MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22); - MD5STEP(F1, a, b, c, d, in[12]+0x6b901122, 7); - MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12); - MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17); - MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22); - - MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562, 5); - MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340, 9); - MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14); - MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20); - MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d, 5); - MD5STEP(F2, d, a, b, c, in[10]+0x02441453, 9); - MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14); - MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20); - MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6, 5); - MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6, 9); - MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14); - MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20); - MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905, 5); - MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8, 9); - MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14); - MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20); - - MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942, 4); - MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11); - MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16); - MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23); - MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44, 4); - MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11); - MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16); - MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23); - MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6, 4); - MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11); - MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16); - MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23); - MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039, 4); - MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11); - MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16); - MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23); - - MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244, 6); - MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10); - MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15); - MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21); - MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3, 6); - MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10); - MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15); - MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21); - MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f, 6); - MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10); - MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15); - MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21); - MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82, 6); - MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10); - MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15); - MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21); - - buf[0] += a; - buf[1] += b; - buf[2] += c; - buf[3] += d; -} - -#undef F1 -#undef F2 -#undef F3 -#undef F4 -#undef MD5STEP - - -#if POOLWORDS % 16 -#error extract_entropy() assumes that POOLWORDS is a multiple of 16 words. -#endif -/* - * This function extracts randomness from the "entropy pool", and - * returns it in a buffer. This function computes how many remaining - * bits of entropy are left in the pool, but it does not restrict the - * number of bytes that are actually obtained. - */ -static inline int -extract_entropy(struct random_bucket *r, char *buf, int nbytes) -{ - int ret, i; - u_int32_t tmp[4]; - - add_timer_randomness(r, &extract_timer_state, nbytes); - - /* Redundant, but just in case... */ - if (r->entropy_count > POOLBITS) - r->entropy_count = POOLBITS; - /* Why is this here? Left in from Ted Ts'o. Perhaps to limit time. */ - if (nbytes > 32768) - nbytes = 32768; - - ret = nbytes; - if (r->entropy_count / 8 >= nbytes) - r->entropy_count -= nbytes*8; - else - r->entropy_count = 0; - - while (nbytes) { - /* Hash the pool to get the output */ - tmp[0] = 0x67452301; - tmp[1] = 0xefcdab89; - tmp[2] = 0x98badcfe; - tmp[3] = 0x10325476; - for (i = 0; i < POOLWORDS; i += 16) - MD5Transform(tmp, r->pool+i); - /* Modify pool so next hash will produce different results */ - add_entropy_word(r, tmp[0]); - add_entropy_word(r, tmp[1]); - add_entropy_word(r, tmp[2]); - add_entropy_word(r, tmp[3]); - /* - * Run the MD5 Transform one more time, since we want - * to add at least minimal obscuring of the inputs to - * add_entropy_word(). --- TYT - */ - MD5Transform(tmp, r->pool); - - /* Copy data to destination buffer */ - i = MIN(nbytes, 16); - bcopy(tmp, buf, i); - nbytes -= i; - buf += i; - } - - /* Wipe data from memory */ - bzero(tmp, sizeof(tmp)); - - return ret; -} - -#ifdef notused /* XXX NOT the exported kernel interface */ -/* - * This function is the exported kernel interface. It returns some - * number of good random numbers, suitable for seeding TCP sequence - * numbers, etc. - */ -void -get_random_bytes(void *buf, u_int nbytes) -{ - extract_entropy(&random_state, (char *) buf, nbytes); -} -#endif /* notused */ - -u_int -read_random(char *buf, u_int nbytes) -{ - if ((nbytes * 8) > random_state.entropy_count) - nbytes = random_state.entropy_count / 8; - - return extract_entropy(&random_state, buf, nbytes); -} - -u_int -read_random_unlimited(char *buf, u_int nbytes) -{ - return extract_entropy(&random_state, buf, nbytes); -} - -#ifdef notused -u_int -write_random(const char *buf, u_int nbytes) -{ - u_int i; - u_int32_t word, *p; - - for (i = nbytes, p = (u_int32_t *)buf; - i >= sizeof(u_int32_t); - i-= sizeof(u_int32_t), p++) - add_entropy_word(&random_state, *p); - if (i) { - word = 0; - bcopy(p, &word, i); - add_entropy_word(&random_state, word); - } - return nbytes; -} -#endif /* notused */ - -int -random_select(dev_t dev, int rw, struct proc *p) -{ - int s, ret; - - if (rw == FWRITE) - return 1; /* heh. */ - - s = splhigh(); - if (random_state.entropy_count >= 8) - ret = 1; - else { - selrecord(p, &random_state.rsel); - ret = 0; - } - splx(s); - - return ret; -} - diff --git a/sys/pc98/pc98/sound/CHANGELOG b/sys/pc98/pc98/sound/CHANGELOG deleted file mode 100644 index e21dfaa..0000000 --- a/sys/pc98/pc98/sound/CHANGELOG +++ /dev/null @@ -1,122 +0,0 @@ -Changelog for version 3.0-950506 ------------------------------------- - -Since 3.0-94xxxx -- Too many changes - -Since 3.0-940818 -- Fixes for Linux 1.1.4x. -- Disables Disney Sound System with SG NX Pro 16 (less noise). - -Since 2.90-2 -- Fixes to soundcard.h -- Non blocking mode to /dev/sequencer -- Experimental detection code for Ensoniq Soundscape. - -Since 2.90 -- Minor and major bug fixes - -Since pre-3.0-940712 -- GUS MAX support -- Partially working MSS/WSS support (could work with some cards). -- Hardware u-Law and A-Law support with AD1848/CS4248 and CS4231 codecs - (GUS MAX, GUS16, WSS etc). Hardware ADPCM is possible with GUS16 and - GUS MAX, but it doesn't work yet. -Since pre-3.0-940426 -- AD1848/CS4248/CS4231 codec support (MSS, GUS MAX, Aztec, Orchid etc). -This codec chip is used in various soundcards. This version is developed -for the 16 bit daughtercard of GUS. It should work with other cards also -if the following requirements are met: - - The I/O, IRQ and DMA settings are jumper selectable or - the card is initialized by booting DOS before booting Linux (etc.). - - You add the IO, IRQ and DMA settings manually to the local.h. - (Just define GUS16_BASE, GUS16_IRQ and GUS16_DMA). Note that - the base address bust be the base address of the codec chip not the - card itself. For the GUS16 these are the same but most MSS compatible - cards have the codec located at card_base+4. -- Some minor changes - -Since 2.5 (******* MAJOR REWRITE ***********) - -This version is based on v2.3. I have tried to maintain two versions -together so that this one should have the same features than v2.5. -Something may still be missing. If you notice such things, please let me -know. - -The Readme.v30 contains more details. - -- /dev/midi## devices. -- /dev/sequencer2 - -Since 2.5-beta2 -- Some fine tuning to the GUS v3.7 mixer code. -- Fixed speed limits for the plain SB (1.0 to 2.0). - -Since 2.5-beta -- Fixed OPL-3 detection with SB. Caused problems with PAS16. -- GUS v3.7 mixer support. - -Since 2.4 -- Mixer support for Sound Galaxy NX Pro (define __SGNXPRO__ on your local.h). -- Fixed truncated sound on /dev/dsp when the device is closed. -- Linear volume mode for GUS -- Pitch bends larger than +/- 2 octaves. -- MIDI recording for SB and SB Pro. (Untested). -- Some other fixes. -- SB16 MIDI and DSP drivers only initialized if SB16 actually installed. -- Implemented better detection for OPL-3. This should be useful if you - have an old SB Pro (the non-OPL-3 one) or a SB 2.0 clone which has a OPL-3. -- SVR4.2 support by Ian Hartas. Initial ALPHA TEST version (untested). - -Since 2.3b -- Fixed bug which made it impossible to make long recordings to disk. - Recording was not restarted after a buffer overflow situation. -- Limited mixer support for GUS. -- Numerous improvements to the GUS driver by Andrew Robinson. Including - some click removal etc. - -Since 2.3 -- Fixed some minor bugs in the SB16 driver. - -Since 2.2b -- Full SB16 DSP support. 8/16 bit, mono/stereo -- The SCO and FreeBSD versions should be in sync now. There are some - problems with SB16 and GUS in the freebsd versions. - The DMA buffer allocation of the SCO version has been polished but - there could still be some problems. At least it hogs memory. - The DMA channel - configuration method used in the sco/System is a hack. -- Support for the MPU emulation of the SB16. -- Some big arrays are now allocated boot time. This makes the bss segment - smaller which makes it possible to use the full driver with - NetBSD. These arrays are not allocated if no suitable soundcard is available. -- Fixed a bug in the compute_and_set_volume in gus_wave.c -- Fixed the too fast mono playback problem of SB Pro and PAS16. - -Since 2.2 -- Stereo recording for SB Pro. Somehow it was missing and nobody - had noticed it earlier. -- Minor polishing. -- Interpreting of boot time arguments (sound=) for Linux. -- Breakup of sb_dsp.c. Parts of the code has been moved to - sb_mixer.c and sb_midi.c - -Since 2.1 -- Preliminary support for SB16. - - The SB16 mixer is supported in it's native mode. - - Digitized voice capability up to 44.1 kHz/8 bit/mono - (16 bit and stereo support coming in the next release). -- Fixed some bugs in the digitized voice driver for PAS16. -- Proper initialization of the SB emulation of latest PAS16 models. - -- Significantly improved /dev/dsp and /dev/audio support. - - Now supports half duplex mode. It's now possible to record and - playback without closing and reopening the device. - - It's possible to use smaller buffers than earlier. There is a new - ioctl(fd, SNDCTL_DSP_SUBDIVIDE, &n) where n should be 1, 2 or 4. - This call instructs the driver to use smaller buffers. The default - buffer size (0.5 to 1.0 seconds) is divided by n. Should be called - immediately after opening the device. - -Since 2.0 -Just cosmetic changes. diff --git a/sys/pc98/pc98/sound/README b/sys/pc98/pc98/sound/README deleted file mode 100644 index 1c31ac6..0000000 --- a/sys/pc98/pc98/sound/README +++ /dev/null @@ -1,86 +0,0 @@ -VoxWare v2.90 release notes --------------------------- - - - This version includes some hidden features which - are described in the file experimental.txt - Some of these features are not enabled by default. Look at - experimental.txt for more info. - - I just decided to release this version with some - incompletely implemented features disabled since - there are some new features required by a popular - application. In addition there is also support - for the GUS MAX and the 16 bit sampling option of GUS. - - The MSS/WSS support works now. At least with SG NX Pro 16. - -********* IMPORTANT ***************************************** -Linux 1.0 or later is required to by this driver version. - -Don't distribute binaries which use /dev/sequencer and are -compiled with the soundcard.h of this version. They will -not work with version 2.x of the driver. -************************************************************* - - -You will need the snd-util-2.5.tar.gz and snd-data-0.1.tar.Z -packages to use this driver. They should be in the same -ftp site or BBS from where you got this driver. For -example at nic.funet.fi:pub/OS/Linux/*. - -If you are looking for the installation instructions, please -look at linux/Readme. - -Compatibility with the earlier versions ---------------------------------------- - -This version is backward compatible with the version 2.X. All programs -compiled with sys/soundcard.h of v2.X should work without problems. -PROGRAMS COMPILED WITH THE sys/soundcard.h OF THIS VERSION WILL NOT -WORK WITH v2.X DRIVER. BE CAREFUL WHEN DISTRIBUTING BINARIES COMPILED -FOR THIS VERSION. - -Contributors ------------- - -This driver contains code by several contributors. In addition several other -persons have given useful suggestions. The following is a list of major -contributors. (I could have forgotten some names.) - - Craig Metz 1/2 of the PAS16 Mixer and PCM support - Rob Hooft Volume computation algorithm for the FM synth. - Mika Liljeberg uLaw encoding and decoding routines - Greg Lee Volume computation algorithm for the GUS and - lot's of valuable suggestions. - Andy Warner ISC port - Jim Lowe FreeBSD port - Anders Baekgaard Bughunting and valuable suggestions. - Joerg Schubert SB16 DSP support. - Andrew Robinson Improvements to the GUS driver - Megens SA MIDI recording for SB and SB Pro. - Mikael Nordqvist Linear volume support for GUS. - Mikael Nordqvist Linear volume support for GUS. - Ian Hartas SVR4.2 port - Markus Aroharju and - Risto Kankkunen Major contributions to the mixer support - of GUS v3.7. - Hunyue Yau Mixer support for SG NX Pro. - Marc Hoffman PSS support. - -Regards, - -Hannu Savolainen -hannu@voxware.pp.fi - -Snail mail: Hannu Savolainen - Hiekkalaiturintie 3 A 8 - 00980 Helsinki - Finland -FAX: +358 0 341 6272 (answers if I have my machine (mgetty) on). - -NOTE! I probably don't answer to Snail mail or FAX messages. Sending answer - to each of them is simply too expensive and time consuming. However I - try to reply every email message I get (within a week). If you don't - get response, please check how your address is written in the message - header. I can't answer if I don't have a valid reply address. diff --git a/sys/pc98/pc98/sound/Readme.aedsp16 b/sys/pc98/pc98/sound/Readme.aedsp16 deleted file mode 100644 index b205a9d..0000000 --- a/sys/pc98/pc98/sound/Readme.aedsp16 +++ /dev/null @@ -1,6 +0,0 @@ -Informations about Audio Excel DSP 16 can be found in the source -file aedsp16.c -Please, read the head of the source before using it. It contain useful -informations. - - Riccardo diff --git a/sys/pc98/pc98/sound/Readme.modules b/sys/pc98/pc98/sound/Readme.modules deleted file mode 100644 index 315540f..0000000 --- a/sys/pc98/pc98/sound/Readme.modules +++ /dev/null @@ -1,87 +0,0 @@ - Linux sound-driver module - (c) Peter Trattler - License: GPL (Gnu Public License) - - -Idea: - -I've modified the sources for the sound driver to allow simply insert and -remove the sound driver from the kernel by calling (only available for Linux) - - insmod /usr/src/linux/modules/sound.o - -and - - rmmod sound - -This may be useful if you are doing one of the following things: - -1) Debugging the sound driver -2) Creating a new device within the sound-driver -3) You do not the sound driver all the time (as it wastes quite a lot of -memory for its buffers) - - -Compilation: - -Go to /usr/src/linux and make the following steps: - -a) configure the sound driver: To do that call "make config" and enable the -sound-driver -- you will be asked different questions about your -sound-hardware (remember not to use a too big DMA-Buffer size; you -should use 16kB, if you have 16Bit devices, otherwise you can use 32kB) - -b) disable the sound driver in the kernel: call make config again but answer -'N' to "Sound card support" - -c) run "make modules"; the sound-driver sound.o should end up in -/usr/src/linux/modules - - -If memory is tight: - -I've allocated at about 70kB for the sound-drivers internal tables. If this -is too much, 'insmod sound.o' will generate the following warning -... -use 'insmod memsize=xxxx' -... -You can only use this command, if you have (I think) at least -modules-1.1.87 or up. You can also switch debugging on by running the command - -insmod sound.o debugmem=1 - - -Files I changed: - -I've only changed the files soundcard.c(most changes) and some changes within -the Makefile, sound_config.h and the Makefile in /usr/src/linux/drivers - - -Bugs: - -a) As the kmalloc (..., GFP_DMA) caused some unexpected errors (I don't know if -it is my fault), I created some code, which is (by default) enabled by - -#define KMALLOC_DMA_BROKEN 1 (within soundcard.c). - -It trys to allocate a large enough region, so that the complete dma-buffer -can be occupied in this space. If it does not fit within this region it -doubles the size of it. But this can cause problems, if the sound-buffer is -too big (as kmalloc can only handle regions at up to circa 100kB). - -So take care to use for 8Bit devices a sound-DMA-buffer of 32kB (maximum) -and for 16Bit devices a maximum of 16kB. Otherwise the allocation scheme -might fail. - -b) Buffers allocated by the different sound devices via calls to kmalloc are -not freed, if the sound driver is removed again (these buffers tend to be -quite small -- so it does not harm a lot) - -c) If there is not enough (kernel-) memory available, the installation of -the sound-driver fails. (This happens quite often, if you did not install the -driver right after booting -- [PS: I've only got 5MB of Ram, so this might -be the source for this problem]) - - -Author: - Peter Trattler (peter@sbox.tu-graz.ac.at) diff --git a/sys/pc98/pc98/sound/Readme.v30 b/sys/pc98/pc98/sound/Readme.v30 deleted file mode 100644 index 8884ad8..0000000 --- a/sys/pc98/pc98/sound/Readme.v30 +++ /dev/null @@ -1,142 +0,0 @@ -VoxWare v3.0 ------------- - -This is a late alpha/early beta of the VoxWare v3.0 to be relased May/June 95. - -All features of v2.90-2 should work as earlier. There could be some -omissions but they are unintentional. I started this version thread -after v2.3 so all features implemented before it are there. - -New features -============ - -There are now two new device interfaces. The /dev/midi## is a raw -tty like interface to MIDI ports. There is a device file for each MIDI -port on your system. They are named (/dev/midi00 to /dev/midiNN). -The second addition is the /dev/music which is higher level interface -than the old /dev/sequencer. It's intended for writing device independent -applications like sequencers. - -/dev/midi## ------------ - -This interface should be usefull for applications like MIDI sysex librarians. -There are (currently) no timing features so making music could be impossible. - -There are as many /dev/midi## devices as there are MIDI ports in the system. -The /dev/midi00 is connected to the first one, /dev/midi01 to the second etc. - -These devices work like tty devices in raw mode. Everything written to them is -sent out to the MIDI port. There is currently an extra delay of at most -1/100th of sec but it will be removed later. - -The reading algorithm is little bit more complicated. There are two different -cases: - -1) There is at least one byte in the input buffer. - -The read returns as many bytes as it can without waiting for more bytes. -For example when a process reads 100 bytes and there are 10 bytes in the -buffer, the read returns just 10 bytes. - -2) The input buffer is empty when the process calls read. - -The read waits for the first byte and then continues as in case 1. By -default it waits infinitely but there is an ioctl for setting a timeout -for this. The ioctl(fd, SNDCTL_MIDI_PRETIME, &time) changes the timeout. -The time is given in 1/10th of seconds (10 means one second). - -Other ioctl calls: - -ioctl(fd, SNDCTL_MIDI_MPUMODE, &mode) is available for full MPU-401 -compatible devices such as MPU-IPC-T, MQ PC Midi Card or MQX-32. -It's not available for the so called MPU UART ports of some soundcards -(PAS16, SB16 etc). By default the MIDI port is in UART mode after open. -If this ioctl is called with mode=1, the interface is put to the intelligent -(coprocessor) mode. NOTE! The MIDI port will be reset when this ioctl is called. -It could have some strange effects if not called immediately after open. This -vall returns EINVAL if the midi port doesn't support the MPU-401 intelligent -mode. - -ioctl(fd, SNDCTL_MIDI_MPUCMD, &cmdstruct) is valid only if the MIDI port -is put to the coprocessor mode using ioctl(SNDCTL_MIDI_MPUMODE). It's used to -send commands to a MPU-401 compatible MIDI cards. Please refer to the -MPU-401 Technical Reference Manual (or Music Quest Technical Reference -Manual) for descriptions of the commands. - -The argument of SNDCTL_MIDI_MPUCOMMAND is of type mpu_command_rec. It -has the following fields: - -typedef struct { - unsigned char cmd; - - char nr_args, nr_returns; - unsigned char data[30]; - } mpu_command_rec; - -where: - cmd Contains the command number. - nr_args Number of arguments of the command. - MUST BE INITIALIZED BEFORE CALL - nr_returns Number of bytes returned by the command. - MUST BE INITIALIZED BEFORE CALL - data Buffer for the command arguments and returned - data. - -Be extremely carefull with the nr_args and nr_returns fields. They -must match the command. An incorrect value will put the card and -the driver out of sync. Refer to the MPU-401/MQX-32M documentation for further -datails. - - - -/dev/music (/dev/sequencer2) ----------------------------- - -This device file works much like the /dev/sequencer which has been present -since the beginning. The main differences are the following: - -- /dev/sequencer makes the MIDI ports to look like the synth devices. In fact -the result is somewhere between the MIDI specification and the synth devices of -/dev/sequencer. Both kind of devices are accessed using the SEQ_START_NOTE() -like macros. The voice number parameters of the API macros have been redefined -to denote MIDI channels. This means that the driver allocates voices for -the channels automaticly (this is a responsibility/right of an application -with /dev/sequencer). The result is that a SEQ_START_NOTE() macro has -similar effects for a synth channel than on a MIDI port. This kind of -solution provides better device independence than the /dev/sequencer. The -drawback is that the new interface doesn't permit so low level access to the -device as the /dev/sequencer does. An application developer must choose between -these two interfaces. I think the old /dev/sequencer is better for applications -like module players while the new one is better for making generic sequencer -programs. - -- There are no separate MIDI devices with the /dev/sequencer2. The -ioctl(SNDCTL_SEQ_NRMIDIS) returns always zero. Instead the MIDI ports are -shown as synth devices. ioctl(SNDCTL_SEQ_NRSYNTHS) on /dev/sequencer2 will -return sum of internal synthesizers (GUS, OPL3) and MIDI ports in the systems. - -- The new interface is used much like the ordinary /dev/sequencer. The -event format is new so you have to use the API macros defined in the -sys/soundcard.h. The interface is will propably change before the final 3.0 -release but using the API macros should ensure compatibility in source level. -The new event format is not recognized by version 2.X so don't try to -distribute binaries compiled with soundcard.h of v3.X. - -- The basic API useage is similar to the current one. There are some new -macros but the older ones should work as earlier. The most important -incompatibility is that the /dev/sequencer2 driver allocates voices itself. -The other one is that the application must send SEQ_START_TIMER() as it's -first event. Otherwise the timer is not started and the application waits -infinitely. - - -There are several new features but I don't document them here. There are -some info in the soundcard.h (near the end). I have also included some -sample code in the directory v30. Full documentation will -appear in the Hacker's Guide later. - -Don't hesitate to contact me in case you have questions or comments. - -Hannu Savolainen -hannu@voxware.pp.fi diff --git a/sys/pc98/pc98/sound/adlib_card.c b/sys/pc98/pc98/sound/adlib_card.c deleted file mode 100644 index 4ec55b9..0000000 --- a/sys/pc98/pc98/sound/adlib_card.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * sound/adlib_card.c - * - * Detection routine for the AdLib card. - * - * Copyright by Hannu Savolainen 1993 - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. 2. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#ifdef PC98 -#include <pc98/pc98/sound/sound_config.h> -#else -#include <i386/isa/sound/sound_config.h> -#endif - -#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_YM3812) - -long -attach_adlib_card (long mem_start, struct address_info *hw_config) -{ - - if (opl3_detect (FM_MONO)) - { - mem_start = opl3_init (mem_start); - } - return mem_start; -} - -int -probe_adlib (struct address_info *hw_config) -{ - return opl3_detect (FM_MONO); -} - -#endif diff --git a/sys/pc98/pc98/sound/audio.c b/sys/pc98/pc98/sound/audio.c deleted file mode 100644 index 51e983d..0000000 --- a/sys/pc98/pc98/sound/audio.c +++ /dev/null @@ -1,587 +0,0 @@ -/* - * sound/audio.c - * - * Device file manager for /dev/audio - * - * Copyright by Hannu Savolainen 1993 - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. 2. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#ifdef PC98 -#include <pc98/pc98/sound/sound_config.h> -#else -#include <i386/isa/sound/sound_config.h> -#endif - -#ifdef CONFIGURE_SOUNDCARD -#ifndef EXCLUDE_AUDIO - -#include <i386/isa/sound/ulaw.h> -#include <i386/isa/sound/coproc.h> - -#define ON 1 -#define OFF 0 - -static int wr_buff_no[MAX_AUDIO_DEV]; /* - - * != -1, if there is - * a incomplete output - * block in the queue. - */ -static int wr_buff_size[MAX_AUDIO_DEV], wr_buff_ptr[MAX_AUDIO_DEV]; - -static int audio_mode[MAX_AUDIO_DEV]; -static int dev_nblock[MAX_AUDIO_DEV]; /* 1 if in noblocking mode */ - -#define AM_NONE 0 -#define AM_WRITE 1 -#define AM_READ 2 - -static char *wr_dma_buf[MAX_AUDIO_DEV]; -static int audio_format[MAX_AUDIO_DEV]; -static int local_conversion[MAX_AUDIO_DEV]; - -static int -set_format (int dev, int fmt) -{ - if (fmt != AFMT_QUERY) - { - - local_conversion[dev] = 0; - - if (!(audio_devs[dev]->format_mask & fmt)) /* Not supported */ - if (fmt == AFMT_MU_LAW) - { - fmt = AFMT_U8; - local_conversion[dev] = AFMT_MU_LAW; - } - else - fmt = AFMT_U8; /* This is always supported */ - - audio_format[dev] = DMAbuf_ioctl (dev, SNDCTL_DSP_SETFMT, fmt, 1); - } - - if (local_conversion[dev]) /* This shadows the HW format */ - return local_conversion[dev]; - - return audio_format[dev]; -} - -int -audio_open (int dev, struct fileinfo *file) -{ - int ret; - int bits; - int dev_type = dev & 0x0f; - int mode = file->mode & O_ACCMODE; - - dev = dev >> 4; - - if (dev_type == SND_DEV_DSP16) - bits = 16; - else - bits = 8; - - if ((ret = DMAbuf_open (dev, mode)) < 0) - return ret; - - if (audio_devs[dev]->coproc) - if ((ret = audio_devs[dev]->coproc-> - open (audio_devs[dev]->coproc->devc, COPR_PCM)) < 0) - { - audio_release (dev, file); - printk ("Sound: Can't access coprocessor device\n"); - - return ret; - } - - local_conversion[dev] = 0; - - if (DMAbuf_ioctl (dev, SNDCTL_DSP_SETFMT, bits, 1) != bits) - { - audio_release (dev, file); - return RET_ERROR (ENXIO); - } - - if (dev_type == SND_DEV_AUDIO) - { - set_format (dev, AFMT_MU_LAW); - } - else - set_format (dev, bits); - - wr_buff_no[dev] = -1; - audio_mode[dev] = AM_NONE; - wr_buff_size[dev] = wr_buff_ptr[dev] = 0; - dev_nblock[dev] = 0; - - return ret; -} - -void -audio_release (int dev, struct fileinfo *file) -{ - int mode; - - dev = dev >> 4; - mode = file->mode & O_ACCMODE; - - if (wr_buff_no[dev] >= 0) - { - DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]); - - wr_buff_no[dev] = -1; - } - - if (audio_devs[dev]->coproc) - audio_devs[dev]->coproc->close (audio_devs[dev]->coproc->devc, COPR_PCM); - DMAbuf_release (dev, mode); -} - -#ifdef NO_INLINE_ASM -static void -translate_bytes (const unsigned char *table, unsigned char *buff, unsigned long n) -{ - unsigned long i; - - for (i = 0; i < n; ++i) - buff[i] = table[buff[i]]; -} - -#else -static inline void -translate_bytes (const void *table, void *buff, unsigned long n) -{ - __asm__ ("cld\n" - "1:\tlodsb\n\t" - "xlatb\n\t" - "stosb\n\t" -"loop 1b\n\t": -: "b" ((long) table), "c" (n), "D" ((long) buff), "S" ((long) buff) -: "bx", "cx", "di", "si", "ax"); -} - -#endif - -int -audio_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) -{ - int c, p, l; - int err; - - dev = dev >> 4; - - p = 0; - c = count; - - if (audio_mode[dev] == AM_READ) /* - * Direction changed - */ - { - wr_buff_no[dev] = -1; - } - - audio_mode[dev] = AM_WRITE; - - if (!count) /* - * Flush output - */ - { - if (wr_buff_no[dev] >= 0) - { - DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]); - - wr_buff_no[dev] = -1; - } - return 0; - } - - while (c) - { /* - * Perform output blocking - */ - if (wr_buff_no[dev] < 0) /* - * There is no incomplete buffers - */ - { - if ((wr_buff_no[dev] = DMAbuf_getwrbuffer (dev, &wr_dma_buf[dev], - &wr_buff_size[dev], - dev_nblock[dev])) < 0) - { - /* Handle nonblocking mode */ -#if defined(__FreeBSD__) - if (dev_nblock[dev] && wr_buff_no[dev] == RET_ERROR (EWOULDBLOCK)) - return wr_buff_no[dev]; /* - * XXX Return error, write() will - * supply # of accepted bytes. - * In fact, in FreeBSD the check - * above should not be needed - */ -#else - if (dev_nblock[dev] && wr_buff_no[dev] == RET_ERROR (EAGAIN)) - return p; /* No more space. Return # of accepted bytes */ -#endif - return wr_buff_no[dev]; - } - wr_buff_ptr[dev] = 0; - } - - l = c; - if (l > (wr_buff_size[dev] - wr_buff_ptr[dev])) - l = (wr_buff_size[dev] - wr_buff_ptr[dev]); - - if (!audio_devs[dev]->copy_from_user) - { /* - * No device specific copy routine - */ - COPY_FROM_USER (&wr_dma_buf[dev][wr_buff_ptr[dev]], buf, p, l); - } - else - audio_devs[dev]->copy_from_user (dev, - wr_dma_buf[dev], wr_buff_ptr[dev], buf, p, l); - - - /* - * Insert local processing here - */ - - if (local_conversion[dev] == AFMT_MU_LAW) - { -#ifdef linux - /* - * This just allows interrupts while the conversion is running - */ - __asm__ ("sti"); -#endif - translate_bytes (ulaw_dsp, (unsigned char *) &wr_dma_buf[dev][wr_buff_ptr[dev]], l); - } - - c -= l; - p += l; - wr_buff_ptr[dev] += l; - - if (wr_buff_ptr[dev] >= wr_buff_size[dev]) - { - if ((err = DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev])) < 0) - { - return err; - } - - wr_buff_no[dev] = -1; - } - - } - - return count; -} - -int -audio_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) -{ - int c, p, l; - char *dmabuf; - int buff_no; - - dev = dev >> 4; - p = 0; - c = count; - - if (audio_mode[dev] == AM_WRITE) - { - if (wr_buff_no[dev] >= 0) - { - DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]); - - wr_buff_no[dev] = -1; - } - } - - audio_mode[dev] = AM_READ; - - while (c) - { - if ((buff_no = DMAbuf_getrdbuffer (dev, &dmabuf, &l, - dev_nblock[dev])) < 0) - { - /* Nonblocking mode handling. Return current # of bytes */ - -#if defined(__FreeBSD__) - if (dev_nblock[dev] && buff_no == RET_ERROR (EWOULDBLOCK)) - return buff_no; /* - * XXX Return error, read() will supply - * # of bytes actually read. In fact, - * in FreeBSD the check above should not - * be needed - */ -#else - if (dev_nblock[dev] && buff_no == RET_ERROR (EAGAIN)) - return p; -#endif - - return buff_no; - } - - if (l > c) - l = c; - - /* - * Insert any local processing here. - */ - - if (local_conversion[dev] == AFMT_MU_LAW) - { -#ifdef linux - /* - * This just allows interrupts while the conversion is running - */ - __asm__ ("sti"); -#endif - - translate_bytes (dsp_ulaw, (unsigned char *) dmabuf, l); - } - - COPY_TO_USER (buf, p, dmabuf, l); - - DMAbuf_rmchars (dev, buff_no, l); - - p += l; - c -= l; - } - - return count - c; -} - -int -audio_ioctl (int dev, struct fileinfo *file, - unsigned int cmd, unsigned int arg) -{ - - dev = dev >> 4; - - if (((cmd >> 8) & 0xff) == 'C') - { - if (audio_devs[dev]->coproc) /* Coprocessor ioctl */ - return audio_devs[dev]->coproc->ioctl (audio_devs[dev]->coproc->devc, cmd, arg, 0); - else - printk ("/dev/dsp%d: No coprocessor for this device\n", dev); - - return RET_ERROR (EREMOTEIO); - } - else - switch (cmd) - { - case SNDCTL_DSP_SYNC: - if (wr_buff_no[dev] >= 0) - { - DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]); - - wr_buff_no[dev] = -1; - } - return DMAbuf_ioctl (dev, cmd, arg, 0); - break; - - case SNDCTL_DSP_POST: - if (wr_buff_no[dev] >= 0) - { - DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]); - - wr_buff_no[dev] = -1; - } - return 0; - break; - - case SNDCTL_DSP_RESET: - wr_buff_no[dev] = -1; - return DMAbuf_ioctl (dev, cmd, arg, 0); - break; - - case SNDCTL_DSP_GETFMTS: - return IOCTL_OUT (arg, audio_devs[dev]->format_mask); - break; - - case SNDCTL_DSP_SETFMT: - return IOCTL_OUT (arg, set_format (dev, IOCTL_IN (arg))); - - case SNDCTL_DSP_GETISPACE: - if (audio_mode[dev] == AM_WRITE) - return RET_ERROR (EBUSY); - - { - audio_buf_info info; - - int err = DMAbuf_ioctl (dev, cmd, (unsigned long) &info, 1); - - if (err < 0) - return err; - - if (wr_buff_no[dev] != -1) - info.bytes += wr_buff_ptr[dev]; - - IOCTL_TO_USER ((char *) arg, 0, (char *) &info, sizeof (info)); - return 0; - } - - case SNDCTL_DSP_GETOSPACE: - if (audio_mode[dev] == AM_READ) - return RET_ERROR (EBUSY); - - { - audio_buf_info info; - - int err = DMAbuf_ioctl (dev, cmd, (unsigned long) &info, 1); - - if (err < 0) - return err; - - if (wr_buff_no[dev] != -1) - info.bytes += wr_buff_size[dev] - wr_buff_ptr[dev]; - - IOCTL_TO_USER ((char *) arg, 0, (char *) &info, sizeof (info)); - return 0; - } - - case SNDCTL_DSP_NONBLOCK: - dev_nblock[dev] = 1; - return 0; - break; - -#ifdef __FreeBSD__ - case FIONBIO: /* XXX Is this the same in Linux? */ - if (*(int *)arg) - dev_nblock[dev] = 1; - else - dev_nblock[dev] = 0; - return 0; - break; - - case FIOASYNC: - return 0; /* XXX Useful for ampling input notification? */ - break; -#endif - - default: - return DMAbuf_ioctl (dev, cmd, arg, 0); - } -} - -long -audio_init (long mem_start) -{ - /* - * NOTE! This routine could be called several times during boot. - */ - return mem_start; -} - -#ifdef ALLOW_SELECT -int -audio_select (int dev, struct fileinfo *file, int sel_type, select_table * wait) -{ - int l; - char *dmabuf; - - dev = dev >> 4; - - switch (sel_type) - { - case SEL_IN: - if (audio_mode[dev] != AM_READ && /* Wrong direction */ - audio_mode[dev] != AM_NONE) - return 0; - - if (DMAbuf_getrdbuffer (dev, &dmabuf, &l, - 1 /* Don't block */ ) >= 0) - return 1; /* We have data */ - - return DMAbuf_select (dev, file, sel_type, wait); - break; - - case SEL_OUT: - if (audio_mode[dev] != AM_WRITE && /* Wrong direction */ - audio_mode[dev] != AM_NONE) - return 0; - - if (wr_buff_no[dev] != -1) - return 1; /* There is space in the current buffer */ - - return DMAbuf_select (dev, file, sel_type, wait); - break; - - case SEL_EX: - return 0; - } - - return 0; -} - -#endif /* ALLOW_SELECT */ - -#else /* EXCLUDE_AUDIO */ -/* - * Stub versions - */ - -int -audio_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) -{ - return RET_ERROR (EIO); -} - -int -audio_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) -{ - return RET_ERROR (EIO); -} - -int -audio_open (int dev, struct fileinfo *file) -{ - return RET_ERROR (ENXIO); -} - -void -audio_release (int dev, struct fileinfo *file) -{ -}; -int -audio_ioctl (int dev, struct fileinfo *file, - unsigned int cmd, unsigned int arg) -{ - return RET_ERROR (EIO); -} - -int -audio_lseek (int dev, struct fileinfo *file, off_t offset, int orig) -{ - return RET_ERROR (EIO); -} - -long -audio_init (long mem_start) -{ - return mem_start; -} - -#endif - -#endif diff --git a/sys/pc98/pc98/sound/dev_table.c b/sys/pc98/pc98/sound/dev_table.c deleted file mode 100644 index 2b6142b..0000000 --- a/sys/pc98/pc98/sound/dev_table.c +++ /dev/null @@ -1,186 +0,0 @@ -/* - * sound/dev_table.c - * - * Device call tables. - * - * Copyright by Hannu Savolainen 1993 - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. 2. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#define _DEV_TABLE_C_ -#ifdef PC98 -#include <pc98/pc98/sound/sound_config.h> -#else -#include <i386/isa/sound/sound_config.h> -#endif - -#ifdef CONFIGURE_SOUNDCARD - -int -snd_find_driver (int type) -{ - int i, n = sizeof (sound_drivers) / sizeof (struct driver_info); - - for (i = 0; i < (n - 1); i++) - if (sound_drivers[i].card_type == type) - return i; - - return -1; /* - * Not found - */ -} - -static long -sndtable_init (long mem_start) -{ - int i, n = sizeof (snd_installed_cards) / sizeof (struct card_info); - int drv; - - printk ("Sound initialization started\n"); - - for (i = 0; i < (n - 1); i++) - if (snd_installed_cards[i].enabled) - if ((drv = snd_find_driver (snd_installed_cards[i].card_type)) == -1) - snd_installed_cards[i].enabled = 0; /* - * Mark as not detected - */ - else if (sound_drivers[drv].probe (&snd_installed_cards[i].config)) - { -#ifndef SHORT_BANNERS - printk ("snd%d", - snd_installed_cards[i].card_type); -#endif - - mem_start = sound_drivers[drv].attach (mem_start, &snd_installed_cards[i].config); -#ifndef SHORT_BANNERS - printk (" at 0x%x irq %d drq %d\n", - snd_installed_cards[i].config.io_base, - snd_installed_cards[i].config.irq, - snd_installed_cards[i].config.dma); -#endif - } - else - snd_installed_cards[i].enabled = 0; /* - * Mark as not detected - */ - printk ("Sound initialization complete\n"); - return mem_start; -} - -int -sndtable_probe (int unit, struct address_info *hw_config) -{ - int i, n = sizeof (snd_installed_cards) / sizeof (struct card_info); - - if (!unit) - return TRUE; - - for (i = 0; i < (n - 1); i++) - if (snd_installed_cards[i].enabled) - if (snd_installed_cards[i].card_type == unit) - { - int drv; - - snd_installed_cards[i].config.io_base = hw_config->io_base; - snd_installed_cards[i].config.irq = hw_config->irq; - snd_installed_cards[i].config.dma = hw_config->dma; - if ((drv = snd_find_driver (snd_installed_cards[i].card_type)) == -1) - snd_installed_cards[i].enabled = 0; /* - * Mark as not - * detected - */ - else if (sound_drivers[drv].probe (hw_config)) - return 1; - snd_installed_cards[i].enabled = 0; /* - * Mark as not detected - */ - return 0; - } - - return FALSE; -} - -int -sndtable_init_card (int unit, struct address_info *hw_config) -{ - int i, n = sizeof (snd_installed_cards) / sizeof (struct card_info); - - if (!unit) - { - if (sndtable_init (0) != 0) - panic ("snd: Invalid memory allocation\n"); - return TRUE; - } - - for (i = 0; i < (n - 1); i++) - if (snd_installed_cards[i].card_type == unit) - { - int drv; - - snd_installed_cards[i].config.io_base = hw_config->io_base; - snd_installed_cards[i].config.irq = hw_config->irq; - snd_installed_cards[i].config.dma = hw_config->dma; - - if ((drv = snd_find_driver (snd_installed_cards[i].card_type)) == -1) - snd_installed_cards[i].enabled = 0; /* - * Mark as not detected - */ - else if (sound_drivers[drv].attach (0, hw_config) != 0) - panic ("snd#: Invalid memory allocation\n"); - return TRUE; - } - - return FALSE; -} - -int -sndtable_get_cardcount (void) -{ - return num_audiodevs + num_mixers + num_synths + num_midis; -} - -struct address_info * -sound_getconf (int card_type) -{ - int j, ptr; - int n = sizeof (snd_installed_cards) / sizeof (struct card_info); - - ptr = -1; - for (j = 0; j < n && ptr == -1; j++) - if (snd_installed_cards[j].card_type == card_type) - ptr = j; - - if (ptr == -1) - return (struct address_info *) NULL; - - return &snd_installed_cards[ptr].config; -} - -#else - -void -sound_setup (char *str, int *ints) -{ -} - -#endif diff --git a/sys/pc98/pc98/sound/dev_table.h b/sys/pc98/pc98/sound/dev_table.h deleted file mode 100644 index 5269f63..0000000 --- a/sys/pc98/pc98/sound/dev_table.h +++ /dev/null @@ -1,429 +0,0 @@ -/* - * dev_table.h - * - * Global definitions for device call tables - * - * Copyright by Hannu Savolainen 1993 - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - -*/ - -#ifndef _DEV_TABLE_H_ -#define _DEV_TABLE_H_ - -/* - * NOTE! NOTE! NOTE! NOTE! - * - * If you modify this file, please check the dev_table.c also. - * - * NOTE! NOTE! NOTE! NOTE! - */ - -struct driver_info { - int card_type; /* From soundcard.h */ - char *name; - long (*attach) (long mem_start, struct address_info *hw_config); - int (*probe) (struct address_info *hw_config); -}; - -struct card_info { - int card_type; /* Link (search key) to the driver list */ - struct address_info config; - int enabled; -}; - -/* - * Device specific parameters (used only by dmabuf.c) - */ -#define MAX_SUB_BUFFERS (32*MAX_REALTIME_FACTOR) - -#define DMODE_NONE 0 -#define DMODE_OUTPUT 1 -#define DMODE_INPUT 2 - -struct dma_buffparms { - int dma_mode; /* DMODE_INPUT, DMODE_OUTPUT or DMODE_NONE */ - - /* - * Pointers to raw buffers - */ - - char *raw_buf[DSP_BUFFCOUNT]; - unsigned long raw_buf_phys[DSP_BUFFCOUNT]; - int raw_count; - - /* - * Device state tables - */ - - unsigned long flags; -#define DMA_BUSY 0x00000001 -#define DMA_RESTART 0x00000002 -#define DMA_ACTIVE 0x00000004 -#define DMA_STARTED 0x00000008 -#define DMA_ALLOC_DONE 0x00000020 - - int open_mode; - - /* - * Queue parameters. - */ - int qlen; - int qhead; - int qtail; - - int nbufs; - int counts[MAX_SUB_BUFFERS]; - int subdivision; - char *buf[MAX_SUB_BUFFERS]; - unsigned long buf_phys[MAX_SUB_BUFFERS]; - - int fragment_size; - int max_fragments; - - int bytes_in_use; - - int underrun_count; -}; - -/* - * Structure for use with various microcontrollers and DSP processors - * in the recent soundcards. - */ -typedef struct coproc_operations { - char name[32]; - int (*open) (void *devc, int sub_device); - void (*close) (void *devc, int sub_device); - int (*ioctl) (void *devc, unsigned int cmd, unsigned int arg, int local); - void (*reset) (void *devc); - - void *devc; /* Driver specific info */ - } coproc_operations; - -struct audio_operations { - char name[32]; - int flags; -#define NOTHING_SPECIAL 0 -#define NEEDS_RESTART 1 -#define DMA_AUTOMODE 2 - int format_mask; /* Bitmask for supported audio formats */ - void *devc; /* Driver specific info */ - int (*open) (int dev, int mode); - void (*close) (int dev); - void (*output_block) (int dev, unsigned long buf, - int count, int intrflag, int dma_restart); - void (*start_input) (int dev, unsigned long buf, - int count, int intrflag, int dma_restart); - int (*ioctl) (int dev, unsigned int cmd, unsigned int arg, int local); - int (*prepare_for_input) (int dev, int bufsize, int nbufs); - int (*prepare_for_output) (int dev, int bufsize, int nbufs); - void (*reset) (int dev); - void (*halt_xfer) (int dev); - int (*local_qlen)(int dev); - void (*copy_from_user)(int dev, char *localbuf, int localoffs, - snd_rw_buf *userbuf, int useroffs, int len); - int buffcount; - long buffsize; - int dmachan; - struct dma_buffparms *dmap; - struct coproc_operations *coproc; - int mixer_dev; -}; - -struct mixer_operations { - char name[32]; - int (*ioctl) (int dev, unsigned int cmd, unsigned int arg); -}; - -struct synth_operations { - struct synth_info *info; - int midi_dev; - int synth_type; - int synth_subtype; - - int (*open) (int dev, int mode); - void (*close) (int dev); - int (*ioctl) (int dev, unsigned int cmd, unsigned int arg); - int (*kill_note) (int dev, int voice, int note, int velocity); - int (*start_note) (int dev, int voice, int note, int velocity); - int (*set_instr) (int dev, int voice, int instr); - void (*reset) (int dev); - void (*hw_control) (int dev, unsigned char *event); - int (*load_patch) (int dev, int format, snd_rw_buf *addr, - int offs, int count, int pmgr_flag); - void (*aftertouch) (int dev, int voice, int pressure); - void (*controller) (int dev, int voice, int ctrl_num, int value); - void (*panning) (int dev, int voice, int value); - void (*volume_method) (int dev, int mode); - int (*pmgr_interface) (int dev, struct patmgr_info *info); - void (*bender) (int dev, int chn, int value); - int (*alloc_voice) (int dev, int chn, int note, struct voice_alloc_info *alloc); - void (*setup_voice) (int dev, int voice, int chn); - - struct voice_alloc_info alloc; - struct channel_info chn_info[16]; -}; - -struct midi_input_info { /* MIDI input scanner variables */ -#define MI_MAX 10 - int m_busy; - unsigned char m_buf[MI_MAX]; - unsigned char m_prev_status; /* For running status */ - int m_ptr; -#define MST_INIT 0 -#define MST_DATA 1 -#define MST_SYSEX 2 - int m_state; - int m_left; - }; - -struct midi_operations { - struct midi_info info; - struct synth_operations *converter; - struct midi_input_info in_info; - int (*open) (int dev, int mode, - void (*inputintr)(int dev, unsigned char data), - void (*outputintr)(int dev) - ); - void (*close) (int dev); - int (*ioctl) (int dev, unsigned int cmd, unsigned int arg); - int (*putc) (int dev, unsigned char data); - int (*start_read) (int dev); - int (*end_read) (int dev); - void (*kick)(int dev); - int (*command) (int dev, unsigned char *data); - int (*buffer_status) (int dev); - int (*prefix_cmd) (int dev, unsigned char status); - struct coproc_operations *coproc; -}; - -struct sound_timer_operations { - struct sound_timer_info info; - int priority; - int devlink; - int (*open)(int dev, int mode); - void (*close)(int dev); - int (*event)(int dev, unsigned char *ev); - unsigned long (*get_time)(int dev); - int (*ioctl) (int dev, unsigned int cmd, unsigned int arg); - void (*arm_timer)(int dev, long time); -}; - -#ifdef _DEV_TABLE_C_ - struct audio_operations *audio_devs[MAX_AUDIO_DEV] = {NULL}; int num_audiodevs = 0; - struct mixer_operations *mixer_devs[MAX_MIXER_DEV] = {NULL}; int num_mixers = 0; - struct synth_operations *synth_devs[MAX_SYNTH_DEV+MAX_MIDI_DEV] = {NULL}; int num_synths = 0; - struct midi_operations *midi_devs[MAX_MIDI_DEV] = {NULL}; int num_midis = 0; - -#ifndef EXCLUDE_SEQUENCER - extern struct sound_timer_operations default_sound_timer; - struct sound_timer_operations *sound_timer_devs[MAX_TIMER_DEV] = - {&default_sound_timer, NULL}; - int num_sound_timers = 1; -#else - struct sound_timer_operations *sound_timer_devs[MAX_TIMER_DEV] = - {NULL}; - int num_sound_timers = 0; -#endif - -/* - * List of low level drivers compiled into the kernel. - */ - - struct driver_info sound_drivers[] = { -#ifndef EXCLUDE_PSS - {SNDCARD_PSS, "Echo Personal Sound System PSS (ESC614)", attach_pss, probe_pss}, -# ifdef PSS_MPU_BASE - {SNDCARD_PSS_MPU, "PSS-MPU", attach_pss_mpu, probe_pss_mpu}, -# endif -# ifdef PSS_MSS_BASE - {SNDCARD_PSS_MSS, "PSS-MSS", attach_pss_mss, probe_pss_mss}, -# endif -#endif -#ifndef EXCLUDE_YM3812 - {SNDCARD_ADLIB, "OPL-2/OPL-3 FM", attach_adlib_card, probe_adlib}, -#endif -#ifndef EXCLUDE_PAS - {SNDCARD_PAS, "ProAudioSpectrum", attach_pas_card, probe_pas}, -#endif -#if !defined(EXCLUDE_MPU401) && !defined(EXCLUDE_MIDI) - {SNDCARD_MPU401,"Roland MPU-401", attach_mpu401, probe_mpu401}, -#endif -#if !defined(EXCLUDE_UART6850) && !defined(EXCLUDE_MIDI) - {SNDCARD_UART6850,"6860 UART Midi", attach_uart6850, probe_uart6850}, -#endif -#ifndef EXCLUDE_SB - {SNDCARD_SB, "SoundBlaster", attach_sb_card, probe_sb}, -#endif -#if !defined(EXCLUDE_SB) && !defined(EXCLUDE_SB16) -#ifndef EXCLUDE_AUDIO - {SNDCARD_SB16, "SoundBlaster16", sb16_dsp_init, sb16_dsp_detect}, -#endif -#ifndef EXCLUDE_MIDI - {SNDCARD_SB16MIDI,"SB16 MIDI", attach_sb16midi, probe_sb16midi}, -#endif -#endif -#ifndef EXCLUDE_GUS16 - {SNDCARD_GUS16, "Ultrasound 16-bit opt.", attach_gus_db16, probe_gus_db16}, -#endif -#ifndef EXCLUDE_MSS - {SNDCARD_MSS, "MS Sound System", attach_ms_sound, probe_ms_sound}, -#endif -#ifndef EXCLUDE_GUS - {SNDCARD_GUS, "Gravis Ultrasound", attach_gus_card, probe_gus}, -#endif -#ifndef EXCLUDE_SSCAPE - {SNDCARD_SSCAPE, "Ensoniq Soundscape", attach_sscape, probe_sscape}, - {SNDCARD_SSCAPE_MSS, "MS Sound System (SoundScape)", attach_ss_ms_sound, probe_ss_ms_sound}, -#endif -#ifndef EXCLUDE_TRIX - {SNDCARD_TRXPRO, "MediaTriX AudioTriX Pro", attach_trix_wss, probe_trix_wss}, - {SNDCARD_TRXPRO_SB, "AudioTriX (SB mode)", attach_trix_sb, probe_trix_sb}, - {SNDCARD_TRXPRO_MPU, "AudioTriX MIDI", attach_trix_mpu, probe_trix_mpu}, -#endif -#ifdef PC98 -#ifndef EXCLUDE_PCM86 - {SNDCARD_PCM86, "PC-9801-86/73", attach_pcm86, probe_pcm86}, -#endif -#endif - {0, "*?*", NULL, NULL} - }; - -#if defined(linux) || defined(__FreeBSD__) -/* - * List of devices actually configured in the system. - * - * Note! The detection order is significant. Don't change it. - */ - - struct card_info snd_installed_cards[] = { -#ifndef EXCLUDE_PSS - {SNDCARD_PSS, {PSS_BASE, PSS_IRQ, PSS_DMA}, SND_DEFAULT_ENABLE}, -# ifdef PSS_MPU_BASE - {SNDCARD_PSS_MPU, {PSS_MPU_BASE, PSS_MPU_IRQ, 0}, SND_DEFAULT_ENABLE}, -# endif -# ifdef PSS_MSS_BASE - {SNDCARD_PSS_MSS, {PSS_MSS_BASE, PSS_MSS_IRQ, PSS_MSS_DMA}, SND_DEFAULT_ENABLE}, -# endif -#endif -#ifndef EXCLUDE_TRIX - {SNDCARD_TRXPRO, {TRIX_BASE, TRIX_IRQ, TRIX_DMA}, SND_DEFAULT_ENABLE}, -# ifdef TRIX_SB_BASE - {SNDCARD_TRXPRO_SB, {TRIX_SB_BASE, TRIX_SB_IRQ, TRIX_SB_DMA}, SND_DEFAULT_ENABLE}, -# endif -# ifdef TRIX_MPU_BASE - {SNDCARD_TRXPRO_MPU, {TRIX_MPU_BASE, TRIX_MPU_IRQ, 0}, SND_DEFAULT_ENABLE}, -# endif -#endif -#ifndef EXCLUDE_SSCAPE - {SNDCARD_SSCAPE, {SSCAPE_BASE, SSCAPE_IRQ, SSCAPE_DMA}, SND_DEFAULT_ENABLE}, - {SNDCARD_SSCAPE_MSS, {SSCAPE_MSS_BASE, SSCAPE_MSS_IRQ, SSCAPE_MSS_DMA}, SND_DEFAULT_ENABLE}, -#endif - -#ifndef EXCLUDE_MSS - {SNDCARD_MSS, {MSS_BASE, MSS_IRQ, MSS_DMA}, SND_DEFAULT_ENABLE}, -# ifdef MSS2_BASE - {SNDCARD_MSS, {MSS2_BASE, MSS2_IRQ, MSS2_DMA}, SND_DEFAULT_ENABLE}, -# endif -#endif - -#ifndef EXCLUDE_PAS - {SNDCARD_PAS, {PAS_BASE, PAS_IRQ, PAS_DMA}, SND_DEFAULT_ENABLE}, -#endif - -#ifndef EXCLUDE_SB - {SNDCARD_SB, {SBC_BASE, SBC_IRQ, SBC_DMA}, SND_DEFAULT_ENABLE}, -#endif - -#if !defined(EXCLUDE_MPU401) && !defined(EXCLUDE_MIDI) - {SNDCARD_MPU401, {MPU_BASE, MPU_IRQ, 0}, SND_DEFAULT_ENABLE}, -#ifdef MPU2_BASE - {SNDCARD_MPU401, {MPU2_BASE, MPU2_IRQ, 0}, SND_DEFAULT_ENABLE}, -#endif -#ifdef MPU3_BASE - {SNDCARD_MPU401, {MPU3_BASE, MPU2_IRQ, 0}, SND_DEFAULT_ENABLE}, -#endif -#endif - -#if !defined(EXCLUDE_UART6850) && !defined(EXCLUDE_MIDI) - {SNDCARD_UART6850, {U6850_BASE, U6850_IRQ, 0}, SND_DEFAULT_ENABLE}, -#endif - -#if !defined(EXCLUDE_SB) && !defined(EXCLUDE_SB16) -#ifndef EXCLUDE_AUDIO - {SNDCARD_SB16, {SBC_BASE, SBC_IRQ, SB16_DMA}, SND_DEFAULT_ENABLE}, -#endif -#ifndef EXCLUDE_MIDI - {SNDCARD_SB16MIDI,{SB16MIDI_BASE, SBC_IRQ, 0}, SND_DEFAULT_ENABLE}, -#endif -#endif - -#ifndef EXCLUDE_GUS -#ifndef EXCLUDE_GUS16 - {SNDCARD_GUS16, {GUS16_BASE, GUS16_IRQ, GUS16_DMA, GUS_DMA_READ}, SND_DEFAULT_ENABLE}, -#endif - {SNDCARD_GUS, {GUS_BASE, GUS_IRQ, GUS_DMA, GUS_DMA_READ}, SND_DEFAULT_ENABLE}, -#endif - -#ifndef EXCLUDE_YM3812 - {SNDCARD_ADLIB, {FM_MONO, 0, 0}, SND_DEFAULT_ENABLE}, -#endif -#ifdef PC98 -#ifndef EXCLUDE_PCM86 - {SNDCARD_PCM86, {0, 0, 0}, SND_DEFAULT_ENABLE}, -#endif -#endif - {0, {0}, 0} - }; - - int num_sound_cards = - sizeof(snd_installed_cards) / sizeof (struct card_info); - -#else - int num_sound_cards = 0; -#endif /* linux */ - - int num_sound_drivers = - sizeof(sound_drivers) / sizeof (struct driver_info); - -#else - extern struct audio_operations * audio_devs[MAX_AUDIO_DEV]; extern int num_audiodevs; - extern struct mixer_operations * mixer_devs[MAX_MIXER_DEV]; extern int num_mixers; - extern struct synth_operations * synth_devs[MAX_SYNTH_DEV+MAX_MIDI_DEV]; extern int num_synths; - extern struct midi_operations * midi_devs[MAX_MIDI_DEV]; extern int num_midis; - extern struct sound_timer_operations * sound_timer_devs[MAX_SYNTH_DEV+MAX_MIDI_DEV]; extern int num_sound_timers; - - extern struct driver_info sound_drivers[]; - extern int num_sound_drivers; - extern struct card_info snd_installed_cards[]; - extern int num_sound_cards; -#endif /* _DEV_TABLE_C_ */ - -int sndtable_probe(int unit, struct address_info *hw_config); -int sndtable_init_card(int unit, struct address_info *hw_config); -int sndtable_get_cardcount (void); -struct address_info *sound_getconf(int card_type); -int snd_find_driver(int type); - -#endif /* _DEV_TABLE_H_ */ diff --git a/sys/pc98/pc98/sound/dmabuf.c b/sys/pc98/pc98/sound/dmabuf.c deleted file mode 100644 index 90673af..0000000 --- a/sys/pc98/pc98/sound/dmabuf.c +++ /dev/null @@ -1,1119 +0,0 @@ -/* - * sound/dmabuf.c - * - * The DMA buffer manager for digitized voice applications - * - * Copyright by Hannu Savolainen 1993, 1994, 1995 - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. 2. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#ifdef PC98 -#include <pc98/pc98/sound/sound_config.h> -#else -#include <i386/isa/sound/sound_config.h> -#endif - -#ifdef CONFIGURE_SOUNDCARD - -#if !defined(EXCLUDE_AUDIO) || !defined(EXCLUDE_GUS) - -DEFINE_WAIT_QUEUES (dev_sleeper[MAX_AUDIO_DEV], dev_sleep_flag[MAX_AUDIO_DEV]); - -static struct dma_buffparms dmaps[MAX_AUDIO_DEV] = -{ - {0}}; /* - - * Primitive way to allocate - * such a large array. - * Needs dynamic run-time alloction. - */ - -static void -reorganize_buffers (int dev) -{ - /* - * This routine breaks the physical device buffers to logical ones. - */ - - struct dma_buffparms *dmap = audio_devs[dev]->dmap; - struct audio_operations *dsp_dev = audio_devs[dev]; - - unsigned i, p, n; - unsigned sr, nc, sz, bsz; - - if (dmap->fragment_size == 0) - { /* Compute the fragment size using the default algorithm */ - - sr = dsp_dev->ioctl (dev, SOUND_PCM_READ_RATE, 0, 1); - nc = dsp_dev->ioctl (dev, SOUND_PCM_READ_CHANNELS, 0, 1); - sz = dsp_dev->ioctl (dev, SOUND_PCM_READ_BITS, 0, 1); - - if (sr < 1 || nc < 1 || sz < 1) - { - printk ("Warning: Invalid PCM parameters[%d] sr=%d, nc=%d, sz=%d\n", - dev, sr, nc, sz); - sr = DSP_DEFAULT_SPEED; - nc = 1; - sz = 8; - } - - sz = sr * nc * sz; - - sz /= 8; /* #bits -> #bytes */ - - /* - * Compute a buffer size for time not exeeding 1 second. - * Usually this algorithm gives a buffer size for 0.5 to 1.0 seconds - * of sound (using the current speed, sample size and #channels). - */ - - bsz = dsp_dev->buffsize; - while (bsz > sz) - bsz /= 2; - - if (dsp_dev->buffcount == 1 && bsz == dsp_dev->buffsize) - bsz /= 2; /* Needs at least 2 buffers */ - - if (dmap->subdivision == 0) /* Not already set */ - dmap->subdivision = 1; /* Init to default value */ - else - bsz /= dmap->subdivision; - - if (bsz < 16) - bsz = 16; /* Just a sanity check */ - - while ((dsp_dev->buffsize * dsp_dev->buffcount) / bsz > MAX_SUB_BUFFERS) - bsz *= 2; - - dmap->fragment_size = bsz; - } - else - { - /* - * The process has specified the buffer sice with SNDCTL_DSP_SETFRAGMENT or - * the buffer sice computation has already been done. - */ - if (dmap->fragment_size > (audio_devs[dev]->buffsize / 2)) - dmap->fragment_size = (audio_devs[dev]->buffsize / 2); - bsz = dmap->fragment_size; - } - - bsz &= ~0x03; /* Force size which is multiple of 4 bytes */ - - /* - * Now computing addresses for the logical buffers - */ - - n = 0; - for (i = 0; i < dmap->raw_count && - n < dmap->max_fragments && - n < MAX_SUB_BUFFERS; i++) - { - p = 0; - - while ((p + bsz) <= dsp_dev->buffsize && - n < dmap->max_fragments && - n < MAX_SUB_BUFFERS) - { - dmap->buf[n] = dmap->raw_buf[i] + p; - dmap->buf_phys[n] = dmap->raw_buf_phys[i] + p; - p += bsz; - n++; - } - } - - dmap->nbufs = n; - dmap->bytes_in_use = n * bsz; - - for (i = 0; i < dmap->nbufs; i++) - { - dmap->counts[i] = 0; - } - - dmap->flags |= DMA_ALLOC_DONE; -} - -static void -dma_init_buffers (int dev) -{ - struct dma_buffparms *dmap = audio_devs[dev]->dmap = &dmaps[dev]; - - RESET_WAIT_QUEUE (dev_sleeper[dev], dev_sleep_flag[dev]); - - dmap->flags = DMA_BUSY; /* Other flags off */ - dmap->qlen = dmap->qhead = dmap->qtail = 0; - dmap->nbufs = 1; - dmap->bytes_in_use = audio_devs[dev]->buffsize; - - dmap->dma_mode = DMODE_NONE; -} - -int -DMAbuf_open (int dev, int mode) -{ - int retval; - struct dma_buffparms *dmap = NULL; - - if (dev >= num_audiodevs) - { - printk ("PCM device %d not installed.\n", dev); - return RET_ERROR (ENXIO); - } - - if (!audio_devs[dev]) - { - printk ("PCM device %d not initialized\n", dev); - return RET_ERROR (ENXIO); - } - - dmap = audio_devs[dev]->dmap = &dmaps[dev]; - - if (dmap->flags & DMA_BUSY) - return RET_ERROR (EBUSY); - -#ifdef USE_RUNTIME_DMAMEM - dmap->raw_buf[0] = NULL; - sound_dma_malloc (dev); -#endif - - if (dmap->raw_buf[0] == NULL) - return RET_ERROR (ENOSPC); /* Memory allocation failed during boot */ - - if ((retval = audio_devs[dev]->open (dev, mode)) < 0) - return retval; - - dmap->open_mode = mode; - dmap->subdivision = dmap->underrun_count = 0; - dmap->fragment_size = 0; - dmap->max_fragments = 65536; /* Just a large value */ - - dma_init_buffers (dev); - audio_devs[dev]->ioctl (dev, SOUND_PCM_WRITE_BITS, 8, 1); - audio_devs[dev]->ioctl (dev, SOUND_PCM_WRITE_CHANNELS, 1, 1); - audio_devs[dev]->ioctl (dev, SOUND_PCM_WRITE_RATE, DSP_DEFAULT_SPEED, 1); - - return 0; -} - -static void -dma_reset (int dev) -{ - int retval; - unsigned long flags; - - DISABLE_INTR (flags); - - audio_devs[dev]->reset (dev); - audio_devs[dev]->close (dev); - - if ((retval = audio_devs[dev]->open (dev, audio_devs[dev]->dmap->open_mode)) < 0) - printk ("Sound: Reset failed - Can't reopen device\n"); - RESTORE_INTR (flags); - - dma_init_buffers (dev); - reorganize_buffers (dev); -} - -static int -dma_sync (int dev) -{ - unsigned long flags; - - if (audio_devs[dev]->dmap->dma_mode == DMODE_OUTPUT) - { - DISABLE_INTR (flags); - - while (!PROCESS_ABORTING (dev_sleeper[dev], dev_sleep_flag[dev]) - && audio_devs[dev]->dmap->qlen) - { - DO_SLEEP (dev_sleeper[dev], dev_sleep_flag[dev], 10 * HZ); - if (TIMED_OUT (dev_sleeper[dev], dev_sleep_flag[dev])) - { - RESTORE_INTR (flags); - return audio_devs[dev]->dmap->qlen; - } - } - RESTORE_INTR (flags); - - /* - * Some devices such as GUS have huge amount of on board RAM for the - * audio data. We have to wait until the device has finished playing. - */ - - DISABLE_INTR (flags); - if (audio_devs[dev]->local_qlen) /* Device has hidden buffers */ - { - while (!(PROCESS_ABORTING (dev_sleeper[dev], dev_sleep_flag[dev])) - && audio_devs[dev]->local_qlen (dev)) - { - DO_SLEEP (dev_sleeper[dev], dev_sleep_flag[dev], HZ); - } - } - RESTORE_INTR (flags); - } - return audio_devs[dev]->dmap->qlen; -} - -int -DMAbuf_release (int dev, int mode) -{ - unsigned long flags; - - if (!(PROCESS_ABORTING (dev_sleeper[dev], dev_sleep_flag[dev])) - && (audio_devs[dev]->dmap->dma_mode == DMODE_OUTPUT)) - { - dma_sync (dev); - } - -#ifdef USE_RUNTIME_DMAMEM - sound_dma_free (dev); -#endif - - DISABLE_INTR (flags); - audio_devs[dev]->reset (dev); - - audio_devs[dev]->close (dev); - - audio_devs[dev]->dmap->dma_mode = DMODE_NONE; - audio_devs[dev]->dmap->flags &= ~DMA_BUSY; - RESTORE_INTR (flags); - - return 0; -} - -int -DMAbuf_getrdbuffer (int dev, char **buf, int *len, int dontblock) -{ - unsigned long flags; - int err = EIO; - struct dma_buffparms *dmap = audio_devs[dev]->dmap; - - DISABLE_INTR (flags); - if (!dmap->qlen) - { - if (dmap->flags & DMA_RESTART) - { - dma_reset (dev); - dmap->flags &= ~DMA_RESTART; - } - - if (dmap->dma_mode == DMODE_OUTPUT) /* Direction change */ - { - dma_sync (dev); - dma_reset (dev); - dmap->dma_mode = DMODE_NONE; - } - - if (!(dmap->flags & DMA_ALLOC_DONE)) - reorganize_buffers (dev); - - if (!dmap->dma_mode) - { - int err; - - if ((err = audio_devs[dev]->prepare_for_input (dev, - dmap->fragment_size, dmap->nbufs)) < 0) - { - RESTORE_INTR (flags); - return err; - } - dmap->dma_mode = DMODE_INPUT; - } - - if (!(dmap->flags & DMA_ACTIVE)) - { - audio_devs[dev]->start_input (dev, dmap->buf_phys[dmap->qtail], - dmap->fragment_size, 0, - !(audio_devs[dev]->flags & DMA_AUTOMODE) || - !(dmap->flags & DMA_STARTED)); - dmap->flags |= DMA_ACTIVE | DMA_STARTED; - } - - if (dontblock) - { - RESTORE_INTR (flags); -#if defined(__FreeBSD__) - return RET_ERROR (EWOULDBLOCK); -#else - return RET_ERROR (EAGAIN); -#endif - } - - /* Wait for the next block */ - - DO_SLEEP (dev_sleeper[dev], dev_sleep_flag[dev], 2 * HZ); - if (TIMED_OUT (dev_sleeper[dev], dev_sleep_flag[dev])) - { - printk ("Sound: DMA timed out - IRQ/DRQ config error?\n"); - dma_reset (dev); - err = EIO; - SET_ABORT_FLAG (dev_sleeper[dev], dev_sleep_flag[dev]); - } - else - err = EINTR; - } - RESTORE_INTR (flags); - - if (!dmap->qlen) - return RET_ERROR (err); - - *buf = &dmap->buf[dmap->qhead][dmap->counts[dmap->qhead]]; - *len = dmap->fragment_size - dmap->counts[dmap->qhead]; - - return dmap->qhead; -} - -int -DMAbuf_rmchars (int dev, int buff_no, int c) -{ - struct dma_buffparms *dmap = audio_devs[dev]->dmap; - - int p = dmap->counts[dmap->qhead] + c; - - if (p >= dmap->fragment_size) - { /* This buffer is completely empty */ - dmap->counts[dmap->qhead] = 0; - if (dmap->qlen <= 0 || dmap->qlen > dmap->nbufs) - printk ("\nSound: Audio queue1 corrupted for dev%d (%d/%d)\n", - dev, dmap->qlen, dmap->nbufs); - dmap->qlen--; - dmap->qhead = (dmap->qhead + 1) % dmap->nbufs; - } - else - dmap->counts[dmap->qhead] = p; - - return 0; -} - -int -DMAbuf_ioctl (int dev, unsigned int cmd, unsigned int arg, int local) -{ - struct dma_buffparms *dmap = audio_devs[dev]->dmap; - - switch (cmd) - { - case SNDCTL_DSP_RESET: - dma_reset (dev); - return 0; - break; - - case SNDCTL_DSP_SYNC: - dma_sync (dev); - dma_reset (dev); - return 0; - break; - - case SNDCTL_DSP_GETBLKSIZE: - if (!(dmap->flags & DMA_ALLOC_DONE)) - reorganize_buffers (dev); - - return IOCTL_OUT (arg, dmap->fragment_size); - break; - - case SNDCTL_DSP_SETBLKSIZE: - { - int size = IOCTL_IN(arg); - - if(!(dmap->flags & DMA_ALLOC_DONE) && size) - { - dmap->fragment_size = size; - return 0; - } - else - return RET_ERROR (EINVAL); /* Too late to change */ - } - break; - - case SNDCTL_DSP_SUBDIVIDE: - { - int fact = IOCTL_IN (arg); - - if (fact == 0) - { - fact = dmap->subdivision; - if (fact == 0) - fact = 1; - return IOCTL_OUT (arg, fact); - } - - if (dmap->subdivision != 0 || - dmap->fragment_size) /* Loo late to change */ - return RET_ERROR (EINVAL); - - if (fact > MAX_REALTIME_FACTOR) - return RET_ERROR (EINVAL); - - if (fact != 1 && fact != 2 && fact != 4 && fact != 8 && fact != 16) - return RET_ERROR (EINVAL); - - dmap->subdivision = fact; - return IOCTL_OUT (arg, fact); - } - break; - - case SNDCTL_DSP_SETFRAGMENT: - { - int fact = IOCTL_IN (arg); - int bytes, count; - - if (fact == 0) - return RET_ERROR (EIO); - - if (dmap->subdivision != 0 || - dmap->fragment_size) /* Loo late to change */ - return RET_ERROR (EINVAL); - - bytes = fact & 0xffff; - count = (fact >> 16) & 0xffff; - - if (count == 0) - count = MAX_SUB_BUFFERS; - - if (bytes < 7 || bytes > 17) /* <64 || > 128k */ - return RET_ERROR (EINVAL); - - if (count < 2) - return RET_ERROR (EINVAL); - - dmap->fragment_size = (1 << bytes); - dmap->max_fragments = count; - - if (dmap->fragment_size > audio_devs[dev]->buffsize) - dmap->fragment_size = audio_devs[dev]->buffsize; - - if (dmap->fragment_size == audio_devs[dev]->buffsize && - audio_devs[dev]->flags & DMA_AUTOMODE) - dmap->fragment_size /= 2; /* Needs at least 2 buffers */ - - dmap->subdivision = 1; /* Disable SNDCTL_DSP_SUBDIVIDE */ - return IOCTL_OUT (arg, bytes | (count << 16)); - } - break; - - case SNDCTL_DSP_GETISPACE: - case SNDCTL_DSP_GETOSPACE: - if (!local) - return RET_ERROR (EINVAL); - - { - audio_buf_info *info = (audio_buf_info *) arg; - - info->fragments = dmap->qlen; - info->fragsize = dmap->fragment_size; - info->bytes = dmap->qlen * dmap->fragment_size; - } - return 0; - - default: - return audio_devs[dev]->ioctl (dev, cmd, arg, local); - } - -} - -static int -space_in_queue (int dev) -{ - int len, max, tmp; - struct dma_buffparms *dmap = audio_devs[dev]->dmap; - - if (dmap->qlen >= dmap->nbufs) /* No space at all */ - return 0; - - /* - * Verify that there are no more pending buffers than the limit - * defined by the process. - */ - - max = dmap->max_fragments; - len = dmap->qlen; - - if (audio_devs[dev]->local_qlen) - { - tmp = audio_devs[dev]->local_qlen (dev); - if (tmp & len) - tmp--; /* - * This buffer has been counted twice - */ - len += tmp; - } - - if (len >= max) - return 0; - return 1; -} - -int -DMAbuf_getwrbuffer (int dev, char **buf, int *size, int dontblock) -{ - unsigned long flags; - int abort, err = EIO; - struct dma_buffparms *dmap = audio_devs[dev]->dmap; - - if (dmap->dma_mode == DMODE_INPUT) /* Direction change */ - { - dma_reset (dev); - dmap->dma_mode = DMODE_NONE; - } - else if (dmap->flags & DMA_RESTART) /* Restart buffering */ - { - dma_sync (dev); - dma_reset (dev); - } - - dmap->flags &= ~DMA_RESTART; - - if (!(dmap->flags & DMA_ALLOC_DONE)) - reorganize_buffers (dev); - - if (!dmap->dma_mode) - { - int err; - - dmap->dma_mode = DMODE_OUTPUT; - if ((err = audio_devs[dev]->prepare_for_output (dev, - dmap->fragment_size, dmap->nbufs)) < 0) - return err; - } - - DISABLE_INTR (flags); - - abort = 0; - while (!space_in_queue (dev) && - !abort) - { - - if (dontblock) - { - RESTORE_INTR (flags); - return RET_ERROR (EAGAIN); - } - - /* - * Wait for free space - */ - DO_SLEEP (dev_sleeper[dev], dev_sleep_flag[dev], 2 * HZ); - if (TIMED_OUT (dev_sleeper[dev], dev_sleep_flag[dev])) - { - printk ("Sound: DMA timed out - IRQ/DRQ config error?\n"); - dma_reset (dev); - err = EIO; - abort = 1; - SET_ABORT_FLAG (dev_sleeper[dev], dev_sleep_flag[dev]); - } - else if (PROCESS_ABORTING (dev_sleeper[dev], dev_sleep_flag[dev])) - { - err = EINTR; - abort = 1; - } - } - RESTORE_INTR (flags); - - if (!space_in_queue (dev)) - { - return RET_ERROR (err); /* Caught a signal ? */ - } - - *buf = dmap->buf[dmap->qtail]; - *size = dmap->fragment_size; - dmap->counts[dmap->qtail] = 0; - - return dmap->qtail; -} - -int -DMAbuf_start_output (int dev, int buff_no, int l) -{ - struct dma_buffparms *dmap = audio_devs[dev]->dmap; - - if (buff_no != dmap->qtail) - printk ("Sound warning: DMA buffers out of sync %d != %d\n", buff_no, dmap->qtail); - - dmap->qlen++; - if (dmap->qlen <= 0 || dmap->qlen > dmap->nbufs) - printk ("\nSound: Audio queue2 corrupted for dev%d (%d/%d)\n", - dev, dmap->qlen, dmap->nbufs); - - dmap->counts[dmap->qtail] = l; - - if ((l != dmap->fragment_size) && - ((audio_devs[dev]->flags & DMA_AUTOMODE) && - audio_devs[dev]->flags & NEEDS_RESTART)) - dmap->flags |= DMA_RESTART; - else - dmap->flags &= ~DMA_RESTART; - - dmap->qtail = (dmap->qtail + 1) % dmap->nbufs; - - if (!(dmap->flags & DMA_ACTIVE)) - { - dmap->flags |= DMA_ACTIVE; - audio_devs[dev]->output_block (dev, dmap->buf_phys[dmap->qhead], - dmap->counts[dmap->qhead], 0, - !(audio_devs[dev]->flags & DMA_AUTOMODE) || - !(dmap->flags & DMA_STARTED)); - dmap->flags |= DMA_STARTED; - } - - return 0; -} - -int -DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode) -{ - int chan = audio_devs[dev]->dmachan; - struct dma_buffparms *dmap = audio_devs[dev]->dmap; -#ifdef linux - unsigned long flags; -#endif - /* - * This function is not as portable as it should be. - */ - - /* - * The count must be one less than the actual size. This is handled by - * set_dma_addr() - */ - - if (audio_devs[dev]->flags & DMA_AUTOMODE) - { /* - * Auto restart mode. Transfer the whole * - * buffer - */ -#ifdef linux - DISABLE_INTR (flags); - disable_dma (chan); - clear_dma_ff (chan); - set_dma_mode (chan, dma_mode | DMA_AUTOINIT); - set_dma_addr (chan, dmap->raw_buf_phys[0]); - set_dma_count (chan, dmap->bytes_in_use); - enable_dma (chan); - RESTORE_INTR (flags); -#else - -#if defined(__FreeBSD__) - - isa_dmastart (B_RAW | ((dma_mode == DMA_MODE_READ) ? B_READ : B_WRITE), - (caddr_t)dmap->raw_buf_phys[0], - dmap->bytes_in_use, - chan); -#else /* else __FreeBSD__ */ -#if defined(GENERIC_SYSV) -#ifndef DMAMODE_AUTO - printk ("sound: Invalid DMA mode for device %d\n", dev); -#endif -#if defined(SVR42) - - /* - ** send full count to snd_dma_prog, it will take care of subtracting - ** one if it is required. - */ - snd_dma_prog (chan, dmap->raw_buf_phys[0], dmap->bytes_in_use, - dma_mode, TRUE); - -#else /* !SVR42 */ - dma_param (chan, ((dma_mode == DMA_MODE_READ) ? DMA_Rdmode : DMA_Wrmode) -#ifdef DMAMODE_AUTO - | DMAMODE_AUTO -#endif - , - dmap->raw_buf_phys[0], dmap->bytes_in_use - 1); - dma_enable (chan); -#endif /* ! SVR42 */ -#else -#error This routine is not valid for this OS. -#endif -#endif - -#endif - } - else - { -#ifdef linux - DISABLE_INTR (flags); - disable_dma (chan); - clear_dma_ff (chan); - set_dma_mode (chan, dma_mode); - set_dma_addr (chan, physaddr); - set_dma_count (chan, count); - enable_dma (chan); - RESTORE_INTR (flags); -#else -#if defined(__FreeBSD__) - isa_dmastart ((dma_mode == DMA_MODE_READ) ? B_READ : B_WRITE, - (caddr_t)physaddr, - count, - chan); -#else /* FreeBSD */ - -#if defined(GENERIC_SYSV) -#if defined(SVR42) - - snd_dma_prog (chan, physaddr, count, dma_mode, FALSE); - -#else /* ! SVR42 */ - dma_param (chan, ((dma_mode == DMA_MODE_READ) ? DMA_Rdmode : DMA_Wrmode), - physaddr, count); - dma_enable (chan); -#endif /* SVR42 */ -#else -#error This routine is not valid for this OS. -#endif /* GENERIC_SYSV */ -#endif - -#endif - } - - return count; -} - -long -DMAbuf_init (long mem_start) -{ - int dev; - -#if defined(SVR42) - snd_dma_init (); -#endif /* SVR42 */ - - /* - * NOTE! This routine could be called several times. - */ - - for (dev = 0; dev < num_audiodevs; dev++) - audio_devs[dev]->dmap = &dmaps[dev]; - return mem_start; -} - -void -DMAbuf_outputintr (int dev, int event_type) -{ - /* - * Event types: - * 0 = DMA transfer done. Device still has more data in the local - * buffer. - * 1 = DMA transfer done. Device doesn't have local buffer or it's - * empty now. - * 2 = No DMA transfer but the device has now more space in it's local - * buffer. - */ - - unsigned long flags; - struct dma_buffparms *dmap = audio_devs[dev]->dmap; - -#if defined(SVR42) - snd_dma_intr (audio_devs[dev]->dmachan); -#endif /* SVR42 */ - - if (event_type != 2) - { - if (dmap->qlen <= 0 || dmap->qlen > dmap->nbufs) - { - printk ("\nSound: Audio queue3 corrupted for dev%d (%d/%d)\n", - dev, dmap->qlen, dmap->nbufs); - return; - } - - dmap->qlen--; - dmap->qhead = (dmap->qhead + 1) % dmap->nbufs; - dmap->flags &= ~DMA_ACTIVE; - -#ifdef __FreeBSD__ - isa_dmadone(0, 0, 0, audio_devs[dev]->dmachan); -#endif - - if (dmap->qlen) - { - audio_devs[dev]->output_block (dev, dmap->buf_phys[dmap->qhead], - dmap->counts[dmap->qhead], 1, - !(audio_devs[dev]->flags & DMA_AUTOMODE)); - dmap->flags |= DMA_ACTIVE; - } - else if (event_type == 1) - { - dmap->underrun_count++; - audio_devs[dev]->halt_xfer (dev); - if ((audio_devs[dev]->flags & DMA_AUTOMODE) && - audio_devs[dev]->flags & NEEDS_RESTART) - dmap->flags |= DMA_RESTART; - else - dmap->flags &= ~DMA_RESTART; - } - } /* event_type != 2 */ - - DISABLE_INTR (flags); - if (SOMEONE_WAITING (dev_sleeper[dev], dev_sleep_flag[dev])) - { - WAKE_UP (dev_sleeper[dev], dev_sleep_flag[dev]); - } - RESTORE_INTR (flags); -#if defined(__FreeBSD__) - if(selinfo[dev].si_pid) - selwakeup(&selinfo[dev]); -#endif -} - -void -DMAbuf_inputintr (int dev) -{ - unsigned long flags; - struct dma_buffparms *dmap = audio_devs[dev]->dmap; - -#if defined(SVR42) - snd_dma_intr (audio_devs[dev]->dmachan); -#endif /* SVR42 */ - -#ifdef __FreeBSD__ - isa_dmadone(0, 0, 0, audio_devs[dev]->dmachan); -#endif - - if (dmap->qlen == (dmap->nbufs - 1)) - { -#if !defined(__FreeBSD__) /* ignore console message. */ - printk ("Sound: Recording overrun\n"); -#endif - dmap->underrun_count++; - audio_devs[dev]->halt_xfer (dev); - dmap->flags &= ~DMA_ACTIVE; - if (audio_devs[dev]->flags & DMA_AUTOMODE) - dmap->flags |= DMA_RESTART; - else - dmap->flags &= ~DMA_RESTART; - } - else - { - dmap->qlen++; - if (dmap->qlen <= 0 || dmap->qlen > dmap->nbufs) - printk ("\nSound: Audio queue4 corrupted for dev%d (%d/%d)\n", - dev, dmap->qlen, dmap->nbufs); - dmap->qtail = (dmap->qtail + 1) % dmap->nbufs; - - audio_devs[dev]->start_input (dev, dmap->buf_phys[dmap->qtail], - dmap->fragment_size, 1, - !(audio_devs[dev]->flags & DMA_AUTOMODE)); - dmap->flags |= DMA_ACTIVE; - } - - DISABLE_INTR (flags); - if (SOMEONE_WAITING (dev_sleeper[dev], dev_sleep_flag[dev])) - { - WAKE_UP (dev_sleeper[dev], dev_sleep_flag[dev]); - } - RESTORE_INTR (flags); -#if defined(__FreeBSD__) - if(selinfo[dev].si_pid) - selwakeup(&selinfo[dev]); -#endif -} - -int -DMAbuf_open_dma (int dev) -{ - unsigned long flags; - int chan = audio_devs[dev]->dmachan; - - if (ALLOC_DMA_CHN (chan, audio_devs[dev]->name)) - { -#if 0 - /* Enough already! This error is reported twice elsewhere */ - printk ("Unable to grab DMA%d for the audio driver\n", chan); -#endif - return RET_ERROR (EBUSY); - } - - DISABLE_INTR (flags); -#ifdef linux - disable_dma (chan); - clear_dma_ff (chan); -#endif - RESTORE_INTR (flags); - - return 0; -} - -void -DMAbuf_close_dma (int dev) -{ - int chan = audio_devs[dev]->dmachan; - - DMAbuf_reset_dma (dev); - RELEASE_DMA_CHN (chan); -} - -void -DMAbuf_reset_dma (int dev) -{ -} - -#ifdef ALLOW_SELECT -int -DMAbuf_select (int dev, struct fileinfo *file, int sel_type, select_table * wait) -{ - struct dma_buffparms *dmap = audio_devs[dev]->dmap; - unsigned long flags; - - switch (sel_type) - { - case SEL_IN: - if (dmap->dma_mode != DMODE_INPUT) - return 0; - - DISABLE_INTR (flags); - if (!dmap->qlen) - { -#if defined(__FreeBSD__) - selrecord(wait, &selinfo[dev]); -#else - dev_sleep_flag[dev].mode = WK_SLEEP; - select_wait (&dev_sleeper[dev], wait); -#endif - RESTORE_INTR (flags); - return 0; - } - RESTORE_INTR (flags); - return 1; - break; - - case SEL_OUT: - if (dmap->dma_mode == DMODE_INPUT) - return 0; - - if (dmap->dma_mode == DMODE_NONE) - return 1; - - DISABLE_INTR (flags); - if (!space_in_queue (dev)) - { -#if defined(__FreeBSD__) - selrecord(wait, &selinfo[dev]); -#else - dev_sleep_flag[dev].mode = WK_SLEEP; - select_wait (&dev_sleeper[dev], wait); -#endif - RESTORE_INTR (flags); - return 0; - } - RESTORE_INTR (flags); - return 1; - break; - - case SEL_EX: - return 0; - } - - return 0; -} - -#endif /* ALLOW_SELECT */ - -#else /* EXCLUDE_AUDIO */ -/* - * Stub versions if audio services not included - */ - -int -DMAbuf_open (int dev, int mode) -{ - return RET_ERROR (ENXIO); -} - -int -DMAbuf_release (int dev, int mode) -{ - return 0; -} - -int -DMAbuf_getwrbuffer (int dev, char **buf, int *size, int dontblock) -{ - return RET_ERROR (EIO); -} - -int -DMAbuf_getrdbuffer (int dev, char **buf, int *len, int dontblock) -{ - return RET_ERROR (EIO); -} - -int -DMAbuf_rmchars (int dev, int buff_no, int c) -{ - return RET_ERROR (EIO); -} - -int -DMAbuf_start_output (int dev, int buff_no, int l) -{ - return RET_ERROR (EIO); -} - -int -DMAbuf_ioctl (int dev, unsigned int cmd, unsigned int arg, int local) -{ - return RET_ERROR (EIO); -} - -long -DMAbuf_init (long mem_start) -{ - return mem_start; -} - -int -DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode) -{ - return RET_ERROR (EIO); -} - -int -DMAbuf_open_dma (int dev) -{ - return RET_ERROR (ENXIO); -} - -void -DMAbuf_close_dma (int dev) -{ - return; -} - -void -DMAbuf_reset_dma (int dev) -{ - return; -} - -void -DMAbuf_inputintr (int dev) -{ - return; -} - -void -DMAbuf_outputintr (int dev, int underrun_flag) -{ - return; -} - -#endif - -#endif diff --git a/sys/pc98/pc98/sound/gus_card.c b/sys/pc98/pc98/sound/gus_card.c deleted file mode 100644 index 0e96df1..0000000 --- a/sys/pc98/pc98/sound/gus_card.c +++ /dev/null @@ -1,197 +0,0 @@ -/* - * sound/gus_card.c - * - * Detection routine for the Gravis Ultrasound. - * - * Copyright by Hannu Savolainen 1993 - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. 2. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#include <i386/isa/sound/sound_config.h> - -#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_GUS) - -#include <i386/isa/sound/gus_hw.h> - -int gus_base, gus_irq, gus_dma; -extern int gus_wave_volume; -extern int gus_pcm_volume; -extern int have_gus_max; - -long -attach_gus_card (long mem_start, struct address_info *hw_config) -{ - int io_addr; - - snd_set_irq_handler (hw_config->irq, gusintr, "Gravis Ultrasound"); - - if (gus_wave_detect (hw_config->io_base)) /* - * Try first the default - */ - { - mem_start = gus_wave_init (mem_start, hw_config->irq, hw_config->dma, - hw_config->dma_read); -#ifndef EXCLUDE_MIDI - mem_start = gus_midi_init (mem_start); -#endif -#ifndef EXCLUDE_SEQUENCER - sound_timer_init (hw_config->io_base + 8); -#endif - return mem_start; - } - -#ifndef EXCLUDE_GUS_IODETECT - - /* - * Look at the possible base addresses (0x2X0, X=1, 2, 3, 4, 5, 6) - */ - - for (io_addr = 0x210; io_addr <= 0x260; io_addr += 0x10) - if (io_addr != hw_config->io_base) /* - * Already tested - */ - if (gus_wave_detect (io_addr)) - { - printk (" WARNING! GUS found at %x, config was %x ", io_addr, hw_config->io_base); - mem_start = gus_wave_init (mem_start, hw_config->irq, hw_config->dma, - hw_config->dma_read); -#ifndef EXCLUDE_MIDI - mem_start = gus_midi_init (mem_start); -#endif -#ifndef EXCLUDE_SEQUENCER - sound_timer_init (io_addr + 8); -#endif - return mem_start; - } - -#endif - - return mem_start; /* - * Not detected - */ -} - -int -probe_gus (struct address_info *hw_config) -{ - int io_addr; - - if (gus_wave_detect (hw_config->io_base)) - return 1; - -#ifndef EXCLUDE_GUS_IODETECT - - /* - * Look at the possible base addresses (0x2X0, X=1, 2, 3, 4, 5, 6) - */ - - for (io_addr = 0x210; io_addr <= 0x260; io_addr += 0x10) - if (io_addr != hw_config->io_base) /* - * Already tested - */ - if (gus_wave_detect (io_addr)) - return 1; - -#endif - - return 0; -} - -void -gusintr (INT_HANDLER_PARMS (irq, dummy)) -{ - unsigned char src; - -#ifdef linux - sti (); -#endif - -#ifndef EXCLUDE_GUSMAX - if (have_gus_max) -# if defined(__FreeBSD__) - ad1848_interrupt (INT_HANDLER_CALL (gus_irq)); -# else - ad1848_interrupt (INT_HANDLER_CALL (irq)); -# endif -#endif - - while (1) - { - if (!(src = INB (u_IrqStatus))) - return; - - if (src & DMA_TC_IRQ) - { - guswave_dma_irq (); - } - - if (src & (MIDI_TX_IRQ | MIDI_RX_IRQ)) - { -#ifndef EXCLUDE_MIDI - gus_midi_interrupt (0); -#endif - } - - if (src & (GF1_TIMER1_IRQ | GF1_TIMER2_IRQ)) - { -#ifndef EXCLUDE_SEQUENCER - sound_timer_interrupt (); -#else - gus_write8 (0x45, 0); /* Stop timers */ -#endif - } - - if (src & (WAVETABLE_IRQ | ENVELOPE_IRQ)) - { - gus_voice_irq (); - } - } -} - -#endif - -/* - * Some extra code for the 16 bit sampling option - */ -#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_GUS16) - -int -probe_gus_db16 (struct address_info *hw_config) -{ - return ad1848_detect (hw_config->io_base); -} - -long -attach_gus_db16 (long mem_start, struct address_info *hw_config) -{ - gus_pcm_volume = 100; - gus_wave_volume = 90; - - ad1848_init ("GUS 16 bit sampling", hw_config->io_base, - hw_config->irq, - hw_config->dma, - hw_config->dma); - return mem_start; -} - -#endif diff --git a/sys/pc98/pc98/sound/gus_midi.c b/sys/pc98/pc98/sound/gus_midi.c deleted file mode 100644 index 876c665..0000000 --- a/sys/pc98/pc98/sound/gus_midi.c +++ /dev/null @@ -1,312 +0,0 @@ -/* - * sound/gus2_midi.c - * - * The low level driver for the GUS Midi Interface. - * - * Copyright by Hannu Savolainen 1993 - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. 2. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#include <i386/isa/sound/sound_config.h> - -#ifdef CONFIGURE_SOUNDCARD - -#include <i386/isa/sound/gus_hw.h> - -#if !defined(EXCLUDE_GUS) && !defined(EXCLUDE_MIDI) - -static int midi_busy = 0, input_opened = 0; -static int my_dev; -static int output_used = 0; -static volatile unsigned char gus_midi_control; - -static void (*midi_input_intr) (int dev, unsigned char data); - -static unsigned char tmp_queue[256]; -static volatile int qlen; -static volatile unsigned char qhead, qtail; -extern int gus_base, gus_irq, gus_dma; - -#define GUS_MIDI_STATUS() INB(u_MidiStatus) - -static int -gus_midi_open (int dev, int mode, - void (*input) (int dev, unsigned char data), - void (*output) (int dev) -) -{ - - if (midi_busy) - { - printk ("GUS: Midi busy\n"); - return RET_ERROR (EBUSY); - } - - OUTB (MIDI_RESET, u_MidiControl); - gus_delay (); - - gus_midi_control = 0; - input_opened = 0; - - if (mode == OPEN_READ || mode == OPEN_READWRITE) - { - gus_midi_control |= MIDI_ENABLE_RCV; - input_opened = 1; - } - - if (mode == OPEN_WRITE || mode == OPEN_READWRITE) - { - gus_midi_control |= MIDI_ENABLE_XMIT; - } - - OUTB (gus_midi_control, u_MidiControl); /* - * Enable - */ - - midi_busy = 1; - qlen = qhead = qtail = output_used = 0; - midi_input_intr = input; - - return 0; -} - -static int -dump_to_midi (unsigned char midi_byte) -{ - unsigned long flags; - int ok = 0; - - output_used = 1; - - DISABLE_INTR (flags); - - if (GUS_MIDI_STATUS () & MIDI_XMIT_EMPTY) - { - ok = 1; - OUTB (midi_byte, u_MidiData); - } - else - { - /* - * Enable Midi xmit interrupts (again) - */ - gus_midi_control |= MIDI_ENABLE_XMIT; - OUTB (gus_midi_control, u_MidiControl); - } - - RESTORE_INTR (flags); - return ok; -} - -static void -gus_midi_close (int dev) -{ - /* - * Reset FIFO pointers, disable intrs - */ - - OUTB (MIDI_RESET, u_MidiControl); - midi_busy = 0; -} - -static int -gus_midi_out (int dev, unsigned char midi_byte) -{ - - unsigned long flags; - - /* - * Drain the local queue first - */ - - DISABLE_INTR (flags); - - while (qlen && dump_to_midi (tmp_queue[qhead])) - { - qlen--; - qhead++; - } - - RESTORE_INTR (flags); - - /* - * Output the byte if the local queue is empty. - */ - - if (!qlen) - if (dump_to_midi (midi_byte)) - return 1; /* - * OK - */ - - /* - * Put to the local queue - */ - - if (qlen >= 256) - return 0; /* - * Local queue full - */ - - DISABLE_INTR (flags); - - tmp_queue[qtail] = midi_byte; - qlen++; - qtail++; - - RESTORE_INTR (flags); - - return 1; -} - -static int -gus_midi_start_read (int dev) -{ - return 0; -} - -static int -gus_midi_end_read (int dev) -{ - return 0; -} - -static int -gus_midi_ioctl (int dev, unsigned cmd, unsigned arg) -{ - return RET_ERROR (EINVAL); -} - -static void -gus_midi_kick (int dev) -{ -} - -static int -gus_midi_buffer_status (int dev) -{ - unsigned long flags; - - if (!output_used) - return 0; - - DISABLE_INTR (flags); - - if (qlen && dump_to_midi (tmp_queue[qhead])) - { - qlen--; - qhead++; - } - - RESTORE_INTR (flags); - - return (qlen > 0) | !(GUS_MIDI_STATUS () & MIDI_XMIT_EMPTY); -} - -#define MIDI_SYNTH_NAME "Gravis Ultrasound Midi" -#define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT -#include <i386/isa/sound/midi_synth.h> - -static struct midi_operations gus_midi_operations = -{ - {"Gravis UltraSound Midi", 0, 0, SNDCARD_GUS}, - &std_midi_synth, - {0}, - gus_midi_open, - gus_midi_close, - gus_midi_ioctl, - gus_midi_out, - gus_midi_start_read, - gus_midi_end_read, - gus_midi_kick, - NULL, /* - * command - */ - gus_midi_buffer_status, - NULL -}; - -long -gus_midi_init (long mem_start) -{ - if (num_midis >= MAX_MIDI_DEV) - { - printk ("Sound: Too many midi devices detected\n"); - return mem_start; - } - - OUTB (MIDI_RESET, u_MidiControl); - - std_midi_synth.midi_dev = my_dev = num_midis; - midi_devs[num_midis++] = &gus_midi_operations; - return mem_start; -} - -void -gus_midi_interrupt (int dummy) -{ - unsigned char stat, data; - unsigned long flags; - - DISABLE_INTR (flags); - - stat = GUS_MIDI_STATUS (); - - if (stat & MIDI_RCV_FULL) - { - data = INB (u_MidiData); - if (input_opened) - midi_input_intr (my_dev, data); - } - - if (stat & MIDI_XMIT_EMPTY) - { - while (qlen && dump_to_midi (tmp_queue[qhead])) - { - qlen--; - qhead++; - } - - if (!qlen) - { - /* - * Disable Midi output interrupts, since no data in the buffer - */ - gus_midi_control &= ~MIDI_ENABLE_XMIT; - OUTB (gus_midi_control, u_MidiControl); - } - } - -#if 0 - if (stat & MIDI_FRAME_ERR) - printk ("GUS: Midi framing error\n"); - if (stat & MIDI_OVERRUN && input_opened) - printk ("GUS: Midi input overrun\n"); -#endif - - RESTORE_INTR (flags); -} - -#endif - -#endif diff --git a/sys/pc98/pc98/sound/gus_vol.c b/sys/pc98/pc98/sound/gus_vol.c deleted file mode 100644 index a8f1121..0000000 --- a/sys/pc98/pc98/sound/gus_vol.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * gus_vol.c - Compute volume for GUS. - * - * Greg Lee 1993. - */ -#include <i386/isa/sound/sound_config.h> -#ifndef EXCLUDE_GUS -#include <i386/isa/sound/gus_linearvol.h> - -extern unsigned short gus_adagio_vol (int vel, int mainv, int xpn, int voicev); -extern unsigned short gus_linear_vol (int vol, int mainvol); - -#define GUS_VOLUME gus_wave_volume - - -extern int gus_wave_volume; - -/* - * Calculate gus volume from note velocity, main volume, expression, and - * intrinsic patch volume given in patch library. Expression is multiplied - * in, so it emphasizes differences in note velocity, while main volume is - * added in -- I don't know whether this is right, but it seems reasonable to - * me. (In the previous stage, main volume controller messages were changed - * to expression controller messages, if they were found to be used for - * dynamic volume adjustments, so here, main volume can be assumed to be - * constant throughout a song.) - * - * Intrinsic patch volume is added in, but if over 64 is also multiplied in, so - * we can give a big boost to very weak voices like nylon guitar and the - * basses. The normal value is 64. Strings are assigned lower values. - */ -unsigned short -gus_adagio_vol (int vel, int mainv, int xpn, int voicev) -{ - int i, m, n, x; - - - /* - * A voice volume of 64 is considered neutral, so adjust the main volume if - * something other than this neutral value was assigned in the patch - * library. - */ - x = 256 + 6 * (voicev - 64); - - /* - * Boost expression by voice volume above neutral. - */ - if (voicev > 65) - xpn += voicev - 64; - xpn += (voicev - 64) / 2; - - /* - * Combine multiplicative and level components. - */ - x = vel * xpn * 6 + (voicev / 4) * x; - -#ifdef GUS_VOLUME - /* - * Further adjustment by installation-specific master volume control - * (default 60). - */ - x = (x * GUS_VOLUME * GUS_VOLUME) / 10000; -#endif - -#ifdef GUS_USE_CHN_MAIN_VOLUME - /* - * Experimental support for the channel main volume - */ - - mainv = (mainv / 2) + 64; /* Scale to 64 to 127 */ - x = (x * mainv * mainv) / 16384; -#endif - - if (x < 2) - return (0); - else if (x >= 65535) - return ((15 << 8) | 255); - - /* - * Convert to gus's logarithmic form with 4 bit exponent i and 8 bit - * mantissa m. - */ - n = x; - i = 7; - if (n < 128) - { - while (i > 0 && n < (1 << i)) - i--; - } - else - while (n > 255) - { - n >>= 1; - i++; - } - /* - * Mantissa is part of linear volume not expressed in exponent. (This is - * not quite like real logs -- I wonder if it's right.) - */ - m = x - (1 << i); - - /* - * Adjust mantissa to 8 bits. - */ - if (m > 0) - { - if (i > 8) - m >>= i - 8; - else if (i < 8) - m <<= 8 - i; - } - - return ((i << 8) + m); -} - -/* - * Volume-values are interpreted as linear values. Volume is based on the - * value supplied with SEQ_START_NOTE(), channel main volume (if compiled in) - * and the volume set by the mixer-device (default 60%). - */ - -unsigned short -gus_linear_vol (int vol, int mainvol) -{ - int mixer_mainvol; - - if (vol <= 0) - vol = 0; - else if (vol >= 127) - vol = 127; - -#ifdef GUS_VOLUME - mixer_mainvol = GUS_VOLUME; -#else - mixer_mainvol = 100; -#endif - -#ifdef GUS_USE_CHN_MAIN_VOLUME - if (mainvol <= 0) - mainvol = 0; - else if (mainvol >= 127) - mainvol = 127; -#else - mainvol = 128; -#endif - - return gus_linearvol[(((vol * mainvol) / 128) * mixer_mainvol) / 100]; -} - -#endif diff --git a/sys/pc98/pc98/sound/gus_wave.c b/sys/pc98/pc98/sound/gus_wave.c deleted file mode 100644 index e0f946d6..0000000 --- a/sys/pc98/pc98/sound/gus_wave.c +++ /dev/null @@ -1,3445 +0,0 @@ -/* - * sound/gus_wave.c - * - * Driver for the Gravis UltraSound wave table synth. - * - * Copyright by Hannu Savolainen 1993, 1994 - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. 2. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#include <i386/isa/sound/sound_config.h> -#include <machine/ultrasound.h> -#include <i386/isa/sound/gus_hw.h> - -static unsigned char gus_look8 __P((int reg)); -static unsigned short gus_read16 __P((int reg)); -static void gus_write_addr __P((int reg, unsigned long address, int is16bit)); -static void gus_write16 __P((int reg, unsigned int data)); - -#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_GUS) - -#define MAX_SAMPLE 150 -#define MAX_PATCH 256 - -struct voice_info - { - unsigned long orig_freq; - unsigned long current_freq; - unsigned long mode; - int bender; - int bender_range; - int panning; - int midi_volume; - unsigned int initial_volume; - unsigned int current_volume; - int loop_irq_mode, loop_irq_parm; -#define LMODE_FINISH 1 -#define LMODE_PCM 2 -#define LMODE_PCM_STOP 3 - int volume_irq_mode, volume_irq_parm; -#define VMODE_HALT 1 -#define VMODE_ENVELOPE 2 -#define VMODE_START_NOTE 3 - - int env_phase; - unsigned char env_rate[6]; - unsigned char env_offset[6]; - - /* - * Volume computation parameters for gus_adagio_vol() - */ - int main_vol, expression_vol, patch_vol; - - /* Variables for "Ultraclick" removal */ - int dev_pending, note_pending, volume_pending, sample_pending; - char kill_pending; - long offset_pending; - - }; - -static struct voice_alloc_info *voice_alloc; - -extern int gus_base; -extern int gus_irq, gus_dma; -static long gus_mem_size = 0; -static long free_mem_ptr = 0; -static int gus_busy[MAX_AUDIO_DEV], gus_dspnum=0; -static int gus_dma_read=0; -static int nr_voices = 0; -static int gus_devnum = 0; -static int volume_base, volume_scale, volume_method; -static int gus_recmask = SOUND_MASK_MIC; -static int recording_active = 0; -static int only_read_access = 0; - -int gus_wave_volume = 60; -static int gus_pcm_volume = 80; -int have_gus_max = 0; -static int gus_line_vol = 100, gus_mic_vol = 0; -static unsigned char mix_image = 0x00; - -/* - * Current version of this driver doesn't allow synth and PCM functions - * at the same time. The active_device specifies the active driver - */ -static int active_device = 0; - -#define GUS_DEV_WAVE 1 /* Wave table synth */ -#define GUS_DEV_PCM_DONE 2 /* PCM device, transfer done */ -#define GUS_DEV_PCM_CONTINUE 3 /* PCM device, transfer done ch. 1/2 */ - -static int gus_sampling_speed; -static int gus_sampling_channels; -static int gus_sampling_bits; - -DEFINE_WAIT_QUEUE (dram_sleeper, dram_sleep_flag); - -/* - * Variables and buffers for PCM output - */ -#define MAX_PCM_BUFFERS (32*MAX_REALTIME_FACTOR) /* Don't change */ - -static int pcm_bsize, pcm_nblk, pcm_banksize; -static int pcm_datasize[MAX_PCM_BUFFERS]; -static volatile int pcm_head, pcm_tail, pcm_qlen; -static volatile int pcm_active; -static volatile int dma_active; -static int pcm_opened = 0; -static int pcm_current_dev; -static int pcm_current_block; -static unsigned long pcm_current_buf; -static int pcm_current_count; -static int pcm_current_intrflag; - -#if defined(__FreeBSD__) -static char *gus_copy_buf; -#endif - -static struct voice_info voices[32]; - -static int freq_div_table[] = -{ - 44100, /* 14 */ - 41160, /* 15 */ - 38587, /* 16 */ - 36317, /* 17 */ - 34300, /* 18 */ - 32494, /* 19 */ - 30870, /* 20 */ - 29400, /* 21 */ - 28063, /* 22 */ - 26843, /* 23 */ - 25725, /* 24 */ - 24696, /* 25 */ - 23746, /* 26 */ - 22866, /* 27 */ - 22050, /* 28 */ - 21289, /* 29 */ - 20580, /* 30 */ - 19916, /* 31 */ - 19293 /* 32 */ -}; - -static struct patch_info *samples; -static long sample_ptrs[MAX_SAMPLE + 1]; -static int sample_map[32]; -static int free_sample; - - -static int patch_table[MAX_PATCH]; -static int patch_map[32]; - -static struct synth_info gus_info = -{"Gravis UltraSound", 0, SYNTH_TYPE_SAMPLE, SAMPLE_TYPE_GUS, 0, 16, 0, MAX_PATCH}; - -static void gus_poke (long addr, unsigned char data); -static void compute_and_set_volume (int voice, int volume, int ramp_time); -extern unsigned short gus_adagio_vol (int vel, int mainv, int xpn, int voicev); -extern unsigned short gus_linear_vol (int vol, int mainvol); -static void compute_volume (int voice, int volume); -static void do_volume_irq (int voice); -static void set_input_volumes (void); - -#define INSTANT_RAMP -1 /* Instant change. No ramping */ -#define FAST_RAMP 0 /* Fastest possible ramp */ - -static void -reset_sample_memory (void) -{ - int i; - - for (i = 0; i <= MAX_SAMPLE; i++) - sample_ptrs[i] = -1; - for (i = 0; i < 32; i++) - sample_map[i] = -1; - for (i = 0; i < 32; i++) - patch_map[i] = -1; - - gus_poke (0, 0); /* Put a silent sample to the beginning */ - gus_poke (1, 0); - free_mem_ptr = 2; - - free_sample = 0; - - for (i = 0; i < MAX_PATCH; i++) - patch_table[i] = -1; -} - -void -gus_delay (void) -{ - int i; - - for (i = 0; i < 7; i++) - INB (u_DRAMIO); -} - -static void -gus_poke (long addr, unsigned char data) -{ /* Writes a byte to the DRAM */ - unsigned long flags; - - DISABLE_INTR (flags); - OUTB (0x43, u_Command); - OUTB (addr & 0xff, u_DataLo); - OUTB ((addr >> 8) & 0xff, u_DataHi); - - OUTB (0x44, u_Command); - OUTB ((addr >> 16) & 0xff, u_DataHi); - OUTB (data, u_DRAMIO); - RESTORE_INTR (flags); -} - -static unsigned char -gus_peek (long addr) -{ /* Reads a byte from the DRAM */ - unsigned long flags; - unsigned char tmp; - - DISABLE_INTR (flags); - OUTB (0x43, u_Command); - OUTB (addr & 0xff, u_DataLo); - OUTB ((addr >> 8) & 0xff, u_DataHi); - - OUTB (0x44, u_Command); - OUTB ((addr >> 16) & 0xff, u_DataHi); - tmp = INB (u_DRAMIO); - RESTORE_INTR (flags); - - return tmp; -} - -void -gus_write8 (int reg, unsigned int data) -{ /* Writes to an indirect register (8 bit) */ - unsigned long flags; - - DISABLE_INTR (flags); - - OUTB (reg, u_Command); - OUTB ((unsigned char) (data & 0xff), u_DataHi); - - RESTORE_INTR (flags); -} - -static unsigned char -gus_read8 (int reg) -{ /* Reads from an indirect register (8 bit). Offset 0x80. */ - unsigned long flags; - unsigned char val; - - DISABLE_INTR (flags); - OUTB (reg | 0x80, u_Command); - val = INB (u_DataHi); - RESTORE_INTR (flags); - - return val; -} - -static unsigned char -gus_look8 (int reg) -{ /* Reads from an indirect register (8 bit). No additional offset. */ - unsigned long flags; - unsigned char val; - - DISABLE_INTR (flags); - OUTB (reg, u_Command); - val = INB (u_DataHi); - RESTORE_INTR (flags); - - return val; -} - -static void -gus_write16 (int reg, unsigned int data) -{ /* Writes to an indirect register (16 bit) */ - unsigned long flags; - - DISABLE_INTR (flags); - - OUTB (reg, u_Command); - - OUTB ((unsigned char) (data & 0xff), u_DataLo); - OUTB ((unsigned char) ((data >> 8) & 0xff), u_DataHi); - - RESTORE_INTR (flags); -} - -static unsigned short -gus_read16 (int reg) -{ /* Reads from an indirect register (16 bit). Offset 0x80. */ - unsigned long flags; - unsigned char hi, lo; - - DISABLE_INTR (flags); - - OUTB (reg | 0x80, u_Command); - - lo = INB (u_DataLo); - hi = INB (u_DataHi); - - RESTORE_INTR (flags); - - return ((hi << 8) & 0xff00) | lo; -} - -static void -gus_write_addr (int reg, unsigned long address, int is16bit) -{ /* Writes an 24 bit memory address */ - unsigned long hold_address; - unsigned long flags; - - DISABLE_INTR (flags); - if (is16bit) - { - /* - * Special processing required for 16 bit patches - */ - - hold_address = address; - address = address >> 1; - address &= 0x0001ffffL; - address |= (hold_address & 0x000c0000L); - } - - gus_write16 (reg, (unsigned short) ((address >> 7) & 0xffff)); - gus_write16 (reg + 1, (unsigned short) ((address << 9) & 0xffff)); - /* Could writing twice fix problems with GUS_VOICE_POS() ? Lets try... */ - gus_delay (); - gus_write16 (reg, (unsigned short) ((address >> 7) & 0xffff)); - gus_write16 (reg + 1, (unsigned short) ((address << 9) & 0xffff)); - RESTORE_INTR (flags); -} - -static void -gus_select_voice (int voice) -{ - if (voice < 0 || voice > 31) - return; - - OUTB (voice, u_Voice); -} - -static void -gus_select_max_voices (int nvoices) -{ - if (nvoices < 14) - nvoices = 14; - if (nvoices > 32) - nvoices = 32; - - voice_alloc->max_voice = nr_voices = nvoices; - - gus_write8 (0x0e, (nvoices - 1) | 0xc0); -} - -static void -gus_voice_on (unsigned int mode) -{ - gus_write8 (0x00, (unsigned char) (mode & 0xfc)); - gus_delay (); - gus_write8 (0x00, (unsigned char) (mode & 0xfc)); -} - -static void -gus_voice_off (void) -{ - gus_write8 (0x00, gus_read8 (0x00) | 0x03); -} - -static void -gus_voice_mode (unsigned int m) -{ - unsigned char mode = (unsigned char) (m & 0xff); - - gus_write8 (0x00, (gus_read8 (0x00) & 0x03) | - (mode & 0xfc)); /* Don't touch last two bits */ - gus_delay (); - gus_write8 (0x00, (gus_read8 (0x00) & 0x03) | (mode & 0xfc)); -} - -static void -gus_voice_freq (unsigned long freq) -{ - unsigned long divisor = freq_div_table[nr_voices - 14]; - unsigned short fc; - - fc = (unsigned short) (((freq << 9) + (divisor >> 1)) / divisor); - fc = fc << 1; - - gus_write16 (0x01, fc); -} - -static void -gus_voice_volume (unsigned int vol) -{ - gus_write8 (0x0d, 0x03); /* Stop ramp before setting volume */ - gus_write16 (0x09, (unsigned short) (vol << 4)); -} - -static void -gus_voice_balance (unsigned int balance) -{ - gus_write8 (0x0c, (unsigned char) (balance & 0xff)); -} - -static void -gus_ramp_range (unsigned int low, unsigned int high) -{ - gus_write8 (0x07, (unsigned char) ((low >> 4) & 0xff)); - gus_write8 (0x08, (unsigned char) ((high >> 4) & 0xff)); -} - -static void -gus_ramp_rate (unsigned int scale, unsigned int rate) -{ - gus_write8 (0x06, (unsigned char) (((scale & 0x03) << 6) | (rate & 0x3f))); -} - -static void -gus_rampon (unsigned int m) -{ - unsigned char mode = (unsigned char) (m & 0xff); - - gus_write8 (0x0d, mode & 0xfc); - gus_delay (); - gus_write8 (0x0d, mode & 0xfc); -} - -static void -gus_ramp_mode (unsigned int m) -{ - unsigned char mode = (unsigned char) (m & 0xff); - - gus_write8 (0x0d, (gus_read8 (0x0d) & 0x03) | - (mode & 0xfc)); /* Leave the last 2 bits alone */ - gus_delay (); - gus_write8 (0x0d, (gus_read8 (0x0d) & 0x03) | (mode & 0xfc)); -} - -static void -gus_rampoff (void) -{ - gus_write8 (0x0d, 0x03); -} - -static void -gus_set_voice_pos (int voice, long position) -{ - int sample_no; - - if ((sample_no = sample_map[voice]) != -1) - if (position < samples[sample_no].len) - if (voices[voice].volume_irq_mode == VMODE_START_NOTE) - voices[voice].offset_pending = position; - else - gus_write_addr (0x0a, sample_ptrs[sample_no] + position, - samples[sample_no].mode & WAVE_16_BITS); -} - -static void -gus_voice_init (int voice) -{ - unsigned long flags; - - DISABLE_INTR (flags); - gus_select_voice (voice); - gus_voice_volume (0); - gus_voice_off (); - gus_write_addr (0x0a, 0, 0); /* Set current position to 0 */ - gus_write8 (0x00, 0x03); /* Voice off */ - gus_write8 (0x0d, 0x03); /* Ramping off */ - voice_alloc->map[voice] = 0; - voice_alloc->alloc_times[voice] = 0; - RESTORE_INTR (flags); - -} - -static void -gus_voice_init2 (int voice) -{ - voices[voice].panning = 0; - voices[voice].mode = 0; - voices[voice].orig_freq = 20000; - voices[voice].current_freq = 20000; - voices[voice].bender = 0; - voices[voice].bender_range = 200; - voices[voice].initial_volume = 0; - voices[voice].current_volume = 0; - voices[voice].loop_irq_mode = 0; - voices[voice].loop_irq_parm = 0; - voices[voice].volume_irq_mode = 0; - voices[voice].volume_irq_parm = 0; - voices[voice].env_phase = 0; - voices[voice].main_vol = 127; - voices[voice].patch_vol = 127; - voices[voice].expression_vol = 127; - voices[voice].sample_pending = -1; -} - -static void -step_envelope (int voice) -{ - unsigned vol, prev_vol, phase; - unsigned char rate; - long int flags; - - if (voices[voice].mode & WAVE_SUSTAIN_ON && voices[voice].env_phase == 2) - { - DISABLE_INTR (flags); - gus_select_voice (voice); - gus_rampoff (); - RESTORE_INTR (flags); - return; - /* - * Sustain phase begins. Continue envelope after receiving note off. - */ - } - - if (voices[voice].env_phase >= 5) - { /* Envelope finished. Shoot the voice down */ - gus_voice_init (voice); - return; - } - - prev_vol = voices[voice].current_volume; - phase = ++voices[voice].env_phase; - compute_volume (voice, voices[voice].midi_volume); - vol = voices[voice].initial_volume * voices[voice].env_offset[phase] / 255; - rate = voices[voice].env_rate[phase]; - - DISABLE_INTR (flags); - gus_select_voice (voice); - - gus_voice_volume (prev_vol); - - - gus_write8 (0x06, rate); /* Ramping rate */ - - voices[voice].volume_irq_mode = VMODE_ENVELOPE; - - if (((vol - prev_vol) / 64) == 0) /* No significant volume change */ - { - RESTORE_INTR (flags); - step_envelope (voice); /* Continue the envelope on the next step */ - return; - } - - if (vol > prev_vol) - { - if (vol >= (4096 - 64)) - vol = 4096 - 65; - gus_ramp_range (0, vol); - gus_rampon (0x20); /* Increasing volume, with IRQ */ - } - else - { - if (vol <= 64) - vol = 65; - gus_ramp_range (vol, 4030); - gus_rampon (0x60); /* Decreasing volume, with IRQ */ - } - voices[voice].current_volume = vol; - RESTORE_INTR (flags); -} - -static void -init_envelope (int voice) -{ - voices[voice].env_phase = -1; - voices[voice].current_volume = 64; - - step_envelope (voice); -} - -static void -start_release (int voice, long int flags) -{ - if (gus_read8 (0x00) & 0x03) - return; /* Voice already stopped */ - - voices[voice].env_phase = 2; /* Will be incremented by step_envelope */ - - voices[voice].current_volume = - voices[voice].initial_volume = - gus_read16 (0x09) >> 4; /* Get current volume */ - - voices[voice].mode &= ~WAVE_SUSTAIN_ON; - gus_rampoff (); - RESTORE_INTR (flags); - step_envelope (voice); -} - -static void -gus_voice_fade (int voice) -{ - int instr_no = sample_map[voice], is16bits; - long int flags; - - DISABLE_INTR (flags); - gus_select_voice (voice); - - if (instr_no < 0 || instr_no > MAX_SAMPLE) - { - gus_write8 (0x00, 0x03); /* Hard stop */ - voice_alloc->map[voice] = 0; - RESTORE_INTR (flags); - return; - } - - is16bits = (samples[instr_no].mode & WAVE_16_BITS) ? 1 : 0; /* 8 or 16 bits */ - - if (voices[voice].mode & WAVE_ENVELOPES) - { - start_release (voice, flags); - return; - } - - /* - * Ramp the volume down but not too quickly. - */ - if ((int) (gus_read16 (0x09) >> 4) < 100) /* Get current volume */ - { - gus_voice_off (); - gus_rampoff (); - gus_voice_init (voice); - return; - } - - gus_ramp_range (65, 4030); - gus_ramp_rate (2, 4); - gus_rampon (0x40 | 0x20); /* Down, once, with IRQ */ - voices[voice].volume_irq_mode = VMODE_HALT; - RESTORE_INTR (flags); -} - -static void -gus_reset (void) -{ - int i; - - gus_select_max_voices (24); - volume_base = 3071; - volume_scale = 4; - volume_method = VOL_METHOD_ADAGIO; - - for (i = 0; i < 32; i++) - { - gus_voice_init (i); /* Turn voice off */ - gus_voice_init2 (i); - } - - INB (u_Status); /* Touch the status register */ - - gus_look8 (0x41); /* Clear any pending DMA IRQs */ - gus_look8 (0x49); /* Clear any pending sample IRQs */ - - gus_read8 (0x0f); /* Clear pending IRQs */ - -} - -static void -gus_initialize (void) -{ - unsigned long flags; - unsigned char dma_image, irq_image, tmp; - - static unsigned char gus_irq_map[16] = - {0, 0, 0, 3, 0, 2, 0, 4, 0, 1, 0, 5, 6, 0, 0, 7}; - - static unsigned char gus_dma_map[8] = - {0, 1, 0, 2, 0, 3, 4, 5}; - - DISABLE_INTR (flags); - gus_write8 (0x4c, 0); /* Reset GF1 */ - gus_delay (); - gus_delay (); - - gus_write8 (0x4c, 1); /* Release Reset */ - gus_delay (); - gus_delay (); - - /* - * Clear all interrupts - */ - - gus_write8 (0x41, 0); /* DMA control */ - gus_write8 (0x45, 0); /* Timer control */ - gus_write8 (0x49, 0); /* Sample control */ - - gus_select_max_voices (24); - - INB (u_Status); /* Touch the status register */ - - gus_look8 (0x41); /* Clear any pending DMA IRQs */ - gus_look8 (0x49); /* Clear any pending sample IRQs */ - gus_read8 (0x0f); /* Clear pending IRQs */ - - gus_reset (); /* Resets all voices */ - - gus_look8 (0x41); /* Clear any pending DMA IRQs */ - gus_look8 (0x49); /* Clear any pending sample IRQs */ - gus_read8 (0x0f); /* Clear pending IRQs */ - - gus_write8 (0x4c, 7); /* Master reset | DAC enable | IRQ enable */ - - /* - * Set up for Digital ASIC - */ - - OUTB (0x05, gus_base + 0x0f); - - mix_image |= 0x02; /* Disable line out */ - OUTB (mix_image, u_Mixer); - - OUTB (0x00, u_IRQDMAControl); - - OUTB (0x00, gus_base + 0x0f); - - /* - * Now set up the DMA and IRQ interface - * - * The GUS supports two IRQs and two DMAs. - * - * Just one DMA channel is used. This prevents simultaneous ADC and DAC. - * Adding this support requires significant changes to the dmabuf.c, dsp.c - * and audio.c also. - */ - - irq_image = 0; - tmp = gus_irq_map[gus_irq]; - if (!tmp) - printk ("Warning! GUS IRQ not selected\n"); - irq_image |= tmp; - irq_image |= 0x40; /* Combine IRQ1 (GF1) and IRQ2 (Midi) */ - - dma_image = gus_dma_map[gus_dma_read] << 3; - if(!dma_image) - printk ("Warning! GUS DMA read channel not selected.\n"); - if(gus_dma_read == gus_dma) - { - dma_image = 0x40; /* dual dma inhibited - Combine DMA1 (DRAM) and IRQ2 (ADC) */ - } - tmp = gus_dma_map[gus_dma]; - if (!tmp) - printk ("Warning! GUS DMA not selected\n"); - dma_image |= tmp; - - /* - * For some reason the IRQ and DMA addresses must be written twice - */ - - /* - * Doing it first time - */ - - OUTB (mix_image, u_Mixer); /* Select DMA control */ - OUTB (dma_image | 0x80, u_IRQDMAControl); /* Set DMA address */ - - OUTB (mix_image | 0x40, u_Mixer); /* Select IRQ control */ - OUTB (irq_image, u_IRQDMAControl); /* Set IRQ address */ - - /* - * Doing it second time - */ - - OUTB (mix_image, u_Mixer); /* Select DMA control */ - OUTB (dma_image, u_IRQDMAControl); /* Set DMA address */ - - OUTB (mix_image | 0x40, u_Mixer); /* Select IRQ control */ - OUTB (irq_image, u_IRQDMAControl); /* Set IRQ address */ - - gus_select_voice (0); /* This disables writes to IRQ/DMA reg */ - - mix_image &= ~0x02; /* Enable line out */ - mix_image |= 0x08; /* Enable IRQ */ - OUTB (mix_image, u_Mixer); /* - * Turn mixer channels on - * Note! Mic in is left off. - */ - - gus_select_voice (0); /* This disables writes to IRQ/DMA reg */ - - gusintr (INT_HANDLER_CALL (0)); /* Serve pending interrupts */ - RESTORE_INTR (flags); -} - -int -gus_wave_detect (int baseaddr) -{ - unsigned long i; - unsigned long loc; - - gus_base = baseaddr; - - gus_write8 (0x4c, 0); /* Reset GF1 */ - gus_delay (); - gus_delay (); - - gus_write8 (0x4c, 1); /* Release Reset */ - gus_delay (); - gus_delay (); - - /* See if there is first block there.... */ - gus_poke (0L, 0xaa); - if (gus_peek (0L) != 0xaa) - return (0); - - /* Now zero it out so that I can check for mirroring .. */ - gus_poke (0L, 0x00); - for (i = 1L; i < 1024L; i++) - { - int n, failed; - - /* check for mirroring ... */ - if (gus_peek (0L) != 0) - break; - loc = i << 10; - - for (n = loc - 1, failed = 0; n <= loc; n++) - { - gus_poke (loc, 0xaa); - if (gus_peek (loc) != 0xaa) - failed = 1; - - gus_poke (loc, 0x55); - if (gus_peek (loc) != 0x55) - failed = 1; - } - - if (failed) - break; - } - gus_mem_size = i << 10; - return 1; -} - -static int -guswave_ioctl (int dev, - unsigned int cmd, unsigned int arg) -{ - - switch (cmd) - { - case SNDCTL_SYNTH_INFO: - gus_info.nr_voices = nr_voices; - IOCTL_TO_USER ((char *) arg, 0, &gus_info, sizeof (gus_info)); - return 0; - break; - - case SNDCTL_SEQ_RESETSAMPLES: - reset_sample_memory (); - return 0; - break; - - case SNDCTL_SEQ_PERCMODE: - return 0; - break; - - case SNDCTL_SYNTH_MEMAVL: - return gus_mem_size - free_mem_ptr - 32; - - default: - return RET_ERROR (EINVAL); - } -} - -static int -guswave_set_instr (int dev, int voice, int instr_no) -{ - int sample_no; - - if (instr_no < 0 || instr_no > MAX_PATCH) - return RET_ERROR (EINVAL); - - if (voice < 0 || voice > 31) - return RET_ERROR (EINVAL); - - if (voices[voice].volume_irq_mode == VMODE_START_NOTE) - { - voices[voice].sample_pending = instr_no; - return 0; - } - - sample_no = patch_table[instr_no]; - patch_map[voice] = -1; - - if (sample_no < 0) - { - printk ("GUS: Undefined patch %d for voice %d\n", instr_no, voice); - return RET_ERROR (EINVAL); /* Patch not defined */ - } - - if (sample_ptrs[sample_no] == -1) /* Sample not loaded */ - { - printk ("GUS: Sample #%d not loaded for patch %d (voice %d)\n", - sample_no, instr_no, voice); - return RET_ERROR (EINVAL); - } - - sample_map[voice] = sample_no; - patch_map[voice] = instr_no; - return 0; -} - -static int -guswave_kill_note (int dev, int voice, int note, int velocity) -{ - unsigned long flags; - - DISABLE_INTR (flags); - /* voice_alloc->map[voice] = 0xffff; */ - if (voices[voice].volume_irq_mode == VMODE_START_NOTE) - { - voices[voice].kill_pending = 1; - RESTORE_INTR (flags); - } - else - { - RESTORE_INTR (flags); - gus_voice_fade (voice); - } - - RESTORE_INTR (flags); - return 0; -} - -static void -guswave_aftertouch (int dev, int voice, int pressure) -{ -#if 0 - short lo_limit, hi_limit; - unsigned long flags; - - if (voice < 0 || voice > 31) - return; - - if (voices[voice].mode & WAVE_ENVELOPES && voices[voice].env_phase != 2) - return; /* Don't mix with envelopes */ - - if (pressure < 32) - { - DISABLE_INTR (flags); - gus_select_voice (voice); - gus_rampoff (); - compute_and_set_volume (voice, 255, 0); /* Back to original volume */ - RESTORE_INTR (flags); - return; - } - - hi_limit = voices[voice].current_volume; - lo_limit = hi_limit * 99 / 100; - if (lo_limit < 65) - lo_limit = 65; - - DISABLE_INTR (flags); - gus_select_voice (voice); - if (hi_limit > (4095 - 65)) - { - hi_limit = 4095 - 65; - gus_voice_volume (hi_limit); - } - gus_ramp_range (lo_limit, hi_limit); - gus_ramp_rate (3, 8); - gus_rampon (0x58); /* Bidirectional, dow, loop */ - RESTORE_INTR (flags); -#endif /* 0 */ -} - -static void -guswave_panning (int dev, int voice, int value) -{ - if (voice >= 0 || voice < 32) - voices[voice].panning = value; -} - -static void -guswave_volume_method (int dev, int mode) -{ - if (mode == VOL_METHOD_LINEAR || mode == VOL_METHOD_ADAGIO) - volume_method = mode; -} - -static void -compute_volume (int voice, int volume) -{ - if (volume < 128) - voices[voice].midi_volume = volume; - - switch (volume_method) - { - case VOL_METHOD_ADAGIO: - voices[voice].initial_volume = - gus_adagio_vol (voices[voice].midi_volume, voices[voice].main_vol, - voices[voice].expression_vol, - voices[voice].patch_vol); - break; - - case VOL_METHOD_LINEAR: /* Totally ignores patch-volume and expression */ - voices[voice].initial_volume = - gus_linear_vol (volume, voices[voice].main_vol); - break; - - default: - voices[voice].initial_volume = volume_base + - (voices[voice].midi_volume * volume_scale); - } - - if (voices[voice].initial_volume > 4030) - voices[voice].initial_volume = 4030; -} - -static void -compute_and_set_volume (int voice, int volume, int ramp_time) -{ - int current, target, rate; - unsigned long flags; - - compute_volume (voice, volume); - voices[voice].current_volume = voices[voice].initial_volume; - - DISABLE_INTR (flags); - /* - * CAUTION! Interrupts disabled. Enable them before returning - */ - - gus_select_voice (voice); - - current = gus_read16 (0x09) >> 4; - target = voices[voice].initial_volume; - - if (ramp_time == INSTANT_RAMP) - { - gus_rampoff (); - gus_voice_volume (target); - RESTORE_INTR (flags); - return; - } - - if (ramp_time == FAST_RAMP) - rate = 63; - else - rate = 16; - gus_ramp_rate (0, rate); - - if ((target - current) / 64 == 0) /* Close enough to target. */ - { - gus_rampoff (); - gus_voice_volume (target); - RESTORE_INTR (flags); - return; - } - - if (target > current) - { - if (target > (4095 - 65)) - target = 4095 - 65; - gus_ramp_range (current, target); - gus_rampon (0x00); /* Ramp up, once, no IRQ */ - } - else - { - if (target < 65) - target = 65; - - gus_ramp_range (target, current); - gus_rampon (0x40); /* Ramp down, once, no irq */ - } - RESTORE_INTR (flags); -} - -static void -dynamic_volume_change (int voice) -{ - unsigned char status; - unsigned long flags; - - DISABLE_INTR (flags); - gus_select_voice (voice); - status = gus_read8 (0x00); /* Get voice status */ - RESTORE_INTR (flags); - - if (status & 0x03) - return; /* Voice was not running */ - - if (!(voices[voice].mode & WAVE_ENVELOPES)) - { - compute_and_set_volume (voice, voices[voice].midi_volume, 1); - return; - } - - /* - * Voice is running and has envelopes. - */ - - DISABLE_INTR (flags); - gus_select_voice (voice); - status = gus_read8 (0x0d); /* Ramping status */ - RESTORE_INTR (flags); - - if (status & 0x03) /* Sustain phase? */ - { - compute_and_set_volume (voice, voices[voice].midi_volume, 1); - return; - } - - if (voices[voice].env_phase < 0) - return; - - compute_volume (voice, voices[voice].midi_volume); - -} - -static void -guswave_controller (int dev, int voice, int ctrl_num, int value) -{ - unsigned long flags; - unsigned long freq; - - if (voice < 0 || voice > 31) - return; - - switch (ctrl_num) - { - case CTRL_PITCH_BENDER: - voices[voice].bender = value; - - if (voices[voice].volume_irq_mode != VMODE_START_NOTE) - { - freq = compute_finetune (voices[voice].orig_freq, value, - voices[voice].bender_range); - voices[voice].current_freq = freq; - - DISABLE_INTR (flags); - gus_select_voice (voice); - gus_voice_freq (freq); - RESTORE_INTR (flags); - } - break; - - case CTRL_PITCH_BENDER_RANGE: - voices[voice].bender_range = value; - break; - case CTL_EXPRESSION: - value /= 128; - case CTRL_EXPRESSION: - if (volume_method == VOL_METHOD_ADAGIO) - { - voices[voice].expression_vol = value; - if (voices[voice].volume_irq_mode != VMODE_START_NOTE) - dynamic_volume_change (voice); - } - break; - - case CTL_PAN: - voices[voice].panning = (value * 2) - 128; - break; - - case CTL_MAIN_VOLUME: - value = (value * 100) / 16383; - - case CTRL_MAIN_VOLUME: - voices[voice].main_vol = value; - if (voices[voice].volume_irq_mode != VMODE_START_NOTE) - dynamic_volume_change (voice); - break; - - default: - break; - } -} - -static int -guswave_start_note2 (int dev, int voice, int note_num, int volume) -{ - int sample, best_sample, best_delta, delta_freq; - int is16bits, samplep, patch, pan; - unsigned long note_freq, base_note, freq, flags; - unsigned char mode = 0; - - if (voice < 0 || voice > 31) - { - printk ("GUS: Invalid voice\n"); - return RET_ERROR (EINVAL); - } - - if (note_num == 255) - { - if (voices[voice].mode & WAVE_ENVELOPES) - { - voices[voice].midi_volume = volume; - dynamic_volume_change (voice); - return 0; - } - - compute_and_set_volume (voice, volume, 1); - return 0; - } - - if ((patch = patch_map[voice]) == -1) - { - return RET_ERROR (EINVAL); - } - - if ((samplep = patch_table[patch]) == -1) - { - return RET_ERROR (EINVAL); - } - - note_freq = note_to_freq (note_num); - - /* - * Find a sample within a patch so that the note_freq is between low_note - * and high_note. - */ - sample = -1; - - best_sample = samplep; - best_delta = 1000000; - while (samplep >= 0 && sample == -1) - { - delta_freq = note_freq - samples[samplep].base_note; - if (delta_freq < 0) - delta_freq = -delta_freq; - if (delta_freq < best_delta) - { - best_sample = samplep; - best_delta = delta_freq; - } - if (samples[samplep].low_note <= note_freq && - note_freq <= samples[samplep].high_note) - sample = samplep; - else - samplep = samples[samplep].key; /* - * Follow link - */ - } - if (sample == -1) - sample = best_sample; - - if (sample == -1) - { - printk ("GUS: Patch %d not defined for note %d\n", patch, note_num); - return 0; /* Should play default patch ??? */ - } - - is16bits = (samples[sample].mode & WAVE_16_BITS) ? 1 : 0; - voices[voice].mode = samples[sample].mode; - voices[voice].patch_vol = samples[sample].volume; - - if (voices[voice].mode & WAVE_ENVELOPES) - { - int i; - - for (i = 0; i < 6; i++) - { - voices[voice].env_rate[i] = samples[sample].env_rate[i]; - voices[voice].env_offset[i] = samples[sample].env_offset[i]; - } - } - - sample_map[voice] = sample; - - base_note = samples[sample].base_note / 100; /* Try to avoid overflows */ - note_freq /= 100; - - freq = samples[sample].base_freq * note_freq / base_note; - - voices[voice].orig_freq = freq; - - /* - * Since the pitch bender may have been set before playing the note, we - * have to calculate the bending now. - */ - - freq = compute_finetune (voices[voice].orig_freq, voices[voice].bender, - voices[voice].bender_range); - voices[voice].current_freq = freq; - - pan = (samples[sample].panning + voices[voice].panning) / 32; - pan += 7; - if (pan < 0) - pan = 0; - if (pan > 15) - pan = 15; - - if (samples[sample].mode & WAVE_16_BITS) - { - mode |= 0x04; /* 16 bits */ - if ((sample_ptrs[sample] >> 18) != - ((sample_ptrs[sample] + samples[sample].len) >> 18)) - printk ("GUS: Sample address error\n"); - } - - /************************************************************************* - * CAUTION! Interrupts disabled. Don't return before enabling - *************************************************************************/ - - DISABLE_INTR (flags); - gus_select_voice (voice); - gus_voice_off (); - gus_rampoff (); - - RESTORE_INTR (flags); - - if (voices[voice].mode & WAVE_ENVELOPES) - { - compute_volume (voice, volume); - init_envelope (voice); - } - else - compute_and_set_volume (voice, volume, 0); - - DISABLE_INTR (flags); - gus_select_voice (voice); - - if (samples[sample].mode & WAVE_LOOP_BACK) - gus_write_addr (0x0a, sample_ptrs[sample] + samples[sample].len - - voices[voice].offset_pending, is16bits); /* start=end */ - else - gus_write_addr (0x0a, sample_ptrs[sample] + voices[voice].offset_pending, - is16bits); /* Sample start=begin */ - - if (samples[sample].mode & WAVE_LOOPING) - { - mode |= 0x08; - - if (samples[sample].mode & WAVE_BIDIR_LOOP) - mode |= 0x10; - - if (samples[sample].mode & WAVE_LOOP_BACK) - { - gus_write_addr (0x0a, - sample_ptrs[sample] + samples[sample].loop_end - - voices[voice].offset_pending, is16bits); - mode |= 0x40; - } - - gus_write_addr (0x02, sample_ptrs[sample] + samples[sample].loop_start, - is16bits); /* Loop start location */ - gus_write_addr (0x04, sample_ptrs[sample] + samples[sample].loop_end, - is16bits); /* Loop end location */ - } - else - { - mode |= 0x20; /* Loop IRQ at the end */ - voices[voice].loop_irq_mode = LMODE_FINISH; /* Ramp down at the end */ - voices[voice].loop_irq_parm = 1; - gus_write_addr (0x02, sample_ptrs[sample], - is16bits); /* Loop start location */ - gus_write_addr (0x04, sample_ptrs[sample] + samples[sample].len - 1, - is16bits); /* Loop end location */ - } - gus_voice_freq (freq); - gus_voice_balance (pan); - gus_voice_on (mode); - RESTORE_INTR (flags); - - return 0; -} - -/* - * New guswave_start_note by Andrew J. Robinson attempts to minimize clicking - * when the note playing on the voice is changed. It uses volume - * ramping. - */ - -static int -guswave_start_note (int dev, int voice, int note_num, int volume) -{ - long int flags; - int mode; - int ret_val = 0; - - DISABLE_INTR (flags); - if (note_num == 255) - { - if (voices[voice].volume_irq_mode == VMODE_START_NOTE) - voices[voice].volume_pending = volume; - else - { - ret_val = guswave_start_note2 (gus_devnum, voice, note_num, volume); - } - } - else - { - gus_select_voice (voice); - mode = gus_read8 (0x00); - if (mode & 0x20) - gus_write8 (0x00, mode & 0xdf); /* No interrupt! */ - - voices[voice].offset_pending = 0; - voices[voice].kill_pending = 0; - voices[voice].volume_irq_mode = 0; - voices[voice].loop_irq_mode = 0; - - if (voices[voice].sample_pending >= 0) - { - RESTORE_INTR (flags); /* Run temporarily with interrupts enabled */ - guswave_set_instr (voices[voice].dev_pending, voice, - voices[voice].sample_pending); - voices[voice].sample_pending = -1; - DISABLE_INTR (flags); - gus_select_voice (voice); /* Reselect the voice (just to be sure) */ - } - - if ((mode & 0x01) || (int) ((gus_read16 (0x09) >> 4) < 2065)) - { - ret_val = guswave_start_note2 (gus_devnum, voice, note_num, volume); - } - else - { - voices[voice].dev_pending = gus_devnum; - voices[voice].note_pending = note_num; - voices[voice].volume_pending = volume; - voices[voice].volume_irq_mode = VMODE_START_NOTE; - - gus_rampoff (); - gus_ramp_range (2000, 4065); - gus_ramp_rate (0, 63); /* Fastest possible rate */ - gus_rampon (0x20 | 0x40); /* Ramp down, once, irq */ - } - } - RESTORE_INTR (flags); - return ret_val; -} - -static void -guswave_reset (int dev) -{ - int i; - - for (i = 0; i < 32; i++) - { - gus_voice_init (i); - gus_voice_init2 (i); - } -} - -static int -guswave_open (int dev, int mode) -{ - int err; - - if (mode & OPEN_WRITE && gus_busy[gus_devnum] || - mode & OPEN_READ && gus_busy[gus_dspnum]) - return RET_ERROR (EBUSY); - - if(gus_busy[gus_devnum] == 0 && gus_busy[gus_dspnum] == 0) - gus_initialize (); - voice_alloc->timestamp = 0; - - if ((err = DMAbuf_open_dma (gus_devnum)) < 0) - return err; - - RESET_WAIT_QUEUE (dram_sleeper, dram_sleep_flag); - gus_busy[gus_devnum] = 1; - active_device = GUS_DEV_WAVE; - - gus_reset (); - - return 0; -} - -static void -guswave_close (int dev) -{ - gus_busy[gus_devnum] = 0; - active_device = 0; - gus_reset (); - - DMAbuf_close_dma (gus_devnum); -} - -static int -guswave_load_patch (int dev, int format, snd_rw_buf * addr, - int offs, int count, int pmgr_flag) -{ - struct patch_info patch; - int instr; - long sizeof_patch; - - unsigned long blk_size, blk_end, left, src_offs, target; - - sizeof_patch = (long) &patch.data[0] - (long) &patch; /* Header size */ - - if (format != GUS_PATCH) - { - printk ("GUS Error: Invalid patch format (key) 0x%x\n", format); - return RET_ERROR (EINVAL); - } - - if (count < sizeof_patch) - { - printk ("GUS Error: Patch header too short\n"); - return RET_ERROR (EINVAL); - } - - count -= sizeof_patch; - - if (free_sample >= MAX_SAMPLE) - { - printk ("GUS: Sample table full\n"); - return RET_ERROR (ENOSPC); - } - - /* - * Copy the header from user space but ignore the first bytes which have - * been transferred already. - */ - - COPY_FROM_USER (&((char *) &patch)[offs], addr, offs, sizeof_patch - offs); - - instr = patch.instr_no; - - if (instr < 0 || instr > MAX_PATCH) - { - printk ("GUS: Invalid patch number %d\n", instr); - return RET_ERROR (EINVAL); - } - - if (count < patch.len) - { - printk ("GUS Warning: Patch record too short (%d<%d)\n", - count, (int) patch.len); - patch.len = count; - } - - if (patch.len <= 0 || patch.len > gus_mem_size) - { - printk ("GUS: Invalid sample length %d\n", (int) patch.len); - return RET_ERROR (EINVAL); - } - - if (patch.mode & WAVE_LOOPING) - { - if (patch.loop_start < 0 || patch.loop_start >= patch.len) - { - printk ("GUS: Invalid loop start\n"); - return RET_ERROR (EINVAL); - } - - if (patch.loop_end < patch.loop_start || patch.loop_end > patch.len) - { - printk ("GUS: Invalid loop end\n"); - return RET_ERROR (EINVAL); - } - } - - free_mem_ptr = (free_mem_ptr + 31) & ~31; /* 32 byte alignment */ - -#define GUS_BANK_SIZE (256*1024) - - if (patch.mode & WAVE_16_BITS) - { - /* - * 16 bit samples must fit one 256k bank. - */ - if (patch.len >= GUS_BANK_SIZE) - { - printk ("GUS: Sample (16 bit) too long %d\n", (int) patch.len); - return RET_ERROR (ENOSPC); - } - - if ((free_mem_ptr / GUS_BANK_SIZE) != - ((free_mem_ptr + patch.len) / GUS_BANK_SIZE)) - { - unsigned long tmp_mem = /* Aling to 256K */ - ((free_mem_ptr / GUS_BANK_SIZE) + 1) * GUS_BANK_SIZE; - - if ((tmp_mem + patch.len) > gus_mem_size) - return RET_ERROR (ENOSPC); - - free_mem_ptr = tmp_mem; /* This leaves unusable memory */ - } - } - - if ((free_mem_ptr + patch.len) > gus_mem_size) - return RET_ERROR (ENOSPC); - - sample_ptrs[free_sample] = free_mem_ptr; - - /* - * Tremolo is not possible with envelopes - */ - - if (patch.mode & WAVE_ENVELOPES) - patch.mode &= ~WAVE_TREMOLO; - - memcpy ((char *) &samples[free_sample], &patch, sizeof_patch); - - /* - * Link this_one sample to the list of samples for patch 'instr'. - */ - - samples[free_sample].key = patch_table[instr]; - patch_table[instr] = free_sample; - - /* - * Use DMA to transfer the wave data to the DRAM - */ - - left = patch.len; - src_offs = 0; - target = free_mem_ptr; - - while (left) /* Not completely transferred yet */ - { - blk_size = audio_devs[gus_devnum]->buffsize; - if (blk_size > left) - blk_size = left; - - /* - * DMA cannot cross 256k bank boundaries. Check for that. - */ - blk_end = target + blk_size; - - if ((target >> 18) != (blk_end >> 18)) - { /* Split the block */ - - blk_end &= ~(256 * 1024 - 1); - blk_size = blk_end - target; - } - -#if defined(GUS_NO_DMA) || defined(GUS_PATCH_NO_DMA) - /* - * For some reason the DMA is not possible. We have to use PIO. - */ - { - long i; - unsigned char data; - - for (i = 0; i < blk_size; i++) - { - GET_BYTE_FROM_USER (data, addr, sizeof_patch + i); - if (patch.mode & WAVE_UNSIGNED) - - if (!(patch.mode & WAVE_16_BITS) || (i & 0x01)) - data ^= 0x80; /* Convert to signed */ - gus_poke (target + i, data); - } - } -#else /* GUS_NO_DMA */ - { - unsigned long address, hold_address; - unsigned char dma_command; - unsigned long flags; - - /* - * OK, move now. First in and then out. - */ - - COPY_FROM_USER (audio_devs[gus_devnum]->dmap->raw_buf[0], - addr, sizeof_patch + src_offs, - blk_size); - - DISABLE_INTR (flags); -/******** INTERRUPTS DISABLED NOW ********/ - gus_write8 (0x41, 0); /* Disable GF1 DMA */ - DMAbuf_start_dma (gus_devnum, - audio_devs[gus_devnum]->dmap->raw_buf_phys[0], - blk_size, DMA_MODE_WRITE); - - /* - * Set the DRAM address for the wave data - */ - - address = target; - - if (audio_devs[gus_devnum]->dmachan > 3) - { - hold_address = address; - address = address >> 1; - address &= 0x0001ffffL; - address |= (hold_address & 0x000c0000L); - } - - gus_write16 (0x42, (address >> 4) & 0xffff); /* DRAM DMA address */ - - /* - * Start the DMA transfer - */ - - dma_command = 0x21; /* IRQ enable, DMA start */ - if (patch.mode & WAVE_UNSIGNED) - dma_command |= 0x80; /* Invert MSB */ - if (patch.mode & WAVE_16_BITS) - dma_command |= 0x40; /* 16 bit _DATA_ */ - if (audio_devs[gus_devnum]->dmachan > 3) - dma_command |= 0x04; /* 16 bit DMA _channel_ */ - - gus_write8 (0x41, dma_command); /* Lets bo luteet (=bugs) */ - - /* - * Sleep here until the DRAM DMA done interrupt is served - */ - active_device = GUS_DEV_WAVE; - - DO_SLEEP (dram_sleeper, dram_sleep_flag, HZ); - if (TIMED_OUT (dram_sleeper, dram_sleep_flag)) - printk ("GUS: DMA Transfer timed out\n"); - RESTORE_INTR (flags); - } -#endif /* GUS_NO_DMA */ - - /* - * Now the next part - */ - - left -= blk_size; - src_offs += blk_size; - target += blk_size; - - gus_write8 (0x41, 0); /* Stop DMA */ - } - - free_mem_ptr += patch.len; - - if (!pmgr_flag) - pmgr_inform (gus_devnum, PM_E_PATCH_LOADED, instr, free_sample, 0, 0); - free_sample++; - return 0; -} - -static void -guswave_hw_control (int dev, unsigned char *event) -{ - int voice, cmd; - unsigned short p1, p2; - unsigned long plong, flags; - - cmd = event[2]; - voice = event[3]; - p1 = *(unsigned short *) &event[4]; - p2 = *(unsigned short *) &event[6]; - plong = *(unsigned long *) &event[4]; - - if ((voices[voice].volume_irq_mode == VMODE_START_NOTE) && - (cmd != _GUS_VOICESAMPLE) && (cmd != _GUS_VOICE_POS)) - do_volume_irq (voice); - - switch (cmd) - { - - case _GUS_NUMVOICES: - DISABLE_INTR (flags); - gus_select_voice (voice); - gus_select_max_voices (p1); - RESTORE_INTR (flags); - break; - - case _GUS_VOICESAMPLE: - guswave_set_instr (dev, voice, p1); - break; - - case _GUS_VOICEON: - DISABLE_INTR (flags); - gus_select_voice (voice); - p1 &= ~0x20; /* Don't allow interrupts */ - gus_voice_on (p1); - RESTORE_INTR (flags); - break; - - case _GUS_VOICEOFF: - DISABLE_INTR (flags); - gus_select_voice (voice); - gus_voice_off (); - RESTORE_INTR (flags); - break; - - case _GUS_VOICEFADE: - gus_voice_fade (voice); - break; - - case _GUS_VOICEMODE: - DISABLE_INTR (flags); - gus_select_voice (voice); - p1 &= ~0x20; /* Don't allow interrupts */ - gus_voice_mode (p1); - RESTORE_INTR (flags); - break; - - case _GUS_VOICEBALA: - DISABLE_INTR (flags); - gus_select_voice (voice); - gus_voice_balance (p1); - RESTORE_INTR (flags); - break; - - case _GUS_VOICEFREQ: - DISABLE_INTR (flags); - gus_select_voice (voice); - gus_voice_freq (plong); - RESTORE_INTR (flags); - break; - - case _GUS_VOICEVOL: - DISABLE_INTR (flags); - gus_select_voice (voice); - gus_voice_volume (p1); - RESTORE_INTR (flags); - break; - - case _GUS_VOICEVOL2: /* Just update the software voice level */ - voices[voice].initial_volume = - voices[voice].current_volume = p1; - break; - - case _GUS_RAMPRANGE: - if (voices[voice].mode & WAVE_ENVELOPES) - break; /* NO-NO */ - DISABLE_INTR (flags); - gus_select_voice (voice); - gus_ramp_range (p1, p2); - RESTORE_INTR (flags); - break; - - case _GUS_RAMPRATE: - if (voices[voice].mode & WAVE_ENVELOPES) - break; /* NJET-NJET */ - DISABLE_INTR (flags); - gus_select_voice (voice); - gus_ramp_rate (p1, p2); - RESTORE_INTR (flags); - break; - - case _GUS_RAMPMODE: - if (voices[voice].mode & WAVE_ENVELOPES) - break; /* NO-NO */ - DISABLE_INTR (flags); - gus_select_voice (voice); - p1 &= ~0x20; /* Don't allow interrupts */ - gus_ramp_mode (p1); - RESTORE_INTR (flags); - break; - - case _GUS_RAMPON: - if (voices[voice].mode & WAVE_ENVELOPES) - break; /* EI-EI */ - DISABLE_INTR (flags); - gus_select_voice (voice); - p1 &= ~0x20; /* Don't allow interrupts */ - gus_rampon (p1); - RESTORE_INTR (flags); - break; - - case _GUS_RAMPOFF: - if (voices[voice].mode & WAVE_ENVELOPES) - break; /* NEJ-NEJ */ - DISABLE_INTR (flags); - gus_select_voice (voice); - gus_rampoff (); - RESTORE_INTR (flags); - break; - - case _GUS_VOLUME_SCALE: - volume_base = p1; - volume_scale = p2; - break; - - case _GUS_VOICE_POS: - DISABLE_INTR (flags); - gus_select_voice (voice); - gus_set_voice_pos (voice, plong); - RESTORE_INTR (flags); - break; - - default:; - } -} - -static int -gus_sampling_set_speed (int speed) -{ - - if (speed <= 0) - speed = gus_sampling_speed; - - if (speed < 4000) - speed = 4000; - - if (speed > 44100) - speed = 44100; - - gus_sampling_speed = speed; - - if (only_read_access) - { - /* Compute nearest valid recording speed and return it */ - - speed = (9878400 / (gus_sampling_speed + 2)) / 16; - speed = (9878400 / (speed * 16)) - 2; - } - return speed; -} - -static int -gus_sampling_set_channels (int channels) -{ - if (!channels) - return gus_sampling_channels; - if (channels > 2) - channels = 2; - if (channels < 1) - channels = 1; - gus_sampling_channels = channels; - return channels; -} - -static int -gus_sampling_set_bits (int bits) -{ - if (!bits) - return gus_sampling_bits; - - if (bits != 8 && bits != 16) - bits = 8; - - gus_sampling_bits = bits; - return bits; -} - -static int -gus_sampling_ioctl (int dev, unsigned int cmd, unsigned int arg, int local) -{ - switch (cmd) - { - case SOUND_PCM_WRITE_RATE: - if (local) - return gus_sampling_set_speed (arg); - return IOCTL_OUT (arg, gus_sampling_set_speed (IOCTL_IN (arg))); - break; - - case SOUND_PCM_READ_RATE: - if (local) - return gus_sampling_speed; - return IOCTL_OUT (arg, gus_sampling_speed); - break; - - case SNDCTL_DSP_STEREO: - if (local) - return gus_sampling_set_channels (arg + 1) - 1; - return IOCTL_OUT (arg, gus_sampling_set_channels (IOCTL_IN (arg) + 1) - 1); - break; - - case SOUND_PCM_WRITE_CHANNELS: - if (local) - return gus_sampling_set_channels (arg); - return IOCTL_OUT (arg, gus_sampling_set_channels (IOCTL_IN (arg))); - break; - - case SOUND_PCM_READ_CHANNELS: - if (local) - return gus_sampling_channels; - return IOCTL_OUT (arg, gus_sampling_channels); - break; - - case SNDCTL_DSP_SETFMT: - if (local) - return gus_sampling_set_bits (arg); - return IOCTL_OUT (arg, gus_sampling_set_bits (IOCTL_IN (arg))); - break; - - case SOUND_PCM_READ_BITS: - if (local) - return gus_sampling_bits; - return IOCTL_OUT (arg, gus_sampling_bits); - - case SOUND_PCM_WRITE_FILTER: /* NOT POSSIBLE */ - return IOCTL_OUT (arg, RET_ERROR (EINVAL)); - break; - - case SOUND_PCM_READ_FILTER: - return IOCTL_OUT (arg, RET_ERROR (EINVAL)); - break; - - } - return RET_ERROR (EINVAL); -} - -static void -gus_sampling_reset (int dev) -{ -} - -static int -gus_sampling_open (int dev, int mode) -{ - int dev_flag; - int init_flag; -#ifdef GUS_NO_DMA - printk ("GUS: DMA mode not enabled. Device not supported\n"); - return RET_ERROR (ENXIO); -#endif - dev_flag = 0; - init_flag = (gus_busy[gus_devnum] == 0 && gus_busy[gus_dspnum] == 0); - if(mode & OPEN_WRITE) - { - if (gus_busy[gus_devnum]) - return RET_ERROR(EBUSY); - if(dev != gus_devnum) - return RET_ERROR(ENXIO); - dev_flag = gus_busy[gus_devnum] = 1; - } - if(mode & OPEN_READ) - { - if(gus_busy[gus_dspnum]) { - if (dev_flag) gus_busy[gus_devnum] = 0; - return RET_ERROR(EBUSY); - } - - if(dev != gus_dspnum) { - if (dev_flag) gus_busy[gus_devnum] = 0; - return RET_ERROR(ENXIO); - } - } - - if(init_flag) - { - gus_initialize (); - - active_device = 0; - - gus_reset (); - reset_sample_memory (); - gus_select_max_voices (14); - - pcm_active = 0; - dma_active = 0; - pcm_opened = 1; - } - if (mode & OPEN_READ) - { - recording_active = 1; - set_input_volumes (); - } - only_read_access = !(mode & OPEN_WRITE); - - return 0; -} - -static void -gus_sampling_close (int dev) -{ - gus_busy[dev] = 0; - if (gus_busy[gus_devnum] == 0 && gus_busy[gus_dspnum] == 0) { - active_device = 0; - gus_reset(); - pcm_opened = 0; - } - - if (recording_active) - set_input_volumes (); - - recording_active = 0; -} - -static void -gus_sampling_update_volume (void) -{ - unsigned long flags; - int voice; - - if (pcm_active && pcm_opened) - for (voice = 0; voice < gus_sampling_channels; voice++) - { - DISABLE_INTR (flags); - gus_select_voice (voice); - gus_rampoff (); - gus_voice_volume (1530 + (25 * gus_pcm_volume)); - gus_ramp_range (65, 1530 + (25 * gus_pcm_volume)); - RESTORE_INTR (flags); - } -} - -static void -play_next_pcm_block (void) -{ - unsigned long flags; - int speed = gus_sampling_speed; - int this_one, is16bits, chn; - unsigned long dram_loc; - unsigned char mode[2], ramp_mode[2]; - - if (!pcm_qlen) - return; - - this_one = pcm_head; - - for (chn = 0; chn < gus_sampling_channels; chn++) - { - mode[chn] = 0x00; - ramp_mode[chn] = 0x03; /* Ramping and rollover off */ - - if (chn == 0) - { - mode[chn] |= 0x20; /* Loop IRQ */ - voices[chn].loop_irq_mode = LMODE_PCM; - } - - if (gus_sampling_bits != 8) - { - is16bits = 1; - mode[chn] |= 0x04; /* 16 bit data */ - } - else - is16bits = 0; - - dram_loc = this_one * pcm_bsize; - dram_loc += chn * pcm_banksize; - - if (this_one == (pcm_nblk - 1)) /* Last fragment of the DRAM buffer */ - { - mode[chn] |= 0x08; /* Enable loop */ - ramp_mode[chn] = 0x03; /* Disable rollover bit */ - } - else - { - if (chn == 0) - ramp_mode[chn] = 0x04; /* Enable rollover bit */ - } - - DISABLE_INTR (flags); - gus_select_voice (chn); - gus_voice_freq (speed); - - if (gus_sampling_channels == 1) - gus_voice_balance (7); /* mono */ - else if (chn == 0) - gus_voice_balance (0); /* left */ - else - gus_voice_balance (15); /* right */ - - if (!pcm_active) /* Playback not already active */ - { - /* - * The playback was not started yet (or there has been a pause). - * Start the voice (again) and ask for a rollover irq at the end of - * this_one block. If this_one one is last of the buffers, use just - * the normal loop with irq. - */ - - gus_voice_off (); - gus_rampoff (); - gus_voice_volume (1530 + (25 * gus_pcm_volume)); - gus_ramp_range (65, 1530 + (25 * gus_pcm_volume)); - - gus_write_addr (0x0a, dram_loc, is16bits); /* Starting position */ - gus_write_addr (0x02, chn * pcm_banksize, is16bits); /* Loop start */ - - if (chn != 0) - gus_write_addr (0x04, pcm_banksize + (pcm_bsize * pcm_nblk) - 1, - is16bits); /* Loop end location */ - } - - if (chn == 0) - gus_write_addr (0x04, dram_loc + pcm_datasize[this_one] - 1, - is16bits); /* Loop end location */ - else - mode[chn] |= 0x08; /* Enable looping */ - - if (pcm_datasize[this_one] != pcm_bsize) - { - /* - * Incompletely filled block. Possibly the last one. - */ - if (chn == 0) - { - mode[chn] &= ~0x08; /* Disable looping */ - mode[chn] |= 0x20; /* Enable IRQ at the end */ - voices[0].loop_irq_mode = LMODE_PCM_STOP; - ramp_mode[chn] = 0x03; /* No rollover bit */ - } - else - { - gus_write_addr (0x04, dram_loc + pcm_datasize[this_one], - is16bits); /* Loop end location */ - mode[chn] &= ~0x08; /* Disable looping */ - } - } - - RESTORE_INTR (flags); - } - - for (chn = 0; chn < gus_sampling_channels; chn++) - { - DISABLE_INTR (flags); - gus_select_voice (chn); - gus_write8 (0x0d, ramp_mode[chn]); - gus_voice_on (mode[chn]); - RESTORE_INTR (flags); - } - - pcm_active = 1; -} - -static void -gus_transfer_output_block (int dev, unsigned long buf, - int total_count, int intrflag, int chn) -{ - /* - * This routine transfers one block of audio data to the DRAM. In mono mode - * it's called just once. When in stereo mode, this_one routine is called - * once for both channels. - * - * The left/mono channel data is transferred to the beginning of dram and the - * right data to the area pointed by gus_page_size. - */ - - int this_one, count; - unsigned long flags; - unsigned char dma_command; - unsigned long address, hold_address; - - DISABLE_INTR (flags); - - count = total_count / gus_sampling_channels; - - if (chn == 0) - { - if (pcm_qlen >= pcm_nblk) - printk ("GUS Warning: PCM buffers out of sync\n"); - - this_one = pcm_current_block = pcm_tail; - pcm_qlen++; - pcm_tail = (pcm_tail + 1) % pcm_nblk; - pcm_datasize[this_one] = count; - } - else - this_one = pcm_current_block; - - gus_write8 (0x41, 0); /* Disable GF1 DMA */ - DMAbuf_start_dma (gus_devnum, buf + (chn * count), count, DMA_MODE_WRITE); - - address = this_one * pcm_bsize; - address += chn * pcm_banksize; - - if (audio_devs[gus_devnum]->dmachan > 3) - { - hold_address = address; - address = address >> 1; - address &= 0x0001ffffL; - address |= (hold_address & 0x000c0000L); - } - - gus_write16 (0x42, (address >> 4) & 0xffff); /* DRAM DMA address */ - - dma_command = 0x21; /* IRQ enable, DMA start */ - - if (gus_sampling_bits != 8) - dma_command |= 0x40; /* 16 bit _DATA_ */ - else - dma_command |= 0x80; /* Invert MSB */ - - if (audio_devs[gus_devnum]->dmachan > 3) - dma_command |= 0x04; /* 16 bit DMA channel */ - - gus_write8 (0x41, dma_command); /* Kickstart */ - - if (chn == (gus_sampling_channels - 1)) /* Last channel */ - { - /* - * Last (right or mono) channel data - */ - dma_active = 1; /* DMA started. There is a unacknowledged buffer */ - active_device = GUS_DEV_PCM_DONE; - if (!pcm_active && (pcm_qlen > 0 || count < pcm_bsize)) - { - play_next_pcm_block (); - } - } - else - { - /* - * Left channel data. The right channel - * is transferred after DMA interrupt - */ - active_device = GUS_DEV_PCM_CONTINUE; - } - - RESTORE_INTR (flags); -} - -static void -gus_sampling_output_block (int dev, unsigned long buf, int total_count, - int intrflag, int restart_dma) -{ - pcm_current_buf = buf; - pcm_current_count = total_count; - pcm_current_intrflag = intrflag; - pcm_current_dev = gus_devnum; - gus_transfer_output_block (gus_devnum, buf, total_count, intrflag, 0); -} - -static void -gus_sampling_start_input (int dev, unsigned long buf, int count, - int intrflag, int restart_dma) -{ - unsigned long flags; - unsigned char mode; - - DISABLE_INTR (flags); - - DMAbuf_start_dma (gus_dspnum, buf, count, DMA_MODE_READ); - - mode = 0xa0; /* DMA IRQ enabled, invert MSB */ - - if (audio_devs[gus_dspnum]->dmachan > 3) - mode |= 0x04; /* 16 bit DMA channel */ - if (gus_sampling_channels > 1) - mode |= 0x02; /* Stereo */ - mode |= 0x01; /* DMA enable */ - - gus_write8 (0x49, mode); - - RESTORE_INTR (flags); -} - -static int -gus_sampling_prepare_for_input (int dev, int bsize, int bcount) -{ - unsigned int rate; - - rate = (9878400 / (gus_sampling_speed + 2)) / 16; - - gus_write8 (0x48, rate & 0xff); /* Set sampling rate */ - - if (gus_sampling_bits != 8) - { - printk ("GUS Error: 16 bit recording not supported\n"); - return RET_ERROR (EINVAL); - } - - return 0; -} - -static int -gus_sampling_prepare_for_output (int dev, int bsize, int bcount) -{ - int i; - - long mem_ptr, mem_size; - - mem_ptr = 0; - mem_size = gus_mem_size / gus_sampling_channels; - - if (mem_size > (256 * 1024)) - mem_size = 256 * 1024; - - pcm_bsize = bsize / gus_sampling_channels; - pcm_head = pcm_tail = pcm_qlen = 0; - - pcm_nblk = MAX_PCM_BUFFERS; - if ((pcm_bsize * pcm_nblk) > mem_size) - pcm_nblk = mem_size / pcm_bsize; - - for (i = 0; i < pcm_nblk; i++) - pcm_datasize[i] = 0; - - pcm_banksize = pcm_nblk * pcm_bsize; - - if (gus_sampling_bits != 8 && pcm_banksize == (256 * 1024)) - pcm_nblk--; - - return 0; -} - -static int -gus_local_qlen (int dev) -{ - return pcm_qlen; -} - -static void -gus_copy_from_user (int dev, char *localbuf, int localoffs, - snd_rw_buf * userbuf, int useroffs, int len) -{ - if (gus_sampling_channels == 1) - { - COPY_FROM_USER (&localbuf[localoffs], userbuf, useroffs, len); - } - else if (gus_sampling_bits == 8) -#if defined(__FreeBSD__) - { - char *in_left = gus_copy_buf; - char *in_right = in_left + 1; - char *out_left = localbuf + (localoffs / 2); - char *out_right = out_left + pcm_bsize; - int i; - - COPY_FROM_USER (gus_copy_buf, userbuf, useroffs, len); - - len /= 2; - - for (i = 0; i < len; i++) - { - *out_left++ = *in_left++; - in_left++; - *out_right++ = *in_right++; - in_right++; - } - } - else - { - short *in_left = (short *)gus_copy_buf; - short *in_right = in_left + 1; - short *out_left = (short *)localbuf + (localoffs / 4); - short *out_right = out_left + (pcm_bsize / 2); - int i; - - COPY_FROM_USER (gus_copy_buf, userbuf, useroffs, len); - - len /= 4; - - for (i = 0; i < len; i++) - { - *out_left++ = *in_left++; - in_left++; - *out_right++ = *in_right++; - in_right++; - } - } -#else - { - int in_left = useroffs; - int in_right = useroffs + 1; - char *out_left, *out_right; - int i; - - len /= 2; - localoffs /= 2; - out_left = &localbuf[localoffs]; - out_right = out_left + pcm_bsize; - - for (i = 0; i < len; i++) - { - GET_BYTE_FROM_USER (*out_left++, userbuf, in_left); - in_left += 2; - GET_BYTE_FROM_USER (*out_right++, userbuf, in_right); - in_right += 2; - } - } - else - { - int in_left = useroffs / 2; - int in_right = useroffs / 2 + 1; - short *out_left, *out_right; - int i; - - len /= 4; - localoffs /= 2; - - out_left = (short *) &localbuf[localoffs]; - out_right = out_left + (pcm_bsize / 2); - - for (i = 0; i < len; i++) - { -#ifdef __FreeBSD__ - GET_SHORT_FROM_USER (*out_left++, userbuf, in_left); - in_left += 2; - GET_SHORT_FROM_USER (*out_right++, userbuf, in_right); - in_right += 2; -#else - GET_SHORT_FROM_USER (*out_left++, (short *) userbuf, in_left); - in_left += 2; - GET_SHORT_FROM_USER (*out_right++, (short *) userbuf, in_right); - in_right += 2; -#endif - } - } -#endif -} - -static struct audio_operations gus_sampling_operations = -{ - "Gravis UltraSound", - NEEDS_RESTART, - AFMT_U8 | AFMT_S16_LE, - NULL, - gus_sampling_open, - gus_sampling_close, - gus_sampling_output_block, - gus_sampling_start_input, - gus_sampling_ioctl, - gus_sampling_prepare_for_input, - gus_sampling_prepare_for_output, - gus_sampling_reset, - gus_sampling_reset, - gus_local_qlen, - gus_copy_from_user -}; - -static struct audio_operations gus_sampling_operations_read = -{ - "Gravis UltraSound - read only", - NEEDS_RESTART, - AFMT_U8 | AFMT_S16_LE, - NULL, - gus_sampling_open, - gus_sampling_close, - gus_sampling_output_block, - gus_sampling_start_input, - gus_sampling_ioctl, - gus_sampling_prepare_for_input, - gus_sampling_prepare_for_output, - gus_sampling_reset, - gus_sampling_reset, - gus_local_qlen, - gus_copy_from_user -}; - -static void -guswave_setup_voice (int dev, int voice, int chn) -{ - struct channel_info *info = - &synth_devs[gus_devnum]->chn_info[chn]; - - guswave_set_instr (gus_devnum, voice, info->pgm_num); - - voices[voice].expression_vol = - info->controllers[CTL_EXPRESSION]; /* Just msb */ - voices[voice].main_vol = - (info->controllers[CTL_MAIN_VOLUME] * 100) / 128; - voices[voice].panning = - (info->controllers[CTL_PAN] * 2) - 128; - voices[voice].bender = info->bender_value; -} - -static void -guswave_bender (int dev, int voice, int value) -{ - int freq; - unsigned long flags; - - voices[voice].bender = value - 8192; - freq = compute_finetune (voices[voice].orig_freq, value, - voices[voice].bender_range); - voices[voice].current_freq = freq; - - DISABLE_INTR (flags); - gus_select_voice (voice); - gus_voice_freq (freq); - RESTORE_INTR (flags); -} - -static int -guswave_patchmgr (int dev, struct patmgr_info *rec) -{ - int i, n; - - switch (rec->command) - { - case PM_GET_DEVTYPE: - rec->parm1 = PMTYPE_WAVE; - return 0; - break; - - case PM_GET_NRPGM: - rec->parm1 = MAX_PATCH; - return 0; - break; - - case PM_GET_PGMMAP: - rec->parm1 = MAX_PATCH; - - for (i = 0; i < MAX_PATCH; i++) - { - int ptr = patch_table[i]; - - rec->data.data8[i] = 0; - - while (ptr >= 0 && ptr < free_sample) - { - rec->data.data8[i]++; - ptr = samples[ptr].key; /* Follow link */ - } - } - return 0; - break; - - case PM_GET_PGM_PATCHES: - { - int ptr = patch_table[rec->parm1]; - - n = 0; - - while (ptr >= 0 && ptr < free_sample) - { - rec->data.data32[n++] = ptr; - ptr = samples[ptr].key; /* Follow link */ - } - } - rec->parm1 = n; - return 0; - break; - - case PM_GET_PATCH: - { - int ptr = rec->parm1; - struct patch_info *pat; - - if (ptr < 0 || ptr >= free_sample) - return RET_ERROR (EINVAL); - - memcpy (rec->data.data8, (char *) &samples[ptr], - sizeof (struct patch_info)); - - pat = (struct patch_info *) rec->data.data8; - - pat->key = GUS_PATCH; /* Restore patch type */ - rec->parm1 = sample_ptrs[ptr]; /* DRAM location */ - rec->parm2 = sizeof (struct patch_info); - } - return 0; - break; - - case PM_SET_PATCH: - { - int ptr = rec->parm1; - struct patch_info *pat; - - if (ptr < 0 || ptr >= free_sample) - return RET_ERROR (EINVAL); - - pat = (struct patch_info *) rec->data.data8; - - if (pat->len > samples[ptr].len) /* Cannot expand sample */ - return RET_ERROR (EINVAL); - - pat->key = samples[ptr].key; /* Ensure the link is correct */ - - memcpy ((char *) &samples[ptr], rec->data.data8, - sizeof (struct patch_info)); - - pat->key = GUS_PATCH; - } - return 0; - break; - - case PM_READ_PATCH: /* Returns a block of wave data from the DRAM */ - { - int sample = rec->parm1; - int n; - long offs = rec->parm2; - int l = rec->parm3; - - if (sample < 0 || sample >= free_sample) - return RET_ERROR (EINVAL); - - if (offs < 0 || offs >= samples[sample].len) - return RET_ERROR (EINVAL); /* Invalid offset */ - - n = samples[sample].len - offs; /* Num of bytes left */ - - if (l > n) - l = n; - - if (l > sizeof (rec->data.data8)) - l = sizeof (rec->data.data8); - - if (l <= 0) - return RET_ERROR (EINVAL); /* - * Was there a bug? - */ - - offs += sample_ptrs[sample]; /* - * Begin offsess + offset to DRAM - */ - - for (n = 0; n < l; n++) - rec->data.data8[n] = gus_peek (offs++); - rec->parm1 = n; /* - * Nr of bytes copied - */ - } - return 0; - break; - - case PM_WRITE_PATCH: /* - * Writes a block of wave data to the DRAM - */ - { - int sample = rec->parm1; - int n; - long offs = rec->parm2; - int l = rec->parm3; - - if (sample < 0 || sample >= free_sample) - return RET_ERROR (EINVAL); - - if (offs < 0 || offs >= samples[sample].len) - return RET_ERROR (EINVAL); /* - * Invalid offset - */ - - n = samples[sample].len - offs; /* - * Nr of bytes left - */ - - if (l > n) - l = n; - - if (l > sizeof (rec->data.data8)) - l = sizeof (rec->data.data8); - - if (l <= 0) - return RET_ERROR (EINVAL); /* - * Was there a bug? - */ - - offs += sample_ptrs[sample]; /* - * Begin offsess + offset to DRAM - */ - - for (n = 0; n < l; n++) - gus_poke (offs++, rec->data.data8[n]); - rec->parm1 = n; /* - * Nr of bytes copied - */ - } - return 0; - break; - - default: - return RET_ERROR (EINVAL); - } -} - -static int -guswave_alloc (int dev, int chn, int note, struct voice_alloc_info *alloc) -{ - int i, p, best = -1, best_time = 0x7fffffff; - - p = alloc->ptr; - /* - * First look for a completely stopped voice - */ - - for (i = 0; i < alloc->max_voice; i++) - { - if (alloc->map[p] == 0) - { - alloc->ptr = p; - return p; - } - if (alloc->alloc_times[p] < best_time) - { - best = p; - best_time = alloc->alloc_times[p]; - } - p = (p + 1) % alloc->max_voice; - } - - /* - * Then look for a releasing voice - */ - - for (i = 0; i < alloc->max_voice; i++) - { - if (alloc->map[p] == 0xffff) - { - alloc->ptr = p; - return p; - } - p = (p + 1) % alloc->max_voice; - } - - if (best >= 0) - p = best; - - alloc->ptr = p; - return p; -} - -static struct synth_operations guswave_operations = -{ - &gus_info, - 0, - SYNTH_TYPE_SAMPLE, - SAMPLE_TYPE_GUS, - guswave_open, - guswave_close, - guswave_ioctl, - guswave_kill_note, - guswave_start_note, - guswave_set_instr, - guswave_reset, - guswave_hw_control, - guswave_load_patch, - guswave_aftertouch, - guswave_controller, - guswave_panning, - guswave_volume_method, - guswave_patchmgr, - guswave_bender, - guswave_alloc, - guswave_setup_voice -}; - -static void -set_input_volumes (void) -{ - unsigned long flags; - unsigned char mask = 0xff & ~0x06; /* Just line out enabled */ - - DISABLE_INTR (flags); - - /* - * Enable channels having vol > 10% - * Note! bit 0x01 means line in DISABLED while 0x04 means - * mic in ENABLED. - */ - if (gus_line_vol > 10) - mask &= ~0x01; - if (gus_mic_vol > 10) - mask |= 0x04; - - if (recording_active) - { - /* - * Disable channel, if not selected for recording - */ - if (!(gus_recmask & SOUND_MASK_LINE)) - mask |= 0x01; - if (!(gus_recmask & SOUND_MASK_MIC)) - mask &= ~0x04; - } - - mix_image &= ~0x07; - mix_image |= mask & 0x07; - OUTB (mix_image, u_Mixer); - - RESTORE_INTR (flags); -} - -int -gus_default_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg) -{ -#define MIX_DEVS (SOUND_MASK_MIC|SOUND_MASK_LINE| \ - SOUND_MASK_SYNTH|SOUND_MASK_PCM) - if (((cmd >> 8) & 0xff) == 'M') - { - if (cmd & IOC_IN) - switch (cmd & 0xff) - { - case SOUND_MIXER_RECSRC: - gus_recmask = IOCTL_IN (arg) & MIX_DEVS; - if (!(gus_recmask & (SOUND_MASK_MIC | SOUND_MASK_LINE))) - gus_recmask = SOUND_MASK_MIC; - /* Note! Input volumes are updated during next open for recording */ - return IOCTL_OUT (arg, gus_recmask); - break; - - case SOUND_MIXER_MIC: - { - int vol = IOCTL_IN (arg) & 0xff; - - if (vol < 0) - vol = 0; - if (vol > 100) - vol = 100; - gus_mic_vol = vol; - set_input_volumes (); - return IOCTL_OUT (arg, vol | (vol << 8)); - } - break; - - case SOUND_MIXER_LINE: - { - int vol = IOCTL_IN (arg) & 0xff; - - if (vol < 0) - vol = 0; - if (vol > 100) - vol = 100; - gus_line_vol = vol; - set_input_volumes (); - return IOCTL_OUT (arg, vol | (vol << 8)); - } - break; - - case SOUND_MIXER_PCM: - gus_pcm_volume = IOCTL_IN (arg) & 0xff; - if (gus_pcm_volume < 0) - gus_pcm_volume = 0; - if (gus_pcm_volume > 100) - gus_pcm_volume = 100; - gus_sampling_update_volume (); - return IOCTL_OUT (arg, gus_pcm_volume | (gus_pcm_volume << 8)); - break; - - case SOUND_MIXER_SYNTH: - { - int voice; - - gus_wave_volume = IOCTL_IN (arg) & 0xff; - - if (gus_wave_volume < 0) - gus_wave_volume = 0; - if (gus_wave_volume > 100) - gus_wave_volume = 100; - - if (active_device == GUS_DEV_WAVE) - for (voice = 0; voice < nr_voices; voice++) - dynamic_volume_change (voice); /* Apply the new vol */ - - return IOCTL_OUT (arg, gus_wave_volume | (gus_wave_volume << 8)); - } - break; - - default: - return RET_ERROR (EINVAL); - } - else - switch (cmd & 0xff) /* - * Return parameters - */ - { - - case SOUND_MIXER_RECSRC: - return IOCTL_OUT (arg, gus_recmask); - break; - - case SOUND_MIXER_DEVMASK: - return IOCTL_OUT (arg, MIX_DEVS); - break; - - case SOUND_MIXER_STEREODEVS: - return IOCTL_OUT (arg, 0); - break; - - case SOUND_MIXER_RECMASK: - return IOCTL_OUT (arg, SOUND_MASK_MIC | SOUND_MASK_LINE); - break; - - case SOUND_MIXER_CAPS: - return IOCTL_OUT (arg, 0); - break; - - case SOUND_MIXER_MIC: - return IOCTL_OUT (arg, gus_mic_vol | (gus_mic_vol << 8)); - break; - - case SOUND_MIXER_LINE: - return IOCTL_OUT (arg, gus_line_vol | (gus_line_vol << 8)); - break; - - case SOUND_MIXER_PCM: - return IOCTL_OUT (arg, gus_pcm_volume | (gus_pcm_volume << 8)); - break; - - case SOUND_MIXER_SYNTH: - return IOCTL_OUT (arg, gus_wave_volume | (gus_wave_volume << 8)); - break; - - default: - return RET_ERROR (EINVAL); - } - } - else - return RET_ERROR (EINVAL); -} - -static struct mixer_operations gus_mixer_operations = -{ - "Gravis Ultrasound", - gus_default_mixer_ioctl -}; - -static long -gus_default_mixer_init (long mem_start) -{ - if (num_mixers < MAX_MIXER_DEV) /* - * Don't install if there is another - * mixer - */ - mixer_devs[num_mixers++] = &gus_mixer_operations; - - return mem_start; -} - -long -gus_wave_init (long mem_start, int irq, int dma, int dma_read) -{ - unsigned long flags; - unsigned char val; - char *model_num = "2.4"; - int gus_type = 0x24; /* 2.4 */ - int mixer_type = 0; - - if (irq < 0 || irq > 15) - { - printk ("ERROR! Invalid IRQ#%d. GUS Disabled", irq); - return mem_start; - } - - if (dma < 0 || dma > 7) - { - printk ("ERROR! Invalid DMA#%d. GUS Disabled", dma); - return mem_start; - } - - if (dma_read == 0) dma_read = dma; - if (dma_read < 0 || dma_read > 7) - { - printk ("ERROR! Invalid DMA#%d. GUS DMA-read disabled", dma_read); - dma_read = dma; - } - /* - * Try to identify the GUS model. - * - * Versions < 3.6 don't have the digital ASIC. Try to probe it first. - */ - - DISABLE_INTR (flags); - OUTB (0x20, gus_base + 0x0f); - val = INB (gus_base + 0x0f); - RESTORE_INTR (flags); - - if (val != 0xff && (val & 0x06)) /* Should be 0x02?? */ - { - /* - * It has the digital ASIC so the card is at least v3.4. - * Next try to detect the true model. - */ - - val = INB (u_MixSelect); - - /* - * Value 255 means pre-3.7 which don't have mixer. - * Values 5 thru 9 mean v3.7 which has a ICS2101 mixer. - * 10 and above is GUS MAX which has the CS4231 codec/mixer. - * - * Sorry. No GUS max support yet but it should be available - * soon after the SDK for GUS MAX is available. - */ - - if (val == 255 || val < 5) - { - model_num = "3.4"; - gus_type = 0x34; - } - else if (val < 10) - { - model_num = "3.7"; - gus_type = 0x37; - mixer_type = ICS2101; - } - else - { - model_num = "MAX"; - gus_type = 0x40; - mixer_type = CS4231; - } - } - else - { - /* - * ASIC not detected so the card must be 2.2 or 2.4. - * There could still be the 16-bit/mixer daughter card. - * It has the same codec/mixer than MAX. - * At this time there is no support for it but it will appear soon. - */ - } - - -#if defined(__FreeBSD__) - printk ("gus0: <Gravis UltraSound %s (%dk)>", model_num, - (int) gus_mem_size / 1024); -#else - printk (" <Gravis UltraSound %s (%dk)>", model_num, (int) gus_mem_size / 1024); -#endif - - sprintf (gus_info.name, "Gravis UltraSound %s (%dk)", model_num, (int) gus_mem_size / 1024); - - gus_irq = irq; - gus_dma = dma; - gus_dma_read = dma_read; - - if (num_synths >= MAX_SYNTH_DEV) - printk ("GUS Error: Too many synthesizers\n"); - else - { - voice_alloc = &guswave_operations.alloc; - synth_devs[num_synths++] = &guswave_operations; - } - -#if defined(__FreeBSD__) - PERMANENT_MALLOC (char *, gus_copy_buf, DSP_BUFFSIZE, mem_start); -#endif - - PERMANENT_MALLOC (struct patch_info *, samples, - (MAX_SAMPLE + 1) * sizeof (*samples), mem_start); - - reset_sample_memory (); - - gus_initialize (); - - if (num_audiodevs < MAX_AUDIO_DEV) - { - audio_devs[gus_devnum = num_audiodevs++] = &gus_sampling_operations; - audio_devs[gus_devnum]->dmachan = dma; - audio_devs[gus_devnum]->buffcount = 1; - audio_devs[gus_devnum]->buffsize = DSP_BUFFSIZE; - gus_dspnum = gus_devnum; - gus_busy[gus_devnum] = 0; - gus_busy[gus_dspnum] = 0; - } - else - printk ("GUS: Too many PCM devices available\n"); - - if (num_audiodevs < MAX_AUDIO_DEV) - { - if(dma_read && dma != dma_read) - { - audio_devs[gus_dspnum = num_audiodevs++]= &gus_sampling_operations_read; - audio_devs[gus_dspnum]->dmachan = gus_dma_read; - audio_devs[gus_dspnum]->buffcount = 1; - audio_devs[gus_dspnum]->buffsize = DSP_BUFFSIZE; - gus_busy[gus_dspnum] = 0; - } - else - { - gus_dspnum = gus_devnum; - } - } - else - printk ("GUS READ: Too many PCM devices available\n"); - - /* - * Mixer dependent initialization. - */ - switch (mixer_type) - { - case ICS2101: - gus_mic_vol = gus_line_vol = gus_pcm_volume = 100; - gus_wave_volume = 90; - return ics2101_mixer_init (mem_start); - - case CS4231: - /* Initialized elsewhere (ad1848.c) */ -#ifndef EXCLUDE_GUSMAX - { - unsigned char max_config = 0x40; /* Codec enable */ - long mixer_init_return; - - if (dma > 3) - max_config |= 0x30; /* 16 bit playback and capture DMAs */ - - max_config |= (gus_base >> 4) & 0x0f; /* Extract the X from 2X0 */ - - OUTB (max_config, gus_base + 0x106); /* UltraMax control */ - mixer_init_return = gus_default_mixer_init(mem_start); - - if (ad1848_detect (gus_base + 0x10c)) - { - gus_mic_vol = gus_line_vol = gus_pcm_volume = 100; - gus_wave_volume = 90; - have_gus_max = 1; - ad1848_init ("GUS MAX", gus_base + 0x10c, - -irq, - dma_read, /* read write reversed */ - dma); - } - else - printk ("[Where's the CS4231?]"); - return mixer_init_return; - } -#endif - default: - return gus_default_mixer_init (mem_start); - } -} - -static void -do_loop_irq (int voice) -{ - unsigned char tmp; - int mode, parm; - unsigned long flags; - - DISABLE_INTR (flags); - gus_select_voice (voice); - - tmp = gus_read8 (0x00); - tmp &= ~0x20; /* - * Disable wave IRQ for this_one voice - */ - gus_write8 (0x00, tmp); - - if (tmp & 0x03) /* Voice stopped */ - voice_alloc->map[voice] = 0; - - mode = voices[voice].loop_irq_mode; - voices[voice].loop_irq_mode = 0; - parm = voices[voice].loop_irq_parm; - - switch (mode) - { - - case LMODE_FINISH: /* - * Final loop finished, shoot volume down - */ - - if ((int) (gus_read16 (0x09) >> 4) < 100) /* - * Get current volume - */ - { - gus_voice_off (); - gus_rampoff (); - gus_voice_init (voice); - break; - } - gus_ramp_range (65, 4065); - gus_ramp_rate (0, 63); /* - * Fastest possible rate - */ - gus_rampon (0x20 | 0x40); /* - * Ramp down, once, irq - */ - voices[voice].volume_irq_mode = VMODE_HALT; - break; - - case LMODE_PCM_STOP: - pcm_active = 0; /* Signal to the play_next_pcm_block routine */ - case LMODE_PCM: - { - int flag; /* 0 or 2 */ - - pcm_qlen--; - pcm_head = (pcm_head + 1) % pcm_nblk; - if (pcm_qlen && pcm_active) - { - play_next_pcm_block (); - } - else - { /* Underrun. Just stop the voice */ - gus_select_voice (0); /* Left channel */ - gus_voice_off (); - gus_rampoff (); - gus_select_voice (1); /* Right channel */ - gus_voice_off (); - gus_rampoff (); - pcm_active = 0; - } - - /* - * If the queue was full before this interrupt, the DMA transfer was - * suspended. Let it continue now. - */ - if (dma_active) - { - if (pcm_qlen == 0) - flag = 1; /* Underflow */ - else - flag = 0; - dma_active = 0; - } - else - flag = 2; /* Just notify the dmabuf.c */ - DMAbuf_outputintr (gus_devnum, flag); - } - break; - - default:; - } - RESTORE_INTR (flags); -} - -static void -do_volume_irq (int voice) -{ - unsigned char tmp; - int mode, parm; - unsigned long flags; - - DISABLE_INTR (flags); - - gus_select_voice (voice); - - tmp = gus_read8 (0x0d); - tmp &= ~0x20; /* - * Disable volume ramp IRQ - */ - gus_write8 (0x0d, tmp); - - mode = voices[voice].volume_irq_mode; - voices[voice].volume_irq_mode = 0; - parm = voices[voice].volume_irq_parm; - - switch (mode) - { - case VMODE_HALT: /* - * Decay phase finished - */ - RESTORE_INTR (flags); - gus_voice_init (voice); - break; - - case VMODE_ENVELOPE: - gus_rampoff (); - RESTORE_INTR (flags); - step_envelope (voice); - break; - - case VMODE_START_NOTE: - RESTORE_INTR (flags); - guswave_start_note2 (voices[voice].dev_pending, voice, - voices[voice].note_pending, voices[voice].volume_pending); - if (voices[voice].kill_pending) - guswave_kill_note (voices[voice].dev_pending, voice, - voices[voice].note_pending, 0); - - if (voices[voice].sample_pending >= 0) - { - guswave_set_instr (voices[voice].dev_pending, voice, - voices[voice].sample_pending); - voices[voice].sample_pending = -1; - } - break; - - default:; - } -} - -void -gus_voice_irq (void) -{ - unsigned long wave_ignore = 0, volume_ignore = 0; - unsigned long voice_bit; - - unsigned char src, voice; - - while (1) - { - src = gus_read8 (0x0f); /* - * Get source info - */ - voice = src & 0x1f; - src &= 0xc0; - - if (src == (0x80 | 0x40)) - return; /* - * No interrupt - */ - - voice_bit = 1 << voice; - - if (!(src & 0x80)) /* - * Wave IRQ pending - */ - if (!(wave_ignore & voice_bit) && (int) voice < nr_voices) /* - * Not done - * yet - */ - { - wave_ignore |= voice_bit; - do_loop_irq (voice); - } - - if (!(src & 0x40)) /* - * Volume IRQ pending - */ - if (!(volume_ignore & voice_bit) && (int) voice < nr_voices) /* - * Not done - * yet - */ - { - volume_ignore |= voice_bit; - do_volume_irq (voice); - } - } -} - -void -guswave_dma_irq (void) -{ - unsigned char status; - - status = gus_look8 (0x41); /* Get DMA IRQ Status */ - if (status & 0x40) /* DMA interrupt pending */ - switch (active_device) - { - case GUS_DEV_WAVE: - if (SOMEONE_WAITING (dram_sleeper, dram_sleep_flag)) - WAKE_UP (dram_sleeper, dram_sleep_flag); - break; - - case GUS_DEV_PCM_CONTINUE: /* Left channel data transferred */ - gus_transfer_output_block (pcm_current_dev, pcm_current_buf, - pcm_current_count, - pcm_current_intrflag, 1); - break; - - case GUS_DEV_PCM_DONE: /* Right or mono channel data transferred */ - if (pcm_qlen < pcm_nblk) - { - int flag = (1 - dma_active) * 2; /* 0 or 2 */ - - if (pcm_qlen == 0) - flag = 1; /* Underrun */ - dma_active = 0; - DMAbuf_outputintr (gus_devnum, flag); - } - break; - - default:; - } - - status = gus_look8 (0x49); /* - * Get Sampling IRQ Status - */ - if (status & 0x40) /* - * Sampling Irq pending - */ - { - if (gus_dma_read && gus_dma_read != gus_dma) - DMAbuf_inputintr (gus_dspnum); - else - DMAbuf_inputintr (gus_devnum); - } - -} - -#endif diff --git a/sys/pc98/pc98/sound/ics2101.c b/sys/pc98/pc98/sound/ics2101.c deleted file mode 100644 index cec1e51..0000000 --- a/sys/pc98/pc98/sound/ics2101.c +++ /dev/null @@ -1,264 +0,0 @@ -/* - * sound/ics2101.c - * - * Driver for the ICS2101 mixer of GUS v3.7. - * - * Copyright by Hannu Savolainen 1994 - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. 2. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#include <i386/isa/sound/sound_config.h> -#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_GUS) - -#include <machine/ultrasound.h> -#include <i386/isa/sound/gus_hw.h> - -#define MIX_DEVS (SOUND_MASK_MIC|SOUND_MASK_LINE| \ - SOUND_MASK_SYNTH| \ - SOUND_MASK_CD | SOUND_MASK_VOLUME) - -extern int gus_base; -static int volumes[ICS_MIXDEVS]; -static int left_fix[ICS_MIXDEVS] = -{1, 1, 1, 2, 1, 2}; -static int right_fix[ICS_MIXDEVS] = -{2, 2, 2, 1, 2, 1}; - -static int -scale_vol (int vol) -{ -#if 1 - /* - * Experimental volume scaling by Risto Kankkunen. - * This should give smoother volume response than just - * a plain multiplication. - */ - int e; - - if (vol < 0) - vol = 0; - if (vol > 100) - vol = 100; - vol = (31 * vol + 50) / 100; - e = 0; - if (vol) - { - while (vol < 16) - { - vol <<= 1; - e--; - } - vol -= 16; - e += 7; - } - return ((e << 4) + vol); -#else - return ((vol * 127) + 50) / 100; -#endif -} - -static void -write_mix (int dev, int chn, int vol) -{ - int *selector; - unsigned long flags; - int ctrl_addr = dev << 3; - int attn_addr = dev << 3; - - vol = scale_vol (vol); - - if (chn == CHN_LEFT) - { - selector = left_fix; - ctrl_addr |= 0x00; - attn_addr |= 0x02; - } - else - { - selector = right_fix; - ctrl_addr |= 0x01; - attn_addr |= 0x03; - } - - DISABLE_INTR (flags); - OUTB (ctrl_addr, u_MixSelect); - OUTB (selector[dev], u_MixData); - OUTB (attn_addr, u_MixSelect); - OUTB ((unsigned char) vol, u_MixData); - RESTORE_INTR (flags); -} - -static int -set_volumes (int dev, int vol) -{ - int left = vol & 0x00ff; - int right = (vol >> 8) & 0x00ff; - - if (left < 0) - left = 0; - if (left > 100) - left = 100; - if (right < 0) - right = 0; - if (right > 100) - right = 100; - - write_mix (dev, CHN_LEFT, left); - write_mix (dev, CHN_RIGHT, right); - - vol = left + (right << 8); - volumes[dev] = vol; - return vol; -} - -static int -ics2101_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg) -{ - if (((cmd >> 8) & 0xff) == 'M') - { - if (cmd & IOC_IN) - switch (cmd & 0xff) - { - case SOUND_MIXER_RECSRC: - return gus_default_mixer_ioctl (dev, cmd, arg); - break; - - case SOUND_MIXER_MIC: - return IOCTL_OUT (arg, set_volumes (DEV_MIC, IOCTL_IN (arg))); - break; - - case SOUND_MIXER_CD: - return IOCTL_OUT (arg, set_volumes (DEV_CD, IOCTL_IN (arg))); - break; - - case SOUND_MIXER_LINE: - return IOCTL_OUT (arg, set_volumes (DEV_LINE, IOCTL_IN (arg))); - break; - - case SOUND_MIXER_SYNTH: - return IOCTL_OUT (arg, set_volumes (DEV_GF1, IOCTL_IN (arg))); - break; - - case SOUND_MIXER_VOLUME: - return IOCTL_OUT (arg, set_volumes (DEV_VOL, IOCTL_IN (arg))); - break; - - default: - return RET_ERROR (EINVAL); - } - else - switch (cmd & 0xff) /* - * Return parameters - */ - { - - case SOUND_MIXER_RECSRC: - return gus_default_mixer_ioctl (dev, cmd, arg); - break; - - case SOUND_MIXER_DEVMASK: - return IOCTL_OUT (arg, MIX_DEVS); - break; - - case SOUND_MIXER_STEREODEVS: - return IOCTL_OUT (arg, SOUND_MASK_LINE | SOUND_MASK_CD | - SOUND_MASK_SYNTH | SOUND_MASK_VOLUME | - SOUND_MASK_MIC); - break; - - case SOUND_MIXER_RECMASK: - return IOCTL_OUT (arg, SOUND_MASK_MIC | SOUND_MASK_LINE); - break; - - case SOUND_MIXER_CAPS: - return IOCTL_OUT (arg, 0); - break; - - case SOUND_MIXER_MIC: - return IOCTL_OUT (arg, volumes[DEV_MIC]); - break; - - case SOUND_MIXER_LINE: - return IOCTL_OUT (arg, volumes[DEV_LINE]); - break; - - case SOUND_MIXER_CD: - return IOCTL_OUT (arg, volumes[DEV_CD]); - break; - - case SOUND_MIXER_VOLUME: - return IOCTL_OUT (arg, volumes[DEV_VOL]); - break; - - case SOUND_MIXER_SYNTH: - return IOCTL_OUT (arg, volumes[DEV_GF1]); - break; - - default: - return RET_ERROR (EINVAL); - } - } - - return RET_ERROR (EINVAL); -} - -static struct mixer_operations ics2101_mixer_operations = -{ - "ICS2101 Multimedia Mixer", - ics2101_mixer_ioctl -}; - -long -ics2101_mixer_init (long mem_start) -{ - int i; - - if (num_mixers < MAX_MIXER_DEV) - { - mixer_devs[num_mixers++] = &ics2101_mixer_operations; - - /* - * Some GUS v3.7 cards had some channels flipped. Disable - * the flipping feature if the model id is other than 5. - */ - - if (INB (u_MixSelect) != 5) - { - for (i = 0; i < ICS_MIXDEVS; i++) - left_fix[i] = 1; - for (i = 0; i < ICS_MIXDEVS; i++) - right_fix[i] = 2; - } - - set_volumes (DEV_GF1, 0x5a5a); - set_volumes (DEV_CD, 0x5a5a); - set_volumes (DEV_MIC, 0x0000); - set_volumes (DEV_LINE, 0x5a5a); - set_volumes (DEV_VOL, 0x5a5a); - set_volumes (DEV_UNUSED, 0x0000); - } - - return mem_start; -} - -#endif diff --git a/sys/pc98/pc98/sound/local.h b/sys/pc98/pc98/sound/local.h deleted file mode 100644 index c243e4b..0000000 --- a/sys/pc98/pc98/sound/local.h +++ /dev/null @@ -1,128 +0,0 @@ -/* for FreeBSD */ -/* - * $Id: local.h,v 1.11 1994/11/01 17:26:50 ache Exp - */ - -#define DSP_BUFFSIZE 65536 -#define SELECTED_SOUND_OPTIONS 0xffffffff -#define SOUND_CONFIG_DATE "Sun Feb 5 14:38:12 EST 1995" -#define SOUND_CONFIG_BY "freebsd-hackers" -#define SOUND_CONFIG_HOST "freefall" -#define SOUND_CONFIG_DOMAIN "cdrom.com" - -/* determine if sound code should be compiled */ -#include "snd.h" -#if NSND > 0 -#define KERNEL_SOUNDCARD -#endif - -#define ALLOW_SELECT - -/* PSS code does not work */ -#ifndef EXCLUDE_PSS -#define EXCLUDE_PSS -#endif - -#include "gus.h" -#if NGUS == 0 && !defined(EXCLUDE_GUS) -#define EXCLUDE_GUS -#endif - -#include "gusxvi.h" -#if NGUSXVI == 0 && !defined(EXCLUDE_GUS16) -#define EXCLUDE_GUS16 -#endif - -#include "mss.h" -#if NMSS == 0 && !defined(EXCLUDE_MSS) -#define EXCLUDE_MSS -#endif - -#include "trix.h" -#if NTRIX == 0 && !defined(EXCLUDE_TRIX) -#define EXCLUDE_TRIX -#endif - -#include "sscape.h" -#if NSSCAPE == 0 && !defined(EXCLUDE_SSCAPE) -#define EXCLUDE_SSCAPE -#endif - -#if NGUS == 0 && !defined(EXCLUDE_GUSMAX) -# define EXCLUDE_GUSMAX -# if defined(EXCLUDE_GUS16) && defined(EXCLUDE_MSS) && !defined(EXCLUDE_AD1848) -# define EXCLUDE_AD1848 -# endif -#else -# define GUSMAX_MIXER -#endif - -#include "sb.h" -#if NSB == 0 && !defined(EXCLUDE_SB) -#define EXCLUDE_SB -#endif - -#include "sbxvi.h" -#if NSBXVI == 0 && !defined(EXCLUDE_SB16) -#define EXCLUDE_SB16 -#endif - -#include "sbmidi.h" -#if NSBMIDI == 0 && !defined(EXCLUDE_SB16MIDI) -#define EXCLUDE_SB16MIDI -#endif - -#include "pas.h" -#if NPAS == 0 && !defined(EXCLUDE_PAS) -#define EXCLUDE_PAS -#endif - -#include "mpu.h" -#if NMPU == 0 && !defined(EXCLUDE_MPU401) -#define EXCLUDE_MPU401 -#endif - -#include "opl.h" -#if NOPL == 0 && !defined(EXCLUDE_YM3812) -#define EXCLUDE_YM3812 -#endif - -#include "uart.h" -#if NUART == 0 && !defined(EXCLUDE_UART6850) -#define EXCLUDE_UART6850 -#endif - -#ifdef PC98 -#include "pcm.h" -#if NPCM == 0 && !defined(EXCLUDE_PCM86) -#define EXCLUDE_PCM86 -#endif -#endif - - -/* nothing but a sequencer (Adlib/OPL) ? */ -#if NGUS == 0 && NSB == 0 && NSBMIDI == 0 && NPAS == 0 && NMPU == 0 && \ - NUART == 0 && NMSS == 0 -#ifndef EXCLUDE_MIDI -#define EXCLUDE_MIDI -#endif -#ifndef EXCLUDE_AUDIO -#if !defined(PC98) || defined(EXCLUDE_PCM86) && defined(EXCLUDE_MSS) -#define EXCLUDE_AUDIO -#endif -#endif -#endif - -/* nothing but a Midi (MPU/UART) ? */ -#if NGUS == 0 && NSB == 0 && NSBMIDI == 0 && NPAS == 0 && NOPL == 0 && \ - NMSS == 0 -/* MPU depends on sequencer timer */ -#if NMPU == 0 && !defined(EXCLUDE_SEQUENCER) -#define EXCLUDE_SEQUENCER -#endif -#ifndef EXCLUDE_AUDIO -#if !defined(PC98) || defined(EXCLUDE_PCM86) && defined(EXCLUDE_MSS) -#define EXCLUDE_AUDIO -#endif -#endif -#endif diff --git a/sys/pc98/pc98/sound/midi_synth.c b/sys/pc98/pc98/sound/midi_synth.c deleted file mode 100644 index 7e4ecb0..0000000 --- a/sys/pc98/pc98/sound/midi_synth.c +++ /dev/null @@ -1,648 +0,0 @@ -/* - * sound/midi_synth.c - * - * High level midi sequencer manager for dumb MIDI interfaces. - * - * Copyright by Hannu Savolainen 1993 - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. 2. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#define USE_SEQ_MACROS -#define USE_SIMPLE_MACROS - -#ifdef PC98 -#include <pc98/pc98/sound/sound_config.h> -#else -#include <i386/isa/sound/sound_config.h> -#endif - -#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_MIDI) - -#define _MIDI_SYNTH_C_ - -DEFINE_WAIT_QUEUE (sysex_sleeper, sysex_sleep_flag); - -#include <i386/isa/sound/midi_synth.h> - -static int midi2synth[MAX_MIDI_DEV]; -static unsigned char prev_out_status[MAX_MIDI_DEV]; - -#define STORE(cmd) \ -{ \ - int len; \ - unsigned char obuf[8]; \ - cmd; \ - seq_input_event(obuf, len); \ -} -#define _seqbuf obuf -#define _seqbufptr 0 -#define _SEQ_ADVBUF(x) len=x - -void -do_midi_msg (int synthno, unsigned char *msg, int mlen) -{ - switch (msg[0] & 0xf0) - { - case 0x90: - if (msg[2] != 0) - { - STORE (SEQ_START_NOTE (synthno, msg[0] & 0x0f, msg[1], msg[2])); - break; - } - msg[2] = 64; - - case 0x80: - STORE (SEQ_STOP_NOTE (synthno, msg[0] & 0x0f, msg[1], msg[2])); - break; - - case 0xA0: - STORE (SEQ_KEY_PRESSURE (synthno, msg[0] & 0x0f, msg[1], msg[2])); - break; - - case 0xB0: - STORE (SEQ_CONTROL (synthno, msg[0] & 0x0f, - msg[1], msg[2])); - break; - - case 0xC0: - STORE (SEQ_SET_PATCH (synthno, msg[0] & 0x0f, msg[1])); - break; - - case 0xD0: - STORE (SEQ_CHN_PRESSURE (synthno, msg[0] & 0x0f, msg[1])); - break; - - case 0xE0: - STORE (SEQ_BENDER (synthno, msg[0] & 0x0f, - (msg[1] % 0x7f) | ((msg[2] & 0x7f) << 7))); - break; - - default: - printk ("MPU: Unknown midi channel message %02x\n", msg[0]); - } -} - -static void -midi_outc (int midi_dev, int data) -{ - int timeout; - - for (timeout = 0; timeout < 32000; timeout++) - if (midi_devs[midi_dev]->putc (midi_dev, (unsigned char) (data & 0xff))) - { - if (data & 0x80) /* - * Status byte - */ - prev_out_status[midi_dev] = - (unsigned char) (data & 0xff); /* - * Store for running status - */ - return; /* - * Mission complete - */ - } - - /* - * Sorry! No space on buffers. - */ - printk ("Midi send timed out\n"); -} - -static int -prefix_cmd (int midi_dev, unsigned char status) -{ - if ((char *) midi_devs[midi_dev]->prefix_cmd == NULL) - return 1; - - return midi_devs[midi_dev]->prefix_cmd (midi_dev, status); -} - -static void -midi_synth_input (int dev, unsigned char data) -{ - int orig_dev; - struct midi_input_info *inc; - - static unsigned char len_tab[] = /* # of data bytes following a status - */ - { - 2, /* 8x */ - 2, /* 9x */ - 2, /* Ax */ - 2, /* Bx */ - 1, /* Cx */ - 1, /* Dx */ - 2, /* Ex */ - 0 /* Fx */ - }; - - if (dev < 0 || dev > num_synths) - return; - - if (data == 0xfe) /* Ignore active sensing */ - return; - - orig_dev = midi2synth[dev]; - inc = &midi_devs[orig_dev]->in_info; - - switch (inc->m_state) - { - case MST_INIT: - if (data & 0x80) /* MIDI status byte */ - { - if ((data & 0xf0) == 0xf0) /* Common message */ - { - switch (data) - { - case 0xf0: /* Sysex */ - inc->m_state = MST_SYSEX; - break; /* Sysex */ - - case 0xf1: /* MTC quarter frame */ - case 0xf3: /* Song select */ - inc->m_state = MST_DATA; - inc->m_ptr = 1; - inc->m_left = 1; - inc->m_buf[0] = data; - break; - - case 0xf2: /* Song position pointer */ - inc->m_state = MST_DATA; - inc->m_ptr = 1; - inc->m_left = 2; - inc->m_buf[0] = data; - break; - - default: - inc->m_buf[0] = data; - inc->m_ptr = 1; - do_midi_msg (dev, inc->m_buf, inc->m_ptr); - inc->m_ptr = 0; - inc->m_left = 0; - } - } - else - { - inc->m_state = MST_DATA; - inc->m_ptr = 1; - inc->m_left = len_tab[(data >> 4) - 8]; - inc->m_buf[0] = inc->m_prev_status = data; - } - } - else if (inc->m_prev_status & 0x80) /* Ignore if no previous status (yet) */ - { /* Data byte (use running status) */ - inc->m_state = MST_DATA; - inc->m_ptr = 2; - inc->m_left = len_tab[(data >> 4) - 8] - 1; - inc->m_buf[0] = inc->m_prev_status; - inc->m_buf[1] = data; - } - break; /* MST_INIT */ - - case MST_DATA: - inc->m_buf[inc->m_ptr++] = data; - if (--inc->m_left <= 0) - { - inc->m_state = MST_INIT; - do_midi_msg (dev, inc->m_buf, inc->m_ptr); - inc->m_ptr = 0; - } - break; /* MST_DATA */ - - case MST_SYSEX: - if (data == 0xf7) /* Sysex end */ - { - inc->m_state = MST_INIT; - inc->m_left = 0; - inc->m_ptr = 0; - } - break; /* MST_SYSEX */ - - default: - printk ("MIDI%d: Unexpected state %d (%02x)\n", orig_dev, inc->m_state, - (int) data); - inc->m_state = MST_INIT; - } -} - -static void -midi_synth_output (int dev) -{ - /* - * Currently NOP - */ -} - -int -midi_synth_ioctl (int dev, - unsigned int cmd, unsigned int arg) -{ - /* - * int orig_dev = synth_devs[dev]->midi_dev; - */ - - switch (cmd) - { - - case SNDCTL_SYNTH_INFO: - IOCTL_TO_USER ((char *) arg, 0, synth_devs[dev]->info, - sizeof (struct synth_info)); - - return 0; - break; - - case SNDCTL_SYNTH_MEMAVL: - return 0x7fffffff; - break; - - default: - return RET_ERROR (EINVAL); - } -} - -int -midi_synth_kill_note (int dev, int channel, int note, int velocity) -{ - int orig_dev = synth_devs[dev]->midi_dev; - int msg, chn; - - if (note < 0 || note > 127) - return 0; - if (channel < 0 || channel > 15) - return 0; - if (velocity < 0) - velocity = 0; - if (velocity > 127) - velocity = 127; - - msg = prev_out_status[orig_dev] & 0xf0; - chn = prev_out_status[orig_dev] & 0x0f; - - if (chn == channel && ((msg == 0x90 && velocity == 64) || msg == 0x80)) - { /* - * Use running status - */ - if (!prefix_cmd (orig_dev, note)) - return 0; - - midi_outc (orig_dev, note); - - if (msg == 0x90) /* - * Running status = Note on - */ - midi_outc (orig_dev, 0); /* - * Note on with velocity 0 == note - * off - */ - else - midi_outc (orig_dev, velocity); - } - else - { - if (velocity == 64) - { - if (!prefix_cmd (orig_dev, 0x90 | (channel & 0x0f))) - return 0; - midi_outc (orig_dev, 0x90 | (channel & 0x0f)); /* - * Note on - */ - midi_outc (orig_dev, note); - midi_outc (orig_dev, 0); /* - * Zero G - */ - } - else - { - if (!prefix_cmd (orig_dev, 0x80 | (channel & 0x0f))) - return 0; - midi_outc (orig_dev, 0x80 | (channel & 0x0f)); /* - * Note off - */ - midi_outc (orig_dev, note); - midi_outc (orig_dev, velocity); - } - } - - return 0; -} - -int -midi_synth_set_instr (int dev, int channel, int instr_no) -{ - int orig_dev = synth_devs[dev]->midi_dev; - - if (instr_no < 0 || instr_no > 127) - return 0; - if (channel < 0 || channel > 15) - return 0; - - if (!prefix_cmd (orig_dev, 0xc0 | (channel & 0x0f))) - return 0; - midi_outc (orig_dev, 0xc0 | (channel & 0x0f)); /* - * Program change - */ - midi_outc (orig_dev, instr_no); - - return 0; -} - -int -midi_synth_start_note (int dev, int channel, int note, int velocity) -{ - int orig_dev = synth_devs[dev]->midi_dev; - int msg, chn; - - if (note < 0 || note > 127) - return 0; - if (channel < 0 || channel > 15) - return 0; - if (velocity < 0) - velocity = 0; - if (velocity > 127) - velocity = 127; - - msg = prev_out_status[orig_dev] & 0xf0; - chn = prev_out_status[orig_dev] & 0x0f; - - if (chn == channel && msg == 0x90) - { /* - * Use running status - */ - if (!prefix_cmd (orig_dev, note)) - return 0; - midi_outc (orig_dev, note); - midi_outc (orig_dev, velocity); - } - else - { - if (!prefix_cmd (orig_dev, 0x90 | (channel & 0x0f))) - return 0; - midi_outc (orig_dev, 0x90 | (channel & 0x0f)); /* - * Note on - */ - midi_outc (orig_dev, note); - midi_outc (orig_dev, velocity); - } - return 0; -} - -void -midi_synth_reset (int dev) -{ -} - -int -midi_synth_open (int dev, int mode) -{ - int orig_dev = synth_devs[dev]->midi_dev; - int err; - unsigned long flags; - struct midi_input_info *inc; - - if (orig_dev < 0 || orig_dev > num_midis) - return RET_ERROR (ENXIO); - - midi2synth[orig_dev] = dev; - prev_out_status[orig_dev] = 0; - - if ((err = midi_devs[orig_dev]->open (orig_dev, mode, - midi_synth_input, midi_synth_output)) < 0) - return err; - - inc = &midi_devs[orig_dev]->in_info; - - DISABLE_INTR (flags); - inc->m_busy = 0; - inc->m_state = MST_INIT; - inc->m_ptr = 0; - inc->m_left = 0; - inc->m_prev_status = 0x00; - RESTORE_INTR (flags); - - return 1; -} - -void -midi_synth_close (int dev) -{ - int orig_dev = synth_devs[dev]->midi_dev; - - /* - * Shut up the synths by sending just single active sensing message. - */ - midi_devs[orig_dev]->putc (orig_dev, 0xfe); - - midi_devs[orig_dev]->close (orig_dev); -} - -void -midi_synth_hw_control (int dev, unsigned char *event) -{ -} - -int -midi_synth_load_patch (int dev, int format, snd_rw_buf * addr, - int offs, int count, int pmgr_flag) -{ - int orig_dev = synth_devs[dev]->midi_dev; - - struct sysex_info sysex; - int i; - unsigned long left, src_offs, eox_seen = 0; - int first_byte = 1; - int hdr_size = (unsigned long) &sysex.data[0] - (unsigned long) &sysex; - - if (!prefix_cmd (orig_dev, 0xf0)) - return 0; - - if (format != SYSEX_PATCH) - { - printk ("MIDI Error: Invalid patch format (key) 0x%x\n", format); - return RET_ERROR (EINVAL); - } - - if (count < hdr_size) - { - printk ("MIDI Error: Patch header too short\n"); - return RET_ERROR (EINVAL); - } - - count -= hdr_size; - - /* - * Copy the header from user space but ignore the first bytes which have - * 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; - - RESET_WAIT_QUEUE (sysex_sleeper, sysex_sleep_flag); - - for (i = 0; i < left && !PROCESS_ABORTING (sysex_sleeper, sysex_sleep_flag); i++) - { - unsigned char data; - - GET_BYTE_FROM_USER (data, 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 RET_ERROR (EINVAL); - } - } - - while (!midi_devs[orig_dev]->putc (orig_dev, (unsigned char) (data & 0xff)) && - !PROCESS_ABORTING (sysex_sleeper, sysex_sleep_flag)) - DO_SLEEP (sysex_sleeper, sysex_sleep_flag, 1); /* 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_aftertouch (int dev, int channel, int pressure) -{ - int orig_dev = synth_devs[dev]->midi_dev; - int msg, chn; - - if (pressure < 0 || pressure > 127) - return; - if (channel < 0 || channel > 15) - return; - - msg = prev_out_status[orig_dev] & 0xf0; - chn = prev_out_status[orig_dev] & 0x0f; - - if (msg != 0xd0 || chn != channel) /* - * Test for running status - */ - { - if (!prefix_cmd (orig_dev, 0xd0 | (channel & 0x0f))) - return; - midi_outc (orig_dev, 0xd0 | (channel & 0x0f)); /* - * Channel pressure - */ - } - else if (!prefix_cmd (orig_dev, pressure)) - return; - - midi_outc (orig_dev, pressure); -} - -void -midi_synth_controller (int dev, int channel, int ctrl_num, int value) -{ - int orig_dev = synth_devs[dev]->midi_dev; - int chn, msg; - - if (ctrl_num < 1 || ctrl_num > 127) - return; /* NOTE! Controller # 0 ignored */ - if (channel < 0 || channel > 15) - return; - - msg = prev_out_status[orig_dev] & 0xf0; - chn = prev_out_status[orig_dev] & 0x0f; - - if (msg != 0xb0 || chn != channel) - { - if (!prefix_cmd (orig_dev, 0xb0 | (channel & 0x0f))) - return; - midi_outc (orig_dev, 0xb0 | (channel & 0x0f)); - } - else if (!prefix_cmd (orig_dev, ctrl_num)) - return; - - midi_outc (orig_dev, ctrl_num); - midi_outc (orig_dev, value & 0x7f); -} - -int -midi_synth_patchmgr (int dev, struct patmgr_info *rec) -{ - return RET_ERROR (EINVAL); -} - -void -midi_synth_bender (int dev, int channel, int value) -{ - int orig_dev = synth_devs[dev]->midi_dev; - int msg, prev_chn; - - if (channel < 0 || channel > 15) - return; - - if (value < 0 || value > 16383) - return; - - msg = prev_out_status[orig_dev] & 0xf0; - prev_chn = prev_out_status[orig_dev] & 0x0f; - - if (msg != 0xd0 || prev_chn != channel) /* - * Test for running status - */ - { - if (!prefix_cmd (orig_dev, 0xe0 | (channel & 0x0f))) - return; - midi_outc (orig_dev, 0xe0 | (channel & 0x0f)); - } - else if (!prefix_cmd (orig_dev, value & 0x7f)) - return; - - midi_outc (orig_dev, value & 0x7f); - midi_outc (orig_dev, (value >> 7) & 0x7f); -} - -void -midi_synth_setup_voice (int dev, int voice, int channel) -{ -} - -#endif diff --git a/sys/pc98/pc98/sound/midibuf.c b/sys/pc98/pc98/sound/midibuf.c deleted file mode 100644 index bb4add6..0000000 --- a/sys/pc98/pc98/sound/midibuf.c +++ /dev/null @@ -1,474 +0,0 @@ -/* - * sound/midibuf.c - * - * Device file manager for /dev/midi# - * - * Copyright by Hannu Savolainen 1993 - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. 2. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#ifdef PC98 -#include <pc98/pc98/sound/sound_config.h> -#else -#include <i386/isa/sound/sound_config.h> -#endif - -static void drain_midi_queue __P((int dev)); - -#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_MIDI) - -/* - * Don't make MAX_QUEUE_SIZE larger than 4000 - */ - -#define MAX_QUEUE_SIZE 4000 - -DEFINE_WAIT_QUEUES (midi_sleeper[MAX_MIDI_DEV], midi_sleep_flag[MAX_MIDI_DEV]); -DEFINE_WAIT_QUEUES (input_sleeper[MAX_MIDI_DEV], input_sleep_flag[MAX_MIDI_DEV]); - -struct midi_buf - { - int len, head, tail; - unsigned char queue[MAX_QUEUE_SIZE]; - }; - -struct midi_parms - { - int prech_timeout; /* - * Timeout before the first ch - */ - }; - -static struct midi_buf *midi_out_buf[MAX_MIDI_DEV] = -{NULL}; -static struct midi_buf *midi_in_buf[MAX_MIDI_DEV] = -{NULL}; -static struct midi_parms parms[MAX_MIDI_DEV]; - -static void midi_poll (unsigned long dummy); - -DEFINE_TIMER (poll_timer, midi_poll); -static volatile int open_devs = 0; - -#define DATA_AVAIL(q) (q->len) -#define SPACE_AVAIL(q) (MAX_QUEUE_SIZE - q->len) - -#define QUEUE_BYTE(q, data) \ - if (SPACE_AVAIL(q)) \ - { \ - unsigned long flags; \ - DISABLE_INTR(flags); \ - q->queue[q->tail] = (data); \ - q->len++; q->tail = (q->tail+1) % MAX_QUEUE_SIZE; \ - RESTORE_INTR(flags); \ - } - -#define REMOVE_BYTE(q, data) \ - if (DATA_AVAIL(q)) \ - { \ - unsigned long flags; \ - DISABLE_INTR(flags); \ - data = q->queue[q->head]; \ - q->len--; q->head = (q->head+1) % MAX_QUEUE_SIZE; \ - RESTORE_INTR(flags); \ - } - -static void -drain_midi_queue (int dev) -{ - - /* - * Give the Midi driver time to drain its output queues - */ - - if (midi_devs[dev]->buffer_status != NULL) - while (!PROCESS_ABORTING (midi_sleeper[dev], midi_sleep_flag[dev]) && - midi_devs[dev]->buffer_status (dev)) - DO_SLEEP (midi_sleeper[dev], midi_sleep_flag[dev], HZ / 10); -} - -static void -midi_input_intr (int dev, unsigned char data) -{ - if (midi_in_buf[dev] == NULL) - return; - - if (data == 0xfe) /* - * Active sensing - */ - return; /* - * Ignore - */ - - if (SPACE_AVAIL (midi_in_buf[dev])) - { - QUEUE_BYTE (midi_in_buf[dev], data); - if (SOMEONE_WAITING (input_sleeper[dev], input_sleep_flag[dev])) - WAKE_UP (input_sleeper[dev], input_sleep_flag[dev]); - } -#if defined(__FreeBSD__) - if (selinfo[dev].si_pid) - selwakeup(&selinfo[dev]); -#endif -} - -static void -midi_output_intr (int dev) -{ - /* - * Currently NOP - */ -#if defined(__FreeBSD__) - if (selinfo[dev].si_pid) - selwakeup(&selinfo[dev]); -#endif -} - -static void -midi_poll (unsigned long dummy) -{ - unsigned long flags; - int dev; - - DISABLE_INTR (flags); - if (open_devs) - { - for (dev = 0; dev < num_midis; dev++) - if (midi_out_buf[dev] != NULL) - { - while (DATA_AVAIL (midi_out_buf[dev]) && - midi_devs[dev]->putc (dev, - midi_out_buf[dev]->queue[midi_out_buf[dev]->head])) - { - midi_out_buf[dev]->head = (midi_out_buf[dev]->head + 1) % MAX_QUEUE_SIZE; - midi_out_buf[dev]->len--; - } - - if (DATA_AVAIL (midi_out_buf[dev]) < 100 && - SOMEONE_WAITING (midi_sleeper[dev], midi_sleep_flag[dev])) - WAKE_UP (midi_sleeper[dev], midi_sleep_flag[dev]); - } - ACTIVATE_TIMER (poll_timer, midi_poll, 1); /* - * Come back later - */ - } - RESTORE_INTR (flags); -} - -int -MIDIbuf_open (int dev, struct fileinfo *file) -{ - int mode, err; - unsigned long flags; - - dev = dev >> 4; - mode = file->mode & O_ACCMODE; - - if (num_midis > MAX_MIDI_DEV) - { - printk ("Sound: FATAL ERROR: Too many midi interfaces\n"); - num_midis = MAX_MIDI_DEV; - } - - if (dev < 0 || dev >= num_midis) - { - printk ("Sound: Nonexistent MIDI interface %d\n", dev); - return RET_ERROR (ENXIO); - } - - /* - * Interrupts disabled. Be careful - */ - - DISABLE_INTR (flags); - if ((err = midi_devs[dev]->open (dev, mode, - midi_input_intr, midi_output_intr)) < 0) - { - RESTORE_INTR (flags); - return err; - } - - parms[dev].prech_timeout = 0; - - RESET_WAIT_QUEUE (midi_sleeper[dev], midi_sleep_flag[dev]); - RESET_WAIT_QUEUE (input_sleeper[dev], input_sleep_flag[dev]); - - midi_in_buf[dev] = (struct midi_buf *) KERNEL_MALLOC (sizeof (struct midi_buf)); - - if (midi_in_buf[dev] == NULL) - { - printk ("midi: Can't allocate buffer\n"); - midi_devs[dev]->close (dev); - RESTORE_INTR (flags); - return RET_ERROR (EIO); - } - midi_in_buf[dev]->len = midi_in_buf[dev]->head = midi_in_buf[dev]->tail = 0; - - midi_out_buf[dev] = (struct midi_buf *) KERNEL_MALLOC (sizeof (struct midi_buf)); - - if (midi_out_buf[dev] == NULL) - { - printk ("midi: Can't allocate buffer\n"); - midi_devs[dev]->close (dev); - KERNEL_FREE (midi_in_buf[dev]); - midi_in_buf[dev] = NULL; - RESTORE_INTR (flags); - return RET_ERROR (EIO); - } - midi_out_buf[dev]->len = midi_out_buf[dev]->head = midi_out_buf[dev]->tail = 0; - if (!open_devs) - ACTIVATE_TIMER (poll_timer, midi_poll, 1); /* - * Come back later - */ - open_devs++; - RESTORE_INTR (flags); - - return err; -} - -void -MIDIbuf_release (int dev, struct fileinfo *file) -{ - int mode; - unsigned long flags; - - dev = dev >> 4; - mode = file->mode & O_ACCMODE; - - DISABLE_INTR (flags); - - /* - * Wait until the queue is empty - */ - - if (mode != OPEN_READ) - { - midi_devs[dev]->putc (dev, 0xfe); /* - * Active sensing to shut the - * devices - */ - - while (!PROCESS_ABORTING (midi_sleeper[dev], midi_sleep_flag[dev]) && - DATA_AVAIL (midi_out_buf[dev])) - DO_SLEEP (midi_sleeper[dev], midi_sleep_flag[dev], 0); /* - * Sync - */ - - drain_midi_queue (dev); /* - * Ensure the output queues are empty - */ - } - - midi_devs[dev]->close (dev); - KERNEL_FREE (midi_in_buf[dev]); - KERNEL_FREE (midi_out_buf[dev]); - midi_in_buf[dev] = NULL; - midi_out_buf[dev] = NULL; - open_devs--; - RESTORE_INTR (flags); -} - -int -MIDIbuf_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) -{ - unsigned long flags; - int c, n, i; - unsigned char tmp_data; - - dev = dev >> 4; - - if (!count) - return 0; - - DISABLE_INTR (flags); - - c = 0; - - while (c < count) - { - n = SPACE_AVAIL (midi_out_buf[dev]); - - if (n == 0) /* - * No space just now. We have to sleep - */ - { - DO_SLEEP (midi_sleeper[dev], midi_sleep_flag[dev], 0); - if (PROCESS_ABORTING (midi_sleeper[dev], midi_sleep_flag[dev])) - { - RESTORE_INTR (flags); - return RET_ERROR (EINTR); - } - - n = SPACE_AVAIL (midi_out_buf[dev]); - } - - if (n > (count - c)) - n = count - c; - - for (i = 0; i < n; i++) - { - COPY_FROM_USER (&tmp_data, buf, c, 1); - QUEUE_BYTE (midi_out_buf[dev], tmp_data); - c++; - } - } - - RESTORE_INTR (flags); - - return c; -} - - -int -MIDIbuf_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) -{ - int n, c = 0; - unsigned long flags; - unsigned char tmp_data; - - dev = dev >> 4; - - DISABLE_INTR (flags); - - if (!DATA_AVAIL (midi_in_buf[dev])) /* - * No data yet, wait - */ - { - DO_SLEEP (input_sleeper[dev], input_sleep_flag[dev], - parms[dev].prech_timeout); - if (PROCESS_ABORTING (input_sleeper[dev], input_sleep_flag[dev])) - c = RET_ERROR (EINTR); /* - * The user is getting restless - */ - } - - if (c == 0 && DATA_AVAIL (midi_in_buf[dev])) /* - * Got some bytes - */ - { - n = DATA_AVAIL (midi_in_buf[dev]); - if (n > count) - n = count; - c = 0; - - while (c < n) - { - REMOVE_BYTE (midi_in_buf[dev], tmp_data); - COPY_TO_USER (buf, c, &tmp_data, 1); - c++; - } - } - - RESTORE_INTR (flags); - - return c; -} - -int -MIDIbuf_ioctl (int dev, struct fileinfo *file, - unsigned int cmd, unsigned int arg) -{ - int val; - - dev = dev >> 4; - - if (((cmd >> 8) & 0xff) == 'C') - { - if (midi_devs[dev]->coproc) /* Coprocessor ioctl */ - return midi_devs[dev]->coproc->ioctl (midi_devs[dev]->coproc->devc, cmd, arg, 0); - else - printk ("/dev/midi%d: No coprocessor for this device\n", dev); - - return RET_ERROR (EREMOTEIO); - } - else - switch (cmd) - { - - case SNDCTL_MIDI_PRETIME: - val = IOCTL_IN (arg); - if (val < 0) - val = 0; - - val = (HZ * val) / 10; - parms[dev].prech_timeout = val; - return IOCTL_OUT (arg, val); - break; - - default: - return midi_devs[dev]->ioctl (dev, cmd, arg); - } -} - -#ifdef ALLOW_SELECT -int -MIDIbuf_select (int dev, struct fileinfo *file, int sel_type, select_table * wait) -{ - dev = dev >> 4; - - switch (sel_type) - { - case SEL_IN: - if (!DATA_AVAIL (midi_in_buf[dev])) - { -#if defined(__FreeBSD__) - selrecord(wait, &selinfo[dev]); -#else - input_sleep_flag[dev].mode = WK_SLEEP; - select_wait (&input_sleeper[dev], wait); -#endif - return 0; - } - return 1; - break; - - case SEL_OUT: - if (SPACE_AVAIL (midi_out_buf[dev])) - { -#if defined(__FreeBSD__) - selrecord(wait, &selinfo[dev]); -#else - midi_sleep_flag[dev].mode = WK_SLEEP; - select_wait (&midi_sleeper[dev], wait); -#endif - return 0; - } - return 1; - break; - - case SEL_EX: - return 0; - } - - return 0; -} - -#endif /* ALLOW_SELECT */ - -long -MIDIbuf_init (long mem_start) -{ - return mem_start; -} - -#endif diff --git a/sys/pc98/pc98/sound/mpu401.c b/sys/pc98/pc98/sound/mpu401.c deleted file mode 100644 index eaee157..0000000 --- a/sys/pc98/pc98/sound/mpu401.c +++ /dev/null @@ -1,1777 +0,0 @@ -/* - * sound/mpu401.c - * - * The low level driver for Roland MPU-401 compatible Midi cards. - * - * Copyright by Hannu Savolainen 1993 - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. 2. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * Modified: - * Riccardo Facchetti 24 Mar 1995 - * - Added the Audio Excel DSP 16 initialization routine. - */ - -#define USE_SEQ_MACROS -#define USE_SIMPLE_MACROS - -#include <i386/isa/sound/sound_config.h> - -#ifdef CONFIGURE_SOUNDCARD - -#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI) -#include <i386/isa/sound/coproc.h> - -static int init_sequence[20]; /* NOTE! pos 0 = len, start pos 1. */ -static int timer_mode = TMR_INTERNAL, timer_caps = TMR_INTERNAL; - -struct mpu_config - { - int base; /* - * I/O base - */ - int irq; - int opened; /* - * Open mode - */ - int devno; - int synthno; - int uart_mode; - int initialized; - int mode; -#define MODE_MIDI 1 -#define MODE_SYNTH 2 - unsigned char version, revision; - unsigned int capabilities; -#define MPU_CAP_INTLG 0x10000000 -#define MPU_CAP_SYNC 0x00000010 -#define MPU_CAP_FSK 0x00000020 -#define MPU_CAP_CLS 0x00000040 -#define MPU_CAP_SMPTE 0x00000080 -#define MPU_CAP_2PORT 0x00000001 - int timer_flag; - -#define MBUF_MAX 10 -#define BUFTEST(dc) if (dc->m_ptr >= MBUF_MAX || dc->m_ptr < 0) \ - {printk("MPU: Invalid buffer pointer %d/%d, s=%d\n", dc->m_ptr, dc->m_left, dc->m_state);dc->m_ptr--;} - int m_busy; - unsigned char m_buf[MBUF_MAX]; - int m_ptr; - int m_state; - int m_left; - unsigned char last_status; - void (*inputintr) (int dev, unsigned char data); - int shared_irq; - }; - -#define DATAPORT(base) (base) -#define COMDPORT(base) (base+1) -#define STATPORT(base) (base+1) - -#define mpu401_status(base) INB(STATPORT(base)) -#define input_avail(base) (!(mpu401_status(base)&INPUT_AVAIL)) -#define output_ready(base) (!(mpu401_status(base)&OUTPUT_READY)) -#define write_command(base, cmd) OUTB(cmd, COMDPORT(base)) -#define read_data(base) INB(DATAPORT(base)) - -#define write_data(base, byte) OUTB(byte, DATAPORT(base)) - -#define OUTPUT_READY 0x40 -#define INPUT_AVAIL 0x80 -#define MPU_ACK 0xF7 -#define MPU_RESET 0xFF -#define UART_MODE_ON 0x3F - -static struct mpu_config dev_conf[MAX_MIDI_DEV] = -{ - {0}}; - -static int n_mpu_devs = 0; -static int irq2dev[16] = -{-1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1}; - -static int reset_mpu401 (struct mpu_config *devc); -static void set_uart_mode (int dev, struct mpu_config *devc, int arg); -static void mpu_timer_init (int midi_dev); -static void mpu_timer_interrupt (void); -static void timer_ext_event (struct mpu_config *devc, int event, int parm); - -static struct synth_info mpu_synth_info_proto = -{"MPU-401 MIDI interface", 0, SYNTH_TYPE_MIDI, 0, 0, 128, 0, 128, SYNTH_CAP_INPUT}; - -static struct synth_info mpu_synth_info[MAX_MIDI_DEV]; - -/* - * States for the input scanner - */ - -#define ST_INIT 0 /* Ready for timing byte or msg */ -#define ST_TIMED 1 /* Leading timing byte rcvd */ -#define ST_DATABYTE 2 /* Waiting for (nr_left) data bytes */ - -#define ST_SYSMSG 100 /* System message (sysx etc). */ -#define ST_SYSEX 101 /* System exclusive msg */ -#define ST_MTC 102 /* Midi Time Code (MTC) qframe msg */ -#define ST_SONGSEL 103 /* Song select */ -#define ST_SONGPOS 104 /* Song position pointer */ - -static unsigned char len_tab[] = /* # of data bytes following a status - */ -{ - 2, /* 8x */ - 2, /* 9x */ - 2, /* Ax */ - 2, /* Bx */ - 1, /* Cx */ - 1, /* Dx */ - 2, /* Ex */ - 0 /* Fx */ -}; - -#define STORE(cmd) \ -{ \ - int len; \ - unsigned char obuf[8]; \ - cmd; \ - seq_input_event(obuf, len); \ -} -#define _seqbuf obuf -#define _seqbufptr 0 -#define _SEQ_ADVBUF(x) len=x - -static int -mpu_input_scanner (struct mpu_config *devc, unsigned char midic) -{ - - switch (devc->m_state) - { - case ST_INIT: - switch (midic) - { - case 0xf8: - /* Timer overflow */ - break; - - case 0xfc: - printk ("<all end>"); - break; - - case 0xfd: - if (devc->timer_flag) - mpu_timer_interrupt (); - break; - - case 0xfe: - return MPU_ACK; - break; - - case 0xf0: - case 0xf1: - case 0xf2: - case 0xf3: - case 0xf4: - case 0xf5: - case 0xf6: - case 0xf7: - printk ("<Trk data rq #%d>", midic & 0x0f); - break; - - case 0xf9: - printk ("<conductor rq>"); - break; - - case 0xff: - devc->m_state = ST_SYSMSG; - break; - - default: - if (midic <= 0xef) - { - /* printk("mpu time: %d ", midic); */ - devc->m_state = ST_TIMED; - } - else - printk ("<MPU: Unknown event %02x> ", midic); - } - break; - - case ST_TIMED: - { - int msg = (midic & 0xf0) >> 4; - - devc->m_state = ST_DATABYTE; - - if (msg < 8) /* Data byte */ - { - /* printk("midi msg (running status) "); */ - msg = (devc->last_status & 0xf0) >> 4; - msg -= 8; - devc->m_left = len_tab[msg] - 1; - - devc->m_ptr = 2; - devc->m_buf[0] = devc->last_status; - devc->m_buf[1] = midic; - - if (devc->m_left <= 0) - { - devc->m_state = ST_INIT; - do_midi_msg (devc->synthno, devc->m_buf, devc->m_ptr); - devc->m_ptr = 0; - } - } - else if (msg == 0xf) /* MPU MARK */ - { - devc->m_state = ST_INIT; - - switch (midic) - { - case 0xf8: - /* printk("NOP "); */ - break; - - case 0xf9: - /* printk("meas end "); */ - break; - - case 0xfc: - /* printk("data end "); */ - break; - - default: - printk ("Unknown MPU mark %02x\n", midic); - } - } - else - { - devc->last_status = midic; - /* printk ("midi msg "); */ - msg -= 8; - devc->m_left = len_tab[msg]; - - devc->m_ptr = 1; - devc->m_buf[0] = midic; - - if (devc->m_left <= 0) - { - devc->m_state = ST_INIT; - do_midi_msg (devc->synthno, devc->m_buf, devc->m_ptr); - devc->m_ptr = 0; - } - } - } - break; - - case ST_SYSMSG: - switch (midic) - { - case 0xf0: - printk ("<SYX>"); - devc->m_state = ST_SYSEX; - break; - - case 0xf1: - devc->m_state = ST_MTC; - break; - - case 0xf2: - devc->m_state = ST_SONGPOS; - devc->m_ptr = 0; - break; - - case 0xf3: - devc->m_state = ST_SONGSEL; - break; - - case 0xf6: - /* printk("tune_request\n"); */ - devc->m_state = ST_INIT; - - /* - * Real time messages - */ - case 0xf8: - /* midi clock */ - devc->m_state = ST_INIT; - timer_ext_event (devc, TMR_CLOCK, 0); - break; - - case 0xfA: - devc->m_state = ST_INIT; - timer_ext_event (devc, TMR_START, 0); - break; - - case 0xFB: - devc->m_state = ST_INIT; - timer_ext_event (devc, TMR_CONTINUE, 0); - break; - - case 0xFC: - devc->m_state = ST_INIT; - timer_ext_event (devc, TMR_STOP, 0); - break; - - case 0xFE: - /* active sensing */ - devc->m_state = ST_INIT; - break; - - case 0xff: - /* printk("midi hard reset"); */ - devc->m_state = ST_INIT; - break; - - default: - printk ("unknown MIDI sysmsg %0x\n", midic); - devc->m_state = ST_INIT; - } - break; - - case ST_MTC: - devc->m_state = ST_INIT; - printk ("MTC frame %x02\n", midic); - break; - - case ST_SYSEX: - if (midic == 0xf7) - { - printk ("<EOX>"); - devc->m_state = ST_INIT; - } - else - printk ("%02x ", midic); - break; - - case ST_SONGPOS: - BUFTEST (devc); - devc->m_buf[devc->m_ptr++] = midic; - if (devc->m_ptr == 2) - { - devc->m_state = ST_INIT; - devc->m_ptr = 0; - timer_ext_event (devc, TMR_SPP, - ((devc->m_buf[1] & 0x7f) << 7) | - (devc->m_buf[0] & 0x7f)); - } - break; - - case ST_DATABYTE: - BUFTEST (devc); - devc->m_buf[devc->m_ptr++] = midic; - if ((--devc->m_left) <= 0) - { - devc->m_state = ST_INIT; - do_midi_msg (devc->synthno, devc->m_buf, devc->m_ptr); - devc->m_ptr = 0; - } - break; - - default: - printk ("Bad state %d ", devc->m_state); - devc->m_state = ST_INIT; - } - - return 1; -} - -static void -mpu401_input_loop (struct mpu_config *devc) -{ - unsigned long flags; - int busy; - int n; - - DISABLE_INTR (flags); - busy = devc->m_busy; - devc->m_busy = 1; - RESTORE_INTR (flags); - - if (busy) /* Already inside the scanner */ - return; - - n = 50; - - while (input_avail (devc->base) && n-- > 0) - { - unsigned char c = read_data (devc->base); - - if (devc->mode == MODE_SYNTH) - { - mpu_input_scanner (devc, c); - } - else if (devc->opened & OPEN_READ && devc->inputintr != NULL) - devc->inputintr (devc->devno, c); - } - - devc->m_busy = 0; -} - -void -mpuintr (INT_HANDLER_PARMS (irq, dummy)) -{ - struct mpu_config *devc; - int dev; - -#ifdef linux - sti (); -#endif - - if (irq < 1 || irq > 15) - { - printk ("MPU-401: Interrupt #%d?\n", irq); - return; - } - - dev = irq2dev[irq]; - if (dev == -1) - { - /* printk ("MPU-401: Interrupt #%d?\n", irq); */ - return; - } - - devc = &dev_conf[dev]; - - if (input_avail (devc->base)) - if (devc->base != 0 && (devc->opened & OPEN_READ || devc->mode == MODE_SYNTH)) - mpu401_input_loop (devc); - else - { - /* Dummy read (just to acknowledge the interrupt) */ - read_data (devc->base); - } - -} - -static int -mpu401_open (int dev, int mode, - void (*input) (int dev, unsigned char data), - void (*output) (int dev) -) -{ - int err; - struct mpu_config *devc; - - if (dev < 0 || dev >= num_midis) - return RET_ERROR (ENXIO); - - devc = &dev_conf[dev]; - - if (devc->opened) - { - printk ("MPU-401: Midi busy\n"); - return RET_ERROR (EBUSY); - } - - /* - * Verify that the device is really running. - * Some devices (such as Ensoniq SoundScape don't - * work before the on board processor (OBP) is initialized - * by downloadin it's microcode. - */ - - if (!devc->initialized) - { - if (mpu401_status (devc->base) == 0xff) /* Bus float */ - { - printk ("MPU-401: Device not initialized properly\n"); - return RET_ERROR (EIO); - } - reset_mpu401 (devc); - } - - irq2dev[devc->irq] = dev; - if (devc->shared_irq == 0) - if ((err = snd_set_irq_handler (devc->irq, mpuintr, midi_devs[dev]->info.name) < 0)) - { - return err; - } - - if (midi_devs[dev]->coproc) - if ((err = midi_devs[dev]->coproc-> - open (midi_devs[dev]->coproc->devc, COPR_MIDI)) < 0) - { - if (devc->shared_irq == 0) - snd_release_irq (devc->irq); - printk ("MPU-401: Can't access coprocessor device\n"); - - return err; - } - - set_uart_mode (dev, devc, 1); - devc->mode = MODE_MIDI; - devc->synthno = 0; - - mpu401_input_loop (devc); - - devc->inputintr = input; - devc->opened = mode; - - return 0; -} - -static void -mpu401_close (int dev) -{ - struct mpu_config *devc; - - devc = &dev_conf[dev]; - - if (devc->uart_mode) - reset_mpu401 (devc); /* - * This disables the UART mode - */ - devc->mode = 0; - - if (devc->shared_irq == 0) - snd_release_irq (devc->irq); - devc->inputintr = NULL; - - if (midi_devs[dev]->coproc) - midi_devs[dev]->coproc->close (midi_devs[dev]->coproc->devc, COPR_MIDI); - devc->opened = 0; -} - -static int -mpu401_out (int dev, unsigned char midi_byte) -{ - int timeout; - unsigned long flags; - - struct mpu_config *devc; - - devc = &dev_conf[dev]; - -#if 0 - /* - * Test for input since pending input seems to block the output. - */ - - if (input_avail (devc->base)) - { - mpu401_input_loop (devc); - } -#endif - /* - * Sometimes it takes about 13000 loops before the output becomes ready - * (After reset). Normally it takes just about 10 loops. - */ - - for (timeout = 3000; timeout > 0 && !output_ready (devc->base); timeout--); - - DISABLE_INTR (flags); - if (!output_ready (devc->base)) - { - printk ("MPU-401: Send data timeout\n"); - RESTORE_INTR (flags); - return 0; - } - - write_data (devc->base, midi_byte); - RESTORE_INTR (flags); - return 1; -} - -static int -mpu401_command (int dev, mpu_command_rec * cmd) -{ - int i, timeout, ok; - int ret = 0; - unsigned long flags; - struct mpu_config *devc; - - devc = &dev_conf[dev]; - - if (devc->uart_mode) /* - * Not possible in UART mode - */ - { - printk ("MPU-401 commands not possible in the UART mode\n"); - return RET_ERROR (EINVAL); - } - - /* - * Test for input since pending input seems to block the output. - */ - if (input_avail (devc->base)) - mpu401_input_loop (devc); - - /* - * Sometimes it takes about 30000 loops before the output becomes ready - * (After reset). Normally it takes just about 10 loops. - */ - - timeout = 30000; -retry: - if (timeout-- <= 0) - { - printk ("MPU-401: Command (0x%x) timeout\n", (int) cmd->cmd); - return RET_ERROR (EIO); - } - - DISABLE_INTR (flags); - - if (!output_ready (devc->base)) - { - RESTORE_INTR (flags); - goto retry; - } - - write_command (devc->base, cmd->cmd); - ok = 0; - for (timeout = 50000; timeout > 0 && !ok; timeout--) - if (input_avail (devc->base)) - { - if (mpu_input_scanner (devc, read_data (devc->base)) == MPU_ACK) - ok = 1; - } - - if (!ok) - { - RESTORE_INTR (flags); - /* printk ("MPU: No ACK to command (0x%x)\n", (int) cmd->cmd); */ - return RET_ERROR (EIO); - } - - if (cmd->nr_args) - for (i = 0; i < cmd->nr_args; i++) - { - for (timeout = 3000; timeout > 0 && !output_ready (devc->base); timeout--); - - if (!mpu401_out (dev, cmd->data[i])) - { - RESTORE_INTR (flags); - printk ("MPU: Command (0x%x), parm send failed.\n", (int) cmd->cmd); - return RET_ERROR (EIO); - } - } - - ret = 0; - cmd->data[0] = 0; - - if (cmd->nr_returns) - for (i = 0; i < cmd->nr_returns; i++) - { - ok = 0; - for (timeout = 5000; timeout > 0 && !ok; timeout--) - if (input_avail (devc->base)) - { - cmd->data[i] = read_data (devc->base); - ok = 1; - } - - if (!ok) - { - RESTORE_INTR (flags); - /* printk ("MPU: No response(%d) to command (0x%x)\n", i, (int) cmd->cmd); */ - return RET_ERROR (EIO); - } - } - - RESTORE_INTR (flags); - - return ret; -} - -static int -exec_cmd (int dev, int cmd, int data) -{ - int ret; - - static mpu_command_rec rec; - - rec.cmd = cmd & 0xff; - rec.nr_args = ((cmd & 0xf0) == 0xE0); - rec.nr_returns = ((cmd & 0xf0) == 0xA0); - rec.data[0] = data & 0xff; - - if ((ret = mpu401_command (dev, &rec)) < 0) - return ret; - return (unsigned char) rec.data[0]; -} - -static int -mpu401_prefix_cmd (int dev, unsigned char status) -{ - struct mpu_config *devc = &dev_conf[dev]; - - if (devc->uart_mode) - return 1; - - if (status < 0xf0) - { - if (exec_cmd (dev, 0xD0, 0) < 0) - return 0; - - return 1; - } - - switch (status) - { - case 0xF0: - if (exec_cmd (dev, 0xDF, 0) < 0) - return 0; - - return 1; - break; - - default: - return 0; - } - - return 0; -} - -static int -mpu401_start_read (int dev) -{ - return 0; -} - -static int -mpu401_end_read (int dev) -{ - return 0; -} - -static int -mpu401_ioctl (int dev, unsigned cmd, unsigned arg) -{ - struct mpu_config *devc; - - devc = &dev_conf[dev]; - - switch (cmd) - { - case 1: - IOCTL_FROM_USER ((char *) &init_sequence, (char *) arg, 0, sizeof (init_sequence)); - return 0; - break; - - case SNDCTL_MIDI_MPUMODE: - if (devc->version == 0) - { - printk ("MPU-401: Intelligent mode not supported by the HW\n"); - return RET_ERROR (EINVAL); - } - set_uart_mode (dev, devc, !IOCTL_IN (arg)); - return 0; - break; - - case SNDCTL_MIDI_MPUCMD: - { - int ret; - mpu_command_rec rec; - - IOCTL_FROM_USER ((char *) &rec, (char *) arg, 0, sizeof (rec)); - - if ((ret = mpu401_command (dev, &rec)) < 0) - return ret; - - IOCTL_TO_USER ((char *) arg, 0, (char *) &rec, sizeof (rec)); - return 0; - } - break; - - default: - return RET_ERROR (EINVAL); - } -} - -static void -mpu401_kick (int dev) -{ -} - -static int -mpu401_buffer_status (int dev) -{ - return 0; /* - * No data in buffers - */ -} - -static int -mpu_synth_ioctl (int dev, - unsigned int cmd, unsigned int arg) -{ - int midi_dev; - struct mpu_config *devc; - - midi_dev = synth_devs[dev]->midi_dev; - - if (midi_dev < 0 || midi_dev > num_midis) - return RET_ERROR (ENXIO); - - devc = &dev_conf[midi_dev]; - - switch (cmd) - { - - case SNDCTL_SYNTH_INFO: - IOCTL_TO_USER ((char *) arg, 0, &mpu_synth_info[midi_dev], - sizeof (struct synth_info)); - - return 0; - break; - - case SNDCTL_SYNTH_MEMAVL: - return 0x7fffffff; - break; - - default: - return RET_ERROR (EINVAL); - } -} - -static int -mpu_synth_open (int dev, int mode) -{ - int midi_dev, err; - struct mpu_config *devc; - - midi_dev = synth_devs[dev]->midi_dev; - - if (midi_dev < 0 || midi_dev > num_midis) - { - return RET_ERROR (ENXIO); - } - - devc = &dev_conf[midi_dev]; - - /* - * Verify that the device is really running. - * Some devices (such as Ensoniq SoundScape don't - * work before the on board processor (OBP) is initialized - * by downloadin it's microcode. - */ - - if (!devc->initialized) - { - if (mpu401_status (devc->base) == 0xff) /* Bus float */ - { - printk ("MPU-401: Device not initialized properly\n"); - return RET_ERROR (EIO); - } - reset_mpu401 (devc); - } - - if (devc->opened) - { - printk ("MPU-401: Midi busy\n"); - return RET_ERROR (EBUSY); - } - - devc->mode = MODE_SYNTH; - devc->synthno = dev; - - devc->inputintr = NULL; - irq2dev[devc->irq] = midi_dev; - if (devc->shared_irq == 0) - if ((err = snd_set_irq_handler (devc->irq, mpuintr, midi_devs[midi_dev]->info.name) < 0)) - { - return err; - } - - if (midi_devs[midi_dev]->coproc) - if ((err = midi_devs[midi_dev]->coproc-> - open (midi_devs[midi_dev]->coproc->devc, COPR_MIDI)) < 0) - { - if (devc->shared_irq == 0) - snd_release_irq (devc->irq); - printk ("MPU-401: Can't access coprocessor device\n"); - - return err; - } - - devc->opened = mode; - reset_mpu401 (devc); - - if (mode & OPEN_READ) - { - exec_cmd (midi_dev, 0x8B, 0); /* Enable data in stop mode */ - exec_cmd (midi_dev, 0x34, 0); /* Return timing bytes in stop mode */ - } - - return 0; -} - -static void -mpu_synth_close (int dev) -{ - int midi_dev; - struct mpu_config *devc; - - midi_dev = synth_devs[dev]->midi_dev; - - devc = &dev_conf[midi_dev]; - exec_cmd (midi_dev, 0x15, 0); /* Stop recording, playback and MIDI */ - exec_cmd (midi_dev, 0x8a, 0); /* Disable data in stopped mode */ - - if (devc->shared_irq == 0) - snd_release_irq (devc->irq); - devc->inputintr = NULL; - - if (midi_devs[midi_dev]->coproc) - midi_devs[midi_dev]->coproc->close (midi_devs[midi_dev]->coproc->devc, COPR_MIDI); - devc->opened = 0; - devc->mode = 0; -} - -#define MIDI_SYNTH_NAME "MPU-401 UART Midi" -#define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT -#include <i386/isa/sound/midi_synth.h> - -static struct synth_operations mpu401_synth_proto = -{ - NULL, - 0, - SYNTH_TYPE_MIDI, - 0, - mpu_synth_open, - mpu_synth_close, - mpu_synth_ioctl, - midi_synth_kill_note, - midi_synth_start_note, - midi_synth_set_instr, - midi_synth_reset, - midi_synth_hw_control, - midi_synth_load_patch, - midi_synth_aftertouch, - midi_synth_controller, - midi_synth_panning, - NULL, - midi_synth_patchmgr, - midi_synth_bender, - NULL, /* alloc */ - midi_synth_setup_voice -}; - -static struct synth_operations mpu401_synth_operations[MAX_MIDI_DEV]; - -static struct midi_operations mpu401_midi_proto = -{ - {"MPU-401 Midi", 0, MIDI_CAP_MPU401, SNDCARD_MPU401}, - NULL, - {0}, - mpu401_open, - mpu401_close, - mpu401_ioctl, - mpu401_out, - mpu401_start_read, - mpu401_end_read, - mpu401_kick, - NULL, - mpu401_buffer_status, - mpu401_prefix_cmd -}; - -static struct midi_operations mpu401_midi_operations[MAX_MIDI_DEV]; - -static void -mpu401_chk_version (struct mpu_config *devc) -{ - int tmp; - - devc->version = devc->revision = 0; - - if ((tmp = exec_cmd (num_midis, 0xAC, 0)) < 0) - return; - - if ((tmp & 0xf0) > 0x20) /* Why it's larger than 2.x ??? */ - return; - - devc->version = tmp; - - if ((tmp = exec_cmd (num_midis, 0xAD, 0)) < 0) - { - devc->version = 0; - return; - } - devc->revision = tmp; -} - -long -attach_mpu401 (long mem_start, struct address_info *hw_config) -{ - unsigned long flags; - char revision_char; - - struct mpu_config *devc; - - if (num_midis >= MAX_MIDI_DEV) - { - printk ("MPU-401: Too many midi devices detected\n"); - return mem_start; - } - - devc = &dev_conf[num_midis]; - - devc->base = hw_config->io_base; - devc->irq = hw_config->irq; - devc->opened = 0; - devc->uart_mode = 0; - devc->initialized = 0; - devc->version = 0; - devc->revision = 0; - devc->capabilities = 0; - devc->timer_flag = 0; - devc->m_busy = 0; - devc->m_state = ST_INIT; - devc->shared_irq = hw_config->always_detect; - - if (!hw_config->always_detect) - { - /* Verify the hardware again */ - if (!reset_mpu401 (devc)) - return mem_start; - - DISABLE_INTR (flags); - mpu401_chk_version (devc); - if (devc->version == 0) - mpu401_chk_version (devc); - RESTORE_INTR (flags); - } - - if (devc->version == 0) - { - memcpy ((char *) &mpu401_synth_operations[num_midis], - (char *) &std_midi_synth, - sizeof (struct synth_operations)); - } - else - { - devc->capabilities |= MPU_CAP_INTLG; /* Supports intelligent mode */ - memcpy ((char *) &mpu401_synth_operations[num_midis], - (char *) &mpu401_synth_proto, - sizeof (struct synth_operations)); - } - - memcpy ((char *) &mpu401_midi_operations[num_midis], - (char *) &mpu401_midi_proto, - sizeof (struct midi_operations)); - - mpu401_midi_operations[num_midis].converter = - &mpu401_synth_operations[num_midis]; - - memcpy ((char *) &mpu_synth_info[num_midis], - (char *) &mpu_synth_info_proto, - sizeof (struct synth_info)); - - n_mpu_devs++; - - if (devc->version == 0x20 && devc->revision >= 0x07) /* MusicQuest interface */ - { - int ports = (devc->revision & 0x08) ? 32 : 16; - - devc->capabilities |= MPU_CAP_SYNC | MPU_CAP_SMPTE | - MPU_CAP_CLS | MPU_CAP_2PORT; - - revision_char = (devc->revision == 0x7f) ? 'M' : ' '; -#if defined(__FreeBSD__) - printk ("mpu0: <MQX-%d%c MIDI Interface>", -#else - printk (" <MQX-%d%c MIDI Interface>", -#endif - ports, - revision_char); - sprintf (mpu_synth_info[num_midis].name, - "MQX-%d%c MIDI Interface #%d", - ports, - revision_char, - n_mpu_devs); - } - else - { - - revision_char = devc->revision ? devc->revision + '@' : ' '; - if (devc->revision > ('Z' - '@')) - revision_char = '+'; - - devc->capabilities |= MPU_CAP_SYNC | MPU_CAP_FSK; - -#if defined(__FreeBSD__) - printk ("mpu0: <MPU-401 MIDI Interface %d.%d%c>", -#else - printk (" <MPU-401 MIDI Interface %d.%d%c>", -#endif - (devc->version & 0xf0) >> 4, - devc->version & 0x0f, - revision_char); - sprintf (mpu_synth_info[num_midis].name, - "MPU-401 %d.%d%c Midi interface #%d", - (devc->version & 0xf0) >> 4, - devc->version & 0x0f, - revision_char, - n_mpu_devs); - } - - strcpy (mpu401_midi_operations[num_midis].info.name, - mpu_synth_info[num_midis].name); - - mpu401_synth_operations[num_midis].midi_dev = devc->devno = num_midis; - mpu401_synth_operations[devc->devno].info = - &mpu_synth_info[devc->devno]; - - if (devc->capabilities & MPU_CAP_INTLG) /* Has timer */ - mpu_timer_init (num_midis); - - irq2dev[devc->irq] = num_midis; - midi_devs[num_midis++] = &mpu401_midi_operations[devc->devno]; - return mem_start; -} - -static int -reset_mpu401 (struct mpu_config *devc) -{ - unsigned long flags; - int ok, timeout, n; - int timeout_limit; - - /* - * Send the RESET command. Try again if no success at the first time. - * (If the device is in the UART mode, it will not ack the reset cmd). - */ - - ok = 0; - - timeout_limit = devc->initialized ? 30000 : 100000; - devc->initialized = 1; - - for (n = 0; n < 2 && !ok; n++) - { - for (timeout = timeout_limit; timeout > 0 && !ok; timeout--) - ok = output_ready (devc->base); - - write_command (devc->base, MPU_RESET); /* - * Send MPU-401 RESET Command - */ - - /* - * Wait at least 25 msec. This method is not accurate so let's make the - * loop bit longer. Cannot sleep since this is called during boot. - */ - - for (timeout = timeout_limit * 2; timeout > 0 && !ok; timeout--) - { - DISABLE_INTR (flags); - if (input_avail (devc->base)) - if (read_data (devc->base) == MPU_ACK) - ok = 1; - RESTORE_INTR (flags); - } - - } - - devc->m_state = ST_INIT; - devc->m_ptr = 0; - devc->m_left = 0; - devc->last_status = 0; - devc->uart_mode = 0; - - return ok; -} - -static void -set_uart_mode (int dev, struct mpu_config *devc, int arg) -{ - - if (!arg && devc->version == 0) - { - return; - } - - if ((devc->uart_mode == 0) == (arg == 0)) - { - return; /* Already set */ - } - - reset_mpu401 (devc); /* This exits the uart mode */ - - if (arg) - { - if (exec_cmd (dev, UART_MODE_ON, 0) < 0) - { - printk ("MPU%d: Can't enter UART mode\n", devc->devno); - devc->uart_mode = 0; - return; - } - } - devc->uart_mode = arg; - -} - -int -probe_mpu401 (struct address_info *hw_config) -{ - int ok = 0; - struct mpu_config tmp_devc; - - tmp_devc.base = hw_config->io_base; - tmp_devc.irq = hw_config->irq; - tmp_devc.initialized = 0; - -#if !defined(EXCLUDE_AEDSP16) && defined(AEDSP16_MPU401) - /* - * Initialize Audio Excel DSP 16 to MPU-401, before any operation. - */ - InitAEDSP16_MPU401 (hw_config); -#endif - - if (hw_config->always_detect) - return 1; - - if (INB (hw_config->io_base + 1) == 0xff) - return 0; /* Just bus float? */ - - ok = reset_mpu401 (&tmp_devc); - - return ok; -} - -/***************************************************** - * Timer stuff - ****************************************************/ - -#if !defined(EXCLUDE_SEQUENCER) - -static volatile int timer_initialized = 0, timer_open = 0, tmr_running = 0; -static volatile int curr_tempo, curr_timebase, hw_timebase; -static int max_timebase = 8; /* 8*24=192 ppqn */ -static volatile unsigned long next_event_time; -static volatile unsigned long curr_ticks, curr_clocks; -static unsigned long prev_event_time; -static int metronome_mode; - -static unsigned long -clocks2ticks (unsigned long clocks) -{ - /* - * The MPU-401 supports just a limited set of possible timebase values. - * Since the applications require more choices, the driver has to - * program the HW to do it's best and to convert between the HW and - * actual timebases. - */ - - return ((clocks * curr_timebase) + (hw_timebase / 2)) / hw_timebase; -} - -static void -set_timebase (int midi_dev, int val) -{ - int hw_val; - - if (val < 48) - val = 48; - if (val > 1000) - val = 1000; - - hw_val = val; - hw_val = (hw_val + 23) / 24; - if (hw_val > max_timebase) - hw_val = max_timebase; - - if (exec_cmd (midi_dev, 0xC0 | (hw_val & 0x0f), 0) < 0) - { - printk ("MPU: Can't set HW timebase to %d\n", hw_val * 24); - return; - } - hw_timebase = hw_val * 24; - curr_timebase = val; - -} - -static void -tmr_reset (void) -{ - unsigned long flags; - - DISABLE_INTR (flags); - next_event_time = 0xffffffff; - prev_event_time = 0; - curr_ticks = curr_clocks = 0; - RESTORE_INTR (flags); -} - -static void -set_timer_mode (int midi_dev) -{ - if (timer_mode & TMR_MODE_CLS) - exec_cmd (midi_dev, 0x3c, 0); /* Use CLS sync */ - else if (timer_mode & TMR_MODE_SMPTE) - exec_cmd (midi_dev, 0x3d, 0); /* Use SMPTE sync */ - - if (timer_mode & TMR_INTERNAL) - { - exec_cmd (midi_dev, 0x80, 0); /* Use MIDI sync */ - } - else - { - if (timer_mode & (TMR_MODE_MIDI | TMR_MODE_CLS)) - { - exec_cmd (midi_dev, 0x82, 0); /* Use MIDI sync */ - exec_cmd (midi_dev, 0x91, 0); /* Enable ext MIDI ctrl */ - } - else if (timer_mode & TMR_MODE_FSK) - exec_cmd (midi_dev, 0x81, 0); /* Use FSK sync */ - } -} - -static void -stop_metronome (int midi_dev) -{ - exec_cmd (midi_dev, 0x84, 0); /* Disable metronome */ -} - -static void -setup_metronome (int midi_dev) -{ - int numerator, denominator; - int clks_per_click, num_32nds_per_beat; - int beats_per_measure; - - numerator = ((unsigned) metronome_mode >> 24) & 0xff; - denominator = ((unsigned) metronome_mode >> 16) & 0xff; - clks_per_click = ((unsigned) metronome_mode >> 8) & 0xff; - num_32nds_per_beat = (unsigned) metronome_mode & 0xff; - beats_per_measure = (numerator * 4) >> denominator; - - if (!metronome_mode) - exec_cmd (midi_dev, 0x84, 0); /* Disable metronome */ - else - { - exec_cmd (midi_dev, 0xE4, clks_per_click); - exec_cmd (midi_dev, 0xE6, beats_per_measure); - exec_cmd (midi_dev, 0x83, 0); /* Enable metronome without accents */ - } -} - -static int -start_timer (int midi_dev) -{ - tmr_reset (); - set_timer_mode (midi_dev); - - if (tmr_running) - return TIMER_NOT_ARMED; /* Already running */ - - if (timer_mode & TMR_INTERNAL) - { - exec_cmd (midi_dev, 0x02, 0); /* Send MIDI start */ - tmr_running = 1; - return TIMER_NOT_ARMED; - } - else - { - exec_cmd (midi_dev, 0x35, 0); /* Enable mode messages to PC */ - exec_cmd (midi_dev, 0x38, 0); /* Enable sys common messages to PC */ - exec_cmd (midi_dev, 0x39, 0); /* Enable real time messages to PC */ - exec_cmd (midi_dev, 0x97, 0); /* Enable system exclusive messages to PC */ - } - - return TIMER_ARMED; -} - -static int -mpu_timer_open (int dev, int mode) -{ - int midi_dev = sound_timer_devs[dev]->devlink; - - if (timer_open) - return RET_ERROR (EBUSY); - - tmr_reset (); - curr_tempo = 50; - exec_cmd (midi_dev, 0xE0, 50); - curr_timebase = hw_timebase = 120; - set_timebase (midi_dev, 120); - timer_open = 1; - metronome_mode = 0; - set_timer_mode (midi_dev); - - exec_cmd (midi_dev, 0xe7, 0x04); /* Send all clocks to host */ - exec_cmd (midi_dev, 0x95, 0); /* Enable clock to host */ - - return 0; -} - -static void -mpu_timer_close (int dev) -{ - int midi_dev = sound_timer_devs[dev]->devlink; - - timer_open = tmr_running = 0; - exec_cmd (midi_dev, 0x15, 0); /* Stop all */ - exec_cmd (midi_dev, 0x94, 0); /* Disable clock to host */ - exec_cmd (midi_dev, 0x8c, 0); /* Disable measure end messages to host */ - stop_metronome (midi_dev); -} - -static int -mpu_timer_event (int dev, unsigned char *event) -{ - unsigned char command = event[1]; - unsigned long parm = *(unsigned int *) &event[4]; - int midi_dev = sound_timer_devs[dev]->devlink; - - switch (command) - { - case TMR_WAIT_REL: - parm += prev_event_time; - case TMR_WAIT_ABS: - if (parm > 0) - { - long time; - - if (parm <= curr_ticks) /* It's the time */ - return TIMER_NOT_ARMED; - - time = parm; - next_event_time = prev_event_time = time; - - return TIMER_ARMED; - } - break; - - case TMR_START: - if (tmr_running) - break; - return start_timer (midi_dev); - break; - - case TMR_STOP: - exec_cmd (midi_dev, 0x01, 0); /* Send MIDI stop */ - stop_metronome (midi_dev); - tmr_running = 0; - break; - - case TMR_CONTINUE: - if (tmr_running) - break; - exec_cmd (midi_dev, 0x03, 0); /* Send MIDI continue */ - setup_metronome (midi_dev); - tmr_running = 1; - break; - - case TMR_TEMPO: - if (parm) - { - if (parm < 8) - parm = 8; - if (parm > 250) - parm = 250; - - if (exec_cmd (midi_dev, 0xE0, parm) < 0) - printk ("MPU: Can't set tempo to %d\n", (int) parm); - curr_tempo = parm; - } - break; - - case TMR_ECHO: - seq_copy_to_input (event, 8); - break; - - case TMR_TIMESIG: - if (metronome_mode) /* Metronome enabled */ - { - metronome_mode = parm; - setup_metronome (midi_dev); - } - break; - - default:; - } - - return TIMER_NOT_ARMED; -} - -static unsigned long -mpu_timer_get_time (int dev) -{ - if (!timer_open) - return 0; - - return curr_ticks; -} - -static int -mpu_timer_ioctl (int dev, - unsigned int command, unsigned int arg) -{ - int midi_dev = sound_timer_devs[dev]->devlink; - - switch (command) - { - case SNDCTL_TMR_SOURCE: - { - int parm = IOCTL_IN (arg) & timer_caps; - - if (parm != 0) - { - timer_mode = parm; - - if (timer_mode & TMR_MODE_CLS) - exec_cmd (midi_dev, 0x3c, 0); /* Use CLS sync */ - else if (timer_mode & TMR_MODE_SMPTE) - exec_cmd (midi_dev, 0x3d, 0); /* Use SMPTE sync */ - } - - return IOCTL_OUT (arg, timer_mode); - } - break; - - case SNDCTL_TMR_START: - start_timer (midi_dev); - return 0; - break; - - case SNDCTL_TMR_STOP: - tmr_running = 0; - exec_cmd (midi_dev, 0x01, 0); /* Send MIDI stop */ - stop_metronome (midi_dev); - return 0; - break; - - case SNDCTL_TMR_CONTINUE: - if (tmr_running) - return 0; - tmr_running = 1; - exec_cmd (midi_dev, 0x03, 0); /* Send MIDI continue */ - return 0; - break; - - case SNDCTL_TMR_TIMEBASE: - { - int val = IOCTL_IN (arg); - - if (val) - set_timebase (midi_dev, val); - - return IOCTL_OUT (arg, curr_timebase); - } - break; - - case SNDCTL_TMR_TEMPO: - { - int val = IOCTL_IN (arg); - int ret; - - if (val) - { - if (val < 8) - val = 8; - if (val > 250) - val = 250; - if ((ret = exec_cmd (midi_dev, 0xE0, val)) < 0) - { - printk ("MPU: Can't set tempo to %d\n", (int) val); - return ret; - } - - curr_tempo = val; - } - - return IOCTL_OUT (arg, curr_tempo); - } - break; - - case SNDCTL_SEQ_CTRLRATE: - if (IOCTL_IN (arg) != 0) /* Can't change */ - return RET_ERROR (EINVAL); - - return IOCTL_OUT (arg, ((curr_tempo * curr_timebase) + 30) / 60); - break; - - case SNDCTL_TMR_METRONOME: - metronome_mode = IOCTL_IN (arg); - setup_metronome (midi_dev); - return 0; - break; - - default: - } - - return RET_ERROR (EINVAL); -} - -static void -mpu_timer_arm (int dev, long time) -{ - if (time < 0) - time = curr_ticks + 1; - else if (time <= curr_ticks) /* It's the time */ - return; - - next_event_time = prev_event_time = time; - - return; -} - -static struct sound_timer_operations mpu_timer = -{ - {"MPU-401 Timer", 0}, - 10, /* Priority */ - 0, /* Local device link */ - mpu_timer_open, - mpu_timer_close, - mpu_timer_event, - mpu_timer_get_time, - mpu_timer_ioctl, - mpu_timer_arm -}; - -static void -mpu_timer_interrupt (void) -{ - - if (!timer_open) - return; - - if (!tmr_running) - return; - - curr_clocks++; - curr_ticks = clocks2ticks (curr_clocks); - - if (curr_ticks >= next_event_time) - { - next_event_time = 0xffffffff; - sequencer_timer (); - } -} - -static void -timer_ext_event (struct mpu_config *devc, int event, int parm) -{ - int midi_dev = devc->devno; - - if (!devc->timer_flag) - return; - - switch (event) - { - case TMR_CLOCK: - printk ("<MIDI clk>"); - break; - - case TMR_START: - printk ("Ext MIDI start\n"); - if (!tmr_running) - if (timer_mode & TMR_EXTERNAL) - { - tmr_running = 1; - setup_metronome (midi_dev); - next_event_time = 0; - STORE (SEQ_START_TIMER ()); - } - break; - - case TMR_STOP: - printk ("Ext MIDI stop\n"); - if (timer_mode & TMR_EXTERNAL) - { - tmr_running = 0; - stop_metronome (midi_dev); - STORE (SEQ_STOP_TIMER ()); - } - break; - - case TMR_CONTINUE: - printk ("Ext MIDI continue\n"); - if (timer_mode & TMR_EXTERNAL) - { - tmr_running = 1; - setup_metronome (midi_dev); - STORE (SEQ_CONTINUE_TIMER ()); - } - break; - - case TMR_SPP: - printk ("Songpos: %d\n", parm); - if (timer_mode & TMR_EXTERNAL) - { - STORE (SEQ_SONGPOS (parm)); - } - break; - } -} - -static void -mpu_timer_init (int midi_dev) -{ - struct mpu_config *devc; - int n; - - devc = &dev_conf[midi_dev]; - - if (timer_initialized) - return; /* There is already a similar timer */ - - timer_initialized = 1; - - mpu_timer.devlink = midi_dev; - dev_conf[midi_dev].timer_flag = 1; - -#if 1 - if (num_sound_timers >= MAX_TIMER_DEV) - n = 0; /* Overwrite the system timer */ - else - n = num_sound_timers++; -#else - n = 0; -#endif - sound_timer_devs[n] = &mpu_timer; - - if (devc->version < 0x20) /* Original MPU-401 */ - timer_caps = TMR_INTERNAL | TMR_EXTERNAL | TMR_MODE_FSK | TMR_MODE_MIDI; - else - { - /* - * The version number 2.0 is used (at least) by the - * MusicQuest cards and the Roland Super-MPU. - * - * MusicQuest has given a special meaning to the bits of the - * revision number. The Super-MPU returns 0. - */ - - if (devc->revision) - timer_caps |= TMR_EXTERNAL | TMR_MODE_MIDI; - - if (devc->revision & 0x02) - timer_caps |= TMR_MODE_CLS; - -#if 0 - if (devc->revision & 0x04) - timer_caps |= TMR_MODE_SMPTE; -#endif - - if (devc->revision & 0x40) - max_timebase = 10; /* Has the 216 and 240 ppqn modes */ - } - - timer_mode = (TMR_INTERNAL | TMR_MODE_MIDI) & timer_caps; - -} - -#endif - -#endif - -#endif diff --git a/sys/pc98/pc98/sound/opl3.c b/sys/pc98/pc98/sound/opl3.c index 749e38f..42379cd 100644 --- a/sys/pc98/pc98/sound/opl3.c +++ b/sys/pc98/pc98/sound/opl3.c @@ -34,11 +34,7 @@ * hooft@chem.ruu.nl */ -#ifdef PC98 -#include <pc98/pc98/sound/sound_config.h> -#else #include <i386/isa/sound/sound_config.h> -#endif #if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_YM3812) diff --git a/sys/pc98/pc98/sound/pas2_card.c b/sys/pc98/pc98/sound/pas2_card.c deleted file mode 100644 index eeff8ae..0000000 --- a/sys/pc98/pc98/sound/pas2_card.c +++ /dev/null @@ -1,420 +0,0 @@ -#define _PAS2_CARD_C_ -/* - * sound/pas2_card.c - * - * Detection routine for the Pro Audio Spectrum cards. - * - * Copyright by Hannu Savolainen 1993 - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. 2. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#include <i386/isa/sound/sound_config.h> - -#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_PAS) - -#define DEFINE_TRANSLATIONS -#include <i386/isa/sound/pas.h> - -static int config_pas_hw __P((struct address_info *hw_config)); -static int detect_pas_hw __P((struct address_info *hw_config)); -static void pas2_msg __P((char *foo)); - -/* - * The Address Translation code is used to convert I/O register addresses to - * be relative to the given base -register - */ - -int translat_code; -static int pas_intr_mask = 0; -static int pas_irq = 0; - -char pas_model; -static char *pas_model_names[] = -{"", "Pro AudioSpectrum+", "CDPC", "Pro AudioSpectrum 16", "Pro AudioSpectrum 16D"}; - -extern void mix_write (unsigned char data, int ioaddr); -/* - * pas_read() and pas_write() are equivalents of INB() and OUTB() - */ -/* - * These routines perform the I/O address translation required - */ -/* - * to support other than the default base address - */ - -unsigned char -pas_read (int ioaddr) -{ - return INB (ioaddr ^ translat_code); -} - -void -pas_write (unsigned char data, int ioaddr) -{ - OUTB (data, ioaddr ^ translat_code); -} - -static void -pas2_msg (char *foo) -{ - printk (" PAS2: %s.\n", foo); -} - -/******************* Begin of the Interrupt Handler ********************/ - -void -pasintr (INT_HANDLER_PARMS (irq, dummy)) -{ - int status; - - status = pas_read (INTERRUPT_STATUS); - pas_write (status, INTERRUPT_STATUS); /* - * Clear interrupt - */ - - if (status & I_S_PCM_SAMPLE_BUFFER_IRQ) - { -#ifndef EXCLUDE_AUDIO - pas_pcm_interrupt (status, 1); -#endif - status &= ~I_S_PCM_SAMPLE_BUFFER_IRQ; - } - if (status & I_S_MIDI_IRQ) - { -#ifndef EXCLUDE_MIDI -#ifdef EXCLUDE_PRO_MIDI - pas_midi_interrupt (); -#endif -#endif - status &= ~I_S_MIDI_IRQ; - } - -} - -int -pas_set_intr (int mask) -{ - int err; - - if (!mask) - return 0; - - if (!pas_intr_mask) - { - if ((err = snd_set_irq_handler (pas_irq, pasintr, "PAS16")) < 0) - return err; - } - pas_intr_mask |= mask; - - pas_write (pas_intr_mask, INTERRUPT_MASK); - return 0; -} - -int -pas_remove_intr (int mask) -{ - if (!mask) - return 0; - - pas_intr_mask &= ~mask; - pas_write (pas_intr_mask, INTERRUPT_MASK); - - if (!pas_intr_mask) - { - snd_release_irq (pas_irq); - } - return 0; -} - -/******************* End of the Interrupt handler **********************/ - -/******************* Begin of the Initialization Code ******************/ - -static int -config_pas_hw (struct address_info *hw_config) -{ - char ok = 1; - unsigned int_ptrs; /* scsi/sound interrupt pointers */ - - pas_irq = hw_config->irq; - - pas_write (0x00, INTERRUPT_MASK); - - pas_write (0x36, SAMPLE_COUNTER_CONTROL); /* - * Local timer control * - * register - */ - - pas_write (0x36, SAMPLE_RATE_TIMER); /* - * Sample rate timer (16 bit) - */ - pas_write (0, SAMPLE_RATE_TIMER); - - pas_write (0x74, SAMPLE_COUNTER_CONTROL); /* - * Local timer control * - * register - */ - - pas_write (0x74, SAMPLE_BUFFER_COUNTER); /* - * Sample count register (16 - * * bit) - */ - pas_write (0, SAMPLE_BUFFER_COUNTER); - - pas_write (F_F_PCM_BUFFER_COUNTER | F_F_PCM_RATE_COUNTER | F_F_MIXER_UNMUTE | 1, FILTER_FREQUENCY); - pas_write (P_C_PCM_DMA_ENABLE | P_C_PCM_MONO | P_C_PCM_DAC_MODE | P_C_MIXER_CROSS_L_TO_L | P_C_MIXER_CROSS_R_TO_R, PCM_CONTROL); - pas_write (S_M_PCM_RESET | S_M_FM_RESET | S_M_SB_RESET | S_M_MIXER_RESET /* - * | - * S_M_OPL3_DUAL_MONO - */ , SERIAL_MIXER); - - pas_write (I_C_1_BOOT_RESET_ENABLE -#ifdef PAS_JOYSTICK_ENABLE - | I_C_1_JOYSTICK_ENABLE -#endif - ,IO_CONFIGURATION_1); - - if (pas_irq < 0 || pas_irq > 15) - { - printk ("PAS2: Invalid IRQ %d", pas_irq); - ok = 0; - } - else - { - int_ptrs = pas_read (IO_CONFIGURATION_3); - int_ptrs |= I_C_3_PCM_IRQ_translate[pas_irq] & 0xf; - pas_write (int_ptrs, IO_CONFIGURATION_3); - if (!I_C_3_PCM_IRQ_translate[pas_irq]) - { - printk ("PAS2: Invalid IRQ %d", pas_irq); - ok = 0; - } - } - - if (hw_config->dma < 0 || hw_config->dma > 7) - { - printk ("PAS2: Invalid DMA selection %d", hw_config->dma); - ok = 0; - } - else - { - pas_write (I_C_2_PCM_DMA_translate[hw_config->dma], IO_CONFIGURATION_2); - if (!I_C_2_PCM_DMA_translate[hw_config->dma]) - { - printk ("PAS2: Invalid DMA selection %d", hw_config->dma); - ok = 0; - } - } - - /* - * This fixes the timing problems of the PAS due to the Symphony chipset - * as per Media Vision. Only define this if your PAS doesn't work correctly. - */ -#ifdef SYMPHONY_PAS - OUTB (0x05, 0xa8); - OUTB (0x60, 0xa9); -#endif - -#ifdef BROKEN_BUS_CLOCK - pas_write (S_C_1_PCS_ENABLE | S_C_1_PCS_STEREO | S_C_1_PCS_REALSOUND | S_C_1_FM_EMULATE_CLOCK, SYSTEM_CONFIGURATION_1); -#else - /* - * pas_write(S_C_1_PCS_ENABLE, SYSTEM_CONFIGURATION_1); - */ - pas_write (S_C_1_PCS_ENABLE | S_C_1_PCS_STEREO | S_C_1_PCS_REALSOUND, SYSTEM_CONFIGURATION_1); -#endif - pas_write (0x18, SYSTEM_CONFIGURATION_3); /* - * ??? - */ - - pas_write (F_F_MIXER_UNMUTE | 0x01, FILTER_FREQUENCY); /* - * Sets mute - * off and * - * selects - * filter - * rate * of - * 17.897 kHz - */ - - if (pas_model == PAS_16 || pas_model == PAS_16D) - pas_write (8, PRESCALE_DIVIDER); - else - pas_write (0, PRESCALE_DIVIDER); - - mix_write (P_M_MV508_ADDRESS | 5, PARALLEL_MIXER); - mix_write (5, PARALLEL_MIXER); - -#if !defined(EXCLUDE_SB_EMULATION) || !defined(EXCLUDE_SB) - - { - struct address_info *sb_config; - - if ((sb_config = sound_getconf (SNDCARD_SB))) - { - unsigned char irq_dma; - - /* - * Turn on Sound Blaster compatibility - */ - /* - * bit 1 = SB emulation - */ - /* - * bit 0 = MPU401 emulation (CDPC only :-( ) - */ - pas_write (0x02, COMPATIBILITY_ENABLE); - - /* - * "Emulation address" - */ - pas_write ((sb_config->io_base >> 4) & 0x0f, EMULATION_ADDRESS); - - if (!E_C_SB_DMA_translate[sb_config->dma]) - printk ("\n\nPAS16 Warning: Invalid SB DMA %d\n\n", - sb_config->dma); - - if (!E_C_SB_IRQ_translate[sb_config->irq]) - printk ("\n\nPAS16 Warning: Invalid SB IRQ %d\n\n", - sb_config->irq); - - irq_dma = E_C_SB_DMA_translate[sb_config->dma] | - E_C_SB_IRQ_translate[sb_config->irq]; - - pas_write (irq_dma, EMULATION_CONFIGURATION); - } - } -#endif - - if (!ok) - pas2_msg ("Driver not enabled"); - - return ok; -} - -static int -detect_pas_hw (struct address_info *hw_config) -{ - unsigned char board_id, foo; - - /* - * WARNING: Setting an option like W:1 or so that disables warm boot reset - * of the card will screw up this detect code something fierce. Adding code - * to handle this means possibly interfering with other cards on the bus if - * you have something on base port 0x388. SO be forewarned. - */ - - OUTB (0xBC, MASTER_DECODE); /* - * Talk to first board - */ - OUTB (hw_config->io_base >> 2, MASTER_DECODE); /* - * Set base address - */ - translat_code = PAS_DEFAULT_BASE ^ hw_config->io_base; - pas_write (1, WAIT_STATE); /* - * One wait-state - */ - - board_id = pas_read (INTERRUPT_MASK); - - if (board_id == 0xff) - return 0; - - /* - * We probably have a PAS-series board, now check for a PAS2-series board - * by trying to change the board revision bits. PAS2-series hardware won't - * let you do this - the bits are read-only. - */ - - foo = board_id ^ 0xe0; - - pas_write (foo, INTERRUPT_MASK); - foo = INB (INTERRUPT_MASK); - pas_write (board_id, INTERRUPT_MASK); - - if (board_id != foo) /* - * Not a PAS2 - */ - return 0; - - pas_model = pas_read (CHIP_REV); - - return pas_model; -} - -long -attach_pas_card (long mem_start, struct address_info *hw_config) -{ - pas_irq = hw_config->irq; - - if (detect_pas_hw (hw_config)) - { - - if (pas_model = pas_read (CHIP_REV)) - { -#ifdef __FreeBSD__ - printk ("pas0: <%s rev %d>", pas_model_names[(int) pas_model], pas_read (BOARD_REV_ID)); -#else - printk (" <%s rev %d>", pas_model_names[(int) pas_model], pas_read (BOARD_REV_ID)); -#endif - } - - if (config_pas_hw (hw_config)) - { - -#ifndef EXCLUDE_AUDIO - mem_start = pas_pcm_init (mem_start, hw_config); -#endif - -#if !defined(EXCLUDE_SB_EMULATION) && !defined(EXCLUDE_SB) - - sb_dsp_disable_midi (); /* - * The SB emulation don't support * - * midi - */ -#endif - -#ifndef EXCLUDE_YM3812 - enable_opl3_mode (0x388, 0x38a, 0); -#endif - -#ifndef EXCLUDE_MIDI -#ifdef EXCLUDE_PRO_MIDI - mem_start = pas_midi_init (mem_start); -#endif -#endif - - pas_init_mixer (); - } - } - - return mem_start; -} - -int -probe_pas (struct address_info *hw_config) -{ - return detect_pas_hw (hw_config); -} - -#endif diff --git a/sys/pc98/pc98/sound/pas2_midi.c b/sys/pc98/pc98/sound/pas2_midi.c deleted file mode 100644 index a83158e..0000000 --- a/sys/pc98/pc98/sound/pas2_midi.c +++ /dev/null @@ -1,341 +0,0 @@ -/* - * sound/pas2_midi.c - * - * The low level driver for the PAS Midi Interface. - * - * Copyright by Hannu Savolainen 1993 - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. 2. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#include <i386/isa/sound/sound_config.h> - -#ifdef CONFIGURE_SOUNDCARD - -#include <i386/isa/sound/pas.h> - -#if !defined(EXCLUDE_PAS) && !defined(EXCLUDE_MIDI) && defined(EXCLUDE_PRO_MIDI) - -static int midi_busy = 0, input_opened = 0; -static int my_dev; -static volatile int ofifo_bytes = 0; - -static unsigned char tmp_queue[256]; -static volatile int qlen; -static volatile unsigned char qhead, qtail; - -static void (*midi_input_intr) (int dev, unsigned char data); - -static int -pas_midi_open (int dev, int mode, - void (*input) (int dev, unsigned char data), - void (*output) (int dev) -) -{ - int err; - unsigned long flags; - unsigned char ctrl; - - - if (midi_busy) - { - printk ("PAS2: Midi busy\n"); - return RET_ERROR (EBUSY); - } - - /* - * Reset input and output FIFO pointers - */ - pas_write (M_C_RESET_INPUT_FIFO | M_C_RESET_OUTPUT_FIFO, - MIDI_CONTROL); - - DISABLE_INTR (flags); - - if ((err = pas_set_intr (I_M_MIDI_IRQ_ENABLE)) < 0) - return err; - - /* - * Enable input available and output FIFO empty interrupts - */ - - ctrl = 0; - input_opened = 0; - midi_input_intr = input; - - if (mode == OPEN_READ || mode == OPEN_READWRITE) - { - ctrl |= M_C_ENA_INPUT_IRQ; /* - * Enable input - */ - input_opened = 1; - } - - if (mode == OPEN_WRITE || mode == OPEN_READWRITE) - { - ctrl |= M_C_ENA_OUTPUT_IRQ | /* - * Enable output - */ - M_C_ENA_OUTPUT_HALF_IRQ; - } - - pas_write (ctrl, - MIDI_CONTROL); - - /* - * Acknowledge any pending interrupts - */ - - pas_write (0xff, MIDI_STATUS); - ofifo_bytes = 0; - - RESTORE_INTR (flags); - - midi_busy = 1; - qlen = qhead = qtail = 0; - return 0; -} - -static void -pas_midi_close (int dev) -{ - - /* - * Reset FIFO pointers, disable intrs - */ - pas_write (M_C_RESET_INPUT_FIFO | M_C_RESET_OUTPUT_FIFO, MIDI_CONTROL); - - pas_remove_intr (I_M_MIDI_IRQ_ENABLE); - midi_busy = 0; -} - -static int -dump_to_midi (unsigned char midi_byte) -{ - int fifo_space, x; - - fifo_space = ((x = pas_read (MIDI_FIFO_STATUS)) >> 4) & 0x0f; - - if (fifo_space == 15 || (fifo_space < 2 && ofifo_bytes > 13)) /* - * Fifo - * full - */ - { - return 0; /* - * Upper layer will call again - */ - } - - ofifo_bytes++; - - pas_write (midi_byte, MIDI_DATA); - - return 1; -} - -static int -pas_midi_out (int dev, unsigned char midi_byte) -{ - - unsigned long flags; - - /* - * Drain the local queue first - */ - - DISABLE_INTR (flags); - - while (qlen && dump_to_midi (tmp_queue[qhead])) - { - qlen--; - qhead++; - } - - RESTORE_INTR (flags); - - /* - * Output the byte if the local queue is empty. - */ - - if (!qlen) - if (dump_to_midi (midi_byte)) - return 1; /* - * OK - */ - - /* - * Put to the local queue - */ - - if (qlen >= 256) - return 0; /* - * Local queue full - */ - - DISABLE_INTR (flags); - - tmp_queue[qtail] = midi_byte; - qlen++; - qtail++; - - RESTORE_INTR (flags); - - return 1; -} - -static int -pas_midi_start_read (int dev) -{ - return 0; -} - -static int -pas_midi_end_read (int dev) -{ - return 0; -} - -static int -pas_midi_ioctl (int dev, unsigned cmd, unsigned arg) -{ - return RET_ERROR (EINVAL); -} - -static void -pas_midi_kick (int dev) -{ - ofifo_bytes = 0; -} - -static int -pas_buffer_status (int dev) -{ - return !qlen; -} - -#define MIDI_SYNTH_NAME "Pro Audio Spectrum Midi" -#define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT -#include <i386/isa/sound/midi_synth.h> - -static struct midi_operations pas_midi_operations = -{ - {"Pro Audio Spectrum", 0, 0, SNDCARD_PAS}, - &std_midi_synth, - {0}, - pas_midi_open, - pas_midi_close, - pas_midi_ioctl, - pas_midi_out, - pas_midi_start_read, - pas_midi_end_read, - pas_midi_kick, - NULL, /* - * command - */ - pas_buffer_status, - NULL -}; - -long -pas_midi_init (long mem_start) -{ - if (num_midis >= MAX_MIDI_DEV) - { - printk ("Sound: Too many midi devices detected\n"); - return mem_start; - } - - std_midi_synth.midi_dev = my_dev = num_midis; - midi_devs[num_midis++] = &pas_midi_operations; - return mem_start; -} - -void -pas_midi_interrupt (void) -{ - unsigned char stat; - int i, incount; - unsigned long flags; - - stat = pas_read (MIDI_STATUS); - - if (stat & M_S_INPUT_AVAIL) /* - * Input byte available - */ - { - incount = pas_read (MIDI_FIFO_STATUS) & 0x0f; /* - * Input FIFO count - */ - if (!incount) - incount = 16; - - for (i = 0; i < incount; i++) - if (input_opened) - { - midi_input_intr (my_dev, pas_read (MIDI_DATA)); - } - else - pas_read (MIDI_DATA); /* - * Flush - */ - } - - if (stat & (M_S_OUTPUT_EMPTY | M_S_OUTPUT_HALF_EMPTY)) - { - if (!(stat & M_S_OUTPUT_EMPTY)) - { - ofifo_bytes = 8; - } - else - { - ofifo_bytes = 0; - } - - DISABLE_INTR (flags); - - while (qlen && dump_to_midi (tmp_queue[qhead])) - { - qlen--; - qhead++; - } - - RESTORE_INTR (flags); - } - -#if 0 - if (stat & M_S_FRAMING_ERROR) - printk ("MIDI framing error\n"); -#endif - - if (stat & M_S_OUTPUT_OVERRUN) - { - printk ("MIDI output overrun %x,%x,%d \n", pas_read (MIDI_FIFO_STATUS), stat, ofifo_bytes); - ofifo_bytes = 100; - } - - pas_write (stat, MIDI_STATUS); /* - * Acknowledge interrupts - */ -} - -#endif - -#endif diff --git a/sys/pc98/pc98/sound/pas2_mixer.c b/sys/pc98/pc98/sound/pas2_mixer.c deleted file mode 100644 index c1ba76b..0000000 --- a/sys/pc98/pc98/sound/pas2_mixer.c +++ /dev/null @@ -1,340 +0,0 @@ -#define _PAS2_MIXER_C_ - -/* - * sound/pas2_mixer.c - * - * Mixer routines for the Pro Audio Spectrum cards. - * - * Copyright by Hannu Savolainen 1993 - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. 2. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#include <i386/isa/sound/sound_config.h> - -#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_PAS) - -#include <i386/isa/sound/pas.h> - -extern void mix_write __P((unsigned char data, int ioaddr)); -static int pas_mixer_ioctl __P((int dev, unsigned int cmd, unsigned int arg)); -static void set_mode __P((int new_mode)); - -#define TRACE(what) /* (what) */ - -extern int translat_code; -extern char pas_model; - -static int rec_devices = (SOUND_MASK_MIC); /* Default recording source */ -static int mode_control = 0; - -#define POSSIBLE_RECORDING_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_SPEAKER | SOUND_MASK_LINE | SOUND_MASK_MIC | \ - SOUND_MASK_CD | SOUND_MASK_ALTPCM) - -#define SUPPORTED_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_SPEAKER | SOUND_MASK_LINE | SOUND_MASK_MIC | \ - SOUND_MASK_CD | SOUND_MASK_ALTPCM | SOUND_MASK_IMIX | \ - SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE | SOUND_MASK_RECLEV | \ - SOUND_MASK_MUTE | SOUND_MASK_ENHANCE | SOUND_MASK_LOUD) - -static unsigned short levels[SOUND_MIXER_NRDEVICES] = -{ - 0x3232, /* Master Volume */ - 0x3232, /* Bass */ - 0x3232, /* Treble */ - 0x5050, /* FM */ - 0x4b4b, /* PCM */ - 0x3232, /* PC Speaker */ - 0x4b4b, /* Ext Line */ - 0x4b4b, /* Mic */ - 0x4b4b, /* CD */ - 0x6464, /* Recording monitor */ - 0x4b4b, /* SB PCM */ - 0x6464 /* Recording level */ -}; - -void -mix_write (unsigned char data, int ioaddr) -{ - /* - * The Revision D cards have a problem with their MVA508 interface. The - * kludge-o-rama fix is to make a 16-bit quantity with identical LSB and - * MSBs out of the output byte and to do a 16-bit out to the mixer port - - * 1. We need to do this because it isn't timing problem but chip access - * sequence problem. - */ - - if (pas_model == PAS_16D) - { - OUTW (data | (data << 8), (ioaddr ^ translat_code) - 1); - OUTB (0x80, 0); - } - else - pas_write (data, ioaddr); -} - -static int -mixer_output (int right_vol, int left_vol, int div, int bits, - int mixer) /* Input or output mixer */ -{ - int left = left_vol * div / 100; - int right = right_vol * div / 100; - - - if (bits & P_M_MV508_MIXER) - { /* - * Select input or output mixer - */ - left |= mixer; - right |= mixer; - } - - if (bits == P_M_MV508_BASS || bits == P_M_MV508_TREBLE) - { /* - * Bass and treble are mono devices - */ - mix_write (P_M_MV508_ADDRESS | bits, PARALLEL_MIXER); - mix_write (left, PARALLEL_MIXER); - right_vol = left_vol; - } - else - { - mix_write (P_M_MV508_ADDRESS | P_M_MV508_LEFT | bits, PARALLEL_MIXER); - mix_write (left, PARALLEL_MIXER); - mix_write (P_M_MV508_ADDRESS | P_M_MV508_RIGHT | bits, PARALLEL_MIXER); - mix_write (right, PARALLEL_MIXER); - } - - return (left_vol | (right_vol << 8)); -} - -static void -set_mode (int new_mode) -{ - mix_write (P_M_MV508_ADDRESS | P_M_MV508_MODE, PARALLEL_MIXER); - mix_write (new_mode, PARALLEL_MIXER); - - mode_control = new_mode; -} - -static int -pas_mixer_set (int whichDev, unsigned int level) -{ - int left, right, devmask, changed, i, mixer = 0; - - TRACE (printk ("static int pas_mixer_set(int whichDev = %d, unsigned int level = %X)\n", whichDev, level)); - - left = level & 0x7f; - right = (level & 0x7f00) >> 8; - - if (whichDev < SOUND_MIXER_NRDEVICES) - if ((1 << whichDev) & rec_devices) - mixer = P_M_MV508_INPUTMIX; - else - mixer = P_M_MV508_OUTPUTMIX; - - switch (whichDev) - { - case SOUND_MIXER_VOLUME: /* Master volume (0-63) */ - levels[whichDev] = mixer_output (right, left, 63, P_M_MV508_MASTER_A, 0); - break; - - /* - * Note! Bass and Treble are mono devices. Will use just the left - * channel. - */ - case SOUND_MIXER_BASS: /* Bass (0-12) */ - levels[whichDev] = mixer_output (right, left, 12, P_M_MV508_BASS, 0); - break; - case SOUND_MIXER_TREBLE: /* Treble (0-12) */ - levels[whichDev] = mixer_output (right, left, 12, P_M_MV508_TREBLE, 0); - break; - - case SOUND_MIXER_SYNTH: /* Internal synthesizer (0-31) */ - levels[whichDev] = mixer_output (right, left, 31, P_M_MV508_MIXER | P_M_MV508_FM, mixer); - break; - case SOUND_MIXER_PCM: /* PAS PCM (0-31) */ - levels[whichDev] = mixer_output (right, left, 31, P_M_MV508_MIXER | P_M_MV508_PCM, mixer); - break; - case SOUND_MIXER_ALTPCM: /* SB PCM (0-31) */ - levels[whichDev] = mixer_output (right, left, 31, P_M_MV508_MIXER | P_M_MV508_SB, mixer); - break; - case SOUND_MIXER_SPEAKER: /* PC speaker (0-31) */ - levels[whichDev] = mixer_output (right, left, 31, P_M_MV508_MIXER | P_M_MV508_SPEAKER, mixer); - break; - case SOUND_MIXER_LINE: /* External line (0-31) */ - levels[whichDev] = mixer_output (right, left, 31, P_M_MV508_MIXER | P_M_MV508_LINE, mixer); - break; - case SOUND_MIXER_CD: /* CD (0-31) */ - levels[whichDev] = mixer_output (right, left, 31, P_M_MV508_MIXER | P_M_MV508_CDROM, mixer); - break; - case SOUND_MIXER_MIC: /* External microphone (0-31) */ - levels[whichDev] = mixer_output (right, left, 31, P_M_MV508_MIXER | P_M_MV508_MIC, mixer); - break; - case SOUND_MIXER_IMIX: /* Recording monitor (0-31) (Output mixer only) */ - levels[whichDev] = mixer_output (right, left, 31, P_M_MV508_MIXER | P_M_MV508_IMIXER, - P_M_MV508_OUTPUTMIX); - break; - case SOUND_MIXER_RECLEV: /* Recording level (0-15) */ - levels[whichDev] = mixer_output (right, left, 15, P_M_MV508_MASTER_B, 0); - break; - - case SOUND_MIXER_MUTE: - return 0; - break; - - case SOUND_MIXER_ENHANCE: - i = 0; - level &= 0x7f; - if (level) - i = (level / 20) - 1; - - mode_control &= ~P_M_MV508_ENHANCE_BITS; - mode_control |= P_M_MV508_ENHANCE_BITS; - set_mode (mode_control); - - if (i) - i = (i + 1) * 20; - return i; - break; - - case SOUND_MIXER_LOUD: - mode_control &= ~P_M_MV508_LOUDNESS; - if (level) - mode_control |= P_M_MV508_LOUDNESS; - set_mode (mode_control); - return !!level; /* 0 or 1 */ - break; - - case SOUND_MIXER_RECSRC: - devmask = level & POSSIBLE_RECORDING_DEVICES; - - changed = devmask ^ rec_devices; - rec_devices = devmask; - - for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) - if (changed & (1 << i)) - { - pas_mixer_set (i, levels[i]); - } - return rec_devices; - break; - - default: - return RET_ERROR (EINVAL); - } - - return (levels[whichDev]); -} - -/*****/ - -static void -pas_mixer_reset (void) -{ - int foo; - - TRACE (printk ("pas2_mixer.c: void pas_mixer_reset(void)\n")); - - for (foo = 0; foo < SOUND_MIXER_NRDEVICES; foo++) - pas_mixer_set (foo, levels[foo]); - - set_mode (P_M_MV508_LOUDNESS | P_M_MV508_ENHANCE_40); -} - -int -pas_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg) -{ - TRACE (printk ("pas2_mixer.c: int pas_mixer_ioctl(unsigned int cmd = %X, unsigned int arg = %X)\n", cmd, arg)); - - if (((cmd >> 8) & 0xff) == 'M') - { - if (cmd & IOC_IN) - return IOCTL_OUT (arg, pas_mixer_set (cmd & 0xff, IOCTL_IN (arg))); - else - { /* - * Read parameters - */ - - switch (cmd & 0xff) - { - - case SOUND_MIXER_RECSRC: - return IOCTL_OUT (arg, rec_devices); - break; - - case SOUND_MIXER_STEREODEVS: - return IOCTL_OUT (arg, SUPPORTED_MIXER_DEVICES & ~(SOUND_MASK_BASS | SOUND_MASK_TREBLE)); - break; - - case SOUND_MIXER_DEVMASK: - return IOCTL_OUT (arg, SUPPORTED_MIXER_DEVICES); - break; - - case SOUND_MIXER_RECMASK: - return IOCTL_OUT (arg, POSSIBLE_RECORDING_DEVICES & SUPPORTED_MIXER_DEVICES); - break; - - case SOUND_MIXER_CAPS: - return IOCTL_OUT (arg, 0); /* No special capabilities */ - break; - - case SOUND_MIXER_MUTE: - return IOCTL_OUT (arg, 0); /* No mute yet */ - break; - - case SOUND_MIXER_ENHANCE: - if (!(mode_control & P_M_MV508_ENHANCE_BITS)) - return IOCTL_OUT (arg, 0); - return IOCTL_OUT (arg, ((mode_control & P_M_MV508_ENHANCE_BITS) + 1) * 20); - break; - - case SOUND_MIXER_LOUD: - if (mode_control & P_M_MV508_LOUDNESS) - return IOCTL_OUT (arg, 1); - return IOCTL_OUT (arg, 0); - break; - - default: - return IOCTL_OUT (arg, levels[cmd & 0xff]); - } - } - } - return RET_ERROR (EINVAL); -} - -static struct mixer_operations pas_mixer_operations = -{ - "Pro Audio Spectrum 16", - pas_mixer_ioctl -}; - -int -pas_init_mixer (void) -{ - pas_mixer_reset (); - - if (num_mixers < MAX_MIXER_DEV) - mixer_devs[num_mixers++] = &pas_mixer_operations; - return 1; -} - -#endif diff --git a/sys/pc98/pc98/sound/patmgr.c b/sys/pc98/pc98/sound/patmgr.c deleted file mode 100644 index 9053415..0000000 --- a/sys/pc98/pc98/sound/patmgr.c +++ /dev/null @@ -1,272 +0,0 @@ -/* - * sound/patmgr.c - * - * The patch maneger interface for the /dev/sequencer - * - * Copyright by Hannu Savolainen 1993 - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. 2. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#define PATMGR_C -#ifdef PC98 -#include <pc98/pc98/sound/sound_config.h> -#else -#include <i386/isa/sound/sound_config.h> -#endif - -#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SEQUENCER) - -DEFINE_WAIT_QUEUES (server_procs[MAX_SYNTH_DEV], - server_wait_flag[MAX_SYNTH_DEV]); - -static struct patmgr_info *mbox[MAX_SYNTH_DEV] = -{NULL}; -static volatile int msg_direction[MAX_SYNTH_DEV] = -{0}; - -static int pmgr_opened[MAX_SYNTH_DEV] = -{0}; - -#define A_TO_S 1 -#define S_TO_A 2 - -DEFINE_WAIT_QUEUE (appl_proc, appl_wait_flag); - -int -pmgr_open (int dev) -{ - if (dev < 0 || dev >= num_synths) - return RET_ERROR (ENXIO); - - if (pmgr_opened[dev]) - return RET_ERROR (EBUSY); - pmgr_opened[dev] = 1; - - RESET_WAIT_QUEUE (server_procs[dev], server_wait_flag[dev]); - - return 0; -} - -void -pmgr_release (int dev) -{ - - if (mbox[dev]) /* - * Killed in action. Inform the client - */ - { - - mbox[dev]->key = PM_ERROR; - mbox[dev]->parm1 = RET_ERROR (EIO); - - if (SOMEONE_WAITING (appl_proc, appl_wait_flag)) - WAKE_UP (appl_proc, appl_wait_flag); - } - - pmgr_opened[dev] = 0; -} - -int -pmgr_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) -{ - unsigned long flags; - int ok = 0; - - if (count != sizeof (struct patmgr_info)) - { - printk ("PATMGR%d: Invalid read count\n", dev); - return RET_ERROR (EIO); - } - - while (!ok && !PROCESS_ABORTING (server_procs[dev], server_wait_flag[dev])) - { - DISABLE_INTR (flags); - - while (!(mbox[dev] && msg_direction[dev] == A_TO_S) && - !PROCESS_ABORTING (server_procs[dev], server_wait_flag[dev])) - { - DO_SLEEP (server_procs[dev], server_wait_flag[dev], 0); - } - - if (mbox[dev] && msg_direction[dev] == A_TO_S) - { - COPY_TO_USER (buf, 0, (char *) mbox[dev], count); - msg_direction[dev] = 0; - ok = 1; - } - - RESTORE_INTR (flags); - - } - - if (!ok) - return RET_ERROR (EINTR); - return count; -} - -int -pmgr_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) -{ - unsigned long flags; - - if (count < 4) - { - printk ("PATMGR%d: Write count < 4\n", dev); - return RET_ERROR (EIO); - } - - COPY_FROM_USER (mbox[dev], buf, 0, 4); - - if (*(unsigned char *) mbox[dev] == SEQ_FULLSIZE) - { - int tmp_dev; - - tmp_dev = ((unsigned short *) mbox[dev])[2]; - if (tmp_dev != dev) - return RET_ERROR (ENXIO); - - return synth_devs[dev]->load_patch (dev, *(unsigned short *) mbox[dev], - buf, 4, count, 1); - } - - if (count != sizeof (struct patmgr_info)) - { - printk ("PATMGR%d: Invalid write count\n", dev); - return RET_ERROR (EIO); - } - - /* - * If everything went OK, there should be a preallocated buffer in the - * mailbox and a client waiting. - */ - - DISABLE_INTR (flags); - - if (mbox[dev] && !msg_direction[dev]) - { - COPY_FROM_USER (&((char *) mbox[dev])[4], buf, 4, count - 4); - msg_direction[dev] = S_TO_A; - - if (SOMEONE_WAITING (appl_proc, appl_wait_flag)) - { - WAKE_UP (appl_proc, appl_wait_flag); - } - } - - RESTORE_INTR (flags); - - return count; -} - -int -pmgr_access (int dev, struct patmgr_info *rec) -{ - unsigned long flags; - int err = 0; - - DISABLE_INTR (flags); - - if (mbox[dev]) - printk (" PATMGR: Server %d mbox full. Why?\n", dev); - else - { - rec->key = PM_K_COMMAND; - mbox[dev] = rec; - msg_direction[dev] = A_TO_S; - - if (SOMEONE_WAITING (server_procs[dev], server_wait_flag[dev])) - { - WAKE_UP (server_procs[dev], server_wait_flag[dev]); - } - - DO_SLEEP (appl_proc, appl_wait_flag, 0); - - if (msg_direction[dev] != S_TO_A) - { - rec->key = PM_ERROR; - rec->parm1 = RET_ERROR (EIO); - } - else if (rec->key == PM_ERROR) - { - err = rec->parm1; - if (err > 0) - err = -err; - } - - mbox[dev] = NULL; - msg_direction[dev] = 0; - } - - RESTORE_INTR (flags); - - return err; -} - -int -pmgr_inform (int dev, int event, unsigned long p1, unsigned long p2, - unsigned long p3, unsigned long p4) -{ - unsigned long flags; - int err = 0; - - if (!pmgr_opened[dev]) - return 0; - - DISABLE_INTR (flags); - - if (mbox[dev]) - printk (" PATMGR: Server %d mbox full. Why?\n", dev); - else - { - if ((mbox[dev] = - (struct patmgr_info *) KERNEL_MALLOC (sizeof (struct patmgr_info))) == NULL) - { - printk ("pmgr: Couldn't allocate memory for a message\n"); - return 0; - } - - mbox[dev]->key = PM_K_EVENT; - mbox[dev]->command = event; - mbox[dev]->parm1 = p1; - mbox[dev]->parm2 = p2; - mbox[dev]->parm3 = p3; - msg_direction[dev] = A_TO_S; - - if (SOMEONE_WAITING (server_procs[dev], server_wait_flag[dev])) - { - WAKE_UP (server_procs[dev], server_wait_flag[dev]); - } - - DO_SLEEP (appl_proc, appl_wait_flag, 0); - if (mbox[dev]) - KERNEL_FREE (mbox[dev]); - mbox[dev] = NULL; - msg_direction[dev] = 0; - } - - RESTORE_INTR (flags); - - return err; -} - -#endif diff --git a/sys/pc98/pc98/sound/pcm86.c b/sys/pc98/pc98/sound/pcm86.c index 974bafe..40c7c25 100644 --- a/sys/pc98/pc98/sound/pcm86.c +++ b/sys/pc98/pc98/sound/pcm86.c @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: pcm86.c,v 2.4 1996/01/24 19:53:34 abtk Exp $ + * $Id: pcm86.c,v 1.2 1996/09/12 11:11:16 asami Exp $ */ /* @@ -36,7 +36,7 @@ */ -#include "sound_config.h" +#include <i386/isa/sound/sound_config.h> #ifdef CONFIGURE_SOUNDCARD diff --git a/sys/pc98/pc98/sound/sb16_dsp.c b/sys/pc98/pc98/sound/sb16_dsp.c index a195dba..5e84e67 100644 --- a/sys/pc98/pc98/sound/sb16_dsp.c +++ b/sys/pc98/pc98/sound/sb16_dsp.c @@ -34,11 +34,7 @@ /* * #define DEB_DMARES */ -#ifdef PC98 -#include <pc98/pc98/sound/sound_config.h> -#else #include <i386/isa/sound/sound_config.h> -#endif #include <i386/isa/sound/sb.h> #include <i386/isa/sound/sb_mixer.h> diff --git a/sys/pc98/pc98/sound/sb16_midi.c b/sys/pc98/pc98/sound/sb16_midi.c index 6cd70f6..7dae750 100644 --- a/sys/pc98/pc98/sound/sb16_midi.c +++ b/sys/pc98/pc98/sound/sb16_midi.c @@ -27,11 +27,7 @@ * */ -#ifdef PC98 -#include <pc98/pc98/sound/sound_config.h> -#else #include <i386/isa/sound/sound_config.h> -#endif #ifdef CONFIGURE_SOUNDCARD diff --git a/sys/pc98/pc98/sound/sb_card.c b/sys/pc98/pc98/sound/sb_card.c deleted file mode 100644 index 6656df7..0000000 --- a/sys/pc98/pc98/sound/sb_card.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * sound/sb_card.c - * - * Detection routine for the SoundBlaster cards. - * - * Copyright by Hannu Savolainen 1993 - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. 2. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * Modified: - * Riccardo Facchetti 24 Mar 1995 - * - Added the Audio Excel DSP 16 initialization routine. - */ - -#ifdef PC98 -#include <pc98/pc98/sound/sound_config.h> -#else -#include <i386/isa/sound/sound_config.h> -#endif - -#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SB) - -long -attach_sb_card (long mem_start, struct address_info *hw_config) -{ -#if !defined(EXCLUDE_AUDIO) || !defined(EXCLUDE_MIDI) - if (!sb_dsp_detect (hw_config)) - return mem_start; - mem_start = sb_dsp_init (mem_start, hw_config); -#endif - - return mem_start; -} - -int -probe_sb (struct address_info *hw_config) -{ -#if !defined(EXCLUDE_AEDSP16) && defined(AEDSP16_SBPRO) - /* - * Initialize Audio Excel DSP 16 to SBPRO. - */ - InitAEDSP16_SBPRO (hw_config); -#endif - return sb_dsp_detect (hw_config); -} - -#endif diff --git a/sys/pc98/pc98/sound/sb_dsp.c b/sys/pc98/pc98/sound/sb_dsp.c index f8922c9..82a2178 100644 --- a/sys/pc98/pc98/sound/sb_dsp.c +++ b/sys/pc98/pc98/sound/sb_dsp.c @@ -33,11 +33,7 @@ * Code added for MV ProSonic/Jazz 16 in 16 bit mode */ -#ifdef PC98 -#include <pc98/pc98/sound/sound_config.h> -#else #include <i386/isa/sound/sound_config.h> -#endif #if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SB) diff --git a/sys/pc98/pc98/sound/sb_midi.c b/sys/pc98/pc98/sound/sb_midi.c deleted file mode 100644 index 0c63af5..0000000 --- a/sys/pc98/pc98/sound/sb_midi.c +++ /dev/null @@ -1,257 +0,0 @@ -/* - * sound/sb_dsp.c - * - * The low level driver for the SoundBlaster DS chips. - * - * Copyright by Hannu Savolainen 1993 - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. 2. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#ifdef PC98 -#include <pc98/pc98/sound/sound_config.h> -#else -#include <i386/isa/sound/sound_config.h> -#endif - -#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SB) && !defined(EXCLUDE_MIDI) - -#include <i386/isa/sound/sb.h> -#undef SB_TEST_IRQ - -/* - * The DSP channel can be used either for input or output. Variable - * 'sb_irq_mode' will be set when the program calls read or write first time - * after open. Current version doesn't support mode changes without closing - * and reopening the device. Support for this feature may be implemented in a - * future version of this driver. - */ - -extern int sb_dsp_ok; /* Set to 1 atfer successful initialization */ -extern int sbc_base; - -extern int sb_midi_mode; -extern int sb_midi_busy; /* - - - * * * * 1 if the process has output to MIDI - * - */ -extern int sb_dsp_busy; -extern int sb_dsp_highspeed; - -extern volatile int sb_irq_mode; -extern int sb_duplex_midi; -extern int sb_intr_active; -static int input_opened = 0; -static int my_dev; - -void (*midi_input_intr) (int dev, unsigned char data); - -static int -sb_midi_open (int dev, int mode, - void (*input) (int dev, unsigned char data), - void (*output) (int dev) -) -{ - int ret; - - if (!sb_dsp_ok) - { - printk ("SB Error: MIDI hardware not installed\n"); - return RET_ERROR (ENXIO); - } - - if (sb_midi_busy) - return RET_ERROR (EBUSY); - - if (mode != OPEN_WRITE && !sb_duplex_midi) - { - if (num_midis == 1) - printk ("SoundBlaster: Midi input not currently supported\n"); - return RET_ERROR (EPERM); - } - - sb_midi_mode = NORMAL_MIDI; - if (mode != OPEN_WRITE) - { - if (sb_dsp_busy || sb_intr_active) - return RET_ERROR (EBUSY); - sb_midi_mode = UART_MIDI; - } - - if (sb_dsp_highspeed) - { - printk ("SB Error: Midi output not possible during stereo or high speed audio\n"); - return RET_ERROR (EBUSY); - } - - if (sb_midi_mode == UART_MIDI) - { - sb_irq_mode = IMODE_MIDI; - - sb_reset_dsp (); - - if (!sb_dsp_command (0x35)) - return RET_ERROR (EIO); /* - * Enter the UART mode - */ - sb_intr_active = 1; - - if ((ret = sb_get_irq ()) < 0) - { - sb_reset_dsp (); - return 0; /* - * IRQ not free - */ - } - input_opened = 1; - midi_input_intr = input; - } - - sb_midi_busy = 1; - - return 0; -} - -static void -sb_midi_close (int dev) -{ - if (sb_midi_mode == UART_MIDI) - { - sb_reset_dsp (); /* - * The only way to kill the UART mode - */ - sb_free_irq (); - } - sb_intr_active = 0; - sb_midi_busy = 0; - input_opened = 0; -} - -static int -sb_midi_out (int dev, unsigned char midi_byte) -{ - unsigned long flags; - - if (sb_midi_mode == NORMAL_MIDI) - { - DISABLE_INTR (flags); - if (sb_dsp_command (0x38)) - sb_dsp_command (midi_byte); - else - printk ("SB Error: Unable to send a MIDI byte\n"); - RESTORE_INTR (flags); - } - else - sb_dsp_command (midi_byte); /* - * UART write - */ - - return 1; -} - -static int -sb_midi_start_read (int dev) -{ - if (sb_midi_mode != UART_MIDI) - { - printk ("SoundBlaster: MIDI input not implemented.\n"); - return RET_ERROR (EPERM); - } - return 0; -} - -static int -sb_midi_end_read (int dev) -{ - if (sb_midi_mode == UART_MIDI) - { - sb_reset_dsp (); - sb_intr_active = 0; - } - return 0; -} - -static int -sb_midi_ioctl (int dev, unsigned cmd, unsigned arg) -{ - return RET_ERROR (EPERM); -} - -void -sb_midi_interrupt (int dummy) -{ - unsigned long flags; - unsigned char data; - - DISABLE_INTR (flags); - - data = INB (DSP_READ); - if (input_opened) - midi_input_intr (my_dev, data); - - RESTORE_INTR (flags); -} - -#define MIDI_SYNTH_NAME "SoundBlaster Midi" -#define MIDI_SYNTH_CAPS 0 -#include <i386/isa/sound/midi_synth.h> - -static struct midi_operations sb_midi_operations = -{ - {"SoundBlaster", 0, 0, SNDCARD_SB}, - &std_midi_synth, - {0}, - sb_midi_open, - sb_midi_close, - sb_midi_ioctl, - sb_midi_out, - sb_midi_start_read, - sb_midi_end_read, - NULL, /* - * Kick - */ - NULL, /* - * command - */ - NULL, /* - * buffer_status - */ - NULL -}; - -void -sb_midi_init (int model) -{ - if (num_midis >= MAX_MIDI_DEV) - { - printk ("Sound: Too many midi devices detected\n"); - return; - } - - std_midi_synth.midi_dev = num_midis; - my_dev = num_midis; - midi_devs[num_midis++] = &sb_midi_operations; -} - -#endif diff --git a/sys/pc98/pc98/sound/sb_mixer.c b/sys/pc98/pc98/sound/sb_mixer.c deleted file mode 100644 index b044412..0000000 --- a/sys/pc98/pc98/sound/sb_mixer.c +++ /dev/null @@ -1,591 +0,0 @@ - -/* - * sound/sb_mixer.c - * - * The low level mixer driver for the SoundBlaster Pro and SB16 cards. - * - * Copyright by Hannu Savolainen 1994 - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. 2. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * Modified: - * Hunyue Yau Jan 6 1994 - * Added code to support the Sound Galaxy NX Pro mixer. - * - */ - -#ifdef PC98 -#include <pc98/pc98/sound/sound_config.h> -#else -#include <i386/isa/sound/sound_config.h> -#endif - -#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SB) && !defined(EXCLUDE_SBPRO) -#define __SB_MIXER_C__ - -#include <i386/isa/sound/sb.h> -#include <i386/isa/sound/sb_mixer.h> -#undef SB_TEST_IRQ - -extern int sbc_base; -extern int sbc_major; -extern int Jazz16_detected; - -static int mixer_initialized = 0; - -static int supported_rec_devices; -static int supported_devices; -static int recmask = 0; -static int mixer_model; -static int mixer_caps; -static mixer_tab *iomap; - -void -sb_setmixer (unsigned int port, unsigned int value) -{ - unsigned long flags; - - DISABLE_INTR (flags); - OUTB ((unsigned char) (port & 0xff), MIXER_ADDR); /* - * Select register - */ - tenmicrosec (); - OUTB ((unsigned char) (value & 0xff), MIXER_DATA); - tenmicrosec (); - RESTORE_INTR (flags); -} - -int -sb_getmixer (unsigned int port) -{ - int val; - unsigned long flags; - - DISABLE_INTR (flags); - OUTB ((unsigned char) (port & 0xff), MIXER_ADDR); /* - * Select register - */ - tenmicrosec (); - val = INB (MIXER_DATA); - tenmicrosec (); - RESTORE_INTR (flags); - - return val; -} - -void -sb_mixer_set_stereo (int mode) -{ - if (!mixer_initialized) - return; - - sb_setmixer (OUT_FILTER, ((sb_getmixer (OUT_FILTER) & ~STEREO_DAC) - | (mode ? STEREO_DAC : MONO_DAC))); -} - -/* - * Returns: - * 0 No mixer detected. - * 1 Only a plain Sound Blaster Pro style mixer detected. - * 2 The Sound Galaxy NX Pro mixer detected. - */ -static int -detect_mixer (void) -{ -#ifdef __SGNXPRO__ - int oldbass, oldtreble; - -#endif - int retcode = 1; - - /* - * Detect the mixer by changing parameters of two volume channels. If the - * values read back match with the values written, the mixer is there (is - * it?) - */ - sb_setmixer (FM_VOL, 0xff); - sb_setmixer (VOC_VOL, 0x33); - - if (sb_getmixer (FM_VOL) != 0xff) - return 0; /* - * No match - */ - if (sb_getmixer (VOC_VOL) != 0x33) - return 0; - -#ifdef __SGNXPRO__ - /* Attempt to detect the SG NX Pro by check for valid bass/treble - * registers. - */ - oldbass = sb_getmixer (BASS_LVL); - oldtreble = sb_getmixer (TREBLE_LVL); - - sb_setmixer (BASS_LVL, 0xaa); - sb_setmixer (TREBLE_LVL, 0x55); - - if ((sb_getmixer (BASS_LVL) != 0xaa) || - (sb_getmixer (TREBLE_LVL) != 0x55)) - { - retcode = 1; /* 1 == Only SB Pro detected */ - } - else - retcode = 2; /* 2 == SG NX Pro detected */ - /* Restore register in either case since SG NX Pro has EEPROM with - * 'preferred' values stored. - */ - sb_setmixer (BASS_LVL, oldbass); - sb_setmixer (TREBLE_LVL, oldtreble); - - /* - * If the SB version is 3.X (SB Pro), assume we have a SG NX Pro 16. - * In this case it's good idea to disable the Disney Sound Source - * compatibility mode. It's useless and just causes noise every time the - * LPT-port is accessed. - * - * Also place the card into WSS mode. - */ - if (sbc_major == 3) - { - OUTB (0x01, sbc_base + 0x1c); - OUTB (0x00, sbc_base + 0x1a); - } - -#endif - return retcode; -} - -static void -change_bits (unsigned char *regval, int dev, int chn, int newval) -{ - unsigned char mask; - int shift; - - mask = (1 << (*iomap)[dev][chn].nbits) - 1; - newval = (int) ((newval * mask) + 50) / 100; /* - * Scale it - */ - - shift = (*iomap)[dev][chn].bitoffs - (*iomap)[dev][LEFT_CHN].nbits + 1; - - *regval &= ~(mask << shift); /* - * Filter out the previous value - */ - *regval |= (newval & mask) << shift; /* - * Set the new value - */ -} - -static int -sb_mixer_get (int dev) -{ - if (!((1 << dev) & supported_devices)) - return RET_ERROR (EINVAL); - - return levels[dev]; -} - -#ifdef JAZZ16 -static char smw_mix_regs[] = /* Left mixer registers */ -{ - 0x0b, /* SOUND_MIXER_VOLUME */ - 0x0d, /* SOUND_MIXER_BASS */ - 0x0d, /* SOUND_MIXER_TREBLE */ - 0x05, /* SOUND_MIXER_SYNTH */ - 0x09, /* SOUND_MIXER_PCM */ - 0x00, /* SOUND_MIXER_SPEAKER */ - 0x03, /* SOUND_MIXER_LINE */ - 0x01, /* SOUND_MIXER_MIC */ - 0x07, /* SOUND_MIXER_CD */ - 0x00, /* SOUND_MIXER_IMIX */ - 0x00, /* SOUND_MIXER_ALTPCM */ - 0x00, /* SOUND_MIXER_RECLEV */ - 0x00, /* SOUND_MIXER_IGAIN */ - 0x00, /* SOUND_MIXER_OGAIN */ - 0x00, /* SOUND_MIXER_LINE1 */ - 0x00, /* SOUND_MIXER_LINE2 */ - 0x00 /* SOUND_MIXER_LINE3 */ -}; - -static void -smw_mixer_init (void) -{ - int i; - - sb_setmixer (0x00, 0x18); /* Mute unused (Telephone) line */ - sb_setmixer (0x10, 0x38); /* Config register 2 */ - - supported_devices = 0; - for (i = 0; i < sizeof (smw_mix_regs); i++) - if (smw_mix_regs[i] != 0) - supported_devices |= (1 << i); - - supported_rec_devices = supported_devices & - ~(SOUND_MASK_BASS | SOUND_MASK_TREBLE | SOUND_MASK_PCM | - SOUND_MASK_VOLUME); -} - -static int -smw_mixer_set (int dev, int value) -{ - int left = value & 0x000000ff; - int right = (value & 0x0000ff00) >> 8; - int reg, val; - - if (left > 100) - left = 100; - if (right > 100) - right = 100; - - if (dev > 31) - return RET_ERROR (EINVAL); - - if (!(supported_devices & (1 << dev))) /* Not supported */ - return RET_ERROR (EINVAL); - - switch (dev) - { - case SOUND_MIXER_VOLUME: - sb_setmixer (0x0b, 96 - (96 * left / 100)); /* 96=mute, 0=max */ - sb_setmixer (0x0c, 96 - (96 * right / 100)); - break; - - case SOUND_MIXER_BASS: - case SOUND_MIXER_TREBLE: - levels[dev] = left | (right << 8); - - /* Set left bass and treble values */ - val = ((levels[SOUND_MIXER_TREBLE] & 0xff) * 16 / 100) << 4; - val |= ((levels[SOUND_MIXER_BASS] & 0xff) * 16 / 100) & 0x0f; - sb_setmixer (0x0d, val); - - /* Set right bass and treble values */ - val = (((levels[SOUND_MIXER_TREBLE] >> 8) & 0xff) * 16 / 100) << 4; - val |= (((levels[SOUND_MIXER_BASS] >> 8) & 0xff) * 16 / 100) & 0x0f; - sb_setmixer (0x0e, val); - break; - - default: - reg = smw_mix_regs[dev]; - if (reg == 0) - return RET_ERROR (EINVAL); - sb_setmixer (reg, (24 - (24 * left / 100)) | 0x20); /* 24=mute, 0=max */ - sb_setmixer (reg + 1, (24 - (24 * right / 100)) | 0x40); - } - - levels[dev] = left | (right << 8); - return left | (right << 8); -} - -#endif - -static int -sb_mixer_set (int dev, int value) -{ - int left = value & 0x000000ff; - int right = (value & 0x0000ff00) >> 8; - - int regoffs; - unsigned char val; - -#ifdef JAZZ16 - if (Jazz16_detected == 2) - return smw_mixer_set (dev, value); -#endif - - if (left > 100) - left = 100; - if (right > 100) - right = 100; - - if (dev > 31) - return RET_ERROR (EINVAL); - - if (!(supported_devices & (1 << dev))) /* - * Not supported - */ - return RET_ERROR (EINVAL); - - regoffs = (*iomap)[dev][LEFT_CHN].regno; - - if (regoffs == 0) - return RET_ERROR (EINVAL); - - val = sb_getmixer (regoffs); - change_bits (&val, dev, LEFT_CHN, left); - - levels[dev] = left | (left << 8); - - if ((*iomap)[dev][RIGHT_CHN].regno != regoffs) /* - * Change register - */ - { - sb_setmixer (regoffs, val); /* - * Save the old one - */ - regoffs = (*iomap)[dev][RIGHT_CHN].regno; - - if (regoffs == 0) - return left | (left << 8); /* - * Just left channel present - */ - - val = sb_getmixer (regoffs); /* - * Read the new one - */ - } - - change_bits (&val, dev, RIGHT_CHN, right); - - sb_setmixer (regoffs, val); - - levels[dev] = left | (right << 8); - return left | (right << 8); -} - -static void -set_recsrc (int src) -{ - sb_setmixer (RECORD_SRC, (sb_getmixer (RECORD_SRC) & ~7) | (src & 0x7)); -} - -static int -set_recmask (int mask) -{ - int devmask, i; - unsigned char regimageL, regimageR; - - devmask = mask & supported_rec_devices; - - switch (mixer_model) - { - case 3: - - if (devmask != SOUND_MASK_MIC && - devmask != SOUND_MASK_LINE && - devmask != SOUND_MASK_CD) - { /* - * More than one devices selected. Drop the * - * previous selection - */ - devmask &= ~recmask; - } - - if (devmask != SOUND_MASK_MIC && - devmask != SOUND_MASK_LINE && - devmask != SOUND_MASK_CD) - { /* - * More than one devices selected. Default to - * * mic - */ - devmask = SOUND_MASK_MIC; - } - - - if (devmask ^ recmask) /* - * Input source changed - */ - { - switch (devmask) - { - - case SOUND_MASK_MIC: - set_recsrc (SRC_MIC); - break; - - case SOUND_MASK_LINE: - set_recsrc (SRC_LINE); - break; - - case SOUND_MASK_CD: - set_recsrc (SRC_CD); - break; - - default: - set_recsrc (SRC_MIC); - } - } - - break; - - case 4: - if (!devmask) - devmask = SOUND_MASK_MIC; - - regimageL = regimageR = 0; - for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) - if ((1 << i) & devmask) - { - regimageL |= sb16_recmasks_L[i]; - regimageR |= sb16_recmasks_R[i]; - } - sb_setmixer (SB16_IMASK_L, regimageL); - sb_setmixer (SB16_IMASK_R, regimageR); - break; - } - - recmask = devmask; - return recmask; -} - -static int -sb_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg) -{ - if (((cmd >> 8) & 0xff) == 'M') - { - if (cmd & IOC_IN) - switch (cmd & 0xff) - { - case SOUND_MIXER_RECSRC: - return IOCTL_OUT (arg, set_recmask (IOCTL_IN (arg))); - break; - - default: - - return IOCTL_OUT (arg, sb_mixer_set (cmd & 0xff, IOCTL_IN (arg))); - } - else - switch (cmd & 0xff) /* - * Return parameters - */ - { - - case SOUND_MIXER_RECSRC: - return IOCTL_OUT (arg, recmask); - break; - - case SOUND_MIXER_DEVMASK: - return IOCTL_OUT (arg, supported_devices); - break; - - case SOUND_MIXER_STEREODEVS: - if (Jazz16_detected) - return IOCTL_OUT (arg, supported_devices); - else - return IOCTL_OUT (arg, supported_devices & - ~(SOUND_MASK_MIC | SOUND_MASK_SPEAKER)); - break; - - case SOUND_MIXER_RECMASK: - return IOCTL_OUT (arg, supported_rec_devices); - break; - - case SOUND_MIXER_CAPS: - return IOCTL_OUT (arg, mixer_caps); - break; - - default: - return IOCTL_OUT (arg, sb_mixer_get (cmd & 0xff)); - } - } - else - return RET_ERROR (EINVAL); -} - -static struct mixer_operations sb_mixer_operations = -{ - "SoundBlaster", - sb_mixer_ioctl -}; - -static void -sb_mixer_reset (void) -{ - int i; - - for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) - sb_mixer_set (i, levels[i]); - set_recmask (SOUND_MASK_MIC); -} - -/* - * Returns a code depending on whether a SG NX Pro was detected. - * 1 == Plain SB Pro - * 2 == SG NX Pro detected. - * 3 == SB16 - * - * Used to update message. - */ -int -sb_mixer_init (int major_model) -{ - int mixer_type = 0; - - sb_setmixer (0x00, 0); /* Reset mixer */ - - if (!(mixer_type = detect_mixer ())) - return 0; /* No mixer. Why? */ - - mixer_initialized = 1; - mixer_model = major_model; - - switch (major_model) - { - case 3: - mixer_caps = SOUND_CAP_EXCL_INPUT; - -#ifdef JAZZ16 - if (Jazz16_detected == 2) /* SM Wave */ - { - supported_devices = 0; - supported_rec_devices = 0; - iomap = &sbpro_mix; - smw_mixer_init (); - mixer_type = 1; - } - else -#endif -#ifdef __SGNXPRO__ - if (mixer_type == 2) /* A SGNXPRO was detected */ - { - supported_devices = SGNXPRO_MIXER_DEVICES; - supported_rec_devices = SGNXPRO_RECORDING_DEVICES; - iomap = &sgnxpro_mix; - } - else -#endif - { - supported_devices = SBPRO_MIXER_DEVICES; - supported_rec_devices = SBPRO_RECORDING_DEVICES; - iomap = &sbpro_mix; - mixer_type = 1; - } - break; - - case 4: - mixer_caps = 0; - supported_devices = SB16_MIXER_DEVICES; - supported_rec_devices = SB16_RECORDING_DEVICES; - iomap = &sb16_mix; - mixer_type = 3; - break; - - default: - printk ("SB Warning: Unsupported mixer type\n"); - return 0; - } - - if (num_mixers < MAX_MIXER_DEV) - mixer_devs[num_mixers++] = &sb_mixer_operations; - sb_mixer_reset (); - return mixer_type; -} - -#endif diff --git a/sys/pc98/pc98/sound/sequencer.c b/sys/pc98/pc98/sound/sequencer.c deleted file mode 100644 index 30da4c6..0000000 --- a/sys/pc98/pc98/sound/sequencer.c +++ /dev/null @@ -1,1992 +0,0 @@ -/* - * sound/sequencer.c - * - * The sequencer personality manager. - * - * Copyright by Hannu Savolainen 1993 - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. 2. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#define SEQUENCER_C -#ifdef PC98 -#include <pc98/pc98/sound/sound_config.h> -#else -#include <i386/isa/sound/sound_config.h> -#endif -#include <i386/isa/sound/midi_ctrl.h> - -extern void seq_drain_midi_queues __P((void)); - -#ifdef CONFIGURE_SOUNDCARD - -#ifndef EXCLUDE_SEQUENCER - -static int sequencer_ok = 0; -static struct sound_timer_operations *tmr; -static int tmr_no = -1; /* Currently selected timer */ -static int pending_timer = -1; /* For timer change operation */ - -/* - * Local counts for number of synth and MIDI devices. These are initialized - * by the sequencer_open. - */ -static int max_mididev = 0; -static int max_synthdev = 0; - -/* - * The seq_mode gives the operating mode of the sequencer: - * 1 = level1 (the default) - * 2 = level2 (extended capabilites) - */ - -#define SEQ_1 1 -#define SEQ_2 2 -static int seq_mode = SEQ_1; - -DEFINE_WAIT_QUEUE (seq_sleeper, seq_sleep_flag); -DEFINE_WAIT_QUEUE (midi_sleeper, midi_sleep_flag); - -static int midi_opened[MAX_MIDI_DEV] = -{0}; -static int midi_written[MAX_MIDI_DEV] = -{0}; - -static unsigned long prev_input_time = 0; -static int prev_event_time; -static unsigned long seq_time = 0; - -#include <i386/isa/sound/tuning.h> - -#define EV_SZ 8 -#define IEV_SZ 8 -static unsigned char *queue = NULL; -static unsigned char *iqueue = NULL; - -static volatile int qhead = 0, qtail = 0, qlen = 0; -static volatile int iqhead = 0, iqtail = 0, iqlen = 0; -static volatile int seq_playing = 0; -static int sequencer_busy = 0; -static int output_treshold; -static int pre_event_timeout; -static unsigned synth_open_mask; - -static int seq_queue (unsigned char *note, char nonblock); -static void seq_startplay (void); -static int seq_sync (void); -static void seq_reset (void); -static int pmgr_present[MAX_SYNTH_DEV] = -{0}; - -#if MAX_SYNTH_DEV > 15 -#error Too many synthesizer devices enabled. -#endif - -int -sequencer_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) -{ - int c = count, p = 0; - int ev_len; - unsigned long flags; - - dev = dev >> 4; - - ev_len = seq_mode == SEQ_1 ? 4 : 8; - - if (dev) /* - * Patch manager device - */ - return pmgr_read (dev - 1, file, buf, count); - - DISABLE_INTR (flags); - if (!iqlen) - { - if (ISSET_FILE_FLAG (file, O_NONBLOCK)) - { - RESTORE_INTR (flags); - return RET_ERROR (EAGAIN); - } - - DO_SLEEP (midi_sleeper, midi_sleep_flag, pre_event_timeout); - - if (!iqlen) - { - RESTORE_INTR (flags); - return 0; - } - } - - while (iqlen && c >= ev_len) - { - - COPY_TO_USER (buf, p, &iqueue[iqhead * IEV_SZ], ev_len); - p += ev_len; - c -= ev_len; - - iqhead = (iqhead + 1) % SEQ_MAX_QUEUE; - iqlen--; - } - RESTORE_INTR (flags); - - return count - c; -} - -static void -sequencer_midi_output (int dev) -{ - /* - * Currently NOP - */ -} - -void -seq_copy_to_input (unsigned char *event, int len) -{ - unsigned long flags; - - /* - * Verify that the len is valid for the current mode. - */ - - if (len != 4 && len != 8) - return; - if ((seq_mode == SEQ_1) != (len == 4)) - return; - - if (iqlen >= (SEQ_MAX_QUEUE - 1)) - return; /* Overflow */ - - DISABLE_INTR (flags); - memcpy (&iqueue[iqtail * IEV_SZ], event, len); - iqlen++; - iqtail = (iqtail + 1) % SEQ_MAX_QUEUE; - - if (SOMEONE_WAITING (midi_sleeper, midi_sleep_flag)) - { - WAKE_UP (midi_sleeper, midi_sleep_flag); - } - RESTORE_INTR (flags); -#if defined(__FreeBSD__) - if (selinfo[0].si_pid) - selwakeup(&selinfo[0]); -#endif -} - -static void -sequencer_midi_input (int dev, unsigned char data) -{ - unsigned int tstamp; - unsigned char event[4]; - - if (data == 0xfe) /* Ignore active sensing */ - return; - - tstamp = GET_TIME () - seq_time; - if (tstamp != prev_input_time) - { - tstamp = (tstamp << 8) | SEQ_WAIT; - - seq_copy_to_input ((unsigned char *) &tstamp, 4); - prev_input_time = tstamp; - } - - event[0] = SEQ_MIDIPUTC; - event[1] = data; - event[2] = dev; - event[3] = 0; - - seq_copy_to_input (event, 4); -} - -void -seq_input_event (unsigned char *event, int len) -{ - unsigned long this_time; - - if (seq_mode == SEQ_2) - this_time = tmr->get_time (tmr_no); - else - this_time = GET_TIME () - seq_time; - - if (this_time != prev_input_time) - { - unsigned char tmp_event[8]; - - tmp_event[0] = EV_TIMING; - tmp_event[1] = TMR_WAIT_ABS; - tmp_event[2] = 0; - tmp_event[3] = 0; - *(unsigned long *) &tmp_event[4] = this_time; - - seq_copy_to_input (tmp_event, 8); - prev_input_time = this_time; - } - - seq_copy_to_input (event, len); -} - -int -sequencer_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) -{ - unsigned char event[EV_SZ], ev_code; - int p = 0, c, ev_size; - int err; - int mode = file->mode & O_ACCMODE; - - dev = dev >> 4; - - DEB (printk ("sequencer_write(dev=%d, count=%d)\n", dev, count)); - - if (mode == OPEN_READ) - return RET_ERROR (EIO); - - if (dev) /* - * Patch manager device - */ - return pmgr_write (dev - 1, file, buf, count); - - c = count; - - while (c >= 4) - { - COPY_FROM_USER (event, buf, p, 4); - ev_code = event[0]; - - if (ev_code == SEQ_FULLSIZE) - { - int err; - - dev = *(unsigned short *) &event[2]; - if (dev < 0 || dev >= max_synthdev) - return RET_ERROR (ENXIO); - - if (!(synth_open_mask & (1 << dev))) - return RET_ERROR (ENXIO); - - err = synth_devs[dev]->load_patch (dev, *(short *) &event[0], buf, p + 4, c, 0); - if (err < 0) - return err; - - return err; - } - - if (ev_code >= 128) - { - if (seq_mode == SEQ_2 && ev_code == SEQ_EXTENDED) - { - printk ("Sequencer: Invalid level 2 event %x\n", ev_code); - return RET_ERROR (EINVAL); - } - - ev_size = 8; - - if (c < ev_size) - { - if (!seq_playing) - seq_startplay (); - return count - c; - } - - COPY_FROM_USER (&event[4], buf, p + 4, 4); - - } - else - { - if (seq_mode == SEQ_2) - { - printk ("Sequencer: 4 byte event in level 2 mode\n"); - return RET_ERROR (EINVAL); - } - ev_size = 4; - } - - if (event[0] == SEQ_MIDIPUTC) - { - - if (!midi_opened[event[2]]) - { - int mode; - int dev = event[2]; - - if (dev >= max_mididev) - { - printk ("Sequencer Error: Nonexistent MIDI device %d\n", dev); - return RET_ERROR (ENXIO); - } - - mode = file->mode & O_ACCMODE; - - if ((err = midi_devs[dev]->open (dev, mode, - sequencer_midi_input, sequencer_midi_output)) < 0) - { - seq_reset (); - printk ("Sequencer Error: Unable to open Midi #%d\n", dev); - return err; - } - - midi_opened[dev] = 1; - } - - } - - if (!seq_queue (event, ISSET_FILE_FLAG (file, O_NONBLOCK))) - { - int processed = count - c; - - if (!seq_playing) - seq_startplay (); - - if (!processed && ISSET_FILE_FLAG (file, O_NONBLOCK)) - return RET_ERROR (EAGAIN); - else - return processed; - } - - p += ev_size; - c -= ev_size; - } - - if (!seq_playing) - seq_startplay (); - - return count; /* This will "eat" chunks shorter than 4 bytes (if written - * alone) Should we really do that ? - */ -} - -static int -seq_queue (unsigned char *note, char nonblock) -{ - - /* - * Test if there is space in the queue - */ - - if (qlen >= SEQ_MAX_QUEUE) - if (!seq_playing) - seq_startplay (); /* - * Give chance to drain the queue - */ - - if (!nonblock && qlen >= SEQ_MAX_QUEUE && !SOMEONE_WAITING (seq_sleeper, seq_sleep_flag)) - { - /* - * Sleep until there is enough space on the queue - */ - DO_SLEEP (seq_sleeper, seq_sleep_flag, 0); - } - - if (qlen >= SEQ_MAX_QUEUE) - { - return 0; /* - * To be sure - */ - } - memcpy (&queue[qtail * EV_SZ], note, EV_SZ); - - qtail = (qtail + 1) % SEQ_MAX_QUEUE; - qlen++; - - return 1; -} - -static int -extended_event (unsigned char *q) -{ - int dev = q[2]; - - if (dev < 0 || dev >= max_synthdev) - return RET_ERROR (ENXIO); - - if (!(synth_open_mask & (1 << dev))) - return RET_ERROR (ENXIO); - - switch (q[1]) - { - case SEQ_NOTEOFF: - synth_devs[dev]->kill_note (dev, q[3], q[4], q[5]); - break; - - case SEQ_NOTEON: - if (q[4] > 127 && q[4] != 255) - return 0; - - synth_devs[dev]->start_note (dev, q[3], q[4], q[5]); - break; - - case SEQ_PGMCHANGE: - synth_devs[dev]->set_instr (dev, q[3], q[4]); - break; - - case SEQ_AFTERTOUCH: - synth_devs[dev]->aftertouch (dev, q[3], q[4]); - break; - - case SEQ_BALANCE: - synth_devs[dev]->panning (dev, q[3], (char) q[4]); - break; - - case SEQ_CONTROLLER: - synth_devs[dev]->controller (dev, q[3], q[4], *(short *) &q[5]); - break; - - case SEQ_VOLMODE: - if (synth_devs[dev]->volume_method != NULL) - synth_devs[dev]->volume_method (dev, q[3]); - break; - - default: - return RET_ERROR (EINVAL); - } - - return 0; -} - -static int -find_voice (int dev, int chn, int note) -{ - unsigned short key; - int i; - - key = (chn << 8) | (note + 1); - - for (i = 0; i < synth_devs[dev]->alloc.max_voice; i++) - if (synth_devs[dev]->alloc.map[i] == key) - return i; - - return -1; -} - -static int -alloc_voice (int dev, int chn, int note) -{ - unsigned short key; - int voice; - - key = (chn << 8) | (note + 1); - - voice = synth_devs[dev]->alloc_voice (dev, chn, note, - &synth_devs[dev]->alloc); - synth_devs[dev]->alloc.map[voice] = key; - synth_devs[dev]->alloc.alloc_times[voice] = - synth_devs[dev]->alloc.timestamp++; - return voice; -} - -static void -seq_chn_voice_event (unsigned char *event) -{ - unsigned char dev = event[1]; - unsigned char cmd = event[2]; - unsigned char chn = event[3]; - unsigned char note = event[4]; - unsigned char parm = event[5]; - int voice = -1; - - if ((int) dev > max_synthdev) - return; - if (!(synth_open_mask & (1 << dev))) - return; - if (!synth_devs[dev]) - return; - - if (seq_mode == SEQ_2) - { - if (synth_devs[dev]->alloc_voice) - voice = find_voice (dev, chn, note); - - if (cmd == MIDI_NOTEON && parm == 0) - { - cmd = MIDI_NOTEOFF; - parm = 64; - } - } - - switch (cmd) - { - case MIDI_NOTEON: - if (note > 127 && note != 255) /* Not a seq2 feature */ - return; - - if (voice == -1 && seq_mode == SEQ_2 && synth_devs[dev]->alloc_voice) - { /* Internal synthesizer (FM, GUS, etc) */ - voice = alloc_voice (dev, chn, note); - } - - if (voice == -1) - voice = chn; - - if (seq_mode == SEQ_2 && dev < num_synths) - { - /* - * The MIDI channel 10 is a percussive channel. Use the note - * number to select the proper patch (128 to 255) to play. - */ - - if (chn == 9) - { - synth_devs[dev]->set_instr (dev, voice, 128 + note); - note = 60; /* Middle C */ - - } - } - - if (seq_mode == SEQ_2) - { - synth_devs[dev]->setup_voice (dev, voice, chn); - } - - synth_devs[dev]->start_note (dev, voice, note, parm); - break; - - case MIDI_NOTEOFF: - if (voice == -1) - voice = chn; - synth_devs[dev]->kill_note (dev, voice, note, parm); - break; - - case MIDI_KEY_PRESSURE: - if (voice == -1) - voice = chn; - synth_devs[dev]->aftertouch (dev, voice, parm); - break; - - default:; - } -} - -static void -seq_chn_common_event (unsigned char *event) -{ - unsigned char dev = event[1]; - unsigned char cmd = event[2]; - unsigned char chn = event[3]; - unsigned char p1 = event[4]; - - /* unsigned char p2 = event[5]; */ - unsigned short w14 = *(short *) &event[6]; - - if ((int) dev > max_synthdev) - return; - if (!(synth_open_mask & (1 << dev))) - return; - if (!synth_devs[dev]) - return; - - switch (cmd) - { - case MIDI_PGM_CHANGE: - if (seq_mode == SEQ_2) - { - synth_devs[dev]->chn_info[chn].pgm_num = p1; - if (dev >= num_synths) - synth_devs[dev]->set_instr (dev, chn, p1); - } - else - synth_devs[dev]->set_instr (dev, chn, p1); - - break; - - case MIDI_CTL_CHANGE: - - if (seq_mode == SEQ_2) - { - if (chn > 15 || p1 > 127) - break; - - synth_devs[dev]->chn_info[chn].controllers[p1] = w14 & 0x7f; - - if (dev < num_synths) - { - int val = w14 & 0x7f; - int i, key; - - if (p1 < 64) /* Combine MSB and LSB */ - { - val = ((synth_devs[dev]-> - chn_info[chn].controllers[p1 & ~32] & 0x7f) << 7) - | (synth_devs[dev]-> - chn_info[chn].controllers[p1 | 32] & 0x7f); - p1 &= ~32; - } - - /* Handle all playing notes on this channel */ - - key = (chn << 8); - - for (i = 0; i < synth_devs[dev]->alloc.max_voice; i++) - if ((synth_devs[dev]->alloc.map[i] & 0xff00) == key) - synth_devs[dev]->controller (dev, i, p1, val); - } - else - synth_devs[dev]->controller (dev, chn, p1, w14); - } - else /* Mode 1 */ - synth_devs[dev]->controller (dev, chn, p1, w14); - break; - - case MIDI_PITCH_BEND: - if (seq_mode == SEQ_2) - { - synth_devs[dev]->chn_info[chn].bender_value = w14; - - if (dev < num_synths) - { /* Handle all playing notes on this channel */ - int i, key; - - key = (chn << 8); - - for (i = 0; i < synth_devs[dev]->alloc.max_voice; i++) - if ((synth_devs[dev]->alloc.map[i] & 0xff00) == key) - synth_devs[dev]->bender (dev, i, w14); - } - else - synth_devs[dev]->bender (dev, chn, w14); - } - else /* MODE 1 */ - synth_devs[dev]->bender (dev, chn, w14); - break; - - default:; - } -} - -static int -seq_timing_event (unsigned char *event) -{ - unsigned char cmd = event[1]; - unsigned int parm = *(int *) &event[4]; - - if (seq_mode == SEQ_2) - { - int ret; - - if ((ret = tmr->event (tmr_no, event)) == TIMER_ARMED) - { - if ((SEQ_MAX_QUEUE - qlen) >= output_treshold) - { - unsigned long flags; - - DISABLE_INTR (flags); - if (SOMEONE_WAITING (seq_sleeper, seq_sleep_flag)) - { - WAKE_UP (seq_sleeper, seq_sleep_flag); - } - RESTORE_INTR (flags); -#if defined(__FreeBSD__) - /* must issue a wakeup for anyone waiting (select) XXX */ -#endif - } - } - return ret; - } - - switch (cmd) - { - case TMR_WAIT_REL: - parm += prev_event_time; - - /* - * NOTE! No break here. Execution of TMR_WAIT_REL continues in the - * next case (TMR_WAIT_ABS) - */ - - case TMR_WAIT_ABS: - if (parm > 0) - { - long time; - - seq_playing = 1; - time = parm; - prev_event_time = time; - - request_sound_timer (time); - - if ((SEQ_MAX_QUEUE - qlen) >= output_treshold) - { - unsigned long flags; - - DISABLE_INTR (flags); - if (SOMEONE_WAITING (seq_sleeper, seq_sleep_flag)) - { - WAKE_UP (seq_sleeper, seq_sleep_flag); - } - RESTORE_INTR (flags); -#if defined(__FreeBSD__) - /* must issue a wakeup for select XXX */ -#endif - } - - return TIMER_ARMED; - } - break; - - case TMR_START: - seq_time = GET_TIME (); - prev_input_time = 0; - prev_event_time = 0; - break; - - case TMR_STOP: - break; - - case TMR_CONTINUE: - break; - - case TMR_TEMPO: - break; - - case TMR_ECHO: - if (seq_mode == SEQ_2) - seq_copy_to_input (event, 8); - else - { - parm = (parm << 8 | SEQ_ECHO); - seq_copy_to_input ((unsigned char *) &parm, 4); - } - break; - - default:; - } - - return TIMER_NOT_ARMED; -} - -static void -seq_local_event (unsigned char *event) -{ - /* unsigned char cmd = event[1]; */ - - printk ("seq_local_event() called. WHY????????\n"); -} - -static int -play_event (unsigned char *q) -{ - /* - * NOTE! This routine returns - * 0 = normal event played. - * 1 = Timer armed. Suspend playback until timer callback. - * 2 = MIDI output buffer full. Restore queue and suspend until timer - */ - unsigned long *delay; - - switch (q[0]) - { - case SEQ_NOTEOFF: - if (synth_open_mask & (1 << 0)) - if (synth_devs[0]) - synth_devs[0]->kill_note (0, q[1], 255, q[3]); - break; - - case SEQ_NOTEON: - if (q[4] < 128 || q[4] == 255) - if (synth_open_mask & (1 << 0)) - if (synth_devs[0]) - synth_devs[0]->start_note (0, q[1], q[2], q[3]); - break; - - case SEQ_WAIT: - delay = (unsigned long *) q; /* - * Bytes 1 to 3 are containing the * - * delay in GET_TIME() - */ - *delay = (*delay >> 8) & 0xffffff; - - if (*delay > 0) - { - long time; - - seq_playing = 1; - time = *delay; - prev_event_time = time; - - request_sound_timer (time); - - if ((SEQ_MAX_QUEUE - qlen) >= output_treshold) - { - unsigned long flags; - - DISABLE_INTR (flags); - if (SOMEONE_WAITING (seq_sleeper, seq_sleep_flag)) - { - WAKE_UP (seq_sleeper, seq_sleep_flag); - } - RESTORE_INTR (flags); -#if defined(__FreeBSD__) - /* must issue a wakeup for selects XXX */ -#endif - } - /* - * The timer is now active and will reinvoke this function - * after the timer expires. Return to the caller now. - */ - return 1; - } - break; - - case SEQ_PGMCHANGE: - if (synth_open_mask & (1 << 0)) - if (synth_devs[0]) - synth_devs[0]->set_instr (0, q[1], q[2]); - break; - - case SEQ_SYNCTIMER: /* - * Reset timer - */ - seq_time = GET_TIME (); - prev_input_time = 0; - prev_event_time = 0; - break; - - case SEQ_MIDIPUTC: /* - * Put a midi character - */ - if (midi_opened[q[2]]) - { - int dev; - - dev = q[2]; - - if (!midi_devs[dev]->putc (dev, q[1])) - { - /* - * Output FIFO is full. Wait one timer cycle and try again. - */ - - seq_playing = 1; - request_sound_timer (-1); - return 2; - } - else - midi_written[dev] = 1; - } - break; - - case SEQ_ECHO: - seq_copy_to_input (q, 4); /* - * Echo back to the process - */ - break; - - case SEQ_PRIVATE: - if ((int) q[1] < max_synthdev) - synth_devs[q[1]]->hw_control (q[1], q); - break; - - case SEQ_EXTENDED: - extended_event (q); - break; - - case EV_CHN_VOICE: - seq_chn_voice_event (q); - break; - - case EV_CHN_COMMON: - seq_chn_common_event (q); - break; - - case EV_TIMING: - if (seq_timing_event (q) == TIMER_ARMED) - { - return 1; - } - break; - - case EV_SEQ_LOCAL: - seq_local_event (q); - break; - - default:; - } - - return 0; -} - -static void -seq_startplay (void) -{ - unsigned long flags; - int this_one, action; - - while (qlen > 0) - { - - DISABLE_INTR (flags); - qhead = ((this_one = qhead) + 1) % SEQ_MAX_QUEUE; - qlen--; - RESTORE_INTR (flags); - - seq_playing = 1; - - if ((action = play_event (&queue[this_one * EV_SZ]))) - { /* Suspend playback. Next timer routine invokes this routine again */ - if (action == 2) - { - qlen++; - qhead = this_one; - } - return; - } - - } - - seq_playing = 0; - - if ((SEQ_MAX_QUEUE - qlen) >= output_treshold) - { - unsigned long flags; - - DISABLE_INTR (flags); - if (SOMEONE_WAITING (seq_sleeper, seq_sleep_flag)) - { - WAKE_UP (seq_sleeper, seq_sleep_flag); - } - RESTORE_INTR (flags); -#if defined(__FreeBSD__) - /* must issue a wakeup for selects XXX */ -#endif - } -} - -static void -reset_controllers (int dev, unsigned char *controller, int update_dev) -{ - - int i; - - for (i = 0; i < 128; i++) - controller[i] = ctrl_def_values[i]; -} - -static void -setup_mode2 (void) -{ - int dev; - - max_synthdev = num_synths; - - for (dev = 0; dev < num_midis; dev++) - if (midi_devs[dev]->converter != NULL) - { - synth_devs[max_synthdev++] = - midi_devs[dev]->converter; - } - - for (dev = 0; dev < max_synthdev; dev++) - { - int chn; - - for (chn = 0; chn < 16; chn++) - { - synth_devs[dev]->chn_info[chn].pgm_num = 0; - reset_controllers (dev, - synth_devs[dev]->chn_info[chn].controllers, - 0); - synth_devs[dev]->chn_info[chn].bender_value = (1 << 7); /* Neutral */ - } - } - - max_mididev = 0; - seq_mode = SEQ_2; -} - -int -sequencer_open (int dev, struct fileinfo *file) -{ - int retval, mode, i; - int level, tmp; - - level = ((dev & 0x0f) == SND_DEV_SEQ2) ? 2 : 1; - - dev = dev >> 4; - mode = file->mode & O_ACCMODE; - - DEB (printk ("sequencer_open(dev=%d)\n", dev)); - - if (!sequencer_ok) - { - printk ("Soundcard: Sequencer not initialized\n"); - return RET_ERROR (ENXIO); - } - - if (dev) /* - * Patch manager device - */ - { - int err; - - dev--; - - if (dev >= MAX_SYNTH_DEV) - return RET_ERROR (ENXIO); - if (pmgr_present[dev]) - return RET_ERROR (EBUSY); - if ((err = pmgr_open (dev)) < 0) - return err; /* - * Failed - */ - - pmgr_present[dev] = 1; - return err; - } - - if (sequencer_busy) - { - printk ("Sequencer busy\n"); - return RET_ERROR (EBUSY); - } - - max_mididev = num_midis; - max_synthdev = num_synths; - pre_event_timeout = 0; - seq_mode = SEQ_1; - - if (pending_timer != -1) - { - tmr_no = pending_timer; - pending_timer = -1; - } - - if (tmr_no == -1) /* Not selected yet */ - { - int i, best; - - best = -1; - for (i = 0; i < num_sound_timers; i++) - if (sound_timer_devs[i]->priority > best) - { - tmr_no = i; - best = sound_timer_devs[i]->priority; - } - - if (tmr_no == -1) /* Should not be */ - tmr_no = 0; - } - - tmr = sound_timer_devs[tmr_no]; - - if (level == 2) - { - if (tmr == NULL) - { - printk ("sequencer: No timer for level 2\n"); - return RET_ERROR (ENXIO); - } - setup_mode2 (); - } - - if (seq_mode == SEQ_1 && (mode == OPEN_READ || mode == OPEN_READWRITE)) - if (!max_mididev) - { - printk ("Sequencer: No Midi devices. Input not possible\n"); - return RET_ERROR (ENXIO); - } - - if (!max_synthdev && !max_mididev) - return RET_ERROR (ENXIO); - - synth_open_mask = 0; - - for (i = 0; i < max_mididev; i++) - { - midi_opened[i] = 0; - midi_written[i] = 0; - } - - /* - * if (mode == OPEN_WRITE || mode == OPEN_READWRITE) - */ - for (i = 0; i < max_synthdev; i++) /* - * Open synth devices - */ - if ((tmp = synth_devs[i]->open (i, mode)) < 0) - { - printk ("Sequencer: Warning! Cannot open synth device #%d (%d)\n", i, tmp); - if (synth_devs[i]->midi_dev) - printk ("(Maps to MIDI dev #%d)\n", synth_devs[i]->midi_dev); - } - else - { - synth_open_mask |= (1 << i); - if (synth_devs[i]->midi_dev) /* - * Is a midi interface - */ - midi_opened[synth_devs[i]->midi_dev] = 1; - } - - seq_time = GET_TIME (); - prev_input_time = 0; - prev_event_time = 0; - - if (seq_mode == SEQ_1 && (mode == OPEN_READ || mode == OPEN_READWRITE)) - { /* - * Initialize midi input devices - */ - for (i = 0; i < max_mididev; i++) - if (!midi_opened[i]) - { - if ((retval = midi_devs[i]->open (i, mode, - sequencer_midi_input, sequencer_midi_output)) >= 0) - midi_opened[i] = 1; - } - } - - if (seq_mode == SEQ_2) - { - tmr->open (tmr_no, seq_mode); - } - - sequencer_busy = 1; - RESET_WAIT_QUEUE (seq_sleeper, seq_sleep_flag); - RESET_WAIT_QUEUE (midi_sleeper, midi_sleep_flag); - output_treshold = SEQ_MAX_QUEUE / 2; - - for (i = 0; i < num_synths; i++) - if (pmgr_present[i]) - pmgr_inform (i, PM_E_OPENED, 0, 0, 0, 0); - - return 0; -} - -void -seq_drain_midi_queues (void) -{ - int i, n; - - /* - * Give the Midi drivers time to drain their output queues - */ - - n = 1; - - while (!PROCESS_ABORTING (seq_sleeper, seq_sleep_flag) && n) - { - n = 0; - - for (i = 0; i < max_mididev; i++) - if (midi_opened[i] && midi_written[i]) - if (midi_devs[i]->buffer_status != NULL) - if (midi_devs[i]->buffer_status (i)) - n++; - - /* - * Let's have a delay - */ - if (n) - { - DO_SLEEP (seq_sleeper, seq_sleep_flag, HZ / 10); - } - } -} - -void -sequencer_release (int dev, struct fileinfo *file) -{ - int i; - int mode = file->mode & O_ACCMODE; - - dev = dev >> 4; - - DEB (printk ("sequencer_release(dev=%d)\n", dev)); - - if (dev) /* - * Patch manager device - */ - { - dev--; - pmgr_release (dev); - pmgr_present[dev] = 0; - return; - } - - /* - * * Wait until the queue is empty (if we don't have nonblock) - */ - - if (mode != OPEN_READ && !ISSET_FILE_FLAG (file, O_NONBLOCK)) - while (!PROCESS_ABORTING (seq_sleeper, seq_sleep_flag) && qlen) - { - seq_sync (); - } - - if (mode != OPEN_READ) - seq_drain_midi_queues (); /* - * Ensure the output queues are empty - */ - seq_reset (); - if (mode != OPEN_READ) - seq_drain_midi_queues (); /* - * Flush the all notes off messages - */ - - for (i = 0; i < max_synthdev; i++) - if (synth_open_mask & (1 << i)) /* - * Actually opened - */ - if (synth_devs[i]) - { - synth_devs[i]->close (i); - - if (synth_devs[i]->midi_dev) - midi_opened[synth_devs[i]->midi_dev] = 0; - } - - for (i = 0; i < num_synths; i++) - if (pmgr_present[i]) - pmgr_inform (i, PM_E_CLOSED, 0, 0, 0, 0); - - for (i = 0; i < max_mididev; i++) - if (midi_opened[i]) - midi_devs[i]->close (i); - - if (seq_mode == SEQ_2) - tmr->close (tmr_no); - - sequencer_busy = 0; -} - -static int -seq_sync (void) -{ - unsigned long flags; - - if (qlen && !seq_playing && !PROCESS_ABORTING (seq_sleeper, seq_sleep_flag)) - seq_startplay (); - - DISABLE_INTR (flags); - if (qlen && !SOMEONE_WAITING (seq_sleeper, seq_sleep_flag)) - { - DO_SLEEP (seq_sleeper, seq_sleep_flag, 0); - } - RESTORE_INTR (flags); - - return qlen; -} - -static void -midi_outc (int dev, unsigned char data) -{ - /* - * NOTE! Calls sleep(). Don't call this from interrupt. - */ - - int n; - unsigned long flags; - - /* - * This routine sends one byte to the Midi channel. - * If the output Fifo is full, it waits until there - * is space in the queue - */ - - n = 3 * HZ; /* Timeout */ - - DISABLE_INTR (flags); - while (n && !midi_devs[dev]->putc (dev, data)) - { - DO_SLEEP (seq_sleeper, seq_sleep_flag, 4); - n--; - } - RESTORE_INTR (flags); -} - -static void -seq_reset (void) -{ - /* - * NOTE! Calls sleep(). Don't call this from interrupt. - */ - - int i; - int chn; - unsigned long flags; - - sound_stop_timer (); - seq_time = GET_TIME (); - prev_input_time = 0; - prev_event_time = 0; - - qlen = qhead = qtail = 0; - iqlen = iqhead = iqtail = 0; - - for (i = 0; i < max_synthdev; i++) - if (synth_open_mask & (1 << i)) - if (synth_devs[i]) - synth_devs[i]->reset (i); - - if (seq_mode == SEQ_2) - { - - for (chn = 0; chn < 16; chn++) - for (i = 0; i < max_synthdev; i++) - if (synth_open_mask & (1 << i)) - if (synth_devs[i]) - { - synth_devs[i]->controller (i, chn, 123, 0); /* All notes off */ - synth_devs[i]->controller (i, chn, 121, 0); /* Reset all ctl */ - synth_devs[i]->bender (i, chn, 1 << 13); /* Bender off */ - } - - } - else - /* seq_mode == SEQ_1 */ - { - for (i = 0; i < max_mididev; i++) - if (midi_written[i]) /* - * Midi used. Some notes may still be playing - */ - { - /* - * Sending just a ACTIVE SENSING message should be enough to stop all - * playing notes. Since there are devices not recognizing the - * active sensing, we have to send some all notes off messages also. - */ - midi_outc (i, 0xfe); - - for (chn = 0; chn < 16; chn++) - { - midi_outc (i, - (unsigned char) (0xb0 + (chn & 0x0f))); /* control change */ - midi_outc (i, 0x7b); /* All notes off */ - midi_outc (i, 0); /* Dummy parameter */ - } - - midi_devs[i]->close (i); - - midi_written[i] = 0; - midi_opened[i] = 0; - } - } - - seq_playing = 0; - - DISABLE_INTR (flags); - if (SOMEONE_WAITING (seq_sleeper, seq_sleep_flag)) - { - /* printk ("Sequencer Warning: Unexpected sleeping process - Waking up\n"); */ - WAKE_UP (seq_sleeper, seq_sleep_flag); - } - RESTORE_INTR (flags); - -} - -static void -seq_panic (void) -{ - /* - * This routine is called by the application in case the user - * wants to reset the system to the default state. - */ - - seq_reset (); - - /* - * Since some of the devices don't recognize the active sensing and - * all notes off messages, we have to shut all notes manually. - * - * TO BE IMPLEMENTED LATER - */ - - /* - * Also return the controllers to their default states - */ -} - -int -sequencer_ioctl (int dev, struct fileinfo *file, - unsigned int cmd, unsigned int arg) -{ - int midi_dev, orig_dev; - int mode = file->mode & O_ACCMODE; - - orig_dev = dev = dev >> 4; - - switch (cmd) - { - case SNDCTL_TMR_TIMEBASE: - case SNDCTL_TMR_TEMPO: - case SNDCTL_TMR_START: - case SNDCTL_TMR_STOP: - case SNDCTL_TMR_CONTINUE: - case SNDCTL_TMR_METRONOME: - case SNDCTL_TMR_SOURCE: - if (dev) /* Patch manager */ - return RET_ERROR (EIO); - - if (seq_mode != SEQ_2) - return RET_ERROR (EINVAL); - return tmr->ioctl (tmr_no, cmd, arg); - break; - - case SNDCTL_TMR_SELECT: - if (dev) /* Patch manager */ - return RET_ERROR (EIO); - - if (seq_mode != SEQ_2) - return RET_ERROR (EINVAL); - pending_timer = IOCTL_IN (arg); - - if (pending_timer < 0 || pending_timer >= num_sound_timers) - { - pending_timer = -1; - return RET_ERROR (EINVAL); - } - - return IOCTL_OUT (arg, pending_timer); - break; - - case SNDCTL_SEQ_PANIC: - seq_panic (); - break; - - case SNDCTL_SEQ_SYNC: - if (dev) /* - * Patch manager - */ - return RET_ERROR (EIO); - - if (mode == OPEN_READ) - return 0; - while (qlen && !PROCESS_ABORTING (seq_sleeper, seq_sleep_flag)) - seq_sync (); - if (qlen) - return RET_ERROR (EINTR); - else - return 0; - break; - - case SNDCTL_SEQ_RESET: - if (dev) /* - * Patch manager - */ - return RET_ERROR (EIO); - - seq_reset (); - return 0; - break; - - case SNDCTL_SEQ_TESTMIDI: - if (dev) /* - * Patch manager - */ - return RET_ERROR (EIO); - - midi_dev = IOCTL_IN (arg); - if (midi_dev >= max_mididev) - return RET_ERROR (ENXIO); - - if (!midi_opened[midi_dev]) - { - int err, mode; - - mode = file->mode & O_ACCMODE; - if ((err = midi_devs[midi_dev]->open (midi_dev, mode, - sequencer_midi_input, - sequencer_midi_output)) < 0) - return err; - } - - midi_opened[midi_dev] = 1; - - return 0; - break; - - case SNDCTL_SEQ_GETINCOUNT: - if (dev) /* - * Patch manager - */ - return RET_ERROR (EIO); - - if (mode == OPEN_WRITE) - return 0; - return IOCTL_OUT (arg, iqlen); - break; - - case SNDCTL_SEQ_GETOUTCOUNT: - - if (mode == OPEN_READ) - return 0; - return IOCTL_OUT (arg, SEQ_MAX_QUEUE - qlen); - break; - - case SNDCTL_SEQ_CTRLRATE: - if (dev) /* Patch manager */ - return RET_ERROR (EIO); - - /* - * If *arg == 0, just return the current rate - */ - if (seq_mode == SEQ_2) - return tmr->ioctl (tmr_no, cmd, arg); - - if (IOCTL_IN (arg) != 0) - return RET_ERROR (EINVAL); - - return IOCTL_OUT (arg, HZ); - break; - - case SNDCTL_SEQ_RESETSAMPLES: - dev = IOCTL_IN (arg); - if (dev < 0 || dev >= num_synths) - return RET_ERROR (ENXIO); - - if (!(synth_open_mask & (1 << dev)) && !orig_dev) - return RET_ERROR (EBUSY); - - if (!orig_dev && pmgr_present[dev]) - pmgr_inform (dev, PM_E_PATCH_RESET, 0, 0, 0, 0); - - return synth_devs[dev]->ioctl (dev, cmd, arg); - break; - - case SNDCTL_SEQ_NRSYNTHS: - return IOCTL_OUT (arg, max_synthdev); - break; - - case SNDCTL_SEQ_NRMIDIS: - return IOCTL_OUT (arg, max_mididev); - break; - - case SNDCTL_SYNTH_MEMAVL: - { - int dev = IOCTL_IN (arg); - - if (dev < 0 || dev >= num_synths) - return RET_ERROR (ENXIO); - - if (!(synth_open_mask & (1 << dev)) && !orig_dev) - return RET_ERROR (EBUSY); - - return IOCTL_OUT (arg, synth_devs[dev]->ioctl (dev, cmd, arg)); - } - break; - - case SNDCTL_FM_4OP_ENABLE: - { - int dev = IOCTL_IN (arg); - - if (dev < 0 || dev >= num_synths) - return RET_ERROR (ENXIO); - - if (!(synth_open_mask & (1 << dev))) - return RET_ERROR (ENXIO); - - synth_devs[dev]->ioctl (dev, cmd, arg); - return 0; - } - break; - - case SNDCTL_SYNTH_INFO: - { - struct synth_info inf; - int dev; - - IOCTL_FROM_USER ((char *) &inf, (char *) arg, 0, sizeof (inf)); - dev = inf.device; - - if (dev < 0 || dev >= max_synthdev) - return RET_ERROR (ENXIO); - - if (!(synth_open_mask & (1 << dev)) && !orig_dev) - return RET_ERROR (EBUSY); - - return synth_devs[dev]->ioctl (dev, cmd, arg); - } - break; - - case SNDCTL_SEQ_OUTOFBAND: - { - struct seq_event_rec event; - unsigned long flags; - - IOCTL_FROM_USER ((char *) &event, (char *) arg, 0, sizeof (event)); - - DISABLE_INTR (flags); - play_event (event.arr); - RESTORE_INTR (flags); - - return 0; - } - break; - - case SNDCTL_MIDI_INFO: - { - struct midi_info inf; - int dev; - - IOCTL_FROM_USER ((char *) &inf, (char *) arg, 0, sizeof (inf)); - dev = inf.device; - - if (dev < 0 || dev >= max_mididev) - return RET_ERROR (ENXIO); - - IOCTL_TO_USER ((char *) arg, 0, (char *) &(midi_devs[dev]->info), sizeof (inf)); - return 0; - } - break; - - case SNDCTL_PMGR_IFACE: - { - struct patmgr_info *inf; - int dev, err; - - if ((inf = (struct patmgr_info *) KERNEL_MALLOC (sizeof (*inf))) == NULL) - { - printk ("patmgr: Can't allocate memory for a message\n"); - return RET_ERROR (EIO); - } - - IOCTL_FROM_USER ((char *) inf, (char *) arg, 0, sizeof (*inf)); - dev = inf->device; - - if (dev < 0 || dev >= num_synths) - { - KERNEL_FREE (inf); - return RET_ERROR (ENXIO); - } - - if (!synth_devs[dev]->pmgr_interface) - { - KERNEL_FREE (inf); - return RET_ERROR (ENXIO); - } - - if ((err = synth_devs[dev]->pmgr_interface (dev, inf)) == -1) - { - KERNEL_FREE (inf); - return err; - } - - IOCTL_TO_USER ((char *) arg, 0, (char *) inf, sizeof (*inf)); - KERNEL_FREE (inf); - return 0; - } - break; - - case SNDCTL_PMGR_ACCESS: - { - struct patmgr_info *inf; - int dev, err; - - if ((inf = (struct patmgr_info *) KERNEL_MALLOC (sizeof (*inf))) == NULL) - { - printk ("patmgr: Can't allocate memory for a message\n"); - return RET_ERROR (EIO); - } - - IOCTL_FROM_USER ((char *) inf, (char *) arg, 0, sizeof (*inf)); - dev = inf->device; - - if (dev < 0 || dev >= num_synths) - { - KERNEL_FREE (inf); - return RET_ERROR (ENXIO); - } - - if (!pmgr_present[dev]) - { - KERNEL_FREE (inf); - return RET_ERROR (ESRCH); - } - - if ((err = pmgr_access (dev, inf)) < 0) - { - KERNEL_FREE (inf); - return err; - } - - IOCTL_TO_USER ((char *) arg, 0, (char *) inf, sizeof (*inf)); - KERNEL_FREE (inf); - return 0; - } - break; - - case SNDCTL_SEQ_TRESHOLD: - { - int tmp = IOCTL_IN (arg); - - if (dev) /* - * Patch manager - */ - return RET_ERROR (EIO); - - if (tmp < 1) - tmp = 1; - if (tmp >= SEQ_MAX_QUEUE) - tmp = SEQ_MAX_QUEUE - 1; - output_treshold = tmp; - return 0; - } - break; - - case SNDCTL_MIDI_PRETIME: - { - int val = IOCTL_IN (arg); - - if (val < 0) - val = 0; - - val = (HZ * val) / 10; - pre_event_timeout = val; - return IOCTL_OUT (arg, val); - } - break; - - default: - if (dev) /* - * Patch manager - */ - return RET_ERROR (EIO); - - if (mode == OPEN_READ) - return RET_ERROR (EIO); - - if (!synth_devs[0]) - return RET_ERROR (ENXIO); - if (!(synth_open_mask & (1 << 0))) - return RET_ERROR (ENXIO); - return synth_devs[0]->ioctl (0, cmd, arg); - break; - } - - return RET_ERROR (EINVAL); -} - -#ifdef ALLOW_SELECT -int -sequencer_select (int dev, struct fileinfo *file, int sel_type, select_table * wait) -{ - unsigned long flags; - - dev = dev >> 4; - - switch (sel_type) - { - case SEL_IN: - DISABLE_INTR (flags); - if (!iqlen) - { -#if defined(__FreeBSD__) - selrecord(wait, &selinfo[dev]); -#else - midi_sleep_flag.mode = WK_SLEEP; - select_wait (&midi_sleeper, wait); -#endif - RESTORE_INTR (flags); - return 0; - } - midi_sleep_flag.mode &= ~WK_SLEEP; - RESTORE_INTR (flags); - return 1; - break; - - case SEL_OUT: - DISABLE_INTR (flags); - if (qlen >= SEQ_MAX_QUEUE) - { -#if defined(__FreeBSD__) - selrecord(wait, &selinfo[dev]); -#else - seq_sleep_flag.mode = WK_SLEEP; - select_wait (&seq_sleeper, wait); -#endif - RESTORE_INTR (flags); - return 0; - } - seq_sleep_flag.mode &= ~WK_SLEEP; - RESTORE_INTR (flags); - return 1; - break; - - case SEL_EX: - return 0; - } - - return 0; -} - -#endif - -void -sequencer_timer (void) -{ - seq_startplay (); -} - -int -note_to_freq (int note_num) -{ - - /* - * This routine converts a midi note to a frequency (multiplied by 1000) - */ - - int note, octave, note_freq; - int notes[] = - { - 261632, 277189, 293671, 311132, 329632, 349232, - 369998, 391998, 415306, 440000, 466162, 493880 - }; - -#define BASE_OCTAVE 5 - - octave = note_num / 12; - note = note_num % 12; - - note_freq = notes[note]; - - if (octave < BASE_OCTAVE) - note_freq >>= (BASE_OCTAVE - octave); - else if (octave > BASE_OCTAVE) - note_freq <<= (octave - BASE_OCTAVE); - - /* - * note_freq >>= 1; - */ - - return note_freq; -} - -unsigned long -compute_finetune (unsigned long base_freq, int bend, int range) -{ - unsigned long amount; - int negative, semitones, cents, multiplier = 1; - - if (!bend) - return base_freq; - if (!range) - return base_freq; - - if (!base_freq) - return base_freq; - - if (range >= 8192) - range = 8191; - - bend = bend * range / 8192; - if (!bend) - return base_freq; - - negative = bend < 0 ? 1 : 0; - - if (bend < 0) - bend *= -1; - if (bend > range) - bend = range; - - /* - if (bend > 2399) - bend = 2399; - */ - while (bend > 2399) - { - multiplier *= 4; - bend -= 2400; - } - - semitones = bend / 100; - cents = bend % 100; - - amount = (int) (semitone_tuning[semitones] * multiplier * cent_tuning[cents]) - / 10000; - - if (negative) - return (base_freq * 10000) / amount; /* - * Bend down - */ - else - return (base_freq * amount) / 10000; /* - * Bend up - */ -} - - -long -sequencer_init (long mem_start) -{ - - sequencer_ok = 1; - PERMANENT_MALLOC (unsigned char *, queue, SEQ_MAX_QUEUE * EV_SZ, mem_start); - PERMANENT_MALLOC (unsigned char *, iqueue, SEQ_MAX_QUEUE * IEV_SZ, mem_start); - - return mem_start; -} - -#else -/* - * Stub version - */ -int -sequencer_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) -{ - return RET_ERROR (EIO); -} - -int -sequencer_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) -{ - return RET_ERROR (EIO); -} - -int -sequencer_open (int dev, struct fileinfo *file) -{ - return RET_ERROR (ENXIO); -} - -void -sequencer_release (int dev, struct fileinfo *file) -{ -} -int -sequencer_ioctl (int dev, struct fileinfo *file, - unsigned int cmd, unsigned int arg) -{ - return RET_ERROR (EIO); -} - -int -sequencer_lseek (int dev, struct fileinfo *file, off_t offset, int orig) -{ - return RET_ERROR (EIO); -} - -long -sequencer_init (long mem_start) -{ - return mem_start; -} - -#ifdef ALLOW_SELECT -int -sequencer_select (int dev, struct fileinfo *file, int sel_type, select_table * wait) -{ - return RET_ERROR (EIO); -} - -#endif - -#endif - -#endif diff --git a/sys/pc98/pc98/sound/sound.doc b/sys/pc98/pc98/sound/sound.doc deleted file mode 100644 index 002bb26..0000000 --- a/sys/pc98/pc98/sound/sound.doc +++ /dev/null @@ -1,120 +0,0 @@ -$Id: sound.doc,v 1.6 1996/04/11 15:34:22 smpatel Exp $ - -Instructions on using audio on a FreeBSD 2.1 (or 2.0-current) system. -See also /sys/i386/conf/LINT. - -To enable sound driver support, the controller sound code must be included -in your config file: - -# SB = SoundBlaster; PAS = ProAudioSpectrum; GUS = Gravis UltraSound -# Controls all sound devices -controller snd0 - -Uncomment one or more of these device entries, depending on what type of -sound card you have: - -# ProAudioSpectrum PCM and Midi - for PAS -#device pas0 at isa? port 0x388 irq 10 drq 6 vector pasintr - -# SoundBlaster DSP driver - for SB, SB Pro, SB16, PAS(emulating SB) -#device sb0 at isa? port 0x220 irq 7 drq 1 vector sbintr - -# SoundBlaster 16 DSP driver - for SB16 - requires sb0 device -#device sbxvi0 at isa? drq 5 - -# SoundBlaster 16 MIDI - for SB16 - requires sb0 device -#device sbmidi0 at isa? port 0x300 - -# Gravis UltraSound - for GUS, GUS16, GUSMAX -# For cards that use 2 DMA Channels: -# drq = Write DMA Channel, flags = Read DMA Channel -#device gus0 at isa? port 0x220 irq 11 drq 1 flags 0x3 vector gusintr - -# Gravis UltraSound 16 bit option - for GUS16 - requires gus0 -#device gusxvi0 at isa? port 0x530 irq 7 drq 3 vector adintr - -# MS Sound System (AD1848 Based Boards) -#device mss0 at isa? port 0x530 irq 10 drq 1 vector adintr - -# Yamaha OPL-2/OPL-3 FM - for SB, SB Pro, SB16, PAS -#device opl0 at isa? port 0x388 - -# MPU-401 - for MPU-401 standalone card -#device mpu0 at isa? port 0x330 irq 6 drq 0 - -# 6850 UART Midi -#device uart0 at isa? port 0x330 irq 5 vector "m6850intr" - -You may add one or more of the following depending on what you do and don't -want compiled into your kernel. Note: Excluding things with EXCLUDE_... -is NOT recommended unless you really know what you're doing. - -#options EXCLUDE_AUDIO # NO digital audio support -#options EXCLUDE_SEQUENCER # NO sequencer support -#options EXCLUDE_MIDI # NO MIDI support whatsoever -#options EXCLUDE_SBPRO # EXCLUDE SB Pro support -#options EXCLUDE_SB_EMULATION # NO PAS SB emulation support -#options EXCLUDE_GUS_IODETECT # NO GUS io detection -#options EXCLUDE_PRO_MIDI # NO PAS MIDI support - -Other Options: - -#options SYMPHONY_PAS - Adds some code to make pas work with Symphony chipsets. Only use - this if your pas doesn't work and you have a Symphony chipset. - -#options BROKEN_BUS_CLOCK - Some systems with the OPTI chipset and a PAS will require you to - use this option. Symptoms are that you will hear a lot of clicking and - popping sounds, like a geiger counter, coming out of the PAS even when - it is not playing anything. - -#options MOZART_PORT - Adds support for Mozart (OAK OTI-601). (Part of the MSS driver) - -#options OPTI_MAD16_PORT - Adds support for the OPTI MAD16 Chip. (Part of the MSS driver) - If your soundcard has a chip labeled "OPTi 82C929" then try this. - -#options __SGNXPRO__ - Adds support for the SG NX Pro mixer. (Part of the SB driver) - -#options JAZZ16 - Adds support for the MV Jazz16 (ProSonic etc). (Part of the SB Driver) - -#options SM_WAVE - Adds support for the SoundMan Wave (Part of the SB Driver) - Note: You will need to do some work to get this to work. - See i386/isa/sound/configure.c - -#options SM_GAMES - Adds support for the Logitech SoundMan Games (Part of the SB Driver) - -#options PAS_JOYSTICK_ENABLE - Enables the gameport on the ProAudio Spectrum - -NOTE: The MPU-401 driver may or may not work, and is unfortunately -unverifiable since no one I know has one. If you can test this, -please let me know! Also note that you will have to change these -settings if your soundcard is set for a non-standard address or IRQ. -Please check your documentation (or verify with any provided DOS utilities -that may have come with your card) and set the IRQ or address fields -accordingly. - - -Also: You can configure more then one card on a single DMA using -the conflicts keyword in your configuration file. This is useful for boards -with more then one type of emulation. - - -Probing problems: Since the SB16 uses the same IRQ and addresses for -the different drivers, some of the snd drivers will not be probed because -the kernel thinks there is a conflict. This can be worked-around by -using the "conflicts" keyword on the sb16's device line. - - -For further information, contact multimedia@freebsd.org - - - Jordan Hubbard (jkh@freefall.cdrom.com) - - Steven Wallace (swallace@freefall.cdrom.com) - - Sujal Patel (smpatel@wam.umd.edu) diff --git a/sys/pc98/pc98/sound/sound_calls.h b/sys/pc98/pc98/sound/sound_calls.h deleted file mode 100644 index d52da0b..0000000 --- a/sys/pc98/pc98/sound/sound_calls.h +++ /dev/null @@ -1,272 +0,0 @@ -/* - * DMA buffer calls - */ - -int DMAbuf_open(int dev, int mode); -int DMAbuf_release(int dev, int mode); -int DMAbuf_getwrbuffer(int dev, char **buf, int *size, int dontblock); -int DMAbuf_getrdbuffer(int dev, char **buf, int *len, int dontblock); -int DMAbuf_rmchars(int dev, int buff_no, int c); -int DMAbuf_start_output(int dev, int buff_no, int l); -int DMAbuf_ioctl(int dev, unsigned int cmd, unsigned int arg, int local); -long DMAbuf_init(long mem_start); -int DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode); -int DMAbuf_open_dma (int dev); -void DMAbuf_close_dma (int dev); -void DMAbuf_reset_dma (int dev); -void DMAbuf_inputintr(int dev); -void DMAbuf_outputintr(int dev, int underflow_flag); -#ifdef ALLOW_SELECT -int DMAbuf_select(int dev, struct fileinfo *file, int sel_type, select_table * wait); -#endif - -/* - * System calls for /dev/dsp and /dev/audio - */ - -int audio_read (int dev, struct fileinfo *file, snd_rw_buf *buf, int count); -int audio_write (int dev, struct fileinfo *file, snd_rw_buf *buf, int count); -int audio_open (int dev, struct fileinfo *file); -void audio_release (int dev, struct fileinfo *file); -int audio_ioctl (int dev, struct fileinfo *file, - unsigned int cmd, unsigned int arg); -int audio_lseek (int dev, struct fileinfo *file, off_t offset, int orig); -long audio_init (long mem_start); - -#ifdef ALLOW_SELECT -int audio_select(int dev, struct fileinfo *file, int sel_type, select_table * wait); -#endif - -/* - * System calls for the /dev/sequencer - */ - -int sequencer_read (int dev, struct fileinfo *file, snd_rw_buf *buf, int count); -int sequencer_write (int dev, struct fileinfo *file, snd_rw_buf *buf, int count); -int sequencer_open (int dev, struct fileinfo *file); -void sequencer_release (int dev, struct fileinfo *file); -int sequencer_ioctl (int dev, struct fileinfo *file, - unsigned int cmd, unsigned int arg); -int sequencer_lseek (int dev, struct fileinfo *file, off_t offset, int orig); -long sequencer_init (long mem_start); -void sequencer_timer(void); -int note_to_freq(int note_num); -unsigned long compute_finetune(unsigned long base_freq, int bend, int range); -void seq_input_event(unsigned char *event, int len); -void seq_copy_to_input (unsigned char *event, int len); - -#ifdef ALLOW_SELECT -int sequencer_select(int dev, struct fileinfo *file, int sel_type, select_table * wait); -#endif - -/* - * System calls for the /dev/midi - */ - -int MIDIbuf_read (int dev, struct fileinfo *file, snd_rw_buf *buf, int count); -int MIDIbuf_write (int dev, struct fileinfo *file, snd_rw_buf *buf, int count); -int MIDIbuf_open (int dev, struct fileinfo *file); -void MIDIbuf_release (int dev, struct fileinfo *file); -int MIDIbuf_ioctl (int dev, struct fileinfo *file, - unsigned int cmd, unsigned int arg); -int MIDIbuf_lseek (int dev, struct fileinfo *file, off_t offset, int orig); -void MIDIbuf_bytes_received(int dev, unsigned char *buf, int count); -long MIDIbuf_init(long mem_start); - -#ifdef ALLOW_SELECT -int MIDIbuf_select(int dev, struct fileinfo *file, int sel_type, select_table * wait); -#endif - -/* - * System calls for the generic midi interface. - * - */ - -long CMIDI_init (long mem_start); -int CMIDI_open (int dev, struct fileinfo *file); -int CMIDI_write (int dev, struct fileinfo *file, snd_rw_buf *buf, int count); -int CMIDI_read (int dev, struct fileinfo *file, snd_rw_buf *buf, int count); -int CMIDI_close (int dev, struct fileinfo *file); - -/* - * - * Misc calls from various sources - */ - -/* From soundcard.c */ -long soundcard_init(long mem_start); -void tenmicrosec(void); -void request_sound_timer (int count); -void sound_stop_timer(void); -int snd_set_irq_handler (int interrupt_level, INT_HANDLER_PROTO(), char *name); -void snd_release_irq(int vect); -void sound_dma_malloc(int dev); -void sound_dma_free(int dev); - -/* From sound_switch.c */ -int sound_read_sw (int dev, struct fileinfo *file, snd_rw_buf *buf, int count); -int sound_write_sw (int dev, struct fileinfo *file, snd_rw_buf *buf, int count); -int sound_open_sw (int dev, struct fileinfo *file); -void sound_release_sw (int dev, struct fileinfo *file); -int sound_ioctl_sw (int dev, struct fileinfo *file, - unsigned int cmd, unsigned long arg); - -/* From sb_dsp.c */ -int sb_dsp_detect (struct address_info *hw_config); -long sb_dsp_init (long mem_start, struct address_info *hw_config); -void sb_dsp_disable_midi(void); -int sb_get_irq(void); -void sb_free_irq(void); -int sb_dsp_command (unsigned char val); -int sb_reset_dsp (void); - -/* From sb16_dsp.c */ -void sb16_dsp_interrupt (int irq); -long sb16_dsp_init(long mem_start, struct address_info *hw_config); -int sb16_dsp_detect(struct address_info *hw_config); - -/* From sb16_midi.c */ -void sb16midiintr (int unit); -long attach_sb16midi(long mem_start, struct address_info * hw_config); -int probe_sb16midi(struct address_info *hw_config); -void sb_midi_interrupt(int dummy); - -/* From sb_midi.c */ -void sb_midi_init(int model); - -/* From sb_mixer.c */ -void sb_setmixer (unsigned int port, unsigned int value); -int sb_getmixer (unsigned int port); -void sb_mixer_set_stereo(int mode); -int sb_mixer_init(int major_model); - -/* From opl3.c */ -int opl3_detect (int ioaddr); -long opl3_init(long mem_start); - -/* From sb_card.c */ -long attach_sb_card(long mem_start, struct address_info *hw_config); -int probe_sb(struct address_info *hw_config); - -/* From adlib_card.c */ -long attach_adlib_card(long mem_start, struct address_info *hw_config); -int probe_adlib(struct address_info *hw_config); - -/* From pas_card.c */ -long attach_pas_card(long mem_start, struct address_info *hw_config); -int probe_pas(struct address_info *hw_config); -int pas_set_intr(int mask); -int pas_remove_intr(int mask); -unsigned char pas_read(int ioaddr); -void pas_write(unsigned char data, int ioaddr); - -/* From pas_audio.c */ -void pas_pcm_interrupt(unsigned char status, int cause); -long pas_pcm_init(long mem_start, struct address_info *hw_config); - -/* From pas_mixer.c */ -int pas_init_mixer(void); - -/* From pas_midi.c */ -long pas_midi_init(long mem_start); -void pas_midi_interrupt(void); - -/* From gus_card.c */ -long attach_gus_card(long mem_start, struct address_info * hw_config); -int probe_gus(struct address_info *hw_config); -int gus_set_midi_irq(int num); -long attach_gus_db16(long mem_start, struct address_info * hw_config); -int probe_gus_db16(struct address_info *hw_config); - -/* From gus_wave.c */ -int gus_wave_detect(int baseaddr); -long gus_wave_init(long mem_start, int irq, int dma, int dma_read); -void gus_voice_irq(void); -void gus_write8(int reg, unsigned int data); -void guswave_dma_irq(void); -void gus_delay(void); -int gus_default_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg); - -/* From gus_midi.c */ -long gus_midi_init(long mem_start); -void gus_midi_interrupt(int dummy); - -/* From mpu401.c */ -long attach_mpu401(long mem_start, struct address_info * hw_config); -int probe_mpu401(struct address_info *hw_config); -void mpuintr(INT_HANDLER_PARMS(irq, dummy)); - -/* From uart6850.c */ -long attach_uart6850(long mem_start, struct address_info * hw_config); -int probe_uart6850(struct address_info *hw_config); - -/* From opl3.c */ -void enable_opl3_mode(int left, int right, int both); - -/* From patmgr.c */ -int pmgr_open(int dev); -void pmgr_release(int dev); -int pmgr_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count); -int pmgr_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count); -int pmgr_access(int dev, struct patmgr_info *rec); -int pmgr_inform(int dev, int event, unsigned long parm1, unsigned long parm2, - unsigned long parm3, unsigned long parm4); - -/* From ics2101.c */ -long ics2101_mixer_init(long mem_start); - -/* From sound_timer.c */ -void sound_timer_init(int io_base); -void sound_timer_interrupt(void); - -/* From ad1848.c */ -void ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture); -int ad1848_detect (int io_base); -void ad1848_interrupt (INT_HANDLER_PARMS(irq, dummy)); -long attach_ms_sound(long mem_start, struct address_info * hw_config); -int probe_ms_sound(struct address_info *hw_config); - -/* From pss.c */ -int probe_pss (struct address_info *hw_config); -long attach_pss (long mem_start, struct address_info *hw_config); -int probe_pss_mpu (struct address_info *hw_config); -long attach_pss_mpu (long mem_start, struct address_info *hw_config); -int probe_pss_mss (struct address_info *hw_config); -long attach_pss_mss (long mem_start, struct address_info *hw_config); - -/* From sscape.c */ -int probe_sscape (struct address_info *hw_config); -long attach_sscape (long mem_start, struct address_info *hw_config); -int probe_ss_ms_sound (struct address_info *hw_config); -long attach_ss_ms_sound(long mem_start, struct address_info * hw_config); - -int pss_read (int dev, struct fileinfo *file, snd_rw_buf *buf, int count); -int pss_write (int dev, struct fileinfo *file, snd_rw_buf *buf, int count); -int pss_open (int dev, struct fileinfo *file); -void pss_release (int dev, struct fileinfo *file); -int pss_ioctl (int dev, struct fileinfo *file, - unsigned int cmd, unsigned int arg); -int pss_lseek (int dev, struct fileinfo *file, off_t offset, int orig); -long pss_init(long mem_start); - -#ifdef PC98 -/* From pcm86.c */ -int probe_pcm86(struct address_info *hw_config); -long attach_pcm86(long mem_start, struct address_info *hw_config); -#endif PC98 - -/* From aedsp16.c */ -int InitAEDSP16_SBPRO(struct address_info *hw_config); -int InitAEDSP16_MSS(struct address_info *hw_config); -int InitAEDSP16_MPU401(struct address_info *hw_config); - -/* From midi_synth.c */ -void do_midi_msg (int synthno, unsigned char *msg, int mlen); - -/* From trix.c */ -long attach_trix_wss (long mem_start, struct address_info *hw_config); -int probe_trix_wss (struct address_info *hw_config); -long attach_trix_sb (long mem_start, struct address_info *hw_config); -int probe_trix_sb (struct address_info *hw_config); -long attach_trix_mpu (long mem_start, struct address_info *hw_config); -int probe_trix_mpu (struct address_info *hw_config); diff --git a/sys/pc98/pc98/sound/sound_switch.c b/sys/pc98/pc98/sound/sound_switch.c index 551c1c1..83994e0 100644 --- a/sys/pc98/pc98/sound/sound_switch.c +++ b/sys/pc98/pc98/sound/sound_switch.c @@ -27,11 +27,7 @@ * */ -#ifdef PC98 -#include <pc98/pc98/sound/sound_config.h> -#else #include <i386/isa/sound/sound_config.h> -#endif #ifdef CONFIGURE_SOUNDCARD diff --git a/sys/pc98/pc98/sound/sound_timer.c b/sys/pc98/pc98/sound/sound_timer.c deleted file mode 100644 index 8e4e002..0000000 --- a/sys/pc98/pc98/sound/sound_timer.c +++ /dev/null @@ -1,406 +0,0 @@ -/* - * sound/sound_timer.c - * - * Timer for the level 2 interface of the /dev/sequencer. Uses the - * 80 and 320 usec timers of OPL-3 (PAS16 only) and GUS. - * - * Copyright by Hannu Savolainen 1993 - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. 2. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#define SEQUENCER_C -#include <i386/isa/sound/sound_config.h> - -#ifdef CONFIGURE_SOUNDCARD - -#if !defined(EXCLUDE_SEQUENCER) && (!defined(EXCLUDE_GUS) || (!defined(EXCLUDE_PAS) && !defined(EXCLUDE_YM3812))) - -static volatile int initialized = 0, opened = 0, tmr_running = 0; -static volatile time_t tmr_offs, tmr_ctr; -static volatile unsigned long ticks_offs; -static volatile int curr_tempo, curr_timebase; -static volatile unsigned long curr_ticks; -static volatile unsigned long next_event_time; -static unsigned long prev_event_time; -static volatile int select_addr, data_addr; -static volatile int curr_timer = 0; -static volatile unsigned long usecs_per_tmr; /* Length of the current interval */ - - -static void -timer_command (unsigned int addr, unsigned int val) -{ - int i; - - OUTB ((unsigned char) (addr & 0xff), select_addr); - - for (i = 0; i < 2; i++) - INB (select_addr); - - OUTB ((unsigned char) (val & 0xff), data_addr); - - for (i = 0; i < 2; i++) - INB (select_addr); -} - -static void -arm_timer (int timer, unsigned int interval) -{ - - curr_timer = timer; - - if (timer == 1) - { - gus_write8 (0x46, 256 - interval); /* Set counter for timer 1 */ - gus_write8 (0x45, 0x04); /* Enable timer 1 IRQ */ - timer_command (0x04, 0x01); /* Start timer 1 */ - } - else - { - gus_write8 (0x47, 256 - interval); /* Set counter for timer 2 */ - gus_write8 (0x45, 0x08); /* Enable timer 2 IRQ */ - timer_command (0x04, 0x02); /* Start timer 2 */ - } -} - -static unsigned long -tmr2ticks (int tmr_value) -{ - /* - * Convert timer ticks to MIDI ticks - */ - - unsigned long tmp; - unsigned long scale; - - tmp = tmr_value * usecs_per_tmr; /* Convert to usecs */ - - scale = (60 * 1000000) / (curr_tempo * curr_timebase); /* usecs per MIDI tick */ - - return (tmp + (scale / 2)) / scale; -} - -static void -reprogram_timer (void) -{ - unsigned long usecs_per_tick; - int timer_no, resolution; - int divisor; - - usecs_per_tick = (60 * 1000000) / (curr_tempo * curr_timebase); - - /* - * Don't kill the system by setting too high timer rate - */ - if (usecs_per_tick < 2000) - usecs_per_tick = 2000; - - if (usecs_per_tick > (256 * 80)) - { - timer_no = 2; - resolution = 320; /* usec */ - } - else - { - timer_no = 1; - resolution = 80; /* usec */ - } - - divisor = (usecs_per_tick + (resolution / 2)) / resolution; - usecs_per_tmr = divisor * resolution; - - arm_timer (timer_no, divisor); -} - -static void -tmr_reset (void) -{ - unsigned long flags; - - DISABLE_INTR (flags); - tmr_offs = 0; - ticks_offs = 0; - tmr_ctr = 0; - next_event_time = 0xffffffff; - prev_event_time = 0; - curr_ticks = 0; - RESTORE_INTR (flags); -} - -static int -timer_open (int dev, int mode) -{ - if (opened) - return RET_ERROR (EBUSY); - - tmr_reset (); - curr_tempo = 60; - curr_timebase = HZ; - opened = 1; - reprogram_timer (); - - return 0; -} - -static void -timer_close (int dev) -{ - opened = tmr_running = 0; - gus_write8 (0x45, 0); /* Disable both timers */ -} - -static int -timer_event (int dev, unsigned char *event) -{ - unsigned char cmd = event[1]; - unsigned long parm = *(int *) &event[4]; - - switch (cmd) - { - case TMR_WAIT_REL: - parm += prev_event_time; - case TMR_WAIT_ABS: - if (parm > 0) - { - long time; - - if (parm <= curr_ticks) /* It's the time */ - return TIMER_NOT_ARMED; - - time = parm; - next_event_time = prev_event_time = time; - - return TIMER_ARMED; - } - break; - - case TMR_START: - tmr_reset (); - tmr_running = 1; - reprogram_timer (); - break; - - case TMR_STOP: - tmr_running = 0; - break; - - case TMR_CONTINUE: - tmr_running = 1; - reprogram_timer (); - break; - - case TMR_TEMPO: - if (parm) - { - if (parm < 8) - parm = 8; - if (parm > 250) - parm = 250; - tmr_offs = tmr_ctr; - ticks_offs += tmr2ticks (tmr_ctr); - tmr_ctr = 0; - curr_tempo = parm; - reprogram_timer (); - } - break; - - case TMR_ECHO: - seq_copy_to_input (event, 8); - break; - - default:; - } - - return TIMER_NOT_ARMED; -} - -static unsigned long -timer_get_time (int dev) -{ - if (!opened) - return 0; - - return curr_ticks; -} - -static int -timer_ioctl (int dev, - unsigned int cmd, unsigned int arg) -{ - switch (cmd) - { - case SNDCTL_TMR_SOURCE: - return IOCTL_OUT (arg, TMR_INTERNAL); - break; - - case SNDCTL_TMR_START: - tmr_reset (); - tmr_running = 1; - return 0; - break; - - case SNDCTL_TMR_STOP: - tmr_running = 0; - return 0; - break; - - case SNDCTL_TMR_CONTINUE: - tmr_running = 1; - return 0; - break; - - case SNDCTL_TMR_TIMEBASE: - { - int val = IOCTL_IN (arg); - - if (val) - { - if (val < 1) - val = 1; - if (val > 1000) - val = 1000; - curr_timebase = val; - } - - return IOCTL_OUT (arg, curr_timebase); - } - break; - - case SNDCTL_TMR_TEMPO: - { - int val = IOCTL_IN (arg); - - if (val) - { - if (val < 8) - val = 8; - if (val > 250) - val = 250; - tmr_offs = tmr_ctr; - ticks_offs += tmr2ticks (tmr_ctr); - tmr_ctr = 0; - curr_tempo = val; - reprogram_timer (); - } - - return IOCTL_OUT (arg, curr_tempo); - } - break; - - case SNDCTL_SEQ_CTRLRATE: - if (IOCTL_IN (arg) != 0) /* Can't change */ - return RET_ERROR (EINVAL); - - return IOCTL_OUT (arg, ((curr_tempo * curr_timebase) + 30) / 60); - break; - - case SNDCTL_TMR_METRONOME: - /* NOP */ - break; - - default: - } - - return RET_ERROR (EINVAL); -} - -static void -timer_arm (int dev, long time) -{ - if (time < 0) - time = curr_ticks + 1; - else if (time <= curr_ticks) /* It's the time */ - return; - - next_event_time = prev_event_time = time; - - return; -} - -static struct sound_timer_operations sound_timer = -{ - {"OPL-3/GUS Timer", 0}, - 1, /* Priority */ - 0, /* Local device link */ - timer_open, - timer_close, - timer_event, - timer_get_time, - timer_ioctl, - timer_arm -}; - -void -sound_timer_interrupt (void) -{ - gus_write8 (0x45, 0); /* Ack IRQ */ - timer_command (4, 0x80); /* Reset IRQ flags */ - - if (!opened) - return; - - if (curr_timer == 1) - gus_write8 (0x45, 0x04); /* Start timer 1 again */ - else - gus_write8 (0x45, 0x08); /* Start timer 2 again */ - - if (!tmr_running) - return; - - tmr_ctr++; - curr_ticks = ticks_offs + tmr2ticks (tmr_ctr); - - if (curr_ticks >= next_event_time) - { - next_event_time = 0xffffffff; - sequencer_timer (); - } -} - -void -sound_timer_init (int io_base) -{ - int n; - - if (initialized) - return; /* There is already a similar timer */ - - select_addr = io_base; - data_addr = io_base + 1; - - initialized = 1; - -#if 1 - if (num_sound_timers >= MAX_TIMER_DEV) - n = 0; /* Overwrite the system timer */ - else - n = num_sound_timers++; -#else - n = 0; -#endif - - sound_timer_devs[n] = &sound_timer; -} - -#endif -#endif diff --git a/sys/pc98/pc98/sound/soundcard.c b/sys/pc98/pc98/sound/soundcard.c index 6a85fb9..1709503 100644 --- a/sys/pc98/pc98/sound/soundcard.c +++ b/sys/pc98/pc98/sound/soundcard.c @@ -26,24 +26,16 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: soundcard.c,v 1.5 1996/09/12 11:11:59 asami Exp $ + * $Id: soundcard.c,v 1.6 1996/10/29 08:36:59 asami Exp $ */ -#ifdef PC98 -#include <pc98/pc98/sound/sound_config.h> -#else #include <i386/isa/sound/sound_config.h> -#endif #include <vm/vm.h> #include <vm/vm_extern.h> #ifdef CONFIGURE_SOUNDCARD -#ifdef PC98 -#include <pc98/pc98/sound/dev_table.h> -#else #include <i386/isa/sound/dev_table.h> -#endif #include <i386/isa/isa_device.h> #include <sys/conf.h> #include <sys/kernel.h> diff --git a/sys/pc98/pc98/sound/sscape.c b/sys/pc98/pc98/sound/sscape.c deleted file mode 100644 index 23d39ce..0000000 --- a/sys/pc98/pc98/sound/sscape.c +++ /dev/null @@ -1,1120 +0,0 @@ -/* - * sound/sscape.c - * - * Low level driver for Ensoniq Soundscape - * - * Copyright by Hannu Savolainen 1994 - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. 2. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#include <i386/isa/sound/sound_config.h> - -#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SSCAPE) - -#include <i386/isa/sound/coproc.h> - -/* - * I/O ports - */ -#define MIDI_DATA 0 -#define MIDI_CTRL 1 -#define HOST_CTRL 2 -#define TX_READY 0x02 -#define RX_READY 0x01 -#define HOST_DATA 3 -#define ODIE_ADDR 4 -#define ODIE_DATA 5 - -/* - * Indirect registers - */ -#define GA_INTSTAT_REG 0 -#define GA_INTENA_REG 1 -#define GA_DMAA_REG 2 -#define GA_DMAB_REG 3 -#define GA_INTCFG_REG 4 -#define GA_DMACFG_REG 5 -#define GA_CDCFG_REG 6 -#define GA_SMCFGA_REG 7 -#define GA_SMCFGB_REG 8 -#define GA_HMCTL_REG 9 - -/* - * DMA channel identifiers (A and B) - */ -#define SSCAPE_DMA_A 0 -#define SSCAPE_DMA_B 1 - -#define PORT(name) (devc->base+name) - -/* - * Host commands recognized by the OBP microcode - */ -#define CMD_GEN_HOST_ACK 0x80 -#define CMD_GEN_MPU_ACK 0x81 -#define CMD_GET_BOARD_TYPE 0x82 -#define CMD_SET_CONTROL 0x88 -#define CMD_GET_CONTROL 0x89 -#define CMD_SET_MT32 0x96 -#define CMD_GET_MT32 0x97 -#define CMD_SET_EXTMIDI 0x9b -#define CMD_GET_EXTMIDI 0x9c - -#define CMD_ACK 0x80 - -typedef struct sscape_info - { - int base, irq, dma; - int ok; /* Properly detected */ - int dma_allocated; - int my_audiodev; - int opened; - } - -sscape_info; -static struct sscape_info dev_info = -{0}; -static struct sscape_info *devc = &dev_info; - -DEFINE_WAIT_QUEUE (sscape_sleeper, sscape_sleep_flag); - -#ifdef REVEAL_SPEA -/* Spea and Reveal have assigned interrupt bits differently than Ensoniq */ -static char valid_interrupts[] = -{9, 7, 5, 15}; - -#else -static char valid_interrupts[] = -{9, 5, 7, 10}; - -#endif - -static unsigned char -sscape_read (struct sscape_info *devc, int reg) -{ - unsigned long flags; - unsigned char val; - - DISABLE_INTR (flags); - OUTB (reg, PORT (ODIE_ADDR)); - val = INB (PORT (ODIE_DATA)); - RESTORE_INTR (flags); - return val; -} - -static void -sscape_write (struct sscape_info *devc, int reg, int data) -{ - unsigned long flags; - - DISABLE_INTR (flags); - OUTB (reg, PORT (ODIE_ADDR)); - OUTB (data, PORT (ODIE_DATA)); - RESTORE_INTR (flags); -} - -static void -host_open (struct sscape_info *devc) -{ - OUTB (0x00, PORT (HOST_CTRL)); /* Put the board to the host mode */ -} - -static void -host_close (struct sscape_info *devc) -{ - OUTB (0x03, PORT (HOST_CTRL)); /* Put the board to the MIDI mode */ -} - -static int -host_write (struct sscape_info *devc, unsigned char *data, int count) -{ - unsigned long flags; - int i, timeout; - - DISABLE_INTR (flags); - - /* - * Send the command and data bytes - */ - - for (i = 0; i < count; i++) - { - for (timeout = 10000; timeout > 0; timeout--) - if (INB (PORT (HOST_CTRL)) & TX_READY) - break; - - if (timeout <= 0) - { - RESTORE_INTR (flags); - return 0; - } - - OUTB (data[i], PORT (HOST_DATA)); - } - - - RESTORE_INTR (flags); - - return 1; -} - -static int -host_read (struct sscape_info *devc) -{ - unsigned long flags; - int timeout; - unsigned char data; - - DISABLE_INTR (flags); - - /* - * Read a byte - */ - - for (timeout = 10000; timeout > 0; timeout--) - if (INB (PORT (HOST_CTRL)) & RX_READY) - break; - - if (timeout <= 0) - { - RESTORE_INTR (flags); - return -1; - } - - data = INB (PORT (HOST_DATA)); - - RESTORE_INTR (flags); - - return data; -} - -static int -host_command1 (struct sscape_info *devc, int cmd) -{ - unsigned char buf[10]; - - buf[0] = (unsigned char) (cmd & 0xff); - - return host_write (devc, buf, 1); -} - -static int -host_command2 (struct sscape_info *devc, int cmd, int parm1) -{ - unsigned char buf[10]; - - buf[0] = (unsigned char) (cmd & 0xff); - buf[1] = (unsigned char) (parm1 & 0xff); - - return host_write (devc, buf, 2); -} - -static int -host_command3 (struct sscape_info *devc, int cmd, int parm1, int parm2) -{ - unsigned char buf[10]; - - buf[0] = (unsigned char) (cmd & 0xff); - buf[1] = (unsigned char) (parm1 & 0xff); - buf[2] = (unsigned char) (parm2 & 0xff); - - return host_write (devc, buf, 3); -} - -static void -set_mt32 (struct sscape_info *devc, int value) -{ - host_open (devc); - host_command2 (devc, CMD_SET_MT32, - value ? 1 : 0); - if (host_read (devc) != CMD_ACK) - { - printk ("SNDSCAPE: Setting MT32 mode failed\n"); - } - host_close (devc); -} - -static int -get_board_type (struct sscape_info *devc) -{ - int tmp; - - host_open (devc); - if (!host_command1 (devc, CMD_GET_BOARD_TYPE)) - tmp = -1; - else - tmp = host_read (devc); - host_close (devc); - return tmp; -} - -void -sscapeintr (INT_HANDLER_PARMS (irq, dummy)) -{ - unsigned char bits, tmp; - static int debug = 0; - - printk ("sscapeintr(0x%02x)\n", (bits = sscape_read (devc, GA_INTSTAT_REG))); - if (SOMEONE_WAITING (sscape_sleeper, sscape_sleep_flag)) - { - WAKE_UP (sscape_sleeper, sscape_sleep_flag); - } - - if (bits & 0x02) /* Host interface interrupt */ - { - printk ("SSCAPE: Host interrupt, data=%02x\n", host_read (devc)); - } - -#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI) - if (bits & 0x01) - { - mpuintr (INT_HANDLER_CALL (irq)); - if (debug++ > 10) /* Temporary debugging hack */ - { - sscape_write (devc, GA_INTENA_REG, 0x00); /* Disable all interrupts */ - } - } -#endif - - /* - * Acknowledge interrupts (toggle the interrupt bits) - */ - - tmp = sscape_read (devc, GA_INTENA_REG); - sscape_write (devc, GA_INTENA_REG, (~bits & 0x0e) | (tmp & 0xf1)); - -} - -static void -sscape_enable_intr (struct sscape_info *devc, unsigned intr_bits) -{ - unsigned char temp, orig; - - temp = orig = sscape_read (devc, GA_INTENA_REG); - temp |= intr_bits; - temp |= 0x80; /* Master IRQ enable */ - - if (temp == orig) - return; /* No change */ - - sscape_write (devc, GA_INTENA_REG, temp); -} - -static void -sscape_disable_intr (struct sscape_info *devc, unsigned intr_bits) -{ - unsigned char temp, orig; - - temp = orig = sscape_read (devc, GA_INTENA_REG); - temp &= ~intr_bits; - if ((temp & ~0x80) == 0x00) - temp = 0x00; /* Master IRQ disable */ - if (temp == orig) - return; /* No change */ - - sscape_write (devc, GA_INTENA_REG, temp); -} - -static void -do_dma (struct sscape_info *devc, int dma_chan, unsigned long buf, int blk_size, int mode) -{ - unsigned char temp; - - if (dma_chan != SSCAPE_DMA_A) - { - printk ("SSCAPE: Tried to use DMA channel != A. Why?\n"); - return; - } - - DMAbuf_start_dma (devc->my_audiodev, - buf, - blk_size, mode); - - temp = devc->dma << 4; /* Setup DMA channel select bits */ - if (devc->dma <= 3) - temp |= 0x80; /* 8 bit DMA channel */ - - temp |= 1; /* Trigger DMA */ - sscape_write (devc, GA_DMAA_REG, temp); - temp &= 0xfe; /* Clear DMA trigger */ - sscape_write (devc, GA_DMAA_REG, temp); -} - -static int -verify_mpu (struct sscape_info *devc) -{ - /* - * The SoundScape board could be in three modes (MPU, 8250 and host). - * If the card is not in the MPU mode, enabling the MPU driver will - * cause infinite loop (the driver believes that there is always some - * received data in the buffer. - * - * Detect this by looking if there are more than 10 received MIDI bytes - * (0x00) in the buffer. - */ - - int i; - - for (i = 0; i < 10; i++) - { - if (INB (devc->base + HOST_CTRL) & 0x80) - return 1; - - if (INB (devc->base) != 0x00) - return 1; - } - - printk ("SoundScape: The device is not in the MPU-401 mode\n"); - return 0; -} - -static int -sscape_coproc_open (void *dev_info, int sub_device) -{ - if (sub_device == COPR_MIDI) - { - set_mt32 (devc, 0); - if (!verify_mpu (devc)) - return RET_ERROR (EIO); - } - - return 0; -} - -static void -sscape_coproc_close (void *dev_info, int sub_device) -{ - struct sscape_info *devc = dev_info; - unsigned long flags; - - DISABLE_INTR (flags); - if (devc->dma_allocated) - { - sscape_write (devc, GA_DMAA_REG, 0x20); /* DMA channel disabled */ -#ifndef EXCLUDE_NATIVE_PCM - DMAbuf_close_dma (devc->my_audiodev); -#endif - devc->dma_allocated = 0; - } - RESET_WAIT_QUEUE (sscape_sleeper, sscape_sleep_flag); - RESTORE_INTR (flags); - - return; -} - -static void -sscape_coproc_reset (void *dev_info) -{ -} - -static int -sscape_download_boot (struct sscape_info *devc, unsigned char *block, int size, int flag) -{ - unsigned long flags; - unsigned char temp; - int done, timeout; - - if (flag & CPF_FIRST) - { - /* - * First block. Have to allocate DMA and to reset the board - * before continuing. - */ - - DISABLE_INTR (flags); - if (devc->dma_allocated == 0) - { -#ifndef EXCLUDE_NATIVE_PCM - if (DMAbuf_open_dma (devc->my_audiodev) < 0) - { - RESTORE_INTR (flags); - return 0; - } -#endif - - devc->dma_allocated = 1; - } - RESTORE_INTR (flags); - - sscape_write (devc, GA_HMCTL_REG, - (temp = sscape_read (devc, GA_HMCTL_REG)) & 0x3f); /*Reset */ - - for (timeout = 10000; timeout > 0; timeout--) - sscape_read (devc, GA_HMCTL_REG); /* Delay */ - - /* Take board out of reset */ - sscape_write (devc, GA_HMCTL_REG, - (temp = sscape_read (devc, GA_HMCTL_REG)) | 0x80); - } - - /* - * Transfer one code block using DMA - */ - memcpy (audio_devs[devc->my_audiodev]->dmap->raw_buf[0], block, size); - - DISABLE_INTR (flags); -/******** INTERRUPTS DISABLED NOW ********/ - do_dma (devc, SSCAPE_DMA_A, - audio_devs[devc->my_audiodev]->dmap->raw_buf_phys[0], - size, DMA_MODE_WRITE); - - /* - * Wait until transfer completes. - */ - RESET_WAIT_QUEUE (sscape_sleeper, sscape_sleep_flag); - done = 0; - timeout = 100; - while (!done && timeout-- > 0) - { - int resid; - - DO_SLEEP (sscape_sleeper, sscape_sleep_flag, 1); - clear_dma_ff (devc->dma); - if ((resid = get_dma_residue (devc->dma)) == 0) - done = 1; - } - - RESTORE_INTR (flags); - if (!done) - return 0; - - if (flag & CPF_LAST) - { - /* - * Take the board out of reset - */ - OUTB (0x00, PORT (HOST_CTRL)); - OUTB (0x00, PORT (MIDI_CTRL)); - - temp = sscape_read (devc, GA_HMCTL_REG); - temp |= 0x40; - sscape_write (devc, GA_HMCTL_REG, temp); /* Kickstart the board */ - - /* - * Wait until the ODB wakes up - */ - - DISABLE_INTR (flags); - done = 0; - timeout = 5 * HZ; - while (!done && timeout-- > 0) - { - DO_SLEEP (sscape_sleeper, sscape_sleep_flag, 1); - if (INB (PORT (HOST_DATA)) == 0xff) /* OBP startup acknowledge */ - done = 1; - } - RESTORE_INTR (flags); - if (!done) - { - printk ("SoundScape: The OBP didn't respond after code download\n"); - return 0; - } - - DISABLE_INTR (flags); - done = 0; - timeout = 5 * HZ; - while (!done && timeout-- > 0) - { - DO_SLEEP (sscape_sleeper, sscape_sleep_flag, 1); - if (INB (PORT (HOST_DATA)) == 0xfe) /* Host startup acknowledge */ - done = 1; - } - RESTORE_INTR (flags); - if (!done) - { - printk ("SoundScape: OBP Initialization failed.\n"); - return 0; - } - - printk ("SoundScape board of type %d initialized OK\n", - get_board_type (devc)); - -#ifdef SSCAPE_DEBUG3 - /* - * Temporary debugging aid. Print contents of the registers after - * downloading the code. - */ - { - int i; - - for (i = 0; i < 13; i++) - printk ("I%d = %02x (new value)\n", i, sscape_read (devc, i)); - } -#endif - - } - - return 1; -} - -static int -download_boot_block (void *dev_info, copr_buffer * buf) -{ - if (buf->len <= 0 || buf->len > sizeof (buf->data)) - return RET_ERROR (EINVAL); - - if (!sscape_download_boot (devc, buf->data, buf->len, buf->flags)) - { - printk ("SSCAPE: Unable to load microcode block to the OBP.\n"); - return RET_ERROR (EIO); - } - - return 0; -} - -static int -sscape_coproc_ioctl (void *dev_info, unsigned int cmd, unsigned int arg, int local) -{ - - switch (cmd) - { - case SNDCTL_COPR_RESET: - sscape_coproc_reset (dev_info); - return 0; - break; - - case SNDCTL_COPR_LOAD: - { - copr_buffer *buf; - int err; - - buf = (copr_buffer *) KERNEL_MALLOC (sizeof (copr_buffer)); - IOCTL_FROM_USER ((char *) buf, (char *) arg, 0, sizeof (*buf)); - err = download_boot_block (dev_info, buf); - KERNEL_FREE (buf); - return err; - } - break; - - default: - return RET_ERROR (EINVAL); - } - - return RET_ERROR (EINVAL); -} - -static coproc_operations sscape_coproc_operations = -{ - "SoundScape M68K", - sscape_coproc_open, - sscape_coproc_close, - sscape_coproc_ioctl, - sscape_coproc_reset, - &dev_info -}; - -static int -sscape_audio_open (int dev, int mode) -{ - unsigned long flags; - sscape_info *devc = (sscape_info *) audio_devs[dev]->devc; - - DISABLE_INTR (flags); - if (devc->opened) - { - RESTORE_INTR (flags); - return RET_ERROR (EBUSY); - } - - if (devc->dma_allocated == 0) - { - int err; - - if ((err = DMAbuf_open_dma (devc->my_audiodev)) < 0) - { - RESTORE_INTR (flags); - return err; - } - - devc->dma_allocated = 1; - } - - devc->opened = 1; - RESTORE_INTR (flags); -#ifdef SSCAPE_DEBUG4 - /* - * Temporary debugging aid. Print contents of the registers - * when the device is opened. - */ - { - int i; - - for (i = 0; i < 13; i++) - printk ("I%d = %02x\n", i, sscape_read (devc, i)); - } -#endif - - return 0; -} - -static void -sscape_audio_close (int dev) -{ - unsigned long flags; - sscape_info *devc = (sscape_info *) audio_devs[dev]->devc; - - DEB (printk ("sscape_audio_close(void)\n")); - - DISABLE_INTR (flags); - - if (devc->dma_allocated) - { - sscape_write (devc, GA_DMAA_REG, 0x20); /* DMA channel disabled */ - DMAbuf_close_dma (dev); - devc->dma_allocated = 0; - } - devc->opened = 0; - - RESTORE_INTR (flags); -} - -static int -set_speed (sscape_info * devc, int arg) -{ - return 8000; -} - -static int -set_channels (sscape_info * devc, int arg) -{ - return 1; -} - -static int -set_format (sscape_info * devc, int arg) -{ - return AFMT_U8; -} - -static int -sscape_audio_ioctl (int dev, unsigned int cmd, unsigned int arg, int local) -{ - sscape_info *devc = (sscape_info *) audio_devs[dev]->devc; - - switch (cmd) - { - case SOUND_PCM_WRITE_RATE: - if (local) - return set_speed (devc, arg); - return IOCTL_OUT (arg, set_speed (devc, IOCTL_IN (arg))); - - case SOUND_PCM_READ_RATE: - if (local) - return 8000; - return IOCTL_OUT (arg, 8000); - - case SNDCTL_DSP_STEREO: - if (local) - return set_channels (devc, arg + 1) - 1; - return IOCTL_OUT (arg, set_channels (devc, IOCTL_IN (arg) + 1) - 1); - - case SOUND_PCM_WRITE_CHANNELS: - if (local) - return set_channels (devc, arg); - return IOCTL_OUT (arg, set_channels (devc, IOCTL_IN (arg))); - - case SOUND_PCM_READ_CHANNELS: - if (local) - return 1; - return IOCTL_OUT (arg, 1); - - case SNDCTL_DSP_SAMPLESIZE: - if (local) - return set_format (devc, arg); - return IOCTL_OUT (arg, set_format (devc, IOCTL_IN (arg))); - - case SOUND_PCM_READ_BITS: - if (local) - return 8; - return IOCTL_OUT (arg, 8); - - default:; - } - return RET_ERROR (EINVAL); -} - -static void -sscape_audio_output_block (int dev, unsigned long buf, int count, int intrflag, int dma_restart) -{ -} - -static void -sscape_audio_start_input (int dev, unsigned long buf, int count, int intrflag, int dma_restart) -{ -} - -static int -sscape_audio_prepare_for_input (int dev, int bsize, int bcount) -{ - return 0; -} - -static int -sscape_audio_prepare_for_output (int dev, int bsize, int bcount) -{ - return 0; -} - -static void -sscape_audio_halt (int dev) -{ -} - -static void -sscape_audio_reset (int dev) -{ - sscape_audio_halt (dev); -} - -static struct audio_operations sscape_audio_operations = -{ - "Ensoniq SoundScape channel A", - 0, - AFMT_U8 | AFMT_S16_LE, - NULL, - sscape_audio_open, - sscape_audio_close, - sscape_audio_output_block, - sscape_audio_start_input, - sscape_audio_ioctl, - sscape_audio_prepare_for_input, - sscape_audio_prepare_for_output, - sscape_audio_reset, - sscape_audio_halt, - NULL, - NULL -}; - -long -attach_sscape (long mem_start, struct address_info *hw_config) -{ - int my_dev; - -#ifndef SSCAPE_REGS - /* - * Config register values for Spea/V7 Media FX and Ensoniq S-2000. - * These values are card - * dependent. If you have another SoundScape based card, you have to - * find the correct values. Do the following: - * - Compile this driver with SSCAPE_DEBUG1 defined. - * - Shut down and power off your machine. - * - Boot with DOS so that the SSINIT.EXE program is run. - * - Warm boot to {Linux|SYSV|BSD} and write down the lines displayed - * when detecting the SoundScape. - * - Modify the following list to use the values printed during boot. - * Undefine the SSCAPE_DEBUG1 - */ -#define SSCAPE_REGS { \ -/* I0 */ 0x00, \ - 0xf0, /* Note! Ignored. Set always to 0xf0 */ \ - 0x20, /* Note! Ignored. Set always to 0x20 */ \ - 0x20, /* Note! Ignored. Set always to 0x20 */ \ - 0xf5, /* Ignored */ \ - 0x10, \ - 0x00, \ - 0x2e, /* I7 MEM config A. Likely to vary between models */ \ - 0x00, /* I8 MEM config A. Likely to vary between models */ \ -/* I9 */ 0x40 /* Ignored */ \ - } -#endif - - unsigned long flags; - static unsigned char regs[10] = SSCAPE_REGS; - - int i, irq_bits = 0xff; - - if (!probe_sscape (hw_config)) - return mem_start; - - printk (" <Ensoniq Soundscape>"); - - for (i = 0; i < sizeof (valid_interrupts); i++) - if (hw_config->irq == valid_interrupts[i]) - { - irq_bits = i; - break; - } - - if (hw_config->irq > 15 || (regs[4] = irq_bits == 0xff)) - { - printk ("Invalid IRQ%d\n", hw_config->irq); - return mem_start; - } - - DISABLE_INTR (flags); - - for (i = 1; i < 10; i++) - switch (i) - { - case 1: /* Host interrupt enable */ - sscape_write (devc, i, 0xf0); /* All interrupts enabled */ - break; - - case 2: /* DMA A status/trigger register */ - case 3: /* DMA B status/trigger register */ - sscape_write (devc, i, 0x20); /* DMA channel disabled */ - break; - - case 4: /* Host interrupt config reg */ - sscape_write (devc, i, 0xf0 | (irq_bits << 2) | irq_bits); - break; - - case 5: /* Don't destroy CD-ROM DMA config bits (0xc0) */ - sscape_write (devc, i, (regs[i] & 0x3f) | - (sscape_read (devc, i) & 0x0c)); - break; - - case 6: /* CD-ROM config. Don't touch. */ - break; - - case 9: /* Master control reg. Don't modify CR-ROM bits. Disable SB emul */ - sscape_write (devc, i, - (sscape_read (devc, i) & 0xf0) | 0x00); - break; - - default: - sscape_write (devc, i, regs[i]); - } - - RESTORE_INTR (flags); - -#ifdef SSCAPE_DEBUG2 - /* - * Temporary debugging aid. Print contents of the registers after - * changing them. - */ - { - int i; - - for (i = 0; i < 13; i++) - printk ("I%d = %02x (new value)\n", i, sscape_read (devc, i)); - } -#endif - -#if !defined(EXCLUDE_MIDI) && !defined(EXCLUDE_MPU_EMU) - hw_config->always_detect = 1; - if (probe_mpu401 (hw_config)) - { - int prev_devs; - - prev_devs = num_midis; - mem_start = attach_mpu401 (mem_start, hw_config); - - if (num_midis == (prev_devs + 1)) /* The MPU driver installed itself */ - midi_devs[prev_devs]->coproc = &sscape_coproc_operations; - } -#endif - -#ifndef EXCLUDE_NATIVE_PCM - /* Not supported yet */ - -#ifndef EXCLUDE_AUDIO - if (num_audiodevs < MAX_AUDIO_DEV) - { - audio_devs[my_dev = num_audiodevs++] = &sscape_audio_operations; - audio_devs[my_dev]->dmachan = hw_config->dma; - audio_devs[my_dev]->buffcount = 1; - audio_devs[my_dev]->buffsize = DSP_BUFFSIZE; - audio_devs[my_dev]->devc = devc; - devc->my_audiodev = my_dev; - devc->opened = 0; - audio_devs[my_dev]->coproc = &sscape_coproc_operations; - if (snd_set_irq_handler (hw_config->irq, sscapeintr, "SoundScape") < 0) - printk ("Error: Can't allocate IRQ for SoundScape\n"); - - sscape_write (devc, GA_INTENA_REG, 0x80); /* Master IRQ enable */ - } - else - printk ("SoundScape: More than enough audio devices detected\n"); -#endif -#endif - devc->ok = 1; - return mem_start; -} - -int -probe_sscape (struct address_info *hw_config) -{ - unsigned char save; - - devc->base = hw_config->io_base; - devc->irq = hw_config->irq; - devc->dma = hw_config->dma; - - /* - * First check that the address register of "ODIE" is - * there and that it has exactly 4 writeable bits. - * First 4 bits - */ - if ((save = INB (PORT (ODIE_ADDR))) & 0xf0) - return 0; - - OUTB (0x00, PORT (ODIE_ADDR)); - if (INB (PORT (ODIE_ADDR)) != 0x00) - return 0; - - OUTB (0xff, PORT (ODIE_ADDR)); - if (INB (PORT (ODIE_ADDR)) != 0x0f) - return 0; - - OUTB (save, PORT (ODIE_ADDR)); - - /* - * Now verify that some indirect registers return zero on some bits. - * This may break the driver with some future revisions of "ODIE" but... - */ - - if (sscape_read (devc, 0) & 0x0c) - return 0; - - if (sscape_read (devc, 1) & 0x0f) - return 0; - - if (sscape_read (devc, 5) & 0x0f) - return 0; - -#ifdef SSCAPE_DEBUG1 - /* - * Temporary debugging aid. Print contents of the registers before - * changing them. - */ - { - int i; - - for (i = 0; i < 13; i++) - printk ("I%d = %02x (old value)\n", i, sscape_read (devc, i)); - } -#endif - - return 1; -} - -int -probe_ss_ms_sound (struct address_info *hw_config) -{ - int i, irq_bits = 0xff; - - if (devc->ok == 0) - { - printk ("SoundScape: Invalid initialization order.\n"); - return 0; - } - - for (i = 0; i < sizeof (valid_interrupts); i++) - if (hw_config->irq == valid_interrupts[i]) - { - irq_bits = i; - break; - } -#ifdef REVEAL_SPEA - { - int tmp, status = 0; - int cc; - - if (!((tmp = sscape_read (devc, GA_HMCTL_REG)) & 0xc0)) - { - sscape_write (devc, GA_HMCTL_REG, tmp | 0x80); - for (cc = 0; cc < 200000; ++cc) - INB (devc->base + ODIE_ADDR); - } - } -#endif - - if (hw_config->irq > 15 || irq_bits == 0xff) - { - printk ("SoundScape: Invalid MSS IRQ%d\n", hw_config->irq); - return 0; - } - - return ad1848_detect (hw_config->io_base); -} - -long -attach_ss_ms_sound (long mem_start, struct address_info *hw_config) -{ - /* - * This routine configures the SoundScape card for use with the - * Win Sound System driver. The AD1848 codec interface uses the CD-ROM - * config registers of the "ODIE". - */ - - int i, irq_bits = 0xff; - -#ifdef EXCLUDE_NATIVE_PCM - int prev_devs = num_audiodevs; - -#endif - - /* - * Setup the DMA polarity. - */ - sscape_write (devc, GA_DMACFG_REG, 0x50); - - /* - * Take the gate-arry off of the DMA channel. - */ - sscape_write (devc, GA_DMAB_REG, 0x20); - - /* - * Init the AD1848 (CD-ROM) config reg. - */ - - for (i = 0; i < sizeof (valid_interrupts); i++) - if (hw_config->irq == valid_interrupts[i]) - { - irq_bits = i; - break; - } - - sscape_write (devc, GA_CDCFG_REG, 0x89 | (hw_config->dma << 4) | - (irq_bits << 1)); - - if (hw_config->irq == devc->irq) - printk ("SoundScape: Warning! The WSS mode can't share IRQ with MIDI\n"); - - ad1848_init ("SoundScape", hw_config->io_base, - hw_config->irq, - hw_config->dma, - hw_config->dma); - -#ifdef EXCLUDE_NATIVE_PCM - if (num_audiodevs == (prev_devs + 1)) /* The AD1848 driver installed itself */ - audio_devs[prev_devs]->coproc = &sscape_coproc_operations; -#endif -#ifdef SSCAPE_DEBUG5 - /* - * Temporary debugging aid. Print contents of the registers - * after the AD1848 device has been initialized. - */ - { - int i; - - for (i = 0; i < 13; i++) - printk ("I%d = %02x\n", i, sscape_read (devc, i)); - } -#endif - - return mem_start; -} - -#endif diff --git a/sys/pc98/pc98/sound/sys_timer.c b/sys/pc98/pc98/sound/sys_timer.c deleted file mode 100644 index 8abeacb..0000000 --- a/sys/pc98/pc98/sound/sys_timer.c +++ /dev/null @@ -1,308 +0,0 @@ -/* - * sound/sys_timer.c - * - * The default timer for the Level 2 sequencer interface - * Uses the (100HZ) timer of kernel. - * - * Copyright by Hannu Savolainen 1993 - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. 2. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#define SEQUENCER_C -#ifdef PC98 -#include <pc98/pc98/sound/sound_config.h> -#else -#include <i386/isa/sound/sound_config.h> -#endif - -#ifdef CONFIGURE_SOUNDCARD - -#ifndef EXCLUDE_SEQUENCER - -static volatile int opened = 0, tmr_running = 0; -static volatile time_t tmr_offs, tmr_ctr; -static volatile unsigned long ticks_offs; -static volatile int curr_tempo, curr_timebase; -static volatile unsigned long curr_ticks; -static volatile unsigned long next_event_time; -static unsigned long prev_event_time; - -static void poll_def_tmr (unsigned long dummy); - -DEFINE_TIMER (def_tmr, poll_def_tmr); - -static unsigned long -tmr2ticks (int tmr_value) -{ - /* - * Convert system timer ticks (HZ) to MIDI ticks - */ - - unsigned long tmp; - unsigned long scale; - - tmp = (tmr_value * 1000) / HZ; /* Convert to msecs */ - - scale = (60 * 1000) / (curr_tempo * curr_timebase); /* msecs per MIDI tick */ - - return (tmp + (scale / 2)) / scale; -} - -static void -poll_def_tmr (unsigned long dummy) -{ - - if (opened) - { - ACTIVATE_TIMER (def_tmr, poll_def_tmr, 1); - - if (tmr_running) - { - tmr_ctr++; - curr_ticks = ticks_offs + tmr2ticks (tmr_ctr); - - if (curr_ticks >= next_event_time) - { - next_event_time = 0xffffffff; - sequencer_timer (); - } - } - } -} - -static void -tmr_reset (void) -{ - unsigned long flags; - - DISABLE_INTR (flags); - tmr_offs = 0; - ticks_offs = 0; - tmr_ctr = 0; - next_event_time = 0xffffffff; - prev_event_time = 0; - curr_ticks = 0; - RESTORE_INTR (flags); -} - -static int -def_tmr_open (int dev, int mode) -{ - if (opened) - return RET_ERROR (EBUSY); - - tmr_reset (); - curr_tempo = 60; - curr_timebase = HZ; - opened = 1; - - ACTIVATE_TIMER (def_tmr, poll_def_tmr, 1); - - return 0; -} - -static void -def_tmr_close (int dev) -{ - opened = tmr_running = 0; -} - -static int -def_tmr_event (int dev, unsigned char *event) -{ - unsigned char cmd = event[1]; - unsigned long parm = *(int *) &event[4]; - - switch (cmd) - { - case TMR_WAIT_REL: - parm += prev_event_time; - case TMR_WAIT_ABS: - if (parm > 0) - { - long time; - - if (parm <= curr_ticks) /* It's the time */ - return TIMER_NOT_ARMED; - - time = parm; - next_event_time = prev_event_time = time; - - return TIMER_ARMED; - } - break; - - case TMR_START: - tmr_reset (); - tmr_running = 1; - break; - - case TMR_STOP: - tmr_running = 0; - break; - - case TMR_CONTINUE: - tmr_running = 1; - break; - - case TMR_TEMPO: - if (parm) - { - if (parm < 8) - parm = 8; - if (parm > 250) - parm = 250; - tmr_offs = tmr_ctr; - ticks_offs += tmr2ticks (tmr_ctr); - tmr_ctr = 0; - curr_tempo = parm; - } - break; - - case TMR_ECHO: - seq_copy_to_input (event, 8); - break; - - default:; - } - - return TIMER_NOT_ARMED; -} - -static unsigned long -def_tmr_get_time (int dev) -{ - if (!opened) - return 0; - - return curr_ticks; -} - -static int -def_tmr_ioctl (int dev, - unsigned int cmd, unsigned int arg) -{ - switch (cmd) - { - case SNDCTL_TMR_SOURCE: - return IOCTL_OUT (arg, TMR_INTERNAL); - break; - - case SNDCTL_TMR_START: - tmr_reset (); - tmr_running = 1; - return 0; - break; - - case SNDCTL_TMR_STOP: - tmr_running = 0; - return 0; - break; - - case SNDCTL_TMR_CONTINUE: - tmr_running = 1; - return 0; - break; - - case SNDCTL_TMR_TIMEBASE: - { - int val = IOCTL_IN (arg); - - if (val) - { - if (val < 1) - val = 1; - if (val > 1000) - val = 1000; - curr_timebase = val; - } - - return IOCTL_OUT (arg, curr_timebase); - } - break; - - case SNDCTL_TMR_TEMPO: - { - int val = IOCTL_IN (arg); - - if (val) - { - if (val < 8) - val = 8; - if (val > 250) - val = 250; - tmr_offs = tmr_ctr; - ticks_offs += tmr2ticks (tmr_ctr); - tmr_ctr = 0; - curr_tempo = val; - } - - return IOCTL_OUT (arg, curr_tempo); - } - break; - - case SNDCTL_SEQ_CTRLRATE: - if (IOCTL_IN (arg) != 0) /* Can't change */ - return RET_ERROR (EINVAL); - - return IOCTL_OUT (arg, ((curr_tempo * curr_timebase) + 30) / 60); - break; - - case SNDCTL_TMR_METRONOME: - /* NOP */ - break; - - default:; - } - - return RET_ERROR (EINVAL); -} - -static void -def_tmr_arm (int dev, long time) -{ - if (time < 0) - time = curr_ticks + 1; - else if (time <= curr_ticks) /* It's the time */ - return; - - next_event_time = prev_event_time = time; - - return; -} - -struct sound_timer_operations default_sound_timer = -{ - {"System Timer", 0}, - 0, /* Priority */ - 0, /* Local device link */ - def_tmr_open, - def_tmr_close, - def_tmr_event, - def_tmr_get_time, - def_tmr_ioctl, - def_tmr_arm -}; - -#endif -#endif diff --git a/sys/pc98/pc98/sound/trix.c b/sys/pc98/pc98/sound/trix.c deleted file mode 100644 index 21ca20a..0000000 --- a/sys/pc98/pc98/sound/trix.c +++ /dev/null @@ -1,323 +0,0 @@ -/* - * sound/trix.c - * - * Low level driver for the MediaTriX AudioTriX Pro - * (MT-0002-PC Control Chip) - * - * Copyright by Hannu Savolainen 1995 - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. 2. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#include <i386/isa/sound/sound_config.h> - -#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_TRIX) - -#ifdef INCLUDE_TRIX_BOOT -#include <i386/isa/sound/trix_boot.h> -#endif - -static int kilroy_was_here = 0; /* Don't detect twice */ -static int sb_initialized = 0; -static int mpu_initialized = 0; - -static unsigned char -trix_read (int addr) -{ - OUTB ((unsigned char) addr, 0x390); /* MT-0002-PC ASIC address */ - return INB (0x391); /* MT-0002-PC ASIC data */ -} - -static void -trix_write (int addr, int data) -{ - OUTB ((unsigned char) addr, 0x390); /* MT-0002-PC ASIC address */ - OUTB ((unsigned char) data, 0x391); /* MT-0002-PC ASIC data */ -} - -static void -download_boot (int base) -{ - int i = 0, n = sizeof (trix_boot); - - trix_write (0xf8, 0x00); /* ??????? */ - OUTB (0x01, base + 6); /* Clear the internal data pointer */ - OUTB (0x00, base + 6); /* Restart */ - - /* - * Write the boot code to the RAM upload/download register. - * Each write increments the internal data pointer. - */ - OUTB (0x01, base + 6); /* Clear the internal data pointer */ - OUTB (0x1A, 0x390); /* Select RAM download/upload port */ - - for (i = 0; i < n; i++) - OUTB (trix_boot[i], 0x391); - for (i = n; i < 10016; i++) /* Clear up to first 16 bytes of data RAM */ - OUTB (0x00, 0x391); - OUTB (0x00, base + 6); /* Reset */ - OUTB (0x50, 0x390); /* ?????? */ -} - -static int -trix_set_wss_port (struct address_info *hw_config) -{ - unsigned char addr_bits; - - if (kilroy_was_here) /* Already initialized */ - return 0; - - kilroy_was_here = 1; - - if (trix_read (0x15) != 0x71) /* No asic signature */ - return 0; - - /* - * Disable separate wave playback and recording DMA channels since - * the driver doesn't support duplex mode yet. - */ - - trix_write (0x13, trix_read (0x13) & ~0x80); - trix_write (0x14, trix_read (0x14) & ~0x80); - - /* - * Configure the ASIC to place the codec to the proper I/O location - */ - - switch (hw_config->io_base) - { - case 0x530: - addr_bits = 0; - break; - case 0x604: - addr_bits = 1; - break; - case 0xE80: - addr_bits = 2; - break; - case 0xF40: - addr_bits = 3; - break; - default: - return 0; - } - - trix_write (0x19, (trix_read (0x19) & 0x03) | addr_bits); - return 1; -} - -/* - * Probe and attach routines for the Windows Sound System mode of - * AudioTriX Pro - */ - -int -probe_trix_wss (struct address_info *hw_config) -{ - /* - * Check if the IO port returns valid signature. The original MS Sound - * system returns 0x04 while some cards (AudioTriX Pro for example) - * return 0x00. - */ - if (!trix_set_wss_port (hw_config)) - return 0; - - if ((INB (hw_config->io_base + 3) & 0x3f) != 0x00) - { - DDB (printk ("No MSS signature detected on port 0x%x\n", hw_config->io_base)); - return 0; - } - - if (hw_config->irq > 11) - { - printk ("AudioTriX: Bad WSS IRQ %d\n", hw_config->irq); - return 0; - } - - if (hw_config->dma != 0 && hw_config->dma != 1 && hw_config->dma != 3) - { - printk ("AudioTriX: Bad WSS DMA %d\n", hw_config->dma); - return 0; - } - - /* - * Check that DMA0 is not in use with a 8 bit board. - */ - - if (hw_config->dma == 0 && INB (hw_config->io_base + 3) & 0x80) - { - printk ("AudioTriX: Can't use DMA0 with a 8 bit card\n"); - return 0; - } - - if (hw_config->irq > 7 && hw_config->irq != 9 && INB (hw_config->io_base + 3) & 0x80) - { - printk ("AudioTriX: Can't use IRQ%d with a 8 bit card\n", hw_config->irq); - return 0; - } - - return ad1848_detect (hw_config->io_base + 4); -} - -long -attach_trix_wss (long mem_start, struct address_info *hw_config) -{ - static unsigned char interrupt_bits[12] = - {-1, -1, -1, -1, -1, -1, -1, 0x08, -1, 0x10, 0x18, 0x20}; - char bits; - - static unsigned char dma_bits[4] = - {1, 2, 0, 3}; - - int config_port = hw_config->io_base + 0, version_port = hw_config->io_base + 3; - - if (!kilroy_was_here) - return mem_start; - - /* - * Set the IRQ and DMA addresses. - */ - - bits = interrupt_bits[hw_config->irq]; - if (bits == -1) - return mem_start; - - OUTB (bits | 0x40, config_port); - if ((INB (version_port) & 0x40) == 0) - printk ("[IRQ Conflict?]"); - - OUTB (bits | dma_bits[hw_config->dma], config_port); /* Write IRQ+DMA setup */ - - ad1848_init ("AudioTriX Pro", hw_config->io_base + 4, - hw_config->irq, - hw_config->dma, - hw_config->dma); - return mem_start; -} - -int -probe_trix_sb (struct address_info *hw_config) -{ - - int tmp; - unsigned char conf; - static char irq_translate[] = - {-1, -1, -1, 0, 1, 2, -1, 3}; - -#ifndef INCLUDE_TRIX_BOOT - return 0; /* No boot code -> no fun */ -#endif - if (!kilroy_was_here) - return 0; /* AudioTriX Pro has not been detected earlier */ - - if (sb_initialized) - return 0; - - if (hw_config->io_base & 0xffffff8f != 0x200) - return 0; - - tmp = hw_config->irq; - if (tmp > 7) - return 0; - if (irq_translate[tmp] == -1) - return 0; - - tmp = hw_config->dma; - if (tmp != 1 && tmp != 3) - return 0; - - conf = 0x84; /* DMA and IRQ enable */ - conf |= hw_config->io_base & 0x70; /* I/O address bits */ - conf |= irq_translate[hw_config->irq]; - if (hw_config->dma == 3) - conf |= 0x08; - trix_write (0x1b, conf); - - download_boot (hw_config->io_base); - sb_initialized = 1; - - return 1; -} - -long -attach_trix_sb (long mem_start, struct address_info *hw_config) -{ - printk (" <AudioTriX>"); - return mem_start; -} - -long -attach_trix_mpu (long mem_start, struct address_info *hw_config) -{ - return attach_mpu401 (mem_start, hw_config); -} - -int -probe_trix_mpu (struct address_info *hw_config) -{ - unsigned char conf; - static char irq_bits[] = - {-1, -1, -1, 1, 2, 3, -1, 4, -1, 5}; - - if (!kilroy_was_here) - return 0; /* AudioTriX Pro has not been detected earlier */ - - if (!sb_initialized) - return 0; - - if (mpu_initialized) - return 0; - - if (hw_config->irq > 9) - return 0; - - if (irq_bits[hw_config->irq] == -1) - return 0; - - switch (hw_config->io_base) - { - case 0x330: - conf = 0x00; - break; - case 0x370: - conf = 0x04; - break; - case 0x3b0: - conf = 0x08; - break; - case 0x3f0: - conf = 0x0c; - break; - default: - return 0; /* Invalid port */ - } - - conf |= irq_bits[hw_config->irq] << 4; - - trix_write (0x19, (trix_read (0x19) & 0x83) | conf); - - mpu_initialized = 1; - - return probe_mpu401 (hw_config); -} - -#endif diff --git a/sys/pc98/pc98/sound/uart6850.c b/sys/pc98/pc98/sound/uart6850.c deleted file mode 100644 index d925727..0000000 --- a/sys/pc98/pc98/sound/uart6850.c +++ /dev/null @@ -1,327 +0,0 @@ -/* - * sound/uart6850.c - * - * Copyright by Hannu Savolainen 1993 - * - * Mon Nov 22 22:38:35 MET 1993 marco@driq.home.usn.nl: - * added 6850 support, used with COVOX SoundMaster II and custom cards. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. 2. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#include <i386/isa/sound/sound_config.h> - -#ifdef CONFIGURE_SOUNDCARD - -#if !defined(EXCLUDE_UART6850) && !defined(EXCLUDE_MIDI) - -#define DATAPORT (uart6850_base) /* - * * * Midi6850 Data I/O Port on IBM - * */ -#define COMDPORT (uart6850_base+1) /* - * * * Midi6850 Command Port on IBM */ -#define STATPORT (uart6850_base+1) /* - * * * Midi6850 Status Port on IBM */ - -#define uart6850_status() INB(STATPORT) -#define input_avail() ((uart6850_status()&INPUT_AVAIL)) -#define output_ready() ((uart6850_status()&OUTPUT_READY)) -#define uart6850_cmd(cmd) OUTB(cmd, COMDPORT) -#define uart6850_read() INB(DATAPORT) -#define uart6850_write(byte) OUTB(byte, DATAPORT) - -#define OUTPUT_READY 0x02 /* - * * * Mask for Data Read Ready Bit */ -#define INPUT_AVAIL 0x01 /* - * * * Mask for Data Send Ready Bit */ - -#define UART_RESET 0x95 /* - * * * 6850 Total Reset Command */ -#define UART_MODE_ON 0x03 /* - * * * 6850 Send/Receive UART Mode */ - -static int uart6850_opened = 0; -static int uart6850_base = 0x330; -static int uart6850_irq; -static int uart6850_detected = 0; -static int my_dev; - -static int reset_uart6850 (void); -static void (*midi_input_intr) (int dev, unsigned char data); - -static void -uart6850_input_loop (void) -{ - int count; - - count = 10; - - while (count) /* - * Not timed out - */ - if (input_avail ()) - { - unsigned char c = uart6850_read (); - - count = 100; - - if (uart6850_opened & OPEN_READ) - midi_input_intr (my_dev, c); - } - else - while (!input_avail () && count) - count--; -} - -void -m6850intr (int unit) -{ - if (input_avail ()) - uart6850_input_loop (); -} - -/* - * It looks like there is no input interrupts in the UART mode. Let's try - * polling. - */ - -static void -poll_uart6850 (unsigned long dummy) -{ - unsigned long flags; - - DEFINE_TIMER (uart6850_timer, poll_uart6850); - - if (!(uart6850_opened & OPEN_READ)) - return; /* - * No longer required - */ - - DISABLE_INTR (flags); - - if (input_avail ()) - uart6850_input_loop (); - - ACTIVATE_TIMER (uart6850_timer, poll_uart6850, 1); /* - * Come back later - */ - - RESTORE_INTR (flags); -} - -static int -uart6850_open (int dev, int mode, - void (*input) (int dev, unsigned char data), - void (*output) (int dev) -) -{ - if (uart6850_opened) - { - printk ("Midi6850: Midi busy\n"); - return RET_ERROR (EBUSY); - } - - uart6850_cmd (UART_RESET); - - uart6850_input_loop (); - - midi_input_intr = input; - uart6850_opened = mode; - poll_uart6850 (0); /* - * Enable input polling - */ - - return 0; -} - -static void -uart6850_close (int dev) -{ - uart6850_cmd (UART_MODE_ON); - - uart6850_opened = 0; -} - -static int -uart6850_out (int dev, unsigned char midi_byte) -{ - int timeout; - unsigned long flags; - - /* - * Test for input since pending input seems to block the output. - */ - - DISABLE_INTR (flags); - - if (input_avail ()) - uart6850_input_loop (); - - RESTORE_INTR (flags); - - /* - * Sometimes it takes about 13000 loops before the output becomes ready - * (After reset). Normally it takes just about 10 loops. - */ - - for (timeout = 30000; timeout > 0 && !output_ready (); timeout--); /* - * Wait - */ - - if (!output_ready ()) - { - printk ("Midi6850: Timeout\n"); - return 0; - } - - uart6850_write (midi_byte); - return 1; -} - -static int -uart6850_command (int dev, unsigned char *midi_byte) -{ - return 1; -} - -static int -uart6850_start_read (int dev) -{ - return 0; -} - -static int -uart6850_end_read (int dev) -{ - return 0; -} - -static int -uart6850_ioctl (int dev, unsigned cmd, unsigned arg) -{ - return RET_ERROR (EINVAL); -} - -static void -uart6850_kick (int dev) -{ -} - -static int -uart6850_buffer_status (int dev) -{ - return 0; /* - * No data in buffers - */ -} - -#define MIDI_SYNTH_NAME "6850 UART Midi" -#define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT -#include <i386/isa/sound/midi_synth.h> - -static struct midi_operations uart6850_operations = -{ - {"6850 UART", 0, 0, SNDCARD_UART6850}, - &std_midi_synth, - {0}, - uart6850_open, - uart6850_close, - uart6850_ioctl, - uart6850_out, - uart6850_start_read, - uart6850_end_read, - uart6850_kick, - uart6850_command, - uart6850_buffer_status -}; - - -long -attach_uart6850 (long mem_start, struct address_info *hw_config) -{ - int ok, timeout; - unsigned long flags; - - if (num_midis >= MAX_MIDI_DEV) - { - printk ("Sound: Too many midi devices detected\n"); - return mem_start; - } - - uart6850_base = hw_config->io_base; - uart6850_irq = hw_config->irq; - - if (!uart6850_detected) - return RET_ERROR (EIO); - - DISABLE_INTR (flags); - - for (timeout = 30000; timeout < 0 && !output_ready (); timeout--); /* - * Wait - */ - uart6850_cmd (UART_MODE_ON); - - ok = 1; - - RESTORE_INTR (flags); - -#if defined(__FreeBSD__) - printk ("uart0: <6850 Midi Interface>"); -#else - printk (" <6850 Midi Interface>"); -#endif - - std_midi_synth.midi_dev = my_dev = num_midis; - midi_devs[num_midis++] = &uart6850_operations; - return mem_start; -} - -static int -reset_uart6850 (void) -{ - uart6850_read (); - return 1; /* - * OK - */ -} - - -int -probe_uart6850 (struct address_info *hw_config) -{ - int ok = 0; - - uart6850_base = hw_config->io_base; - uart6850_irq = hw_config->irq; - - if (snd_set_irq_handler (uart6850_irq, m6850intr, "MIDI6850") < 0) - return 0; - - ok = reset_uart6850 (); - - uart6850_detected = ok; - return ok; -} - -#endif - -#endif diff --git a/sys/pc98/pc98/sound/ulaw.h b/sys/pc98/pc98/sound/ulaw.h deleted file mode 100644 index 4a071dd..0000000 --- a/sys/pc98/pc98/sound/ulaw.h +++ /dev/null @@ -1,71 +0,0 @@ -static unsigned char ulaw_dsp[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 2, - 5, 9, 13, 17, 21, 25, 29, 33, - 37, 41, 45, 49, 53, 57, 61, 65, - 68, 70, 72, 74, 76, 78, 80, 82, - 84, 86, 88, 90, 92, 94, 96, 98, - 100, 101, 102, 103, 104, 105, 106, 107, - 108, 109, 110, 111, 112, 113, 114, 115, - 115, 116, 116, 117, 117, 118, 118, 119, - 119, 120, 120, 121, 121, 122, 122, 123, - 123, 123, 124, 124, 124, 124, 125, 125, - 125, 125, 126, 126, 126, 126, 127, 127, - 127, 127, 127, 127, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 252, 248, 244, 240, 236, 232, 228, 224, - 220, 216, 212, 208, 204, 200, 196, 192, - 189, 187, 185, 183, 181, 179, 177, 175, - 173, 171, 169, 167, 165, 163, 161, 159, - 157, 156, 155, 154, 153, 152, 151, 150, - 149, 148, 147, 146, 145, 144, 143, 142, - 142, 141, 141, 140, 140, 139, 139, 138, - 138, 137, 137, 136, 136, 135, 135, 134, - 134, 134, 133, 133, 133, 133, 132, 132, - 132, 132, 131, 131, 131, 131, 130, 130, - 130, 130, 130, 130, 129, 129, 129, 129, - 129, 129, 129, 129, 128, 128, 128, 128, -}; - -#ifndef DSP_ULAW_NOT_WANTED -static unsigned char dsp_ulaw[] = { - 31, 31, 31, 32, 32, 32, 32, 33, - 33, 33, 33, 34, 34, 34, 34, 35, - 35, 35, 35, 36, 36, 36, 36, 37, - 37, 37, 37, 38, 38, 38, 38, 39, - 39, 39, 39, 40, 40, 40, 40, 41, - 41, 41, 41, 42, 42, 42, 42, 43, - 43, 43, 43, 44, 44, 44, 44, 45, - 45, 45, 45, 46, 46, 46, 46, 47, - 47, 47, 47, 48, 48, 49, 49, 50, - 50, 51, 51, 52, 52, 53, 53, 54, - 54, 55, 55, 56, 56, 57, 57, 58, - 58, 59, 59, 60, 60, 61, 61, 62, - 62, 63, 63, 64, 65, 66, 67, 68, - 69, 70, 71, 72, 73, 74, 75, 76, - 77, 78, 79, 81, 83, 85, 87, 89, - 91, 93, 95, 99, 103, 107, 111, 119, - 255, 247, 239, 235, 231, 227, 223, 221, - 219, 217, 215, 213, 211, 209, 207, 206, - 205, 204, 203, 202, 201, 200, 199, 198, - 197, 196, 195, 194, 193, 192, 191, 191, - 190, 190, 189, 189, 188, 188, 187, 187, - 186, 186, 185, 185, 184, 184, 183, 183, - 182, 182, 181, 181, 180, 180, 179, 179, - 178, 178, 177, 177, 176, 176, 175, 175, - 175, 175, 174, 174, 174, 174, 173, 173, - 173, 173, 172, 172, 172, 172, 171, 171, - 171, 171, 170, 170, 170, 170, 169, 169, - 169, 169, 168, 168, 168, 168, 167, 167, - 167, 167, 166, 166, 166, 166, 165, 165, - 165, 165, 164, 164, 164, 164, 163, 163, - 163, 163, 162, 162, 162, 162, 161, 161, - 161, 161, 160, 160, 160, 160, 159, 159, -}; -#endif /* !DSP_ULAW_NOT_WANTED */ diff --git a/sys/pc98/pc98/spkr.c b/sys/pc98/pc98/spkr.c index 611bd16..5bfbe08 100644 --- a/sys/pc98/pc98/spkr.c +++ b/sys/pc98/pc98/spkr.c @@ -4,12 +4,12 @@ * v1.4 by Eric S. Raymond (esr@snark.thyrsus.com) Aug 1993 * modified for FreeBSD by Andrew A. Chernov <ache@astral.msk.su> * - * $Id: spkr.c,v 1.3 1996/08/30 10:43:09 asami Exp $ + * $Id: spkr.c,v 1.4 1996/09/04 09:52:27 asami Exp $ */ /* * modified for PC98 - * $Id: spkr.c,v 1.3 1996/08/30 10:43:09 asami Exp $ + * $Id: spkr.c,v 1.4 1996/09/04 09:52:27 asami Exp $ */ #include "speaker.h" @@ -19,23 +19,18 @@ #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> -#include <sys/errno.h> #include <sys/buf.h> -#include <sys/proc.h> #include <sys/uio.h> #include <sys/conf.h> #ifdef PC98 #include <pc98/pc98/pc98.h> -#include <pc98/pc98/timerreg.h> #else #include <i386/isa/isa.h> -#include <i386/isa/timerreg.h> #endif +#include <i386/isa/timerreg.h> #include <machine/clock.h> #include <machine/speaker.h> - - #ifdef DEVFS #include <sys/devfsext.h> void *devfs_token; @@ -55,53 +50,25 @@ static struct cdevsw spkr_cdevsw = /**************** MACHINE DEPENDENT PART STARTS HERE ************************* * * This section defines a function tone() which causes a tone of given - * frequency and duration from the 80x86's console speaker. + * frequency and duration from the ISA console speaker. * Another function endtone() is defined to force sound off, and there is * also a rest() entry point to do pauses. * * Audible sound is generated using the Programmable Interval Timer (PIT) and - * Programmable Peripheral Interface (PPI) attached to the 80x86's speaker. The + * Programmable Peripheral Interface (PPI) attached to the ISA speaker. The * PPI controls whether sound is passed through at all; the PIT's channel 2 is * used to generate clicks (a square wave) of whatever frequency is desired. */ /* - * PIT and PPI port addresses and control values - * - * Most of the magic is hidden in the TIMER_PREP value, which selects PIT - * channel 2, frequency LSB first, square-wave mode and binary encoding. - * The encoding is as follows: - * - * +----------+----------+---------------+-----+ - * | 1 0 | 1 1 | 0 1 1 | 0 | - * | SC1 SC0 | RW1 RW0 | M2 M1 M0 | BCD | - * +----------+----------+---------------+-----+ - * Counter Write Mode 3 Binary - * Channel 2 LSB first, (Square Wave) Encoding - * MSB second + * PPI control values. + * XXX should be in a header and used in clock.c. */ #ifdef PC98 #define PPI_SPKR 0x08 /* turn these PPI bits on to pass sound */ #define PIT_COUNT 0x3fdb /* PIT count address */ -#define PIT_MODE 0x76 /* set timer mode for sound generation */ #else #define PPI_SPKR 0x03 /* turn these PPI bits on to pass sound */ -#define PIT_MODE 0xB6 /* set timer mode for sound generation */ -#endif - -/* - * Magic numbers for timer control. - */ -#ifdef PC98 -#ifndef AUTO_CLOCK -#ifndef PC98_8M -#define TIMER_CLK 2457600L /* ???? for 5MHz system */ -#else -#define TIMER_CLK 1996800L /* ???? for 8MHz system */ -#endif -#endif /* !AUTO_CLOCK */ -#else /* IBM_PC */ -#define TIMER_CLK 1193180L /* corresponds to 18.2 MHz tick rate */ #endif #define SPKRPRI PSOCK @@ -131,7 +98,7 @@ tone(thz, ticks) else divisor = 2457600L / thz; #else - divisor = TIMER_CLK / thz; + divisor = timer_freq / thz; #endif /* PC98 */ #ifdef DEBUG @@ -142,9 +109,9 @@ tone(thz, ticks) sps = splclock(); #ifdef PC98 - if (acquire_timer1(PIT_MODE)) { + if (acquire_timer1(TIMER_SEL1 | TIMER_SQWAVE | TIMER_16BIT)) { #else - if (acquire_timer2(PIT_MODE)) { + if (acquire_timer2(TIMER_SEL2 | TIMER_SQWAVE | TIMER_16BIT)) { #endif /* enter list of waiting procs ??? */ splx(sps); diff --git a/sys/pc98/pc98/syscons.c b/sys/pc98/pc98/syscons.c index 12514f3..1f98d41 100644 --- a/sys/pc98/pc98/syscons.c +++ b/sys/pc98/pc98/syscons.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: syscons.c,v 1.11 1996/10/23 07:25:30 asami Exp $ + * $Id: syscons.c,v 1.12 1996/10/29 08:36:27 asami Exp $ */ #include "sc.h" @@ -69,8 +69,8 @@ #define KANJI #include <pc98/pc98/pc98.h> #include <i386/isa/isa_device.h> -#include <pc98/pc98/timerreg.h> -#include <pc98/pc98/kbdtables.h> +#include <i386/isa/timerreg.h> +#include <i386/isa/kbdtables.h> #include <pc98/pc98/syscons.h> #else #include <i386/isa/isa.h> @@ -122,8 +122,7 @@ static term_stat kernel_console; static default_attr *current_default; static int flags = 0; static char init_done = COLD; -static u_short buffer[ROW*COL]; -static char in_debugger = FALSE; +static u_short sc_buffer[ROW*COL]; static char switch_in_progress = FALSE; static char write_in_progress = FALSE; static char blink_in_progress = FALSE; @@ -180,7 +179,6 @@ struct tty *sccons[MAXCONS+2]; #define MOUSE_TTY &sccons[MAXCONS+1] static struct tty sccons[MAXCONS+2]; #endif - #define SC_MOUSE 128 #define SC_CONSOLE 255 #ifdef PC98 @@ -210,7 +208,9 @@ static int scprobe(struct isa_device *dev); static void scstart(struct tty *tp); static void scmousestart(struct tty *tp); static void scinit(void); -static u_int scgetc(int noblock); +static u_int scgetc(u_int flags); +#define SCGETC_CN 1 +#define SCGETC_NONBLOCK 2 static scr_stat *get_scr_stat(dev_t dev); static scr_stat *alloc_scp(void); static void init_scp(scr_stat *scp); @@ -252,7 +252,7 @@ static void toggle_splash_screen(scr_stat *scp); #endif struct isa_driver scdriver = { - scprobe, scattach, "sc", 1 + scprobe, scattach, "sc", 1 }; static d_open_t scopen; @@ -499,8 +499,10 @@ scattach(struct isa_device *dev) scp->atr_buf = (u_short *)malloc(scp->xsize*scp->ysize*sizeof(u_short), M_DEVBUF, M_NOWAIT); #endif - /* copy screen to buffer */ - bcopyw(buffer, scp->scr_buf, scp->xsize * scp->ysize * sizeof(u_short)); + + /* copy temporary buffer to final buffer */ + bcopyw(sc_buffer, scp->scr_buf, scp->xsize * scp->ysize * sizeof(u_short)); + #ifdef PC98 bcopyw(Atrat, scp->atr_buf, scp->xsize * scp->ysize * sizeof(u_short)); #endif @@ -697,7 +699,7 @@ scintr(int unit) mark_all(cur_console); } - c = scgetc(1); + c = scgetc(SCGETC_NONBLOCK); cur_tty = VIRTUAL_TTY(get_scr_num()); if (!(cur_tty->t_state & TS_ISOPEN)) @@ -1347,7 +1349,7 @@ scioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p) case KIOCSOUND: /* make tone (*data) hz */ if (scp == cur_console) { if (*(int*)data) { - int pitch = TIMER_FREQ/(*(int*)data); + int pitch = timer_freq / *(int*)data; #ifdef PC98 /* enable counter 1 */ @@ -1602,10 +1604,8 @@ sccnputc(dev_t dev, int c) scp->term = kernel_console; current_default = &kernel_default; - if ((scp->scr_buf == buffer || in_debugger) && - !(scp->status & UNKNOWN_MODE)) { + if (!(scp->status & UNKNOWN_MODE)) remove_cursor_image(scp); - } buf[0] = c; ansi_put(scp, buf, 1); kernel_console = scp->term; @@ -1633,7 +1633,7 @@ int sccngetc(dev_t dev) { int s = spltty(); /* block scintr while we poll */ - int c = scgetc(0); + int c = scgetc(SCGETC_CN); splx(s); return(c); } @@ -1644,7 +1644,7 @@ sccncheckc(dev_t dev) int c, s; s = spltty(); - c = scgetc(1); + c = scgetc(SCGETC_CN | SCGETC_NONBLOCK); splx(s); return(c == NOKEY ? -1 : c); /* c == -1 can't happen */ } @@ -1680,6 +1680,7 @@ scrn_timer() /* should we just return ? */ if ((scp->status&UNKNOWN_MODE) || blink_in_progress || switch_in_progress) { timeout((timeout_func_t)scrn_timer, 0, hz/10); + splx(s); return; } @@ -3009,10 +3010,8 @@ scinit(void) #ifdef AUTO_CLOCK if (pc98_machine_type & M_8M) { BELL_PITCH = 1339; - TIMER_FREQ = 1996800L; } else { BELL_PITCH = 1678; - TIMER_FREQ = 2457600L; } #endif /* AUTO_CLOCK */ outb(0x62, 0xd); @@ -3079,8 +3078,13 @@ scinit(void) current_default = &user_default; console[0] = &main_console; init_scp(console[0]); - console[0]->scr_buf = console[0]->mouse_pos = buffer; - console[0]->cursor_pos = console[0]->cursor_oldpos = buffer + hw_cursor; + + /* copy screen to temporary buffer */ + bcopyw(Crtat, sc_buffer, + console[0]->xsize * console[0]->ysize * sizeof(u_short)); + + console[0]->scr_buf = console[0]->mouse_pos = sc_buffer; + console[0]->cursor_pos = console[0]->cursor_oldpos = sc_buffer + hw_cursor; #ifdef PC98 console[0]->atr_buf = Atrat; console[0]->cursor_atr = Atrat + hw_cursor; @@ -3265,12 +3269,13 @@ history_down_line(scr_stat *scp) } /* - * scgetc(noblock) - get character from keyboard. - * If noblock = 0 wait until a key is pressed. - * Else return NOKEY. + * scgetc(flags) - get character from keyboard. + * If flags & SCGETC_CN, then avoid harmful side effects. + * If flags & SCGETC_NONBLOCK, then wait until a key is pressed, else + * return NOKEY if there is nothing there. */ static u_int -scgetc(int noblock) +scgetc(u_int flags) { u_char scancode, keycode; u_int state, action; @@ -3286,17 +3291,18 @@ next_code: { kbd_wait(); scancode = inb(KB_DATA); - } else if (noblock) + } else if (flags & SCGETC_NONBLOCK) #else scancode = inb(KB_DATA); - else if (noblock) + else if (flags & SCGETC_NONBLOCK) #endif return(NOKEY); else goto next_code; /* do the /dev/random device a favour */ - add_keyboard_randomness(scancode); + if (!(flags & SCGETC_CN)) + add_keyboard_randomness(scancode); if (cur_console->status & KBD_RAW_MODE) return scancode; @@ -3731,9 +3737,7 @@ next_code: if (cur_console->smode.mode == VT_AUTO && console[0]->smode.mode == VT_AUTO) switch_scr(cur_console, 0); - in_debugger = TRUE; Debugger("manual escape to debugger"); - in_debugger = FALSE; return(NOKEY); #else printf("No debugger in kernel\n"); diff --git a/sys/pc98/pc98/syscons.h b/sys/pc98/pc98/syscons.h index 39bd568..bb20855 100644 --- a/sys/pc98/pc98/syscons.h +++ b/sys/pc98/pc98/syscons.h @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: syscons.h,v 1.5 1996/10/23 07:25:33 asami Exp $ + * $Id: syscons.h,v 1.6 1996/10/29 08:36:28 asami Exp $ */ #ifndef _PC98_PC98_SYSCONS_H_ @@ -98,14 +98,11 @@ #ifndef AUTO_CLOCK #ifndef PC98_8M #define BELL_PITCH 1678 -#define TIMER_FREQ 2457600 /* should be in pc98.h */ #else #define BELL_PITCH 1339 -#define TIMER_FREQ 1996800 /* should be in pc98.h */ #endif #else /* AUTO_CLOCK */ static unsigned int BELL_PITCH = 1678; -static unsigned int TIMER_FREQ = 2457600; #endif /* AUTO_CLOCK */ #else /* IBM-PC */ #define BELL_PITCH 800 diff --git a/sys/pc98/pc98/timerreg.h b/sys/pc98/pc98/timerreg.h deleted file mode 100644 index 3ab9ae8..0000000 --- a/sys/pc98/pc98/timerreg.h +++ /dev/null @@ -1,93 +0,0 @@ -/*- - * Copyright (c) 1993 The Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: Header: timerreg.h,v 1.2 93/02/28 15:08:58 mccanne Exp - * timerreg.h,v 1.2 1993/10/16 13:46:26 rgrimes Exp - */ - -/* - * - * Register definitions for the Intel 8253 Programmable Interval Timer. - * - * This chip has three independent 16-bit down counters that can be - * read on the fly. There are three mode registers and three countdown - * registers. The countdown registers are addressed directly, via the - * first three I/O ports. The three mode registers are accessed via - * the fourth I/O port, with two bits in the mode byte indicating the - * register. (Why are hardware interfaces always so braindead?). - * - * To write a value into the countdown register, the mode register - * is first programmed with a command indicating the which byte of - * the two byte register is to be modified. The three possibilities - * are load msb (TMR_MR_MSB), load lsb (TMR_MR_LSB), or load lsb then - * msb (TMR_MR_BOTH). - * - * To read the current value ("on the fly") from the countdown register, - * you write a "latch" command into the mode register, then read the stable - * value from the corresponding I/O port. For example, you write - * TMR_MR_LATCH into the corresponding mode register. Presumably, - * after doing this, a write operation to the I/O port would result - * in undefined behavior (but hopefully not fry the chip). - * Reading in this manner has no side effects. - * - * The outputs of the three timers are connected as follows: - * - * timer 0 -> irq 0 - * timer 1 -> speaker (via keyboard controller) - * timer 2 -> RS232C - * - * Timer 0 is used to call hardclock. - * Timer 1 is used to generate console beeps. - */ - -/* - * Macros for specifying values to be written into a mode register. - */ -#define TIMER_CNTR0 0x071 /* timer 0 counter port */ -#define TIMER_CNTR1 0x3fdb /* timer 1 counter port */ -#define TIMER_CNTR2 0x075 /* timer 2 counter port */ -#define TIMER_MODE 0x077 /* timer mode port */ -#define TIMER_SEL0 0x00 /* select counter 0 */ -#define TIMER_SEL1 0x40 /* select counter 1 */ -#define TIMER_SEL2 0x80 /* select counter 2 */ -#define TIMER_INTTC 0x00 /* mode 0, intr on terminal cnt */ -#define TIMER_ONESHOT 0x02 /* mode 1, one shot */ -#define TIMER_RATEGEN 0x04 /* mode 2, rate generator */ -#define TIMER_SQWAVE 0x06 /* mode 3, square wave */ -#define TIMER_SWSTROBE 0x08 /* mode 4, s/w triggered strobe */ -#define TIMER_HWSTROBE 0x0a /* mode 5, h/w triggered strobe */ -#define TIMER_LATCH 0x00 /* latch counter for reading */ -#define TIMER_LSB 0x10 /* r/w counter LSB */ -#define TIMER_MSB 0x20 /* r/w counter MSB */ -#define TIMER_16BIT 0x30 /* r/w counter 16 bits, LSB first */ -#define TIMER_BCD 0x01 /* count in BCD */ - diff --git a/sys/pc98/pc98/vector.s b/sys/pc98/pc98/vector.s deleted file mode 100644 index cfa37ad..0000000 --- a/sys/pc98/pc98/vector.s +++ /dev/null @@ -1,305 +0,0 @@ -/* - * from: vector.s, 386BSD 0.1 unknown origin - * $Id: vector.s,v 1.1.1.1 1996/06/14 10:04:48 asami Exp $ - */ - -#include "opt_auto_eoi.h" - -/* - * modified for PC98 - * vector.s,v 1.2 1994/03/14 09:44:21 kakefuda Exp - */ - -#include <i386/isa/icu.h> -#ifdef PC98 -#include <pc98/pc98/pc98.h> -#else -#include <i386/isa/isa.h> -#endif - -#define ICU_EOI 0x20 /* XXX - define elsewhere */ - -#define IRQ_BIT(irq_num) (1 << ((irq_num) % 8)) -#define IRQ_BYTE(irq_num) ((irq_num) / 8) - -#ifdef AUTO_EOI_1 -#define ENABLE_ICU1 /* use auto-EOI to reduce i/o */ -#define OUTB_ICU1 -#else -#define ENABLE_ICU1 \ - movb $ICU_EOI,%al ; /* as soon as possible send EOI ... */ \ - OUTB_ICU1 /* ... to clear in service bit */ -#define OUTB_ICU1 \ - outb %al,$IO_ICU1 -#endif - -#ifdef AUTO_EOI_2 -/* - * The data sheet says no auto-EOI on slave, but it sometimes works. - */ -#define ENABLE_ICU1_AND_2 ENABLE_ICU1 -#else -#define ENABLE_ICU1_AND_2 \ - movb $ICU_EOI,%al ; /* as above */ \ - outb %al,$IO_ICU2 ; /* but do second icu first ... */ \ - OUTB_ICU1 /* ... then first icu (if !AUTO_EOI_1) */ -#endif - -#ifdef FAST_INTR_HANDLER_USES_ES -#define ACTUALLY_PUSHED 1 -#define MAYBE_MOVW_AX_ES movl %ax,%es -#define MAYBE_POPL_ES popl %es -#define MAYBE_PUSHL_ES pushl %es -#else -/* - * We can usually skip loading %es for fastintr handlers. %es should - * only be used for string instructions, and fastintr handlers shouldn't - * do anything slow enough to justify using a string instruction. - */ -#define ACTUALLY_PUSHED 0 -#define MAYBE_MOVW_AX_ES -#define MAYBE_POPL_ES -#define MAYBE_PUSHL_ES -#endif - -/* - * Macros for interrupt interrupt entry, call to handler, and exit. - * - * XXX - the interrupt frame is set up to look like a trap frame. This is - * usually a waste of time. The only interrupt handlers that want a frame - * are the clock handler (it wants a clock frame), the npx handler (it's - * easier to do right all in assembler). The interrupt return routine - * needs a trap frame for rare AST's (it could easily convert the frame). - * The direct costs of setting up a trap frame are two pushl's (error - * code and trap number), an addl to get rid of these, and pushing and - * popping the call-saved regs %esi, %edi and %ebp twice, The indirect - * costs are making the driver interface nonuniform so unpending of - * interrupts is more complicated and slower (call_driver(unit) would - * be easier than ensuring an interrupt frame for all handlers. Finally, - * there are some struct copies in the npx handler and maybe in the clock - * handler that could be avoided by working more with pointers to frames - * instead of frames. - * - * XXX - should we do a cld on every system entry to avoid the requirement - * for scattered cld's? - * - * Coding notes for *.s: - * - * If possible, avoid operations that involve an operand size override. - * Word-sized operations might be smaller, but the operand size override - * makes them slower on on 486's and no faster on 386's unless perhaps - * the instruction pipeline is depleted. E.g., - * - * Use movl to seg regs instead of the equivalent but more descriptive - * movw - gas generates an irelevant (slower) operand size override. - * - * Use movl to ordinary regs in preference to movw and especially - * in preference to movz[bw]l. Use unsigned (long) variables with the - * top bits clear instead of unsigned short variables to provide more - * opportunities for movl. - * - * If possible, use byte-sized operations. They are smaller and no slower. - * - * Use (%reg) instead of 0(%reg) - gas generates larger code for the latter. - * - * If the interrupt frame is made more flexible, INTR can push %eax first - * and decide the ipending case with less overhead, e.g., by avoiding - * loading segregs. - */ - -#define FAST_INTR(irq_num, vec_name, enable_icus) \ - .text ; \ - SUPERALIGN_TEXT ; \ -IDTVEC(vec_name) ; \ - pushl %eax ; /* save only call-used registers */ \ - pushl %ecx ; \ - pushl %edx ; \ - pushl %ds ; \ - MAYBE_PUSHL_ES ; \ - movl $KDSEL,%eax ; \ - movl %ax,%ds ; \ - MAYBE_MOVW_AX_ES ; \ - FAKE_MCOUNT((4+ACTUALLY_PUSHED)*4(%esp)) ; \ - pushl _intr_unit + (irq_num) * 4 ; \ - call *_intr_handler + (irq_num) * 4 ; /* do the work ASAP */ \ - enable_icus ; /* (re)enable ASAP (helps edge trigger?) */ \ - addl $4,%esp ; \ - incl _cnt+V_INTR ; /* book-keeping can wait */ \ - movl _intr_countp + (irq_num) * 4,%eax ; \ - incl (%eax) ; \ - movl _cpl,%eax ; /* are we unmasking pending HWIs or SWIs? */ \ - notl %eax ; \ - andl _ipending,%eax ; \ - jne 1f ; /* yes, handle them */ \ - MEXITCOUNT ; \ - MAYBE_POPL_ES ; \ - popl %ds ; \ - popl %edx ; \ - popl %ecx ; \ - popl %eax ; \ - iret ; \ -; \ - ALIGN_TEXT ; \ -1: ; \ - movl _cpl,%eax ; \ - movl $HWI_MASK|SWI_MASK,_cpl ; /* limit nesting ... */ \ - sti ; /* ... to do this as early as possible */ \ - MAYBE_POPL_ES ; /* discard most of thin frame ... */ \ - popl %ecx ; /* ... original %ds ... */ \ - popl %edx ; \ - xchgl %eax,4(%esp) ; /* orig %eax; save cpl */ \ - pushal ; /* build fat frame (grrr) ... */ \ - pushl %ecx ; /* ... actually %ds ... */ \ - pushl %es ; \ - movl $KDSEL,%eax ; \ - movl %ax,%es ; \ - movl (2+8+0)*4(%esp),%ecx ; /* ... %ecx from thin frame ... */ \ - movl %ecx,(2+6)*4(%esp) ; /* ... to fat frame ... */ \ - movl (2+8+1)*4(%esp),%eax ; /* ... cpl from thin frame */ \ - pushl %eax ; \ - subl $4,%esp ; /* junk for unit number */ \ - incb _intr_nesting_level ; \ - MEXITCOUNT ; \ - jmp _doreti - -#define INTR(irq_num, vec_name, icu, enable_icus, reg) \ - .text ; \ - SUPERALIGN_TEXT ; \ -IDTVEC(vec_name) ; \ - pushl $0 ; /* dummy error code */ \ - pushl $0 ; /* dummy trap type */ \ - pushal ; \ - pushl %ds ; /* save our data and extra segments ... */ \ - pushl %es ; \ - movl $KDSEL,%eax ; /* ... and reload with kernel's own ... */ \ - movl %ax,%ds ; /* ... early for obsolete reasons */ \ - movl %ax,%es ; \ - movb _imen + IRQ_BYTE(irq_num),%al ; \ - orb $IRQ_BIT(irq_num),%al ; \ - movb %al,_imen + IRQ_BYTE(irq_num) ; \ - outb %al,$icu+2 ; \ - enable_icus ; \ - incl _cnt+V_INTR ; /* tally interrupts */ \ - movl _cpl,%eax ; \ - testb $IRQ_BIT(irq_num),%reg ; \ - jne 2f ; \ - incb _intr_nesting_level ; \ -__CONCAT(Xresume,irq_num): ; \ - FAKE_MCOUNT(12*4(%esp)) ; /* XXX late to avoid double count */ \ - movl _intr_countp + (irq_num) * 4,%eax ; \ - incl (%eax) ; \ - movl _cpl,%eax ; \ - pushl %eax ; \ - pushl _intr_unit + (irq_num) * 4 ; \ - orl _intr_mask + (irq_num) * 4,%eax ; \ - movl %eax,_cpl ; \ - sti ; \ - call *_intr_handler + (irq_num) * 4 ; \ - cli ; /* must unmask _imen and icu atomically */ \ - movb _imen + IRQ_BYTE(irq_num),%al ; \ - andb $~IRQ_BIT(irq_num),%al ; \ - movb %al,_imen + IRQ_BYTE(irq_num) ; \ - outb %al,$icu+2 ; \ - sti ; /* XXX _doreti repeats the cli/sti */ \ - MEXITCOUNT ; \ - /* We could usually avoid the following jmp by inlining some of */ \ - /* _doreti, but it's probably better to use less cache. */ \ - jmp _doreti ; \ -; \ - ALIGN_TEXT ; \ -2: ; \ - /* XXX skip mcounting here to avoid double count */ \ - orb $IRQ_BIT(irq_num),_ipending + IRQ_BYTE(irq_num) ; \ - popl %es ; \ - popl %ds ; \ - popal ; \ - addl $4+4,%esp ; \ - iret - -MCOUNT_LABEL(bintr) - FAST_INTR(0,fastintr0, ENABLE_ICU1) - FAST_INTR(1,fastintr1, ENABLE_ICU1) - FAST_INTR(2,fastintr2, ENABLE_ICU1) - FAST_INTR(3,fastintr3, ENABLE_ICU1) - FAST_INTR(4,fastintr4, ENABLE_ICU1) - FAST_INTR(5,fastintr5, ENABLE_ICU1) - FAST_INTR(6,fastintr6, ENABLE_ICU1) - FAST_INTR(7,fastintr7, ENABLE_ICU1) - FAST_INTR(8,fastintr8, ENABLE_ICU1_AND_2) - FAST_INTR(9,fastintr9, ENABLE_ICU1_AND_2) - FAST_INTR(10,fastintr10, ENABLE_ICU1_AND_2) - FAST_INTR(11,fastintr11, ENABLE_ICU1_AND_2) - FAST_INTR(12,fastintr12, ENABLE_ICU1_AND_2) - FAST_INTR(13,fastintr13, ENABLE_ICU1_AND_2) - FAST_INTR(14,fastintr14, ENABLE_ICU1_AND_2) - FAST_INTR(15,fastintr15, ENABLE_ICU1_AND_2) - INTR(0,intr0, IO_ICU1, ENABLE_ICU1, al) - INTR(1,intr1, IO_ICU1, ENABLE_ICU1, al) - INTR(2,intr2, IO_ICU1, ENABLE_ICU1, al) - INTR(3,intr3, IO_ICU1, ENABLE_ICU1, al) - INTR(4,intr4, IO_ICU1, ENABLE_ICU1, al) - INTR(5,intr5, IO_ICU1, ENABLE_ICU1, al) - INTR(6,intr6, IO_ICU1, ENABLE_ICU1, al) - INTR(7,intr7, IO_ICU1, ENABLE_ICU1, al) - INTR(8,intr8, IO_ICU2, ENABLE_ICU1_AND_2, ah) - INTR(9,intr9, IO_ICU2, ENABLE_ICU1_AND_2, ah) - INTR(10,intr10, IO_ICU2, ENABLE_ICU1_AND_2, ah) - INTR(11,intr11, IO_ICU2, ENABLE_ICU1_AND_2, ah) - INTR(12,intr12, IO_ICU2, ENABLE_ICU1_AND_2, ah) - INTR(13,intr13, IO_ICU2, ENABLE_ICU1_AND_2, ah) - INTR(14,intr14, IO_ICU2, ENABLE_ICU1_AND_2, ah) - INTR(15,intr15, IO_ICU2, ENABLE_ICU1_AND_2, ah) -MCOUNT_LABEL(eintr) - - .data -ihandlers: /* addresses of interrupt handlers */ - /* actually resumption addresses for HWI's */ - .long Xresume0, Xresume1, Xresume2, Xresume3 - .long Xresume4, Xresume5, Xresume6, Xresume7 - .long Xresume8, Xresume9, Xresume10, Xresume11 - .long Xresume12, Xresume13, Xresume14, Xresume15 - .long swi_tty, swi_net, 0, 0, 0, 0, 0, 0 - .long 0, 0, 0, 0, 0, 0, _softclock, swi_ast -imasks: /* masks for interrupt handlers */ - .space NHWI*4 /* padding; HWI masks are elsewhere */ - .long SWI_TTY_MASK, SWI_NET_MASK, 0, 0, 0, 0, 0, 0 - .long 0, 0, 0, 0, 0, 0, SWI_CLOCK_MASK, SWI_AST_MASK - .globl _intr_nesting_level -_intr_nesting_level: - .byte 0 - .space 3 - -/* - * Interrupt counters and names. The format of these and the label names - * must agree with what vmstat expects. The tables are indexed by device - * ids so that we don't have to move the names around as devices are - * attached. - */ -#include "vector.h" - .globl _intrcnt, _eintrcnt -_intrcnt: - .space (NR_DEVICES + ICU_LEN) * 4 -_eintrcnt: - - .globl _intrnames, _eintrnames -_intrnames: - .ascii DEVICE_NAMES - .asciz "stray irq0" - .asciz "stray irq1" - .asciz "stray irq2" - .asciz "stray irq3" - .asciz "stray irq4" - .asciz "stray irq5" - .asciz "stray irq6" - .asciz "stray irq7" - .asciz "stray irq8" - .asciz "stray irq9" - .asciz "stray irq10" - .asciz "stray irq11" - .asciz "stray irq12" - .asciz "stray irq13" - .asciz "stray irq14" - .asciz "stray irq15" -_eintrnames: - - .text |