📄 aachba.c
字号:
* * 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(int devtype, void *data, int tindex){ struct scsi_inq *str; char *findit; struct aac_driver_ident *mp; extern struct aac_driver_ident aac_drivers[]; /* HACK FIXME */ mp = &aac_drivers[devtype]; str = (struct scsi_inq *)(data); /* cast data to scsi inq block */ inqstrcpy (mp->vname, str->vid); inqstrcpy (mp->model, str->pid); /* last six chars reserved for vol type */ findit = str->pid; for ( ; *findit != ' '; findit++); /* walk till we find a space then incr by 1 */ findit++; if (tindex < (sizeof(container_types)/sizeof(char *))){ inqstrcpy (container_types[tindex], findit); } inqstrcpy ("0001", str->prl);}void set_sense(char *sense_buf, u8 sense_key, u8 sense_code, u8 a_sense_code, u8 incorrect_length, u8 bit_pointer, unsigned field_pointer, unsigned long 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 the 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 == SENKEY_ILLEGAL) 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 == SENKEY_ILLEGAL) { 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 */ /* Illegal parameter is in the CDB block */ sense_buf[15] |= bit_pointer; sense_buf[16] = field_pointer >> 8; /* MSB */ sense_buf[17] = field_pointer; /* LSB */ }}static void aac_io_done(Scsi_Cmnd * scsicmd){ unsigned long cpu_flags; spin_lock_irqsave(&io_request_lock, cpu_flags); scsicmd->scsi_done(scsicmd); spin_unlock_irqrestore(&io_request_lock, cpu_flags);}static void __aac_io_done(Scsi_Cmnd * scsicmd){ scsicmd->scsi_done(scsicmd);}static void read_callback(void *context, struct fib * fibptr){ struct aac_dev *dev; struct aac_read_reply *readreply; Scsi_Cmnd *scsicmd; unsigned long lba; int cid; scsicmd = (Scsi_Cmnd *) context; dev = (struct aac_dev *)scsicmd->host->hostdata; cid =TARGET_LUN_TO_CONTAINER(scsicmd->target, scsicmd->lun); lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3]; dprintk((KERN_DEBUG "read_callback[cpu %d]: lba = %ld, t = %ld.\n", smp_processor_id(), lba, jiffies)); if (fibptr == NULL) BUG(); if(scsicmd->use_sg) pci_unmap_sg(dev->pdev, (struct scatterlist *)scsicmd->buffer, scsicmd->use_sg, scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); else if(scsicmd->request_bufflen) pci_unmap_single(dev->pdev, (u32)scsicmd->SCp.ptr, scsicmd->request_bufflen, scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); readreply = (struct aac_read_reply *)fib_data(fibptr); if (le32_to_cpu(readreply->status) == ST_OK) scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD; else { printk(KERN_WARNING "read_callback: read failed, status = %d\n", readreply->status); scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION; set_sense((char *) &sense_data[cid], SENKEY_HW_ERR, SENCODE_INTERNAL_TARGET_FAILURE, ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0, 0, 0); } fib_complete(fibptr); fib_free(fibptr); aac_io_done(scsicmd);}static void write_callback(void *context, struct fib * fibptr){ struct aac_dev *dev; struct aac_write_reply *writereply; Scsi_Cmnd *scsicmd; unsigned long lba; int cid; scsicmd = (Scsi_Cmnd *) context; dev = (struct aac_dev *)scsicmd->host->hostdata; cid = TARGET_LUN_TO_CONTAINER(scsicmd->target, scsicmd->lun); lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3]; dprintk((KERN_DEBUG "write_callback[cpu %d]: lba = %ld, t = %ld.\n", smp_processor_id(), lba, jiffies)); if (fibptr == NULL) BUG(); if(scsicmd->use_sg) pci_unmap_sg(dev->pdev, (struct scatterlist *)scsicmd->buffer, scsicmd->use_sg, scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); else if(scsicmd->request_bufflen) pci_unmap_single(dev->pdev, (u32)scsicmd->SCp.ptr, scsicmd->request_bufflen, scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); writereply = (struct aac_write_reply *) fib_data(fibptr); if (le32_to_cpu(writereply->status) == ST_OK) scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD; else { printk(KERN_WARNING "write_callback: write failed, status = %d\n", writereply->status); scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION; set_sense((char *) &sense_data[cid], SENKEY_HW_ERR, SENCODE_INTERNAL_TARGET_FAILURE, ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0, 0, 0); } fib_complete(fibptr); fib_free(fibptr); aac_io_done(scsicmd);}int aac_read(Scsi_Cmnd * scsicmd, int cid){ unsigned long lba; unsigned long count; unsigned long byte_count = 0; int status; struct aac_read *readcmd; u16 fibsize; struct aac_dev *dev; struct fib * cmd_fibcontext; dev = (struct aac_dev *)scsicmd->host->hostdata; /* * Get block address and transfer length */ if (scsicmd->cmnd[0] == SS_READ) /* 6 byte command */ { dprintk((KERN_DEBUG "aachba: received a read(6) command on target %d.\n", cid)); lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3]; count = scsicmd->cmnd[4]; if (count == 0) count = 256; } else { dprintk((KERN_DEBUG "aachba: received a read(10) command on target %d.\n", cid)); lba = (scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5]; count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8]; } dprintk((KERN_DEBUG "aac_read[cpu %d]: lba = %lu, t = %ld.\n", smp_processor_id(), lba, jiffies)); /* * Alocate and initialize a Fib */ if (!(cmd_fibcontext = fib_alloc(dev))) { scsicmd->result = DID_ERROR << 16; aac_io_done(scsicmd); return (-1); } fib_init(cmd_fibcontext); readcmd = (struct aac_read *) fib_data(cmd_fibcontext); readcmd->command = cpu_to_le32(VM_CtBlockRead); readcmd->cid = cpu_to_le32(cid); readcmd->block = cpu_to_le32(lba); readcmd->count = cpu_to_le32(count * 512); readcmd->sg.count = cpu_to_le32(1); if (count * 512 > (64 * 1024)) BUG(); /* * Build Scatter/Gather list */ if (scsicmd->use_sg) /* use scatter/gather list */ { struct scatterlist *sg; int i; int sg_count; sg = (struct scatterlist *) scsicmd->request_buffer; sg_count = pci_map_sg(dev->pdev, sg, scsicmd->use_sg, scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); byte_count = 0; for (i = 0; i < sg_count; i++) { readcmd->sg.sg[i].addr = cpu_to_le32(sg_dma_address(sg)); readcmd->sg.sg[i].count = cpu_to_le32(sg_dma_len(sg)); byte_count += sg->length; if (sg->length > (64 * 1024)) BUG(); sg++; } readcmd->sg.count = cpu_to_le32(sg_count); if (sg_count > MAX_DRIVER_SG_SEGMENT_COUNT) BUG(); } else if(scsicmd->request_bufflen) { u32 addr; addr = pci_map_single(dev->pdev, scsicmd->request_buffer, scsicmd->request_bufflen, scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); scsicmd->SCp.ptr = (void *)addr; readcmd->sg.sg[0].addr = cpu_to_le32(addr); readcmd->sg.sg[0].count = cpu_to_le32(scsicmd->request_bufflen); byte_count = scsicmd->request_bufflen; if (byte_count > (64 * 1024)) BUG(); } if (byte_count != readcmd->count) BUG(); /* * Now send the Fib to the adapter */ fibsize = sizeof(struct aac_read) + ((readcmd->sg.count - 1) * sizeof (struct sgentry)); status = fib_send(ContainerCommand, cmd_fibcontext, fibsize, FsaNormal, 0, 1, (fib_callback) read_callback, (void *) scsicmd); /* * Check that the command queued to the controller */ if (status == -EINPROGRESS) return 0; printk(KERN_WARNING "aac_read: fib_send failed with status: %d.\n", status); /* * For some reason, the Fib didn't queue, return QUEUE_FULL */ scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | QUEUE_FULL; aac_io_done(scsicmd); fib_complete(cmd_fibcontext); fib_free(cmd_fibcontext); return -1;}static int aac_write(Scsi_Cmnd * scsicmd, int cid){ unsigned long lba; unsigned long count; unsigned long byte_count = 0; int status; struct aac_write *writecmd; u16 fibsize; struct aac_dev *dev; struct fib * cmd_fibcontext; dev = (struct aac_dev *)scsicmd->host->hostdata; /* * Get block address and transfer length */ if (scsicmd->cmnd[0] == SS_WRITE) /* 6 byte command */ { lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3]; count = scsicmd->cmnd[4]; if (count == 0) count = 256; } else { dprintk((KERN_DEBUG "aachba: received a write(10) command on target %d.\n", cid)); lba = (scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5]; count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8]; } dprintk((KERN_DEBUG "aac_write[cpu %d]: lba = %lu, t = %ld.\n", smp_processor_id(), lba, jiffies)); /* * Allocate and initialize a Fib then setup a BlockWrite command */ if (!(cmd_fibcontext = fib_alloc(dev))) { scsicmd->result = DID_ERROR << 16; aac_io_done(scsicmd); return -1; } fib_init(cmd_fibcontext); writecmd = (struct aac_write *) fib_data(cmd_fibcontext); writecmd->command = cpu_to_le32(VM_CtBlockWrite); writecmd->cid = cpu_to_le32(cid); writecmd->block = cpu_to_le32(lba); writecmd->count = cpu_to_le32(count * 512); writecmd->sg.count = cpu_to_le32(1); /* FIXME: why isnt ->stable setup */ if (count * 512 > (64 * 1024)) { BUG(); } /* * Build Scatter/Gather list */ if (scsicmd->use_sg) { struct scatterlist *sg; int i; int sg_count; sg = (struct scatterlist *) scsicmd->request_buffer; sg_count = pci_map_sg(dev->pdev, sg, scsicmd->use_sg, scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); byte_count = 0; for (i = 0; i < scsicmd->use_sg; i++) { writecmd->sg.sg[i].addr = cpu_to_le32(sg_dma_address(sg)); writecmd->sg.sg[i].count = cpu_to_le32(sg_dma_len(sg)); byte_count += sg->length; if (sg->length > (64 * 1024)) BUG(); sg++; } writecmd->sg.count = cpu_to_le32(sg_count); if (sg_count > MAX_DRIVER_SG_SEGMENT_COUNT) BUG(); } else if(scsicmd->request_bufflen) { u32 addr; addr = pci_map_single(dev->pdev, scsicmd->request_buffer, scsicmd->request_bufflen, scsi_to_pci_dma_dir(scsicmd->sc_data_direction));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -