DiskOnChip test.
David Woodhouse
David.Woodhouse at mvhi.com
Tue Aug 3 12:20:53 EDT 1999
Please would anyone with a Disk-On-Chip compile and load the attached driver,
then mail me back it's output, along with a note saying what size of
Disk-On-Chip you have (and whether it's a 2000 or a Millennium.)
Alternatively, if you have any Disk-On-Chip hardware which isn't being used
ATM, other than the 4Mb units of which I have two, just send them to me at the
address below :)
Thanks.
-------------- next part --------------
/* Linux driver for Disk-On-Chip 2000 */
/* (c) 1999 Machine Vision Holdings, Inc. */
/* Author: David Woodhouse <dwmw2 at mvhi.com> */
/* $Id: doc-kernel.c,v 1.2 1999/08/03 16:18:51 dwmw2 Exp $ */
#include <linux/kernel.h>
#include <linux/module.h>
#include <asm/errno.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <linux/miscdevice.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/sched.h>
#define DoC_CDSN_IO 0x800
#define DoC_ChipID 0x1000
#define DoC_DOCStatus 0x1001
#define DoC_DOCControl 0x1002
#define DoC_FloorSelect 0x1003
#define DoC_CSDNControl 0x1004
#define DoC_CSDNDeviceSelect 0x1005
#define DoC_ECCConf 0x1006
#define DoC_UnknownCheck 0x1007
#define DoC_CSDNSlowIO 0x100d
#define DoC_ECCSyndrome0 0x1010
#define DoC_ECCSyndrome1 0x1011
#define DoC_ECCSyndrome2 0x1012
#define DoC_ECCSyndrome3 0x1013
#define DoC_ECCSyndrome4 0x1014
#define DoC_ECCSyndrome5 0x1015
#define DoC_AliasResolution 0x101b
#define DoC_ConfigInput 0x101c
#define DoC_ReadPipeInit 0x101d
#define DoC_WritePipeTerm 0x101e
#define DoC_LastDataRead 0x101f
#define DoC_NOP 0x1020
#define DoC_IPLalias 0x1800
#define ReadDOC(adr, reg) readb(((unsigned long)adr) + DoC_##reg)
#define WriteDOC(d, adr, reg) writeb(d, ((unsigned long)adr) + DoC_##reg)
#define DOC_MODE_RESET 0
#define DOC_MODE_NORMAL 1
#define DOC_MODE_RESERVED1 2
#define DOC_MODE_RESERVED2 3
#define DOC_MODE_MDWREN 4
#define DOC_MODE_CLR_ERR 0x80
#define DOC_ChipID_Doc2k 0x20
#define DOC_ChipID_DocMil 0x30
#define CSDN_CTRL_FR_B 0x80
#define CSDN_CTRL_WP 8
#define CSDN_CTRL_ALE 4
#define CSDN_CTRL_CLE 2
#define CSDN_CTRL_CE 1
static ssize_t doc_read (struct file *filp, char *buf, size_t count, loff_t *ptr);
static ssize_t doc_write (struct file *file, const char *buf, size_t count, loff_t *ppos);
static int doc_release(struct inode *inode, struct file *file);
static int doc_open(struct inode *inode, struct file *filp);
struct file_operations doc_fops={
NULL, /* llseek */
doc_read, /* read */
doc_write, /* write */
NULL, /* readdir */
NULL, /* poll */
NULL, /* ioctl */
NULL, /* mmap */
doc_open, /* open */
NULL, /* flush */
doc_release, /* release */
NULL /* fsync */
};
struct miscdevice doc_miscdev={
157,
"doc",
&doc_fops
};
#define DOCLOC 0xd8000
unsigned long docptr=0;
int doccheck(unsigned long potential);
void docidentify(unsigned long docptr, int chip);
static inline int DoC_WaitReady(unsigned long docptr)
{
unsigned long c=0;
while (!(ReadDOC(docptr, CSDNControl) & CSDN_CTRL_FR_B) && --c)
printk("Waiting\n");
return (c!=0);
}
static inline int DoC_Command(unsigned long docptr, unsigned char command)
{
WriteDOC( /* Doc2000 driver used 0x1d but I don't know what the
0x10 bit does */
0x10 | CSDN_CTRL_WP | CSDN_CTRL_CLE | CSDN_CTRL_CE,
docptr, CSDNControl);
if (DoC_WaitReady(docptr))
return 1;
WriteDOC(command, docptr, IPLalias);
// WriteDOC(0x00, docptr, IPLalias);
WriteDOC( 0x10 | CSDN_CTRL_WP | CSDN_CTRL_CE, docptr, CSDNControl);
return DoC_WaitReady(docptr);
}
static inline int DoC_Address (unsigned long docptr, unsigned long ofs)
{
WriteDOC( /* Doc2000 driver used 0x1d but I don't know what the
0x10 bit does */
0x10 | CSDN_CTRL_WP | CSDN_CTRL_ALE | CSDN_CTRL_CE,
docptr, CSDNControl);
if (DoC_WaitReady(docptr))
return 1;
WriteDOC(ofs & 0xff, docptr, IPLalias);
WriteDOC((ofs >> 8) & 0xff, docptr, IPLalias);
WriteDOC((ofs >> 16) & 0xff, docptr, IPLalias);
WriteDOC( 0x10 | CSDN_CTRL_WP | CSDN_CTRL_CE, docptr, CSDNControl);
return DoC_WaitReady(docptr);
}
static inline int DoC_SelectChip(unsigned long docptr, int chip)
{
WriteDOC( chip, docptr, CSDNDeviceSelect);
return DoC_WaitReady(docptr);
}
int init_module(void)
{
int status;
docptr=(unsigned long)ioremap(0xd8000, 0x2000);
status=doccheck(docptr);
if (status)
{
printk("DOC found at 0x%lx\n",docptr);
docidentify(docptr, 0);
docidentify(docptr, 1);
docidentify(docptr, 2);
docidentify(docptr, 3);
docidentify(docptr, 4);
docidentify(docptr, 5);
docidentify(docptr, 6);
docidentify(docptr, 7);
docidentify(docptr, 8);
docidentify(docptr, 9);
docidentify(docptr, 10);
docidentify(docptr, 11);
docidentify(docptr, 12);
docidentify(docptr, 13);
docidentify(docptr, 14);
docidentify(docptr, 15);
misc_register (&doc_miscdev);
return 0;
}
else
{
printk("DOC not found at 0x%lx\n", docptr);
return -ENXIO;
}
}
void cleanup_module(void)
{
if (docptr)
iounmap((void *)docptr);
docptr = 0;
misc_deregister (&doc_miscdev);
}
int doccheck(unsigned long potential)
{
unsigned long window=potential;
unsigned char tmp, tmp2, ChipID;
/* Routine copied from the Linux DOC driver */
if (readb(window) != 0x55 || readb(window+1) != 0xaa)
{
printk ("Start of window not 0x55 0xaa: %2.2X %2.2X\n",
(unsigned int)readb(window),(unsigned int)readb(window+1));
return 0;
}
tmp2 = ReadDOC(window, DOCControl);
WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET,
window, DOCControl);
WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET,
window, DOCControl);
WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL,
window, DOCControl);
WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL,
window, DOCControl);
ChipID = ReadDOC(window, ChipID);
switch (ChipID) {
case DOC_ChipID_Doc2k:
printk("Disk-On-Chip 2000 (v1) found\n");
tmp = ReadDOC(window, UnknownCheck) & 4;
if ((ReadDOC(window, UnknownCheck) & 4) != tmp)
{
return 1;
}
break;
case DOC_ChipID_DocMil:
printk("Disk-On-Chip Millennium (v1) found\n");
tmp = ReadDOC(window, ECCConf) & 4;
if ((ReadDOC(window, ECCConf) & 4) != tmp)
{
return 1;
}
break;
default:
WriteDOC(tmp2, window, DOCControl);
printk("Unrecognised device %2.2X: Family %d, Category %d, Version %d\n",
ChipID, ChipID >> 4,( ChipID >> 3) & 1, ChipID & 7);
return 0;
}
printk("Failed TOGGLE test\n");
WriteDOC(tmp2, window, DOCControl);
return 0;
}
void docidentify(unsigned long docptr, int chip)
{
unsigned char mfr, id;
DoC_SelectChip(docptr, chip);
DoC_Command(docptr, 0x90);
DoC_Address(docptr, 0);
mfr = ReadDOC(docptr, IPLalias);
id = ReadDOC(docptr, IPLalias);
if (mfr != 0x98)
{
printk("Chip #%d: Unknown manufacturer 0x%2.2X, id %2.2X\n",chip, mfr, id);
return;
}
switch (id) {
case 0x6b: /* Toshiba TC5832DC */
printk("Chip #%d: Toshiba TC5832DC\n", chip);
return;
default:
printk("Chip #%d: Unknown Toshiba (Chip ID 0x%2.2x)\n",
chip, id);
return;
}
}
static ssize_t doc_read (struct file *filp, char *buf, size_t count, loff_t *ptr)
{
size_t di;
loff_t ofs = *ptr;
di = 0;
for (ofs = *ptr; ofs < *ptr + count ; ofs++)
{
if (!(ofs & 0xf)) {
// Tell the thing to latch the address we give it (ALE)
WriteDOC( /* Doc2000 driver used 0x1d but I don't know what the
0x10 bit does */
0x10 | CSDN_CTRL_WP | CSDN_CTRL_ALE | CSDN_CTRL_CE,
docptr, CSDNControl);
// NOP? This should do nothing according to the spec.
//WriteDOC( 1 + ReadDOC(docptr, ChipID), docptr, ChipID);
DoC_WaitReady(docptr);
// The Doc2000 driver does both of these. I don't know why. On the
// Doc2000, only the IPLalias one appears to be needed.
// WriteDOC( ofs & 0xff, docptr, CDSN_Slow_IO);
WriteDOC(ofs & 0xff, docptr, IPLalias);
// WriteDOC( (ofs >> 8) & 0xff, docptr, CDSN_Slow_IO);
WriteDOC((ofs >> 8) & 0xff, docptr, IPLalias);
// WriteDOC( (ofs >> 16) & 0xff, docptr, CDSN_Slow_IO);
WriteDOC((ofs >> 16) & 0xff, docptr, IPLalias);
// WriteDOC( (ofs >> 24) & 0xff, docptr, CDSN_Slow_IO);
//WriteDOC((ofs >> 24) & 0xff, docptr, IPLalias);
/* What does the 0x10 bit do? */
WriteDOC( 0x10 | CSDN_CTRL_WP | CSDN_CTRL_CE, docptr, CSDNControl);
// NOP? This should do nothing according to the spec.
WriteDOC( ReadDOC(docptr, ChipID), docptr, ChipID);
DoC_WaitReady(docptr);
// (void)ReadDOC(docptr, CSDNControl);
}
//(void)readb(docptr + 0x100d);
buf[di++] = ReadDOC(docptr, IPLalias);
}
*ptr = ofs;
return count;
}
static ssize_t doc_write (struct file *file, const char *buf, size_t count, loff_t *ppos)
{
return -EIO;
}
static int doc_release(struct inode *inode, struct file *file)
{
return 0;
}
static int doc_open(struct inode *inode, struct file *filp)
{
return 0;
}
-------------- next part --------------
---- ---- ----
David Woodhouse David.Woodhouse at mvhi.com Office: (+44) 1223 810302
Project Leader, Process Information Systems Mobile: (+44) 976 658355
Axiom (Cambridge) Ltd., Swaffham Bulbeck, Cambridge, CB5 0NA, UK.
finger dwmw2 at ferret.lmh.ox.ac.uk for PGP key.
More information about the linux-mtd
mailing list