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/i386at/if_par.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 /*
    2  * Mach Operating System
    3  * Copyright (c) 1993,1991,1990,1989 Carnegie Mellon University
    4  * All Rights Reserved.
    5  * 
    6  * Permission to use, copy, modify and distribute this software and its
    7  * documentation is hereby granted, provided that both the copyright
    8  * notice and this permission notice appear in all copies of the
    9  * software, derivative works or modified versions, and any portions
   10  * thereof, and that both notices appear in supporting documentation.
   11  * 
   12  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   13  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
   14  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   15  * 
   16  * Carnegie Mellon requests users of this software to return to
   17  * 
   18  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   19  *  School of Computer Science
   20  *  Carnegie Mellon University
   21  *  Pittsburgh PA 15213-3890
   22  * 
   23  * any improvements or extensions that they make and grant Carnegie Mellon
   24  * the rights to redistribute these changes.
   25  */
   26 /*
   27  * HISTORY
   28  * $Log:        if_par.c,v $
   29  * Revision 2.6  93/01/24  13:17:30  danner
   30  *      Typo.
   31  *      [92/10/01            rvb]
   32  * 
   33  * Revision 2.5  93/01/14  17:30:49  danner
   34  *      Proper spl typing.
   35  *      [92/11/30            af]
   36  * 
   37  * Revision 2.4  92/03/01  00:40:07  rpd
   38  *      Cleaned up syntactically incorrect ifdefs.
   39  *      [92/02/29            rpd]
   40  * 
   41  * Revision 2.3  92/02/25  15:35:52  elf
   42  *      Do NET_DSTADDR correctly.
   43  *      [92/02/21            rvb]
   44  *      On output side, skip ether header -- they are not put on the wire.
   45  *      And some cleanup
   46  *      [92/02/19            rvb]
   47  *      Add lpr and par devices.  (taken from 2.5)
   48  *      BEING DEBUGGED -- not operational
   49  *      [92/02/13            rvb]
   50  * 
   51  * Revision 2.3  91/07/15  13:42:18  mrt
   52  *      Don't set UNUSED bits in intr_enable.
   53  *      [91/06/27            mg32]
   54  * 
   55  * Revision 2.2  91/04/02  12:08:46  mbj
   56  *      Changed protocol to utilitize LapLink cables.  Incompatible with
   57  *      previous revisions.
   58  *      [91/03/15            mg32]
   59  *      Added more documentation on how we use parallel interface.
   60  *      [90/09/17            mg32]
   61  *      Created 08/05/90.
   62  *      Parallel port network driver.
   63  *      [90/08/14            mg32]
   64  * 
   65  */
   66 
   67 /* 
   68  *      Parallel port network driver v1.1
   69  *      All rights reserved.
   70  */ 
   71 
   72 /*
   73  Subject: parallel network interface
   74 
   75  The printer network driver has the following hardware requirements for the
   76  interconnection cable:
   77 
   78  Connections:
   79  Side1          Side2           Function        Side1    / Side2
   80  Pin 5          Pin 10  Interrupt strobe: send status (w)/send status (r)
   81  Pin 2          Pin 15  Data bits       :       write    / read
   82  Pin 3          Pin 13  Data bits       :       write    / read
   83  Pin 4          Pin 12  Data bits       :       write    / read
   84  Pin 6          Pin 11  Data bits       :       write    / read
   85  Pin 10         Pin 5
   86  Pin 11         Pin 6
   87  Pin 12         Pin 4
   88  Pin 13         Pin 3
   89  Pin 15         Pin 2
   90  Pins 18-25     Pins 18-25 (ground interconnections)
   91 
   92  The cable is "symmetric" in that either side can be plugged into either of the
   93  computers.  
   94 
   95  The hardware requirements are as follows:
   96  Port 0x378 must be writable with the following specifications:
   97         Bit 4 -> pin 6
   98         Bit 3 -> pin 5
   99         Bit 2 -> pin 4
  100         Bit 1 -> pin 3
  101         Bit 0 -> pin 2
  102  Port 0x379 must be readable with the following specifications:
  103         Bit 7 <- pin 11
  104         Bit 6 <- pin 10
  105         Bit 5 <- pin 12
  106         Bit 4 <- pin 13
  107         Bit 3 <- pin 15
  108  Port 0x37a must be readable and writable with the following specifications:
  109         Bit 4 -> interrupt enable
  110  So Port 0x378 connects to  Port 0x379 as
  111         Bit 3 -> pin 5  :  pin 10 -> Bit 6      0x08 -> 0x40
  112 
  113         Bit 4 -> pin 6  :  pin 11 -> Bit 7      0x08<<1 -> ~ 0x80
  114         Bit 2 -> pin 4  :  pin 12 -> Bit 5      0x07 -> 0x38
  115         Bit 1 -> pin 3  :  pin 13 -> Bit 4      0x07 -> 0x38
  116         Bit 0 -> pin 2  :  pin 15 -> Bit 3      0x07 -> 0x38
  117  [note: bit 0 is considered the least significant bit, pins on the connector
  118  are numbered starting with 1, -> represents sending data out on the bus, <-
  119  represents reading data from the bus]
  120 
  121  Pins 1,7,8,9, and 16 are currently unused, and may be allowed to "float".
  122 
  123  The data is sent in 4 bit "nybbles", with the highest 4 bits being sent first.
  124 
  125  To bring up the interface, all that should be required is 
  126         ifconfig par0 <your ip address> <connected machine's ip address> up
  127  and to bring down the interface
  128         ifconfig par0 down
  129  You may get a warning message (such as printer out of paper) once you down
  130  the interface, as the port is monitored for both printer and network activity
  131  depending on whether par0 is up or down, and when you down the interface the
  132  printer driver will then read whatever is on the port (which will be the last
  133  message from the other computer).
  134  */
  135 
  136 #include <par.h>
  137 #if NPAR > 0
  138 
  139 #include        <kern/time_out.h>
  140 #include        <device/device_types.h>
  141 #include        <device/errno.h>
  142 #include        <device/io_req.h>
  143 #include        <device/if_hdr.h>
  144 #include        <device/if_ether.h>
  145 #include        <device/net_status.h>
  146 #include        <device/net_io.h>
  147 
  148 #include <i386/ipl.h>
  149 #include <i386/pio.h>
  150 #include <chips/busses.h>
  151 #include <i386at/if_par.h>
  152 
  153 
  154 int parintr();
  155 int parioctl();
  156 int parattach();
  157 int paroutput();
  158 
  159 int (*oldvect)();
  160 int oldunit;
  161 
  162 extern struct bus_device *lprinfo[];
  163 
  164 int par_watch = 0;
  165 
  166 struct par_softc {
  167         struct ifnet ds_if;
  168         u_char  ds_addr[6];             /* Ethernet hardware address */
  169         u_char  address[6];
  170         char    sc_buf[PARMTU+sizeof(struct ifnet *)];
  171 } par_softc[NPAR];
  172 
  173 void parintoff(unit)
  174 int unit;
  175 {
  176 struct bus_device *lpdev = lprinfo[unit];
  177 
  178         outb(INTR(lpdev->address), 0x07);
  179         par_softc[unit].ds_if.if_flags &= ~IFF_RUNNING;
  180         ivect[lpdev->sysdep1] = oldvect;
  181         iunit[lpdev->sysdep1] = oldunit;
  182 }
  183 
  184 void parinit(unit)
  185 int unit;
  186 {
  187 struct bus_device *lpdev = lprinfo[unit];
  188 
  189         if (ivect[lpdev->sysdep1] != parintr) {
  190                 oldvect = ivect[lpdev->sysdep1];
  191                 oldunit = iunit[lpdev->sysdep1];
  192                 ivect[lpdev->sysdep1] = parintr;
  193                 iunit[lpdev->sysdep1] = unit;
  194         }
  195         outb(INTR(lpdev->address),0x11);
  196         par_softc[unit].ds_if.if_flags |= IFF_RUNNING;
  197         *(struct ifnet **)par_softc[unit].sc_buf = &par_softc[unit].ds_if;
  198 }
  199 
  200 struct ether_header     par_eh;
  201 
  202 int parattach(dev)
  203 struct bus_device *dev;
  204 {
  205         u_char          unit = (u_char)dev->unit;
  206         struct ifnet    *ifp;
  207         struct par_softc*sp;
  208 
  209         if ((unit < 0) || (unit >= NPAR))
  210                 return(0);
  211         printf("\n  par%d: at lpr%d, port = %x, spl = %d, pic = %d. ",
  212                 unit, unit, dev->address, dev->sysdep, dev->sysdep1);
  213 
  214         sp = &par_softc[unit];
  215         ifp = &(sp->ds_if);
  216 
  217         *(sp->ds_addr)      = *(sp->address)     = 0x11;
  218         *(sp->ds_addr + 1)  = *(sp->address + 1) = 0x22;
  219         *(sp->ds_addr + 2)  = *(sp->address + 2) = 0x33;
  220         *(sp->ds_addr + 3)  = *(sp->address + 3) = 0x44;
  221         *(sp->ds_addr + 4)  = *(sp->address + 4) = 0x55;
  222         *(sp->ds_addr + 5)  = *(sp->address + 5) = 0x66;
  223 
  224         par_eh.ether_dhost[5] = par_eh.ether_shost[0] = 0x11;
  225         par_eh.ether_dhost[4] = par_eh.ether_shost[1] = 0x22;
  226         par_eh.ether_dhost[3] = par_eh.ether_shost[2] = 0x33;
  227         par_eh.ether_dhost[2] = par_eh.ether_shost[3] = 0x44;
  228         par_eh.ether_dhost[1] = par_eh.ether_shost[4] = 0x55;
  229         par_eh.ether_dhost[0] = par_eh.ether_shost[5] = 0x66;
  230         par_eh.ether_type = htons(0x0800);
  231 
  232         printf("ethernet id [%x:%x:%x:%x:%x:%x]",
  233                 sp->address[0],sp->address[1],sp->address[2],
  234                 sp->address[3],sp->address[4],sp->address[5]);
  235 
  236         ifp->if_unit = unit;
  237         ifp->if_mtu = ETHERMTU;
  238         ifp->if_flags = IFF_POINTOPOINT;
  239         ifp->if_header_size = sizeof(struct ether_header);
  240         ifp->if_header_format = HDR_ETHERNET;
  241         ifp->if_address_size = 6;
  242         ifp->if_address = (char *)&par_softc[unit].address[0];
  243         if_init_queues(ifp);
  244         return(0);
  245 }
  246 
  247 int parstart(); /* forward */
  248 
  249 /*ARGSUSED*/
  250 paropen(dev, flag)
  251         dev_t   dev;
  252         int     flag;
  253 {
  254         register int    unit = minor(dev);
  255 
  256         if (unit < 0 || unit >= NPAR)
  257             return (ENXIO);
  258 
  259         par_softc[unit].ds_if.if_flags |= IFF_UP;
  260         parinit(unit);
  261         return(0);
  262 }
  263 
  264 paroutput(dev, ior)
  265         dev_t           dev;
  266         io_req_t        ior;
  267 {
  268         register int    unit = minor(dev);
  269 
  270         if (unit < 0 || unit >= NPAR)
  271             return (ENXIO);
  272         return (net_write(&par_softc[unit].ds_if, parstart, ior));
  273 }
  274 
  275 parsetinput(dev, receive_port, priority, filter, filter_count)
  276         dev_t           dev;
  277         mach_port_t     receive_port;
  278         int             priority;
  279         filter_t        filter[];
  280         unsigned int    filter_count;
  281 {
  282         register int unit = minor(dev);
  283 
  284         if (unit < 0 || unit >= NPAR)
  285             return (ENXIO);
  286 
  287         return (net_set_filter(&par_softc[unit].ds_if,
  288                         receive_port, priority,
  289                         filter, filter_count));
  290 }
  291 
  292 int parstart(unit)
  293 {
  294         struct ifnet    *ifp = &(par_softc[unit].ds_if);
  295         u_short         addr = lprinfo[unit]->address;
  296         struct sockaddr *dst;
  297         int             len, i;
  298         spl_t           s;
  299         u_char          *mcp, c;
  300         io_req_t        m;
  301 
  302         if (!(ifp->if_flags & IFF_RUNNING)) {
  303 #ifdef  WHY
  304                 m_free(m);
  305                 parintoff(unit);
  306                 return(ENETDOWN);
  307 #else   WHY
  308                 parintoff(unit);
  309                 return(-1);
  310 #endif  WHY
  311         }
  312         s = SPLNET();
  313 
  314         IF_DEQUEUE(&ifp->if_snd, m);
  315         if (m == 0) {
  316                 splx(s);
  317                 return 0;
  318         }
  319         len = m->io_count;
  320         if (par_watch)
  321                 printf("O%d\n",len);
  322         len -= 14 /* XXX */;
  323         mcp = (u_char *)m->io_data + 14 /* XXX */;
  324         while (len--) {
  325                 c=*mcp++;
  326                 outb(OUTPUT(addr),((c&0x80)>>3) | ((c&0x70)>>4) | 0x08);
  327                 i=MAXSPIN;
  328                 while (!(inb(INPUT(addr))&0x40) && --i);
  329                 outb(OUTPUT(addr),((c&0x08)<<1) | (c&0x07));
  330                 i=MAXSPIN;
  331                 while ((inb(INPUT(addr))&0x40) && --i);
  332         }
  333         outb(OUTPUT(addr),(((c&0x08)<<1) | (c&0x07))^0x17);
  334         iodone(m);
  335         splx(s);
  336         return (0);
  337 }
  338 
  339 /*ARGSUSED*/
  340 pargetstat(dev, flavor, status, count)
  341         dev_t           dev;
  342         int             flavor;
  343         dev_status_t    status;         /* pointer to OUT array */
  344         unsigned int    *count;         /* out */
  345 {
  346         register int    unit = minor(dev);
  347 
  348         if (unit < 0 || unit >= NPAR)
  349             return (ENXIO);
  350 
  351 
  352         switch (flavor) {
  353             case NET_DSTADDR:
  354                 return (D_SUCCESS);
  355                 break;
  356         }
  357 
  358         return (net_getstat(&par_softc[unit].ds_if,
  359                             flavor,
  360                             status,
  361                             count));
  362 }
  363 
  364 parsetstat(dev, flavor, status, count)
  365         dev_t           dev;
  366         int             flavor;
  367         dev_status_t    status;
  368         unsigned int    count;
  369 {
  370         register int    unit = minor(dev);
  371         register struct par_softc *sp;
  372 
  373         if (unit < 0 || unit >= NPAR)
  374             return (ENXIO);
  375 
  376         sp = &par_softc[unit];
  377 
  378         switch (flavor) {
  379             case NET_STATUS:
  380             {
  381                 /*
  382                  * All we can change are flags, and not many of those.
  383                  */
  384                 register struct net_status *ns = (struct net_status *)status;
  385                 int     mode = 0;
  386 
  387                 if (count < NET_STATUS_COUNT)
  388                     return (D_INVALID_SIZE);
  389 
  390 #if     0
  391                 /* ha ha ha */
  392                 if (ns->flags & IFF_ALLMULTI)
  393                     mode |= MOD_ENAL;
  394                 if (ns->flags & IFF_PROMISC)
  395                     mode |= MOD_PROM;
  396                 /*
  397                  * Force a complete reset if the receive mode changes
  398                  * so that these take effect immediately.
  399                  */
  400                 if (sp->mode != mode) {
  401                     sp->mode = mode;
  402                     if (sp->flags & DSF_RUNNING) {
  403                         sp->flags &= ~(DSF_LOCK | DSF_RUNNING);
  404                         parinit(unit);
  405                     }
  406                 }
  407 #endif
  408                 break;
  409             }
  410             case NET_ADDRESS:
  411             {
  412                 register union ether_cvt {
  413                     char        addr[6];
  414                     int         lwd[2];
  415                 } *ec = (union ether_cvt *)status;
  416 
  417                 if (count < sizeof(*ec)/sizeof(int))
  418                     return (D_INVALID_SIZE);
  419 
  420                 ec->lwd[0] = ntohl(ec->lwd[0]);
  421                 ec->lwd[1] = ntohl(ec->lwd[1]);
  422 /*              at3c501seteh(sp->base, ec->addr);*/
  423                 break;
  424             }
  425 
  426             default:
  427                 return (D_INVALID_OPERATION);
  428         }
  429         return (D_SUCCESS);
  430 }
  431 
  432 int parintr(unit)
  433 int unit;
  434 {
  435         register struct par_softc *sp = &par_softc[unit];
  436         u_short         addr = lprinfo[unit]->address;
  437         char            *trav = sp->sc_buf;
  438         short           len = 0;
  439         u_char          c, c2;
  440         int             i;
  441         ipc_kmsg_t              new_kmsg;
  442         struct ether_header     *ehp;
  443         struct packet_header    *pkt;
  444         struct ifnet *ifp = &(sp->ds_if);
  445 
  446         do {
  447                 c2=inb(INPUT(addr));
  448                 outb(OUTPUT(addr),0x08);
  449                 i=MAXSPIN;
  450                 while(((c=inb(INPUT(addr)))&0x40) && --i);
  451 
  452                 c = inb(INPUT(addr));
  453                 outb(OUTPUT(addr),0x00);
  454                 if (!i)
  455                         break;
  456 
  457                 if (++len > ETHERMTU) {
  458                         trav = sp->sc_buf;
  459                         len = 0;
  460                         continue;
  461                 }
  462                 *trav++ = ((~c2)&0x80) | ((c2&0x38)<<1) | (((~c)&0x80)>>4) | ((c&0x38)>>3);
  463                 i=MAXSPIN;
  464                 while (!((c2=inb(INPUT(addr)))&0x40) && --i)
  465                         if (((c2^0xb8)&0xf8) == (c&0xf8))
  466                 goto end;
  467         } while (i);
  468 end:
  469         if (len < 20)           /* line noise ? */
  470                 return;
  471         if (par_watch)
  472                 printf("I%d\n",len);
  473 
  474         new_kmsg = net_kmsg_get();
  475         if (new_kmsg == IKM_NULL) {
  476                 /*
  477                  * Drop the packet.
  478                 */
  479                 sp->ds_if.if_rcvdrops++;    
  480                 return;
  481         }
  482         ehp = (struct ether_header *) (&net_kmsg(new_kmsg)->header[0]);
  483         pkt = (struct packet_header *) (&net_kmsg(new_kmsg)->packet[0]);
  484         *ehp = par_eh;
  485 
  486         bcopy (sp->sc_buf, (char *) (pkt + 1), len);
  487 
  488         pkt->type = ehp->ether_type;
  489         pkt->length = len + sizeof(struct packet_header);
  490         /*
  491          * Hand the packet to the network module.
  492          */
  493         net_packet(ifp, new_kmsg, pkt->length,
  494                    ethernet_priority(new_kmsg));
  495         return(0);
  496 }
  497 #endif

Cache object: a3c12a14774edbd170a0e24436f0a758


[ 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.