Annotation of Gnu-Mach/i386/i386at/gpl/linux/linux_block.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Linux block driver support.
                      3:  *
                      4:  * Copyright (C) 1996 The University of Utah and the Computer Systems
                      5:  * Laboratory at the University of Utah (CSL)
                      6:  *
                      7:  * This program is free software; you can redistribute it and/or modify
                      8:  * it under the terms of the GNU General Public License as published by
                      9:  * the Free Software Foundation; either version 2, or (at your option)
                     10:  * any later version.
                     11:  *
                     12:  * This program is distributed in the hope that it will be useful,
                     13:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     14:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     15:  * GNU General Public License for more details.
                     16:  *
                     17:  * You should have received a copy of the GNU General Public License
                     18:  * along with this program; if not, write to the Free Software
                     19:  * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
                     20:  *
                     21:  *     Author: Shantanu Goel, University of Utah CSL
                     22:  */
                     23: 
                     24: /*
                     25:  *  linux/drivers/block/ll_rw_blk.c
                     26:  *
                     27:  * Copyright (C) 1991, 1992 Linus Torvalds
                     28:  * Copyright (C) 1994,      Karl Keyte: Added support for disk statistics
                     29:  */
                     30: 
                     31: /*
                     32:  *  linux/fs/block_dev.c
                     33:  *
                     34:  *  Copyright (C) 1991, 1992  Linus Torvalds
                     35:  */
                     36: 
                     37: /*
                     38:  *  linux/fs/buffer.c
                     39:  *
                     40:  *  Copyright (C) 1991, 1992  Linus Torvalds
                     41:  */
                     42: 
                     43: #include <sys/types.h>
                     44: #include <mach/mach_types.h>
                     45: #include <mach/kern_return.h>
                     46: #include <mach/mig_errors.h>
                     47: #include <mach/port.h>
                     48: #include <mach/vm_param.h>
                     49: #include <mach/notify.h>
                     50: 
                     51: #include <ipc/ipc_port.h>
                     52: #include <ipc/ipc_space.h>
                     53: 
                     54: #include <vm/vm_map.h>
                     55: #include <vm/vm_kern.h>
                     56: #include <vm/vm_page.h>
                     57: 
                     58: #include <device/device_types.h>
                     59: #include <device/device_port.h>
                     60: #include <device/disk_status.h>
                     61: #include "device_reply.h"
                     62: 
                     63: #include <i386at/dev_hdr.h>
                     64: #include <i386at/device_emul.h>
                     65: #include <i386at/disk.h>
                     66: 
                     67: #include <i386at/gpl/linux/linux_emul.h>
                     68: 
                     69: #define MACH_INCLUDE
                     70: #include <linux/fs.h>
                     71: #include <linux/blk.h>
                     72: #include <linux/string.h>
                     73: #include <linux/errno.h>
                     74: #include <linux/fcntl.h>
                     75: #include <linux/major.h>
                     76: #include <linux/kdev_t.h>
                     77: #include <linux/delay.h>
                     78: #include <linux/malloc.h>
                     79: 
                     80: /* Location of VTOC in units for sectors (512 bytes).  */
                     81: #define PDLOCATION 29
                     82: 
                     83: /* Linux kernel variables.  */
                     84: 
                     85: /* One of these exists for each
                     86:    driver associated with a major number.  */
                     87: struct device_struct
                     88: {
                     89:   const char *name;            /* device name */
                     90:   struct file_operations *fops;        /* operations vector */
                     91:   int busy:1;                  /* driver is being opened/closed */
                     92:   int want:1;                  /* someone wants to open/close driver */
                     93:   struct gendisk *gd;          /* DOS partition information */
                     94:   int *default_slice;          /* what slice to use when none is given */
                     95:   struct disklabel **label;    /* disklabels for each DOS partition */
                     96: };
                     97: 
                     98: /* An entry in the Mach name to Linux major number conversion table.  */
                     99: struct name_map
                    100: {
                    101:   const char *name;    /* Mach name for device */
                    102:   unsigned major;      /* Linux major number */
                    103:   unsigned unit;       /* Linux unit number */
                    104:   int read_only;       /* 1 if device is read only */
                    105: };
                    106: 
                    107: /* Driver operation table.  */
                    108: static struct device_struct blkdevs[MAX_BLKDEV];
                    109: 
                    110: /* Driver request function table.  */
                    111: struct blk_dev_struct blk_dev[MAX_BLKDEV] =
                    112: {
                    113:   { NULL, NULL },              /* 0 no_dev */
                    114:   { NULL, NULL },              /* 1 dev mem */
                    115:   { NULL, NULL },              /* 2 dev fd */
                    116:   { NULL, NULL },              /* 3 dev ide0 or hd */
                    117:   { NULL, NULL },              /* 4 dev ttyx */
                    118:   { NULL, NULL },              /* 5 dev tty */
                    119:   { NULL, NULL },              /* 6 dev lp */
                    120:   { NULL, NULL },              /* 7 dev pipes */
                    121:   { NULL, NULL },              /* 8 dev sd */
                    122:   { NULL, NULL },              /* 9 dev st */
                    123:   { NULL, NULL },              /* 10 */
                    124:   { NULL, NULL },              /* 11 */
                    125:   { NULL, NULL },              /* 12 */
                    126:   { NULL, NULL },              /* 13 */
                    127:   { NULL, NULL },              /* 14 */
                    128:   { NULL, NULL },              /* 15 */
                    129:   { NULL, NULL },              /* 16 */
                    130:   { NULL, NULL },              /* 17 */
                    131:   { NULL, NULL },              /* 18 */
                    132:   { NULL, NULL },              /* 19 */
                    133:   { NULL, NULL },              /* 20 */
                    134:   { NULL, NULL },              /* 21 */
                    135:   { NULL, NULL }               /* 22 dev ide1 */
                    136: };
                    137: 
                    138: /*
                    139:  * blk_size contains the size of all block-devices in units of 1024 byte
                    140:  * sectors:
                    141:  *
                    142:  * blk_size[MAJOR][MINOR]
                    143:  *
                    144:  * if (!blk_size[MAJOR]) then no minor size checking is done.
                    145:  */
                    146: int *blk_size[MAX_BLKDEV] = { NULL, NULL, };
                    147: 
                    148: /*
                    149:  * blksize_size contains the size of all block-devices:
                    150:  *
                    151:  * blksize_size[MAJOR][MINOR]
                    152:  *
                    153:  * if (!blksize_size[MAJOR]) then 1024 bytes is assumed.
                    154:  */
                    155: int *blksize_size[MAX_BLKDEV] = { NULL, NULL, };
                    156: 
                    157: /*
                    158:  * hardsect_size contains the size of the hardware sector of a device.
                    159:  *
                    160:  * hardsect_size[MAJOR][MINOR]
                    161:  *
                    162:  * if (!hardsect_size[MAJOR])
                    163:  *             then 512 bytes is assumed.
                    164:  * else
                    165:  *             sector_size is hardsect_size[MAJOR][MINOR]
                    166:  * This is currently set by some scsi device and read by the msdos fs driver
                    167:  * This might be a some uses later.
                    168:  */
                    169: int *hardsect_size[MAX_BLKDEV] = { NULL, NULL, };
                    170: 
                    171: /* This specifies how many sectors to read ahead on the disk.
                    172:    This is unused in Mach.  It is here to make drivers compile.  */
                    173: int read_ahead[MAX_BLKDEV] = {0, };
                    174: 
                    175: /* Use to wait on when there are no free requests.
                    176:    This is unused in Mach.  It is here to make drivers compile.  */
                    177: struct wait_queue *wait_for_request = NULL;
                    178: 
                    179: /* Initialize block drivers.  */
                    180: void
                    181: blk_dev_init ()
                    182: {
                    183: #ifdef CONFIG_BLK_DEV_IDE
                    184:   ide_init ();
                    185: #endif
                    186: #ifdef CONFIG_BLK_DEV_FD
                    187:   floppy_init ();
                    188: #endif
                    189: }
                    190: 
                    191: /* Return 1 if major number MAJOR corresponds to a disk device.  */
                    192: static inline int
                    193: disk_major (int major)
                    194: {
                    195:   return (major == IDE0_MAJOR
                    196:          || major == IDE1_MAJOR
                    197:          || major == IDE2_MAJOR
                    198:          || major == IDE3_MAJOR
                    199:          || major == SCSI_DISK_MAJOR);
                    200: }
                    201: 
                    202: /* Linux kernel block support routines.  */
                    203: 
                    204: /* Register a driver for major number MAJOR,
                    205:    with name NAME, and operations vector FOPS.  */
                    206: int
                    207: register_blkdev (unsigned major, const char *name,
                    208:                 struct file_operations *fops)
                    209: {
                    210:   int err = 0;
                    211: 
                    212:   if (major == 0)
                    213:     {
                    214:       for (major = MAX_BLKDEV - 1; major > 0; major--)
                    215:        if (blkdevs[major].fops == NULL)
                    216:          goto out;
                    217:       return -LINUX_EBUSY;
                    218:     }
                    219:   if (major >= MAX_BLKDEV)
                    220:     return -LINUX_EINVAL;
                    221:   if (blkdevs[major].fops && blkdevs[major].fops != fops)
                    222:     return -LINUX_EBUSY;
                    223: 
                    224: out:
                    225:   blkdevs[major].name = name;
                    226:   blkdevs[major].fops = fops;
                    227:   blkdevs[major].busy = 0;
                    228:   blkdevs[major].want = 0;
                    229:   blkdevs[major].gd = NULL;
                    230:   blkdevs[major].default_slice = NULL;
                    231:   blkdevs[major].label = NULL;
                    232:   return 0;
                    233: }
                    234: 
                    235: /* Unregister the driver associated with
                    236:    major number MAJOR and having the name NAME.  */
                    237: int
                    238: unregister_blkdev (unsigned major, const char *name)
                    239: {
                    240:   int err;
                    241: 
                    242:   if (major >= MAX_BLKDEV)
                    243:     return -LINUX_EINVAL;
                    244:   if (! blkdevs[major].fops || strcmp (blkdevs[major].name, name))
                    245:     return -LINUX_EINVAL;
                    246:   blkdevs[major].fops = NULL;
                    247:   if (blkdevs[major].default_slice)
                    248:     {
                    249:       assert (blkdevs[major].gd);
                    250:       kfree ((vm_offset_t) blkdevs[major].default_slice,
                    251:             sizeof (int) * blkdevs[major].gd->max_nr);
                    252:     }
                    253:   if (blkdevs[major].label)
                    254:     {
                    255:       assert (blkdevs[major].gd);
                    256:       kfree ((vm_offset_t) blkdevs[major].label,
                    257:             (sizeof (struct disklabel *)
                    258:              * blkdevs[major].gd->max_p * blkdevs[major].gd->max_nr));
                    259:     }
                    260:   return 0;
                    261: }
                    262: 
                    263: /* One of these is associated with
                    264:    each page allocated by the buffer management routines.  */
                    265: struct pagehdr
                    266: {
                    267:   unsigned char busy;          /* page header is in use */
                    268:   unsigned char avail;         /* number of blocks available in page */
                    269:   unsigned short bitmap;       /* free space bitmap */
                    270:   void *blks;                  /* the actual page */
                    271:   struct pagehdr *next;                /* next header in list */
                    272: };
                    273: 
                    274: /* This structure describes the different block sizes.  */
                    275: struct bufsize
                    276: {
                    277:   unsigned short size;         /* size of block */
                    278:   unsigned short avail;                /* # available blocks */
                    279:   struct pagehdr *pages;       /* page list */
                    280: };
                    281: 
                    282: /* List of supported block sizes.  */
                    283: static struct bufsize bufsizes[] =
                    284: {
                    285:   {  512, 0, NULL },
                    286:   { 1024, 0, NULL },
                    287:   { 2048, 0, NULL },
                    288:   { 4096, 0, NULL },
                    289: };
                    290: 
                    291: /* Page headers.  */
                    292: static struct pagehdr pagehdrs[50];    /* XXX: needs to be dynamic */
                    293: 
                    294: /* Find the block size that is greater than or equal to SIZE.  */
                    295: static struct bufsize *
                    296: get_bufsize (int size)
                    297: {
                    298:   struct bufsize *bs, *ebs;
                    299: 
                    300:   bs = &bufsizes[0];
                    301:   ebs = &bufsizes[sizeof (bufsizes) / sizeof (bufsizes[0])];
                    302:   while (bs < ebs)
                    303:     {
                    304:       if (bs->size >= size)
                    305:        return bs;
                    306:       bs++;
                    307:     }
                    308: 
                    309:   panic ("%s:%d: alloc_buffer: bad buffer size %d", __FILE__, __LINE__, size);
                    310: }
                    311: 
                    312: /* Free all pages that are not in use.
                    313:    Called by __get_free_pages when pages are running low.  */
                    314: void
                    315: collect_buffer_pages ()
                    316: {
                    317:   struct bufsize *bs, *ebs;
                    318:   struct pagehdr *ph, **prev_ph;
                    319: 
                    320:   bs = &bufsizes[0];
                    321:   ebs = &bufsizes[sizeof (bufsizes) / sizeof (bufsizes[0])];
                    322:   while (bs < ebs)
                    323:     {
                    324:       if (bs->avail >= PAGE_SIZE / bs->size)
                    325:        {
                    326:          ph = bs->pages;
                    327:          prev_ph = &bs->pages;
                    328:          while (ph)
                    329:            if (ph->avail == PAGE_SIZE / bs->size)
                    330:              {
                    331:                bs->avail -= ph->avail;
                    332:                ph->busy = 0;
                    333:                *prev_ph = ph->next;
                    334:                free_pages ((unsigned long) ph->blks, 0);
                    335:                ph = *prev_ph;
                    336:              }
                    337:            else
                    338:              {
                    339:                prev_ph = &ph->next;
                    340:                ph = ph->next;
                    341:              }
                    342:        }
                    343:       bs++;
                    344:     }
                    345: }
                    346: 
                    347: /* Allocate a buffer of at least SIZE bytes.  */
                    348: static void *
                    349: alloc_buffer (int size)
                    350: {
                    351:   int i;
                    352:   unsigned flags;
                    353:   struct bufsize *bs;
                    354:   struct pagehdr *ph, *eph;
                    355: 
                    356:   bs = get_bufsize (size);
                    357:   save_flags (flags);
                    358:   cli ();
                    359:   if (bs->avail == 0)
                    360:     {
                    361:       ph = &pagehdrs[0];
                    362:       eph = &pagehdrs[sizeof (pagehdrs) / sizeof (pagehdrs[0])];
                    363:       while (ph < eph && ph->busy)
                    364:        ph++;
                    365:       if (ph == eph)
                    366:        {
                    367:          restore_flags (flags);
                    368:          printf ("%s:%d: alloc_buffer: ran out of page headers\n",
                    369:                  __FILE__, __LINE__);
                    370:          return NULL;
                    371:        }
                    372:       ph->blks = (void *) __get_free_pages (GFP_KERNEL, 0, ~0UL);
                    373:       if (! ph->blks)
                    374:        {
                    375:          restore_flags (flags);
                    376:          return NULL;
                    377:        }
                    378:       ph->busy = 1;
                    379:       ph->avail = PAGE_SIZE / bs->size;
                    380:       ph->bitmap = 0;
                    381:       ph->next = bs->pages;
                    382:       bs->pages = ph;
                    383:       bs->avail += ph->avail;
                    384:     }
                    385:   for (ph = bs->pages; ph; ph = ph->next)
                    386:     if (ph->avail)
                    387:       for (i = 0; i < PAGE_SIZE / bs->size; i++)
                    388:        if ((ph->bitmap & (1 << i)) == 0)
                    389:          {
                    390:            bs->avail--;
                    391:            ph->avail--;
                    392:            ph->bitmap |= 1 << i;
                    393:            restore_flags (flags);
                    394:            return ph->blks + i * bs->size;
                    395:          }
                    396: 
                    397:   panic ("%s:%d: alloc_buffer: list destroyed", __FILE__, __LINE__);
                    398: }
                    399: 
                    400: /* Free buffer P of SIZE bytes previously allocated by alloc_buffer.  */
                    401: static void
                    402: free_buffer (void *p, int size)
                    403: {
                    404:   int i;
                    405:   unsigned flags;
                    406:   struct bufsize *bs;
                    407:   struct pagehdr *ph;
                    408: 
                    409:   bs = get_bufsize (size);
                    410:   save_flags (flags);
                    411:   cli ();
                    412:   for (ph = bs->pages; ph; ph = ph->next)
                    413:     if (p >= ph->blks && p < ph->blks + PAGE_SIZE)
                    414:       break;
                    415:   assert (ph);
                    416:   i = (int) (p - ph->blks) / bs->size;
                    417:   assert (ph->bitmap & (1 << i));
                    418:   ph->bitmap &= ~(1 << i);
                    419:   ph->avail++;
                    420:   bs->avail++;
                    421:   restore_flags (flags);
                    422: }
                    423: 
                    424: /* Allocate a buffer of SIZE bytes and
                    425:    associate it with block number BLOCK of device DEV.  */
                    426: struct buffer_head *
                    427: getblk (kdev_t dev, int block, int size)
                    428: {
                    429:   struct buffer_head *bh;
                    430: 
                    431:   assert (size <= PAGE_SIZE);
                    432: 
                    433:   bh = linux_kmalloc (sizeof (struct buffer_head), GFP_KERNEL);
                    434:   if (! bh)
                    435:     return NULL;
                    436:   bh->b_data = alloc_buffer (size);
                    437:   if (! bh->b_data)
                    438:     {
                    439:       linux_kfree (bh);
                    440:       return NULL;
                    441:     }
                    442:   bh->b_dev = dev;
                    443:   bh->b_size = size;
                    444:   bh->b_state = 1 << BH_Lock;
                    445:   bh->b_blocknr = block;
                    446:   bh->b_page_list = NULL;
                    447:   bh->b_request = NULL;
                    448:   bh->b_reqnext = NULL;
                    449:   bh->b_wait = NULL;
                    450:   bh->b_sem = NULL;
                    451:   return bh;
                    452: }
                    453: 
                    454: /* Release buffer BH previously allocated by getblk.  */
                    455: void
                    456: __brelse (struct buffer_head *bh)
                    457: {
                    458:   if (bh->b_request)
                    459:     linux_kfree (bh->b_request);
                    460:   free_buffer (bh->b_data, bh->b_size);
                    461:   linux_kfree (bh);
                    462: }
                    463: 
                    464: /* Check for I/O errors upon completion of I/O operation RW
                    465:    on the buffer list BH.  The number of buffers is NBUF.
                    466:    Copy any data from bounce buffers and free them.  */
                    467: static int
                    468: check_for_error (int rw, int nbuf, struct buffer_head **bh)
                    469: {
                    470:   int err;
                    471:   struct request *req;
                    472: 
                    473:   req = bh[0]->b_request;
                    474:   if (! req)
                    475:     {
                    476:       while (--nbuf >= 0)
                    477:        if (bh[nbuf]->b_page_list)
                    478:          {
                    479:            bh[nbuf]->b_page_list = NULL;
                    480:            free_buffer (bh[nbuf]->b_data, bh[nbuf]->b_size);
                    481:          }
                    482:       return -LINUX_ENOMEM;
                    483:     }
                    484: 
                    485:   bh[0]->b_request = NULL;
                    486:   err = 0;
                    487: 
                    488:   while (--nbuf >= 0)
                    489:     {
                    490:       struct buffer_head *bhp = bh[nbuf];
                    491: 
                    492:       if (bhp->b_page_list)
                    493:        {
                    494:          if (rw == READ && buffer_uptodate (bhp))
                    495:            {
                    496:              int amt;
                    497:              vm_page_t *pages = bhp->b_page_list;
                    498: 
                    499:              amt = PAGE_SIZE - bhp->b_off;
                    500:              if (amt > bhp->b_usrcnt)
                    501:                amt = bhp->b_usrcnt;
                    502:              memcpy ((void *) pages[bhp->b_index]->phys_addr + bhp->b_off,
                    503:                      bhp->b_data, amt);
                    504:              if (amt < bhp->b_usrcnt)
                    505:                memcpy ((void *) pages[bhp->b_index + 1]->phys_addr,
                    506:                        bhp->b_data + amt, bhp->b_usrcnt - amt);
                    507:            }
                    508:          bhp->b_page_list = NULL;
                    509:          free_buffer (bhp->b_data, bhp->b_size);
                    510:        }
                    511:       if (! buffer_uptodate (bhp))
                    512:        err = -LINUX_EIO;
                    513:     }
                    514: 
                    515:   linux_kfree (req);
                    516:   return err;
                    517: }
                    518: 
                    519: /* Allocate a buffer of SIZE bytes and fill it with data
                    520:    from device DEV starting at block number BLOCK.  */
                    521: struct buffer_head *
                    522: bread (kdev_t dev, int block, int size)
                    523: {
                    524:   int err;
                    525:   struct buffer_head *bh;
                    526: 
                    527:   bh = getblk (dev, block, size);
                    528:   if (! bh)
                    529:     return NULL;
                    530:   ll_rw_block (READ, 1, &bh);
                    531:   wait_on_buffer (bh);
                    532:   err = check_for_error (READ, 1, &bh);
                    533:   if (err)
                    534:     {
                    535:       __brelse (bh);
                    536:       return NULL;
                    537:     }
                    538:   return bh;
                    539: }
                    540: 
                    541: /* Return the block size for device DEV in *BSIZE and
                    542:    log2(block size) in *BSHIFT.  */
                    543: static inline void
                    544: get_block_size (kdev_t dev, int *bsize, int *bshift)
                    545: {
                    546:   int i, size, shift;
                    547: 
                    548:   size = BLOCK_SIZE;
                    549:   if (blksize_size[MAJOR (dev)]
                    550:       && blksize_size[MAJOR (dev)][MINOR (dev)])
                    551:     size = blksize_size[MAJOR (dev)][MINOR (dev)];
                    552:   for (i = size, shift = 0; i != 1; shift++, i >>= 1)
                    553:     ;
                    554:   *bsize = size;
                    555:   *bshift = shift;
                    556: }
                    557: 
                    558: /* Enqueue request REQ on a driver's queue.  */
                    559: static inline void
                    560: enqueue_request (struct request *req)
                    561: {
                    562:   struct request *tmp;
                    563:   struct blk_dev_struct *dev;
                    564: 
                    565:   dev = blk_dev + MAJOR (req->rq_dev);
                    566:   cli ();
                    567:   tmp = dev->current_request;
                    568:   if (! tmp)
                    569:     {
                    570:       dev->current_request = req;
                    571:       (*dev->request_fn) ();
                    572:       sti ();
                    573:       return;
                    574:     }
                    575:   while (tmp->next)
                    576:     {
                    577:       if ((IN_ORDER (tmp, req) || ! IN_ORDER (tmp, tmp->next))
                    578:          && IN_ORDER (req, tmp->next))
                    579:        break;
                    580:       tmp = tmp->next;
                    581:     }
                    582:   req->next = tmp->next;
                    583:   tmp->next = req;
                    584:   if (scsi_major (MAJOR (req->rq_dev)))
                    585:     (*dev->request_fn) ();
                    586:   sti ();
                    587: }
                    588: 
                    589: /* Perform the I/O operation RW on the buffer list BH
                    590:    containing NR buffers.  */
                    591: void
                    592: ll_rw_block (int rw, int nr, struct buffer_head **bh)
                    593: {
                    594:   int i, bsize, bshift;
                    595:   unsigned major;
                    596:   struct request *r;
                    597: 
                    598:   r = (struct request *) linux_kmalloc (sizeof (struct request), GFP_KERNEL);
                    599:   if (! r)
                    600:     {
                    601:       bh[0]->b_request = NULL;
                    602:       return;
                    603:     }
                    604:   bh[0]->b_request = r;
                    605: 
                    606:   major = MAJOR (bh[0]->b_dev);
                    607:   assert (major < MAX_BLKDEV);
                    608: 
                    609:   get_block_size (bh[0]->b_dev, &bsize, &bshift);
                    610:   assert (bsize <= PAGE_SIZE);
                    611: 
                    612:   for (i = 0, r->nr_sectors = 0; i < nr - 1; i++)
                    613:     {
                    614:       r->nr_sectors += bh[i]->b_size >> 9;
                    615:       bh[i]->b_reqnext = bh[i + 1];
                    616:     }
                    617:   r->nr_sectors += bh[i]->b_size >> 9;
                    618:   bh[i]->b_reqnext = NULL;
                    619: 
                    620:   r->rq_status = RQ_ACTIVE;
                    621:   r->rq_dev = bh[0]->b_dev;
                    622:   r->cmd = rw;
                    623:   r->errors = 0;
                    624:   r->sector = bh[0]->b_blocknr << (bshift - 9);
                    625:   r->current_nr_sectors = bh[0]->b_size >> 9;
                    626:   r->buffer = bh[0]->b_data;
                    627:   r->sem = bh[0]->b_sem;
                    628:   r->bh = bh[0];
                    629:   r->bhtail = bh[nr - 1];
                    630:   r->next = NULL;
                    631: 
                    632:   enqueue_request (r);
                    633: }
                    634: 
                    635: /* Maximum amount of data to write per invocation of the driver.  */
                    636: #define WRITE_MAXPHYS  (VM_MAP_COPY_PAGE_LIST_MAX << PAGE_SHIFT)
                    637: #define WRITE_MAXPHYSPG        (WRITE_MAXPHYS >> PAGE_SHIFT)
                    638: 
                    639: int linux_block_write_trace = 0;
                    640: 
                    641: /* Write COUNT bytes of data from user buffer BUF
                    642:    to device specified by INODE at location specified by FILP.  */
                    643: int
                    644: block_write (struct inode *inode, struct file *filp,
                    645:             const char *buf, int count)
                    646: {
                    647:   char *p;
                    648:   int i, bsize, bmask, bshift;
                    649:   int err = 0, have_page_list = 1;
                    650:   int resid = count, unaligned;
                    651:   int page_index, pages, amt, cnt, nbuf;
                    652:   unsigned blk;
                    653:   vm_map_copy_t copy;
                    654:   struct request req;
                    655:   struct semaphore sem;
                    656:   struct name_map *np = filp->f_np;
                    657:   struct buffer_head *bh, *bhp, **bhlist;
                    658: 
                    659:   /* Compute device block size.  */
                    660:   get_block_size (inode->i_rdev, &bsize, &bshift);
                    661:   assert (bsize <= PAGE_SIZE);
                    662:   bmask = bsize - 1;
                    663: 
                    664:   copy = (vm_map_copy_t) buf;
                    665:   assert (copy);
                    666:   assert (copy->type == VM_MAP_COPY_PAGE_LIST);
                    667: 
                    668:   p = (char *) copy->offset;
                    669:   pages = copy->cpy_npages;
                    670:   blk = (filp->f_pos + bmask) >> bshift;
                    671: 
                    672:   if (linux_block_write_trace)
                    673:     printf ("block_write: at %d: f_pos 0x%x, count %d, blk 0x%x, p 0x%x\n",
                    674:            __LINE__, (unsigned) filp->f_pos, count, blk, p);
                    675: 
                    676:   /* Allocate buffer headers.  */
                    677:   nbuf = ((round_page ((vm_offset_t) p + resid) - trunc_page ((vm_offset_t) p))
                    678:          >> PAGE_SHIFT);
                    679:   if (nbuf > WRITE_MAXPHYSPG)
                    680:     nbuf = WRITE_MAXPHYSPG;
                    681:   if ((filp->f_pos & bmask) || ((int) p & PAGE_MASK))
                    682:     nbuf *= 2;
                    683:   bh = (struct buffer_head *) kalloc ((sizeof (*bh) + sizeof (*bhlist))
                    684:                                      * nbuf);
                    685:   if (! bh)
                    686:     {
                    687:       err = -LINUX_ENOMEM;
                    688:       goto out;
                    689:     }
                    690:   bhlist = (struct buffer_head **) (bh + nbuf);
                    691: 
                    692:   /* Write any partial block.  */
                    693:   if (filp->f_pos & bmask)
                    694:     {
                    695:       char *b, *q;
                    696:       int use_req;
                    697: 
                    698:       use_req = (disk_major (MAJOR (inode->i_rdev)) && ! np->read_only);
                    699: 
                    700:       amt = bsize - (filp->f_pos & bmask);
                    701:       if (amt > resid)
                    702:        amt = resid;
                    703: 
                    704:       if (linux_block_write_trace)
                    705:        printf ("block_write: at %d: amt %d, resid %d\n",
                    706:                __LINE__, amt, resid);
                    707: 
                    708:       if (use_req)
                    709:        {
                    710:          i = (amt + 511) & ~511;
                    711:          req.buffer = b = alloc_buffer (i);
                    712:          if (! b)
                    713:            {
                    714:              printf ("%s:%d: block_write: ran out of buffers\n",
                    715:                      __FILE__, __LINE__);
                    716:              err = -LINUX_ENOMEM;
                    717:              goto out;
                    718:            }
                    719:          req.sector = filp->f_pos >> 9;
                    720:          req.nr_sectors = i >> 9;
                    721:          req.current_nr_sectors = i >> 9;
                    722:          req.rq_status = RQ_ACTIVE;
                    723:          req.rq_dev = inode->i_rdev;
                    724:          req.cmd = READ;
                    725:          req.errors = 0;
                    726:          req.sem = &sem;
                    727:          req.bh = NULL;
                    728:          req.bhtail = NULL;
                    729:          req.next = NULL;
                    730: 
                    731:          sem.count = 0;
                    732:          sem.wait = NULL;
                    733: 
                    734:          enqueue_request (&req);
                    735:          __down (&sem);
                    736: 
                    737:          if (req.errors)
                    738:            {
                    739:              free_buffer (b, i);
                    740:              err = -LINUX_EIO;
                    741:              goto out;
                    742:            }
                    743:          q = b + (filp->f_pos & 511);
                    744:        }
                    745:       else
                    746:        {
                    747:          i = bsize;
                    748:          bhp = bh;
                    749:          bhp->b_data = b = alloc_buffer (i);
                    750:          if (! b)
                    751:            {
                    752:              err = -LINUX_ENOMEM;
                    753:              goto out;
                    754:            }
                    755:          bhp->b_blocknr = filp->f_pos >> bshift;
                    756:          bhp->b_dev = inode->i_rdev;
                    757:          bhp->b_size = bsize;
                    758:          bhp->b_state = 1 << BH_Lock;
                    759:          bhp->b_page_list = NULL;
                    760:          bhp->b_request = NULL;
                    761:          bhp->b_reqnext = NULL;
                    762:          bhp->b_wait = NULL;
                    763:          bhp->b_sem = NULL;
                    764: 
                    765:          ll_rw_block (READ, 1, &bhp);
                    766:          wait_on_buffer (bhp);
                    767:          err = check_for_error (READ, 1, &bhp);
                    768:          if (err)
                    769:            {
                    770:              free_buffer (b, i);
                    771:              goto out;
                    772:            }
                    773:          q = b + (filp->f_pos & bmask);
                    774:        }
                    775: 
                    776:       cnt = PAGE_SIZE - ((int) p & PAGE_MASK);
                    777:       if (cnt > amt)
                    778:        cnt = amt;
                    779:       memcpy (q, ((void *) copy->cpy_page_list[0]->phys_addr
                    780:                  + ((int) p & PAGE_MASK)),
                    781:              cnt);
                    782:       if (cnt < amt)
                    783:        {
                    784:          assert (copy->cpy_npages >= 2);
                    785:          memcpy (q + cnt,
                    786:                  (void *) copy->cpy_page_list[1]->phys_addr, amt - cnt);
                    787:        }
                    788:       else
                    789:        assert (copy->cpy_npages >= 1);
                    790: 
                    791:       if (use_req)
                    792:        {
                    793:          req.buffer = b;
                    794:          req.sector = filp->f_pos >> 9;
                    795:          req.nr_sectors = i >> 9;
                    796:          req.current_nr_sectors = i >> 9;
                    797:          req.rq_status = RQ_ACTIVE;
                    798:          req.rq_dev = inode->i_rdev;
                    799:          req.cmd = WRITE;
                    800:          req.errors = 0;
                    801:          req.sem = &sem;
                    802:          req.bh = NULL;
                    803:          req.bhtail = NULL;
                    804:          req.next = NULL;
                    805: 
                    806:          sem.count = 0;
                    807:          sem.wait = NULL;
                    808: 
                    809:          enqueue_request (&req);
                    810:          __down (&sem);
                    811: 
                    812:          if (req.errors)
                    813:            err = -LINUX_EIO;
                    814:        }
                    815:       else
                    816:        {
                    817:          bhp->b_state = (1 << BH_Dirty) | (1 << BH_Lock);
                    818:          ll_rw_block (WRITE, 1, &bhp);
                    819:          err = check_for_error (WRITE, 1, &bhp);
                    820:        }
                    821:       free_buffer (b, i);
                    822:       if (err)
                    823:        {
                    824:          if (linux_block_write_trace)
                    825:            printf ("block_write: at %d\n", __LINE__);
                    826: 
                    827:          goto out;
                    828:        }
                    829:       resid -= amt;
                    830:       if (resid == 0)
                    831:        goto out;
                    832:       p += amt;
                    833:     }
                    834: 
                    835:   unaligned = (int) p & 511;
                    836: 
                    837:   /* Write full blocks.  */
                    838:   while (resid > bsize)
                    839:     {
                    840:       assert (have_page_list == 1);
                    841: 
                    842:       /* Construct buffer list.  */
                    843:       for (i = 0, bhp = bh; resid > bsize && i < nbuf; i++, bhp++)
                    844:        {
                    845:          page_index = ((trunc_page ((vm_offset_t) p)
                    846:                         - trunc_page (copy->offset))
                    847:                        >> PAGE_SHIFT);
                    848: 
                    849:          if (page_index == pages)
                    850:            break;
                    851: 
                    852:          bhlist[i] = bhp;
                    853:          bhp->b_dev = inode->i_rdev;
                    854:          bhp->b_state = (1 << BH_Dirty) | (1 << BH_Lock);
                    855:          bhp->b_blocknr = blk;
                    856:          bhp->b_wait = NULL;
                    857:          bhp->b_page_list = NULL;
                    858:          bhp->b_sem = &sem;
                    859: 
                    860:          cnt = PAGE_SIZE - ((int) p & PAGE_MASK);
                    861:          if (! unaligned && cnt >= bsize)
                    862:            {
                    863:              if (cnt > resid)
                    864:                cnt = resid;
                    865:              bhp->b_size = cnt & ~bmask;
                    866:              bhp->b_data = (((char *)
                    867:                              copy->cpy_page_list[page_index]->phys_addr)
                    868:                             + ((int) p & PAGE_MASK));
                    869:            }
                    870:          else
                    871:            {
                    872:              if (cnt < bsize)
                    873:                {
                    874:                  if (page_index == pages - 1)
                    875:                    break;
                    876:                  bhp->b_size = bsize;
                    877:                }
                    878:              else
                    879:                {
                    880:                  bhp->b_size = cnt;
                    881:                  if (bhp->b_size > resid)
                    882:                    bhp->b_size = resid;
                    883:                  bhp->b_size &= ~bmask;
                    884:                }
                    885:              bhp->b_data = alloc_buffer (bhp->b_size);
                    886:              if (! bhp->b_data)
                    887:                {
                    888:                  printf ("%s:%d: block_write: ran out of buffers\n",
                    889:                          __FILE__, __LINE__);
                    890:                  while (--i >= 0)
                    891:                    if (bhlist[i]->b_page_list)
                    892:                      free_buffer (bhlist[i]->b_data, bhlist[i]->b_size);
                    893:                  err = -LINUX_ENOMEM;
                    894:                  goto out;
                    895:                }
                    896:              bhp->b_page_list = (void *) 1;
                    897:              if (cnt > bhp->b_size)
                    898:                cnt = bhp->b_size;
                    899:              memcpy (bhp->b_data,
                    900:                      ((void *) copy->cpy_page_list[page_index]->phys_addr
                    901:                       + ((int) p & PAGE_MASK)),
                    902:                      cnt);
                    903:              if (cnt < bhp->b_size)
                    904:                memcpy (bhp->b_data + cnt,
                    905:                        ((void *)
                    906:                         copy->cpy_page_list[page_index + 1]->phys_addr),
                    907:                        bhp->b_size - cnt);
                    908:            }
                    909: 
                    910:          p += bhp->b_size;
                    911:          resid -= bhp->b_size;
                    912:          blk += bhp->b_size >> bshift;
                    913:        }
                    914: 
                    915:       assert (i > 0);
                    916: 
                    917:       sem.count = 0;
                    918:       sem.wait = NULL;
                    919: 
                    920:       /* Do the write.  */
                    921:       ll_rw_block (WRITE, i, bhlist);
                    922:       __down (&sem);
                    923:       err = check_for_error (WRITE, i, bhlist);
                    924:       if (err || resid == 0)
                    925:        goto out;
                    926: 
                    927:       /* Discard current page list.  */
                    928:       vm_map_copy_discard (copy);
                    929:       have_page_list = 0;
                    930: 
                    931:       /* Compute # pages to wire down.  */
                    932:       pages = ((round_page ((vm_offset_t) p + resid)
                    933:                - trunc_page ((vm_offset_t) p))
                    934:               >> PAGE_SHIFT);
                    935:       if (pages > WRITE_MAXPHYSPG)
                    936:        pages = WRITE_MAXPHYSPG;
                    937: 
                    938:       /* Wire down user pages and get page list.  */
                    939:       err = vm_map_copyin_page_list (current_map (),
                    940:                                     trunc_page ((vm_offset_t) p),
                    941:                                     pages << PAGE_SHIFT, FALSE,
                    942:                                     FALSE, &copy, FALSE);
                    943:       if (err)
                    944:        {
                    945:          if (err == KERN_INVALID_ADDRESS || err == KERN_PROTECTION_FAILURE)
                    946:            err = -LINUX_EINVAL;
                    947:          else
                    948:            err = -LINUX_ENOMEM;
                    949:          goto out;
                    950:        }
                    951: 
                    952:       assert (pages == copy->cpy_npages);
                    953:       assert (! vm_map_copy_has_cont (copy));
                    954: 
                    955:       have_page_list = 1;
                    956:     }
                    957: 
                    958:   /* Write any partial count.  */
                    959:   if (resid > 0)
                    960:     {
                    961:       char *b;
                    962:       int use_req;
                    963: 
                    964:       assert (have_page_list);
                    965:       assert (pages >= 1);
                    966: 
                    967:       use_req = (disk_major (MAJOR (inode->i_rdev)) && ! np->read_only);
                    968: 
                    969:       if (linux_block_write_trace)
                    970:        printf ("block_write: at %d: resid %d\n", __LINE__, resid);
                    971: 
                    972:       if (use_req)
                    973:        {
                    974:          i = (resid + 511) & ~511;
                    975:          req.buffer = b = alloc_buffer (i);
                    976:          if (! b)
                    977:            {
                    978:              printf ("%s:%d: block_write: ran out of buffers\n",
                    979:                      __FILE__, __LINE__);
                    980:              err = -LINUX_ENOMEM;
                    981:              goto out;
                    982:            }
                    983:          req.sector = blk << (bshift - 9);
                    984:          req.nr_sectors = i >> 9;
                    985:          req.current_nr_sectors = i >> 9;
                    986:          req.rq_status = RQ_ACTIVE;
                    987:          req.rq_dev = inode->i_rdev;
                    988:          req.cmd = READ;
                    989:          req.errors = 0;
                    990:          req.sem = &sem;
                    991:          req.bh = NULL;
                    992:          req.bhtail = NULL;
                    993:          req.next = NULL;
                    994: 
                    995:          sem.count = 0;
                    996:          sem.wait = NULL;
                    997: 
                    998:          enqueue_request (&req);
                    999:          __down (&sem);
                   1000: 
                   1001:          if (req.errors)
                   1002:            {
                   1003:              free_buffer (b, i);
                   1004:              err = -LINUX_EIO;
                   1005:              goto out;
                   1006:            }
                   1007:        }
                   1008:       else
                   1009:        {
                   1010:          i = bsize;
                   1011:          bhp = bh;
                   1012:          bhp->b_data = b = alloc_buffer (i);
                   1013:          if (! b)
                   1014:            {
                   1015:              err = -LINUX_ENOMEM;
                   1016:              goto out;
                   1017:            }
                   1018:          bhp->b_blocknr = blk;
                   1019:          bhp->b_dev = inode->i_rdev;
                   1020:          bhp->b_size = bsize;
                   1021:          bhp->b_state = 1 << BH_Lock;
                   1022:          bhp->b_page_list = NULL;
                   1023:          bhp->b_request = NULL;
                   1024:          bhp->b_reqnext = NULL;
                   1025:          bhp->b_wait = NULL;
                   1026:          bhp->b_sem = NULL;
                   1027: 
                   1028:          ll_rw_block (READ, 1, &bhp);
                   1029:          wait_on_buffer (bhp);
                   1030:          err = check_for_error (READ, 1, &bhp);
                   1031:          if (err)
                   1032:            {
                   1033:              free_buffer (b, i);
                   1034:              goto out;
                   1035:            }
                   1036:        }
                   1037: 
                   1038:       page_index = ((trunc_page ((vm_offset_t) p) - trunc_page (copy->offset))
                   1039:                    >> PAGE_SHIFT);
                   1040:       cnt = PAGE_SIZE - ((int) p & PAGE_MASK);
                   1041:       if (cnt > resid)
                   1042:        cnt = resid;
                   1043:       memcpy (b, ((void *) copy->cpy_page_list[page_index]->phys_addr
                   1044:                  + ((int) p & PAGE_MASK)),
                   1045:              cnt);
                   1046:       if (cnt < resid)
                   1047:        {
                   1048:          assert (copy->cpy_npages >= 2);
                   1049:          memcpy (b + cnt,
                   1050:                  (void *) copy->cpy_page_list[page_index + 1]->phys_addr,
                   1051:                  resid - cnt);
                   1052:        }
                   1053:       else
                   1054:        assert (copy->cpy_npages >= 1);
                   1055: 
                   1056:       if (use_req)
                   1057:        {
                   1058:          req.buffer = b;
                   1059:          req.sector = blk << (bshift - 9);
                   1060:          req.nr_sectors = i >> 9;
                   1061:          req.current_nr_sectors = i >> 9;
                   1062:          req.rq_status = RQ_ACTIVE;
                   1063:          req.rq_dev = inode->i_rdev;
                   1064:          req.cmd = WRITE;
                   1065:          req.errors = 0;
                   1066:          req.sem = &sem;
                   1067:          req.bh = NULL;
                   1068:          req.bhtail = NULL;
                   1069:          req.next = NULL;
                   1070: 
                   1071:          sem.count = 0;
                   1072:          sem.wait = NULL;
                   1073: 
                   1074:          enqueue_request (&req);
                   1075:          __down (&sem);
                   1076: 
                   1077:          if (req.errors)
                   1078:            err = -LINUX_EIO;
                   1079:        }
                   1080:       else
                   1081:        {
                   1082:          bhp->b_state = (1 << BH_Dirty) | (1 << BH_Lock);
                   1083:          ll_rw_block (WRITE, 1, &bhp);
                   1084:          err = check_for_error (WRITE, 1, &bhp);
                   1085:        }
                   1086:       free_buffer (b, i);
                   1087:       if (! err)
                   1088:        resid = 0;
                   1089:     }
                   1090: 
                   1091: out:
                   1092:   if (have_page_list)
                   1093:     vm_map_copy_discard (copy);
                   1094:   if (bh)
                   1095:     kfree ((vm_offset_t) bh,
                   1096:           (sizeof (*bh) + sizeof (*bhlist)) * nbuf);
                   1097:   filp->f_resid = resid;
                   1098:   return err;
                   1099: }
                   1100: 
                   1101: int linux_block_read_trace = 0;
                   1102: #define LINUX_BLOCK_READ_TRACE (linux_block_read_trace == -1 \
                   1103:                                || linux_block_read_trace == inode->i_rdev)
                   1104: 
                   1105: /* Maximum amount of data to read per driver invocation.  */
                   1106: #define READ_MAXPHYS   (64*1024)
                   1107: #define READ_MAXPHYSPG (READ_MAXPHYS >> PAGE_SHIFT)
                   1108: 
                   1109: /* Read COUNT bytes of data into user buffer BUF
                   1110:    from device specified by INODE from location specified by FILP.  */
                   1111: int
                   1112: block_read (struct inode *inode, struct file *filp, char *buf, int count)
                   1113: {
                   1114:   int err = 0, resid = count;
                   1115:   int i, bsize, bmask, bshift;
                   1116:   int pages, amt, unaligned;
                   1117:   int page_index, nbuf;
                   1118:   int have_page_list = 0;
                   1119:   unsigned blk;
                   1120:   vm_offset_t off, wire_offset, offset;
                   1121:   vm_object_t object;
                   1122:   vm_page_t *page_list;
                   1123:   struct request req;
                   1124:   struct semaphore sem;
                   1125:   struct name_map *np = filp->f_np;
                   1126:   struct buffer_head *bh, *bhp, **bhlist;
                   1127: 
                   1128:   /* Get device block size.  */
                   1129:   get_block_size (inode->i_rdev, &bsize, &bshift);
                   1130:   assert (bsize <= PAGE_SIZE);
                   1131:   bmask = bsize - 1;
                   1132: 
                   1133:   off = 0;
                   1134:   blk = (filp->f_pos + bmask) >> bshift;
                   1135: 
                   1136:   /* Allocate buffer headers.  */
                   1137:   nbuf = round_page (count) >> PAGE_SHIFT;
                   1138:   if (nbuf > READ_MAXPHYSPG)
                   1139:     nbuf = READ_MAXPHYSPG;
                   1140:   if (filp->f_pos & bmask)
                   1141:     nbuf *= 2;
                   1142:   bh = (struct buffer_head *) kalloc ((sizeof (*bh) + sizeof (*bhlist)) * nbuf
                   1143:                                      + sizeof (*page_list) * READ_MAXPHYSPG);
                   1144:   if (! bh)
                   1145:     return -LINUX_ENOMEM;
                   1146:   bhlist = (struct buffer_head **) (bh + nbuf);
                   1147:   page_list = (vm_page_t *) (bhlist + nbuf);
                   1148: 
                   1149:   /* Allocate an object to hold the data.  */
                   1150:   object = vm_object_allocate (round_page (count));
                   1151:   if (! object)
                   1152:     {
                   1153:       err = -LINUX_ENOMEM;
                   1154:       goto out;
                   1155:     }
                   1156: 
                   1157:   /* Compute number of pages to be wired at a time.  */
                   1158:   pages = round_page (count) >> PAGE_SHIFT;
                   1159:   if (pages > READ_MAXPHYSPG)
                   1160:     pages = READ_MAXPHYSPG;
                   1161: 
                   1162:   /* Allocate and wire down pages in the object.  */
                   1163:   for (i = 0, wire_offset = offset = 0; i < pages; i++, offset += PAGE_SIZE)
                   1164:     {
                   1165:       while (1)
                   1166:        {
                   1167:          page_list[i] = vm_page_grab ();
                   1168:          if (page_list[i])
                   1169:            {
                   1170:              assert (page_list[i]->busy);
                   1171:              assert (! page_list[i]->wanted);
                   1172:              break;
                   1173:            }
                   1174:          vm_page_wait (NULL);
                   1175:        }
                   1176:       vm_object_lock (object);
                   1177:       vm_page_lock_queues ();
                   1178:       assert (! vm_page_lookup (object, offset));
                   1179:       vm_page_insert (page_list[i], object, offset);
                   1180:       assert (page_list[i]->wire_count == 0);
                   1181:       vm_page_wire (page_list[i]);
                   1182:       vm_page_unlock_queues ();
                   1183:       vm_object_unlock (object);
                   1184:     }
                   1185:   have_page_list = 1;
                   1186: 
                   1187:   /* Read any partial block.  */
                   1188:   if (filp->f_pos & bmask)
                   1189:     {
                   1190:       char *b, *q;
                   1191:       int use_req;
                   1192: 
                   1193:       use_req = (disk_major (MAJOR (inode->i_rdev)) && ! np->read_only);
                   1194: 
                   1195:       amt = bsize - (filp->f_pos & bmask);
                   1196:       if (amt > resid)
                   1197:        amt = resid;
                   1198: 
                   1199:       if (LINUX_BLOCK_READ_TRACE)
                   1200:        printf ("block_read: at %d: amt %d, resid %d\n",
                   1201:                __LINE__, amt, resid);
                   1202: 
                   1203:       if (use_req)
                   1204:        {
                   1205:          i = (amt + 511) & ~511;
                   1206:          req.buffer = b = alloc_buffer (i);
                   1207:          if (! b)
                   1208:            {
                   1209:              printf ("%s:%d: block_read: ran out of buffers\n",
                   1210:                      __FILE__, __LINE__);
                   1211:              err = -LINUX_ENOMEM;
                   1212:              goto out;
                   1213:            }
                   1214:          req.sector = filp->f_pos >> 9;
                   1215:          req.nr_sectors = i >> 9;
                   1216:          req.current_nr_sectors = i >> 9;
                   1217:          req.rq_status = RQ_ACTIVE;
                   1218:          req.rq_dev = inode->i_rdev;
                   1219:          req.cmd = READ;
                   1220:          req.errors = 0;
                   1221:          req.sem = &sem;
                   1222:          req.bh = NULL;
                   1223:          req.bhtail = NULL;
                   1224:          req.next = NULL;
                   1225: 
                   1226:          sem.count = 0;
                   1227:          sem.wait = NULL;
                   1228: 
                   1229:          enqueue_request (&req);
                   1230:          __down (&sem);
                   1231: 
                   1232:          if (req.errors)
                   1233:            {
                   1234:              free_buffer (b, i);
                   1235:              err = -LINUX_EIO;
                   1236:              goto out;
                   1237:            }
                   1238:          q = b + (filp->f_pos & 511);
                   1239:        }
                   1240:       else
                   1241:        {
                   1242:          i = bsize;
                   1243:          bhp = bh;
                   1244:          bhp->b_data = b = alloc_buffer (i);
                   1245:          if (! b)
                   1246:            {
                   1247:              err = -LINUX_ENOMEM;
                   1248:              goto out;
                   1249:            }
                   1250:          bhp->b_blocknr = filp->f_pos >> bshift;
                   1251:          bhp->b_dev = inode->i_rdev;
                   1252:          bhp->b_size = bsize;
                   1253:          bhp->b_state = 1 << BH_Lock;
                   1254:          bhp->b_page_list = NULL;
                   1255:          bhp->b_request = NULL;
                   1256:          bhp->b_reqnext = NULL;
                   1257:          bhp->b_wait = NULL;
                   1258:          bhp->b_sem = NULL;
                   1259: 
                   1260:          ll_rw_block (READ, 1, &bhp);
                   1261:          wait_on_buffer (bhp);
                   1262:          err = check_for_error (READ, 1, &bhp);
                   1263:          if (err)
                   1264:            {
                   1265:              free_buffer (b, i);
                   1266:              goto out;
                   1267:            }
                   1268:          q = b + (filp->f_pos & bmask);
                   1269:        }
                   1270: 
                   1271:       memcpy ((void *) page_list[0]->phys_addr, q, amt);
                   1272: 
                   1273:       free_buffer (b, i);
                   1274:       resid -= amt;
                   1275:       if (resid == 0)
                   1276:        {
                   1277:          if (LINUX_BLOCK_READ_TRACE)
                   1278:            printf ("block_read: at %d\n", __LINE__);
                   1279: 
                   1280:          assert (pages == 1);
                   1281:          goto out;
                   1282:        }
                   1283:       off += amt;
                   1284:     }
                   1285: 
                   1286:   unaligned = off & 511;
                   1287: 
                   1288:   /* Read full blocks.  */
                   1289:   while (resid > bsize)
                   1290:     {
                   1291:       /* Construct buffer list to hand to the driver.  */
                   1292:       for (i = 0, bhp = bh; resid > bsize && i < nbuf; bhp++, i++)
                   1293:        {
                   1294:          if (off == wire_offset + (pages << PAGE_SHIFT))
                   1295:            break;
                   1296: 
                   1297:          bhlist[i] = bhp;
                   1298:          bhp->b_dev = inode->i_rdev;
                   1299:          bhp->b_state = 1 << BH_Lock;
                   1300:          bhp->b_blocknr = blk;
                   1301:          bhp->b_wait = NULL;
                   1302:          bhp->b_sem = &sem;
                   1303: 
                   1304:          page_index = (trunc_page (off) - wire_offset) >> PAGE_SHIFT;
                   1305:          amt = PAGE_SIZE - (off & PAGE_MASK);
                   1306:          if (! unaligned && amt >= bsize)
                   1307:            {
                   1308:              if (amt > resid)
                   1309:                amt = resid;
                   1310:              bhp->b_size = amt & ~bmask;
                   1311:              bhp->b_data = ((char *) page_list[page_index]->phys_addr
                   1312:                             + (off & PAGE_MASK));
                   1313:              bhp->b_page_list = NULL;
                   1314:            }
                   1315:          else
                   1316:            {
                   1317:              if (amt < bsize)
                   1318:                {
                   1319:                  if (page_index == pages - 1)
                   1320:                    {
                   1321:                      assert (round_page (count) - off >= resid);
                   1322:                      break;
                   1323:                    }
                   1324:                  bhp->b_size = bsize;
                   1325:                }
                   1326:              else
                   1327:                {
                   1328:                  if (amt > resid)
                   1329:                    amt = resid;
                   1330:                  bhp->b_size = amt & ~bmask;
                   1331:                }
                   1332:              bhp->b_data = alloc_buffer (bhp->b_size);
                   1333:              if (! bhp->b_data)
                   1334:                {
                   1335:                  printf ("%s:%d: block_read: ran out of buffers\n",
                   1336:                          __FILE__, __LINE__);
                   1337: 
                   1338:                  while (--i >= 0)
                   1339:                    if (bhp->b_page_list)
                   1340:                      free_buffer (bhp->b_data, bhp->b_size);
                   1341:                  err = -LINUX_ENOMEM;
                   1342:                  goto out;
                   1343:                }
                   1344:              bhp->b_page_list = page_list;
                   1345:              bhp->b_index = page_index;
                   1346:              bhp->b_off = off & PAGE_MASK;
                   1347:              bhp->b_usrcnt = bhp->b_size;
                   1348:            }
                   1349: 
                   1350:          resid -= bhp->b_size;
                   1351:          off += bhp->b_size;
                   1352:          blk += bhp->b_size >> bshift;
                   1353:        }
                   1354: 
                   1355:       assert (i > 0);
                   1356: 
                   1357:       sem.count = 0;
                   1358:       sem.wait = NULL;
                   1359: 
                   1360:       /* Do the read.  */
                   1361:       ll_rw_block (READ, i, bhlist);
                   1362:       __down (&sem);
                   1363:       err = check_for_error (READ, i, bhlist);
                   1364:       if (err || resid == 0)
                   1365:        goto out;
                   1366: 
                   1367:       /* Unwire the pages and mark them dirty.  */
                   1368:       offset = trunc_page (off);
                   1369:       for (i = 0; wire_offset < offset; i++, wire_offset += PAGE_SIZE)
                   1370:        {
                   1371:          vm_object_lock (object);
                   1372:          vm_page_lock_queues ();
                   1373:          assert (vm_page_lookup (object, wire_offset) == page_list[i]);
                   1374:          assert (page_list[i]->wire_count == 1);
                   1375:          assert (! page_list[i]->active && ! page_list[i]->inactive);
                   1376:          assert (! page_list[i]->reference);
                   1377:          page_list[i]->dirty = TRUE;
                   1378:          page_list[i]->reference = TRUE;
                   1379:          page_list[i]->busy = FALSE;
                   1380:          vm_page_unwire (page_list[i]);
                   1381:          vm_page_unlock_queues ();
                   1382:          vm_object_unlock (object);
                   1383:        }
                   1384: 
                   1385:       assert (i <= pages);
                   1386: 
                   1387:       /* Wire down the next chunk of the object.  */
                   1388:       if (i == pages)
                   1389:        {
                   1390:          i = 0;
                   1391:          offset = wire_offset;
                   1392:          have_page_list = 0;
                   1393:        }
                   1394:       else
                   1395:        {
                   1396:          int j;
                   1397: 
                   1398:          for (j = 0; i < pages; page_list[j++] = page_list[i++])
                   1399:            offset += PAGE_SIZE;
                   1400:          i = j;
                   1401:        }
                   1402:       pages = (round_page (count) - wire_offset) >> PAGE_SHIFT;
                   1403:       if (pages > READ_MAXPHYSPG)
                   1404:        pages = READ_MAXPHYSPG;
                   1405:       while (i < pages)
                   1406:        {
                   1407:          while (1)
                   1408:            {
                   1409:              page_list[i] = vm_page_grab ();
                   1410:              if (page_list[i])
                   1411:                {
                   1412:                  assert (page_list[i]->busy);
                   1413:                  assert (! page_list[i]->wanted);
                   1414:                  break;
                   1415:                }
                   1416:              vm_page_wait (NULL);
                   1417:            }
                   1418:          vm_object_lock (object);
                   1419:          vm_page_lock_queues ();
                   1420:          assert (! vm_page_lookup (object, offset));
                   1421:          vm_page_insert (page_list[i], object, offset);
                   1422:          assert (page_list[i]->wire_count == 0);
                   1423:          vm_page_wire (page_list[i]);
                   1424:          vm_page_unlock_queues ();
                   1425:          vm_object_unlock (object);
                   1426:          i++;
                   1427:          offset += PAGE_SIZE;
                   1428:        }
                   1429:       have_page_list = 1;
                   1430:     }
                   1431: 
                   1432:   /* Read any partial count.  */
                   1433:   if (resid > 0)
                   1434:     {
                   1435:       char *b;
                   1436:       int use_req;
                   1437: 
                   1438:       assert (have_page_list);
                   1439:       assert (pages >= 1);
                   1440: 
                   1441:       use_req = (disk_major (MAJOR (inode->i_rdev)) && ! np->read_only);
                   1442: 
                   1443:       amt = bsize - (filp->f_pos & bmask);
                   1444:       if (amt > resid)
                   1445:        amt = resid;
                   1446: 
                   1447:       if (LINUX_BLOCK_READ_TRACE)
                   1448:        printf ("block_read: at %d: resid %d\n", __LINE__, amt, resid);
                   1449: 
                   1450:       if (use_req)
                   1451:        {
                   1452:          i = (resid + 511) & ~511;
                   1453:          req.buffer = b = alloc_buffer (i);
                   1454:          if (! b)
                   1455:            {
                   1456:              printf ("%s:%d: block_read: ran out of buffers\n",
                   1457:                      __FILE__, __LINE__);
                   1458:              err = -LINUX_ENOMEM;
                   1459:              goto out;
                   1460:            }
                   1461:          req.sector = blk << (bshift - 9);
                   1462:          req.nr_sectors = i >> 9;
                   1463:          req.current_nr_sectors = i >> 9;
                   1464:          req.rq_status = RQ_ACTIVE;
                   1465:          req.rq_dev = inode->i_rdev;
                   1466:          req.cmd = READ;
                   1467:          req.errors = 0;
                   1468:          req.sem = &sem;
                   1469:          req.bh = NULL;
                   1470:          req.bhtail = NULL;
                   1471:          req.next = NULL;
                   1472: 
                   1473:          sem.count = 0;
                   1474:          sem.wait = NULL;
                   1475: 
                   1476:          enqueue_request (&req);
                   1477:          __down (&sem);
                   1478: 
                   1479:          if (req.errors)
                   1480:            {
                   1481:              free_buffer (b, i);
                   1482:              err = -LINUX_EIO;
                   1483:              goto out;
                   1484:            }
                   1485:        }
                   1486:       else
                   1487:        {
                   1488:          i = bsize;
                   1489:          bhp = bh;
                   1490:          bhp->b_data = b = alloc_buffer (i);
                   1491:          if (! b)
                   1492:            {
                   1493:              err = -LINUX_ENOMEM;
                   1494:              goto out;
                   1495:            }
                   1496:          bhp->b_blocknr = blk;
                   1497:          bhp->b_dev = inode->i_rdev;
                   1498:          bhp->b_size = bsize;
                   1499:          bhp->b_state = 1 << BH_Lock;
                   1500:          bhp->b_page_list = NULL;
                   1501:          bhp->b_request = NULL;
                   1502:          bhp->b_reqnext = NULL;
                   1503:          bhp->b_wait = NULL;
                   1504:          bhp->b_sem = NULL;
                   1505: 
                   1506:          ll_rw_block (READ, 1, &bhp);
                   1507:          wait_on_buffer (bhp);
                   1508:          err = check_for_error (READ, 1, &bhp);
                   1509:          if (err)
                   1510:            {
                   1511:              free_buffer (b, i);
                   1512:              goto out;
                   1513:            }
                   1514:        }
                   1515: 
                   1516:       page_index = (trunc_page (off) - wire_offset) >> PAGE_SHIFT;
                   1517:       amt = PAGE_SIZE - (off & PAGE_MASK);
                   1518:       if (amt > resid)
                   1519:        amt = resid;
                   1520:       memcpy (((void *) page_list[page_index]->phys_addr
                   1521:               + (off & PAGE_MASK)),
                   1522:              b, amt);
                   1523:       if (amt < resid)
                   1524:        {
                   1525:          assert (pages >= 2);
                   1526:          memcpy ((void *) page_list[page_index + 1]->phys_addr,
                   1527:                  b + amt, resid - amt);
                   1528:        }
                   1529:       else
                   1530:        assert (pages >= 1);
                   1531: 
                   1532:       free_buffer (b, i);
                   1533:     }
                   1534: 
                   1535: out:
                   1536:   if (have_page_list)
                   1537:     {
                   1538:       for (i = 0; i < pages; i++, wire_offset += PAGE_SIZE)
                   1539:        {
                   1540:          vm_object_lock (object);
                   1541:          vm_page_lock_queues ();
                   1542:          assert (vm_page_lookup (object, wire_offset) == page_list[i]);
                   1543:          assert (page_list[i]->wire_count == 1);
                   1544:          assert (! page_list[i]->active && ! page_list[i]->inactive);
                   1545:          assert (! page_list[i]->reference);
                   1546:          page_list[i]->dirty = TRUE;
                   1547:          page_list[i]->reference = TRUE;
                   1548:          page_list[i]->busy = FALSE;
                   1549:          vm_page_unwire (page_list[i]);
                   1550:          vm_page_unlock_queues ();
                   1551:          vm_object_unlock (object);
                   1552:        }
                   1553:     }      
                   1554:   kfree ((vm_offset_t) bh,
                   1555:         ((sizeof (*bh) + sizeof (*bhlist)) * nbuf
                   1556:          + sizeof (*page_list) * READ_MAXPHYSPG));
                   1557:   if (err)
                   1558:     {
                   1559:       if (object)
                   1560:        {
                   1561:          assert (object->ref_count == 1);
                   1562:          vm_object_deallocate (object);
                   1563:        }
                   1564:     }
                   1565:   else
                   1566:     {
                   1567:       assert (object);
                   1568:       assert (object->ref_count == 1);
                   1569: 
                   1570:       filp->f_resid = 0;
                   1571:       filp->f_object = object;
                   1572:     }
                   1573: 
                   1574:   if (LINUX_BLOCK_READ_TRACE)
                   1575:     printf ("block_read: at %d: err %d\n", __LINE__, err);
                   1576: 
                   1577:   return err;
                   1578: }
                   1579: 
                   1580: /*
                   1581:  * This routine checks whether a removable media has been changed,
                   1582:  * and invalidates all buffer-cache-entries in that case. This
                   1583:  * is a relatively slow routine, so we have to try to minimize using
                   1584:  * it. Thus it is called only upon a 'mount' or 'open'. This
                   1585:  * is the best way of combining speed and utility, I think.
                   1586:  * People changing diskettes in the middle of an operation deserve
                   1587:  * to loose :-)
                   1588:  */
                   1589: int
                   1590: check_disk_change (kdev_t dev)
                   1591: {
                   1592:   unsigned i;
                   1593:   struct file_operations * fops;
                   1594: 
                   1595:   i = MAJOR(dev);
                   1596:   if (i >= MAX_BLKDEV || (fops = blkdevs[i].fops) == NULL)
                   1597:     return 0;
                   1598:   if (fops->check_media_change == NULL)
                   1599:     return 0;
                   1600:   if (! (*fops->check_media_change) (dev))
                   1601:     return 0;
                   1602: 
                   1603:   /*  printf ("Disk change detected on device %s\n", kdevname(dev));*/
                   1604: 
                   1605:   if (fops->revalidate)
                   1606:     (*fops->revalidate) (dev);
                   1607: 
                   1608:   return 1;
                   1609: }
                   1610: 
                   1611: /* Mach device interface routines.  */
                   1612: 
                   1613: /* Mach name to Linux major/minor number mapping table.  */
                   1614: static struct name_map name_to_major[] =
                   1615: {
                   1616:   /* IDE disks */
                   1617:   { "hd0", IDE0_MAJOR, 0, 0 },
                   1618:   { "hd1", IDE0_MAJOR, 1, 0 },
                   1619:   { "hd2", IDE1_MAJOR, 0, 0 },
                   1620:   { "hd3", IDE1_MAJOR, 1, 0 },
                   1621:   { "hd4", IDE2_MAJOR, 0, 0 },
                   1622:   { "hd5", IDE2_MAJOR, 1, 0 },
                   1623:   { "hd6", IDE3_MAJOR, 0, 0 },
                   1624:   { "hd7", IDE3_MAJOR, 1, 0 },
                   1625: 
                   1626:   /* IDE CDROMs */
                   1627:   { "wcd0", IDE0_MAJOR, 0, 1 },
                   1628:   { "wcd1", IDE0_MAJOR, 1, 1 },
                   1629:   { "wcd2", IDE1_MAJOR, 0, 1 },
                   1630:   { "wcd3", IDE1_MAJOR, 1, 1 },
                   1631:   { "wcd4", IDE2_MAJOR, 0, 1 },
                   1632:   { "wcd5", IDE2_MAJOR, 1, 1 },
                   1633:   { "wcd6", IDE3_MAJOR, 0, 1 },
                   1634:   { "wcd7", IDE3_MAJOR, 1, 1 },
                   1635: 
                   1636:   /* SCSI disks */
                   1637:   { "sd0", SCSI_DISK_MAJOR, 0, 0 },
                   1638:   { "sd1", SCSI_DISK_MAJOR, 1, 0 },
                   1639:   { "sd2", SCSI_DISK_MAJOR, 2, 0 },
                   1640:   { "sd3", SCSI_DISK_MAJOR, 3, 0 },
                   1641:   { "sd4", SCSI_DISK_MAJOR, 4, 0 },
                   1642:   { "sd5", SCSI_DISK_MAJOR, 5, 0 },
                   1643:   { "sd6", SCSI_DISK_MAJOR, 6, 0 },
                   1644:   { "sd7", SCSI_DISK_MAJOR, 7, 0 },
                   1645: 
                   1646:   /* SCSI CDROMs */
                   1647:   { "cd0", SCSI_CDROM_MAJOR, 0, 1 },
                   1648:   { "cd1", SCSI_CDROM_MAJOR, 1, 1 },
                   1649: 
                   1650:   /* Floppy disks */
                   1651:   { "fd0", FLOPPY_MAJOR, 0, 0 },
                   1652:   { "fd1", FLOPPY_MAJOR, 1, 0 },
                   1653: };
                   1654: 
                   1655: #define NUM_NAMES (sizeof (name_to_major) / sizeof (name_to_major[0]))
                   1656: 
                   1657: /* One of these is associated with each open instance of a device.  */
                   1658: struct block_data
                   1659: {
                   1660:   const char *name;            /* Mach name for device */
                   1661:   int want:1;                  /* someone is waiting for I/O to complete */
                   1662:   int open_count;              /* number of opens */
                   1663:   int iocount;                 /* number of pending I/O operations */
                   1664:   int part;                    /* BSD partition number (-1 if none) */
                   1665:   ipc_port_t port;             /* port representing device */
                   1666:   struct device_struct *ds;    /* driver operation table entry */
                   1667:   struct device device;                /* generic device header */
                   1668:   struct file file;            /* Linux file structure */
                   1669:   struct inode inode;          /* Linux inode structure */
                   1670:   struct name_map *np;         /* name to inode map */
                   1671:   struct block_data *next;     /* forward link */
                   1672: };
                   1673: 
                   1674: /* List of open devices.  */
                   1675: static struct block_data *open_list;
                   1676: 
                   1677: /* Forward declarations.  */
                   1678: 
                   1679: extern struct device_emulation_ops linux_block_emulation_ops;
                   1680: 
                   1681: static io_return_t device_close (void *);
                   1682: 
                   1683: /* Return a send right for block device BD.  */
                   1684: static ipc_port_t
                   1685: dev_to_port (void *bd)
                   1686: {
                   1687:   return (bd
                   1688:          ? ipc_port_make_send (((struct block_data *) bd)->port)
                   1689:          : IP_NULL);
                   1690: }
                   1691: 
                   1692: /* Return 1 if C is a letter of the alphabet.  */
                   1693: static inline int
                   1694: isalpha (int c)
                   1695: {
                   1696:   return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
                   1697: }
                   1698: 
                   1699: /* Return 1 if C is a digit.  */
                   1700: static inline int
                   1701: isdigit (int c)
                   1702: {
                   1703:   return c >= '0' && c <= '9';
                   1704: }
                   1705: 
                   1706: int linux_device_open_trace = 0;
                   1707: 
                   1708: static io_return_t
                   1709: device_open (ipc_port_t reply_port, mach_msg_type_name_t reply_port_type,
                   1710:             dev_mode_t mode, char *name, device_t *devp)
                   1711: {
                   1712:   char *p;
                   1713:   int i, part = -1, slice = 0, err = 0;
                   1714:   unsigned major, minor;
                   1715:   kdev_t dev;
                   1716:   ipc_port_t notify;
                   1717:   struct file file;
                   1718:   struct inode inode;
                   1719:   struct name_map *np;
                   1720:   struct device_struct *ds;
                   1721:   struct block_data *bd = NULL, *bdp;
                   1722: 
                   1723:   if (linux_device_open_trace)
                   1724:     printf ("device_open: at %d: name %s\n", __LINE__, name);
                   1725: 
                   1726:   /* Parse name into name, unit, DOS partition (slice) and partition.  */
                   1727:   for (p = name; isalpha (*p); p++)
                   1728:     ;
                   1729:   if (p == name || ! isdigit (*p))
                   1730:     {
                   1731:       if (linux_device_open_trace)
                   1732:        printf ("device_open: at %d\n", __LINE__);
                   1733: 
                   1734:       return D_NO_SUCH_DEVICE;
                   1735:     }
                   1736:   do
                   1737:     p++;
                   1738:   while (isdigit (*p));
                   1739:   if (*p)
                   1740:     {
                   1741:       char *q = p;
                   1742: 
                   1743:       if (! isalpha (*q))
                   1744:        {
                   1745:          if (linux_device_open_trace)
                   1746:            printf ("device_open: at %d\n", __LINE__);
                   1747: 
                   1748:          return D_NO_SUCH_DEVICE;
                   1749:        }
                   1750:       if (*q == 's' && isdigit (*(q + 1)))
                   1751:        {
                   1752:          q++;
                   1753:          slice = 0;
                   1754:          do
                   1755:            slice = slice * 10 + *q++ - '0';
                   1756:          while (isdigit (*q));
                   1757:          if (! *q)
                   1758:            goto find_major;
                   1759:          if (! isalpha (*q))
                   1760:            {
                   1761:              if (linux_device_open_trace)
                   1762:                printf ("device_open: at %d\n", __LINE__);
                   1763: 
                   1764:              return D_NO_SUCH_DEVICE;
                   1765:            }
                   1766:        }
                   1767:       if (*(q + 1))
                   1768:        {
                   1769:          if (linux_device_open_trace)
                   1770:            printf ("device_open: at %d\n", __LINE__);
                   1771: 
                   1772:          return D_NO_SUCH_DEVICE;
                   1773:        }
                   1774:       part = *q - 'a';
                   1775:     }
                   1776:   else
                   1777:     slice = -1;
                   1778: 
                   1779: find_major:
                   1780:   /* Convert name to major number.  */
                   1781:   for (i = 0, np = name_to_major; i < NUM_NAMES; i++, np++)
                   1782:     {
                   1783:       int len = strlen (np->name);
                   1784: 
                   1785:       if (len == p - name && ! strncmp (np->name, name, len))
                   1786:        break;
                   1787:     }
                   1788:   if (i == NUM_NAMES)
                   1789:     {
                   1790:       if (linux_device_open_trace)
                   1791:        printf ("device_open: at %d\n", __LINE__);
                   1792: 
                   1793:       return D_NO_SUCH_DEVICE;
                   1794:     }
                   1795: 
                   1796:   major = np->major;
                   1797:   ds = &blkdevs[major];
                   1798: 
                   1799:   /* Check that driver exists.  */
                   1800:   if (! ds->fops)
                   1801:     {
                   1802:       if (linux_device_open_trace)
                   1803:        printf ("device_open: at %d\n", __LINE__);
                   1804: 
                   1805:       return D_NO_SUCH_DEVICE;
                   1806:     }
                   1807: 
                   1808:   /* Slice and partition numbers are only used by disk drives.
                   1809:      The test for read-only is for IDE CDROMs.  */
                   1810:   if (! disk_major (major) || np->read_only)
                   1811:     {
                   1812:       slice = -1;
                   1813:       part = -1;
                   1814:     }
                   1815: 
                   1816:   /* Wait for any other open/close calls to finish.  */
                   1817:   ds = &blkdevs[major];
                   1818:   while (ds->busy)
                   1819:     {
                   1820:       ds->want = 1;
                   1821:       assert_wait ((event_t) ds, FALSE);
                   1822:       thread_block (0);
                   1823:     }
                   1824:   ds->busy = 1;
                   1825: 
                   1826:   /* Compute minor number.  */
                   1827:   if (disk_major (major) && ! ds->gd)
                   1828:     {
                   1829:       struct gendisk *gd;
                   1830: 
                   1831:       for (gd = gendisk_head; gd && gd->major != major; gd = gd->next)
                   1832:        ;
                   1833:       assert (gd);
                   1834:       ds->gd = gd;
                   1835:     }
                   1836:   minor = np->unit;
                   1837:   if (ds->gd)
                   1838:     minor <<= ds->gd->minor_shift;
                   1839:   dev = MKDEV (major, minor);
                   1840: 
                   1841:   /* If no DOS partition is specified, find one we can handle.  */
                   1842:   if (slice == 0 && (! ds->default_slice || ds->default_slice[np->unit] == 0))
                   1843:     {
                   1844:       int sysid, bsize, bshift;
                   1845:       struct mboot *mp;
                   1846:       struct ipart *pp;
                   1847:       struct buffer_head *bhp;
                   1848: 
                   1849:       /* Open partition 0.  */
                   1850:       inode.i_rdev = dev;
                   1851:       file.f_mode = O_RDONLY;
                   1852:       file.f_flags = 0;
                   1853:       if (ds->fops->open)
                   1854:        {
                   1855:          linux_intr_pri = SPL5;
                   1856:          err = (*ds->fops->open) (&inode, &file);
                   1857:          if (err)
                   1858:            {
                   1859:              if (linux_device_open_trace)
                   1860:                printf ("device_open: at %d\n", __LINE__);
                   1861: 
                   1862:              err = linux_to_mach_error (err);
                   1863:              goto out;
                   1864:            }
                   1865:        }
                   1866: 
                   1867:       /* Allocate a buffer for I/O.  */
                   1868:       get_block_size (inode.i_rdev, &bsize, &bshift);
                   1869:       assert (bsize <= PAGE_SIZE);
                   1870:       bhp = getblk (inode.i_rdev, 0, bsize);
                   1871:       if (! bhp)
                   1872:        {
                   1873:          if (linux_device_open_trace)
                   1874:            printf ("device_open: at %d\n", __LINE__);
                   1875: 
                   1876:          err = D_NO_MEMORY;
                   1877:          goto slice_done;
                   1878:        }
                   1879: 
                   1880:       /* Read DOS partition table.  */
                   1881:       ll_rw_block (READ, 1, &bhp);
                   1882:       wait_on_buffer (bhp);
                   1883:       err = check_for_error (READ, 1, &bhp);
                   1884:       if (err)
                   1885:        {
                   1886:          printf ("%s: error reading boot sector\n", np->name);
                   1887:          err = linux_to_mach_error (err);
                   1888:          goto slice_done;
                   1889:        }
                   1890: 
                   1891:       /* Check for valid partition table.  */
                   1892:       mp = (struct mboot *) bhp->b_data;
                   1893:       if (mp->signature != BOOT_MAGIC)
                   1894:        {
                   1895:          printf ("%s: invalid partition table\n", np->name);
                   1896:          err = D_NO_SUCH_DEVICE;
                   1897:          goto slice_done;
                   1898:        }
                   1899: 
                   1900:       /* Search for a Mach, BSD or Linux partition.  */
                   1901:       sysid = 0;
                   1902:       pp = (struct ipart *) mp->parts;
                   1903:       for (i = 0; i < FD_NUMPART; i++, pp++)
                   1904:        {
                   1905:          if ((pp->systid == UNIXOS
                   1906:               || pp->systid == BSDOS
                   1907:               || pp->systid == LINUXOS)
                   1908:              && (! sysid || pp->bootid == ACTIVE))
                   1909:            {
                   1910:              sysid = pp->systid;
                   1911:              slice = i + 1;
                   1912:            }
                   1913:        }
                   1914:       if (! sysid)
                   1915:        {
                   1916:          printf ("%s: No Mach, BSD or Linux partition found\n", np->name);
                   1917:          err = D_NO_SUCH_DEVICE;
                   1918:          goto slice_done;
                   1919:        }
                   1920: 
                   1921:       /*      printf ("%s: default slice %d: %s OS\n", np->name, slice,
                   1922:              (sysid == UNIXOS ? "Mach" : (sysid == BSDOS ? "BSD" : "LINUX")));*/
                   1923: 
                   1924:     slice_done:
                   1925:       if (ds->fops->release)
                   1926:        (*ds->fops->release) (&inode, &file);
                   1927:       __brelse (bhp);
                   1928:       if (err)
                   1929:        goto out;
                   1930:       if (! ds->default_slice)
                   1931:        {
                   1932:          ds->default_slice = (int *) kalloc (sizeof (int) * ds->gd->max_nr);
                   1933:          if (! ds->default_slice)
                   1934:            {
                   1935:              if (linux_device_open_trace)
                   1936:                printf ("device_open: at %d\n", __LINE__);
                   1937: 
                   1938:              err = D_NO_MEMORY;
                   1939:              goto out;
                   1940:            }
                   1941:          memset (ds->default_slice, 0, sizeof (int) * ds->gd->max_nr);
                   1942:        }
                   1943:       ds->default_slice[np->unit] = slice;
                   1944:     }
                   1945: 
                   1946:   /* Add slice to minor number.  */
                   1947:   if (slice == 0)
                   1948:     slice = ds->default_slice[np->unit];
                   1949:   if (slice > 0)
                   1950:     {
                   1951:       if (slice >= ds->gd->max_p)
                   1952:        {
                   1953:          if (linux_device_open_trace)
                   1954:            printf ("device_open: at %d\n", __LINE__);
                   1955: 
                   1956:          err = D_NO_SUCH_DEVICE;
                   1957:          goto out;
                   1958:        }
                   1959:       minor |= slice;
                   1960: 
                   1961:       if (linux_device_open_trace)
                   1962:        printf ("device_open: at %d: start_sect 0x%x, nr_sects %d\n",
                   1963:                __LINE__, ds->gd->part[minor].start_sect,
                   1964:                ds->gd->part[minor].nr_sects);
                   1965:     }
                   1966:   dev = MKDEV (major, minor);
                   1967: 
                   1968:   /* Initialize file structure.  */
                   1969:   file.f_mode = (mode == D_READ || np->read_only) ? O_RDONLY : O_RDWR;
                   1970:   file.f_flags = (mode & D_NODELAY) ? O_NDELAY : 0;
                   1971: 
                   1972:   /* Check if the device is currently open.  */
                   1973:   for (bdp = open_list; bdp; bdp = bdp->next)
                   1974:     if (bdp->inode.i_rdev == dev
                   1975:        && bdp->part == part
                   1976:        && bdp->file.f_mode == file.f_mode
                   1977:        && bdp->file.f_flags == file.f_flags)
                   1978:       {
                   1979:        bd = bdp;
                   1980:        goto out;
                   1981:       }
                   1982: 
                   1983:   /* Open the device.  */
                   1984:   if (ds->fops->open)
                   1985:     {
                   1986:       inode.i_rdev = dev;
                   1987:       linux_intr_pri = SPL5;
                   1988:       err = (*ds->fops->open) (&inode, &file);
                   1989:       if (err)
                   1990:        {
                   1991:          if (linux_device_open_trace)
                   1992:            printf ("device_open: at %d\n", __LINE__);
                   1993: 
                   1994:          err = linux_to_mach_error (err);
                   1995:          goto out;
                   1996:        }
                   1997:     }
                   1998:       
                   1999:   /* Read disklabel.  */
                   2000:   if (part >= 0 && (! ds->label || ! ds->label[minor]))
                   2001:     {
                   2002:       int bsize, bshift;
                   2003:       struct evtoc *evp;
                   2004:       struct disklabel *lp, *dlp;
                   2005:       struct buffer_head *bhp;
                   2006: 
                   2007:       assert (disk_major (major));
                   2008: 
                   2009:       /* Allocate a disklabel.  */
                   2010:       lp = (struct disklabel *) kalloc (sizeof (struct disklabel));
                   2011:       if (! lp)
                   2012:        {
                   2013:          if (linux_device_open_trace)
                   2014:            printf ("device_open: at %d\n", __LINE__);
                   2015: 
                   2016:          err = D_NO_MEMORY;
                   2017:          goto bad;
                   2018:        }
                   2019: 
                   2020:       /* Allocate a buffer for I/O.  */
                   2021:       get_block_size (dev, &bsize, &bshift);
                   2022:       assert (bsize <= PAGE_SIZE);
                   2023:       bhp = getblk (dev, LBLLOC >> (bshift - 9), bsize);
                   2024:       if (! bhp)
                   2025:        {
                   2026:          if (linux_device_open_trace)
                   2027:            printf ("device_open: at %d\n", __LINE__);
                   2028: 
                   2029:          err = D_NO_MEMORY;
                   2030:          goto label_done;
                   2031:        }
                   2032: 
                   2033:       /* Set up 'c' partition to span the entire DOS partition.  */
                   2034:       lp->d_npartitions = PART_DISK + 1;
                   2035:       memset (lp->d_partitions, 0, MAXPARTITIONS * sizeof (struct partition));
                   2036:       lp->d_partitions[PART_DISK].p_offset = ds->gd->part[minor].start_sect;
                   2037:       lp->d_partitions[PART_DISK].p_size = ds->gd->part[minor].nr_sects;
                   2038: 
                   2039:       /* Try reading a BSD disklabel.  */
                   2040:       ll_rw_block (READ, 1, &bhp);
                   2041:       wait_on_buffer (bhp);
                   2042:       err = check_for_error (READ, 1, &bhp);
                   2043:       if (err)
                   2044:        {
                   2045:          printf ("%s: error reading BSD label\n", np->name);
                   2046:          err = 0;
                   2047:          goto vtoc;
                   2048:        }
                   2049:       dlp = (struct disklabel *) (bhp->b_data + ((LBLLOC << 9) & (bsize - 1)));
                   2050:       if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC)
                   2051:        goto vtoc;
                   2052:       /*      printf ("%s: BSD LABEL\n", np->name);*/
                   2053:       lp->d_npartitions = dlp->d_npartitions;
                   2054:       memcpy (lp->d_partitions, dlp->d_partitions,
                   2055:              MAXPARTITIONS * sizeof (struct partition));
                   2056: 
                   2057:       /* Check for NetBSD DOS partition bogosity.  */
                   2058:       for (i = 0; i < lp->d_npartitions; i++)
                   2059:        if (lp->d_partitions[i].p_size > ds->gd->part[minor].nr_sects)
                   2060:          ds->gd->part[minor].nr_sects = lp->d_partitions[i].p_size;
                   2061:       goto label_done;
                   2062: 
                   2063:     vtoc:
                   2064:       /* Try reading VTOC.  */
                   2065:       bhp->b_blocknr = PDLOCATION >> (bshift - 9);
                   2066:       bhp->b_state = 1 << BH_Lock;
                   2067:       ll_rw_block (READ, 1, &bhp);
                   2068:       wait_on_buffer (bhp);
                   2069:       err = check_for_error (READ, 1, &bhp);
                   2070:       if (err)
                   2071:        {
                   2072:          printf ("%s: error reading evtoc\n", np->name);
                   2073:          err = linux_to_mach_error (err);
                   2074:          goto label_done;
                   2075:        }
                   2076:       evp = (struct evtoc *) (bhp->b_data + ((PDLOCATION << 9) & (bsize - 1)));
                   2077:       if (evp->sanity != VTOC_SANE)
                   2078:        {
                   2079:          printf ("%s: No BSD or Mach label found\n", np->name);
                   2080:          err = D_NO_SUCH_DEVICE;
                   2081:          goto label_done;
                   2082:        }
                   2083:       /*      printf ("%s: LOCAL LABEL\n", np->name);*/
                   2084:       lp->d_npartitions = (evp->nparts > MAXPARTITIONS
                   2085:                           ? MAXPARTITIONS : evp->nparts);
                   2086:       for (i = 0; i < lp->d_npartitions; i++)
                   2087:        {
                   2088:          lp->d_partitions[i].p_size = evp->part[i].p_size;
                   2089:          lp->d_partitions[i].p_offset = evp->part[i].p_start;
                   2090:          lp->d_partitions[i].p_fstype = FS_BSDFFS;
                   2091:        }
                   2092: 
                   2093:     label_done:
                   2094:       if (bhp)
                   2095:        __brelse (bhp);
                   2096:       if (err)
                   2097:        {
                   2098:          kfree ((vm_offset_t) lp, sizeof (struct disklabel));
                   2099:          goto bad;
                   2100:        }
                   2101:       if (! ds->label)
                   2102:        {
                   2103:          ds->label = (struct disklabel **) kalloc (sizeof (struct disklabel *)
                   2104:                                                    * ds->gd->max_p
                   2105:                                                    * ds->gd->max_nr);
                   2106:          if (! ds->label)
                   2107:            {
                   2108:              if (linux_device_open_trace)
                   2109:                printf ("device_open: at %d\n", __LINE__);
                   2110: 
                   2111:              kfree ((vm_offset_t) lp, sizeof (struct disklabel));
                   2112:              err = D_NO_MEMORY;
                   2113:              goto bad;
                   2114:            }
                   2115:          memset (ds->label, 0,
                   2116:                  (sizeof (struct disklabel *)
                   2117:                   * ds->gd->max_p * ds->gd->max_nr));
                   2118:        }
                   2119:       ds->label[minor] = lp;
                   2120:     }
                   2121: 
                   2122:   /* Check partition number.  */
                   2123:   if (part >= 0
                   2124:       && (part >= ds->label[minor]->d_npartitions
                   2125:          || ds->label[minor]->d_partitions[part].p_size == 0))
                   2126:     {
                   2127:       err = D_NO_SUCH_DEVICE;
                   2128:       goto bad;
                   2129:     }
                   2130: 
                   2131:   /* Allocate and initialize device data.  */
                   2132:   bd = (struct block_data *) kalloc (sizeof (struct block_data));
                   2133:   if (! bd)
                   2134:     {
                   2135:       if (linux_device_open_trace)
                   2136:        printf ("device_open: at %d\n", __LINE__);
                   2137: 
                   2138:       err = D_NO_MEMORY;
                   2139:       goto bad;
                   2140:     }
                   2141:   bd->want = 0;
                   2142:   bd->open_count = 0;
                   2143:   bd->iocount = 0;
                   2144:   bd->part = part;
                   2145:   bd->ds = ds;
                   2146:   bd->device.emul_data = bd;
                   2147:   bd->device.emul_ops = &linux_block_emulation_ops;
                   2148:   bd->inode.i_rdev = dev;
                   2149:   bd->file.f_mode = file.f_mode;
                   2150:   bd->file.f_np = np;
                   2151:   bd->file.f_flags = file.f_flags;
                   2152:   bd->port = ipc_port_alloc_kernel ();
                   2153:   if (bd->port == IP_NULL)
                   2154:     {
                   2155:       if (linux_device_open_trace)
                   2156:        printf ("device_open: at %d\n", __LINE__);
                   2157: 
                   2158:       err = KERN_RESOURCE_SHORTAGE;
                   2159:       goto bad;
                   2160:     }
                   2161:   ipc_kobject_set (bd->port, (ipc_kobject_t) &bd->device, IKOT_DEVICE);
                   2162:   notify = ipc_port_make_sonce (bd->port);
                   2163:   ip_lock (bd->port);
                   2164:   ipc_port_nsrequest (bd->port, 1, notify, &notify);
                   2165:   assert (notify == IP_NULL);
                   2166: 
                   2167:   goto out;
                   2168: 
                   2169: bad:
                   2170:   if (ds->fops->release)
                   2171:     (*ds->fops->release) (&inode, &file);
                   2172: 
                   2173: out:
                   2174:   ds->busy = 0;
                   2175:   if (ds->want)
                   2176:     {
                   2177:       ds->want = 0;
                   2178:       thread_wakeup ((event_t) ds);
                   2179:     }
                   2180: 
                   2181:   if (bd && bd->open_count > 0)
                   2182:     {
                   2183:       if (err)
                   2184:        *devp = NULL;
                   2185:       else
                   2186:        {
                   2187:          *devp = &bd->device;
                   2188:          bd->open_count++;
                   2189:        }
                   2190:       return err;
                   2191:     }
                   2192: 
                   2193:   if (err)
                   2194:     {
                   2195:       if (bd)
                   2196:        {
                   2197:          if (bd->port != IP_NULL)
                   2198:            {
                   2199:              ipc_kobject_set (bd->port, IKO_NULL, IKOT_NONE);
                   2200:              ipc_port_dealloc_kernel (bd->port);
                   2201:            }
                   2202:          kfree ((vm_offset_t) bd, sizeof (struct block_data));
                   2203:          bd = NULL;
                   2204:        }
                   2205:     }
                   2206:   else
                   2207:     {
                   2208:       bd->open_count = 1;
                   2209:       bd->next = open_list;
                   2210:       open_list = bd;
                   2211:     }
                   2212: 
                   2213:   if (IP_VALID (reply_port))
                   2214:     ds_device_open_reply (reply_port, reply_port_type, err, dev_to_port (bd));
                   2215:   else if (! err)
                   2216:     device_close (bd);
                   2217: 
                   2218:   return MIG_NO_REPLY;
                   2219: }
                   2220: 
                   2221: static io_return_t
                   2222: device_close (void *d)
                   2223: {
                   2224:   struct block_data *bd = d, *bdp, **prev;
                   2225:   struct device_struct *ds = bd->ds;
                   2226: 
                   2227:   /* Wait for any other open/close to complete.  */
                   2228:   while (ds->busy)
                   2229:     {
                   2230:       ds->want = 1;
                   2231:       assert_wait ((event_t) ds, FALSE);
                   2232:       thread_block (0);
                   2233:     }
                   2234:   ds->busy = 1;
                   2235: 
                   2236:   if (--bd->open_count == 0)
                   2237:     {
                   2238:       /* Wait for pending I/O to complete.  */
                   2239:       while (bd->iocount > 0)
                   2240:        {
                   2241:          bd->want = 1;
                   2242:          assert_wait ((event_t) bd, FALSE);
                   2243:          thread_block (0);
                   2244:        }
                   2245: 
                   2246:       /* Remove device from open list.  */
                   2247:       prev = &open_list;
                   2248:       bdp = open_list;
                   2249:       while (bdp)
                   2250:        {
                   2251:          if (bdp == bd)
                   2252:            {
                   2253:              *prev = bdp->next;
                   2254:              break;
                   2255:            }
                   2256:          prev = &bdp->next;
                   2257:          bdp = bdp->next;
                   2258:        }
                   2259: 
                   2260:       assert (bdp == bd);
                   2261: 
                   2262:       if (ds->fops->release)
                   2263:        (*ds->fops->release) (&bd->inode, &bd->file);
                   2264: 
                   2265:       ipc_kobject_set (bd->port, IKO_NULL, IKOT_NONE);
                   2266:       ipc_port_dealloc_kernel (bd->port);
                   2267:       kfree ((vm_offset_t) bd, sizeof (struct block_data));
                   2268:     }
                   2269: 
                   2270:   ds->busy = 0;
                   2271:   if (ds->want)
                   2272:     {
                   2273:       ds->want = 0;
                   2274:       thread_wakeup ((event_t) ds);
                   2275:     }
                   2276:   return D_SUCCESS;
                   2277: }
                   2278: 
                   2279: /* XXX: Assumes all drivers use block_write.  */
                   2280: static io_return_t
                   2281: device_write (void *d, ipc_port_t reply_port,
                   2282:              mach_msg_type_name_t reply_port_type, dev_mode_t mode,
                   2283:              recnum_t bn, io_buf_ptr_t data, unsigned int count,
                   2284:              int *bytes_written)
                   2285: {
                   2286:   int major, minor;
                   2287:   unsigned sz, maxsz, off;
                   2288:   io_return_t err = 0;
                   2289:   struct block_data *bd = d;
                   2290: 
                   2291:   if (! bd->ds->fops->write)
                   2292:     {
                   2293:       printf ("device_write: at %d\n", __LINE__);
                   2294:       return D_INVALID_OPERATION;
                   2295:     }
                   2296: 
                   2297:   if ((int) count <= 0)
                   2298:     {
                   2299:       printf ("device_write: at %d\n", __LINE__);
                   2300:       return D_INVALID_SIZE;
                   2301:     }
                   2302: 
                   2303:   major = MAJOR (bd->inode.i_rdev);
                   2304:   minor = MINOR (bd->inode.i_rdev);
                   2305: 
                   2306:   if (disk_major (major))
                   2307:     {
                   2308:       assert (bd->ds->gd);
                   2309: 
                   2310:       if (bd->part >= 0)
                   2311:        {
                   2312:          struct disklabel *lp;
                   2313: 
                   2314:          assert (bd->ds->label);
                   2315:          lp = bd->ds->label[minor];
                   2316:          assert (lp);
                   2317:          maxsz = lp->d_partitions[bd->part].p_size;
                   2318:          off = (lp->d_partitions[bd->part].p_offset
                   2319:                 - bd->ds->gd->part[minor].start_sect);
                   2320: 
                   2321:          if (linux_block_write_trace)
                   2322:            printf ("device_write: at %d: dev %s, part %d, "
                   2323:                    "offset 0x%x (%u), start_sect 0x%x (%u), "
                   2324:                    "maxsz 0x%x (%u)\n",
                   2325:                    __LINE__,
                   2326:                    kdevname (bd->inode.i_rdev),
                   2327:                    bd->part,
                   2328:                    lp->d_partitions[bd->part].p_offset,
                   2329:                    lp->d_partitions[bd->part].p_offset,
                   2330:                    bd->ds->gd->part[minor].start_sect,
                   2331:                    bd->ds->gd->part[minor].start_sect,
                   2332:                    maxsz, maxsz);
                   2333: 
                   2334:          assert (off < bd->ds->gd->part[minor].nr_sects);
                   2335:        }
                   2336:       else
                   2337:        {
                   2338:          maxsz = bd->ds->gd->part[minor].nr_sects;
                   2339:          off = 0;
                   2340:        }
                   2341:     }
                   2342:   else
                   2343:     {
                   2344:       assert (blk_size[major]);
                   2345:       maxsz = blk_size[major][minor] << (BLOCK_SIZE_BITS - 9);
                   2346:       off = 0;
                   2347:     }
                   2348: 
                   2349:   if (bn >= maxsz)
                   2350:     {
                   2351:       if (linux_block_write_trace)
                   2352:        printf ("device_write: at %d\n", __LINE__);
                   2353: 
                   2354:       return D_INVALID_SIZE;
                   2355:     }
                   2356: 
                   2357:   bd->iocount++;
                   2358: 
                   2359:   sz = (count + 511) >> 9;
                   2360:   if (sz > maxsz - bn)
                   2361:     {
                   2362:       sz = maxsz - bn;
                   2363:       if (count > (sz << 9))
                   2364:        count = sz << 9;
                   2365:     }
                   2366: 
                   2367:   bd->file.f_pos = (loff_t) (bn + off) << 9;
                   2368: 
                   2369:   err = (*bd->ds->fops->write) (&bd->inode, &bd->file, (char *) data, count);
                   2370:   if (err)
                   2371:     err = linux_to_mach_error (err);
                   2372: 
                   2373:   if (linux_block_write_trace)
                   2374:     printf ("device_write: at %d: err %d\n", __LINE__, err);
                   2375: 
                   2376:   if (IP_VALID (reply_port))
                   2377:     ds_device_write_reply (reply_port, reply_port_type,
                   2378:                           err, count - bd->file.f_resid);
                   2379: 
                   2380:   if (--bd->iocount == 0 && bd->want)
                   2381:     {
                   2382:       bd->want = 0;
                   2383:       thread_wakeup ((event_t) bd);
                   2384:     }
                   2385:   return MIG_NO_REPLY;
                   2386: }
                   2387: 
                   2388: /* XXX: Assumes all drivers use block_read.  */
                   2389: static io_return_t
                   2390: device_read (void *d, ipc_port_t reply_port,
                   2391:             mach_msg_type_name_t reply_port_type, dev_mode_t mode,
                   2392:             recnum_t bn, int count, io_buf_ptr_t *data,
                   2393:             unsigned *bytes_read)
                   2394: {
                   2395:   int major, minor;
                   2396:   unsigned sz, maxsz, off;
                   2397:   io_return_t err = 0;
                   2398:   vm_offset_t addr;
                   2399:   vm_object_t object;
                   2400:   vm_map_copy_t copy;
                   2401:   struct block_data *bd = d;
                   2402:   struct inode *inode = &bd->inode;
                   2403: 
                   2404:   *data = 0;
                   2405:   *bytes_read = 0;
                   2406: 
                   2407:   if (! bd->ds->fops->read)
                   2408:     return D_INVALID_OPERATION;
                   2409: 
                   2410:   if (count <= 0)
                   2411:     return D_INVALID_SIZE;
                   2412: 
                   2413:   major = MAJOR (bd->inode.i_rdev);
                   2414:   minor = MINOR (bd->inode.i_rdev);
                   2415: 
                   2416:   if (LINUX_BLOCK_READ_TRACE)
                   2417:     printf ("device_read: at %d: major %d, minor %d, count %d, recnum %u\n",
                   2418:            __LINE__, major, minor, count, bn);
                   2419: 
                   2420:   if (disk_major (major))
                   2421:     {
                   2422:       assert (bd->ds->gd);
                   2423: 
                   2424:       if (bd->part >= 0)
                   2425:        {
                   2426:          struct disklabel *lp;
                   2427: 
                   2428:          assert (bd->ds->label);
                   2429:          lp = bd->ds->label[minor];
                   2430:          assert (lp);
                   2431:          maxsz = lp->d_partitions[bd->part].p_size;
                   2432:          off = (lp->d_partitions[bd->part].p_offset
                   2433:                 - bd->ds->gd->part[minor].start_sect);
                   2434: 
                   2435:          if (LINUX_BLOCK_READ_TRACE)
                   2436:            printf ("device_read: at %d: dev %s, part %d, offset 0x%x, "
                   2437:                    "size %d, start_sect 0x%x, nr_sects %d\n",
                   2438:                    __LINE__, kdevname (major), bd->part, off, maxsz,
                   2439:                    bd->ds->gd->part[minor].start_sect,
                   2440:                    bd->ds->gd->part[minor].nr_sects);
                   2441: 
                   2442:          assert (off < bd->ds->gd->part[minor].nr_sects);
                   2443:        }
                   2444:       else
                   2445:        {
                   2446:          maxsz = bd->ds->gd->part[minor].nr_sects;
                   2447:          off = 0;
                   2448:        }
                   2449:     }
                   2450:   else
                   2451:     {
                   2452:       assert (blk_size[major]);
                   2453:       maxsz = blk_size[major][minor] << (BLOCK_SIZE_BITS - 9);
                   2454:       off = 0;
                   2455:     }
                   2456: 
                   2457:   if (bn > maxsz)
                   2458:     return D_INVALID_SIZE;
                   2459: 
                   2460:   /* Be backward compatible with Unix.  */
                   2461:   if (bn == maxsz)
                   2462:     {
                   2463:       if (LINUX_BLOCK_READ_TRACE)
                   2464:        printf ("device_read: at %d\n", __LINE__);
                   2465:       return 0;
                   2466:     }
                   2467: 
                   2468:   sz = (count + 511) >> 9;
                   2469:   if (sz > maxsz - bn)
                   2470:     {
                   2471:       sz = maxsz - bn;
                   2472:       if (count > (sz << 9))
                   2473:        count = sz << 9;
                   2474:     }
                   2475: 
                   2476:   bd->file.f_pos = (loff_t) (bn + off) << 9;
                   2477:   bd->file.f_object = NULL;
                   2478: 
                   2479:   if (LINUX_BLOCK_READ_TRACE)
                   2480:     printf ("device_read: at %d: f_pos 0x%x\n",
                   2481:            __LINE__, (unsigned) bd->file.f_pos);
                   2482: 
                   2483:   bd->iocount++;
                   2484: 
                   2485:   err = (*bd->ds->fops->read) (&bd->inode, &bd->file, (char *) data, count);
                   2486:   if (err)
                   2487:     err = linux_to_mach_error (err);
                   2488:   else
                   2489:     {
                   2490:       object = bd->file.f_object;
                   2491:       assert (object);
                   2492:       assert (object->ref_count == 1);
                   2493:       err = vm_map_copyin_object (object, 0, round_page (count), &copy);
                   2494:       assert (object->ref_count == 1);
                   2495:       if (err)
                   2496:        vm_object_deallocate (object);
                   2497:       else
                   2498:        {
                   2499:          assert (copy->cpy_object->ref_count == 1);
                   2500:          *data = (io_buf_ptr_t) copy;
                   2501:          *bytes_read = count - bd->file.f_resid;
                   2502:        }
                   2503:     }
                   2504:   if (--bd->iocount == 0 && bd->want)
                   2505:     {
                   2506:       bd->want = 0;
                   2507:       thread_wakeup ((event_t) bd);
                   2508:     }
                   2509:   return err;
                   2510: }
                   2511: 
                   2512: static io_return_t
                   2513: device_get_status (void *d, dev_flavor_t flavor, dev_status_t status,
                   2514:                   mach_msg_type_number_t *status_count)
                   2515: {
                   2516:   struct block_data *bd = d;
                   2517: 
                   2518:   switch (flavor)
                   2519:     {
                   2520:     case DEV_GET_SIZE:
                   2521:       if (*status_count != DEV_GET_SIZE_COUNT)
                   2522:        return D_INVALID_SIZE;
                   2523:       if (disk_major (MAJOR (bd->inode.i_rdev)))
                   2524:        {
                   2525:          assert (bd->ds->gd);
                   2526: 
                   2527:          if (bd->part >= 0)
                   2528:            {
                   2529:              struct disklabel *lp;
                   2530: 
                   2531:              assert (bd->ds->label);
                   2532:              lp = bd->ds->label[MINOR (bd->inode.i_rdev)];
                   2533:              assert (lp);
                   2534:              (status[DEV_GET_SIZE_DEVICE_SIZE]
                   2535:               = lp->d_partitions[bd->part].p_size << 9);
                   2536:            }
                   2537:          else
                   2538:            (status[DEV_GET_SIZE_DEVICE_SIZE]
                   2539:             = bd->ds->gd->part[MINOR (bd->inode.i_rdev)].nr_sects << 9);
                   2540:        }
                   2541:       else
                   2542:        {
                   2543:          assert (blk_size[MAJOR (bd->inode.i_rdev)]);
                   2544:          (status[DEV_GET_SIZE_DEVICE_SIZE]
                   2545:           = (blk_size[MAJOR (bd->inode.i_rdev)][MINOR (bd->inode.i_rdev)]
                   2546:              << BLOCK_SIZE_BITS));
                   2547:        }
                   2548:       /* It would be nice to return the block size as reported by
                   2549:         the driver, but a lot of user level code assumes the sector
                   2550:         size to be 512.  */
                   2551:       status[DEV_GET_SIZE_RECORD_SIZE] = 512;
                   2552:       break;
                   2553: 
                   2554:     default:
                   2555:       return D_INVALID_OPERATION;
                   2556:     }
                   2557: 
                   2558:   return D_SUCCESS;
                   2559: }
                   2560: 
                   2561: struct device_emulation_ops linux_block_emulation_ops =
                   2562: {
                   2563:   NULL,
                   2564:   NULL,
                   2565:   dev_to_port,
                   2566:   device_open,
                   2567:   device_close,
                   2568:   device_write,
                   2569:   NULL,
                   2570:   device_read,
                   2571:   NULL,
                   2572:   NULL,
                   2573:   device_get_status,
                   2574:   NULL,
                   2575:   NULL,
                   2576:   NULL,
                   2577:   NULL,
                   2578:   NULL
                   2579: };

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.