11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        comm.c    (c) 1997-8  Grant R. Guenther <grant@torque.net>
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                              Under the terms of the GNU General Public License.
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	comm.c is a low-level protocol driver for some older models
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	of the DataStor "Commuter" parallel to IDE adapter.  Some of
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	the parallel port devices marketed by Arista currently
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	use this adapter.
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Changes:
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	1.01	GRG 1998.05.05  init_proto, release_proto
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define COMM_VERSION      "1.01"
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h>
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h>
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/wait.h>
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h>
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "paride.h"
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* mode codes:  0  nybble reads, 8-bit writes
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                1  8-bit reads and writes
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                2  8-bit EPP mode
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define j44(a,b)	(((a>>3)&0x0f)|((b<<1)&0xf0))
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define P1	w2(5);w2(0xd);w2(0xd);w2(5);w2(4);
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define P2	w2(5);w2(7);w2(7);w2(5);w2(4);
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* cont = 0 - access the IDE register file
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   cont = 1 - access the IDE command set
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int  cont_map[2] = { 0x08, 0x10 };
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int comm_read_regr( PIA *pi, int cont, int regr )
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{       int     l, h, r;
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r = regr + cont_map[cont];
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        switch (pi->mode)  {
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        case 0: w0(r); P1; w0(0);
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        	w2(6); l = r1(); w0(0x80); h = r1(); w2(4);
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                return j44(l,h);
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        case 1: w0(r+0x20); P1;
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        	w0(0); w2(0x26); h = r0(); w2(4);
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                return h;
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 2:
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 3:
6310e705f83c3e796893a70fb872895ba604901166Takashi Iwai        case 4: w3(r+0x20); (void)r1();
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        	w2(0x24); h = r4(); w2(4);
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                return h;
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        return -1;
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void comm_write_regr( PIA *pi, int cont, int regr, int val )
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{       int  r;
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r = regr + cont_map[cont];
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        switch (pi->mode)  {
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        case 0:
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        case 1: w0(r); P1; w0(val); P2;
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 2:
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 3:
8510e705f83c3e796893a70fb872895ba604901166Takashi Iwai        case 4: w3(r); (void)r1(); w4(val);
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                break;
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void comm_connect ( PIA *pi  )
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{       pi->saved_r0 = r0();
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        pi->saved_r2 = r2();
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        w2(4); w0(0xff); w2(6);
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        w2(4); w0(0xaa); w2(6);
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        w2(4); w0(0x00); w2(6);
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        w2(4); w0(0x87); w2(6);
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        w2(4); w0(0xe0); w2(0xc); w2(0xc); w2(4);
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void comm_disconnect ( PIA *pi )
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{       w2(0); w2(0); w2(0); w2(4);
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	w0(pi->saved_r0);
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        w2(pi->saved_r2);
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void comm_read_block( PIA *pi, char * buf, int count )
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{       int     i, l, h;
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        switch (pi->mode) {
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        case 0: w0(0x48); P1;
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                for(i=0;i<count;i++) {
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        w0(0); w2(6); l = r1();
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        w0(0x80); h = r1(); w2(4);
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        buf[i] = j44(l,h);
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                break;
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        case 1: w0(0x68); P1; w0(0);
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                for(i=0;i<count;i++) {
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        w2(0x26); buf[i] = r0(); w2(0x24);
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		w2(4);
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12910e705f83c3e796893a70fb872895ba604901166Takashi Iwai	case 2: w3(0x68); (void)r1(); w2(0x24);
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i=0;i<count;i++) buf[i] = r4();
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		w2(4);
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13410e705f83c3e796893a70fb872895ba604901166Takashi Iwai        case 3: w3(0x68); (void)r1(); w2(0x24);
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                for (i=0;i<count/2;i++) ((u16 *)buf)[i] = r4w();
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                w2(4);
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                break;
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13910e705f83c3e796893a70fb872895ba604901166Takashi Iwai        case 4: w3(0x68); (void)r1(); w2(0x24);
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                for (i=0;i<count/4;i++) ((u32 *)buf)[i] = r4l();
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                w2(4);
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                break;
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* NB: Watch out for the byte swapped writes ! */
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void comm_write_block( PIA *pi, char * buf, int count )
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{       int	k;
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        switch (pi->mode) {
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        case 0:
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        case 1: w0(0x68); P1;
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        	for (k=0;k<count;k++) {
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        w2(5); w0(buf[k^1]); w2(7);
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                w2(5); w2(4);
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                break;
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16310e705f83c3e796893a70fb872895ba604901166Takashi Iwai        case 2: w3(0x48); (void)r1();
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                for (k=0;k<count;k++) w4(buf[k^1]);
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                break;
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16710e705f83c3e796893a70fb872895ba604901166Takashi Iwai        case 3: w3(0x48); (void)r1();
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                for (k=0;k<count/2;k++) w4w(pi_swab16(buf,k));
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                break;
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17110e705f83c3e796893a70fb872895ba604901166Takashi Iwai        case 4: w3(0x48); (void)r1();
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                for (k=0;k<count/4;k++) w4l(pi_swab32(buf,k));
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                break;
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void comm_log_adapter( PIA *pi, char * scratch, int verbose )
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{       char    *mode_string[5] = {"4-bit","8-bit","EPP-8","EPP-16","EPP-32"};
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        printk("%s: comm %s, DataStor Commuter at 0x%x, ",
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                pi->device,COMM_VERSION,pi->port);
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        printk("mode %d (%s), delay %d\n",pi->mode,
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mode_string[pi->mode],pi->delay);
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pi_protocol comm = {
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.owner		= THIS_MODULE,
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name		= "comm",
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.max_mode	= 5,
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.epp_first	= 2,
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.default_delay	= 1,
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.max_units	= 1,
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.write_regr	= comm_write_regr,
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.read_regr	= comm_read_regr,
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.write_block	= comm_write_block,
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.read_block	= comm_read_block,
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.connect	= comm_connect,
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.disconnect	= comm_disconnect,
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.log_adapter	= comm_log_adapter,
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init comm_init(void)
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
208b4178ab58aa81f4ed3c75c48940682fe3b45d880Alexey Dobriyan	return paride_register(&comm);
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit comm_exit(void)
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
213f4330002d11f032559954cbff68a5cad95b6d27fAlexey Dobriyan	paride_unregister(&comm);
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(comm_init)
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(comm_exit)
219