kernels/linux-2.4.0/drivers/scsi/ips.c
/****************************************************************************/
/*                                                                          */
/* Routine Name: ips_newusrcmd                                              */
/*                                                                          */
/* Routine Description:                                                     */
/*                                                                          */
/*   Process a user command and make it ready to send                       */
/*                                                                          */
/****************************************************************************/


Routine Description.

Process a user command and make it ready to send
Routine Description . Process a user command and make it ready to send
static int
ips_newusrcmd(ips_ha_t *ha, ips_passthru_t *pt, ips_scb_t *scb) {
   IPS_SG_LIST    *sg_list;
   char           *user_area;
   char           *kern_area;
   u32             datasize;
   METHOD_TRACE("ips_usrcmd", 1);
   if ((!scb) || (!pt) || (!ha))
      return (0);
   sg_list = scb->sg_list;
   memcpy(&scb->cmd, &pt->CoppCP.cmd, sizeof(IPS_IOCTL_CMD));
   memcpy(&scb->dcdb, &pt->CoppCP.dcdb, sizeof(IPS_DCDB_TABLE));
   scb->sg_list = sg_list;
   scb->scb_busaddr = VIRT_TO_BUS(scb);
   scb->bus = scb->scsi_cmd->channel;
   scb->target_id = scb->scsi_cmd->target;
   scb->lun = scb->scsi_cmd->lun;
   scb->sg_len = 0;
   scb->data_len = 0;
   scb->flags = 0;
   scb->op_code = 0;
   scb->callback = ipsintr_done;
   scb->timeout = ips_cmd_timeout;
   scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
   if ((scb->cmd.basic_io.op_code == IPS_CMD_READ_SG) ||
       (scb->cmd.basic_io.op_code == IPS_CMD_WRITE_SG) ||
       (scb->cmd.basic_io.op_code == IPS_CMD_DCDB_SG))
      return (0);
   if (pt->CmdBSize) {
      if (pt->CmdBSize > ha->ioctl_datasize) {
         void *bigger_struct;
         bigger_struct = kmalloc(pt->CmdBSize, GFP_ATOMIC|GFP_DMA);
         if (bigger_struct) {
            kfree(ha->ioctl_data);
            ha->ioctl_data = bigger_struct;
            ha->ioctl_datasize = pt->CmdBSize;
         } else
            return (0);
      }
      scb->data_busaddr = VIRT_TO_BUS(ha->ioctl_data);
      user_area = *((char **) &scb->scsi_cmd->cmnd[4]);
      kern_area = ha->ioctl_data;
      datasize = *((u32 *) &scb->scsi_cmd->cmnd[8]);
      if (copy_from_user(kern_area, user_area, datasize) > 0) {
         DEBUG_VAR(1, "(%s%d) passthru failed - unable to copy in user data",
                   ips_name, ha->host_num);
         return (0);
      }
   } else {
      scb->data_busaddr = 0L;
   }
   if (scb->cmd.dcdb.op_code == IPS_CMD_DCDB)
      scb->cmd.dcdb.dcdb_address = VIRT_TO_BUS(&scb->dcdb);
   if (pt->CmdBSize) {
      if (scb->cmd.dcdb.op_code == IPS_CMD_DCDB)
         scb->dcdb.buffer_pointer = scb->data_busaddr;
      else
         scb->cmd.basic_io.sg_addr = scb->data_busaddr;
   }
   if (pt->TimeOut) {
      scb->timeout = pt->TimeOut;
      if (pt->TimeOut <= 10)
         scb->dcdb.cmd_attribute |= IPS_TIMEOUT10;
      else if (pt->TimeOut <= 60)
         scb->dcdb.cmd_attribute |= IPS_TIMEOUT60;
      else
         scb->dcdb.cmd_attribute |= IPS_TIMEOUT20M;
   }
   scb->scsi_cmd->result = DID_OK << 16;
   return (1);
}
static int ips_newusrcmd ( ips_ha_t * ha , ips_passthru_t * pt , ips_scb_t * scb ) { IPS_SG_LIST * sg_list ; char * user_area ; char * kern_area ; u32 datasize ; METHOD_TRACE ( " " , 1 ) ; if ( ( ! scb ) || ( ! pt ) || ( ! ha ) ) return ( 0 ) ; sg_list = scb -> sg_list ; memcpy ( & scb -> cmd , & pt -> CoppCP . cmd , sizeof ( IPS_IOCTL_CMD ) ) ; memcpy ( & scb -> dcdb , & pt -> CoppCP . dcdb , sizeof ( IPS_DCDB_TABLE ) ) ; scb -> sg_list = sg_list ; scb -> scb_busaddr = VIRT_TO_BUS ( scb ) ; scb -> bus = scb -> scsi_cmd -> channel ; scb -> target_id = scb -> scsi_cmd -> target ; scb -> lun = scb -> scsi_cmd -> lun ; scb -> sg_len = 0 ; scb -> data_len = 0 ; scb -> flags = 0 ; scb -> op_code = 0 ; scb -> callback = ipsintr_done ; scb -> timeout = ips_cmd_timeout ; scb -> cmd . basic_io . command_id = IPS_COMMAND_ID ( ha , scb ) ; if ( ( scb -> cmd . basic_io . op_code == IPS_CMD_READ_SG ) || ( scb -> cmd . basic_io . op_code == IPS_CMD_WRITE_SG ) || ( scb -> cmd . basic_io . op_code == IPS_CMD_DCDB_SG ) ) return ( 0 ) ; if ( pt -> CmdBSize ) { if ( pt -> CmdBSize > ha -> ioctl_datasize ) { void * bigger_struct ; bigger_struct = kmalloc ( pt -> CmdBSize , GFP_ATOMIC | GFP_DMA ) ; if ( bigger_struct ) { kfree ( ha -> ioctl_data ) ; ha -> ioctl_data = bigger_struct ; ha -> ioctl_datasize = pt -> CmdBSize ; } else return ( 0 ) ; } scb -> data_busaddr = VIRT_TO_BUS ( ha -> ioctl_data ) ; user_area = * ( ( char * * ) & scb -> scsi_cmd -> cmnd [ 4 ] ) ; kern_area = ha -> ioctl_data ; datasize = * ( ( u32 * ) & scb -> scsi_cmd -> cmnd [ 8 ] ) ; if ( copy_from_user ( kern_area , user_area , datasize ) > 0 ) { DEBUG_VAR ( 1 , " " , ips_name , ha -> host_num ) ; return ( 0 ) ; } } else { scb -> data_busaddr = 0L ; } if ( scb -> cmd . dcdb . op_code == IPS_CMD_DCDB ) scb -> cmd . dcdb . dcdb_address = VIRT_TO_BUS ( & scb -> dcdb ) ; if ( pt -> CmdBSize ) { if ( scb -> cmd . dcdb . op_code == IPS_CMD_DCDB ) scb -> dcdb . buffer_pointer = scb -> data_busaddr ; else scb -> cmd . basic_io . sg_addr = scb -> data_busaddr ; } if ( pt -> TimeOut ) { scb -> timeout = pt -> TimeOut ; if ( pt -> TimeOut <= 10 ) scb -> dcdb . cmd_attribute |= IPS_TIMEOUT10 ; else if ( pt -> TimeOut <= 60 ) scb -> dcdb . cmd_attribute |= IPS_TIMEOUT60 ; else scb -> dcdb . cmd_attribute |= IPS_TIMEOUT20M ; } scb -> scsi_cmd -> result = DID_OK << 16 ; return ( 1 ) ; }
Routine Name: ips_newusrcmd
Routine Name : ips_newusrcmd
/* Save the S/G list pointer so it doesn't get clobbered */ /* copy in the CP */ /* FIX stuff that might be wrong */ /* we don't support DCDB/READ/WRITE Scatter Gather */ /* try to allocate a bigger struct */ /* free the old memory */ /* use the new memory */ /* Attempt to copy in the data */ /* set timeouts */ /* assume success */ /* success */