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

📄 led.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
📖 第 1 页 / 共 2 页
字号:
/*   **    ** led_get_diskio_stats()   **    ** calculate the disk-io througput in the system   ** (analog to linux/fs/proc/proc_misc.c)   **    */static unsigned long led_diskio_counter;static void led_get_diskio_stats(int addvalue){		static unsigned int diskio_total_last, diskio_max;	int major, disk, total;		total = 0;	for (major = 0; major < DK_MAX_MAJOR; major++) {	    for (disk = 0; disk < DK_MAX_DISK; disk++)		total += kstat.dk_drive[major][disk];	}	total -= diskio_total_last;		if (total) {	    if (total >= diskio_max) {		led_diskio_counter += addvalue;	        diskio_max = total; /* new maximum value found */ 	    } else		led_diskio_counter += CALC_ADD(total, diskio_max, addvalue);	}		diskio_total_last += total; }/*   ** led_tasklet_func()   **    ** is scheduled at every timer interrupt from time.c and   ** updates the chassis LCD/LED     TODO:    - display load average (older machines like 715/64 have 4 "free" LED's for that)    - optimizations */static unsigned char currentleds;	/* stores current value of the LEDs */#define HEARTBEAT_LEN (HZ*6/100)#define HEARTBEAT_2ND_RANGE_START (HZ*22/100)#define HEARTBEAT_2ND_RANGE_END   (HEARTBEAT_2ND_RANGE_START + HEARTBEAT_LEN)static void led_tasklet_func(unsigned long unused){	static unsigned int count, count_HZ;	static unsigned char lastleds;	/* exit if not initialized */	if (!led_func_ptr)	    return;	/* increment the local counters */	++count;	if (++count_HZ == HZ)	    count_HZ = 0;	if (led_heartbeat)	{		/* flash heartbeat-LED like a real heart (2 x short then a long delay) */		if (count_HZ<HEARTBEAT_LEN || 		    (count_HZ>=HEARTBEAT_2ND_RANGE_START && count_HZ<HEARTBEAT_2ND_RANGE_END)) 		    currentleds |= LED_HEARTBEAT;		else		    currentleds &= ~LED_HEARTBEAT;	}	/* gather network and diskio statistics and flash LEDs respectively */	if (led_lanrxtx)	{		if ((count & 31) == 0)			led_get_net_stats(30);		if (led_net_rx_counter) {			led_net_rx_counter--;			currentleds |= LED_LAN_RCV;		}		else    			currentleds &= ~LED_LAN_RCV;		if (led_net_tx_counter) {			led_net_tx_counter--;			currentleds |= LED_LAN_TX;		}		else    			currentleds &= ~LED_LAN_TX;	}	if (led_diskio)	{		/* avoid to calculate diskio-stats at same irq as netio-stats ! */		if ((count & 31) == 15) 			led_get_diskio_stats(30);		if (led_diskio_counter) {			led_diskio_counter--;			currentleds |= LED_DISK_IO;		}		else    			currentleds &= ~LED_DISK_IO;	}	/* update the LCD/LEDs */	if (currentleds != lastleds) {	    led_func_ptr(currentleds);	    lastleds = currentleds;	}}/* main led tasklet struct (scheduled from time.c) */DECLARE_TASKLET_DISABLED(led_tasklet, led_tasklet_func, 0);/*   ** led_halt()   **    ** called by the reboot notifier chain at shutdown and stops all   ** LED/LCD activities.   **  */static int led_halt(struct notifier_block *, unsigned long, void *);static struct notifier_block led_notifier = {	notifier_call: led_halt,};static int led_halt(struct notifier_block *nb, unsigned long event, void *buf) {	char *txt;		switch (event) {	case SYS_RESTART:	txt = "SYSTEM RESTART";				break;	case SYS_HALT:		txt = "SYSTEM HALT";				break;	case SYS_POWER_OFF:	txt = "SYSTEM POWER OFF";				break;	default:		return NOTIFY_DONE;	}		/* completely stop the LED/LCD tasklet */	tasklet_disable(&led_tasklet);	if (lcd_info.model == DISPLAY_MODEL_LCD)		lcd_print(txt);	else		if (led_func_ptr)			led_func_ptr(0xff); /* turn all LEDs ON */		unregister_reboot_notifier(&led_notifier);	return NOTIFY_OK;}/*   ** register_led_driver()   **    ** registers an external LED or LCD for usage by this driver.   ** currently only LCD-, LASI- and ASP-style LCD/LED's are supported.   **  */int __init register_led_driver(int model, char *cmd_reg, char *data_reg){	static int initialized;		if (initialized || !data_reg)	    return 1;		lcd_info.model = model;		/* store the values */	LCD_CMD_REG = (cmd_reg == LED_CMD_REG_NONE) ? NULL : cmd_reg;	switch (lcd_info.model) {	case DISPLAY_MODEL_LCD:		LCD_DATA_REG = data_reg;		printk(KERN_INFO "LCD display at %p,%p registered\n", 			LCD_CMD_REG , LCD_DATA_REG);		led_func_ptr = led_LCD_driver;		lcd_print( "Linux " UTS_RELEASE );		led_type = LED_HASLCD;		break;	case DISPLAY_MODEL_LASI:		LED_DATA_REG = data_reg;		led_func_ptr = led_LASI_driver;		printk(KERN_INFO "LED display at %p registered\n", LED_DATA_REG);		led_type = LED_NOLCD;		break;	case DISPLAY_MODEL_OLD_ASP:		LED_DATA_REG = data_reg;		led_func_ptr = led_ASP_driver;		printk(KERN_INFO "LED (ASP-style) display at %p registered\n", 		    LED_DATA_REG);		led_type = LED_NOLCD;		break;	default:		printk(KERN_ERR "%s: Wrong LCD/LED model %d !\n",		       __FUNCTION__, lcd_info.model);		return 1;	}		/* mark the LCD/LED driver now as initialized and 	 * register to the reboot notifier chain */	initialized++;	register_reboot_notifier(&led_notifier);	/* start the led tasklet for the first time */	tasklet_enable(&led_tasklet);		return 0;}/*   ** register_led_regions()   **    ** register_led_regions() registers the LCD/LED regions for /procfs.   ** At bootup - where the initialisation of the LCD/LED normally happens -    ** not all internal structures of request_region() are properly set up,   ** so that we delay the led-registration until after busdevices_init()    ** has been executed.   ** */void __init register_led_regions(void){	switch (lcd_info.model) {	case DISPLAY_MODEL_LCD:		request_mem_region((unsigned long)LCD_CMD_REG,  1, "lcd_cmd");		request_mem_region((unsigned long)LCD_DATA_REG, 1, "lcd_data");		break;	case DISPLAY_MODEL_LASI:	case DISPLAY_MODEL_OLD_ASP:		request_mem_region((unsigned long)LED_DATA_REG, 1, "led_data");		break;	}}/*   **    ** lcd_print()   **    ** Displays the given string on the LCD-Display of newer machines.   ** lcd_print() disables the timer-based led tasklet during its    ** execution and enables it afterwards again.   ** */int lcd_print( char *str ){	int i;	if (!led_func_ptr || lcd_info.model != DISPLAY_MODEL_LCD)	    return 0;		/* temporarily disable the led tasklet */	tasklet_disable(&led_tasklet);	/* copy display string to buffer for procfs */	strncpy(lcd_text, str, sizeof(lcd_text)-1);		/* Set LCD Cursor to 1st character */	gsc_writeb(lcd_info.reset_cmd1, LCD_CMD_REG);	udelay(lcd_info.min_cmd_delay);	/* Print the string */	for (i=0; i < lcd_info.lcd_width; i++) {	    if (str && *str)		gsc_writeb(*str++, LCD_DATA_REG);	    else		gsc_writeb(' ', LCD_DATA_REG);	    udelay(lcd_info.min_cmd_delay);	}		/* re-enable the led tasklet */	tasklet_enable(&led_tasklet);	return lcd_info.lcd_width;}/*   ** led_init()   **    ** led_init() is called very early in the bootup-process from setup.c    ** and asks the PDC for an usable chassis LCD or LED.   ** If the PDC doesn't return any info, then the LED   ** is detected by lasi.c or asp.c and registered with the   ** above functions lasi_led_init() or asp_led_init().   ** KittyHawk machines have often a buggy PDC, so that   ** we explicitly check for those machines here. */int __init led_init(void){	struct pdc_chassis_info chassis_info;	int ret;	/* Work around the buggy PDC of KittyHawk-machines */	switch (CPU_HVERSION) {	case 0x580:		/* KittyHawk DC2-100 (K100) */	case 0x581:		/* KittyHawk DC3-120 (K210) */	case 0x582:		/* KittyHawk DC3 100 (K400) */	case 0x583:		/* KittyHawk DC3 120 (K410) */	case 0x58B:		/* KittyHawk DC2 100 (K200) */		printk(KERN_INFO "%s: KittyHawk-Machine (hversion 0x%x) found, "				"LED detection skipped.\n", __FILE__, CPU_HVERSION);		goto found;	/* use the preinitialized values of lcd_info */	}	/* initialize the struct, so that we can check for valid return values */	lcd_info.model = DISPLAY_MODEL_NONE;	chassis_info.actcnt = chassis_info.maxcnt = 0;	if ((ret = pdc_chassis_info(&chassis_info, &lcd_info, sizeof(lcd_info))) == PDC_OK) {		DPRINTK((KERN_INFO "%s: chassis info: model=%d (%s), "			 "lcd_width=%d, cmd_delay=%u,\n"			 "%s: sizecnt=%d, actcnt=%ld, maxcnt=%ld\n",		         __FILE__, lcd_info.model,			 (lcd_info.model==DISPLAY_MODEL_LCD) ? "LCD" :			  (lcd_info.model==DISPLAY_MODEL_LASI) ? "LED" : "unknown",			 lcd_info.lcd_width, lcd_info.min_cmd_delay,			 __FILE__, sizeof(lcd_info), 			 chassis_info.actcnt, chassis_info.maxcnt));		DPRINTK((KERN_INFO "%s: cmd=%p, data=%p, reset1=%x, reset2=%x, act_enable=%d\n",			__FILE__, lcd_info.lcd_cmd_reg_addr, 			lcd_info.lcd_data_reg_addr, lcd_info.reset_cmd1,  			lcd_info.reset_cmd2, lcd_info.act_enable ));			/* check the results. Some machines have a buggy PDC */		if (chassis_info.actcnt <= 0 || chassis_info.actcnt != chassis_info.maxcnt)			goto not_found;		switch (lcd_info.model) {		case DISPLAY_MODEL_LCD:		/* LCD display */			if (chassis_info.actcnt < 				offsetof(struct pdc_chassis_lcd_info_ret_block, _pad)-1)				goto not_found;			if (!lcd_info.act_enable) {				DPRINTK((KERN_INFO "PDC prohibited usage of the LCD.\n"));				goto not_found;			}			break;		case DISPLAY_MODEL_NONE:	/* no LED or LCD available */			printk(KERN_INFO "PDC reported no LCD or LED.\n");			goto not_found;		case DISPLAY_MODEL_LASI:	/* Lasi style 8 bit LED display */			if (chassis_info.actcnt != 8 && chassis_info.actcnt != 32)				goto not_found;			break;		default:			printk(KERN_WARNING "PDC reported unknown LCD/LED model %d\n",			       lcd_info.model);			goto not_found;		} /* switch() */found:		/* register the LCD/LED driver */		register_led_driver(lcd_info.model, LCD_CMD_REG, LCD_DATA_REG);		return 0;	} else { /* if() */		DPRINTK((KERN_INFO "pdc_chassis_info call failed with retval = %d\n", ret));	}not_found:	lcd_info.model = DISPLAY_MODEL_NONE;	return 1;}#ifdef CONFIG_PROC_FSmodule_init(led_create_procfs)#endif

⌨️ 快捷键说明

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