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

📄 voyager_cat.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
			return 1;		}		outb(VOYAGER_CAT_HEADER, CAT_DATA);		outb(value, CAT_DATA);		if(inb(CAT_DATA) != VOYAGER_CAT_HEADER) {			CDEBUG(("cat_senddata: failed to get correct header response to sent data\n"));			return 1;		}		if(reg > VOYAGER_SUBADDRHI) {			outb(VOYAGER_CAT_RUN, CAT_CMD);			outb(VOYAGER_CAT_END, CAT_CMD);			outb(VOYAGER_CAT_RUN, CAT_CMD);		}				return 0;	}	else {		__u16 hbytes = asicp->ireg_length / BITS_PER_BYTE;		__u16 dbytes = (modp->num_asics - 1 + asicp->ireg_length)/BITS_PER_BYTE;		__u8 padbits, dseq[VOYAGER_MAX_SCAN_PATH], 			hseq[VOYAGER_MAX_REG_SIZE];		int i;		if((padbits = (modp->num_asics - 1 			       + asicp->ireg_length) % BITS_PER_BYTE) != 0) {			padbits = BITS_PER_BYTE - padbits;			dbytes++;		}		if(asicp->ireg_length % BITS_PER_BYTE)			hbytes++;				cat_build_header(hseq, hbytes, 1, asicp->ireg_length);				for(i = 0; i < dbytes + hbytes; i++)			dseq[i] = 0xff;		CDEBUG(("cat_senddata: dbytes=%d, hbytes=%d, padbits=%d\n",			dbytes, hbytes, padbits));		cat_pack(dseq, modp->num_asics - 1 + asicp->ireg_length,			 hseq, hbytes * BITS_PER_BYTE);		cat_pack(dseq, asicp->asic_location, &value, 			 asicp->ireg_length);#ifdef VOYAGER_CAT_DEBUG		printk("dseq ");		for(i=0; i<hbytes+dbytes; i++) {			printk("0x%x ", dseq[i]);		}		printk("\n");#endif		return cat_shiftout(dseq, dbytes, hbytes, padbits);	}}static intcat_write(voyager_module_t *modp, voyager_asic_t *asicp, __u8 reg,	 __u8 value){	if(cat_sendinst(modp, asicp, reg, VOYAGER_WRITE_CONFIG))		return 1;	return cat_senddata(modp, asicp, reg, value);}static intcat_read(voyager_module_t *modp, voyager_asic_t *asicp, __u8 reg,	 __u8 *value){	if(cat_sendinst(modp, asicp, reg, VOYAGER_READ_CONFIG))		return 1;	return cat_getdata(modp, asicp, reg, value);}static intcat_subaddrsetup(voyager_module_t *modp, voyager_asic_t *asicp, __u16 offset,		 __u16 len){	__u8 val;	if(len > 1) {		/* set auto increment */		__u8 newval;				if(cat_read(modp, asicp, VOYAGER_AUTO_INC_REG, &val)) {			CDEBUG(("cat_subaddrsetup: read of VOYAGER_AUTO_INC_REG failed\n"));			return 1;		}		CDEBUG(("cat_subaddrsetup: VOYAGER_AUTO_INC_REG = 0x%x\n", val));		newval = val | VOYAGER_AUTO_INC;		if(newval != val) {			if(cat_write(modp, asicp, VOYAGER_AUTO_INC_REG, val)) {				CDEBUG(("cat_subaddrsetup: write to VOYAGER_AUTO_INC_REG failed\n"));				return 1;			}		}	}	if(cat_write(modp, asicp, VOYAGER_SUBADDRLO, (__u8)(offset &0xff))) {		CDEBUG(("cat_subaddrsetup: write to SUBADDRLO failed\n"));		return 1;	}	if(asicp->subaddr > VOYAGER_SUBADDR_LO) {		if(cat_write(modp, asicp, VOYAGER_SUBADDRHI, (__u8)(offset >> 8))) {			CDEBUG(("cat_subaddrsetup: write to SUBADDRHI failed\n"));			return 1;		}		cat_read(modp, asicp, VOYAGER_SUBADDRHI, &val);		CDEBUG(("cat_subaddrsetup: offset = %d, hi = %d\n", offset, val));	}	cat_read(modp, asicp, VOYAGER_SUBADDRLO, &val);	CDEBUG(("cat_subaddrsetup: offset = %d, lo = %d\n", offset, val));	return 0;}		static intcat_subwrite(voyager_module_t *modp, voyager_asic_t *asicp, __u16 offset,	    __u16 len, void *buf){	int i, retval;	/* FIXME: need special actions for VOYAGER_CAT_ID here */	if(asicp->asic_id == VOYAGER_CAT_ID) {		CDEBUG(("cat_subwrite: ATTEMPT TO WRITE TO CAT ASIC\n"));		/* FIXME -- This is supposed to be handled better		 * There is a problem writing to the cat asic in the		 * PSI.  The 30us delay seems to work, though */		udelay(30);	}			if((retval = cat_subaddrsetup(modp, asicp, offset, len)) != 0) {		printk("cat_subwrite: cat_subaddrsetup FAILED\n");		return retval;	}		if(cat_sendinst(modp, asicp, VOYAGER_SUBADDRDATA, VOYAGER_WRITE_CONFIG)) {		printk("cat_subwrite: cat_sendinst FAILED\n");		return 1;	}	for(i = 0; i < len; i++) {		if(cat_senddata(modp, asicp, 0xFF, ((__u8 *)buf)[i])) {			printk("cat_subwrite: cat_sendata element at %d FAILED\n", i);			return 1;		}	}	return 0;}static intcat_subread(voyager_module_t *modp, voyager_asic_t *asicp, __u16 offset,	    __u16 len, void *buf){	int i, retval;	if((retval = cat_subaddrsetup(modp, asicp, offset, len)) != 0) {		CDEBUG(("cat_subread: cat_subaddrsetup FAILED\n"));		return retval;	}	if(cat_sendinst(modp, asicp, VOYAGER_SUBADDRDATA, VOYAGER_READ_CONFIG)) {		CDEBUG(("cat_subread: cat_sendinst failed\n"));		return 1;	}	for(i = 0; i < len; i++) {		if(cat_getdata(modp, asicp, 0xFF,			       &((__u8 *)buf)[i])) {			CDEBUG(("cat_subread: cat_getdata element %d failed\n", i));			return 1;		}	}	return 0;}/* buffer for storing EPROM data read in during initialisation */static __initdata __u8 eprom_buf[0xFFFF];static voyager_module_t *voyager_initial_module;/* Initialise the cat bus components.  We assume this is called by the * boot cpu *after* all memory initialisation has been done (so we can * use kmalloc) but before smp initialisation, so we can probe the SMP * configuration and pick up necessary information.  */void __initvoyager_cat_init(void){	voyager_module_t **modpp = &voyager_initial_module;	voyager_asic_t **asicpp;	voyager_asic_t *qabc_asic = NULL;	int i, j;	unsigned long qic_addr = 0;	__u8 qabc_data[0x20];	__u8 num_submodules, val;	voyager_eprom_hdr_t *eprom_hdr = (voyager_eprom_hdr_t *)&eprom_buf[0];		__u8 cmos[4];	unsigned long addr;		/* initiallise the SUS mailbox */	for(i=0; i<sizeof(cmos); i++)		cmos[i] = voyager_extended_cmos_read(VOYAGER_DUMP_LOCATION + i);	addr = *(unsigned long *)cmos;	if((addr & 0xff000000) != 0xff000000) {		printk(KERN_ERR "Voyager failed to get SUS mailbox (addr = 0x%lx\n", addr);	} else {		static struct resource res;				res.name = "voyager SUS";		res.start = addr;		res.end = addr+0x3ff;				request_resource(&iomem_resource, &res);		voyager_SUS = (struct voyager_SUS *)			ioremap(addr, 0x400);		printk(KERN_NOTICE "Voyager SUS mailbox version 0x%x\n",		       voyager_SUS->SUS_version);		voyager_SUS->kernel_version = VOYAGER_MAILBOX_VERSION;		voyager_SUS->kernel_flags = VOYAGER_OS_HAS_SYSINT;	}	/* clear the processor counts */	voyager_extended_vic_processors = 0;	voyager_quad_processors = 0;	printk("VOYAGER: beginning CAT bus probe\n");	/* set up the SuperSet Port Block which tells us where the	 * CAT communication port is */	sspb = inb(VOYAGER_SSPB_RELOCATION_PORT) * 0x100;	VDEBUG(("VOYAGER DEBUG: sspb = 0x%x\n", sspb));	/* now find out if were 8 slot or normal */	if((inb(VIC_PROC_WHO_AM_I) & EIGHT_SLOT_IDENTIFIER)	   == EIGHT_SLOT_IDENTIFIER) {		voyager_8slot = 1;		printk(KERN_NOTICE "Voyager: Eight slot 51xx configuration detected\n");	}	for(i = VOYAGER_MIN_MODULE;	    i <= VOYAGER_MAX_MODULE; i++) {		__u8 input;		int asic;		__u16 eprom_size;		__u16 sp_offset;		outb(VOYAGER_CAT_DESELECT, VOYAGER_CAT_CONFIG_PORT);		outb(i, VOYAGER_CAT_CONFIG_PORT);		/* check the presence of the module */		outb(VOYAGER_CAT_RUN, CAT_CMD);		outb(VOYAGER_CAT_IRCYC, CAT_CMD);		outb(VOYAGER_CAT_HEADER, CAT_DATA);		/* stream series of alternating 1's and 0's to stimulate		 * response */		outb(0xAA, CAT_DATA);		input = inb(CAT_DATA);		outb(VOYAGER_CAT_END, CAT_CMD);		if(input != VOYAGER_CAT_HEADER) {			continue;		}		CDEBUG(("VOYAGER DEBUG: found module id 0x%x, %s\n", i,			cat_module_name(i)));		*modpp = kmalloc(sizeof(voyager_module_t), GFP_KERNEL); /*&voyager_module_storage[cat_count++];*/		if(*modpp == NULL) {			printk("**WARNING** kmalloc failure in cat_init\n");			continue;		}		memset(*modpp, 0, sizeof(voyager_module_t));		/* need temporary asic for cat_subread.  It will be		 * filled in correctly later */		(*modpp)->asic = kmalloc(sizeof(voyager_asic_t), GFP_KERNEL); /*&voyager_asic_storage[asic_count];*/		if((*modpp)->asic == NULL) {			printk("**WARNING** kmalloc failure in cat_init\n");			continue;		}		memset((*modpp)->asic, 0, sizeof(voyager_asic_t));		(*modpp)->asic->asic_id = VOYAGER_CAT_ID;		(*modpp)->asic->subaddr = VOYAGER_SUBADDR_HI;		(*modpp)->module_addr = i;		(*modpp)->scan_path_connected = 0;		if(i == VOYAGER_PSI) {			/* Exception leg for modules with no EEPROM */			printk("Module \"%s\"\n", cat_module_name(i));			continue;		}			       		CDEBUG(("cat_init: Reading eeprom for module 0x%x at offset %d\n", i, VOYAGER_XSUM_END_OFFSET));		outb(VOYAGER_CAT_RUN, CAT_CMD);		cat_disconnect(*modpp, (*modpp)->asic);		if(cat_subread(*modpp, (*modpp)->asic,			       VOYAGER_XSUM_END_OFFSET, sizeof(eprom_size),			       &eprom_size)) {			printk("**WARNING**: Voyager couldn't read EPROM size for module 0x%x\n", i);			outb(VOYAGER_CAT_END, CAT_CMD);			continue;		}		if(eprom_size > sizeof(eprom_buf)) {			printk("**WARNING**: Voyager insufficient size to read EPROM data, module 0x%x.  Need %d\n", i, eprom_size);			outb(VOYAGER_CAT_END, CAT_CMD);			continue;		}		outb(VOYAGER_CAT_END, CAT_CMD);		outb(VOYAGER_CAT_RUN, CAT_CMD);		CDEBUG(("cat_init: module 0x%x, eeprom_size %d\n", i, eprom_size));		if(cat_subread(*modpp, (*modpp)->asic, 0, 			       eprom_size, eprom_buf)) {			outb(VOYAGER_CAT_END, CAT_CMD);			continue;		}		outb(VOYAGER_CAT_END, CAT_CMD);		printk("Module \"%s\", version 0x%x, tracer 0x%x, asics %d\n",		       cat_module_name(i), eprom_hdr->version_id,		       *((__u32 *)eprom_hdr->tracer),  eprom_hdr->num_asics);		(*modpp)->ee_size = eprom_hdr->ee_size;		(*modpp)->num_asics = eprom_hdr->num_asics;		asicpp = &((*modpp)->asic);		sp_offset = eprom_hdr->scan_path_offset;		/* All we really care about are the Quad cards.  We                 * identify them because they are in a processor slot                 * and have only four asics */		if((i < 0x10 || (i>=0x14 && i < 0x1c) || i>0x1f)) {			modpp = &((*modpp)->next);			continue;		}		/* Now we know it's in a processor slot, does it have		 * a quad baseboard submodule */		outb(VOYAGER_CAT_RUN, CAT_CMD);		cat_read(*modpp, (*modpp)->asic, VOYAGER_SUBMODPRESENT,			 &num_submodules);		/* lowest two bits, active low */		num_submodules = ~(0xfc | num_submodules);		CDEBUG(("VOYAGER CAT: %d submodules present\n", num_submodules));		if(num_submodules == 0) {			/* fill in the dyadic extended processors */			__u8 cpu = i & 0x07;			printk("Module \"%s\": Dyadic Processor Card\n",			       cat_module_name(i));			voyager_extended_vic_processors |= (1<<cpu);			cpu += 4;			voyager_extended_vic_processors |= (1<<cpu);			outb(VOYAGER_CAT_END, CAT_CMD);			continue;		}		/* now we want to read the asics on the first submodule,		 * which should be the quad base board */		cat_read(*modpp, (*modpp)->asic, VOYAGER_SUBMODSELECT, &val);		CDEBUG(("cat_init: SUBMODSELECT value = 0x%x\n", val));		val = (val & 0x7c) | VOYAGER_QUAD_BASEBOARD;		cat_write(*modpp, (*modpp)->asic, VOYAGER_SUBMODSELECT, val);		outb(VOYAGER_CAT_END, CAT_CMD);			 		CDEBUG(("cat_init: Reading eeprom for module 0x%x at offset %d\n", i, VOYAGER_XSUM_END_OFFSET));		outb(VOYAGER_CAT_RUN, CAT_CMD);		cat_disconnect(*modpp, (*modpp)->asic);		if(cat_subread(*modpp, (*modpp)->asic,			       VOYAGER_XSUM_END_OFFSET, sizeof(eprom_size),			       &eprom_size)) {			printk("**WARNING**: Voyager couldn't read EPROM size for module 0x%x\n", i);			outb(VOYAGER_CAT_END, CAT_CMD);			continue;		}		if(eprom_size > sizeof(eprom_buf)) {			printk("**WARNING**: Voyager insufficient size to read EPROM data, module 0x%x.  Need %d\n", i, eprom_size);			outb(VOYAGER_CAT_END, CAT_CMD);			continue;		}		outb(VOYAGER_CAT_END, CAT_CMD);		outb(VOYAGER_CAT_RUN, CAT_CMD);		CDEBUG(("cat_init: module 0x%x, eeprom_size %d\n", i, eprom_size));		if(cat_subread(*modpp, (*modpp)->asic, 0, 			       eprom_size, eprom_buf)) {			outb(VOYAGER_CAT_END, CAT_CMD);			continue;		}		outb(VOYAGER_CAT_END, CAT_CMD);		/* Now do everything for the QBB submodule 1 */		(*modpp)->ee_size = eprom_hdr->ee_size;		(*modpp)->num_asics = eprom_hdr->num_asics;		asicpp = &((*modpp)->asic);		sp_offset = eprom_hdr->scan_path_offset;		/* get rid of the dummy CAT asic and read the real one */		kfree((*modpp)->asic);		for(asic=0; asic < (*modpp)->num_asics; asic++) {			int j;			voyager_asic_t *asicp = *asicpp 				= kzalloc(sizeof(voyager_asic_t), GFP_KERNEL); /*&voyager_asic_storage[asic_count++];*/			voyager_sp_table_t *sp_table;			voyager_at_t *asic_table;			voyager_jtt_t *jtag_table;			if(asicp == NULL) {				printk("**WARNING** kmalloc failure in cat_init\n");				continue;			}			asicpp = &(asicp->next);

⌨️ 快捷键说明

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