1 2 3#include <linux/module.h> 4#include <linux/types.h> 5#include <linux/errno.h> 6#include <linux/miscdevice.h> 7#include <linux/slab.h> 8#include <linux/fcntl.h> 9#include <linux/poll.h> 10#include <linux/init.h> 11#include <linux/string.h> 12#include <linux/smp_lock.h> 13 14/* 15 * <linux/blk.h> is controlled from the outside with these definitions. 16 */ 17#define MAJOR_NR JSFD_MAJOR 18 19#define DEVICE_NAME "jsfd" 20#define DEVICE_REQUEST jsfd_do_request 21#define DEVICE_NR(device) (MINOR(device)) 22#define DEVICE_ON(device) 23#define DEVICE_OFF(device) 24#define DEVICE_NO_RANDOM 25 26#include <linux/blk.h> 27 28 29#include <asm/uaccess.h> 30#include <asm/pgtable.h> 31#include <asm/io.h> 32#include <asm/pcic.h> 33#include <asm/oplib.h> 34 35#include <asm/jsflash.h> /* ioctl arguments. <linux/> ?? */ 36#define JSFIDSZ (sizeof(struct jsflash_ident_arg)) 37#define JSFPRGSZ (sizeof(struct jsflash_program_arg)) 38 39/* 40 * Our device numbers have no business in system headers. 41 * The only thing a user knows is the device name /dev/jsflash. 42 * 43 * Block devices are laid out like this: 44 * minor+0 - Bootstrap, for 8MB SIMM 0x20400000[0x800000] 45 * minor+1 - Filesystem to mount, normally 0x20400400[0x7ffc00] 46 * minor+2 - Whole flash area for any case... 0x20000000[0x01000000] 47 * Total 3 minors per flash device. 48 * 49 * It is easier to have static size vectors, so we define 50 * a total minor range JSF_MAX, which must cover all minors. 51 */ 52/* character device */ 53#define JSF_MINOR 178 /* 178 is registered with hpa */ 54/* block device */ 55#define JSF_MAX 3 /* 3 minors wasted total so far. */ 56#define JSF_NPART 3 /* 3 minors per flash device */ 57#define JSF_PART_BITS 2 /* 2 bits of minors to cover JSF_NPART */ 58#define JSF_PART_MASK 0x3 /* 2 bits mask */ 59 60/* 61 * Access functions. 62 * We could ioremap(), but it's easier this way. 63 */ 64static unsigned int jsf_inl(unsigned long addr) 65{ 66 unsigned long retval; 67 68 __asm__ __volatile__("lda [%1] %2, %0\n\t" : 69 "=r" (retval) : 70 "r" (addr), "i" (ASI_M_BYPASS)); 71 return retval; 72} 73 74static void jsf_outl(unsigned long addr, __u32 data) 75{ 76 77 __asm__ __volatile__("sta %0, [%1] %2\n\t" : : 78 "r" (data), "r" (addr), "i" (ASI_M_BYPASS) : 79 "memory"); 80} 81 82/* 83 * soft carrier 84 */ 85 86struct jsfd_part { 87 unsigned long dbase; 88 unsigned long dsize; 89 int refcnt; 90}; 91 92struct jsflash { 93 unsigned long base; 94 unsigned long size; 95 unsigned long busy; /* In use? */ 96 struct jsflash_ident_arg id; 97 /* int mbase; */ /* Minor base, typically zero */ 98 struct jsfd_part dv[JSF_NPART]; 99}; 100 101/* 102 * We do not map normal memory or obio as a safety precaution. 103 * But offsets are real, for ease of userland programming. 104 */ 105#define JSF_BASE_TOP 0x30000000 106#define JSF_BASE_ALL 0x20000000 107 108#define JSF_BASE_JK 0x20400000 109 110/* 111 */ 112static int jsfd_blksizes[JSF_MAX]; 113static int jsfd_sizes[JSF_MAX]; 114static u64 jsfd_bytesizes[JSF_MAX]; 115 116/* 117 * Let's pretend we may have several of these... 118 */ 119static struct jsflash jsf0; 120 121static void jsf_wait(unsigned long p) { 122 unsigned int x1, x2; 123 124 for (;;) { 125 x1 = jsf_inl(p); 126 x2 = jsf_inl(p); 127 if ((x1 & 0x40404040) == (x2 & 0x40404040)) return; 128 } 129} 130 131/* 132 * Programming will only work if Flash is clean, 133 * we leave it to the programmer application. 134 * 135 * AMD must be programmed one byte at a time; 136 * thus, Simple Tech SIMM must be written 4 bytes at a time. 137 * 138 * Write waits for the chip to become ready after the write 139 * was finished. This is done so that application would read 140 * consistent data after the write is done. 141 */ 142static void jsf_write4(unsigned long fa, u32 data) { 143 144 jsf_outl(fa, 0xAAAAAAAA); /* Unlock 1 Write 1 */ 145 jsf_outl(fa, 0x55555555); /* Unlock 1 Write 2 */ 146 jsf_outl(fa, 0xA0A0A0A0); /* Byte Program */ 147 jsf_outl(fa, data); 148 149 jsf_wait(fa); 150} 151 152/* 153 */ 154static void jsfd_read(char *buf, unsigned long p, size_t togo) { 155 union byte4 { 156 char s[4]; 157 unsigned int n; 158 } b; 159 160 while (togo >= 4) { 161 togo -= 4; 162 b.n = jsf_inl(p); 163 memcpy(buf, b.s, 4); 164 p += 4; 165 buf += 4; 166 } 167} 168 169static void jsfd_do_request(request_queue_t *q) 170{ 171 struct request *req; 172 int dev; 173 struct jsfd_part *jdp; 174 unsigned long offset; 175 size_t len; 176 177 for (;;) { 178 INIT_REQUEST; /* if (QUEUE_EMPTY) return; */ 179 req = CURRENT; 180 181 dev = MINOR(req->rq_dev); 182 if (dev >= JSF_MAX || (dev & JSF_PART_MASK) >= JSF_NPART) { 183 end_request(0); 184 continue; 185 } 186 jdp = &jsf0.dv[dev & JSF_PART_MASK]; 187 188 offset = req->sector << 9; 189 len = req->current_nr_sectors << 9; 190 if ((offset + len) > jdp->dsize) { 191 end_request(0); 192 continue; 193 } 194 195 if (req->cmd == WRITE) { 196 printk(KERN_ERR "jsfd: write\n"); 197 end_request(0); 198 continue; 199 } 200 if (req->cmd != READ) { 201 printk(KERN_ERR "jsfd: bad req->cmd %d\n", req->cmd); 202 end_request(0); 203 continue; 204 } 205 206 if ((jdp->dbase & 0xff000000) != 0x20000000) { 207 printk(KERN_ERR "jsfd: bad base %x\n", (int)jdp->dbase); 208 end_request(0); 209 continue; 210 } 211 212/* printk("jsfd%d: read buf %p off %x len %x\n", dev, req->buffer, (int)offset, (int)len); */ /* P3 */ 213 jsfd_read(req->buffer, jdp->dbase + offset, len); 214 215 end_request(1); 216 } 217} 218 219/* 220 * The memory devices use the full 32/64 bits of the offset, and so we cannot 221 * check against negative addresses: they are ok. The return value is weird, 222 * though, in that case (0). 223 * 224 * also note that seeking relative to the "end of file" isn't supported: 225 * it has no meaning, so it returns -EINVAL. 226 */ 227static loff_t jsf_lseek(struct file * file, loff_t offset, int orig) 228{ 229 switch (orig) { 230 case 0: 231 file->f_pos = offset; 232 return file->f_pos; 233 case 1: 234 file->f_pos += offset; 235 return file->f_pos; 236 default: 237 return -EINVAL; 238 } 239} 240 241/* 242 * OS SIMM Cannot be read in other size but a 32bits word. 243 */ 244static ssize_t jsf_read(struct file * file, char * buf, 245 size_t togo, loff_t *ppos) 246{ 247 unsigned long p = *ppos; 248 char *tmp = buf; 249 250 union byte4 { 251 char s[4]; 252 unsigned int n; 253 } b; 254 255 if (verify_area(VERIFY_WRITE, buf, togo)) 256 return -EFAULT; 257 258 if (p < JSF_BASE_ALL || p >= JSF_BASE_TOP) { 259 return 0; 260 } 261 262 if ((p + togo) < p /* wrap */ 263 || (p + togo) >= JSF_BASE_TOP) { 264 togo = JSF_BASE_TOP - p; 265 } 266 267 if (p < JSF_BASE_ALL && togo != 0) { 268 /* 269 * Implementation of clear_user() calls __bzero 270 * without regard to modversions, 271 * so we cannot build a module. 272 */ 273 return 0; 274 } 275 276 while (togo >= 4) { 277 togo -= 4; 278 b.n = jsf_inl(p); 279 copy_to_user(tmp, b.s, 4); 280 tmp += 4; 281 p += 4; 282 } 283 284 285 *ppos = p; 286 return tmp-buf; 287} 288 289static ssize_t jsf_write(struct file * file, const char * buf, 290 size_t count, loff_t *ppos) 291{ 292 return -ENOSPC; 293} 294 295/* 296 */ 297static int jsf_ioctl_erase(unsigned long arg) 298{ 299 unsigned long p; 300 301 /* p = jsf0.base; hits wrong bank */ 302 p = 0x20400000; 303 304 jsf_outl(p, 0xAAAAAAAA); /* Unlock 1 Write 1 */ 305 jsf_outl(p, 0x55555555); /* Unlock 1 Write 2 */ 306 jsf_outl(p, 0x80808080); /* Erase setup */ 307 jsf_outl(p, 0xAAAAAAAA); /* Unlock 2 Write 1 */ 308 jsf_outl(p, 0x55555555); /* Unlock 2 Write 2 */ 309 jsf_outl(p, 0x10101010); /* Chip erase */ 310 311 jsf_wait(p); 312 313 return 0; 314} 315 316/* 317 * Program a block of flash. 318 * Very simple because we can do it byte by byte anyway. 319 */ 320static int jsf_ioctl_program(unsigned long arg) 321{ 322 struct jsflash_program_arg abuf; 323 char *uptr; 324 unsigned long p; 325 unsigned int togo; 326 union { 327 unsigned int n; 328 char s[4]; 329 } b; 330 331 if (verify_area(VERIFY_READ, (void *)arg, JSFPRGSZ)) 332 return -EFAULT; 333 copy_from_user(&abuf, (char *)arg, JSFPRGSZ); 334 p = abuf.off; 335 togo = abuf.size; 336 if ((togo & 3) || (p & 3)) return -EINVAL; 337 338 uptr = (char *) (unsigned long) abuf.data; 339 if (verify_area(VERIFY_READ, uptr, togo)) 340 return -EFAULT; 341 while (togo != 0) { 342 togo -= 4; 343 copy_from_user(&b.s[0], uptr, 4); 344 jsf_write4(p, b.n); 345 p += 4; 346 uptr += 4; 347 } 348 349 return 0; 350} 351 352static int jsf_ioctl(struct inode *inode, struct file *f, unsigned int cmd, 353 unsigned long arg) 354{ 355 int error = -ENOTTY; 356 357 if (!capable(CAP_SYS_ADMIN)) 358 return -EPERM; 359 switch (cmd) { 360 case JSFLASH_IDENT: 361 if (verify_area(VERIFY_WRITE, (void *)arg, JSFIDSZ)) 362 return -EFAULT; 363 copy_to_user(arg, &jsf0.id, JSFIDSZ); 364 error = 0; 365 break; 366 case JSFLASH_ERASE: 367 error = jsf_ioctl_erase(arg); 368 break; 369 case JSFLASH_PROGRAM: 370 error = jsf_ioctl_program(arg); 371 break; 372 } 373 374 return error; 375} 376 377static int jsfd_ioctl(struct inode *inode, struct file *file, 378 unsigned int cmd, unsigned long arg) 379{ 380 int dev; 381 382 if (!capable(CAP_SYS_ADMIN)) 383 return -EPERM; 384 if (!inode) 385 return -EINVAL; 386 if ((dev = MINOR(inode->i_rdev)) >= JSF_MAX) return -ENODEV; 387 388 switch (cmd) { 389 case BLKGETSIZE: 390 return put_user(jsfd_bytesizes[dev] >> 9, (unsigned long *) arg); 391 case BLKGETSIZE64: 392 return put_user(jsfd_bytesizes[dev], (u64 *) arg); 393 394 395 /* case BLKFLSBUF: */ /* Program, then read, what happens? Stale? */ 396 default: ; 397 } 398 return -ENOTTY; 399} 400 401static int jsf_mmap(struct file * file, struct vm_area_struct * vma) 402{ 403 return -ENXIO; 404} 405 406static int jsf_open(struct inode * inode, struct file * filp) 407{ 408 409 if (jsf0.base == 0) return -ENXIO; 410 if (test_and_set_bit(0, (void *)&jsf0.busy) != 0) 411 return -EBUSY; 412 413 return 0; 414} 415 416static int jsfd_open(struct inode *inode, struct file *file) 417{ 418 struct jsfd_part *jdp; 419 int dev; 420 421 if (!inode) 422 return -EINVAL; 423 dev = MINOR(inode->i_rdev); 424 if (dev >= JSF_MAX || (dev & JSF_PART_MASK) >= JSF_NPART) { 425 printk(KERN_ALERT "jsfd_open: illegal minor %d\n", dev); 426 return -ENODEV; 427 } 428 429 jdp = &jsf0.dv[dev]; 430 jdp->refcnt++; 431 432 return 0; 433} 434 435static int jsf_release(struct inode *inode, struct file *file) 436{ 437 jsf0.busy = 0; 438 return 0; 439} 440 441static int jsfd_release(struct inode *inode, struct file *file) 442{ 443 struct jsfd_part *jdp; 444 int dev; 445 446 if (!inode) 447 return -ENODEV; 448 dev = MINOR(inode->i_rdev); 449 if (dev >= JSF_MAX || (dev & JSF_PART_MASK) >= JSF_NPART) { 450 printk(KERN_ALERT "jsfd_release: illegal minor %d\n", dev); 451 return -ENODEV; 452 } 453 454 jdp = &jsf0.dv[dev]; 455 if (jdp->refcnt <= 0) { 456 printk(KERN_ALERT "jsfd_release: bad ref on minor %d\n", dev); 457 } else { 458 --jdp->refcnt; 459 } 460 /* N.B. Doesn't lo->file need an fput?? */ 461 return 0; 462} 463 464static struct file_operations jsf_fops = { 465 owner: THIS_MODULE, 466 llseek: jsf_lseek, 467 read: jsf_read, 468 write: jsf_write, 469 ioctl: jsf_ioctl, 470 mmap: jsf_mmap, 471 open: jsf_open, 472 release: jsf_release, 473}; 474 475static struct miscdevice jsf_dev = { JSF_MINOR, "jsflash", &jsf_fops }; 476 477static struct block_device_operations jsfd_fops = { 478 owner: THIS_MODULE, 479 open: jsfd_open, 480 release: jsfd_release, 481 ioctl: jsfd_ioctl, 482}; 483 484EXPORT_NO_SYMBOLS; 485 486int jsflash_init(void) 487{ 488 int rc; 489 struct jsflash *jsf; 490 int node; 491 char banner[128]; 492 struct linux_prom_registers reg0; 493 494 node = prom_getchild(prom_root_node); 495 node = prom_searchsiblings(node, "flash-memory"); 496 if (node != 0 && node != -1) { 497 if (prom_getproperty(node, "reg", 498 (char *)®0, sizeof(reg0)) == -1) { 499 printk("jsflash: no \"reg\" property\n"); 500 return -ENXIO; 501 } 502 if (reg0.which_io != 0) { 503 printk("jsflash: bus number nonzero: 0x%x:%x\n", 504 reg0.which_io, reg0.phys_addr); 505 return -ENXIO; 506 } 507 /* 508 * Flash may be somewhere else, for instance on Ebus. 509 * So, don't do the following check for IIep flash space. 510 */ 511 if ((int)reg0.reg_size <= 0) { 512 printk("jsflash: bad size 0x%x\n", (int)reg0.reg_size); 513 return -ENXIO; 514 } 515 } else { 516 printk("jsflash: no /flash-memory node, use PROLL >= 12\n"); 517 prom_getproperty(prom_root_node, "banner-name", banner, 128); 518 if (strcmp (banner, "JavaStation-NC") != 0 && 519 strcmp (banner, "JavaStation-E") != 0) { 520 return -ENXIO; 521 } 522 reg0.which_io = 0; 523 reg0.phys_addr = 0x20400000; 524 reg0.reg_size = 0x00800000; 525 } 526 527 /* Let us be really paranoid for modifications to probing code. */ 528 /* extern enum sparc_cpu sparc_cpu_model; */ /* in <asm/system.h> */ 529 if (sparc_cpu_model != sun4m) { 530 /* We must be on sun4m because we use MMU Bypass ASI. */ 531 return -ENXIO; 532 } 533 534 if (jsf0.base == 0) { 535 jsf = &jsf0; 536 537 jsf->base = reg0.phys_addr; 538 jsf->size = reg0.reg_size; 539 540 jsf->id.off = JSF_BASE_ALL; 541 jsf->id.size = 0x01000000; /* 16M - all segments */ 542 strcpy(jsf->id.name, "Krups_all"); 543 544 jsf->dv[0].dbase = jsf->base; 545 jsf->dv[0].dsize = jsf->size; 546 jsf->dv[1].dbase = jsf->base + 1024; 547 jsf->dv[1].dsize = jsf->size - 1024; 548 jsf->dv[2].dbase = JSF_BASE_ALL; 549 jsf->dv[2].dsize = 0x01000000; 550 551 printk("Espresso Flash @0x%lx [%d MB]\n", jsf->base, 552 (int) (jsf->size / (1024*1024))); 553 } 554 555 if ((rc = misc_register(&jsf_dev)) != 0) { 556 printk(KERN_ERR "jsf: unable to get misc minor %d\n", 557 JSF_MINOR); 558 jsf0.base = 0; 559 return rc; 560 } 561 562 return 0; 563} 564 565int jsfd_init(void) { 566 struct jsflash *jsf; 567 struct jsfd_part *jdp; 568 int i; 569 570 if (jsf0.base == 0) { 571 return -ENXIO; 572 } 573 574 if (register_blkdev(JSFD_MAJOR, "jsfd", &jsfd_fops)) { 575 printk("jsfd_init: unable to get major number %d\n", 576 JSFD_MAJOR); 577 return -EIO; 578 } 579 580 blksize_size[JSFD_MAJOR] = jsfd_blksizes; 581 blk_size[JSFD_MAJOR] = jsfd_sizes; 582 583 blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST); 584 /* blk_queue_headactive(BLK_DEFAULT_QUEUE(MAJOR_NR), 0); */ 585 for (i = 0; i < JSF_MAX; i++) { 586 if ((i & JSF_PART_MASK) >= JSF_NPART) continue; 587 jsf = &jsf0; /* actually, &jsfv[i >> JSF_PART_BITS] */ 588 jdp = &jsf->dv[i&JSF_PART_MASK]; 589 590 jdp->refcnt = 0; 591 592 jsfd_blksizes[i] = 1024; 593 jsfd_bytesizes[i] = jdp->dsize; 594 jsfd_sizes[i] = jsfd_bytesizes[i] >> 10; 595 register_disk(NULL, MKDEV(JSFD_MAJOR, i), 1, &jsfd_fops, 596 jsfd_bytesizes[i] >> 9); 597 set_device_ro(MKDEV(JSFD_MAJOR, i), 1); 598 } 599 return 0; 600} 601 602#ifdef MODULE 603MODULE_LICENSE("GPL"); 604 605int init_module(void) { 606 int rc; 607 608 if ((rc = jsflash_init()) == 0) { 609 jsfd_init(); 610 return 0; 611 } 612 return rc; 613} 614 615void cleanup_module(void) { 616 617 /* for (all probed units) { } */ 618 if (jsf0.busy) 619 printk("jsf0: cleaning busy unit\n"); 620 jsf0.base = 0; 621 jsf0.busy = 0; 622 623 misc_deregister(&jsf_dev); 624 if (unregister_blkdev(JSFD_MAJOR, "jsfd") != 0) 625 printk("jsfd: cleanup_module failed\n"); 626 blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); 627} 628#endif 629