📄 linit.c
字号:
* aac_driverinfo - Returns the host adapter name * @host_ptr: Scsi host to report on * * Returns a static string describing the device in question */const char *aac_driverinfo(struct Scsi_Host *host_ptr){ struct aac_dev *dev = (struct aac_dev *)host_ptr->hostdata; return aac_drivers[dev->cardtype].name;}/** * aac_get_driver_ident * @devtype: index into lookup table * * Returns a pointer to the entry in the driver lookup table. */struct aac_driver_ident* aac_get_driver_ident(int devtype){ return &aac_drivers[devtype];}/** * aac_biosparm - return BIOS parameters for disk * @disk: SCSI disk object to process * @device: kdev_t of the disk in question * @geom: geometry block to fill in * * Return the Heads/Sectors/Cylinders BIOS Disk Parameters for Disk. * The default disk geometry is 64 heads, 32 sectors, and the appropriate * number of cylinders so as not to exceed drive capacity. In order for * disks equal to or larger than 1 GB to be addressable by the BIOS * without exceeding the BIOS limitation of 1024 cylinders, Extended * Translation should be enabled. With Extended Translation enabled, * drives between 1 GB inclusive and 2 GB exclusive are given a disk * geometry of 128 heads and 32 sectors, and drives above 2 GB inclusive * are given a disk geometry of 255 heads and 63 sectors. However, if * the BIOS detects that the Extended Translation setting does not match * the geometry in the partition table, then the translation inferred * from the partition table will be used by the BIOS, and a warning may * be displayed. */ static int aac_biosparm(Scsi_Disk *disk, kdev_t dev, int *geom){ struct diskparm *param = (struct diskparm *)geom; struct buffer_head * buf; dprintk((KERN_DEBUG "aac_biosparm.\n")); /* * Assuming extended translation is enabled - #REVISIT# */ if( disk->capacity >= 2 * 1024 * 1024 ) /* 1 GB in 512 byte sectors */ { if( disk->capacity >= 4 * 1024 * 1024 ) /* 2 GB in 512 byte sectors */ { param->heads = 255; param->sectors = 63; } else { param->heads = 128; param->sectors = 32; } } else { param->heads = 64; param->sectors = 32; } param->cylinders = disk->capacity/(param->heads * param->sectors); /* * Read the first 1024 bytes from the disk device */ buf = bread(MKDEV(MAJOR(dev), MINOR(dev)&~0xf), 0, block_size(dev)); if(buf == NULL) return 0; /* * If the boot sector partition table is valid, search for a partition * table entry whose end_head matches one of the standard geometry * translations ( 64/32, 128/32, 255/63 ). */ if(*(unsigned short *)(buf->b_data + 0x1fe) == cpu_to_le16(0xaa55)) { struct partition *first = (struct partition * )(buf->b_data + 0x1be); struct partition *entry = first; int saved_cylinders = param->cylinders; int num; unsigned char end_head, end_sec; for(num = 0; num < 4; num++) { end_head = entry->end_head; end_sec = entry->end_sector & 0x3f; if(end_head == 63) { param->heads = 64; param->sectors = 32; break; } else if(end_head == 127) { param->heads = 128; param->sectors = 32; break; } else if(end_head == 254) { param->heads = 255; param->sectors = 63; break; } entry++; } if(num == 4) { end_head = first->end_head; end_sec = first->end_sector & 0x3f; } param->cylinders = disk->capacity / (param->heads * param->sectors); if(num < 4 && end_sec == param->sectors) { if(param->cylinders != saved_cylinders) dprintk((KERN_DEBUG "Adopting geometry: heads=%d, sectors=%d from partition table %d.\n", param->heads, param->sectors, num)); } else if(end_head > 0 || end_sec > 0) { dprintk((KERN_DEBUG "Strange geometry: heads=%d, sectors=%d in partition table %d.\n", end_head + 1, end_sec, num)); dprintk((KERN_DEBUG "Using geometry: heads=%d, sectors=%d.\n", param->heads, param->sectors)); } } brelse(buf); return 0;}/** * aac_queuedepth - compute queue depths * @host: SCSI host in question * @dev: SCSI device we are considering * * Selects queue depths for each target device based on the host adapter's * total capacity and the queue depth supported by the target device. * A queue depth of one automatically disables tagged queueing. */static void aac_queuedepth(struct Scsi_Host * host, Scsi_Device * dev ){ Scsi_Device * dptr; dprintk((KERN_DEBUG "aac_queuedepth.\n")); dprintk((KERN_DEBUG "Device # Q Depth Online\n")); dprintk((KERN_DEBUG "---------------------------\n")); for(dptr = dev; dptr != NULL; dptr = dptr->next) { if(dptr->host == host) { dptr->queue_depth = 10; dprintk((KERN_DEBUG " %2d %d %d\n", dptr->id, dptr->queue_depth, dptr->online)); } }}/** * aac_eh_abort - Abort command if possible. * @cmd: SCSI command block to abort * * Called when the midlayer wishes to abort a command. We don't support * this facility, and our firmware looks after life for us. We just * report this as failing */ static int aac_eh_abort(Scsi_Cmnd *cmd){ return FAILED;}/** * aac_eh_device_reset - Reset command handling * @cmd: SCSI command block causing the reset * * Issue a reset of a SCSI device. We are ourselves not truely a SCSI * controller and our firmware will do the work for us anyway. Thus this * is a no-op. We just return FAILED. */static int aac_eh_device_reset(Scsi_Cmnd *cmd){ return FAILED;}/** * aac_eh_bus_reset - Reset command handling * @scsi_cmd: SCSI command block causing the reset * * Issue a reset of a SCSI bus. We are ourselves not truely a SCSI * controller and our firmware will do the work for us anyway. Thus this * is a no-op. We just return FAILED. */static int aac_eh_bus_reset(Scsi_Cmnd* cmd){ return FAILED;}/** * aac_eh_hba_reset - Reset command handling * @scsi_cmd: SCSI command block causing the reset * * Issue a reset of a SCSI host. If things get this bad then arguably we should * go take a look at what the host adapter is doing and see if something really * broke (as can occur at least on my Dell QC card if a drive keeps failing spinup) */static int aac_eh_reset(Scsi_Cmnd* cmd){ printk(KERN_ERR "aacraid: Host adapter reset request. SCSI hang ?\n"); return FAILED;}/** * aac_ioctl - Handle SCSI ioctls * @scsi_dev_ptr: scsi device to operate upon * @cmd: ioctl command to use issue * @arg: ioctl data pointer * * Issue an ioctl on an aacraid device. Returns a standard unix error code or * zero for success */ static int aac_ioctl(Scsi_Device * scsi_dev_ptr, int cmd, void * arg){ struct aac_dev *dev; dprintk((KERN_DEBUG "aac_ioctl.\n")); dev = (struct aac_dev *)scsi_dev_ptr->host->hostdata; return aac_do_ioctl(dev, cmd, arg);}/** * aac_cfg_open - open a configuration file * @inode: inode being opened * @file: file handle attached * * Called when the configuration device is opened. Does the needed * set up on the handle and then returns * * Bugs: This needs extending to check a given adapter is present * so we can support hot plugging, and to ref count adapters. */static int aac_cfg_open(struct inode * inode, struct file * file ){ unsigned minor_number = MINOR(inode->i_rdev); if(minor_number >= aac_count) return -ENODEV; return 0;}/** * aac_cfg_release - close down an AAC config device * @inode: inode of configuration file * @file: file handle of configuration file * * Called when the last close of the configuration file handle * is performed. */ static int aac_cfg_release(struct inode * inode, struct file * file ){ return 0;}/** * aac_cfg_ioctl - AAC configuration request * @inode: inode of device * @file: file handle * @cmd: ioctl command code * @arg: argument * * Handles a configuration ioctl. Currently this involves wrapping it * up and feeding it into the nasty windowsalike glue layer. * * Bugs: Needs locking against parallel ioctls lower down * Bugs: Needs to handle hot plugging */ static int aac_cfg_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg ){ struct aac_dev *dev = aac_devices[MINOR(inode->i_rdev)]; return aac_do_ioctl(dev, cmd, (void *)arg);}/* * To use the low level SCSI driver support using the linux kernel loadable * module interface we should initialize the global variable driver_interface * (datatype Scsi_Host_Template) and then include the file scsi_module.c. */ static Scsi_Host_Template driver_template = { module: THIS_MODULE, name: "AAC", proc_info: aac_procinfo, detect: aac_detect, release: aac_release, info: aac_driverinfo, ioctl: aac_ioctl, queuecommand: aac_queuecommand, bios_param: aac_biosparm, can_queue: AAC_NUM_IO_FIB, this_id: 16, sg_tablesize: 16, max_sectors: 128, cmd_per_lun: AAC_NUM_IO_FIB, eh_abort_handler: aac_eh_abort, eh_device_reset_handler:aac_eh_device_reset, eh_bus_reset_handler: aac_eh_bus_reset, eh_host_reset_handler: aac_eh_reset, use_new_eh_code: 1, use_clustering: ENABLE_CLUSTERING,};#include "scsi_module.c"/** * aac_procinfo - Implement /proc/scsi/<drivername>/<n> * @proc_buffer: memory buffer for I/O * @start_ptr: pointer to first valid data * @offset: offset into file * @bytes_available: space left * @host_no: scsi host ident * @write: direction of I/O * * Used to export driver statistics and other infos to the world outside * the kernel using the proc file system. Also provides an interface to * feed the driver with information. * * For reads * - if offset > 0 return 0 * - if offset == 0 write data to proc_buffer and set the start_ptr to * beginning of proc_buffer, return the number of characters written. * For writes * - writes currently not supported, return 0 * * Bugs: Only offset zero is handled */static int aac_procinfo(char *proc_buffer, char **start_ptr,off_t offset, int bytes_available, int host_no, int write){ if(write || offset > 0) return 0; *start_ptr = proc_buffer; return sprintf(proc_buffer, "%s %d\n", "Raid Controller, scsi hba number", host_no);}EXPORT_NO_SYMBOLS;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -