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

📄 dtlk.c

📁 powerpc内核mpc8241linux系统下char驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
	TRACE_RET;	dtlk_stop_timer();	return 0;}int __init dtlk_init(void){	dtlk_port_lpc = 0;	dtlk_port_tts = 0;	dtlk_busy = 0;	dtlk_timer_active = 0;	dtlk_major = register_chrdev(0, "dtlk", &dtlk_fops);	if (dtlk_major == 0) {		printk(KERN_ERR "DoubleTalk PC - cannot register device\n");		return 0;	}	if (dtlk_dev_probe() == 0)		printk(", MAJOR %d\n", dtlk_major);	init_timer(&dtlk_timer);	dtlk_timer.function = dtlk_timer_tick;	dtlk_process_list = NULL;	return 0;}#ifdef MODULEint init_module(void){	return dtlk_init();}void cleanup_module(void){	dtlk_write_bytes("goodbye", 8);	current->state = TASK_INTERRUPTIBLE;	schedule_timeout(5 * HZ / 10);		/* nap 0.50 sec but						   could be awakened						   earlier by						   signals... */	dtlk_write_tts(DTLK_CLEAR);	unregister_chrdev(dtlk_major, "dtlk");	release_region(dtlk_port_lpc, DTLK_IO_EXTENT);}#endif/* ------------------------------------------------------------------------ *//* sleep for ms milliseconds */static void dtlk_delay(int ms){	current->state = TASK_INTERRUPTIBLE;	schedule_timeout((ms * HZ + 1000 - HZ) / 1000);	current->state = TASK_RUNNING;}static int dtlk_readable(void){	TRACE_TEXT(" dtlk_readable");	return inb_p(dtlk_port_lpc) != 0x7f;}static int dtlk_writeable(void){	/* TRACE_TEXT(" dtlk_writeable"); */#ifdef TRACING	printk(" dtlk_writeable(%02x)", inb_p(dtlk_port_tts));#endif	return inb_p(dtlk_port_tts) & TTS_WRITABLE;}static int __init dtlk_dev_probe(void){	unsigned int testval = 0;	int i = 0;	struct dtlk_settings *sp;	if (dtlk_port_lpc | dtlk_port_tts)		return -EBUSY;	for (i = 0; dtlk_portlist[i]; i++) {#if 0		printk("DoubleTalk PC - Port %03x = %04x\n",		       dtlk_portlist[i], (testval = inw_p(dtlk_portlist[i])));#endif		if (check_region(dtlk_portlist[i], DTLK_IO_EXTENT))			continue;		testval = inw_p(dtlk_portlist[i]);		if ((testval &= 0xfbff) == 0x107f) {			request_region(dtlk_portlist[i], DTLK_IO_EXTENT, 				       "dtlk");			dtlk_port_lpc = dtlk_portlist[i];			dtlk_port_tts = dtlk_port_lpc + 1;			sp = dtlk_interrogate();			printk("DoubleTalk PC at %03x-%03x, "			       "ROM version %s, serial number %u",			       dtlk_portlist[i], dtlk_portlist[i] +			       DTLK_IO_EXTENT - 1,			       sp->rom_version, sp->serial_number);                        /* put LPC port into known state, so			   dtlk_readable() gives valid result */			outb_p(0xff, dtlk_port_lpc);                         /* INIT string and index marker */			dtlk_write_bytes("\036\1@\0\0012I\r", 8);			/* posting an index takes 18 msec.  Here, we			   wait up to 100 msec to see whether it			   appears. */			dtlk_delay(100);			dtlk_has_indexing = dtlk_readable();#ifdef INSCOPE			{/* This macro records ten samples read from the LPC port, for later display */#define LOOK					\for (i = 0; i < 10; i++)			\  {						\    buffer[b++] = inb_p(dtlk_port_lpc);		\    __delay(loops_per_sec/1000000);             \  }				char buffer[1000];				int b = 0, i, j;				LOOK				    outb_p(0xff, dtlk_port_lpc);				buffer[b++] = 0;				LOOK				    dtlk_write_bytes("\0012I\r", 4);				buffer[b++] = 0;				__delay(50 * loops_per_sec / 1000);				outb_p(0xff, dtlk_port_lpc);				buffer[b++] = 0;				LOOK				    printk("\n");				for (j = 0; j < b; j++)					printk(" %02x", buffer[j]);				printk("\n");			}#endif				/* INSCOPE */#ifdef OUTSCOPE			{/* This macro records ten samples read from the TTS port, for later display */#define LOOK					\for (i = 0; i < 10; i++)			\  {						\    buffer[b++] = inb_p(dtlk_port_tts);		\    __delay(loops_per_sec/1000000);  /* 1 us */ \  }				char buffer[1000];				int b = 0, i, j;				__delay(loops_per_sec / 100);	/* 10 ms */				LOOK				    outb_p(0x03, dtlk_port_tts);				buffer[b++] = 0;				LOOK				    LOOK				    printk("\n");				for (j = 0; j < b; j++)					printk(" %02x", buffer[j]);				printk("\n");			}#endif				/* OUTSCOPE */			dtlk_write_bytes("Double Talk found", 18);			return 0;		}	}	printk(KERN_INFO "\nDoubleTalk PC - not found\n");	return -ENODEV;}/*   static void dtlk_handle_error(char op, char rc, unsigned int minor)   {   printk(KERN_INFO"\nDoubleTalk PC - MINOR: %d, OPCODE: %d, ERROR: %d\n",    minor, op, rc);   return;   } *//* interrogate the DoubleTalk PC and return its settings */static struct dtlk_settings *dtlk_interrogate(void){	unsigned char *t;	static char buf[sizeof(struct dtlk_settings) + 1];	int total, i;	static struct dtlk_settings status;	TRACE_TEXT("(dtlk_interrogate");	dtlk_write_bytes("\030\001?", 3);	for (total = 0, i = 0; i < 50; i++) {		buf[total] = dtlk_read_tts();		if (total > 2 && buf[total] == 0x7f)			break;		if (total < sizeof(struct dtlk_settings))			 total++;	}	/*	   if (i==50) printk("interrogate() read overrun\n");	   for (i=0; i<sizeof(buf); i++)	   printk(" %02x", buf[i]);	   printk("\n");	 */	t = buf;	status.serial_number = t[0] + t[1] * 256; /* serial number is						     little endian */	t += 2;	i = 0;	while (*t != '\r') {		status.rom_version[i] = *t;		if (i < sizeof(status.rom_version) - 1)			i++;		t++;	}	status.rom_version[i] = 0;	t++;	status.mode = *t++;	status.punc_level = *t++;	status.formant_freq = *t++;	status.pitch = *t++;	status.speed = *t++;	status.volume = *t++;	status.tone = *t++;	status.expression = *t++;	status.ext_dict_loaded = *t++;	status.ext_dict_status = *t++;	status.free_ram = *t++;	status.articulation = *t++;	status.reverb = *t++;	status.eob = *t++;	status.has_indexing = dtlk_has_indexing;	TRACE_RET;	return &status;}static char dtlk_read_tts(void){	int portval, retries = 0;	char ch;	TRACE_TEXT("(dtlk_read_tts");	/* verify DT is ready, read char, wait for ACK */	do {		portval = inb_p(dtlk_port_tts);	} while ((portval & TTS_READABLE) == 0 && retries++ < DTLK_MAX_RETRIES);	if (retries == DTLK_MAX_RETRIES)		printk(KERN_ERR "dtlk_read_tts() timeout\n");	ch = inb_p(dtlk_port_tts);	/* input from TTS port */	ch &= 0x7f;	outb_p(ch, dtlk_port_tts);	retries = 0;	do {		portval = inb_p(dtlk_port_tts);	} while ((portval & TTS_READABLE) != 0 && retries++ < DTLK_MAX_RETRIES);	if (retries == DTLK_MAX_RETRIES)		printk(KERN_ERR "dtlk_read_tts() timeout\n");	TRACE_RET;	return ch;}static char dtlk_read_lpc(void){	int retries = 0;	char ch;	TRACE_TEXT("(dtlk_read_lpc");	/* no need to test -- this is only called when the port is readable */	ch = inb_p(dtlk_port_lpc);	/* input from LPC port */	outb_p(0xff, dtlk_port_lpc);	/* acknowledging a read takes 3-4	   usec.  Here, we wait up to 20 usec	   for the acknowledgement */	retries = (loops_per_sec * 20) / 1000000;	while (inb_p(dtlk_port_lpc) != 0x7f && --retries > 0);	if (retries == 0)		printk(KERN_ERR "dtlk_read_lpc() timeout\n");	TRACE_RET;	return ch;}#ifdef NEVERstatic char dtlk_write_byte(unsigned int minor, const char *buf){	char ch;	int err;	/* TRACE_TEXT("(dtlk_write_byte"); */	err = get_user(ch, buf);	/* printk("  dtlk_write_byte(%d, 0x%02x)", minor, (int)ch); */	ch = dtlk_write_tts(ch);	/* 	   TRACE_RET; */	return ch;}#endif				/* NEVER *//* write n bytes to tts port */static char dtlk_write_bytes(const char *buf, int n){	char val = 0;	/*  printk("dtlk_write_bytes(\"%-*s\", %d)\n", n, buf, n); */	TRACE_TEXT("(dtlk_write_bytes");	while (n-- > 0)		val = dtlk_write_tts(*buf++);	TRACE_RET;	return val;}static char dtlk_write_tts(char ch){	int retries = 0;#ifdef TRACING	printk("  dtlk_write_tts(");	if (' ' <= ch && ch <= '~')		printk("'%c'", ch);	else		printk("0x%02x", ch);#endif	if (ch != DTLK_CLEAR)	/* no flow control for CLEAR command */		while ((inb_p(dtlk_port_tts) & TTS_WRITABLE) == 0 &&		       retries++ < DTLK_MAX_RETRIES)	/* DT ready? */			;	if (retries == DTLK_MAX_RETRIES)		printk(KERN_ERR "dtlk_write_tts() timeout\n");	outb_p(ch, dtlk_port_tts);	/* output to TTS port */	/* the RDY bit goes zero 2-3 usec after writing, and goes	   1 again 180-190 usec later.  Here, we wait up to 10	   usec for the RDY bit to go zero. */	for (retries = 0; retries < loops_per_sec / 100000; retries++)		if ((inb_p(dtlk_port_tts) & TTS_WRITABLE) == 0)			break;#ifdef TRACING	printk(")\n");#endif	return 0;}

⌨️ 快捷键说明

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