Fork me on GitHub

root/drivers/char/lp.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. lp_delay
  2. lp_ready
  3. lp_probe
  4. lp_write_data
  5. lp_open
  6. lp_close
  7. lp_write
  8. lp_init

   1 /*
   2  * fiwix/drivers/char/lp.c
   3  *
   4  * Copyright 2018, Jordi Sanfeliu. All rights reserved.
   5  * Distributed under the terms of the Fiwix License.
   6  */
   7 
   8 #include <fiwix/asm.h>
   9 #include <fiwix/devices.h>
  10 #include <fiwix/fs.h>
  11 #include <fiwix/errno.h>
  12 #include <fiwix/lp.h>
  13 #include <fiwix/stdio.h>
  14 #include <fiwix/string.h>
  15 
  16 struct lp lp_table[LP_MINORS];
  17 
  18 static struct fs_operations lp_driver_fsop = {
  19         0,
  20         0,
  21 
  22         lp_open,
  23         lp_close,
  24         NULL,                   /* read */
  25         lp_write,
  26         NULL,                   /* ioctl */
  27         NULL,                   /* lseek */
  28         NULL,                   /* readdir */
  29         NULL,                   /* mmap */
  30         NULL,                   /* select */
  31 
  32         NULL,                   /* readlink */
  33         NULL,                   /* followlink */
  34         NULL,                   /* bmap */
  35         NULL,                   /* lockup */
  36         NULL,                   /* rmdir */
  37         NULL,                   /* link */
  38         NULL,                   /* unlink */
  39         NULL,                   /* symlink */
  40         NULL,                   /* mkdir */
  41         NULL,                   /* mknod */
  42         NULL,                   /* truncate */
  43         NULL,                   /* create */
  44         NULL,                   /* rename */
  45 
  46         NULL,                   /* read_block */
  47         NULL,                   /* write_block */
  48 
  49         NULL,                   /* read_inode */
  50         NULL,                   /* write_inode */
  51         NULL,                   /* ialloc */
  52         NULL,                   /* ifree */
  53         NULL,                   /* statfs */
  54         NULL,                   /* read_superblock */
  55         NULL,                   /* remount_fs */
  56         NULL,                   /* write_superblock */
  57         NULL                    /* release_superblock */
  58 };
  59 
  60 static struct device lp_device = {
  61         "lp",
  62         LP_MAJOR,
  63         { 0, 0, 0, 0, 0, 0, 0, 0 },
  64         0,
  65         NULL,
  66         &lp_driver_fsop,
  67         NULL
  68 };
  69 
  70 struct lp lp_table[LP_MINORS] = {
  71         { LP0_ADDR, LP0_ADDR + 1, LP0_ADDR + 2, 0 }
  72 };
  73 
  74 static void lp_delay(void)
  75 {
  76         int n;
  77 
  78         for(n = 0; n < 10000; n++) {
  79                 NOP();
  80         }
  81 }
  82 
  83 static int lp_ready(int minor)
  84 {
  85         int n;
  86 
  87         for(n = 0; n < LP_RDY_RETR; n++) {
  88                 if(inport_b(lp_table[minor].stat) & LP_STAT_BUS) {
  89                         break;
  90                 }
  91                 lp_delay();
  92         }
  93         if(n == LP_RDY_RETR) {
  94                 return 0;
  95         }
  96         return 1;
  97 }
  98 
  99 static int lp_probe(int minor)
 100 {
 101         /* first check */
 102         outport_b(lp_table[minor].data, 0x55);
 103         lp_delay();
 104         if(inport_b(lp_table[minor].data) != 0x55) {
 105                 return 1;               /* did not retain data */
 106         }
 107 
 108         /* second check */
 109         outport_b(lp_table[minor].data, 0xAA);
 110         lp_delay();
 111         if(inport_b(lp_table[minor].data) != 0xAA) {
 112                 return 1;               /* did not retain data */
 113         }
 114         return 0;
 115 }
 116 
 117 static int lp_write_data(int minor, unsigned char c)
 118 {
 119         unsigned char ctrl;
 120 
 121         if(!lp_ready(minor)) {
 122                 return -EBUSY;
 123         }
 124         outport_b(lp_table[minor].data, c);
 125         ctrl = inport_b(lp_table[minor].ctrl);
 126         outport_b(lp_table[minor].ctrl, ctrl | LP_CTRL_STR);
 127         lp_delay();
 128         outport_b(lp_table[minor].ctrl, ctrl);
 129         if(!lp_ready(minor)) {
 130                 return -EBUSY;
 131         }
 132         return 1;
 133 }
 134 
 135 int lp_open(struct inode *i, struct fd *fd_table)
 136 {
 137         int minor;
 138 
 139         minor = MINOR(i->rdev);
 140         if(!TEST_MINOR(lp_device.minors, minor)) {
 141                 return -ENXIO;
 142         }
 143         if(!(lp_table[minor].flags & LP_CTRL_SEL)) {
 144                 return -ENXIO;
 145         }
 146         if(lp_table[minor].flags & LP_STAT_BUS) {
 147                 return -EBUSY;
 148         }
 149         lp_table[minor].flags |= LP_STAT_BUS;
 150         return 0;
 151 }
 152 
 153 int lp_close(struct inode *i, struct fd *fd_table)
 154 {
 155         int minor;
 156 
 157         minor = MINOR(i->rdev);
 158         if(!TEST_MINOR(lp_device.minors, minor)) {
 159                 return -ENXIO;
 160         }
 161         lp_table[minor].flags &= ~LP_STAT_BUS;
 162         return 0;
 163 }
 164 
 165 int lp_write(struct inode *i, struct fd *fd_table, const char *buffer, __size_t count)
 166 {
 167         unsigned int n;
 168         int bytes_written, total_written;
 169         int minor;
 170 
 171         minor = MINOR(i->rdev);
 172         if(!TEST_MINOR(lp_device.minors, minor)) {
 173                 return -ENXIO;
 174         }
 175 
 176         total_written = 0;
 177         for(n = 0; n < count; n++) {
 178                 bytes_written = lp_write_data(minor, buffer[n]);
 179                 if(bytes_written != 1) {
 180                         break;
 181                 }
 182                 total_written += bytes_written;
 183         }
 184 
 185         return total_written;
 186 }
 187 
 188 void lp_init(void)
 189 {
 190         int n;
 191         unsigned char ctrl;
 192 
 193         for(n = 0; n < LP_MINORS; n++) {
 194                 if(!lp_probe(n)) {
 195                         ctrl = inport_b(lp_table[n].ctrl);
 196                         ctrl &= ~LP_CTRL_AUT;   /* disable auto LF */
 197                         ctrl |= LP_CTRL_INI;    /* initialize */
 198                         ctrl |= LP_CTRL_SEL;    /* select in */
 199                         ctrl &= ~LP_CTRL_IRQ;   /* disable IRQ */
 200                         ctrl &= ~LP_CTRL_BID;   /* disable bidirectional mode */
 201                         outport_b(lp_table[n].ctrl, ctrl);
 202                         lp_table[n].flags |= LP_CTRL_SEL;
 203                         printk("lp%d       0x%04X-0x%04X    -           \n", n, lp_table[n].data, lp_table[n].data + 2);
 204                         SET_MINOR(lp_device.minors, n);
 205                 }
 206         }
 207 
 208         for(n = 0; n < LP_MINORS; n++) {
 209                 if(lp_table[n].flags & LP_CTRL_SEL) {
 210                         if(register_device(CHR_DEV, &lp_device)) {
 211                                 printk("WARNING: %s(): unable to register lp device.\n", __FUNCTION__);
 212                         }
 213                         break;
 214                 }
 215         }
 216 }

/* [previous][next][first][last][top][bottom][index][help] */