📄 scsi_target.c
字号:
kmalloc(SGS_SIZE(sizeof (inqdata)), GFP_ATOMIC|GFP_DMA); if (dp == NULL) { printk("scsi_target_alloc: out of memory for inquiry data\n"); spin_lock_irqsave(&scsi_target_lock, flags); add_sdata(ini, ifailure); spin_unlock_irqrestore(&scsi_target_lock, flags); tmd->cd_hflags |= CDFH_SNSVALID; } else { dp->alt_address = NULL; dp->address = SGS_PAYLOAD(dp, char *); dp->length = min(sizeof(inqdata), tmd->cd_totlen); tmd->cd_xfrlen = dp->length; memcpy(dp->address, inqdata, sizeof (inqdata)); /* * If we're not here, say we aren't here. */ if (tmd->cd_lun >= MAX_LUN || tmd->cd_bus >= 2) { dp->address[0] = (3 << 5) | DEFAULT_DEVICE_TYPE; } else if (bp->luns[tmd->cd_bus][tmd->cd_lun] == 0) { dp->address[0] = (1 << 5) | DEFAULT_DEVICE_TYPE; } tmd->cd_data = dp; tmd->cd_hflags |= CDFH_DATA_IN|CDFH_STSVALID; SDprintk2("scsi_target(%s%d): %p (%p) length %d byte0 0x%x\n", bp->h.r_name, bp->h.r_inst, dp->address, dp, dp->length, inqdata[0] & 0xff); tmd->cd_hflags |= CDFH_PRIVATE_0; } } else { SDprintk2("scsi_target(%s%d): illegal field for inquiry data\n", bp->h.r_name, bp->h.r_inst); spin_lock_irqsave(&scsi_target_lock, flags); add_sdata(ini, illfld); spin_unlock_irqrestore(&scsi_target_lock, flags); tmd->cd_hflags |= CDFH_SNSVALID; } goto doit; }#if 0 if (tmd->cd_lun != 0) { spin_lock_irqsave(&scsi_target_lock, flags); add_sdata(ini, notrdy); spin_unlock_irqrestore(&scsi_target_lock, flags); tmd->cd_hflags |= CDFH_SNSVALID; goto doit; }#endif if (tmd->cd_cdb[0] == REQUEST_SENSE) { struct scatterlist *dp = NULL; if (tmd->cd_totlen == 0) tmd->cd_totlen = tmd->cd_cdb[4]; if (tmd->cd_totlen != 0) { dp = (struct scatterlist *) kmalloc(SGS_SIZE(QLTM_SENSELEN), GFP_ATOMIC|GFP_DMA); if (dp == NULL) { printk("scsi_target_alloc: out of memory for sense data\n"); spin_lock_irqsave(&scsi_target_lock, flags); add_sdata(ini, ifailure); spin_unlock_irqrestore(&scsi_target_lock, flags); tmd->cd_hflags |= CDFH_SNSVALID; } else { if (ini->ini_sdata == NULL) { spin_lock_irqsave(&scsi_target_lock, flags); add_sdata(ini, nosense); spin_unlock_irqrestore(&scsi_target_lock, flags); } dp->alt_address = NULL; dp->address = SGS_PAYLOAD(dp, char *); dp->length = min(QLTM_SENSELEN, tmd->cd_totlen); tmd->cd_xfrlen = dp->length; memcpy(dp->address, ini->ini_sdata->sdata, QLTM_SENSELEN); tmd->cd_data = dp; tmd->cd_hflags |= CDFH_DATA_IN; SDprintk2("sense data in scsi_target for %s%d: %p (%p) len %d, " "key/asc/ascq 0x%x/0x%x/0x%x\n", bp->h.r_name, bp->h.r_inst, dp->address, dp, dp->length, dp->address[2]&0xf, dp->address[12]&0xff, dp->address[13]); tmd->cd_hflags |= CDFH_PRIVATE_0; } } tmd->cd_hflags |= CDFH_STSVALID; } else if (tmd->cd_cdb[0] == TEST_UNIT_READY) { tmd->cd_hflags |= CDFH_STSVALID; if (ini->ini_sdata) tmd->cd_hflags |= CDFH_SNSVALID; } else { tmd->cd_hflags |= CDFH_SNSVALID; spin_lock_irqsave(&scsi_target_lock, flags); add_sdata(ini, nolun); spin_unlock_irqrestore(&scsi_target_lock, flags); } if ((tmd->cd_hflags & CDFH_SNSVALID) == 0) { if (ini->ini_sdata) { tmd->cd_hflags |= CDFH_SNSVALID; } }doit: tmd->cd_resid = tmd->cd_totlen; if (tmd->cd_hflags & CDFH_SNSVALID) { tmd->cd_scsi_status = SCSI_CHECK; tmd->cd_hflags |= CDFH_STSVALID; memcpy(tmd->cd_sense, ini->ini_sdata->sdata, QLTM_SENSELEN); } SDprintk("INI%d-Lun%d: tag0x%x cdb0=0x%x totlen=%d ssts=0x%x hflags 0x%x\n", (int) tmd->cd_iid, (int) tmd->cd_lun, tmd->cd_tagval, tmd->cd_cdb[0] & 0xff, tmd->cd_totlen, tmd->cd_scsi_status, tmd->cd_hflags); (*bp->h.r_action)(QIN_TMD_CONT, tmd);}static inline voidscsi_target_ldfree(tmd_cmd_t *tmd){ if (tmd->cd_hflags & CDFH_PRIVATE_0) { SDprintk("scsi_target: freeing tmd->cd_data %p\n", tmd->cd_data); kfree(tmd->cd_data); tmd->cd_hflags &= ~0x80; tmd->cd_data = NULL; }}voidscsi_target_handler(qact_e action, void *arg){ unsigned long flags; bus_t *bp; switch (action) { case QOUT_HBA_REG: { tmd_cmd_t local; hba_register_t local1; spin_lock_irqsave(&scsi_target_lock, flags); for (bp = busses; bp < &busses[MAX_BUS]; bp++) { if (bp->h.r_action == NULL) { break; } } if (bp == &busses[MAX_BUS]) { printk("scsi_target: cannot register any more SCSI busses\n"); break; } bp->h = *(hba_register_t *) arg; bp->h.r_name[6] = 0; bp->h.r_name[7] = 0; spin_unlock_irqrestore(&scsi_target_lock, flags); printk("scsi_target: registering %s%d\n", bp->h.r_name, bp->h.r_inst); local.cd_hba = bp->h.r_identity; local.cd_data = &local1; local1.r_identity = bp; local1.r_action = (void (*)(int, void *)) scsi_target_handler; (*bp->h.r_action)(QIN_HBA_REG, &local); break; } case QOUT_TMD_START: { tmd_cmd_t *tmd = arg; tmd->cd_private = NULL; spin_lock_irqsave(&scsi_target_lock, flags); bp = bus_from_tmd(arg, 0); if (bp == NULL) { printk("scsi_target: bogus QOUT_TMD_START (%p)\n", arg); spin_unlock_irqrestore(&scsi_target_lock, flags); break; } SDprintk2("scsi_target: TMD_START from %s%d\n", bp->h.r_name, bp->h.r_inst); if (p_front) { p_last->cd_private = tmd; } else { p_front = tmd; } p_last = tmd; if (scsi_target_thread_notified == 0) { up(&scsi_thread_sleep_semaphore); scsi_target_thread_notified++; } spin_unlock_irqrestore(&scsi_target_lock, flags); break; } case QOUT_TMD_DONE: { tmd_cmd_t *tmd = arg; ini_t *nptr; spin_lock_irqsave(&scsi_target_lock, flags); bp = bus_from_tmd(tmd, 1); if (bp == NULL) { printk("scsi_target: bogus QOUT_TMD_DONE(%p)\n", arg); spin_unlock_irqrestore(&scsi_target_lock, flags); break; } nptr = ini_from_tmd(bp, tmd); SDprintk2("scsi_target: TMD_DONE from %s%d (0x%x)\n", bp->h.r_name, bp->h.r_inst, tmd->cd_lflags); if (tmd->cd_hflags & CDFH_STSVALID) { if ((tmd->cd_lflags & CDFL_SENTSTATUS) == 0) { if (tmd->cd_xfrlen) { SDprintk("scsi_target: data done, now do status\n"); scsi_target_ldfree(tmd); tmd->cd_xfrlen = 0; spin_unlock_irqrestore(&scsi_target_lock, flags); (*bp->h.r_action)(QIN_TMD_CONT, tmd); break; } printk("scsi_target: already tried to send status\n"); scsi_target_ldfree(tmd); spin_unlock_irqrestore(&scsi_target_lock, flags); (*bp->h.r_action)(QIN_TMD_FIN, arg); break; } } /* * Was sense valid? Do we know whom we were talking to? * If so, and we sent sense, remove the Sense Data that's * current for this initiator. */ if (tmd->cd_hflags & CDFH_SNSVALID) { if (nptr) { if (tmd->cd_lflags & CDFL_SENTSENSE) { rem_sdata(nptr); } } } /* * Was this a REQUEST SENSE command? If so, * remove any sense data for this initiator * which we might have sent. * * XXX: Actually, we should remove it once * XXX: we make it data we would actually * XXX: send. */ if (tmd->cd_cdb[0] == REQUEST_SENSE) { if (nptr) { rem_sdata(nptr); } } scsi_target_ldfree(tmd); spin_unlock_irqrestore(&scsi_target_lock, flags); (*bp->h.r_action)(QIN_TMD_FIN, arg); break; } case QOUT_TEVENT: spin_lock_irqsave(&scsi_target_lock, flags); bp = bus_from_tmd(arg, 1); if (bp == NULL) { spin_unlock_irqrestore(&scsi_target_lock, flags); printk("scsi_target: bogus QOUT_TMD_EVENT (%p)\n", arg); break; } SDprintk("scsi_target: TEVENT from %s%d\n", bp->h.r_name, bp->h.r_inst); spin_unlock_irqrestore(&scsi_target_lock, flags); break; case QOUT_TMSG: spin_lock_irqsave(&scsi_target_lock, flags); bp = bus_from_tmd(arg, 1); if (bp == NULL) { spin_unlock_irqrestore(&scsi_target_lock, flags); printk("scsi_target: bogus QOUT_TMD_MSG (%p)\n", arg); break; } printk("scsi_target: XXXX TMSG from %s%d\n", bp->h.r_name, bp->h.r_inst); spin_unlock_irqrestore(&scsi_target_lock, flags); break; case QOUT_HBA_UNREG: spin_lock_irqsave(&scsi_target_lock, flags); bp = bus_from_tmd(arg, 0); if (bp == NULL) { spin_unlock_irqrestore(&scsi_target_lock, flags); printk("scsi_target: bogus QOUT_HBA_UNREG (%p)\n", arg); break; } printk("scsi_target: unregistering %s%d\n", bp->h.r_name, bp->h.r_inst); memset(bp, 0, sizeof (*bp)); spin_unlock_irqrestore(&scsi_target_lock, flags); break; default: printk("scsi_target: action code %d (0x%x)?\n", action, action); break; }}static intscsi_target_thread(void *arg){ unsigned long flags; siginitsetinv(¤t->blocked, 0); lock_kernel(); daemonize(); sprintf(current->comm, "scsi_target_thread"); unlock_kernel(); up(&scsi_thread_entry_exit_semaphore); SDprintk("scsi_target_thread starting\n"); while (scsi_target_thread_exit == 0) { bus_t *bp; tmd_cmd_t *tp; SDprintk2("scsi_task_thread sleeping\n"); down(&scsi_thread_sleep_semaphore); SDprintk2("scsi_task_thread running\n"); spin_lock_irqsave(&scsi_target_lock, flags); scsi_target_thread_notified = 0; if ((tp = p_front) != NULL) { p_last = p_front = NULL; } spin_unlock_irqrestore(&scsi_target_lock, flags); while (tp) { tmd_cmd_t *active; active = tp; tp = active->cd_private; active->cd_private = NULL; bp = bus_from_tmd(active, 1); if (bp == NULL) { panic("Lost the Bus?"); } scsi_target_start_cmd(active, bp); } } SDprintk("scsi_target_thread exiting\n"); up(&scsi_thread_entry_exit_semaphore); return(0);}static intscsi_target_endis(char *hba_name_unit, int channel, int target, int lun, int en){ tmd_cmd_t ec; bus_t *bp;/* * XXX: yes, there is a race condition here where the bus can * XXX: go away. But in order to solve it, we have to make the * XXX: bus structure stay around while we call into the HBA * XXX: anyway, so fooey,. */ bp = bus_from_name(hba_name_unit); if (bp == NULL) { return (-ENXIO); } if (channel > 1 || channel < 0 || lun < 0 || lun >= MAX_LUN) { return (-EINVAL); } memset(&ec, 0, sizeof (ec)); ec.cd_hba = bp->h.r_identity; ec.cd_bus = channel; ec.cd_iid = target; ec.cd_lun = lun; (*bp->h.r_action)(en? QIN_ENABLE : QIN_DISABLE, &ec); if (ec.cd_lflags & CDFL_ERROR) { return (ec.cd_error); } else { bp->luns[channel][lun] = (en != 0); return (0); }}#ifdef MODULE#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)EXPORT_SYMBOL_NOVERS(scsi_target_handler);MODULE_PARM(scsi_tdebug, "i");#endifint init_module(void){ int r = scsi_target_init(); if (r == 0) { for (r = N_SENSE_BUFS; r > 0; r--) { sdata_t *t = kmalloc(sizeof (sdata_t), GFP_KERNEL); if (t) { t->next = sdp; sdp = t; } } } return (r);}void cleanup_module(void){ int i; scsi_target_thread_exit = 1; up(&scsi_thread_sleep_semaphore); down(&scsi_thread_entry_exit_semaphore); for (i = 0; i < MAX_BUS; i++) { if (busses[i].h.r_action) { int j; tmd_cmd_t tmd; tmd.cd_hba = busses[i].h.r_identity; (*busses[i].h.r_action)(QIN_HBA_UNREG, &tmd); busses[i].h.r_action = NULL; for (j = 0; j < HASH_WIDTH; j++) { ini_t *nptr = busses[i].list[j]; while (nptr) { ini_t *next = nptr->ini_next; kfree(nptr); nptr = next; } } } } while (sdp) { sdata_t *t = sdp->next; kfree(sdp); sdp = t; }#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) && defined(CONFIG_PROC_FS) if (st) { remove_proc_entry("scsi/scsi_target", 0); }#endif if (misc_deregister(&scsi_target_dev)) { printk("scsi_target: warning- could not deregister\n"); }}#endif/* * mode: c * Local variables: * c-indent-level: 4 * c-brace-imaginary-offset: 0 * c-brace-offset: -4 * c-argdecl-indent: 4 * c-label-offset: -4 * c-continued-statement-offset: 4 * c-continued-brace-offset: 0 * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -