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

📄 cmd_scsi.c

📁 F:worksip2440a board可启动u-boot-like.tar.gz F:worksip2440a board可启动u-boot-like.tar.gz
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * (C) Copyright 2001 * Denis Peter, MPL AG Switzerland * * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * * * *//* * SCSI support. */#include <common.h>#include <command.h>#include <asm/processor.h>#include <scsi.h>#include <image.h>#include <pci.h>#undef	SCSI_DEBUG#ifdef	SCSI_DEBUG#define	PRINTF(fmt,args...)	printf (fmt ,##args)#else#define PRINTF(fmt,args...)#endif#if (CONFIG_COMMANDS & CFG_CMD_SCSI)#ifdef CONFIG_SCSI_SYM53C8XX#define SCSI_VEND_ID	0x1000#ifndef CONFIG_SCSI_DEV_ID#define SCSI_DEV_ID		0x0001#else#define SCSI_DEV_ID		CONFIG_SCSI_DEV_ID#endif#else#error CONFIG_SCSI_SYM53C8XX must be defined#endifstatic ccb tempccb;	/* temporary scsi command buffer */static unsigned char tempbuff[512]; /* temporary data buffer */static int scsi_max_devs; /* number of highest available scsi device */static int scsi_curr_dev; /* current device */static block_dev_desc_t scsi_dev_desc[CFG_SCSI_MAX_DEVICE];/******************************************************************************** *  forward declerations of some Setup Routines */void scsi_setup_test_unit_ready(ccb * pccb);void scsi_setup_read_capacity(ccb * pccb);void scsi_setup_read6(ccb * pccb, unsigned long start, unsigned short blocks);void scsi_setup_read_ext(ccb * pccb, unsigned long start, unsigned short blocks);void scsi_setup_inquiry(ccb * pccb);void scsi_ident_cpy (unsigned char *dest, unsigned char *src, unsigned int len);ulong scsi_read(int device, ulong blknr, ulong blkcnt, ulong *buffer);/********************************************************************************* * (re)-scan the scsi bus and reports scsi device info * to the user if mode = 1 */void scsi_scan(int mode){	unsigned char i,perq,modi,lun;	unsigned long capacity,blksz;	ccb* pccb=(ccb *)&tempccb;	if(mode==1) {		printf("scanning bus for devices...\n");	}	for(i=0;i<CFG_SCSI_MAX_DEVICE;i++) {		scsi_dev_desc[i].target=0xff;		scsi_dev_desc[i].lun=0xff;		scsi_dev_desc[i].lba=0;		scsi_dev_desc[i].blksz=0;		scsi_dev_desc[i].type=DEV_TYPE_UNKNOWN;		scsi_dev_desc[i].vendor[0]=0;		scsi_dev_desc[i].product[0]=0;		scsi_dev_desc[i].revision[0]=0;		scsi_dev_desc[i].removable=FALSE;		scsi_dev_desc[i].if_type=IF_TYPE_SCSI;		scsi_dev_desc[i].dev=i;		scsi_dev_desc[i].part_type=PART_TYPE_UNKNOWN;		scsi_dev_desc[i].block_read=scsi_read;	}	scsi_max_devs=0;	for(i=0;i<CFG_SCSI_MAX_SCSI_ID;i++) {		pccb->target=i;		for(lun=0;lun<CFG_SCSI_MAX_LUN;lun++) {			pccb->lun=lun;			pccb->pdata=(unsigned char *)&tempbuff;			pccb->datalen=512;			scsi_setup_inquiry(pccb);			if(scsi_exec(pccb)!=TRUE) {				if(pccb->contr_stat==SCSI_SEL_TIME_OUT) {					PRINTF("Selection timeout ID %d\n",pccb->target);					continue; /* selection timeout => assuming no device present */				}				scsi_print_error(pccb);				continue;			}			perq=tempbuff[0];			modi=tempbuff[1];			if((perq & 0x1f)==0x1f) {				continue; /* skip unknown devices */			}			if((modi&0x80)==0x80) /* drive is removable */				scsi_dev_desc[scsi_max_devs].removable=TRUE;			/* get info for this device */			scsi_ident_cpy(&scsi_dev_desc[scsi_max_devs].vendor[0],&tempbuff[8],8);			scsi_ident_cpy(&scsi_dev_desc[scsi_max_devs].product[0],&tempbuff[16],16);			scsi_ident_cpy(&scsi_dev_desc[scsi_max_devs].revision[0],&tempbuff[32],4);			scsi_dev_desc[scsi_max_devs].target=pccb->target;			scsi_dev_desc[scsi_max_devs].lun=pccb->lun;			pccb->datalen=0;			scsi_setup_test_unit_ready(pccb);			if(scsi_exec(pccb)!=TRUE) {				if(scsi_dev_desc[scsi_max_devs].removable==TRUE) {					scsi_dev_desc[scsi_max_devs].type=perq;					goto removable;				}				scsi_print_error(pccb);				continue;			}			pccb->datalen=8;			scsi_setup_read_capacity(pccb);			if(scsi_exec(pccb)!=TRUE) {				scsi_print_error(pccb);				continue;			}			capacity=((unsigned long)tempbuff[0]<<24)|((unsigned long)tempbuff[1]<<16)|					((unsigned long)tempbuff[2]<<8)|((unsigned long)tempbuff[3]);			blksz=((unsigned long)tempbuff[4]<<24)|((unsigned long)tempbuff[5]<<16)|				((unsigned long)tempbuff[6]<<8)|((unsigned long)tempbuff[7]);			scsi_dev_desc[scsi_max_devs].lba=capacity;			scsi_dev_desc[scsi_max_devs].blksz=blksz;			scsi_dev_desc[scsi_max_devs].type=perq;			init_part(&scsi_dev_desc[scsi_max_devs]);removable:			if(mode==1) {				printf ("  Device %d: ", scsi_max_devs);				dev_print(&scsi_dev_desc[scsi_max_devs]);			} /* if mode */			scsi_max_devs++;		} /* next LUN */	}	if(scsi_max_devs>0)		scsi_curr_dev=0;	else		scsi_curr_dev=-1;}void scsi_init(void){	int busdevfunc;	busdevfunc=pci_find_device(SCSI_VEND_ID,SCSI_DEV_ID,0); /* get PCI Device ID */	if(busdevfunc==-1) {		printf("Error SCSI Controller (%04X,%04X) not found\n",SCSI_VEND_ID,SCSI_DEV_ID);		return;	}#ifdef DEBUG	else {		printf("SCSI Controller (%04X,%04X) found (%d:%d:%d)\n",SCSI_VEND_ID,SCSI_DEV_ID,(busdevfunc>>16)&0xFF,(busdevfunc>>11)&0x1F,(busdevfunc>>8)&0x7);	}#endif	scsi_low_level_init(busdevfunc);	scsi_scan(1);}block_dev_desc_t * scsi_get_dev(int dev){	return((block_dev_desc_t *)&scsi_dev_desc[dev]);}/****************************************************************************** * scsi boot command intepreter. Derived from diskboot */int do_scsiboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]){	char *boot_device = NULL;	char *ep;	int dev, part = 0;	ulong cnt;	ulong addr;	disk_partition_t info;	image_header_t *hdr;	int rcode = 0;	switch (argc) {	case 1:		addr = CFG_LOAD_ADDR;		boot_device = getenv ("bootdevice");		break;	case 2:		addr = simple_strtoul(argv[1], NULL, 16);		boot_device = getenv ("bootdevice");		break;	case 3:		addr = simple_strtoul(argv[1], NULL, 16);		boot_device = argv[2];		break;	default:		printf ("Usage:\n%s\n", cmdtp->usage);		return 1;	}	if (!boot_device) {		puts ("\n** No boot device **\n");		return 1;	}	dev = simple_strtoul(boot_device, &ep, 16);	printf("booting from dev %d\n",dev);	if (scsi_dev_desc[dev].type == DEV_TYPE_UNKNOWN) {		printf ("\n** Device %d not available\n", dev);		return 1;	}	if (*ep) {		if (*ep != ':') {			puts ("\n** Invalid boot device, use `dev[:part]' **\n");			return 1;		}		part = simple_strtoul(++ep, NULL, 16);	}	if (get_partition_info (&scsi_dev_desc[dev], part, &info)) {		printf("error reading partinfo\n");		return 1;	}	if ((strncmp(info.type, BOOT_PART_TYPE, sizeof(info.type)) != 0) &&	    (strncmp(info.type, BOOT_PART_COMP, sizeof(info.type)) != 0)) {		printf ("\n** Invalid partition type \"%.32s\""			" (expect \"" BOOT_PART_TYPE "\")\n",			info.type);		return 1;	}	printf ("\nLoading from SCSI device %d, partition %d: "		"Name: %.32s  Type: %.32s\n",		dev, part, info.name, info.type);	PRINTF ("First Block: %ld,  # of blocks: %ld, Block Size: %ld\n",		info.start, info.size, info.blksz);	if (scsi_read (dev, info.start, 1, (ulong *)addr) != 1) {		printf ("** Read error on %d:%d\n", dev, part);		return 1;	}	hdr = (image_header_t *)addr;	if (hdr->ih_magic == IH_MAGIC) {		print_image_hdr (hdr);		cnt = (hdr->ih_size + sizeof(image_header_t));		cnt += info.blksz - 1;		cnt /= info.blksz;		cnt -= 1;	} else {		printf("\n** Bad Magic Number **\n");		return 1;	}	if (scsi_read (dev, info.start+1, cnt,		      (ulong *)(addr+info.blksz)) != cnt) {

⌨️ 快捷键说明

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