⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rf_camlayer.c

📁 RAIDFrame是个非常好的磁盘阵列RAID仿真工具
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1995 Carnegie-Mellon University. * All rights reserved. * * Author: Mark Holland * * Permission to use, copy, modify and distribute this software and * its documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU *  School of Computer Science *  Carnegie Mellon University *  Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. *//******************************************************************************** * camlayer.c -- code for interfacing to the OSF/1 CAM layer * * the generic call structure is to allocate a RF_DiskOp_t data structure describing * what you want to do by calling one of the "alloc" routines, then actually * do the op by calling the corresponding "do" routine, and the free the RF_DiskOp_t * by calling FreeDiskOp. *******************************************************************************//* $Locker:  $ * $Log: rf_camlayer.c,v $ * Revision 1.33  1996/08/16  17:51:22  jimz * begin AIX additions * * Revision 1.32  1996/07/19  16:10:34  jimz * deal better with disk labels + partitions * * Revision 1.31  1996/07/18  22:57:14  jimz * port simulator to AIX * * Revision 1.30  1996/07/15  17:22:18  jimz * nit-pick code cleanup * resolve stdlib problems on DEC OSF * * Revision 1.29  1996/06/10  11:55:47  jimz * Straightened out some per-array/not-per-array distinctions, fixed * a couple bugs related to confusion. Added shutdown lists. Removed * layout shutdown function (now subsumed by shutdown lists). * * Revision 1.28  1996/06/09  02:36:46  jimz * lots of little crufty cleanup- fixup whitespace * issues, comment #ifdefs, improve typing in some * places (esp size-related) * * Revision 1.27  1996/06/07  21:33:04  jimz * begin using consistent types for sector numbers, * stripe numbers, row+col numbers, recon unit numbers * * Revision 1.26  1996/06/05  18:06:02  jimz * Major code cleanup. The Great Renaming is now done. * Better modularity. Better typing. Fixed a bunch of * synchronization bugs. Made a lot of global stuff * per-desc or per-array. Removed dead code. * * Revision 1.25  1996/06/03  23:28:26  jimz * more bugfixes * check in tree to sync for IPDS runs with current bugfixes * there still may be a problem with threads in the script test * getting I/Os stuck- not trivially reproducible (runs ~50 times * in a row without getting stuck) * * Revision 1.24  1996/05/30  23:22:16  jimz * bugfixes of serialization, timing problems * more cleanup * * Revision 1.23  1996/05/30  11:29:41  jimz * Numerous bug fixes. Stripe lock release code disagreed with the taking code * about when stripes should be locked (I made it consistent: no parity, no lock) * There was a lot of extra serialization of I/Os which I've removed- a lot of * it was to calculate values for the cache code, which is no longer with us. * More types, function, macro cleanup. Added code to properly quiesce the array * on shutdown. Made a lot of stuff array-specific which was (bogusly) general * before. Fixed memory allocation, freeing bugs. * * Revision 1.22  1996/05/27  18:56:37  jimz * more code cleanup * better typing * compiles in all 3 environments * * Revision 1.21  1996/05/24  22:17:04  jimz * continue code + namespace cleanup * typed a bunch of flags * * Revision 1.20  1996/05/23  21:46:35  jimz * checkpoint in code cleanup (release prep) * lots of types, function names have been fixed * * Revision 1.19  1996/05/23  00:33:23  jimz * code cleanup: move all debug decls to rf_options.c, all extern * debug decls to rf_options.h, all debug vars preceded by rf_ * * Revision 1.18  1996/05/18  19:51:34  jimz * major code cleanup- fix syntax, make some types consistent, * add prototypes, clean out dead code, et cetera * * Revision 1.17  1996/05/06  18:44:23  jimz * add ShutdownCamLayer() * * Revision 1.16  1995/12/12  18:10:06  jimz * MIN -> RF_MIN, MAX -> RF_MAX, ASSERT -> RF_ASSERT * fix 80-column brain damage in comments * * Revision 1.15  1995/12/01  15:16:19  root * added copyright info * */#ifdef __osf__#ifndef KERNEL#include <errno.h>#include <fcntl.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <strings.h>#include <ctype.h>#include <unistd.h>#include <sys/ioctl.h>#else /* !KERNEL */#include <labels.h>#endif /* !KERNEL */#include "rf_types.h"#include "rf_sys.h"#include "rf_ccmn.h"#include "rf_raid.h"#include "rf_general.h"#include "rf_camlayer.h"#include "rf_shutdown.h"#include "rf_options.h"/* A "handle" data structure via which we can do I/O through the cam layer * The ua_ccb is not used in the kernel.  Will it mess up anything to leave it here anyway? * We could hack around it by #ifdef'ing it out when in the kernel, but it doesn't seem worth it. */typedef struct _cam_io_handle {  UAGT_CAM_CCB   ua_ccb;  CCB_SCSIIO     ccb;  unsigned char  snsBuf[RF_CAM_SENSEDATALEN];} CamIOHandle;static int camfd = (-1);            /* file descriptor for /dev/cam */#ifndef KERNELstatic void rf_release_sim_queue(CCB_SCSIIO *ccb);static void rf_print_ccb_status(CCB_HEADER  *cp);#endif /* !KERNEL */#ifndef KERNEL/*ARGSUSED*/static void rf_ShutdownCamLayer(ignored)  void  *ignored;{	int rc;	rc = close(camfd);	camfd = (-1);}#endif /* !KERNEL *//*ARGSUSED*/int rf_ConfigureCamLayer(listp)  RF_ShutdownList_t  **listp;{#ifndef KERNEL  int rc;  /* open the cam file */  if ((camfd = open("/dev/cam", O_RDWR, 0)) < 0) {    RF_ERRORMSG("Unable to open /dev/cam\n");    perror("CAM open");    return(errno);  }  rc = rf_ShutdownCreate(listp, rf_ShutdownCamLayer, NULL);  if (rc) {    RF_ERRORMSG3("Unable to add to shutdown list file %s line %d rc=%d\n",      __FILE__, __LINE__, rc);    close(camfd);    return(rc);  }#endif /* !KERNEL */  return(0);}/******************************************************************************** * * creates/destroys a "handle" via which we can do I/O through the cam layer * the return value is cast to void * so that the caller need not know * anything at all about cam data structures. * *******************************************************************************/void *rf_CreateCamIOHandle(){  CamIOHandle *p;  RF_Malloc(p, sizeof(CamIOHandle), (CamIOHandle *));  return((void *)p);}void rf_DestroyCamIOHandle(h)  void  *h;{  RF_Free((CamIOHandle *)h,sizeof(CamIOHandle)); /* unspeakably gratuitous castage here */}/******************************************************************************** * extracts the bus & target IDs from the device file name. * assumes that the file name conforms to the DEC OSF/1 spec *******************************************************************************/int rf_extract_ids(name, bus_id, targ_id, lun)  char  *name;  int   *bus_id;  int   *targ_id;  int   *lun;{  char *p;  unsigned devnum;  for (p=name; (*p) && (*p<'0' || *p>'9'); p++);  if (!*p) {    printf("Invalid device name for disk device \"%s\".\n",name);    return(ENODEV);  }  if (p > name && (*(p-1) >= 'a' && *(p-1) <= 'g')) *lun = *(p-1) - 'a' + 1;  else *lun = 0;  devnum = atoi(p);  *targ_id = devnum&0x7;  *bus_id  = devnum>>3;  return(0);}/******************************************************************************** * these are utility routines used by the code below. *******************************************************************************/#ifndef KERNEL/* allocate the data structures */#define RF_ALLOCATE_CCB_AND_SENSE(_uaccb_, _ccb_, _sns_) { \  RF_Calloc(_ccb_, 1, sizeof(CCB_SCSIIO), (CCB_SCSIIO *)); \  RF_Calloc(_uaccb_, 1, sizeof(UAGT_CAM_CCB), (UAGT_CAM_CCB *)); \  RF_Calloc(_sns_, 1, sizeof(ALL_REQ_SNS_DATA), (ALL_REQ_SNS_DATA *)); \}  /* set up some default parameters */static void rf_set_default_ccb_params(  UAGT_CAM_CCB      *ua_ccb,  CCB_SCSIIO        *ccb,  ALL_REQ_SNS_DATA  *sns,  unsigned           direction,  u_char            *dataptr,  unsigned           datalen,  unsigned           cdblen){  ccb->cam_ch.my_addr        = (struct ccb_header *) ccb;  ccb->cam_ch.cam_ccb_len    = sizeof(CCB_SCSIIO);  ccb->cam_ch.cam_func_code  = XPT_SCSI_IO;  ccb->cam_sense_ptr         = (u_char *) sns;  ccb->cam_sense_len         = (u_char)sizeof(*sns);  ccb->cam_ch.cam_flags      = direction;  ccb->cam_data_ptr          = (u_char *) dataptr;  ccb->cam_dxfer_len         = datalen;  ccb->cam_cdb_len           = cdblen;  ccb->cam_timeout           = CAM_TIME_DEFAULT;    ua_ccb->uagt_ccb           = (CCB_HEADER *) ccb;  ua_ccb->uagt_ccblen        = sizeof(CCB_SCSIIO);  ua_ccb->uagt_snsbuf        = (u_char *) sns;  ua_ccb->uagt_snslen        = sizeof(*sns);  ua_ccb->uagt_cdb           = (CDB_UN *) NULL;  ua_ccb->uagt_cdblen        = 0;  ua_ccb->uagt_buffer        = dataptr;  ua_ccb->uagt_buflen        = datalen;}#endif /* !KERNEL *//******************************************************************************** * the next few routines allocate data structures necessary for telling * the CAM layer what operation we want to do and how to control it. * this is used only at user level. *******************************************************************************//* create a RF_DiskOp_t for doing a READ CAPACITY */int rf_SCSI_AllocReadCapacity(ua_ccb_out)  RF_DiskOp_t  **ua_ccb_out;{  CCB_SCSIIO         *ccb;          /* I/O command control block */  UAGT_CAM_CCB       *ua_ccb;       /* user agent ccb for communication to CAM layer */  ALL_REQ_SNS_DATA   *sns;          /* sense data buffer */  DIR_READ_CAP_DATA  *dat;          /* read capacity data buffer */  DIR_READ_CAP_CDB10 *rdcap;        /* SCSI command descriptor block (cdb) for READ CAPACITY */#ifndef KERNEL  RF_ALLOCATE_CCB_AND_SENSE(ua_ccb, ccb, sns);  RF_Calloc(dat, 1, sizeof(DIR_READ_CAP_DATA), (DIR_READ_CAP_DATA *));  rf_set_default_ccb_params(ua_ccb, ccb, sns, CAM_DIR_IN, (u_char *)dat, sizeof(DIR_READ_CAP_DATA), sizeof(DIR_READ_CAP_CDB10));  rdcap = (DIR_READ_CAP_CDB10 *) &(ccb->cam_cdb_io.cam_cdb_bytes[0]);  (void) bzero( (char *) rdcap, sizeof(DIR_READ_CAP_CDB10) );  rdcap->opcode              = DIR_READCAP_OP;  *ua_ccb_out = (RF_DiskOp_t *) ua_ccb;#endif /* !KERNEL */  return(0);}/* create a RF_DiskOp_t for doing a TEST UNIT READY */int rf_SCSI_AllocTUR(ua_ccb_out)  RF_DiskOp_t  **ua_ccb_out;{  CCB_SCSIIO         *ccb;          /* I/O command control block */  UAGT_CAM_CCB       *ua_ccb;       /* user agent ccb for communication to CAM layer */  ALL_REQ_SNS_DATA   *sns;          /* sense data buffer */  ALL_TUR_CDB        *tur;          /* scsi cdb for TEST UNIT READY */#ifndef KERNEL  RF_ALLOCATE_CCB_AND_SENSE(ua_ccb, ccb, sns);  rf_set_default_ccb_params(ua_ccb, ccb, sns, CAM_DIR_NONE, NULL, 0, sizeof(ALL_TUR_CDB));    tur = (ALL_TUR_CDB *) &(ccb->cam_cdb_io.cam_cdb_bytes[0]);  (void) bzero( (char *) tur, sizeof(ALL_TUR_CDB) );  tur->opcode = ALL_TUR_OP;    *ua_ccb_out = (RF_DiskOp_t *) ua_ccb;#endif /* !KERNEL */  return(0);}/******************************************************************************** * free a previously allocated RF_DiskOp_t.  Common to all alloc routines. *******************************************************************************/int rf_SCSI_FreeDiskOp(op, free_the_buf)  RF_DiskOp_t  *op;  int           free_the_buf;{#ifndef KERNEL  UAGT_CAM_CCB *ua_ccb = (UAGT_CAM_CCB *) op;  if (free_the_buf) {    RF_Free(ua_ccb->uagt_buffer, ua_ccb->uagt_buflen);  }  RF_Free(ua_ccb->uagt_snsbuf, sizeof(ALL_REQ_SNS_DATA));  RF_Free(ua_ccb->uagt_ccb, sizeof(CCB_SCSIIO));  RF_Free(ua_ccb, sizeof(UAGT_CAM_CCB));#endif /* !KERNEL */  return(0);}/*************************************************************************** *  rf_get_big_endian *    little-big endian conversion routine ***************************************************************************/static int rf_get_big_endian(buf, length)  unsigned char  *buf;  int             length;{  register long temp = 0;  int i;  for(i=0; i<length; i++)    temp = (temp << 8) | *buf++;  return(temp);}/******************************************************************************** * the next few routines actually do an operation, after it has been set up by * one of the allocation routines above ********************************************************************************/#ifdef KERNEL/* this gets invoked when a scsi command such as ccmn_tur completes. * copied from p. D-40 of device driver manual. */static void rf_done(ccb)  CCB_SCSIIO  *ccb;{  PDRV_DEVICE *pd;  int s;  pd = (PDRV_DEVICE *) ((PDRV_WS *) ccb->cam_pdrv_ptr)->pws_pdrv;  if (!pd) RF_PANIC();  PDRV_IPLSMP_LOCK(pd, LK_RETRY, s);  if (!ccb->cam_req_map) {              /* not really necessary (yet) b/c we only use this for TUR and READ CAP */    wakeup(ccb);  }  PDRV_IPLSMP_UNLOCK(pd, s);}#endif /* KERNEL *//******************************************************************************** * generic routine to perform an op, called from "do" routines below ********************************************************************************/static int rf_do_scsi_op(dev, ua_ccb, str, max_retries)  dev_t          dev;  UAGT_CAM_CCB  *ua_ccb;      /* user agent ccb for comm to cam layer */  char          *str;         /* identify what op we're doing for err report */  int            max_retries; /* max number of allowable retries */{  CCB_SCSIIO *ccb = (CCB_SCSIIO *) ua_ccb->uagt_ccb;  int status = 0;#ifdef KERNEL  PDRV_DEVICE *pdrv_ptr;  pdrv_ptr = GET_PDRV_PTR(dev);#endif /* KERNEL */  for (; max_retries>=0; max_retries--) {#ifndef KERNEL    if (ioctl(camfd, UAGT_CAM_IO, (caddr_t) ua_ccb) < 0) {      fprintf(stderr,"%s: ",str);      perror("Error on CAM UAGT ioctl:");      return(-1);        /* no retry in this case */    }    if (ccb->cam_ch.cam_status != CAM_REQ_CMP) {      RF_ERRORMSG1("SCSI CAM error on %s\n",str);      rf_print_ccb_status( &(ccb->cam_ch) );      if (ccb->cam_ch.cam_status & CAM_SIM_QFRZN)        rf_release_sim_queue(ccb);      continue;    } else break;#else  /* KERNEL */    status = ccmn_send_ccb_wait(pdrv_ptr, ccb, 0, WAIT_PRIORITY);    if (!status) break;#endif /* KERNEL */      }  return(status);}/* do a TEST UNIT READY.  bus,targ,lun is actually redundant since we have dev.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -