ppc64: Don't set Kp bit on SLB
[openbios/afaerber.git] / utils / devbios / filesystem.c
blob0dab71128684d29abe16729603fcde07fca9f815
1 /*
2 * OpenBIOS - free your system!
3 * ( firmware/flash device driver for Linux )
4 *
5 * filesystem.c - vfs character device interface
6 *
7 * This program is part of a free implementation of the IEEE 1275-1994
8 * Standard for Boot (Initialization Configuration) Firmware.
10 * Copyright (C) 1998-2004 Stefan Reinauer, <stepan@openbios.org>
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; version 2 of the License.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
27 #include <linux/config.h>
28 #include <linux/version.h>
29 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) && defined(MODVERSIONS)
30 #include <linux/modversions.h>
31 #endif
32 #include <linux/module.h>
33 #include <linux/errno.h>
34 #include <linux/types.h>
35 #include <linux/vmalloc.h>
36 #include <linux/fcntl.h>
37 #include <linux/delay.h>
39 #include <asm/uaccess.h>
41 #include "bios.h"
42 #include "flashchips.h"
43 #include "pcisets.h"
44 #include "programming.h"
46 #ifdef MODULE
47 void inc_mod(void);
48 void dec_mod(void);
49 #endif
52 * ******************************************
54 * /dev/bios filesystem operations
56 * ******************************************
59 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
60 #define FDEV (MINOR(file->f_dentry->d_inode->i_rdev))
61 #else
62 #define FDEV (iminor(file->f_dentry->d_inode))
63 #endif
64 #define CFLASH flashdevices[FDEV]
65 // #define BIOS_SIZE ((flashchips[CFLASH.flashnum].size)*1024)
66 #define BIOS_SIZE (CFLASH.size)
68 static loff_t bios_llseek(struct file *file, loff_t offset, int origin )
70 currflash=FDEV;
71 switch(origin) {
72 case 0:
73 break;
74 case 1:
75 offset += file->f_pos;
76 break;
77 case 2:
78 offset += BIOS_SIZE;
79 break;
81 return((offset >= 0)?(file->f_pos = offset):-EINVAL);
84 static ssize_t bios_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
86 signed int size=((BIOS_SIZE-*ppos>count) ? count : BIOS_SIZE-*ppos);
87 unsigned char *addr = (unsigned char*)CFLASH.mapped + CFLASH.offset;
88 int i;
90 currflash = FDEV;
92 devices[flashdevices[currflash].idx].activate();
94 for (i=0;i<size;i++)
95 buffer[i]=flash_readb(addr,*ppos+i);
97 devices[flashdevices[currflash].idx].deactivate();
99 *ppos+=size;
100 return size;
103 static ssize_t bios_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
105 unsigned long flags;
106 unsigned int offset=0, startsec=0, endsec=0;
107 unsigned int secnum=0, size=0, writeoffs=0;
108 unsigned int i, fn;
109 unsigned char *clipboard;
110 unsigned char *addr = (unsigned char*)CFLASH.mapped + CFLASH.offset;
112 currflash=FDEV;
113 fn=CFLASH.flashnum;
115 /* Some security checks. */
117 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
118 if (!suser())
119 return -EACCES;
120 #endif
122 if (!write) {
123 printk (KERN_WARNING "Writing is disabled for security reasons. RTFM.\n");
124 return -EACCES;
127 if (!flashchips[fn].supported) {
128 printk (KERN_ERR "BIOS: Flash device not supported.\n");
129 return -EMEDIUMTYPE;
132 if ( count > BIOS_SIZE-*ppos )
133 return -EFBIG;
135 /* FIXME: Autoselect(AMD) BC-90
136 * -> 00/MID;
137 * 01/PID;
138 * 02/Protected (1=yes/0=no)
141 /* Determine size of data to be written */
143 if (!(flashchips[fn].flags & f_needs_erase) ) {
144 offset=(unsigned int)*ppos&~(flashchips[fn].pagesize-1);
145 size=(((unsigned int)*ppos+count+(flashchips[fn].pagesize-1))&
146 ~(flashchips[CFLASH.flashnum].pagesize-1))-offset;
147 } else {
148 while (flashchips[fn].sectors[secnum] <= flashchips[fn].size ) {
149 if ((unsigned int)*ppos >= flashchips[fn].sectors[secnum]*1024) {
150 offset=flashchips[fn].sectors[secnum]*1024;
151 startsec=secnum;
153 if ((unsigned int)*ppos+count-1 <= flashchips[fn].sectors[secnum]*1024) {
154 size=(flashchips[fn].sectors[secnum]*1024)-offset;
155 endsec=secnum-1;
156 break;
158 secnum++;
162 #ifdef DEBUG
163 printk (KERN_DEBUG "BIOS: Write [0x%06x..0x%06x] [0x%06x..0x%06x]\n",
164 (unsigned int)(*ppos),(unsigned int)(*ppos+count-1),offset,offset+size-1);
165 #endif
167 /* prepare data for writing */
169 clipboard=vmalloc(size);
171 spin_lock_irqsave(&bios_lock, flags);
173 devices[flashdevices[currflash].idx].activate();
175 for (i=0; i < size; i++)
176 clipboard[i] = flash_readb(addr,offset+i);
178 copy_from_user(clipboard+(*ppos-offset), buffer, count);
180 /* start write access */
182 if (flashchips[fn].flags & f_intel_compl) {
183 iflash_erase_sectors(addr,fn,startsec,endsec);
185 for (i=0;i<size;i++)
186 iflash_program_byte(addr, offset+i, clipboard[i]);
188 flash_command(addr, 0xff);
190 } else {
192 if (flashchips[fn].flags & f_needs_erase) {
193 if (size == flashchips[fn].size*1024) { /* whole chip erase */
194 printk (KERN_DEBUG "BIOS: Erasing via whole chip method\n");
195 flash_erase(addr, fn);
196 } else {
197 printk (KERN_DEBUG "BIOS: Erasing via sector method\n");
198 flash_erase_sectors(addr, fn,startsec,endsec);
202 while (size>0) {
203 if ((flashchips[fn].flags & f_manuf_compl) != f_atmel_compl) {
204 flash_program(addr);
205 } else {
206 flash_program_atmel(addr);
208 for (i=0;i<flashchips[fn].pagesize;i++) {
209 flash_writeb(addr,offset+writeoffs+i,clipboard[writeoffs+i]);
211 if ((flashchips[fn].flags & f_manuf_compl) == f_atmel_compl) {
212 udelay(750);
213 } else {
214 if (flashchips[fn].pagesize==1)
215 udelay(30);
216 else
217 udelay(300);
220 if (flash_ready_poll(addr,offset+writeoffs+flashchips[fn].pagesize-1,
221 clipboard[writeoffs+flashchips[fn].pagesize-1])) {
222 printk (KERN_ERR "BIOS: Error occured, please repeat write operation.\n");
224 flash_command(addr, 0xf0);
226 writeoffs += flashchips[fn].pagesize;
227 size -= flashchips[fn].pagesize;
231 devices[flashdevices[currflash].idx].deactivate();
233 spin_unlock_irqrestore(&bios_lock, flags);
235 vfree(clipboard);
237 *ppos+=count;
238 return count;
241 static int bios_open(struct inode *inode, struct file *file)
243 currflash=FDEV;
245 if (flashcount<=FDEV) {
246 printk (KERN_ERR "BIOS: There is no device (%d).\n",FDEV);
247 return -ENODEV;
250 #ifdef DEBUG
251 printk(KERN_DEBUG "BIOS: Opening device %d\n",FDEV);
252 #endif
253 /* Only one shall open for writing */
255 if ((CFLASH.open_cnt && (file->f_flags & O_EXCL)) ||
256 (CFLASH.open_mode & O_EXCL) ||
257 ((file->f_mode & 2) && (CFLASH.open_mode & O_RDWR)))
258 return -EBUSY;
260 if (file->f_flags & O_EXCL)
261 CFLASH.open_mode |= O_EXCL;
263 if (file->f_mode & 2)
264 CFLASH.open_mode |= O_RDWR;
266 CFLASH.open_cnt++;
269 #ifdef MODULE
270 inc_mod();
271 #endif
272 return 0;
275 static int bios_release(struct inode *inode, struct file *file)
277 currflash=FDEV;
278 if (file->f_flags & O_EXCL)
279 CFLASH.open_mode &= ~O_EXCL;
281 if (file->f_mode & 2)
282 CFLASH.open_mode &= ~O_RDWR;
284 CFLASH.open_cnt--;
286 #ifdef MODULE
287 dec_mod();
288 #endif
289 return 0;
292 struct file_operations bios_fops = {
293 .owner = THIS_MODULE,
294 .llseek = bios_llseek,
295 .read = bios_read,
296 .write = bios_write,
297 .open = bios_open,
298 .release = bios_release,