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

📄 h8.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Hitachi H8/337 Microcontroller driver * * The H8 is used to deal with the power and thermal environment * of a system. * * Fixes: *	June 1999, AV	added releasing /proc/driver/h8 *	Feb  2000, Borislav Deianov *			changed queues to use list.h instead of lists.h */#include <linux/config.h>#include <linux/module.h>#include <asm/system.h>#include <asm/segment.h>#include <asm/io.h>#include <linux/types.h>#include <linux/stddef.h>#include <linux/timer.h>#include <linux/fcntl.h>#include <linux/linkage.h>#include <linux/stat.h>#include <linux/proc_fs.h>#include <linux/miscdevice.h>#include <linux/list.h>#include <linux/ioport.h>#include <linux/poll.h>#include <linux/init.h>#include <linux/slab.h>#define __KERNEL_SYSCALLS__#include <asm/unistd.h>#include "h8.h"#define DEBUG_H8#ifdef DEBUG_H8#define Dprintk		printk#else#define Dprintk#endif#define XDprintk if(h8_debug==-1)printk/* * The h8 device is one of the misc char devices. */#define H8_MINOR_DEV   140/* * Forward declarations. */static int   h8_init(void);int          h8_display_blank(void);int          h8_display_unblank(void);static void  h8_intr(int irq, void *dev_id, struct pt_regs *regs);static int   h8_get_info(char *, char **, off_t, int);/* * Support Routines. */static void h8_hw_init(void);static void h8_start_new_cmd(void);static void h8_send_next_cmd_byte(void);static void h8_read_event_status(void);static void h8_sync(void);static void h8_q_cmd(u_char *, int, int);static void h8_cmd_done(h8_cmd_q_t *qp);static int  h8_alloc_queues(void);static u_long h8_get_cpu_speed(void);static int h8_get_curr_temp(u_char curr_temp[]);static void h8_get_max_temp(void);static void h8_get_upper_therm_thold(void);static void h8_set_upper_therm_thold(int);static int h8_get_ext_status(u_char stat_word[]);static int h8_monitor_thread(void *);static int h8_manage_therm(void);static void h8_set_cpu_speed(int speed_divisor);static void h8_start_monitor_timer(unsigned long secs);static void h8_activate_monitor(unsigned long unused);/* in arch/alpha/kernel/lca.c */extern void lca_clock_print(void);extern int  lca_get_clock(void);extern void lca_clock_fiddle(int);static void h8_set_event_mask(int);static void h8_clear_event_mask(int);/* * Driver structures */static struct timer_list h8_monitor_timer;static int h8_monitor_timer_active = 0;static char  driver_version[] = "X0.0";/* no spaces */union	intr_buf intrbuf;int	intr_buf_ptr;union   intr_buf xx;	u_char  last_temp;/* * I/O Macros for register reads and writes. */#define H8_READ(a) 	inb((a))#define H8_WRITE(d,a)	outb((d),(a))#define	H8_GET_STATUS	H8_READ((h8_base) + H8_STATUS_REG_OFF)#define H8_READ_DATA	H8_READ((h8_base) + H8_DATA_REG_OFF)#define WRITE_DATA(d)	H8_WRITE((d), h8_base + H8_DATA_REG_OFF)#define WRITE_CMD(d)	H8_WRITE((d), h8_base + H8_CMD_REG_OFF)unsigned int h8_base = H8_BASE_ADDR;unsigned int h8_irq = H8_IRQ;unsigned int h8_state = H8_IDLE;unsigned int h8_index = -1;unsigned int h8_enabled = 0;LIST_HEAD(h8_actq);LIST_HEAD(h8_cmdq);LIST_HEAD(h8_freeq);/*  * Globals used in thermal control of Alphabook1. */int cpu_speed_divisor = -1;			int h8_event_mask = 0;			DECLARE_WAIT_QUEUE_HEAD(h8_monitor_wait);unsigned int h8_command_mask = 0;int h8_uthermal_threshold = DEFAULT_UTHERMAL_THRESHOLD;int h8_uthermal_window = UTH_HYSTERESIS;		      int h8_debug = 0xfffffdfc;int h8_ldamp = MHZ_115;int h8_udamp = MHZ_57;u_char h8_current_temp = 0;u_char h8_system_temp = 0;int h8_sync_channel = 0;DECLARE_WAIT_QUEUE_HEAD(h8_sync_wait);int h8_init_performed;/* CPU speeds and clock divisor values */int speed_tab[6] = {230, 153, 115, 57, 28, 14};  /* * H8 interrupt handler */static void h8_intr(int irq, void *dev_id, struct pt_regs *regs){	u_char	stat_reg, data_reg;	h8_cmd_q_t *qp = list_entry(h8_actq.next, h8_cmd_q_t, link);	stat_reg = H8_GET_STATUS;	data_reg = H8_READ_DATA;	XDprintk("h8_intr: state %d status 0x%x data 0x%x\n", h8_state, stat_reg, data_reg);	switch (h8_state) {	  /* Response to an asynchronous event. */	case H8_IDLE: { /* H8_IDLE */	    if (stat_reg & H8_OFULL) {	        if (data_reg == H8_INTR) {		    h8_state = H8_INTR_MODE;		    /* Executing a command to determine what happened. */		    WRITE_CMD(H8_RD_EVENT_STATUS);		    intr_buf_ptr = 1;		    WRITE_CMD(H8_RD_EVENT_STATUS);		} else {		    Dprintk("h8_intr: idle stat 0x%x data 0x%x\n",			    stat_reg, data_reg);		}	    } else {	        Dprintk("h8_intr: bogus interrupt\n");	    }	    break;	}	case H8_INTR_MODE: { /* H8_INTR_MODE */	    XDprintk("H8 intr/intr_mode\n");	    if (data_reg == H8_BYTE_LEVEL_ACK) {	        return;	    } else if (data_reg == H8_CMD_ACK) {	        return;	    } else {	        intrbuf.byte[intr_buf_ptr] = data_reg;		if(!intr_buf_ptr) {		    h8_state = H8_IDLE;		    h8_read_event_status();		}		intr_buf_ptr--;	    }	    break;	}	/* Placed in this state by h8_start_new_cmd(). */	case H8_XMIT: { /* H8_XMIT */	    XDprintk("H8 intr/xmit\n");	    /* If a byte level acknowledgement has been received */	    if (data_reg == H8_BYTE_LEVEL_ACK) {	        XDprintk("H8 intr/xmit BYTE ACK\n");		qp->nacks++;		if (qp->nacks > qp->ncmd)		    if(h8_debug & 0x1)		        Dprintk("h8intr: bogus # of acks!\n");		/* 		 * If the number of bytes sent is less than the total 		 * number of bytes in the command.		 */ 		if (qp->cnt < qp->ncmd) {		    h8_send_next_cmd_byte();		}		return;		/* If the complete command has produced an acknowledgement. */	    } else if (data_reg == H8_CMD_ACK) {	        XDprintk("H8 intr/xmit CMD ACK\n");		/* If there are response bytes */		if (qp->nrsp)		    h8_state = H8_RCV;		else		    h8_state = H8_IDLE;		qp->cnt = 0;		return;		/* Error, need to start over with a clean slate. */	    } else if (data_reg == H8_NACK) {	        XDprintk("h8_intr: NACK received restarting command\n");		qp->nacks = 0;		qp->cnt = 0;		h8_state = H8_IDLE;		WRITE_CMD(H8_SYNC);		return;	    } else {	        Dprintk ("h8intr: xmit unknown data 0x%x \n", data_reg);		return;	    }	    break;	}	case H8_RESYNC: { /* H8_RESYNC */	    XDprintk("H8 intr/resync\n");	    if (data_reg == H8_BYTE_LEVEL_ACK) {	        return;	    } else if (data_reg == H8_SYNC_BYTE) {	        h8_state = H8_IDLE;		if (!list_empty(&h8_actq))		    h8_send_next_cmd_byte();	    } else {	        Dprintk ("h8_intr: resync unknown data 0x%x \n", data_reg);		return;	    }	    break;	} 	case H8_RCV: { /* H8_RCV */	    XDprintk("H8 intr/rcv\n");	    if (qp->cnt < qp->nrsp) {	        qp->rcvbuf[qp->cnt] = data_reg;		qp->cnt++;		/* If command reception finished. */		if (qp->cnt == qp->nrsp) {		    h8_state = H8_IDLE;		    list_del(&qp->link);		    h8_cmd_done (qp);		    /* More commands to send over? */		    if (!list_empty(&h8_cmdq))		        h8_start_new_cmd();		}		return;	    } else {	        Dprintk ("h8intr: rcv overflow cmd 0x%x\n", qp->cmdbuf[0]);	    }	    break;	}	default: /* default */	    Dprintk("H8 intr/unknown\n");	    break;	}	return;}static void __exit h8_cleanup (void){	remove_proc_entry("driver/h8", NULL);        release_region(h8_base, 8);        free_irq(h8_irq, NULL);}static int __init h8_init(void){        if(request_irq(h8_irq, h8_intr, SA_INTERRUPT, "h8", NULL))        {                printk(KERN_ERR "H8: error: IRQ %d is not free\n", h8_irq);                return -EIO;        }        printk(KERN_INFO "H8 at 0x%x IRQ %d\n", h8_base, h8_irq);        create_proc_info_entry("driver/h8", 0, NULL, h8_get_info);        request_region(h8_base, 8, "h8");	h8_alloc_queues();	h8_hw_init();	kernel_thread(h8_monitor_thread, NULL, 0);        return 0;}module_init(h8_init);module_exit(h8_cleanup);static void __init h8_hw_init(void){	u_char	buf[H8_MAX_CMD_SIZE];	/* set CPU speed to max for booting */	h8_set_cpu_speed(MHZ_230);	/*	 * Initialize the H8	 */	h8_sync();  /* activate interrupts */	/* To clear conditions left by console */	h8_read_event_status(); 	/* Perform a conditioning read */	buf[0] = H8_DEVICE_CONTROL;	buf[1] = 0xff;	buf[2] = 0x0;	h8_q_cmd(buf, 3, 1);	/* Turn on built-in and external mice, capture power switch */	buf[0] = H8_DEVICE_CONTROL;	buf[1] = 0x0;	buf[2] = H8_ENAB_INT_PTR | H8_ENAB_EXT_PTR |	       /*H8_DISAB_PWR_OFF_SW |*/ H8_ENAB_LOW_SPD_IND;	h8_q_cmd(buf, 3, 1);        h8_enabled = 1;	return;}static int h8_get_info(char *buf, char **start, off_t fpos, int length){#ifdef CONFIG_PROC_FS        char *p;        if (!h8_enabled)                return 0;        p = buf;        /*           0) Linux driver version (this will change if format changes)           1)            2)            3)           4)	*/                    p += sprintf(p, "%s \n",                     driver_version		     );        return p - buf;#else	return 0;#endif}/* Called from console driver -- must make sure h8_enabled. */int h8_display_blank(void){#ifdef CONFIG_H8_DISPLAY_BLANK        int     error;        if (!h8_enabled)                return 0;        error = h8_set_display_power_state(H8_STATE_STANDBY);        if (error == H8_SUCCESS)                return 1;        h8_error("set display standby", error);#endif        return 0;}

⌨️ 快捷键说明

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