diff options
author | Jens Axboe <axboe@kernel.dk> | 2018-05-15 15:54:11 -0400 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2018-05-15 15:56:16 -0400 |
commit | da3c6efea5b975a2ba341a5681b778a82443788c (patch) | |
tree | 371c3082dd848fab4c38e223dc499b5b94ff5711 /drivers/sbus | |
parent | 6fcefbe578811bf938908e1ec43347d205133ad0 (diff) |
Remove jsflash driver
Nobody is using it anymore, and it's been abandoned. Since David
is fine with removing it, kill it.
Suggested-by: Christoph Hellwig <hch@lst.de>
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'drivers/sbus')
-rw-r--r-- | drivers/sbus/char/Kconfig | 7 | ||||
-rw-r--r-- | drivers/sbus/char/Makefile | 1 | ||||
-rw-r--r-- | drivers/sbus/char/jsflash.c | 660 |
3 files changed, 0 insertions, 668 deletions
diff --git a/drivers/sbus/char/Kconfig b/drivers/sbus/char/Kconfig index bf3c5f735614..89edd13fd572 100644 --- a/drivers/sbus/char/Kconfig +++ b/drivers/sbus/char/Kconfig | |||
@@ -28,13 +28,6 @@ config TADPOLE_TS102_UCTRL | |||
28 | events, and can also notice the attachment/detachment of external | 28 | events, and can also notice the attachment/detachment of external |
29 | monitors and mice. | 29 | monitors and mice. |
30 | 30 | ||
31 | config SUN_JSFLASH | ||
32 | tristate "JavaStation OS Flash SIMM" | ||
33 | depends on SPARC32 | ||
34 | help | ||
35 | If you say Y here, you will be able to boot from your JavaStation's | ||
36 | Flash memory. | ||
37 | |||
38 | config BBC_I2C | 31 | config BBC_I2C |
39 | tristate "UltraSPARC-III bootbus i2c controller driver" | 32 | tristate "UltraSPARC-III bootbus i2c controller driver" |
40 | depends on PCI && SPARC64 | 33 | depends on PCI && SPARC64 |
diff --git a/drivers/sbus/char/Makefile b/drivers/sbus/char/Makefile index 8c48ed96683f..44347c918f6b 100644 --- a/drivers/sbus/char/Makefile +++ b/drivers/sbus/char/Makefile | |||
@@ -15,6 +15,5 @@ obj-$(CONFIG_DISPLAY7SEG) += display7seg.o | |||
15 | obj-$(CONFIG_OBP_FLASH) += flash.o | 15 | obj-$(CONFIG_OBP_FLASH) += flash.o |
16 | obj-$(CONFIG_SUN_OPENPROMIO) += openprom.o | 16 | obj-$(CONFIG_SUN_OPENPROMIO) += openprom.o |
17 | obj-$(CONFIG_TADPOLE_TS102_UCTRL) += uctrl.o | 17 | obj-$(CONFIG_TADPOLE_TS102_UCTRL) += uctrl.o |
18 | obj-$(CONFIG_SUN_JSFLASH) += jsflash.o | ||
19 | obj-$(CONFIG_BBC_I2C) += bbc.o | 18 | obj-$(CONFIG_BBC_I2C) += bbc.o |
20 | obj-$(CONFIG_ORACLE_DAX) += oradax.o | 19 | obj-$(CONFIG_ORACLE_DAX) += oradax.o |
diff --git a/drivers/sbus/char/jsflash.c b/drivers/sbus/char/jsflash.c deleted file mode 100644 index 8520587b8d09..000000000000 --- a/drivers/sbus/char/jsflash.c +++ /dev/null | |||
@@ -1,660 +0,0 @@ | |||
1 | /* | ||
2 | * drivers/sbus/char/jsflash.c | ||
3 | * | ||
4 | * Copyright (C) 1991, 1992 Linus Torvalds (drivers/char/mem.c) | ||
5 | * Copyright (C) 1997 Eddie C. Dost (drivers/sbus/char/flash.c) | ||
6 | * Copyright (C) 1997-2000 Pavel Machek <pavel@ucw.cz> (drivers/block/nbd.c) | ||
7 | * Copyright (C) 1999-2000 Pete Zaitcev | ||
8 | * | ||
9 | * This driver is used to program OS into a Flash SIMM on | ||
10 | * Krups and Espresso platforms. | ||
11 | * | ||
12 | * TODO: do not allow erase/programming if file systems are mounted. | ||
13 | * TODO: Erase/program both banks of a 8MB SIMM. | ||
14 | * | ||
15 | * It is anticipated that programming an OS Flash will be a routine | ||
16 | * procedure. In the same time it is exceedingly dangerous because | ||
17 | * a user can program its OBP flash with OS image and effectively | ||
18 | * kill the machine. | ||
19 | * | ||
20 | * This driver uses an interface different from Eddie's flash.c | ||
21 | * as a silly safeguard. | ||
22 | * | ||
23 | * XXX The flash.c manipulates page caching characteristics in a certain | ||
24 | * dubious way; also it assumes that remap_pfn_range() can remap | ||
25 | * PCI bus locations, which may be false. ioremap() must be used | ||
26 | * instead. We should discuss this. | ||
27 | */ | ||
28 | |||
29 | #include <linux/module.h> | ||
30 | #include <linux/mutex.h> | ||
31 | #include <linux/types.h> | ||
32 | #include <linux/errno.h> | ||
33 | #include <linux/miscdevice.h> | ||
34 | #include <linux/fcntl.h> | ||
35 | #include <linux/poll.h> | ||
36 | #include <linux/init.h> | ||
37 | #include <linux/string.h> | ||
38 | #include <linux/genhd.h> | ||
39 | #include <linux/blkdev.h> | ||
40 | #include <linux/uaccess.h> | ||
41 | #include <asm/pgtable.h> | ||
42 | #include <asm/io.h> | ||
43 | #include <asm/pcic.h> | ||
44 | #include <asm/oplib.h> | ||
45 | |||
46 | #include <asm/jsflash.h> /* ioctl arguments. <linux/> ?? */ | ||
47 | #define JSFIDSZ (sizeof(struct jsflash_ident_arg)) | ||
48 | #define JSFPRGSZ (sizeof(struct jsflash_program_arg)) | ||
49 | |||
50 | /* | ||
51 | * Our device numbers have no business in system headers. | ||
52 | * The only thing a user knows is the device name /dev/jsflash. | ||
53 | * | ||
54 | * Block devices are laid out like this: | ||
55 | * minor+0 - Bootstrap, for 8MB SIMM 0x20400000[0x800000] | ||
56 | * minor+1 - Filesystem to mount, normally 0x20400400[0x7ffc00] | ||
57 | * minor+2 - Whole flash area for any case... 0x20000000[0x01000000] | ||
58 | * Total 3 minors per flash device. | ||
59 | * | ||
60 | * It is easier to have static size vectors, so we define | ||
61 | * a total minor range JSF_MAX, which must cover all minors. | ||
62 | */ | ||
63 | /* character device */ | ||
64 | #define JSF_MINOR 178 /* 178 is registered with hpa */ | ||
65 | /* block device */ | ||
66 | #define JSF_MAX 3 /* 3 minors wasted total so far. */ | ||
67 | #define JSF_NPART 3 /* 3 minors per flash device */ | ||
68 | #define JSF_PART_BITS 2 /* 2 bits of minors to cover JSF_NPART */ | ||
69 | #define JSF_PART_MASK 0x3 /* 2 bits mask */ | ||
70 | |||
71 | static DEFINE_MUTEX(jsf_mutex); | ||
72 | |||
73 | /* | ||
74 | * Access functions. | ||
75 | * We could ioremap(), but it's easier this way. | ||
76 | */ | ||
77 | static unsigned int jsf_inl(unsigned long addr) | ||
78 | { | ||
79 | unsigned long retval; | ||
80 | |||
81 | __asm__ __volatile__("lda [%1] %2, %0\n\t" : | ||
82 | "=r" (retval) : | ||
83 | "r" (addr), "i" (ASI_M_BYPASS)); | ||
84 | return retval; | ||
85 | } | ||
86 | |||
87 | static void jsf_outl(unsigned long addr, __u32 data) | ||
88 | { | ||
89 | |||
90 | __asm__ __volatile__("sta %0, [%1] %2\n\t" : : | ||
91 | "r" (data), "r" (addr), "i" (ASI_M_BYPASS) : | ||
92 | "memory"); | ||
93 | } | ||
94 | |||
95 | /* | ||
96 | * soft carrier | ||
97 | */ | ||
98 | |||
99 | struct jsfd_part { | ||
100 | unsigned long dbase; | ||
101 | unsigned long dsize; | ||
102 | }; | ||
103 | |||
104 | struct jsflash { | ||
105 | unsigned long base; | ||
106 | unsigned long size; | ||
107 | unsigned long busy; /* In use? */ | ||
108 | struct jsflash_ident_arg id; | ||
109 | /* int mbase; */ /* Minor base, typically zero */ | ||
110 | struct jsfd_part dv[JSF_NPART]; | ||
111 | }; | ||
112 | |||
113 | /* | ||
114 | * We do not map normal memory or obio as a safety precaution. | ||
115 | * But offsets are real, for ease of userland programming. | ||
116 | */ | ||
117 | #define JSF_BASE_TOP 0x30000000 | ||
118 | #define JSF_BASE_ALL 0x20000000 | ||
119 | |||
120 | #define JSF_BASE_JK 0x20400000 | ||
121 | |||
122 | /* | ||
123 | */ | ||
124 | static struct gendisk *jsfd_disk[JSF_MAX]; | ||
125 | |||
126 | /* | ||
127 | * Let's pretend we may have several of these... | ||
128 | */ | ||
129 | static struct jsflash jsf0; | ||
130 | |||
131 | /* | ||
132 | * Wait for AMD to finish its embedded algorithm. | ||
133 | * We use the Toggle bit DQ6 (0x40) because it does not | ||
134 | * depend on the data value as /DATA bit DQ7 does. | ||
135 | * | ||
136 | * XXX Do we need any timeout here? So far it never hanged, beware broken hw. | ||
137 | */ | ||
138 | static void jsf_wait(unsigned long p) { | ||
139 | unsigned int x1, x2; | ||
140 | |||
141 | for (;;) { | ||
142 | x1 = jsf_inl(p); | ||
143 | x2 = jsf_inl(p); | ||
144 | if ((x1 & 0x40404040) == (x2 & 0x40404040)) return; | ||
145 | } | ||
146 | } | ||
147 | |||
148 | /* | ||
149 | * Programming will only work if Flash is clean, | ||
150 | * we leave it to the programmer application. | ||
151 | * | ||
152 | * AMD must be programmed one byte at a time; | ||
153 | * thus, Simple Tech SIMM must be written 4 bytes at a time. | ||
154 | * | ||
155 | * Write waits for the chip to become ready after the write | ||
156 | * was finished. This is done so that application would read | ||
157 | * consistent data after the write is done. | ||
158 | */ | ||
159 | static void jsf_write4(unsigned long fa, u32 data) { | ||
160 | |||
161 | jsf_outl(fa, 0xAAAAAAAA); /* Unlock 1 Write 1 */ | ||
162 | jsf_outl(fa, 0x55555555); /* Unlock 1 Write 2 */ | ||
163 | jsf_outl(fa, 0xA0A0A0A0); /* Byte Program */ | ||
164 | jsf_outl(fa, data); | ||
165 | |||
166 | jsf_wait(fa); | ||
167 | } | ||
168 | |||
169 | /* | ||
170 | */ | ||
171 | static void jsfd_read(char *buf, unsigned long p, size_t togo) { | ||
172 | union byte4 { | ||
173 | char s[4]; | ||
174 | unsigned int n; | ||
175 | } b; | ||
176 | |||
177 | while (togo >= 4) { | ||
178 | togo -= 4; | ||
179 | b.n = jsf_inl(p); | ||
180 | memcpy(buf, b.s, 4); | ||
181 | p += 4; | ||
182 | buf += 4; | ||
183 | } | ||
184 | } | ||
185 | |||
186 | static int jsfd_queue; | ||
187 | |||
188 | static struct request *jsfd_next_request(void) | ||
189 | { | ||
190 | struct request_queue *q; | ||
191 | struct request *rq; | ||
192 | int old_pos = jsfd_queue; | ||
193 | |||
194 | do { | ||
195 | q = jsfd_disk[jsfd_queue]->queue; | ||
196 | if (++jsfd_queue == JSF_MAX) | ||
197 | jsfd_queue = 0; | ||
198 | if (q) { | ||
199 | rq = blk_fetch_request(q); | ||
200 | if (rq) | ||
201 | return rq; | ||
202 | } | ||
203 | } while (jsfd_queue != old_pos); | ||
204 | |||
205 | return NULL; | ||
206 | } | ||
207 | |||
208 | static void jsfd_request(void) | ||
209 | { | ||
210 | struct request *req; | ||
211 | |||
212 | req = jsfd_next_request(); | ||
213 | while (req) { | ||
214 | struct jsfd_part *jdp = req->rq_disk->private_data; | ||
215 | unsigned long offset = blk_rq_pos(req) << 9; | ||
216 | size_t len = blk_rq_cur_bytes(req); | ||
217 | blk_status_t err = BLK_STS_IOERR; | ||
218 | void *p; | ||
219 | |||
220 | if ((offset + len) > jdp->dsize) | ||
221 | goto end; | ||
222 | |||
223 | if (rq_data_dir(req) != READ) { | ||
224 | printk(KERN_ERR "jsfd: write\n"); | ||
225 | goto end; | ||
226 | } | ||
227 | |||
228 | if ((jdp->dbase & 0xff000000) != 0x20000000) { | ||
229 | printk(KERN_ERR "jsfd: bad base %x\n", (int)jdp->dbase); | ||
230 | goto end; | ||
231 | } | ||
232 | |||
233 | p = kmap_atomic(bio_page(bio)) + bio_offset(bio); | ||
234 | jsfd_read(p, jdp->dbase + offset, len); | ||
235 | kunmap_atomic(p); | ||
236 | err = BLK_STS_OK; | ||
237 | end: | ||
238 | if (!__blk_end_request_cur(req, err)) | ||
239 | req = jsfd_next_request(); | ||
240 | } | ||
241 | } | ||
242 | |||
243 | static void jsfd_do_request(struct request_queue *q) | ||
244 | { | ||
245 | jsfd_request(); | ||
246 | } | ||
247 | |||
248 | /* | ||
249 | * The memory devices use the full 32/64 bits of the offset, and so we cannot | ||
250 | * check against negative addresses: they are ok. The return value is weird, | ||
251 | * though, in that case (0). | ||
252 | * | ||
253 | * also note that seeking relative to the "end of file" isn't supported: | ||
254 | * it has no meaning, so it returns -EINVAL. | ||
255 | */ | ||
256 | static loff_t jsf_lseek(struct file * file, loff_t offset, int orig) | ||
257 | { | ||
258 | loff_t ret; | ||
259 | |||
260 | mutex_lock(&jsf_mutex); | ||
261 | switch (orig) { | ||
262 | case 0: | ||
263 | file->f_pos = offset; | ||
264 | ret = file->f_pos; | ||
265 | break; | ||
266 | case 1: | ||
267 | file->f_pos += offset; | ||
268 | ret = file->f_pos; | ||
269 | break; | ||
270 | default: | ||
271 | ret = -EINVAL; | ||
272 | } | ||
273 | mutex_unlock(&jsf_mutex); | ||
274 | return ret; | ||
275 | } | ||
276 | |||
277 | /* | ||
278 | * OS SIMM Cannot be read in other size but a 32bits word. | ||
279 | */ | ||
280 | static ssize_t jsf_read(struct file * file, char __user * buf, | ||
281 | size_t togo, loff_t *ppos) | ||
282 | { | ||
283 | unsigned long p = *ppos; | ||
284 | char __user *tmp = buf; | ||
285 | |||
286 | union byte4 { | ||
287 | char s[4]; | ||
288 | unsigned int n; | ||
289 | } b; | ||
290 | |||
291 | if (p < JSF_BASE_ALL || p >= JSF_BASE_TOP) { | ||
292 | return 0; | ||
293 | } | ||
294 | |||
295 | if ((p + togo) < p /* wrap */ | ||
296 | || (p + togo) >= JSF_BASE_TOP) { | ||
297 | togo = JSF_BASE_TOP - p; | ||
298 | } | ||
299 | |||
300 | if (p < JSF_BASE_ALL && togo != 0) { | ||
301 | #if 0 /* __bzero XXX */ | ||
302 | size_t x = JSF_BASE_ALL - p; | ||
303 | if (x > togo) x = togo; | ||
304 | clear_user(tmp, x); | ||
305 | tmp += x; | ||
306 | p += x; | ||
307 | togo -= x; | ||
308 | #else | ||
309 | /* | ||
310 | * Implementation of clear_user() calls __bzero | ||
311 | * without regard to modversions, | ||
312 | * so we cannot build a module. | ||
313 | */ | ||
314 | return 0; | ||
315 | #endif | ||
316 | } | ||
317 | |||
318 | while (togo >= 4) { | ||
319 | togo -= 4; | ||
320 | b.n = jsf_inl(p); | ||
321 | if (copy_to_user(tmp, b.s, 4)) | ||
322 | return -EFAULT; | ||
323 | tmp += 4; | ||
324 | p += 4; | ||
325 | } | ||
326 | |||
327 | /* | ||
328 | * XXX Small togo may remain if 1 byte is ordered. | ||
329 | * It would be nice if we did a word size read and unpacked it. | ||
330 | */ | ||
331 | |||
332 | *ppos = p; | ||
333 | return tmp-buf; | ||
334 | } | ||
335 | |||
336 | static ssize_t jsf_write(struct file * file, const char __user * buf, | ||
337 | size_t count, loff_t *ppos) | ||
338 | { | ||
339 | return -ENOSPC; | ||
340 | } | ||
341 | |||
342 | /* | ||
343 | */ | ||
344 | static int jsf_ioctl_erase(unsigned long arg) | ||
345 | { | ||
346 | unsigned long p; | ||
347 | |||
348 | /* p = jsf0.base; hits wrong bank */ | ||
349 | p = 0x20400000; | ||
350 | |||
351 | jsf_outl(p, 0xAAAAAAAA); /* Unlock 1 Write 1 */ | ||
352 | jsf_outl(p, 0x55555555); /* Unlock 1 Write 2 */ | ||
353 | jsf_outl(p, 0x80808080); /* Erase setup */ | ||
354 | jsf_outl(p, 0xAAAAAAAA); /* Unlock 2 Write 1 */ | ||
355 | jsf_outl(p, 0x55555555); /* Unlock 2 Write 2 */ | ||
356 | jsf_outl(p, 0x10101010); /* Chip erase */ | ||
357 | |||
358 | #if 0 | ||
359 | /* | ||
360 | * This code is ok, except that counter based timeout | ||
361 | * has no place in this world. Let's just drop timeouts... | ||
362 | */ | ||
363 | { | ||
364 | int i; | ||
365 | __u32 x; | ||
366 | for (i = 0; i < 1000000; i++) { | ||
367 | x = jsf_inl(p); | ||
368 | if ((x & 0x80808080) == 0x80808080) break; | ||
369 | } | ||
370 | if ((x & 0x80808080) != 0x80808080) { | ||
371 | printk("jsf0: erase timeout with 0x%08x\n", x); | ||
372 | } else { | ||
373 | printk("jsf0: erase done with 0x%08x\n", x); | ||
374 | } | ||
375 | } | ||
376 | #else | ||
377 | jsf_wait(p); | ||
378 | #endif | ||
379 | |||
380 | return 0; | ||
381 | } | ||
382 | |||
383 | /* | ||
384 | * Program a block of flash. | ||
385 | * Very simple because we can do it byte by byte anyway. | ||
386 | */ | ||
387 | static int jsf_ioctl_program(void __user *arg) | ||
388 | { | ||
389 | struct jsflash_program_arg abuf; | ||
390 | char __user *uptr; | ||
391 | unsigned long p; | ||
392 | unsigned int togo; | ||
393 | union { | ||
394 | unsigned int n; | ||
395 | char s[4]; | ||
396 | } b; | ||
397 | |||
398 | if (copy_from_user(&abuf, arg, JSFPRGSZ)) | ||
399 | return -EFAULT; | ||
400 | p = abuf.off; | ||
401 | togo = abuf.size; | ||
402 | if ((togo & 3) || (p & 3)) return -EINVAL; | ||
403 | |||
404 | uptr = (char __user *) (unsigned long) abuf.data; | ||
405 | while (togo != 0) { | ||
406 | togo -= 4; | ||
407 | if (copy_from_user(&b.s[0], uptr, 4)) | ||
408 | return -EFAULT; | ||
409 | jsf_write4(p, b.n); | ||
410 | p += 4; | ||
411 | uptr += 4; | ||
412 | } | ||
413 | |||
414 | return 0; | ||
415 | } | ||
416 | |||
417 | static long jsf_ioctl(struct file *f, unsigned int cmd, unsigned long arg) | ||
418 | { | ||
419 | mutex_lock(&jsf_mutex); | ||
420 | int error = -ENOTTY; | ||
421 | void __user *argp = (void __user *)arg; | ||
422 | |||
423 | if (!capable(CAP_SYS_ADMIN)) { | ||
424 | mutex_unlock(&jsf_mutex); | ||
425 | return -EPERM; | ||
426 | } | ||
427 | switch (cmd) { | ||
428 | case JSFLASH_IDENT: | ||
429 | if (copy_to_user(argp, &jsf0.id, JSFIDSZ)) { | ||
430 | mutex_unlock(&jsf_mutex); | ||
431 | return -EFAULT; | ||
432 | } | ||
433 | break; | ||
434 | case JSFLASH_ERASE: | ||
435 | error = jsf_ioctl_erase(arg); | ||
436 | break; | ||
437 | case JSFLASH_PROGRAM: | ||
438 | error = jsf_ioctl_program(argp); | ||
439 | break; | ||
440 | } | ||
441 | |||
442 | mutex_unlock(&jsf_mutex); | ||
443 | return error; | ||
444 | } | ||
445 | |||
446 | static int jsf_mmap(struct file * file, struct vm_area_struct * vma) | ||
447 | { | ||
448 | return -ENXIO; | ||
449 | } | ||
450 | |||
451 | static int jsf_open(struct inode * inode, struct file * filp) | ||
452 | { | ||
453 | mutex_lock(&jsf_mutex); | ||
454 | if (jsf0.base == 0) { | ||
455 | mutex_unlock(&jsf_mutex); | ||
456 | return -ENXIO; | ||
457 | } | ||
458 | if (test_and_set_bit(0, (void *)&jsf0.busy) != 0) { | ||
459 | mutex_unlock(&jsf_mutex); | ||
460 | return -EBUSY; | ||
461 | } | ||
462 | |||
463 | mutex_unlock(&jsf_mutex); | ||
464 | return 0; /* XXX What security? */ | ||
465 | } | ||
466 | |||
467 | static int jsf_release(struct inode *inode, struct file *file) | ||
468 | { | ||
469 | jsf0.busy = 0; | ||
470 | return 0; | ||
471 | } | ||
472 | |||
473 | static const struct file_operations jsf_fops = { | ||
474 | .owner = THIS_MODULE, | ||
475 | .llseek = jsf_lseek, | ||
476 | .read = jsf_read, | ||
477 | .write = jsf_write, | ||
478 | .unlocked_ioctl = jsf_ioctl, | ||
479 | .mmap = jsf_mmap, | ||
480 | .open = jsf_open, | ||
481 | .release = jsf_release, | ||
482 | }; | ||
483 | |||
484 | static struct miscdevice jsf_dev = { JSF_MINOR, "jsflash", &jsf_fops }; | ||
485 | |||
486 | static const struct block_device_operations jsfd_fops = { | ||
487 | .owner = THIS_MODULE, | ||
488 | }; | ||
489 | |||
490 | static int jsflash_init(void) | ||
491 | { | ||
492 | int rc; | ||
493 | struct jsflash *jsf; | ||
494 | phandle node; | ||
495 | char banner[128]; | ||
496 | struct linux_prom_registers reg0; | ||
497 | |||
498 | node = prom_getchild(prom_root_node); | ||
499 | node = prom_searchsiblings(node, "flash-memory"); | ||
500 | if (node != 0 && (s32)node != -1) { | ||
501 | if (prom_getproperty(node, "reg", | ||
502 | (char *)®0, sizeof(reg0)) == -1) { | ||
503 | printk("jsflash: no \"reg\" property\n"); | ||
504 | return -ENXIO; | ||
505 | } | ||
506 | if (reg0.which_io != 0) { | ||
507 | printk("jsflash: bus number nonzero: 0x%x:%x\n", | ||
508 | reg0.which_io, reg0.phys_addr); | ||
509 | return -ENXIO; | ||
510 | } | ||
511 | /* | ||
512 | * Flash may be somewhere else, for instance on Ebus. | ||
513 | * So, don't do the following check for IIep flash space. | ||
514 | */ | ||
515 | #if 0 | ||
516 | if ((reg0.phys_addr >> 24) != 0x20) { | ||
517 | printk("jsflash: suspicious address: 0x%x:%x\n", | ||
518 | reg0.which_io, reg0.phys_addr); | ||
519 | return -ENXIO; | ||
520 | } | ||
521 | #endif | ||
522 | if ((int)reg0.reg_size <= 0) { | ||
523 | printk("jsflash: bad size 0x%x\n", (int)reg0.reg_size); | ||
524 | return -ENXIO; | ||
525 | } | ||
526 | } else { | ||
527 | /* XXX Remove this code once PROLL ID12 got widespread */ | ||
528 | printk("jsflash: no /flash-memory node, use PROLL >= 12\n"); | ||
529 | prom_getproperty(prom_root_node, "banner-name", banner, 128); | ||
530 | if (strcmp (banner, "JavaStation-NC") != 0 && | ||
531 | strcmp (banner, "JavaStation-E") != 0) { | ||
532 | return -ENXIO; | ||
533 | } | ||
534 | reg0.which_io = 0; | ||
535 | reg0.phys_addr = 0x20400000; | ||
536 | reg0.reg_size = 0x00800000; | ||
537 | } | ||
538 | |||
539 | /* Let us be really paranoid for modifications to probing code. */ | ||
540 | if (sparc_cpu_model != sun4m) { | ||
541 | /* We must be on sun4m because we use MMU Bypass ASI. */ | ||
542 | return -ENXIO; | ||
543 | } | ||
544 | |||
545 | if (jsf0.base == 0) { | ||
546 | jsf = &jsf0; | ||
547 | |||
548 | jsf->base = reg0.phys_addr; | ||
549 | jsf->size = reg0.reg_size; | ||
550 | |||
551 | /* XXX Redo the userland interface. */ | ||
552 | jsf->id.off = JSF_BASE_ALL; | ||
553 | jsf->id.size = 0x01000000; /* 16M - all segments */ | ||
554 | strcpy(jsf->id.name, "Krups_all"); | ||
555 | |||
556 | jsf->dv[0].dbase = jsf->base; | ||
557 | jsf->dv[0].dsize = jsf->size; | ||
558 | jsf->dv[1].dbase = jsf->base + 1024; | ||
559 | jsf->dv[1].dsize = jsf->size - 1024; | ||
560 | jsf->dv[2].dbase = JSF_BASE_ALL; | ||
561 | jsf->dv[2].dsize = 0x01000000; | ||
562 | |||
563 | printk("Espresso Flash @0x%lx [%d MB]\n", jsf->base, | ||
564 | (int) (jsf->size / (1024*1024))); | ||
565 | } | ||
566 | |||
567 | if ((rc = misc_register(&jsf_dev)) != 0) { | ||
568 | printk(KERN_ERR "jsf: unable to get misc minor %d\n", | ||
569 | JSF_MINOR); | ||
570 | jsf0.base = 0; | ||
571 | return rc; | ||
572 | } | ||
573 | |||
574 | return 0; | ||
575 | } | ||
576 | |||
577 | static int jsfd_init(void) | ||
578 | { | ||
579 | static DEFINE_SPINLOCK(lock); | ||
580 | struct jsflash *jsf; | ||
581 | struct jsfd_part *jdp; | ||
582 | int err; | ||
583 | int i; | ||
584 | |||
585 | if (jsf0.base == 0) | ||
586 | return -ENXIO; | ||
587 | |||
588 | err = -ENOMEM; | ||
589 | for (i = 0; i < JSF_MAX; i++) { | ||
590 | struct gendisk *disk = alloc_disk(1); | ||
591 | if (!disk) | ||
592 | goto out; | ||
593 | disk->queue = blk_init_queue(jsfd_do_request, &lock); | ||
594 | if (!disk->queue) { | ||
595 | put_disk(disk); | ||
596 | goto out; | ||
597 | } | ||
598 | jsfd_disk[i] = disk; | ||
599 | } | ||
600 | |||
601 | if (register_blkdev(JSFD_MAJOR, "jsfd")) { | ||
602 | err = -EIO; | ||
603 | goto out; | ||
604 | } | ||
605 | |||
606 | for (i = 0; i < JSF_MAX; i++) { | ||
607 | struct gendisk *disk = jsfd_disk[i]; | ||
608 | if ((i & JSF_PART_MASK) >= JSF_NPART) continue; | ||
609 | jsf = &jsf0; /* actually, &jsfv[i >> JSF_PART_BITS] */ | ||
610 | jdp = &jsf->dv[i&JSF_PART_MASK]; | ||
611 | |||
612 | disk->major = JSFD_MAJOR; | ||
613 | disk->first_minor = i; | ||
614 | sprintf(disk->disk_name, "jsfd%d", i); | ||
615 | disk->fops = &jsfd_fops; | ||
616 | set_capacity(disk, jdp->dsize >> 9); | ||
617 | disk->private_data = jdp; | ||
618 | add_disk(disk); | ||
619 | set_disk_ro(disk, 1); | ||
620 | } | ||
621 | return 0; | ||
622 | out: | ||
623 | while (i--) | ||
624 | put_disk(jsfd_disk[i]); | ||
625 | return err; | ||
626 | } | ||
627 | |||
628 | MODULE_LICENSE("GPL"); | ||
629 | |||
630 | static int __init jsflash_init_module(void) { | ||
631 | int rc; | ||
632 | |||
633 | if ((rc = jsflash_init()) == 0) { | ||
634 | jsfd_init(); | ||
635 | return 0; | ||
636 | } | ||
637 | return rc; | ||
638 | } | ||
639 | |||
640 | static void __exit jsflash_cleanup_module(void) | ||
641 | { | ||
642 | int i; | ||
643 | |||
644 | for (i = 0; i < JSF_MAX; i++) { | ||
645 | if ((i & JSF_PART_MASK) >= JSF_NPART) continue; | ||
646 | del_gendisk(jsfd_disk[i]); | ||
647 | blk_cleanup_queue(jsfd_disk[i]->queue); | ||
648 | put_disk(jsfd_disk[i]); | ||
649 | } | ||
650 | if (jsf0.busy) | ||
651 | printk("jsf0: cleaning busy unit\n"); | ||
652 | jsf0.base = 0; | ||
653 | jsf0.busy = 0; | ||
654 | |||
655 | misc_deregister(&jsf_dev); | ||
656 | unregister_blkdev(JSFD_MAJOR, "jsfd"); | ||
657 | } | ||
658 | |||
659 | module_init(jsflash_init_module); | ||
660 | module_exit(jsflash_cleanup_module); | ||