The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/pckbport/pckbport.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /* $NetBSD: pckbport.c,v 1.3 2004/03/24 17:26:53 drochner Exp $ */
    2 
    3 /*
    4  * Copyright (c) 2004 Ben Harris
    5  * Copyright (c) 1998
    6  *      Matthias Drochner.  All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __KERNEL_RCSID(0, "$NetBSD: pckbport.c,v 1.3 2004/03/24 17:26:53 drochner Exp $");
   31 
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 #include <sys/callout.h>
   35 #include <sys/kernel.h>
   36 #include <sys/proc.h>
   37 #include <sys/device.h>
   38 #include <sys/malloc.h>
   39 #include <sys/errno.h>
   40 #include <sys/queue.h>
   41 #include <sys/lock.h>
   42 
   43 #include <dev/pckbport/pckbportvar.h>
   44 
   45 #include "locators.h"
   46 
   47 #ifdef __HAVE_NWSCONS /* XXX: this port uses sys/dev/pckbport */
   48 #include "pckbd.h"
   49 #else /* ie: only md drivers attach to pckbport */
   50 #define NPCKBD 0
   51 #endif
   52 #if (NPCKBD > 0)
   53 #include <dev/pckbport/pckbdvar.h>
   54 #endif
   55 
   56 /* descriptor for one device command */
   57 struct pckbport_devcmd {
   58         TAILQ_ENTRY(pckbport_devcmd) next;
   59         int flags;
   60 #define KBC_CMDFLAG_SYNC 1 /* give descriptor back to caller */
   61 #define KBC_CMDFLAG_SLOW 2
   62         u_char cmd[4];
   63         int cmdlen, cmdidx, retries;
   64         u_char response[4];
   65         int status, responselen, responseidx;
   66 };
   67 
   68 /* data per slave device */
   69 struct pckbport_slotdata {
   70         int polling;    /* don't process data in interrupt handler */
   71         TAILQ_HEAD(, pckbport_devcmd) cmdqueue; /* active commands */
   72         TAILQ_HEAD(, pckbport_devcmd) freequeue; /* free commands */
   73 #define NCMD 5
   74         struct pckbport_devcmd cmds[NCMD];
   75 };
   76 
   77 #define CMD_IN_QUEUE(q) (TAILQ_FIRST(&(q)->cmdqueue) != NULL)
   78 
   79 static void pckbport_init_slotdata(struct pckbport_slotdata *);
   80 static int pckbport_submatch(struct device *, struct cfdata *, void *);
   81 static int pckbportprint(void *, const char *);
   82 
   83 static struct pckbport_slotdata pckbport_cons_slotdata;
   84 
   85 static int pckbport_poll_data1(pckbport_tag_t, pckbport_slot_t);
   86 static int pckbport_send_devcmd(struct pckbport_tag *, pckbport_slot_t,
   87                                   u_char);
   88 static void pckbport_poll_cmd1(struct pckbport_tag *, pckbport_slot_t,
   89                                  struct pckbport_devcmd *);
   90 
   91 static void pckbport_cleanqueue(struct pckbport_slotdata *);
   92 static void pckbport_cleanup(void *);
   93 static int pckbport_cmdresponse(struct pckbport_tag *, pckbport_slot_t,
   94                                         u_char);
   95 static void pckbport_start(struct pckbport_tag *, pckbport_slot_t);
   96 
   97 static const char * const pckbport_slot_names[] = { "kbd", "aux" };
   98 
   99 static struct pckbport_tag pckbport_cntag;
  100 
  101 #define KBC_DEVCMD_ACK 0xfa
  102 #define KBC_DEVCMD_RESEND 0xfe
  103 
  104 #define KBD_DELAY       DELAY(8)
  105 
  106 static int
  107 pckbport_poll_data1(pckbport_tag_t t, pckbport_slot_t slot)
  108 {
  109 
  110         return t->t_ops->t_poll_data1(t->t_cookie, slot);
  111 }
  112 
  113 static int
  114 pckbport_send_devcmd(struct pckbport_tag *t, pckbport_slot_t slot, u_char val)
  115 {
  116 
  117         return t->t_ops->t_send_devcmd(t->t_cookie, slot, val);
  118 }
  119 
  120 static int
  121 pckbport_submatch(struct device *parent, struct cfdata *cf, void *aux)
  122 {
  123         struct pckbport_attach_args *pa = aux;
  124 
  125         if (cf->cf_loc[PCKBPORTCF_SLOT] != PCKBPORTCF_SLOT_DEFAULT &&
  126             cf->cf_loc[PCKBPORTCF_SLOT] != pa->pa_slot)
  127                 return 0;
  128         return config_match(parent, cf, aux);
  129 }
  130 
  131 pckbport_tag_t
  132 pckbport_attach(void *cookie, struct pckbport_accessops const *ops)
  133 {
  134         pckbport_tag_t t;
  135 
  136         if (cookie == pckbport_cntag.t_cookie &&
  137             ops == pckbport_cntag.t_ops)
  138                 return &pckbport_cntag;
  139         t = malloc(sizeof(struct pckbport_tag), M_DEVBUF, M_NOWAIT | M_ZERO);
  140         if (t == NULL) return NULL;
  141         t->t_cookie = cookie;
  142         t->t_ops = ops;
  143         return t;
  144 }
  145 
  146 struct device *
  147 pckbport_attach_slot(struct device *dev, pckbport_tag_t t,
  148     pckbport_slot_t slot)
  149 {
  150         struct pckbport_attach_args pa;
  151         void *sdata;
  152         struct device *found;
  153         int alloced = 0;
  154 
  155         pa.pa_tag = t;
  156         pa.pa_slot = slot;
  157 
  158         if (t->t_slotdata[slot] == NULL) {
  159                 sdata = malloc(sizeof(struct pckbport_slotdata),
  160                     M_DEVBUF, M_NOWAIT);
  161                 if (sdata == NULL) {
  162                         printf("%s: no memory\n", dev->dv_xname);
  163                         return 0;
  164                 }
  165                 t->t_slotdata[slot] = sdata;
  166                 pckbport_init_slotdata(t->t_slotdata[slot]);
  167                 alloced++;
  168         }
  169 
  170         found = config_found_sm(dev, &pa, pckbportprint, pckbport_submatch);
  171 
  172         if (found == NULL && alloced) {
  173                 free(t->t_slotdata[slot], M_DEVBUF);
  174                 t->t_slotdata[slot] = NULL;
  175         }
  176 
  177         return found;
  178 }
  179 
  180 int
  181 pckbportprint(void *aux, const char *pnp)
  182 {
  183         struct pckbport_attach_args *pa = aux;
  184 
  185         if (!pnp)
  186                 aprint_normal(" (%s slot)", pckbport_slot_names[pa->pa_slot]);
  187         return QUIET;
  188 }
  189 
  190 void
  191 pckbport_init_slotdata(struct pckbport_slotdata *q)
  192 {
  193         int i;
  194 
  195         TAILQ_INIT(&q->cmdqueue);
  196         TAILQ_INIT(&q->freequeue);
  197 
  198         for (i = 0; i < NCMD; i++)
  199                 TAILQ_INSERT_TAIL(&q->freequeue, &(q->cmds[i]), next);
  200 
  201         q->polling = 0;
  202 }
  203 
  204 void
  205 pckbport_flush(pckbport_tag_t t, pckbport_slot_t slot)
  206 {
  207 
  208         (void)pckbport_poll_data1(t, slot);
  209 }
  210 
  211 int
  212 pckbport_poll_data(pckbport_tag_t t, pckbport_slot_t slot)
  213 {
  214         struct pckbport_slotdata *q = t->t_slotdata[slot];
  215         int c;
  216 
  217         c = pckbport_poll_data1(t, slot);
  218         if (c != -1 && q && CMD_IN_QUEUE(q))
  219                 /*
  220                  * we jumped into a running command - try to deliver
  221                  * the response
  222                  */
  223                 if (pckbport_cmdresponse(t, slot, c))
  224                         return -1;
  225         return c;
  226 }
  227 
  228 /*
  229  * switch scancode translation on / off
  230  * return nonzero on success
  231  */
  232 int
  233 pckbport_xt_translation(pckbport_tag_t t, pckbport_slot_t slot, int on)
  234 {
  235 
  236         return t->t_ops->t_xt_translation(t->t_cookie, slot, on);
  237 }
  238 
  239 void
  240 pckbport_slot_enable(pckbport_tag_t t, pckbport_slot_t slot, int on)
  241 {
  242 
  243         t->t_ops->t_slot_enable(t->t_cookie, slot, on);
  244 }
  245 
  246 void
  247 pckbport_set_poll(pckbport_tag_t t, pckbport_slot_t slot, int on)
  248 {
  249 
  250         t->t_slotdata[slot]->polling = on;
  251         t->t_ops->t_set_poll(t->t_cookie, slot, on);
  252 }
  253 
  254 /*
  255  * Pass command to device, poll for ACK and data.
  256  * to be called at spltty()
  257  */
  258 static void
  259 pckbport_poll_cmd1(struct pckbport_tag *t, pckbport_slot_t slot,
  260     struct pckbport_devcmd *cmd)
  261 {
  262         int i, c = 0;
  263 
  264         while (cmd->cmdidx < cmd->cmdlen) {
  265                 if (!pckbport_send_devcmd(t, slot, cmd->cmd[cmd->cmdidx])) {
  266                         printf("pckbport_cmd: send error\n");
  267                         cmd->status = EIO;
  268                         return;
  269                 }
  270                 for (i = 10; i; i--) { /* 1s ??? */
  271                         c = pckbport_poll_data1(t, slot);
  272                         if (c != -1)
  273                                 break;
  274                 }
  275 
  276                 if (c == KBC_DEVCMD_ACK) {
  277                         cmd->cmdidx++;
  278                         continue;
  279                 }
  280                 if (c == KBC_DEVCMD_RESEND) {
  281 #ifdef PCKBPORTDEBUG
  282                         printf("pckbport_cmd: RESEND\n");
  283 #endif
  284                         if (cmd->retries++ < 5)
  285                                 continue;
  286                         else {
  287 #ifdef PCKBPORTDEBUG
  288                                 printf("pckbport: cmd failed\n");
  289 #endif
  290                                 cmd->status = EIO;
  291                                 return;
  292                         }
  293                 }
  294                 if (c == -1) {
  295 #ifdef PCKBPORTDEBUG
  296                         printf("pckbport_cmd: timeout\n");
  297 #endif
  298                         cmd->status = EIO;
  299                         return;
  300                 }
  301 #ifdef PCKBPORTDEBUG
  302                 printf("pckbport_cmd: lost 0x%x\n", c);
  303 #endif
  304         }
  305 
  306         while (cmd->responseidx < cmd->responselen) {
  307                 if (cmd->flags & KBC_CMDFLAG_SLOW)
  308                         i = 100; /* 10s ??? */
  309                 else
  310                         i = 10; /* 1s ??? */
  311                 while (i--) {
  312                         c = pckbport_poll_data1(t, slot);
  313                         if (c != -1)
  314                                 break;
  315                 }
  316                 if (c == -1) {
  317 #ifdef PCKBPORTDEBUG
  318                         printf("pckbport_cmd: no data\n");
  319 #endif
  320                         cmd->status = ETIMEDOUT;
  321                         return;
  322                 } else
  323                         cmd->response[cmd->responseidx++] = c;
  324         }
  325 }
  326 
  327 /* for use in autoconfiguration */
  328 int
  329 pckbport_poll_cmd(pckbport_tag_t t, pckbport_slot_t slot, u_char *cmd, int len,
  330     int responselen, u_char *respbuf, int slow)
  331 {
  332         struct pckbport_devcmd nc;
  333 
  334         if ((len > 4) || (responselen > 4))
  335                 return (EINVAL);
  336 
  337         memset(&nc, 0, sizeof(nc));
  338         memcpy(nc.cmd, cmd, len);
  339         nc.cmdlen = len;
  340         nc.responselen = responselen;
  341         nc.flags = (slow ? KBC_CMDFLAG_SLOW : 0);
  342 
  343         pckbport_poll_cmd1(t, slot, &nc);
  344 
  345         if (nc.status == 0 && respbuf)
  346                 memcpy(respbuf, nc.response, responselen);
  347 
  348         return nc.status;
  349 }
  350 
  351 /*
  352  * Clean up a command queue, throw away everything.
  353  */
  354 void
  355 pckbport_cleanqueue(struct pckbport_slotdata *q)
  356 {
  357         struct pckbport_devcmd *cmd;
  358 #ifdef PCKBPORTDEBUG
  359         int i;
  360 #endif
  361 
  362         while ((cmd = TAILQ_FIRST(&q->cmdqueue))) {
  363                 TAILQ_REMOVE(&q->cmdqueue, cmd, next);
  364 #ifdef PCKBPORTDEBUG
  365                 printf("pckbport_cleanqueue: removing");
  366                 for (i = 0; i < cmd->cmdlen; i++)
  367                         printf(" %02x", cmd->cmd[i]);
  368                 printf("\n");
  369 #endif
  370                 TAILQ_INSERT_TAIL(&q->freequeue, cmd, next);
  371         }
  372 }
  373 
  374 /*
  375  * Timeout error handler: clean queues and data port.
  376  * XXX could be less invasive.
  377  */
  378 void
  379 pckbport_cleanup(void *self)
  380 {
  381         struct pckbport_tag *t = self;
  382         int s;
  383 
  384         printf("pckbport: command timeout\n");
  385 
  386         s = spltty();
  387 
  388         if (t->t_slotdata[PCKBPORT_KBD_SLOT])
  389                 pckbport_cleanqueue(t->t_slotdata[PCKBPORT_KBD_SLOT]);
  390         if (t->t_slotdata[PCKBPORT_AUX_SLOT])
  391                 pckbport_cleanqueue(t->t_slotdata[PCKBPORT_AUX_SLOT]);
  392 
  393 #if 0 /* XXXBJH Move to controller driver? */
  394         while (bus_space_read_1(t->t_iot, t->t_ioh_c, 0) & KBS_DIB) {
  395                 KBD_DELAY;
  396                 (void) bus_space_read_1(t->t_iot, t->t_ioh_d, 0);
  397         }
  398 #endif
  399 
  400         /* reset KBC? */
  401 
  402         splx(s);
  403 }
  404 
  405 /*
  406  * Pass command to device during normal operation.
  407  * to be called at spltty()
  408  */
  409 void
  410 pckbport_start(struct pckbport_tag *t, pckbport_slot_t slot)
  411 {
  412         struct pckbport_slotdata *q = t->t_slotdata[slot];
  413         struct pckbport_devcmd *cmd = TAILQ_FIRST(&q->cmdqueue);
  414 
  415         if (q->polling) {
  416                 do {
  417                         pckbport_poll_cmd1(t, slot, cmd);
  418                         if (cmd->status)
  419                                 printf("pckbport_start: command error\n");
  420 
  421                         TAILQ_REMOVE(&q->cmdqueue, cmd, next);
  422                         if (cmd->flags & KBC_CMDFLAG_SYNC)
  423                                 wakeup(cmd);
  424                         else {
  425                                 callout_stop(&t->t_cleanup);
  426                                 TAILQ_INSERT_TAIL(&q->freequeue, cmd, next);
  427                         }
  428                         cmd = TAILQ_FIRST(&q->cmdqueue);
  429                 } while (cmd);
  430                 return;
  431         }
  432 
  433         if (!pckbport_send_devcmd(t, slot, cmd->cmd[cmd->cmdidx])) {
  434                 printf("pckbport_start: send error\n");
  435                 /* XXX what now? */
  436                 return;
  437         }
  438 }
  439 
  440 /*
  441  * Handle command responses coming in asynchronously,
  442  * return nonzero if valid response.
  443  * to be called at spltty()
  444  */
  445 int
  446 pckbport_cmdresponse(struct pckbport_tag *t, pckbport_slot_t slot, u_char data)
  447 {
  448         struct pckbport_slotdata *q = t->t_slotdata[slot];
  449         struct pckbport_devcmd *cmd = TAILQ_FIRST(&q->cmdqueue);
  450 
  451 #ifdef DIAGNOSTIC
  452         if (!cmd)
  453                 panic("pckbport_cmdresponse: no active command");
  454 #endif
  455         if (cmd->cmdidx < cmd->cmdlen) {
  456                 if (data != KBC_DEVCMD_ACK && data != KBC_DEVCMD_RESEND)
  457                         return 0;
  458 
  459                 if (data == KBC_DEVCMD_RESEND) {
  460                         if (cmd->retries++ < 5)
  461                                 /* try again last command */
  462                                 goto restart;
  463                         else {
  464 #ifdef PCKBPORTDEBUG
  465                                 printf("pckbport: cmd failed\n");
  466 #endif
  467                                 cmd->status = EIO;
  468                                 /* dequeue */
  469                         }
  470                 } else {
  471                         if (++cmd->cmdidx < cmd->cmdlen)
  472                                 goto restart;
  473                         if (cmd->responselen)
  474                                 return 1;
  475                         /* else dequeue */
  476                 }
  477         } else if (cmd->responseidx < cmd->responselen) {
  478                 cmd->response[cmd->responseidx++] = data;
  479                 if (cmd->responseidx < cmd->responselen)
  480                         return 1;
  481                 /* else dequeue */
  482         } else
  483                 return 0;
  484 
  485         /* dequeue: */
  486         TAILQ_REMOVE(&q->cmdqueue, cmd, next);
  487         if (cmd->flags & KBC_CMDFLAG_SYNC)
  488                 wakeup(cmd);
  489         else {
  490                 callout_stop(&t->t_cleanup);
  491                 TAILQ_INSERT_TAIL(&q->freequeue, cmd, next);
  492         }
  493         if (!CMD_IN_QUEUE(q))
  494                 return 1;
  495 restart:
  496         pckbport_start(t, slot);
  497         return 1;
  498 }
  499 
  500 /*
  501  * Put command into the device's command queue, return zero or errno.
  502  */
  503 int
  504 pckbport_enqueue_cmd(pckbport_tag_t t, pckbport_slot_t slot, u_char *cmd,
  505     int len, int responselen, int sync, u_char *respbuf)
  506 {
  507         struct pckbport_slotdata *q = t->t_slotdata[slot];
  508         struct pckbport_devcmd *nc;
  509         int s, isactive, res = 0;
  510 
  511         if ((len > 4) || (responselen > 4))
  512                 return EINVAL;
  513         s = spltty();
  514         nc = TAILQ_FIRST(&q->freequeue);
  515         if (nc)
  516                 TAILQ_REMOVE(&q->freequeue, nc, next);
  517         splx(s);
  518         if (!nc)
  519                 return ENOMEM;
  520 
  521         memset(nc, 0, sizeof(*nc));
  522         memcpy(nc->cmd, cmd, len);
  523         nc->cmdlen = len;
  524         nc->responselen = responselen;
  525         nc->flags = (sync ? KBC_CMDFLAG_SYNC : 0);
  526 
  527         s = spltty();
  528 
  529         if (q->polling && sync)
  530                 /*
  531                  * XXX We should poll until the queue is empty.
  532                  * But we don't come here normally, so make
  533                  * it simple and throw away everything.
  534                  */
  535                 pckbport_cleanqueue(q);
  536 
  537         isactive = CMD_IN_QUEUE(q);
  538         TAILQ_INSERT_TAIL(&q->cmdqueue, nc, next);
  539         if (!isactive)
  540                 pckbport_start(t, slot);
  541 
  542         if (q->polling)
  543                 res = (sync ? nc->status : 0);
  544         else if (sync) {
  545                 if ((res = tsleep(nc, 0, "kbccmd", 1*hz))) {
  546                         TAILQ_REMOVE(&q->cmdqueue, nc, next);
  547                         pckbport_cleanup(t);
  548                 } else
  549                         res = nc->status;
  550         } else
  551                 callout_reset(&t->t_cleanup, hz, pckbport_cleanup, t);
  552 
  553         if (sync) {
  554                 if (respbuf)
  555                         memcpy(respbuf, nc->response, responselen);
  556                 TAILQ_INSERT_TAIL(&q->freequeue, nc, next);
  557         }
  558 
  559         splx(s);
  560 
  561         return res;
  562 }
  563 
  564 void
  565 pckbport_set_inputhandler(pckbport_tag_t t, pckbport_slot_t slot,
  566     pckbport_inputfcn func, void *arg, char *name)
  567 {
  568 
  569         if (slot >= PCKBPORT_NSLOTS)
  570                 panic("pckbport_set_inputhandler: bad slot %d", slot);
  571 
  572         t->t_ops->t_intr_establish(t->t_cookie, slot);
  573 
  574         t->t_inputhandler[slot] = func;
  575         t->t_inputarg[slot] = arg;
  576         t->t_subname[slot] = name;
  577 }
  578 
  579 void
  580 pckbportintr(pckbport_tag_t t, pckbport_slot_t slot, int data)
  581 {
  582         struct pckbport_slotdata *q;
  583 
  584         q = t->t_slotdata[slot];
  585 
  586         if (!q) {
  587                 /* XXX do something for live insertion? */
  588                 printf("pckbportintr: no dev for slot %d\n", slot);
  589                 return;
  590         }
  591 
  592         if (CMD_IN_QUEUE(q) && pckbport_cmdresponse(t, slot, data))
  593                 return;
  594 
  595         if (t->t_inputhandler[slot])
  596                 (*t->t_inputhandler[slot])(t->t_inputarg[slot], data);
  597 #ifdef PCKBPORTDEBUG
  598         else
  599                 printf("pckbportintr: slot %d lost %d\n", slot, data);
  600 #endif
  601 }
  602 
  603 int
  604 pckbport_cnattach(void *cookie, struct pckbport_accessops const *ops,
  605     pckbport_slot_t slot)
  606 {
  607         int res = 0;
  608         pckbport_tag_t t = &pckbport_cntag;
  609 
  610         t->t_cookie = cookie;
  611         t->t_ops = ops;
  612 
  613         /* flush */
  614         pckbport_flush(t, slot);
  615 
  616 #if (NPCKBD > 0)
  617         res = pckbd_cnattach(t, slot);
  618 #elif (NPCKBPORT_MACHDEP_CNATTACH > 0)
  619         res = pckbport_machdep_cnattach(t, slot);
  620 #else
  621         res = ENXIO;
  622 #endif /* NPCKBPORT_MACHDEP_CNATTACH > 0 */
  623 
  624         if (res == 0) {
  625                 t->t_slotdata[slot] = &pckbport_cons_slotdata;
  626                 pckbport_init_slotdata(&pckbport_cons_slotdata);
  627         }
  628 
  629         return res;
  630 }

Cache object: 8d85e9426a05f9166e32e8c1828ff365


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.