Subversion Repositories shark

Rev

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
}