scsi_targ_bh.c
来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 723 行 · 第 1/2 页
C
723 行
/* * Implementation of the Target Mode 'Black Hole device' for CAM. * * Copyright (c) 1999 Justin T. Gibbs. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions, and the following disclaimer, * without modification, immediately at the beginning of the file. * 2. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: scsi_targ_bh.c,v 1.1.2.1 1999/03/07 00:40:31 gibbs Exp $ */#include <stddef.h> /* For offsetof */#include <sys/param.h>#include <sys/queue.h>#include <sys/systm.h>#include <sys/kernel.h>#include <sys/types.h>#include <sys/buf.h>#include <sys/conf.h>#include <sys/devicestat.h>#include <sys/malloc.h>#include <sys/uio.h>#include <cam/cam.h>#include <cam/cam_ccb.h>#include <cam/cam_extend.h>#include <cam/cam_periph.h>#include <cam/cam_queue.h>#include <cam/cam_xpt_periph.h>#include <cam/cam_debug.h>#include <cam/scsi/scsi_all.h>#include <cam/scsi/scsi_message.h>typedef enum { TARGBH_STATE_NORMAL, TARGBH_STATE_EXCEPTION, TARGBH_STATE_TEARDOWN} targbh_state;typedef enum { TARGBH_FLAG_NONE = 0x00, TARGBH_FLAG_LUN_ENABLED = 0x01} targbh_flags;typedef enum { TARGBH_CCB_WORKQ, TARGBH_CCB_WAITING} targbh_ccb_types;#define MAX_ACCEPT 8#define MAX_IMMEDIATE 16#define MAX_BUF_SIZE 256 /* Max inquiry/sense/mode page transfer */#define MIN(a, b) ((a > b) ? b : a)/* Offsets into our private CCB area for storing accept information */#define ccb_type ppriv_field0#define ccb_descr ppriv_ptr1/* We stick a pointer to the originating accept TIO in each continue I/O CCB */#define ccb_atio ppriv_ptr1TAILQ_HEAD(ccb_queue, ccb_hdr);struct targbh_softc { struct ccb_queue pending_queue; struct ccb_queue work_queue; struct ccb_queue unknown_atio_queue; struct devstat device_stats; targbh_state state; targbh_flags flags; u_int init_level; u_int inq_data_len; struct ccb_accept_tio *accept_tio_list; struct ccb_hdr_slist immed_notify_slist;};struct targbh_cmd_desc { struct ccb_accept_tio* atio_link; u_int data_resid; /* How much left to transfer */ u_int data_increment;/* Amount to send before next disconnect */ void* data; /* The data. Can be from backing_store or not */ void* backing_store;/* Backing store allocated for this descriptor*/ u_int max_size; /* Size of backing_store */ u_int32_t timeout; u_int8_t status; /* Status to return to initiator */};static struct scsi_inquiry_data no_lun_inq_data ={ T_NODEVICE | (SID_QUAL_BAD_LU << 5), 0, /* version */2, /* format version */2};static struct scsi_sense_data no_lun_sense_data ={ SSD_CURRENT_ERROR|SSD_ERRCODE_VALID, 0, SSD_KEY_NOT_READY, { 0, 0, 0, 0 }, /*extra_len*/offsetof(struct scsi_sense_data, fru) - offsetof(struct scsi_sense_data, extra_len), { 0, 0, 0, 0 }, /* Logical Unit Not Supported */ /*ASC*/0x25, /*ASCQ*/0};static const int request_sense_size = offsetof(struct scsi_sense_data, fru);static periph_init_t targbhinit;static void targbhasync(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg);static cam_status targbhenlun(struct cam_periph *periph);static cam_status targbhdislun(struct cam_periph *periph);static periph_ctor_t targbhctor;static periph_dtor_t targbhdtor;static periph_start_t targbhstart;static void targbhdone(struct cam_periph *periph, union ccb *done_ccb);#ifdef NOTYETstatic int targbherror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags);#endifstatic struct targbh_cmd_desc* targbhallocdescr(void);static void targbhfreedescr(struct targbh_cmd_desc *buf); static struct periph_driver targbhdriver ={ targbhinit, "targbh", TAILQ_HEAD_INITIALIZER(targbhdriver.units), /* generation */ 0};DATA_SET(periphdriver_set, targbhdriver);static voidtargbhinit(void){ cam_status status; struct cam_path *path; /* * Install a global async callback. This callback will * receive async callbacks like "new path registered". */ status = xpt_create_path(&path, /*periph*/NULL, CAM_XPT_PATH_ID, CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD); if (status == CAM_REQ_CMP) { struct ccb_setasync csa; xpt_setup_ccb(&csa.ccb_h, path, /*priority*/5); csa.ccb_h.func_code = XPT_SASYNC_CB; csa.event_enable = AC_PATH_REGISTERED; csa.callback = targbhasync; csa.callback_arg = NULL; xpt_action((union ccb *)&csa); status = csa.ccb_h.status; xpt_free_path(path); } if (status != CAM_REQ_CMP) { printf("targbh: Failed to attach master async callback " "due to status 0x%x!\n", status); }}static voidtargbhasync(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg){ struct cam_periph *periph; periph = (struct cam_periph *)callback_arg; switch (code) { case AC_PATH_REGISTERED: { struct ccb_pathinq *cpi; struct cam_path *new_path; cam_status status; cpi = (struct ccb_pathinq *)arg; /* Only attach to controllers that support target mode */ if ((cpi->target_sprt & PIT_PROCESSOR) == 0) break; /* * Allocate a peripheral instance for * this target instance. */ status = xpt_create_path(&new_path, NULL, xpt_path_path_id(path), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD); if (status != CAM_REQ_CMP) { printf("targbhasync: Unable to create path " "due to status 0x%x\n", status); break; } status = cam_periph_alloc(targbhctor, NULL, targbhdtor, targbhstart, "targbh", CAM_PERIPH_BIO, new_path, targbhasync, AC_PATH_REGISTERED, cpi); xpt_free_path(new_path); if (status != CAM_REQ_CMP && status != CAM_REQ_INPROG) printf("targbhasync: Unable to allocate new periph " "due to status 0x%x\n", status); break; } case AC_PATH_DEREGISTERED: { targbhdislun(periph); break; } default: break; }}/* Attempt to enable our lun */static cam_statustargbhenlun(struct cam_periph *periph){ union ccb immed_ccb; struct targbh_softc *softc; cam_status status; int i; softc = (struct targbh_softc *)periph->softc; if ((softc->flags & TARGBH_FLAG_LUN_ENABLED) != 0) return (CAM_REQ_CMP); xpt_setup_ccb(&immed_ccb.ccb_h, periph->path, /*priority*/1); immed_ccb.ccb_h.func_code = XPT_EN_LUN; /* Don't need support for any vendor specific commands */ immed_ccb.cel.grp6_len = 0; immed_ccb.cel.grp7_len = 0; immed_ccb.cel.enable = 1; xpt_action(&immed_ccb); status = immed_ccb.ccb_h.status; if (status != CAM_REQ_CMP) { xpt_print_path(periph->path); printf("targbhenlun - Enable Lun Rejected for status 0x%x\n", status); return (status); } softc->flags |= TARGBH_FLAG_LUN_ENABLED; /* * Build up a buffer of accept target I/O * operations for incoming selections. */ for (i = 0; i < MAX_ACCEPT; i++) { struct ccb_accept_tio *atio; atio = (struct ccb_accept_tio*)malloc(sizeof(*atio), M_DEVBUF, M_NOWAIT); if (atio == NULL) { status = CAM_RESRC_UNAVAIL; break; } atio->ccb_h.ccb_descr = targbhallocdescr(); if (atio->ccb_h.ccb_descr == NULL) { free(atio, M_DEVBUF); status = CAM_RESRC_UNAVAIL; break; } xpt_setup_ccb(&atio->ccb_h, periph->path, /*priority*/1); atio->ccb_h.func_code = XPT_ACCEPT_TARGET_IO; atio->ccb_h.cbfcnp = targbhdone; xpt_action((union ccb *)atio); status = atio->ccb_h.status; if (status != CAM_REQ_INPROG) { targbhfreedescr(atio->ccb_h.ccb_descr); free(atio, M_DEVBUF); break; } ((struct targbh_cmd_desc*)atio->ccb_h.ccb_descr)->atio_link = softc->accept_tio_list; softc->accept_tio_list = atio; } if (i == 0) { xpt_print_path(periph->path); printf("targbhenlun - Could not allocate accept tio CCBs: " "status = 0x%x\n", status); targbhdislun(periph); return (CAM_REQ_CMP_ERR); } /* * Build up a buffer of immediate notify CCBs * so the SIM can tell us of asynchronous target mode events. */ for (i = 0; i < MAX_ACCEPT; i++) { struct ccb_immed_notify *inot; inot = (struct ccb_immed_notify*)malloc(sizeof(*inot), M_DEVBUF, M_NOWAIT); if (inot == NULL) { status = CAM_RESRC_UNAVAIL; break; } xpt_setup_ccb(&inot->ccb_h, periph->path, /*priority*/1); inot->ccb_h.func_code = XPT_IMMED_NOTIFY; inot->ccb_h.cbfcnp = targbhdone; xpt_action((union ccb *)inot); status = inot->ccb_h.status; if (status != CAM_REQ_INPROG) { free(inot, M_DEVBUF); break; } SLIST_INSERT_HEAD(&softc->immed_notify_slist, &inot->ccb_h, periph_links.sle); } if (i == 0) { xpt_print_path(periph->path); printf("targbhenlun - Could not allocate immediate notify " "CCBs: status = 0x%x\n", status); targbhdislun(periph); return (CAM_REQ_CMP_ERR); } return (CAM_REQ_CMP);}static cam_statustargbhdislun(struct cam_periph *periph){ union ccb ccb; struct targbh_softc *softc;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?