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

📄 bpp.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * drivers/sbus/char/bpp.c * * Copyright (c) 1995 Picture Elements *      Stephen Williams (steve@icarus.com) *      Gus Baldauf (gbaldauf@ix.netcom.com) * * Linux/SPARC port by Peter Zaitcev. * Integration into SPARC tree by Tom Dyas. */#include <linux/kernel.h>#include <linux/module.h>#include <linux/fs.h>#include <linux/errno.h>#include <linux/sched.h>#include <linux/smp_lock.h>#include <linux/spinlock.h>#include <linux/timer.h>#include <linux/ioport.h>#include <linux/major.h>#include <linux/devfs_fs_kernel.h>#include <asm/uaccess.h>#include <asm/io.h>#if defined(__i386__)# include <asm/system.h>#endif#if defined(__sparc__)# include <linux/init.h># include <linux/delay.h>         /* udelay() */# include <asm/oplib.h>           /* OpenProm Library */# include <asm/sbus.h>#endif#include <asm/bpp.h>#define BPP_PROBE_CODE 0x55#define BPP_DELAY 100static const unsigned  BPP_MAJOR = LP_MAJOR;static const char* dev_name = "bpp";/* When switching from compatibility to a mode where I can read, try   the following mode first. *//* const unsigned char DEFAULT_ECP = 0x10; */static const unsigned char DEFAULT_ECP = 0x30;static const unsigned char DEFAULT_NIBBLE = 0x00;/* * These are 1284 time constraints, in units of jiffies. */static const unsigned long TIME_PSetup = 1;static const unsigned long TIME_PResponse = 6;static const unsigned long TIME_IDLE_LIMIT = 2000;/* * One instance per supported subdevice... */# define BPP_NO 3enum IEEE_Mode { COMPATIBILITY, NIBBLE, ECP, ECP_RLE, EPP };struct inst {      unsigned present  : 1; /* True if the hardware exists */      unsigned enhanced : 1; /* True if the hardware in "enhanced" */      unsigned opened   : 1; /* True if the device is opened already */      unsigned run_flag : 1; /* True if waiting for a repeate byte */      unsigned char direction; /* 0 --> out, 0x20 --> IN */      unsigned char pp_state; /* State of host controlled pins. */      enum IEEE_Mode mode;      unsigned char run_length;      unsigned char repeat_byte;      /* These members manage timeouts for programmed delays */      wait_queue_head_t wait_queue;      struct timer_list timer_list;};static struct inst instances[BPP_NO];#if defined(__i386__)const unsigned short base_addrs[BPP_NO] = { 0x278, 0x378, 0x3bc };/* * These are for data access. * Control lines accesses are hidden in set_bits() and get_bits(). * The exception is the probe procedure, which is system-dependent. */#define bpp_outb_p(data, base)  outb_p((data), (base))#define bpp_inb(base)  inb(base)#define bpp_inb_p(base)  inb_p(base)/* * This method takes the pin values mask and sets the hardware pins to * the requested value: 1 == high voltage, 0 == low voltage. This * burries the annoying PC bit inversion and preserves the direction * flag. */static void set_pins(unsigned short pins, unsigned minor){      unsigned char bits = instances[minor].direction;  /* == 0x20 */      if (! (pins & BPP_PP_nStrobe))   bits |= 1;      if (! (pins & BPP_PP_nAutoFd))   bits |= 2;      if (   pins & BPP_PP_nInit)      bits |= 4;      if (! (pins & BPP_PP_nSelectIn)) bits |= 8;      instances[minor].pp_state = bits;      outb_p(bits, base_addrs[minor]+2);}static unsigned short get_pins(unsigned minor){      unsigned short bits = 0;      unsigned value = instances[minor].pp_state;      if (! (value & 0x01)) bits |= BPP_PP_nStrobe;      if (! (value & 0x02)) bits |= BPP_PP_nAutoFd;      if (value & 0x04)     bits |= BPP_PP_nInit;      if (! (value & 0x08)) bits |= BPP_PP_nSelectIn;      value = inb_p(base_addrs[minor]+1);      if (value & 0x08)     bits |= BPP_GP_nFault;      if (value & 0x10)     bits |= BPP_GP_Select;      if (value & 0x20)     bits |= BPP_GP_PError;      if (value & 0x40)     bits |= BPP_GP_nAck;      if (! (value & 0x80)) bits |= BPP_GP_Busy;      return bits;}#endif /* __i386__ */#if defined(__sparc__)/* * Register block */      /* DMA registers */#define BPP_CSR      0x00#define BPP_ADDR     0x04#define BPP_BCNT     0x08#define BPP_TST_CSR  0x0C      /* Parallel Port registers */#define BPP_HCR      0x10#define BPP_OCR      0x12#define BPP_DR       0x14#define BPP_TCR      0x15#define BPP_OR       0x16#define BPP_IR       0x17#define BPP_ICR      0x18#define BPP_SIZE     0x1A/* BPP_CSR.  Bits of type RW1 are cleared with writting '1'. */#define P_DEV_ID_MASK   0xf0000000      /* R   */#define P_DEV_ID_ZEBRA  0x40000000#define P_DEV_ID_L64854 0xa0000000      /*      == NCR 89C100+89C105. Pity. */#define P_NA_LOADED     0x08000000      /* R    NA wirtten but was not used */#define P_A_LOADED      0x04000000      /* R    */#define P_DMA_ON        0x02000000      /* R    DMA is not disabled */#define P_EN_NEXT       0x01000000      /* RW   */#define P_TCI_DIS       0x00800000      /* RW   TCI forbidden from interrupts */#define P_DIAG          0x00100000      /* RW   Disables draining and resetting                                                of P-FIFO on loading of P_ADDR*/#define P_BURST_SIZE    0x000c0000      /* RW   SBus burst size */#define P_BURST_8       0x00000000#define P_BURST_4       0x00040000#define P_BURST_1       0x00080000      /*      "No burst" write */#define P_TC            0x00004000      /* RW1  Term Count, can be cleared when                                           P_EN_NEXT=1 */#define P_EN_CNT        0x00002000      /* RW   */#define P_EN_DMA        0x00000200      /* RW   */#define P_WRITE         0x00000100      /* R    DMA dir, 1=to ram, 0=to port */#define P_RESET         0x00000080      /* RW   */#define P_SLAVE_ERR     0x00000040      /* RW1  Access size error */#define P_INVALIDATE    0x00000020      /* W    Drop P-FIFO */#define P_INT_EN        0x00000010      /* RW   OK to P_INT_PEND||P_ERR_PEND */#define P_DRAINING      0x0000000c      /* R    P-FIFO is draining to memory */#define P_ERR_PEND      0x00000002      /* R    */#define P_INT_PEND      0x00000001      /* R    *//* BPP_HCR. Time is in increments of SBus clock. */#define P_HCR_TEST      0x8000      /* Allows buried counters to be read */#define P_HCR_DSW       0x7f00      /* Data strobe width (in ticks) */#define P_HCR_DDS       0x007f      /* Data setup before strobe (in ticks) *//* BPP_OCR. */#define P_OCR_MEM_CLR   0x8000#define P_OCR_DATA_SRC  0x4000      /* )                  */#define P_OCR_DS_DSEL   0x2000      /* )  Bidirectional      */#define P_OCR_BUSY_DSEL 0x1000      /* )    selects            */#define P_OCR_ACK_DSEL  0x0800      /* )                  */#define P_OCR_EN_DIAG   0x0400#define P_OCR_BUSY_OP   0x0200      /* Busy operation */#define P_OCR_ACK_OP    0x0100      /* Ack operation */#define P_OCR_SRST      0x0080      /* Reset state machines. Not selfcleaning. */#define P_OCR_IDLE      0x0008      /* PP data transfer state machine is idle */#define P_OCR_V_ILCK    0x0002      /* Versatec faded. Zebra only. */#define P_OCR_EN_VER    0x0001      /* Enable Versatec (0 - enable). Zebra only. *//* BPP_TCR */#define P_TCR_DIR       0x08#define P_TCR_BUSY      0x04#define P_TCR_ACK       0x02#define P_TCR_DS        0x01        /* Strobe *//* BPP_OR */#define P_OR_V3         0x20        /* )                 */#define P_OR_V2         0x10        /* ) on Zebra only   */#define P_OR_V1         0x08        /* )                 */#define P_OR_INIT       0x04#define P_OR_AFXN       0x02        /* Auto Feed */#define P_OR_SLCT_IN    0x01/* BPP_IR */#define P_IR_PE         0x04#define P_IR_SLCT       0x02#define P_IR_ERR        0x01/* BPP_ICR */#define P_DS_IRQ        0x8000      /* RW1  */#define P_ACK_IRQ       0x4000      /* RW1  */#define P_BUSY_IRQ      0x2000      /* RW1  */#define P_PE_IRQ        0x1000      /* RW1  */#define P_SLCT_IRQ      0x0800      /* RW1  */#define P_ERR_IRQ       0x0400      /* RW1  */#define P_DS_IRQ_EN     0x0200      /* RW   Always on rising edge */#define P_ACK_IRQ_EN    0x0100      /* RW   Always on rising edge */#define P_BUSY_IRP      0x0080      /* RW   1= rising edge */#define P_BUSY_IRQ_EN   0x0040      /* RW   */#define P_PE_IRP        0x0020      /* RW   1= rising edge */#define P_PE_IRQ_EN     0x0010      /* RW   */#define P_SLCT_IRP      0x0008      /* RW   1= rising edge */#define P_SLCT_IRQ_EN   0x0004      /* RW   */#define P_ERR_IRP       0x0002      /* RW1  1= rising edge */#define P_ERR_IRQ_EN    0x0001      /* RW   */unsigned long base_addrs[BPP_NO];#define bpp_outb_p(data, base)	sbus_writeb(data, (base) + BPP_DR)#define bpp_inb_p(base)		sbus_readb((base) + BPP_DR)#define bpp_inb(base)		sbus_readb((base) + BPP_DR)static void set_pins(unsigned short pins, unsigned minor){      unsigned long base = base_addrs[minor];      unsigned char bits_tcr = 0, bits_or = 0;      if (instances[minor].direction & 0x20) bits_tcr |= P_TCR_DIR;      if (   pins & BPP_PP_nStrobe)          bits_tcr |= P_TCR_DS;      if (   pins & BPP_PP_nAutoFd)          bits_or |= P_OR_AFXN;      if (! (pins & BPP_PP_nInit))           bits_or |= P_OR_INIT;      if (! (pins & BPP_PP_nSelectIn))       bits_or |= P_OR_SLCT_IN;      sbus_writeb(bits_or, base + BPP_OR);      sbus_writeb(bits_tcr, base + BPP_TCR);}/* * i386 people read output pins from a software image. * We may get them back from hardware. * Again, inversion of pins must he buried here. */static unsigned short get_pins(unsigned minor){      unsigned long base = base_addrs[minor];      unsigned short bits = 0;      unsigned value_tcr = sbus_readb(base + BPP_TCR);      unsigned value_ir = sbus_readb(base + BPP_IR);      unsigned value_or = sbus_readb(base + BPP_OR);      if (value_tcr & P_TCR_DS)         bits |= BPP_PP_nStrobe;      if (value_or & P_OR_AFXN)         bits |= BPP_PP_nAutoFd;      if (! (value_or & P_OR_INIT))     bits |= BPP_PP_nInit;      if (! (value_or & P_OR_SLCT_IN))  bits |= BPP_PP_nSelectIn;      if (value_ir & P_IR_ERR)          bits |= BPP_GP_nFault;      if (! (value_ir & P_IR_SLCT))     bits |= BPP_GP_Select;      if (! (value_ir & P_IR_PE))       bits |= BPP_GP_PError;      if (! (value_tcr & P_TCR_ACK))    bits |= BPP_GP_nAck;      if (value_tcr & P_TCR_BUSY)       bits |= BPP_GP_Busy;      return bits;}#endif /* __sparc__ */static void bpp_wake_up(unsigned long val){ wake_up(&instances[val].wait_queue); }static void snooze(unsigned long snooze_time, unsigned minor){      init_timer(&instances[minor].timer_list);      instances[minor].timer_list.expires = jiffies + snooze_time + 1;      instances[minor].timer_list.data    = minor;      add_timer(&instances[minor].timer_list);      sleep_on (&instances[minor].wait_queue);}static int wait_for(unsigned short set, unsigned short clr,               unsigned long delay, unsigned minor){      unsigned short pins = get_pins(minor);      unsigned long extime = 0;      /*       * Try a real fast scan for the first jiffy, in case the device       * responds real good. The first while loop guesses an expire       * time accounting for possible wraparound of jiffies.       */      while (time_after_eq(jiffies, extime)) extime = jiffies + 1;      while ( (time_before(jiffies, extime))              && (((pins & set) != set) || ((pins & clr) != 0)) ) {            pins = get_pins(minor);      }      delay -= 1;      /*       * If my delay expired or the pins are still not where I want       * them, then resort to using the timer and greatly reduce my       * sample rate. If the peripheral is going to be slow, this will       * give the CPU up to some more worthy process.       */      while ( delay && (((pins & set) != set) || ((pins & clr) != 0)) ) {            snooze(1, minor);            pins = get_pins(minor);            delay -= 1;      }      if (delay == 0) return -1;      else return pins;}/* * 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 */

⌨️ 快捷键说明

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