| Start/ | End/ | |||
| True | False | - | Line | Source |
| 1 | /* | |||
| 2 | * IEEE 1284.3 Parallel port daisy chain and multiplexor code | |||
| 3 | * | |||
| 4 | * Copyright (C) 1999, 2000 Tim Waugh <tim@cyberelk.demon.co.uk> | |||
| 5 | * | |||
| 6 | * This program is free software; you can redistribute it and/or | |||
| 7 | * modify it under the terms of the GNU General Public License | |||
| 8 | * as published by the Free Software Foundation; either version | |||
| 9 | * 2 of the License, or (at your option) any later version. | |||
| 10 | * | |||
| 11 | * ??-12-1998: Initial implementation. | |||
| 12 | * 31-01-1999: Make port-cloning transparent. | |||
| 13 | * 13-02-1999: Move DeviceID technique from parport_probe. | |||
| 14 | * 13-03-1999: Get DeviceID from non-IEEE 1284.3 devices too. | |||
| 15 | * 22-02-2000: Count devices that are actually detected. | |||
| 16 | * | |||
| 17 | * Any part of this program may be used in documents licensed under | |||
| 18 | * the GNU Free Documentation License, Version 1.1 or any later version | |||
| 19 | * published by the Free Software Foundation. | |||
| 20 | */ | |||
| 21 | ||||
| 22 | #include <linux/module.h> | |||
| 23 | #include <linux/parport.h> | |||
| 24 | #include <linux/delay.h> | |||
| 25 | #include <linux/sched.h> | |||
| 26 | ||||
| 27 | #include <asm/current.h> | |||
| 28 | #include <asm/uaccess.h> | |||
| 29 | ||||
| 30 | #undef DEBUG | |||
| 31 | ||||
| 32 | #ifdef DEBUG | |||
| 33 | #define DPRINTK(stuff...) printk (stuff) | |||
| 34 | #else | |||
| 35 | #define DPRINTK(stuff...) | |||
| 36 | #endif | |||
| 37 | ||||
| 38 | static struct daisydev { | |||
| 39 | struct daisydev *next; | |||
| 40 | struct parport *port; | |||
| 41 | int daisy; | |||
| 42 | int devnum; | |||
| 43 | } *topology = NULL; | |||
| 44 | static DEFINE_SPINLOCK(topology_lock); | |||
| 45 | ||||
| 46 | static int numdevs = 0; | |||
| 47 | ||||
| 48 | /* Forward-declaration of lower-level functions. */ | |||
| 49 | static int mux_present (struct parport *port); | |||
| 50 | static int num_mux_ports (struct parport *port); | |||
| 51 | static int select_port (struct parport *port); | |||
| 52 | static int assign_addrs (struct parport *port); | |||
| 53 | ||||
| 54 | /* Add a device to the discovered topology. */ | |||
| 2 | 2 | 55 | static void add_dev (int devnum, struct parport *port, int daisy) | |
| 56 | { | |||
| 57 | struct daisydev *newdev, **p; | |||
| 58 | newdev = kmalloc (sizeof (struct daisydev), GFP_KERNEL); | |||
| 2 | 0 | - | 59 | if (newdev) { |
| 60 | newdev->port = port; | |||
| 61 | newdev->daisy = daisy; | |||
| 62 | newdev->devnum = devnum; | |||
| 63 | spin_lock(&topology_lock); | |||
| 63 | do | |||
| 0 | 2 | - | 63 | do-while (0) |
| 0 | 2 | - | 63 | do-while (0) |
| 0 | 2 | - | 64 | for (p = &topology; *p && (*p)->devnum<devnum; p = &(*p)->next) |
| 0 | - | 64 | T && T | |
| 0 | - | 64 | T && F | |
| 2 | 64 | F && _ | ||
| 65 | ; | |||
| 66 | newdev->next = *p; | |||
| 67 | *p = newdev; | |||
| 68 | spin_unlock(&topology_lock); | |||
| 68 | do | |||
| 0 | 2 | - | 68 | do-while (0) |
| 0 | 2 | - | 68 | do-while (0) |
| 69 | } | |||
| 70 | } | |||
| 71 | ||||
| 72 | /* Clone a parport (actually, make an alias). */ | |||
| 0 | 0 | - | 73 | static struct parport *clone_parport (struct parport *real, int muxport) |
| 74 | { | |||
| 75 | struct parport *extra = parport_register_port (real->base, | |||
| 76 | real->irq, | |||
| 77 | real->dma, | |||
| 78 | real->ops); | |||
| 0 | 0 | - | 79 | if (extra) { |
| 80 | extra->portnum = real->portnum; | |||
| 81 | extra->physport = real; | |||
| 82 | extra->muxport = muxport; | |||
| 83 | real->slaves[muxport-1] = extra; | |||
| 84 | } | |||
| 85 | ||||
| 0 | - | 86 | return extra; | |
| 87 | } | |||
| 88 | ||||
| 89 | /* Discover the IEEE1284.3 topology on a port -- muxes and daisy chains. | |||
| 90 | * Return value is number of devices actually detected. */ | |||
| 1 | 0 | 91 | int parport_daisy_init (struct parport *port) | |
| 92 | { | |||
| 93 | int detected = 0; | |||
| 94 | char *deviceid; | |||
| 95 | static const char *th[] = { /*0*/"th", "st", "nd", "rd", "th" }; | |||
| 96 | int num_ports; | |||
| 97 | int i; | |||
| 98 | int last_try = 0; | |||
| 99 | ||||
| 100 | again: | |||
| 101 | /* Because this is called before any other devices exist, | |||
| 102 | * we don't have to claim exclusive access. */ | |||
| 103 | ||||
| 104 | /* If mux present on normal port, need to create new | |||
| 105 | * parports for each extra port. */ | |||
| 106 | if (port->muxport < 0 && mux_present (port) && | |||
| 107 | /* don't be fooled: a mux must have 2 or 4 ports. */ | |||
| 0 | 2 | - | 108 | ((num_ports = num_mux_ports (port)) == 2 || num_ports == 4)) { |
| 0 | - | 108 | T && T && (T || _) | |
| 0 | - | 108 | T && T && (F || T) | |
| 0 | - | 108 | T && T && (F || F) | |
| 2 | 108 | T && F && (_ || _) | ||
| 0 | - | 108 | F && _ && (_ || _) | |
| 109 | /* Leave original as port zero. */ | |||
| 110 | port->muxport = 0; | |||
| 111 | printk (KERN_INFO | |||
| 112 | "%s: 1st (default) port of %d-way multiplexor\n", | |||
| 113 | port->name, num_ports); | |||
| 0 | 0 | - | 114 | for (i = 1; i < num_ports; i++) { |
| 115 | /* Clone the port. */ | |||
| 116 | struct parport *extra = clone_parport (port, i); | |||
| 0 | 0 | - | 117 | if (!extra) { |
| 0 | 0 | - | 118 | if (signal_pending (current)) |
| 0 | - | 119 | break; | |
| 120 | ||||
| 121 | schedule (); | |||
| 0 | - | 122 | continue; | |
| 123 | } | |||
| 124 | ||||
| 125 | printk (KERN_INFO | |||
| 126 | "%s: %d%s port of %d-way multiplexor on %s\n", | |||
| 127 | extra->name, i + 1, th[i + 1], num_ports, | |||
| 128 | port->name); | |||
| 129 | ||||
| 130 | /* Analyse that port too. We won't recurse | |||
| 131 | forever because of the 'port->muxport < 0' | |||
| 132 | test above. */ | |||
| 133 | parport_daisy_init(extra); | |||
| 134 | } | |||
| 135 | } | |||
| 136 | ||||
| 0 | 2 | - | 137 | if (port->muxport >= 0) |
| 138 | select_port (port); | |||
| 139 | ||||
| 140 | parport_daisy_deselect_all (port); | |||
| 141 | detected += assign_addrs (port); | |||
| 142 | ||||
| 143 | /* Count the potential legacy device at the end. */ | |||
| 144 | add_dev (numdevs++, port, -1); | |||
| 145 | ||||
| 146 | /* Find out the legacy device's IEEE 1284 device ID. */ | |||
| 147 | deviceid = kmalloc (1024, GFP_KERNEL); | |||
| 2 | 0 | - | 148 | if (deviceid) { |
| 0 | 2 | - | 149 | if (parport_device_id (numdevs - 1, deviceid, 1024) > 2) |
| 150 | detected++; | |||
| 151 | ||||
| 152 | kfree (deviceid); | |||
| 153 | } | |||
| 154 | ||||
| 1 | 1 | 155 | if (!detected && !last_try) { | |
| 1 | 155 | T && T | ||
| 1 | 155 | T && F | ||
| 0 | - | 155 | F && _ | |
| 156 | /* No devices were detected. Perhaps they are in some | |||
| 157 | funny state; let's try to reset them and see if | |||
| 158 | they wake up. */ | |||
| 159 | parport_daisy_fini (port); | |||
| 160 | parport_write_control (port, PARPORT_CONTROL_SELECT); | |||
| 161 | udelay (50); | |||
| 1 | 0 | - | 161 | ternary-?: __builtin_constant_p ( 50 ) |
| 0 | 1 | - | 161 | ternary-?: ( 50 ) > 20000 |
| 162 | parport_write_control (port, | |||
| 163 | PARPORT_CONTROL_SELECT | | |||
| 164 | PARPORT_CONTROL_INIT); | |||
| 165 | udelay (50); | |||
| 1 | 0 | - | 165 | ternary-?: __builtin_constant_p ( 50 ) |
| 0 | 1 | - | 165 | ternary-?: ( 50 ) > 20000 |
| 166 | last_try = 1; | |||
| 1 | 167 | goto again; | ||
| 168 | } | |||
| 169 | ||||
| 1 | 170 | return detected; | ||
| 171 | } | |||
| 172 | ||||
| 173 | /* Forget about devices on a physical port. */ | |||
| 1 | 0 | 174 | void parport_daisy_fini (struct parport *port) | |
| 175 | { | |||
| 176 | struct daisydev **p; | |||
| 177 | ||||
| 178 | spin_lock(&topology_lock); | |||
| 178 | do | |||
| 0 | 1 | - | 178 | do-while (0) |
| 0 | 1 | - | 178 | do-while (0) |
| 179 | p = &topology; | |||
| 1 | 1 | 180 | while (*p) { | |
| 181 | struct daisydev *dev = *p; | |||
| 0 | 1 | - | 182 | if (dev->port != port) { |
| 183 | p = &dev->next; | |||
| 0 | - | 184 | continue; | |
| 185 | } | |||
| 186 | *p = dev->next; | |||
| 187 | kfree(dev); | |||
| 188 | } | |||
| 189 | ||||
| 190 | /* Gaps in the numbering could be handled better. How should | |||
| 191 | someone enumerate through all IEEE1284.3 devices in the | |||
| 192 | topology?. */ | |||
| 1 | 0 | - | 193 | if (!topology) numdevs = 0; |
| 194 | spin_unlock(&topology_lock); | |||
| 194 | do | |||
| 0 | 1 | - | 194 | do-while (0) |
| 0 | 1 | - | 194 | do-while (0) |
| 1 | 195 | return; | ||
| 196 | } | |||
| 197 | ||||
| 198 | /** | |||
| 199 | * parport_open - find a device by canonical device number | |||
| 200 | * @devnum: canonical device number | |||
| 201 | * @name: name to associate with the device | |||
| 202 | * @pf: preemption callback | |||
| 203 | * @kf: kick callback | |||
| 204 | * @irqf: interrupt handler | |||
| 205 | * @flags: registration flags | |||
| 206 | * @handle: driver data | |||
| 207 | * | |||
| 208 | * This function is similar to parport_register_device(), except | |||
| 209 | * that it locates a device by its number rather than by the port | |||
| 210 | * it is attached to. | |||
| 211 | * | |||
| 212 | * All parameters except for @devnum are the same as for | |||
| 213 | * parport_register_device(). The return value is the same as | |||
| 214 | * for parport_register_device(). | |||
| 215 | **/ | |||
| 216 | ||||
| 2 | 0 | 217 | struct pardevice *parport_open (int devnum, const char *name, | |
| 218 | int (*pf) (void *), void (*kf) (void *), | |||
| 219 | void (*irqf) (int, void *, struct pt_regs *), | |||
| 220 | int flags, void *handle) | |||
| 221 | { | |||
| 222 | struct daisydev *p = topology; | |||
| 223 | struct parport *port; | |||
| 224 | struct pardevice *dev; | |||
| 225 | int daisy; | |||
| 226 | ||||
| 227 | spin_lock(&topology_lock); | |||
| 227 | do | |||
| 0 | 2 | - | 227 | do-while (0) |
| 0 | 2 | - | 227 | do-while (0) |
| 0 | 2 | - | 228 | while (p && p->devnum != devnum) |
| 0 | - | 228 | T && T | |
| 2 | 228 | T && F | ||
| 0 | - | 228 | F && _ | |
| 229 | p = p->next; | |||
| 230 | ||||
| 0 | 2 | - | 231 | if (!p) { |
| 232 | spin_unlock(&topology_lock); | |||
| 232 | do | |||
| 0 | 0 | - | 232 | do-while (0) |
| 0 | 0 | - | 232 | do-while (0) |
| 0 | - | 233 | return NULL; | |
| 234 | } | |||
| 235 | ||||
| 236 | daisy = p->daisy; | |||
| 237 | port = parport_get_port(p->port); | |||
| 238 | spin_unlock(&topology_lock); | |||
| 238 | do | |||
| 0 | 2 | - | 238 | do-while (0) |
| 0 | 2 | - | 238 | do-while (0) |
| 239 | ||||
| 240 | dev = parport_register_device (port, name, pf, kf, | |||
| 241 | irqf, flags, handle); | |||
| 242 | parport_put_port(port); | |||
| 0 | 2 | - | 243 | if (!dev) |
| 0 | - | 244 | return NULL; | |
| 245 | ||||
| 246 | dev->daisy = daisy; | |||
| 247 | ||||
| 248 | /* Check that there really is a device to select. */ | |||
| 0 | 2 | - | 249 | if (daisy >= 0) { |
| 250 | int selected; | |||
| 251 | parport_claim_or_block (dev); | |||
| 252 | selected = port->daisy; | |||
| 253 | parport_release (dev); | |||
| 254 | ||||
| 0 | 0 | - | 255 | if (selected != daisy) { |
| 256 | /* No corresponding device. */ | |||
| 257 | parport_unregister_device (dev); | |||
| 0 | - | 258 | return NULL; | |
| 259 | } | |||
| 260 | } | |||
| 261 | ||||
| 2 | 262 | return dev; | ||
| 263 | } | |||
| 264 | ||||
| 265 | /** | |||
| 266 | * parport_close - close a device opened with parport_open() | |||
| 267 | * @dev: device to close | |||
| 268 | * | |||
| 269 | * This is to parport_open() as parport_unregister_device() is to | |||
| 270 | * parport_register_device(). | |||
| 271 | **/ | |||
| 272 | ||||
| 2 | 2 | 273 | void parport_close (struct pardevice *dev) | |
| 274 | { | |||
| 275 | parport_unregister_device (dev); | |||
| 276 | } | |||
| 277 | ||||
| 278 | /** | |||
| 279 | * parport_device_num - convert device coordinates | |||
| 280 | * @parport: parallel port number | |||
| 281 | * @mux: multiplexor port number (-1 for no multiplexor) | |||
| 282 | * @daisy: daisy chain address (-1 for no daisy chain address) | |||
| 283 | * | |||
| 284 | * This tries to locate a device on the given parallel port, | |||
| 285 | * multiplexor port and daisy chain address, and returns its | |||
| 286 | * device number or -NXIO if no device with those coordinates | |||
| 287 | * exists. | |||
| 288 | **/ | |||
| 289 | ||||
| 2 | 0 | 290 | int parport_device_num (int parport, int mux, int daisy) | |
| 291 | { | |||
| 292 | int res = -ENXIO; | |||
| 293 | struct daisydev *dev; | |||
| 294 | ||||
| 295 | spin_lock(&topology_lock); | |||
| 295 | do | |||
| 0 | 2 | - | 295 | do-while (0) |
| 0 | 2 | - | 295 | do-while (0) |
| 296 | dev = topology; | |||
| 297 | while (dev && dev->port->portnum != parport && | |||
| 0 | 2 | - | 298 | dev->port->muxport != mux && dev->daisy != daisy) |
| 0 | - | 298 | T && T && T && T | |
| 0 | - | 298 | T && T && T && F | |
| 0 | - | 298 | T && T && F && _ | |
| 2 | 298 | T && F && _ && _ | ||
| 0 | - | 298 | F && _ && _ && _ | |
| 299 | dev = dev->next; | |||
| 2 | 0 | - | 300 | if (dev) |
| 301 | res = dev->devnum; | |||
| 302 | spin_unlock(&topology_lock); | |||
| 302 | do | |||
| 0 | 2 | - | 302 | do-while (0) |
| 0 | 2 | - | 302 | do-while (0) |
| 303 | ||||
| 2 | 304 | return res; | ||
| 305 | } | |||
| 306 | ||||
| 307 | /* Send a daisy-chain-style CPP command packet. */ | |||
| 2 | 0 | 308 | static int cpp_daisy (struct parport *port, int cmd) | |
| 309 | { | |||
| 310 | unsigned char s; | |||
| 311 | ||||
| 312 | parport_data_forward (port); | |||
| 313 | parport_write_data (port, 0xaa); udelay (2); | |||
| 2 | 0 | - | 313 | ternary-?: __builtin_constant_p ( 2 ) |
| 0 | 2 | - | 313 | ternary-?: ( 2 ) > 20000 |
| 314 | parport_write_data (port, 0x55); udelay (2); | |||
| 2 | 0 | - | 314 | ternary-?: __builtin_constant_p ( 2 ) |
| 0 | 2 | - | 314 | ternary-?: ( 2 ) > 20000 |
| 315 | parport_write_data (port, 0x00); udelay (2); | |||
| 2 | 0 | - | 315 | ternary-?: __builtin_constant_p ( 2 ) |
| 0 | 2 | - | 315 | ternary-?: ( 2 ) > 20000 |
| 316 | parport_write_data (port, 0xff); udelay (2); | |||
| 2 | 0 | - | 316 | ternary-?: __builtin_constant_p ( 2 ) |
| 0 | 2 | - | 316 | ternary-?: ( 2 ) > 20000 |
| 317 | s = parport_read_status (port) & (PARPORT_STATUS_BUSY | |||
| 318 | | PARPORT_STATUS_PAPEROUT | |||
| 319 | | PARPORT_STATUS_SELECT | |||
| 320 | | PARPORT_STATUS_ERROR); | |||
| 321 | if (s != (PARPORT_STATUS_BUSY | |||
| 322 | | PARPORT_STATUS_PAPEROUT | |||
| 323 | | PARPORT_STATUS_SELECT | |||
| 2 | 0 | - | 324 | | PARPORT_STATUS_ERROR)) { |
| 325 | DPRINTK (KERN_DEBUG "%s: cpp_daisy: aa5500ff(%02x)\n", | |||
| 326 | port->name, s); | |||
| 2 | 327 | return -ENXIO; | ||
| 328 | } | |||
| 329 | ||||
| 330 | parport_write_data (port, 0x87); udelay (2); | |||
| 0 | 0 | - | 330 | ternary-?: __builtin_constant_p ( 2 ) |
| 0 | 0 | - | 330 | ternary-?: ( 2 ) > 20000 |
| 331 | s = parport_read_status (port) & (PARPORT_STATUS_BUSY | |||
| 332 | | PARPORT_STATUS_PAPEROUT | |||
| 333 | | PARPORT_STATUS_SELECT | |||
| 334 | | PARPORT_STATUS_ERROR); | |||
| 0 | 0 | - | 335 | if (s != (PARPORT_STATUS_SELECT | PARPORT_STATUS_ERROR)) { |
| 336 | DPRINTK (KERN_DEBUG "%s: cpp_daisy: aa5500ff87(%02x)\n", | |||
| 337 | port->name, s); | |||
| 0 | - | 338 | return -ENXIO; | |
| 339 | } | |||
| 340 | ||||
| 341 | parport_write_data (port, 0x78); udelay (2); | |||
| 0 | 0 | - | 341 | ternary-?: __builtin_constant_p ( 2 ) |
| 0 | 0 | - | 341 | ternary-?: ( 2 ) > 20000 |
| 342 | parport_write_data (port, cmd); udelay (2); | |||
| 0 | 0 | - | 342 | ternary-?: __builtin_constant_p ( 2 ) |
| 0 | 0 | - | 342 | ternary-?: ( 2 ) > 20000 |
| 343 | parport_frob_control (port, | |||
| 344 | PARPORT_CONTROL_STROBE, | |||
| 345 | PARPORT_CONTROL_STROBE); | |||
| 346 | udelay (1); | |||
| 0 | 0 | - | 346 | ternary-?: __builtin_constant_p ( 1 ) |
| 0 | 0 | - | 346 | ternary-?: ( 1 ) > 20000 |
| 347 | s = parport_read_status (port); | |||
| 348 | parport_frob_control (port, PARPORT_CONTROL_STROBE, 0); | |||
| 349 | udelay (1); | |||
| 0 | 0 | - | 349 | ternary-?: __builtin_constant_p ( 1 ) |
| 0 | 0 | - | 349 | ternary-?: ( 1 ) > 20000 |
| 350 | parport_write_data (port, 0xff); udelay (2); | |||
| 0 | 0 | - | 350 | ternary-?: __builtin_constant_p ( 2 ) |
| 0 | 0 | - | 350 | ternary-?: ( 2 ) > 20000 |
| 351 | ||||
| 0 | - | 352 | return s; | |
| 353 | } | |||
| 354 | ||||
| 355 | /* Send a mux-style CPP command packet. */ | |||
| 2 | 0 | 356 | static int cpp_mux (struct parport *port, int cmd) | |
| 357 | { | |||
| 358 | unsigned char s; | |||
| 359 | int rc; | |||
| 360 | ||||
| 361 | parport_data_forward (port); | |||
| 362 | parport_write_data (port, 0xaa); udelay (2); | |||
| 2 | 0 | - | 362 | ternary-?: __builtin_constant_p ( 2 ) |
| 0 | 2 | - | 362 | ternary-?: ( 2 ) > 20000 |
| 363 | parport_write_data (port, 0x55); udelay (2); | |||
| 2 | 0 | - | 363 | ternary-?: __builtin_constant_p ( 2 ) |
| 0 | 2 | - | 363 | ternary-?: ( 2 ) > 20000 |
| 364 | parport_write_data (port, 0xf0); udelay (2); | |||
| 2 | 0 | - | 364 | ternary-?: __builtin_constant_p ( 2 ) |
| 0 | 2 | - | 364 | ternary-?: ( 2 ) > 20000 |
| 365 | parport_write_data (port, 0x0f); udelay (2); | |||
| 2 | 0 | - | 365 | ternary-?: __builtin_constant_p ( 2 ) |
| 0 | 2 | - | 365 | ternary-?: ( 2 ) > 20000 |
| 366 | parport_write_data (port, 0x52); udelay (2); | |||
| 2 | 0 | - | 366 | ternary-?: __builtin_constant_p ( 2 ) |
| 0 | 2 | - | 366 | ternary-?: ( 2 ) > 20000 |
| 367 | parport_write_data (port, 0xad); udelay (2); | |||
| 2 | 0 | - | 367 | ternary-?: __builtin_constant_p ( 2 ) |
| 0 | 2 | - | 367 | ternary-?: ( 2 ) > 20000 |
| 368 | parport_write_data (port, cmd); udelay (2); | |||
| 2 | 0 | - | 368 | ternary-?: __builtin_constant_p ( 2 ) |
| 0 | 2 | - | 368 | ternary-?: ( 2 ) > 20000 |
| 369 | ||||
| 370 | s = parport_read_status (port); | |||
| 0 | 2 | - | 371 | if (!(s & PARPORT_STATUS_ACK)) { |
| 372 | DPRINTK (KERN_DEBUG "%s: cpp_mux: aa55f00f52ad%02x(%02x)\n", | |||
| 373 | port->name, cmd, s); | |||
| 0 | - | 374 | return -EIO; | |
| 375 | } | |||
| 376 | ||||
| 377 | rc = (((s & PARPORT_STATUS_SELECT ? 1 : 0) << 0) | | |||
| 2 | 0 | - | 377 | ternary-?: s & 0x10 |
| 378 | ((s & PARPORT_STATUS_PAPEROUT ? 1 : 0) << 1) | | |||
| 2 | 0 | - | 378 | ternary-?: s & 0x20 |
| 379 | ((s & PARPORT_STATUS_BUSY ? 0 : 1) << 2) | | |||
| 0 | 2 | - | 379 | ternary-?: s & 0x80 |
| 380 | ((s & PARPORT_STATUS_ERROR ? 0 : 1) << 3)); | |||
| 2 | 0 | - | 380 | ternary-?: s & 0x8 |
| 381 | ||||
| 2 | 382 | return rc; | ||
| 383 | } | |||
| 384 | ||||
| 2 | 2 | 385 | void parport_daisy_deselect_all (struct parport *port) | |
| 386 | { | |||
| 387 | cpp_daisy (port, 0x30); | |||
| 388 | } | |||
| 389 | ||||
| 0 | 0 | - | 390 | int parport_daisy_select (struct parport *port, int daisy, int mode) |
| 391 | { | |||
| 392 | switch (mode) | |||
| 393 | { | |||
| 394 | // For these modes we should switch to EPP mode: | |||
| 0 | - | 395 | case IEEE1284_MODE_EPP: | |
| 0 | - | 396 | case IEEE1284_MODE_EPPSL: | |
| 0 | - | 397 | case IEEE1284_MODE_EPPSWE: | |
| 398 | return !(cpp_daisy (port, 0x20 + daisy) & | |||
| 0 | - | 399 | PARPORT_STATUS_ERROR); | |
| 400 | ||||
| 401 | // For these modes we should switch to ECP mode: | |||
| 0 | - | 402 | case IEEE1284_MODE_ECP: | |
| 0 | - | 403 | case IEEE1284_MODE_ECPRLE: | |
| 0 | - | 404 | case IEEE1284_MODE_ECPSWE: | |
| 405 | return !(cpp_daisy (port, 0xd0 + daisy) & | |||
| 0 | - | 406 | PARPORT_STATUS_ERROR); | |
| 407 | ||||
| 408 | // Nothing was told for BECP in Daisy chain specification. | |||
| 409 | // May be it's wise to use ECP? | |||
| 0 | - | 410 | case IEEE1284_MODE_BECP: | |
| 411 | // Others use compat mode | |||
| 0 | - | 412 | case IEEE1284_MODE_NIBBLE: | |
| 0 | - | 413 | case IEEE1284_MODE_BYTE: | |
| 0 | - | 414 | case IEEE1284_MODE_COMPAT: | |
| 0 | - | 415 | default: | |