/*
 * nasd_ioctl.c
 *
 * ioctl operations for EDRFS.
 *
 * Author: Nat Lanza
 */
/*
 * Copyright (c) of Carnegie Mellon University, 1999.
 *
 * Permission to reproduce, use, and prepare derivative works of
 * this software for internal use is granted provided the copyright
 * and "No Warranty" statements are included with all reproductions
 * and derivative works. This software may also be redistributed
 * without charge provided that the copyright and "No Warranty"
 * statements are included in all redistributions.
 *
 * NO WARRANTY. THIS SOFTWARE IS FURNISHED ON AN "AS IS" BASIS.
 * CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER
 * EXPRESSED OR IMPLIED AS TO THE MATTER INCLUDING, BUT NOT LIMITED
 * TO: WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY
 * OF RESULTS OR RESULTS OBTAINED FROM USE OF THIS SOFTWARE. CARNEGIE
 * MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT
 * TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.
 */

#include <nasd/nasd_options.h>
#include <nasd/nasd_sys.h>
#include <nasd/nasd_types.h>
#include <nasd/nasd_mem.h>
#include <nasd/linux/nasd_edrfs_client_linux.h>
#include <nasd/linux/nasd_edrfs_client_linux_ioctl.h>
#include <nasd/nasd_edrfs_types_marshall.h>

#include <linux/kernel.h>

#include <asm/system.h>
#include <asm/uaccess.h>

int nasd_edrfs_ioctl(struct inode  *inode,
		     struct file   *filp,
		     unsigned int   cmd,
		     unsigned long  arg) {
  int err = 0, err2 = 0, size;
  nasd_status_t rc = NASD_SUCCESS;
  void *karg;

  size = _IOC_SIZE(cmd);
  err = nasd_sys_wire_buf((void *) arg, size, &karg, NASD_WIRE_DIR_ALL);
  if (err) { return -err; }
  
  switch (cmd) {
    case NASD_EDRFS_GET_NASDID: {
      nasd_edrfs_file_ident_t *fid = (nasd_edrfs_file_ident_t *) karg;
      nasd_edrfs_inode_info_t *inode_info = NASD_EDRFS_INODE_INFO(inode);
      nasd_edrfs_sb_info_t    *sb_info = NASD_EDRFS_SUPER_SBINFO(inode->i_sb);
      nasd_edrfs_credential_t  in_credential;
      
      in_credential.uid = current->uid;
      in_credential.gid = current->gid;

      rc = nasd_edrfs_find_or_get_cookie(&sb_info->handles,
					 &inode_info->ident,
					 &in_credential,
					 &(fid->cookie));
      if (rc != NASD_SUCCESS) {
	err = nasd_edrfs_convert_error(rc, 0);
	goto out;
      }

      fid->nasd_identifier = inode_info->ident.nasd_identifier;
      fid->partnum         = inode_info->ident.partnum;
      fid->drive_address   = sb_info->handles.drive_address;

      break;
    }
    case NASD_EDRFS_GET_THRESHOLD:
      /* XXX haven't decided how to handle this yet */
      break;
    case NASD_EDRFS_SET_THRESHOLD:
      /* XXX haven't decided how to handle this yet */
      break;
    case NASD_EDRFS_USER_CONTROL:
      /* XXX we don't actually do anything here 'cause
	     we don't cache yet XXX */
      break;
    default:
      err = -EINVAL;
  }

 out:

  err2 = nasd_sys_unwire_buf((void *) arg, size, karg, NASD_WIRE_DIR_ALL);
  
  if (err)  { return -err;  }
  if (err2) { return -err2; }
  return 0;
}
