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; }
/* primarily for the debugger */ void make_mregs_dec_valid( void ) { if( __stop == kGo ) mregs->spr[S_DEC] = mregs->dec_stamp - get_tbl(); }
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); }
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 }
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; }