示例#1
0
static int aha1542_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *cmd)
{
    struct aha1542_hostdata *aha1542 = shost_priv(sh);
    u8 direction;
    u8 target = cmd->device->id;
    u8 lun = cmd->device->lun;
    unsigned long flags;
    int bufflen = scsi_bufflen(cmd);
    int mbo, sg_count;
    struct mailbox *mb = aha1542->mb;
    struct ccb *ccb = aha1542->ccb;
    struct chain *cptr;

    if (*cmd->cmnd == REQUEST_SENSE) {
        /* Don't do the command - we have the sense data already */
        cmd->result = 0;
        cmd->scsi_done(cmd);
        return 0;
    }
#ifdef DEBUG
    {
        int i = -1;
        if (*cmd->cmnd == READ_10 || *cmd->cmnd == WRITE_10)
            i = xscsi2int(cmd->cmnd + 2);
        else if (*cmd->cmnd == READ_6 || *cmd->cmnd == WRITE_6)
            i = scsi2int(cmd->cmnd + 2);
        shost_printk(KERN_DEBUG, sh, "aha1542_queuecommand: dev %d cmd %02x pos %d len %d",
                     target, *cmd->cmnd, i, bufflen);
        print_hex_dump_bytes("command: ", DUMP_PREFIX_NONE, cmd->cmnd, cmd->cmd_len);
    }
#endif
    if (bufflen) {	/* allocate memory before taking host_lock */
        sg_count = scsi_sg_count(cmd);
        cptr = kmalloc(sizeof(*cptr) * sg_count, GFP_KERNEL | GFP_DMA);
        if (!cptr)
            return SCSI_MLQUEUE_HOST_BUSY;
    } else {
        sg_count = 0;
        cptr = NULL;
    }

    /* Use the outgoing mailboxes in a round-robin fashion, because this
       is how the host adapter will scan for them */

    spin_lock_irqsave(sh->host_lock, flags);
    mbo = aha1542->aha1542_last_mbo_used + 1;
    if (mbo >= AHA1542_MAILBOXES)
        mbo = 0;

    do {
        if (mb[mbo].status == 0 && aha1542->int_cmds[mbo] == NULL)
            break;
        mbo++;
        if (mbo >= AHA1542_MAILBOXES)
            mbo = 0;
    } while (mbo != aha1542->aha1542_last_mbo_used);

    if (mb[mbo].status || aha1542->int_cmds[mbo])
        panic("Unable to find empty mailbox for aha1542.\n");

    aha1542->int_cmds[mbo] = cmd;	/* This will effectively prevent someone else from
					   screwing with this cdb. */

    aha1542->aha1542_last_mbo_used = mbo;

#ifdef DEBUG
    shost_printk(KERN_DEBUG, sh, "Sending command (%d %p)...", mbo, cmd->scsi_done);
#endif

    any2scsi(mb[mbo].ccbptr, isa_virt_to_bus(&ccb[mbo]));	/* This gets trashed for some reason */

    memset(&ccb[mbo], 0, sizeof(struct ccb));

    ccb[mbo].cdblen = cmd->cmd_len;

    direction = 0;
    if (*cmd->cmnd == READ_10 || *cmd->cmnd == READ_6)
        direction = 8;
    else if (*cmd->cmnd == WRITE_10 || *cmd->cmnd == WRITE_6)
        direction = 16;

    memcpy(ccb[mbo].cdb, cmd->cmnd, ccb[mbo].cdblen);

    if (bufflen) {
        struct scatterlist *sg;
        int i;

        ccb[mbo].op = 2;	/* SCSI Initiator Command  w/scatter-gather */
        cmd->host_scribble = (void *)cptr;
        scsi_for_each_sg(cmd, sg, sg_count, i) {
            any2scsi(cptr[i].dataptr, isa_page_to_bus(sg_page(sg))
                     + sg->offset);
            any2scsi(cptr[i].datalen, sg->length);
        };
        any2scsi(ccb[mbo].datalen, sg_count * sizeof(struct chain));
        any2scsi(ccb[mbo].dataptr, isa_virt_to_bus(cptr));
#ifdef DEBUG
        shost_printk(KERN_DEBUG, sh, "cptr %p: ", cptr);
        print_hex_dump_bytes("cptr: ", DUMP_PREFIX_NONE, cptr, 18);
#endif
    } else {
示例#2
0
文件: aha1542.c 项目: avagin/linux
static int aha1542_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *cmd)
{
	struct aha1542_cmd *acmd = scsi_cmd_priv(cmd);
	struct aha1542_hostdata *aha1542 = shost_priv(sh);
	u8 direction;
	u8 target = cmd->device->id;
	u8 lun = cmd->device->lun;
	unsigned long flags;
	int bufflen = scsi_bufflen(cmd);
	int mbo, sg_count;
	struct mailbox *mb = aha1542->mb;
	struct ccb *ccb = aha1542->ccb;

	if (*cmd->cmnd == REQUEST_SENSE) {
		/* Don't do the command - we have the sense data already */
		cmd->result = 0;
		cmd->scsi_done(cmd);
		return 0;
	}
#ifdef DEBUG
	{
		int i = -1;
		if (*cmd->cmnd == READ_10 || *cmd->cmnd == WRITE_10)
			i = xscsi2int(cmd->cmnd + 2);
		else if (*cmd->cmnd == READ_6 || *cmd->cmnd == WRITE_6)
			i = scsi2int(cmd->cmnd + 2);
		shost_printk(KERN_DEBUG, sh, "aha1542_queuecommand: dev %d cmd %02x pos %d len %d",
						target, *cmd->cmnd, i, bufflen);
		print_hex_dump_bytes("command: ", DUMP_PREFIX_NONE, cmd->cmnd, cmd->cmd_len);
	}
#endif
	sg_count = scsi_dma_map(cmd);
	if (sg_count) {
		size_t len = sg_count * sizeof(struct chain);

		acmd->chain = kmalloc(len, GFP_DMA);
		if (!acmd->chain)
			goto out_unmap;
		acmd->chain_handle = dma_map_single(sh->dma_dev, acmd->chain,
				len, DMA_TO_DEVICE);
		if (dma_mapping_error(sh->dma_dev, acmd->chain_handle))
			goto out_free_chain;
	}

	/* Use the outgoing mailboxes in a round-robin fashion, because this
	   is how the host adapter will scan for them */

	spin_lock_irqsave(sh->host_lock, flags);
	mbo = aha1542->aha1542_last_mbo_used + 1;
	if (mbo >= AHA1542_MAILBOXES)
		mbo = 0;

	do {
		if (mb[mbo].status == 0 && aha1542->int_cmds[mbo] == NULL)
			break;
		mbo++;
		if (mbo >= AHA1542_MAILBOXES)
			mbo = 0;
	} while (mbo != aha1542->aha1542_last_mbo_used);

	if (mb[mbo].status || aha1542->int_cmds[mbo])
		panic("Unable to find empty mailbox for aha1542.\n");

	aha1542->int_cmds[mbo] = cmd;	/* This will effectively prevent someone else from
					   screwing with this cdb. */

	aha1542->aha1542_last_mbo_used = mbo;

#ifdef DEBUG
	shost_printk(KERN_DEBUG, sh, "Sending command (%d %p)...", mbo, cmd->scsi_done);
#endif

	/* This gets trashed for some reason */
	any2scsi(mb[mbo].ccbptr, aha1542->ccb_handle + mbo * sizeof(*ccb));

	memset(&ccb[mbo], 0, sizeof(struct ccb));

	ccb[mbo].cdblen = cmd->cmd_len;

	direction = 0;
	if (*cmd->cmnd == READ_10 || *cmd->cmnd == READ_6)
		direction = 8;
	else if (*cmd->cmnd == WRITE_10 || *cmd->cmnd == WRITE_6)
		direction = 16;

	memcpy(ccb[mbo].cdb, cmd->cmnd, ccb[mbo].cdblen);

	if (bufflen) {
		struct scatterlist *sg;
		int i;

		ccb[mbo].op = 2;	/* SCSI Initiator Command  w/scatter-gather */
		scsi_for_each_sg(cmd, sg, sg_count, i) {
			any2scsi(acmd->chain[i].dataptr, sg_dma_address(sg));
			any2scsi(acmd->chain[i].datalen, sg_dma_len(sg));
		};
		any2scsi(ccb[mbo].datalen, sg_count * sizeof(struct chain));
		any2scsi(ccb[mbo].dataptr, acmd->chain_handle);
#ifdef DEBUG
		shost_printk(KERN_DEBUG, sh, "cptr %p: ", acmd->chain);
		print_hex_dump_bytes("cptr: ", DUMP_PREFIX_NONE, acmd->chain, 18);
#endif
	} else {