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

📄 voyager_cat.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
			asicp->asic_location = asic;			sp_table = (voyager_sp_table_t *)(eprom_buf + sp_offset);			asicp->asic_id = sp_table->asic_id;			asic_table = (voyager_at_t *)(eprom_buf + sp_table->asic_data_offset);			for(j=0; j<4; j++)				asicp->jtag_id[j] = asic_table->jtag_id[j];			jtag_table = (voyager_jtt_t *)(eprom_buf + asic_table->jtag_offset);			asicp->ireg_length = jtag_table->ireg_len;			asicp->bit_location = (*modpp)->inst_bits;			(*modpp)->inst_bits += asicp->ireg_length;			if(asicp->ireg_length > (*modpp)->largest_reg)				(*modpp)->largest_reg = asicp->ireg_length;			if (asicp->ireg_length < (*modpp)->smallest_reg ||			    (*modpp)->smallest_reg == 0)				(*modpp)->smallest_reg = asicp->ireg_length;			CDEBUG(("asic 0x%x, ireg_length=%d, bit_location=%d\n",				asicp->asic_id, asicp->ireg_length,				asicp->bit_location));			if(asicp->asic_id == VOYAGER_QUAD_QABC) {				CDEBUG(("VOYAGER CAT: QABC ASIC found\n"));				qabc_asic = asicp;			}			sp_offset += sizeof(voyager_sp_table_t);		}		CDEBUG(("Module inst_bits = %d, largest_reg = %d, smallest_reg=%d\n",			(*modpp)->inst_bits, (*modpp)->largest_reg,			(*modpp)->smallest_reg));		/* OK, now we have the QUAD ASICs set up, use them.		 * we need to:		 *		 * 1. Find the Memory area for the Quad CPIs.		 * 2. Find the Extended VIC processor		 * 3. Configure a second extended VIC processor (This		 *    cannot be done for the 51xx.		 * */		outb(VOYAGER_CAT_RUN, CAT_CMD);		cat_connect(*modpp, (*modpp)->asic);		CDEBUG(("CAT CONNECTED!!\n"));		cat_subread(*modpp, qabc_asic, 0, sizeof(qabc_data), qabc_data);		qic_addr = qabc_data[5] << 8;		qic_addr = (qic_addr | qabc_data[6]) << 8;		qic_addr = (qic_addr | qabc_data[7]) << 8;		printk("Module \"%s\": Quad Processor Card; CPI 0x%lx, SET=0x%x\n",		       cat_module_name(i), qic_addr, qabc_data[8]);#if 0				/* plumbing fails---FIXME */		if((qabc_data[8] & 0xf0) == 0) {			/* FIXME: 32 way 8 CPU slot monster cannot be			 * plumbed this way---need to check for it */			printk("Plumbing second Extended Quad Processor\n");			/* second VIC line hardwired to Quad CPU 1 */			qabc_data[8] |= 0x20;			cat_subwrite(*modpp, qabc_asic, 8, 1, &qabc_data[8]);#ifdef VOYAGER_CAT_DEBUG			/* verify plumbing */			cat_subread(*modpp, qabc_asic, 8, 1, &qabc_data[8]);			if((qabc_data[8] & 0xf0) == 0) {				CDEBUG(("PLUMBING FAILED: 0x%x\n", qabc_data[8]));			}#endif		}#endif		{			struct resource *res = kzalloc(sizeof(struct resource),GFP_KERNEL);			res->name = kmalloc(128, GFP_KERNEL);			sprintf((char *)res->name, "Voyager %s Quad CPI", cat_module_name(i));			res->start = qic_addr;			res->end = qic_addr + 0x3ff;			request_resource(&iomem_resource, res);		}		qic_addr = (unsigned long)ioremap(qic_addr, 0x400);						for(j = 0; j < 4; j++) {			__u8 cpu;			if(voyager_8slot) {				/* 8 slot has a different mapping,				 * each slot has only one vic line, so				 * 1 cpu in each slot must be < 8 */				cpu = (i & 0x07) + j*8;			} else {				cpu = (i & 0x03) + j*4;			}			if( (qabc_data[8] & (1<<j))) {				voyager_extended_vic_processors |= (1<<cpu);			}			if(qabc_data[8] & (1<<(j+4)) ) {				/* Second SET register plumbed: Quad				 * card has two VIC connected CPUs.				 * Secondary cannot be booted as a VIC				 * CPU */				voyager_extended_vic_processors |= (1<<cpu);				voyager_allowed_boot_processors &= (~(1<<cpu));			}			voyager_quad_processors |= (1<<cpu);			voyager_quad_cpi_addr[cpu] = (struct voyager_qic_cpi *)				(qic_addr+(j<<8));			CDEBUG(("CPU%d: CPI address 0x%lx\n", cpu,				(unsigned long)voyager_quad_cpi_addr[cpu]));		}		outb(VOYAGER_CAT_END, CAT_CMD);						*asicpp = NULL;		modpp = &((*modpp)->next);	}	*modpp = NULL;	printk("CAT Bus Initialisation finished: extended procs 0x%x, quad procs 0x%x, allowed vic boot = 0x%x\n", voyager_extended_vic_processors, voyager_quad_processors, voyager_allowed_boot_processors);	request_resource(&ioport_resource, &vic_res);	if(voyager_quad_processors)		request_resource(&ioport_resource, &qic_res);	/* set up the front power switch */}intvoyager_cat_readb(__u8 module, __u8 asic, int reg){	return 0;}static intcat_disconnect(voyager_module_t *modp, voyager_asic_t *asicp) {	__u8 val;	int err = 0;	if(!modp->scan_path_connected)		return 0;	if(asicp->asic_id != VOYAGER_CAT_ID) {		CDEBUG(("cat_disconnect: ASIC is not CAT\n"));		return 1;	}	err = cat_read(modp, asicp, VOYAGER_SCANPATH, &val);	if(err) {		CDEBUG(("cat_disconnect: failed to read SCANPATH\n"));		return err;	}	val &= VOYAGER_DISCONNECT_ASIC;	err = cat_write(modp, asicp, VOYAGER_SCANPATH, val);	if(err) {		CDEBUG(("cat_disconnect: failed to write SCANPATH\n"));		return err;	}	outb(VOYAGER_CAT_END, CAT_CMD);	outb(VOYAGER_CAT_RUN, CAT_CMD);	modp->scan_path_connected = 0;	return 0;}static intcat_connect(voyager_module_t *modp, voyager_asic_t *asicp) {	__u8 val;	int err = 0;	if(modp->scan_path_connected)		return 0;	if(asicp->asic_id != VOYAGER_CAT_ID) {		CDEBUG(("cat_connect: ASIC is not CAT\n"));		return 1;	}	err = cat_read(modp, asicp, VOYAGER_SCANPATH, &val);	if(err) {		CDEBUG(("cat_connect: failed to read SCANPATH\n"));		return err;	}	val |= VOYAGER_CONNECT_ASIC;	err = cat_write(modp, asicp, VOYAGER_SCANPATH, val);	if(err) {		CDEBUG(("cat_connect: failed to write SCANPATH\n"));		return err;	}	outb(VOYAGER_CAT_END, CAT_CMD);	outb(VOYAGER_CAT_RUN, CAT_CMD);	modp->scan_path_connected = 1;	return 0;}voidvoyager_cat_power_off(void){	/* Power the machine off by writing to the PSI over the CAT         * bus */	__u8 data;	voyager_module_t psi = { 0 };	voyager_asic_t psi_asic = { 0 };	psi.asic = &psi_asic;	psi.asic->asic_id = VOYAGER_CAT_ID;	psi.asic->subaddr = VOYAGER_SUBADDR_HI;	psi.module_addr = VOYAGER_PSI;	psi.scan_path_connected = 0;	outb(VOYAGER_CAT_END, CAT_CMD);	/* Connect the PSI to the CAT Bus */	outb(VOYAGER_CAT_DESELECT, VOYAGER_CAT_CONFIG_PORT);	outb(VOYAGER_PSI, VOYAGER_CAT_CONFIG_PORT);	outb(VOYAGER_CAT_RUN, CAT_CMD);	cat_disconnect(&psi, &psi_asic);	/* Read the status */	cat_subread(&psi, &psi_asic, VOYAGER_PSI_GENERAL_REG, 1, &data);	outb(VOYAGER_CAT_END, CAT_CMD);	CDEBUG(("PSI STATUS 0x%x\n", data));	/* These two writes are power off prep and perform */	data = PSI_CLEAR;	outb(VOYAGER_CAT_RUN, CAT_CMD);	cat_subwrite(&psi, &psi_asic, VOYAGER_PSI_GENERAL_REG, 1, &data);	outb(VOYAGER_CAT_END, CAT_CMD);	data = PSI_POWER_DOWN;	outb(VOYAGER_CAT_RUN, CAT_CMD);	cat_subwrite(&psi, &psi_asic, VOYAGER_PSI_GENERAL_REG, 1, &data);	outb(VOYAGER_CAT_END, CAT_CMD);}struct voyager_status voyager_status = { 0 };voidvoyager_cat_psi(__u8 cmd, __u16 reg, __u8 *data){	voyager_module_t psi = { 0 };	voyager_asic_t psi_asic = { 0 };	psi.asic = &psi_asic;	psi.asic->asic_id = VOYAGER_CAT_ID;	psi.asic->subaddr = VOYAGER_SUBADDR_HI;	psi.module_addr = VOYAGER_PSI;	psi.scan_path_connected = 0;	outb(VOYAGER_CAT_END, CAT_CMD);	/* Connect the PSI to the CAT Bus */	outb(VOYAGER_CAT_DESELECT, VOYAGER_CAT_CONFIG_PORT);	outb(VOYAGER_PSI, VOYAGER_CAT_CONFIG_PORT);	outb(VOYAGER_CAT_RUN, CAT_CMD);	cat_disconnect(&psi, &psi_asic);	switch(cmd) {	case VOYAGER_PSI_READ:		cat_read(&psi, &psi_asic, reg, data);		break;	case VOYAGER_PSI_WRITE:		cat_write(&psi, &psi_asic, reg, *data);		break;	case VOYAGER_PSI_SUBREAD:		cat_subread(&psi, &psi_asic, reg, 1, data);		break;	case VOYAGER_PSI_SUBWRITE:		cat_subwrite(&psi, &psi_asic, reg, 1, data);		break;	default:		printk(KERN_ERR "Voyager PSI, unrecognised command %d\n", cmd);		break;	}	outb(VOYAGER_CAT_END, CAT_CMD);}voidvoyager_cat_do_common_interrupt(void){	/* This is caused either by a memory parity error or something	 * in the PSI */	__u8 data;	voyager_module_t psi = { 0 };	voyager_asic_t psi_asic = { 0 };	struct voyager_psi psi_reg;	int i; re_read:	psi.asic = &psi_asic;	psi.asic->asic_id = VOYAGER_CAT_ID;	psi.asic->subaddr = VOYAGER_SUBADDR_HI;	psi.module_addr = VOYAGER_PSI;	psi.scan_path_connected = 0;	outb(VOYAGER_CAT_END, CAT_CMD);	/* Connect the PSI to the CAT Bus */	outb(VOYAGER_CAT_DESELECT, VOYAGER_CAT_CONFIG_PORT);	outb(VOYAGER_PSI, VOYAGER_CAT_CONFIG_PORT);	outb(VOYAGER_CAT_RUN, CAT_CMD);	cat_disconnect(&psi, &psi_asic);	/* Read the status.  NOTE: Need to read *all* the PSI regs here	 * otherwise the cmn int will be reasserted */	for(i = 0; i < sizeof(psi_reg.regs); i++) {		cat_read(&psi, &psi_asic, i, &((__u8 *)&psi_reg.regs)[i]);	}	outb(VOYAGER_CAT_END, CAT_CMD);	if((psi_reg.regs.checkbit & 0x02) == 0) {		psi_reg.regs.checkbit |= 0x02;		cat_write(&psi, &psi_asic, 5, psi_reg.regs.checkbit);		printk("VOYAGER RE-READ PSI\n");		goto re_read;	}	outb(VOYAGER_CAT_RUN, CAT_CMD);	for(i = 0; i < sizeof(psi_reg.subregs); i++) {		/* This looks strange, but the PSI doesn't do auto increment		 * correctly */		cat_subread(&psi, &psi_asic, VOYAGER_PSI_SUPPLY_REG + i, 			    1, &((__u8 *)&psi_reg.subregs)[i]); 	}	outb(VOYAGER_CAT_END, CAT_CMD);#ifdef VOYAGER_CAT_DEBUG	printk("VOYAGER PSI: ");	for(i=0; i<sizeof(psi_reg.regs); i++)		printk("%02x ", ((__u8 *)&psi_reg.regs)[i]);	printk("\n           ");	for(i=0; i<sizeof(psi_reg.subregs); i++)		printk("%02x ", ((__u8 *)&psi_reg.subregs)[i]);	printk("\n");#endif	if(psi_reg.regs.intstatus & PSI_MON) {		/* switch off or power fail */		if(psi_reg.subregs.supply & PSI_SWITCH_OFF) {			if(voyager_status.switch_off) {				printk(KERN_ERR "Voyager front panel switch turned off again---Immediate power off!\n");				voyager_cat_power_off();				/* not reached */			} else {				printk(KERN_ERR "Voyager front panel switch turned off\n");				voyager_status.switch_off = 1;				voyager_status.request_from_kernel = 1;				wake_up_process(voyager_thread);			}			/* Tell the hardware we're taking care of the			 * shutdown, otherwise it will power the box off			 * within 3 seconds of the switch being pressed and,			 * which is much more important to us, continue to 			 * assert the common interrupt */			data = PSI_CLR_SWITCH_OFF;			outb(VOYAGER_CAT_RUN, CAT_CMD);			cat_subwrite(&psi, &psi_asic, VOYAGER_PSI_SUPPLY_REG,				     1, &data);			outb(VOYAGER_CAT_END, CAT_CMD);		} else {			VDEBUG(("Voyager ac fail reg 0x%x\n",				psi_reg.subregs.ACfail));			if((psi_reg.subregs.ACfail & AC_FAIL_STAT_CHANGE) == 0) {				/* No further update */				return;			}#if 0			/* Don't bother trying to find out who failed.			 * FIXME: This probably makes the code incorrect on			 * anything other than a 345x */			for(i=0; i< 5; i++) {				if( psi_reg.subregs.ACfail &(1<<i)) {					break;				}			}			printk(KERN_NOTICE "AC FAIL IN SUPPLY %d\n", i);#endif			/* DON'T do this: it shuts down the AC PSI 			outb(VOYAGER_CAT_RUN, CAT_CMD);			data = PSI_MASK_MASK | i;			cat_subwrite(&psi, &psi_asic, VOYAGER_PSI_MASK,				     1, &data);			outb(VOYAGER_CAT_END, CAT_CMD);			*/			printk(KERN_ERR "Voyager AC power failure\n");			outb(VOYAGER_CAT_RUN, CAT_CMD);			data = PSI_COLD_START;			cat_subwrite(&psi, &psi_asic, VOYAGER_PSI_GENERAL_REG,				     1, &data);			outb(VOYAGER_CAT_END, CAT_CMD);			voyager_status.power_fail = 1;			voyager_status.request_from_kernel = 1;			wake_up_process(voyager_thread);		}					} else if(psi_reg.regs.intstatus & PSI_FAULT) {		/* Major fault! */		printk(KERN_ERR "Voyager PSI Detected major fault, immediate power off!\n");		voyager_cat_power_off();		/* not reached */	} else if(psi_reg.regs.intstatus & (PSI_DC_FAIL | PSI_ALARM					    | PSI_CURRENT | PSI_DVM					    | PSI_PSCFAULT | PSI_STAT_CHG)) {		/* other psi fault */		printk(KERN_WARNING "Voyager PSI status 0x%x\n", data);		/* clear the PSI fault */		outb(VOYAGER_CAT_RUN, CAT_CMD);		cat_write(&psi, &psi_asic, VOYAGER_PSI_STATUS_REG, 0);		outb(VOYAGER_CAT_END, CAT_CMD);	}}

⌨️ 快捷键说明

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