📄 i2o_block.c
字号:
* delayed_request: the delayed request with the queue to start * * If the request queue is stopped for a disk, and there is no open * request, a new event is created, which calls this function to start * the queue after I2O_BLOCK_REQUEST_TIME. Otherwise the queue will never * be started again. */static void i2o_block_delayed_request_fn(void *delayed_request){ struct i2o_block_delayed_request *dreq = delayed_request; struct request_queue *q = dreq->queue; unsigned long flags; spin_lock_irqsave(q->queue_lock, flags); blk_start_queue(q); spin_unlock_irqrestore(q->queue_lock, flags); kfree(dreq);};/** * i2o_block_end_request - Post-processing of completed commands * @req: request which should be completed * @uptodate: 1 for success, 0 for I/O error, < 0 for specific error * @nr_bytes: number of bytes to complete * * Mark the request as complete. The lock must not be held when entering. * */static void i2o_block_end_request(struct request *req, int uptodate, int nr_bytes){ struct i2o_block_request *ireq = req->special; struct i2o_block_device *dev = ireq->i2o_blk_dev; request_queue_t *q = req->q; unsigned long flags; if (end_that_request_chunk(req, uptodate, nr_bytes)) { int leftover = (req->hard_nr_sectors << KERNEL_SECTOR_SHIFT); if (blk_pc_request(req)) leftover = req->data_len; if (end_io_error(uptodate)) end_that_request_chunk(req, 0, leftover); } add_disk_randomness(req->rq_disk); spin_lock_irqsave(q->queue_lock, flags); end_that_request_last(req); if (likely(dev)) { dev->open_queue_depth--; list_del(&ireq->queue); } blk_start_queue(q); spin_unlock_irqrestore(q->queue_lock, flags); i2o_block_sglist_free(ireq); i2o_block_request_free(ireq);};/** * i2o_block_reply - Block OSM reply handler. * @c: I2O controller from which the message arrives * @m: message id of reply * qmsg: the actuall I2O message reply * * This function gets all the message replies. * */static int i2o_block_reply(struct i2o_controller *c, u32 m, struct i2o_message *msg){ struct request *req; int uptodate = 1; req = i2o_cntxt_list_get(c, le32_to_cpu(msg->u.s.tcntxt)); if (unlikely(!req)) { osm_err("NULL reply received!\n"); return -1; } /* * Lets see what is cooking. We stuffed the * request in the context. */ if ((le32_to_cpu(msg->body[0]) >> 24) != 0) { u32 status = le32_to_cpu(msg->body[0]); /* * Device not ready means two things. One is that the * the thing went offline (but not a removal media) * * The second is that you have a SuperTrak 100 and the * firmware got constipated. Unlike standard i2o card * setups the supertrak returns an error rather than * blocking for the timeout in these cases. * * Don't stick a supertrak100 into cache aggressive modes */ osm_err("TID %03x error status: 0x%02x, detailed status: " "0x%04x\n", (le32_to_cpu(msg->u.head[1]) >> 12 & 0xfff), status >> 24, status & 0xffff); req->errors++; uptodate = 0; } i2o_block_end_request(req, uptodate, le32_to_cpu(msg->body[1])); return 1;};static void i2o_block_event(struct i2o_event *evt){ osm_debug("event received\n"); kfree(evt);};/* * SCSI-CAM for ioctl geometry mapping * Duplicated with SCSI - this should be moved into somewhere common * perhaps genhd ? * * LBA -> CHS mapping table taken from: * * "Incorporating the I2O Architecture into BIOS for Intel Architecture * Platforms" * * This is an I2O document that is only available to I2O members, * not developers. * * From my understanding, this is how all the I2O cards do this * * Disk Size | Sectors | Heads | Cylinders * ---------------+---------+-------+------------------- * 1 < X <= 528M | 63 | 16 | X/(63 * 16 * 512) * 528M < X <= 1G | 63 | 32 | X/(63 * 32 * 512) * 1 < X <528M | 63 | 16 | X/(63 * 16 * 512) * 1 < X <528M | 63 | 16 | X/(63 * 16 * 512) * */#define BLOCK_SIZE_528M 1081344#define BLOCK_SIZE_1G 2097152#define BLOCK_SIZE_21G 4403200#define BLOCK_SIZE_42G 8806400#define BLOCK_SIZE_84G 17612800static void i2o_block_biosparam(unsigned long capacity, unsigned short *cyls, unsigned char *hds, unsigned char *secs){ unsigned long heads, sectors, cylinders; sectors = 63L; /* Maximize sectors per track */ if (capacity <= BLOCK_SIZE_528M) heads = 16; else if (capacity <= BLOCK_SIZE_1G) heads = 32; else if (capacity <= BLOCK_SIZE_21G) heads = 64; else if (capacity <= BLOCK_SIZE_42G) heads = 128; else heads = 255; cylinders = (unsigned long)capacity / (heads * sectors); *cyls = (unsigned short)cylinders; /* Stuff return values */ *secs = (unsigned char)sectors; *hds = (unsigned char)heads;}/** * i2o_block_open - Open the block device * * Power up the device, mount and lock the media. This function is called, * if the block device is opened for access. * * Returns 0 on success or negative error code on failure. */static int i2o_block_open(struct inode *inode, struct file *file){ struct i2o_block_device *dev = inode->i_bdev->bd_disk->private_data; if (!dev->i2o_dev) return -ENODEV; if (dev->power > 0x1f) i2o_block_device_power(dev, 0x02); i2o_block_device_mount(dev->i2o_dev, -1); i2o_block_device_lock(dev->i2o_dev, -1); osm_debug("Ready.\n"); return 0;};/** * i2o_block_release - Release the I2O block device * * Unlock and unmount the media, and power down the device. Gets called if * the block device is closed. * * Returns 0 on success or negative error code on failure. */static int i2o_block_release(struct inode *inode, struct file *file){ struct gendisk *disk = inode->i_bdev->bd_disk; struct i2o_block_device *dev = disk->private_data; u8 operation; /* * This is to deail with the case of an application * opening a device and then the device dissapears while * it's in use, and then the application tries to release * it. ex: Unmounting a deleted RAID volume at reboot. * If we send messages, it will just cause FAILs since * the TID no longer exists. */ if (!dev->i2o_dev) return 0; i2o_block_device_flush(dev->i2o_dev); i2o_block_device_unlock(dev->i2o_dev, -1); if (dev->flags & (1 << 3 | 1 << 4)) /* Removable */ operation = 0x21; else operation = 0x24; i2o_block_device_power(dev, operation); return 0;}/** * i2o_block_ioctl - Issue device specific ioctl calls. * @cmd: ioctl command * @arg: arg * * Handles ioctl request for the block device. * * Return 0 on success or negative error on failure. */static int i2o_block_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ struct gendisk *disk = inode->i_bdev->bd_disk; struct i2o_block_device *dev = disk->private_data; void __user *argp = (void __user *)arg; /* Anyone capable of this syscall can do *real bad* things */ if (!capable(CAP_SYS_ADMIN)) return -EPERM; switch (cmd) { case HDIO_GETGEO: { struct hd_geometry g; i2o_block_biosparam(get_capacity(disk), &g.cylinders, &g.heads, &g.sectors); g.start = get_start_sect(inode->i_bdev); return copy_to_user(argp, &g, sizeof(g)) ? -EFAULT : 0; } case BLKI2OGRSTRAT: return put_user(dev->rcache, (int __user *)arg); case BLKI2OGWSTRAT: return put_user(dev->wcache, (int __user *)arg); case BLKI2OSRSTRAT: if (arg < 0 || arg > CACHE_SMARTFETCH) return -EINVAL; dev->rcache = arg; break; case BLKI2OSWSTRAT: if (arg != 0 && (arg < CACHE_WRITETHROUGH || arg > CACHE_SMARTBACK)) return -EINVAL; dev->wcache = arg; break; } return -ENOTTY;};/** * i2o_block_media_changed - Have we seen a media change? * @disk: gendisk which should be verified * * Verifies if the media has changed. * * Returns 1 if the media was changed or 0 otherwise. */static int i2o_block_media_changed(struct gendisk *disk){ struct i2o_block_device *p = disk->private_data; if (p->media_change_flag) { p->media_change_flag = 0; return 1; } return 0;}/** * i2o_block_transfer - Transfer a request to/from the I2O controller * @req: the request which should be transfered * * This function converts the request into a I2O message. The necessary * DMA buffers are allocated and after everything is setup post the message * to the I2O controller. No cleanup is done by this function. It is done * on the interrupt side when the reply arrives. * * Return 0 on success or negative error code on failure. */static int i2o_block_transfer(struct request *req){ struct i2o_block_device *dev = req->rq_disk->private_data; struct i2o_controller *c; int tid = dev->i2o_dev->lct_data.tid; struct i2o_message __iomem *msg; u32 __iomem *mptr; struct i2o_block_request *ireq = req->special; u32 m; u32 tcntxt; u32 sgl_offset = SGL_OFFSET_8; u32 ctl_flags = 0x00000000; int rc; u32 cmd; if (unlikely(!dev->i2o_dev)) { osm_err("transfer to removed drive\n"); rc = -ENODEV; goto exit; } c = dev->i2o_dev->iop; m = i2o_msg_get(c, &msg); if (m == I2O_QUEUE_EMPTY) { rc = -EBUSY; goto exit; } tcntxt = i2o_cntxt_list_add(c, req); if (!tcntxt) { rc = -ENOMEM; goto nop_msg; } writel(i2o_block_driver.context, &msg->u.s.icntxt); writel(tcntxt, &msg->u.s.tcntxt); mptr = &msg->body[0]; if (rq_data_dir(req) == READ) { cmd = I2O_CMD_BLOCK_READ << 24; switch (dev->rcache) { case CACHE_PREFETCH: ctl_flags = 0x201F0008; break; case CACHE_SMARTFETCH: if (req->nr_sectors > 16) ctl_flags = 0x201F0008; else ctl_flags = 0x001F0000; break; default: break; } } else { cmd = I2O_CMD_BLOCK_WRITE << 24; switch (dev->wcache) { case CACHE_WRITETHROUGH: ctl_flags = 0x001F0008; break; case CACHE_WRITEBACK: ctl_flags = 0x001F0010; break; case CACHE_SMARTBACK: if (req->nr_sectors > 16) ctl_flags = 0x001F0004; else ctl_flags = 0x001F0010; break; case CACHE_SMARTTHROUGH: if (req->nr_sectors > 16) ctl_flags = 0x001F0004; else ctl_flags = 0x001F0010; default: break; } }#ifdef CONFIG_I2O_EXT_ADAPTEC if (c->adaptec) { u8 cmd[10]; u32 scsi_flags; u16 hwsec = queue_hardsect_size(req->q) >> KERNEL_SECTOR_SHIFT; memset(cmd, 0, 10); sgl_offset = SGL_OFFSET_12;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -