aachba.c
来自「linux 内核源代码」· C语言 代码 · 共 2,197 行 · 第 1/5 页
C
2,197 行
/* * Check that the command queued to the controller */ if (status == -EINPROGRESS) { scsicmd->SCp.phase = AAC_OWNER_FIRMWARE; return 0; } printk(KERN_WARNING "aac_get_container_name: aac_fib_send failed with status: %d.\n", status); aac_fib_complete(cmd_fibcontext); aac_fib_free(cmd_fibcontext); return -1;}static int aac_probe_container_callback2(struct scsi_cmnd * scsicmd){ struct fsa_dev_info *fsa_dev_ptr = ((struct aac_dev *)(scsicmd->device->host->hostdata))->fsa_dev; if ((fsa_dev_ptr[scmd_id(scsicmd)].valid & 1)) return aac_scsi_cmd(scsicmd); scsicmd->result = DID_NO_CONNECT << 16; scsicmd->scsi_done(scsicmd); return 0;}static void _aac_probe_container2(void * context, struct fib * fibptr){ struct fsa_dev_info *fsa_dev_ptr; int (*callback)(struct scsi_cmnd *); struct scsi_cmnd * scsicmd = (struct scsi_cmnd *)context; if (!aac_valid_context(scsicmd, fibptr)) return; scsicmd->SCp.Status = 0; fsa_dev_ptr = fibptr->dev->fsa_dev; if (fsa_dev_ptr) { struct aac_mount * dresp = (struct aac_mount *) fib_data(fibptr); fsa_dev_ptr += scmd_id(scsicmd); if ((le32_to_cpu(dresp->status) == ST_OK) && (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) && (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) { fsa_dev_ptr->valid = 1; fsa_dev_ptr->type = le32_to_cpu(dresp->mnt[0].vol); fsa_dev_ptr->size = ((u64)le32_to_cpu(dresp->mnt[0].capacity)) + (((u64)le32_to_cpu(dresp->mnt[0].capacityhigh)) << 32); fsa_dev_ptr->ro = ((le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY) != 0); } if ((fsa_dev_ptr->valid & 1) == 0) fsa_dev_ptr->valid = 0; scsicmd->SCp.Status = le32_to_cpu(dresp->count); } aac_fib_complete(fibptr); aac_fib_free(fibptr); callback = (int (*)(struct scsi_cmnd *))(scsicmd->SCp.ptr); scsicmd->SCp.ptr = NULL; (*callback)(scsicmd); return;}static void _aac_probe_container1(void * context, struct fib * fibptr){ struct scsi_cmnd * scsicmd; struct aac_mount * dresp; struct aac_query_mount *dinfo; int status; dresp = (struct aac_mount *) fib_data(fibptr); dresp->mnt[0].capacityhigh = 0; if ((le32_to_cpu(dresp->status) != ST_OK) || (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE)) { _aac_probe_container2(context, fibptr); return; } scsicmd = (struct scsi_cmnd *) context; if (!aac_valid_context(scsicmd, fibptr)) return; aac_fib_init(fibptr); dinfo = (struct aac_query_mount *)fib_data(fibptr); dinfo->command = cpu_to_le32(VM_NameServe64); dinfo->count = cpu_to_le32(scmd_id(scsicmd)); dinfo->type = cpu_to_le32(FT_FILESYS); status = aac_fib_send(ContainerCommand, fibptr, sizeof(struct aac_query_mount), FsaNormal, 0, 1, _aac_probe_container2, (void *) scsicmd); /* * Check that the command queued to the controller */ if (status == -EINPROGRESS) scsicmd->SCp.phase = AAC_OWNER_FIRMWARE; else if (status < 0) { /* Inherit results from VM_NameServe, if any */ dresp->status = cpu_to_le32(ST_OK); _aac_probe_container2(context, fibptr); }}static int _aac_probe_container(struct scsi_cmnd * scsicmd, int (*callback)(struct scsi_cmnd *)){ struct fib * fibptr; int status = -ENOMEM; if ((fibptr = aac_fib_alloc((struct aac_dev *)scsicmd->device->host->hostdata))) { struct aac_query_mount *dinfo; aac_fib_init(fibptr); dinfo = (struct aac_query_mount *)fib_data(fibptr); dinfo->command = cpu_to_le32(VM_NameServe); dinfo->count = cpu_to_le32(scmd_id(scsicmd)); dinfo->type = cpu_to_le32(FT_FILESYS); scsicmd->SCp.ptr = (char *)callback; status = aac_fib_send(ContainerCommand, fibptr, sizeof(struct aac_query_mount), FsaNormal, 0, 1, _aac_probe_container1, (void *) scsicmd); /* * Check that the command queued to the controller */ if (status == -EINPROGRESS) { scsicmd->SCp.phase = AAC_OWNER_FIRMWARE; return 0; } if (status < 0) { scsicmd->SCp.ptr = NULL; aac_fib_complete(fibptr); aac_fib_free(fibptr); } } if (status < 0) { struct fsa_dev_info *fsa_dev_ptr = ((struct aac_dev *)(scsicmd->device->host->hostdata))->fsa_dev; if (fsa_dev_ptr) { fsa_dev_ptr += scmd_id(scsicmd); if ((fsa_dev_ptr->valid & 1) == 0) { fsa_dev_ptr->valid = 0; return (*callback)(scsicmd); } } } return status;}/** * aac_probe_container - query a logical volume * @dev: device to query * @cid: container identifier * * Queries the controller about the given volume. The volume information * is updated in the struct fsa_dev_info structure rather than returned. */static int aac_probe_container_callback1(struct scsi_cmnd * scsicmd){ scsicmd->device = NULL; return 0;}int aac_probe_container(struct aac_dev *dev, int cid){ struct scsi_cmnd *scsicmd = kmalloc(sizeof(*scsicmd), GFP_KERNEL); struct scsi_device *scsidev = kmalloc(sizeof(*scsidev), GFP_KERNEL); int status; if (!scsicmd || !scsidev) { kfree(scsicmd); kfree(scsidev); return -ENOMEM; } scsicmd->list.next = NULL; scsicmd->scsi_done = (void (*)(struct scsi_cmnd*))aac_probe_container_callback1; scsicmd->device = scsidev; scsidev->sdev_state = 0; scsidev->id = cid; scsidev->host = dev->scsi_host_ptr; if (_aac_probe_container(scsicmd, aac_probe_container_callback1) == 0) while (scsicmd->device == scsidev) schedule(); kfree(scsidev); status = scsicmd->SCp.Status; kfree(scsicmd); return status;}/* Local Structure to set SCSI inquiry data strings */struct scsi_inq { char vid[8]; /* Vendor ID */ char pid[16]; /* Product ID */ char prl[4]; /* Product Revision Level */};/** * InqStrCopy - string merge * @a: string to copy from * @b: string to copy to * * Copy a String from one location to another * without copying \0 */static void inqstrcpy(char *a, char *b){ while(*a != (char)0) *b++ = *a++;}static char *container_types[] = { "None", "Volume", "Mirror", "Stripe", "RAID5", "SSRW", "SSRO", "Morph", "Legacy", "RAID4", "RAID10", "RAID00", "V-MIRRORS", "PSEUDO R4", "RAID50", "RAID5D", "RAID5D0", "RAID1E", "RAID6", "RAID60", "Unknown"};/* Function: setinqstr * * Arguments: [1] pointer to void [1] int * * Purpose: Sets SCSI inquiry data strings for vendor, product * and revision level. Allows strings to be set in platform dependant * files instead of in OS dependant driver source. */static void setinqstr(struct aac_dev *dev, void *data, int tindex){ struct scsi_inq *str; str = (struct scsi_inq *)(data); /* cast data to scsi inq block */ memset(str, ' ', sizeof(*str)); if (dev->supplement_adapter_info.AdapterTypeText[0]) { char * cp = dev->supplement_adapter_info.AdapterTypeText; int c = sizeof(str->vid); while (*cp && *cp != ' ' && --c) ++cp; c = *cp; *cp = '\0'; inqstrcpy (dev->supplement_adapter_info.AdapterTypeText, str->vid); *cp = c; while (*cp && *cp != ' ') ++cp; while (*cp == ' ') ++cp; /* last six chars reserved for vol type */ c = 0; if (strlen(cp) > sizeof(str->pid)) { c = cp[sizeof(str->pid)]; cp[sizeof(str->pid)] = '\0'; } inqstrcpy (cp, str->pid); if (c) cp[sizeof(str->pid)] = c; } else { struct aac_driver_ident *mp = aac_get_driver_ident(dev->cardtype); inqstrcpy (mp->vname, str->vid); /* last six chars reserved for vol type */ inqstrcpy (mp->model, str->pid); } if (tindex < ARRAY_SIZE(container_types)){ char *findit = str->pid; for ( ; *findit != ' '; findit++); /* walk till we find a space */ /* RAID is superfluous in the context of a RAID device */ if (memcmp(findit-4, "RAID", 4) == 0) *(findit -= 4) = ' '; if (((findit - str->pid) + strlen(container_types[tindex])) < (sizeof(str->pid) + sizeof(str->prl))) inqstrcpy (container_types[tindex], findit + 1); } inqstrcpy ("V1.0", str->prl);}static void get_container_serial_callback(void *context, struct fib * fibptr){ struct aac_get_serial_resp * get_serial_reply; struct scsi_cmnd * scsicmd; BUG_ON(fibptr == NULL); scsicmd = (struct scsi_cmnd *) context; if (!aac_valid_context(scsicmd, fibptr)) return; get_serial_reply = (struct aac_get_serial_resp *) fib_data(fibptr); /* Failure is irrelevant, using default value instead */ if (le32_to_cpu(get_serial_reply->status) == CT_OK) { char sp[13]; /* EVPD bit set */ sp[0] = INQD_PDT_DA; sp[1] = scsicmd->cmnd[2]; sp[2] = 0; sp[3] = snprintf(sp+4, sizeof(sp)-4, "%08X", le32_to_cpu(get_serial_reply->uid)); aac_internal_transfer(scsicmd, sp, 0, sizeof(sp)); } scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; aac_fib_complete(fibptr); aac_fib_free(fibptr); scsicmd->scsi_done(scsicmd);}/** * aac_get_container_serial - get container serial, none blocking. */static int aac_get_container_serial(struct scsi_cmnd * scsicmd){ int status; struct aac_get_serial *dinfo; struct fib * cmd_fibcontext; struct aac_dev * dev; dev = (struct aac_dev *)scsicmd->device->host->hostdata; if (!(cmd_fibcontext = aac_fib_alloc(dev))) return -ENOMEM; aac_fib_init(cmd_fibcontext); dinfo = (struct aac_get_serial *) fib_data(cmd_fibcontext); dinfo->command = cpu_to_le32(VM_ContainerConfig); dinfo->type = cpu_to_le32(CT_CID_TO_32BITS_UID); dinfo->cid = cpu_to_le32(scmd_id(scsicmd)); status = aac_fib_send(ContainerCommand, cmd_fibcontext, sizeof (struct aac_get_serial), FsaNormal, 0, 1, (fib_callback) get_container_serial_callback, (void *) scsicmd); /* * Check that the command queued to the controller */ if (status == -EINPROGRESS) { scsicmd->SCp.phase = AAC_OWNER_FIRMWARE; return 0; } printk(KERN_WARNING "aac_get_container_serial: aac_fib_send failed with status: %d.\n", status); aac_fib_complete(cmd_fibcontext); aac_fib_free(cmd_fibcontext); return -1;}/* Function: setinqserial * * Arguments: [1] pointer to void [1] int * * Purpose: Sets SCSI Unit Serial number. * This is a fake. We should read a proper * serial number from the container. <SuSE>But * without docs it's quite hard to do it :-) * So this will have to do in the meantime.</SuSE> */static int setinqserial(struct aac_dev *dev, void *data, int cid){ /* * This breaks array migration. */ return snprintf((char *)(data), sizeof(struct scsi_inq) - 4, "%08X%02X", le32_to_cpu(dev->adapter_info.serial[0]), cid);}static void set_sense(u8 *sense_buf, u8 sense_key, u8 sense_code, u8 a_sense_code, u8 incorrect_length, u8 bit_pointer, u16 field_pointer, u32 residue){ sense_buf[0] = 0xF0; /* Sense data valid, err code 70h (current error) */ sense_buf[1] = 0; /* Segment number, always zero */ if (incorrect_length) { sense_buf[2] = sense_key | 0x20;/* Set ILI bit | sense key */ sense_buf[3] = BYTE3(residue); sense_buf[4] = BYTE2(residue); sense_buf[5] = BYTE1(residue); sense_buf[6] = BYTE0(residue); } else sense_buf[2] = sense_key; /* Sense key */ if (sense_key == ILLEGAL_REQUEST) sense_buf[7] = 10; /* Additional sense length */ else sense_buf[7] = 6; /* Additional sense length */ sense_buf[12] = sense_code; /* Additional sense code */ sense_buf[13] = a_sense_code; /* Additional sense code qualifier */ if (sense_key == ILLEGAL_REQUEST) { sense_buf[15] = 0; if (sense_code == SENCODE_INVALID_PARAM_FIELD) sense_buf[15] = 0x80;/* Std sense key specific field */ /* Illegal parameter is in the parameter block */ if (sense_code == SENCODE_INVALID_CDB_FIELD) sense_buf[15] = 0xc0;/* Std sense key specific field */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?