1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51#ifdef MODULE
52# ifndef __KERNEL__
53# define __KERNEL__
54# endif
55# define __NO_VERSION__
56#endif
57
58#include <linux/module.h>
59#include <linux/version.h>
60
61#ifdef MODULE
62char kernel_version [] = UTS_RELEASE;
63#endif
64
65#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
66# define XPRAM_VERSION 24
67#else
68# define XPRAM_VERSION 22
69#endif
70
71#if (XPRAM_VERSION == 24)
72# include <linux/config.h>
73# include <linux/init.h>
74#endif
75#include <linux/sched.h>
76#include <linux/kernel.h>
77#include <linux/slab.h>
78#if (XPRAM_VERSION == 24)
79# include <linux/devfs_fs_kernel.h>
80#endif
81#include <linux/fs.h>
82#include <linux/errno.h>
83#include <linux/timer.h>
84#include <linux/types.h>
85#include <linux/ctype.h>
86#include <linux/fcntl.h>
87#include <linux/hdreg.h>
88
89#include <asm/system.h>
90#include <asm/uaccess.h>
91
92#if (XPRAM_VERSION == 24)
93#define MAJOR_NR xpram_major
94int xpram_major;
95devfs_handle_t xpram_devfs_handle;
96
97#define DEVICE_NR(device) MINOR(device)
98#define DEVICE_NAME "xpram"
99#define DEVICE_INTR xpram_intrptr
100#define DEVICE_NO_RANDOM
101#define DEVICE_OFF(d)
102
103#include <linux/blk.h>
104
105#include "xpram.h"
106
107__setup("xpram_parts=", xpram_setup);
108#endif
109
110
111
112
113
114
115
116
117
118
119
120#define XPRAM_DEBUG 4
121
122#define PRINTK_HEADER XPRAM_NAME
123
124#if XPRAM_DEBUG > 0
125#define PRINT_DEBUG(x...) printk ( KERN_DEBUG PRINTK_HEADER "debug:" x )
126#define PRINT_INFO(x...) printk ( KERN_INFO PRINTK_HEADER "info:" x )
127#define PRINT_WARN(x...) printk ( KERN_WARNING PRINTK_HEADER "warning:" x )
128#define PRINT_ERR(x...) printk ( KERN_ERR PRINTK_HEADER "error:" x )
129#define PRINT_FATAL(x...) panic ( PRINTK_HEADER "panic:"x )
130#else
131#define PRINT_DEBUG(x...) printk ( KERN_DEBUG PRINTK_HEADER "debug:" x )
132#define PRINT_INFO(x...) printk ( KERN_DEBUG PRINTK_HEADER "info:" x )
133#define PRINT_WARN(x...) printk ( KERN_DEBUG PRINTK_HEADER "warning:" x )
134#define PRINT_ERR(x...) printk ( KERN_DEBUG PRINTK_HEADER "error:" x )
135#define PRINT_FATAL(x...) printk ( KERN_DEBUG PRINTK_HEADER "panic:" x )
136#endif
137
138#if (XPRAM_VERSION == 22)
139#define MAJOR_NR xpram_major
140int xpram_major;
141
142#define DEVICE_NR(device) MINOR(device)
143#define DEVICE_NAME "xpram"
144#define DEVICE_INTR xpram_intrptr
145#define DEVICE_NO_RANDOM
146
147
148#define DEVICE_OFF(d)
149
150#define DEVICE_REQUEST *xpram_dummy_device_request
151
152#include <linux/blk.h>
153
154#include "xpram.h"
155#endif
156
157
158
159
160
161
162
163
164static int major = XPRAM_MAJOR;
165static int devs = XPRAM_DEVS;
166static int rahead = XPRAM_RAHEAD;
167static int sizes[XPRAM_MAX_DEVS] = { 0, };
168static int blksize = XPRAM_BLKSIZE;
169static int hardsect = XPRAM_HARDSECT;
170
171int xpram_devs, xpram_rahead;
172int xpram_blksize, xpram_hardsect;
173int xpram_mem_avail = 0;
174unsigned int xpram_sizes[XPRAM_MAX_DEVS];
175
176
177MODULE_PARM(devs,"i");
178MODULE_PARM(sizes,"1-" __MODULE_STRING(XPRAM_MAX_DEVS) "i");
179
180MODULE_PARM_DESC(devs, "number of devices (\"partitions\"), " \
181 "the default is " __MODULE_STRING(XPRAM_DEVS) "\n");
182MODULE_PARM_DESC(sizes, "list of device (partition) sizes " \
183 "the defaults are 0s \n" \
184 "All devices with size 0 equally partition the "
185 "remaining space on the expanded strorage not "
186 "claimed by explicit sizes\n");
187MODULE_LICENSE("GPL");
188
189
190
191
192Xpram_Dev *xpram_devices = NULL;
193int *xpram_blksizes = NULL;
194int *xpram_hardsects = NULL;
195int *xpram_offsets = NULL;
196
197#define MIN(x,y) ((x) < (y) ? (x) : (y))
198#define MAX(x,y) ((x) > (y) ? (x) : (y))
199
200
201
202
203
204
205#define NEXT4(x) ((x & 0x3) ? (x+4-(x &0x3)) : (x))
206#define LAST4(x) ((x & 0x3) ? (x-4+(x & 0x3)) : (x))
207
208#if 0
209#define NEXT4(x) ((((x-1)>>2)>>2)+4)
210#define LAST4(x) (((x+3)>>2)<<2)
211#endif
212
213
214#define XPRAM_INVALF -1
215#define XPRAM_HEXF 0
216#define XPRAM_DECF 1
217
218
219
220
221
222
223
224
225
226
227
228
229static void
230xpram_scan_to_next_comma (char **strptr)
231{
232 while ( ((**strptr) != ',') && (**strptr) )
233 (*strptr)++;
234}
235
236
237
238
239
240
241
242
243static int
244xpram_get_hexdigit (char c)
245{
246 if ((c >= '0') && (c <= '9'))
247 return c - '0';
248 if ((c >= 'a') && (c <= 'f'))
249 return c + 10 - 'a';
250 if ((c >= 'A') && (c <= 'F'))
251 return c + 10 - 'A';
252 return -1;
253}
254
255
256
257
258
259
260
261
262
263
264
265
266
267static int
268xpram_int_format(char **strptr)
269{
270 if ( !isdigit(**strptr) )
271 return XPRAM_INVALF;
272 if ( (**strptr == '0')
273 && ( (*((*strptr)+1) == 'x') || (*((*strptr) +1) == 'X') )
274 && isxdigit(*((*strptr)+2)) ) {
275 *strptr=(*strptr)+2;
276 return XPRAM_HEXF;
277 } else return XPRAM_DECF;
278}
279
280
281
282
283
284
285
286
287
288
289
290static int
291xpram_read_decint (char ** strptr)
292{
293 int res=0;
294 while ( isdigit(**strptr) ) {
295 res = (res*10) + xpram_get_hexdigit(**strptr);
296 (*strptr)++;
297 }
298 return res;
299}
300
301
302
303
304
305
306
307
308
309
310
311static int
312xpram_read_hexint (char ** strptr)
313{
314 int res=0;
315 while ( isxdigit(**strptr) ) {
316 res = (res<<4) + xpram_get_hexdigit(**strptr);
317 (*strptr)++;
318 }
319 return res;
320}
321
322
323
324
325
326
327
328
329
330
331
332static int
333xpram_read_int (char ** strptr)
334{
335 switch ( xpram_int_format(strptr) ) {
336 case XPRAM_INVALF: return -EINVAL;
337 case XPRAM_HEXF: return xpram_read_hexint(strptr);
338 case XPRAM_DECF: return xpram_read_decint(strptr);
339 default: return -EINVAL;
340 }
341}
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358static int
359xpram_read_size (char ** strptr)
360{
361 int res;
362
363 res=xpram_read_int(strptr);
364 if ( res < 0 )return res;
365 switch ( **strptr ) {
366 case 'g':
367 case 'G': res=res*1024;
368 case 'm':
369 case 'M': res=res*1024;
370 case 'k' :
371 case 'K' : (* strptr)++;
372 }
373
374 return res;
375}
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395static int
396xpram_read_size_list_tail (char ** strptr, int maxl, int * ilist)
397{
398 int i=0;
399 char *str = *strptr;
400 int res=0;
401
402 while ( (*str == ',') && (i < maxl) ) {
403 str++;
404 ilist[i] = xpram_read_size(&str);
405 if ( ilist[i] == -EINVAL ) {
406 xpram_scan_to_next_comma(&str);
407 res = -EINVAL;
408 }
409 i++;
410 }
411 return res;
412#if 0
413 if ( *str != 0 && *str != ' ' ) {
414 ilist[MAX(i-1,0)] = -EINVAL;
415 return -EINVAL;
416 } else return 0;
417#endif
418}
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435long xpram_page_in (unsigned long page_addr, unsigned long xpage_index)
436{
437 int cc=0;
438 unsigned long real_page_addr = __pa(page_addr);
439#ifndef CONFIG_ARCH_S390X
440 __asm__ __volatile__ (
441 " lr 1,%1 \n"
442 " lr 2,%2 \n"
443 " .long 0xb22e0012 \n"
444
445 "0: ipm %0 \n"
446 " srl %0,28 \n"
447 "1: \n"
448 ".section .fixup,\"ax\"\n"
449 "2: lhi %0,2 \n"
450 " bras 1,3f \n"
451 " .long 1b \n"
452 "3: l 1,0(1) \n"
453 " br 1 \n"
454 ".previous \n"
455 ".section __ex_table,\"a\"\n"
456 " .align 4 \n"
457 " .long 0b,2b \n"
458 ".previous \n"
459 : "=d" (cc) : "d" (real_page_addr), "d" (xpage_index) : "cc", "1", "2"
460 );
461#else
462 __asm__ __volatile__ (
463 " lgr 1,%1 \n"
464 " lgr 2,%2 \n"
465 " .long 0xb22e0012 \n"
466
467 "0: ipm %0 \n"
468 " srl %0,28 \n"
469 "1: \n"
470 ".section .fixup,\"ax\"\n"
471 "2: lghi %0,2 \n"
472 " jg 1b \n"
473 ".previous \n"
474 ".section __ex_table,\"a\"\n"
475 " .align 8 \n"
476 " .quad 0b,2b \n"
477 ".previous \n"
478 : "=d" (cc) : "d" (real_page_addr), "d" (xpage_index) : "cc", "1", "2"
479 );
480#endif
481 switch (cc) {
482 case 0: return 0;
483 case 1: return -EIO;
484 case 2: return -ENXIO;
485 case 3: return -ENXIO;
486 default: return -EIO;
487 };
488}
489
490
491
492
493
494
495
496
497
498
499long xpram_page_out (unsigned long page_addr, unsigned long xpage_index)
500{
501 int cc=0;
502 unsigned long real_page_addr = __pa(page_addr);
503#ifndef CONFIG_ARCH_S390X
504 __asm__ __volatile__ (
505 " lr 1,%1 \n"
506 " lr 2,%2 \n"
507 " .long 0xb22f0012 \n"
508
509 "0: ipm %0 \n"
510 " srl %0,28 \n"
511 "1: \n"
512 ".section .fixup,\"ax\"\n"
513 "2: lhi %0,2 \n"
514 " bras 1,3f \n"
515 " .long 1b \n"
516 "3: l 1,0(1) \n"
517 " br 1 \n"
518 ".previous \n"
519 ".section __ex_table,\"a\"\n"
520 " .align 4 \n"
521 " .long 0b,2b \n"
522 ".previous \n"
523 : "=d" (cc) : "d" (real_page_addr), "d" (xpage_index) : "cc", "1", "2"
524 );
525#else
526 __asm__ __volatile__ (
527 " lgr 1,%1 \n"
528 " lgr 2,%2 \n"
529 " .long 0xb22f0012 \n"
530
531 "0: ipm %0 \n"
532 " srl %0,28 \n"
533 "1: \n"
534 ".section .fixup,\"ax\"\n"
535 "2: lghi %0,2 \n"
536 " jg 1b \n"
537 ".previous \n"
538 ".section __ex_table,\"a\"\n"
539 " .align 8 \n"
540 " .quad 0b,2b \n"
541 ".previous \n"
542 : "=d" (cc) : "d" (real_page_addr), "d" (xpage_index) : "cc", "1", "2"
543 );
544#endif
545 switch (cc) {
546 case 0: return 0;
547 case 1: return -EIO;
548 case 2: { PRINT_ERR("expanded storage lost!\n"); return -ENXIO; }
549 case 3: return -ENXIO;
550 default: return -EIO;
551 }
552}
553
554
555
556
557
558
559int xpram_size(void)
560{
561 int cc=0;
562 unsigned long base=0;
563 unsigned long po, pi, rpi;
564
565 unsigned long mem_page = __get_free_page(GFP_KERNEL);
566
567
568 pi=1;
569 for (po=0; po <= 32; po++) {
570 cc=xpram_page_in(mem_page,base+pi-1);
571 if ( cc ) break;
572 pi <<= 1;
573 }
574 if ( cc && (po < 31 ) ) {
575 pi >>=1;
576 base += pi;
577 pi >>=1;
578 for ( ; pi > 0; pi >>= 1) {
579 rpi = pi - 1;
580 cc=xpram_page_in(mem_page,base+rpi);
581 if ( !cc ) base += pi;
582 }
583 }
584
585 free_page (mem_page);
586
587 if ( cc && (po < 31) )
588 return (XPRAM_KB_IN_PG * base);
589 else
590 return INT_MAX;
591}
592
593
594
595
596
597int xpram_open (struct inode *inode, struct file *filp)
598{
599 Xpram_Dev *dev;
600 int num = MINOR(inode->i_rdev);
601
602
603 if (num >= xpram_devs) return -ENODEV;
604 dev = xpram_devices + num;
605
606 PRINT_DEBUG("calling xpram_open for device %d\n",num);
607 PRINT_DEBUG(" size %dkB, name %s, usage: %d\n",
608 dev->size,dev->device_name, atomic_read(&(dev->usage)));
609
610 atomic_inc(&(dev->usage));
611 return 0;
612}
613
614int xpram_release (struct inode *inode, struct file *filp)
615{
616 Xpram_Dev *dev = xpram_devices + MINOR(inode->i_rdev);
617
618 PRINT_DEBUG("calling xpram_release for device %d (size %dkB, usage: %d)\n",MINOR(inode->i_rdev) ,dev->size,atomic_read(&(dev->usage)));
619
620
621
622
623
624
625 if (!atomic_dec_return(&(dev->usage))) {
626
627
628 }
629 return(0);
630}
631
632
633
634
635
636
637int xpram_ioctl (struct inode *inode, struct file *filp,
638 unsigned int cmd, unsigned long arg)
639{
640 int err, size;
641 struct hd_geometry *geo = (struct hd_geometry *)arg;
642
643 PRINT_DEBUG("ioctl 0x%x 0x%lx\n", cmd, arg);
644 switch(cmd) {
645
646 case BLKGETSIZE:
647
648 return put_user( 1024* xpram_sizes[MINOR(inode->i_rdev)]
649 / XPRAM_SOFTSECT,
650 (unsigned long *) arg);
651
652 case BLKGETSIZE64:
653 return put_user( (u64)(1024* xpram_sizes[MINOR(inode->i_rdev)]
654 / XPRAM_SOFTSECT) << 9,
655 (u64 *) arg);
656
657 case BLKFLSBUF:
658 fsync_dev(inode->i_rdev);
659 if ( capable(CAP_SYS_ADMIN) )invalidate_buffers(inode->i_rdev);
660 return 0;
661
662 case BLKRAGET:
663 if (!arg) return -EINVAL;
664 err = 0;
665
666
667 put_user(read_ahead[MAJOR(inode->i_rdev)], (long *)arg);
668
669 return 0;
670
671 case BLKRASET:
672 if (!capable(CAP_SYS_ADMIN)) return -EACCES;
673 if (arg > 0xff) return -EINVAL;
674 read_ahead[MAJOR(inode->i_rdev)] = arg;
675 atomic_eieio();
676 return 0;
677
678 case BLKRRPART:
679 return -EINVAL;
680
681
682#if (XPRAM_VERSION == 22)
683 RO_IOCTLS(inode->i_rdev, arg);
684
685
686
687#endif
688
689 case HDIO_GETGEO:
690
691
692
693
694
695 size = xpram_mem_avail * 1024 / XPRAM_SOFTSECT;
696
697 size &= ~0x3f;
698 if (geo==NULL) return -EINVAL;
699
700
701
702
703
704 put_user(size >> 6, &geo->cylinders);
705 put_user( 4, &geo->heads);
706 put_user( 16, &geo->sectors);
707 put_user( 4, &geo->start);
708
709 return 0;
710 }
711
712 return -EINVAL;
713}
714
715
716
717
718
719#if (XPRAM_VERSION == 22)
720struct file_operations xpram_fops = {
721 NULL,
722 block_read,
723 block_write,
724 NULL,
725 NULL,
726 xpram_ioctl,
727 NULL,
728 xpram_open,
729 NULL,
730 xpram_release,
731 block_fsync,
732 NULL,
733 NULL,
734 NULL
735};
736#endif
737
738#if (XPRAM_VERSION == 24)
739struct block_device_operations xpram_devops =
740{
741 owner: THIS_MODULE,
742 ioctl: xpram_ioctl,
743 open: xpram_open,
744 release: xpram_release,
745};
746#endif
747
748
749
750
751
752void xpram_request(request_queue_t * queue)
753{
754 Xpram_Dev *device;
755
756
757
758 unsigned long page_no;
759 unsigned long sects_to_copy;
760 char * buffer;
761 int dev_no;
762 int fault;
763#if ( XPRAM_VERSION == 24 )
764 struct request * current_req;
765#else
766# define current_req CURRENT
767#endif
768
769 while(1) {
770 INIT_REQUEST;
771
772 fault=0;
773#if ( XPRAM_VERSION == 24 )
774 current_req = blkdev_entry_next_request (&queue->queue_head);
775#endif
776 dev_no = DEVICE_NR(current_req->rq_dev);
777
778 if ( dev_no > xpram_devs ) {
779 static int count = 0;
780 if (count++ < 5)
781 PRINT_WARN(" request for unknown device\n");
782 end_request(0);
783 continue;
784 }
785
786
787 device = xpram_devices + dev_no;
788 sects_to_copy = current_req->current_nr_sectors;
789
790 if ( XPRAM_SEC2KB(sects_to_copy) > xpram_sizes[dev_no] ) {
791 PRINT_WARN(" request past end of device\n");
792 end_request(0);
793 continue;
794 }
795
796
797#if 0
798 PRINT_DEBUG(" req %lx, sect %lx, to copy %lx, buf addr %lx\n", (unsigned long) current_req, current_req->sector, sects_to_copy, (unsigned long) current_req->buffer);
799#endif
800 buffer = current_req->buffer;
801#if XPRAM_SEC_IN_PG != 1
802
803 if ( current_req->sector & (XPRAM_SEC_IN_PG - 1) ) {
804 PRINT_WARN(" request does not start at an expanded storage page boundery\n");
805 PRINT_WARN(" referenced sector: %ld\n",current_req->sector);
806 end_request(0);
807 continue;
808 }
809
810 if ( sects_to_copy & (XPRAM_SEC_IN_PG - 1) ) {
811 PRINT_WARN(" request referes to a partial expanded storage page\n");
812 end_request(0);
813 continue;
814 }
815#endif
816
817 if ( ((unsigned long)buffer) & (XPRAM_PGSIZE-1) ) {
818 PRINT_WARN(" request buffer is not aligned with kernel pages\n");
819 end_request(0);
820 continue;
821 }
822
823
824 page_no = (xpram_offsets[dev_no] >> XPRAM_KB_IN_PG_ORDER)
825 + (current_req->sector >> XPRAM_SEC_IN_PG_ORDER);
826
827#if 0
828 PRINT_DEBUG("request: %d ( dev %d, copy %d sectors, at page %d ) \n", current_req->cmd,dev_no,sects_to_copy,page_no);
829#endif
830
831 switch(current_req->cmd) {
832 case READ:
833 do {
834 if ( (fault=xpram_page_in((unsigned long)buffer,page_no)) ) {
835 PRINT_WARN("xpram(dev %d): page in failed for page %ld.\n",dev_no,page_no);
836 break;
837 }
838 sects_to_copy -= XPRAM_SEC_IN_PG;
839 buffer += XPRAM_PGSIZE;
840 page_no++;
841 } while ( sects_to_copy > 0 );
842 break;
843 case WRITE:
844 do {
845 if ( (fault=xpram_page_out((unsigned long)buffer,page_no))
846 ) {
847 PRINT_WARN("xpram(dev %d): page out failed for page %ld.\n",dev_no,page_no);
848 break;
849 }
850 sects_to_copy -= XPRAM_SEC_IN_PG;
851 buffer += XPRAM_PGSIZE;
852 page_no++;
853 } while ( sects_to_copy > 0 );
854 break;
855 default:
856
857 end_request(0);
858 continue;
859 }
860 if ( fault ) end_request(0);
861 else end_request(1);
862 }
863}
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892#if (XPRAM_VERSION == 22)
893void xpram_setup (char *str, int *ints)
894#else
895int xpram_setup (char *str)
896#endif
897{
898 devs = xpram_read_int(&str);
899 if ( devs != -EINVAL )
900 if ( xpram_read_size_list_tail(&str,devs,sizes) < 0 ) {
901 PRINT_ERR("error while reading xpram parameters.\n");
902#if (XPRAM_VERSION == 24)
903 return -EINVAL;
904#endif
905 }
906#if (XPRAM_VERSION == 24)
907 else return 0;
908 else return -EINVAL;
909#elif (XPRAM_VERSION == 22)
910 return;
911#endif
912}
913
914
915
916
917
918
919
920
921int xpram_init(void)
922{
923 int result, i;
924 int mem_usable;
925 int mem_needed=0;
926
927
928
929 int mem_auto_no=0;
930 int mem_auto;
931#if (XPRAM_VERSION == 24)
932 int minor_length;
933 int minor_thresh;
934
935 request_queue_t *q;
936#endif
937
938
939
940
941
942
943 xpram_rahead = rahead;
944 xpram_blksize = blksize;
945 xpram_hardsect = hardsect;
946
947 PRINT_INFO("initializing: %s\n","");
948
949 xpram_major = major;
950 if ( (devs <= 0) || (devs > XPRAM_MAX_DEVS) ) {
951 PRINT_ERR("invalid number %d of devices\n",devs);
952 PRINT_ERR("Giving up xpram\n");
953 return -EINVAL;
954 }
955 xpram_devs = devs;
956 for (i=0; i < xpram_devs; i++) {
957 if ( sizes[i] < 0 ) {
958 PRINT_ERR("Invalid partition size %d kB\n",xpram_sizes[i]);
959 PRINT_ERR("Giving up xpram\n");
960 return -EINVAL;
961 } else {
962 xpram_sizes[i] = NEXT4(sizes[i]);
963 if ( sizes[i] ) mem_needed += xpram_sizes[i];
964 else mem_auto_no++;
965 }
966 }
967
968 PRINT_DEBUG(" major %d \n", xpram_major);
969 PRINT_INFO(" number of devices (partitions): %d \n", xpram_devs);
970 for (i=0; i < xpram_devs; i++) {
971 if ( sizes[i] )
972 PRINT_INFO(" size of partition %d: %d kB\n", i, xpram_sizes[i]);
973 else
974 PRINT_INFO(" size of partition %d to be set automatically\n",i);
975 }
976 PRINT_DEBUG(" memory needed (for sized partitions): %d kB\n", mem_needed);
977 PRINT_DEBUG(" partitions to be sized automatically: %d\n", mem_auto_no);
978
979#if 0
980
981
982
983
984
985
986 if (hardsect != 512) {
987 PRINT_ERR("Can't change hardsect size\n");
988 hardsect = xpram_hardsect = 512;
989 }
990#endif
991 PRINT_INFO(" hardsector size: %dB \n",xpram_hardsect);
992
993
994
995
996#if (XPRAM_VERSION == 22)
997 result = register_blkdev(xpram_major, "xpram", &xpram_fops);
998#elif (XPRAM_VERSION == 24)
999 result = devfs_register_blkdev(xpram_major, "xpram", &xpram_devops);
1000#endif
1001 if (result < 0) {
1002 PRINT_ERR("Can't get major %d\n",xpram_major);
1003 PRINT_ERR("Giving up xpram\n");
1004 return result;
1005 }
1006#if (XPRAM_VERSION == 24)
1007 xpram_devfs_handle = devfs_mk_dir (NULL, "slram", NULL);
1008 devfs_register_series (xpram_devfs_handle, "%u", XPRAM_MAX_DEVS,
1009 DEVFS_FL_DEFAULT, XPRAM_MAJOR, 0,
1010 S_IFBLK | S_IRUSR | S_IWUSR,
1011 &xpram_devops, NULL);
1012#endif
1013 if (xpram_major == 0) xpram_major = result;
1014 major = xpram_major;
1015
1016 result = -ENOMEM;
1017
1018
1019
1020
1021
1022 xpram_mem_avail = xpram_size();
1023 if (!xpram_mem_avail) {
1024 PRINT_ERR("No or not enough expanded memory available\n");
1025 PRINT_ERR("Giving up xpram\n");
1026 result = -ENODEV;
1027 goto fail_malloc;
1028 }
1029 PRINT_INFO(" %d kB expanded memory found.\n",xpram_mem_avail );
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039#if (XPRAM_VERSION == 22)
1040 blk_dev[major].request_fn = xpram_request;
1041#elif (XPRAM_VERSION == 24)
1042 q = BLK_DEFAULT_QUEUE (major);
1043 blk_init_queue (q, xpram_request);
1044 blk_queue_headactive (BLK_DEFAULT_QUEUE (major), 0);
1045#endif
1046 read_ahead[major] = xpram_rahead;
1047
1048
1049 mem_usable=xpram_mem_avail-(XPRAM_UNUSED*(xpram_devs-1));
1050 if ( mem_needed > mem_usable ) {
1051 PRINT_ERR("Not enough expanded memory available\n");
1052 PRINT_ERR("Giving up xpram\n");
1053 goto fail_malloc;
1054 }
1055
1056
1057
1058
1059
1060
1061
1062
1063 if ( mem_auto_no ) {
1064 mem_auto=LAST4((mem_usable-mem_needed)/mem_auto_no);
1065 PRINT_INFO(" automatically determined partition size: %d kB\n", mem_auto);
1066 for (i=0; i < xpram_devs; i++)
1067 if (xpram_sizes[i] == 0) xpram_sizes[i] = mem_auto;
1068 }
1069 blk_size[major]=xpram_sizes;
1070
1071 xpram_offsets = kmalloc(xpram_devs * sizeof(int), GFP_KERNEL);
1072 if (!xpram_offsets) {
1073 PRINT_ERR("Not enough memory for xpram_offsets\n");
1074 PRINT_ERR("Giving up xpram\n");
1075 goto fail_malloc;
1076 }
1077 xpram_offsets[0] = 0;
1078 for (i=1; i < xpram_devs; i++)
1079 xpram_offsets[i] = xpram_offsets[i-1] + xpram_sizes[i-1] + XPRAM_UNUSED;
1080
1081#if 0
1082 for (i=0; i < xpram_devs; i++)
1083 PRINT_DEBUG(" device(%d) offset = %d kB, size = %d kB\n",i, xpram_offsets[i], xpram_sizes[i]);
1084#endif
1085
1086 xpram_blksizes = kmalloc(xpram_devs * sizeof(int), GFP_KERNEL);
1087 if (!xpram_blksizes) {
1088 PRINT_ERR("Not enough memory for xpram_blksizes\n");
1089 PRINT_ERR("Giving up xpram\n");
1090 goto fail_malloc_blksizes;
1091 }
1092 for (i=0; i < xpram_devs; i++)
1093 xpram_blksizes[i] = xpram_blksize;
1094 blksize_size[major]=xpram_blksizes;
1095
1096 xpram_hardsects = kmalloc(xpram_devs * sizeof(int), GFP_KERNEL);
1097 if (!xpram_hardsects) {
1098 PRINT_ERR("Not enough memory for xpram_hardsects\n");
1099 PRINT_ERR("Giving up xpram\n");
1100 goto fail_malloc_hardsects;
1101 }
1102 for (i=0; i < xpram_devs; i++)
1103 xpram_hardsects[i] = xpram_hardsect;
1104 hardsect_size[major]=xpram_hardsects;
1105
1106
1107
1108
1109
1110
1111 xpram_devices = kmalloc(xpram_devs * sizeof (Xpram_Dev), GFP_KERNEL);
1112 if (!xpram_devices) {
1113 PRINT_ERR("Not enough memory for xpram_devices\n");
1114 PRINT_ERR("Giving up xpram\n");
1115 goto fail_malloc_devices;
1116 }
1117 memset(xpram_devices, 0, xpram_devs * sizeof (Xpram_Dev));
1118#if (XPRAM_VERSION == 24)
1119 minor_length = 1;
1120 minor_thresh = 10;
1121#endif
1122 for (i=0; i < xpram_devs; i++) {
1123
1124 xpram_devices[i].size = xpram_sizes[i];
1125 atomic_set(&(xpram_devices[i].usage),0);
1126#if (XPRAM_VERSION == 24)
1127 if (i == minor_thresh) {
1128 minor_length++;
1129 minor_thresh *= 10;
1130 }
1131 xpram_devices[i].device_name =
1132 kmalloc(1 + strlen(XPRAM_DEVICE_NAME_PREFIX) + minor_length,GFP_KERNEL);
1133 if ( xpram_devices[i].device_name == NULL ) {
1134 PRINT_ERR("Not enough memory for xpram_devices[%d].device_name\n",i);
1135 PRINT_ERR("Giving up xpram\n");
1136 goto fail_devfs_register;
1137 }
1138 sprintf(xpram_devices[i].device_name,XPRAM_DEVICE_NAME_PREFIX "%d",i);
1139
1140 PRINT_DEBUG("initializing xpram_open for device %d\n",i);
1141 PRINT_DEBUG(" size %dkB, name %s, usage: %d\n",
1142 xpram_devices[i].size,xpram_devices[i].device_name, atomic_read(&(xpram_devices[i].usage)));
1143
1144#if 0
1145 xpram_devices[i].devfs_entry =
1146 devfs_register(NULL ,
1147 xpram_devices[i].device_name, 0,
1148 0 ,
1149 XPRAM_MAJOR,i,
1150 0755 ,
1151 0 , 0 ,
1152 &xpram_devops,
1153 (void *) &(xpram_devices[i])
1154 );
1155 if ( xpram_devices[i].devfs_entry == NULL ) {
1156 PRINT_ERR("devfs system registry failed\n");
1157 PRINT_ERR("Giving up xpram\n");
1158 goto fail_devfs_register;
1159 }
1160#endif
1161#endif
1162
1163 }
1164
1165 return 0;
1166
1167
1168#if (XPRAM_VERSION == 24)
1169 fail_devfs_register:
1170 for (i=0; i < xpram_devs; i++) {
1171 if ( xpram_devices[i].device_name )
1172 kfree(xpram_devices[i].device_name);
1173 }
1174 kfree(xpram_devices);
1175#endif
1176 fail_malloc_blksizes:
1177 kfree (xpram_offsets);
1178 fail_malloc_hardsects:
1179 kfree (xpram_blksizes);
1180 blksize_size[major] = NULL;
1181 fail_malloc_devices:
1182 kfree(xpram_hardsects);
1183 hardsect_size[major] = NULL;
1184 fail_malloc:
1185 read_ahead[major] = 0;
1186#if (XPRAM_VERSION == 22)
1187 blk_dev[major].request_fn = NULL;
1188#endif
1189
1190 unregister_blkdev(major, "xpram");
1191 return result;
1192}
1193
1194
1195
1196
1197
1198int init_module(void)
1199{
1200 int rc = 0;
1201
1202 PRINT_INFO ("trying to load module\n");
1203 rc = xpram_init ();
1204 if (rc == 0) {
1205 PRINT_INFO ("Module loaded successfully\n");
1206 } else {
1207 PRINT_WARN ("Module load returned rc=%d\n", rc);
1208 }
1209 return rc;
1210}
1211
1212void cleanup_module(void)
1213{
1214 int i;
1215
1216
1217
1218
1219 for (i=0; i<xpram_devs; i++)
1220 fsync_dev(MKDEV(xpram_major, i));
1221
1222#if (XPRAM_VERSION == 22)
1223 blk_dev[major].request_fn = NULL;
1224#endif
1225 read_ahead[major] = 0;
1226 blk_size[major] = NULL;
1227 kfree(blksize_size[major]);
1228 blksize_size[major] = NULL;
1229 kfree(hardsect_size[major]);
1230 hardsect_size[major] = NULL;
1231 kfree(xpram_offsets);
1232
1233
1234#if (XPRAM_VERSION == 22)
1235 unregister_blkdev(major, "xpram");
1236#elif (XPRAM_VERSION == 24)
1237 devfs_unregister(xpram_devfs_handle);
1238 if (devfs_unregister_blkdev(MAJOR_NR, "xpram"))
1239 printk(KERN_WARNING "xpram: cannot unregister blkdev\n");
1240#endif
1241 kfree(xpram_devices);
1242}
1243