~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/mtd/docprobe.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 
  2 /* Linux driver for Disk-On-Chip devices    */
  3 /* Probe routines common to all DoC devices */
  4 /* (c) 1999 Machine Vision Holdings, Inc.   */
  5 /* Author: David Woodhouse <dwmw2@mvhi.com> */
  6 /* $Id: docprobe.c,v 1.21 2000/12/03 19:32:34 dwmw2 Exp $ */
  7 
  8 
  9 
 10 /* DOC_PASSIVE_PROBE:
 11    In order to ensure that the BIOS checksum is correct at boot time, and 
 12    hence that the onboard BIOS extension gets executed, the DiskOnChip 
 13    goes into reset mode when it is read sequentially: all registers 
 14    return 0xff until the chip is woken up again by writing to the 
 15    DOCControl register. 
 16 
 17    Unfortunately, this means that the probe for the DiskOnChip is unsafe, 
 18    because one of the first things it does is write to where it thinks 
 19    the DOCControl register should be - which may well be shared memory 
 20    for another device. I've had machines which lock up when this is 
 21    attempted. Hence the possibility to do a passive probe, which will fail 
 22    to detect a chip in reset mode, but is at least guaranteed not to lock
 23    the machine.
 24 
 25    If you have this problem, uncomment the following line:
 26 #define DOC_PASSIVE_PROBE
 27 */
 28 
 29 
 30 /* DOC_SINGLE_DRIVER:
 31    Millennium driver has been merged into DOC2000 driver.
 32 
 33    The newly-merged driver doesn't appear to work for writing. It's the
 34    same with the DiskOnChip 2000 and the Millennium. If you have a 
 35    Millennium and you want write support to work, remove the definition
 36    of DOC_SINGLE_DRIVER below to use the old doc2001-specific driver.
 37 
 38    Otherwise, it's left on in the hope that it'll annoy someone with
 39    a Millennium enough that they go through and work out what the 
 40    difference is :)
 41 */
 42 #define DOC_SINGLE_DRIVER
 43 
 44 #include <linux/config.h>
 45 #include <linux/kernel.h>
 46 #include <linux/module.h>
 47 #include <asm/errno.h>
 48 #include <asm/io.h>
 49 #include <asm/uaccess.h>
 50 #include <linux/miscdevice.h>
 51 #include <linux/pci.h>
 52 #include <linux/delay.h>
 53 #include <linux/malloc.h>
 54 #include <linux/sched.h>
 55 #include <linux/init.h>
 56 #include <linux/types.h>
 57 
 58 #include <linux/mtd/mtd.h>
 59 #include <linux/mtd/nand.h>
 60 #include <linux/mtd/doc2000.h>
 61 
 62 /* Where to look for the devices? */
 63 #ifndef CONFIG_MTD_DOCPROBE_ADDRESS
 64 #define CONFIG_MTD_DOCPROBE_ADDRESS 0
 65 #endif
 66 
 67 
 68 static unsigned long doc_config_location = CONFIG_MTD_DOCPROBE_ADDRESS;
 69 MODULE_PARM(doc_config_location, "l");
 70 
 71 
 72 static unsigned long __initdata doc_locations[] = {
 73 #if defined (__alpha__) || defined(__i386__)
 74 #ifdef CONFIG_MTD_DOCPROBE_HIGH
 75         0xfffc8000, 0xfffca000, 0xfffcc000, 0xfffce000, 
 76         0xfffd0000, 0xfffd2000, 0xfffd4000, 0xfffd6000,
 77         0xfffd8000, 0xfffda000, 0xfffdc000, 0xfffde000, 
 78         0xfffe0000, 0xfffe2000, 0xfffe4000, 0xfffe6000, 
 79         0xfffe8000, 0xfffea000, 0xfffec000, 0xfffee000,
 80 #else /*  CONFIG_MTD_DOCPROBE_HIGH */
 81         0xc8000, 0xca000, 0xcc000, 0xce000, 
 82         0xd0000, 0xd2000, 0xd4000, 0xd6000,
 83         0xd8000, 0xda000, 0xdc000, 0xde000, 
 84         0xe0000, 0xe2000, 0xe4000, 0xe6000, 
 85         0xe8000, 0xea000, 0xec000, 0xee000,
 86 #endif /*  CONFIG_MTD_DOCPROBE_HIGH */
 87 #elif defined(__ppc__)
 88         0xe4000000,
 89 #else 
 90 #warning Unknown architecture for DiskOnChip. No default probe locations defined
 91 #endif
 92         0 };
 93 
 94 /* doccheck: Probe a given memory window to see if there's a DiskOnChip present */
 95 
 96 static inline int __init doccheck(unsigned long potential, unsigned long physadr)
 97 {
 98         unsigned long window=potential;
 99         unsigned char tmp, ChipID;
100 #ifndef DOC_PASSIVE_PROBE
101         unsigned char tmp2;
102 #endif
103 
104         /* Routine copied from the Linux DOC driver */
105 
106 #ifdef CONFIG_MTD_DOCPROBE_55AA
107         /* Check for 0x55 0xAA signature at beginning of window,
108            this is no longer true once we remove the IPL (for Millennium */
109         if (ReadDOC(window, Sig1) != 0x55 || ReadDOC(window, Sig2) != 0xaa)
110                 return 0;
111 #endif /* CONFIG_MTD_DOCPROBE_55AA */
112 
113 #ifndef DOC_PASSIVE_PROBE       
114         /* It's not possible to cleanly detect the DiskOnChip - the
115          * bootup procedure will put the device into reset mode, and
116          * it's not possible to talk to it without actually writing
117          * to the DOCControl register. So we store the current contents
118          * of the DOCControl register's location, in case we later decide
119          * that it's not a DiskOnChip, and want to put it back how we
120          * found it. 
121          */
122         tmp2 = ReadDOC(window, DOCControl);
123         
124         /* Reset the DiskOnChip ASIC */
125         WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, 
126                  window, DOCControl);
127         WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, 
128                  window, DOCControl);
129         
130         /* Enable the DiskOnChip ASIC */
131         WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, 
132                  window, DOCControl);
133         WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, 
134                  window, DOCControl);
135 #endif /* !DOC_PASSIVE_PROBE */ 
136 
137         ChipID = ReadDOC(window, ChipID);
138   
139         switch (ChipID) {
140         case DOC_ChipID_Doc2k:
141                 /* Check the TOGGLE bit in the ECC register */
142                 tmp = ReadDOC(window, 2k_ECCStatus) & DOC_TOGGLE_BIT;
143                 if ((ReadDOC(window, 2k_ECCStatus) & DOC_TOGGLE_BIT) != tmp)
144                                 return ChipID;
145                 break;
146                 
147         case DOC_ChipID_DocMil:
148                 /* Check the TOGGLE bit in the ECC register */
149                 tmp = ReadDOC(window, ECCConf) & DOC_TOGGLE_BIT;
150                 if ((ReadDOC(window, ECCConf) & DOC_TOGGLE_BIT) != tmp)
151                                 return ChipID;
152                 break;
153                 
154         default:
155 #ifndef CONFIG_MTD_DOCPROBE_55AA
156                 printk(KERN_WARNING "Possible DiskOnChip with unknown ChipID %2.2X found at 0x%lx\n",
157                        ChipID, physadr);
158 #endif
159 #ifndef DOC_PASSIVE_PROBE
160                 /* Put back the contents of the DOCControl register, in case it's not
161                  * actually a DiskOnChip.
162                  */
163                 WriteDOC(tmp2, window, DOCControl);
164 #endif
165                 return 0;
166         }
167 
168         printk(KERN_WARNING "DiskOnChip failed TOGGLE test, dropping.\n");
169 
170 #ifndef DOC_PASSIVE_PROBE
171         /* Put back the contents of the DOCControl register: it's not a DiskOnChip */
172         WriteDOC(tmp2, window, DOCControl);
173 #endif
174         return 0;
175 }   
176 
177 
178 static void DoC_Probe(unsigned long physadr)
179 {
180         unsigned long docptr;
181         struct DiskOnChip *this;
182         struct mtd_info *mtd;
183         int ChipID;
184         char namebuf[15];
185         char *name = namebuf;
186         char *im_funcname = NULL;
187         char *im_modname = NULL;
188         void (*initroutine)(struct mtd_info *) = NULL;
189 
190         docptr = (unsigned long)ioremap(physadr, 0x2000);
191         
192         if (!docptr)
193                 return;
194         
195         if ((ChipID = doccheck(docptr, physadr))) {
196                 
197                 mtd = kmalloc(sizeof(struct DiskOnChip) + sizeof(struct mtd_info), GFP_KERNEL);
198 
199                 if (!mtd) {
200                         printk("Cannot allocate memory for data structures. Dropping.\n");
201                         iounmap((void *)docptr);
202                         return;
203                 }
204                 
205                 this = (struct DiskOnChip *)(&mtd[1]);
206                 
207                 memset((char *)mtd,0, sizeof(struct mtd_info));
208                 memset((char *)this, 0, sizeof(struct DiskOnChip));
209 
210                 mtd->priv = this;
211                 this->virtadr = docptr;
212                 this->physadr = physadr;
213                 this->ChipID = ChipID;
214                 sprintf(namebuf, "with ChipID %2.2X", ChipID);
215 
216                 switch(ChipID) {
217                 case DOC_ChipID_Doc2k:
218                         name="2000";
219                         im_funcname = "DoC2k_init";
220                         im_modname = "doc2000";
221                         break;
222                         
223                 case DOC_ChipID_DocMil:
224                         name="Millennium";
225 #ifdef DOC_SINGLE_DRIVER
226                         im_funcname = "DoC2k_init";
227                         im_modname = "doc2000";
228 #else
229                         im_funcname = "DoCMil_init";
230                         im_modname = "doc2001";
231 #endif /* DOC_SINGLE_DRIVER */
232                         break;
233                 }
234 
235                 if (im_funcname)
236                         initroutine = inter_module_get_request(im_funcname, im_modname);
237 
238                 if (initroutine) {
239                         (*initroutine)(mtd);
240                         inter_module_put(im_funcname);
241                         return;
242                 }
243                 printk("Cannot find driver for DiskOnChip %s at 0x%lX\n", name, physadr);
244         }
245         iounmap((void *)docptr);
246 }
247 
248 
249 /****************************************************************************
250  *
251  * Module stuff
252  *
253  ****************************************************************************/
254 
255 #if LINUX_VERSION_CODE < 0x20212 && defined(MODULE)
256 #define init_doc init_module
257 #endif
258 
259 int __init init_doc(void)
260 {
261         int i;
262         
263         printk(KERN_NOTICE "M-Systems DiskOnChip driver. (C) 1999 Machine Vision Holdings, Inc.\n");
264 #ifdef PRERELEASE
265         printk(KERN_INFO "$Id: docprobe.c,v 1.21 2000/12/03 19:32:34 dwmw2 Exp $\n");
266 #endif
267         if (doc_config_location) {
268                 printk("Using configured probe address 0x%lx\n", doc_config_location);
269                 DoC_Probe(doc_config_location);
270         } else {
271                 for (i=0; doc_locations[i]; i++) {
272                         DoC_Probe(doc_locations[i]);
273                 }
274         }
275         /* So it looks like we've been used and we get unloaded */
276         MOD_INC_USE_COUNT;
277         MOD_DEC_USE_COUNT;
278         return 0;
279         
280 }
281 
282 module_init(init_doc);
283 
284 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.