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

📄 cycx_drv.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
/** cycx_drv.c	Cyclom 2X Support Module.**		This module is a library of common hardware specific*		functions used by the Cyclades Cyclom 2X sync card.** Author:	Arnaldo Carvalho de Melo <acme@conectiva.com.br>** Copyright:	(c) 1998-2003 Arnaldo Carvalho de Melo** Based on sdladrv.c by Gene Kozin <genek@compuserve.com>**		This program is free software; you can redistribute it and/or*		modify it under the terms of the GNU General Public License*		as published by the Free Software Foundation; either version*		2 of the License, or (at your option) any later version.* ============================================================================* 1999/11/11	acme		set_current_state(TASK_INTERRUPTIBLE), code*				cleanup* 1999/11/08	acme		init_cyc2x deleted, doing nothing* 1999/11/06	acme		back to read[bw], write[bw] and memcpy_to and*				fromio to use dpmbase ioremaped* 1999/10/26	acme		use isa_read[bw], isa_write[bw] & isa_memcpy_to*				& fromio* 1999/10/23	acme		cleanup to only supports cyclom2x: all the other*				boards are no longer manufactured by cyclades,*				if someone wants to support them... be my guest!* 1999/05/28    acme		cycx_intack & cycx_intde gone for good* 1999/05/18	acme		lots of unlogged work, submitting to Linus...* 1999/01/03	acme		more judicious use of data types* 1999/01/03	acme		judicious use of data types :>*				cycx_inten trying to reset pending interrupts*				from cyclom 2x - I think this isn't the way to*				go, but for now...* 1999/01/02	acme		cycx_intack ok, I think there's nothing to do*				to ack an int in cycx_drv.c, only handle it in*				cyx_isr (or in the other protocols: cyp_isr,*				cyf_isr, when they get implemented.* Dec 31, 1998	acme		cycx_data_boot & cycx_code_boot fixed, crossing*				fingers to see x25_configure in cycx_x25.c*				work... :)* Dec 26, 1998	acme		load implementation fixed, seems to work! :)*				cycx_2x_dpmbase_options with all the possible*				DPM addresses (20).*				cycx_intr implemented (test this!)*				general code cleanup* Dec  8, 1998	Ivan Passos	Cyclom-2X firmware load implementation.* Aug  8, 1998	acme		Initial version.*/#include <linux/init.h>		/* __init */#include <linux/module.h>#include <linux/kernel.h>	/* printk(), and other useful stuff */#include <linux/stddef.h>	/* offsetof(), etc. */#include <linux/errno.h>	/* return codes */#include <linux/sched.h>	/* for jiffies, HZ, etc. */#include <linux/cycx_drv.h>	/* API definitions */#include <linux/cycx_cfm.h>	/* CYCX firmware module definitions */#include <linux/delay.h>	/* udelay, msleep_interruptible */#include <asm/io.h>		/* read[wl], write[wl], ioremap, iounmap */#define	MOD_VERSION	0#define	MOD_RELEASE	6MODULE_AUTHOR("Arnaldo Carvalho de Melo");MODULE_DESCRIPTION("Cyclom 2x Sync Card Driver");MODULE_LICENSE("GPL");/* Hardware-specific functions */static int load_cyc2x(struct cycx_hw *hw, struct cycx_firmware *cfm, u32 len);static void cycx_bootcfg(struct cycx_hw *hw);static int reset_cyc2x(void __iomem *addr);static int detect_cyc2x(void __iomem *addr);/* Miscellaneous functions */static int get_option_index(long *optlist, long optval);static u16 checksum(u8 *buf, u32 len);#define wait_cyc(addr) cycx_exec(addr + CMD_OFFSET)/* Global Data *//* private data */static char modname[] = "cycx_drv";static char fullname[] = "Cyclom 2X Support Module";static char copyright[] = "(c) 1998-2003 Arnaldo Carvalho de Melo "			  "<acme@conectiva.com.br>";/* Hardware configuration options. * These are arrays of configuration options used by verification routines. * The first element of each array is its size (i.e. number of options). */static long cyc2x_dpmbase_options[] = {	20,	0xA0000, 0xA4000, 0xA8000, 0xAC000, 0xB0000, 0xB4000, 0xB8000,	0xBC000, 0xC0000, 0xC4000, 0xC8000, 0xCC000, 0xD0000, 0xD4000,	0xD8000, 0xDC000, 0xE0000, 0xE4000, 0xE8000, 0xEC000};static long cycx_2x_irq_options[]  = { 7, 3, 5, 9, 10, 11, 12, 15 };/* Kernel Loadable Module Entry Points *//* Module 'insert' entry point. * o print announcement * o initialize static data * * Return:	0	Ok *		< 0	error. * Context:	process */static int __init cycx_drv_init(void){	printk(KERN_INFO "%s v%u.%u %s\n", fullname, MOD_VERSION, MOD_RELEASE,			 copyright);	return 0;}/* Module 'remove' entry point. * o release all remaining system resources */static void cycx_drv_cleanup(void){}/* Kernel APIs *//* Set up adapter. * o detect adapter type * o verify hardware configuration options * o check for hardware conflicts * o set up adapter shared memory * o test adapter memory * o load firmware * Return:	0	ok. *		< 0	error */EXPORT_SYMBOL(cycx_setup);int cycx_setup(struct cycx_hw *hw, void *cfm, u32 len, unsigned long dpmbase){	int err;	/* Verify IRQ configuration options */	if (!get_option_index(cycx_2x_irq_options, hw->irq)) {		printk(KERN_ERR "%s: IRQ %d is invalid!\n", modname, hw->irq);		return -EINVAL;	}	/* Setup adapter dual-port memory window and test memory */	if (!dpmbase) {		printk(KERN_ERR "%s: you must specify the dpm address!\n",				modname); 		return -EINVAL;	} else if (!get_option_index(cyc2x_dpmbase_options, dpmbase)) {		printk(KERN_ERR "%s: memory address 0x%lX is invalid!\n",				modname, dpmbase);		return -EINVAL;	}	hw->dpmbase = ioremap(dpmbase, CYCX_WINDOWSIZE);	hw->dpmsize = CYCX_WINDOWSIZE;	if (!detect_cyc2x(hw->dpmbase)) {		printk(KERN_ERR "%s: adapter Cyclom 2X not found at "				"address 0x%lX!\n", modname, dpmbase);		return -EINVAL;	}	printk(KERN_INFO "%s: found Cyclom 2X card at address 0x%lX.\n",			 modname, dpmbase);	/* Load firmware. If loader fails then shut down adapter */	err = load_cyc2x(hw, cfm, len);	if (err)		cycx_down(hw);         /* shutdown adapter */	return err;}EXPORT_SYMBOL(cycx_down);int cycx_down(struct cycx_hw *hw){	iounmap(hw->dpmbase);	return 0;}/* Enable interrupt generation.  */static void cycx_inten(struct cycx_hw *hw){	writeb(0, hw->dpmbase);}/* Generate an interrupt to adapter's CPU. */EXPORT_SYMBOL(cycx_intr);void cycx_intr(struct cycx_hw *hw){	writew(0, hw->dpmbase + GEN_CYCX_INTR);}/* Execute Adapter Command. * o Set exec flag. * o Busy-wait until flag is reset. */EXPORT_SYMBOL(cycx_exec);int cycx_exec(void __iomem *addr){	u16 i = 0;	/* wait till addr content is zeroed */	while (readw(addr)) {		udelay(1000);		if (++i > 50)			return -1;	}	return 0;}/* Read absolute adapter memory. * Transfer data from adapter's memory to data buffer. */EXPORT_SYMBOL(cycx_peek);int cycx_peek(struct cycx_hw *hw, u32 addr, void *buf, u32 len){	if (len == 1)		*(u8*)buf = readb(hw->dpmbase + addr);	else		memcpy_fromio(buf, hw->dpmbase + addr, len);	return 0;}/* Write Absolute Adapter Memory. * Transfer data from data buffer to adapter's memory. */EXPORT_SYMBOL(cycx_poke);int cycx_poke(struct cycx_hw *hw, u32 addr, void *buf, u32 len){	if (len == 1)		writeb(*(u8*)buf, hw->dpmbase + addr);	else		memcpy_toio(hw->dpmbase + addr, buf, len);	return 0;}/* Hardware-Specific Functions *//* Load Aux Routines *//* Reset board hardware.   return 1 if memory exists at addr and 0 if not. */static int memory_exists(void __iomem *addr){	int tries = 0;	for (; tries < 3 ; tries++) {		writew(TEST_PATTERN, addr + 0x10);		if (readw(addr + 0x10) == TEST_PATTERN)			if (readw(addr + 0x10) == TEST_PATTERN)				return 1;		msleep_interruptible(1 * 1000);	}	return 0;}/* Load reset code. */static void reset_load(void __iomem *addr, u8 *buffer, u32 cnt){	void __iomem *pt_code = addr + RESET_OFFSET;	u16 i; /*, j; */	for (i = 0 ; i < cnt ; i++) {/*		for (j = 0 ; j < 50 ; j++); Delay - FIXME busy waiting... */		writeb(*buffer++, pt_code++);	}}/* Load buffer using boot interface. * o copy data from buffer to Cyclom-X memory * o wait for reset code to copy it to right portion of memory */static int buffer_load(void __iomem *addr, u8 *buffer, u32 cnt){	memcpy_toio(addr + DATA_OFFSET, buffer, cnt);	writew(GEN_BOOT_DAT, addr + CMD_OFFSET);	return wait_cyc(addr);}/* Set up entry point and kick start Cyclom-X CPU. */

⌨️ 快捷键说明

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