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