50 #include <linux/module.h>
53 #include <linux/types.h>
56 #include <linux/errno.h>
59 #include <linux/sched.h>
62 #include <asm/uaccess.h>
63 #include <linux/wait.h>
65 #include <linux/poll.h>
69 #define TRACE_TEXT(str) printk(str);
70 #define TRACE_RET printk(")")
72 #define TRACE_TEXT(str) ((void) 0)
73 #define TRACE_RET ((void) 0)
77 static void dtlk_timer_tick(
unsigned long data);
79 static int dtlk_major;
80 static int dtlk_port_lpc;
81 static int dtlk_port_tts;
83 static int dtlk_has_indexing;
84 static unsigned int dtlk_portlist[] =
85 {0x25e, 0x29e, 0x2de, 0x31e, 0x35e, 0x39e, 0};
90 static ssize_t dtlk_read(
struct file *,
char __user *,
91 size_t nbytes, loff_t * ppos);
92 static ssize_t dtlk_write(
struct file *,
const char __user *,
93 size_t nbytes, loff_t * ppos);
95 static int dtlk_open(
struct inode *,
struct file *);
96 static int dtlk_release(
struct inode *,
struct file *);
97 static long dtlk_ioctl(
struct file *
file,
98 unsigned int cmd,
unsigned long arg);
106 .unlocked_ioctl = dtlk_ioctl,
108 .release = dtlk_release,
113 static int dtlk_dev_probe(
void);
115 static int dtlk_readable(
void);
116 static char dtlk_read_lpc(
void);
117 static char dtlk_read_tts(
void);
118 static int dtlk_writeable(
void);
119 static char dtlk_write_bytes(
const char *
buf,
int n);
120 static char dtlk_write_tts(
char);
126 size_t count, loff_t * ppos)
128 unsigned int minor = iminor(file->
f_path.dentry->d_inode);
135 if (minor !=
DTLK_MINOR || !dtlk_has_indexing)
139 while (i < count && dtlk_readable()) {
140 ch = dtlk_read_lpc();
152 if (
retries == loops_per_jiffy)
158 static ssize_t dtlk_write(
struct file *file,
const char __user *buf,
159 size_t count, loff_t * ppos)
168 for (i = 0; i <
count; i++) {
171 if (
' ' <= ch && ch <=
'~')
184 while (i < count && !
get_user(ch, buf) &&
205 if (
inb_p(dtlk_port_tts) &
220 printk(
"dtlk: write timeout. "
221 "inb_p(dtlk_port_tts) = 0x%02x\n",
222 inb_p(dtlk_port_tts));
231 static unsigned int dtlk_poll(
struct file *file,
poll_table *
wait)
234 unsigned long expires;
243 poll_wait(file, &dtlk_process_list, wait);
245 if (dtlk_has_indexing && dtlk_readable()) {
249 if (dtlk_writeable()) {
262 static void dtlk_timer_tick(
unsigned long data)
268 static long dtlk_ioctl(
struct file *file,
281 sp = dtlk_interrogate();
288 portval =
inb_p(dtlk_port_tts);
297 static int dtlk_open(
struct inode *
inode,
struct file *file)
302 switch (iminor(inode)) {
313 static int dtlk_release(
struct inode *inode,
struct file *file)
317 switch (iminor(inode)) {
331 static int __init dtlk_init(
void)
338 dtlk_major = register_chrdev(0,
"dtlk", &dtlk_fops);
339 if (dtlk_major < 0) {
343 err = dtlk_dev_probe();
345 unregister_chrdev(dtlk_major,
"dtlk");
348 printk(
", MAJOR %d\n", dtlk_major);
355 static void __exit dtlk_cleanup (
void)
357 dtlk_write_bytes(
"goodbye", 8);
364 unregister_chrdev(dtlk_major,
"dtlk");
373 static int dtlk_readable(
void)
376 printk(
" dtlk_readable=%u@%u",
inb_p(dtlk_port_lpc) != 0x7f, jiffies);
378 return inb_p(dtlk_port_lpc) != 0x7f;
381 static int dtlk_writeable(
void)
390 static int __init dtlk_dev_probe(
void)
392 unsigned int testval = 0;
396 if (dtlk_port_lpc | dtlk_port_tts)
399 for (i = 0; dtlk_portlist[
i]; i++) {
401 printk(
"DoubleTalk PC - Port %03x = %04x\n",
402 dtlk_portlist[i], (testval =
inw_p(dtlk_portlist[i])));
408 testval =
inw_p(dtlk_portlist[i]);
409 if ((testval &= 0xfbff) == 0x107f) {
410 dtlk_port_lpc = dtlk_portlist[
i];
411 dtlk_port_tts = dtlk_port_lpc + 1;
413 sp = dtlk_interrogate();
414 printk(
"DoubleTalk PC at %03x-%03x, "
415 "ROM version %s, serial number %u",
416 dtlk_portlist[i], dtlk_portlist[i] +
422 outb_p(0xff, dtlk_port_lpc);
425 dtlk_write_bytes(
"\036\1@\0\0012I\r", 8);
430 dtlk_has_indexing = dtlk_readable();
432 printk(
", indexing %d\n", dtlk_has_indexing);
438 for (i = 0; i < 10; i++) \
440 buffer[b++] = inb_p(dtlk_port_lpc); \
441 __delay(loops_per_jiffy/(1000000/HZ)); \
447 outb_p(0xff, dtlk_port_lpc);
450 dtlk_write_bytes(
"\0012I\r", 4);
452 __delay(50 * loops_per_jiffy / (1000/
HZ));
453 outb_p(0xff, dtlk_port_lpc);
458 for (j = 0; j <
b; j++)
459 printk(
" %02x", buffer[j]);
468 for (i = 0; i < 10; i++) \
470 buffer[b++] = inb_p(dtlk_port_tts); \
471 __delay(loops_per_jiffy/(1000000/HZ)); \
478 outb_p(0x03, dtlk_port_tts);
484 for (j = 0; j <
b; j++)
485 printk(
" %02x", buffer[j]);
490 dtlk_write_bytes(
"Double Talk found", 18);
518 dtlk_write_bytes(
"\030\001?", 3);
519 for (total = 0, i = 0; i < 50; i++) {
520 buf[total] = dtlk_read_tts();
521 if (total > 2 && buf[total] == 0x7f)
533 status.serial_number = t[0] + t[1] * 256;
540 if (i <
sizeof(
status.rom_version) - 1)
549 status.formant_freq = *t++;
555 status.ext_dict_loaded = *t++;
556 status.ext_dict_status = *t++;
558 status.articulation = *t++;
561 status.has_indexing = dtlk_has_indexing;
566 static char dtlk_read_tts(
void)
574 portval =
inb_p(dtlk_port_tts);
580 ch =
inb_p(dtlk_port_tts);
582 outb_p(ch, dtlk_port_tts);
586 portval =
inb_p(dtlk_port_tts);
587 }
while ((portval & TTS_READABLE) != 0 &&
596 static char dtlk_read_lpc(
void)
604 ch =
inb_p(dtlk_port_lpc);
606 outb_p(0xff, dtlk_port_lpc);
611 retries = (loops_per_jiffy * 20) / (1000000/
HZ);
612 while (
inb_p(dtlk_port_lpc) != 0x7f && --retries > 0);
621 static char dtlk_write_bytes(
const char *buf,
int n)
627 val = dtlk_write_tts(*buf++);
632 static char dtlk_write_tts(
char ch)
636 printk(
" dtlk_write_tts(");
637 if (
' ' <= ch && ch <=
'~')
649 outb_p(ch, dtlk_port_tts);
653 for (retries = 0; retries < loops_per_jiffy / (100000/
HZ); retries++)
654 if ((
inb_p(dtlk_port_tts) & TTS_WRITABLE) == 0)