static bool_t tick_timer_init(void) { u64_t timclk; u32_t count; if(!clk_get_rate("timclk", &timclk)) { LOG_E("can't get the clock of \'timclk\'"); return FALSE; } /* for 1ms reload count */ count = (u32_t)div64(timclk, 1000); if(!request_irq("TMIER2_3", timer_interrupt)) { LOG_E("can't request irq \'TMIER2_3\'"); return FALSE; } /* using timer3 for tick, 1ms for reload value */ writel(REALVIEW_T3_LOAD, count); /* setting timer controller */ writel(REALVIEW_T3_CTRL, REALVIEW_TC_32BIT | REALVIEW_TC_DIV1 | REALVIEW_TC_IE | REALVIEW_TC_PERIODIC); /* clear all interrupt */ writel(REALVIEW_T3_ICLR, 0x0); /* enable timer3 */ writel(REALVIEW_T3_CTRL, readl(REALVIEW_T3_CTRL) | REALVIEW_TC_ENABLE); return TRUE; }
static bool_t tick_timer_init(void) { u64_t pclk; if(!clk_get_rate("pclk", &pclk)) return FALSE; if(!request_irq("TIMER4", timer_interrupt)) return FALSE; /* use pwm timer 4, prescaler for timer 4 is 16 */ writel(S3C6410_TCFG0, (readl(S3C6410_TCFG0) & ~(0xff<<8)) | (0x0f<<8)); /* select mux input for pwm timer4 is 1/2 */ writel(S3C6410_TCFG1, (readl(S3C6410_TCFG1) & ~(0xf<<16)) | (0x01<<16)); /* load value for 10 ms timeout */ writel(S3C6410_TCNTB4, (u32_t)div64(pclk, (2 * 16 * 100))); /* auto load, manaual update of timer 4 and stop timer4 */ writel(S3C6410_TCON, (readl(S3C6410_TCON) & ~(0x7<<20)) | (0x06<<20)); /* enable timer4 interrupt and clear interrupt status bit */ writel(S3C6410_TINT_CSTAT, (readl(S3C6410_TINT_CSTAT) & ~(0x1<<4)) | (0x01<<4) | (0x01<<9)); /* start timer4 */ writel(S3C6410_TCON, (readl(S3C6410_TCON) & ~(0x7<<20)) | (0x05<<20)); return TRUE; }
static void testdiv0(void) { int funcidx; assert(cmp64u(j, 0) == 0); /* loop through the 5 different division functions */ for (funcidx = 0; funcidx < 5; funcidx++) { expect_SIGFPE = 1; if (setjmp(jmpbuf_SIGFPE) == 0) { /* divide by zero using various functions */ switch (funcidx) { case 0: div64(i, j); ERR; break; case 1: div64u64(i, ex64lo(j)); ERR; break; case 2: div64u(i, ex64lo(j)); ERR; break; case 3: rem64(i, j); ERR; break; case 4: rem64u(i, ex64lo(j)); ERR; break; default: assert(0); ERR; break; } /* if we reach this point there was no signal and an * error has been recorded */ expect_SIGFPE = 0; } else { /* a signal has been received and expect_SIGFPE has * been reset; all is ok now */ assert(!expect_SIGFPE); } } }
static bool_t s5pv210fb_set_clock(struct s5pv210fb_lcd * lcd) { u64_t hclk, pixel_clock; u32_t div; u32_t cfg; /* * get hclk for lcd */ if(! clk_get_rate("dsys-hclk", &hclk)) return FALSE; pixel_clock = ( lcd->freq * (lcd->timing.h_fp + lcd->timing.h_bp + lcd->timing.h_sw + lcd->width) * (lcd->timing.v_fp + lcd->timing.v_bp + lcd->timing.v_sw + lcd->height) ); div = (u32_t)div64(hclk, pixel_clock); if(mod64(hclk, pixel_clock) > 0) div++; /* * fixed clock source: hclk */ cfg = readl(S5PV210_VIDCON0); cfg &= ~(S5PV210_VIDCON0_CLKSEL_MASK | S5PV210_VIDCON0_CLKVALUP_MASK | S5PV210_VIDCON0_VCLKEN_MASK | S5PV210_VIDCON0_CLKDIR_MASK); cfg |= (S5PV210_VIDCON0_CLKSEL_HCLK | S5PV210_VIDCON0_CLKVALUP_ALWAYS | S5PV210_VIDCON0_VCLKEN_NORMAL | S5PV210_VIDCON0_CLKDIR_DIVIDED); cfg |= S5PV210_VIDCON0_CLKVAL_F(div - 1); writel(S5PV210_VIDCON0, cfg); return TRUE; }
static bool_t keyboard_probe(struct input * input) { u32_t divisor; u64_t kclk; u8_t data; if(! clk_get_rate("kclk", &kclk)) { LOG_E("can't get the clock of 'kclk'"); return FALSE; } /* set keyboard's clock divisor */ divisor = (u32_t)(div64(kclk, 8000000) - 1); writeb(REALVIEW_KEYBOARD_CLKDIV, divisor); /* enable keyboard controller */ writeb(REALVIEW_KEYBOARD_CR, REALVIEW_KEYBOARD_CR_EN); /* clear a receive buffer */ kmi_read(&data); /* reset keyboard, and wait ack and pass/fail code */ if(! kmi_write(0xff) ) return FALSE; if(! kmi_read(&data)) return FALSE; if(data != 0xaa) return FALSE; /* set keyboard's typematic rate/delay */ kmi_write(0xf3); /* 10.9pcs, 500ms */ kmi_write(0x2b); /* scan code set 2 */ kmi_write(0xf0); kmi_write(0x02); /* set all keys typematic/make/break */ kmi_write(0xfa); /* set keyboard's number lock, caps lock, and scroll lock */ kmi_write(0xed); kmi_write(0x02); if(!request_irq("KMI0", keyboard_interrupt)) { LOG_E("can't request irq 'KMI0'"); writeb(REALVIEW_KEYBOARD_CR, 0); return FALSE; } /* re-enables keyboard */ writeb(REALVIEW_KEYBOARD_CR, REALVIEW_KEYBOARD_CR_EN | REALVIEW_KEYBOARD_CR_RXINTREN); return TRUE; }
static void testdiv(void) { u64_t q, r; #if TIMED struct timeval tvstart, tvend; printf("i=0x%.8x%.8x; j=0x%.8x%.8x\n", ex64hi(i), ex64lo(i), ex64hi(j), ex64lo(j)); fflush(stdout); if (gettimeofday(&tvstart, NULL) < 0) ERR; #endif /* division by zero has a separate test */ if (cmp64u(j, 0) == 0) { testdiv0(); return; } /* perform division, store q in k to make ERR more informative */ q = div64(i, j); r = rem64(i, j); k = q; #if TIMED if (gettimeofday(&tvend, NULL) < 0) ERR; tvend.tv_sec -= tvstart.tv_sec; tvend.tv_usec -= tvstart.tv_usec; if (tvend.tv_usec < 0) { tvend.tv_sec -= 1; tvend.tv_usec += 1000000; } printf("q=0x%.8x%.8x; r=0x%.8x%.8x; time=%d.%.6d\n", ex64hi(q), ex64lo(q), ex64hi(r), ex64lo(r), tvend.tv_sec, tvend.tv_usec); fflush(stdout); #endif /* compare to 64/32-bit division if possible */ if (!ex64hi(j)) { if (cmp64(q, div64u64(i, ex64lo(j))) != 0) ERR; if (!ex64hi(q)) { if (cmp64u(q, div64u(i, ex64lo(j))) != 0) ERR; } if (cmp64u(r, rem64u(i, ex64lo(j))) != 0) ERR; /* compare to 32-bit division if possible */ if (!ex64hi(i)) { if (cmp64u(q, ex64lo(i) / ex64lo(j)) != 0) ERR; if (cmp64u(r, ex64lo(i) % ex64lo(j)) != 0) ERR; } } /* check results using i = q j + r and r < j */ if (cmp64(i, add64(mul64(q, j), r)) != 0) ERR; if (cmp64(r, j) >= 0) ERR; }
/* * Send traffic from a scheduler instance due by 'now'. * Return a pointer to the head of the queue. */ static struct mbuf * serve_sched(struct mq *q, struct dn_sch_inst *si, uint64_t now) { struct mq def_q; struct dn_schk *s = si->sched; struct mbuf *m = NULL; int delay_line_idle = (si->dline.mq.head == NULL); int done, bw; if (q == NULL) { q = &def_q; q->head = NULL; } bw = s->link.bandwidth; si->kflags &= ~DN_ACTIVE; if (bw > 0) si->credit += (now - si->sched_time) * bw; else si->credit = 0; si->sched_time = now; done = 0; while (si->credit >= 0 && (m = s->fp->dequeue(si)) != NULL) { uint64_t len_scaled; done++; len_scaled = (bw == 0) ? 0 : hz * (m->m_pkthdr.len * 8 + extra_bits(m, s)); si->credit -= len_scaled; /* Move packet in the delay line */ dn_tag_get(m)->output_time = dn_cfg.curr_time + s->link.delay ; mq_append(&si->dline.mq, m); } /* * If credit >= 0 the instance is idle, mark time. * Otherwise put back in the heap, and adjust the output * time of the last inserted packet, m, which was too early. */ if (si->credit >= 0) { si->idle_time = now; } else { uint64_t t; KASSERT (bw > 0, ("bw=0 and credit<0 ?")); t = div64(bw - 1 - si->credit, bw); if (m) dn_tag_get(m)->output_time += t; si->kflags |= DN_ACTIVE; heap_insert(&dn_cfg.evheap, now + t, si); } if (delay_line_idle && done) transmit_event(q, &si->dline, now); return q->head; }
void DivIntNum16(void) { /* 11 */ /* 64 bit 除算 var: 足す数の入った変数 */ int *var = getCaliVariable(); gint64 i; l_1000A0C8 = *var; i = mul64(l_1000A0C8, numbase); l_1000A0D8 = div64(l_1000A0D8, i); DEBUG_COMMAND("ShCalc.DivIntNum16 %p:\n", var); }
/* * Convert the additional MAC overheads/delays into an equivalent * number of bits for the given data rate. The samples are * in milliseconds so we need to divide by 1000. */ static uint64_t extra_bits(struct mbuf *m, struct dn_schk *s) { int index; uint64_t bits; struct dn_profile *pf = s->profile; if (!pf || pf->samples_no == 0) return 0; index = random() % pf->samples_no; bits = div64((uint64_t)pf->samples[index] * s->link.bandwidth, 1000); if (index >= pf->loss_level) { struct dn_pkt_tag *dt = dn_tag_get(m); if (dt) dt->dn_dir = DIR_DROP; } return bits; }
void GetIntNum16(void) { /* 3 */ /* 64 bit 演算した結果を得る var: 数値をいれる変数 */ int *var = getCaliVariable(); gint64 i; i = div64(l_1000A0D8, numbase); if (i > 65535) { i = l_1000A0C8 = 65535; } *var = i; DEBUG_COMMAND("ShCalc.GetIntNum16 %d:\n", var); }
PUBLIC short cpu_load(void) { u64_t current_tsc, *current_idle; u64_t tsc_delta, idle_delta, busy; struct proc *idle; short load; #ifdef CONFIG_SMP unsigned cpu = cpuid; #endif u64_t *last_tsc, *last_idle; last_tsc = get_cpu_var_ptr(cpu, cpu_last_tsc); last_idle = get_cpu_var_ptr(cpu, cpu_last_idle); idle = get_cpu_var_ptr(cpu, idle_proc);; read_tsc_64(¤t_tsc); current_idle = &idle->p_cycles; /* ptr to idle proc */ /* calculate load since last cpu_load invocation */ if (!is_zero64(*last_tsc)) { tsc_delta = sub64(current_tsc, *last_tsc); idle_delta = sub64(*current_idle, *last_idle); busy = sub64(tsc_delta, idle_delta); busy = mul64(busy, make64(100, 0)); load = ex64lo(div64(busy, tsc_delta)); if (load > 100) load = 100; } else load = 0; *last_tsc = current_tsc; *last_idle = *current_idle; return load; }
/* * common function for ioctl. */ static int s5pv210_ioctl(u32_t ch, int cmd, void * arg) { const u32_t udivslot_code[16] = {0x0000, 0x0080, 0x0808, 0x0888, 0x2222, 0x4924, 0x4a52, 0x54aa, 0x5555, 0xd555, 0xd5d5, 0xddd5, 0xdddd, 0xdfdd, 0xdfdf, 0xffdf}; u32_t baud, baud_div_reg, baud_divslot_reg; u8_t data_bit_reg, parity_reg, stop_bit_reg; u64_t pclk; struct serial_parameter param; if((ch < 0) || (ch > 3)) return -1; memcpy(¶m, &uart_param[ch], sizeof(struct serial_parameter)); switch(cmd) { case IOCTL_WR_SERIAL_BAUD_RATE: param.baud_rate = *((enum SERIAL_BAUD_RATE *)arg); break; case IOCTL_WR_SERIAL_DATA_BITS: param.data_bit = *((enum SERIAL_DATA_BITS *)arg); break; case IOCTL_WR_SERIAL_PARITY_BIT: param.parity = *((enum SERIAL_PARITY_BIT *)arg); break; case IOCTL_WR_SERIAL_STOP_BITS: param.stop_bit = *((enum SERIAL_STOP_BITS *)arg); break; case IOCTL_RD_SERIAL_BAUD_RATE: *((enum SERIAL_BAUD_RATE *)arg) = param.baud_rate; return 0; case IOCTL_RD_SERIAL_DATA_BITS: *((enum SERIAL_DATA_BITS *)arg) = param.data_bit; return 0; case IOCTL_RD_SERIAL_PARITY_BIT: *((enum SERIAL_PARITY_BIT *)arg) = param.parity; return 0; case IOCTL_RD_SERIAL_STOP_BITS: *((enum SERIAL_STOP_BITS *)arg) = param.stop_bit; return 0; default: return -1; } switch(param.baud_rate) { case B50: baud = 50; break; case B75: baud = 75; break; case B110: baud = 110; break; case B134: baud = 134; break; case B200: baud = 200; break; case B300: baud = 300; break; case B600: baud = 600; break; case B1200: baud = 1200; break; case B1800: baud = 1800; break; case B2400: baud = 2400; break; case B4800: baud = 4800; break; case B9600: baud = 9600; break; case B19200: baud = 19200; break; case B38400: baud = 38400; break; case B57600: baud = 57600; break; case B76800: baud = 76800; break; case B115200: baud = 115200; break; case B230400: baud = 230400; break; case B380400: baud = 380400; break; case B460800: baud = 460800; break; case B921600: baud = 921600; break; default: return -1; } switch(param.data_bit) { case DATA_BITS_5: data_bit_reg = 0x0; break; case DATA_BITS_6: data_bit_reg = 0x1; break; case DATA_BITS_7: data_bit_reg = 0x2; break; case DATA_BITS_8: data_bit_reg = 0x3; break; default: return -1; } switch(param.parity) { case PARITY_NONE: parity_reg = 0x0; break; case PARITY_EVEN: parity_reg = 0x5; break; case PARITY_ODD: parity_reg = 0x4; break; default: return -1; } switch(param.stop_bit) { case STOP_BITS_1: stop_bit_reg = 0; break; case STOP_BITS_1_5: return -1; case STOP_BITS_2: stop_bit_reg = 1; break; default: return -1; } if(clk_get_rate("psys-pclk", &pclk)) { baud_div_reg = (u32_t)(div64(pclk, (baud * 16)) ) - 1; baud_divslot_reg = udivslot_code[( (u32_t)div64(mod64(pclk, (baud*16)), baud) ) & 0xf]; } else return -1; switch(ch) { case 0: writel(S5PV210_UBRDIV0, baud_div_reg); writel(S5PV210_UDIVSLOT0, baud_divslot_reg); writel(S5PV210_ULCON0, (data_bit_reg<<0 | stop_bit_reg <<2 | parity_reg<<3)); break; case 1: writel(S5PV210_UBRDIV1, baud_div_reg); writel(S5PV210_UDIVSLOT1, baud_divslot_reg); writel(S5PV210_ULCON1, (data_bit_reg<<0 | stop_bit_reg <<2 | parity_reg<<3)); break; case 2: writel(S5PV210_UBRDIV2, baud_div_reg); writel(S5PV210_UDIVSLOT2, baud_divslot_reg); writel(S5PV210_ULCON2, (data_bit_reg<<0 | stop_bit_reg <<2 | parity_reg<<3)); break; case 3: writel(S5PV210_UBRDIV3, baud_div_reg); writel(S5PV210_UDIVSLOT3, baud_divslot_reg); writel(S5PV210_ULCON3, (data_bit_reg<<0 | stop_bit_reg <<2 | parity_reg<<3)); break; default: return -1; } memcpy(&uart_param[ch], ¶m, sizeof(struct serial_parameter)); return 0; }
static bool_t mouse_probe(struct input * input) { u32_t divisor; u64_t kclk; u8_t data; if(! clk_get_rate("kclk", &kclk)) { LOG_E("can't get the clock of 'kclk'"); return FALSE; } /* set mouse's clock divisor */ divisor = (u32_t)(div64(kclk, 8000000) - 1); writeb(REALVIEW_MOUSE_CLKDIV, divisor); /* enable mouse controller */ writeb(REALVIEW_MOUSE_CR, REALVIEW_MOUSE_CR_EN); /* reset mouse, and wait ack and pass/fail code */ if(! kmi_write(0xff) ) return FALSE; if(! kmi_read(&data)) return FALSE; if(data != 0xaa) return FALSE; /* enable scroll wheel */ kmi_write(0xf3); kmi_write(200); kmi_write(0xf3); kmi_write(100); kmi_write(0xf3); kmi_write(80); kmi_write(0xf2); kmi_read(&data); kmi_read(&data); /* set sample rate, 100 samples/sec */ kmi_write(0xf3); kmi_write(100); /* set resolution, 4 counts per mm, 1:1 scaling */ kmi_write(0xe8); kmi_write(0x02); kmi_write(0xe6); /* enable data reporting */ kmi_write(0xf4); /* clear a receive buffer */ kmi_read(&data); kmi_read(&data); kmi_read(&data); kmi_read(&data); if(!request_irq("KMI1", mouse_interrupt)) { LOG_E("can't request irq 'KMI1'"); writeb(REALVIEW_MOUSE_CR, 0); return FALSE; } /* re-enables mouse */ writeb(REALVIEW_MOUSE_CR, REALVIEW_MOUSE_CR_EN | REALVIEW_MOUSE_CR_RXINTREN); return TRUE; }
static void fb_init(struct fb * fb) { u64_t hclk; /* set gpf15 (backlight pin) output and pull up and low level */ writel(S3C6410_GPFCON, (readl(S3C6410_GPFCON) & ~(0x3<<30)) | (0x1<<30)); writel(S3C6410_GPFPUD, (readl(S3C6410_GPFPUD) & ~(0x3<<30)) | (0x2<<30)); writel(S3C6410_GPFDAT, (readl(S3C6410_GPFDAT) & ~(0x1<<15)) | (0x0<<15)); /* must be '0' for normal-path instead of by-pass */ writel(S3C6410_MIFPCON, 0); /* select tft lcd type (rgb i/f) */ writel(S3C6410_SPCON, (readl(S3C6410_SPCON) & ~(0x3<<0)) | (0x1<<0)); /* lcd port config */ writel(S3C6410_GPICON, 0xaaaaaaaa); writel(S3C6410_GPJCON, 0xaaaaaaaa); /* initial lcd controler */ writel(S3C6410_VIDCON1, REGS_VIDCON1); writel(S3C6410_VIDTCON0, REGS_VIDTCON0); writel(S3C6410_VIDTCON1, REGS_VIDTCON1); writel(S3C6410_VIDTCON2, REGS_VIDTCON2); writel(S3C6410_DITHMODE, REGS_DITHMODE); /* get hclk for lcd */ clk_get_rate("hclk", &hclk); writel(S3C6410_VIDCON0, (REGS_VIDCON0 | S3C6410_VIDCON0_CLKVAL_F((u32_t)(div64(hclk, PIXEL_CLOCK) - 1)) ) ); /* turn all windows off */ writel(S3C6410_WINCON0, (readl(S3C6410_WINCON0) & ~0x1)); writel(S3C6410_WINCON1, (readl(S3C6410_WINCON1) & ~0x1)); writel(S3C6410_WINCON2, (readl(S3C6410_WINCON2) & ~0x1)); writel(S3C6410_WINCON3, (readl(S3C6410_WINCON3) & ~0x1)); writel(S3C6410_WINCON4, (readl(S3C6410_WINCON4) & ~0x1)); /* turn all windows color map off */ writel(S3C6410_WIN0MAP, (readl(S3C6410_WIN0MAP) & ~(1<<24))); writel(S3C6410_WIN1MAP, (readl(S3C6410_WIN1MAP) & ~(1<<24))); writel(S3C6410_WIN2MAP, (readl(S3C6410_WIN2MAP) & ~(1<<24))); writel(S3C6410_WIN3MAP, (readl(S3C6410_WIN3MAP) & ~(1<<24))); writel(S3C6410_WIN4MAP, (readl(S3C6410_WIN4MAP) & ~(1<<24))); /* turn all windows color key off */ writel(S3C6410_W1KEYCON0, (readl(S3C6410_W1KEYCON0) & ~(3<<25))); writel(S3C6410_W2KEYCON0, (readl(S3C6410_W2KEYCON0) & ~(3<<25))); writel(S3C6410_W3KEYCON0, (readl(S3C6410_W3KEYCON0) & ~(3<<25))); writel(S3C6410_W4KEYCON0, (readl(S3C6410_W4KEYCON0) & ~(3<<25))); /* config window 0 */ writel(S3C6410_WINCON0, (readl(S3C6410_WINCON0) & ~(0x1<<22 | 0x1<<16 | 0x3<<9 | 0xf<<2 | 0x1<<0)) | (0x5<<2 | 0x1<<16)); /* window 0 frambuffer addresss */ writel(S3C6410_VIDW00ADD0B0, ((u32_t)fb->info->surface.pixels)); writel(S3C6410_VIDW00ADD0B1, ((u32_t)fb->info->surface.pixels)); writel(S3C6410_VIDW00ADD1B0, (((u32_t)fb->info->surface.pixels) + LCD_WIDTH*LCD_HEIGHT*LCD_BPP/8)& 0x00ffffff); writel(S3C6410_VIDW00ADD1B1, (((u32_t)fb->info->surface.pixels) + LCD_WIDTH*LCD_HEIGHT*LCD_BPP/8)& 0x00ffffff); writel(S3C6410_VIDW00ADD2, (LCD_WIDTH*LCD_BPP/8) & 0x00001fff); /* config view port */ writel(S3C6410_VIDOSD0A, OSD_LTX(0) | OSD_LTY(0)); writel(S3C6410_VIDOSD0B, OSD_RBX(LCD_WIDTH) | OSD_RBY(LCD_HEIGHT)); writel(S3C6410_VIDOSD0C, OSDSIZE(LCD_WIDTH * LCD_HEIGHT)); /* enable window 0 */ writel(S3C6410_WINCON0, (readl(S3C6410_WINCON0) | 0x1)); /* enable video controller output */ writel(S3C6410_VIDCON0, (readl(S3C6410_VIDCON0) | 0x3)); /* delay for avoid flash screen */ mdelay(50); }
static int red_drops (struct dn_queue *q, int len) { /* * RED algorithm * * RED calculates the average queue size (avg) using a low-pass filter * with an exponential weighted (w_q) moving average: * avg <- (1-w_q) * avg + w_q * q_size * where q_size is the queue length (measured in bytes or * packets). * * If q_size == 0, we compute the idle time for the link, and set * avg = (1 - w_q)^(idle/s) * where s is the time needed for transmitting a medium-sized packet. * * Now, if avg < min_th the packet is enqueued. * If avg > max_th the packet is dropped. Otherwise, the packet is * dropped with probability P function of avg. */ struct dn_fsk *fs = q->fs; int64_t p_b = 0; /* Queue in bytes or packets? */ uint32_t q_size = (fs->fs.flags & DN_QSIZE_BYTES) ? q->ni.len_bytes : q->ni.length; /* Average queue size estimation. */ if (q_size != 0) { /* Queue is not empty, avg <- avg + (q_size - avg) * w_q */ int diff = SCALE(q_size) - q->avg; int64_t v = SCALE_MUL((int64_t)diff, (int64_t)fs->w_q); q->avg += (int)v; } else { /* * Queue is empty, find for how long the queue has been * empty and use a lookup table for computing * (1 - * w_q)^(idle_time/s) where s is the time to send a * (small) packet. * XXX check wraps... */ if (q->avg) { u_int t = div64((dn_cfg.curr_time - q->q_time), fs->lookup_step); q->avg = (t < fs->lookup_depth) ? SCALE_MUL(q->avg, fs->w_q_lookup[t]) : 0; } } /* Should i drop? */ if (q->avg < fs->min_th) { q->count = -1; return (0); /* accept packet */ } if (q->avg >= fs->max_th) { /* average queue >= max threshold */ if (fs->fs.flags & DN_IS_GENTLE_RED) { /* * According to Gentle-RED, if avg is greater than * max_th the packet is dropped with a probability * p_b = c_3 * avg - c_4 * where c_3 = (1 - max_p) / max_th * c_4 = 1 - 2 * max_p */ p_b = SCALE_MUL((int64_t)fs->c_3, (int64_t)q->avg) - fs->c_4; } else { q->count = -1; return (1); } } else if (q->avg > fs->min_th) { /* * We compute p_b using the linear dropping function * p_b = c_1 * avg - c_2 * where c_1 = max_p / (max_th - min_th) * c_2 = max_p * min_th / (max_th - min_th) */ p_b = SCALE_MUL((int64_t)fs->c_1, (int64_t)q->avg) - fs->c_2; } if (fs->fs.flags & DN_QSIZE_BYTES) p_b = div64((p_b * len) , fs->max_pkt_size); if (++q->count == 0) q->random = random() & 0xffff; else { /* * q->count counts packets arrived since last drop, so a greater * value of q->count means a greater packet drop probability. */ if (SCALE_MUL(p_b, SCALE((int64_t)q->count)) > q->random) { q->count = 0; /* After a drop we calculate a new random value. */ q->random = random() & 0xffff; return (1); /* drop */ } } /* End of RED algorithm. */ return (0); /* accept */ }