/* 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 void __exit dtlk_cleanup (void) { dtlk_write_bytes("goodbye", 8); msleep_interruptible(500); /* 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); }
static void __exit dtlk_cleanup (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); devfs_unregister_chrdev(dtlk_major, "dtlk"); devfs_unregister(devfs_handle); release_region(dtlk_port_lpc, DTLK_IO_EXTENT); }
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 (!request_region(dtlk_portlist[i], DTLK_IO_EXTENT, "dtlk")) continue; testval = inw_p(dtlk_portlist[i]); if ((testval &= 0xfbff) == 0x107f) { 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. */ msleep_interruptible(100); dtlk_has_indexing = dtlk_readable(); #ifdef TRACING printk(", indexing %d\n", dtlk_has_indexing); #endif #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_jiffy/(1000000/HZ)); \ } 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_jiffy / (1000/HZ)); 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_jiffy/(1000000/HZ)); /* 1 us */ \ } char buffer[1000]; int b = 0, i, j; mdelay(10); /* 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; } release_region(dtlk_portlist[i], DTLK_IO_EXTENT); } printk(KERN_INFO "DoubleTalk PC - not found\n"); return -ENODEV; }