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

📄 bpp.c

📁 底层驱动开发
💻 C
📖 第 1 页 / 共 3 页
字号:
        /* 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;}static int terminate(unsigned minor){      int rc;        /* Event 22: Request termination of 1284 mode */      set_pins(BPP_PP_nAutoFd|BPP_PP_nStrobe|BPP_PP_nInit, minor);        /* Wait for Events 23 and 24: ACK termination request. */      rc = wait_for(BPP_GP_Busy|BPP_GP_nFault,                BPP_GP_nAck,                TIME_PSetup+TIME_PResponse,                minor);      instances[minor].direction = 0;      instances[minor].mode = COMPATIBILITY;      if (rc == -1) {          return -EIO;      }        /* Event 25: Handshake by lowering nAutoFd */      set_pins(BPP_PP_nStrobe|BPP_PP_nInit, minor);        /* Event 26: Peripheral wiggles lines... */        /* Event 27: Peripheral sets nAck HIGH to ack handshake */      rc = wait_for(BPP_GP_nAck, 0, TIME_PResponse, minor);      if (rc == -1) {          set_pins(BPP_PP_nAutoFd|BPP_PP_nStrobe|BPP_PP_nInit, minor);          return -EIO;      }        /* Event 28: Finish phase by raising nAutoFd */      set_pins(BPP_PP_nAutoFd|BPP_PP_nStrobe|BPP_PP_nInit, minor);      return 0;}static DEFINE_SPINLOCK(bpp_open_lock);/* * Allow only one process to open the device at a time. */static int bpp_open(struct inode *inode, struct file *f){      unsigned minor = iminor(inode);      int ret;      spin_lock(&bpp_open_lock);      ret = 0;      if (minor >= BPP_NO) {	      ret = -ENODEV;      } else {	      if (! instances[minor].present) {		      ret = -ENODEV;	      } else {		      if (instances[minor].opened) 			      ret = -EBUSY;		      else			      instances[minor].opened = 1;	      }      }      spin_unlock(&bpp_open_lock);      return ret;}/* * When the process closes the device, this method is called to clean * up and reset the hardware. Always leave the device in compatibility * mode as this is a reasonable place to clean up from messes made by * ioctls, or other mayhem. */static int bpp_release(struct inode *inode, struct file *f){      unsigned minor = iminor(inode);      spin_lock(&bpp_open_lock);      instances[minor].opened = 0;      if (instances[minor].mode != COMPATIBILITY)	      terminate(minor);      spin_unlock(&bpp_open_lock);      return 0;}static long read_nibble(unsigned minor, char __user *c, unsigned long cnt){      unsigned long remaining = cnt;      long rc;      while (remaining > 0) {          unsigned char byte = 0;          int pins;          /* Event 7: request nibble */          set_pins(BPP_PP_nSelectIn|BPP_PP_nStrobe, minor);          /* Wait for event 9: Peripher strobes first nibble */          pins = wait_for(0, BPP_GP_nAck, TIME_IDLE_LIMIT, minor);          if (pins == -1) return -ETIMEDOUT;          /* Event 10: I handshake nibble */          set_pins(BPP_PP_nSelectIn|BPP_PP_nStrobe|BPP_PP_nAutoFd, minor);          if (pins & BPP_GP_nFault) byte |= 0x01;          if (pins & BPP_GP_Select) byte |= 0x02;          if (pins & BPP_GP_PError) byte |= 0x04;          if (pins & BPP_GP_Busy)   byte |= 0x08;          /* Wait for event 11: Peripheral handshakes nibble */          rc = wait_for(BPP_GP_nAck, 0, TIME_PResponse, minor);          /* Event 7: request nibble */          set_pins(BPP_PP_nSelectIn|BPP_PP_nStrobe, minor);          /* Wait for event 9: Peripher strobes first nibble */          pins = wait_for(0, BPP_GP_nAck, TIME_PResponse, minor);          if (rc == -1) return -ETIMEDOUT;          /* Event 10: I handshake nibble */          set_pins(BPP_PP_nSelectIn|BPP_PP_nStrobe|BPP_PP_nAutoFd, minor);          if (pins & BPP_GP_nFault) byte |= 0x10;          if (pins & BPP_GP_Select) byte |= 0x20;          if (pins & BPP_GP_PError) byte |= 0x40;          if (pins & BPP_GP_Busy)   byte |= 0x80;          if (put_user(byte, c))		  return -EFAULT;          c += 1;          remaining -= 1;          /* Wait for event 11: Peripheral handshakes nibble */          rc = wait_for(BPP_GP_nAck, 0, TIME_PResponse, minor);          if (rc == -1) return -EIO;      }      return cnt - remaining;}static long read_ecp(unsigned minor, char __user *c, unsigned long cnt){      unsigned long remaining;      long rc;        /* Turn ECP mode from forward to reverse if needed. */      if (! instances[minor].direction) {          unsigned short pins = get_pins(minor);            /* Event 38: Turn the bus around */          instances[minor].direction = 0x20;          pins &= ~BPP_PP_nAutoFd;          set_pins(pins, minor);            /* Event 39: Set pins for reverse mode. */          snooze(TIME_PSetup, minor);          set_pins(BPP_PP_nStrobe|BPP_PP_nSelectIn, minor);            /* Wait for event 40: Peripheral ready to be strobed */          rc = wait_for(0, BPP_GP_PError, TIME_PResponse, minor);          if (rc == -1) return -ETIMEDOUT;      }      remaining = cnt;      while (remaining > 0) {            /* If there is a run length for a repeated byte, repeat */            /* that byte a few times. */          if (instances[minor].run_length && !instances[minor].run_flag) {              char buffer[128];              unsigned idx;              unsigned repeat = remaining < instances[minor].run_length                                     ? remaining                               : instances[minor].run_length;              for (idx = 0 ;  idx < repeat ;  idx += 1)                buffer[idx] = instances[minor].repeat_byte;              if (copy_to_user(c, buffer, repeat))		      return -EFAULT;              remaining -= repeat;              c += repeat;              instances[minor].run_length -= repeat;          }          if (remaining == 0) break;            /* Wait for Event 43: Data active on the bus. */          rc = wait_for(0, BPP_GP_nAck, TIME_IDLE_LIMIT, minor);          if (rc == -1) break;          if (rc & BPP_GP_Busy) {                /* OK, this is data. read it in. */              unsigned char byte = bpp_inb(base_addrs[minor]);              if (put_user(byte, c))		      return -EFAULT;              c += 1;              remaining -= 1;              if (instances[minor].run_flag) {                  instances[minor].repeat_byte = byte;                  instances[minor].run_flag = 0;              }          } else {              unsigned char byte = bpp_inb(base_addrs[minor]);              if (byte & 0x80) {                  printk("bpp%d: "                         "Ignoring ECP channel %u from device.\n",                         minor, byte & 0x7f);              } else {                  instances[minor].run_length = byte;                  instances[minor].run_flag = 1;              }          }            /* Event 44: I got it. */          set_pins(BPP_PP_nStrobe|BPP_PP_nAutoFd|BPP_PP_nSelectIn, minor);            /* Wait for event 45: peripheral handshake */          rc = wait_for(BPP_GP_nAck, 0, TIME_PResponse, minor);          if (rc == -1) return -ETIMEDOUT;             /* Event 46: Finish handshake */          set_pins(BPP_PP_nStrobe|BPP_PP_nSelectIn, minor);      }      return cnt - remaining;}static ssize_t bpp_read(struct file *f, char __user *c, size_t cnt, loff_t * ppos){      long rc;      unsigned minor = iminor(f->f_dentry->d_inode);      if (minor >= BPP_NO) return -ENODEV;      if (!instances[minor].present) return -ENODEV;      switch (instances[minor].mode) {        default:          if (instances[minor].mode != COMPATIBILITY)            terminate(minor);          if (instances[minor].enhanced) {              /* For now, do all reads with ECP-RLE mode */              unsigned short pins;              rc = negotiate(DEFAULT_ECP, minor);              if (rc < 0) break;              instances[minor].mode = ECP_RLE;              /* Event 30: set nAutoFd low to setup for ECP mode */              pins = get_pins(minor);              pins &= ~BPP_PP_nAutoFd;              set_pins(pins, minor);              /* Wait for Event 31: peripheral ready */              rc = wait_for(BPP_GP_PError, 0, TIME_PResponse, minor);              if (rc == -1) return -ETIMEDOUT;              rc = read_ecp(minor, c, cnt);          } else {              rc = negotiate(DEFAULT_NIBBLE, minor);              if (rc < 0) break;              instances[minor].mode = NIBBLE;              rc = read_nibble(minor, c, cnt);          }          break;        case NIBBLE:          rc = read_nibble(minor, c, cnt);          break;        case ECP:        case ECP_RLE:          rc = read_ecp(minor, c, cnt);          break;      }      return rc;}/* * 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 __user *c, unsigned long cnt){      long rc;      unsigned short pins = get_pins(minor);      unsigned long remaining = cnt;      while (remaining > 0) {            unsigned char byte;            if (get_user(byte, c))		    return -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);

⌨️ 快捷键说明

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