/* * Compatibility mode handshaking is a matter of writing data, * strobing it, and waiting for the printer to stop being busy. */ static long write_compat(unsigned minor, const char *c, unsigned long cnt) { long rc; unsigned short pins = get_pins(minor); unsigned long remaining = cnt; while (remaining > 0) { unsigned char byte; get_user_ret(byte, c, -EFAULT); c += 1; rc = wait_for(BPP_GP_nAck, BPP_GP_Busy, TIME_IDLE_LIMIT, minor); if (rc == -1) return -ETIMEDOUT; bpp_outb_p(byte, base_addrs[minor]); remaining -= 1; /* snooze(1, minor); */ pins &= ~BPP_PP_nStrobe; set_pins(pins, minor); rc = wait_for(BPP_GP_Busy, 0, TIME_PResponse, minor); pins |= BPP_PP_nStrobe; set_pins(pins, minor); } return cnt - remaining; }
static int bpp_ioctl(struct inode *inode, struct file *f, unsigned int cmd, unsigned long arg) { int errno = 0; unsigned minor = MINOR(inode->i_rdev); if (minor >= BPP_NO) return -ENODEV; if (!instances[minor].present) return -ENODEV; switch (cmd) { case BPP_PUT_PINS: set_pins(arg, minor); break; case BPP_GET_PINS: errno = get_pins(minor); break; case BPP_PUT_DATA: bpp_outb_p(arg, base_addrs[minor]); break; case BPP_GET_DATA: errno = bpp_inb_p(base_addrs[minor]); break; case BPP_SET_INPUT: if (arg) if (instances[minor].enhanced) { unsigned short bits = get_pins(minor); instances[minor].direction = 0x20; set_pins(bits, minor); } else { errno = -ENOTTY; } else { unsigned short bits = get_pins(minor); instances[minor].direction = 0x00; set_pins(bits, minor); } break; default: errno = -EINVAL; } return errno; }
/* * Write data using ECP mode. Watch out that the port may be set up * for reading. If so, turn the port around. */ static long write_ecp(unsigned minor, const char __user *c, unsigned long cnt) { unsigned short pins = get_pins(minor); unsigned long remaining = cnt; if (instances[minor].direction) { int rc; /* Event 47 Request bus be turned around */ pins |= BPP_PP_nInit; set_pins(pins, minor); /* Wait for Event 49: Peripheral relinquished bus */ rc = wait_for(BPP_GP_PError, 0, TIME_PResponse, minor); pins |= BPP_PP_nAutoFd; instances[minor].direction = 0; set_pins(pins, minor); } while (remaining > 0) { unsigned char byte; int rc; if (get_user(byte, c)) return -EFAULT; rc = wait_for(0, BPP_GP_Busy, TIME_PResponse, minor); if (rc == -1) return -ETIMEDOUT; c += 1; bpp_outb_p(byte, base_addrs[minor]); pins &= ~BPP_PP_nStrobe; set_pins(pins, minor); pins |= BPP_PP_nStrobe; rc = wait_for(BPP_GP_Busy, 0, TIME_PResponse, minor); if (rc == -1) return -EIO; set_pins(pins, minor); } return cnt - remaining; }
/* * Return ZERO(0) If the negotiation succeeds, an errno otherwise. An * errno means something broke, and I do not yet know how to fix it. */ static int negotiate(unsigned char mode, unsigned minor) { int rc; unsigned short pins = get_pins(minor); if (pins & BPP_PP_nSelectIn) return -EIO; /* Event 0: Write the mode to the data lines */ bpp_outb_p(mode, base_addrs[minor]); snooze(TIME_PSetup, minor); /* Event 1: Strobe the mode code into the peripheral */ set_pins(BPP_PP_nSelectIn|BPP_PP_nStrobe|BPP_PP_nInit, minor); /* Wait for Event 2: Peripheral responds as a 1284 device. */ rc = wait_for(BPP_GP_PError|BPP_GP_Select|BPP_GP_nFault, BPP_GP_nAck, TIME_PResponse, minor); if (rc == -1) return -ETIMEDOUT; /* Event 3: latch extensibility request */ set_pins(BPP_PP_nSelectIn|BPP_PP_nInit, minor); /* ... quick nap while peripheral ponders the byte i'm sending...*/ snooze(1, minor); /* Event 4: restore strobe, to ACK peripheral's response. */ set_pins(BPP_PP_nSelectIn|BPP_PP_nAutoFd|BPP_PP_nStrobe|BPP_PP_nInit, minor); /* Wait for Event 6: Peripheral latches response bits */ rc = wait_for(BPP_GP_nAck, 0, TIME_PSetup+TIME_PResponse, minor); if (rc == -1) return -EIO; /* A 1284 device cannot refuse nibble mode */ if (mode == DEFAULT_NIBBLE) return 0; if (pins & BPP_GP_Select) return 0; return -EPROTONOSUPPORT; }