!C99Shell v. 1.0 pre-release build #13!

Software: Apache/2.0.54 (Unix) mod_perl/1.99_09 Perl/v5.8.0 mod_ssl/2.0.54 OpenSSL/0.9.7l DAV/2 FrontPage/5.0.2.2635 PHP/4.4.0 mod_gzip/2.0.26.1a 

uname -a: Linux snow.he.net 4.4.276-v2-mono-1 #1 SMP Wed Jul 21 11:21:17 PDT 2021 i686 

uid=99(nobody) gid=98(nobody) groups=98(nobody) 

Safe-mode: OFF (not secure)

/usr/src/linux-2.4.18-xfs-1.1/drivers/mtd/chips/   drwxr-xr-x
Free 318.33 GB of 458.09 GB (69.49%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Feedback    Self remove    Logout    


Viewing file:     sharp.c (12.86 KB)      -rw-r--r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/*
 * MTD chip driver for pre-CFI Sharp flash chips
 *
 * Copyright 2000,2001 David A. Schleef <ds@schleef.org>
 *           2000,2001 Lineo, Inc.
 *
 * $Id: sharp.c,v 1.6 2001/10/02 15:05:12 dwmw2 Exp $
 *
 * Devices supported:
 *   LH28F016SCT Symmetrical block flash memory, 2Mx8
 *   LH28F008SCT Symmetrical block flash memory, 1Mx8
 *
 * Documentation:
 *   http://www.sharpmeg.com/datasheets/memic/flashcmp/
 *   http://www.sharpmeg.com/datasheets/memic/flashcmp/01symf/16m/016sctl9.pdf
 *   016sctl9.pdf
 *
 * Limitations:
 *   This driver only supports 4x1 arrangement of chips.
 *   Not tested on anything but PowerPC.
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/mtd/map.h>
#include <linux/mtd/cfi.h>
#include <linux/delay.h>

#define CMD_RESET        0xffffffff
#define CMD_READ_ID        0x90909090
#define CMD_READ_STATUS        0x70707070
#define CMD_CLEAR_STATUS    0x50505050
#define CMD_BLOCK_ERASE_1    0x20202020
#define CMD_BLOCK_ERASE_2    0xd0d0d0d0
#define CMD_BYTE_WRITE        0x40404040
#define CMD_SUSPEND        0xb0b0b0b0
#define CMD_RESUME        0xd0d0d0d0
#define CMD_SET_BLOCK_LOCK_1    0x60606060
#define CMD_SET_BLOCK_LOCK_2    0x01010101
#define CMD_SET_MASTER_LOCK_1    0x60606060
#define CMD_SET_MASTER_LOCK_2    0xf1f1f1f1
#define CMD_CLEAR_BLOCK_LOCKS_1    0x60606060
#define CMD_CLEAR_BLOCK_LOCKS_2    0xd0d0d0d0

#define SR_READY        0x80808080 // 1 = ready
#define SR_ERASE_SUSPEND    0x40404040 // 1 = block erase suspended
#define SR_ERROR_ERASE        0x20202020 // 1 = error in block erase or clear lock bits
#define SR_ERROR_WRITE        0x10101010 // 1 = error in byte write or set lock bit
#define    SR_VPP            0x08080808 // 1 = Vpp is low
#define SR_WRITE_SUSPEND    0x04040404 // 1 = byte write suspended
#define SR_PROTECT        0x02020202 // 1 = lock bit set
#define SR_RESERVED        0x01010101

#define SR_ERRORS (SR_ERROR_ERASE|SR_ERROR_WRITE|SR_VPP|SR_PROTECT)

/* Configuration options */

#undef AUTOUNLOCK  /* automatically unlocks blocks before erasing */

struct mtd_info *sharp_probe(struct map_info *);

static int sharp_probe_map(struct map_info *map,struct mtd_info *mtd);

static int sharp_read(struct mtd_info *mtd, loff_t from, size_t len,
    size_t *retlen, u_char *buf);
static int sharp_write(struct mtd_info *mtd, loff_t from, size_t len,
    size_t *retlen, const u_char *buf);
static int sharp_erase(struct mtd_info *mtd, struct erase_info *instr);
static void sharp_sync(struct mtd_info *mtd);
static int sharp_suspend(struct mtd_info *mtd);
static void sharp_resume(struct mtd_info *mtd);
static void sharp_destroy(struct mtd_info *mtd);

static int sharp_write_oneword(struct map_info *map, struct flchip *chip,
    unsigned long adr, __u32 datum);
static int sharp_erase_oneblock(struct map_info *map, struct flchip *chip,
    unsigned long adr);
#ifdef AUTOUNLOCK
static void sharp_unlock_oneblock(struct map_info *map, struct flchip *chip,
    unsigned long adr);
#endif


struct sharp_info{
    struct flchip *chip;
    int bogus;
    int chipshift;
    int numchips;
    struct flchip chips[1];
};

struct mtd_info *sharp_probe(struct map_info *map);
static void sharp_destroy(struct mtd_info *mtd);

static struct mtd_chip_driver sharp_chipdrv = {
    probe: sharp_probe,
    destroy: sharp_destroy,
    name: "sharp",
    module: THIS_MODULE
};


struct mtd_info *sharp_probe(struct map_info *map)
{
    struct mtd_info *mtd = NULL;
    struct sharp_info *sharp = NULL;
    int width;

    mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
    if(!mtd)
        return NULL;

    sharp = kmalloc(sizeof(*sharp), GFP_KERNEL);
    if(!sharp)
        return NULL;

    memset(mtd, 0, sizeof(*mtd));

    width = sharp_probe_map(map,mtd);
    if(!width){
        kfree(mtd);
        kfree(sharp);
        return NULL;
    }

    mtd->priv = map;
    mtd->type = MTD_NORFLASH;
    mtd->erase = sharp_erase;
    mtd->read = sharp_read;
    mtd->write = sharp_write;
    mtd->sync = sharp_sync;
    mtd->suspend = sharp_suspend;
    mtd->resume = sharp_resume;
    mtd->flags = MTD_CAP_NORFLASH;
    mtd->name = map->name;

    memset(sharp, 0, sizeof(*sharp));
    sharp->chipshift = 23;
    sharp->numchips = 1;
    sharp->chips[0].start = 0;
    sharp->chips[0].state = FL_READY;
    sharp->chips[0].mutex = &sharp->chips[0]._spinlock;
    sharp->chips[0].word_write_time = 0;
    init_waitqueue_head(&sharp->chips[0].wq);
    spin_lock_init(&sharp->chips[0]._spinlock);

    map->fldrv = &sharp_chipdrv;
    map->fldrv_priv = sharp;

    MOD_INC_USE_COUNT;
    return mtd;
}

static int sharp_probe_map(struct map_info *map,struct mtd_info *mtd)
{
    unsigned long tmp;
    unsigned long base = 0;
    u32 read0, read4;
    int width = 4;

    tmp = map->read32(map, base+0);

    map->write32(map, CMD_READ_ID, base+0);

    read0=map->read32(map, base+0);
    read4=map->read32(map, base+4);
    if(read0 == 0x89898989){
        printk("Looks like sharp flash\n");
        switch(read4){
        case 0xaaaaaaaa:
        case 0xa0a0a0a0:
            /* aa - LH28F016SCT-L95 2Mx8, 32 64k blocks*/
            /* a0 - LH28F016SCT-Z4  2Mx8, 32 64k blocks*/
            mtd->erasesize = 0x10000 * width;
            mtd->size = 0x200000 * width;
            return width;
        case 0xa6a6a6a6:
            /* a6 - LH28F008SCT-L12 1Mx8, 16 64k blocks*/
            /* a6 - LH28F008SCR-L85 1Mx8, 16 64k blocks*/
            mtd->erasesize = 0x10000 * width;
            mtd->size = 0x100000 * width;
            return width;
#if 0
        case 0x00000000: /* unknown */
            /* XX - LH28F004SCT 512kx8, 8 64k blocks*/
            mtd->erasesize = 0x10000 * width;
            mtd->size = 0x80000 * width;
            return width;
#endif
        default:
            printk("Sort-of looks like sharp flash, 0x%08x 0x%08x\n",
                read0,read4);
        }
    }else if((map->read32(map, base+0) == CMD_READ_ID)){
        /* RAM, probably */
        printk("Looks like RAM\n");
        map->write32(map, tmp, base+0);
    }else{
        printk("Doesn't look like sharp flash, 0x%08x 0x%08x\n",
            read0,read4);
    }

    return 0;
}

/* This function returns with the chip->mutex lock held. */
static int sharp_wait(struct map_info *map, struct flchip *chip)
{
    __u16 status;
    unsigned long timeo = jiffies + HZ;
    DECLARE_WAITQUEUE(wait, current);
    int adr = 0;

retry:
    spin_lock_bh(chip->mutex);

    switch(chip->state){
    case FL_READY:
        map->write32(map,CMD_READ_STATUS,adr);
        chip->state = FL_STATUS;
    case FL_STATUS:
        status = map->read32(map,adr);
//printk("status=%08x\n",status);

        udelay(100);
        if((status & SR_READY)!=SR_READY){
//printk(".status=%08x\n",status);
            udelay(100);
        }
        break;
    default:
        printk("Waiting for chip\n");

        set_current_state(TASK_INTERRUPTIBLE);
        add_wait_queue(&chip->wq, &wait);

        spin_unlock_bh(chip->mutex);

        schedule();
        remove_wait_queue(&chip->wq, &wait);

        if(signal_pending(current))
            return -EINTR;

        timeo = jiffies + HZ;

        goto retry;
    }

    map->write32(map,CMD_RESET, adr);

    chip->state = FL_READY;

    return 0;
}

static void sharp_release(struct flchip *chip)
{
    wake_up(&chip->wq);
    spin_unlock_bh(chip->mutex);
}

static int sharp_read(struct mtd_info *mtd, loff_t from, size_t len,
    size_t *retlen, u_char *buf)
{
    struct map_info *map = mtd->priv;
    struct sharp_info *sharp = map->fldrv_priv;
    int chipnum;
    int ret = 0;
    int ofs = 0;

    chipnum = (from >> sharp->chipshift);
    ofs = from & ((1 << sharp->chipshift)-1);

    *retlen = 0;

    while(len){
        unsigned long thislen;

        if(chipnum>=sharp->numchips)
            break;

        thislen = len;
        if(ofs+thislen >= (1<<sharp->chipshift))
            thislen = (1<<sharp->chipshift) - ofs;

        ret = sharp_wait(map,&sharp->chips[chipnum]);
        if(ret<0)
            break;

        map->copy_from(map,buf,ofs,thislen);

        sharp_release(&sharp->chips[chipnum]);

        *retlen += thislen;
        len -= thislen;
        buf += thislen;

        ofs = 0;
        chipnum++;
    }
    return ret;
}

static int sharp_write(struct mtd_info *mtd, loff_t to, size_t len,
    size_t *retlen, const u_char *buf)
{
    struct map_info *map = mtd->priv;
    struct sharp_info *sharp = map->fldrv_priv;
    int ret = 0;
    int i,j;
    int chipnum;
    unsigned long ofs;
    union { u32 l; unsigned char uc[4]; } tbuf;

    *retlen = 0;

    while(len){
        tbuf.l = 0xffffffff;
        chipnum = to >> sharp->chipshift;
        ofs = to & ((1<<sharp->chipshift)-1);

        j=0;
        for(i=ofs&3;i<4 && len;i++){
            tbuf.uc[i] = *buf;
            buf++;
            to++;
            len--;
            j++;
        }
        sharp_write_oneword(map, &sharp->chips[chipnum], ofs&~3, tbuf.l);
        if(ret<0)
            return ret;
        (*retlen)+=j;
    }

    return 0;
}

static int sharp_write_oneword(struct map_info *map, struct flchip *chip,
    unsigned long adr, __u32 datum)
{
    int ret;
    int timeo;
    int try;
    int i;
    int status = 0;

    ret = sharp_wait(map,chip);

    for(try=0;try<10;try++){
        map->write32(map,CMD_BYTE_WRITE,adr);
        /* cpu_to_le32 -> hack to fix the writel be->le conversion */
        map->write32(map,cpu_to_le32(datum),adr);

        chip->state = FL_WRITING;

        timeo = jiffies + (HZ/2);

        map->write32(map,CMD_READ_STATUS,adr);
        for(i=0;i<100;i++){
            status = map->read32(map,adr);
            if((status & SR_READY)==SR_READY)
                break;
        }
        if(i==100){
            printk("sharp: timed out writing\n");
        }

        if(!(status&SR_ERRORS))
            break;

        printk("sharp: error writing byte at addr=%08lx status=%08x\n",adr,status);

        map->write32(map,CMD_CLEAR_STATUS,adr);
    }
    map->write32(map,CMD_RESET,adr);
    chip->state = FL_READY;

    wake_up(&chip->wq);
    spin_unlock_bh(chip->mutex);

    return 0;
}

static int sharp_erase(struct mtd_info *mtd, struct erase_info *instr)
{
    struct map_info *map = mtd->priv;
    struct sharp_info *sharp = map->fldrv_priv;
    unsigned long adr,len;
    int chipnum, ret=0;

//printk("sharp_erase()\n");
    if(instr->addr & (mtd->erasesize - 1))
        return -EINVAL;
    if(instr->len & (mtd->erasesize - 1))
        return -EINVAL;
    if(instr->len + instr->addr > mtd->size)
        return -EINVAL;

    chipnum = instr->addr >> sharp->chipshift;
    adr = instr->addr & ((1<<sharp->chipshift)-1);
    len = instr->len;

    while(len){
        ret = sharp_erase_oneblock(map, &sharp->chips[chipnum], adr);
        if(ret)return ret;

        adr += mtd->erasesize;
        len -= mtd->erasesize;
        if(adr >> sharp->chipshift){
            adr = 0;
            chipnum++;
            if(chipnum>=sharp->numchips)
                break;
        }
    }

    if(instr->callback)
        instr->callback(instr);

    return 0;
}

static int sharp_do_wait_for_ready(struct map_info *map, struct flchip *chip,
    unsigned long adr)
{
    int ret;
    int timeo;
    int status;
    DECLARE_WAITQUEUE(wait, current);

    map->write32(map,CMD_READ_STATUS,adr);
    status = map->read32(map,adr);

    timeo = jiffies + HZ;

    while(jiffies<timeo){
        map->write32(map,CMD_READ_STATUS,adr);
        status = map->read32(map,adr);
        if((status & SR_READY)==SR_READY){
            ret = 0;
            goto out;
        }
        set_current_state(TASK_INTERRUPTIBLE);
        add_wait_queue(&chip->wq, &wait);

        //spin_unlock_bh(chip->mutex);

        schedule_timeout(1);
        schedule();
        remove_wait_queue(&chip->wq, &wait);

        //spin_lock_bh(chip->mutex);
        
        if (signal_pending(current)){
            ret = -EINTR;
            goto out;
        }
        
    }
    ret = -ETIME;
out:
    return ret;
}

static int sharp_erase_oneblock(struct map_info *map, struct flchip *chip,
    unsigned long adr)
{
    int ret;
    //int timeo;
    int status;
    //int i;

//printk("sharp_erase_oneblock()\n");

#ifdef AUTOUNLOCK
    /* This seems like a good place to do an unlock */
    sharp_unlock_oneblock(map,chip,adr);
#endif

    map->write32(map,CMD_BLOCK_ERASE_1,adr);
    map->write32(map,CMD_BLOCK_ERASE_2,adr);

    chip->state = FL_ERASING;

    ret = sharp_do_wait_for_ready(map,chip,adr);
    if(ret<0)return ret;

    map->write32(map,CMD_READ_STATUS,adr);
    status = map->read32(map,adr);

    if(!(status&SR_ERRORS)){
        map->write32(map,CMD_RESET,adr);
        chip->state = FL_READY;
        //spin_unlock_bh(chip->mutex);
        return 0;
    }

    printk("sharp: error erasing block at addr=%08lx status=%08x\n",adr,status);
    map->write32(map,CMD_CLEAR_STATUS,adr);

    //spin_unlock_bh(chip->mutex);

    return -EIO;
}

#ifdef AUTOUNLOCK
static void sharp_unlock_oneblock(struct map_info *map, struct flchip *chip,
    unsigned long adr)
{
    int i;
    int status;

    map->write32(map,CMD_CLEAR_BLOCK_LOCKS_1,adr);
    map->write32(map,CMD_CLEAR_BLOCK_LOCKS_2,adr);

    udelay(100);

    status = map->read32(map,adr);
    printk("status=%08x\n",status);

    for(i=0;i<1000;i++){
        //map->write32(map,CMD_READ_STATUS,adr);
        status = map->read32(map,adr);
        if((status & SR_READY)==SR_READY)
            break;
        udelay(100);
    }
    if(i==1000){
        printk("sharp: timed out unlocking block\n");
    }

    if(!(status&SR_ERRORS)){
        map->write32(map,CMD_RESET,adr);
        chip->state = FL_READY;
        return;
    }

    printk("sharp: error unlocking block at addr=%08lx status=%08x\n",adr,status);
    map->write32(map,CMD_CLEAR_STATUS,adr);
}
#endif

static void sharp_sync(struct mtd_info *mtd)
{
    //printk("sharp_sync()\n");
}

static int sharp_suspend(struct mtd_info *mtd)
{
    printk("sharp_suspend()\n");
    return -EINVAL;
}

static void sharp_resume(struct mtd_info *mtd)
{
    printk("sharp_resume()\n");
    
}

static void sharp_destroy(struct mtd_info *mtd)
{
    printk("sharp_destroy()\n");

}

int __init sharp_probe_init(void)
{
    printk("MTD Sharp chip driver <ds@lineo.com>\n");

    register_mtd_chip_driver(&sharp_chipdrv);

    return 0;
}

static void __exit sharp_probe_exit(void)
{
    unregister_mtd_chip_driver(&sharp_chipdrv);
}

module_init(sharp_probe_init);
module_exit(sharp_probe_exit);


MODULE_LICENSE("GPL");
MODULE_AUTHOR("David Schleef <ds@schleef.org>");
MODULE_DESCRIPTION("Old MTD chip driver for pre-CFI Sharp flash chips");

:: Command execute ::

Enter:
 
Select:
 

:: Search ::
  - regexp 

:: Upload ::
 
[ Read-Only ]

:: Make Dir ::
 
[ Read-Only ]
:: Make File ::
 
[ Read-Only ]

:: Go Dir ::
 
:: Go File ::
 

--[ c99shell v. 1.0 pre-release build #13 powered by Captain Crunch Security Team | http://ccteam.ru | Generation time: 0.012 ]--