11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* $Id: mntfunc.c,v 1.19.6.4 2005/01/31 12:22:20 armin Exp $
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Driver for Eicon DIVA Server ISDN cards.
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Maint module
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright 2000-2003 by Armin Schindler (mac@melware.de)
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright 2000-2003 Cytronics & Melware (info@melware.de)
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This software may be used and distributed according to the terms
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * of the GNU General Public License, incorporated herein by reference.
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "platform.h"
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "di_defs.h"
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "divasync.h"
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "debug_if.h"
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern char *DRIVERRELEASE_MNT;
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DBG_MINIMUM  (DL_LOG + DL_FTL + DL_ERR)
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DBG_DEFAULT  (DBG_MINIMUM + DL_XLOG + DL_REG)
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void DIVA_DIDD_Read(void *, int);
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic dword notify_handle;
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DESCRIPTOR DAdapter;
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DESCRIPTOR MAdapter;
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DESCRIPTOR MaintDescriptor =
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    { IDI_DIMAINT, 0, 0, (IDI_CALL) diva_maint_prtComp };
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern int diva_os_copy_to_user(void *os_handle, void __user *dst,
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				const void *src, int length);
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern int diva_os_copy_from_user(void *os_handle, void *dst,
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  const void __user *src, int length);
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void no_printf(unsigned char *x, ...)
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* dummy debug function */
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "debuglib.c"
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  DIDD callback function
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void *didd_callback(void *context, DESCRIPTOR * adapter,
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   int removal)
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (adapter->type == IDI_DADAPTER) {
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DBG_ERR(("cb: Change in DAdapter ? Oops ?."));
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else if (adapter->type == IDI_DIMAINT) {
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (removal) {
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			DbgDeregister();
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			memset(&MAdapter, 0, sizeof(MAdapter));
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dprintf = no_printf;
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			memcpy(&MAdapter, adapter, sizeof(MAdapter));
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dprintf = (DIVA_DI_PRINTF) MAdapter.request;
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			DbgRegister("MAINT", DRIVERRELEASE_MNT, DBG_DEFAULT);
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else if ((adapter->type > 0) && (adapter->type < 16)) {
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (removal) {
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			diva_mnt_remove_xdi_adapter(adapter);
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			diva_mnt_add_xdi_adapter(adapter);
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (NULL);
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * connect to didd
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int DIVA_INIT_FUNCTION connect_didd(void)
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int x = 0;
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int dadapter = 0;
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	IDI_SYNC_REQ req;
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DESCRIPTOR DIDD_Table[MAX_DESCRIPTORS];
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DIVA_DIDD_Read(DIDD_Table, sizeof(DIDD_Table));
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (x = 0; x < MAX_DESCRIPTORS; x++) {
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (DIDD_Table[x].type == IDI_DADAPTER) {	/* DADAPTER found */
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dadapter = 1;
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			memcpy(&DAdapter, &DIDD_Table[x], sizeof(DAdapter));
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			req.didd_notify.e.Req = 0;
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			req.didd_notify.e.Rc =
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    IDI_SYNC_REQ_DIDD_REGISTER_ADAPTER_NOTIFY;
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			req.didd_notify.info.callback = (void *)didd_callback;
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			req.didd_notify.info.context = NULL;
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			DAdapter.request((ENTITY *) & req);
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (req.didd_notify.e.Rc != 0xff)
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return (0);
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			notify_handle = req.didd_notify.info.handle;
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Register MAINT (me) */
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			req.didd_add_adapter.e.Req = 0;
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			req.didd_add_adapter.e.Rc =
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    IDI_SYNC_REQ_DIDD_ADD_ADAPTER;
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			req.didd_add_adapter.info.descriptor =
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    (void *) &MaintDescriptor;
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			DAdapter.request((ENTITY *) & req);
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (req.didd_add_adapter.e.Rc != 0xff)
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return (0);
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else if ((DIDD_Table[x].type > 0)
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   && (DIDD_Table[x].type < 16)) {
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			diva_mnt_add_xdi_adapter(&DIDD_Table[x]);
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (dadapter);
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * disconnect from didd
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void DIVA_EXIT_FUNCTION disconnect_didd(void)
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	IDI_SYNC_REQ req;
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	req.didd_notify.e.Req = 0;
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	req.didd_notify.e.Rc = IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER_NOTIFY;
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	req.didd_notify.info.handle = notify_handle;
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DAdapter.request((ENTITY *) & req);
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	req.didd_remove_adapter.e.Req = 0;
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	req.didd_remove_adapter.e.Rc = IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER;
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	req.didd_remove_adapter.info.p_request =
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    (IDI_CALL) MaintDescriptor.request;
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DAdapter.request((ENTITY *) & req);
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * read/write maint
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint maint_read_write(void __user *buf, int count)
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	byte data[128];
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dword cmd, id, mask;
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret = 0;
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (count < (3 * sizeof(dword)))
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (-EFAULT);
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (diva_os_copy_from_user(NULL, (void *) &data[0],
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   buf, 3 * sizeof(dword))) {
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (-EFAULT);
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cmd = *(dword *) & data[0];	/* command */
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	id = *(dword *) & data[4];	/* driver id */
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mask = *(dword *) & data[8];	/* mask or size */
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (cmd) {
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case DITRACE_CMD_GET_DRIVER_INFO:
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((ret = diva_get_driver_info(id, data, sizeof(data))) > 0) {
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if ((count < ret) || diva_os_copy_to_user
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    (NULL, buf, (void *) &data[0], ret))
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ret = -EFAULT;
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ret = -EINVAL;
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case DITRACE_READ_DRIVER_DBG_MASK:
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((ret = diva_get_driver_dbg_mask(id, (byte *) data)) > 0) {
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if ((count < ret) || diva_os_copy_to_user
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    (NULL, buf, (void *) &data[0], ret))
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ret = -EFAULT;
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ret = -ENODEV;
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case DITRACE_WRITE_DRIVER_DBG_MASK:
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((ret = diva_set_driver_dbg_mask(id, mask)) <= 0) {
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ret = -ENODEV;
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    /*
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds       Filter commands will ignore the ID due to fact that filtering affects
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds       the B- channel and Audio Tap trace levels only. Also MAINT driver will
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds       select the right trace ID by itself
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds       */
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case DITRACE_WRITE_SELECTIVE_TRACE_FILTER:
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!mask) {
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ret = diva_set_trace_filter (1, "*");
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else if (mask < sizeof(data)) {
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (diva_os_copy_from_user(NULL, data, (char __user *)buf+12, mask)) {
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ret = -EFAULT;
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else {
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ret = diva_set_trace_filter ((int)mask, data);
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ret = -EINVAL;
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case DITRACE_READ_SELECTIVE_TRACE_FILTER:
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((ret = diva_get_trace_filter (sizeof(data), data)) > 0) {
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (diva_os_copy_to_user (NULL, buf, data, ret))
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ret = -EFAULT;
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ret = -ENODEV;
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case DITRACE_READ_TRACE_ENTRY:{
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			diva_os_spin_lock_magic_t old_irql;
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			word size;
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			diva_dbg_entry_head_t *pmsg;
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			byte *pbuf;
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!(pbuf = diva_os_malloc(0, mask))) {
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return (-ENOMEM);
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			for(;;) {
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (!(pmsg =
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				    diva_maint_get_message(&size, &old_irql))) {
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					break;
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (size > mask) {
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					diva_maint_ack_message(0, &old_irql);
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					ret = -EINVAL;
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					break;
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ret = size;
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				memcpy(pbuf, pmsg, size);
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				diva_maint_ack_message(1, &old_irql);
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if ((count < size) ||
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     diva_os_copy_to_user (NULL, buf, (void *) pbuf, size))
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							ret = -EFAULT;
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			diva_os_free(0, pbuf);
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case DITRACE_READ_TRACE_ENTRYS:{
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			diva_os_spin_lock_magic_t old_irql;
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			word size;
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			diva_dbg_entry_head_t *pmsg;
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			byte *pbuf = NULL;
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			int written = 0;
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (mask < 4096) {
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ret = -EINVAL;
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!(pbuf = diva_os_malloc(0, mask))) {
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return (-ENOMEM);
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			for (;;) {
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (!(pmsg =
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     diva_maint_get_message(&size, &old_irql))) {
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					break;
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if ((size + 8) > mask) {
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					diva_maint_ack_message(0, &old_irql);
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					break;
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/*
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   Write entry length
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 */
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				pbuf[written++] = (byte) size;
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				pbuf[written++] = (byte) (size >> 8);
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				pbuf[written++] = 0;
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				pbuf[written++] = 0;
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/*
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   Write message
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 */
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				memcpy(&pbuf[written], pmsg, size);
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				diva_maint_ack_message(1, &old_irql);
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				written += size;
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				mask -= (size + 4);
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pbuf[written++] = 0;
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pbuf[written++] = 0;
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pbuf[written++] = 0;
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pbuf[written++] = 0;
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if ((count < written) || diva_os_copy_to_user(NULL, buf, (void *) pbuf, written)) {
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ret = -EFAULT;
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else {
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ret = written;
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			diva_os_free(0, pbuf);
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = -EINVAL;
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (ret);
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  init
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint DIVA_INIT_FUNCTION mntfunc_init(int *buffer_length, void **buffer,
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				    unsigned long diva_dbg_mem)
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (*buffer_length < 64) {
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*buffer_length = 64;
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (*buffer_length > 512) {
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*buffer_length = 512;
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*buffer_length *= 1024;
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (diva_dbg_mem) {
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*buffer = (void *) diva_dbg_mem;
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		while ((*buffer_length >= (64 * 1024))
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       &&
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       (!(*buffer = diva_os_malloc (0, *buffer_length)))) {
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			*buffer_length -= 1024;
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!*buffer) {
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			DBG_ERR(("init: Can not alloc trace buffer"));
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return (0);
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (diva_maint_init(*buffer, *buffer_length, (diva_dbg_mem == 0))) {
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!diva_dbg_mem) {
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			diva_os_free (0, *buffer);
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DBG_ERR(("init: maint init failed"));
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (0);
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!connect_didd()) {
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DBG_ERR(("init: failed to connect to DIDD."));
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		diva_maint_finit();
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!diva_dbg_mem) {
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			diva_os_free (0, *buffer);
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (0);
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (1);
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  exit
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid DIVA_EXIT_FUNCTION mntfunc_finit(void)
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void *buffer;
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i = 100;
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DbgDeregister();
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (diva_mnt_shutdown_xdi_adapters() && i--) {
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		diva_os_sleep(10);
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	disconnect_didd();
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((buffer = diva_maint_finit())) {
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		diva_os_free (0, buffer);
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(&MAdapter, 0, sizeof(MAdapter));
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dprintf = no_printf;
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
371