summaryrefslogtreecommitdiffstats
path: root/drivers/sbus
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/sbus')
-rw-r--r--drivers/sbus/audio/.cvsignore2
-rw-r--r--drivers/sbus/audio/amd7930.c270
-rw-r--r--drivers/sbus/audio/audio.c288
-rw-r--r--drivers/sbus/audio/cs4231.c157
-rw-r--r--drivers/sbus/audio/cs4231.h10
-rw-r--r--drivers/sbus/audio/dbri.c15
-rw-r--r--drivers/sbus/audio/dmy.c2
-rw-r--r--drivers/sbus/char/Config.in3
-rw-r--r--drivers/sbus/char/Makefile8
-rw-r--r--drivers/sbus/char/aurora.c2
-rw-r--r--drivers/sbus/char/bpp.c24
-rw-r--r--drivers/sbus/char/envctrl.c1373
-rw-r--r--drivers/sbus/char/flash.c45
-rw-r--r--drivers/sbus/char/openprom.c2
-rw-r--r--drivers/sbus/char/pcikbd.c52
-rw-r--r--drivers/sbus/char/rtc.c27
-rw-r--r--drivers/sbus/char/sab82532.c383
-rw-r--r--drivers/sbus/char/su.c32
-rw-r--r--drivers/sbus/char/sunkbd.c11
-rw-r--r--drivers/sbus/char/sunmouse.c30
-rw-r--r--drivers/sbus/char/sunserial.c25
-rw-r--r--drivers/sbus/char/uctrl.c155
-rw-r--r--drivers/sbus/char/zs.c28
-rw-r--r--drivers/sbus/dvma.c8
-rw-r--r--drivers/sbus/sbus.c19
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(&current->sigmask_lock);
+ siginitsetinv(&current->blocked, sigmask(SIGKILL));
+ recalc_sigpending(current);
+ spin_unlock_irq(&current->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(&current->sigmask_lock);
+ flush_signals(current);
+ spin_unlock_irq(&current->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);