static irqreturn_t mpc52xx_lpbfifo_irq(int irq, void *dev_id)
{
	struct mpc52xx_lpbfifo_request *req;
	u32 status = in_8(lpbfifo.regs + LPBFIFO_REG_BYTES_DONE_STATUS);
	void __iomem *reg;
	u32 *data;
	int count, i;
	int do_callback = 0;
	u32 ts;
	unsigned long flags;
	int dma, write, poll_dma;

	spin_lock_irqsave(&lpbfifo.lock, flags);
	ts = get_tbl();

	req = lpbfifo.req;
	if (!req) {
		spin_unlock_irqrestore(&lpbfifo.lock, flags);
		pr_err("bogus LPBFIFO IRQ\n");
		return IRQ_HANDLED;
	}

	dma = !(req->flags & MPC52XX_LPBFIFO_FLAG_NO_DMA);
	write = req->flags & MPC52XX_LPBFIFO_FLAG_WRITE;
	poll_dma = req->flags & MPC52XX_LPBFIFO_FLAG_POLL_DMA;

	if (dma && !write) {
		spin_unlock_irqrestore(&lpbfifo.lock, flags);
		pr_err("bogus LPBFIFO IRQ (dma and not writting)\n");
		return IRQ_HANDLED;
	}

	if ((status & 0x01) == 0) {
		goto out;
	}

	/*                 */
	if (status & 0x10) {
		out_be32(lpbfifo.regs + LPBFIFO_REG_ENABLE, 0x01010000);
		do_callback = 1;
		goto out;
	}

	/*                           */
	count = in_be32(lpbfifo.regs + LPBFIFO_REG_BYTES_DONE_STATUS);
	count &= 0x00ffffff;

	if (!dma && !write) {
		/*                               */
		reg = lpbfifo.regs + LPBFIFO_REG_FIFO_DATA;
		data = req->data + req->pos;
		for (i = 0; i < count; i += 4)
			*data++ = in_be32(reg);
	}

	/*                                    */
	req->pos += count;

	/*                        */
	if (req->size - req->pos)
		mpc52xx_lpbfifo_kick(req); /*                 */
	else
		do_callback = 1;

 out:
	/*               */
	out_8(lpbfifo.regs + LPBFIFO_REG_BYTES_DONE_STATUS, 0x01);

	if (dma && (status & 0x11)) {
		/*
                                                            
                                  
    
                                                               
                           
    
                                                             
             
   */
		bcom_retrieve_buffer(lpbfifo.bcom_cur_task, &status, NULL);
	}
	req->last_byte = ((u8 *)req->data)[req->size - 1];

	/*                                                                    
                            */
	if (do_callback)
		lpbfifo.req = NULL;

	if (irq != 0) /*                                */
		req->irq_count++;

	req->irq_ticks += get_tbl() - ts;
	spin_unlock_irqrestore(&lpbfifo.lock, flags);

	/*                                                           */
	if (do_callback && req->callback)
		req->callback(req);

	return IRQ_HANDLED;
}
/**
 * mpc52xx_lpbfifo_irq - IRQ handler for LPB FIFO
 *
 * On transmit, the dma completion irq triggers before the fifo completion
 * triggers.  Handle the dma completion here instead of the LPB FIFO Bestcomm
 * task completion irq because everything is not really done until the LPB FIFO
 * completion irq triggers.
 *
 * In other words:
 * For DMA, on receive, the "Fat Lady" is the bestcom completion irq. on
 * transmit, the fifo completion irq is the "Fat Lady". The opera (or in this
 * case the DMA/FIFO operation) is not finished until the "Fat Lady" sings.
 *
 * Reasons for entering this routine:
 * 1) PIO mode rx and tx completion irq
 * 2) DMA interrupt mode tx completion irq
 * 3) DMA polled mode tx
 *
 * Exit conditions:
 * 1) Transfer aborted
 * 2) FIFO complete without DMA; more data to do
 * 3) FIFO complete without DMA; all data transferred
 * 4) FIFO complete using DMA
 *
 * Condition 1 can occur regardless of whether or not DMA is used.
 * It requires executing the callback to report the error and exiting
 * immediately.
 *
 * Condition 2 requires programming the FIFO with the next block of data
 *
 * Condition 3 requires executing the callback to report completion
 *
 * Condition 4 means the same as 3, except that we also retrieve the bcom
 * buffer so DMA doesn't get clogged up.
 *
 * To make things trickier, the spinlock must be dropped before
 * executing the callback, otherwise we could end up with a deadlock
 * or nested spinlock condition.  The out path is non-trivial, so
 * extra fiddling is done to make sure all paths lead to the same
 * outbound code.
 */
static irqreturn_t mpc52xx_lpbfifo_irq(int irq, void *dev_id)
{
	struct mpc52xx_lpbfifo_request *req;
	u32 status = in_8(lpbfifo.regs + LPBFIFO_REG_BYTES_DONE_STATUS);
	void __iomem *reg;
	u32 *data;
	int count, i;
	int do_callback = 0;
	u32 ts;
	unsigned long flags;
	int dma, write, poll_dma;

	spin_lock_irqsave(&lpbfifo.lock, flags);
	ts = get_tbl();

	req = lpbfifo.req;
	if (!req) {
		spin_unlock_irqrestore(&lpbfifo.lock, flags);
		pr_err("bogus LPBFIFO IRQ\n");
		return IRQ_HANDLED;
	}

	dma = !(req->flags & MPC52XX_LPBFIFO_FLAG_NO_DMA);
	write = req->flags & MPC52XX_LPBFIFO_FLAG_WRITE;
	poll_dma = req->flags & MPC52XX_LPBFIFO_FLAG_POLL_DMA;

	if (dma && !write) {
		spin_unlock_irqrestore(&lpbfifo.lock, flags);
		pr_err("bogus LPBFIFO IRQ (dma and not writting)\n");
		return IRQ_HANDLED;
	}

	if ((status & 0x01) == 0) {
		goto out;
	}

	/* check abort bit */
	if (status & 0x10) {
		out_be32(lpbfifo.regs + LPBFIFO_REG_ENABLE, 0x01010000);
		do_callback = 1;
		goto out;
	}

	/* Read result from hardware */
	count = in_be32(lpbfifo.regs + LPBFIFO_REG_BYTES_DONE_STATUS);
	count &= 0x00ffffff;

	if (!dma && !write) {
		/* copy the data out of the FIFO */
		reg = lpbfifo.regs + LPBFIFO_REG_FIFO_DATA;
		data = req->data + req->pos;
		for (i = 0; i < count; i += 4)
			*data++ = in_be32(reg);
	}

	/* Update transfer position and count */
	req->pos += count;

	/* Decide what to do next */
	if (req->size - req->pos)
		mpc52xx_lpbfifo_kick(req); /* more work to do */
	else
		do_callback = 1;

 out:
	/* Clear the IRQ */
	out_8(lpbfifo.regs + LPBFIFO_REG_BYTES_DONE_STATUS, 0x01);

	if (dma && (status & 0x11)) {
		/*
		 * Count the DMA as complete only when the FIFO completion
		 * status or abort bits are set.
		 *
		 * (status & 0x01) should always be the case except sometimes
		 * when using polled DMA.
		 *
		 * (status & 0x10) {transfer aborted}: This case needs more
		 * testing.
		 */
		bcom_retrieve_buffer(lpbfifo.bcom_cur_task, &status, NULL);
	}
	req->last_byte = ((u8 *)req->data)[req->size - 1];

	/* When the do_callback flag is set; it means the transfer is finished
	 * so set the FIFO as idle */
	if (do_callback)
		lpbfifo.req = NULL;

	if (irq != 0) /* don't increment on polled case */
		req->irq_count++;

	req->irq_ticks += get_tbl() - ts;
	spin_unlock_irqrestore(&lpbfifo.lock, flags);

	/* Spinlock is released; it is now safe to call the callback */
	if (do_callback && req->callback)
		req->callback(req);

	return IRQ_HANDLED;
}
示例#3
0
/* primarily for the debugger */
void
make_mregs_dec_valid( void )
{
	if( __stop == kGo )
		mregs->spr[S_DEC] = mregs->dec_stamp - get_tbl();
}
示例#4
0
void __init
mpc52xx_calibrate_decr(void)
{
    int current_time, previous_time;
    int tbl_start, tbl_end;
    unsigned int xlbfreq, cpufreq, ipbfreq, pcifreq, divisor;

    xlbfreq = __res.bi_busfreq;
    /* if bootloader didn't pass bus frequencies, calculate them */
    if (xlbfreq == 0) {
        /* Get RTC & Clock manager modules */
        struct mpc52xx_rtc __iomem *rtc;
        struct mpc52xx_cdm __iomem *cdm;

        rtc = ioremap(MPC52xx_PA(MPC52xx_RTC_OFFSET), MPC52xx_RTC_SIZE);
        cdm = ioremap(MPC52xx_PA(MPC52xx_CDM_OFFSET), MPC52xx_CDM_SIZE);

        if ((rtc==NULL) || (cdm==NULL))
            panic("Can't ioremap RTC/CDM while computing bus freq");

        /* Count bus clock during 1/64 sec */
        out_be32(&rtc->dividers, 0x8f1f0000);	/* Set RTC 64x faster */
        previous_time = in_be32(&rtc->time);
        while ((current_time = in_be32(&rtc->time)) == previous_time) ;
        tbl_start = get_tbl();
        previous_time = current_time;
        while ((current_time = in_be32(&rtc->time)) == previous_time) ;
        tbl_end = get_tbl();
        out_be32(&rtc->dividers, 0xffff0000);	/* Restore RTC */

        /* Compute all frequency from that & CDM settings */
        xlbfreq = (tbl_end - tbl_start) << 8;
        cpufreq = (xlbfreq * core_mult[in_be32(&cdm->rstcfg)&0x1f])/10;
        ipbfreq = (in_8(&cdm->ipb_clk_sel) & 1) ?
                  xlbfreq / 2 : xlbfreq;
        switch (in_8(&cdm->pci_clk_sel) & 3) {
        case 0:
            pcifreq = ipbfreq;
            break;
        case 1:
            pcifreq = ipbfreq / 2;
            break;
        default:
            pcifreq = xlbfreq / 4;
            break;
        }
        __res.bi_busfreq = xlbfreq;
        __res.bi_intfreq = cpufreq;
        __res.bi_ipbfreq = ipbfreq;
        __res.bi_pcifreq = pcifreq;

        /* Release mapping */
        iounmap(rtc);
        iounmap(cdm);
    }

    divisor = 4;

    tb_ticks_per_jiffy = xlbfreq / HZ / divisor;
    tb_to_us = mulhwu_scale_factor(xlbfreq / divisor, 1000000);
}
示例#5
0
文件: smp.c 项目: dduval/kernel-rhel3
void __init smp_software_tb_sync(int cpu)
{
#define PASSES 4	/* 4 passes.. */
	int pass;
	int i, j;

	/* stop - start will be the number of timebase ticks it takes for cpu0
	 * to send a message to all others and the first reponse to show up.
	 *
	 * ASSUMPTION: this time is similiar for all cpus
	 * ASSUMPTION: the time to send a one-way message is ping/2
	 */
	register unsigned long start = 0;
	register unsigned long stop = 0;
	register unsigned long temp = 0;

	set_tb(0, 0);

	/* multiple passes to get in l1 cache.. */
	for (pass = 2; pass < 2+PASSES; pass++){
		if (cpu == 0){
			mb();
			for (i = j = 1; i < smp_num_cpus; i++, j++){
				/* skip stuck cpus */
				while (!cpu_callin_map[j])
					++j;
				while (cpu_callin_map[j] != pass)
					barrier();
			}
			mb();
			tb_sync_flag = pass;
			start = get_tbl();	/* start timing */
			while (tb_sync_flag)
				mb();
			stop = get_tbl();	/* end timing */
			/* theoretically, the divisor should be 2, but
			 * I get better results on my dual mtx. someone
			 * please report results on other smp machines..
			 */
			tb_offset = (stop-start)/4;
			mb();
			tb_sync_flag = pass;
			udelay(10);
			mb();
			tb_sync_flag = 0;
			mb();
			set_tb(0,0);
			mb();
		} else {
			cpu_callin_map[cpu] = pass;
			mb();
			while (!tb_sync_flag)
				mb();		/* wait for cpu0 */
			mb();
			tb_sync_flag = 0;	/* send response for timing */
			mb();
			while (!tb_sync_flag)
				mb();
			temp = tb_offset;	/* make sure offset is loaded */
			while (tb_sync_flag)
				mb();
			set_tb(0,temp);		/* now, set the timebase */
			mb();
		}
	}
	if (cpu == 0) {
		smp_tb_synchronized = 1;
		printk("smp_software_tb_sync: %d passes, final offset: %ld\n",
			PASSES, tb_offset);
	}
	/* so time.c doesn't get confused */
	set_dec(tb_ticks_per_jiffy);
	last_jiffy_stamp(cpu) = 0;
}
//
// Getting the speed of the processors in Hz. We get this from /proc/cpuinfo.
// Example output of /proc/cpuinfo:
//////////////////////////////////////////////////////////////////////
// processor    : 0
// vendor_id    : GenuineIntel
// cpu family   : 6
// model                : 7
// model name   : Pentium III (Katmai)
// stepping     : 3
// cpu MHz              : 497.845315
// cache size   : 512 KB
// ... file continues on ...
//////////////////////////////////////////////////////////////////////
// Note: We just take the first CPU we find and return its CPU speed.
double Performance::Get_Timer_Resolution()
{
#if defined(IOMTR_CPU_I386) || defined(IOMTR_CPU_XSCALE) || defined(IOMTR_CPU_X86_64) || defined(IOMTR_CPU_IA64)
	int c;
	char label[40];
	int scanDecodes;
	double result;
	FILE *cpuInfo;

	int khz;

	if (kstatfd > 0 && ioctl(kstatfd, IM_IOC_GETCPUKHZ, &khz) >= 0) {
		cout << "CPU KHZ: " << khz << endl;
		return (double)khz *1000.0;
	}

	cpuInfo = fopen("/proc/cpuinfo", "r");
	if (!cpuInfo) {
		cerr << "Error determining CPU speed.\n";
		return (0.0);
	}

	do {
		fscanf(cpuInfo, "%7c", label);
		if (!strncmp(label, "cpu MHz", 7)) {
			scanDecodes = fscanf(cpuInfo, "%*s %lf", &result);
			result *= 1000000.0;
			fclose(cpuInfo);
			if (scanDecodes == 1) {
				return (result);
			} else {
				cerr << "Error determining CPU speed.\n";
				return (0.0);
			}
		} else if (!strncmp(label, "cpu GHz", 7)) {
			scanDecodes = fscanf(cpuInfo, "%*s %lf", &result);
			result *= 1000000000.0;
			fclose(cpuInfo);
			if (scanDecodes == 1) {
				return (result);
			} else {
				cerr << "Error determining CPU speed.\n";
				return (0.0);
			}
		}
		// Skip to the next line.
		do {
			c = getc(cpuInfo);
		} while ((c != '\n') && (c != EOF));
	} while (c != EOF);
	fclose(cpuInfo);
	cerr << "Error determining CPU speed.\n";
	return (0.0);
#elif defined(IOMTR_CPU_PPC)
#define USEC(tv)	(tv.tv_sec*1000000+tv.tv_usec)

	struct timeval tv1, tv2;
	DWORD t1, t2;

	double result;

	gettimeofday(&tv1, NULL);
	t1 = get_tbl();
	sleep(1);
	t2 = get_tbl();
	gettimeofday(&tv2, NULL);

	result = ((double)(t2 - t1)) * (1000000.0 / (double)(USEC(tv2) - USEC(tv1)));

	return (result);
#else
#warning ===> WARNING: You have to do some coding here to get the port done!
#endif
}
示例#7
0
char *get_var(unsigned long long *size_ptr, char *var_index){

    char *ptr = NULL;
    unsigned long long size = 0;	//if Zero - not write able

    if(*var_index == '_'){	/* global variables */
	var_index++;

        if(*var_index == '_'){	//??__variable?? - show environment variable
	    var_index++;
	    ptr = getenv(var_index);
	}else if(*var_index == '#'){	//??_#variable?? - show command variable index.html?variable=5
	    var_index++;
	    if(*var_index == '#'){	//??_##variable?? - show local command variable index.html?variable=5
		var_index++;
		return get_arg(var_index, size_ptr, 1);
	    }
	    return get_arg(var_index, size_ptr, 0);
//	    if(ptr) size = strlen(ptr) + 1;//for remove_show_chars needed
	}else if(*var_index == '%'){	//??_%variable?? - show new_variable
	    var_index++;
	    return get_cfg_value(size_ptr, var_index, 1);
	}else if(*var_index == '&'){	//??_&variable?? - show fresh_variable
	    var_index++;
	    return get_cfg_value(size_ptr, var_index, 2);
	}else if(*var_index == '@'){	//??_@variable?? - show variable from rnd table
	    var_index++;
	    ptr = get_tbl(var_index);
	}else if(*var_index == '?'){	//??_?file|expression?? -> in file this expression
	    var_index++;

	FILE *fip;
	char *ptr1;
	
	
	ptr1 = w_strtok(&var_index, '|');
	if (ptr1){
	
	    if((fip = fopen(ptr1,"r")) == NULL)
		printf("No file: %s\n", ptr1);
	    else{
	    while(fgets(copybuf,sizeof(copybuf),fip) != NULL){
		if((ptr1 = parsestr1_(copybuf,var_index)) != NULL){
		    ptr = ptr1;
		    break;
		}
	    }
	    fclose(fip);
	    }
	}
	return ptr;
	} else if(!strcmp(var_index,"referer")){
	    ptr = referer;
	} else if(!strcmp(var_index,"short_referer")){
/*	    ptr = "";
    	    char *c = referer;	//get only name of html
    	    while (*c){
		if(*c == '/') ptr = c + 1;
		c++;
	    }
*/		ptr = parsestr1_(referer, "/L/L");	//get the last '/'
	}else if(!strcmp(var_index,"user_agent")){
	    ptr = user_agent;
	}else if(!strcmp(var_index,"ip")){
	    ptr = ip;
	    size = 20;
	}else if(!strcmp(var_index,"port")){
	    ptr = port;
	    size = 10;
	}else if(!strcmp(var_index,"srv_ip")){
	    ptr = CONFIG.IP;
	}else if(!strcmp(var_index,"srv_port")){
	    ptr = CONFIG.ADMIN_PORT;
	}else if(!strcmp(var_index,"dns_name")){
	    ptr = dns_name;
	}else if(!strcmp(var_index,"etc_save")){
	    ptr = etc_save;
	    size = 2;
	}else if(!strcmp(var_index,"file_name")){
	    ptr = file;
	}else if(!strcmp(var_index,"buf")){
	    ptr = buf;
	    size = 16384;
	}

    
    }/*end of global variables*/
    else  return get_cfg_value(size_ptr, var_index, 0); /*if not found - return NULL*/
    
    if(size_ptr) *size_ptr = size; 
    return ptr;
}