at v2.6.17-rc2 468 lines 9.4 kB view raw
1/* 2 paride.c (c) 1997-8 Grant R. Guenther <grant@torque.net> 3 Under the terms of the GNU General Public License. 4 5 This is the base module for the family of device drivers 6 that support parallel port IDE devices. 7 8*/ 9 10/* Changes: 11 12 1.01 GRG 1998.05.03 Use spinlocks 13 1.02 GRG 1998.05.05 init_proto, release_proto, ktti 14 1.03 GRG 1998.08.15 eliminate compiler warning 15 1.04 GRG 1998.11.28 added support for FRIQ 16 1.05 TMW 2000.06.06 use parport_find_number instead of 17 parport_enumerate 18 1.06 TMW 2001.03.26 more sane parport-or-not resource management 19*/ 20 21#define PI_VERSION "1.06" 22 23#include <linux/module.h> 24#include <linux/config.h> 25#include <linux/kmod.h> 26#include <linux/types.h> 27#include <linux/kernel.h> 28#include <linux/ioport.h> 29#include <linux/string.h> 30#include <linux/spinlock.h> 31#include <linux/wait.h> 32#include <linux/sched.h> /* TASK_* */ 33 34#ifdef CONFIG_PARPORT_MODULE 35#define CONFIG_PARPORT 36#endif 37 38#ifdef CONFIG_PARPORT 39#include <linux/parport.h> 40#endif 41 42#include "paride.h" 43 44MODULE_LICENSE("GPL"); 45 46#define MAX_PROTOS 32 47 48static struct pi_protocol *protocols[MAX_PROTOS]; 49 50static DEFINE_SPINLOCK(pi_spinlock); 51 52void pi_write_regr(PIA * pi, int cont, int regr, int val) 53{ 54 pi->proto->write_regr(pi, cont, regr, val); 55} 56 57EXPORT_SYMBOL(pi_write_regr); 58 59int pi_read_regr(PIA * pi, int cont, int regr) 60{ 61 return pi->proto->read_regr(pi, cont, regr); 62} 63 64EXPORT_SYMBOL(pi_read_regr); 65 66void pi_write_block(PIA * pi, char *buf, int count) 67{ 68 pi->proto->write_block(pi, buf, count); 69} 70 71EXPORT_SYMBOL(pi_write_block); 72 73void pi_read_block(PIA * pi, char *buf, int count) 74{ 75 pi->proto->read_block(pi, buf, count); 76} 77 78EXPORT_SYMBOL(pi_read_block); 79 80#ifdef CONFIG_PARPORT 81 82static void pi_wake_up(void *p) 83{ 84 PIA *pi = (PIA *) p; 85 unsigned long flags; 86 void (*cont) (void) = NULL; 87 88 spin_lock_irqsave(&pi_spinlock, flags); 89 90 if (pi->claim_cont && !parport_claim(pi->pardev)) { 91 cont = pi->claim_cont; 92 pi->claim_cont = NULL; 93 pi->claimed = 1; 94 } 95 96 spin_unlock_irqrestore(&pi_spinlock, flags); 97 98 wake_up(&(pi->parq)); 99 100 if (cont) 101 cont(); 102} 103 104#endif 105 106int pi_schedule_claimed(PIA * pi, void (*cont) (void)) 107{ 108#ifdef CONFIG_PARPORT 109 unsigned long flags; 110 111 spin_lock_irqsave(&pi_spinlock, flags); 112 if (pi->pardev && parport_claim(pi->pardev)) { 113 pi->claim_cont = cont; 114 spin_unlock_irqrestore(&pi_spinlock, flags); 115 return 0; 116 } 117 pi->claimed = 1; 118 spin_unlock_irqrestore(&pi_spinlock, flags); 119#endif 120 return 1; 121} 122EXPORT_SYMBOL(pi_schedule_claimed); 123 124void pi_do_claimed(PIA * pi, void (*cont) (void)) 125{ 126 if (pi_schedule_claimed(pi, cont)) 127 cont(); 128} 129 130EXPORT_SYMBOL(pi_do_claimed); 131 132static void pi_claim(PIA * pi) 133{ 134 if (pi->claimed) 135 return; 136 pi->claimed = 1; 137#ifdef CONFIG_PARPORT 138 if (pi->pardev) 139 wait_event(pi->parq, 140 !parport_claim((struct pardevice *) pi->pardev)); 141#endif 142} 143 144static void pi_unclaim(PIA * pi) 145{ 146 pi->claimed = 0; 147#ifdef CONFIG_PARPORT 148 if (pi->pardev) 149 parport_release((struct pardevice *) (pi->pardev)); 150#endif 151} 152 153void pi_connect(PIA * pi) 154{ 155 pi_claim(pi); 156 pi->proto->connect(pi); 157} 158 159EXPORT_SYMBOL(pi_connect); 160 161void pi_disconnect(PIA * pi) 162{ 163 pi->proto->disconnect(pi); 164 pi_unclaim(pi); 165} 166 167EXPORT_SYMBOL(pi_disconnect); 168 169static void pi_unregister_parport(PIA * pi) 170{ 171#ifdef CONFIG_PARPORT 172 if (pi->pardev) { 173 parport_unregister_device((struct pardevice *) (pi->pardev)); 174 pi->pardev = NULL; 175 } 176#endif 177} 178 179void pi_release(PIA * pi) 180{ 181 pi_unregister_parport(pi); 182#ifndef CONFIG_PARPORT 183 if (pi->reserved) 184 release_region(pi->port, pi->reserved); 185#endif /* !CONFIG_PARPORT */ 186 if (pi->proto->release_proto) 187 pi->proto->release_proto(pi); 188 module_put(pi->proto->owner); 189} 190 191EXPORT_SYMBOL(pi_release); 192 193static int default_test_proto(PIA * pi, char *scratch, int verbose) 194{ 195 int j, k; 196 int e[2] = { 0, 0 }; 197 198 pi->proto->connect(pi); 199 200 for (j = 0; j < 2; j++) { 201 pi_write_regr(pi, 0, 6, 0xa0 + j * 0x10); 202 for (k = 0; k < 256; k++) { 203 pi_write_regr(pi, 0, 2, k ^ 0xaa); 204 pi_write_regr(pi, 0, 3, k ^ 0x55); 205 if (pi_read_regr(pi, 0, 2) != (k ^ 0xaa)) 206 e[j]++; 207 } 208 } 209 pi->proto->disconnect(pi); 210 211 if (verbose) 212 printk("%s: %s: port 0x%x, mode %d, test=(%d,%d)\n", 213 pi->device, pi->proto->name, pi->port, 214 pi->mode, e[0], e[1]); 215 216 return (e[0] && e[1]); /* not here if both > 0 */ 217} 218 219static int pi_test_proto(PIA * pi, char *scratch, int verbose) 220{ 221 int res; 222 223 pi_claim(pi); 224 if (pi->proto->test_proto) 225 res = pi->proto->test_proto(pi, scratch, verbose); 226 else 227 res = default_test_proto(pi, scratch, verbose); 228 pi_unclaim(pi); 229 230 return res; 231} 232 233int pi_register(PIP * pr) 234{ 235 int k; 236 237 for (k = 0; k < MAX_PROTOS; k++) 238 if (protocols[k] && !strcmp(pr->name, protocols[k]->name)) { 239 printk("paride: %s protocol already registered\n", 240 pr->name); 241 return 0; 242 } 243 k = 0; 244 while ((k < MAX_PROTOS) && (protocols[k])) 245 k++; 246 if (k == MAX_PROTOS) { 247 printk("paride: protocol table full\n"); 248 return 0; 249 } 250 protocols[k] = pr; 251 pr->index = k; 252 printk("paride: %s registered as protocol %d\n", pr->name, k); 253 return 1; 254} 255 256EXPORT_SYMBOL(pi_register); 257 258void pi_unregister(PIP * pr) 259{ 260 if (!pr) 261 return; 262 if (protocols[pr->index] != pr) { 263 printk("paride: %s not registered\n", pr->name); 264 return; 265 } 266 protocols[pr->index] = NULL; 267} 268 269EXPORT_SYMBOL(pi_unregister); 270 271static int pi_register_parport(PIA * pi, int verbose) 272{ 273#ifdef CONFIG_PARPORT 274 275 struct parport *port; 276 277 port = parport_find_base(pi->port); 278 if (!port) 279 return 0; 280 281 pi->pardev = parport_register_device(port, 282 pi->device, NULL, 283 pi_wake_up, NULL, 0, (void *) pi); 284 parport_put_port(port); 285 if (!pi->pardev) 286 return 0; 287 288 init_waitqueue_head(&pi->parq); 289 290 if (verbose) 291 printk("%s: 0x%x is %s\n", pi->device, pi->port, port->name); 292 293 pi->parname = (char *) port->name; 294#endif 295 296 return 1; 297} 298 299static int pi_probe_mode(PIA * pi, int max, char *scratch, int verbose) 300{ 301 int best, range; 302 303 if (pi->mode != -1) { 304 if (pi->mode >= max) 305 return 0; 306 range = 3; 307 if (pi->mode >= pi->proto->epp_first) 308 range = 8; 309 if ((range == 8) && (pi->port % 8)) 310 return 0; 311 pi->reserved = range; 312 return (!pi_test_proto(pi, scratch, verbose)); 313 } 314 best = -1; 315 for (pi->mode = 0; pi->mode < max; pi->mode++) { 316 range = 3; 317 if (pi->mode >= pi->proto->epp_first) 318 range = 8; 319 if ((range == 8) && (pi->port % 8)) 320 break; 321 pi->reserved = range; 322 if (!pi_test_proto(pi, scratch, verbose)) 323 best = pi->mode; 324 } 325 pi->mode = best; 326 return (best > -1); 327} 328 329static int pi_probe_unit(PIA * pi, int unit, char *scratch, int verbose) 330{ 331 int max, s, e; 332 333 s = unit; 334 e = s + 1; 335 336 if (s == -1) { 337 s = 0; 338 e = pi->proto->max_units; 339 } 340 341 if (!pi_register_parport(pi, verbose)) 342 return 0; 343 344 if (pi->proto->test_port) { 345 pi_claim(pi); 346 max = pi->proto->test_port(pi); 347 pi_unclaim(pi); 348 } else 349 max = pi->proto->max_mode; 350 351 if (pi->proto->probe_unit) { 352 pi_claim(pi); 353 for (pi->unit = s; pi->unit < e; pi->unit++) 354 if (pi->proto->probe_unit(pi)) { 355 pi_unclaim(pi); 356 if (pi_probe_mode(pi, max, scratch, verbose)) 357 return 1; 358 pi_unregister_parport(pi); 359 return 0; 360 } 361 pi_unclaim(pi); 362 pi_unregister_parport(pi); 363 return 0; 364 } 365 366 if (!pi_probe_mode(pi, max, scratch, verbose)) { 367 pi_unregister_parport(pi); 368 return 0; 369 } 370 return 1; 371 372} 373 374int pi_init(PIA * pi, int autoprobe, int port, int mode, 375 int unit, int protocol, int delay, char *scratch, 376 int devtype, int verbose, char *device) 377{ 378 int p, k, s, e; 379 int lpts[7] = { 0x3bc, 0x378, 0x278, 0x268, 0x27c, 0x26c, 0 }; 380 381 s = protocol; 382 e = s + 1; 383 384 if (!protocols[0]) 385 request_module("paride_protocol"); 386 387 if (autoprobe) { 388 s = 0; 389 e = MAX_PROTOS; 390 } else if ((s < 0) || (s >= MAX_PROTOS) || (port <= 0) || 391 (!protocols[s]) || (unit < 0) || 392 (unit >= protocols[s]->max_units)) { 393 printk("%s: Invalid parameters\n", device); 394 return 0; 395 } 396 397 for (p = s; p < e; p++) { 398 struct pi_protocol *proto = protocols[p]; 399 if (!proto) 400 continue; 401 /* still racy */ 402 if (!try_module_get(proto->owner)) 403 continue; 404 pi->proto = proto; 405 pi->private = 0; 406 if (proto->init_proto && proto->init_proto(pi) < 0) { 407 pi->proto = NULL; 408 module_put(proto->owner); 409 continue; 410 } 411 if (delay == -1) 412 pi->delay = pi->proto->default_delay; 413 else 414 pi->delay = delay; 415 pi->devtype = devtype; 416 pi->device = device; 417 418 pi->parname = NULL; 419 pi->pardev = NULL; 420 init_waitqueue_head(&pi->parq); 421 pi->claimed = 0; 422 pi->claim_cont = NULL; 423 424 pi->mode = mode; 425 if (port != -1) { 426 pi->port = port; 427 if (pi_probe_unit(pi, unit, scratch, verbose)) 428 break; 429 pi->port = 0; 430 } else { 431 k = 0; 432 while ((pi->port = lpts[k++])) 433 if (pi_probe_unit 434 (pi, unit, scratch, verbose)) 435 break; 436 if (pi->port) 437 break; 438 } 439 if (pi->proto->release_proto) 440 pi->proto->release_proto(pi); 441 module_put(proto->owner); 442 } 443 444 if (!pi->port) { 445 if (autoprobe) 446 printk("%s: Autoprobe failed\n", device); 447 else 448 printk("%s: Adapter not found\n", device); 449 return 0; 450 } 451#ifndef CONFIG_PARPORT 452 if (!request_region(pi->port, pi->reserved, pi->device)) { 453 printk(KERN_WARNING "paride: Unable to request region 0x%x\n", 454 pi->port); 455 return 0; 456 } 457#endif /* !CONFIG_PARPORT */ 458 459 if (pi->parname) 460 printk("%s: Sharing %s at 0x%x\n", pi->device, 461 pi->parname, pi->port); 462 463 pi->proto->log_adapter(pi, scratch, verbose); 464 465 return 1; 466} 467 468EXPORT_SYMBOL(pi_init);