/* 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 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 ssize_t dtlk_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos) { int i = 0, retries = 0, ch; TRACE_TEXT("(dtlk_write"); #ifdef TRACING printk(" \""); { int i, ch; for (i = 0; i < count; i++) { if (get_user(ch, buf + i)) return -EFAULT; if (' ' <= ch && ch <= '~') printk("%c", ch); else printk("\\%03o", ch); } printk("\""); } #endif if (iminor(file->f_path.dentry->d_inode) != DTLK_MINOR) return -EINVAL; while (1) { while (i < count && !get_user(ch, buf) && (ch == DTLK_CLEAR || dtlk_writeable())) { dtlk_write_tts(ch); buf++; i++; if (i % 5 == 0) /* We yield our time until scheduled again. This reduces the transfer rate to 500 bytes/sec, but that's still enough to keep up with the speech synthesizer. */ msleep_interruptible(1); else { /* the RDY bit goes zero 2-3 usec after writing, and goes 1 again 180-190 usec later. Here, we wait up to 250 usec for the RDY bit to go nonzero. */ for (retries = 0; retries < loops_per_jiffy / (4000/HZ); retries++) if (inb_p(dtlk_port_tts) & TTS_WRITABLE) break; } retries = 0; } if (i == count) return i; if (file->f_flags & O_NONBLOCK) break; msleep_interruptible(1); if (++retries > 10 * HZ) { /* wait no more than 10 sec from last write */ printk("dtlk: write timeout. " "inb_p(dtlk_port_tts) = 0x%02x\n", inb_p(dtlk_port_tts)); TRACE_RET; return -EBUSY; } } TRACE_RET; return -EAGAIN; }