Rev 2 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
2 | pj | 1 | /* |
2 | * Project: S.Ha.R.K. |
||
3 | * |
||
4 | * Coordinators: |
||
5 | * Giorgio Buttazzo <giorgio@sssup.it> |
||
6 | * Paolo Gai <pj@gandalf.sssup.it> |
||
7 | * |
||
8 | * Authors : |
||
9 | * Paolo Gai <pj@gandalf.sssup.it> |
||
10 | * Massimiliano Giorgi <massy@gandalf.sssup.it> |
||
11 | * Luca Abeni <luca@gandalf.sssup.it> |
||
12 | * (see the web pages for full authors list) |
||
13 | * |
||
14 | * ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy) |
||
15 | * |
||
16 | * http://www.sssup.it |
||
17 | * http://retis.sssup.it |
||
18 | * http://shark.sssup.it |
||
19 | */ |
||
20 | |||
21 | |||
22 | /*************************************** |
||
23 | |||
24 | CVS : $Id: bdev.c,v 1.1.1.1 2002-03-29 14:12:49 pj Exp $ |
||
25 | |||
26 | Revision: $Revision: 1.1.1.1 $ |
||
27 | |||
28 | Last update: $Date: 2002-03-29 14:12:49 $ |
||
29 | |||
30 | This module contains the block device manager: it export some functions |
||
31 | to the rest of the kernel that are mapped to a real device driver |
||
32 | sub-system. |
||
33 | |||
34 | ***************************************/ |
||
35 | |||
36 | /* |
||
37 | * Copyright (C) 1999 Massimiliano Giorgi |
||
38 | * |
||
39 | * This program is free software; you can redistribute it and/or modify |
||
40 | * it under the terms of the GNU General Public License as published by |
||
41 | * the Free Software Foundation; either version 2 of the License, or |
||
42 | * (at your option) any later version. |
||
43 | * |
||
44 | * This program is distributed in the hope that it will be useful, |
||
45 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
46 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
47 | * GNU General Public License for more details. |
||
48 | * |
||
49 | * You should have received a copy of the GNU General Public License |
||
50 | * along with this program; if not, write to the Free Software |
||
51 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
||
52 | * |
||
53 | */ |
||
54 | |||
55 | #include "glue.h" |
||
56 | #include <fs/bdevconf.h> |
||
57 | #include <fs/bdev.h> |
||
58 | #include <fs/magic.h> |
||
59 | #include <fs/assert.h> |
||
60 | #include <fs/sysmacro.h> |
||
61 | #include <fs/bdevinit.h> |
||
62 | #include <fs/fsind.h> |
||
63 | //#include <fs/mutex.h> |
||
64 | |||
65 | #include "bdev.h" |
||
66 | |||
67 | /*+ Log Level to use +*/ |
||
68 | #define BDEVLOG KERN_ERR |
||
69 | |||
70 | /*+ an entry for every block device +*/ |
||
71 | static struct block_device bdev[MAXBLOCKDEVICE]; |
||
72 | |||
73 | /*+ an index into bdev_minor +*/ |
||
74 | int bdev_minor_index=0; |
||
75 | |||
76 | /*+ an entry for every block device minor number +*/ |
||
77 | struct block_device_minor bdev_minor[MAXBLOCKDEVICEMINOR]; |
||
78 | |||
79 | /*+ some operations must be done in mutual exclusion +*/ |
||
80 | NOP_mutexattr_t bdevdef_mutexattr=NOP_MUTEXATTR_INITIALIZER; |
||
81 | __b_mutex_t mutex; |
||
82 | void *bmutexattr=NULL; |
||
83 | static BDEV_PARMS defaultparms=BASE_BDEV; |
||
84 | |||
85 | /*++++++++++++++++++++++++++++++++++++++ |
||
86 | |||
87 | Initialize the block device manager and then initialize every |
||
88 | block-device sub-system defined into bdevconf.h (Actualy it is |
||
89 | impossible to load a module at run-time). |
||
90 | |||
91 | int bdev_init |
||
92 | return 0 on success, other value on error |
||
93 | |||
94 | BDEV_PARMS *parms |
||
95 | pointer to a structure that contains all device inizialization parameter |
||
96 | ++++++++++++++++++++++++++++++++++++++*/ |
||
97 | |||
98 | int bdev_init(BDEV_PARMS *parms) |
||
99 | { |
||
100 | int i; |
||
101 | |||
102 | if (parms==NULL) parms=&defaultparms; |
||
103 | |||
104 | /* 'bmutexattr' initialization */ |
||
105 | bmutexattr=parms->bmutexattr; |
||
106 | if (bmutexattr==NULL) bmutexattr=&bdevdef_mutexattr; |
||
107 | |||
108 | /* initialize mutex */ |
||
109 | __b_mutex_init(&mutex); |
||
110 | |||
111 | /* initialize the bdev[] table */ |
||
112 | for (i=0;i<MAXBLOCKDEVICE;i++) { |
||
113 | magic_set(bdev[i].magic,BLOCK_DEVICE_MAGIC); |
||
114 | bdev[i].bd_flag_used=0; |
||
115 | } |
||
116 | |||
117 | /* initialize the bdev_minor[] table */ |
||
118 | /*for (i=0;i<MAX*/ |
||
119 | |||
120 | #ifdef IDE_BLOCK_DEVICE |
||
121 | /* if requested initialize the IDE subsystem */ |
||
122 | ide_init(parms); |
||
123 | #endif |
||
124 | |||
125 | #ifdef LOOP_BLOCK_DEVICE |
||
126 | /* if requested initialize the "loop device" subsystem */ |
||
127 | loop_init(parms); |
||
128 | #endif |
||
129 | |||
130 | return 0; |
||
131 | } |
||
132 | |||
133 | /*++++++++++++++++++++++++++++++++++++++ |
||
134 | |||
135 | Every block device sub-system must call this function yo register |
||
136 | itself to the device block manager. |
||
137 | |||
138 | int bdev_register |
||
139 | return 0 on success, -1 on failure |
||
140 | |||
141 | __dev_t devmajor |
||
142 | major block device number to register |
||
143 | |||
144 | char *name |
||
145 | the name of the device (must be a pointer to static data) |
||
146 | |||
147 | struct block_device *dev |
||
148 | information to hook the block device routine |
||
149 | ++++++++++++++++++++++++++++++++++++++*/ |
||
150 | |||
151 | int bdev_register(__dev_t devmajor, char *name, struct block_device *dev) |
||
152 | { |
||
153 | __dev_t mj=major(devmajor); |
||
154 | |||
155 | /* check for consistency */ |
||
156 | if (mj<=0||mj>=MAXBLOCKDEVICE) { |
||
157 | printk(BDEVLOG "bdev: request to register invalid major %i", |
||
158 | mj); |
||
159 | return -1; |
||
160 | } |
||
161 | if (bdev[mj].bd_flag_used) { |
||
162 | printk(BDEVLOG "bdev: requet to register used major %i", |
||
163 | mj); |
||
164 | return -1; |
||
165 | } |
||
166 | magic_assert(bdev[mj].magic,BLOCK_DEVICE_MAGIC, |
||
167 | "bdev: device(%i,%i) overwritten prior to use", |
||
168 | mj,minor(devmajor)); |
||
169 | |||
170 | /* register the device */ |
||
171 | memcpy(bdev+mj,dev,sizeof(struct block_device)); |
||
172 | bdev[mj].bd_flag_used=1; |
||
173 | bdev[mj].bd_name=name; |
||
174 | magic_set(bdev[mj].magic,BLOCK_DEVICE_MAGIC); |
||
175 | |||
176 | return 0; |
||
177 | } |
||
178 | |||
179 | static __uint8_t part2sysind(__uint8_t par_ind) |
||
180 | { |
||
181 | switch(par_ind) { |
||
182 | case FSPAR_DOS12: |
||
183 | case FSPAR_DOS16: |
||
184 | case FSPAR_DOSBIG: |
||
185 | return FS_MSDOS; |
||
186 | case FSPAR_LNXNTV: |
||
187 | return FS_EXT2; |
||
188 | } |
||
189 | return FS_DEFAULT; |
||
190 | } |
||
191 | |||
192 | /*++++++++++++++++++++++++++++++++++++++ |
||
193 | |||
194 | Every block device sub-system must call this function to register |
||
195 | itself to the device block manager (these information are used by |
||
196 | the devfs filesystem to export device name to the system in a |
||
197 | POSIX fanshion). |
||
198 | |||
199 | int bdev_register_minor |
||
200 | return a minor index on success, <0 on failure |
||
201 | |||
202 | __dev_t device |
||
203 | block device to register |
||
204 | |||
205 | char *name |
||
206 | the name of the device |
||
207 | |||
208 | __uint8_t fsind |
||
209 | file system indicator (see fsind.h) |
||
210 | ++++++++++++++++++++++++++++++++++++++*/ |
||
211 | |||
212 | int bdev_register_minor(__dev_t device, char *name,__uint8_t fsind) |
||
213 | { |
||
214 | /* checks for bad requests */ |
||
215 | if (bdev_minor_index==MAXBLOCKDEVICEMINOR) return -1; |
||
216 | if (major(device)>MAXBLOCKDEVICE) return -2; |
||
217 | if (!bdev[major(device)].bd_flag_used) return -3; |
||
218 | |||
219 | /* register minor device */ |
||
220 | strncpy(bdev_minor[bdev_minor_index].bdm_name,name,MAXDEVICENAME); |
||
221 | bdev_minor[bdev_minor_index].bdm_name[MAXDEVICENAME-1]='\0'; |
||
222 | bdev_minor[bdev_minor_index].bdm_device=device; |
||
223 | bdev_minor[bdev_minor_index].bdm_fsind=part2sysind(fsind); |
||
224 | |||
225 | return bdev_minor_index++; |
||
226 | } |
||
227 | |||
228 | /*++++++++++++++++++++++++++++++++++++++ |
||
229 | |||
230 | Find a device using its name. |
||
231 | |||
232 | __dev_t bdev_find_byname |
||
233 | return a device number on success, <0 on failure |
||
234 | |||
235 | char *name |
||
236 | the name of the device to find |
||
237 | ++++++++++++++++++++++++++++++++++++++*/ |
||
238 | |||
239 | __dev_t bdev_find_byname(char *name) |
||
240 | { |
||
241 | char *s0,*s1,*s2; |
||
242 | char saved; |
||
243 | int i; |
||
244 | |||
245 | /* |
||
246 | * a name can be, for example, "/dev/ide/hda1"; |
||
247 | * after this code s0 is a pointer to "ide" (the major name) and s1 is |
||
248 | * a pointer to "hda1" (the minor name) |
||
249 | */ |
||
250 | s0=name; |
||
251 | s1=strchr(name,'/'); |
||
252 | if (s1==NULL) return -1; |
||
253 | while ((s2=strchr(s1+1,'/'))!=NULL) { |
||
254 | s0=s1+1; |
||
255 | s1=s2; |
||
256 | } |
||
257 | saved=*s1; |
||
258 | *s1++='\0'; |
||
259 | |||
260 | /* search for a device... */ |
||
261 | for (i=0;i<bdev_minor_index;i++) |
||
262 | /* compare a minor name */ |
||
263 | if (!strcmp(s1,bdev_minor[i].bdm_name)) |
||
264 | /* compare a major name */ |
||
265 | if (!strcmp(bdev[major(bdev_minor[i].bdm_device)].bd_name,s0)) { |
||
266 | *(s1-1)=saved; |
||
267 | return bdev_minor[i].bdm_device; |
||
268 | } |
||
269 | *(s1-1)=saved; |
||
270 | return -2; |
||
271 | } |
||
272 | |||
273 | |||
274 | /*++++++++++++++++++++++++++++++++++++++ |
||
275 | |||
276 | Find major and minor name using a device id (__dev_t). |
||
277 | |||
278 | int bdev_findname |
||
279 | return 0 on success; -1 on failure. |
||
280 | |||
281 | __dev_t dev |
||
282 | device identification |
||
283 | |||
284 | char **major |
||
285 | the major name is pointed here |
||
286 | |||
287 | char **minor |
||
288 | the minor name is pointed here |
||
289 | ++++++++++++++++++++++++++++++++++++++*/ |
||
290 | |||
291 | int bdev_findname(__dev_t dev, char **major,char **minor) |
||
292 | { |
||
293 | int i; |
||
294 | |||
295 | assertk(major!=NULL&&minor!=NULL); |
||
296 | |||
297 | for (i=0;i<bdev_minor_index;i++) |
||
298 | if (bdev_minor[i].bdm_device==dev) { |
||
299 | *minor=bdev_minor[i].bdm_name; |
||
300 | *major=bdev[major(dev)].bd_name; |
||
301 | return 0; |
||
302 | } |
||
303 | |||
304 | return -1; |
||
305 | } |
||
306 | |||
307 | /*++++++++++++++++++++++++++++++++++++++ |
||
308 | |||
309 | Find a device using its file system indicator (the first device |
||
310 | that use this file system). |
||
311 | |||
312 | __dev_t bdev_find_byfs |
||
313 | return a device number on success, <0 on failure |
||
314 | |||
315 | __uint8_t fsind |
||
316 | file system indicator |
||
317 | ++++++++++++++++++++++++++++++++++++++*/ |
||
318 | |||
319 | __dev_t bdev_find_byfs(__uint8_t fsind) |
||
320 | { |
||
321 | int i; |
||
322 | for (i=0;i<bdev_minor_index;i++) |
||
323 | if (bdev_minor[i].bdm_fsind==fsind) |
||
324 | return bdev_minor[i].bdm_device; |
||
325 | return -1; |
||
326 | } |
||
327 | |||
328 | /*++++++++++++++++++++++++++++++++++++++ |
||
329 | |||
330 | Scan all devices into the system: for every device found call |
||
331 | the callback function, if it returns -1 continue scanning else |
||
332 | the values passed is returned. |
||
333 | |||
334 | __dev_t bdev_find_byfs |
||
335 | return a device number on success, <0 on failure |
||
336 | |||
337 | __uint8_t fsind |
||
338 | file system indicator |
||
339 | ++++++++++++++++++++++++++++++++++++++*/ |
||
340 | |||
341 | int bdev_scan_devices(int(*callback)(__dev_t,__uint8_t)) |
||
342 | { |
||
343 | int res=0; |
||
344 | int i; |
||
345 | |||
346 | for (i=0;i<bdev_minor_index;i++) { |
||
347 | res=callback(bdev_minor[i].bdm_device, |
||
348 | bdev_minor[i].bdm_fsind |
||
349 | ); |
||
350 | if (res!=-1) break; |
||
351 | } |
||
352 | return res; |
||
353 | } |
||
354 | |||
355 | //#ifndef NDEBUG |
||
356 | |||
357 | #include <fs/major.h> |
||
358 | extern int ide_dump_startsize(__dev_t, __blkcnt_t*, __blkcnt_t*); |
||
359 | |||
360 | void bdev_dump_names(void) |
||
361 | { |
||
362 | int i; |
||
363 | __blkcnt_t start,size; |
||
364 | |||
365 | printk(KERN_INFO "block device names:"); |
||
366 | for (i=0;i<bdev_minor_index;i++) { |
||
367 | start=size=0; |
||
368 | if (major(bdev_minor[i].bdm_device)==MAJOR_B_IDE) |
||
369 | ide_dump_startsize(bdev_minor[i].bdm_device,&start,&size); |
||
370 | printk(KERN_INFO " %s/%8s %08x (start-%-8li size-%-8li sysind-%02x)", |
||
371 | bdev[major(bdev_minor[i].bdm_device)].bd_name, |
||
372 | bdev_minor[i].bdm_name, |
||
373 | bdev_minor[i].bdm_device, |
||
374 | (long int)start,(long int)size, |
||
375 | bdev_minor[i].bdm_fsind |
||
376 | ); |
||
377 | } |
||
378 | |||
379 | } |
||
380 | |||
381 | void bdev_dump_status(void) |
||
382 | { |
||
383 | int counter,i; |
||
384 | |||
385 | printk(KERN_INFO "block device status:"); |
||
386 | printk(KERN_INFO " registered devices:"); |
||
387 | for (counter=0,i=0;i<MAXBLOCKDEVICE;i++) |
||
388 | if (bdev[i].bd_flag_used) { |
||
389 | printk(KERN_INFO " %s",bdev[i].bd_name); |
||
390 | counter++; |
||
391 | } |
||
392 | printk(KERN_INFO " num. majors: %i",counter); |
||
393 | printk(KERN_INFO " num. minors: %i",bdev_minor_index); |
||
394 | |||
395 | #ifdef IDE_BLOCK_DEVICE |
||
396 | ide_dump_status(); |
||
397 | #endif |
||
398 | |||
399 | } |
||
400 | |||
401 | //#endif |
||
402 | |||
403 | /*++++++++++++++++++++++++++++++++++++++ |
||
404 | |||
405 | Try to lock a device. |
||
406 | Locking a device means that the locking entity can do I/O on that |
||
407 | device (no check is performed during I/O operations). |
||
408 | |||
409 | int bdev_trylock |
||
410 | return 1 on success, 0 on failure and, -1 on error |
||
411 | |||
412 | __dev_t dev |
||
413 | device to lock |
||
414 | ++++++++++++++++++++++++++++++++++++++*/ |
||
415 | |||
416 | int bdev_trylock(__dev_t dev) |
||
417 | { |
||
418 | int res; |
||
419 | |||
420 | magic_assert(bdev[major(dev)].magic,BLOCK_DEVICE_MAGIC, |
||
421 | "bdev: device(%04x:%04x) overwritten", |
||
422 | major(dev),minor(dev)); |
||
423 | |||
424 | if (!bdev[major(dev)].bd_flag_used) { |
||
425 | printk(BDEVLOG "bdev: device(%04x:%04x) not registered", |
||
426 | major(dev),minor(dev)); |
||
427 | return -1; |
||
428 | } |
||
429 | |||
430 | __b_mutex_lock(&mutex); |
||
431 | res=bdev[major(dev)].bd_op->_trylock(dev); |
||
432 | __b_mutex_unlock(&mutex); |
||
433 | |||
434 | return res; |
||
435 | } |
||
436 | |||
437 | /*++++++++++++++++++++++++++++++++++++++ |
||
438 | |||
439 | Try to unlock a device. |
||
440 | |||
441 | int bdev_tryunlock |
||
442 | return 1 on success, 0 on failure and, -1 on error |
||
443 | |||
444 | __dev_t dev |
||
445 | device to unlock |
||
446 | ++++++++++++++++++++++++++++++++++++++*/ |
||
447 | |||
448 | int bdev_tryunlock(__dev_t dev) |
||
449 | { |
||
450 | int res; |
||
451 | |||
452 | magic_assert(bdev[major(dev)].magic,BLOCK_DEVICE_MAGIC, |
||
453 | "bdev: device(%04x:%04x) overwritten", |
||
454 | major(dev),minor(dev)); |
||
455 | |||
456 | if (!bdev[major(dev)].bd_flag_used) { |
||
457 | printk(BDEVLOG "bdev: device(%04x:%04x) not registered", |
||
458 | major(dev),minor(dev)); |
||
459 | return -1; |
||
460 | } |
||
461 | |||
462 | __b_mutex_lock(&mutex); |
||
463 | res=bdev[major(dev)].bd_op->_tryunlock(dev); |
||
464 | __b_mutex_unlock(&mutex); |
||
465 | |||
466 | return res; |
||
467 | } |
||
468 | |||
469 | |||
470 | /*++++++++++++++++++++++++++++++++++++++ |
||
471 | |||
472 | The following function are used to "virtualize" the call of a function |
||
473 | of a block device sub-system. |
||
474 | Actually they are implemeted by function to perform some parameters |
||
475 | check but they will be implemented by macro. |
||
476 | +latex+ \\ |
||
477 | |||
478 | This function request to read a block number. |
||
479 | |||
480 | int bdev_read |
||
481 | return 0 on success, other value on error |
||
482 | |||
483 | __dev_t dev |
||
484 | device where to read from |
||
485 | |||
486 | __blkcnt_t blocknum |
||
487 | block number to read |
||
488 | |||
489 | __uint8_t *buffer |
||
490 | buffer for the readed data |
||
491 | ++++++++++++++++++++++++++++++++++++++*/ |
||
492 | |||
493 | int bdev_read(__dev_t dev, __blkcnt_t blocknum, __uint8_t *buffer) |
||
494 | { |
||
495 | |||
496 | magic_assert(bdev[major(dev)].magic,BLOCK_DEVICE_MAGIC, |
||
497 | "bdev: device(%04x:%04x) overwritten", |
||
498 | major(dev),minor(dev)); |
||
499 | |||
500 | if (!bdev[major(dev)].bd_flag_used) { |
||
501 | printk(BDEVLOG "bdev: device(%04x:%04x) not registered", |
||
502 | major(dev),minor(dev)); |
||
503 | return -1; |
||
504 | } |
||
505 | |||
506 | if (blocknum<0) { |
||
507 | printk(BDEVLOG "bdev: device(%04x:%04x) read request out of range", |
||
508 | major(dev),minor(dev)); |
||
509 | return -1; |
||
510 | } |
||
511 | |||
512 | return bdev[major(dev)].bd_op->read(dev,blocknum,buffer); |
||
513 | } |
||
514 | |||
515 | /*++++++++++++++++++++++++++++++++++++++ |
||
516 | |||
517 | This function request to move the head to a specified block of a device. |
||
518 | |||
519 | int bdev_seek |
||
520 | return 0 on success, other value on error |
||
521 | |||
522 | __dev_t dev |
||
523 | device to seek |
||
524 | |||
525 | __blkcnt_t blocknum |
||
526 | block number to seek into |
||
527 | ++++++++++++++++++++++++++++++++++++++*/ |
||
528 | |||
529 | int bdev_seek(__dev_t dev, __blkcnt_t blocknum) |
||
530 | { |
||
531 | magic_assert(bdev[major(dev)].magic,BLOCK_DEVICE_MAGIC, |
||
532 | "bdev: device(%04x:%04x) overwritten", |
||
533 | major(dev),minor(dev)); |
||
534 | |||
535 | if (!bdev[major(dev)].bd_flag_used) { |
||
536 | printk(BDEVLOG "bdev: device(%04x:%04x) not registered", |
||
537 | major(dev),minor(dev)); |
||
538 | return -1; |
||
539 | } |
||
540 | |||
541 | if (blocknum<0) { |
||
542 | printk(BDEVLOG "bdev: device(%04x:%04x) seek request out of range", |
||
543 | major(dev),minor(dev)); |
||
544 | return -1; |
||
545 | } |
||
546 | |||
547 | return bdev[major(dev)].bd_op->seek(dev,blocknum); |
||
548 | } |
||
549 | |||
550 | /*++++++++++++++++++++++++++++++++++++++ |
||
551 | |||
552 | Write a block into a device. |
||
553 | |||
554 | int bdev_write |
||
555 | return 0 on success, other value on error |
||
556 | |||
557 | __dev_t dev |
||
558 | device to write into |
||
559 | |||
560 | __blkcnt_t blocknum |
||
561 | block number to write |
||
562 | |||
563 | __uint8_t *buffer |
||
564 | buffer with data to write |
||
565 | ++++++++++++++++++++++++++++++++++++++*/ |
||
566 | |||
567 | int bdev_write(__dev_t dev, __blkcnt_t blocknum, __uint8_t *buffer) |
||
568 | { |
||
569 | magic_assert(bdev[major(dev)].magic,BLOCK_DEVICE_MAGIC, |
||
570 | "bdev: device(%04x:%04x) overwritten", |
||
571 | major(dev),minor(dev)); |
||
572 | |||
573 | if (!bdev[major(dev)].bd_flag_used) { |
||
574 | printk(BDEVLOG "bdev: device(%04x:%04x) not registered", |
||
575 | major(dev),minor(dev)); |
||
576 | return -1; |
||
577 | } |
||
578 | |||
579 | if (blocknum<0) { |
||
580 | printk(BDEVLOG "bdev: device(%04x:%04x) write request out of range", |
||
581 | major(dev),minor(dev)); |
||
582 | return -1; |
||
583 | } |
||
584 | |||
585 | return bdev[major(dev)].bd_op->write(dev,blocknum,buffer); |
||
586 | } |