OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [uclinux/] [uClinux-2.0.x/] [drivers/] [block/] [linear.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 199 simons
 
2
/*
3
   linear.c : Multiple Devices driver for Linux
4
              Copyright (C) 1994-96 Marc ZYNGIER
5
              <zyngier@ufr-info-p7.ibp.fr> or
6
              <maz@gloups.fdn.fr>
7
 
8
   Linear mode management functions.
9
 
10
   This program is free software; you can redistribute it and/or modify
11
   it under the terms of the GNU General Public License as published by
12
   the Free Software Foundation; either version 2, or (at your option)
13
   any later version.
14
 
15
   You should have received a copy of the GNU General Public License
16
   (for example /usr/src/linux/COPYING); if not, write to the Free
17
   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
*/
19
 
20
#include <linux/module.h>
21
 
22
#include <linux/md.h>
23
#include <linux/linear.h>
24
#include <linux/malloc.h>
25
 
26
#define MAJOR_NR MD_MAJOR
27
#define MD_DRIVER
28
#define MD_PERSONALITY
29
 
30
static int linear_run (int minor, struct md_dev *mddev)
31
{
32
  int cur=0, i, size, dev0_size, nb_zone;
33
  struct linear_data *data;
34
 
35
  MOD_INC_USE_COUNT;
36
 
37
  mddev->private=kmalloc (sizeof (struct linear_data), GFP_KERNEL);
38
  data=(struct linear_data *) mddev->private;
39
 
40
  /*
41
     Find out the smallest device. This was previously done
42
     at registry time, but since it violates modularity,
43
     I moved it here... Any comment ? ;-)
44
   */
45
 
46
  data->smallest=mddev->devices;
47
  for (i=1; i<mddev->nb_dev; i++)
48
    if (data->smallest->size > mddev->devices[i].size)
49
      data->smallest=mddev->devices+i;
50
 
51
  nb_zone=data->nr_zones=
52
    md_size[minor]/data->smallest->size +
53
    (md_size[minor]%data->smallest->size ? 1 : 0);
54
 
55
  data->hash_table=kmalloc (sizeof (struct linear_hash)*nb_zone, GFP_KERNEL);
56
 
57
  size=mddev->devices[cur].size;
58
 
59
  i=0;
60
  while (cur<mddev->nb_dev)
61
  {
62
    data->hash_table[i].dev0=mddev->devices+cur;
63
 
64
    if (size>=data->smallest->size) /* If we completely fill the slot */
65
    {
66
      data->hash_table[i++].dev1=NULL;
67
      size-=data->smallest->size;
68
 
69
      if (!size)
70
      {
71
        if (++cur==mddev->nb_dev) continue;
72
        size=mddev->devices[cur].size;
73
      }
74
 
75
      continue;
76
    }
77
 
78
    if (++cur==mddev->nb_dev) /* Last dev, set dev1 as NULL */
79
    {
80
      data->hash_table[i].dev1=NULL;
81
      continue;
82
    }
83
 
84
    dev0_size=size;             /* Here, we use a 2nd dev to fill the slot */
85
    size=mddev->devices[cur].size;
86
    data->hash_table[i++].dev1=mddev->devices+cur;
87
    size-=(data->smallest->size - dev0_size);
88
  }
89
 
90
  return 0;
91
}
92
 
93
static int linear_stop (int minor, struct md_dev *mddev)
94
{
95
  struct linear_data *data=(struct linear_data *) mddev->private;
96
 
97
  kfree (data->hash_table);
98
  kfree (data);
99
 
100
  MOD_DEC_USE_COUNT;
101
 
102
  return 0;
103
}
104
 
105
 
106
static int linear_map (struct md_dev *mddev, kdev_t *rdev,
107
                       unsigned long *rsector, unsigned long size)
108
{
109
  struct linear_data *data=(struct linear_data *) mddev->private;
110
  struct linear_hash *hash;
111
  struct real_dev *tmp_dev;
112
  long block;
113
 
114
  block=*rsector >> 1;
115
  hash=data->hash_table+(block/data->smallest->size);
116
 
117
  if (block >= (hash->dev0->size + hash->dev0->offset))
118
  {
119
    if (!hash->dev1)
120
    {
121
      printk ("linear_map : hash->dev1==NULL for block %ld\n", block);
122
      return (-1);
123
    }
124
 
125
    tmp_dev=hash->dev1;
126
  }
127
  else
128
    tmp_dev=hash->dev0;
129
 
130
  if (block >= (tmp_dev->size + tmp_dev->offset) || block < tmp_dev->offset)
131
    printk ("Block %ld out of bounds on dev %s size %d offset %d\n",
132
            block, kdevname(tmp_dev->dev), tmp_dev->size, tmp_dev->offset);
133
 
134
  *rdev=tmp_dev->dev;
135
  *rsector=(block-(tmp_dev->offset)) << 1;
136
 
137
  return (0);
138
}
139
 
140
static int linear_status (char *page, int minor, struct md_dev *mddev)
141
{
142
  int sz=0;
143
 
144
#undef MD_DEBUG
145
#ifdef MD_DEBUG
146
  int j;
147
  struct linear_data *data=(struct linear_data *) mddev->private;
148
 
149
  sz+=sprintf (page+sz, "      ");
150
  for (j=0; j<data->nr_zones; j++)
151
  {
152
    sz+=sprintf (page+sz, "[%s",
153
                 partition_name (data->hash_table[j].dev0->dev));
154
 
155
    if (data->hash_table[j].dev1)
156
      sz+=sprintf (page+sz, "/%s] ",
157
                   partition_name(data->hash_table[j].dev1->dev));
158
    else
159
      sz+=sprintf (page+sz, "] ");
160
  }
161
 
162
  sz+=sprintf (page+sz, "\n");
163
#endif
164
  sz+=sprintf (page+sz, " %dk rounding", 1<<FACTOR_SHIFT(FACTOR(mddev)));
165
  return sz;
166
}
167
 
168
 
169
static struct md_personality linear_personality=
170
{
171
  "linear",
172
  linear_map,
173
  NULL,
174
  NULL,
175
  linear_run,
176
  linear_stop,
177
  linear_status,
178
  NULL,                         /* no ioctls */
179
 
180
};
181
 
182
 
183
#ifndef MODULE
184
 
185
void linear_init (void)
186
{
187
  register_md_personality (LINEAR, &linear_personality);
188
}
189
 
190
#else
191
 
192
int init_module (void)
193
{
194
  return (register_md_personality (LINEAR, &linear_personality));
195
}
196
 
197
void cleanup_module (void)
198
{
199
  unregister_md_personality (LINEAR);
200
}
201
 
202
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.