Subversion Repositories shark

Rev

Rev 686 | 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
 
686 giacomo 24
  CVS :        $Id: bdev.c,v 1.2 2004-05-26 11:20:23 giacomo Exp $
2 pj 25
 
686 giacomo 26
  Revision:    $Revision: 1.2 $
2 pj 27
 
686 giacomo 28
  Last update: $Date: 2004-05-26 11:20:23 $
2 pj 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*);
686 giacomo 359
extern void ide_dump_status(void);
2 pj 360
 
361
void bdev_dump_names(void)
362
{
363
  int i;
364
  __blkcnt_t start,size;
365
 
366
  printk(KERN_INFO "block device names:");
367
  for (i=0;i<bdev_minor_index;i++) {
368
    start=size=0;
369
    if (major(bdev_minor[i].bdm_device)==MAJOR_B_IDE)
370
      ide_dump_startsize(bdev_minor[i].bdm_device,&start,&size);
371
    printk(KERN_INFO "    %s/%8s   %08x (start-%-8li size-%-8li sysind-%02x)",
372
           bdev[major(bdev_minor[i].bdm_device)].bd_name,
373
           bdev_minor[i].bdm_name,
374
           bdev_minor[i].bdm_device,
375
           (long int)start,(long int)size,
376
           bdev_minor[i].bdm_fsind         
377
           );
378
  }
379
 
380
}
381
 
382
void bdev_dump_status(void)
383
{
384
  int counter,i;
385
 
386
  printk(KERN_INFO "block device status:");
387
  printk(KERN_INFO "  registered devices:");
388
  for (counter=0,i=0;i<MAXBLOCKDEVICE;i++)
389
    if (bdev[i].bd_flag_used) {
390
      printk(KERN_INFO "    %s",bdev[i].bd_name);
391
      counter++;
392
    }  
393
  printk(KERN_INFO "  num. majors: %i",counter);
394
  printk(KERN_INFO "  num. minors: %i",bdev_minor_index);
395
 
396
#ifdef IDE_BLOCK_DEVICE
397
  ide_dump_status();
398
#endif
399
 
400
}
401
 
402
//#endif
403
 
404
/*++++++++++++++++++++++++++++++++++++++
405
 
406
  Try to lock a device.
407
  Locking a device means that the locking entity can do I/O on that
408
  device (no check is performed during I/O operations).
409
 
410
  int bdev_trylock
411
    return 1 on success, 0 on failure and, -1 on error
412
 
413
  __dev_t dev
414
    device to lock
415
  ++++++++++++++++++++++++++++++++++++++*/
416
 
417
int bdev_trylock(__dev_t dev)
418
{
419
  int res;
420
 
421
  magic_assert(bdev[major(dev)].magic,BLOCK_DEVICE_MAGIC,
422
               "bdev: device(%04x:%04x) overwritten",
423
               major(dev),minor(dev));
424
 
425
  if (!bdev[major(dev)].bd_flag_used) {
426
    printk(BDEVLOG "bdev: device(%04x:%04x) not registered",
427
           major(dev),minor(dev));       
428
    return -1;
429
  }
430
 
431
  __b_mutex_lock(&mutex);
432
  res=bdev[major(dev)].bd_op->_trylock(dev);
433
  __b_mutex_unlock(&mutex);
434
 
435
  return res;
436
}
437
 
438
/*++++++++++++++++++++++++++++++++++++++
439
 
440
  Try to unlock a device.
441
 
442
  int bdev_tryunlock
443
    return 1 on success, 0 on failure and, -1 on error
444
 
445
  __dev_t dev
446
    device to unlock
447
  ++++++++++++++++++++++++++++++++++++++*/
448
 
449
int bdev_tryunlock(__dev_t dev)
450
{
451
  int res;
452
 
453
  magic_assert(bdev[major(dev)].magic,BLOCK_DEVICE_MAGIC,
454
               "bdev: device(%04x:%04x) overwritten",
455
               major(dev),minor(dev));
456
 
457
  if (!bdev[major(dev)].bd_flag_used) {
458
    printk(BDEVLOG "bdev: device(%04x:%04x) not registered",
459
           major(dev),minor(dev));       
460
    return -1;
461
  }
462
 
463
  __b_mutex_lock(&mutex);
464
  res=bdev[major(dev)].bd_op->_tryunlock(dev);
465
  __b_mutex_unlock(&mutex);
466
 
467
  return res;
468
}
469
 
470
 
471
/*++++++++++++++++++++++++++++++++++++++
472
 
473
  The following function are used to "virtualize" the call of a function
474
  of a block device sub-system.
475
  Actually they are implemeted by function to perform some parameters
476
  check but they will be implemented by macro.
477
  +latex+ \\
478
 
479
  This function request to read a block number.
480
 
481
  int bdev_read
482
    return 0 on success, other value on error
483
 
484
  __dev_t dev
485
    device where to read from
486
 
487
  __blkcnt_t blocknum
488
    block number to read
489
 
490
  __uint8_t *buffer
491
    buffer for the readed data
492
  ++++++++++++++++++++++++++++++++++++++*/
493
 
494
int bdev_read(__dev_t dev, __blkcnt_t blocknum, __uint8_t *buffer)
495
{
496
 
497
  magic_assert(bdev[major(dev)].magic,BLOCK_DEVICE_MAGIC,
498
               "bdev: device(%04x:%04x) overwritten",
499
               major(dev),minor(dev));
500
 
501
  if (!bdev[major(dev)].bd_flag_used) {
502
    printk(BDEVLOG "bdev: device(%04x:%04x) not registered",
503
           major(dev),minor(dev));       
504
    return -1;
505
  }
506
 
507
  if (blocknum<0) {
508
    printk(BDEVLOG "bdev: device(%04x:%04x) read request out of range",
509
           major(dev),minor(dev));       
510
    return -1;
511
  }
512
 
513
  return bdev[major(dev)].bd_op->read(dev,blocknum,buffer);
514
}
515
 
516
/*++++++++++++++++++++++++++++++++++++++
517
 
518
  This function request to move the head to a specified block of a device.
519
 
520
  int bdev_seek
521
    return 0 on success, other value on error
522
 
523
  __dev_t dev
524
    device to seek
525
 
526
  __blkcnt_t blocknum
527
    block number to seek into
528
  ++++++++++++++++++++++++++++++++++++++*/
529
 
530
int bdev_seek(__dev_t dev, __blkcnt_t blocknum)
531
{
532
  magic_assert(bdev[major(dev)].magic,BLOCK_DEVICE_MAGIC,
533
               "bdev: device(%04x:%04x) overwritten",
534
               major(dev),minor(dev));
535
 
536
  if (!bdev[major(dev)].bd_flag_used) {
537
    printk(BDEVLOG "bdev: device(%04x:%04x) not registered",
538
           major(dev),minor(dev));       
539
    return -1;
540
  }
541
 
542
  if (blocknum<0) {
543
    printk(BDEVLOG "bdev: device(%04x:%04x) seek request out of range",
544
           major(dev),minor(dev));       
545
    return -1;
546
  }
547
 
548
  return bdev[major(dev)].bd_op->seek(dev,blocknum);
549
}
550
 
551
/*++++++++++++++++++++++++++++++++++++++
552
 
553
  Write a block into a device.
554
 
555
  int bdev_write
556
    return 0 on success, other value on error
557
 
558
  __dev_t dev
559
    device to write into
560
 
561
  __blkcnt_t blocknum
562
    block number to write
563
 
564
  __uint8_t *buffer
565
    buffer with data to write
566
  ++++++++++++++++++++++++++++++++++++++*/
567
 
568
int bdev_write(__dev_t dev, __blkcnt_t blocknum, __uint8_t *buffer)
569
{
570
  magic_assert(bdev[major(dev)].magic,BLOCK_DEVICE_MAGIC,              
571
               "bdev: device(%04x:%04x) overwritten",
572
               major(dev),minor(dev));
573
 
574
  if (!bdev[major(dev)].bd_flag_used) {
575
    printk(BDEVLOG "bdev: device(%04x:%04x) not registered",
576
           major(dev),minor(dev));       
577
    return -1;
578
  }
579
 
580
  if (blocknum<0) {
581
    printk(BDEVLOG "bdev: device(%04x:%04x) write request out of range",
582
           major(dev),minor(dev));       
583
    return -1;
584
  }
585
 
586
  return bdev[major(dev)].bd_op->write(dev,blocknum,buffer);
587
}