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

📄 scsi_debug.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Id: scsi_debug.c,v 1.1 1992/07/24 06:27:38 root Exp root $ *  linux/kernel/scsi_debug.c * *  Copyright (C) 1992  Eric Youngdale *  Simulate a host adapter with 2 disks attached.  Do a lot of checking *  to make sure that we are not getting blocks mixed up, and panic if *  anything out of the ordinary is seen. */#include <linux/module.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/errno.h>#include <linux/timer.h>#include <linux/types.h>#include <linux/string.h>#include <linux/genhd.h>#include <linux/fs.h>#include <linux/proc_fs.h>#include <asm/system.h>#include <asm/io.h>#ifdef MODULE#include <linux/module.h>#endif#include <linux/blk.h>#include "scsi.h"#include "hosts.h"#include "sd.h"#include<linux/stat.h>struct proc_dir_entry proc_scsi_scsi_debug = {    PROC_SCSI_SCSI_DEBUG, 10, "scsi_debug",    S_IFDIR | S_IRUGO | S_IXUGO, 2};/* A few options that we want selected */#define NR_HOSTS_PRESENT 20#define NR_FAKE_DISKS   6#define N_HEAD          32#define N_SECTOR        64#define DISK_READONLY(TGT)      (1)#define DISK_REMOVEABLE(TGT)    (1)/* Do not attempt to use a timer to simulate a real disk with latency *//* Only use this in the actual kernel, not in the simulator. *//* #define IMMEDIATE *//* Skip some consistency checking.  Good for benchmarking */#define SPEEDY/* Read return zeros. Undefine for benchmarking */#define CLEAR/* Number of real scsi disks that will be detected ahead of time */static int NR_REAL=-1;#define NR_BLK_DEV  12#ifndef MAJOR_NR#define MAJOR_NR 8#endif#define START_PARTITION 4/* Number of jiffies to wait before completing a command */#define DISK_SPEED     10#define CAPACITY (0x80000)static int starts[] = {N_HEAD, N_HEAD * N_SECTOR, 50000, CAPACITY, 0};static int npart = 0;#include "scsi_debug.h"#ifdef DEBUG#define DEB(x) x#else#define DEB(x)#endif#ifdef SPEEDY#define VERIFY1_DEBUG(RW) #define VERIFY_DEBUG(RW) #else#define VERIFY1_DEBUG(RW)                           \    if (bufflen != 1024) {printk("%d", bufflen); panic("(1)Bad bufflen");};         \    start = 0;                          \    if ((MINOR(SCpnt->request.rq_dev) & 0xf) != 0) start = starts[(MINOR(SCpnt->request.rq_dev) & 0xf) - 1];        \    if (bh){                            \	if (bh->b_size != 1024) panic ("Wrong bh size");    \	if ((bh->b_blocknr << 1) + start != block)          \	{   printk("Wrong bh block# %d %d ",bh->b_blocknr, block);  \	    panic ("Wrong bh block#"); \	};  \	if (bh->b_dev != SCpnt->request.rq_dev)  \	    panic ("Bad bh target"); \    };#define VERIFY_DEBUG(RW)                            \    if (bufflen != 1024 && (!SCpnt->use_sg)) {printk("%x %d\n ",bufflen, SCpnt->use_sg); panic("Bad bufflen");};    \    start = 0;                          \    if ((MINOR(SCpnt->request.rq_dev) & 0xf) > npart) panic ("Bad partition");    \    if ((MINOR(SCpnt->request.rq_dev) & 0xf) != 0) start = starts[(MINOR(SCpnt->request.rq_dev) & 0xf) - 1];        \    if (SCpnt->request.cmd != RW) panic ("Wrong  operation");       \    if (SCpnt->request.sector + start != block) panic("Wrong block.");  \    if (SCpnt->request.current_nr_sectors != 2 && (!SCpnt->use_sg)) panic ("Wrong # blocks");   \    if (SCpnt->request.bh){                         \	if (SCpnt->request.bh->b_size != 1024) panic ("Wrong bh size"); \	if ((SCpnt->request.bh->b_blocknr << 1) + start != block)           \	{   printk("Wrong bh block# %d %d ",SCpnt->request.bh->b_blocknr, block);  \	    panic ("Wrong bh block#"); \	};  \	if (SCpnt->request.bh->b_dev != SCpnt->request.rq_dev) \	    panic ("Bad bh target");\    };#endiftypedef void (*done_fct_t)(Scsi_Cmnd *);static volatile done_fct_t do_done[SCSI_DEBUG_MAILBOXES] = {NULL, };static void scsi_debug_intr_handle(unsigned long);static struct timer_list timeout[SCSI_DEBUG_MAILBOXES];Scsi_Cmnd * SCint[SCSI_DEBUG_MAILBOXES] = {NULL,};static char SCrst[SCSI_DEBUG_MAILBOXES] = {0,};/* * Semaphore used to simulate bus lockups. */static int scsi_debug_lockup = 0;static char sense_buffer[128] = {0,};static void scsi_dump(Scsi_Cmnd * SCpnt, int flag){    int i;#if 0    unsigned char * pnt;#endif    unsigned int * lpnt;    struct scatterlist * sgpnt = NULL;    printk("use_sg: %d",SCpnt->use_sg);    if (SCpnt->use_sg){	sgpnt = (struct scatterlist *) SCpnt->buffer;	for(i=0; i<SCpnt->use_sg; i++) {	    lpnt = (int *) sgpnt[i].alt_address;	    printk(":%p %p %d\n",sgpnt[i].alt_address, sgpnt[i].address, sgpnt[i].length);	    if (lpnt) printk(" (Alt %x) ",lpnt[15]);	};    } else {	printk("nosg: %p %p %d\n",SCpnt->request.buffer, SCpnt->buffer,	       SCpnt->bufflen);	lpnt = (int *) SCpnt->request.buffer;	if (lpnt) printk(" (Alt %x) ",lpnt[15]);    };    lpnt = (unsigned int *) SCpnt;    for (i=0;i<sizeof(Scsi_Cmnd)/4+1; i++) {	if ((i & 7) == 0) printk("\n");	printk("%x ",*lpnt++);    };    printk("\n");    if (flag == 0) return;    lpnt = (unsigned int *) sgpnt[0].alt_address;    for (i=0;i<sizeof(Scsi_Cmnd)/4+1; i++) {	if ((i & 7) == 0) printk("\n");	printk("%x ",*lpnt++);    };#if 0    printk("\n");    lpnt = (unsigned int *) sgpnt[0].address;    for (i=0;i<sizeof(Scsi_Cmnd)/4+1; i++) {	if ((i & 7) == 0) printk("\n");	printk("%x ",*lpnt++);    };    printk("\n");#endif    printk("DMA free %d sectors.\n", scsi_dma_free_sectors);}int scsi_debug_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)){    unchar *cmd = (unchar *) SCpnt->cmnd;    struct partition * p;    int block;    struct buffer_head * bh = NULL;    unsigned char * buff;    int nbytes, sgcount;    int scsi_debug_errsts;    struct scatterlist * sgpnt;    int target = SCpnt->target;    int bufflen = SCpnt->request_bufflen;    unsigned long flags;    int i;    sgcount = 0;    sgpnt = NULL;        /*     * If we are being notified of the mid-level reposessing a command due to timeout,     * just return.     */    if( done == NULL )    {        return 0;    }    DEB(if (target >= NR_FAKE_DISKS)         {             SCpnt->result = DID_TIME_OUT << 16;done(SCpnt);return 0;        });        buff = (unsigned char *) SCpnt->request_buffer;        if(target>=NR_FAKE_DISKS || SCpnt->lun != 0)     {	SCpnt->result =  DID_NO_CONNECT << 16;	done(SCpnt);	return 0;    }        if( SCrst[target] != 0 && !scsi_debug_lockup )    {        SCrst[target] = 0;        memset(SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer));        SCpnt->sense_buffer[0] = 0x70;        SCpnt->sense_buffer[2] = UNIT_ATTENTION;	SCpnt->result = (CHECK_CONDITION << 1);	done(SCpnt);             }    switch(*cmd){    case REQUEST_SENSE:	SCSI_LOG_LLQUEUE(3,printk("Request sense...\n"));#ifndef DEBUG	{ 	    int i;	    printk("scsi_debug: Requesting sense buffer (%p %p %p %d):", SCpnt, buff, done, bufflen);	    for(i=0;i<12;i++) printk("%d ",sense_buffer[i]);	    printk("\n");	};#endif	memset(buff, 0, bufflen);	memcpy(buff, sense_buffer, bufflen);	memset(sense_buffer, 0, sizeof(sense_buffer));	SCpnt->result = 0;	done(SCpnt); 	return 0;    case ALLOW_MEDIUM_REMOVAL:	if(cmd[4])         {            SCSI_LOG_LLQUEUE(2,printk("Medium removal inhibited..."));        }	else        {            SCSI_LOG_LLQUEUE(2,printk("Medium removal enabled..."));        }	scsi_debug_errsts = 0;	break;    case INQUIRY:	SCSI_LOG_LLQUEUE(3,printk("Inquiry...(%p %d)\n", buff, bufflen));	memset(buff, 0, bufflen);	buff[0] = TYPE_DISK;	buff[1] = DISK_REMOVEABLE(target) ? 0x80 : 0;  /* Removable disk */	buff[2] = 1;	buff[4] = 33 - 5;	memcpy(&buff[8],"Foo Inc",7);	memcpy(&buff[16],"XYZZY",5);	memcpy(&buff[32],"1",1);	scsi_debug_errsts = 0;	break;    case TEST_UNIT_READY:	SCSI_LOG_LLQUEUE(3,printk("Test unit ready(%p %d)\n", buff, bufflen));	if (buff)	    memset(buff, 0, bufflen);	scsi_debug_errsts = 0;	break;    case READ_CAPACITY:	SCSI_LOG_LLQUEUE(3,printk("Read Capacity\n"));	if(NR_REAL < 0) NR_REAL = (MINOR(SCpnt->request.rq_dev) >> 4) & 0x0f;	memset(buff, 0, bufflen);	buff[0] = (CAPACITY >> 24);	buff[1] = (CAPACITY >> 16) & 0xff;	buff[2] = (CAPACITY >> 8) & 0xff;	buff[3] = CAPACITY & 0xff;	buff[6] = 2; /* 512 byte sectors */	scsi_debug_errsts = 0;	break;    case READ_10:    case READ_6:#ifdef DEBUG	printk("Read...");#endif	if ((*cmd) == READ_10)	    block = cmd[5] + (cmd[4] << 8) + (cmd[3] << 16) + (cmd[2] << 24); 	else 	    block = cmd[3] + (cmd[2] << 8) + ((cmd[1] & 0x1f) << 16);	VERIFY_DEBUG(READ);#if defined(SCSI_SETUP_LATENCY) || defined(SCSI_DATARATE)    {	int delay = SCSI_SETUP_LATENCY;		delay += SCpnt->request.nr_sectors * SCSI_DATARATE;	if(delay) usleep(delay);    };#endif	#ifdef DEBUG	printk("(r%d)",SCpnt->request.nr_sectors);#endif	nbytes = bufflen;	if(SCpnt->use_sg){	    sgcount = 0;	    sgpnt = (struct scatterlist *) buff;	    buff = sgpnt[sgcount].address;	    bufflen = sgpnt[sgcount].length;	    bh = SCpnt->request.bh;	};	scsi_debug_errsts = 0;	do{	    VERIFY1_DEBUG(READ);	    /* For the speedy test, we do not even want to fill the buffer with anything */#ifdef CLEAR	    memset(buff, 0, bufflen);#endif	    /* If this is block 0, then we want to read the partition table for this	     * device.  Let's make one up */	    if(block == 0) {	    	int i;                memset(buff, 0, bufflen);		*((unsigned short *) (buff+510)) = 0xAA55;		p = (struct partition* ) (buff + 0x1be);		i = 0;		while(starts[i+1]){		    p->start_sect = starts[i];		    p->nr_sects = starts[i+1] - starts [i];		    p->sys_ind = 0x81;  /* Linux partition */                    p->head       = (i == 0 ? 1 : 0);                    p->sector     = 1;                    p->cyl        = starts[i] / N_HEAD / N_SECTOR;                    p->end_head   = N_HEAD - 1;                    p->end_sector = N_SECTOR;                    p->end_cyl    = starts[i + 1] / N_HEAD / N_SECTOR;		    p++;		    i++;		};		if (!npart) npart = i;		scsi_debug_errsts = 0;		break;	    };#ifdef DEBUG	    if (SCpnt->use_sg) printk("Block %x (%d %d)\n",block, SCpnt->request.nr_sectors,				      SCpnt->request.current_nr_sectors);#endif	    #if 0	    /* Simulate a disk change */	    if(block == 0xfff0) {		sense_buffer[0] = 0x70;		sense_buffer[2] = UNIT_ATTENTION;		starts[0] += 10;

⌨️ 快捷键说明

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