rtapi_parport.h
1 // Copyright 2014 Jeff Epler 2 // 3 // This program is free software; you can redistribute it and/or modify 4 // it under the terms of the GNU General Public License as published by 5 // the Free Software Foundation; either version 2 of the License, or 6 // (at your option) any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU General Public License for more details. 12 // 13 // You should have received a copy of the GNU General Public License 14 // along with this program; if not, write to the Free Software 15 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 #ifndef RTAPI_PARPORT_H 17 #define RTAPI_PARPORT_H 18 19 #include <rtapi.h> 20 #include <rtapi_io.h> 21 #include <linux/parport.h> 22 23 #define RTAPI_PARPORT_DATA_PORT(t) (t->base + 0) 24 #define RTAPI_PARPORT_STATUS_PORT(t) (t->base + 1) 25 #define RTAPI_PARPORT_CONTROL_PORT(t) (t->base + 2) 26 #define RTAPI_PARPORT_EPP_ADDR_PORT(t) (t->base + 3) 27 #define RTAPI_PARPORT_EPP_DATA_PORT(t) (t->base + 4) 28 #define RTAPI_PARPORT_ECR_PORT(t) (t->base_hi + 2) 29 30 typedef struct rtapi_parport_t 31 { 32 unsigned short base; 33 unsigned short base_hi; 34 #ifdef __KERNEL__ 35 struct pardevice *linux_dev; 36 void *region; 37 void *region_hi; 38 #else 39 int fd; 40 #endif 41 } rtapi_parport_t; 42 43 RTAPI_BEGIN_DECLS 44 45 static inline int rtapi_parport_data_read(rtapi_parport_t *t) { 46 return rtapi_inb(RTAPI_PARPORT_DATA_PORT(t)); 47 } 48 49 static inline int rtapi_parport_control_read(rtapi_parport_t *t) { 50 return rtapi_inb(RTAPI_PARPORT_CONTROL_PORT(t)); 51 } 52 53 static inline int rtapi_parport_status_read(rtapi_parport_t *t) { 54 return rtapi_inb(RTAPI_PARPORT_STATUS_PORT(t)); 55 } 56 57 static inline unsigned char rtapi_parport_epp_data_readb(rtapi_parport_t *t) { 58 return rtapi_inb(RTAPI_PARPORT_EPP_DATA_PORT(t)); 59 } 60 61 static inline unsigned long rtapi_parport_epp_data_readl(rtapi_parport_t *t) { 62 return rtapi_inl(RTAPI_PARPORT_EPP_DATA_PORT(t)); 63 } 64 65 static inline unsigned long rtapi_parport_ecr_read(rtapi_parport_t *t) { 66 return rtapi_inb(RTAPI_PARPORT_ECR_PORT(t)); 67 } 68 69 70 static inline void rtapi_parport_data_write(rtapi_parport_t *t, unsigned char v) { 71 rtapi_outb(v, RTAPI_PARPORT_DATA_PORT(t)); 72 } 73 74 static inline void rtapi_parport_control_write(rtapi_parport_t *t, unsigned char v) { 75 rtapi_outb(v, RTAPI_PARPORT_CONTROL_PORT(t)); 76 } 77 78 static inline void rtapi_parport_status_write(rtapi_parport_t *t, unsigned char v) { 79 rtapi_outb(v, RTAPI_PARPORT_STATUS_PORT(t)); 80 } 81 82 static inline void rtapi_parport_epp_addr_write(rtapi_parport_t *t, unsigned char v) { 83 rtapi_outb(v, RTAPI_PARPORT_EPP_ADDR_PORT(t)); 84 } 85 86 static inline void rtapi_parport_epp_data_writeb(rtapi_parport_t *t, unsigned char v) { 87 rtapi_outb(v, RTAPI_PARPORT_EPP_DATA_PORT(t)); 88 } 89 90 static inline void rtapi_parport_epp_data_writel(rtapi_parport_t *t, unsigned long v) { 91 rtapi_outl(v, RTAPI_PARPORT_EPP_DATA_PORT(t)); 92 } 93 94 static inline void rtapi_parport_ecr_write(rtapi_parport_t *t, unsigned char v) { 95 rtapi_outb(v, RTAPI_PARPORT_EPP_ADDR_PORT(t)); 96 } 97 98 #ifdef __KERNEL__ 99 static int 100 rtapi_parport_get(const char *name, rtapi_parport_t *port, 101 unsigned short base, unsigned short base_hi, unsigned int modes) 102 { 103 int retval = 0; 104 struct parport *linux_port = 0; 105 memset(port, 0, sizeof(rtapi_parport_t)); 106 107 // I/O addresses 1..16 are assumed to be linux parport numbers 108 if(base < 16) { 109 linux_port = parport_find_number(base); 110 if(!linux_port) 111 { 112 rtapi_print_msg(RTAPI_MSG_ERR, 113 "PARPORT: ERROR: linux parport %d not found\n", 114 base); 115 return -ENODEV; 116 } 117 } else { 118 linux_port = parport_find_base(base); 119 } 120 121 if(linux_port) 122 { 123 if((modes & linux_port->modes) != modes) 124 { 125 rtapi_print_msg(RTAPI_MSG_WARN, 126 "PARPORT: linux parport %s does not support mode %x.\n" 127 "PARPORT: continuing anyway.\n", 128 linux_port->name, modes); 129 } 130 rtapi_print_msg(RTAPI_MSG_INFO, 131 "PARPORT: Using Linux parport %s at ioaddr=0x%lx:0x%lx\n", 132 linux_port->name, linux_port->base, linux_port->base_hi); 133 port->linux_dev = parport_register_device(linux_port, 134 name, NULL, NULL, NULL, 0, NULL); 135 136 if(!port->linux_dev) 137 { 138 parport_put_port(linux_port); 139 rtapi_print_msg(RTAPI_MSG_ERR, 140 "PARPORT: ERROR: port %s register failed\n", linux_port->name); 141 return -EIO; 142 } 143 144 retval = parport_claim(port->linux_dev); 145 if(retval < 0) 146 { 147 parport_put_port(linux_port); 148 parport_unregister_device(port->linux_dev); 149 rtapi_print_msg(RTAPI_MSG_ERR, 150 "PARPORT: ERROR: port %s claim failed\n", linux_port->name); 151 return retval; 152 } 153 154 port->base = linux_port->base; 155 if(linux_port->base_hi > 0) { 156 port->base_hi = linux_port->base_hi; 157 } else if(base_hi != (unsigned short)-1) { 158 if(base_hi == 0) base_hi = port->base + 0x400; 159 rtapi_print_msg(RTAPI_MSG_DBG, 160 "PARPORT: DEBUG: linux reports no ioaddr_hi, using 0x%x", 161 base_hi); 162 port->region_hi = 163 rtapi_request_region(base_hi, 3, name); 164 if(port->region_hi) { 165 rtapi_print_msg(RTAPI_MSG_DBG, 166 "PARPORT: DEBUG: got requested region starting at 0x%x", 167 base_hi); 168 port->base_hi = base_hi; 169 } else { 170 rtapi_print_msg(RTAPI_MSG_DBG, 171 "PARPORT: DEBUG: did not get requested region starting at 0x%x", 172 base_hi); 173 } 174 } 175 parport_put_port(linux_port); 176 } else { 177 if(base_hi == 0) base_hi = base + 0x400; 178 179 port->base = base; 180 rtapi_print_msg(RTAPI_MSG_INFO, 181 "Using direct parport at ioaddr=0x%x:0x%x\n", base, base_hi); 182 183 // SPP access needs only 3 bytes, but EPP needs 8. Allocating 8 184 // is likely to always be OK, and it simplifies things (since the 185 // exact allocation size is also needed at deallocation). 186 port->region = rtapi_request_region(base, 8, name); 187 if(!port->region) 188 { 189 rtapi_print_msg(RTAPI_MSG_ERR, 190 "PARPORT: ERROR: request_region(0x%x) failed\n", base); 191 return -EBUSY; 192 } 193 194 if(base_hi != (unsigned short)-1) 195 { 196 port->base_hi = base_hi; 197 port->region_hi = 198 rtapi_request_region(base_hi, 3, name); 199 if(!port->region_hi) 200 { 201 rtapi_print_msg(RTAPI_MSG_ERR, 202 "PARPORT: ERROR: request_region(0x%x) failed\n", base_hi); 203 rtapi_release_region(port->base, 8); 204 return -EBUSY; 205 } 206 } 207 } 208 return 0; 209 } 210 211 static void rtapi_parport_release(rtapi_parport_t *port) 212 { 213 if(port->linux_dev) 214 { 215 rtapi_print_msg(RTAPI_MSG_INFO, 216 "PARPORT: Releasing Linux parport at ioaddr=0x%lx:0x%lx\n", 217 port->linux_dev->port->base, port->linux_dev->port->base_hi); 218 parport_release(port->linux_dev); 219 parport_unregister_device(port->linux_dev); 220 } 221 if(port->region) { 222 rtapi_print_msg(RTAPI_MSG_INFO, 223 "PARPORT: Releasing I/O region ioaddr=0x%x\n", port->base); 224 rtapi_release_region(port->base, 8); 225 } 226 if(port->region_hi) { 227 rtapi_print_msg(RTAPI_MSG_INFO, 228 "PARPORT: Releasing high I/O region ioaddr=0x%x\n", 229 port->base_hi); 230 rtapi_release_region(port->base_hi, 3); 231 } 232 memset(port, 0, sizeof(rtapi_parport_t)); 233 } 234 #else 235 int rtapi_parport_get(const char *mod_name, rtapi_parport_t *port, unsigned short base, unsigned short base_hi, unsigned int modes); 236 void rtapi_parport_release(rtapi_parport_t *port); 237 #endif 238 239 RTAPI_END_DECLS 240 241 #endif