📄 jsflash.c
字号:
#if 0 /* * This code is ok, except that counter based timeout * has no place in this world. Let's just drop timeouts... */ { int i; __u32 x; for (i = 0; i < 1000000; i++) { x = jsf_inl(p); if ((x & 0x80808080) == 0x80808080) break; } if ((x & 0x80808080) != 0x80808080) { printk("jsf0: erase timeout with 0x%08x\n", x); } else { printk("jsf0: erase done with 0x%08x\n", x); } }#else jsf_wait(p);#endif return 0;}/* * Program a block of flash. * Very simple because we can do it byte by byte anyway. */static int jsf_ioctl_program(unsigned long arg){ struct jsflash_program_arg abuf; char *uptr; unsigned long p; unsigned int togo; union { unsigned int n; char s[4]; } b; if (verify_area(VERIFY_READ, (void *)arg, JSFPRGSZ)) return -EFAULT; copy_from_user(&abuf, (char *)arg, JSFPRGSZ); p = abuf.off; togo = abuf.size; if ((togo & 3) || (p & 3)) return -EINVAL; uptr = (char *) (unsigned long) abuf.data; if (verify_area(VERIFY_READ, uptr, togo)) return -EFAULT; while (togo != 0) { togo -= 4; copy_from_user(&b.s[0], uptr, 4); jsf_write4(p, b.n); p += 4; uptr += 4; } return 0;}static int jsf_ioctl(struct inode *inode, struct file *f, unsigned int cmd, unsigned long arg){ int error = -ENOTTY; if (!capable(CAP_SYS_ADMIN)) return -EPERM; switch (cmd) { case JSFLASH_IDENT: if (verify_area(VERIFY_WRITE, (void *)arg, JSFIDSZ)) return -EFAULT; copy_to_user(arg, &jsf0.id, JSFIDSZ); error = 0; break; case JSFLASH_ERASE: error = jsf_ioctl_erase(arg); break; case JSFLASH_PROGRAM: error = jsf_ioctl_program(arg); break; } return error;}static int jsfd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ int dev; if (!capable(CAP_SYS_ADMIN)) return -EPERM; if (!inode) return -EINVAL; if ((dev = MINOR(inode->i_rdev)) >= JSF_MAX) return -ENODEV; switch (cmd) { case BLKGETSIZE: return put_user(jsfd_bytesizes[dev] >> 9, (long *) arg);#if 0 case BLKROSET: case BLKROGET: case BLKSSZGET: return blk_ioctl(inode->i_rdev, cmd, arg);#endif /* case BLKFLSBUF: */ /* Program, then read, what happens? Stale? */ default: ; } return -ENOTTY;}static int jsf_mmap(struct file * file, struct vm_area_struct * vma){ return -ENXIO;}static int jsf_open(struct inode * inode, struct file * filp){ if (jsf0.base == 0) return -ENXIO; if (test_and_set_bit(0, (void *)&jsf0.busy) != 0) return -EBUSY; return 0; /* XXX What security? */}static int jsfd_open(struct inode *inode, struct file *file){ struct jsfd_part *jdp; int dev; if (!inode) return -EINVAL; dev = MINOR(inode->i_rdev); if (dev >= JSF_MAX || (dev & JSF_PART_MASK) >= JSF_NPART) { printk(KERN_ALERT "jsfd_open: illegal minor %d\n", dev); return -ENODEV; } jdp = &jsf0.dv[dev]; jdp->refcnt++; MOD_INC_USE_COUNT; return 0;}static int jsf_release(struct inode *inode, struct file *file){ lock_kernel(); jsf0.busy = 0; unlock_kernel(); return 0;}static int jsfd_release(struct inode *inode, struct file *file){ struct jsfd_part *jdp; int dev; if (!inode) return -ENODEV; dev = MINOR(inode->i_rdev); if (dev >= JSF_MAX || (dev & JSF_PART_MASK) >= JSF_NPART) { printk(KERN_ALERT "jsfd_release: illegal minor %d\n", dev); return -ENODEV; } jdp = &jsf0.dv[dev]; if (jdp->refcnt <= 0) { printk(KERN_ALERT "jsfd_release: bad ref on minor %d\n", dev); } else { --jdp->refcnt; } /* N.B. Doesn't lo->file need an fput?? */ MOD_DEC_USE_COUNT; return 0;}static struct file_operations jsf_fops = { owner: THIS_MODULE, llseek: jsf_lseek, read: jsf_read, write: jsf_write, ioctl: jsf_ioctl, mmap: jsf_mmap, open: jsf_open, release: jsf_release,};static struct miscdevice jsf_dev = { JSF_MINOR, "jsflash", &jsf_fops };static struct block_device_operations jsfd_fops = { open: jsfd_open, release: jsfd_release, ioctl: jsfd_ioctl,};EXPORT_NO_SYMBOLS;int jsflash_init(void){ int rc; struct jsflash *jsf; int node; char banner[128]; struct linux_prom_registers reg0; node = prom_getchild(prom_root_node); node = prom_searchsiblings(node, "flash-memory"); if (node != 0 && node != -1) { if (prom_getproperty(node, "reg", (char *)®0, sizeof(reg0)) == -1) { printk("jsflash: no \"reg\" property\n"); return -ENXIO; } if (reg0.which_io != 0) { printk("jsflash: bus number nonzero: 0x%x:%x\n", reg0.which_io, reg0.phys_addr); return -ENXIO; } /* * Flash may be somewhere else, for instance on Ebus. * So, don't do the following check for IIep flash space. */#if 0 if ((reg0.phys_addr >> 24) != 0x20) { printk("jsflash: suspicious address: 0x%x:%x\n", reg0.which_io, reg0.phys_addr); return -ENXIO; }#endif if ((int)reg0.reg_size <= 0) { printk("jsflash: bad size 0x%x\n", (int)reg0.reg_size); return -ENXIO; } } else { /* XXX Remove this code once PROLL ID12 got widespread */ printk("jsflash: no /flash-memory node, use PROLL >= 12\n"); prom_getproperty(prom_root_node, "banner-name", banner, 128); if (strcmp (banner, "JavaStation-NC") != 0 && strcmp (banner, "JavaStation-E") != 0) { return -ENXIO; } reg0.which_io = 0; reg0.phys_addr = 0x20400000; reg0.reg_size = 0x00800000; } /* Let us be really paranoid for modifications to probing code. */ /* extern enum sparc_cpu sparc_cpu_model; */ /* in <asm/system.h> */ if (sparc_cpu_model != sun4m) { /* We must be on sun4m because we use MMU Bypass ASI. */ return -ENXIO; } if (jsf0.base == 0) { jsf = &jsf0; jsf->base = reg0.phys_addr; jsf->size = reg0.reg_size; /* XXX Redo the userland interface. */ jsf->id.off = JSF_BASE_ALL; jsf->id.size = 0x01000000; /* 16M - all segments */ strcpy(jsf->id.name, "Krups_all"); jsf->dv[0].dbase = jsf->base; jsf->dv[0].dsize = jsf->size; jsf->dv[1].dbase = jsf->base + 1024; jsf->dv[1].dsize = jsf->size - 1024; jsf->dv[2].dbase = JSF_BASE_ALL; jsf->dv[2].dsize = 0x01000000; printk("Espresso Flash @0x%lx [%d MB]\n", jsf->base, (int) (jsf->size / (1024*1024))); } if ((rc = misc_register(&jsf_dev)) != 0) { printk(KERN_ERR "jsf: unable to get misc minor %d\n", JSF_MINOR); jsf0.base = 0; return rc; } return 0;}int jsfd_init(void) { struct jsflash *jsf; struct jsfd_part *jdp; int i; if (jsf0.base == 0) { return -ENXIO; } if (register_blkdev(JSFD_MAJOR, "jsfd", &jsfd_fops)) { printk("jsfd_init: unable to get major number %d\n", JSFD_MAJOR); return -EIO; } blksize_size[JSFD_MAJOR] = jsfd_blksizes; blk_size[JSFD_MAJOR] = jsfd_sizes; blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST); /* blk_queue_headactive(BLK_DEFAULT_QUEUE(MAJOR_NR), 0); */ for (i = 0; i < JSF_MAX; i++) { if ((i & JSF_PART_MASK) >= JSF_NPART) continue; jsf = &jsf0; /* actually, &jsfv[i >> JSF_PART_BITS] */ jdp = &jsf->dv[i&JSF_PART_MASK]; jdp->refcnt = 0; jsfd_blksizes[i] = 1024; jsfd_bytesizes[i] = jdp->dsize; jsfd_sizes[i] = jsfd_bytesizes[i] >> 10; register_disk(NULL, MKDEV(JSFD_MAJOR, i), 1, &jsfd_fops, jsfd_bytesizes[i] >> 9); set_device_ro(MKDEV(JSFD_MAJOR, i), 1); } return 0;}#ifdef MODULEint init_module(void) { int rc; if ((rc = jsflash_init()) == 0) { jsfd_init(); return 0; } return rc;}void cleanup_module(void) { /* for (all probed units) { } */ if (jsf0.busy) printk("jsf0: cleaning busy unit\n"); jsf0.base = 0; jsf0.busy = 0; misc_deregister(&jsf_dev); if (unregister_blkdev(JSFD_MAJOR, "jsfd") != 0) printk("jsfd: cleanup_module failed\n"); blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -