kernels/linux-2.4.0/drivers/scsi/ips.c
/****************************************************************************/
/*                                                                          */
/* Routine Name: ips_make_passthru                                          */
/*                                                                          */
/* Routine Description:                                                     */
/*                                                                          */
/*   Make a passthru command out of the info in the Scsi block              */
/*                                                                          */
/****************************************************************************/


Routine Description.

Make a passthru command out of the info in the Scsi block
Routine Description . Make a passthru command out of the info in the Scsi block
static int
ips_make_passthru(ips_ha_t *ha, Scsi_Cmnd *SC, ips_scb_t *scb) {
   ips_passthru_t *pt;
   METHOD_TRACE("ips_make_passthru", 1);
   if (!SC->request_bufflen || !SC->request_buffer) {
      DEBUG_VAR(1, "(%s%d) No passthru structure",
                ips_name, ha->host_num);
      return (IPS_FAILURE);
   }
   if (SC->request_bufflen < sizeof(ips_passthru_t)) {
      DEBUG_VAR(1, "(%s%d) Passthru structure wrong size",
             ips_name, ha->host_num);
      return (IPS_FAILURE);
   }
   if ((((char *) SC->request_buffer)[0] != 'C') ||
       (((char *) SC->request_buffer)[1] != 'O') ||
       (((char *) SC->request_buffer)[2] != 'P') ||
       (((char *) SC->request_buffer)[3] != 'P')) {
      DEBUG_VAR(1, "(%s%d) Wrong signature on passthru structure.",
                ips_name, ha->host_num);
      return (IPS_FAILURE);
   }
   pt = (ips_passthru_t *) SC->request_buffer;
   switch (pt->CoppCmd) {
   case IPS_NUMCTRLS:
      memcpy(SC->request_buffer + sizeof(ips_passthru_t),
             &ips_num_controllers, sizeof(int));
      SC->result = DID_OK << 16;
      return (IPS_SUCCESS_IMM);
   case IPS_CTRLINFO:
      memcpy(SC->request_buffer + sizeof(ips_passthru_t),
             ha, sizeof(ips_ha_t));
      SC->result = DID_OK << 16;
      return (IPS_SUCCESS_IMM);
   case IPS_COPPUSRCMD:
   case IPS_COPPIOCCMD:
      if (SC->cmnd[0] == IPS_IOCTL_COMMAND) {
         if (SC->request_bufflen < (sizeof(ips_passthru_t) + pt->CmdBSize)) {
            DEBUG_VAR(1, "(%s%d) Passthru structure wrong size",
                      ips_name, ha->host_num);
            return (IPS_FAILURE);
         }
         if (ips_usrcmd(ha, pt, scb))
            return (IPS_SUCCESS);
         else
            return (IPS_FAILURE);
      } else if (SC->cmnd[0] == IPS_IOCTL_NEW_COMMAND) {
         if (SC->request_bufflen < (sizeof(ips_passthru_t))) {
            DEBUG_VAR(1, "(%s%d) Passthru structure wrong size",
                      ips_name, ha->host_num);
            return (IPS_FAILURE);
         }
         if (ips_newusrcmd(ha, pt, scb))
            return (IPS_SUCCESS);
         else
            return (IPS_FAILURE);
      }
      break;
   case IPS_FLASHBIOS:
      if (SC->cmnd[0] != IPS_IOCTL_NEW_COMMAND)
         return (IPS_FAILURE);
      if ((ha->device_id != IPS_COPPERHEAD_DEVICEID) ||
          (ha->revision_id > IPS_REVID_TROMBONE64)) {
         DEBUG_VAR(1, "(%s%d) flash bios failed - unsupported controller",
                   ips_name, ha->host_num);
         return (IPS_FAILURE);
      }
      if ((!ha->func.programbios) ||
          (!ha->func.erasebios) ||
          (!ha->func.verifybios))
         return (IPS_FAILURE);
      memcpy(&pt->CmdBuffer, &SC->cmnd[4], 4);
      memcpy(&pt->CmdBSize, &SC->cmnd[8], 4);
      if ((!pt->CmdBSize) || (!pt->CmdBuffer))
         return (IPS_FAILURE);
      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 (IPS_FAILURE);
      }
      if (copy_from_user(ha->ioctl_data, pt->CmdBuffer, pt->CmdBSize) > 0) {
         DEBUG_VAR(1, "(%s%d) flash bios failed - unable to copy user buffer",
                   ips_name, ha->host_num);
         return (IPS_FAILURE);
      }
      if ((*ha->func.erasebios)(ha)) {
         DEBUG_VAR(1, "(%s%d) flash bios failed - unable to erase flash",
                   ips_name, ha->host_num);
         return (IPS_FAILURE);
      }
      if ((*ha->func.programbios)(ha, ha->ioctl_data, pt->CmdBSize)) {
         DEBUG_VAR(1, "(%s%d) flash bios failed - unable to program flash",
                   ips_name, ha->host_num);
         return (IPS_FAILURE);
      }
      if ((*ha->func.verifybios)(ha, ha->ioctl_data, pt->CmdBSize)) {
         DEBUG_VAR(1, "(%s%d) flash bios failed - unable to verify flash",
                   ips_name, ha->host_num);
         return (IPS_FAILURE);
      }
      return (IPS_SUCCESS_IMM);
   } 
   return (IPS_FAILURE);
}
static int ips_make_passthru ( ips_ha_t * ha , Scsi_Cmnd * SC , ips_scb_t * scb ) { ips_passthru_t * pt ; METHOD_TRACE ( " " , 1 ) ; if ( ! SC -> request_bufflen || ! SC -> request_buffer ) { DEBUG_VAR ( 1 , " " , ips_name , ha -> host_num ) ; return ( IPS_FAILURE ) ; } if ( SC -> request_bufflen < sizeof ( ips_passthru_t ) ) { DEBUG_VAR ( 1 , " " , ips_name , ha -> host_num ) ; return ( IPS_FAILURE ) ; } if ( ( ( ( char * ) SC -> request_buffer ) [ 0 ] != ' ' ) || ( ( ( char * ) SC -> request_buffer ) [ 1 ] != ' ' ) || ( ( ( char * ) SC -> request_buffer ) [ 2 ] != ' ' ) || ( ( ( char * ) SC -> request_buffer ) [ 3 ] != ' ' ) ) { DEBUG_VAR ( 1 , " " , ips_name , ha -> host_num ) ; return ( IPS_FAILURE ) ; } pt = ( ips_passthru_t * ) SC -> request_buffer ; switch ( pt -> CoppCmd ) { case IPS_NUMCTRLS : memcpy ( SC -> request_buffer + sizeof ( ips_passthru_t ) , & ips_num_controllers , sizeof ( int ) ) ; SC -> result = DID_OK << 16 ; return ( IPS_SUCCESS_IMM ) ; case IPS_CTRLINFO : memcpy ( SC -> request_buffer + sizeof ( ips_passthru_t ) , ha , sizeof ( ips_ha_t ) ) ; SC -> result = DID_OK << 16 ; return ( IPS_SUCCESS_IMM ) ; case IPS_COPPUSRCMD : case IPS_COPPIOCCMD : if ( SC -> cmnd [ 0 ] == IPS_IOCTL_COMMAND ) { if ( SC -> request_bufflen < ( sizeof ( ips_passthru_t ) + pt -> CmdBSize ) ) { DEBUG_VAR ( 1 , " " , ips_name , ha -> host_num ) ; return ( IPS_FAILURE ) ; } if ( ips_usrcmd ( ha , pt , scb ) ) return ( IPS_SUCCESS ) ; else return ( IPS_FAILURE ) ; } else if ( SC -> cmnd [ 0 ] == IPS_IOCTL_NEW_COMMAND ) { if ( SC -> request_bufflen < ( sizeof ( ips_passthru_t ) ) ) { DEBUG_VAR ( 1 , " " , ips_name , ha -> host_num ) ; return ( IPS_FAILURE ) ; } if ( ips_newusrcmd ( ha , pt , scb ) ) return ( IPS_SUCCESS ) ; else return ( IPS_FAILURE ) ; } break ; case IPS_FLASHBIOS : if ( SC -> cmnd [ 0 ] != IPS_IOCTL_NEW_COMMAND ) return ( IPS_FAILURE ) ; if ( ( ha -> device_id != IPS_COPPERHEAD_DEVICEID ) || ( ha -> revision_id > IPS_REVID_TROMBONE64 ) ) { DEBUG_VAR ( 1 , " " , ips_name , ha -> host_num ) ; return ( IPS_FAILURE ) ; } if ( ( ! ha -> func . programbios ) || ( ! ha -> func . erasebios ) || ( ! ha -> func . verifybios ) ) return ( IPS_FAILURE ) ; memcpy ( & pt -> CmdBuffer , & SC -> cmnd [ 4 ] , 4 ) ; memcpy ( & pt -> CmdBSize , & SC -> cmnd [ 8 ] , 4 ) ; if ( ( ! pt -> CmdBSize ) || ( ! pt -> CmdBuffer ) ) return ( IPS_FAILURE ) ; 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 ( IPS_FAILURE ) ; } if ( copy_from_user ( ha -> ioctl_data , pt -> CmdBuffer , pt -> CmdBSize ) > 0 ) { DEBUG_VAR ( 1 , " " , ips_name , ha -> host_num ) ; return ( IPS_FAILURE ) ; } if ( ( * ha -> func . erasebios ) ( ha ) ) { DEBUG_VAR ( 1 , " " , ips_name , ha -> host_num ) ; return ( IPS_FAILURE ) ; } if ( ( * ha -> func . programbios ) ( ha , ha -> ioctl_data , pt -> CmdBSize ) ) { DEBUG_VAR ( 1 , " " , ips_name , ha -> host_num ) ; return ( IPS_FAILURE ) ; } if ( ( * ha -> func . verifybios ) ( ha , ha -> ioctl_data , pt -> CmdBSize ) ) { DEBUG_VAR ( 1 , " " , ips_name , ha -> host_num ) ; return ( IPS_FAILURE ) ; } return ( IPS_SUCCESS_IMM ) ; } return ( IPS_FAILURE ) ; }
Routine Name: ips_make_passthru
Routine Name : ips_make_passthru
/* no data */ /* wrong size */ /* signature doesn't match */ /*
    * Some notes about the passthru interface used
    *
    * IF the scsi op_code == 0x0d then we assume
    * that the data came along with/goes with the
    * packet we received from the sg driver. In this
    * case the CmdBSize field of the pt structure is
    * used for the size of the buffer.
    *
    * IF the scsi op_code == 0x81 then we assume that
    * we will need our own buffer and we will copy the
    * data to/from the user buffer passed in the scsi
    * command.  The data address resides at offset 4
    * in the scsi command.  The length of the data resides
    * at offset 8 in the scsi command.
    */ /* wrong size */ /* wrong size */ /* we must use the new interface */ /* don't flash the BIOS on future cards */ /*
       * Check to make sure we have functions
       * to handle the request
       */ /* copy in the size/buffer ptr from the scsi command */ /* must have a buffer */ /* make sure buffer is big enough */ /* try to allocate a bigger struct */ /* free the old memory */ /* use the new memory */ /* copy in the buffer */ /* end switch */