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

📄 via686a.c

📁 《linux驱动程序设计从入门到精通》一书中所有的程序代码含驱动和相应的应用程序
💻 C
📖 第 1 页 / 共 3 页
字号:
	u16 twoBits = val & 3;	/* no interpolation for these */	if (twoBits == 0 || eightBits == 255)		return TEMP_FROM_REG(eightBits);	/* do some linear interpolation */	return (tempLUT[eightBits] * (4 - twoBits) +	        tempLUT[eightBits + 1] * twoBits) * 25;}#define ALARMS_FROM_REG(val) (val)#define DIV_FROM_REG(val) (1 << (val))#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1)/* For the VIA686A, we need to keep some data in memory.   The structure is dynamically allocated, at the same time when a new   via686a client is allocated. */struct via686a_data {	struct i2c_client client;	struct semaphore update_lock;	char valid;		/* !=0 if following fields are valid */	unsigned long last_updated;	/* In jiffies */	u8 in[5];		/* Register value */	u8 in_max[5];		/* Register value */	u8 in_min[5];		/* Register value */	u8 fan[2];		/* Register value */	u8 fan_min[2];		/* Register value */	u16 temp[3];		/* Register value 10 bit */	u8 temp_over[3];	/* Register value */	u8 temp_hyst[3];	/* Register value */	u8 fan_div[2];		/* Register encoding, shifted right */	u16 alarms;		/* Register encoding, combined */};static struct pci_dev *s_bridge;	/* pointer to the (only) via686a */static int via686a_attach_adapter(struct i2c_adapter *adapter);static int via686a_detect(struct i2c_adapter *adapter, int address, int kind);static int via686a_detach_client(struct i2c_client *client);static inline int via686a_read_value(struct i2c_client *client, u8 reg){	return (inb_p(client->addr + reg));}static inline void via686a_write_value(struct i2c_client *client, u8 reg,				       u8 value){	outb_p(value, client->addr + reg);}static struct via686a_data *via686a_update_device(struct device *dev);static void via686a_init_client(struct i2c_client *client);/* following are the sysfs callback functions *//* 7 voltage sensors */static ssize_t show_in(struct device *dev, char *buf, int nr) {	struct via686a_data *data = via686a_update_device(dev);	return sprintf(buf, "%ld\n", IN_FROM_REG(data->in[nr], nr));}static ssize_t show_in_min(struct device *dev, char *buf, int nr) {	struct via686a_data *data = via686a_update_device(dev);	return sprintf(buf, "%ld\n", IN_FROM_REG(data->in_min[nr], nr));}static ssize_t show_in_max(struct device *dev, char *buf, int nr) {	struct via686a_data *data = via686a_update_device(dev);	return sprintf(buf, "%ld\n", IN_FROM_REG(data->in_max[nr], nr));}static ssize_t set_in_min(struct device *dev, const char *buf, 		size_t count, int nr) {	struct i2c_client *client = to_i2c_client(dev);	struct via686a_data *data = i2c_get_clientdata(client);	unsigned long val = simple_strtoul(buf, NULL, 10);	data->in_min[nr] = IN_TO_REG(val,nr);	via686a_write_value(client, VIA686A_REG_IN_MIN(nr), 			data->in_min[nr]);	return count;}static ssize_t set_in_max(struct device *dev, const char *buf, 		size_t count, int nr) {	struct i2c_client *client = to_i2c_client(dev);	struct via686a_data *data = i2c_get_clientdata(client);	unsigned long val = simple_strtoul(buf, NULL, 10);	data->in_max[nr] = IN_TO_REG(val,nr);	via686a_write_value(client, VIA686A_REG_IN_MAX(nr), 			data->in_max[nr]);	return count;}#define show_in_offset(offset)					\static ssize_t 							\	show_in##offset (struct device *dev, char *buf)		\{								\	return show_in(dev, buf, 0x##offset);			\}								\static ssize_t 							\	show_in##offset##_min (struct device *dev, char *buf)	\{								\	return show_in_min(dev, buf, 0x##offset);		\}								\static ssize_t 							\	show_in##offset##_max (struct device *dev, char *buf)	\{								\	return show_in_max(dev, buf, 0x##offset);		\}								\static ssize_t set_in##offset##_min (struct device *dev, 	\		const char *buf, size_t count) 			\{								\	return set_in_min(dev, buf, count, 0x##offset);		\}								\static ssize_t set_in##offset##_max (struct device *dev,	\			const char *buf, size_t count)		\{								\	return set_in_max(dev, buf, count, 0x##offset);		\}								\static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in##offset, NULL);\static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, 	\		show_in##offset##_min, set_in##offset##_min);	\static DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, 	\		show_in##offset##_max, set_in##offset##_max);show_in_offset(0);show_in_offset(1);show_in_offset(2);show_in_offset(3);show_in_offset(4);/* 3 temperatures */static ssize_t show_temp(struct device *dev, char *buf, int nr) {	struct via686a_data *data = via686a_update_device(dev);	return sprintf(buf, "%ld\n", TEMP_FROM_REG10(data->temp[nr]));}static ssize_t show_temp_over(struct device *dev, char *buf, int nr) {	struct via686a_data *data = via686a_update_device(dev);	return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp_over[nr]));}static ssize_t show_temp_hyst(struct device *dev, char *buf, int nr) {	struct via686a_data *data = via686a_update_device(dev);	return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp_hyst[nr]));}static ssize_t set_temp_over(struct device *dev, const char *buf, 		size_t count, int nr) {	struct i2c_client *client = to_i2c_client(dev);	struct via686a_data *data = i2c_get_clientdata(client);	int val = simple_strtol(buf, NULL, 10);	data->temp_over[nr] = TEMP_TO_REG(val);	via686a_write_value(client, VIA686A_REG_TEMP_OVER(nr), data->temp_over[nr]);	return count;}static ssize_t set_temp_hyst(struct device *dev, const char *buf, 		size_t count, int nr) {	struct i2c_client *client = to_i2c_client(dev);	struct via686a_data *data = i2c_get_clientdata(client);	int val = simple_strtol(buf, NULL, 10);	data->temp_hyst[nr] = TEMP_TO_REG(val);	via686a_write_value(client, VIA686A_REG_TEMP_HYST(nr), data->temp_hyst[nr]);	return count;}#define show_temp_offset(offset)					\static ssize_t show_temp_##offset (struct device *dev, char *buf)	\{									\	return show_temp(dev, buf, 0x##offset - 1);			\}									\static ssize_t								\show_temp_##offset##_over (struct device *dev, char *buf)		\{									\	return show_temp_over(dev, buf, 0x##offset - 1);			\}									\static ssize_t								\show_temp_##offset##_hyst (struct device *dev, char *buf)		\{									\	return show_temp_hyst(dev, buf, 0x##offset - 1);			\}									\static ssize_t set_temp_##offset##_over (struct device *dev, 		\		const char *buf, size_t count) 				\{									\	return set_temp_over(dev, buf, count, 0x##offset - 1);		\}									\static ssize_t set_temp_##offset##_hyst (struct device *dev, 		\		const char *buf, size_t count) 				\{									\	return set_temp_hyst(dev, buf, count, 0x##offset - 1);		\}									\static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp_##offset, NULL);\static DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, 		\		show_temp_##offset##_over, set_temp_##offset##_over);	\static DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO | S_IWUSR, 		\		show_temp_##offset##_hyst, set_temp_##offset##_hyst);	show_temp_offset(1);show_temp_offset(2);show_temp_offset(3);/* 2 Fans */static ssize_t show_fan(struct device *dev, char *buf, int nr) {	struct via686a_data *data = via686a_update_device(dev);	return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan[nr], 				DIV_FROM_REG(data->fan_div[nr])) );}static ssize_t show_fan_min(struct device *dev, char *buf, int nr) {	struct via686a_data *data = via686a_update_device(dev);	return sprintf(buf,"%d\n",		FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])) );}static ssize_t show_fan_div(struct device *dev, char *buf, int nr) {	struct via686a_data *data = via686a_update_device(dev);	return sprintf(buf,"%d\n", DIV_FROM_REG(data->fan_div[nr]) );}static ssize_t set_fan_min(struct device *dev, const char *buf, 		size_t count, int nr) {	struct i2c_client *client = to_i2c_client(dev);	struct via686a_data *data = i2c_get_clientdata(client);	int val = simple_strtol(buf, NULL, 10);	data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));	via686a_write_value(client, VIA686A_REG_FAN_MIN(nr+1), data->fan_min[nr]);	return count;}static ssize_t set_fan_div(struct device *dev, const char *buf, 		size_t count, int nr) {	struct i2c_client *client = to_i2c_client(dev);	struct via686a_data *data = i2c_get_clientdata(client);	int val = simple_strtol(buf, NULL, 10);	int old = via686a_read_value(client, VIA686A_REG_FANDIV);	data->fan_div[nr] = DIV_TO_REG(val);	old = (old & 0x0f) | (data->fan_div[1] << 6) | (data->fan_div[0] << 4);	via686a_write_value(client, VIA686A_REG_FANDIV, old);	return count;}#define show_fan_offset(offset)						\static ssize_t show_fan_##offset (struct device *dev, char *buf)	\{									\	return show_fan(dev, buf, 0x##offset - 1);			\}									\static ssize_t show_fan_##offset##_min (struct device *dev, char *buf)	\{									\	return show_fan_min(dev, buf, 0x##offset - 1);			\}									\static ssize_t show_fan_##offset##_div (struct device *dev, char *buf)	\{									\	return show_fan_div(dev, buf, 0x##offset - 1);			\}									\static ssize_t set_fan_##offset##_min (struct device *dev, 		\	const char *buf, size_t count) 					\{									\	return set_fan_min(dev, buf, count, 0x##offset - 1);		\}									\static ssize_t set_fan_##offset##_div (struct device *dev, 		\		const char *buf, size_t count) 				\{									\	return set_fan_div(dev, buf, count, 0x##offset - 1);		\}									\static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, NULL);\static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, 		\		show_fan_##offset##_min, set_fan_##offset##_min);	\static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, 		\		show_fan_##offset##_div, set_fan_##offset##_div);show_fan_offset(1);show_fan_offset(2);/* Alarms */static ssize_t show_alarms(struct device *dev, char *buf) {	struct via686a_data *data = via686a_update_device(dev);	return sprintf(buf,"%d\n", ALARMS_FROM_REG(data->alarms));}static DEVICE_ATTR(alarms, S_IRUGO | S_IWUSR, show_alarms, NULL);/* The driver. I choose to use type i2c_driver, as at is identical to both   smbus_driver and isa_driver, and clients could be of either kind */static struct i2c_driver via686a_driver = {	.owner		= THIS_MODULE,	.name		= "via686a",	.id		= I2C_DRIVERID_VIA686A,	.flags		= I2C_DF_NOTIFY,	.attach_adapter	= via686a_attach_adapter,	.detach_client	= via686a_detach_client,};

⌨️ 快捷键说明

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