/* * NVRAM WakeUp * Copyright (C) 2001-2004, Sergei Haller. * * $Id: nvramops.c 682 2004-05-03 22:40:13Z bistr-o-math $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include #include #include #include #include #include #include #include "nvram-wakeup.h" int fd_rtc, fd_nvram; void open_nvram(int _directisa, int mode) { if (_directisa == OFF) { char mode_str[10]; switch (mode) { case O_RDONLY: sprintf(mode_str, "O_RDONLY"); break; case O_WRONLY: sprintf(mode_str, "O_WRONLY"); break; default: sprintf(mode_str, "%d", mode); break; } /* open the nvram device */ nvprintf(LOG_DEBUG, "Opening %s in %s mode...\n", NVRAM_DEV, mode_str); fd_nvram = open(NVRAM_DEV, mode); if (fd_nvram == -1) { nvprintf(LOG_ERR, "%s: %m\n", NVRAM_DEV); exit(2); } } else { /* get permission */ nvprintf(LOG_DEBUG, "Requesting permissions for io ports 0x70...0x75\n"); if (ioperm(0x70, 6, 1) == -1) { nvprintf(LOG_ERR, "An error occurred while requesting permissions: %m\n"); exit(2); } } } void close_nvram(int _directisa) { if (_directisa == OFF) { /* close the nvram device again */ close(fd_nvram); } else { /* release ports */ ioperm( 0x70, 4, 0 ); } } int read_whole_nvram(int _directisa, int upper_method, unsigned char * bytes) { int addr; char reg_A; int nvramSize = 0; if (_directisa == OFF) { /* Now we read whole nvram ... */ lseek(fd_nvram, 0, SEEK_SET); /* just to be sure we are at the beginning */ nvramSize = read(fd_nvram, bytes, MAXNVRAMSIZE); if (nvramSize < 0) { nvprintf(LOG_ERR, "An error occurred while reading nvram: %m\n"); exit(2); } } else /* if (_directisa == ON) */ { for(addr=0;addr<=13;addr++) { outb(addr, 0x70); bytes[addr+114] = inb(0x71); } for(addr=14;addr<=127;addr++) { outb(addr, 0x70); bytes[addr-14] = inb(0x71); } switch (upper_method) { case OFF: nvramSize = 128; break; case INTEL: for(addr=0;addr<=127;addr++) { outb(addr, 0x72); bytes[addr+128] = inb(0x73); } nvramSize = 256; break; case DS1685: reg_A = bytes[0xA+114]; outb(0xA, 0x70); outb(reg_A | 0x10, 0x71); /* set bit 4 of register A and enable upper nvram access */ for(addr=0;addr<=127;addr++) { outb(addr, 0x70); bytes[addr+128] = inb(0x71); } outb(0xA, 0x70); outb(reg_A, 0x71); /* restore contents of register A */ nvramSize = 256; break; case VT82Cxxx: for(addr=128;addr<=255;addr++) { outb(addr, 0x72); bytes[addr] = inb(0x73); } nvramSize = 256; break; case VT8235_37: for(addr=128;addr<=255;addr++) { outb(addr, 0x74); bytes[addr] = inb(0x75); } nvramSize = 256; break; default: nvramSize = 128; break; } } nvprintf(LOG_DEBUG, "The size of NVRAM is %u bytes.\n", nvramSize); return nvramSize; } void write_back(int _directisa, int upper_method, int addr, unsigned char * bytes) { int retval; char reg_A = bytes[0xA+114]; nvprintf(LOG_DEBUG, "Writing value 0x%02X into byte 0x%02X of NVRAM\n", bytes[addr], addr); if (_directisa == OFF) { lseek(fd_nvram, addr, SEEK_SET); retval = write(fd_nvram, &bytes[addr], 1); if (retval != 1) { nvprintf(LOG_CRIT, "Error occurred while writing byte 0x%02X of %s: %m\n", addr, NVRAM_DEV); exit(2); } } else /* _directisa == ON */ { if (addr<114) { outb(addr+14, 0x70); outb(bytes[addr], 0x71); } else if (addr<128) { outb(addr-114, 0x70); outb(bytes[addr], 0x71); } /* upper nvram needs special treatment */ else switch (upper_method) { case INTEL: outb(addr-128, 0x72); outb(bytes[addr], 0x73); break; case DS1685: outb(0xA, 0x70); outb(reg_A | 0x10, 0x71); /* set bit 4 of register A and enable upper nvram access */ outb(addr-128, 0x70); outb(bytes[addr], 0x71); outb(0xA, 0x70); outb(reg_A, 0x71); /* restore contents of register A */ break; case VT82Cxxx: outb(addr, 0x72); outb(bytes[addr], 0x73); break; case VT8235_37: outb(addr, 0x74); outb(bytes[addr], 0x75); break; } } }