diff options
Diffstat (limited to 'drivers/sbus')
-rw-r--r-- | drivers/sbus/audio/.cvsignore | 2 | ||||
-rw-r--r-- | drivers/sbus/audio/amd7930.c | 270 | ||||
-rw-r--r-- | drivers/sbus/audio/audio.c | 288 | ||||
-rw-r--r-- | drivers/sbus/audio/cs4231.c | 157 | ||||
-rw-r--r-- | drivers/sbus/audio/cs4231.h | 10 | ||||
-rw-r--r-- | drivers/sbus/audio/dbri.c | 15 | ||||
-rw-r--r-- | drivers/sbus/audio/dmy.c | 2 | ||||
-rw-r--r-- | drivers/sbus/char/Config.in | 3 | ||||
-rw-r--r-- | drivers/sbus/char/Makefile | 8 | ||||
-rw-r--r-- | drivers/sbus/char/aurora.c | 2 | ||||
-rw-r--r-- | drivers/sbus/char/bpp.c | 24 | ||||
-rw-r--r-- | drivers/sbus/char/envctrl.c | 1373 | ||||
-rw-r--r-- | drivers/sbus/char/flash.c | 45 | ||||
-rw-r--r-- | drivers/sbus/char/openprom.c | 2 | ||||
-rw-r--r-- | drivers/sbus/char/pcikbd.c | 52 | ||||
-rw-r--r-- | drivers/sbus/char/rtc.c | 27 | ||||
-rw-r--r-- | drivers/sbus/char/sab82532.c | 383 | ||||
-rw-r--r-- | drivers/sbus/char/su.c | 32 | ||||
-rw-r--r-- | drivers/sbus/char/sunkbd.c | 11 | ||||
-rw-r--r-- | drivers/sbus/char/sunmouse.c | 30 | ||||
-rw-r--r-- | drivers/sbus/char/sunserial.c | 25 | ||||
-rw-r--r-- | drivers/sbus/char/uctrl.c | 155 | ||||
-rw-r--r-- | drivers/sbus/char/zs.c | 28 | ||||
-rw-r--r-- | drivers/sbus/dvma.c | 8 | ||||
-rw-r--r-- | drivers/sbus/sbus.c | 19 |
25 files changed, 2375 insertions, 596 deletions
diff --git a/drivers/sbus/audio/.cvsignore b/drivers/sbus/audio/.cvsignore new file mode 100644 index 000000000..857dd22e9 --- /dev/null +++ b/drivers/sbus/audio/.cvsignore @@ -0,0 +1,2 @@ +.depend +.*.flags diff --git a/drivers/sbus/audio/amd7930.c b/drivers/sbus/audio/amd7930.c index 9b71e0a80..e61d74793 100644 --- a/drivers/sbus/audio/amd7930.c +++ b/drivers/sbus/audio/amd7930.c @@ -102,6 +102,11 @@ #include <asm/audioio.h> #include "amd7930.h" +static __u8 bilinear2mulaw(__u8 data); +static __u8 mulaw2bilinear(__u8 data); +static __u8 linear2mulaw(__u16 data); +static __u16 mulaw2linear(__u8 data); + #if defined (AMD79C30_ISDN) || defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x200ff #include "../../isdn/hisax/hisax.h" #include "../../isdn/hisax/isdnl1.h" @@ -146,8 +151,12 @@ struct amd7930_channel { /* Callback routine (and argument) when input is done on */ void (*input_callback)(); void * input_callback_arg; + + int input_format; + int output_format; }; + /* Private information we store for each amd7930 chip. */ struct amd7930_info { struct amd7930_channel D; @@ -173,6 +182,9 @@ struct amd7930_info { int irq; volatile int ints_on; + /* Format type */ + int format_type; + /* Someone to signal when the ISDN LIU state changes */ int liu_state; @@ -489,10 +501,25 @@ static void transceive_Bchannel(struct amd7930_channel *channel, if (channel->output_ptr && channel->output_count > 0) { /* Send the next byte and advance buffer pointer. */ - *io_reg = *(channel->output_ptr); + switch(channel->output_format) { + case AUDIO_ENCODING_ULAW: + case AUDIO_ENCODING_ALAW: + *io_reg = *(channel->output_ptr); + break; + case AUDIO_ENCODING_LINEAR8: + *io_reg = bilinear2mulaw(*(channel->output_ptr)); + break; + case AUDIO_ENCODING_LINEAR: + if (channel->output_count >= 2) { + *io_reg = linear2mulaw(*((__u16*)(channel->output_ptr))); + channel->output_ptr++; + channel->output_count--; + }; + }; channel->output_ptr++; channel->output_count--; + /* Done with the buffer? Notify the midlevel driver. */ if (channel->output_count == 0) { channel->output_ptr = NULL; @@ -510,7 +537,21 @@ static void transceive_Bchannel(struct amd7930_channel *channel, if (channel->input_ptr && channel->input_count > 0) { /* Get the next byte and advance buffer pointer. */ - *(channel->input_ptr) = *io_reg; + switch(channel->input_format) { + case AUDIO_ENCODING_ULAW: + case AUDIO_ENCODING_ALAW: + *(channel->input_ptr) = *io_reg; + break; + case AUDIO_ENCODING_LINEAR8: + *(channel->input_ptr) = mulaw2bilinear(*io_reg); + break; + case AUDIO_ENCODING_LINEAR: + if (channel->input_count >= 2) { + *((__u16*)(channel->input_ptr)) = mulaw2linear(*io_reg); + channel->input_ptr++; + channel->input_count--; + } else *(channel->input_ptr) = 0; + }; channel->input_ptr++; channel->input_count--; @@ -565,6 +606,20 @@ static void amd7930_interrupt(int irq, void *dev_id, struct pt_regs *intr_regs) static int amd7930_open(struct inode * inode, struct file * file, struct sparcaudio_driver *drv) { + struct amd7930_info *info = (struct amd7930_info *)drv->private; + + switch(MINOR(inode->i_rdev) & 0xf) { + case SPARCAUDIO_AUDIO_MINOR: + info->format_type = AUDIO_ENCODING_ULAW; + break; + case SPARCAUDIO_DSP_MINOR: + info->format_type = AUDIO_ENCODING_LINEAR8; + break; + case SPARCAUDIO_DSP16_MINOR: + info->format_type = AUDIO_ENCODING_LINEAR; + break; + }; + MOD_INC_USE_COUNT; return 0; } @@ -637,8 +692,9 @@ static void amd7930_start_output(struct sparcaudio_driver *drv, if (info->Baudio) { info->Baudio->output_ptr = buffer; info->Baudio->output_count = count; - info->Baudio->output_callback = (void *) &sparcaudio_output_done; - info->Baudio->output_callback_arg = (void *) drv; + info->Baudio->output_format = info->format_type; + info->Baudio->output_callback = (void *) &sparcaudio_output_done; + info->Baudio->output_callback_arg = (void *) drv; info->Baudio->xmit_idle_char = 0; } } @@ -667,6 +723,7 @@ static void amd7930_start_input(struct sparcaudio_driver *drv, if (info->Baudio) { info->Baudio->input_ptr = buffer; info->Baudio->input_count = count; + info->Baudio->input_format = info->format_type; info->Baudio->input_callback = (void *) &sparcaudio_input_done; info->Baudio->input_callback_arg = (void *) drv; } @@ -700,7 +757,7 @@ static int amd7930_sunaudio_getdev_sunos(struct sparcaudio_driver *drv) static int amd7930_get_formats(struct sparcaudio_driver *drv) { - return (AFMT_MU_LAW | AFMT_A_LAW); + return (AFMT_MU_LAW | AFMT_A_LAW | AFMT_U8 | AFMT_S16_BE); } static int amd7930_get_output_ports(struct sparcaudio_driver *drv) @@ -850,9 +907,11 @@ static int amd7930_get_input_port(struct sparcaudio_driver *drv) static int amd7930_get_encoding(struct sparcaudio_driver *drv) { struct amd7930_info *info = (struct amd7930_info *)drv->private; - if (info->map.mmr1 & AM_MAP_MMR1_ALAW) + if ((info->map.mmr1 & AM_MAP_MMR1_ALAW) && + (info->format_type == AUDIO_ENCODING_ALAW)) return AUDIO_ENCODING_ALAW; - return AUDIO_ENCODING_ULAW; + + return info->format_type; } static int @@ -861,15 +920,20 @@ amd7930_set_encoding(struct sparcaudio_driver *drv, int value) struct amd7930_info *info = (struct amd7930_info *)drv->private; switch (value) { - case AUDIO_ENCODING_ULAW: - info->map.mmr1 &= ~AM_MAP_MMR1_ALAW; - break; case AUDIO_ENCODING_ALAW: info->map.mmr1 |= AM_MAP_MMR1_ALAW; break; + case AUDIO_ENCODING_LINEAR8: + case AUDIO_ENCODING_LINEAR: + case AUDIO_ENCODING_ULAW: + info->map.mmr1 &= ~AM_MAP_MMR1_ALAW; + break; default: return -EINVAL; - } + }; + + info->format_type = value; + amd7930_update_map(drv); return 0; } @@ -1390,6 +1454,7 @@ static void amd7930_bxmit(int dev, unsigned int chan, Bchan->output_ptr = buffer; Bchan->output_count = count; + Bchan->output_format = AUDIO_ENCODING_ULAW; Bchan->output_callback = (void *) callback; Bchan->output_callback_arg = callback_arg; @@ -1418,6 +1483,7 @@ static void amd7930_brecv(int dev, unsigned int chan, Bchan->input_ptr = buffer; Bchan->input_count = size; + Bchan->input_format = AUDIO_ENCODING_ULAW; Bchan->input_callback = (void *) callback; Bchan->input_callback_arg = callback_arg; @@ -1568,6 +1634,11 @@ static int amd7930_attach(struct sparcaudio_driver *drv, int node, info->rgain = 128; info->pgain = 200; info->mgain = 0; + info->format_type = AUDIO_ENCODING_ULAW; + info->Bb.input_format = AUDIO_ENCODING_ULAW; + info->Bb.output_format = AUDIO_ENCODING_ULAW; + info->Bc.input_format = AUDIO_ENCODING_ULAW; + info->Bc.output_format = AUDIO_ENCODING_ULAW; amd7930_update_map(drv); /* Register the amd7930 with the midlevel audio driver. */ @@ -1608,7 +1679,7 @@ static void amd7930_detach(struct sparcaudio_driver *drv) #ifdef MODULE int init_module(void) #else -__initfunc(int amd7930_init(void)) +int __init amd7930_init(void) #endif { struct linux_sbus *bus; @@ -1651,3 +1722,178 @@ void cleanup_module(void) } } #endif + + +/*************************************************************/ +/* Audio format conversion */ +/*************************************************************/ + +/* Translation tables */ + +static unsigned char ulaw[] = { + 3, 7, 11, 15, 19, 23, 27, 31, + 35, 39, 43, 47, 51, 55, 59, 63, + 66, 68, 70, 72, 74, 76, 78, 80, + 82, 84, 86, 88, 90, 92, 94, 96, + 98, 99, 100, 101, 102, 103, 104, 105, + 106, 107, 108, 109, 110, 111, 112, 113, + 113, 114, 114, 115, 115, 116, 116, 117, + 117, 118, 118, 119, 119, 120, 120, 121, + 121, 121, 122, 122, 122, 122, 123, 123, + 123, 123, 124, 124, 124, 124, 125, 125, + 125, 125, 125, 125, 126, 126, 126, 126, + 126, 126, 126, 126, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 253, 249, 245, 241, 237, 233, 229, 225, + 221, 217, 213, 209, 205, 201, 197, 193, + 190, 188, 186, 184, 182, 180, 178, 176, + 174, 172, 170, 168, 166, 164, 162, 160, + 158, 157, 156, 155, 154, 153, 152, 151, + 150, 149, 148, 147, 146, 145, 144, 143, + 143, 142, 142, 141, 141, 140, 140, 139, + 139, 138, 138, 137, 137, 136, 136, 135, + 135, 135, 134, 134, 134, 134, 133, 133, + 133, 133, 132, 132, 132, 132, 131, 131, + 131, 131, 131, 131, 130, 130, 130, 130, + 130, 130, 130, 130, 129, 129, 129, 129, + 129, 129, 129, 129, 129, 129, 129, 129, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128 +}; + +static __u8 mulaw2bilinear(__u8 data) +{ + return ulaw[data]; +} + + +static unsigned char linear[] = { + 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 2, 0, 0, 0, 3, + 0, 0, 0, 4, 0, 0, 0, 5, + 0, 0, 0, 6, 0, 0, 0, 7, + 0, 0, 0, 8, 0, 0, 0, 9, + 0, 0, 0, 10, 0, 0, 0, 11, + 0, 0, 0, 12, 0, 0, 0, 13, + 0, 0, 0, 14, 0, 0, 0, 15, + 0, 0, 16, 0, 17, 0, 18, 0, + 19, 0, 20, 0, 21, 0, 22, 0, + 23, 0, 24, 0, 25, 0, 26, 0, + 27, 0, 28, 0, 29, 0, 30, 0, + 31, 0, 32, 33, 34, 35, 36, 37, + 38, 39, 40, 41, 42, 43, 44, 45, + 46, 48, 50, 52, 54, 56, 58, 60, + 62, 65, 69, 73, 77, 83, 91, 103, + 255, 231, 219, 211, 205, 201, 197, 193, + 190, 188, 186, 184, 182, 180, 178, 176, + 174, 173, 172, 171, 170, 169, 168, 167, + 166, 165, 164, 163, 162, 161, 160, 0, + 159, 0, 158, 0, 157, 0, 156, 0, + 155, 0, 154, 0, 153, 0, 152, 0, + 151, 0, 150, 0, 149, 0, 148, 0, + 147, 0, 146, 0, 145, 0, 144, 0, + 0, 143, 0, 0, 0, 142, 0, 0, + 0, 141, 0, 0, 0, 140, 0, 0, + 0, 139, 0, 0, 0, 138, 0, 0, + 0, 137, 0, 0, 0, 136, 0, 0, + 0, 135, 0, 0, 0, 134, 0, 0, + 0, 133, 0, 0, 0, 132, 0, 0, + 0, 131, 0, 0, 0, 130, 0, 0, + 0, 129, 0, 0, 0, 128, 0, 0 +}; + +static __u8 bilinear2mulaw(__u8 data) +{ + return linear[data]; +} + +static int exp_lut[256] = { + 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 +}; + +#define BIAS 0x84 +#define CLIP 32635 + +#define SWAP_ENDIAN(x) ((x >> 8) | ((x & 0xff) << 8)) + +static __u8 linear2mulaw(__u16 data) +{ + static int sign, exponent, mantissa; + + /* not really sure, if swapping is ok - comment next line to disable it */ + data = SWAP_ENDIAN(data); + + sign = (data >> 8) & 0x80; + if (sign != 0) data = -data; + + if (data > CLIP) data = CLIP; + data += BIAS; + exponent = exp_lut[(data >> 7) & 0xFF]; + mantissa = (data >> (exponent + 3)) & 0x0F; + + return (~(sign | (exponent << 4) | mantissa)); +} + +static __u16 mulaw2linear(__u8 data) +{ + /* this conversion is not working */ + return data; +} + +#if 0 +#define INOUT(x,y) (((x) << 16) | (y)) +static int convert_audio(int in_format, int out_format, __u8* buffer, int count) +{ + static int i,sign,exponent; + static __u16 data; + + if (in_format == out_format) return count; + + switch(INOUT(in_format, out_format)) { + case INOUT(AUDIO_ENCODING_ULAW, AUDIO_ENCODING_LINEAR8): + for (i = 0;i < count; i++) { + buffer[i] = ulaw[buffer[i]]; + }; + break; + case INOUT(AUDIO_ENCODING_ULAW, AUDIO_ENCODING_LINEAR): + break; + case INOUT(AUDIO_ENCODING_LINEAR, AUDIO_ENCODING_ULAW): + /* buffer is two-byte => convert to first */ + for (i = 0; i < count/2; i++) { + data = ((__u16*)buffer)[i]; + sign = (data >> 8) & 0x80; + if (data > CLIP) data = CLIP; + data += BIAS; + exponent = exp_lut[(data >> 7) & 0xFF]; + buffer[i] = ~(sign | (exponent << 4) | + ((data >> (exponent + 3)) & 0x0F)); + }; + break; + case INOUT(AUDIO_ENCODING_LINEAR8, AUDIO_ENCODING_ULAW): + for (i = 0; i < count; i++) { + buffer[i] = linear[buffer[i]]; + }; + break; + default: + return 0; + }; + + return count; +} +#undef INOUT +#endif + +#undef BIAS +#undef CLIP +#undef SWAP_ENDIAN diff --git a/drivers/sbus/audio/audio.c b/drivers/sbus/audio/audio.c index 112effea6..885abe1a8 100644 --- a/drivers/sbus/audio/audio.c +++ b/drivers/sbus/audio/audio.c @@ -1,12 +1,12 @@ /* * drivers/sbus/audio/audio.c * - * Copyright (C) 1996 Thomas K. Dyas (tdyas@noc.rutgers.edu) - * Copyright (C) 1997,1998 Derrick J. Brashear (shadow@dementia.org) - * Copyright (C) 1997 Brent Baccala (baccala@freesoft.org) + * Copyright 1996 Thomas K. Dyas (tdyas@noc.rutgers.edu) + * Copyright 1997,1998,1999 Derrick J. Brashear (shadow@dementia.org) + * Copyright 1997 Brent Baccala (baccala@freesoft.org) * * Mixer code adapted from code contributed by and - * Copyright (C) 1998 Michael Mraka (michael@fi.muni.cz) + * Copyright 1998 Michael Mraka (michael@fi.muni.cz) * and with fixes from Michael Shuey (shuey@ecn.purdue.edu) * The mixer code cheats; Sparc hardware doesn't generally allow independent * line control, and this fakes it badly. @@ -40,11 +40,17 @@ #undef __AUDIO_DEBUG #define __AUDIO_ERROR #undef __AUDIO_TRACE +#undef __AUDIO_OSSDEBUG #ifdef __AUDIO_DEBUG #define dprintk(x) printk x #else #define dprintk(x) #endif +#ifdef __AUDIO_OSSDEBUG +#define oprintk(x) printk x +#else +#define oprintk(x) +#endif #ifdef __AUDIO_ERROR #define eprintk(x) printk x #else @@ -117,10 +123,12 @@ int register_sparcaudio_driver(struct sparcaudio_driver *drv, int duplex) * TODO: Make number of input/output buffers tunable parameters */ +#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x202ff init_waitqueue_head(&drv->open_wait); init_waitqueue_head(&drv->output_write_wait); init_waitqueue_head(&drv->output_drain_wait); init_waitqueue_head(&drv->input_read_wait); +#endif drv->num_output_buffers = 8; drv->output_buffer_size = (4096 * 2); @@ -269,6 +277,7 @@ void sparcaudio_output_done(struct sparcaudio_driver * drv, int status) * If status & 2, a buffer was claimed for DMA and is still in use. * * The playing_count for non-DMA hardware should never be non-zero. + * Value of status for non-DMA hardware should always be 1. */ if (status & 1) { if (drv->playing_count) @@ -305,8 +314,9 @@ void sparcaudio_output_done(struct sparcaudio_driver * drv, int status) /* If we got back a buffer, see if anyone wants to write to it */ if ((status & 1) || ((drv->output_count + drv->playing_count) - < drv->num_output_buffers)) + < drv->num_output_buffers)) { wake_up_interruptible(&drv->output_write_wait); + } /* If the output queue is empty, shut down the driver. */ if ((drv->output_count < 1) && (drv->playing_count < 1)) { @@ -638,8 +648,11 @@ static int sparcaudio_mixer_ioctl(struct inode * inode, struct file * file, { struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >> SPARCAUDIO_DEVICE_SHIFT)]; - unsigned long i = 0, j = 0; - unsigned int k; + unsigned long i = 0, j = 0, l = 0, m = 0; + unsigned int k = 0; + + if (_SIOC_DIR(cmd) & _SIOC_WRITE) + drv->mixer_modify_counter++; if(cmd == SOUND_MIXER_INFO) { audio_device_t tmp; @@ -651,9 +664,7 @@ static int sparcaudio_mixer_ioctl(struct inode * inode, struct file * file, memset(&info, 0, sizeof(info)); strncpy(info.id, tmp.name, sizeof(info.id)); strncpy(info.name, "Sparc Audio", sizeof(info.name)); - - /* XXX do this right... */ - info.modify_counter = 0; + info.modify_counter = drv->mixer_modify_counter; if(copy_to_user((char *)arg, &info, sizeof(info))) retval = -EFAULT; @@ -665,74 +676,130 @@ static int sparcaudio_mixer_ioctl(struct inode * inode, struct file * file, switch (cmd) { case SOUND_MIXER_WRITE_RECLEV: - case SOUND_MIXER_WRITE_MIC: - case SOUND_MIXER_WRITE_CD: - case SOUND_MIXER_WRITE_LINE: - case SOUND_MIXER_WRITE_IMIX: - if(get_user(k, arg)) + if(COPY_IN(arg, k)) return -EFAULT; - tprintk(("setting input volume (0x%x)", k)); + iretry: + oprintk(("setting input volume (0x%x)", k)); if (drv->ops->get_input_channels) j = drv->ops->get_input_channels(drv); - if (j == 1) { - i = s_to_m(k); - tprintk((" for mono to %d\n", i)); - if (drv->ops->set_input_volume) - drv->ops->set_input_volume(drv, i); - if (drv->ops->get_input_volume) - i = drv->ops->get_input_volume(drv); - i = m_to_s(i); - } else { - i = s_to_g(k); - j = s_to_b(k); - tprintk((" for stereo to to %d (bal %d)\n", i, j)); - if (drv->ops->set_input_volume) - drv->ops->set_input_volume(drv, i); - if (drv->ops->get_input_volume) - i = drv->ops->get_input_volume(drv); - if (drv->ops->set_input_balance) - drv->ops->set_input_balance(drv, j); - if (drv->ops->get_input_balance) - j = drv->ops->get_input_balance(drv); - i = b_to_s(i,j); - } + if (drv->ops->get_input_volume) + l = drv->ops->get_input_volume(drv); + if (drv->ops->get_input_balance) + m = drv->ops->get_input_balance(drv); + i = OSS_TO_GAIN(k); + j = OSS_TO_BAL(k); + oprintk((" for stereo to to %d (bal %d):", i, j)); + if (drv->ops->set_input_volume) + drv->ops->set_input_volume(drv, i); + if (drv->ops->set_input_balance) + drv->ops->set_input_balance(drv, j); + case SOUND_MIXER_READ_RECLEV: + if (drv->ops->get_input_volume) + i = drv->ops->get_input_volume(drv); + if (drv->ops->get_input_balance) + j = drv->ops->get_input_balance(drv); + oprintk((" got (0x%x)\n", BAL_TO_OSS(i,j))); + i = BAL_TO_OSS(i,j); + /* Try to be reasonable about volume changes */ + if ((cmd == SOUND_MIXER_WRITE_RECLEV) && (i != k) && + (i == BAL_TO_OSS(l,m))) + { + k += (OSS_LEFT(k) > OSS_LEFT(i)) ? 256 : -256; + k += (OSS_RIGHT(k) > OSS_RIGHT(i)) ? 1 : -1; + oprintk((" try 0x%x\n", k)); + goto iretry; + } return COPY_OUT(arg, i); - case SOUND_MIXER_WRITE_PCM: case SOUND_MIXER_WRITE_VOLUME: - case SOUND_MIXER_WRITE_SPEAKER: - if(get_user(k, arg)) + if(COPY_IN(arg, k)) + return -EFAULT; + if (drv->ops->get_output_muted && drv->ops->set_output_muted) { + i = drv->ops->get_output_muted(drv); + if ((k == 0) || ((i == 0) && (OSS_LEFT(k) < 100))) + drv->ops->set_output_muted(drv, 1); + else + drv->ops->set_output_muted(drv, 0); + } + case SOUND_MIXER_READ_VOLUME: + if (drv->ops->get_output_muted) + i = drv->ops->get_output_muted(drv); + k = 0x6464 * (1 - i); + return COPY_OUT(arg, k); + case SOUND_MIXER_WRITE_PCM: + if(COPY_IN(arg, k)) return -EFAULT; - tprintk(("setting output volume (0x%x)", k)); + oretry: + oprintk(("setting output volume (0x%x)\n", k)); if (drv->ops->get_output_channels) j = drv->ops->get_output_channels(drv); - if (j == 1) { - i = s_to_m(k); - tprintk((" for mono to %d\n", i)); - if (drv->ops->set_output_volume) - drv->ops->set_output_volume(drv, i); - if (drv->ops->get_output_volume) - i = drv->ops->get_output_volume(drv); - i = m_to_s(i); - } else { - i = s_to_g(k); - j = s_to_b(k); - tprintk((" for stereo to to %d (bal %d)\n", i, j)); - if (drv->ops->set_output_volume) - drv->ops->set_output_volume(drv, i); - if (drv->ops->get_output_volume) - i = drv->ops->get_output_volume(drv); - if (drv->ops->set_output_balance) - drv->ops->set_output_balance(drv, j); - if (drv->ops->get_output_balance) - j = drv->ops->get_output_balance(drv); - i = b_to_s(i,j); - } + if (drv->ops->get_output_volume) + l = drv->ops->get_output_volume(drv); + if (drv->ops->get_output_balance) + m = drv->ops->get_output_balance(drv); + oprintk((" started as (0x%x)\n", BAL_TO_OSS(l,m))); + i = OSS_TO_GAIN(k); + j = OSS_TO_BAL(k); + oprintk((" for stereo to %d (bal %d)\n", i, j)); + if (drv->ops->set_output_volume) + drv->ops->set_output_volume(drv, i); + if (drv->ops->set_output_balance) + drv->ops->set_output_balance(drv, j); + case SOUND_MIXER_READ_PCM: + if (drv->ops->get_output_volume) + i = drv->ops->get_output_volume(drv); + if (drv->ops->get_output_balance) + j = drv->ops->get_output_balance(drv); + oprintk((" got 0x%x\n", BAL_TO_OSS(i,j))); + i = BAL_TO_OSS(i,j); + /* Try to be reasonable about volume changes */ + if ((cmd == SOUND_MIXER_WRITE_PCM) && (i != k) && + (i == BAL_TO_OSS(l,m))) + { + k += (OSS_LEFT(k) > OSS_LEFT(i)) ? 256 : -256; + k += (OSS_RIGHT(k) > OSS_RIGHT(i)) ? 1 : -1; + oprintk((" try 0x%x\n", k)); + goto oretry; + } return COPY_OUT(arg, i); + case SOUND_MIXER_READ_SPEAKER: + k = OSS_PORT_AUDIO(drv, AUDIO_SPEAKER); + return COPY_OUT(arg, k); + case SOUND_MIXER_READ_MIC: + k = OSS_IPORT_AUDIO(drv, AUDIO_MICROPHONE); + return COPY_OUT(arg, k); + case SOUND_MIXER_READ_CD: + k = OSS_IPORT_AUDIO(drv, AUDIO_CD); + return COPY_OUT(arg, k); + case SOUND_MIXER_READ_LINE: + k = OSS_IPORT_AUDIO(drv, AUDIO_LINE_IN); + return COPY_OUT(arg, k); + case SOUND_MIXER_READ_LINE1: + k = OSS_PORT_AUDIO(drv, AUDIO_HEADPHONE); + return COPY_OUT(arg, k); + case SOUND_MIXER_READ_LINE2: + k = OSS_PORT_AUDIO(drv, AUDIO_LINE_OUT); + return COPY_OUT(arg, k); + + case SOUND_MIXER_WRITE_MIC: + case SOUND_MIXER_WRITE_CD: + case SOUND_MIXER_WRITE_LINE: + case SOUND_MIXER_WRITE_LINE1: + case SOUND_MIXER_WRITE_LINE2: + case SOUND_MIXER_WRITE_SPEAKER: + if(COPY_IN(arg, k)) + return -EFAULT; + OSS_TWIDDLE_IPORT(drv, cmd, SOUND_MIXER_WRITE_LINE, AUDIO_LINE_IN, k); + OSS_TWIDDLE_IPORT(drv, cmd, SOUND_MIXER_WRITE_MIC, AUDIO_MICROPHONE, k); + OSS_TWIDDLE_IPORT(drv, cmd, SOUND_MIXER_WRITE_CD, AUDIO_CD, k); + + OSS_TWIDDLE_PORT(drv, cmd, SOUND_MIXER_WRITE_SPEAKER, AUDIO_SPEAKER, k); + OSS_TWIDDLE_PORT(drv, cmd, SOUND_MIXER_WRITE_LINE1, AUDIO_HEADPHONE, k); + OSS_TWIDDLE_PORT(drv, cmd, SOUND_MIXER_WRITE_LINE2, AUDIO_LINE_OUT, k); + return COPY_OUT(arg, k); case SOUND_MIXER_READ_RECSRC: if (drv->ops->get_input_port) i = drv->ops->get_input_port(drv); /* only one should ever be selected */ - if (i & AUDIO_ANALOG_LOOPBACK) j = SOUND_MASK_IMIX; /* ? */ if (i & AUDIO_CD) j = SOUND_MASK_CD; if (i & AUDIO_LINE_IN) j = SOUND_MASK_LINE; if (i & AUDIO_MICROPHONE) j = SOUND_MASK_MIC; @@ -741,14 +808,13 @@ static int sparcaudio_mixer_ioctl(struct inode * inode, struct file * file, case SOUND_MIXER_WRITE_RECSRC: if (!drv->ops->set_input_port) return -EINVAL; - if(get_user(k, arg)) + if(COPY_IN(arg, k)) return -EFAULT; /* only one should ever be selected */ - if (k & SOUND_MASK_IMIX) j = AUDIO_ANALOG_LOOPBACK; if (k & SOUND_MASK_CD) j = AUDIO_CD; if (k & SOUND_MASK_LINE) j = AUDIO_LINE_IN; if (k & SOUND_MASK_MIC) j = AUDIO_MICROPHONE; - tprintk(("setting inport to %d\n", j)); + oprintk(("setting inport to %d\n", j)); i = drv->ops->set_input_port(drv, j); return COPY_OUT(arg, i); @@ -759,7 +825,6 @@ static int sparcaudio_mixer_ioctl(struct inode * inode, struct file * file, if (i & AUDIO_MICROPHONE) j |= SOUND_MASK_MIC; if (i & AUDIO_LINE_IN) j |= SOUND_MASK_LINE; if (i & AUDIO_CD) j |= SOUND_MASK_CD; - if (i & AUDIO_ANALOG_LOOPBACK) j |= SOUND_MASK_IMIX; /* ? */ return COPY_OUT(arg, j); case SOUND_MIXER_READ_CAPS: /* mixer capabilities */ @@ -767,62 +832,27 @@ static int sparcaudio_mixer_ioctl(struct inode * inode, struct file * file, return COPY_OUT(arg, i); case SOUND_MIXER_READ_DEVMASK: /* all supported devices */ - case SOUND_MIXER_READ_STEREODEVS: /* what supports stereo */ if (drv->ops->get_input_ports) i = drv->ops->get_input_ports(drv); /* what do we support? */ if (i & AUDIO_MICROPHONE) j |= SOUND_MASK_MIC; if (i & AUDIO_LINE_IN) j |= SOUND_MASK_LINE; if (i & AUDIO_CD) j |= SOUND_MASK_CD; - if (i & AUDIO_ANALOG_LOOPBACK) j |= SOUND_MASK_IMIX; /* ? */ if (drv->ops->get_output_ports) i = drv->ops->get_output_ports(drv); if (i & AUDIO_SPEAKER) j |= SOUND_MASK_SPEAKER; - if (i & AUDIO_HEADPHONE) j |= SOUND_MASK_LINE; /* ? */ - if (i & AUDIO_LINE_OUT) j |= SOUND_MASK_LINE; - + if (i & AUDIO_HEADPHONE) j |= SOUND_MASK_LINE1; + if (i & AUDIO_LINE_OUT) j |= SOUND_MASK_LINE2; + j |= SOUND_MASK_VOLUME; - + + case SOUND_MIXER_READ_STEREODEVS: /* what supports stereo */ + j |= SOUND_MASK_PCM|SOUND_MASK_RECLEV; + if (cmd == SOUND_MIXER_READ_STEREODEVS) j &= ~(MONO_DEVICES); return COPY_OUT(arg, j); - case SOUND_MIXER_READ_PCM: - case SOUND_MIXER_READ_SPEAKER: - case SOUND_MIXER_READ_VOLUME: - if (drv->ops->get_output_channels) - j = drv->ops->get_output_channels(drv); - if (j == 1) { - if (drv->ops->get_output_volume) - i = drv->ops->get_output_volume(drv); - i = m_to_s(i); - } else { - if (drv->ops->get_output_volume) - i = drv->ops->get_output_volume(drv); - if (drv->ops->get_output_balance) - j = drv->ops->get_output_balance(drv); - i = b_to_s(i,j); - } - return COPY_OUT(arg, i); - case SOUND_MIXER_READ_RECLEV: - case SOUND_MIXER_READ_MIC: - case SOUND_MIXER_READ_CD: - case SOUND_MIXER_READ_LINE: - case SOUND_MIXER_READ_IMIX: - if (drv->ops->get_input_channels) - j = drv->ops->get_input_channels(drv); - if (j == 1) { - if (drv->ops->get_input_volume) - i = drv->ops->get_input_volume(drv); - i = m_to_s(i); - } else { - if (drv->ops->get_input_volume) - i = drv->ops->get_input_volume(drv); - if (drv->ops->get_input_balance) - j = drv->ops->get_input_balance(drv); - i = b_to_s(i,j); - } - return COPY_OUT(arg, i); default: return -EINVAL; } @@ -881,6 +911,10 @@ static int sparcaudio_ioctl(struct inode * inode, struct file * file, case SPARCAUDIO_DSP_MINOR: case SPARCAUDIO_AUDIO_MINOR: case SPARCAUDIO_AUDIOCTL_MINOR: + /* According to the OSS prog int, you can mixer ioctl /dev/dsp */ + if (_IOC_TYPE(cmd) == 'M') + return sparcaudio_mixer_ioctl(inode, + file, cmd, (unsigned int *)arg); switch (cmd) { case I_GETSIG: case I_GETSIG_SOLARIS: @@ -1997,6 +2031,36 @@ static int sparcaudio_open(struct inode * inode, struct file * file) return -ENXIO; } + /* From the dbri driver: + * SunOS 5.5.1 audio(7I) man page says: + * "Upon the initial open() of the audio device, the driver + * will reset the data format of the device to the default + * state of 8-bit, 8KHz, mono u-law data." + * + * Of course, we only do this for /dev/audio, and assume + * OSS semantics on /dev/dsp + */ + + if ((minor & 0xf) == SPARCAUDIO_AUDIO_MINOR) { + if (file->f_mode & FMODE_WRITE) { + if (drv->ops->set_output_channels) + drv->ops->set_output_channels(drv, 1); + if (drv->ops->set_output_encoding) + drv->ops->set_output_encoding(drv, AUDIO_ENCODING_ULAW); + if (drv->ops->set_output_rate) + drv->ops->set_output_rate(drv, 8000); + } + + if (file->f_mode & FMODE_READ) { + if (drv->ops->set_input_channels) + drv->ops->set_input_channels(drv, 1); + if (drv->ops->set_input_encoding) + drv->ops->set_input_encoding(drv, AUDIO_ENCODING_ULAW); + if (drv->ops->set_input_rate) + drv->ops->set_input_rate(drv, 8000); + } + } + MOD_INC_USE_COUNT; /* Success! */ @@ -2098,7 +2162,7 @@ EXPORT_SYMBOL(sparcaudio_input_done); #ifdef MODULE int init_module(void) #else -__initfunc(int sparcaudio_init(void)) +int __init sparcaudio_init(void) #endif { #if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x20100 diff --git a/drivers/sbus/audio/cs4231.c b/drivers/sbus/audio/cs4231.c index 61eca1336..7de793c57 100644 --- a/drivers/sbus/audio/cs4231.c +++ b/drivers/sbus/audio/cs4231.c @@ -1,7 +1,9 @@ /* * drivers/sbus/audio/cs4231.c * - * Copyright 1996, 1997, 1998 Derrick J Brashear (shadow@andrew.cmu.edu) + * Copyright 1996, 1997, 1998, 1999 Derrick J Brashear (shadow@andrew.cmu.edu) + * The 4231/ebus support was written by David Miller, who didn't bother + * crediting himself here, so I will. * * Based on the AMD7930 driver: * Copyright 1996 Thomas K. Dyas (tdyas@noc.rutgers.edu) @@ -11,7 +13,7 @@ * * This was culled from the Crystal docs on the 4231a, and the addendum they * faxed me on the 4231. - * The APC DMA controller support unfortunately is not documented. Thanks, Sun + * The APC DMA controller support unfortunately is not documented. Thanks, Sun. */ #include <linux/config.h> @@ -36,6 +38,7 @@ #if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x200ff && defined(CONFIG_PCI) #define EB4231_SUPPORT #include <asm/ebus.h> +#include <asm/pbm.h> #endif #include <asm/audioio.h> @@ -69,15 +72,17 @@ static int cs4231_record_gain(struct sparcaudio_driver *drv, int value, static int cs4231_play_gain(struct sparcaudio_driver *drv, int value, unsigned char balance); static void cs4231_ready(struct sparcaudio_driver *drv); -static void cs4231_playintr(struct sparcaudio_driver *drv); +static void cs4231_playintr(struct sparcaudio_driver *drv, int); static int cs4231_recintr(struct sparcaudio_driver *drv); static int cs4231_output_muted(struct sparcaudio_driver *drv, int value); static void cs4231_pollinput(struct sparcaudio_driver *drv); -static void eb4231_pollinput(struct sparcaudio_driver *drv); static int cs4231_length_to_samplecount(struct audio_prinfo *thisdir, unsigned int length); static void cs4231_getsamplecount(struct sparcaudio_driver *drv, unsigned int length, unsigned int value); +#ifdef EB4231_SUPPORT +static void eb4231_pollinput(struct sparcaudio_driver *drv); +#endif #define CHIP_READY udelay(100); cs4231_ready(drv); udelay(1000); @@ -416,8 +421,8 @@ cs4231_set_input_channels(struct sparcaudio_driver *drv, int value) int tmp_bits; tprintk(("input channels %d\n", value)); - cs4231_chip->regs->iar = IAR_AUTOCAL_BEGIN | 0x1c; - tmp_bits = cs4231_chip->regs->idr; + CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), (IAR_AUTOCAL_BEGIN | 0x1c)); + tmp_bits = CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); switch (value) { case 1: CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), CS4231_MONO_ON(tmp_bits)); @@ -1228,11 +1233,20 @@ static void cs4231_release(struct inode * inode, struct file * file, struct spar MOD_DEC_USE_COUNT; } -static void cs4231_playintr(struct sparcaudio_driver *drv) +static void cs4231_playintr(struct sparcaudio_driver *drv, int push) { struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; int status = 0; + if (!push) { + if (!cs4231_chip->perchip_info.play.active) { + cs4231_chip->regs->dmapnva = cs4231_chip->output_next_dma_handle; + cs4231_chip->regs->dmapnc = cs4231_chip->output_next_dma_size; + } + sparcaudio_output_done(drv, 0); + return; + } + if (cs4231_chip->playlen == 0 && cs4231_chip->output_size > 0) cs4231_chip->playlen = cs4231_chip->output_size; @@ -1421,7 +1435,7 @@ static int eb4231_recintr(struct sparcaudio_driver *drv) status += 2; } - sparcaudio_input_done(drv, 1); + sparcaudio_input_done(drv, status); return 1; } @@ -1489,21 +1503,20 @@ static void cs4231_start_output(struct sparcaudio_driver *drv, __u8 * buffer, cs4231_chip->regs->dmacsr &= ~APC_XINT_PLAY; cs4231_chip->regs->dmacsr &= ~APC_PPAUSE; - cs4231_playintr(drv); + cs4231_playintr(drv, cs4231_chip->regs->dmapnva == 0 ? 1 : 0); cs4231_chip->regs->dmacsr |= APC_PLAY_SETUP; cs4231_enable_play(drv); cs4231_ready(drv); - } else - cs4231_playintr(drv); + } } #ifdef EB4231_SUPPORT static void eb4231_stop_output(struct sparcaudio_driver *drv) { struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - int dcsr; + unsigned int dcsr; dprintk(("eb4231_stop_output: dcsr 0x%x dacr 0x%x dbcr %d\n", readl(&cs4231_chip->eb2p->dcsr), @@ -1635,6 +1648,68 @@ static void cs4231_stop_input(struct sparcaudio_driver *drv) cs4231_pollinput(drv); } +#ifdef EB4231_SUPPORT +static void eb4231_start_input(struct sparcaudio_driver *drv, __u8 * buffer, + unsigned long count) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + unsigned int dcsr; + + cs4231_chip->input_ptr = buffer; + cs4231_chip->input_size = count; + + if (cs4231_chip->perchip_info.record.active || + (cs4231_chip->perchip_info.record.pause)) + return; + + cs4231_ready(drv); + + cs4231_chip->perchip_info.record.active = 1; + cs4231_chip->recording_count = 0; + + dcsr = readl(&cs4231_chip->eb2c->dcsr); + if (!(dcsr & EBUS_DCSR_EN_DMA)) { + writel(EBUS_DCSR_RESET, &(cs4231_chip->eb2c->dcsr)); + writel(EBUS_DCSR_BURST_SZ_16, &(cs4231_chip->eb2c->dcsr)); + + eb4231_recintr(drv); + + writel(EBUS_DCSR_BURST_SZ_16 | + (EBUS_DCSR_EN_DMA | EBUS_DCSR_INT_EN | EBUS_DCSR_EN_CNT | EBUS_DCSR_EN_NEXT), + &(cs4231_chip->eb2c->dcsr)); + + cs4231_enable_rec(drv); + cs4231_ready(drv); + } else + eb4231_recintr(drv); +} + +static void eb4231_stop_input(struct sparcaudio_driver *drv) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + unsigned int dcsr; + + cs4231_chip->perchip_info.record.active = 0; + + cs4231_chip->input_ptr = NULL; + cs4231_chip->input_size = 0; + if (cs4231_chip->input_dma_handle) { + cs4231_chip->input_dma_handle = 0; + cs4231_chip->input_dma_size = 0; + } + if (cs4231_chip->input_next_dma_handle) { + cs4231_chip->input_next_dma_handle = 0; + cs4231_chip->input_next_dma_size = 0; + } + + dcsr = readl(&(cs4231_chip->eb2c->dcsr)); + if (dcsr & EBUS_DCSR_EN_DMA) + writel(dcsr & ~EBUS_DCSR_EN_DMA, &(cs4231_chip->eb2c->dcsr)); + + cs4231_disable_rec(drv); +} +#endif + static int cs4231_set_output_pause(struct sparcaudio_driver *drv, int value) { struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; @@ -1763,13 +1838,25 @@ void eb4231_cinterrupt(int irq, void *dev_id, struct pt_regs *regs) struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; int dummy; - /* Read status. */ - dummy = readl(&cs4231_chip->eb2c->dcsr); + /* Clear the interrupt. */ + dummy = readl(&(cs4231_chip->eb2c->dcsr)); + writel(dummy, &(cs4231_chip->eb2c->dcsr)); + + if ((dummy & EBUS_DCSR_TC) != 0 + /*&& (dummy & EBUS_DCSR_A_LOADED) != 0*/) { + cs4231_chip->perchip_info.record.samples += + cs4231_length_to_samplecount(&(cs4231_chip->perchip_info.record), + cs4231_chip->reclen); + eb4231_recintr(drv); + } - cs4231_chip->perchip_info.record.samples += - cs4231_length_to_samplecount(&(cs4231_chip->perchip_info.record), - cs4231_chip->reclen); - eb4231_recintr(drv); + if ((dummy & EBUS_DCSR_A_LOADED) == 0) { + cs4231_chip->perchip_info.record.active = 0; + eb4231_recintr(drv); +#if 1 + eb4231_getsamplecount(drv, cs4231_chip->reclen, 1); +#endif + } } /* ebus audio play interrupt handler. */ @@ -1827,7 +1914,8 @@ void cs4231_interrupt(int irq, void *dev_id, struct pt_regs *regs) cs4231_chip->perchip_info.play.samples += cs4231_length_to_samplecount(&(cs4231_chip->perchip_info.play), cs4231_chip->playlen); - cs4231_playintr(drv); + if (!(dummy & APC_XINT_EMPT)) + cs4231_playintr(drv, 1); } /* Any other conditions we need worry about? */ } @@ -1859,7 +1947,7 @@ void cs4231_interrupt(int irq, void *dev_id, struct pt_regs *regs) cs4231_chip->perchip_info.play.error = 1; } cs4231_chip->perchip_info.play.active = 0; - cs4231_playintr(drv); + cs4231_playintr(drv, 0); cs4231_getsamplecount(drv, cs4231_chip->playlen, 0); } @@ -1937,8 +2025,8 @@ static struct sparcaudio_operations eb4231_ops = { cs4231_ioctl, eb4231_start_output, eb4231_stop_output, - cs4231_start_input, - cs4231_stop_input, + eb4231_start_input, + eb4231_stop_input, cs4231_audio_getdev, cs4231_set_output_volume, cs4231_get_output_volume, @@ -2137,16 +2225,9 @@ static int eb4231_attach(struct sparcaudio_driver *drv, nregs = len / sizeof(regs[0]); - cs4231_chip->regs = (struct cs4231_regs *)edev->base_address[0]; - cs4231_chip->eb2p = (struct linux_ebus_dma *)edev->base_address[1]; - cs4231_chip->eb2c = (struct linux_ebus_dma *)edev->base_address[2]; - - request_region((unsigned long)cs4231_chip->regs, - sizeof(struct cs4231_regs), "cs4231 regs"); - request_region((unsigned long)cs4231_chip->eb2c, - sizeof(struct linux_ebus_dma), "4231 capture DMA"); - request_region((unsigned long)cs4231_chip->eb2p, - sizeof(struct linux_ebus_dma), "4231 playback DMA"); + cs4231_chip->regs = (struct cs4231_regs *)edev->resource[0].start; + cs4231_chip->eb2p = (struct linux_ebus_dma *)edev->resource[1].start; + cs4231_chip->eb2c = (struct linux_ebus_dma *)edev->resource[2].start; cs4231_chip->status |= CS_STATUS_IS_EBUS; @@ -2176,13 +2257,6 @@ static int eb4231_attach(struct sparcaudio_driver *drv, free_irq(cs4231_chip->irq, drv); disable_irq(cs4231_chip->irq2); free_irq(cs4231_chip->irq2, drv); - - release_region((unsigned long)cs4231_chip->regs, - sizeof(struct cs4231_regs)); - release_region((unsigned long)cs4231_chip->eb2c, - sizeof(struct linux_ebus_dma)); - release_region((unsigned long)cs4231_chip->eb2p, - sizeof(struct linux_ebus_dma)); kfree(drv->private); return -EIO; } @@ -2216,7 +2290,7 @@ static int eb4231_attach(struct sparcaudio_driver *drv, #ifdef MODULE int init_module(void) #else -__initfunc(int cs4231_init(void)) +int __init cs4231_init(void) #endif { struct linux_sbus *sbus; @@ -2275,9 +2349,6 @@ static void cs4231_detach(struct sparcaudio_driver *drv) #ifdef EB4231_SUPPORT disable_irq(cs4231_chip->irq2); free_irq(cs4231_chip->irq2, drv); - release_region((unsigned long)cs4231_chip->regs, sizeof(struct cs4231_regs)); - release_region((unsigned long)cs4231_chip->eb2c, sizeof(struct linux_ebus_dma)); - release_region((unsigned long)cs4231_chip->eb2p, sizeof(struct linux_ebus_dma)); #endif } kfree(drv->private); diff --git a/drivers/sbus/audio/cs4231.h b/drivers/sbus/audio/cs4231.h index 892ed7e88..45702e86a 100644 --- a/drivers/sbus/audio/cs4231.h +++ b/drivers/sbus/audio/cs4231.h @@ -255,19 +255,19 @@ struct cs4231_chip { #define APC_XINT_PLAY 0x40000 /* Playback ext intr */ #define APC_XINT_CAPT 0x20000 /* Capture ext intr */ #define APC_XINT_GENL 0x10000 /* Error ext intr */ -#define APC_XINT_EMPT 0x8000 /* Pipe empty interrupt */ -#define APC_XINT_PEMP 0x4000 /* Play pipe empty */ +#define APC_XINT_EMPT 0x8000 /* Pipe empty interrupt (0 write to pva) */ +#define APC_XINT_PEMP 0x4000 /* Play pipe empty (pva and pnva not set) */ #define APC_XINT_PNVA 0x2000 /* Playback NVA dirty */ #define APC_XINT_PENA 0x1000 /* play pipe empty Int enable */ #define APC_XINT_COVF 0x800 /* Cap data dropped on floor */ #define APC_XINT_CNVA 0x400 /* Capture NVA dirty */ -#define APC_XINT_CEMP 0x200 /* Capture pipe empty interrupt */ +#define APC_XINT_CEMP 0x200 /* Capture pipe empty (cva and cnva not set) */ #define APC_XINT_CENA 0x100 /* Cap. pipe empty int enable */ #define APC_PPAUSE 0x80 /* Pause the play DMA */ #define APC_CPAUSE 0x40 /* Pause the capture DMA */ #define APC_CDC_RESET 0x20 /* CODEC RESET */ -#define APC_PDMA_READY 0x08 /* Play DMA Go */ -#define APC_CDMA_READY 0x04 /* Capture DMA Go */ +#define APC_PDMA_READY 0x08 /* Play DMA Go */ +#define APC_CDMA_READY 0x04 /* Capture DMA Go */ #define APC_CHIP_RESET 0x01 /* Reset the chip */ #define APC_INIT_SETUP (APC_CDMA_READY | APC_PDMA_READY | APC_XINT_ENA | APC_XINT_PLAY | APC_XINT_GENL | APC_INT_PENDING | APC_PLAY_INT | APC_CAPT_INT | APC_GENL_INT) diff --git a/drivers/sbus/audio/dbri.c b/drivers/sbus/audio/dbri.c index 9f76c92e6..e6dfaf185 100644 --- a/drivers/sbus/audio/dbri.c +++ b/drivers/sbus/audio/dbri.c @@ -1907,19 +1907,11 @@ static int dbri_open(struct inode * inode, struct file * file, { MOD_INC_USE_COUNT; - /* SunOS 5.5.1 audio(7I) man page says: - * "Upon the initial open() of the audio device, the driver - * will reset the data format of the device to the default - * state of 8-bit, 8KHz, mono u-law data." - * - * I've also taken the liberty of setting half gain and + /* + * I've taken the liberty of setting half gain and * mid balance, to put the codec in a known state. */ - dbri_set_output_channels(drv, 1); - dbri_set_output_encoding(drv, AUDIO_ENCODING_ULAW); - dbri_set_output_rate(drv, 8000); - dbri_set_output_balance(drv, AUDIO_MID_BALANCE); dbri_set_output_volume(drv, AUDIO_MAX_GAIN/2); @@ -2162,7 +2154,6 @@ int dbri_bopen(int dev, unsigned int chan, int hdlcmode, u_char xmit_idle_char) { struct dbri *dbri; - int val; if (dev >= num_drivers || chan > 1) { return -1; @@ -2356,7 +2347,7 @@ static int dbri_attach(struct sparcaudio_driver *drv, #ifdef MODULE int init_module(void) #else -__initfunc(int dbri_init(void)) +int __init dbri_init(void) #endif { struct linux_sbus *bus; diff --git a/drivers/sbus/audio/dmy.c b/drivers/sbus/audio/dmy.c index bd1bec8ee..fd68ba202 100644 --- a/drivers/sbus/audio/dmy.c +++ b/drivers/sbus/audio/dmy.c @@ -643,7 +643,7 @@ static struct sparcaudio_operations dummy_ops = { #ifdef MODULE int init_module(void) #else -__initfunc(int dummy_init(void)) +int __init dummy_init(void) #endif { num_drivers = 0; diff --git a/drivers/sbus/char/Config.in b/drivers/sbus/char/Config.in index 5882a2bb4..7b9cda19c 100644 --- a/drivers/sbus/char/Config.in +++ b/drivers/sbus/char/Config.in @@ -9,9 +9,10 @@ if [ "$ARCH" = "sparc64" ]; then fi if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - tristate 'Bidirectional parallel port support (EXPERIMENTAL)' CONFIG_SUN_BPP + tristate 'Bidirectional parallel port support (obsolete)' CONFIG_SUN_BPP tristate 'Videopix Frame Grabber (EXPERIMENTAL)' CONFIG_SUN_VIDEOPIX tristate 'Aurora Multiboard 1600se (EXPERIMENTAL)' CONFIG_SUN_AURORA + tristate 'Tadpole TS102 Microcontroller support' CONFIG_TADPOLE_TS102_UCTRL # XXX Why don't we do "source drivers/char/Config.in" somewhere? if [ "$CONFIG_PCI" = "y" ]; then diff --git a/drivers/sbus/char/Makefile b/drivers/sbus/char/Makefile index c516d98fd..9a4a59fe6 100644 --- a/drivers/sbus/char/Makefile +++ b/drivers/sbus/char/Makefile @@ -95,6 +95,14 @@ else endif endif +ifeq ($(CONFIG_TADPOLE_TS102_UCTRL),y) +O_OBJS += uctrl.o +else + ifeq ($(CONFIG_TADPOLE_TS102_UCTRL),m) + M_OBJS += uctrl.o + endif +endif + include $(TOPDIR)/Rules.make sunkbdmap.o: sunkeymap.c diff --git a/drivers/sbus/char/aurora.c b/drivers/sbus/char/aurora.c index fde6f7649..5ec3107cb 100644 --- a/drivers/sbus/char/aurora.c +++ b/drivers/sbus/char/aurora.c @@ -1327,7 +1327,7 @@ printk("block_til_ready: start\n"); bp->r[chip]->r[CD180_MSVR]=port->MSVR;/* auto drops DTR */ } sti(); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) { if (port->flags & ASYNC_HUP_NOTIFY) diff --git a/drivers/sbus/char/bpp.c b/drivers/sbus/char/bpp.c index a19028c6f..0bd64dcce 100644 --- a/drivers/sbus/char/bpp.c +++ b/drivers/sbus/char/bpp.c @@ -148,18 +148,18 @@ static unsigned short get_pins(unsigned minor) */ struct bpp_regs { /* DMA registers */ - __u32 p_csr; /* DMA Control/Status Register */ - __u32 p_addr; /* Address Register */ - __u32 p_bcnt; /* Byte Count Register */ - __u32 p_tst_csr; /* Test Control/Status (DMA2 only) */ + __volatile__ __u32 p_csr; /* DMA Control/Status Register */ + __volatile__ __u32 p_addr; /* Address Register */ + __volatile__ __u32 p_bcnt; /* Byte Count Register */ + __volatile__ __u32 p_tst_csr; /* Test Control/Status (DMA2 only) */ /* Parallel Port registers */ - __u16 p_hcr; /* Hardware Configuration Register */ - __u16 p_ocr; /* Operation Configuration Register */ - __u8 p_dr; /* Parallel Data Register */ - __u8 p_tcr; /* Transfer Control Register */ - __u8 p_or; /* Output Register */ - __u8 p_ir; /* Input Register */ - __u16 p_icr; /* Interrupt Control Register */ + __volatile__ __u16 p_hcr; /* Hardware Configuration Register */ + __volatile__ __u16 p_ocr; /* Operation Configuration Register */ + __volatile__ __u8 p_dr; /* Parallel Data Register */ + __volatile__ __u8 p_tcr; /* Transfer Control Register */ + __volatile__ __u8 p_or; /* Output Register */ + __volatile__ __u8 p_ir; /* Input Register */ + __volatile__ __u16 p_icr; /* Interrupt Control Register */ }; /* P_CSR. Bits of type RW1 are cleared with writting '1'. */ @@ -1050,7 +1050,7 @@ static inline void freeLptPort(int idx) #ifdef MODULE int init_module(void) #else -__initfunc(int bpp_init(void)) +int __init bpp_init(void) #endif { int rc; diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c index fbc93415d..b6ec0a42d 100644 --- a/drivers/sbus/char/envctrl.c +++ b/drivers/sbus/char/envctrl.c @@ -1,17 +1,23 @@ -/* $Id: envctrl.c,v 1.9 1998/11/06 07:38:20 ecd Exp $ +/* $Id: envctrl.c,v 1.12 1999/08/31 06:58:04 davem Exp $ * envctrl.c: Temperature and Fan monitoring on Machines providing it. * * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) */ +#include <linux/version.h> #include <linux/config.h> #include <linux/module.h> + +#define __KERNEL_SYSCALLS__ #include <linux/sched.h> +#include <linux/unistd.h> #include <linux/errno.h> #include <linux/delay.h> #include <linux/ioport.h> #include <linux/init.h> +#include <linux/malloc.h> #include <linux/miscdevice.h> +#include <linux/smp_lock.h> #include <asm/ebus.h> #include <asm/uaccess.h> @@ -20,8 +26,16 @@ #define ENVCTRL_MINOR 162 -#undef DEBUG_BUS_SCAN +#undef U450_SUPPORT /* might fry you machine, careful here !!! */ + +#define DEBUG 1 +#define DEBUG_BUS_SCAN 1 + + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,0) +#define schedule_timeout(a) { current->timeout = jiffies + (a); schedule(); } +#endif #define PCF8584_ADDRESS 0x55 @@ -61,13 +75,196 @@ #define I2C_WRITE 0x00 #define I2C_READ 0x01 -struct pcf8584_reg +/* PCF8584 register offsets */ +#define I2C_DATA 0x00UL +#define I2C_CSR 0x01UL + +struct i2c_device { + unsigned char addr; + struct i2c_device *next; +}; + +static unsigned long i2c_regs; +static struct i2c_device *i2c_devices; + +static int errno; + +#define MAX_TEMPERATURE 111 +#define MAX_FAN_SPEED 63 + + +/* + * UltraAXi constants. + */ +#define AXI_THERM_ADDR 0x9e +#define AXI_THERM_PORT_CPU 0 +#define AXI_THERM_PORT_MOD 1 +#define AXI_THERM_PORT_PCI 2 +#define AXI_THERM_PORT_DISK 3 + +#define AXI_FAN_ADDR 0x4e +#define AXI_FAN_PORT_FRONT 0 +#define AXI_FAN_PORT_BACK 1 + +#define AXI_PIO_ADDR 0x70 + +/* + * Ultra 450 constants. + */ +#define U450_FAN_ADDR 0x4e +#define U450_FAN_PORT_CPU 0 +#define U450_FAN_PORT_PS 1 + +#define U450_PIO_ADDR 0x70 +#define U450_TIMER_ADDR 0xa0 + +static unsigned char +axi_cpu_temp_table[256] = +{ + 0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x67, + 0x66, 0x65, 0x64, 0x63, 0x61, 0x60, 0x5f, 0x5e, + 0x5d, 0x5b, 0x5a, 0x59, 0x58, 0x57, 0x55, 0x54, + 0x53, 0x52, 0x50, 0x4f, 0x4e, 0x4d, 0x4c, 0x4a, + 0x49, 0x48, 0x47, 0x46, 0x44, 0x43, 0x42, 0x41, + 0x40, 0x3e, 0x3d, 0x3c, 0x3c, 0x3b, 0x3b, 0x3a, + 0x3a, 0x39, 0x39, 0x38, 0x38, 0x37, 0x37, 0x36, + 0x36, 0x35, 0x35, 0x34, 0x34, 0x33, 0x33, 0x32, + 0x32, 0x31, 0x31, 0x30, 0x30, 0x2f, 0x2f, 0x2e, + 0x2d, 0x2d, 0x2c, 0x2c, 0x2b, 0x2b, 0x2a, 0x2a, + 0x29, 0x29, 0x28, 0x28, 0x27, 0x27, 0x26, 0x26, + 0x25, 0x25, 0x24, 0x24, 0x23, 0x23, 0x22, 0x22, + 0x21, 0x21, 0x20, 0x20, 0x1f, 0x1f, 0x1e, 0x1e, + 0x1e, 0x1e, 0x1d, 0x1d, 0x1d, 0x1d, 0x1c, 0x1c, + 0x1c, 0x1c, 0x1b, 0x1b, 0x1b, 0x1b, 0x1a, 0x1a, + 0x1a, 0x1a, 0x1a, 0x19, 0x19, 0x19, 0x19, 0x18, + 0x18, 0x18, 0x18, 0x17, 0x17, 0x17, 0x17, 0x16, + 0x16, 0x16, 0x16, 0x16, 0x16, 0x15, 0x15, 0x15, + 0x15, 0x14, 0x14, 0x14, 0x14, 0x13, 0x13, 0x13, + 0x13, 0x12, 0x12, 0x12, 0x12, 0x12, 0x11, 0x11, + 0x11, 0x11, 0x10, 0x10, 0x10, 0x10, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0c, 0x0c, 0x0c, 0x0c, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, + 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x05, 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, + 0x04, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static unsigned char +axi_mod_temp_table[256] = { - __volatile__ unsigned char data; - __volatile__ unsigned char csr; + 0x65, 0x64, 0x63, 0x62, 0x61, 0x60, 0x5f, 0x5e, + 0x5d, 0x5c, 0x5b, 0x5a, 0x59, 0x58, 0x57, 0x56, + 0x55, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x4e, + 0x4d, 0x4c, 0x4b, 0x4a, 0x49, 0x48, 0x47, 0x46, + 0x45, 0x44, 0x43, 0x42, 0x41, 0x40, 0x3f, 0x3e, + 0x3d, 0x3c, 0x3b, 0x3b, 0x3b, 0x3a, 0x3a, 0x39, + 0x39, 0x38, 0x38, 0x37, 0x37, 0x36, 0x36, 0x35, + 0x35, 0x35, 0x34, 0x34, 0x33, 0x33, 0x32, 0x32, + 0x31, 0x31, 0x30, 0x30, 0x2f, 0x2f, 0x2e, 0x2e, + 0x2e, 0x2d, 0x2d, 0x2c, 0x2c, 0x2b, 0x2b, 0x2a, + 0x2a, 0x29, 0x29, 0x29, 0x28, 0x28, 0x27, 0x27, + 0x26, 0x26, 0x25, 0x25, 0x24, 0x24, 0x23, 0x23, + 0x23, 0x22, 0x22, 0x21, 0x21, 0x20, 0x20, 0x1f, + 0x1f, 0x1e, 0x1e, 0x1e, 0x1d, 0x1d, 0x1d, 0x1d, + 0x1d, 0x1c, 0x1c, 0x1c, 0x1c, 0x1b, 0x1b, 0x1b, + 0x1b, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x19, 0x19, + 0x19, 0x19, 0x18, 0x18, 0x18, 0x18, 0x17, 0x17, + 0x17, 0x17, 0x17, 0x16, 0x16, 0x16, 0x16, 0x15, + 0x15, 0x15, 0x15, 0x14, 0x14, 0x14, 0x14, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x12, 0x12, 0x12, 0x12, + 0x11, 0x11, 0x11, 0x11, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0b, 0x0b, 0x0b, 0x0b, 0x0a, 0x0a, + 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x08, + 0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, + 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -static struct pcf8584_reg *i2c; +static unsigned char +axi_fan_speeds[112] = +{ + 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, + 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, + 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, + 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x20, + 0x22, 0x23, 0x25, 0x27, 0x28, 0x2a, 0x2b, 0x2d, + 0x2f, 0x30, 0x32, 0x33, 0x35, 0x37, 0x38, 0x3a, + 0x3b, 0x3d, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f +}; + + +struct therm_regs { + u32 addr; + u32 port; + u32 min_temp; + u32 warning; + u32 shutdown; + u32 num; + u32 den; +}; + +struct thermistor { + char name[8]; + struct therm_regs regs; + unsigned char (*temperature) (struct thermistor *); + unsigned char (*fan_speed) (struct thermistor *); + struct thermistor *next; /* all thermistors */ + struct thermistor *chain; /* thermistors for one fan */ +}; + +struct fan_regs { + u32 addr; + u32 port; +}; + +struct fan { + char name[8]; + struct fan_regs regs; + int (*set_speed)(struct fan *, unsigned char value); + int (*check_failure)(struct fan *); + unsigned char value; + struct thermistor *monitor; + struct fan *next; +}; + + +struct environment { + struct thermistor *thermistors; + struct fan *fans; + unsigned char *cpu_temp_table; + unsigned char *cpu_fan_speeds; + unsigned char *ps_temp_table; + unsigned char *ps_fan_speeds; + void (*enable) (struct environment *); + void (*disable) (struct environment *); + void (*keep_alive) (struct environment *); + int interval; + pid_t kenvd_pid; + wait_queue_head_t kenvd_wait; + int terminate; +}; + + +static struct environment envctrl; #ifdef DEBUG_BUS_SCAN @@ -78,37 +275,42 @@ struct i2c_addr_map { }; static struct i2c_addr_map devmap[] = { - { 0x38, 0x78, "PCF8574A" }, - { 0x20, 0x78, "TDA8444" }, - { 0x48, 0x78, "PCF8591" }, + { 0x70, 0xf0, "PCF8574A" }, + { 0x40, 0xf0, "TDA8444" }, + { 0x90, 0xf0, "PCF8591" }, + { 0xa0, 0xf0, "PCF8583" }, }; #define NR_DEVMAP (sizeof(devmap) / sizeof(devmap[0])) #endif static __inline__ int -PUT_DATA(__volatile__ unsigned char *data, char *buffer, int user) +PUT_DATA(unsigned long data, char *buffer, int user) { if (user) { - if (put_user(*data, buffer)) + u8 tmp = readb(data); + if (put_user(tmp, buffer)) return -EFAULT; } else { - *buffer = *data; + *buffer = readb(data); } return 0; } static __inline__ int -GET_DATA(__volatile__ unsigned char *data, const char *buffer, int user) +GET_DATA(unsigned long data, const char *buffer, int user) { if (user) { - if (get_user(*data, buffer)) + u8 tmp; + if (get_user(tmp, buffer)) return -EFAULT; + writeb(tmp, data); } else { - *data = *buffer; + writeb(*buffer, data); } return 0; } + static int i2c_read(unsigned char dev, char *buffer, int len, int user) { @@ -117,16 +319,17 @@ i2c_read(unsigned char dev, char *buffer, int len, int user) int error = -ENODEV; int count = 0; - i2c->data = (dev << 1) | I2C_READ; + writeb((dev & 0xfe) | I2C_READ, i2c_regs + I2C_DATA); - while (!(i2c->csr & STATUS_BB)) + while (!(readb(i2c_regs + I2C_CSR) & STATUS_BB)) udelay(1); - i2c->csr = CONTROL_PIN | CONTROL_ES0 | CONTROL_STA | CONTROL_ACK; + writeb(CONTROL_PIN | CONTROL_ES0 | CONTROL_STA | CONTROL_ACK, + i2c_regs + I2C_CSR); do { udelay(1); - while ((stat = i2c->csr) & STATUS_PIN) + while ((stat = readb(i2c_regs + I2C_CSR)) & STATUS_PIN) udelay(1); if (stat & STATUS_LRB) @@ -142,29 +345,30 @@ i2c_read(unsigned char dev, char *buffer, int len, int user) break; if (count++ > 0) { - error = PUT_DATA(&i2c->data, buffer++, user); + error = PUT_DATA(i2c_regs + I2C_DATA, buffer++, user); if (error) break; } else - dummy = i2c->data; + dummy = readb(i2c_regs + I2C_DATA); } while (1); - i2c->csr = CONTROL_ES0; + writeb(CONTROL_ES0, i2c_regs + I2C_CSR); if (!error && (count++ > 0)) - error = PUT_DATA(&i2c->data, buffer++, user); + error = PUT_DATA(i2c_regs + I2C_DATA, buffer++, user); else - dummy = i2c->data; + dummy = readb(i2c_regs + I2C_DATA); udelay(1); - while ((stat = i2c->csr) & STATUS_PIN) + while ((stat = readb(i2c_regs + I2C_CSR)) & STATUS_PIN) udelay(1); stop: - i2c->csr = CONTROL_PIN | CONTROL_ES0 | CONTROL_STO | CONTROL_ACK; + writeb(CONTROL_PIN | CONTROL_ES0 | CONTROL_STO | CONTROL_ACK, + i2c_regs + I2C_CSR); if (!error && (count++ > 0)) - error = PUT_DATA(&i2c->data, buffer++, user); + error = PUT_DATA(i2c_regs + I2C_DATA, buffer++, user); else - dummy = i2c->data; + dummy = readb(i2c_regs + I2C_DATA); if (error) return error; @@ -176,20 +380,33 @@ i2c_write(unsigned char dev, const char *buffer, int len, int user) { int error = -ENODEV; int count = 0; + int timeout; - while (!(i2c->csr & STATUS_BB)) + timeout = 1000000; + while (!(readb(i2c_regs + I2C_CSR) & STATUS_BB) && --timeout) udelay(1); + if (!timeout) { + printk("%s [%d]: TIMEOUT\n", __FUNCTION__, __LINE__); + return -ENODEV; + } - i2c->data = (dev << 1) | I2C_WRITE; - i2c->csr = CONTROL_PIN | CONTROL_ES0 | CONTROL_STA | CONTROL_ACK; + writeb((dev & 0xfe) | I2C_WRITE, i2c_regs + I2C_DATA); + writeb(CONTROL_PIN | CONTROL_ES0 | CONTROL_STA | CONTROL_ACK, + i2c_regs + I2C_CSR); do { unsigned char stat; udelay(1); - while ((stat = i2c->csr) & STATUS_PIN) + timeout = 1000000; + while (((stat = readb(i2c_regs + I2C_CSR)) & STATUS_PIN) && --timeout) udelay(1); + if (!timeout) { + printk("%s [%d]: TIMEOUT\n", __FUNCTION__, __LINE__); + break; + } + if (stat & STATUS_LRB) break; @@ -197,32 +414,172 @@ i2c_write(unsigned char dev, const char *buffer, int len, int user) if (count == len) break; - error = GET_DATA(&i2c->data, buffer++, user); + error = GET_DATA(i2c_regs + I2C_DATA, buffer++, user); if (error) break; count++; } while (1); - i2c->csr = CONTROL_PIN | CONTROL_ES0 | CONTROL_STO | CONTROL_ACK; + writeb(CONTROL_PIN | CONTROL_ES0 | CONTROL_STO | CONTROL_ACK, + i2c_regs + I2C_CSR); return error; } -__initfunc(static int i2c_scan_bus(void)) +#ifdef U450_SUPPORT +static int +i2c_write_read(unsigned char dev, char *outbuf, int outlen, + char *inbuf, int inlen, int user) +{ + unsigned char dummy; + unsigned char stat; + int error = -ENODEV; + int count = 0; + + while (!(readb(i2c_regs + I2C_CSR) & STATUS_BB)) + udelay(1); + + writeb((dev & 0xfe) | I2C_WRITE, i2c_regs + I2C_DATA); + writeb(CONTROL_PIN | CONTROL_ES0 | CONTROL_STA | CONTROL_ACK, + i2c_regs + I2C_CSR); + + do { + unsigned char stat; + + udelay(1); + while ((stat = readb(i2c_regs + I2C_CSR)) & STATUS_PIN) + udelay(1); + + if (stat & STATUS_LRB) + break; + + error = count; + if (count == outlen) + break; + + error = GET_DATA(i2c_regs + I2C_DATA, outbuf++, user); + if (error) + break; + + count++; + } while (1); + + if (error < 0) { + writeb(CONTROL_PIN | CONTROL_ES0 | + CONTROL_STO | CONTROL_ACK, i2c_regs + I2C_CSR); + return error; + } + + writeb(CONTROL_ES0 | CONTROL_STA | CONTROL_ACK, i2c_regs + I2C_CSR); + udelay(1); + writeb((dev & 0xfe) | I2C_READ, i2c_regs + I2C_DATA); + + count = 0; + do { + udelay(1); + while ((stat = readb(i2c_regs + I2C_CSR)) & STATUS_PIN) + udelay(1); + + if (stat & STATUS_LRB) + goto stop; + + error = 0; + if (inlen == 0) { + count--; + break; + } + + if (count == (inlen - 1)) + break; + + if (count++ > 0) { + error = PUT_DATA(i2c_regs + I2C_DATA, inbuf++, user); + if (error) + break; + } else + dummy = readb(i2c_regs + I2C_DATA); + } while (1); + + writeb(CONTROL_ES0, i2c_regs + I2C_CSR); + if (!error && (count++ > 0)) + error = PUT_DATA(i2c_regs + I2C_DATA, inbuf++, user); + else + dummy = readb(i2c_regs + I2C_DATA); + + udelay(1); + while ((stat = readb(i2c_regs + I2C_CSR)) & STATUS_PIN) + udelay(1); + +stop: + writeb(CONTROL_PIN | CONTROL_ES0 | CONTROL_STO | CONTROL_ACK, + i2c_regs + I2C_CSR); + if (!error && (count++ > 0)) + error = PUT_DATA(i2c_regs + I2C_DATA, inbuf++, user); + else + dummy = readb(i2c_regs + I2C_DATA); + + if (error) + return error; + return count - 1; +} +#endif /* U450_SUPPORT */ + +static struct i2c_device * +i2c_find_device(unsigned char addr) { - unsigned char dev; + struct i2c_device *dev; + + for (dev = i2c_devices; dev; dev = dev->next) { + if (dev->addr == addr) + return dev; + } + return 0; +} + +static void +i2c_free_devices(void) +{ + struct i2c_device *dev; + + dev = i2c_devices; + while (dev) { + i2c_devices = dev->next; + kfree(dev); + dev = i2c_devices; + } +} + +static __init int i2c_scan_bus(void) +{ + struct i2c_device *dev, **last; + unsigned int addr; int count = 0; - for (dev = 1; dev < 128; dev++) { - if (i2c_read(dev, 0, 0, 0) == 0) { + last = &i2c_devices; + for (addr = 0; addr < 256; addr += 2) { + if (i2c_write(addr, 0, 0, 0) == 0) { #ifdef DEBUG_BUS_SCAN int i; for (i = 0; i < NR_DEVMAP; i++) - if ((dev & devmap[i].mask) == devmap[i].addr) + if ((addr & devmap[i].mask) == devmap[i].addr) break; - printk("envctrl: i2c device at %02x: %s\n", dev, + printk("envctrl: i2c device at %02x: %s\n", addr, i < NR_DEVMAP ? devmap[i].name : "unknown"); #endif + + dev = kmalloc(sizeof(struct i2c_device), GFP_KERNEL); + if (!dev) { + printk("i2c: can't alloc i2c_device\n"); + i2c_free_devices(); + return -ENOMEM; + } + memset(dev, 0, sizeof(struct i2c_device)); + + dev->addr = addr; + + *last = dev; + last = &dev->next; + count++; } } @@ -233,6 +590,872 @@ __initfunc(static int i2c_scan_bus(void)) return 0; } + +static int +read_8591(unsigned char dev, unsigned char offset, unsigned char *value) +{ + unsigned char data[2]; + + data[0] = 0x40 | offset; + if (i2c_write(dev, data, 1, 0) != 1) + return -1; + if (i2c_read(dev, data, 2, 0) != 2) + return -1; + *value = data[1]; + return 0; +} + +static int +write_8444(unsigned char dev, unsigned char offset, unsigned char value) +{ + unsigned char data[2]; + + data[0] = offset; + data[1] = value; + if (i2c_write(dev, data, 2, 0) != 2) + return -1; + return 0; +} + +#ifdef U450_SUPPORT +static int +read_8583(unsigned char dev, unsigned char offset, unsigned char *value) +{ + unsigned char data; + + data = offset; + if (i2c_write_read(dev, &data, 1, &data, 1, 0) != 1) + return -1; + *value = data; + return 0; +} + +static int +write_8583(unsigned char dev, unsigned char offset, unsigned char value) +{ + unsigned char data[2]; + + data[0] = offset; + data[1] = value; + if (i2c_write(dev, data, 2, 0) != 2) + return -1; + return 0; +} +#endif /* U450_SUPPORT */ + +struct thermistor * +find_thermistor(const char *name, struct thermistor *from) +{ + int n; + + if (!from) + from = envctrl.thermistors; + else + from = from->next; + + n = strlen(name); + while (from && strncmp(from->name, name, n)) + from = from->next; + + return from; +} + +void +check_temperatures(struct environment *env) +{ + struct thermistor *t; + + for (t = env->thermistors; t; t = t->next) { +#ifdef DEBUG + printk("Thermistor `%s' [%02x:%d]: " + "%d C (%d C, %d C)\n", + t->name, t->regs.addr, t->regs.port, + t->temperature(t), t->regs.warning, t->regs.shutdown); +#endif + + /* + * Implement slow-down or shutdown here... + */ + } +} + +void +check_fan_speeds(struct environment *env) +{ + unsigned char speed, max; + struct thermistor *t; + struct fan *f; + + for (f = env->fans; f; f = f->next) { +#ifdef DEBUG + printk("Fan `%s' [%02x:%d]:", f->name, + f->regs.addr, f->regs.port); +#endif + max = 0; + for (t = f->monitor; t; t = t->chain) { + speed = t->fan_speed(t); + if (speed > max) + max = speed; +#ifdef DEBUG + printk(" %s:%02x", t->name, speed); +#endif + } + + f->set_speed(f, max); +#ifdef DEBUG + printk(" -> %02x\n", f->value); +#endif + } +} + +void +envctrl_fans_blast(struct environment *env) +{ + struct fan *f; + + for (f = env->fans; f; f = f->next) + f->set_speed(f, MAX_FAN_SPEED); +} + +int +kenvd(void *data) +{ + struct environment *env = data; + + MOD_INC_USE_COUNT; + lock_kernel(); + + env->kenvd_pid = current->pid; + + exit_files(current); + exit_mm(current); + + spin_lock_irq(¤t->sigmask_lock); + siginitsetinv(¤t->blocked, sigmask(SIGKILL)); + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + + current->session = 1; + current->pgrp = 1; + strcpy(current->comm, "kenvd"); + + if (env->enable) + env->enable(env); + + while (!env->terminate) { + + check_temperatures(env); + check_fan_speeds(env); + if (env->keep_alive) + env->keep_alive(env); + + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(env->interval * HZ); + + if (signal_pending(current)) { + spin_lock_irq(¤t->sigmask_lock); + flush_signals(current); + spin_unlock_irq(¤t->sigmask_lock); + break; + } + } + + if (env->disable) + env->disable(env); + + env->kenvd_pid = 0; + wake_up(&envctrl.kenvd_wait); + + MOD_DEC_USE_COUNT; + return 0; +} + +void +envctrl_stop(void) +{ + DECLARE_WAITQUEUE(wait, current); + struct thermistor *t; + struct fan *f; + pid_t pid; + + if (envctrl.kenvd_pid) { + pid = envctrl.kenvd_pid; + + current->state = TASK_INTERRUPTIBLE; + add_wait_queue(&envctrl.kenvd_wait, &wait); + + envctrl.terminate = 1; + kill_proc(pid, SIGKILL, 1); + + schedule(); + + remove_wait_queue(&envctrl.kenvd_wait, &wait); + current->state = TASK_RUNNING; + } + + t = envctrl.thermistors; + while (t) { + envctrl.thermistors = t->next; + kfree(t); + t = envctrl.thermistors; + } + + f = envctrl.fans; + while (f) { + envctrl.fans = f->next; + kfree(f); + f = envctrl.fans; + } + + if (envctrl.cpu_temp_table) + kfree(envctrl.cpu_temp_table); + + if (envctrl.cpu_fan_speeds) + kfree(envctrl.cpu_fan_speeds); + + if (envctrl.ps_temp_table) + kfree(envctrl.ps_temp_table); + + if (envctrl.ps_fan_speeds) + kfree(envctrl.ps_fan_speeds); +} + + +static unsigned char +axi_get_temperature(struct thermistor *t) +{ + unsigned char value; + + if (read_8591(t->regs.addr, t->regs.port, &value) < 0) + return MAX_TEMPERATURE; + if (t->regs.port == AXI_THERM_PORT_CPU) + return axi_cpu_temp_table[value]; + else + return axi_mod_temp_table[value]; +} + +static unsigned char +axi_get_fan_speed(struct thermistor *t) +{ + unsigned char temp; + + temp = t->temperature(t); + if (temp >= MAX_TEMPERATURE) + return MAX_FAN_SPEED; + + return axi_fan_speeds[temp]; +} + +static int +axi_set_fan_speed(struct fan *f, unsigned char value) +{ + if (value != f->value) { + if (write_8444(f->regs.addr, f->regs.port, value)) + return -1; + f->value = value; + } + return 0; +} + +static void +axi_toggle_i2c_int(struct environment *env) +{ + unsigned char data; + + if (i2c_read(AXI_PIO_ADDR, &data, 1, 0) != 1) + return; + + data &= ~(0x08); + if (i2c_write(AXI_PIO_ADDR, &data, 1, 0) != 1) + return; + mdelay(1); + + data |= 0x08; + if (i2c_write(AXI_PIO_ADDR, &data, 1, 0) != 1) + return; + mdelay(1); +} + + +static int +rasctrl_setup(int node) +{ + struct thermistor *t, **tlast; + struct fan *f, **flast; + char tmp[32]; + int monitor; + int shutdown; + int warning; + int i; + + prom_getstring(prom_root_node, "name", tmp, sizeof(tmp)); + if (strcmp(tmp, "SUNW,UltraSPARC-IIi-Engine")) { + printk("SUNW,rasctrl will work only on Ultra AXi\n"); + return -ENODEV; + } + + monitor = prom_getintdefault(node, "env-monitor", 0); + if (monitor == 0) + return -ENODEV; + + envctrl.interval = prom_getintdefault(node, "env-mon-interval", 60); + warning = prom_getintdefault(node, "warning-temp", 55); + shutdown = prom_getintdefault(node, "shutdown-temp", 58); + + tlast = &envctrl.thermistors; + for (i = 0; i < 4; i++) { + t = kmalloc(sizeof(struct thermistor), GFP_KERNEL); + if (!t) + goto out; + memset(t, 0, sizeof(struct thermistor)); + + t->regs.addr = AXI_THERM_ADDR; + t->regs.port = i; + t->regs.warning = warning; + t->regs.shutdown = shutdown; + + switch (i) { + case AXI_THERM_PORT_CPU: + sprintf(t->name, "%.7s", "CPU"); + break; + case AXI_THERM_PORT_MOD: + sprintf(t->name, "%.7s", "MOD"); + break; + case AXI_THERM_PORT_PCI: + sprintf(t->name, "%.7s", "PCI"); + break; + case AXI_THERM_PORT_DISK: + sprintf(t->name, "%.7s", "DISK"); + break; + } + + t->temperature = axi_get_temperature; + t->fan_speed = axi_get_fan_speed; + + if (!i2c_find_device(t->regs.addr)) { + printk("envctrl: `%s': i2c device %02x not found\n", + t->name, t->regs.addr); + kfree(t); + continue; + } + + *tlast = t; + tlast = &t->next; + } + + flast = &envctrl.fans; + for (i = 0; i < 2; i++) { + f = kmalloc(sizeof(struct fan), GFP_KERNEL); + if (!f) + goto out; + memset(f, 0, sizeof(struct fan)); + + f->regs.addr = AXI_FAN_ADDR; + f->regs.port = i; + + switch (i) { + case AXI_FAN_PORT_FRONT: + sprintf(f->name, "%.7s", "FRONT"); + t = NULL; + while ((t = find_thermistor("CPU", t))) { + t->chain = f->monitor; + f->monitor = t; + } + break; + case AXI_FAN_PORT_BACK: + sprintf(f->name, "%.7s", "BACK"); + t = NULL; + while ((t = find_thermistor("PCI", t))) { + t->chain = f->monitor; + f->monitor = t; + } + break; + } + + if (!f->monitor) { + kfree(f); + continue; + } + + if (!i2c_find_device(f->regs.addr)) { + printk("envctrl: `%s': i2c device %02x not found\n", + f->name, f->regs.addr); + kfree(f); + continue; + } + + *flast = f; + flast = &f->next; + + f->check_failure = NULL; + f->set_speed = axi_set_fan_speed; + } + + envctrl.enable = axi_toggle_i2c_int; + envctrl.disable = envctrl_fans_blast; + +#ifdef DEBUG + printk("Warn: %d C, Shutdown %d C, Interval %d s, Monitor %d\n", + warning, shutdown, envctrl.interval, monitor); +#endif + return 0; + +out: + envctrl_stop(); + return -ENODEV; +} + + +#ifdef U450_SUPPORT + +static unsigned char +envctrl_get_temperature(struct thermistor *t) +{ + unsigned char value; + + if (read_8591(t->regs.addr, t->regs.port, &value) < 0) + return MAX_TEMPERATURE; + if (!strncmp(t->name, "CPU", 3)) + return envctrl.cpu_temp_table[value]; + else + return envctrl.ps_temp_table[value]; +} + +static unsigned char +envctrl_get_fan_speed(struct thermistor *t) +{ + unsigned char temp; + + temp = t->temperature(t); + if (temp >= MAX_TEMPERATURE) + return MAX_FAN_SPEED; + + if (!strncmp(t->name, "CPU", 3)) + return envctrl.cpu_fan_speeds[temp]; + else + return envctrl.ps_fan_speeds[temp]; +} + +static int +envctrl_set_fan_speed(struct fan *f, unsigned char value) +{ + if (value != f->value) { + if (write_8444(f->regs.addr, f->regs.port, value)) + return -1; + f->value = value; + } + + return 0; +} + +static unsigned char u450_default_thermisters[] = +{ + /* CPU0 */ + 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x46, + 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x43, 0x50, 0x55, 0x30, 0x00, + /* CPU1 */ + 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x46, + 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x43, 0x50, 0x55, 0x31, 0x00, + /* CPU2 */ + 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x46, + 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x43, 0x50, 0x55, 0x32, 0x00, + /* CPU3 */ + 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x46, + 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x43, 0x50, 0x55, 0x33, 0x00, + /* PS0 */ + 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x5a, + 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x50, 0x53, 0x30, 0x00, + /* PS1 */ + 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x5a, + 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x50, 0x53, 0x31, 0x00, + /* PS2 */ + 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x5a, + 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x50, 0x53, 0x32, 0x00, + /* AMB */ + 0x00, 0x00, 0x00, 0x9a, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x28, + 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x41, 0x4d, 0x42, 0x00 +}; + +static unsigned char u450_default_cpu_temp_factors[] = +{ + 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, + 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, + 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, + 0x96, 0x94, 0x92, 0x90, 0x8f, 0x8e, 0x8d, 0x8c, + 0x8a, 0x88, 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, + 0x81, 0x80, 0x7f, 0x7e, 0x7d, 0x7c, 0x7b, 0x7a, + 0x79, 0x79, 0x78, 0x78, 0x77, 0x76, 0x75, 0x74, + 0x73, 0x72, 0x71, 0x70, 0x70, 0x6f, 0x6f, 0x6e, + 0x6e, 0x6e, 0x6d, 0x6d, 0x6c, 0x6b, 0x6a, 0x6a, + 0x69, 0x69, 0x68, 0x67, 0x66, 0x65, 0x65, 0x64, + 0x64, 0x64, 0x63, 0x63, 0x62, 0x62, 0x61, 0x61, + 0x60, 0x60, 0x5f, 0x5f, 0x5e, 0x5e, 0x5d, 0x5d, + 0x5c, 0x5c, 0x5b, 0x5b, 0x5b, 0x5a, 0x5a, 0x5a, + 0x59, 0x59, 0x58, 0x58, 0x57, 0x57, 0x56, 0x56, + 0x55, 0x55, 0x54, 0x54, 0x53, 0x53, 0x52, 0x52, + 0x52, 0x51, 0x51, 0x50, 0x50, 0x50, 0x50, 0x4f, + 0x4f, 0x4f, 0x4e, 0x4e, 0x4e, 0x4d, 0x4d, 0x4d, + 0x4c, 0x4c, 0x4c, 0x4b, 0x4b, 0x4b, 0x4a, 0x4a, + 0x4a, 0x49, 0x49, 0x49, 0x48, 0x48, 0x48, 0x47, + 0x47, 0x47, 0x46, 0x46, 0x46, 0x46, 0x45, 0x45, + 0x45, 0x44, 0x44, 0x44, 0x44, 0x43, 0x43, 0x43, + 0x43, 0x42, 0x42, 0x42, 0x42, 0x41, 0x41, 0x41, + 0x40, 0x40, 0x40, 0x3f, 0x3f, 0x3f, 0x3e, 0x3e, + 0x3e, 0x3d, 0x3d, 0x3d, 0x3d, 0x3c, 0x3c, 0x3c, + 0x3c, 0x3b, 0x3b, 0x3b, 0x3a, 0x3a, 0x3a, 0x39, + 0x39, 0x39, 0x38, 0x38, 0x38, 0x38, 0x37, 0x37, + 0x37, 0x37, 0x36, 0x36, 0x36, 0x35, 0x35, 0x35, + 0x34, 0x34, 0x34, 0x33, 0x33, 0x33, 0x33, 0x32, + 0x32, 0x32, 0x31, 0x31, 0x31, 0x30, 0x30, 0x30, + 0x2f, 0x2f, 0x2f, 0x2e, 0x2e, 0x2e, 0x2d, 0x2d, + 0x2d, 0x2c, 0x2c, 0x2c, 0x2b, 0x2b, 0x2b, 0x2a, + 0x2a, 0x2a, 0x29, 0x29, 0x29, 0x28, 0x28, 0x28 +}; + +static unsigned char u450_default_cpu_fan_speeds[] = +{ + 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, + 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, + 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, + 0x1f, 0x1f, 0x1f, 0x1f, 0x20, 0x21, 0x22, 0x23, + 0x24, 0x25, 0x26, 0x27, 0x28, 0x2a, 0x2b, 0x2d, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f +}; + +static unsigned char u450_default_ps_temp_factors[] = +{ + 0x9a, 0x96, 0x82, 0x7d, 0x78, 0x73, 0x6e, 0x6b, + 0x69, 0x67, 0x64, 0x5f, 0x5a, 0x57, 0x55, 0x53, + 0x51, 0x50, 0x4e, 0x4d, 0x4c, 0x4b, 0x49, 0x47, + 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40, 0x3f, + 0x3e, 0x3d, 0x3c, 0x3c, 0x3b, 0x3a, 0x39, 0x39, + 0x38, 0x37, 0x37, 0x36, 0x35, 0x35, 0x34, 0x33, + 0x32, 0x32, 0x32, 0x31, 0x31, 0x30, 0x30, 0x2f, + 0x2f, 0x2e, 0x2e, 0x2d, 0x2d, 0x2c, 0x2c, 0x2b, + 0x2a, 0x2a, 0x29, 0x29, 0x28, 0x28, 0x27, 0x27, + 0x26, 0x26, 0x25, 0x25, 0x25, 0x25, 0x24, 0x24, + 0x23, 0x23, 0x23, 0x22, 0x22, 0x22, 0x21, 0x21, + 0x21, 0x20, 0x20, 0x20, 0x1f, 0x1f, 0x1e, 0x1e, + 0x1e, 0x1d, 0x1d, 0x1d, 0x1d, 0x1c, 0x1c, 0x1c, + 0x1b, 0x1b, 0x1b, 0x1a, 0x1a, 0x1a, 0x19, 0x19, + 0x19, 0x18, 0x18, 0x18, 0x18, 0x17, 0x17, 0x17, + 0x17, 0x16, 0x16, 0x16, 0x16, 0x15, 0x15, 0x15, + 0x14, 0x14, 0x14, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x12, 0x12, 0x12, 0x12, 0x11, 0x11, 0x11, 0x11, + 0x10, 0x10, 0x10, 0x10, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0e, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static unsigned char u450_default_ps_fan_speeds[] = +{ + 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, + 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, + 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, + 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x21, 0x22, 0x23, + 0x24, 0x25, 0x26, 0x26, 0x27, 0x28, 0x29, 0x2a, + 0x2b, 0x2d, 0x2e, 0x2f, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, + 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f +}; + +static void +u450_toggle_i2c_int(struct environment *env) +{ + unsigned char tmp[80]; + unsigned char data; + int i, n; + + write_8583(U450_TIMER_ADDR, 0, 0x84); + write_8583(U450_TIMER_ADDR, 8, 0x0a); + write_8583(U450_TIMER_ADDR, 7, 0x00); + write_8583(U450_TIMER_ADDR, 0, 0x04); + + n = sprintf(tmp, "envctrl: PCF8583:"); + for (i = 0; i < 16; i++) { + if (read_8583(U450_TIMER_ADDR, i, &data) < 0) { + printk("envctrl: error reading PCF8583\n"); + break; + } + n += sprintf(tmp+n, " %02x", data); + } + printk("%s\n", tmp); + +#if 1 + data = 0x70; + if (i2c_write(U450_PIO_ADDR, &data, 1, 0) != 1) + return; + mdelay(1); + + data = 0x78; + if (i2c_write(U450_PIO_ADDR, &data, 1, 0) != 1) + return; + mdelay(1); +#endif +} + +static void +u450_set_egg_timer(struct environment *env) +{ + unsigned char value; + +#if 0 + write_8583(U450_TIMER_ADDR, 0x00, 0x84); + read_8583(U450_TIMER_ADDR, 0x07, &value); + write_8583(U450_TIMER_ADDR, 0x07, 0x00); + write_8583(U450_TIMER_ADDR, 0x00, 0x04); +#else + read_8583(U450_TIMER_ADDR, 0x07, &value); + printk("envctrl: TIMER [%02x:07]: %02x\n", U450_TIMER_ADDR, value); + read_8583(U450_TIMER_ADDR, 0x00, &value); + printk("envctrl: TIMER [%02x:00]: %02x\n", U450_TIMER_ADDR, value); +#endif +} + +static int +envctrl_setup(int node) +{ + struct thermistor *t, **tlast; + struct fan *f, **flast; + unsigned char *tmp = NULL, *p; + int len, n, err; + int defaults = 0; + + len = prom_getproplen(node, "thermisters"); + if (len <= 0) { + printk("envctrl: no property `thermisters', using defaults\n"); + defaults++; + len = sizeof(u450_default_thermisters); + } + + tmp = (unsigned char *)kmalloc(len, GFP_KERNEL); + if (!tmp) { + printk("envctrl: can't allocate property buffer\n"); + return -ENODEV; + } + + if (defaults) { + memcpy(tmp, u450_default_thermisters, len); + } else { + err = prom_getproperty(node, "thermisters", tmp, len); + if (err < 0) { + printk("envctrl: error reading property `thermisters'\n"); + kfree(tmp); + return -ENODEV; + } + } + + p = tmp; + err = -ENOMEM; + + tlast = &envctrl.thermistors; + while (len > sizeof(struct therm_regs)) { + t = kmalloc(sizeof(struct thermistor), GFP_KERNEL); + if (!t) { + printk("envctrl: can't allocate thermistor struct\n"); + goto out; + } + memset(t, 0, sizeof(struct thermistor)); + + memcpy(&t->regs, p, sizeof(struct therm_regs)); + p += sizeof(struct therm_regs); + len -= sizeof(struct therm_regs); + + n = strlen(p) + 1; + strncpy(t->name, p, 7); + p += n; + len -= n; + + if (!i2c_find_device(t->regs.addr)) { + printk("envctrl: `%s': i2c device %02x not found\n", + t->name, t->regs.addr); + kfree(t); + continue; + } + + t->temperature = envctrl_get_temperature; + t->fan_speed = envctrl_get_fan_speed; + + *tlast = t; + tlast = &t->next; + } + + flast = &envctrl.fans; + for (n = 0; n < 2; n++) { + f = kmalloc(sizeof(struct fan), GFP_KERNEL); + if (!f) + goto out; + memset(f, 0, sizeof(struct fan)); + + f->regs.addr = U450_FAN_ADDR; + f->regs.port = n; + + switch (n) { + case U450_FAN_PORT_CPU: + sprintf(f->name, "%.7s", "CPU"); + t = NULL; + while ((t = find_thermistor("CPU", t))) { + t->chain = f->monitor; + f->monitor = t; + } + break; + case U450_FAN_PORT_PS: + sprintf(f->name, "%.7s", "PS"); + t = NULL; + while ((t = find_thermistor("PS", t))) { + t->chain = f->monitor; + f->monitor = t; + } + break; + } + + if (!f->monitor) { + kfree(f); + continue; + } + + if (!i2c_find_device(f->regs.addr)) { + printk("envctrl: `%s': i2c device %02x not found\n", + f->name, f->regs.addr); + kfree(f); + continue; + } + + *flast = f; + flast = &f->next; + + f->check_failure = NULL; + f->set_speed = envctrl_set_fan_speed; + } + + envctrl.cpu_temp_table = kmalloc(256, GFP_KERNEL); + if (!envctrl.cpu_temp_table) { + printk("envctrl: can't allocate temperature table\n"); + goto out; + } + if (defaults) { + memcpy(envctrl.cpu_temp_table, + u450_default_cpu_temp_factors, 256); + } else { + err = prom_getproperty(node, "cpu-temp-factors", + envctrl.cpu_temp_table, 256); + if (err) { + printk("envctrl: can't read `cpu-temp-factors'\n"); + goto out; + } + } + + envctrl.cpu_fan_speeds = kmalloc(112, GFP_KERNEL); + if (!envctrl.cpu_fan_speeds) { + printk("envctrl: can't allocate fan speed table\n"); + goto out; + } + if (defaults) { + memcpy(envctrl.cpu_fan_speeds, + u450_default_cpu_fan_speeds, 112); + } else { + err = prom_getproperty(node, "cpu-fan-speeds", + envctrl.cpu_fan_speeds, 112); + if (err) { + printk("envctrl: can't read `cpu-fan-speeds'\n"); + goto out; + } + } + + envctrl.ps_temp_table = kmalloc(256, GFP_KERNEL); + if (!envctrl.ps_temp_table) { + printk("envctrl: can't allocate temperature table\n"); + goto out; + } + if (defaults) { + memcpy(envctrl.ps_temp_table, + u450_default_ps_temp_factors, 256); + } else { + err = prom_getproperty(node, "ps-temp-factors", + envctrl.ps_temp_table, 256); + if (err) { + printk("envctrl: can't read `ps-temp-factors'\n"); + goto out; + } + } + + envctrl.ps_fan_speeds = kmalloc(112, GFP_KERNEL); + if (!envctrl.ps_fan_speeds) { + printk("envctrl: can't allocate fan speed table\n"); + goto out; + } + if (defaults) { + memcpy(envctrl.ps_fan_speeds, + u450_default_ps_fan_speeds, 112); + } else { + err = prom_getproperty(node, "ps-fan-speeds", + envctrl.ps_fan_speeds, 112); + if (err) { + printk("envctrl: can't read `ps-fan-speeds'\n"); + goto out; + } + } + + envctrl.enable = u450_toggle_i2c_int; + envctrl.keep_alive = u450_set_egg_timer; + envctrl.disable = envctrl_fans_blast; + envctrl.interval = 60; + + kfree(tmp); + return 0; + +out: + if (tmp) + kfree(tmp); + + envctrl_stop(); + return err; +} +#endif /* U450_SUPPORT */ + + + static loff_t envctrl_llseek(struct file *file, loff_t offset, int type) { @@ -266,7 +1489,9 @@ envctrl_ioctl(struct inode *inode, struct file *file, case I2CIOCSADR: if (get_user(addr, (int *)arg)) return -EFAULT; - data = addr & 0x7f; + data = addr & 0xfe; + if (!i2c_find_device(addr & 0xfe)) + return -ENODEV; file->private_data = (void *)data; break; case I2CIOCGADR: @@ -317,12 +1542,13 @@ static struct miscdevice envctrl_dev = { #ifdef MODULE int init_module(void) #else -__initfunc(int envctrl_init(void)) +int __init envctrl_init(void) #endif { #ifdef CONFIG_PCI struct linux_ebus *ebus; struct linux_ebus_device *edev = 0; + pid_t pid; int err; for_each_ebus(ebus) { @@ -339,33 +1565,55 @@ ebus_done: return -ENODEV; } - if (check_region(edev->base_address[0], sizeof(*i2c))) { - printk("%s: Can't get region %lx, %d\n", - __FUNCTION__, edev->base_address[0], (int)sizeof(*i2c)); - return -ENODEV; - } - - i2c = (struct pcf8584_reg *)edev->base_address[0]; - - request_region((unsigned long)i2c, sizeof(*i2c), "i2c"); - - i2c->csr = CONTROL_PIN; - i2c->data = PCF8584_ADDRESS; - i2c->csr = CONTROL_PIN | CONTROL_ES1; - i2c->data = CLK_4_43 | BUS_CLK_90; - i2c->csr = CONTROL_PIN | CONTROL_ES0 | CONTROL_ACK; + i2c_regs = edev->resource[0].start; + writeb(CONTROL_PIN, i2c_regs + I2C_CSR); + writeb(PCF8584_ADDRESS >> 1, i2c_regs + I2C_DATA); + writeb(CONTROL_PIN | CONTROL_ES1, i2c_regs + I2C_CSR); + writeb(CLK_4_43 | BUS_CLK_90, i2c_regs + I2C_DATA); + writeb(CONTROL_PIN | CONTROL_ES0 | CONTROL_ACK, i2c_regs + I2C_CSR); mdelay(10); if (misc_register(&envctrl_dev)) { printk("%s: unable to get misc minor %d\n", __FUNCTION__, envctrl_dev.minor); - release_region((unsigned long)i2c, sizeof(*i2c)); + return -ENODEV; } err = i2c_scan_bus(); - if (err) - release_region((unsigned long)i2c, sizeof(*i2c)); - return err; + if (err) { + i2c_free_devices(); + misc_deregister(&envctrl_dev); + return err; + } + + memset(&envctrl, 0, sizeof(struct environment)); + + err = -ENODEV; + if (!strcmp(edev->prom_name, "SUNW,rasctrl")) + err = rasctrl_setup(edev->prom_node); +#ifdef U450_SUPPORT + else if (!strcmp(edev->prom_name, "SUNW,envctrl")) + err = envctrl_setup(edev->prom_node); +#endif + + if (err) { + envctrl_stop(); + i2c_free_devices(); + misc_deregister(&envctrl_dev); + return err; + } + + init_waitqueue_head(&envctrl.kenvd_wait); + + pid = kernel_thread(kenvd, (void *)&envctrl, CLONE_FS); + if (pid < 0) { + envctrl_stop(); + i2c_free_devices(); + misc_deregister(&envctrl_dev); + return -ENODEV; + } + + return 0; #else return -ENODEV; #endif @@ -375,7 +1623,8 @@ ebus_done: #ifdef MODULE void cleanup_module(void) { + envctrl_stop(); + i2c_free_devices(); misc_deregister(&envctrl_dev); - release_region((unsigned long)i2c, sizeof(*i2c)); } #endif diff --git a/drivers/sbus/char/flash.c b/drivers/sbus/char/flash.c index 6bd2eabfb..6764486c8 100644 --- a/drivers/sbus/char/flash.c +++ b/drivers/sbus/char/flash.c @@ -1,4 +1,4 @@ -/* $Id: flash.c,v 1.11 1999/03/09 14:06:45 davem Exp $ +/* $Id: flash.c,v 1.13 1999/08/31 06:58:06 davem Exp $ * flash.c: Allow mmap access to the OBP Flash, for OBP updates. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -22,11 +22,11 @@ #include <asm/ebus.h> static struct { - unsigned long read_base; - unsigned long write_base; - unsigned long read_size; - unsigned long write_size; - unsigned long busy; + unsigned long read_base; /* Physical read address */ + unsigned long write_base; /* Physical write address */ + unsigned long read_size; /* Size of read area */ + unsigned long write_size; /* Size of write area */ + unsigned long busy; /* In use? */ } flash; #define FLASH_MINOR 152 @@ -41,7 +41,7 @@ flash_mmap(struct file *file, struct vm_area_struct *vma) return -ENXIO; if (flash.read_base == flash.write_base) { - addr = __pa(flash.read_base); + addr = flash.read_base; size = flash.read_size; } else { if ((vma->vm_flags & VM_READ) && @@ -49,10 +49,10 @@ flash_mmap(struct file *file, struct vm_area_struct *vma) return -EINVAL; if (vma->vm_flags & VM_READ) { - addr = __pa(flash.read_base); + addr = flash.read_base; size = flash.read_size; } else if (vma->vm_flags & VM_WRITE) { - addr = __pa(flash.write_base); + addr = flash.write_base; size = flash.write_size; } else return -ENXIO; @@ -152,7 +152,7 @@ EXPORT_NO_SYMBOLS; #ifdef MODULE int init_module(void) #else -__initfunc(int flash_init(void)) +int __init flash_init(void) #endif { struct linux_sbus *sbus; @@ -167,20 +167,17 @@ __initfunc(int flash_init(void)) prom_apply_sbus_ranges(sdev->my_bus, &sdev->reg_addrs[0], sdev->num_registers, sdev); if (sdev->reg_addrs[0].phys_addr == sdev->reg_addrs[1].phys_addr) { - flash.read_base = (unsigned long)sparc_alloc_io(sdev->reg_addrs[0].phys_addr, 0, - sdev->reg_addrs[0].reg_size, "flashprom", - sdev->reg_addrs[0].which_io, 0); + flash.read_base = ((unsigned long)sdev->reg_addrs[0].phys_addr) | + (((unsigned long)sdev->reg_addrs[0].which_io)<<32UL); flash.read_size = sdev->reg_addrs[0].reg_size; flash.write_base = flash.read_base; flash.write_size = flash.read_size; } else { - flash.read_base = (unsigned long)sparc_alloc_io(sdev->reg_addrs[0].phys_addr, 0, - sdev->reg_addrs[0].reg_size, "flashprom", - sdev->reg_addrs[0].which_io, 0); + flash.read_base = ((unsigned long)sdev->reg_addrs[0].phys_addr) | + (((unsigned long)sdev->reg_addrs[0].which_io)<<32UL); flash.read_size = sdev->reg_addrs[0].reg_size; - flash.write_base = (unsigned long)sparc_alloc_io(sdev->reg_addrs[1].phys_addr, 0, - sdev->reg_addrs[1].reg_size, "flashprom", - sdev->reg_addrs[1].which_io, 0); + flash.write_base = ((unsigned long)sdev->reg_addrs[1].phys_addr) | + (((unsigned long)sdev->reg_addrs[1].which_io)<<32UL); flash.write_size = sdev->reg_addrs[1].reg_size; } flash.busy = 0; @@ -207,14 +204,14 @@ __initfunc(int flash_init(void)) nregs = len / sizeof(regs[0]); - flash.read_base = edev->base_address[0]; + flash.read_base = edev->resource[0].start; flash.read_size = regs[0].reg_size; if (nregs == 1) { - flash.write_base = edev->base_address[0]; + flash.write_base = edev->resource[0].start; flash.write_size = regs[0].reg_size; } else if (nregs == 2) { - flash.write_base = edev->base_address[1]; + flash.write_base = edev->resource[1].start; flash.write_size = regs[1].reg_size; } else { printk("flash: Strange number of regs %d\n", nregs); @@ -229,8 +226,8 @@ __initfunc(int flash_init(void)) } printk("OBP Flash: RD %lx[%lx] WR %lx[%lx]\n", - __pa(flash.read_base), flash.read_size, - __pa(flash.write_base), flash.write_size); + flash.read_base, flash.read_size, + flash.write_base, flash.write_size); err = misc_register(&flash_dev); if (err) { diff --git a/drivers/sbus/char/openprom.c b/drivers/sbus/char/openprom.c index 7d17e08ea..2e67dd4af 100644 --- a/drivers/sbus/char/openprom.c +++ b/drivers/sbus/char/openprom.c @@ -577,7 +577,7 @@ EXPORT_NO_SYMBOLS; #ifdef MODULE int init_module(void) #else -__initfunc(int openprom_init(void)) +int __init openprom_init(void) #endif { unsigned long flags; diff --git a/drivers/sbus/char/pcikbd.c b/drivers/sbus/char/pcikbd.c index d5a15a612..dc34fe4cd 100644 --- a/drivers/sbus/char/pcikbd.c +++ b/drivers/sbus/char/pcikbd.c @@ -1,4 +1,4 @@ -/* $Id: pcikbd.c,v 1.30 1999/06/03 15:02:36 davem Exp $ +/* $Id: pcikbd.c,v 1.35 1999/09/01 08:09:26 davem Exp $ * pcikbd.c: Ultra/AX PC keyboard support. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -367,7 +367,7 @@ void pcikbd_leds(unsigned char leds) } -__initfunc(static int pcikbd_wait_for_input(void)) +static int __init pcikbd_wait_for_input(void) { int status, data; unsigned long start = jiffies; @@ -384,7 +384,7 @@ __initfunc(static int pcikbd_wait_for_input(void)) return -1; } -__initfunc(static void pcikbd_write(int address, int data)) +static void __init pcikbd_write(int address, int data) { int status; @@ -436,7 +436,7 @@ static void nop_kd_mksound(unsigned int hz, unsigned int ticks) extern void (*kd_mksound)(unsigned int hz, unsigned int ticks); -__initfunc(static char *do_pcikbd_init_hw(void)) +static char * __init do_pcikbd_init_hw(void) { while(pcikbd_wait_for_input() != -1) @@ -479,7 +479,7 @@ __initfunc(static char *do_pcikbd_init_hw(void)) return NULL; /* success */ } -__initfunc(void pcikbd_init_hw(void)) +void __init pcikbd_init_hw(void) { struct linux_ebus *ebus; struct linux_ebus_device *edev; @@ -516,16 +516,7 @@ __initfunc(void pcikbd_init_hw(void)) return; found: - pcikbd_iobase = child->base_address[0]; -#ifdef __sparc_v9__ - if (check_region(pcikbd_iobase, sizeof(unsigned long))) { - printk("8042: can't get region %lx, %d\n", - pcikbd_iobase, (int)sizeof(unsigned long)); - return; - } - request_region(pcikbd_iobase, sizeof(unsigned long), "8042 controller"); -#endif - + pcikbd_iobase = child->resource[0].start; pcikbd_irq = child->irqs[0]; if (request_irq(pcikbd_irq, &pcikbd_interrupt, SA_SHIRQ, "keyboard", (void *)pcikbd_iobase)) { @@ -559,17 +550,11 @@ ebus_done: if (!edev) pcibeep_iobase = (pcikbd_iobase & ~(0xffffff)) | 0x722000; else - pcibeep_iobase = edev->base_address[0]; + pcibeep_iobase = edev->resource[0].start; - if (check_region(pcibeep_iobase, sizeof(unsigned int))) { - printk("8042: can't get region %lx, %d\n", - pcibeep_iobase, (int)sizeof(unsigned int)); - } else { - request_region(pcibeep_iobase, sizeof(unsigned int), "speaker"); - kd_mksound = pcikbd_kd_mksound; - printk("8042(speaker): iobase[%016lx]%s\n", pcibeep_iobase, - edev ? "" : " (forced)"); - } + kd_mksound = pcikbd_kd_mksound; + printk("8042(speaker): iobase[%016lx]%s\n", pcibeep_iobase, + edev ? "" : " (forced)"); #endif disable_irq(pcikbd_irq); @@ -711,7 +696,7 @@ static void aux_write_dev(int val) * Write to device & handle returned ack */ -__initfunc(static int aux_write_ack(int val)) +static int __init aux_write_ack(int val) { aux_write_dev(val); poll_aux_status(); @@ -893,7 +878,7 @@ static ssize_t aux_read(struct file * file, char * buffer, return -EAGAIN; add_wait_queue(&queue->proc_list, &wait); repeat: - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); if (queue_empty() && !signal_pending(current)) { schedule(); goto repeat; @@ -943,7 +928,7 @@ static struct miscdevice psaux_mouse = { PSMOUSE_MINOR, "ps2aux", &psaux_fops }; -__initfunc(int pcimouse_init(void)) +int __init pcimouse_init(void) { struct linux_ebus *ebus; struct linux_ebus_device *edev; @@ -971,14 +956,7 @@ __initfunc(int pcimouse_init(void)) return -ENODEV; found: - pcimouse_iobase = child->base_address[0]; - /* - * Just in case the iobases for kbd/mouse ever differ... - */ - if (!check_region(pcimouse_iobase, sizeof(unsigned long))) - request_region(pcimouse_iobase, sizeof(unsigned long), - "8042 controller"); - + pcimouse_iobase = child->resource[0].start; pcimouse_irq = child->irqs[0]; } @@ -1027,7 +1005,7 @@ found: } -__initfunc(int ps2kbd_probe(unsigned long *memory_start)) +int __init ps2kbd_probe(unsigned long *memory_start) { int pnode, enode, node, dnode, xnode; int kbnode = 0, msnode = 0, bnode = 0; diff --git a/drivers/sbus/char/rtc.c b/drivers/sbus/char/rtc.c index a86a53411..2a6f8624b 100644 --- a/drivers/sbus/char/rtc.c +++ b/drivers/sbus/char/rtc.c @@ -1,4 +1,4 @@ -/* $Id: rtc.c,v 1.14 1999/06/03 15:02:38 davem Exp $ +/* $Id: rtc.c,v 1.18 1999/08/31 18:51:36 davem Exp $ * * Linux/SPARC Real Time Clock Driver * Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu) @@ -29,12 +29,16 @@ static int rtc_busy = 0; /* Retrieve the current date and time from the real time clock. */ void get_rtc_time(struct rtc_time *t) { - register struct mostek48t02 *regs = mstk48t02_regs; + unsigned long regs = mstk48t02_regs; unsigned long flags; + u8 tmp; save_flags(flags); cli(); - regs->creg |= MSTK_CREG_READ; + + tmp = mostek_read(regs + MOSTEK_CREG); + tmp |= MSTK_CREG_READ; + mostek_write(regs + MOSTEK_CREG, tmp); t->sec = MSTK_REG_SEC(regs); t->min = MSTK_REG_MIN(regs); @@ -44,19 +48,24 @@ void get_rtc_time(struct rtc_time *t) t->month = MSTK_REG_MONTH(regs); t->year = MSTK_CVT_YEAR( MSTK_REG_YEAR(regs) ); - regs->creg &= ~MSTK_CREG_READ; + tmp = mostek_read(regs + MOSTEK_CREG); + tmp &= ~MSTK_CREG_READ; + mostek_write(regs + MOSTEK_CREG, tmp); restore_flags(flags); } /* Set the current date and time inthe real time clock. */ void set_rtc_time(struct rtc_time *t) { - register struct mostek48t02 *regs = mstk48t02_regs; + unsigned long regs = mstk48t02_regs; unsigned long flags; + u8 tmp; save_flags(flags); cli(); - regs->creg |= MSTK_CREG_WRITE; + tmp = mostek_read(regs + MOSTEK_CREG); + tmp |= MSTK_CREG_WRITE; + mostek_write(regs + MOSTEK_CREG, tmp); MSTK_SET_REG_SEC(regs,t->sec); MSTK_SET_REG_MIN(regs,t->min); @@ -66,7 +75,9 @@ void set_rtc_time(struct rtc_time *t) MSTK_SET_REG_MONTH(regs,t->month); MSTK_SET_REG_YEAR(regs,t->year - MSTK_YEAR_ZERO); - regs->creg &= ~MSTK_CREG_WRITE; + tmp = mostek_read(regs + MOSTEK_CREG); + tmp &= ~MSTK_CREG_WRITE; + mostek_write(regs + MOSTEK_CREG, tmp); restore_flags(flags); } @@ -145,7 +156,7 @@ EXPORT_NO_SYMBOLS; #ifdef MODULE int init_module(void) #else -__initfunc(int rtc_sun_init(void)) +int __init rtc_sun_init(void) #endif { int error; diff --git a/drivers/sbus/char/sab82532.c b/drivers/sbus/char/sab82532.c index 1387a6f15..6a8125080 100644 --- a/drivers/sbus/char/sab82532.c +++ b/drivers/sbus/char/sab82532.c @@ -1,4 +1,4 @@ -/* $Id: sab82532.c,v 1.32 1999/07/03 08:57:41 davem Exp $ +/* $Id: sab82532.c,v 1.35 1999/09/01 08:09:29 davem Exp $ * sab82532.c: ASYNC Driver for the SIEMENS SAB82532 DUSCC. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -174,7 +174,7 @@ static struct ebrg_struct ebrg_table[] = { static __inline__ void sab82532_tec_wait(struct sab82532 *info) { int count = SAB82532_MAX_TEC_DELAY; - while ((info->regs->r.star & SAB82532_STAR_TEC) && --count) + while ((readb(&info->regs->r.star) & SAB82532_STAR_TEC) && --count) udelay(1); } @@ -188,12 +188,13 @@ static __inline__ void sab82532_start_tx(struct sab82532 *info) if (info->xmit_cnt <= 0) goto out; - if (!(info->regs->r.star & SAB82532_STAR_XFW)) + if (!(readb(&info->regs->r.star) & SAB82532_STAR_XFW)) goto out; info->all_sent = 0; for (i = 0; i < info->xmit_fifo_size; i++) { - info->regs->w.xfifo[i] = info->xmit_buf[info->xmit_tail++]; + u8 val = info->xmit_buf[info->xmit_tail++]; + writeb(val, &info->regs->w.xfifo[i]); info->xmit_tail &= (SERIAL_XMIT_SIZE - 1); info->icount.tx++; if (--info->xmit_cnt <= 0) @@ -201,9 +202,9 @@ static __inline__ void sab82532_start_tx(struct sab82532 *info) } /* Issue a Transmit Frame command. */ - if (info->regs->r.star & SAB82532_STAR_CEC) + if (readb(&info->regs->r.star) & SAB82532_STAR_CEC) udelay(1); - info->regs->w.cmdr = SAB82532_CMDR_XF; + writeb(SAB82532_CMDR_XF, &info->regs->w.cmdr); out: restore_flags(flags); @@ -228,7 +229,7 @@ static void sab82532_stop(struct tty_struct *tty) save_flags(flags); cli(); info->interrupt_mask1 |= SAB82532_IMR1_XPR; - info->regs->w.imr1 = info->interrupt_mask1; + writeb(info->interrupt_mask1, &info->regs->w.imr1); restore_flags(flags); } @@ -242,14 +243,14 @@ static void sab82532_start(struct tty_struct *tty) save_flags(flags); cli(); info->interrupt_mask1 &= ~(SAB82532_IMR1_XPR); - info->regs->w.imr1 = info->interrupt_mask1; + writeb(info->interrupt_mask1, &info->regs->w.imr1); sab82532_start_tx(info); restore_flags(flags); } static void batten_down_hatches(struct sab82532 *info) { - unsigned char saved_rfc; + unsigned char saved_rfc, tmp; /* If we are doing kadb, we call the debugger * else we just drop into the boot monitor. @@ -262,11 +263,13 @@ static void batten_down_hatches(struct sab82532 *info) /* * Set FIFO to single character mode. */ - saved_rfc = info->regs->r.rfc; - info->regs->rw.rfc &= ~(SAB82532_RFC_RFDF); - if (info->regs->r.star & SAB82532_STAR_CEC) + saved_rfc = readb(&info->regs->r.rfc); + tmp = readb(&info->regs->rw.rfc); + tmp &= ~(SAB82532_RFC_RFDF); + writeb(tmp, &info->regs->rw.rfc); + if (readb(&info->regs->r.star) & SAB82532_STAR_CEC) udelay(1); - info->regs->w.cmdr = SAB82532_CMDR_RRES; + writeb(SAB82532_CMDR_RRES, &info->regs->w.cmdr); #ifndef __sparc_v9__ if ((((unsigned long)linux_dbvec) >= DEBUG_FIRSTVADDR) && @@ -279,10 +282,10 @@ static void batten_down_hatches(struct sab82532 *info) /* * Reset FIFO to character + status mode. */ - info->regs->w.rfc = saved_rfc; - if (info->regs->r.star & SAB82532_STAR_CEC) + writeb(saved_rfc, &info->regs->w.rfc); + if (readb(&info->regs->r.star) & SAB82532_STAR_CEC) udelay(1); - info->regs->w.cmdr = SAB82532_CMDR_RRES; + writeb(SAB82532_CMDR_RRES, &info->regs->w.cmdr); } /* @@ -333,15 +336,15 @@ static inline void receive_chars(struct sab82532 *info, } if (stat->sreg.isr0 & SAB82532_ISR0_TCD) { - count = info->regs->r.rbcl & (info->recv_fifo_size - 1); + count = readb(&info->regs->r.rbcl) & (info->recv_fifo_size - 1); free_fifo++; } /* Issue a FIFO read command in case we where idle. */ if (stat->sreg.isr0 & SAB82532_ISR0_TIME) { - if (info->regs->r.star & SAB82532_STAR_CEC) + if (readb(&info->regs->r.star) & SAB82532_STAR_CEC) udelay(1); - info->regs->w.cmdr = SAB82532_CMDR_RFRD; + writeb(SAB82532_CMDR_RFRD, &info->regs->w.cmdr); } if (stat->sreg.isr0 & SAB82532_ISR0_RFO) { @@ -353,13 +356,13 @@ static inline void receive_chars(struct sab82532 *info, /* Read the FIFO. */ for (i = 0; i < count; i++) - buf[i] = info->regs->r.rfifo[i]; + buf[i] = readb(&info->regs->r.rfifo[i]); /* Issue Receive Message Complete command. */ if (free_fifo) { - if (info->regs->r.star & SAB82532_STAR_CEC) + if (readb(&info->regs->r.star) & SAB82532_STAR_CEC) udelay(1); - info->regs->w.cmdr = SAB82532_CMDR_RMC; + writeb(SAB82532_CMDR_RMC, &info->regs->w.cmdr); } if (info->is_console) @@ -410,26 +413,27 @@ static inline void transmit_chars(struct sab82532 *info, if (stat->sreg.isr1 & SAB82532_ISR1_ALLS) info->all_sent = 1; - if (!(info->regs->r.star & SAB82532_STAR_XFW)) + if (!(readb(&info->regs->r.star) & SAB82532_STAR_XFW)) return; if (!info->tty) { info->interrupt_mask1 |= SAB82532_IMR1_XPR; - info->regs->w.imr1 = info->interrupt_mask1; + writeb(info->interrupt_mask1, &info->regs->w.imr1); return; } if ((info->xmit_cnt <= 0) || info->tty->stopped || info->tty->hw_stopped) { info->interrupt_mask1 |= SAB82532_IMR1_XPR; - info->regs->w.imr1 = info->interrupt_mask1; + writeb(info->interrupt_mask1, &info->regs->w.imr1); return; } /* Stuff 32 bytes into Transmit FIFO. */ info->all_sent = 0; for (i = 0; i < info->xmit_fifo_size; i++) { - info->regs->w.xfifo[i] = info->xmit_buf[info->xmit_tail++]; + u8 val = info->xmit_buf[info->xmit_tail++]; + writeb(val, &info->regs->w.xfifo[i]); info->xmit_tail &= (SERIAL_XMIT_SIZE - 1); info->icount.tx++; if (--info->xmit_cnt <= 0) @@ -437,9 +441,9 @@ static inline void transmit_chars(struct sab82532 *info, } /* Issue a Transmit Frame command. */ - if (info->regs->r.star & SAB82532_STAR_CEC) + if (readb(&info->regs->r.star) & SAB82532_STAR_CEC) udelay(1); - info->regs->w.cmdr = SAB82532_CMDR_XF; + writeb(SAB82532_CMDR_XF, &info->regs->w.cmdr); if (info->xmit_cnt < WAKEUP_CHARS) sab82532_sched_event(info, RS_EVENT_WRITE_WAKEUP); @@ -449,7 +453,7 @@ static inline void transmit_chars(struct sab82532 *info, #endif if (info->xmit_cnt <= 0) { info->interrupt_mask1 |= SAB82532_IMR1_XPR; - info->regs->w.imr1 = info->interrupt_mask1; + writeb(info->interrupt_mask1, &info->regs->w.imr1); } } @@ -490,7 +494,7 @@ static inline void check_status(struct sab82532 *info, check_modem: if (stat->sreg.isr0 & SAB82532_ISR0_CDSC) { - info->dcd = (info->regs->r.vstr & SAB82532_VSTR_CD) ? 0 : 1; + info->dcd = (readb(&info->regs->r.vstr) & SAB82532_VSTR_CD) ? 0 : 1; info->icount.dcd++; modem_change++; #if 0 @@ -498,15 +502,15 @@ check_modem: #endif } if (stat->sreg.isr1 & SAB82532_ISR1_CSC) { - info->cts = info->regs->r.star & SAB82532_STAR_CTS; + info->cts = readb(&info->regs->r.star) & SAB82532_STAR_CTS; info->icount.cts++; modem_change++; #if 0 printk("CTS change: %d, CTS %s\n", info->icount.cts, info->cts ? "on" : "off"); #endif } - if ((info->regs->r.pvr & info->pvr_dsr_bit) ^ info->dsr) { - info->dsr = (info->regs->r.pvr & info->pvr_dsr_bit) ? 0 : 1; + if ((readb(&info->regs->r.pvr) & info->pvr_dsr_bit) ^ info->dsr) { + info->dsr = (readb(&info->regs->r.pvr) & info->pvr_dsr_bit) ? 0 : 1; info->icount.dsr++; modem_change++; #if 0 @@ -548,7 +552,7 @@ check_modem: sab82532_sched_event(info, RS_EVENT_WRITE_WAKEUP); info->interrupt_mask1 &= ~(SAB82532_IMR1_XPR); - info->regs->w.imr1 = info->interrupt_mask1; + writeb(info->interrupt_mask1, &info->regs->w.imr1); sab82532_start_tx(info); } } else { @@ -576,10 +580,10 @@ static void sab82532_interrupt(int irq, void *dev_id, struct pt_regs *regs) #endif status.stat = 0; - if (info->regs->r.gis & SAB82532_GIS_ISA0) - status.sreg.isr0 = info->regs->r.isr0; - if (info->regs->r.gis & SAB82532_GIS_ISA1) - status.sreg.isr1 = info->regs->r.isr1; + if (readb(&info->regs->r.gis) & SAB82532_GIS_ISA0) + status.sreg.isr0 = readb(&info->regs->r.isr0); + if (readb(&info->regs->r.gis) & SAB82532_GIS_ISA1) + status.sreg.isr1 = readb(&info->regs->r.isr1); #ifdef SERIAL_DEBUG_INTR printk("%d<%02x.%02x>", info->line, @@ -601,10 +605,10 @@ static void sab82532_interrupt(int irq, void *dev_id, struct pt_regs *regs) next: info = info->next; status.stat = 0; - if (info->regs->r.gis & SAB82532_GIS_ISB0) - status.sreg.isr0 = info->regs->r.isr0; - if (info->regs->r.gis & SAB82532_GIS_ISB1) - status.sreg.isr1 = info->regs->r.isr1; + if (readb(&info->regs->r.gis) & SAB82532_GIS_ISB0) + status.sreg.isr0 = readb(&info->regs->r.isr0); + if (readb(&info->regs->r.gis) & SAB82532_GIS_ISB1) + status.sreg.isr1 = readb(&info->regs->r.isr1); #ifdef SERIAL_DEBUG_INTR printk("%d<%02x.%02x>", info->line, @@ -690,63 +694,73 @@ static void do_serial_hangup(void *private_) static void sab82532_init_line(struct sab82532 *info) { - unsigned char stat; + unsigned char stat, tmp; /* * Wait for any commands or immediate characters */ - if (info->regs->r.star & SAB82532_STAR_CEC) + if (readb(&info->regs->r.star) & SAB82532_STAR_CEC) udelay(1); sab82532_tec_wait(info); /* * Clear the FIFO buffers. */ - if (info->regs->r.star & SAB82532_STAR_CEC) + if (readb(&info->regs->r.star) & SAB82532_STAR_CEC) udelay(1); - info->regs->w.cmdr = SAB82532_CMDR_RRES; - if (info->regs->r.star & SAB82532_STAR_CEC) + writeb(SAB82532_CMDR_RRES, &info->regs->w.cmdr); + if (readb(&info->regs->r.star) & SAB82532_STAR_CEC) udelay(1); - info->regs->w.cmdr = SAB82532_CMDR_XRES; + writeb(SAB82532_CMDR_XRES, &info->regs->w.cmdr); /* * Clear the interrupt registers. */ - stat = info->regs->r.isr0; - stat = info->regs->r.isr1; + stat = readb(&info->regs->r.isr0); + stat = readb(&info->regs->r.isr1); /* * Now, initialize the UART */ - info->regs->w.ccr0 = 0; /* power-down */ - info->regs->w.ccr0 = SAB82532_CCR0_MCE | SAB82532_CCR0_SC_NRZ | - SAB82532_CCR0_SM_ASYNC; - info->regs->w.ccr1 = SAB82532_CCR1_ODS | SAB82532_CCR1_BCR | 7; - info->regs->w.ccr2 = SAB82532_CCR2_BDF | SAB82532_CCR2_SSEL | - SAB82532_CCR2_TOE; - info->regs->w.ccr3 = 0; - info->regs->w.ccr4 = SAB82532_CCR4_MCK4 | SAB82532_CCR4_EBRG; - info->regs->w.mode = SAB82532_MODE_RTS | SAB82532_MODE_FCTS | - SAB82532_MODE_RAC; - info->regs->w.rfc = SAB82532_RFC_DPS | SAB82532_RFC_RFDF; + writeb(0, &info->regs->w.ccr0); /* power-down */ + writeb(SAB82532_CCR0_MCE | SAB82532_CCR0_SC_NRZ | + SAB82532_CCR0_SM_ASYNC, &info->regs->w.ccr0); + writeb(SAB82532_CCR1_ODS | SAB82532_CCR1_BCR | 7, &info->regs->w.ccr1); + writeb(SAB82532_CCR2_BDF | SAB82532_CCR2_SSEL | + SAB82532_CCR2_TOE, &info->regs->w.ccr2); + writeb(0, &info->regs->w.ccr3); + writeb(SAB82532_CCR4_MCK4 | SAB82532_CCR4_EBRG, &info->regs->w.ccr4); + writeb(SAB82532_MODE_RTS | SAB82532_MODE_FCTS | + SAB82532_MODE_RAC, &info->regs->w.mode); + writeb(SAB82532_RFC_DPS | SAB82532_RFC_RFDF, &info->regs->w.rfc); switch (info->recv_fifo_size) { case 1: - info->regs->w.rfc |= SAB82532_RFC_RFTH_1; + tmp = readb(&info->regs->w.rfc); + tmp |= SAB82532_RFC_RFTH_1; + writeb(tmp, &info->regs->w.rfc); break; case 4: - info->regs->w.rfc |= SAB82532_RFC_RFTH_4; + tmp = readb(&info->regs->w.rfc); + tmp |= SAB82532_RFC_RFTH_4; + writeb(tmp, &info->regs->w.rfc); break; case 16: - info->regs->w.rfc |= SAB82532_RFC_RFTH_16; + tmp = readb(&info->regs->w.rfc); + tmp |= SAB82532_RFC_RFTH_16; + writeb(tmp, &info->regs->w.rfc); break; default: info->recv_fifo_size = 32; /* fall through */ case 32: - info->regs->w.rfc |= SAB82532_RFC_RFTH_32; + tmp = readb(&info->regs->w.rfc); + tmp |= SAB82532_RFC_RFTH_32; + writeb(tmp, &info->regs->w.rfc); break; } - info->regs->rw.ccr0 |= SAB82532_CCR0_PU; /* power-up */ + tmp = readb(&info->regs->rw.ccr0); + tmp |= SAB82532_CCR0_PU; /* power-up */ + writeb(tmp, &info->regs->rw.ccr0); } static int startup(struct sab82532 *info) @@ -788,9 +802,16 @@ static int startup(struct sab82532 *info) sab82532_init_line(info); if (info->tty->termios->c_cflag & CBAUD) { - info->regs->rw.mode &= ~(SAB82532_MODE_FRTS); - info->regs->rw.mode |= SAB82532_MODE_RTS; - info->regs->rw.pvr &= ~(info->pvr_dtr_bit); + u8 tmp; + + tmp = readb(&info->regs->rw.mode); + tmp &= ~(SAB82532_MODE_FRTS); + tmp |= SAB82532_MODE_RTS; + writeb(tmp, &info->regs->rw.mode); + + tmp = readb(&info->regs->rw.pvr); + tmp &= ~(info->pvr_dtr_bit); + writeb(tmp, &info->regs->rw.pvr); } /* @@ -798,11 +819,11 @@ static int startup(struct sab82532 *info) */ info->interrupt_mask0 = SAB82532_IMR0_PERR | SAB82532_IMR0_FERR | SAB82532_IMR0_PLLA; - info->regs->w.imr0 = info->interrupt_mask0; + writeb(info->interrupt_mask0, &info->regs->w.imr0); info->interrupt_mask1 = SAB82532_IMR1_BRKT | SAB82532_IMR1_XOFF | SAB82532_IMR1_TIN | SAB82532_IMR1_XON | SAB82532_IMR1_XPR; - info->regs->w.imr1 = info->interrupt_mask1; + writeb(info->interrupt_mask1, &info->regs->w.imr1); if (info->tty) clear_bit(TTY_IO_ERROR, &info->tty->flags); @@ -829,6 +850,7 @@ errout: static void shutdown(struct sab82532 *info) { unsigned long flags; + u8 tmp; if (!(info->flags & ASYNC_INITIALIZED)) return; @@ -853,12 +875,12 @@ static void shutdown(struct sab82532 *info) if (info->is_console) { info->interrupt_mask0 = SAB82532_IMR0_PERR | SAB82532_IMR0_FERR | SAB82532_IMR0_PLLA | SAB82532_IMR0_CDSC; - info->regs->w.imr0 = info->interrupt_mask0; + writeb(info->interrupt_mask0, &info->regs->w.imr0); info->interrupt_mask1 = SAB82532_IMR1_BRKT | SAB82532_IMR1_ALLS | SAB82532_IMR1_XOFF | SAB82532_IMR1_TIN | SAB82532_IMR1_CSC | SAB82532_IMR1_XON | SAB82532_IMR1_XPR; - info->regs->w.imr1 = info->interrupt_mask1; + writeb(info->interrupt_mask1, &info->regs->w.imr1); if (info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags); info->flags &= ~ASYNC_INITIALIZED; @@ -868,24 +890,30 @@ static void shutdown(struct sab82532 *info) /* Disable Interrupts */ info->interrupt_mask0 = 0xff; - info->regs->w.imr0 = info->interrupt_mask0; + writeb(info->interrupt_mask0, &info->regs->w.imr0); info->interrupt_mask1 = 0xff; - info->regs->w.imr1 = info->interrupt_mask1; + writeb(info->interrupt_mask1, &info->regs->w.imr1); if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) { - info->regs->rw.mode |= SAB82532_MODE_FRTS; - info->regs->rw.mode |= SAB82532_MODE_RTS; - info->regs->rw.pvr |= info->pvr_dtr_bit; + writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_FRTS, &info->regs->rw.mode); + writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_RTS, &info->regs->rw.mode); + writeb(readb(&info->regs->rw.pvr) | info->pvr_dtr_bit, &info->regs->rw.pvr); } /* Disable break condition */ - info->regs->rw.dafo &= ~(SAB82532_DAFO_XBRK); + tmp = readb(&info->regs->rw.dafo); + tmp &= ~(SAB82532_DAFO_XBRK); + writeb(tmp, &info->regs->rw.dafo); /* Disable Receiver */ - info->regs->rw.mode &= ~(SAB82532_MODE_RAC); + tmp = readb(&info->regs->rw.mode); + tmp &= ~(SAB82532_MODE_RAC); + writeb(tmp, &info->regs->rw.mode); /* Power Down */ - info->regs->rw.ccr0 &= ~(SAB82532_CCR0_PU); + tmp = readb(&info->regs->rw.ccr0); + tmp &= ~(SAB82532_CCR0_PU); + writeb(tmp, &info->regs->rw.ccr0); if (info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags); @@ -999,23 +1027,23 @@ static void change_speed(struct sab82532 *info) SAB82532_ISR0_TIME; save_flags(flags); cli(); - if (info->regs->r.star & SAB82532_STAR_CEC) + if (readb(&info->regs->r.star) & SAB82532_STAR_CEC) udelay(1); sab82532_tec_wait(info); - info->regs->w.dafo = dafo; - info->regs->w.bgr = ebrg & 0xff; - info->regs->rw.ccr2 &= ~(0xc0); - info->regs->rw.ccr2 |= (ebrg >> 2) & 0xc0; + writeb(dafo, &info->regs->w.dafo); + writeb(ebrg & 0xff, &info->regs->w.bgr); + writeb(readb(&info->regs->rw.ccr2) & ~(0xc0), &info->regs->rw.ccr2); + writeb(readb(&info->regs->rw.ccr2) | ((ebrg >> 2) & 0xc0), &info->regs->rw.ccr2); if (info->flags & ASYNC_CTS_FLOW) { - info->regs->rw.mode &= ~(SAB82532_MODE_RTS); - info->regs->rw.mode |= SAB82532_MODE_FRTS; - info->regs->rw.mode &= ~(SAB82532_MODE_FCTS); + writeb(readb(&info->regs->rw.mode) & ~(SAB82532_MODE_RTS), &info->regs->rw.mode); + writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_FRTS, &info->regs->rw.mode); + writeb(readb(&info->regs->rw.mode) & ~(SAB82532_MODE_FCTS), &info->regs->rw.mode); } else { - info->regs->rw.mode |= SAB82532_MODE_RTS; - info->regs->rw.mode &= ~(SAB82532_MODE_FRTS); - info->regs->rw.mode |= SAB82532_MODE_FCTS; + writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_RTS, &info->regs->rw.mode); + writeb(readb(&info->regs->rw.mode) & ~(SAB82532_MODE_FRTS), &info->regs->rw.mode); + writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_FCTS, &info->regs->rw.mode); } - info->regs->rw.mode |= SAB82532_MODE_RAC; + writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_RAC, &info->regs->rw.mode); restore_flags(flags); } @@ -1056,7 +1084,7 @@ static void sab82532_flush_chars(struct tty_struct *tty) save_flags(flags); cli(); info->interrupt_mask1 &= ~(SAB82532_IMR1_XPR); - info->regs->w.imr1 = info->interrupt_mask1; + writeb(info->interrupt_mask1, &info->regs->w.imr1); sab82532_start_tx(info); restore_flags(flags); } @@ -1108,7 +1136,7 @@ static int sab82532_write(struct tty_struct * tty, int from_user, if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) { info->interrupt_mask1 &= ~(SAB82532_IMR1_XPR); - info->regs->w.imr1 = info->interrupt_mask1; + writeb(info->interrupt_mask1, &info->regs->w.imr1); sab82532_start_tx(info); } @@ -1167,7 +1195,7 @@ static void sab82532_send_xchar(struct tty_struct *tty, char ch) save_flags(flags); cli(); sab82532_tec_wait(info); - info->regs->w.tic = ch; + writeb(ch, &info->regs->w.tic); restore_flags(flags); } @@ -1196,7 +1224,7 @@ static void sab82532_throttle(struct tty_struct * tty) sab82532_send_xchar(tty, STOP_CHAR(tty)); #if 0 if (tty->termios->c_cflag & CRTSCTS) - info->regs->rw.mode |= SAB82532_MODE_RTS; + writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_RTS, &info->regs->rw.mode); #endif } @@ -1222,7 +1250,7 @@ static void sab82532_unthrottle(struct tty_struct * tty) #if 0 if (tty->termios->c_cflag & CRTSCTS) - info->regs->rw.mode &= ~(SAB82532_MODE_RTS); + writeb(readb(&info->regs->rw.mode) & ~(SAB82532_MODE_RTS), &info->regs->rw.mode); #endif } @@ -1286,13 +1314,13 @@ static int get_modem_info(struct sab82532 * info, unsigned int *value) { unsigned int result; - result = ((info->regs->r.mode & SAB82532_MODE_RTS) ? - ((info->regs->r.mode & SAB82532_MODE_FRTS) ? 0 : TIOCM_RTS) + result = ((readb(&info->regs->r.mode) & SAB82532_MODE_RTS) ? + ((readb(&info->regs->r.mode) & SAB82532_MODE_FRTS) ? 0 : TIOCM_RTS) : TIOCM_RTS) - | ((info->regs->r.pvr & info->pvr_dtr_bit) ? 0 : TIOCM_DTR) - | ((info->regs->r.vstr & SAB82532_VSTR_CD) ? 0 : TIOCM_CAR) - | ((info->regs->r.pvr & info->pvr_dsr_bit) ? 0 : TIOCM_DSR) - | ((info->regs->r.star & SAB82532_STAR_CTS) ? TIOCM_CTS : 0); + | ((readb(&info->regs->r.pvr) & info->pvr_dtr_bit) ? 0 : TIOCM_DTR) + | ((readb(&info->regs->r.vstr) & SAB82532_VSTR_CD) ? 0 : TIOCM_CAR) + | ((readb(&info->regs->r.pvr) & info->pvr_dsr_bit) ? 0 : TIOCM_DSR) + | ((readb(&info->regs->r.star) & SAB82532_STAR_CTS) ? TIOCM_CTS : 0); return put_user(result,value); } @@ -1308,34 +1336,34 @@ static int set_modem_info(struct sab82532 * info, unsigned int cmd, switch (cmd) { case TIOCMBIS: if (arg & TIOCM_RTS) { - info->regs->rw.mode &= ~(SAB82532_MODE_FRTS); - info->regs->rw.mode |= SAB82532_MODE_RTS; + writeb(readb(&info->regs->rw.mode) & ~(SAB82532_MODE_FRTS), &info->regs->rw.mode); + writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_RTS, &info->regs->rw.mode); } if (arg & TIOCM_DTR) { - info->regs->rw.pvr &= ~(info->pvr_dtr_bit); + writeb(readb(&info->regs->rw.pvr) & ~(info->pvr_dtr_bit), &info->regs->rw.pvr); } break; case TIOCMBIC: if (arg & TIOCM_RTS) { - info->regs->rw.mode |= SAB82532_MODE_FRTS; - info->regs->rw.mode |= SAB82532_MODE_RTS; + writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_FRTS, &info->regs->rw.mode); + writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_RTS, &info->regs->rw.mode); } if (arg & TIOCM_DTR) { - info->regs->rw.pvr |= info->pvr_dtr_bit; + writeb(readb(&info->regs->rw.pvr) | info->pvr_dtr_bit, &info->regs->rw.pvr); } break; case TIOCMSET: if (arg & TIOCM_RTS) { - info->regs->rw.mode &= ~(SAB82532_MODE_FRTS); - info->regs->rw.mode |= SAB82532_MODE_RTS; + writeb(readb(&info->regs->rw.mode) & ~(SAB82532_MODE_FRTS), &info->regs->rw.mode); + writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_RTS, &info->regs->rw.mode); } else { - info->regs->rw.mode |= SAB82532_MODE_FRTS; - info->regs->rw.mode |= SAB82532_MODE_RTS; + writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_FRTS, &info->regs->rw.mode); + writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_RTS, &info->regs->rw.mode); } if (arg & TIOCM_DTR) { - info->regs->rw.pvr &= ~(info->pvr_dtr_bit); + writeb(readb(&info->regs->rw.pvr) & ~(info->pvr_dtr_bit), &info->regs->rw.pvr); } else { - info->regs->rw.pvr |= info->pvr_dtr_bit; + writeb(readb(&info->regs->rw.pvr) | info->pvr_dtr_bit, &info->regs->rw.pvr); } break; default: @@ -1363,9 +1391,9 @@ static void sab82532_break(struct tty_struct *tty, int break_state) #endif save_flags(flags); cli(); if (break_state == -1) - info->regs->rw.dafo |= SAB82532_DAFO_XBRK; + writeb(readb(&info->regs->rw.dafo) | SAB82532_DAFO_XBRK, &info->regs->rw.dafo); else - info->regs->rw.dafo &= ~(SAB82532_DAFO_XBRK); + writeb(readb(&info->regs->rw.dafo) & ~(SAB82532_DAFO_XBRK), &info->regs->rw.dafo); restore_flags(flags); } @@ -1496,19 +1524,19 @@ static void sab82532_set_termios(struct tty_struct *tty, /* Handle transition to B0 status */ if ((old_termios->c_cflag & CBAUD) && !(tty->termios->c_cflag & CBAUD)) { - info->regs->w.mode |= SAB82532_MODE_FRTS; - info->regs->w.mode |= SAB82532_MODE_RTS; - info->regs->w.pvr |= info->pvr_dtr_bit; + writeb(readb(&info->regs->w.mode) | SAB82532_MODE_FRTS, &info->regs->w.mode); + writeb(readb(&info->regs->w.mode) | SAB82532_MODE_RTS, &info->regs->w.mode); + writeb(readb(&info->regs->w.pvr) | info->pvr_dtr_bit, &info->regs->w.pvr); } /* Handle transition away from B0 status */ if (!(old_termios->c_cflag & CBAUD) && (tty->termios->c_cflag & CBAUD)) { - info->regs->w.pvr &= ~(info->pvr_dtr_bit); + writeb(readb(&info->regs->w.pvr) & ~(info->pvr_dtr_bit), &info->regs->w.pvr); if (!tty->hw_stopped || !(tty->termios->c_cflag & CRTSCTS)) { - info->regs->w.mode &= ~(SAB82532_MODE_FRTS); - info->regs->w.mode |= SAB82532_MODE_RTS; + writeb(readb(&info->regs->w.mode) & ~(SAB82532_MODE_FRTS), &info->regs->w.mode); + writeb(readb(&info->regs->w.mode) | SAB82532_MODE_RTS, &info->regs->w.mode); } } @@ -1606,9 +1634,9 @@ static void sab82532_close(struct tty_struct *tty, struct file * filp) * the receiver. */ info->interrupt_mask0 |= SAB82532_IMR0_TCD; - info->regs->w.imr0 = info->interrupt_mask0; + writeb(info->interrupt_mask0, &info->regs->w.imr0); #if 0 - info->regs->rw.mode &= ~(SAB82532_MODE_RAC); + writeb(readb(&info->regs->rw.mode) & ~(SAB82532_MODE_RAC), &info->regs->rw.mode); #endif if (info->flags & ASYNC_INITIALIZED) { /* @@ -1797,12 +1825,12 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, cli(); if (!(info->flags & ASYNC_CALLOUT_ACTIVE) && (tty->termios->c_cflag & CBAUD)) { - info->regs->rw.pvr &= ~(info->pvr_dtr_bit); - info->regs->rw.mode |= SAB82532_MODE_FRTS; - info->regs->rw.mode &= ~(SAB82532_MODE_RTS); + writeb(readb(&info->regs->rw.pvr) & ~(info->pvr_dtr_bit), &info->regs->rw.pvr); + writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_FRTS, &info->regs->rw.mode); + writeb(readb(&info->regs->rw.mode) & ~(SAB82532_MODE_RTS), &info->regs->rw.mode); } sti(); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); if (tty_hung_up_p(filp) || !(info->flags & ASYNC_INITIALIZED)) { #ifdef SERIAL_DO_RESTART @@ -1817,7 +1845,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, } if (!(info->flags & ASYNC_CALLOUT_ACTIVE) && !(info->flags & ASYNC_CLOSING) && - (do_clocal || !(info->regs->r.vstr & SAB82532_VSTR_CD))) + (do_clocal || !(readb(&info->regs->r.vstr) & SAB82532_VSTR_CD))) break; if (signal_pending(current)) { retval = -ERESTARTSYS; @@ -1825,7 +1853,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, } #ifdef SERIAL_DEBUG_OPEN printk("block_til_ready blocking: ttyS%d, count = %d, flags = %x, clocal = %d, vstr = %02x\n", - info->line, info->count, info->flags, do_clocal, info->regs->r.vstr); + info->line, info->count, info->flags, do_clocal, readb(&info->regs->r.vstr)); #endif schedule(); } @@ -1995,19 +2023,19 @@ line_info(char *buf, struct sab82532 *info) stat_buf[0] = 0; stat_buf[1] = 0; save_flags(flags); cli(); - if (info->regs->r.mode & SAB82532_MODE_RTS) { - if (!(info->regs->r.mode & SAB82532_MODE_FRTS)) + if (readb(&info->regs->r.mode) & SAB82532_MODE_RTS) { + if (!(readb(&info->regs->r.mode) & SAB82532_MODE_FRTS)) strcat(stat_buf, "|RTS"); } else { strcat(stat_buf, "|RTS"); } - if (info->regs->r.star & SAB82532_STAR_CTS) + if (readb(&info->regs->r.star) & SAB82532_STAR_CTS) strcat(stat_buf, "|CTS"); - if (!(info->regs->r.pvr & info->pvr_dtr_bit)) + if (!(readb(&info->regs->r.pvr) & info->pvr_dtr_bit)) strcat(stat_buf, "|DTR"); - if (!(info->regs->r.pvr & info->pvr_dsr_bit)) + if (!(readb(&info->regs->r.pvr) & info->pvr_dsr_bit)) strcat(stat_buf, "|DSR"); - if (!(info->regs->r.vstr & SAB82532_VSTR_CD)) + if (!(readb(&info->regs->r.vstr) & SAB82532_VSTR_CD)) strcat(stat_buf, "|CD"); restore_flags(flags); @@ -2065,7 +2093,7 @@ done: * sab82532_init() is called at boot-time to initialize the serial driver. * --------------------------------------------------------------------- */ -__initfunc(static int get_sab82532(unsigned long *memory_start)) +static int __init get_sab82532(unsigned long *memory_start) { struct linux_ebus *ebus; struct linux_ebus_device *edev = 0; @@ -2083,7 +2111,7 @@ ebus_done: if (!edev) return -ENODEV; - regs = edev->base_address[0]; + regs = edev->resource[0].start; offset = sizeof(union sab82532_async_regs); for (i = 0; i < 2; i++) { @@ -2107,16 +2135,7 @@ ebus_done: sab->xmit_fifo_size = 32; sab->recv_fifo_size = 32; - if (check_region((unsigned long)sab->regs, - sizeof(union sab82532_async_regs))) { - kfree(sab); - continue; - } - request_region((unsigned long)sab->regs, - sizeof(union sab82532_async_regs), - "serial(sab82532)"); - - sab->regs->w.ipc = SAB82532_IPC_IC_ACT_LOW; + writeb(SAB82532_IPC_IC_ACT_LOW, &sab->regs->w.ipc); sab->next = sab82532_chain; sab82532_chain = sab; @@ -2126,16 +2145,15 @@ ebus_done: return 0; } -__initfunc(static void -sab82532_kgdb_hook(int line)) +static void __init sab82532_kgdb_hook(int line) { prom_printf("sab82532: kgdb support is not implemented, yet\n"); prom_halt(); } -__initfunc(static inline void show_serial_version(void)) +static inline void __init show_serial_version(void) { - char *revision = "$Revision: 1.32 $"; + char *revision = "$Revision: 1.35 $"; char *version, *p; version = strchr(revision, ' '); @@ -2148,7 +2166,7 @@ __initfunc(static inline void show_serial_version(void)) /* * The serial driver boot-time initialization code! */ -__initfunc(int sab82532_init(void)) +int __init sab82532_init(void) { struct sab82532 *info; int i; @@ -2220,9 +2238,9 @@ __initfunc(int sab82532_init(void)) for (info = sab82532_chain, i = 0; info; info = info->next, i++) { info->magic = SERIAL_MAGIC; - info->type = info->regs->r.vstr & 0x0f; - info->regs->w.pcr = ~((1 << 1) | (1 << 2) | (1 << 4)); - info->regs->w.pim = 0xff; + info->type = readb(&info->regs->r.vstr) & 0x0f; + writeb(~((1 << 1) | (1 << 2) | (1 << 4)), &info->regs->w.pcr); + writeb(0xff, &info->regs->w.pim); if (info->line == 0) { info->pvr_dsr_bit = (1 << 0); info->pvr_dtr_bit = (1 << 1); @@ -2230,9 +2248,9 @@ __initfunc(int sab82532_init(void)) info->pvr_dsr_bit = (1 << 3); info->pvr_dtr_bit = (1 << 2); } - info->regs->w.pvr = (1 << 1) | (1 << 2) | (1 << 4); - info->regs->rw.mode |= SAB82532_MODE_FRTS; - info->regs->rw.mode |= SAB82532_MODE_RTS; + writeb((1 << 1) | (1 << 2) | (1 << 4), &info->regs->w.pvr); + writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_FRTS, &info->regs->rw.mode); + writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_RTS, &info->regs->rw.mode); info->custom_divisor = 16; info->close_delay = 5*HZ/10; @@ -2276,7 +2294,7 @@ __initfunc(int sab82532_init(void)) return 0; } -__initfunc(int sab82532_probe(unsigned long *memory_start)) +int __init sab82532_probe(unsigned long *memory_start) { int node, enode, snode; char model[32]; @@ -2340,7 +2358,6 @@ void cleanup_module(void) { unsigned long flags; int e1, e2; - int i; /* printk("Unloading %s: version %s\n", serial_name, serial_version); */ save_flags(flags); @@ -2357,12 +2374,6 @@ void cleanup_module(void) e2); restore_flags(flags); - for (i = 0; i < NR_PORTS; i++) { - struct sab82532 *info = (struct sab82532 *)sab82532_table[i]->driver_data; - if (info->type != PORT_UNKNOWN) - release_region((unsigned long)info->regs, - sizeof(union sab82532_async_regs)); - } if (tmp_buf) { free_page((unsigned long) tmp_buf); tmp_buf = NULL; @@ -2379,7 +2390,7 @@ sab82532_console_putchar(struct sab82532 *info, char c) save_flags(flags); cli(); sab82532_tec_wait(info); - info->regs->w.tic = c; + writeb(c, &info->regs->w.tic); restore_flags(flags); } @@ -2445,12 +2456,12 @@ sab82532_console_setup(struct console *con, char *options) */ info->interrupt_mask0 = SAB82532_IMR0_PERR | SAB82532_IMR0_FERR | SAB82532_IMR0_PLLA | SAB82532_IMR0_CDSC; - info->regs->w.imr0 = info->interrupt_mask0; + writeb(info->interrupt_mask0, &info->regs->w.imr0); info->interrupt_mask1 = SAB82532_IMR1_BRKT | SAB82532_IMR1_ALLS | SAB82532_IMR1_XOFF | SAB82532_IMR1_TIN | SAB82532_IMR1_CSC | SAB82532_IMR1_XON | SAB82532_IMR1_XPR; - info->regs->w.imr1 = info->interrupt_mask1; + writeb(info->interrupt_mask1, &info->regs->w.imr1); printk("Console: ttyS%d (SAB82532)\n", info->line); @@ -2524,24 +2535,24 @@ sab82532_console_setup(struct console *con, char *options) info->flags |= ASYNC_CHECK_CD; save_flags(flags); cli(); - if (info->regs->r.star & SAB82532_STAR_CEC) + if (readb(&info->regs->r.star) & SAB82532_STAR_CEC) udelay(1); sab82532_tec_wait(info); - info->regs->w.dafo = dafo; - info->regs->w.bgr = ebrg & 0xff; - info->regs->rw.ccr2 &= ~(0xc0); - info->regs->rw.ccr2 |= (ebrg >> 2) & 0xc0; + writeb(dafo, &info->regs->w.dafo); + writeb(ebrg & 0xff, &info->regs->w.bgr); + writeb(readb(&info->regs->rw.ccr2) & ~(0xc0), &info->regs->rw.ccr2); + writeb(readb(&info->regs->rw.ccr2) | ((ebrg >> 2) & 0xc0), &info->regs->rw.ccr2); if (info->flags & ASYNC_CTS_FLOW) { - info->regs->rw.mode &= ~(SAB82532_MODE_RTS); - info->regs->rw.mode |= SAB82532_MODE_FRTS; - info->regs->rw.mode &= ~(SAB82532_MODE_FCTS); + writeb(readb(&info->regs->rw.mode) & ~(SAB82532_MODE_RTS), &info->regs->rw.mode); + writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_FRTS, &info->regs->rw.mode); + writeb(readb(&info->regs->rw.mode) & ~(SAB82532_MODE_FCTS), &info->regs->rw.mode); } else { - info->regs->rw.mode |= SAB82532_MODE_RTS; - info->regs->rw.mode &= ~(SAB82532_MODE_FRTS); - info->regs->rw.mode |= SAB82532_MODE_FCTS; + writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_RTS, &info->regs->rw.mode); + writeb(readb(&info->regs->rw.mode) & ~(SAB82532_MODE_FRTS), &info->regs->rw.mode); + writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_FCTS, &info->regs->rw.mode); } - info->regs->rw.pvr &= ~(info->pvr_dtr_bit); - info->regs->rw.mode |= SAB82532_MODE_RAC; + writeb(~(info->pvr_dtr_bit), &info->regs->rw.pvr); + writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_RAC, &info->regs->rw.mode); restore_flags(flags); return 0; @@ -2561,7 +2572,7 @@ static struct console sab82532_console = { NULL }; -__initfunc(int sab82532_console_init(void)) +int __init sab82532_console_init(void) { extern int con_is_present(void); diff --git a/drivers/sbus/char/su.c b/drivers/sbus/char/su.c index b1c95163c..21596e2cf 100644 --- a/drivers/sbus/char/su.c +++ b/drivers/sbus/char/su.c @@ -1,4 +1,4 @@ -/* $Id: su.c,v 1.22 1999/07/03 08:57:43 davem Exp $ +/* $Id: su.c,v 1.28 1999/09/01 08:09:32 davem Exp $ * su.c: Small serial driver for keyboard/mouse interface on sparc32/PCI * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -1965,7 +1965,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp, serial_inp(info, UART_MCR) | (UART_MCR_DTR | UART_MCR_RTS)); restore_flags(flags); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); if (tty_hung_up_p(filp) || !(info->flags & ASYNC_INITIALIZED)) { #ifdef SERIAL_DO_RESTART @@ -2212,9 +2212,9 @@ done: * number, and identifies which options were configured into this * driver. */ -__initfunc(static __inline__ void show_su_version(void)) +static __inline__ void __init show_su_version(void) { - char *revision = "$Revision: 1.22 $"; + char *revision = "$Revision: 1.28 $"; char *version, *p; version = strchr(revision, ' '); @@ -2251,11 +2251,7 @@ autoconfig(struct su_struct *info) for_each_ebus(ebus) { for_each_ebusdev(dev, ebus) { if (dev->prom_node == info->port_node) { - info->port = dev->base_address[0]; -#ifdef __sparc_v9__ - if (check_region(info->port, 8)) - return; -#endif + info->port = dev->resource[0].start; info->irq = dev->irqs[0]; goto ebus_done; } @@ -2400,10 +2396,6 @@ ebus_done: sprintf(info->name, "su(%s)", su_typev[info->port_type]); -#ifdef __sparc_v9__ - request_region(info->port, 8, info->name); -#endif - /* * Reset the UART. */ @@ -2418,7 +2410,7 @@ ebus_done: /* * The serial driver boot-time initialization code! */ -__initfunc(int su_serial_init(void)) +int __init su_serial_init(void) { int i; struct su_struct *info; @@ -2516,7 +2508,7 @@ __initfunc(int su_serial_init(void)) return 0; } -__initfunc(int su_kbd_ms_init(void)) +int __init su_kbd_ms_init(void) { int i; struct su_struct *info; @@ -2541,7 +2533,7 @@ __initfunc(int su_kbd_ms_init(void)) if (info->type == PORT_UNKNOWN) continue; - printk(KERN_INFO "%s at %16lx (irq = %s) is a %s\n", + printk(KERN_INFO "%s at 0x%lx (irq = %s) is a %s\n", info->name, info->port, __irq_itoa(info->irq), uart_config[info->type].name); @@ -2559,7 +2551,7 @@ __initfunc(int su_kbd_ms_init(void)) * of device tree. 'su' may be found under obio, ebus, isa and pci. * We walk over the tree and find them wherever PROM hides them. */ -__initfunc(void su_probe_any(struct su_probe_scan *t, int sunode)) +void __init su_probe_any(struct su_probe_scan *t, int sunode) { struct su_struct *info; int len; @@ -2590,7 +2582,7 @@ __initfunc(void su_probe_any(struct su_probe_scan *t, int sunode)) } } -__initfunc(int su_probe (unsigned long *memory_start)) +int __init su_probe (unsigned long *memory_start) { int node; int len; @@ -2792,7 +2784,7 @@ serial_console_device(struct console *c) * - initialize the serial port * Return non-zero if we didn't find a serial port. */ -__initfunc(static int serial_console_setup(struct console *co, char *options)) +static int __init serial_console_setup(struct console *co, char *options) { struct su_struct *info; unsigned cval; @@ -2915,7 +2907,7 @@ static struct console sercons = { /* * Register console. */ -__initfunc(int su_serial_console_init(void)) +int __init su_serial_console_init(void) { extern int con_is_present(void); diff --git a/drivers/sbus/char/sunkbd.c b/drivers/sbus/char/sunkbd.c index 7a403a3da..e8e6a168c 100644 --- a/drivers/sbus/char/sunkbd.c +++ b/drivers/sbus/char/sunkbd.c @@ -79,11 +79,6 @@ extern void scrollfront(int); struct l1a_kbd_state l1a_state = { 0, 0 }; -/* Dummy function for now, we need it to link. -DaveM */ -void kbd_reset_setup(char *str, int *ints) -{ -} - #ifndef CONFIG_PCI DECLARE_WAIT_QUEUE_HEAD(keypress_wait); #endif @@ -1217,7 +1212,7 @@ static void sunkbd_kd_mksound(unsigned int hz, unsigned int ticks) extern void (*kd_mksound)(unsigned int hz, unsigned int ticks); -__initfunc(int sun_kbd_init(void)) +int __init sun_kbd_init(void) { int i, opt_node; struct kbd_struct kbd0; @@ -1305,7 +1300,7 @@ kbd_read (struct file *f, char *buffer, size_t count, loff_t *ppos) p = buffer; for (; p < end && kbd_head != kbd_tail;){ #ifdef CONFIG_SPARC32_COMPAT - if (current->tss.flags & SPARC_FLAG_32BIT) { + if (current->thread.flags & SPARC_FLAG_32BIT) { copy_to_user_ret((Firm_event *)p, &kbd_queue [kbd_tail], sizeof(Firm_event)-sizeof(struct timeval), -EFAULT); p += sizeof(Firm_event)-sizeof(struct timeval); @@ -1507,7 +1502,7 @@ file_operations kbd_fops = NULL, /* revalidate */ }; -__initfunc(void keyboard_zsinit(void (*put_char)(unsigned char))) +void __init keyboard_zsinit(void (*put_char)(unsigned char)) { int timeout = 0; diff --git a/drivers/sbus/char/sunmouse.c b/drivers/sbus/char/sunmouse.c index 1c71ea53c..77fe2ee77 100644 --- a/drivers/sbus/char/sunmouse.c +++ b/drivers/sbus/char/sunmouse.c @@ -69,7 +69,7 @@ struct sun_mouse { unsigned char prev_state; /* Previous button state */ int delta_x; /* Current delta-x */ int delta_y; /* Current delta-y */ - int present; + int present; int ready; /* set if there if data is available */ int active; /* set if device is open */ int vuid_mode; /* VUID_NATIVE or VUID_FIRM_EVENT */ @@ -170,11 +170,16 @@ void mouse_baud_detection(unsigned char c) static int ctr = 0; if(wait_for_synchron) { - if((c < 0x80) || (c > 0x87)) + if((c & ~0x0f) != 0x80) mouse_bogon_bytes++; else { - ctr = 0; - wait_for_synchron = 0; + if (c & 8) { + ctr = 2; + wait_for_synchron = 0; + } else { + ctr = 0; + wait_for_synchron = 0; + } } } else { ctr++; @@ -212,6 +217,11 @@ sun_mouse_inbyte(unsigned char byte) mouse_baud_detection(byte); if (!gen_events){ + if (((byte & ~0x0f) == 0x80) && (byte & 0x8)) { + /* Push dummy 4th and 5th byte for last txn */ + push_char(0x0); + push_char(0x0); + } push_char (byte); return; } @@ -220,7 +230,7 @@ sun_mouse_inbyte(unsigned char byte) * we are starting at byte zero in the transaction * protocol. */ - if(byte >= 0x80 && byte <= 0x87) + if((byte & ~0x0f) == 0x80) sunmouse.byte = 0; mvalue = (signed char) byte; @@ -234,6 +244,12 @@ sun_mouse_inbyte(unsigned char byte) ((sunmouse.button_state & 0x2) ? "DOWN" : "UP"), ((sunmouse.button_state & 0x1) ? "DOWN" : "UP")); #endif + /* To deal with the Sparcbook 3 */ + if (byte & 0x8) { + sunmouse.byte += 2; + sunmouse.delta_y = 0; + sunmouse.delta_x = 0; + } sunmouse.byte++; return; case 1: @@ -386,7 +402,7 @@ sun_mouse_read(struct file *file, char *buffer, while (p < end && !queue_empty ()){ #ifdef CONFIG_SPARC32_COMPAT - if (current->tss.flags & SPARC_FLAG_32BIT) { + if (current->thread.flags & SPARC_FLAG_32BIT) { Firm_event *q = get_from_queue(); copy_to_user_ret((Firm_event *)p, q, @@ -492,7 +508,7 @@ static struct miscdevice sun_mouse_mouse = { SUN_MOUSE_MINOR, "sunmouse", &sun_mouse_fops }; -__initfunc(int sun_mouse_init(void)) +int __init sun_mouse_init(void) { if (!sunmouse.present) return -ENODEV; diff --git a/drivers/sbus/char/sunserial.c b/drivers/sbus/char/sunserial.c index 075062cf1..60ff763e6 100644 --- a/drivers/sbus/char/sunserial.c +++ b/drivers/sbus/char/sunserial.c @@ -1,4 +1,4 @@ -/* $Id: sunserial.c,v 1.68 1998/12/09 18:53:51 davem Exp $ +/* $Id: sunserial.c,v 1.70 1999/09/04 20:28:17 davem Exp $ * serial.c: Serial port driver infrastructure for the Sparc. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -20,13 +20,12 @@ int serial_console; -__initfunc(int con_is_present(void)) +int __init con_is_present(void) { return serial_console ? 0 : 1; } -__initfunc(static void -nop_rs_kgdb_hook(int channel)) +static void __init nop_rs_kgdb_hook(int channel) { printk("Oops: %s called\n", __FUNCTION__); } @@ -63,13 +62,12 @@ int rs_init(void) return err; } -__initfunc(void -rs_kgdb_hook(int channel)) +void __init rs_kgdb_hook(int channel) { rs_ops.rs_kgdb_hook(channel); } -__initfunc(long serial_console_init(long kmem_start, long kmem_end)) +long __init serial_console_init(long kmem_start, long kmem_end) { return kmem_start; } @@ -352,8 +350,7 @@ extern int sab82532_probe(unsigned long *); extern int ps2kbd_probe(unsigned long *); #endif -__initfunc(unsigned long -sun_serial_setup(unsigned long memory_start)) +unsigned long __init sun_serial_setup(unsigned long memory_start) { int ret = 1; @@ -389,12 +386,10 @@ sun_serial_setup(unsigned long memory_start)) * So be very careful not to probe for keyboards if we are on a * serial console. */ - if (!serial_console) { - if (ps2kbd_probe(&memory_start) == 0) - return memory_start; - if (su_probe(&memory_start) == 0) - return memory_start; - } + if (!serial_console) + ps2kbd_probe(&memory_start); + if (su_probe(&memory_start) == 0) + return memory_start; #endif if (!ret) diff --git a/drivers/sbus/char/uctrl.c b/drivers/sbus/char/uctrl.c new file mode 100644 index 000000000..b11de29eb --- /dev/null +++ b/drivers/sbus/char/uctrl.c @@ -0,0 +1,155 @@ +/* $Id: uctrl.c,v 1.2 1999/09/07 23:11:08 shadow Exp $ + * uctrl.c: TS102 Microcontroller interface on Tadpole Sparcbook 3 + * + * Copyright 1999 Derrick J Brashear (shadow@dementia.org) + */ + +#include <linux/config.h> +#include <linux/module.h> +#include <linux/sched.h> +#include <linux/errno.h> +#include <linux/delay.h> +#include <linux/interrupt.h> +#include <linux/malloc.h> +#include <linux/ioport.h> +#include <linux/init.h> +#include <linux/miscdevice.h> +#include <linux/mm.h> + +#include <asm/openprom.h> +#include <asm/oplib.h> +#include <asm/system.h> +#include <asm/irq.h> +#include <asm/io.h> +#include <asm/pgtable.h> +#include <asm/sbus.h> + +#define UCTRL_MINOR 174 + +struct uctrl_driver { + volatile u32 *regs; + int irq; +}; + +static struct uctrl_driver drv; + +static loff_t +uctrl_llseek(struct file *file, loff_t offset, int type) +{ + return -ESPIPE; +} + +static int +uctrl_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + switch (cmd) { + default: + return -EINVAL; + } + return 0; +} + +static int +uctrl_open(struct inode *inode, struct file *file) +{ + MOD_INC_USE_COUNT; + return 0; +} + +static int +uctrl_release(struct inode *inode, struct file *file) +{ + MOD_DEC_USE_COUNT; + return 0; +} + +void uctrl_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct uctrl_driver *driver = (struct uctrl_driver *)dev_id; + printk("in uctrl_interrupt\n"); +} + +static struct file_operations uctrl_fops = { + uctrl_llseek, + NULL, /* read */ + NULL, /* write */ + NULL, /* readdir */ + NULL, /* poll */ + uctrl_ioctl, + NULL, /* mmap */ + uctrl_open, + NULL, /* flush */ + uctrl_release +}; + +static struct miscdevice uctrl_dev = { + UCTRL_MINOR, + "uctrl", + &uctrl_fops +}; + +#ifdef MODULE +int init_module(void) +#else +__initfunc(int uctrl_init(void)) +#endif +{ + struct uctrl_driver *driver = &drv; + int len; + struct linux_prom_irqs tmp_irq[2]; + unsigned int vaddr[2] = { 0, 0 }; + int tmpnode, uctrlnode = prom_getchild(prom_root_node); + + tmpnode = prom_searchsiblings(uctrlnode, "obio"); + + if (tmpnode) + uctrlnode = prom_getchild(tmpnode); + + uctrlnode = prom_searchsiblings(uctrlnode, "uctrl"); + + if (!uctrlnode) + return -ENODEV; + + /* the prom mapped it for us */ + len = prom_getproperty(uctrlnode, "address", (void *) vaddr, + sizeof(vaddr)); + driver->regs = vaddr[0]; + + len = prom_getproperty(uctrlnode, "intr", (char *) tmp_irq, + sizeof(tmp_irq)); + if(!driver->irq) + driver->irq = tmp_irq[0].pri; + + request_irq(driver->irq, uctrl_interrupt, 0, + "uctrl", driver); + + enable_irq(driver->irq); + + if (misc_register(&uctrl_dev)) { + printk("%s: unable to get misc minor %d\n", + __FUNCTION__, uctrl_dev.minor); + disable_irq(driver->irq); + free_irq(driver->irq, driver); + return -ENODEV; + } + + printk(KERN_INFO, "uctrl: 0x%x (irq %d)\n", driver->regs, __irq_itoa(driver->irq)); + return 0; +} + + +#ifdef MODULE +void cleanup_module(void) +{ + struct uctrl_driver *driver = &drv; + + misc_deregister(&uctrl_dev); + if (driver->irq) { + disable_irq(driver->irq); + free_irq(driver->irq, driver); + } + if (driver->regs) + driver->regs = 0; +} +#endif diff --git a/drivers/sbus/char/zs.c b/drivers/sbus/char/zs.c index 977161435..8ed6e2737 100644 --- a/drivers/sbus/char/zs.c +++ b/drivers/sbus/char/zs.c @@ -1,4 +1,4 @@ -/* $Id: zs.c,v 1.42 1999/05/12 11:15:26 davem Exp $ +/* $Id: zs.c,v 1.45 1999/09/01 08:09:35 davem Exp $ * zs.c: Zilog serial port driver for the Sparc. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -1711,7 +1711,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, if (!(info->flags & ZILOG_CALLOUT_ACTIVE)) zs_rtsdtr(info, 1); sti(); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); if (tty_hung_up_p(filp) || !(info->flags & ZILOG_INITIALIZED)) { #ifdef SERIAL_DEBUG_OPEN @@ -1844,7 +1844,7 @@ int zs_open(struct tty_struct *tty, struct file * filp) static void show_serial_version(void) { - char *revision = "$Revision: 1.42 $"; + char *revision = "$Revision: 1.45 $"; char *version, *p; version = strchr(revision, ' '); @@ -1862,8 +1862,7 @@ static void show_serial_version(void) * we have a special version for sun4u. */ #ifdef __sparc_v9__ -__initfunc(static struct sun_zslayout * -get_zs(int chip)) +static struct sun_zslayout * __init get_zs(int chip) { unsigned int vaddr[2] = { 0, 0 }; unsigned long mapped_addr = 0; @@ -1971,8 +1970,7 @@ get_zs(int chip)) return (struct sun_zslayout *) (unsigned long) vaddr[0]; } #else /* !(__sparc_v9__) */ -__initfunc(static struct sun_zslayout * -get_zs(int chip)) +static struct sun_zslayout * __init get_zs(int chip) { struct linux_prom_irqs tmp_irq[2]; unsigned int paddr = 0; @@ -2012,9 +2010,8 @@ get_zs(int chip)) /* Can use the prom for other machine types */ zsnode = prom_getchild(prom_root_node); if (sparc_cpu_model == sun4d) { - int node; int no = 0; - + tmpnode = zsnode; zsnode = 0; bbnode = 0; @@ -2113,7 +2110,7 @@ void zs_change_mouse_baud(int newbaud) write_zsreg(zs_soft[channel].zs_channel, R13, ((brg >> 8) & 0xff)); } -__initfunc(int zs_probe (unsigned long *memory_start)) +int __init zs_probe (unsigned long *memory_start) { char *p; int node; @@ -2266,7 +2263,7 @@ static inline void zs_prepare(void) restore_flags(flags); } -__initfunc(int zs_init(void)) +int __init zs_init(void) { int channel, brg, i; unsigned long flags; @@ -2535,8 +2532,7 @@ __initfunc(int zs_init(void)) * for /dev/ttyb which is determined in setup_arch() from the * boot command line flags. */ -__initfunc(static void -zs_kgdb_hook(int tty_num)) +static void __init zs_kgdb_hook(int tty_num) { int chip = 0; @@ -2648,8 +2644,7 @@ static kdev_t zs_console_device(struct console *con) return MKDEV(TTY_MAJOR, 64 + con->index); } -__initfunc(static int -zs_console_setup(struct console *con, char *options)) +static int __init zs_console_setup(struct console *con, char *options) { struct sun_serial *info; int i, brg, baud; @@ -2730,8 +2725,7 @@ static struct console zs_console = { NULL }; -__initfunc(static int -zs_console_init(void)) +static int __init zs_console_init(void) { extern int con_is_present(void); diff --git a/drivers/sbus/dvma.c b/drivers/sbus/dvma.c index cf60be798..e5e5a655d 100644 --- a/drivers/sbus/dvma.c +++ b/drivers/sbus/dvma.c @@ -29,8 +29,7 @@ dump_dma_regs(struct sparc_dma_registers *dregs) return; } -__initfunc(void -init_one_dvma(struct Linux_SBus_DMA *dma, int num_dma)) +void __init init_one_dvma(struct Linux_SBus_DMA *dma, int num_dma) { printk("dma%d: ", num_dma); @@ -75,8 +74,7 @@ init_one_dvma(struct Linux_SBus_DMA *dma, int num_dma)) } /* Probe this SBus DMA module(s) */ -__initfunc(void -dvma_init(struct linux_sbus *sbus)) +void __init dvma_init(struct linux_sbus *sbus) { struct linux_sbus_device *this_dev; struct Linux_SBus_DMA *dma; @@ -133,7 +131,7 @@ dvma_init(struct linux_sbus *sbus)) #include <asm/sun4paddr.h> -__initfunc(void sun4_dvma_init(void)) +void __init sun4_dvma_init(void) { struct Linux_SBus_DMA *dma; struct Linux_SBus_DMA *dchain; diff --git a/drivers/sbus/sbus.c b/drivers/sbus/sbus.c index 8b18c6875..ad7825c89 100644 --- a/drivers/sbus/sbus.c +++ b/drivers/sbus/sbus.c @@ -1,4 +1,4 @@ -/* $Id: sbus.c,v 1.77 1999/05/29 06:25:57 davem Exp $ +/* $Id: sbus.c,v 1.80 1999/09/02 05:44:33 shadow Exp $ * sbus.c: SBus support routines. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -40,8 +40,7 @@ extern void prom_sbus_ranges_init (int, struct linux_sbus *); /* #define DEBUG_FILL */ -__initfunc(static void -fill_sbus_device(int nd, struct linux_sbus_device *sbus_dev)) +static void __init fill_sbus_device(int nd, struct linux_sbus_device *sbus_dev) { int grrr, len; unsigned long dev_base_addr, base; @@ -209,10 +208,13 @@ extern int flash_init(void); #ifdef CONFIG_SUN_AURORA extern int aurora_init(void); #endif +#ifdef CONFIG_TADPOLE_TS102_UCTRL +extern int ts102_uctrl_init(void); +#endif -__initfunc(static void -sbus_do_child_siblings(int start_node, struct linux_sbus_device *child, - struct linux_sbus *sbus)) +static void __init sbus_do_child_siblings(int start_node, + struct linux_sbus_device *child, + struct linux_sbus *sbus) { struct linux_sbus_device *this_dev = child; int this_node = start_node; @@ -240,7 +242,7 @@ sbus_do_child_siblings(int start_node, struct linux_sbus_device *child, } } -__initfunc(void sbus_init(void)) +void __init sbus_init(void) { register int nd, this_sbus, sbus_devs, topnd, iommund; unsigned int sbus_clock; @@ -446,6 +448,9 @@ __initfunc(void sbus_init(void)) #ifdef CONFIG_SUN_AURORA aurora_init(); #endif +#ifdef CONFIG_TADPOLE_TS102_UCTRL + ts102_uctrl_init(); +#endif #ifdef __sparc_v9__ if (sparc_cpu_model == sun4u) { extern void clock_probe(void); |