Commit 286d075e authored by Linus Torvalds's avatar Linus Torvalds

- Jaroslav Kysela: ymfpci driver

- Linus: get rid of bogus MS_INVALIDATE semantics
- Linus: final part of the PageDirty() saga
- Rusty Russell: 4-way SMP iptables fix
- Al Viro: oops - bad ext2 inode dirty block bug
parent 971c8cf0
......@@ -143,6 +143,9 @@ if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND_OSS" = "m" ]; then
dep_tristate ' Yamaha OPL3-SA1 audio controller' CONFIG_SOUND_OPL3SA1 $CONFIG_SOUND_OSS
dep_tristate ' Yamaha OPL3-SA2, SA3, and SAx based PnP cards' CONFIG_SOUND_OPL3SA2 $CONFIG_SOUND_OSS
dep_tristate ' Yamaha PCI legacy mode support' CONFIG_SOUND_YMPCI $CONFIG_SOUND_OSS $CONFIG_PCI
if [ "$CONFIG_SOUND_YMPCI" = "n" ]; then
dep_tristate 'Yamaha PCI native mode support (EXPERIMENTAL)' CONFIG_SOUND_YMFPCI $CONFIG_SOUND_OSS
fi
dep_tristate ' 6850 UART support' CONFIG_SOUND_UART6850 $CONFIG_SOUND_OSS
dep_tristate ' Gallant Audio Cards (SC-6000 and SC-6600 based)' CONFIG_SOUND_AEDSP16 $CONFIG_SOUND_OSS
......
......@@ -67,6 +67,7 @@ obj-$(CONFIG_SOUND_AWE32_SYNTH) += awe_wave.o
obj-$(CONFIG_SOUND_VIA82CXXX) += via82cxxx_audio.o ac97_codec.o
obj-$(CONFIG_SOUND_YMPCI) += ymf_sb.o sb_lib.o uart401.o
obj-$(CONFIG_SOUND_YMFPCI) += ymfpci.o ac97_codec.o
obj-$(CONFIG_SOUND_MSNDCLAS) += msnd.o msnd_classic.o
obj-$(CONFIG_SOUND_MSNDPIN) += msnd.o msnd_pinnacle.o
obj-$(CONFIG_SOUND_VWSND) += vwsnd.o
......
/*
* Copyright 1999 Jaroslav Kysela <perex@suse.cz>
* Copyright 2000 Alan Cox <alan@redhat.com>
*
* Yamaha YMF7xx driver.
*
* This code is a result of high-speed collision
* between ymfpci.c of ALSA and cs46xx.c of Linux.
* -- Pete Zaitcev <zaitcev@metabyte.com>; 2000/09/18
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* TODO:
* - Use P44Slot for 44.1 playback.
* - Capture and duplex
* - 96KHz playback for DVD - use pitch of 2.0.
* - uLaw for Sun apps.
* - Retain DMA buffer on close, do not wait the end of frame.
* - Cleanup
* ? merge ymf_pcm and state
* ? pcm interrupt no pointer
* ? underused structure members
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/pci.h>
#include <linux/malloc.h>
#include <linux/poll.h>
#include <linux/ac97_codec.h>
#include <linux/sound.h>
#include <asm/io.h>
#include <asm/dma.h>
#include <asm/uaccess.h>
#include "ymfpci.h"
#define snd_magic_cast(t, p, err) ((t *)(p))
/* Channels, such as play and record. I do only play a.t.m. XXX */
#define NR_HW_CH 1
static void ymfpci_free(ymfpci_t *codec);
static int ymf_playback_trigger(ymfpci_t *codec, ymfpci_pcm_t *ypcm, int cmd);
static int ymfpci_voice_alloc(ymfpci_t *codec, ymfpci_voice_type_t type,
int pair, ymfpci_voice_t **rvoice);
static int ymfpci_voice_free(ymfpci_t *codec, ymfpci_voice_t *pvoice);
static int ymf_playback_prepare(ymfpci_t *codec, struct ymf_state *state);
static int ymf_state_alloc(ymfpci_t *unit, int nvirt, int instance);
static ymfpci_t *ymf_devs = NULL;
/*
* constants
*/
static struct ymf_devid {
int id;
char *name;
} ymf_devv[] = {
{ PCI_DEVICE_ID_YAMAHA_724, "YMF724" },
{ PCI_DEVICE_ID_YAMAHA_724F, "YMF724F" },
{ PCI_DEVICE_ID_YAMAHA_740, "YMF740" },
{ PCI_DEVICE_ID_YAMAHA_740C, "YMF740C" },
{ PCI_DEVICE_ID_YAMAHA_744, "YMF744" },
{ PCI_DEVICE_ID_YAMAHA_754, "YMF754" },
};
/*
* Mindlessly copied from cs46xx XXX
*/
extern __inline__ unsigned ld2(unsigned int x)
{
unsigned r = 0;
if (x >= 0x10000) {
x >>= 16;
r += 16;
}
if (x >= 0x100) {
x >>= 8;
r += 8;
}
if (x >= 0x10) {
x >>= 4;
r += 4;
}
if (x >= 4) {
x >>= 2;
r += 2;
}
if (x >= 2)
r++;
return r;
}
/*
* common I/O routines
*/
static inline u8 ymfpci_readb(ymfpci_t *codec, u32 offset)
{
return readb(codec->reg_area_virt + offset);
}
static inline void ymfpci_writeb(ymfpci_t *codec, u32 offset, u8 val)
{
writeb(val, codec->reg_area_virt + offset);
}
static inline u16 ymfpci_readw(ymfpci_t *codec, u32 offset)
{
return readw(codec->reg_area_virt + offset);
}
static inline void ymfpci_writew(ymfpci_t *codec, u32 offset, u16 val)
{
writew(val, codec->reg_area_virt + offset);
}
static inline u32 ymfpci_readl(ymfpci_t *codec, u32 offset)
{
return readl(codec->reg_area_virt + offset);
}
static inline void ymfpci_writel(ymfpci_t *codec, u32 offset, u32 val)
{
writel(val, codec->reg_area_virt + offset);
}
static int ymfpci_codec_ready(ymfpci_t *codec, int secondary, int sched)
{
signed long end_time;
u32 reg = secondary ? YDSXGR_SECSTATUSADR : YDSXGR_PRISTATUSADR;
end_time = jiffies + 3 * (HZ / 4);
do {
if ((ymfpci_readw(codec, reg) & 0x8000) == 0)
return 0;
if (sched) {
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(1);
}
} while (end_time - (signed long)jiffies >= 0);
printk("ymfpci_codec_ready: codec %i is not ready [0x%x]\n",
secondary, ymfpci_readw(codec, reg));
return -EBUSY;
}
static void ymfpci_codec_write(struct ac97_codec *dev, u8 reg, u16 val)
{
ymfpci_t *codec = dev->private_data;
u32 cmd;
/* XXX Do make use of dev->id */
ymfpci_codec_ready(codec, 0, 0);
cmd = ((YDSXG_AC97WRITECMD | reg) << 16) | val;
ymfpci_writel(codec, YDSXGR_AC97CMDDATA, cmd);
}
static u16 ymfpci_codec_read(struct ac97_codec *dev, u8 reg)
{
ymfpci_t *codec = dev->private_data;
if (ymfpci_codec_ready(codec, 0, 0))
return ~0;
ymfpci_writew(codec, YDSXGR_AC97CMDADR, YDSXG_AC97READCMD | reg);
if (ymfpci_codec_ready(codec, 0, 0))
return ~0;
if (codec->device_id == PCI_DEVICE_ID_YAMAHA_744 && codec->rev < 2) {
int i;
for (i = 0; i < 600; i++)
ymfpci_readw(codec, YDSXGR_PRISTATUSDATA);
}
return ymfpci_readw(codec, YDSXGR_PRISTATUSDATA);
}
/*
* Misc routines
*/
/*
* Calculate the actual sampling rate relatetively to the base clock (48kHz).
*/
static u32 ymfpci_calc_delta(u32 rate)
{
switch (rate) {
case 8000: return 0x02aaab00;
case 11025: return 0x03accd00;
case 16000: return 0x05555500;
case 22050: return 0x07599a00;
case 32000: return 0x0aaaab00;
case 44100: return 0x0eb33300;
default: return ((rate << 16) / 48000) << 12;
}
}
static u32 def_rate[8] = {
100, 2000, 8000, 11025, 16000, 22050, 32000, 48000
};
static u32 ymfpci_calc_lpfK(u32 rate)
{
u32 i;
static u32 val[8] = {
0x00570000, 0x06AA0000, 0x18B20000, 0x20930000,
0x2B9A0000, 0x35A10000, 0x3EAA0000, 0x40000000
};
if (rate == 44100)
return 0x40000000; /* FIXME: What's the right value? */
for (i = 0; i < 8; i++)
if (rate <= def_rate[i])
return val[i];
return val[0];
}
static u32 ymfpci_calc_lpfQ(u32 rate)
{
u32 i;
static u32 val[8] = {
0x35280000, 0x34A70000, 0x32020000, 0x31770000,
0x31390000, 0x31C90000, 0x33D00000, 0x40000000
};
if (rate == 44100)
return 0x370A0000;
for (i = 0; i < 8; i++)
if (rate <= def_rate[i])
return val[i];
return val[0];
}
static u32 ymf_calc_lend(u32 rate)
{
return (rate * YMF_SAMPF) / 48000;
}
/*
* XXX Find if this function exists in the OSS framework.
* XXX Make sure we do no panic when ADPCM is selected.
*/
static int ymf_pcm_format_width(int format)
{
static int mask16 = AFMT_S16_LE|AFMT_S16_BE|AFMT_U16_LE|AFMT_U16_BE;
if ((format & (format-1)) != 0) {
printk(KERN_ERR "ymfpci: format 0x%x is not a power of 2\n", format);
return 8;
}
if (format == AFMT_IMA_ADPCM) return 4;
if ((format & mask16) != 0) return 16;
return 8;
}
static void ymf_pcm_update_shift(struct ymf_pcm_format *f)
{
f->shift = 0;
if (f->voices == 2)
f->shift++;
if (ymf_pcm_format_width(f->format) == 16)
f->shift++;
}
/*
* Whole OSS-style DMA machinery is taken from cs46xx.
*/
/* Are you sure 32K is not too much? See if mpg123 skips on loaded systems. */
#define DMABUF_DEFAULTORDER (15-PAGE_SHIFT)
#define DMABUF_MINORDER 1
/* allocate DMA buffer, playback and recording buffer should be allocated seperately */
static int alloc_dmabuf(struct ymf_state *state)
{
struct ymf_dmabuf *dmabuf = &state->dmabuf;
void *rawbuf = NULL;
int order;
struct page * map, * mapend;
/* alloc as big a chunk as we can */
for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--)
if((rawbuf = (void *)__get_free_pages(GFP_KERNEL|GFP_DMA, order)))
break;
if (!rawbuf)
return -ENOMEM;
#if 0
printk(KERN_DEBUG "ymfpci: allocated %ld (order = %d) bytes at %p\n",
PAGE_SIZE << order, order, rawbuf);
#endif
dmabuf->ready = dmabuf->mapped = 0;
dmabuf->rawbuf = rawbuf;
dmabuf->buforder = order;
/* now mark the pages as reserved; otherwise remap_page_range doesn't do what we want */
mapend = virt_to_page(rawbuf + (PAGE_SIZE << order) - 1);
for (map = virt_to_page(rawbuf); map <= mapend; map++)
set_bit(PG_reserved, &map->flags);
return 0;
}
/* free DMA buffer */
static void dealloc_dmabuf(struct ymf_state *state)
{
struct ymf_dmabuf *dmabuf = &state->dmabuf;
struct page *map, *mapend;
if (dmabuf->rawbuf) {
/* undo marking the pages as reserved */
mapend = virt_to_page(dmabuf->rawbuf + (PAGE_SIZE << dmabuf->buforder) - 1);
for (map = virt_to_page(dmabuf->rawbuf); map <= mapend; map++)
clear_bit(PG_reserved, &map->flags);
free_pages((unsigned long)dmabuf->rawbuf,dmabuf->buforder);
}
dmabuf->rawbuf = NULL;
dmabuf->mapped = dmabuf->ready = 0;
}
static int prog_dmabuf(struct ymf_state *state, unsigned rec)
{
struct ymf_dmabuf *dmabuf = &state->dmabuf;
int w_16;
unsigned bytepersec;
unsigned bufsize;
unsigned long flags;
int redzone;
int ret;
w_16 = ymf_pcm_format_width(state->format.format) == 16;
spin_lock_irqsave(&state->unit->reg_lock, flags);
dmabuf->hwptr = dmabuf->swptr = 0;
dmabuf->total_bytes = 0;
dmabuf->count = dmabuf->error = 0;
spin_unlock_irqrestore(&state->unit->reg_lock, flags);
/* allocate DMA buffer if not allocated yet */
if (!dmabuf->rawbuf)
if ((ret = alloc_dmabuf(state)))
return ret;
bytepersec = state->format.rate << state->format.shift;
/*
* Create fake fragment sizes and numbers for OSS ioctls.
*/
bufsize = PAGE_SIZE << dmabuf->buforder;
if (dmabuf->ossfragshift) {
if ((1000 << dmabuf->ossfragshift) < bytepersec)
dmabuf->fragshift = ld2(bytepersec/1000);
else
dmabuf->fragshift = dmabuf->ossfragshift;
} else {
/* lets hand out reasonable big ass buffers by default */
dmabuf->fragshift = (dmabuf->buforder + PAGE_SHIFT -2);
}
dmabuf->numfrag = bufsize >> dmabuf->fragshift;
while (dmabuf->numfrag < 4 && dmabuf->fragshift > 3) {
dmabuf->fragshift--;
dmabuf->numfrag = bufsize >> dmabuf->fragshift;
}
dmabuf->fragsize = 1 << dmabuf->fragshift;
dmabuf->fragsamples = dmabuf->fragsize >> state->format.shift;
dmabuf->dmasize = dmabuf->numfrag << dmabuf->fragshift;
/*
* Import what Doom might have set with SNDCTL_DSD_SETFRAGMENT.
*/
if (dmabuf->ossmaxfrags >= 2 && dmabuf->ossmaxfrags < dmabuf->numfrag) {
dmabuf->numfrag = dmabuf->ossmaxfrags;
dmabuf->dmasize = dmabuf->numfrag << dmabuf->fragshift;
redzone = ymf_calc_lend(state->format.rate);
redzone <<= (state->format.shift + 1);
if (dmabuf->dmasize < redzone*3) {
/*
* The driver works correctly with minimum dmasize
* of redzone*2, but it produces stoppage and clicks.
* So, make it little larger for smoother sound.
* XXX Make dmasize a wholy divisible by fragsize.
*/
// printk(KERN_ERR "ymfpci: dmasize=%d < redzone=%d * 3\n",
// dmabuf->dmasize, redzone);
dmabuf->dmasize = redzone*3;
}
}
memset(dmabuf->rawbuf, w_16 ? 0 : 0x80, dmabuf->dmasize);
/*
* Now set up the ring
*/
spin_lock_irqsave(&state->unit->reg_lock, flags);
if (rec) {
/* ymf_rec_setup(state); */
} else {
if ((ret = ymf_playback_prepare(state->unit, state)) != 0) {
return ret;
}
}
spin_unlock_irqrestore(&state->unit->reg_lock, flags);
/* set the ready flag for the dma buffer (this comment is not stupid) */
dmabuf->ready = 1;
#if 0
printk("prog_dmabuf: rate %d format 0x%x,"
" numfrag %d fragsize %d dmasize %d\n",
state->format.rate, state->format.format, dmabuf->numfrag,
dmabuf->fragsize, dmabuf->dmasize);
#endif
return 0;
}
static void ymf_start_dac(struct ymf_state *state)
{
ymf_playback_trigger(state->unit, &state->ypcm, 1);
}
/*
* Wait until output is drained.
* This does not kill the hardware for the sake of ioctls.
*/
static void ymf_wait_dac(struct ymf_state *state)
{
struct ymf_unit *unit = state->unit;
ymfpci_pcm_t *ypcm = &state->ypcm;
DECLARE_WAITQUEUE(waita, current);
unsigned long flags;
add_wait_queue(&state->dmabuf.wait, &waita);
spin_lock_irqsave(&unit->reg_lock, flags);
if (state->dmabuf.count != 0 && !state->ypcm.running) {
ymf_playback_trigger(unit, ypcm, 1);
}
#if 0
if (file->f_flags & O_NONBLOCK) {
/*
* XXX Our mistake is to attach DMA buffer to state
* rather than to some per-device structure.
* Cannot skip waiting, can only make it shorter.
*/
}
#endif
while (ypcm->running) {
spin_unlock_irqrestore(&unit->reg_lock, flags);
set_current_state(TASK_UNINTERRUPTIBLE);
schedule();
spin_lock_irqsave(&unit->reg_lock, flags);
}
spin_unlock_irqrestore(&unit->reg_lock, flags);
set_current_state(TASK_RUNNING);
remove_wait_queue(&state->dmabuf.wait, &waita);
/*
* This function may take up to 4 seconds to reach this point
* (32K circular buffer, 8000 Hz). User notices.
*/
}
/*
* Hardware start management
*/
static void ymfpci_hw_start(ymfpci_t *codec)
{
unsigned long flags;
spin_lock_irqsave(&codec->reg_lock, flags);
if (codec->start_count++ == 0) {
ymfpci_writel(codec, YDSXGR_MODE, 3);
codec->active_bank = ymfpci_readl(codec, YDSXGR_CTRLSELECT) & 1;
}
spin_unlock_irqrestore(&codec->reg_lock, flags);
}
static void ymfpci_hw_stop(ymfpci_t *codec)
{
unsigned long flags;
long timeout = 1000;
spin_lock_irqsave(&codec->reg_lock, flags);
if (--codec->start_count == 0) {
ymfpci_writel(codec, YDSXGR_MODE, 0);
while (timeout-- > 0) {
if ((ymfpci_readl(codec, YDSXGR_STATUS) & 2) == 0)
break;
}
}
spin_unlock_irqrestore(&codec->reg_lock, flags);
}
/*
* Playback voice management
*/
static int voice_alloc(ymfpci_t *codec, ymfpci_voice_type_t type, int pair, ymfpci_voice_t **rvoice)
{
ymfpci_voice_t *voice, *voice2;
int idx;
*rvoice = NULL;
for (idx = 0; idx < 64; idx += pair ? 2 : 1) {
voice = &codec->voices[idx];
voice2 = pair ? &codec->voices[idx+1] : NULL;
if (voice->use || (voice2 && voice2->use))
continue;
voice->use = 1;
if (voice2)
voice2->use = 1;
switch (type) {
case YMFPCI_PCM:
voice->pcm = 1;
if (voice2)
voice2->pcm = 1;
break;
case YMFPCI_SYNTH:
voice->synth = 1;
break;
case YMFPCI_MIDI:
voice->midi = 1;
break;
}
ymfpci_hw_start(codec);
if (voice2)
ymfpci_hw_start(codec);
*rvoice = voice;
return 0;
}
return -ENOMEM;
}
static int ymfpci_voice_alloc(ymfpci_t *codec, ymfpci_voice_type_t type,
int pair, ymfpci_voice_t **rvoice)
{
unsigned long flags;
int result;
spin_lock_irqsave(&codec->voice_lock, flags);
for (;;) {
result = voice_alloc(codec, type, pair, rvoice);
if (result == 0 || type != YMFPCI_PCM)
break;
/* TODO: synth/midi voice deallocation */
break;
}
spin_unlock_irqrestore(&codec->voice_lock, flags);
return result;
}
static int ymfpci_voice_free(ymfpci_t *codec, ymfpci_voice_t *pvoice)
{
unsigned long flags;
ymfpci_hw_stop(codec);
spin_lock_irqsave(&codec->voice_lock, flags);
pvoice->use = pvoice->pcm = pvoice->synth = pvoice->midi = 0;
pvoice->ypcm = NULL;
pvoice->interrupt = NULL;
spin_unlock_irqrestore(&codec->voice_lock, flags);
return 0;
}
/*
* PCM part
*/
static void ymf_pcm_interrupt(ymfpci_t *codec, ymfpci_voice_t *voice)
{
ymfpci_pcm_t *ypcm;
int redzone;
int pos, delta, swptr;
int played, distance;
struct ymf_state *state;
struct ymf_dmabuf *dmabuf;
char silence;
if ((ypcm = voice->ypcm) == NULL) {
/* P3 */ printk("ymf_pcm_interrupt: voice %d: no ypcm\n", voice->number);
return;
}
if ((state = ypcm->state) == NULL) {
/* P3 */ printk("ymf_pcm_interrupt: voice %d: no state\n", voice->number);
ypcm->running = 0; // lock it
return;
}
dmabuf = &state->dmabuf;
spin_lock(&codec->reg_lock);
if (ypcm->running) {
/* P3 */ /** printk("ymfpci: %d, intr bank %d count %d start 0x%x:%x\n",
voice->number, codec->active_bank, dmabuf->count,
voice->bank[0].start, voice->bank[1].start); **/
silence = (ymf_pcm_format_width(state->format.format) == 16) ?
0 : 0x80;
/* We need actual left-hand-side redzone size here. */
redzone = ymf_calc_lend(state->format.rate);
redzone <<= (state->format.shift + 1);
swptr = dmabuf->swptr;
pos = voice->bank[codec->active_bank].start;
pos <<= state->format.shift;
if (pos < 0 || pos >= dmabuf->dmasize) { /* ucode bug */
printk(KERN_ERR
"ymfpci%d: %d: runaway: hwptr %d dmasize %d\n",
codec->inst, voice->number,
dmabuf->hwptr, dmabuf->dmasize);
pos = 0;
}
if (pos < dmabuf->hwptr) {
delta = dmabuf->dmasize - dmabuf->hwptr;
memset(dmabuf->rawbuf + dmabuf->hwptr, silence, delta);
delta += pos;
memset(dmabuf->rawbuf, silence, pos);
} else {
delta = pos - dmabuf->hwptr;
memset(dmabuf->rawbuf + dmabuf->hwptr, silence, delta);
}
dmabuf->hwptr = pos;
if (dmabuf->count == 0) {
printk("ymfpci%d: %d: strain: hwptr %d\n",
codec->inst, voice->number, dmabuf->hwptr);
ymf_playback_trigger(codec, ypcm, 0);
}
if (swptr <= pos) {
distance = pos - swptr;
} else {
distance = dmabuf->dmasize - (swptr - pos);
}
if (distance < redzone) {
/*
* hwptr inside redzone => DMA ran out of samples.
*/
if (delta < dmabuf->count) {
/*
* Lost interrupt or other screwage.
*/
printk("ymfpci%d: %d: lost: delta %d"
" hwptr %d swptr %d distance %d count %d\n",
codec->inst, voice->number, delta,
dmabuf->hwptr, swptr, distance, dmabuf->count);
} else {
/*
* Normal end of DMA.
*/
// printk("ymfpci%d: %d: done: delta %d"
// " hwptr %d swptr %d distance %d count %d\n",
// codec->inst, voice->number, delta,
// dmabuf->hwptr, swptr, distance, dmabuf->count);
}
played = dmabuf->count;
if (ypcm->running) {
ymf_playback_trigger(codec, ypcm, 0);
}
} else {
/*
* hwptr is chipping away towards a remote swptr.
* Calculate other distance and apply it to count.
*/
if (swptr >= pos) {
distance = swptr - pos;
} else {
distance = dmabuf->dmasize - (pos - swptr);
}
if (distance < dmabuf->count) {
played = dmabuf->count - distance;
} else {
played = 0;
}
}
dmabuf->total_bytes += played;
dmabuf->count -= played;
if (dmabuf->count < dmabuf->dmasize / 2) {
wake_up(&dmabuf->wait);
}
}
spin_unlock(&codec->reg_lock);
}
#if HAVE_RECORD
static void ymfpci_pcm_capture_interrupt(snd_pcm_subchn_t *substream)
{
snd_pcm_runtime_t *runtime = substream->runtime;
ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, );
ymfpci_t *codec = ypcm->codec;
u32 pos, delta;
spin_lock(&codec->reg_lock);
if (ypcm->running) {
pos = codec->bank_capture[ypcm->capture_bank_number][codec->active_bank]->start << ypcm->shift_offset;
if (pos < ypcm->last_pos) // <-- dmabuf->hwptr
delta = pos + (ypcm->buffer_size - ypcm->last_pos);
else
delta = pos - ypcm->last_pos;
ypcm->frag_pos += delta;
ypcm->last_pos = pos;
while (ypcm->frag_pos >= ypcm->frag_size) {
ypcm->frag_pos -= ypcm->frag_size;
// printk("done - active_bank = 0x%x, start = 0x%x\n", codec->active_bank, voice->bank[codec->active_bank].start);
spin_unlock(&codec->reg_lock);
snd_pcm_transfer_done(substream);
spin_lock(&codec->reg_lock);
}
}
spin_unlock(&codec->reg_lock);
}
#endif
static int ymf_playback_trigger(ymfpci_t *codec, ymfpci_pcm_t *ypcm, int cmd)
{
if (ypcm->voices[0] == NULL) {
/* P3 */ printk("ymfpci: trigger %d no voice\n", cmd);
return -EINVAL;
}
if (cmd != 0) {
codec->ctrl_playback[ypcm->voices[0]->number + 1] = virt_to_bus(ypcm->voices[0]->bank);
if (ypcm->voices[1] != NULL)
codec->ctrl_playback[ypcm->voices[1]->number + 1] = virt_to_bus(ypcm->voices[1]->bank);
ypcm->running = 1;
} else {
codec->ctrl_playback[ypcm->voices[0]->number + 1] = 0;
if (ypcm->voices[1] != NULL)
codec->ctrl_playback[ypcm->voices[1]->number + 1] = 0;
ypcm->running = 0;
}
return 0;
}
#if HAVE_RECORD
static int ymfpci_capture_trigger(void *private_data,
snd_pcm_subchn_t * substream,
int cmd)
{
unsigned long flags;
ymfpci_t *codec = snd_magic_cast(ymfpci_t, private_data, -ENXIO);
ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, substream->runtime->private_data, -ENXIO);
int result = 0;
u32 tmp;
spin_lock_irqsave(&codec->reg_lock, flags);
if (cmd == SND_PCM_TRIGGER_GO) {
tmp = ymfpci_readl(codec, YDSXGR_MAPOFREC) | (1 << ypcm->capture_bank_number);
ymfpci_writel(codec, YDSXGR_MAPOFREC, tmp);
ypcm->running = 1;
} else if (cmd == SND_PCM_TRIGGER_STOP) {
tmp = ymfpci_readl(codec, YDSXGR_MAPOFREC) & ~(1 << ypcm->capture_bank_number);
ymfpci_writel(codec, YDSXGR_MAPOFREC, tmp);
ypcm->running = 0;
} else {
result = -EINVAL;
}
spin_unlock_irqrestore(&codec->reg_lock, flags);
return result;
}
#endif
static int ymfpci_pcm_voice_alloc(ymfpci_pcm_t *ypcm, int voices)
{
int err;
if (ypcm->voices[1] != NULL && voices < 2) {
ymfpci_voice_free(ypcm->codec, ypcm->voices[1]);
ypcm->voices[1] = NULL;
}
if (voices == 1 && ypcm->voices[0] != NULL)
return 0; /* already allocated */
if (voices == 2 && ypcm->voices[0] != NULL && ypcm->voices[1] != NULL)
return 0; /* already allocated */
if (voices > 1) {
if (ypcm->voices[0] != NULL && ypcm->voices[1] == NULL) {
ymfpci_voice_free(ypcm->codec, ypcm->voices[0]);
ypcm->voices[0] = NULL;
}
}
err = ymfpci_voice_alloc(ypcm->codec, YMFPCI_PCM, voices > 1, &ypcm->voices[0]);
if (err < 0)
return err;
ypcm->voices[0]->ypcm = ypcm;
ypcm->voices[0]->interrupt = ymf_pcm_interrupt;
if (voices > 1) {
ypcm->voices[1] = &ypcm->codec->voices[ypcm->voices[0]->number + 1];
ypcm->voices[1]->ypcm = ypcm;
}
return 0;
}
static void ymf_pcm_init_voice(ymfpci_voice_t *voice, int stereo,
int rate, int w_16, unsigned long addr, unsigned int end, int spdif)
{
u32 format;
u32 delta = ymfpci_calc_delta(rate);
u32 lpfQ = ymfpci_calc_lpfQ(rate);
u32 lpfK = ymfpci_calc_lpfK(rate);
ymfpci_playback_bank_t *bank;
int nbank;
format = (stereo ? 0x00010000 : 0) | (w_16 ? 0 : 0x80000000);
if (stereo)
end >>= 1;
if (w_16)
end >>= 1;
/* P3 */ // printk("ymf_pcm_init_voice: %d: Rate %d Format 0x%08x Delta 0x%x End 0x%x\n",
// voice->number, rate, format, delta, end);
for (nbank = 0; nbank < 2; nbank++) {
bank = &voice->bank[nbank];
bank->format = format;
bank->loop_default = 0; /* 0-loops forever, otherwise count */
bank->base = addr;
bank->loop_start = 0;
bank->loop_end = end;
bank->loop_frac = 0;
bank->eg_gain_end = 0x40000000;
bank->lpfQ = lpfQ;
bank->status = 0;
bank->num_of_frames = 0;
bank->loop_count = 0;
bank->start = 0;
bank->start_frac = 0;
bank->delta =
bank->delta_end = delta;
bank->lpfK =
bank->lpfK_end = lpfK;
bank->eg_gain = 0x40000000;
bank->lpfD1 =
bank->lpfD2 = 0;
bank->left_gain =
bank->right_gain =
bank->left_gain_end =
bank->right_gain_end =
bank->eff1_gain =
bank->eff2_gain =
bank->eff3_gain =
bank->eff1_gain_end =
bank->eff2_gain_end =
bank->eff3_gain_end = 0;
if (!stereo) {
if (!spdif) {
bank->left_gain =
bank->right_gain =
bank->left_gain_end =
bank->right_gain_end = 0x40000000;
} else {
bank->eff2_gain =
bank->eff2_gain_end =
bank->eff3_gain =
bank->eff3_gain_end = 0x40000000;
}
} else {
if (!spdif) {
if ((voice->number & 1) == 0) {
bank->format |= 1;
bank->left_gain =
bank->left_gain_end = 0x40000000;
} else {
bank->right_gain =
bank->right_gain_end = 0x40000000;
}
} else {
if ((voice->number & 1) == 0) {
bank->format |= 1;
bank->eff2_gain =
bank->eff2_gain_end = 0x40000000;
} else {
bank->eff3_gain =
bank->eff3_gain_end = 0x40000000;
}
}
}
}
}
/*
* XXX Use new cache coherent PCI DMA routines instead of virt_to_bus.
*/
static int ymf_playback_prepare(ymfpci_t *codec, struct ymf_state *state)
{
ymfpci_pcm_t *ypcm = &state->ypcm;
int err, nvoice;
if ((err = ymfpci_pcm_voice_alloc(ypcm, state->format.voices)) < 0) {
/* Cannot be unless we leak voices in ymf_release! */
printk(KERN_ERR "ymfpci%d: cannot allocate voice!\n",
codec->inst);
return err;
}
for (nvoice = 0; nvoice < state->format.voices; nvoice++) {
ymf_pcm_init_voice(ypcm->voices[nvoice],
state->format.voices == 2, state->format.rate,
ymf_pcm_format_width(state->format.format) == 16,
virt_to_bus(state->dmabuf.rawbuf), state->dmabuf.dmasize,
ypcm->spdif);
}
return 0;
}
#if 0 /* old */
static int ymfpci_capture_prepare(void *private_data,
snd_pcm_subchn_t * substream)
{
ymfpci_t *codec = snd_magic_cast(ymfpci_t, private_data, -ENXIO);
snd_pcm_runtime_t *runtime = substream->runtime;
ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, -ENXIO);
ymfpci_capture_bank_t * bank;
int nbank;
u32 rate, format;
ypcm->frag_size = snd_pcm_lib_transfer_fragment(substream);
ypcm->buffer_size = snd_pcm_lib_transfer_size(substream);
ypcm->frag_pos = 0;
ypcm->last_pos = 0;
ypcm->shift_offset = 0;
rate = ((48000 * 4096) / runtime->format.rate) - 1;
format = 0;
if (runtime->format.voices == 2)
format |= 2;
if (snd_pcm_format_width(runtime->format.format) == 8)
format |= 1;
switch (ypcm->capture_bank_number) {
case 0:
ymfpci_writel(codec, YDSXGR_RECFORMAT, format);
ymfpci_writel(codec, YDSXGR_RECSLOTSR, rate);
break;
case 1:
ymfpci_writel(codec, YDSXGR_ADCFORMAT, format);
ymfpci_writel(codec, YDSXGR_ADCSLOTSR, rate);
break;
}
for (nbank = 0; nbank < 2; nbank++) {
bank = codec->bank_capture[ypcm->capture_bank_number][nbank];
bank->base = virt_to_bus(runtime->dma_area->buf);
bank->loop_end = ypcm->buffer_size;
bank->start = 0;
bank->num_of_loops = 0;
}
if (runtime->digital.dig_valid)
/*runtime->digital.type == SND_PCM_DIG_AES_IEC958*/
ymfpci_writew(codec, YDSXGR_SPDIFOUTSTATUS, runtime->digital.dig_status[0] |
(runtime->digital.dig_status[1] << 8));
return 0;
}
static unsigned int ymfpci_playback_pointer(void *private_data,
snd_pcm_subchn_t * substream)
{
ymfpci_t *codec = snd_magic_cast(ymfpci_t, private_data, -ENXIO);
snd_pcm_runtime_t *runtime = substream->runtime;
ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, -ENXIO);
ymfpci_voice_t *voice = ypcm->voices[0];
unsigned long flags;
unsigned int result;
spin_lock_irqsave(&codec->reg_lock, flags);
if (ypcm->running && voice)
result = voice->bank[codec->active_bank].start << ypcm->shift_offset;
else
result = 0;
spin_unlock_irqrestore(&codec->reg_lock, flags);
return result;
}
static unsigned int ymfpci_capture_pointer(void *private_data,
snd_pcm_subchn_t * substream)
{
ymfpci_t *codec = snd_magic_cast(ymfpci_t, private_data, -ENXIO);
snd_pcm_runtime_t *runtime = substream->runtime;
ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, -ENXIO);
unsigned long flags;
unsigned int result;
spin_lock_irqsave(&codec->reg_lock, flags);
if (ypcm->running)
result = codec->bank_capture[ypcm->capture_bank_number][codec->active_bank]->start << ypcm->shift_offset;
else
result = 0;
spin_unlock_irqrestore(&codec->reg_lock, flags);
return result;
}
#endif /* old */
void ymf_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
ymfpci_t *codec = dev_id;
u32 status, nvoice, mode;
ymfpci_voice_t *voice;
status = ymfpci_readl(codec, YDSXGR_STATUS);
if (status & 0x80000000) {
spin_lock(&codec->reg_lock);
ymfpci_writel(codec, YDSXGR_STATUS, 0x80000000);
mode = ymfpci_readl(codec, YDSXGR_MODE) | 2;
ymfpci_writel(codec, YDSXGR_MODE, mode);
spin_unlock(&codec->reg_lock);
codec->active_bank = ymfpci_readl(codec, YDSXGR_CTRLSELECT) & 1;
spin_lock(&codec->voice_lock);
for (nvoice = 0; nvoice < 64; nvoice++) {
voice = &codec->voices[nvoice];
if (voice->interrupt)
voice->interrupt(codec, voice);
}
spin_unlock(&codec->voice_lock);
}
status = ymfpci_readl(codec, YDSXGR_INTFLAG);
if (status & 1) {
/* timer handler */
ymfpci_writel(codec, YDSXGR_INTFLAG, ~0);
}
}
static void ymf_pcm_free_substream(ymfpci_pcm_t *ypcm)
{
ymfpci_t *codec;
if (ypcm) {
codec = ypcm->codec;
if (ypcm->voices[1])
ymfpci_voice_free(codec, ypcm->voices[1]);
if (ypcm->voices[0])
ymfpci_voice_free(codec, ypcm->voices[0]);
}
}
static int ymf_state_alloc(ymfpci_t *unit, int nvirt, int instance)
{
ymfpci_pcm_t *ypcm;
struct ymf_state *state;
if ((state = kmalloc(sizeof(struct ymf_state), GFP_KERNEL)) == NULL) {
goto out0;
}
memset(state, 0, sizeof(struct ymf_state));
init_waitqueue_head(&state->open_wait);
init_waitqueue_head(&state->dmabuf.wait);
ypcm = &state->ypcm;
ypcm->state = state;
ypcm->codec = unit;
ypcm->type = PLAYBACK_VOICE;
state->unit = unit;
state->virt = nvirt;
state->format.format = AFMT_U8;
state->format.rate = 8000;
state->format.voices = 1;
ymf_pcm_update_shift(&state->format);
unit->states[nvirt] = state;
return 0;
out0:
return -ENOMEM;
}
#if HAVE_RECORD
static int ymfpci_capture_open(void *private_data,
snd_pcm_subchn_t * substream,
u32 capture_bank_number)
{
ymfpci_t *codec = snd_magic_cast(ymfpci_t, private_data, -ENXIO);
snd_pcm_runtime_t *runtime = substream->runtime;
ymfpci_pcm_t *ypcm;
int err;
if ((err = snd_pcm_dma_alloc(substream, !capture_bank_number ? codec->dma2ptr : codec->dma3ptr, "YMFPCI - ADC")) < 0)
return err;
ypcm = snd_magic_kcalloc(ymfpci_pcm_t, 0, GFP_KERNEL);
if (ypcm == NULL) {
snd_pcm_dma_free(substream);
return -ENOMEM;
}
ypcm->codec = codec;
ypcm->type = capture_bank_number + CAPTURE_REC;
ypcm->substream = substream;
ypcm->capture_bank_number = capture_bank_number;
codec->capture_substream[capture_bank_number] = substream;
runtime->hw = &ymfpci_capture;
snd_pcm_set_mixer(substream, codec->mixer->device, codec->ac97->me_capture);
runtime->private_data = ypcm;
runtime->private_free = ymfpci_pcm_free_substream;
ymfpci_hw_start(codec);
return 0;
}
#endif /* old */
/* AES/IEC958 channel status bits */
#define SND_PCM_AES0_PROFESSIONAL (1<<0) /* 0 = consumer, 1 = professional */
#define SND_PCM_AES0_NONAUDIO (1<<1) /* 0 = audio, 1 = non-audio */
#define SND_PCM_AES0_PRO_EMPHASIS (7<<2) /* mask - emphasis */
#define SND_PCM_AES0_PRO_EMPHASIS_NOTID (0<<2) /* emphasis not indicated */
#define SND_PCM_AES0_PRO_EMPHASIS_NONE (1<<2) /* none emphasis */
#define SND_PCM_AES0_PRO_EMPHASIS_5015 (3<<2) /* 50/15us emphasis */
#define SND_PCM_AES0_PRO_EMPHASIS_CCITT (7<<2) /* CCITT J.17 emphasis */
#define SND_PCM_AES0_PRO_FREQ_UNLOCKED (1<<5) /* source sample frequency: 0 = locked, 1 = unlocked */
#define SND_PCM_AES0_PRO_FS (3<<6) /* mask - sample frequency */
#define SND_PCM_AES0_PRO_FS_NOTID (0<<6) /* fs not indicated */
#define SND_PCM_AES0_PRO_FS_44100 (1<<6) /* 44.1kHz */
#define SND_PCM_AES0_PRO_FS_48000 (2<<6) /* 48kHz */
#define SND_PCM_AES0_PRO_FS_32000 (3<<6) /* 32kHz */
#define SND_PCM_AES0_CON_NOT_COPYRIGHT (1<<2) /* 0 = copyright, 1 = not copyright */
#define SND_PCM_AES0_CON_EMPHASIS (7<<3) /* mask - emphasis */
#define SND_PCM_AES0_CON_EMPHASIS_NONE (0<<3) /* none emphasis */
#define SND_PCM_AES0_CON_EMPHASIS_5015 (1<<3) /* 50/15us emphasis */
#define SND_PCM_AES0_CON_MODE (3<<6) /* mask - mode */
#define SND_PCM_AES1_PRO_MODE (15<<0) /* mask - channel mode */
#define SND_PCM_AES1_PRO_MODE_NOTID (0<<0) /* not indicated */
#define SND_PCM_AES1_PRO_MODE_STEREOPHONIC (2<<0) /* stereophonic - ch A is left */
#define SND_PCM_AES1_PRO_MODE_SINGLE (4<<0) /* single channel */
#define SND_PCM_AES1_PRO_MODE_TWO (8<<0) /* two channels */
#define SND_PCM_AES1_PRO_MODE_PRIMARY (12<<0) /* primary/secondary */
#define SND_PCM_AES1_PRO_MODE_BYTE3 (15<<0) /* vector to byte 3 */
#define SND_PCM_AES1_PRO_USERBITS (15<<4) /* mask - user bits */
#define SND_PCM_AES1_PRO_USERBITS_NOTID (0<<4) /* not indicated */
#define SND_PCM_AES1_PRO_USERBITS_192 (8<<4) /* 192-bit structure */
#define SND_PCM_AES1_PRO_USERBITS_UDEF (12<<4) /* user defined application */
#define SND_PCM_AES1_CON_CATEGORY 0x7f
#define SND_PCM_AES1_CON_GENERAL 0x00
#define SND_PCM_AES1_CON_EXPERIMENTAL 0x40
#define SND_PCM_AES1_CON_SOLIDMEM_MASK 0x0f
#define SND_PCM_AES1_CON_SOLIDMEM_ID 0x08
#define SND_PCM_AES1_CON_BROADCAST1_MASK 0x07
#define SND_PCM_AES1_CON_BROADCAST1_ID 0x04
#define SND_PCM_AES1_CON_DIGDIGCONV_MASK 0x07
#define SND_PCM_AES1_CON_DIGDIGCONV_ID 0x02
#define SND_PCM_AES1_CON_ADC_COPYRIGHT_MASK 0x1f
#define SND_PCM_AES1_CON_ADC_COPYRIGHT_ID 0x06
#define SND_PCM_AES1_CON_ADC_MASK 0x1f
#define SND_PCM_AES1_CON_ADC_ID 0x16
#define SND_PCM_AES1_CON_BROADCAST2_MASK 0x0f
#define SND_PCM_AES1_CON_BROADCAST2_ID 0x0e
#define SND_PCM_AES1_CON_LASEROPT_MASK 0x07
#define SND_PCM_AES1_CON_LASEROPT_ID 0x01
#define SND_PCM_AES1_CON_MUSICAL_MASK 0x07
#define SND_PCM_AES1_CON_MUSICAL_ID 0x05
#define SND_PCM_AES1_CON_MAGNETIC_MASK 0x07
#define SND_PCM_AES1_CON_MAGNETIC_ID 0x03
#define SND_PCM_AES1_CON_IEC908_CD (SND_PCM_AES1_CON_LASEROPT_ID|0x00)
#define SND_PCM_AES1_CON_NON_IEC908_CD (SND_PCM_AES1_CON_LASEROPT_ID|0x08)
#define SND_PCM_AES1_CON_PCM_CODER (SND_PCM_AES1_CON_DIGDIGCONV_ID|0x00)
#define SND_PCM_AES1_CON_SAMPLER (SND_PCM_AES1_CON_DIGDIGCONV_ID|0x20)
#define SND_PCM_AES1_CON_MIXER (SND_PCM_AES1_CON_DIGDIGCONV_ID|0x10)
#define SND_PCM_AES1_CON_RATE_CONVERTER (SND_PCM_AES1_CON_DIGDIGCONV_ID|0x18)
#define SND_PCM_AES1_CON_SYNTHESIZER (SND_PCM_AES1_CON_MUSICAL_ID|0x00)
#define SND_PCM_AES1_CON_MICROPHONE (SND_PCM_AES1_CON_MUSICAL_ID|0x08)
#define SND_PCM_AES1_CON_DAT (SND_PCM_AES1_CON_MAGNETIC_ID|0x00)
#define SND_PCM_AES1_CON_VCR (SND_PCM_AES1_CON_MAGNETIC_ID|0x08)
#define SND_PCM_AES1_CON_ORIGINAL (1<<7) /* this bits depends on the category code */
#define SND_PCM_AES2_PRO_SBITS (7<<0) /* mask - sample bits */
#define SND_PCM_AES2_PRO_SBITS_20 (2<<0) /* 20-bit - coordination */
#define SND_PCM_AES2_PRO_SBITS_24 (4<<0) /* 24-bit - main audio */
#define SND_PCM_AES2_PRO_SBITS_UDEF (6<<0) /* user defined application */
#define SND_PCM_AES2_PRO_WORDLEN (7<<3) /* mask - source word length */
#define SND_PCM_AES2_PRO_WORDLEN_NOTID (0<<3) /* not indicated */
#define SND_PCM_AES2_PRO_WORDLEN_22_18 (2<<3) /* 22-bit or 18-bit */
#define SND_PCM_AES2_PRO_WORDLEN_23_19 (4<<3) /* 23-bit or 19-bit */
#define SND_PCM_AES2_PRO_WORDLEN_24_20 (5<<3) /* 24-bit or 20-bit */
#define SND_PCM_AES2_PRO_WORDLEN_20_16 (6<<3) /* 20-bit or 16-bit */
#define SND_PCM_AES2_CON_SOURCE (15<<0) /* mask - source number */
#define SND_PCM_AES2_CON_SOURCE_UNSPEC (0<<0) /* unspecified */
#define SND_PCM_AES2_CON_CHANNEL (15<<4) /* mask - channel number */
#define SND_PCM_AES2_CON_CHANNEL_UNSPEC (0<<4) /* unspecified */
#define SND_PCM_AES3_CON_FS (15<<0) /* mask - sample frequency */
#define SND_PCM_AES3_CON_FS_44100 (0<<0) /* 44.1kHz */
#define SND_PCM_AES3_CON_FS_48000 (2<<0) /* 48kHz */
#define SND_PCM_AES3_CON_FS_32000 (3<<0) /* 32kHz */
#define SND_PCM_AES3_CON_CLOCK (3<<4) /* mask - clock accuracy */
#define SND_PCM_AES3_CON_CLOCK_1000PPM (0<<4) /* 1000 ppm */
#define SND_PCM_AES3_CON_CLOCK_50PPM (1<<4) /* 50 ppm */
#define SND_PCM_AES3_CON_CLOCK_VARIABLE (2<<4) /* variable pitch */
#if HAVE_RECORD /* old */
static int ymfpci_capture_close(void *private_data,
snd_pcm_subchn_t * substream)
{
ymfpci_t *codec = snd_magic_cast(ymfpci_t, private_data, -ENXIO);
snd_pcm_runtime_t *runtime = substream->runtime;
ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, -ENXIO);
if (ypcm != NULL) {
codec->capture_substream[ypcm->capture_bank_number] = NULL;
ymfpci_hw_stop(codec);
}
snd_pcm_dma_free(substream);
return 0;
}
#endif
/*
* User interface
*/
static loff_t ymf_llseek(struct file *file, loff_t offset, int origin)
{
return -ESPIPE;
}
/* in this loop, dmabuf.count signifies the amount of data that is waiting to be copied to
the user's buffer. it is filled by the dma machine and drained by this loop. */
static ssize_t ymf_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
{
#if HAVE_RECORD
struct cs_state *state = (struct cs_state *)file->private_data;
struct dmabuf *dmabuf = &state->dmabuf;
ssize_t ret;
unsigned long flags;
unsigned swptr;
int cnt;
#ifdef DEBUG
printk("cs461x: cs_read called, count = %d\n", count);
#endif
if (ppos != &file->f_pos)
return -ESPIPE;
if (dmabuf->mapped)
return -ENXIO;
if (!dmabuf->ready && (ret = prog_dmabuf(state, 1)))
return ret;
if (!access_ok(VERIFY_WRITE, buffer, count))
return -EFAULT;
ret = 0;
while (count > 0) {
spin_lock_irqsave(&state->card->lock, flags);
if (dmabuf->count > (signed) dmabuf->dmasize) {
/* buffer overrun, we are recovering from sleep_on_timeout,
resync hwptr and swptr, make process flush the buffer */
dmabuf->count = dmabuf->dmasize;
dmabuf->swptr = dmabuf->hwptr;
}
swptr = dmabuf->swptr;
cnt = dmabuf->dmasize - swptr;
if (dmabuf->count < cnt)
cnt = dmabuf->count;
spin_unlock_irqrestore(&state->card->lock, flags);
if (cnt > count)
cnt = count;
if (cnt <= 0) {
unsigned long tmo;
/* buffer is empty, start the dma machine and wait for data to be
recorded */
start_adc(state);
if (file->f_flags & O_NONBLOCK) {
if (!ret) ret = -EAGAIN;
return ret;
}
/* This isnt strictly right for the 810 but it'll do */
tmo = (dmabuf->dmasize * HZ) / (dmabuf->rate * 2);
tmo >>= sample_shift[dmabuf->fmt];
/* There are two situations when sleep_on_timeout returns, one is when
the interrupt is serviced correctly and the process is waked up by
ISR ON TIME. Another is when timeout is expired, which means that
either interrupt is NOT serviced correctly (pending interrupt) or it
is TOO LATE for the process to be scheduled to run (scheduler latency)
which results in a (potential) buffer overrun. And worse, there is
NOTHING we can do to prevent it. */
if (!interruptible_sleep_on_timeout(&dmabuf->wait, tmo)) {
#ifdef DEBUG
printk(KERN_ERR "cs461x: recording schedule timeout, "
"dmasz %u fragsz %u count %i hwptr %u swptr %u\n",
dmabuf->dmasize, dmabuf->fragsize, dmabuf->count,
dmabuf->hwptr, dmabuf->swptr);
#endif
/* a buffer overrun, we delay the recovery untill next time the
while loop begin and we REALLY have space to record */
}
if (signal_pending(current)) {
ret = ret ? ret : -ERESTARTSYS;
return ret;
}
continue;
}
if (copy_to_user(buffer, dmabuf->rawbuf + swptr, cnt)) {
if (!ret) ret = -EFAULT;
return ret;
}
swptr = (swptr + cnt) % dmabuf->dmasize;
spin_lock_irqsave(&state->card->lock, flags);
dmabuf->swptr = swptr;
dmabuf->count -= cnt;
spin_unlock_irqrestore(&state->card->lock, flags);
count -= cnt;
buffer += cnt;
ret += cnt;
start_adc(state);
}
return ret;
#else
return -EINVAL;
#endif
}
static ssize_t ymf_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
{
struct ymf_state *state = (struct ymf_state *)file->private_data;
struct ymf_dmabuf *dmabuf = &state->dmabuf;
DECLARE_WAITQUEUE(waita, current);
ssize_t ret;
unsigned long flags;
unsigned int swptr;
int cnt; /* This many to go in this revolution */
int redzone;
int delay;
/* P3 */ /* printk("ymf_write: count %d\n", count); */
if (ppos != &file->f_pos)
return -ESPIPE;
if (dmabuf->mapped)
return -ENXIO;
if (!dmabuf->ready && (ret = prog_dmabuf(state, 0)))
return ret;
if (!access_ok(VERIFY_READ, buffer, count))
return -EFAULT;
ret = 0;
/*
* Alan's cs46xx works without a red zone - marvel of ingenuity.
* We are not so brilliant... Red zone does two things:
* 1. allows for safe start after a pause as we have no way
* to know what the actual, relentlessly advancing, hwptr is.
* 2. makes computations in ymf_pcm_interrupt simpler.
*/
redzone = ymf_calc_lend(state->format.rate) << state->format.shift;
redzone *= 3; /* 2 redzone + 1 possible uncertainty reserve. */
add_wait_queue(&dmabuf->wait, &waita);
while (count > 0) {
spin_lock_irqsave(&state->unit->reg_lock, flags);
if (dmabuf->count < 0) {
printk(KERN_ERR
"ymf_write: count %d, was legal in cs46xx\n",
dmabuf->count);
dmabuf->count = 0;
}
if (dmabuf->count == 0) {
swptr = dmabuf->hwptr;
if (state->ypcm.running) {
/*
* Add uncertainty reserve.
*/
cnt = ymf_calc_lend(state->format.rate);
cnt <<= state->format.shift;
if ((swptr += cnt) >= dmabuf->dmasize) {
swptr -= dmabuf->dmasize;
}
}
dmabuf->swptr = swptr;
} else {
/*
* XXX This is not right if dmabuf->count is small -
* about 2*x frame size or less. We cannot count on
* on appending and not causing an artefact.
* Should use a variation of the count==0 case above.
*/
swptr = dmabuf->swptr;
}
cnt = dmabuf->dmasize - swptr;
if (dmabuf->count + cnt > dmabuf->dmasize - redzone)
cnt = (dmabuf->dmasize - redzone) - dmabuf->count;
spin_unlock_irqrestore(&state->unit->reg_lock, flags);
if (cnt > count)
cnt = count;
if (cnt <= 0) {
/* P3 */ /* printk("ymf_write: full, count %d swptr %d\n",
dmabuf->count, dmabuf->swptr); */
/*
* buffer is full, start the dma machine and
* wait for data to be played
*/
spin_lock_irqsave(&state->unit->reg_lock, flags);
if (!state->ypcm.running) {
ymf_playback_trigger(state->unit, &state->ypcm, 1);
}
spin_unlock_irqrestore(&state->unit->reg_lock, flags);
if (file->f_flags & O_NONBLOCK) {
if (!ret) ret = -EAGAIN;
break;
}
set_current_state(TASK_INTERRUPTIBLE);
schedule();
if (signal_pending(current)) {
if (!ret) ret = -ERESTARTSYS;
break;
}
continue;
}
if (copy_from_user(dmabuf->rawbuf + swptr, buffer, cnt)) {
if (!ret) ret = -EFAULT;
break;
}
if ((swptr += cnt) >= dmabuf->dmasize) {
swptr -= dmabuf->dmasize;
}
spin_lock_irqsave(&state->unit->reg_lock, flags);
dmabuf->swptr = swptr;
dmabuf->count += cnt;
/*
* Start here is a bad idea - may cause startup click
* in /bin/play when dmabuf is not full yet.
* However, some broken applications do not make
* any use of SNDCTL_DSP_SYNC (Doom is the worst).
* One frame is about 5.3ms, Doom write size is 46ms.
*/
delay = state->format.rate / 20; /* 50ms */
delay <<= state->format.shift;
if (dmabuf->count >= delay && !state->ypcm.running) {
ymf_playback_trigger(state->unit, &state->ypcm, 1);
}
spin_unlock_irqrestore(&state->unit->reg_lock, flags);
count -= cnt;
buffer += cnt;
ret += cnt;
}
set_current_state(TASK_RUNNING);
remove_wait_queue(&dmabuf->wait, &waita);
/* P3 */ /* printk("ymf_write: dmabuf.count %d\n", dmabuf->count); */
return ret;
}
static unsigned int ymf_poll(struct file *file, struct poll_table_struct *wait)
{
struct ymf_state *state = (struct ymf_state *)file->private_data;
struct ymf_dmabuf *dmabuf = &state->dmabuf;
unsigned long flags;
unsigned int mask = 0;
if (file->f_mode & (FMODE_WRITE | FMODE_READ))
poll_wait(file, &dmabuf->wait, wait);
spin_lock_irqsave(&state->unit->reg_lock, flags);
if (file->f_mode & FMODE_READ) {
if (dmabuf->count >= (signed)dmabuf->fragsize)
mask |= POLLIN | POLLRDNORM;
}
if (file->f_mode & FMODE_WRITE) {
if (dmabuf->mapped) {
if (dmabuf->count >= (signed)dmabuf->fragsize)
mask |= POLLOUT | POLLWRNORM;
} else {
if ((signed)dmabuf->dmasize >= dmabuf->count + (signed)dmabuf->fragsize)
mask |= POLLOUT | POLLWRNORM;
}
}
spin_unlock_irqrestore(&state->unit->reg_lock, flags);
return mask;
}
static int ymf_mmap(struct file *file, struct vm_area_struct *vma)
{
struct ymf_state *state = (struct ymf_state *)file->private_data;
struct ymf_dmabuf *dmabuf = &state->dmabuf;
int ret;
unsigned long size;
if (vma->vm_flags & VM_WRITE) {
if ((ret = prog_dmabuf(state, 0)) != 0)
return ret;
} else if (vma->vm_flags & VM_READ) {
if ((ret = prog_dmabuf(state, 1)) != 0)
return ret;
} else
return -EINVAL;
if (vma->vm_pgoff != 0)
return -EINVAL;
size = vma->vm_end - vma->vm_start;
if (size > (PAGE_SIZE << dmabuf->buforder))
return -EINVAL;
if (remap_page_range(vma->vm_start, virt_to_phys(dmabuf->rawbuf),
size, vma->vm_page_prot))
return -EAGAIN;
dmabuf->mapped = 1;
return 0;
}
static int ymf_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct ymf_state *state = (struct ymf_state *)file->private_data;
struct ymf_dmabuf *dmabuf = &state->dmabuf;
unsigned long flags;
audio_buf_info abinfo;
count_info cinfo;
int val;
switch (cmd) {
case OSS_GETVERSION:
return put_user(SOUND_VERSION, (int *)arg);
case SNDCTL_DSP_RESET:
/* FIXME: spin_lock ? */
if (file->f_mode & FMODE_WRITE) {
ymf_wait_dac(state);
dmabuf->ready = 0;
dmabuf->swptr = dmabuf->hwptr = 0;
dmabuf->count = dmabuf->total_bytes = 0;
}
#if HAVE_RECORD
if (file->f_mode & FMODE_READ) {
stop_adc(state);
synchronize_irq();
dmabuf->ready = 0;
dmabuf->swptr = dmabuf->hwptr = 0;
dmabuf->count = dmabuf->total_bytes = 0;
}
#endif
return 0;
case SNDCTL_DSP_SYNC:
if (file->f_mode & FMODE_WRITE) {
if (file->f_flags & O_NONBLOCK) {
spin_lock_irqsave(&state->unit->reg_lock, flags);
if (dmabuf->count != 0 && !state->ypcm.running) {
ymf_start_dac(state);
}
spin_unlock_irqrestore(&state->unit->reg_lock, flags);
} else {
ymf_wait_dac(state);
}
}
return 0;
case SNDCTL_DSP_SPEED: /* set smaple rate */
if (get_user(val, (int *)arg))
return -EFAULT;
/* P3 */ /* printk("ymfpci: ioctl SNDCTL_DSP_SPEED %d\n", val); */
if (val >= 8000 && val <= 48000) {
spin_lock_irqsave(&state->unit->reg_lock, flags);
if (file->f_mode & FMODE_WRITE) {
ymf_wait_dac(state);
}
#if HAVE_RECORD
if (file->f_mode & FMODE_READ) {
stop_adc(state);
}
#endif
dmabuf->ready = 0;
state->format.rate = val;
ymf_pcm_update_shift(&state->format);
spin_unlock_irqrestore(&state->unit->reg_lock, flags);
}
return put_user(state->format.rate, (int *)arg);
/*
* OSS manual does not mention SNDCTL_DSP_STEREO at all.
* All channels are mono and if you want stereo, you
* play into two channels with SNDCTL_DSP_CHANNELS.
* However, mpg123 uses it. I wonder, why Michael Hipp uses it.
*/
case SNDCTL_DSP_STEREO: /* set stereo or mono channel */
if (get_user(val, (int *)arg))
return -EFAULT;
/* P3 */ /* printk("ymfpci: ioctl SNDCTL_DSP_STEREO %d\n", val); */
if (file->f_mode & FMODE_WRITE) {
ymf_wait_dac(state);
spin_lock_irqsave(&state->unit->reg_lock, flags);
dmabuf->ready = 0;
state->format.voices = val ? 2 : 1;
ymf_pcm_update_shift(&state->format);
spin_unlock_irqrestore(&state->unit->reg_lock, flags);
}
#if HAVE_RECORD
if (file->f_mode & FMODE_READ) {
/* stop_adc(state); */
dmabuf->ready = 0;
if(val)
dmabuf->fmt |= CS_FMT_STEREO;
else
dmabuf->fmt &= ~CS_FMT_STEREO;
}
#endif
return 0;
case SNDCTL_DSP_GETBLKSIZE:
/* P3 */ /* printk("ymfpci: ioctl SNDCTL_DSP_GETBLKSIZE\n"); */
if (file->f_mode & FMODE_WRITE) {
if ((val = prog_dmabuf(state, 0)))
return val;
return put_user(dmabuf->fragsize, (int *)arg);
}
if (file->f_mode & FMODE_READ) {
if ((val = prog_dmabuf(state, 1)))
return val;
return put_user(dmabuf->fragsize, (int *)arg);
}
return -EINVAL;
case SNDCTL_DSP_GETFMTS: /* Returns a mask of supported sample format*/
/* P3 */ /* printk("ymfpci: ioctl SNDCTL_DSP_GETFMTS\n"); */
return put_user(AFMT_S16_LE|AFMT_U8, (int *)arg);
case SNDCTL_DSP_SETFMT: /* Select sample format */
if (get_user(val, (int *)arg))
return -EFAULT;
/* P3 */ /* printk("ymfpci: ioctl SNDCTL_DSP_SETFMT 0x%x\n", val); */
if (val == AFMT_S16_LE || val == AFMT_U8) {
spin_lock_irqsave(&state->unit->reg_lock, flags);
if (file->f_mode & FMODE_WRITE) {
ymf_wait_dac(state);
}
#if HAVE_RECORD
if (file->f_mode & FMODE_READ) {
stop_adc(state);
}
#endif
dmabuf->ready = 0;
state->format.format = val;
ymf_pcm_update_shift(&state->format);
spin_unlock_irqrestore(&state->unit->reg_lock, flags);
}
return put_user(state->format.format, (int *)arg);
case SNDCTL_DSP_CHANNELS:
if (get_user(val, (int *)arg))
return -EFAULT;
/* P3 */ /* printk("ymfpci: ioctl SNDCTL_DSP_CHANNELS 0x%x\n", val); */
if (val != 0) {
spin_lock_irqsave(&state->unit->reg_lock, flags);
if (file->f_mode & FMODE_WRITE) {
ymf_wait_dac(state);
if (val == 1 || val == 2) {
dmabuf->ready = 0;
state->format.voices = val;
ymf_pcm_update_shift(&state->format);
}
}
#if HAVE_RECORD
if (file->f_mode & FMODE_READ) {
stop_adc(state);
dmabuf->ready = 0;
}
#endif
spin_unlock_irqrestore(&state->unit->reg_lock, flags);
}
return put_user(state->format.voices, (int *)arg);
case SNDCTL_DSP_POST:
/*
* Quoting OSS PG:
* The ioctl SNDCTL_DSP_POST is a lightweight version of
* SNDCTL_DSP_SYNC. It just tells to the driver that there
* is likely to be a pause in the output. This makes it
* possible for the device to handle the pause more
* intelligently. This ioctl doesn't block the application.
*
* The paragraph above is a clumsy way to say "flush ioctl".
* This ioctl is used by mpg123.
*/
/* P3 */ /* printk("ymfpci: ioctl SNDCTL_DSP_POST\n"); */
spin_lock_irqsave(&state->unit->reg_lock, flags);
if (dmabuf->count != 0 && !state->ypcm.running) {
ymf_start_dac(state);
}
spin_unlock_irqrestore(&state->unit->reg_lock, flags);
return 0;
case SNDCTL_DSP_SUBDIVIDE:
if (dmabuf->subdivision)
return -EINVAL;
if (get_user(val, (int *)arg))
return -EFAULT;
if (val != 1 && val != 2)
return -EINVAL;
dmabuf->subdivision = val;
return 0;
case SNDCTL_DSP_SETFRAGMENT:
if (get_user(val, (int *)arg))
return -EFAULT;
/* P3: these frags are for Doom. Amasingly, it sets [2,2**11]. */
/* P3 */ // printk("ymfpci: ioctl SNDCTL_DSP_SETFRAGMENT 0x%x\n", val);
dmabuf->ossfragshift = val & 0xffff;
dmabuf->ossmaxfrags = (val >> 16) & 0xffff;
switch (dmabuf->ossmaxfrags) {
case 1:
dmabuf->ossfragshift = 12;
return 0;
default:
/* Fragments must be 2K long */
dmabuf->ossfragshift = 11;
dmabuf->ossmaxfrags = 2;
}
return 0;
case SNDCTL_DSP_GETOSPACE:
/* P3 */ /* printk("ymfpci: ioctl SNDCTL_DSP_GETOSPACE\n"); */
if (!(file->f_mode & FMODE_WRITE))
return -EINVAL;
if (!dmabuf->ready && (val = prog_dmabuf(state, 0)) != 0)
return val;
spin_lock_irqsave(&state->unit->reg_lock, flags);
/* cs_update_ptr(state); */ /* XXX Always up to date? */
abinfo.fragsize = dmabuf->fragsize;
abinfo.bytes = dmabuf->dmasize - dmabuf->count;
abinfo.fragstotal = dmabuf->numfrag;
abinfo.fragments = abinfo.bytes >> dmabuf->fragshift;
spin_unlock_irqrestore(&state->unit->reg_lock, flags);
return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
#if HAVE_RECORD
case SNDCTL_DSP_GETISPACE:
if (!(file->f_mode & FMODE_READ))
return -EINVAL;
if (!dmabuf->ready && (val = prog_dmabuf(state, 1)) != 0)
return val;
spin_lock_irqsave(&state->card->lock, flags);
cs_update_ptr(state);
abinfo.fragsize = dmabuf->fragsize;
abinfo.bytes = dmabuf->count;
abinfo.fragstotal = dmabuf->numfrag;
abinfo.fragments = abinfo.bytes >> dmabuf->fragshift;
spin_unlock_irqrestore(&state->card->lock, flags);
return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
#endif
case SNDCTL_DSP_NONBLOCK:
/* P3 */ /* printk("ymfpci: ioctl SNDCTL_DSP_NONBLOCK\n"); */
file->f_flags |= O_NONBLOCK;
return 0;
case SNDCTL_DSP_GETCAPS:
/* P3 */ /* printk("ymfpci: ioctl SNDCTL_DSP_GETCAPS\n"); */
/* return put_user(DSP_CAP_REALTIME|DSP_CAP_TRIGGER|DSP_CAP_MMAP,
(int *)arg); */
return put_user(0, (int *)arg);
#if 0 /* old */
case SNDCTL_DSP_GETTRIGGER:
val = 0;
if (file->f_mode & FMODE_READ && dmabuf->enable)
val |= PCM_ENABLE_INPUT;
if (file->f_mode & FMODE_WRITE && dmabuf->enable)
val |= PCM_ENABLE_OUTPUT;
return put_user(val, (int *)arg);
case SNDCTL_DSP_SETTRIGGER:
if (get_user(val, (int *)arg))
return -EFAULT;
if (file->f_mode & FMODE_READ) {
if (val & PCM_ENABLE_INPUT) {
if (!dmabuf->ready && (ret = prog_dmabuf(state, 1)))
return ret;
start_adc(state);
} else
stop_adc(state);
}
if (file->f_mode & FMODE_WRITE) {
if (val & PCM_ENABLE_OUTPUT) {
if (!dmabuf->ready && (ret = prog_dmabuf(state, 0)))
return ret;
start_dac(state); // sure?
} else
stop_dac(state);
}
return 0;
#endif
#if HAVE_RECORD
case SNDCTL_DSP_GETIPTR:
if (!(file->f_mode & FMODE_READ))
return -EINVAL;
spin_lock_irqsave(&state->unit->reg_lock, flags);
cs_update_ptr(state);
cinfo.bytes = dmabuf->total_bytes;
cinfo.blocks = dmabuf->count >> dmabuf->fragshift;
cinfo.ptr = dmabuf->hwptr;
if (dmabuf->mapped)
dmabuf->count &= dmabuf->fragsize-1;
spin_unlock_irqrestore(&state->unit->reg_lock, flags);
return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
#endif
case SNDCTL_DSP_GETOPTR:
/* P3 */ /* printk("ymfpci: ioctl SNDCTL_DSP_GETOPTR\n"); */
if (!(file->f_mode & FMODE_WRITE))
return -EINVAL;
spin_lock_irqsave(&state->unit->reg_lock, flags);
/* cs_update_ptr(state); */ /* Always up to date */
cinfo.bytes = dmabuf->total_bytes;
cinfo.blocks = dmabuf->count >> dmabuf->fragshift;
cinfo.ptr = dmabuf->hwptr;
if (dmabuf->mapped)
dmabuf->count &= dmabuf->fragsize-1;
spin_unlock_irqrestore(&state->unit->reg_lock, flags);
return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
case SNDCTL_DSP_SETDUPLEX: /* XXX TODO */
/* P3 */ /* printk("ymfpci: ioctl SNDCTL_DSP_SETDUPLEX\n"); */
return -EINVAL;
#if 0 /* old */
case SNDCTL_DSP_GETODELAY:
if (!(file->f_mode & FMODE_WRITE))
return -EINVAL;
spin_lock_irqsave(&state->unit->reg_lock, flags);
cs_update_ptr(state);
val = dmabuf->count;
spin_unlock_irqrestore(&state->card->lock, flags);
return put_user(val, (int *)arg);
#endif
case SOUND_PCM_READ_RATE:
return put_user(state->format.rate, (int *)arg);
case SOUND_PCM_READ_CHANNELS:
return put_user(state->format.voices, (int *)arg);
case SOUND_PCM_READ_BITS:
return put_user(AFMT_S16_LE, (int *)arg);
case SNDCTL_DSP_MAPINBUF:
case SNDCTL_DSP_MAPOUTBUF:
case SNDCTL_DSP_SETSYNCRO:
case SOUND_PCM_WRITE_FILTER:
case SOUND_PCM_READ_FILTER:
return -ENOTTY;
default:
/* P3 */ printk("ymfpci: ioctl cmd 0x%x\n", cmd);
/*
* Some programs mix up audio devices and ioctls
* or perhaps they expect "universal" ioctls,
* for instance we get SNDCTL_TMR_CONTINUE here.
* XXX Is there sound_generic_ioctl() around?
*/
}
return -ENOTTY;
}
static int ymf_open(struct inode *inode, struct file *file)
{
ymfpci_t *unit;
int minor, instance;
struct ymf_state *state;
int nvirt;
int err;
/*
* This is how we do it currently: only one channel is used
* in every board, so that we could use several boards in one machine.
* We waste 63 out of 64 playback slots, but so what.
* OSS model is constructed for devices with single playback channel.
*/
minor = MINOR(inode->i_rdev);
if ((minor & 0x0F) == 3) { /* /dev/dspN */
;
} else {
return -ENXIO;
}
instance = (minor >> 4) & 0x0F;
nvirt = 0; /* Such is the partitioning of minor */
/* XXX Semaphore here! */
for (unit = ymf_devs; unit != NULL; unit = unit->next) {
if (unit->inst == instance) break;
}
if (unit == NULL) return -ENODEV;
if (unit->states[nvirt] != NULL) {
/* P3 */ printk("ymfpci%d: busy\n", unit->inst);
return -EBUSY;
}
if ((err = ymf_state_alloc(unit, nvirt, instance)) != 0) {
return err;
}
state = unit->states[nvirt];
file->private_data = state;
/*
* XXX This ymf_playback_prepare is totally unneeded here.
* The question is if we want to allow write to fail if
* prog_dmabuf fails... Say, no memory in DMA zone?
*/
if ((err = ymf_playback_prepare(unit, state)) != 0) {
/* XXX This recovery is ugly as hell. */
ymf_pcm_free_substream(&state->ypcm);
unit->states[state->virt] = NULL;
kfree(state);
return err;
}
#if 0 /* test if interrupts work */
ymfpci_writew(codec, YDSXGR_TIMERCOUNT, 0xfffe); /* ~ 680ms */
ymfpci_writeb(codec, YDSXGR_TIMERCTRL,
(YDSXGR_TIMERCTRL_TEN|YDSXGR_TIMERCTRL_TIEN));
#endif
MOD_INC_USE_COUNT;
return 0;
}
static int ymf_release(struct inode *inode, struct file *file)
{
struct ymf_state *state = (struct ymf_state *)file->private_data;
ymfpci_t *codec = state->unit;
#if 0 /* test if interrupts work */
ymfpci_writeb(codec, YDSXGR_TIMERCTRL, 0);
#endif
/* XXX Use the semaphore to unrace us with opens */
if (state != codec->states[state->virt]) {
printk(KERN_ERR "ymfpci%d.%d: state mismatch\n",
state->unit->inst, state->virt);
return -EIO;
}
/*
* XXX Solve the case of O_NONBLOCK close - don't deallocate here.
* Deallocate when unloading the driver and we can wait.
*/
ymf_wait_dac(state);
dealloc_dmabuf(state);
ymf_pcm_free_substream(&state->ypcm);
codec->states[state->virt] = NULL;
kfree(state);
MOD_DEC_USE_COUNT;
return 0;
}
/*
* Mixer operations are based on cs46xx.
*/
static int ymf_open_mixdev(struct inode *inode, struct file *file)
{
int i;
int minor = MINOR(inode->i_rdev);
ymfpci_t *codec;
for (codec = ymf_devs; codec != NULL; codec = codec->next) {
for (i = 0; i < NR_AC97; i++) {
if (codec->ac97_codec[i] != NULL &&
codec->ac97_codec[i]->dev_mixer == minor)
goto match;
}
}
if (!codec)
return -ENODEV;
match:
file->private_data = codec->ac97_codec[i];
MOD_INC_USE_COUNT;
return 0;
}
static int ymf_ioctl_mixdev(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct ac97_codec *codec = (struct ac97_codec *)file->private_data;
return codec->mixer_ioctl(codec, cmd, arg);
}
static int ymf_release_mixdev(struct inode *inode, struct file *file)
{
MOD_DEC_USE_COUNT;
return 0;
}
static /*const*/ struct file_operations ymf_fops = {
llseek: ymf_llseek,
read: ymf_read,
write: ymf_write,
poll: ymf_poll,
ioctl: ymf_ioctl,
mmap: ymf_mmap,
open: ymf_open,
release: ymf_release,
};
static /*const*/ struct file_operations ymf_mixer_fops = {
llseek: ymf_llseek,
ioctl: ymf_ioctl_mixdev,
open: ymf_open_mixdev,
release: ymf_release_mixdev,
};
/*
* initialization routines
*/
static void ymfpci_aclink_reset(struct pci_dev * pci)
{
u8 cmd;
pci_read_config_byte(pci, PCIR_DSXGCTRL, &cmd);
if (cmd & 0x03) {
pci_write_config_byte(pci, PCIR_DSXGCTRL, cmd & 0xfc);
pci_write_config_byte(pci, PCIR_DSXGCTRL, cmd | 0x03);
pci_write_config_byte(pci, PCIR_DSXGCTRL, cmd & 0xfc);
}
}
static void ymfpci_enable_dsp(ymfpci_t *codec)
{
ymfpci_writel(codec, YDSXGR_CONFIG, 0x00000001);
}
static void ymfpci_disable_dsp(ymfpci_t *codec)
{
u32 val;
int timeout = 1000;
val = ymfpci_readl(codec, YDSXGR_CONFIG);
if (val)
ymfpci_writel(codec, YDSXGR_CONFIG, 0x00000000);
while (timeout-- > 0) {
val = ymfpci_readl(codec, YDSXGR_STATUS);
if ((val & 0x00000002) == 0)
break;
}
}
#include "ymfpci_image.h"
static void ymfpci_download_image(ymfpci_t *codec)
{
int i, ver_1e;
u16 ctrl;
ymfpci_writel(codec, YDSXGR_NATIVEDACOUTVOL, 0x00000000);
ymfpci_disable_dsp(codec);
ymfpci_writel(codec, YDSXGR_MODE, 0x00010000);
ymfpci_writel(codec, YDSXGR_MODE, 0x00000000);
ymfpci_writel(codec, YDSXGR_MAPOFREC, 0x00000000);
ymfpci_writel(codec, YDSXGR_MAPOFEFFECT, 0x00000000);
ymfpci_writel(codec, YDSXGR_PLAYCTRLBASE, 0x00000000);
ymfpci_writel(codec, YDSXGR_RECCTRLBASE, 0x00000000);
ymfpci_writel(codec, YDSXGR_EFFCTRLBASE, 0x00000000);
ctrl = ymfpci_readw(codec, YDSXGR_GLOBALCTRL);
ymfpci_writew(codec, YDSXGR_GLOBALCTRL, ctrl & ~0x0007);
/* setup DSP instruction code */
for (i = 0; i < YDSXG_DSPLENGTH; i++)
ymfpci_writel(codec, YDSXGR_DSPINSTRAM + i, DspInst[i >> 2]);
switch (codec->device_id) {
case PCI_DEVICE_ID_YAMAHA_724F:
case PCI_DEVICE_ID_YAMAHA_740C:
case PCI_DEVICE_ID_YAMAHA_744:
case PCI_DEVICE_ID_YAMAHA_754:
ver_1e = 1;
break;
default:
ver_1e = 0;
}
if (ver_1e) {
/* setup control instruction code */
for (i = 0; i < YDSXG_CTRLLENGTH; i++)
ymfpci_writel(codec, YDSXGR_CTRLINSTRAM + i, CntrlInst1E[i >> 2]);
} else {
for (i = 0; i < YDSXG_CTRLLENGTH; i++)
ymfpci_writel(codec, YDSXGR_CTRLINSTRAM + i, CntrlInst[i >> 2]);
}
ymfpci_enable_dsp(codec);
}
static int ymfpci_memalloc(ymfpci_t *codec)
{
long size, playback_ctrl_size;
int voice, bank;
u8 *ptr;
playback_ctrl_size = 4 + 4 * YDSXG_PLAYBACK_VOICES;
codec->bank_size_playback = ymfpci_readl(codec, YDSXGR_PLAYCTRLSIZE) << 2;
codec->bank_size_capture = ymfpci_readl(codec, YDSXGR_RECCTRLSIZE) << 2;
codec->bank_size_effect = ymfpci_readl(codec, YDSXGR_EFFCTRLSIZE) << 2;
codec->work_size = YDSXG_DEFAULT_WORK_SIZE;
size = ((playback_ctrl_size + 0x00ff) & ~0x00ff) +
((codec->bank_size_playback * 2 * YDSXG_PLAYBACK_VOICES + 0xff) & ~0xff) +
((codec->bank_size_capture * 2 * YDSXG_CAPTURE_VOICES + 0xff) & ~0xff) +
((codec->bank_size_effect * 2 * YDSXG_EFFECT_VOICES + 0xff) & ~0xff) +
codec->work_size;
ptr = (u8 *)kmalloc(size + 0x00ff, GFP_KERNEL);
if (ptr == NULL)
return -ENOMEM;
codec->work_ptr = ptr;
ptr += 0x00ff;
(long)ptr &= ~0x00ff;
codec->bank_base_playback = ptr;
codec->ctrl_playback = (u32 *)ptr;
codec->ctrl_playback[0] = YDSXG_PLAYBACK_VOICES;
ptr += (playback_ctrl_size + 0x00ff) & ~0x00ff;
for (voice = 0; voice < YDSXG_PLAYBACK_VOICES; voice++) {
for (bank = 0; bank < 2; bank++) {
codec->bank_playback[voice][bank] = (ymfpci_playback_bank_t *)ptr;
ptr += codec->bank_size_playback;
}
codec->voices[voice].number = voice;
codec->voices[voice].bank = codec->bank_playback[voice][0];
}
ptr += (codec->bank_size_playback + 0x00ff) & ~0x00ff;
codec->bank_base_capture = ptr;
for (voice = 0; voice < YDSXG_CAPTURE_VOICES; voice++)
for (bank = 0; bank < 2; bank++) {
codec->bank_capture[voice][bank] = (ymfpci_capture_bank_t *)ptr;
ptr += codec->bank_size_capture;
}
ptr += (codec->bank_size_capture + 0x00ff) & ~0x00ff;
codec->bank_base_effect = ptr;
for (voice = 0; voice < YDSXG_EFFECT_VOICES; voice++)
for (bank = 0; bank < 2; bank++) {
codec->bank_effect[voice][bank] = (ymfpci_effect_bank_t *)ptr;
ptr += codec->bank_size_effect;
}
ptr += (codec->bank_size_effect + 0x00ff) & ~0x00ff;
codec->work_base = ptr;
ymfpci_writel(codec, YDSXGR_PLAYCTRLBASE, virt_to_bus(codec->bank_base_playback));
ymfpci_writel(codec, YDSXGR_RECCTRLBASE, virt_to_bus(codec->bank_base_capture));
ymfpci_writel(codec, YDSXGR_EFFCTRLBASE, virt_to_bus(codec->bank_base_effect));
ymfpci_writel(codec, YDSXGR_WORKBASE, virt_to_bus(codec->work_base));
ymfpci_writel(codec, YDSXGR_WORKSIZE, codec->work_size >> 2);
/* S/PDIF output initialization */
ymfpci_writew(codec, YDSXGR_SPDIFOUTCTRL, 0);
ymfpci_writew(codec, YDSXGR_SPDIFOUTSTATUS,
SND_PCM_AES0_CON_EMPHASIS_NONE |
(SND_PCM_AES1_CON_ORIGINAL << 8) |
(SND_PCM_AES1_CON_PCM_CODER << 8));
/* S/PDIF input initialization */
ymfpci_writew(codec, YDSXGR_SPDIFINCTRL, 0);
/* move this volume setup to mixer */
ymfpci_writel(codec, YDSXGR_NATIVEDACOUTVOL, 0x3fff3fff);
ymfpci_writel(codec, YDSXGR_BUF441OUTVOL, 0x3fff3fff);
ymfpci_writel(codec, YDSXGR_NATIVEADCINVOL, 0x3fff3fff);
ymfpci_writel(codec, YDSXGR_NATIVEDACINVOL, 0x3fff3fff);
return 0;
}
static int ymf_ac97_init(ymfpci_t *card, int num_ac97)
{
struct ac97_codec *codec;
u16 eid;
if ((codec = kmalloc(sizeof(struct ac97_codec), GFP_KERNEL)) == NULL)
return -ENOMEM;
memset(codec, 0, sizeof(struct ac97_codec));
/* initialize some basic codec information, other fields will be filled
in ac97_probe_codec */
codec->private_data = card;
codec->id = num_ac97;
codec->codec_read = ymfpci_codec_read;
codec->codec_write = ymfpci_codec_write;
if (ac97_probe_codec(codec) == 0) {
/* Alan does not have this printout. P3 */
printk("ymfpci: ac97_probe_codec failed\n");
return -ENODEV;
}
eid = ymfpci_codec_read(codec, AC97_EXTENDED_ID);
if (eid==0xFFFFFF)
{
printk(KERN_WARNING "ymfpci: no codec attached ?\n");
kfree(codec);
return -ENODEV;
}
card->ac97_features = eid;
if ((codec->dev_mixer = register_sound_mixer(&ymf_mixer_fops, -1)) < 0) {
printk(KERN_ERR "ymfpci: couldn't register mixer!\n");
kfree(codec);
return -ENODEV;
}
card->ac97_codec[num_ac97] = codec;
return 0;
}
static int /* __init */
ymf_install(struct pci_dev *pcidev, int instance, int devx)
{
ymfpci_t *codec;
int err;
if ((codec = kmalloc(sizeof(ymfpci_t), GFP_KERNEL)) == NULL) {
printk(KERN_ERR "ymfpci: no core\n");
return -ENOMEM;
}
memset(codec, 0, sizeof(*codec));
spin_lock_init(&codec->reg_lock);
spin_lock_init(&codec->voice_lock);
codec->pci = pcidev;
codec->inst = instance;
codec->irq = pcidev->irq;
codec->device_id = pcidev->device;
pci_read_config_byte(pcidev, PCI_REVISION_ID, (u8 *)&codec->rev);
codec->reg_area_phys = pci_resource_start(pcidev, 0);
codec->reg_area_virt = (unsigned long)ioremap(codec->reg_area_phys, 0x8000);
pci_set_master(pcidev);
/* XXX KERN_INFO */
printk("ymfpci%d: %s at 0x%lx IRQ %d\n", instance,
ymf_devv[devx].name, codec->reg_area_phys, codec->irq);
ymfpci_aclink_reset(pcidev);
if (ymfpci_codec_ready(codec, 0, 1) < 0) {
ymfpci_free(codec);
return -ENODEV;
}
ymfpci_download_image(codec);
udelay(100); /* seems we need some delay after downloading image.. */
if (ymfpci_memalloc(codec) < 0) {
ymfpci_free(codec);
return -ENODEV;
}
/* ymfpci_proc_init(card, codec); */
if (request_irq(codec->irq, ymf_interrupt, SA_SHIRQ, "ymfpci", codec) != 0) {
printk(KERN_ERR "ymfpci%d: unable to request IRQ %d\n",
codec->inst, codec->irq);
ymfpci_free(codec);
return -ENODEV;
}
/* register /dev/dsp */
if ((codec->dev_audio = register_sound_dsp(&ymf_fops, -1)) < 0) {
printk(KERN_ERR "ymfpci%d: unable to register dsp\n", codec->inst);
free_irq(codec->irq, codec);
ymfpci_free(codec);
return -ENODEV;
}
/*
* Poke just the primary for the moment.
*/
if ((err = ymf_ac97_init(codec, 0)) != 0) {
unregister_sound_dsp(codec->dev_audio);
free_irq(codec->irq, codec);
ymfpci_free(codec);
return err;
}
codec->next = ymf_devs;
ymf_devs = codec;
return 0;
}
static void
ymfpci_free(ymfpci_t *codec)
{
u16 ctrl;
/* ymfpci_proc_done(codec); */
unregister_sound_dsp(codec->dev_audio);
ymfpci_writel(codec, YDSXGR_NATIVEDACOUTVOL, 0);
ymfpci_writel(codec, YDSXGR_BUF441OUTVOL, 0);
ymfpci_writel(codec, YDSXGR_STATUS, ~0);
ymfpci_disable_dsp(codec);
ymfpci_writel(codec, YDSXGR_PLAYCTRLBASE, 0);
ymfpci_writel(codec, YDSXGR_RECCTRLBASE, 0);
ymfpci_writel(codec, YDSXGR_EFFCTRLBASE, 0);
ymfpci_writel(codec, YDSXGR_WORKBASE, 0);
ymfpci_writel(codec, YDSXGR_WORKSIZE, 0);
ctrl = ymfpci_readw(codec, YDSXGR_GLOBALCTRL);
ymfpci_writew(codec, YDSXGR_GLOBALCTRL, ctrl & ~0x0007);
if (codec->reg_area_virt)
iounmap((void *)codec->reg_area_virt);
if (codec->work_ptr)
kfree(codec->work_ptr);
if (codec->ac97_codec[0]) {
unregister_sound_mixer(codec->ac97_codec[0]->dev_mixer);
kfree(codec->ac97_codec[0]);
}
kfree(codec);
}
MODULE_AUTHOR("Jaroslav Kysela");
MODULE_DESCRIPTION("Yamaha YMF7xx PCI Audio");
static int /* __init */
ymf_probe(void)
{
struct pci_dev *pcidev;
int foundone;
int i;
if (!pci_present())
return -ENODEV;
/*
* Print our proud ego-nursing "Hello, World!" message as in MS-DOS.
*/
/* printk(KERN_INFO "ymfpci: Yamaha YMF7xx\n"); */
/*
* Not very efficient, but Alan did it so in cs46xx.c.
*/
foundone = 0;
pcidev = NULL;
for (i = 0; i < sizeof(ymf_devv)/sizeof(ymf_devv[0]); i++) {
while ((pcidev = pci_find_device(PCI_VENDOR_ID_YAMAHA,
ymf_devv[i].id, pcidev)) != NULL) {
if (ymf_install(pcidev, foundone, i) == 0) {
foundone++;
}
}
}
return foundone;
}
static int ymf_init_module(void)
{
if (ymf_probe()==0)
printk(KERN_ERR "ymfpci: No devices found.\n");
return 0;
}
static void ymf_cleanup_module (void)
{
ymfpci_t *next;
while (ymf_devs){
next = ymf_devs->next;
free_irq(ymf_devs->irq, ymf_devs);
ymfpci_free(ymf_devs);
ymf_devs = next;
}
}
module_init(ymf_init_module);
module_exit(ymf_cleanup_module);
#ifndef __YMFPCI_H
#define __YMFPCI_H
/*
* Copyright (c) by Jaroslav Kysela <perex@suse.cz>
* Definitions for Yahama YMF724/740/744/754 chips
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/*
* Direct registers
*/
/* #define YMFREG(codec, reg) (codec->port + YDSXGR_##reg) */
#define YDSXGR_INTFLAG 0x0004
#define YDSXGR_ACTIVITY 0x0006
#define YDSXGR_GLOBALCTRL 0x0008
#define YDSXGR_ZVCTRL 0x000A
#define YDSXGR_TIMERCTRL 0x0010
#define YDSXGR_TIMERCTRL_TEN 0x0001
#define YDSXGR_TIMERCTRL_TIEN 0x0002
#define YDSXGR_TIMERCOUNT 0x0012
#define YDSXGR_SPDIFOUTCTRL 0x0018
#define YDSXGR_SPDIFOUTSTATUS 0x001C
#define YDSXGR_EEPROMCTRL 0x0020
#define YDSXGR_SPDIFINCTRL 0x0034
#define YDSXGR_SPDIFINSTATUS 0x0038
#define YDSXGR_DSPPROGRAMDL 0x0048
#define YDSXGR_DLCNTRL 0x004C
#define YDSXGR_GPIOININTFLAG 0x0050
#define YDSXGR_GPIOININTENABLE 0x0052
#define YDSXGR_GPIOINSTATUS 0x0054
#define YDSXGR_GPIOOUTCTRL 0x0056
#define YDSXGR_GPIOFUNCENABLE 0x0058
#define YDSXGR_GPIOTYPECONFIG 0x005A
#define YDSXGR_AC97CMDDATA 0x0060
#define YDSXGR_AC97CMDADR 0x0062
#define YDSXGR_PRISTATUSDATA 0x0064
#define YDSXGR_PRISTATUSADR 0x0066
#define YDSXGR_SECSTATUSDATA 0x0068
#define YDSXGR_SECSTATUSADR 0x006A
#define YDSXGR_SECCONFIG 0x0070
#define YDSXGR_LEGACYOUTVOL 0x0080
#define YDSXGR_LEGACYOUTVOLL 0x0080
#define YDSXGR_LEGACYOUTVOLR 0x0082
#define YDSXGR_NATIVEDACOUTVOL 0x0084
#define YDSXGR_NATIVEDACOUTVOLL 0x0084
#define YDSXGR_NATIVEDACOUTVOLR 0x0086
#define YDSXGR_SPDIFOUTVOL 0x0088
#define YDSXGR_SPDIFOUTVOLL 0x0088
#define YDSXGR_SPDIFOUTVOLR 0x008A
#define YDSXGR_AC3OUTVOL 0x008C
#define YDSXGR_AC3OUTVOLL 0x008C
#define YDSXGR_AC3OUTVOLR 0x008E
#define YDSXGR_PRIADCOUTVOL 0x0090
#define YDSXGR_PRIADCOUTVOLL 0x0090
#define YDSXGR_PRIADCOUTVOLR 0x0092
#define YDSXGR_LEGACYLOOPVOL 0x0094
#define YDSXGR_LEGACYLOOPVOLL 0x0094
#define YDSXGR_LEGACYLOOPVOLR 0x0096
#define YDSXGR_NATIVEDACLOOPVOL 0x0098
#define YDSXGR_NATIVEDACLOOPVOLL 0x0098
#define YDSXGR_NATIVEDACLOOPVOLR 0x009A
#define YDSXGR_SPDIFLOOPVOL 0x009C
#define YDSXGR_SPDIFLOOPVOLL 0x009E
#define YDSXGR_SPDIFLOOPVOLR 0x009E
#define YDSXGR_AC3LOOPVOL 0x00A0
#define YDSXGR_AC3LOOPVOLL 0x00A0
#define YDSXGR_AC3LOOPVOLR 0x00A2
#define YDSXGR_PRIADCLOOPVOL 0x00A4
#define YDSXGR_PRIADCLOOPVOLL 0x00A4
#define YDSXGR_PRIADCLOOPVOLR 0x00A6
#define YDSXGR_NATIVEADCINVOL 0x00A8
#define YDSXGR_NATIVEADCINVOLL 0x00A8
#define YDSXGR_NATIVEADCINVOLR 0x00AA
#define YDSXGR_NATIVEDACINVOL 0x00AC
#define YDSXGR_NATIVEDACINVOLL 0x00AC
#define YDSXGR_NATIVEDACINVOLR 0x00AE
#define YDSXGR_BUF441OUTVOL 0x00B0
#define YDSXGR_BUF441OUTVOLL 0x00B0
#define YDSXGR_BUF441OUTVOLR 0x00B2
#define YDSXGR_BUF441LOOPVOL 0x00B4
#define YDSXGR_BUF441LOOPVOLL 0x00B4
#define YDSXGR_BUF441LOOPVOLR 0x00B6
#define YDSXGR_SPDIFOUTVOL2 0x00B8
#define YDSXGR_SPDIFOUTVOL2L 0x00B8
#define YDSXGR_SPDIFOUTVOL2R 0x00BA
#define YDSXGR_SPDIFLOOPVOL2 0x00BC
#define YDSXGR_SPDIFLOOPVOL2L 0x00BC
#define YDSXGR_SPDIFLOOPVOL2R 0x00BE
#define YDSXGR_ADCSLOTSR 0x00C0
#define YDSXGR_RECSLOTSR 0x00C4
#define YDSXGR_ADCFORMAT 0x00C8
#define YDSXGR_RECFORMAT 0x00CC
#define YDSXGR_P44SLOTSR 0x00D0
#define YDSXGR_STATUS 0x0100
#define YDSXGR_CTRLSELECT 0x0104
#define YDSXGR_MODE 0x0108
#define YDSXGR_SAMPLECOUNT 0x010C
#define YDSXGR_NUMOFSAMPLES 0x0110
#define YDSXGR_CONFIG 0x0114
#define YDSXGR_PLAYCTRLSIZE 0x0140
#define YDSXGR_RECCTRLSIZE 0x0144
#define YDSXGR_EFFCTRLSIZE 0x0148
#define YDSXGR_WORKSIZE 0x014C
#define YDSXGR_MAPOFREC 0x0150
#define YDSXGR_MAPOFEFFECT 0x0154
#define YDSXGR_PLAYCTRLBASE 0x0158
#define YDSXGR_RECCTRLBASE 0x015C
#define YDSXGR_EFFCTRLBASE 0x0160
#define YDSXGR_WORKBASE 0x0164
#define YDSXGR_DSPINSTRAM 0x1000
#define YDSXGR_CTRLINSTRAM 0x4000
#define YDSXG_AC97READCMD 0x8000
#define YDSXG_AC97WRITECMD 0x0000
#define PCIR_DSXGCTRL 0x48
#define YDSXG_DSPLENGTH 0x0080
#define YDSXG_CTRLLENGTH 0x3000
#define YDSXG_DEFAULT_WORK_SIZE 0x0400
#define YDSXG_PLAYBACK_VOICES 64
#define YDSXG_CAPTURE_VOICES 2
#define YDSXG_EFFECT_VOICES 5
/* maxinum number of AC97 codecs connected, AC97 2.0 defined 4 */
#define NR_AC97 2
#define YMF_SAMPF 256 /* Samples per frame @48000 */
/*
* The slot/voice control bank (2 of these per voice)
*/
typedef struct stru_ymfpci_playback_bank {
u32 format;
u32 loop_default;
u32 base; /* 32-bit address */
u32 loop_start; /* 32-bit offset */
u32 loop_end; /* 32-bit offset */
u32 loop_frac; /* 8-bit fraction - loop_start */
u32 delta_end; /* pitch delta end */
u32 lpfK_end;
u32 eg_gain_end;
u32 left_gain_end;
u32 right_gain_end;
u32 eff1_gain_end;
u32 eff2_gain_end;
u32 eff3_gain_end;
u32 lpfQ;
u32 status; /* P3: Always 0 for some reason. */
u32 num_of_frames;
u32 loop_count;
u32 start; /* P3: J. reads this to know where chip is. */
u32 start_frac;
u32 delta;
u32 lpfK;
u32 eg_gain;
u32 left_gain;
u32 right_gain;
u32 eff1_gain;
u32 eff2_gain;
u32 eff3_gain;
u32 lpfD1;
u32 lpfD2;
} ymfpci_playback_bank_t;
typedef struct stru_ymfpci_capture_bank {
u32 base; /* 32-bit address */
u32 loop_end; /* 32-bit offset */
u32 start; /* 32-bit offset */
u32 num_of_loops; /* counter */
} ymfpci_capture_bank_t;
typedef struct stru_ymfpci_effect_bank {
u32 base; /* 32-bit address */
u32 loop_end; /* 32-bit offset */
u32 start; /* 32-bit offset */
u32 temp;
} ymfpci_effect_bank_t;
typedef struct stru_ymfpci_voice ymfpci_voice_t;
typedef struct ymf_pcm ymfpci_pcm_t;
/*
* Throughout the code Yaroslav names YMF unit pointer "codec"
* even though it does not correspond to any codec. Must be historic.
* We replace it with "unit" over time.
* AC97 parts use "codec" to denote a codec, naturally.
*/
typedef struct ymf_unit ymfpci_t;
typedef enum {
YMFPCI_PCM,
YMFPCI_SYNTH,
YMFPCI_MIDI
} ymfpci_voice_type_t;
struct stru_ymfpci_voice {
ymfpci_t *codec;
int number;
int use: 1,
pcm: 1,
synth: 1,
midi: 1;
ymfpci_playback_bank_t *bank;
void (*interrupt)(ymfpci_t *codec, ymfpci_voice_t *voice);
ymfpci_pcm_t *ypcm;
};
typedef enum {
PLAYBACK_VOICE,
CAPTURE_REC,
CAPTURE_AC97,
EFFECT_DRY_LEFT,
EFFECT_DRY_RIGHT,
EFFECT_EFF1,
EFFECT_EFF2,
EFFECT_EFF3
} ymfpci_pcm_type_t;
struct ymf_pcm {
ymfpci_t *codec;
ymfpci_pcm_type_t type;
struct ymf_state *state;
ymfpci_voice_t *voices[2]; /* playback only */
int running; // +
int spdif;
};
struct ymf_unit {
unsigned int device_id; /* PCI device ID */
unsigned int rev; /* PCI revision */
unsigned long reg_area_phys;
unsigned long reg_area_virt;
void *work_ptr; // +
unsigned int bank_size_playback;
unsigned int bank_size_capture;
unsigned int bank_size_effect;
unsigned int work_size;
void *bank_base_playback; // +
void *bank_base_capture; // +
void *bank_base_effect; // +
void *work_base; // +
u32 *ctrl_playback;
ymfpci_playback_bank_t *bank_playback[YDSXG_PLAYBACK_VOICES][2];
ymfpci_capture_bank_t *bank_capture[YDSXG_CAPTURE_VOICES][2];
ymfpci_effect_bank_t *bank_effect[YDSXG_EFFECT_VOICES][2];
int start_count;
u32 active_bank;
ymfpci_voice_t voices[64];
struct ac97_codec *ac97_codec[NR_AC97];
u16 ac97_features;
struct pci_dev *pci;
int irq;
int inst; /* Unit number (instance) */
spinlock_t reg_lock;
spinlock_t voice_lock;
/* soundcore stuff */
int dev_audio;
ymfpci_t *next; // *
struct ymf_state *states[1]; // *
/* ypcm may be the same thing as state, but not for record, effects. */
};
/*
* "Software" or virtual channel, an instance of opened /dev/dsp.
*/
struct ymf_dmabuf {
/* OSS buffer management stuff */
void *rawbuf;
unsigned buforder;
unsigned numfrag;
unsigned fragshift;
/* our buffer acts like a circular ring */
unsigned hwptr; /* where dma last started */
unsigned swptr; /* where driver last clear/filled */
int count; /* fill count */
unsigned total_bytes; /* total bytes dmaed by hardware */
unsigned error; /* number of over/underruns */
wait_queue_head_t wait; /* put process on wait queue when no more space in buffer */
/* redundant, but makes calculations easier */
unsigned fragsize;
unsigned dmasize; /* Total rawbuf[] size */
unsigned fragsamples;
/* OSS stuff */
unsigned mapped:1;
unsigned ready:1;
unsigned ossfragshift;
int ossmaxfrags;
unsigned subdivision;
};
struct ymf_pcm_format {
int format; /* OSS format */
int rate; /* rate in Hz */
int voices; /* number of voices */
int shift; /* redundant, computed from the above */
};
struct ymf_state {
struct ymf_unit *unit; /* backpointer */
/* single open lock mechanism, only used for recording */
struct semaphore open_sem;
wait_queue_head_t open_wait;
/* virtual channel number */
int virt; // * unused a.t.m.
struct ymf_pcm ypcm; // *
struct ymf_dmabuf dmabuf; // *
struct ymf_pcm_format format; // *
};
#endif /* __YMFPCI_H */
#ifndef _HWMCODE_
#define _HWMCODE_
static unsigned long int DspInst[] = {
0x00000081, 0x000001a4, 0x0000000a, 0x0000002f,
0x00080253, 0x01800317, 0x0000407b, 0x0000843f,
0x0001483c, 0x0001943c, 0x0005d83c, 0x00001c3c,
0x0000c07b, 0x00050c3f, 0x0121503c, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000
};
static unsigned long int CntrlInst[] = {
0x000007, 0x240007, 0x0C0007, 0x1C0007,
0x060007, 0x700002, 0x000020, 0x030040,
0x007104, 0x004286, 0x030040, 0x000F0D,
0x000810, 0x20043A, 0x000282, 0x00020D,
0x000810, 0x20043A, 0x001282, 0x200E82,
0x001A82, 0x032D0D, 0x000810, 0x10043A,
0x02D38D, 0x000810, 0x18043A, 0x00010D,
0x020015, 0x0000FD, 0x000020, 0x038860,
0x039060, 0x038060, 0x038040, 0x038040,
0x038040, 0x018040, 0x000A7D, 0x038040,
0x038040, 0x018040, 0x200402, 0x000882,
0x08001A, 0x000904, 0x015986, 0x000007,
0x260007, 0x000007, 0x000007, 0x018A06,
0x000007, 0x030C8D, 0x000810, 0x18043A,
0x260007, 0x00087D, 0x018042, 0x00160A,
0x04A206, 0x000007, 0x00218D, 0x000810,
0x08043A, 0x21C206, 0x000007, 0x0007FD,
0x018042, 0x08000A, 0x000904, 0x029386,
0x000195, 0x090D04, 0x000007, 0x000820,
0x0000F5, 0x000B7D, 0x01F060, 0x0000FD,
0x032206, 0x018040, 0x000A7D, 0x038042,
0x13804A, 0x18000A, 0x001820, 0x059060,
0x058860, 0x018040, 0x0000FD, 0x018042,
0x70000A, 0x000115, 0x071144, 0x032386,
0x030000, 0x007020, 0x034A06, 0x018040,
0x00348D, 0x000810, 0x08043A, 0x21EA06,
0x000007, 0x02D38D, 0x000810, 0x18043A,
0x018206, 0x000007, 0x240007, 0x000F8D,
0x000810, 0x00163A, 0x002402, 0x005C02,
0x0028FD, 0x000020, 0x018040, 0x08000D,
0x000815, 0x510984, 0x000007, 0x00004D,
0x000E5D, 0x000E02, 0x00418D, 0x000810,
0x08043A, 0x2C8A06, 0x000007, 0x00008D,
0x000924, 0x000F02, 0x00458D, 0x000810,
0x08043A, 0x2C8A06, 0x000007, 0x00387D,
0x018042, 0x08000A, 0x001015, 0x010984,
0x018386, 0x000007, 0x01AA06, 0x000007,
0x0008FD, 0x018042, 0x18000A, 0x001904,
0x218086, 0x280007, 0x001810, 0x28043A,
0x280C02, 0x00000D, 0x000810, 0x28143A,
0x08808D, 0x000820, 0x0002FD, 0x018040,
0x200007, 0x00020D, 0x189904, 0x000007,
0x00402D, 0x0000BD, 0x0002FD, 0x018042,
0x08000A, 0x000904, 0x055A86, 0x000007,
0x000100, 0x000A20, 0x00047D, 0x018040,
0x018042, 0x20000A, 0x003015, 0x012144,
0x034986, 0x000007, 0x002104, 0x034986,
0x000007, 0x000F8D, 0x000810, 0x280C3A,
0x023944, 0x06C986, 0x000007, 0x001810,
0x28043A, 0x08810D, 0x000820, 0x0002FD,
0x018040, 0x200007, 0x002810, 0x78003A,
0x00688D, 0x000810, 0x08043A, 0x288A06,
0x000007, 0x00400D, 0x001015, 0x189904,
0x292904, 0x393904, 0x000007, 0x060206,
0x000007, 0x0004F5, 0x00007D, 0x000020,
0x00008D, 0x010860, 0x018040, 0x00047D,
0x038042, 0x21804A, 0x18000A, 0x021944,
0x215886, 0x000007, 0x004075, 0x71F104,
0x000007, 0x010042, 0x28000A, 0x002904,
0x212086, 0x000007, 0x003C0D, 0x30A904,
0x000007, 0x00077D, 0x018042, 0x08000A,
0x000904, 0x07DA86, 0x00057D, 0x002820,
0x03B060, 0x07F206, 0x018040, 0x003020,
0x03A860, 0x018040, 0x0002FD, 0x018042,
0x08000A, 0x000904, 0x07FA86, 0x000007,
0x00057D, 0x018042, 0x28040A, 0x000E8D,
0x000810, 0x280C3A, 0x00000D, 0x000810,
0x28143A, 0x09000D, 0x000820, 0x0002FD,
0x018040, 0x200007, 0x003DFD, 0x000020,
0x018040, 0x00107D, 0x008D8D, 0x000810,
0x08043A, 0x288A06, 0x000007, 0x000815,
0x08001A, 0x010984, 0x095186, 0x00137D,
0x200500, 0x280F20, 0x338F60, 0x3B8F60,
0x438F60, 0x4B8F60, 0x538F60, 0x5B8F60,
0x038A60, 0x018040, 0x007FBD, 0x383DC4,
0x000007, 0x001A7D, 0x001375, 0x018042,
0x09004A, 0x10000A, 0x0B8D04, 0x139504,
0x000007, 0x000820, 0x019060, 0x001104,
0x212086, 0x010040, 0x0017FD, 0x018042,
0x08000A, 0x000904, 0x212286, 0x000007,
0x00197D, 0x038042, 0x09804A, 0x10000A,
0x000924, 0x001664, 0x0011FD, 0x038042,
0x2B804A, 0x19804A, 0x00008D, 0x218944,
0x000007, 0x002244, 0x0AE186, 0x000007,
0x001A64, 0x002A24, 0x00197D, 0x080102,
0x100122, 0x000820, 0x039060, 0x018040,
0x003DFD, 0x00008D, 0x000820, 0x018040,
0x001375, 0x001A7D, 0x010042, 0x09804A,
0x10000A, 0x00021D, 0x0189E4, 0x2992E4,
0x309144, 0x000007, 0x00060D, 0x000A15,
0x000C1D, 0x001025, 0x00A9E4, 0x012BE4,
0x000464, 0x01B3E4, 0x0232E4, 0x000464,
0x000464, 0x000464, 0x000464, 0x00040D,
0x08B1C4, 0x000007, 0x000820, 0x000BF5,
0x030040, 0x00197D, 0x038042, 0x09804A,
0x000A24, 0x08000A, 0x080E64, 0x000007,
0x100122, 0x000820, 0x031060, 0x010040,
0x0064AC, 0x00027D, 0x000020, 0x018040,
0x00107D, 0x018042, 0x0011FD, 0x3B804A,
0x09804A, 0x20000A, 0x000095, 0x1A1144,
0x00A144, 0x0D2086, 0x00040D, 0x00B984,
0x0D2186, 0x0018FD, 0x018042, 0x0010FD,
0x09804A, 0x28000A, 0x000095, 0x010924,
0x002A64, 0x0D1186, 0x000007, 0x002904,
0x0D2286, 0x000007, 0x0D2A06, 0x080002,
0x00008D, 0x00387D, 0x000820, 0x018040,
0x00127D, 0x018042, 0x10000A, 0x003904,
0x0DD186, 0x00080D, 0x7FFFB5, 0x00B984,
0x0DA186, 0x000025, 0x0E7A06, 0x00002D,
0x000015, 0x00082D, 0x02C78D, 0x000820,
0x0EC206, 0x00000D, 0x7F8035, 0x00B984,
0x0E7186, 0x400025, 0x00008D, 0x110944,
0x000007, 0x00018D, 0x109504, 0x000007,
0x009164, 0x000424, 0x000424, 0x000424,
0x100102, 0x280002, 0x02C68D, 0x000820,
0x0EC206, 0x00018D, 0x00042D, 0x00008D,
0x109504, 0x000007, 0x00020D, 0x109184,
0x000007, 0x02C70D, 0x000820, 0x00008D,
0x0038FD, 0x018040, 0x003BFD, 0x001020,
0x03A860, 0x000815, 0x313184, 0x212184,
0x000007, 0x03B060, 0x03A060, 0x018040,
0x0022FD, 0x000095, 0x010924, 0x000424,
0x000424, 0x001264, 0x100102, 0x000820,
0x039060, 0x018040, 0x001924, 0x00FB8D,
0x00397D, 0x000820, 0x058040, 0x038042,
0x09844A, 0x000606, 0x08040A, 0x000424,
0x000424, 0x00117D, 0x018042, 0x08000A,
0x000A24, 0x280502, 0x280C02, 0x09800D,
0x000820, 0x0002FD, 0x018040, 0x200007,
0x0022FD, 0x018042, 0x08000A, 0x000095,
0x280DC4, 0x011924, 0x00197D, 0x018042,
0x0011FD, 0x09804A, 0x10000A, 0x0000B5,
0x113144, 0x0A8D04, 0x000007, 0x080A44,
0x129504, 0x000007, 0x0023FD, 0x001020,
0x038040, 0x101244, 0x000007, 0x000820,
0x039060, 0x018040, 0x0002FD, 0x018042,
0x08000A, 0x000904, 0x10FA86, 0x000007,
0x003BFD, 0x000100, 0x000A10, 0x0B807A,
0x13804A, 0x090984, 0x000007, 0x000095,
0x013D04, 0x118086, 0x10000A, 0x100002,
0x090984, 0x000007, 0x038042, 0x11804A,
0x090D04, 0x000007, 0x10000A, 0x090D84,
0x000007, 0x00257D, 0x000820, 0x018040,
0x00010D, 0x000810, 0x28143A, 0x00127D,
0x018042, 0x20000A, 0x00197D, 0x018042,
0x00117D, 0x31804A, 0x10000A, 0x003124,
0x01280D, 0x00397D, 0x000820, 0x058040,
0x038042, 0x09844A, 0x000606, 0x08040A,
0x300102, 0x003124, 0x000424, 0x000424,
0x001224, 0x280502, 0x001A4C, 0x130186,
0x700002, 0x00002D, 0x030000, 0x00387D,
0x018042, 0x10000A, 0x132A06, 0x002124,
0x0000AD, 0x100002, 0x00010D, 0x000924,
0x006B24, 0x01368D, 0x00397D, 0x000820,
0x058040, 0x038042, 0x09844A, 0x000606,
0x08040A, 0x003264, 0x00008D, 0x000A24,
0x001020, 0x00227D, 0x018040, 0x013C0D,
0x000810, 0x08043A, 0x29D206, 0x000007,
0x002820, 0x00207D, 0x018040, 0x00117D,
0x038042, 0x13804A, 0x33800A, 0x00387D,
0x018042, 0x08000A, 0x000904, 0x163A86,
0x000007, 0x00008D, 0x030964, 0x01478D,
0x00397D, 0x000820, 0x058040, 0x038042,
0x09844A, 0x000606, 0x08040A, 0x380102,
0x000424, 0x000424, 0x001224, 0x0002FD,
0x018042, 0x08000A, 0x000904, 0x14A286,
0x000007, 0x280502, 0x001A4C, 0x163986,
0x000007, 0x032164, 0x00632C, 0x003DFD,
0x018042, 0x08000A, 0x000095, 0x090904,
0x000007, 0x000820, 0x001A4C, 0x156186,
0x018040, 0x030000, 0x157A06, 0x002124,
0x00010D, 0x000924, 0x006B24, 0x015B8D,
0x00397D, 0x000820, 0x058040, 0x038042,
0x09844A, 0x000606, 0x08040A, 0x003A64,
0x000095, 0x001224, 0x0002FD, 0x018042,
0x08000A, 0x000904, 0x15DA86, 0x000007,
0x01628D, 0x000810, 0x08043A, 0x29D206,
0x000007, 0x14D206, 0x000007, 0x007020,
0x08010A, 0x10012A, 0x0020FD, 0x038860,
0x039060, 0x018040, 0x00227D, 0x018042,
0x003DFD, 0x08000A, 0x31844A, 0x000904,
0x16D886, 0x18008B, 0x00008D, 0x189904,
0x00312C, 0x17AA06, 0x000007, 0x00324C,
0x173386, 0x000007, 0x001904, 0x173086,
0x000007, 0x000095, 0x199144, 0x00222C,
0x003124, 0x00636C, 0x000E3D, 0x001375,
0x000BFD, 0x010042, 0x09804A, 0x10000A,
0x038AEC, 0x0393EC, 0x00224C, 0x17A986,
0x000007, 0x00008D, 0x189904, 0x00226C,
0x00322C, 0x30050A, 0x301DAB, 0x002083,
0x0018FD, 0x018042, 0x08000A, 0x018924,
0x300502, 0x001083, 0x001875, 0x010042,
0x10000A, 0x00008D, 0x010924, 0x001375,
0x330542, 0x330CCB, 0x332CCB, 0x3334CB,
0x333CCB, 0x3344CB, 0x334CCB, 0x3354CB,
0x305C8B, 0x006083, 0x0002F5, 0x010042,
0x08000A, 0x000904, 0x187A86, 0x000007,
0x001E2D, 0x0005FD, 0x018042, 0x08000A,
0x028924, 0x280502, 0x00060D, 0x000810,
0x280C3A, 0x00008D, 0x000810, 0x28143A,
0x0A808D, 0x000820, 0x0002F5, 0x010040,
0x220007, 0x001275, 0x030042, 0x21004A,
0x00008D, 0x1A0944, 0x000007, 0x01980D,
0x000810, 0x08043A, 0x2B2206, 0x000007,
0x0001F5, 0x030042, 0x0D004A, 0x10000A,
0x089144, 0x000007, 0x000820, 0x010040,
0x0025F5, 0x0A3144, 0x000007, 0x000820,
0x032860, 0x030040, 0x00217D, 0x038042,
0x0B804A, 0x10000A, 0x000820, 0x031060,
0x030040, 0x00008D, 0x000124, 0x00012C,
0x000E64, 0x001A64, 0x00636C, 0x08010A,
0x10012A, 0x000820, 0x031060, 0x030040,
0x0020FD, 0x018042, 0x08000A, 0x00227D,
0x018042, 0x10000A, 0x000820, 0x031060,
0x030040, 0x00197D, 0x018042, 0x08000A,
0x0022FD, 0x038042, 0x10000A, 0x000820,
0x031060, 0x030040, 0x090D04, 0x000007,
0x000820, 0x030040, 0x038042, 0x0B804A,
0x10000A, 0x000820, 0x031060, 0x030040,
0x038042, 0x13804A, 0x19804A, 0x110D04,
0x198D04, 0x000007, 0x08000A, 0x001020,
0x031860, 0x030860, 0x030040, 0x00008D,
0x0B0944, 0x000007, 0x000820, 0x010040,
0x0005F5, 0x030042, 0x08000A, 0x000820,
0x010040, 0x0000F5, 0x010042, 0x08000A,
0x000904, 0x1C6086, 0x001E75, 0x030042,
0x01044A, 0x000C0A, 0x1C7206, 0x000007,
0x000402, 0x000C02, 0x00177D, 0x001AF5,
0x018042, 0x03144A, 0x031C4A, 0x03244A,
0x032C4A, 0x03344A, 0x033C4A, 0x03444A,
0x004C0A, 0x00043D, 0x0013F5, 0x001AFD,
0x030042, 0x0B004A, 0x1B804A, 0x13804A,
0x20000A, 0x089144, 0x19A144, 0x0389E4,
0x0399EC, 0x005502, 0x005D0A, 0x030042,
0x0B004A, 0x1B804A, 0x13804A, 0x20000A,
0x089144, 0x19A144, 0x0389E4, 0x0399EC,
0x006502, 0x006D0A, 0x030042, 0x0B004A,
0x19004A, 0x2B804A, 0x13804A, 0x21804A,
0x30000A, 0x089144, 0x19A144, 0x2AB144,
0x0389E4, 0x0399EC, 0x007502, 0x007D0A,
0x03A9E4, 0x000702, 0x00107D, 0x000415,
0x018042, 0x08000A, 0x0109E4, 0x000F02,
0x002AF5, 0x0019FD, 0x010042, 0x09804A,
0x10000A, 0x000934, 0x001674, 0x0029F5,
0x010042, 0x10000A, 0x00917C, 0x002075,
0x010042, 0x08000A, 0x000904, 0x1ED286,
0x0026F5, 0x0027F5, 0x030042, 0x09004A,
0x10000A, 0x000A3C, 0x00167C, 0x001A75,
0x000BFD, 0x010042, 0x51804A, 0x48000A,
0x160007, 0x001075, 0x010042, 0x282C0A,
0x281D12, 0x282512, 0x001F32, 0x1E0007,
0x0E0007, 0x001975, 0x010042, 0x002DF5,
0x0D004A, 0x10000A, 0x009144, 0x1FB286,
0x010042, 0x28340A, 0x000E5D, 0x00008D,
0x000375, 0x000820, 0x010040, 0x05D2F4,
0x54D104, 0x00735C, 0x205386, 0x000007,
0x0C0007, 0x080007, 0x0A0007, 0x02040D,
0x000810, 0x08043A, 0x332206, 0x000007,
0x205A06, 0x000007, 0x080007, 0x002275,
0x010042, 0x20000A, 0x002104, 0x212086,
0x001E2D, 0x0002F5, 0x010042, 0x08000A,
0x000904, 0x209286, 0x000007, 0x002010,
0x30043A, 0x00057D, 0x0180C3, 0x08000A,
0x028924, 0x280502, 0x280C02, 0x0A810D,
0x000820, 0x0002F5, 0x010040, 0x220007,
0x0004FD, 0x018042, 0x70000A, 0x030000,
0x007020, 0x06FA06, 0x018040, 0x02180D,
0x000810, 0x08043A, 0x2B2206, 0x000007,
0x0002FD, 0x018042, 0x08000A, 0x000904,
0x218A86, 0x000007, 0x01F206, 0x000007,
0x000875, 0x0009FD, 0x00010D, 0x220A06,
0x000295, 0x000B75, 0x00097D, 0x00000D,
0x000515, 0x010042, 0x18000A, 0x001904,
0x287886, 0x0006F5, 0x001020, 0x010040,
0x0004F5, 0x000820, 0x010040, 0x000775,
0x010042, 0x09804A, 0x10000A, 0x001124,
0x000904, 0x22BA86, 0x000815, 0x080102,
0x101204, 0x22DA06, 0x000575, 0x081204,
0x000007, 0x100102, 0x000575, 0x000425,
0x021124, 0x100102, 0x000820, 0x031060,
0x010040, 0x001924, 0x287886, 0x00008D,
0x000464, 0x009D04, 0x278886, 0x180102,
0x000575, 0x010042, 0x28040A, 0x00018D,
0x000924, 0x280D02, 0x00000D, 0x000924,
0x281502, 0x10000D, 0x000820, 0x0002F5,
0x010040, 0x200007, 0x001175, 0x0002FD,
0x018042, 0x08000A, 0x000904, 0x23C286,
0x000007, 0x000100, 0x080B20, 0x130B60,
0x1B0B60, 0x030A60, 0x010040, 0x050042,
0x3D004A, 0x35004A, 0x2D004A, 0x20000A,
0x0006F5, 0x010042, 0x28140A, 0x0004F5,
0x010042, 0x08000A, 0x000315, 0x010D04,
0x24CA86, 0x004015, 0x000095, 0x010D04,
0x24B886, 0x100022, 0x10002A, 0x24E206,
0x000007, 0x333104, 0x2AA904, 0x000007,
0x032124, 0x280502, 0x001124, 0x000424,
0x000424, 0x003224, 0x00292C, 0x00636C,
0x25F386, 0x000007, 0x02B164, 0x000464,
0x000464, 0x00008D, 0x000A64, 0x280D02,
0x10008D, 0x000820, 0x0002F5, 0x010040,
0x220007, 0x00008D, 0x38B904, 0x000007,
0x03296C, 0x30010A, 0x0002F5, 0x010042,
0x08000A, 0x000904, 0x25BA86, 0x000007,
0x02312C, 0x28050A, 0x00008D, 0x01096C,
0x280D0A, 0x10010D, 0x000820, 0x0002F5,
0x010040, 0x220007, 0x001124, 0x000424,
0x000424, 0x003224, 0x300102, 0x032944,
0x267A86, 0x000007, 0x300002, 0x0004F5,
0x010042, 0x08000A, 0x000315, 0x010D04,
0x26C086, 0x003124, 0x000464, 0x300102,
0x0002F5, 0x010042, 0x08000A, 0x000904,
0x26CA86, 0x000007, 0x003124, 0x300502,
0x003924, 0x300583, 0x000883, 0x0005F5,
0x010042, 0x28040A, 0x00008D, 0x008124,
0x280D02, 0x00008D, 0x008124, 0x281502,
0x10018D, 0x000820, 0x0002F5, 0x010040,
0x220007, 0x001025, 0x000575, 0x030042,
0x09004A, 0x10000A, 0x0A0904, 0x121104,
0x000007, 0x001020, 0x050860, 0x050040,
0x0006FD, 0x018042, 0x09004A, 0x10000A,
0x0000A5, 0x0A0904, 0x121104, 0x000007,
0x000820, 0x019060, 0x010040, 0x0002F5,
0x010042, 0x08000A, 0x000904, 0x284286,
0x000007, 0x230A06, 0x000007, 0x000606,
0x000007, 0x0002F5, 0x010042, 0x08000A,
0x000904, 0x289286, 0x000007, 0x000100,
0x080B20, 0x138B60, 0x1B8B60, 0x238B60,
0x2B8B60, 0x338B60, 0x3B8B60, 0x438B60,
0x4B8B60, 0x538B60, 0x5B8B60, 0x638B60,
0x6B8B60, 0x738B60, 0x7B8B60, 0x038F60,
0x0B8F60, 0x138F60, 0x1B8F60, 0x238F60,
0x2B8F60, 0x338F60, 0x3B8F60, 0x438F60,
0x4B8F60, 0x538F60, 0x5B8F60, 0x638F60,
0x6B8F60, 0x738F60, 0x7B8F60, 0x038A60,
0x000606, 0x018040, 0x00008D, 0x000A64,
0x280D02, 0x000A24, 0x00027D, 0x018042,
0x10000A, 0x001224, 0x0003FD, 0x018042,
0x08000A, 0x000904, 0x2A8286, 0x000007,
0x00018D, 0x000A24, 0x000464, 0x000464,
0x080102, 0x000924, 0x000424, 0x000424,
0x100102, 0x02000D, 0x009144, 0x2AD986,
0x000007, 0x0001FD, 0x018042, 0x08000A,
0x000A44, 0x2ABB86, 0x018042, 0x0A000D,
0x000820, 0x0002FD, 0x018040, 0x200007,
0x00027D, 0x001020, 0x000606, 0x018040,
0x0002F5, 0x010042, 0x08000A, 0x000904,
0x2B2A86, 0x000007, 0x00037D, 0x018042,
0x08000A, 0x000904, 0x2B5A86, 0x000007,
0x000075, 0x002E7D, 0x010042, 0x0B804A,
0x000020, 0x000904, 0x000686, 0x010040,
0x31844A, 0x30048B, 0x000883, 0x00008D,
0x000810, 0x28143A, 0x00008D, 0x000810,
0x280C3A, 0x000675, 0x010042, 0x08000A,
0x003815, 0x010924, 0x280502, 0x0B000D,
0x000820, 0x0002F5, 0x010040, 0x000606,
0x220007, 0x000464, 0x000464, 0x000606,
0x000007, 0x000134, 0x007F8D, 0x00093C,
0x281D12, 0x282512, 0x001F32, 0x0E0007,
0x00010D, 0x00037D, 0x000820, 0x018040,
0x05D2F4, 0x000007, 0x080007, 0x00037D,
0x018042, 0x08000A, 0x000904, 0x2D0286,
0x000007, 0x000606, 0x000007, 0x000007,
0x000012, 0x100007, 0x320007, 0x600007,
0x100080, 0x48001A, 0x004904, 0x2D6186,
0x000007, 0x001210, 0x58003A, 0x000145,
0x5C5D04, 0x000007, 0x000080, 0x48001A,
0x004904, 0x2DB186, 0x000007, 0x001210,
0x50003A, 0x005904, 0x2E0886, 0x000045,
0x0000C5, 0x7FFFF5, 0x7FFF7D, 0x07D524,
0x004224, 0x500102, 0x200502, 0x000082,
0x40001A, 0x004104, 0x2E3986, 0x000007,
0x003865, 0x40001A, 0x004020, 0x00104D,
0x04C184, 0x301B86, 0x000040, 0x040007,
0x000165, 0x000145, 0x004020, 0x000040,
0x000765, 0x080080, 0x40001A, 0x004104,
0x2EC986, 0x000007, 0x001210, 0x40003A,
0x004104, 0x2F2286, 0x00004D, 0x0000CD,
0x004810, 0x20043A, 0x000882, 0x40001A,
0x004104, 0x2F3186, 0x000007, 0x004820,
0x005904, 0x300886, 0x000040, 0x0007E5,
0x200480, 0x2816A0, 0x3216E0, 0x3A16E0,
0x4216E0, 0x021260, 0x000040, 0x000032,
0x400075, 0x00007D, 0x07D574, 0x200512,
0x000082, 0x40001A, 0x004104, 0x2FE186,
0x000007, 0x037206, 0x640007, 0x060007,
0x0000E5, 0x000020, 0x000040, 0x000A65,
0x000020, 0x020040, 0x020040, 0x000040,
0x000165, 0x000042, 0x70000A, 0x007104,
0x30A286, 0x000007, 0x018206, 0x640007,
0x050000, 0x007020, 0x000040, 0x037206,
0x640007, 0x000007, 0x00306D, 0x028860,
0x029060, 0x08000A, 0x028860, 0x008040,
0x100012, 0x00100D, 0x009184, 0x314186,
0x000E0D, 0x009184, 0x325186, 0x000007,
0x300007, 0x001020, 0x003B6D, 0x008040,
0x000080, 0x08001A, 0x000904, 0x316186,
0x000007, 0x001220, 0x000DED, 0x008040,
0x008042, 0x10000A, 0x40000D, 0x109544,
0x000007, 0x001020, 0x000DED, 0x008040,
0x008042, 0x20040A, 0x000082, 0x08001A,
0x000904, 0x31F186, 0x000007, 0x003B6D,
0x008042, 0x08000A, 0x000E15, 0x010984,
0x329B86, 0x600007, 0x08001A, 0x000C15,
0x010984, 0x328386, 0x000020, 0x1A0007,
0x0002ED, 0x008040, 0x620007, 0x00306D,
0x028042, 0x0A804A, 0x000820, 0x0A804A,
0x000606, 0x10804A, 0x000007, 0x282512,
0x001F32, 0x05D2F4, 0x54D104, 0x00735C,
0x000786, 0x000007, 0x0C0007, 0x0A0007,
0x1C0007, 0x003465, 0x020040, 0x004820,
0x025060, 0x40000A, 0x024060, 0x000040,
0x454944, 0x000007, 0x004020, 0x003AE5,
0x000040, 0x0028E5, 0x000042, 0x48000A,
0x004904, 0x386886, 0x002C65, 0x000042,
0x40000A, 0x0000D5, 0x454104, 0x000007,
0x000655, 0x054504, 0x34F286, 0x0001D5,
0x054504, 0x34F086, 0x002B65, 0x000042,
0x003AE5, 0x50004A, 0x40000A, 0x45C3D4,
0x000007, 0x454504, 0x000007, 0x0000CD,
0x444944, 0x000007, 0x454504, 0x000007,
0x00014D, 0x554944, 0x000007, 0x045144,
0x34E986, 0x002C65, 0x000042, 0x48000A,
0x4CD104, 0x000007, 0x04C144, 0x34F386,
0x000007, 0x160007, 0x002CE5, 0x040042,
0x40000A, 0x004020, 0x000040, 0x002965,
0x000042, 0x40000A, 0x004104, 0x356086,
0x000007, 0x002402, 0x36A206, 0x005C02,
0x0025E5, 0x000042, 0x40000A, 0x004274,
0x002AE5, 0x000042, 0x40000A, 0x004274,
0x500112, 0x0029E5, 0x000042, 0x40000A,
0x004234, 0x454104, 0x000007, 0x004020,
0x000040, 0x003EE5, 0x000020, 0x000040,
0x002DE5, 0x400152, 0x50000A, 0x045144,
0x364A86, 0x0000C5, 0x003EE5, 0x004020,
0x000040, 0x002BE5, 0x000042, 0x40000A,
0x404254, 0x000007, 0x002AE5, 0x004020,
0x000040, 0x500132, 0x040134, 0x005674,
0x0029E5, 0x020042, 0x42000A, 0x000042,
0x50000A, 0x05417C, 0x0028E5, 0x000042,
0x48000A, 0x0000C5, 0x4CC144, 0x371086,
0x0026E5, 0x0027E5, 0x020042, 0x40004A,
0x50000A, 0x00423C, 0x00567C, 0x0028E5,
0x004820, 0x000040, 0x281D12, 0x282512,
0x001F72, 0x002965, 0x000042, 0x40000A,
0x004104, 0x37AA86, 0x0E0007, 0x160007,
0x1E0007, 0x003EE5, 0x000042, 0x40000A,
0x004104, 0x37E886, 0x002D65, 0x000042,
0x28340A, 0x003465, 0x020042, 0x42004A,
0x004020, 0x4A004A, 0x50004A, 0x05D2F4,
0x54D104, 0x00735C, 0x385186, 0x000007,
0x000606, 0x080007, 0x0C0007, 0x080007,
0x0A0007, 0x0001E5, 0x020045, 0x004020,
0x000060, 0x000365, 0x000040, 0x002E65,
0x001A20, 0x0A1A60, 0x000040, 0x003465,
0x020042, 0x42004A, 0x004020, 0x4A004A,
0x000606, 0x50004A, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000
};
// --------------------------------------------
// DS-1E Controller InstructionRAM Code
// 1999/06/21
// Buf441 slot is Enabled.
// --------------------------------------------
// 04/09 creat
// 04/12 stop nise fix
// 06/21 WorkingOff timming
static unsigned long int CntrlInst1E[] = {
0x000007, 0x240007, 0x0C0007, 0x1C0007,
0x060007, 0x700002, 0x000020, 0x030040,
0x007104, 0x004286, 0x030040, 0x000F0D,
0x000810, 0x20043A, 0x000282, 0x00020D,
0x000810, 0x20043A, 0x001282, 0x200E82,
0x00800D, 0x000810, 0x20043A, 0x001A82,
0x03460D, 0x000810, 0x10043A, 0x02EC0D,
0x000810, 0x18043A, 0x00010D, 0x020015,
0x0000FD, 0x000020, 0x038860, 0x039060,
0x038060, 0x038040, 0x038040, 0x038040,
0x018040, 0x000A7D, 0x038040, 0x038040,
0x018040, 0x200402, 0x000882, 0x08001A,
0x000904, 0x017186, 0x000007, 0x260007,
0x400007, 0x000007, 0x03258D, 0x000810,
0x18043A, 0x260007, 0x284402, 0x00087D,
0x018042, 0x00160A, 0x05A206, 0x000007,
0x440007, 0x00230D, 0x000810, 0x08043A,
0x22FA06, 0x000007, 0x0007FD, 0x018042,
0x08000A, 0x000904, 0x02AB86, 0x000195,
0x090D04, 0x000007, 0x000820, 0x0000F5,
0x000B7D, 0x01F060, 0x0000FD, 0x033A06,
0x018040, 0x000A7D, 0x038042, 0x13804A,
0x18000A, 0x001820, 0x059060, 0x058860,
0x018040, 0x0000FD, 0x018042, 0x70000A,
0x000115, 0x071144, 0x033B86, 0x030000,
0x007020, 0x036206, 0x018040, 0x00360D,
0x000810, 0x08043A, 0x232206, 0x000007,
0x02EC0D, 0x000810, 0x18043A, 0x019A06,
0x000007, 0x240007, 0x000F8D, 0x000810,
0x00163A, 0x002402, 0x005C02, 0x0028FD,
0x000020, 0x018040, 0x08000D, 0x000815,
0x510984, 0x000007, 0x00004D, 0x000E5D,
0x000E02, 0x00430D, 0x000810, 0x08043A,
0x2E1206, 0x000007, 0x00008D, 0x000924,
0x000F02, 0x00470D, 0x000810, 0x08043A,
0x2E1206, 0x000007, 0x480480, 0x001210,
0x28043A, 0x00778D, 0x000810, 0x280C3A,
0x00068D, 0x000810, 0x28143A, 0x284402,
0x03258D, 0x000810, 0x18043A, 0x07FF8D,
0x000820, 0x0002FD, 0x018040, 0x260007,
0x200007, 0x0002FD, 0x018042, 0x08000A,
0x000904, 0x051286, 0x000007, 0x240007,
0x02EC0D, 0x000810, 0x18043A, 0x00387D,
0x018042, 0x08000A, 0x001015, 0x010984,
0x019B86, 0x000007, 0x01B206, 0x000007,
0x0008FD, 0x018042, 0x18000A, 0x001904,
0x22B886, 0x280007, 0x001810, 0x28043A,
0x280C02, 0x00000D, 0x000810, 0x28143A,
0x08808D, 0x000820, 0x0002FD, 0x018040,
0x200007, 0x00020D, 0x189904, 0x000007,
0x00402D, 0x0000BD, 0x0002FD, 0x018042,
0x08000A, 0x000904, 0x065A86, 0x000007,
0x000100, 0x000A20, 0x00047D, 0x018040,
0x018042, 0x20000A, 0x003015, 0x012144,
0x036186, 0x000007, 0x002104, 0x036186,
0x000007, 0x000F8D, 0x000810, 0x280C3A,
0x023944, 0x07C986, 0x000007, 0x001810,
0x28043A, 0x08810D, 0x000820, 0x0002FD,
0x018040, 0x200007, 0x002810, 0x78003A,
0x00788D, 0x000810, 0x08043A, 0x2A1206,
0x000007, 0x00400D, 0x001015, 0x189904,
0x292904, 0x393904, 0x000007, 0x070206,
0x000007, 0x0004F5, 0x00007D, 0x000020,
0x00008D, 0x010860, 0x018040, 0x00047D,
0x038042, 0x21804A, 0x18000A, 0x021944,
0x229086, 0x000007, 0x004075, 0x71F104,
0x000007, 0x010042, 0x28000A, 0x002904,
0x225886, 0x000007, 0x003C0D, 0x30A904,
0x000007, 0x00077D, 0x018042, 0x08000A,
0x000904, 0x08DA86, 0x00057D, 0x002820,
0x03B060, 0x08F206, 0x018040, 0x003020,
0x03A860, 0x018040, 0x0002FD, 0x018042,
0x08000A, 0x000904, 0x08FA86, 0x000007,
0x00057D, 0x018042, 0x28040A, 0x000E8D,
0x000810, 0x280C3A, 0x00000D, 0x000810,
0x28143A, 0x09000D, 0x000820, 0x0002FD,
0x018040, 0x200007, 0x003DFD, 0x000020,
0x018040, 0x00107D, 0x009D8D, 0x000810,
0x08043A, 0x2A1206, 0x000007, 0x000815,
0x08001A, 0x010984, 0x0A5186, 0x00137D,
0x200500, 0x280F20, 0x338F60, 0x3B8F60,
0x438F60, 0x4B8F60, 0x538F60, 0x5B8F60,
0x038A60, 0x018040, 0x00107D, 0x018042,
0x08000A, 0x000215, 0x010984, 0x3A8186,
0x000007, 0x007FBD, 0x383DC4, 0x000007,
0x001A7D, 0x001375, 0x018042, 0x09004A,
0x10000A, 0x0B8D04, 0x139504, 0x000007,
0x000820, 0x019060, 0x001104, 0x225886,
0x010040, 0x0017FD, 0x018042, 0x08000A,
0x000904, 0x225A86, 0x000007, 0x00197D,
0x038042, 0x09804A, 0x10000A, 0x000924,
0x001664, 0x0011FD, 0x038042, 0x2B804A,
0x19804A, 0x00008D, 0x218944, 0x000007,
0x002244, 0x0C1986, 0x000007, 0x001A64,
0x002A24, 0x00197D, 0x080102, 0x100122,
0x000820, 0x039060, 0x018040, 0x003DFD,
0x00008D, 0x000820, 0x018040, 0x001375,
0x001A7D, 0x010042, 0x09804A, 0x10000A,
0x00021D, 0x0189E4, 0x2992E4, 0x309144,
0x000007, 0x00060D, 0x000A15, 0x000C1D,
0x001025, 0x00A9E4, 0x012BE4, 0x000464,
0x01B3E4, 0x0232E4, 0x000464, 0x000464,
0x000464, 0x000464, 0x00040D, 0x08B1C4,
0x000007, 0x000820, 0x000BF5, 0x030040,
0x00197D, 0x038042, 0x09804A, 0x000A24,
0x08000A, 0x080E64, 0x000007, 0x100122,
0x000820, 0x031060, 0x010040, 0x0064AC,
0x00027D, 0x000020, 0x018040, 0x00107D,
0x018042, 0x0011FD, 0x3B804A, 0x09804A,
0x20000A, 0x000095, 0x1A1144, 0x00A144,
0x0E5886, 0x00040D, 0x00B984, 0x0E5986,
0x0018FD, 0x018042, 0x0010FD, 0x09804A,
0x28000A, 0x000095, 0x010924, 0x002A64,
0x0E4986, 0x000007, 0x002904, 0x0E5A86,
0x000007, 0x0E6206, 0x080002, 0x00008D,
0x00387D, 0x000820, 0x018040, 0x00127D,
0x018042, 0x10000A, 0x003904, 0x0F0986,
0x00080D, 0x7FFFB5, 0x00B984, 0x0ED986,
0x000025, 0x0FB206, 0x00002D, 0x000015,
0x00082D, 0x02E00D, 0x000820, 0x0FFA06,
0x00000D, 0x7F8035, 0x00B984, 0x0FA986,
0x400025, 0x00008D, 0x110944, 0x000007,
0x00018D, 0x109504, 0x000007, 0x009164,
0x000424, 0x000424, 0x000424, 0x100102,
0x280002, 0x02DF0D, 0x000820, 0x0FFA06,
0x00018D, 0x00042D, 0x00008D, 0x109504,
0x000007, 0x00020D, 0x109184, 0x000007,
0x02DF8D, 0x000820, 0x00008D, 0x0038FD,
0x018040, 0x003BFD, 0x001020, 0x03A860,
0x000815, 0x313184, 0x212184, 0x000007,
0x03B060, 0x03A060, 0x018040, 0x0022FD,
0x000095, 0x010924, 0x000424, 0x000424,
0x001264, 0x100102, 0x000820, 0x039060,
0x018040, 0x001924, 0x010F0D, 0x00397D,
0x000820, 0x058040, 0x038042, 0x09844A,
0x000606, 0x08040A, 0x000424, 0x000424,
0x00117D, 0x018042, 0x08000A, 0x000A24,
0x280502, 0x280C02, 0x09800D, 0x000820,
0x0002FD, 0x018040, 0x200007, 0x0022FD,
0x018042, 0x08000A, 0x000095, 0x280DC4,
0x011924, 0x00197D, 0x018042, 0x0011FD,
0x09804A, 0x10000A, 0x0000B5, 0x113144,
0x0A8D04, 0x000007, 0x080A44, 0x129504,
0x000007, 0x0023FD, 0x001020, 0x038040,
0x101244, 0x000007, 0x000820, 0x039060,
0x018040, 0x0002FD, 0x018042, 0x08000A,
0x000904, 0x123286, 0x000007, 0x003BFD,
0x000100, 0x000A10, 0x0B807A, 0x13804A,
0x090984, 0x000007, 0x000095, 0x013D04,
0x12B886, 0x10000A, 0x100002, 0x090984,
0x000007, 0x038042, 0x11804A, 0x090D04,
0x000007, 0x10000A, 0x090D84, 0x000007,
0x00257D, 0x000820, 0x018040, 0x00010D,
0x000810, 0x28143A, 0x00127D, 0x018042,
0x20000A, 0x00197D, 0x018042, 0x00117D,
0x31804A, 0x10000A, 0x003124, 0x013B8D,
0x00397D, 0x000820, 0x058040, 0x038042,
0x09844A, 0x000606, 0x08040A, 0x300102,
0x003124, 0x000424, 0x000424, 0x001224,
0x280502, 0x001A4C, 0x143986, 0x700002,
0x00002D, 0x030000, 0x00387D, 0x018042,
0x10000A, 0x146206, 0x002124, 0x0000AD,
0x100002, 0x00010D, 0x000924, 0x006B24,
0x014A0D, 0x00397D, 0x000820, 0x058040,
0x038042, 0x09844A, 0x000606, 0x08040A,
0x003264, 0x00008D, 0x000A24, 0x001020,
0x00227D, 0x018040, 0x014F8D, 0x000810,
0x08043A, 0x2B5A06, 0x000007, 0x002820,
0x00207D, 0x018040, 0x00117D, 0x038042,
0x13804A, 0x33800A, 0x00387D, 0x018042,
0x08000A, 0x000904, 0x177286, 0x000007,
0x00008D, 0x030964, 0x015B0D, 0x00397D,
0x000820, 0x058040, 0x038042, 0x09844A,
0x000606, 0x08040A, 0x380102, 0x000424,
0x000424, 0x001224, 0x0002FD, 0x018042,
0x08000A, 0x000904, 0x15DA86, 0x000007,
0x280502, 0x001A4C, 0x177186, 0x000007,
0x032164, 0x00632C, 0x003DFD, 0x018042,
0x08000A, 0x000095, 0x090904, 0x000007,
0x000820, 0x001A4C, 0x169986, 0x018040,
0x030000, 0x16B206, 0x002124, 0x00010D,
0x000924, 0x006B24, 0x016F0D, 0x00397D,
0x000820, 0x058040, 0x038042, 0x09844A,
0x000606, 0x08040A, 0x003A64, 0x000095,
0x001224, 0x0002FD, 0x018042, 0x08000A,
0x000904, 0x171286, 0x000007, 0x01760D,
0x000810, 0x08043A, 0x2B5A06, 0x000007,
0x160A06, 0x000007, 0x007020, 0x08010A,
0x10012A, 0x0020FD, 0x038860, 0x039060,
0x018040, 0x00227D, 0x018042, 0x003DFD,
0x08000A, 0x31844A, 0x000904, 0x181086,
0x18008B, 0x00008D, 0x189904, 0x00312C,
0x18E206, 0x000007, 0x00324C, 0x186B86,
0x000007, 0x001904, 0x186886, 0x000007,
0x000095, 0x199144, 0x00222C, 0x003124,
0x00636C, 0x000E3D, 0x001375, 0x000BFD,
0x010042, 0x09804A, 0x10000A, 0x038AEC,
0x0393EC, 0x00224C, 0x18E186, 0x000007,
0x00008D, 0x189904, 0x00226C, 0x00322C,
0x30050A, 0x301DAB, 0x002083, 0x0018FD,
0x018042, 0x08000A, 0x018924, 0x300502,
0x001083, 0x001875, 0x010042, 0x10000A,
0x00008D, 0x010924, 0x001375, 0x330542,
0x330CCB, 0x332CCB, 0x3334CB, 0x333CCB,
0x3344CB, 0x334CCB, 0x3354CB, 0x305C8B,
0x006083, 0x0002F5, 0x010042, 0x08000A,
0x000904, 0x19B286, 0x000007, 0x001E2D,
0x0005FD, 0x018042, 0x08000A, 0x028924,
0x280502, 0x00060D, 0x000810, 0x280C3A,
0x00008D, 0x000810, 0x28143A, 0x0A808D,
0x000820, 0x0002F5, 0x010040, 0x220007,
0x001275, 0x030042, 0x21004A, 0x00008D,
0x1A0944, 0x000007, 0x01AB8D, 0x000810,
0x08043A, 0x2CAA06, 0x000007, 0x0001F5,
0x030042, 0x0D004A, 0x10000A, 0x089144,
0x000007, 0x000820, 0x010040, 0x0025F5,
0x0A3144, 0x000007, 0x000820, 0x032860,
0x030040, 0x00217D, 0x038042, 0x0B804A,
0x10000A, 0x000820, 0x031060, 0x030040,
0x00008D, 0x000124, 0x00012C, 0x000E64,
0x001A64, 0x00636C, 0x08010A, 0x10012A,
0x000820, 0x031060, 0x030040, 0x0020FD,
0x018042, 0x08000A, 0x00227D, 0x018042,
0x10000A, 0x000820, 0x031060, 0x030040,
0x00197D, 0x018042, 0x08000A, 0x0022FD,
0x038042, 0x10000A, 0x000820, 0x031060,
0x030040, 0x090D04, 0x000007, 0x000820,
0x030040, 0x038042, 0x0B804A, 0x10000A,
0x000820, 0x031060, 0x030040, 0x038042,
0x13804A, 0x19804A, 0x110D04, 0x198D04,
0x000007, 0x08000A, 0x001020, 0x031860,
0x030860, 0x030040, 0x00008D, 0x0B0944,
0x000007, 0x000820, 0x010040, 0x0005F5,
0x030042, 0x08000A, 0x000820, 0x010040,
0x0000F5, 0x010042, 0x08000A, 0x000904,
0x1D9886, 0x001E75, 0x030042, 0x01044A,
0x000C0A, 0x1DAA06, 0x000007, 0x000402,
0x000C02, 0x00177D, 0x001AF5, 0x018042,
0x03144A, 0x031C4A, 0x03244A, 0x032C4A,
0x03344A, 0x033C4A, 0x03444A, 0x004C0A,
0x00043D, 0x0013F5, 0x001AFD, 0x030042,
0x0B004A, 0x1B804A, 0x13804A, 0x20000A,
0x089144, 0x19A144, 0x0389E4, 0x0399EC,
0x005502, 0x005D0A, 0x030042, 0x0B004A,
0x1B804A, 0x13804A, 0x20000A, 0x089144,
0x19A144, 0x0389E4, 0x0399EC, 0x006502,
0x006D0A, 0x030042, 0x0B004A, 0x19004A,
0x2B804A, 0x13804A, 0x21804A, 0x30000A,
0x089144, 0x19A144, 0x2AB144, 0x0389E4,
0x0399EC, 0x007502, 0x007D0A, 0x03A9E4,
0x000702, 0x00107D, 0x000415, 0x018042,
0x08000A, 0x0109E4, 0x000F02, 0x002AF5,
0x0019FD, 0x010042, 0x09804A, 0x10000A,
0x000934, 0x001674, 0x0029F5, 0x010042,
0x10000A, 0x00917C, 0x002075, 0x010042,
0x08000A, 0x000904, 0x200A86, 0x0026F5,
0x0027F5, 0x030042, 0x09004A, 0x10000A,
0x000A3C, 0x00167C, 0x001A75, 0x000BFD,
0x010042, 0x51804A, 0x48000A, 0x160007,
0x001075, 0x010042, 0x282C0A, 0x281D12,
0x282512, 0x001F32, 0x1E0007, 0x0E0007,
0x001975, 0x010042, 0x002DF5, 0x0D004A,
0x10000A, 0x009144, 0x20EA86, 0x010042,
0x28340A, 0x000E5D, 0x00008D, 0x000375,
0x000820, 0x010040, 0x05D2F4, 0x54D104,
0x00735C, 0x218B86, 0x000007, 0x0C0007,
0x080007, 0x0A0007, 0x02178D, 0x000810,
0x08043A, 0x34B206, 0x000007, 0x219206,
0x000007, 0x080007, 0x002275, 0x010042,
0x20000A, 0x002104, 0x225886, 0x001E2D,
0x0002F5, 0x010042, 0x08000A, 0x000904,
0x21CA86, 0x000007, 0x002010, 0x30043A,
0x00057D, 0x0180C3, 0x08000A, 0x028924,
0x280502, 0x280C02, 0x0A810D, 0x000820,
0x0002F5, 0x010040, 0x220007, 0x0004FD,
0x018042, 0x70000A, 0x030000, 0x007020,
0x07FA06, 0x018040, 0x022B8D, 0x000810,
0x08043A, 0x2CAA06, 0x000007, 0x0002FD,
0x018042, 0x08000A, 0x000904, 0x22C286,
0x000007, 0x020206, 0x000007, 0x000875,
0x0009FD, 0x00010D, 0x234206, 0x000295,
0x000B75, 0x00097D, 0x00000D, 0x000515,
0x010042, 0x18000A, 0x001904, 0x2A0086,
0x0006F5, 0x001020, 0x010040, 0x0004F5,
0x000820, 0x010040, 0x000775, 0x010042,
0x09804A, 0x10000A, 0x001124, 0x000904,
0x23F286, 0x000815, 0x080102, 0x101204,
0x241206, 0x000575, 0x081204, 0x000007,
0x100102, 0x000575, 0x000425, 0x021124,
0x100102, 0x000820, 0x031060, 0x010040,
0x001924, 0x2A0086, 0x00008D, 0x000464,
0x009D04, 0x291086, 0x180102, 0x000575,
0x010042, 0x28040A, 0x00018D, 0x000924,
0x280D02, 0x00000D, 0x000924, 0x281502,
0x10000D, 0x000820, 0x0002F5, 0x010040,
0x200007, 0x001175, 0x0002FD, 0x018042,
0x08000A, 0x000904, 0x24FA86, 0x000007,
0x000100, 0x080B20, 0x130B60, 0x1B0B60,
0x030A60, 0x010040, 0x050042, 0x3D004A,
0x35004A, 0x2D004A, 0x20000A, 0x0006F5,
0x010042, 0x28140A, 0x0004F5, 0x010042,
0x08000A, 0x000315, 0x010D04, 0x260286,
0x004015, 0x000095, 0x010D04, 0x25F086,
0x100022, 0x10002A, 0x261A06, 0x000007,
0x333104, 0x2AA904, 0x000007, 0x032124,
0x280502, 0x284402, 0x001124, 0x400102,
0x000424, 0x000424, 0x003224, 0x00292C,
0x00636C, 0x277386, 0x000007, 0x02B164,
0x000464, 0x000464, 0x00008D, 0x000A64,
0x280D02, 0x10008D, 0x000820, 0x0002F5,
0x010040, 0x220007, 0x00008D, 0x38B904,
0x000007, 0x03296C, 0x30010A, 0x0002F5,
0x010042, 0x08000A, 0x000904, 0x270286,
0x000007, 0x00212C, 0x28050A, 0x00316C,
0x00046C, 0x00046C, 0x28450A, 0x001124,
0x006B64, 0x100102, 0x00008D, 0x01096C,
0x280D0A, 0x10010D, 0x000820, 0x0002F5,
0x010040, 0x220007, 0x004124, 0x000424,
0x000424, 0x003224, 0x300102, 0x032944,
0x27FA86, 0x000007, 0x300002, 0x0004F5,
0x010042, 0x08000A, 0x000315, 0x010D04,
0x284086, 0x003124, 0x000464, 0x300102,
0x0002F5, 0x010042, 0x08000A, 0x000904,
0x284A86, 0x000007, 0x284402, 0x003124,
0x300502, 0x003924, 0x300583, 0x000883,
0x0005F5, 0x010042, 0x28040A, 0x00008D,
0x008124, 0x280D02, 0x00008D, 0x008124,
0x281502, 0x10018D, 0x000820, 0x0002F5,
0x010040, 0x220007, 0x001025, 0x000575,
0x030042, 0x09004A, 0x10000A, 0x0A0904,
0x121104, 0x000007, 0x001020, 0x050860,
0x050040, 0x0006FD, 0x018042, 0x09004A,
0x10000A, 0x0000A5, 0x0A0904, 0x121104,
0x000007, 0x000820, 0x019060, 0x010040,
0x0002F5, 0x010042, 0x08000A, 0x000904,
0x29CA86, 0x000007, 0x244206, 0x000007,
0x000606, 0x000007, 0x0002F5, 0x010042,
0x08000A, 0x000904, 0x2A1A86, 0x000007,
0x000100, 0x080B20, 0x138B60, 0x1B8B60,
0x238B60, 0x2B8B60, 0x338B60, 0x3B8B60,
0x438B60, 0x4B8B60, 0x538B60, 0x5B8B60,
0x638B60, 0x6B8B60, 0x738B60, 0x7B8B60,
0x038F60, 0x0B8F60, 0x138F60, 0x1B8F60,
0x238F60, 0x2B8F60, 0x338F60, 0x3B8F60,
0x438F60, 0x4B8F60, 0x538F60, 0x5B8F60,
0x638F60, 0x6B8F60, 0x738F60, 0x7B8F60,
0x038A60, 0x000606, 0x018040, 0x00008D,
0x000A64, 0x280D02, 0x000A24, 0x00027D,
0x018042, 0x10000A, 0x001224, 0x0003FD,
0x018042, 0x08000A, 0x000904, 0x2C0A86,
0x000007, 0x00018D, 0x000A24, 0x000464,
0x000464, 0x080102, 0x000924, 0x000424,
0x000424, 0x100102, 0x02000D, 0x009144,
0x2C6186, 0x000007, 0x0001FD, 0x018042,
0x08000A, 0x000A44, 0x2C4386, 0x018042,
0x0A000D, 0x000820, 0x0002FD, 0x018040,
0x200007, 0x00027D, 0x001020, 0x000606,
0x018040, 0x0002F5, 0x010042, 0x08000A,
0x000904, 0x2CB286, 0x000007, 0x00037D,
0x018042, 0x08000A, 0x000904, 0x2CE286,
0x000007, 0x000075, 0x002E7D, 0x010042,
0x0B804A, 0x000020, 0x000904, 0x000686,
0x010040, 0x31844A, 0x30048B, 0x000883,
0x00008D, 0x000810, 0x28143A, 0x00008D,
0x000810, 0x280C3A, 0x000675, 0x010042,
0x08000A, 0x003815, 0x010924, 0x280502,
0x0B000D, 0x000820, 0x0002F5, 0x010040,
0x000606, 0x220007, 0x000464, 0x000464,
0x000606, 0x000007, 0x000134, 0x007F8D,
0x00093C, 0x281D12, 0x282512, 0x001F32,
0x0E0007, 0x00010D, 0x00037D, 0x000820,
0x018040, 0x05D2F4, 0x000007, 0x080007,
0x00037D, 0x018042, 0x08000A, 0x000904,
0x2E8A86, 0x000007, 0x000606, 0x000007,
0x000007, 0x000012, 0x100007, 0x320007,
0x600007, 0x460007, 0x100080, 0x48001A,
0x004904, 0x2EF186, 0x000007, 0x001210,
0x58003A, 0x000145, 0x5C5D04, 0x000007,
0x000080, 0x48001A, 0x004904, 0x2F4186,
0x000007, 0x001210, 0x50003A, 0x005904,
0x2F9886, 0x000045, 0x0000C5, 0x7FFFF5,
0x7FFF7D, 0x07D524, 0x004224, 0x500102,
0x200502, 0x000082, 0x40001A, 0x004104,
0x2FC986, 0x000007, 0x003865, 0x40001A,
0x004020, 0x00104D, 0x04C184, 0x31AB86,
0x000040, 0x040007, 0x000165, 0x000145,
0x004020, 0x000040, 0x000765, 0x080080,
0x40001A, 0x004104, 0x305986, 0x000007,
0x001210, 0x40003A, 0x004104, 0x30B286,
0x00004D, 0x0000CD, 0x004810, 0x20043A,
0x000882, 0x40001A, 0x004104, 0x30C186,
0x000007, 0x004820, 0x005904, 0x319886,
0x000040, 0x0007E5, 0x200480, 0x2816A0,
0x3216E0, 0x3A16E0, 0x4216E0, 0x021260,
0x000040, 0x000032, 0x400075, 0x00007D,
0x07D574, 0x200512, 0x000082, 0x40001A,
0x004104, 0x317186, 0x000007, 0x038A06,
0x640007, 0x0000E5, 0x000020, 0x000040,
0x000A65, 0x000020, 0x020040, 0x020040,
0x000040, 0x000165, 0x000042, 0x70000A,
0x007104, 0x323286, 0x000007, 0x060007,
0x019A06, 0x640007, 0x050000, 0x007020,
0x000040, 0x038A06, 0x640007, 0x000007,
0x00306D, 0x028860, 0x029060, 0x08000A,
0x028860, 0x008040, 0x100012, 0x00100D,
0x009184, 0x32D186, 0x000E0D, 0x009184,
0x33E186, 0x000007, 0x300007, 0x001020,
0x003B6D, 0x008040, 0x000080, 0x08001A,
0x000904, 0x32F186, 0x000007, 0x001220,
0x000DED, 0x008040, 0x008042, 0x10000A,
0x40000D, 0x109544, 0x000007, 0x001020,
0x000DED, 0x008040, 0x008042, 0x20040A,
0x000082, 0x08001A, 0x000904, 0x338186,
0x000007, 0x003B6D, 0x008042, 0x08000A,
0x000E15, 0x010984, 0x342B86, 0x600007,
0x08001A, 0x000C15, 0x010984, 0x341386,
0x000020, 0x1A0007, 0x0002ED, 0x008040,
0x620007, 0x00306D, 0x028042, 0x0A804A,
0x000820, 0x0A804A, 0x000606, 0x10804A,
0x000007, 0x282512, 0x001F32, 0x05D2F4,
0x54D104, 0x00735C, 0x000786, 0x000007,
0x0C0007, 0x0A0007, 0x1C0007, 0x003465,
0x020040, 0x004820, 0x025060, 0x40000A,
0x024060, 0x000040, 0x454944, 0x000007,
0x004020, 0x003AE5, 0x000040, 0x0028E5,
0x000042, 0x48000A, 0x004904, 0x39F886,
0x002C65, 0x000042, 0x40000A, 0x0000D5,
0x454104, 0x000007, 0x000655, 0x054504,
0x368286, 0x0001D5, 0x054504, 0x368086,
0x002B65, 0x000042, 0x003AE5, 0x50004A,
0x40000A, 0x45C3D4, 0x000007, 0x454504,
0x000007, 0x0000CD, 0x444944, 0x000007,
0x454504, 0x000007, 0x00014D, 0x554944,
0x000007, 0x045144, 0x367986, 0x002C65,
0x000042, 0x48000A, 0x4CD104, 0x000007,
0x04C144, 0x368386, 0x000007, 0x160007,
0x002CE5, 0x040042, 0x40000A, 0x004020,
0x000040, 0x002965, 0x000042, 0x40000A,
0x004104, 0x36F086, 0x000007, 0x002402,
0x383206, 0x005C02, 0x0025E5, 0x000042,
0x40000A, 0x004274, 0x002AE5, 0x000042,
0x40000A, 0x004274, 0x500112, 0x0029E5,
0x000042, 0x40000A, 0x004234, 0x454104,
0x000007, 0x004020, 0x000040, 0x003EE5,
0x000020, 0x000040, 0x002DE5, 0x400152,
0x50000A, 0x045144, 0x37DA86, 0x0000C5,
0x003EE5, 0x004020, 0x000040, 0x002BE5,
0x000042, 0x40000A, 0x404254, 0x000007,
0x002AE5, 0x004020, 0x000040, 0x500132,
0x040134, 0x005674, 0x0029E5, 0x020042,
0x42000A, 0x000042, 0x50000A, 0x05417C,
0x0028E5, 0x000042, 0x48000A, 0x0000C5,
0x4CC144, 0x38A086, 0x0026E5, 0x0027E5,
0x020042, 0x40004A, 0x50000A, 0x00423C,
0x00567C, 0x0028E5, 0x004820, 0x000040,
0x281D12, 0x282512, 0x001F72, 0x002965,
0x000042, 0x40000A, 0x004104, 0x393A86,
0x0E0007, 0x160007, 0x1E0007, 0x003EE5,
0x000042, 0x40000A, 0x004104, 0x397886,
0x002D65, 0x000042, 0x28340A, 0x003465,
0x020042, 0x42004A, 0x004020, 0x4A004A,
0x50004A, 0x05D2F4, 0x54D104, 0x00735C,
0x39E186, 0x000007, 0x000606, 0x080007,
0x0C0007, 0x080007, 0x0A0007, 0x0001E5,
0x020045, 0x004020, 0x000060, 0x000365,
0x000040, 0x002E65, 0x001A20, 0x0A1A60,
0x000040, 0x003465, 0x020042, 0x42004A,
0x004020, 0x4A004A, 0x000606, 0x50004A,
0x0017FD, 0x018042, 0x08000A, 0x000904,
0x225A86, 0x000007, 0x00107D, 0x018042,
0x0011FD, 0x33804A, 0x19804A, 0x20000A,
0x000095, 0x2A1144, 0x01A144, 0x3B9086,
0x00040D, 0x00B184, 0x3B9186, 0x0018FD,
0x018042, 0x0010FD, 0x09804A, 0x38000A,
0x000095, 0x010924, 0x003A64, 0x3B8186,
0x000007, 0x003904, 0x3B9286, 0x000007,
0x3B9A06, 0x00000D, 0x00008D, 0x000820,
0x00387D, 0x018040, 0x700002, 0x00117D,
0x018042, 0x00197D, 0x29804A, 0x30000A,
0x380002, 0x003124, 0x000424, 0x000424,
0x002A24, 0x280502, 0x00068D, 0x000810,
0x28143A, 0x00750D, 0x00B124, 0x002264,
0x3D0386, 0x284402, 0x000810, 0x280C3A,
0x0B800D, 0x000820, 0x0002FD, 0x018040,
0x200007, 0x00758D, 0x00B124, 0x100102,
0x012144, 0x3E4986, 0x001810, 0x10003A,
0x00387D, 0x018042, 0x08000A, 0x000904,
0x3E4886, 0x030000, 0x3E4A06, 0x0000BD,
0x00008D, 0x023164, 0x000A64, 0x280D02,
0x0B808D, 0x000820, 0x0002FD, 0x018040,
0x200007, 0x00387D, 0x018042, 0x08000A,
0x000904, 0x3E3286, 0x030000, 0x0002FD,
0x018042, 0x08000A, 0x000904, 0x3D8286,
0x000007, 0x002810, 0x28043A, 0x00750D,
0x030924, 0x002264, 0x280D02, 0x02316C,
0x28450A, 0x0B810D, 0x000820, 0x0002FD,
0x018040, 0x200007, 0x00008D, 0x000A24,
0x3E4A06, 0x100102, 0x001810, 0x10003A,
0x0000BD, 0x003810, 0x30043A, 0x00187D,
0x018042, 0x0018FD, 0x09804A, 0x20000A,
0x0000AD, 0x028924, 0x07212C, 0x001010,
0x300583, 0x300D8B, 0x3014BB, 0x301C83,
0x002083, 0x00137D, 0x038042, 0x33844A,
0x33ACCB, 0x33B4CB, 0x33BCCB, 0x33C4CB,
0x33CCCB, 0x33D4CB, 0x305C8B, 0x006083,
0x001E0D, 0x0005FD, 0x018042, 0x20000A,
0x020924, 0x00068D, 0x00A96C, 0x00009D,
0x0002FD, 0x018042, 0x08000A, 0x000904,
0x3F6A86, 0x000007, 0x280502, 0x280D0A,
0x284402, 0x001810, 0x28143A, 0x0C008D,
0x000820, 0x0002FD, 0x018040, 0x220007,
0x003904, 0x225886, 0x001E0D, 0x00057D,
0x018042, 0x20000A, 0x020924, 0x0000A5,
0x0002FD, 0x018042, 0x08000A, 0x000904,
0x402A86, 0x000007, 0x280502, 0x280C02,
0x002010, 0x28143A, 0x0C010D, 0x000820,
0x0002FD, 0x018040, 0x225A06, 0x220007,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000
};
#endif //_HWMCODE_
......@@ -53,7 +53,7 @@ adfs_get_block(struct inode *inode, long block, struct buffer_head *bh, int crea
return 0;
}
static int adfs_writepage(struct file *file, struct page *page)
static int adfs_writepage(struct page *page)
{
return block_write_full_page(page, adfs_get_block);
}
......
......@@ -338,7 +338,7 @@ static int affs_get_block(struct inode *inode, long block, struct buffer_head *b
}
static int affs_writepage(struct file *file, struct page *page)
static int affs_writepage(struct page *page)
{
return block_write_full_page(page,affs_get_block);
}
......
......@@ -135,7 +135,7 @@ static int bfs_get_block(struct inode * inode, long block,
return err;
}
static int bfs_writepage(struct file *file, struct page *page)
static int bfs_writepage(struct page *page)
{
return block_write_full_page(page, bfs_get_block);
}
......
......@@ -1583,9 +1583,11 @@ static void unmap_underlying_metadata(struct buffer_head * bh)
*/
static int __block_write_full_page(struct inode *inode, struct page *page, get_block_t *get_block)
{
int err, i, need_balance_dirty = 0;
int err, i;
unsigned long block;
struct buffer_head *bh, *head;
struct buffer_head *arr[MAX_BUF_PER_PAGE];
int nr = 0;
if (!PageLocked(page))
BUG();
......@@ -1607,7 +1609,6 @@ static int __block_write_full_page(struct inode *inode, struct page *page, get_b
* Leave it to the low-level FS to make all those
* decisions (block #0 may actually be a valid block)
*/
bh->b_end_io = end_buffer_io_sync;
if (!buffer_mapped(bh)) {
err = get_block(inode, block, bh, 1);
if (err)
......@@ -1616,22 +1617,27 @@ static int __block_write_full_page(struct inode *inode, struct page *page, get_b
unmap_underlying_metadata(bh);
}
set_bit(BH_Uptodate, &bh->b_state);
if (!atomic_set_buffer_dirty(bh)) {
buffer_insert_inode_queue(bh, inode);
__mark_dirty(bh);
need_balance_dirty = 1;
}
set_bit(BH_Dirty, &bh->b_state);
bh->b_end_io = end_buffer_io_async;
atomic_inc(&bh->b_count);
arr[nr++] = bh;
bh = bh->b_this_page;
block++;
} while (bh != head);
if (need_balance_dirty)
balance_dirty(bh->b_dev);
if (nr) {
ll_rw_block(WRITE, nr, arr);
} else {
UnlockPage(page);
}
SetPageUptodate(page);
return 0;
out:
if (nr) {
ll_rw_block(WRITE, nr, arr);
} else {
UnlockPage(page);
}
ClearPageUptodate(page);
return err;
}
......@@ -2021,8 +2027,11 @@ int block_write_full_page(struct page *page, get_block_t *get_block)
/* things got complicated... */
offset = inode->i_size & (PAGE_CACHE_SIZE-1);
/* OK, are we completely out? */
if (page->index >= end_index+1 || !offset)
if (page->index >= end_index+1 || !offset) {
UnlockPage(page);
return -EIO;
}
/* Sigh... will have to work, then... */
err = __block_prepare_write(inode, page, 0, offset, get_block);
if (!err) {
......@@ -2031,6 +2040,7 @@ int block_write_full_page(struct page *page, get_block_t *get_block)
__block_commit_write(inode,page,0,offset);
done:
kunmap(page);
UnlockPage(page);
return err;
}
ClearPageUptodate(page);
......
......@@ -650,7 +650,7 @@ struct buffer_head * ext2_bread (struct inode * inode, int block,
return NULL;
}
static int ext2_writepage(struct file *file, struct page *page)
static int ext2_writepage(struct page *page)
{
return block_write_full_page(page,ext2_get_block);
}
......@@ -1208,7 +1208,7 @@ static int ext2_update_inode(struct inode * inode, int do_sync)
raw_inode->i_block[0] = cpu_to_le32(kdev_t_to_nr(inode->i_rdev));
else for (block = 0; block < EXT2_N_BLOCKS; block++)
raw_inode->i_block[block] = inode->u.ext2_i.i_data[block];
mark_buffer_dirty_inode(bh, inode);
mark_buffer_dirty(bh);
if (do_sync) {
ll_rw_block (WRITE, 1, &bh);
wait_on_buffer (bh);
......
......@@ -735,7 +735,7 @@ static int is_exec(char *extension)
return 0;
}
static int fat_writepage(struct file *file, struct page *page)
static int fat_writepage(struct page *page)
{
return block_write_full_page(page,fat_get_block);
}
......
......@@ -220,7 +220,7 @@ int hfs_notify_change_hdr(struct dentry *dentry, struct iattr * attr)
return __hfs_notify_change(dentry, attr, HFS_HDR);
}
static int hfs_writepage(struct file *file, struct page *page)
static int hfs_writepage(struct page *page)
{
return block_write_full_page(page,hfs_get_block);
}
......
......@@ -93,7 +93,7 @@ int hpfs_get_block(struct inode *inode, long iblock, struct buffer_head *bh_resu
return 0;
}
static int hpfs_writepage(struct file *file, struct page *page)
static int hpfs_writepage(struct page *page)
{
return block_write_full_page(page,hpfs_get_block);
}
......
......@@ -396,7 +396,7 @@ struct buffer_head * minix_bread(struct inode * inode, int block, int create)
return NULL;
}
static int minix_writepage(struct file *file, struct page *page)
static int minix_writepage(struct page *page)
{
return block_write_full_page(page,minix_get_block);
}
......
......@@ -250,20 +250,17 @@ nfs_writepage_async(struct file *file, struct inode *inode, struct page *page,
* Write an mmapped page to the server.
*/
int
nfs_writepage(struct file *file, struct page *page)
nfs_writepage(struct page *page)
{
struct inode *inode;
unsigned long end_index;
unsigned offset = PAGE_CACHE_SIZE;
int err;
struct address_space *mapping = page->mapping;
if (!file) {
struct address_space *mapping = page->mapping;
if (!mapping)
BUG();
inode = (struct inode *)mapping->host;
} else
inode = file->f_dentry->d_inode;
if (!mapping)
BUG();
inode = (struct inode *)mapping->host;
if (!inode)
BUG();
end_index = inode->i_size >> PAGE_CACHE_SHIFT;
......@@ -276,21 +273,25 @@ nfs_writepage(struct file *file, struct page *page)
goto do_it;
/* things got complicated... */
offset = inode->i_size & (PAGE_CACHE_SIZE-1);
/* OK, are we completely out? */
err = -EIO;
if (page->index >= end_index+1 || !offset)
return -EIO;
goto out;
do_it:
if (!PageError(page) && NFS_SERVER(inode)->rsize >= PAGE_CACHE_SIZE) {
err = nfs_writepage_async(file, inode, page, 0, offset);
err = nfs_writepage_async(NULL, inode, page, 0, offset);
if (err >= 0)
goto out_ok;
}
err = nfs_writepage_sync(file, inode, page, 0, offset);
if ( err == offset)
goto out_ok;
err = nfs_writepage_sync(NULL, inode, page, 0, offset);
if ( err == offset) {
out_ok:
err = 0;
}
out:
UnlockPage(page);
return err;
out_ok:
return 0;
}
/*
......
......@@ -590,7 +590,7 @@ static struct inode_operations ntfs_dir_inode_operations = {
};
/*
static int ntfs_writepage(struct file *file, struct page *page)
static int ntfs_writepage(struct page *page)
{
return block_write_full_page(page,ntfs_get_block);
}
......
......@@ -415,7 +415,7 @@ static void qnx4_put_super(struct super_block *sb)
return;
}
static int qnx4_writepage(struct file *file, struct page *page)
static int qnx4_writepage(struct page *page)
{
return block_write_full_page(page,qnx4_get_block);
}
......
......@@ -78,7 +78,7 @@ static int ramfs_readpage(struct file *file, struct page * page)
* Writing: just make sure the page gets marked dirty, so that
* the page stealer won't grab it.
*/
static int ramfs_writepage(struct file *file, struct page *page)
static int ramfs_writepage(struct page *page)
{
SetPageDirty(page);
return 0;
......
......@@ -916,7 +916,7 @@ struct buffer_head *sysv_file_bread(struct inode *inode, int block, int create)
return NULL;
}
static int sysv_writepage(struct file *file, struct page *page)
static int sysv_writepage(struct page *page)
{
return block_write_full_page(page,sysv_get_block);
}
......
......@@ -67,7 +67,7 @@ static int udf_adinicb_readpage(struct file *file, struct page * page)
return 0;
}
static int udf_adinicb_writepage(struct file *file, struct page *page)
static int udf_adinicb_writepage(struct page *page)
{
struct inode *inode = (struct inode *)page->mapping->host;
......
......@@ -125,7 +125,7 @@ void udf_discard_prealloc(struct inode * inode)
udf_trunc(inode);
}
static int udf_writepage(struct file *file, struct page *page)
static int udf_writepage(struct page *page)
{
return block_write_full_page(page, udf_get_block);
}
......
......@@ -518,7 +518,7 @@ struct buffer_head * ufs_bread (struct inode * inode, unsigned fragment,
return NULL;
}
static int ufs_writepage(struct file *file, struct page *page)
static int ufs_writepage(struct page *page)
{
return block_write_full_page(page,ufs_getfrag_block);
}
......
......@@ -352,7 +352,7 @@ struct page;
struct address_space;
struct address_space_operations {
int (*writepage)(struct file *, struct page *);
int (*writepage)(struct page *);
int (*readpage)(struct file *, struct page *);
int (*sync_page)(struct page *);
int (*prepare_write)(struct file *, struct page *, unsigned, unsigned);
......
......@@ -204,7 +204,7 @@ typedef struct page {
*/
#define UnlockPage(page) do { \
smp_mb__before_clear_bit(); \
clear_bit(PG_locked, &(page)->flags); \
if (!test_and_clear_bit(PG_locked, &(page)->flags)) BUG(); \
smp_mb__after_clear_bit(); \
if (waitqueue_active(&page->wait)) \
wake_up(&page->wait); \
......
......@@ -192,7 +192,7 @@ extern void nfs_complete_unlink(struct dentry *);
/*
* linux/fs/nfs/write.c
*/
extern int nfs_writepage(struct file *file, struct page *);
extern int nfs_writepage(struct page *);
extern int nfs_flush_incompatible(struct file *file, struct page *page);
extern int nfs_updatepage(struct file *, struct page *, unsigned int, unsigned int);
/*
......
......@@ -1469,15 +1469,15 @@ struct page * filemap_nopage(struct vm_area_struct * area,
* The "mapping" test takes care of somebody having truncated the
* page and thus made this write-page a no-op..
*/
static int filemap_write_page(struct file *file,
struct page * page,
int wait)
static int filemap_write_page(struct page * page, int wait)
{
struct address_space * mapping = page->mapping;
int error = 0;
if (mapping)
error = mapping->a_ops->writepage(file, page);
if (mapping && mapping->a_ops->writepage) {
ClearPageDirty(page);
error = mapping->a_ops->writepage(page);
}
return error;
}
......@@ -1490,11 +1490,8 @@ static int filemap_write_page(struct file *file,
extern void wakeup_bdflush(int);
int filemap_swapout(struct page * page, struct file *file)
{
int error;
error = filemap_write_page(file, page, 0);
wakeup_bdflush(0);
return error;
SetPageDirty(page);
return 0;
}
/* Called with mm->page_table_lock held to protect against other
......@@ -1503,56 +1500,26 @@ int filemap_swapout(struct page * page, struct file *file)
static inline int filemap_sync_pte(pte_t * ptep, struct vm_area_struct *vma,
unsigned long address, unsigned int flags)
{
unsigned long pgoff;
pte_t pte;
struct page *page;
int error;
pte = *ptep;
if (!(flags & MS_INVALIDATE)) {
if (!pte_present(pte))
goto out;
if (!ptep_test_and_clear_dirty(ptep))
goto out;
flush_page_to_ram(pte_page(pte));
flush_cache_page(vma, address);
flush_tlb_page(vma, address);
page = pte_page(pte);
page_cache_get(page);
} else {
if (pte_none(pte))
goto out;
flush_cache_page(vma, address);
pte = ptep_get_and_clear(ptep);
flush_tlb_page(vma, address);
if (!pte_present(pte)) {
spin_unlock(&vma->vm_mm->page_table_lock);
swap_free(pte_to_swp_entry(pte));
spin_lock(&vma->vm_mm->page_table_lock);
goto out;
}
page = pte_page(pte);
if (!pte_dirty(pte) || flags == MS_INVALIDATE) {
page_cache_free(page);
goto out;
}
}
pgoff = (address - vma->vm_start) >> PAGE_CACHE_SHIFT;
pgoff += vma->vm_pgoff;
if (page->index != pgoff) {
printk("weirdness: pgoff=%lu index=%lu address=%lu vm_start=%lu vm_pgoff=%lu\n",
pgoff, page->index, address, vma->vm_start, vma->vm_pgoff);
}
if (!pte_present(pte))
goto out;
if (!ptep_test_and_clear_dirty(ptep))
goto out;
flush_page_to_ram(pte_page(pte));
flush_cache_page(vma, address);
flush_tlb_page(vma, address);
page = pte_page(pte);
page_cache_get(page);
spin_unlock(&vma->vm_mm->page_table_lock);
lock_page(page);
error = filemap_write_page(vma->vm_file, page, 1);
UnlockPage(page);
lock_page(page);
error = filemap_write_page(page, 1);
page_cache_free(page);
spin_lock(&vma->vm_mm->page_table_lock);
......@@ -1650,21 +1617,12 @@ int filemap_sync(struct vm_area_struct * vma, unsigned long address,
return error;
}
/*
* This handles (potentially partial) area unmaps..
*/
static void filemap_unmap(struct vm_area_struct *vma, unsigned long start, size_t len)
{
filemap_sync(vma, start, len, MS_ASYNC);
}
/*
* Shared mappings need to be able to do the right thing at
* close/unmap/sync. They will also use the private file as
* backing-store for swapping..
*/
static struct vm_operations_struct file_shared_mmap = {
unmap: filemap_unmap, /* unmap - we need to sync the pages */
sync: filemap_sync,
nopage: filemap_nopage,
swapout: filemap_swapout,
......
......@@ -17,7 +17,7 @@
#include <asm/pgtable.h>
static int swap_writepage(struct file *file, struct page *page)
static int swap_writepage(struct page *page)
{
rw_swap_page(WRITE, page, 0);
return 0;
......
......@@ -602,7 +602,7 @@ int page_launder(int gfp_mask, int sync)
* last copy..
*/
if (PageDirty(page)) {
int (*writepage)(struct file *, struct page *) = page->mapping->a_ops->writepage;
int (*writepage)(struct page *) = page->mapping->a_ops->writepage;
if (!writepage)
goto page_active;
......@@ -619,12 +619,12 @@ int page_launder(int gfp_mask, int sync)
page_cache_get(page);
spin_unlock(&pagemap_lru_lock);
writepage(NULL, page);
UnlockPage(page);
writepage(page);
page_cache_release(page);
/* And re-start the thing.. */
goto dirty_page_rescan;
spin_lock(&pagemap_lru_lock);
continue;
}
/*
......
......@@ -89,10 +89,8 @@ struct ipt_table_info
unsigned int hook_entry[NF_IP_NUMHOOKS];
unsigned int underflow[NF_IP_NUMHOOKS];
char padding[SMP_ALIGN((NF_IP_NUMHOOKS*2+2)*sizeof(unsigned int))];
/* ipt_entry tables: one per CPU */
char entries[0];
char entries[0] __attribute__((aligned(SMP_CACHE_BYTES)));
};
static LIST_HEAD(ipt_target);
......@@ -101,7 +99,7 @@ static LIST_HEAD(ipt_tables);
#define ADD_COUNTER(c,b,p) do { (c).bcnt += (b); (c).pcnt += (p); } while(0)
#ifdef CONFIG_SMP
#define TABLE_OFFSET(t,p) (SMP_ALIGN((t)->size)*cpu_number_map(p))
#define TABLE_OFFSET(t,p) (SMP_ALIGN((t)->size)*(p))
#else
#define TABLE_OFFSET(t,p) 0
#endif
......@@ -283,7 +281,8 @@ ipt_do_table(struct sk_buff **pskb,
read_lock_bh(&table->lock);
IP_NF_ASSERT(table->valid_hooks & (1 << hook));
table_base = (void *)table->private->entries
+ TABLE_OFFSET(table->private, smp_processor_id());
+ TABLE_OFFSET(table->private,
cpu_number_map(smp_processor_id()));
e = get_entry(table_base, table->private->hook_entry[hook]);
#ifdef CONFIG_NETFILTER_DEBUG
......@@ -860,7 +859,7 @@ translate_table(const char *name,
/* And one copy for every other CPU */
for (i = 1; i < smp_num_cpus; i++) {
memcpy(newinfo->entries + SMP_ALIGN(newinfo->size*i),
memcpy(newinfo->entries + SMP_ALIGN(newinfo->size)*i,
newinfo->entries,
SMP_ALIGN(newinfo->size));
}
......@@ -1359,7 +1358,7 @@ int ipt_register_table(struct ipt_table *table)
int ret;
struct ipt_table_info *newinfo;
static struct ipt_table_info bootstrap
= { 0, 0, { 0 }, { 0 }, { }, { } };
= { 0, 0, { 0 }, { 0 }, { } };
MOD_INC_USE_COUNT;
newinfo = vmalloc(sizeof(struct ipt_table_info)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment