Writing to CMOS RAM

tom@zapata.demon.co.uk
Wed, 3 Jun 1998 10:00:44 GMT


1) I've managed (in a very ugly way) to write to the CMOS RAM
on a Toshiba Libretto. This is a usefull thing to do because the
Libretto stores settings for things like Alarm Power On Enble/Disable
and Alarm Power On Time in the CMOS RAM and setting the correct
bytes and bits changes the settings.

I've used the format of nvram.c code to read the data as /dev/libretto_cmos
and /proc/libretto_cmos. I can write and alter the settings in the
read_proc_info
procedure (I said it was ugly) but not in the write_proc_info procedure or the
file_ops write procedure.

Does anyone know why this is so?

An extract is appended below.

2) I'm not sure how to read and set the checksum so I just don't do it
which obviously gives errros on reboot or waking from hiberbate.
The CMOS RAM I am wrting to starts at the bytes which are offset
50 above the RTC RAM ie. where nvram.c stops.

Thanks for any help.

--------------------------------
//////////////////
// doesn't work //
//////////////////

static int libretto_cmos_write_proc( struct file * file, const char
*buffer, unsigned long count,void *data)
{
unsigned long flags;
unsigned i=0 ;
unsigned char val;
const char *tmp = buffer;
char c;
unsigned char contents[LIBRETTO_CMOS_BYTES];

//printk(KERN_NOTICE "in cmos write count:%d\n",count);

save_flags(flags);
cli();

// if (!libretto_cmos_check_checksum_int()) {
// restore_flags(flags);
// return( -EIO );
// }

for( i = 0; i < LIBRETTO_CMOS_BYTES; ++i )
contents[i] = libretto_cmos_read_int( i );

for( ; count-- > 0 ; ++tmp ) {
get_user( c, tmp );
// printk(KERN_NOTICE "cmos:i:%d c:%c \n", i, c);
switch (c){
case 'a':{
// printk(KERN_NOTICE "cmos:case a c:%c \n", c);
val = contents[ ALARM_BYTE ];
// printk(KERN_NOTICE "cmos:val:%d \n", val);
set_bit(ALARM_BIT,&val);
// printk(KERN_NOTICE "cmos:val:%d \n", val);
libretto_cmos_write_int(val,ALARM_BYTE);
libretto_cmos_write_int(1,1);//BCD hour for alarm = 01
libretto_cmos_write_int(0,2);//minute=0
val = libretto_cmos_read_int( ALARM_BYTE );
// printk(KERN_NOTICE "cmos:val:%d \n", val);

}
case 'b':{
val = contents[ ALARM_BYTE ];
clear_bit(ALARM_BIT,&val);
libretto_cmos_write_int(val,ALARM_BYTE);
}
}
}
// libretto_cmos_set_checksum_int();

restore_flags(flags);
return( tmp - buffer );
}

////////////////
// this works //
////////////////

static int libretto_cmos_read_proc( char *buffer, char **start, off_t offset,
int size, int *eof, void *data )
{
unsigned long flags;
unsigned char contents[LIBRETTO_CMOS_BYTES];
int i, len = 0;
off_t begin = 0;

save_flags(flags);
cli();
for( i = 0; i < LIBRETTO_CMOS_BYTES; ++i )
contents[i] = libretto_cmos_read_int( i );
libretto_cmos_write_int(209,0); //power on alarm enabled
//panel power on/off set
//auto off 10mins
libretto_cmos_write_int(1,1);//BCD hour for alarm = 01
libretto_cmos_write_int(0,2);//minute=0
restore_flags(flags);

*eof = proc_infos( contents, buffer, &len, &begin, offset, size );

if (offset >= begin + len)
return( 0 );
*start = buffer + (begin - offset);
return( size < begin + len - offset ? size : begin + len - offset );

}

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu