summaryrefslogtreecommitdiff
path: root/devio/dev.h
blob: de51d7888a23255e1b5a13ba5caa17bc34b953d9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/* A handle on a mach device.

   Copyright (C) 1995 Free Software Foundation, Inc.

   Written by Miles Bader <miles@gnu.ai.mit.edu>

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License as
   published by the Free Software Foundation; either version 2, or (at
   your option) any later version.

   This program is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */

#ifndef __DEV_H__
#define __DEV_H__

#include <mach.h>
#include <device/device.h>

#include "iostate.h"

/* #define FAKE */
#define MSG

#ifdef MSG
#include <stdio.h>
#include <string.h>
#include <unistd.h>
extern FILE *debug;
extern struct mutex debug_lock;
#endif

/* ---------------------------------------------------------------- */

/* Information about a kernel device.  */
struct dev
{
  /* The device port for the kernel device we're doing paging on.  */
  device_t port;
  /* The mach device name which we opened.  */
  char *name;

  /* The total size of DEV.  */
  vm_size_t size;

  /* The block size of DEV.  I/O to DEV must occur in multiples of
     block_size.  */
  int dev_block_size;
  /* The block size in which we will do I/O; this must be a multiple of
     DEV_BLOCK_SIZE.  */
  int block_size;

  /* Various attributes of this device (see below for the DEV_ flag bits).
     This field is constant.  */
  int flags;

  /* Current state of our output stream -- location and the buffer used to do
     buffered i/o.  */
  struct io_state io_state;

  /* The pager we're using to do disk i/o for us.  If NULL, a pager hasn't
     been allocated yet.  Lock the lock in IO_STATE if you want to update
     this field.  */
  struct pager *pager;
  /* The port_bucket for paging ports.  */
  struct port_bucket *pager_port_bucket;

  /* The current owner of the open device.  For terminals, this affects
     controlling terminal behavior (see term_become_ctty).  For all objects
     this affects old-style async IO.  Negative values represent pgrps.  This
     has nothing to do with the owner of a file (as returned by io_stat, and
     as used for various permission checks by filesystems).  An owner of 0
     indicates that there is no owner.  */
  pid_t owner;
};

/* Various bits to be set in the flags field.  */

/* True if this device should be used in `block' mode, with buffering of
   sub-block-size i/o.  */
#define DEV_BUFFERED	0x1
/* True if this device only supports serial i/o (that is, there's only one
   read/write location, which must explicitly be moved to do i/o elsewhere.*/
#define DEV_SERIAL	0x2
/* True if we can change the current i/o location of a serial device.  */
#define DEV_SEEKABLE	0x4
/* True if a device cannot be written on.  */
#define DEV_READONLY	0x8

/* Returns TRUE if any of the flags in BITS are set for DEV.  */
#define dev_is(dev, bits) ((dev)->flags & (bits))

/* Returns true if it's ok to call dev_write on these arguments, without
   first copying BUF to a page-aligned buffer.  */
#define dev_write_valid(dev, buf, len, offs) \
  ((len) <= IO_INBAND_MAX || (buf) % vm_page_size == 0)

/* Returns a pointer to a new device structure in DEV for the kernel device
   NAME, with the given FLAGS.  If BLOCK_SIZE is non-zero, it should be the
   desired block size, and must be a multiple of the device block size.
   If an error occurs, the error code is returned, otherwise 0.  */
error_t dev_open(char *name, int flags, int block_size, struct dev **dev);

/* Free DEV and any resources it consumes.  */
void dev_close(struct dev *dev);

/* Reads AMOUNT bytes from DEV and returns it in BUF and BUF_LEN (using the
   standard mach out-array convention).  *OFFS is incremented to reflect the
   amount read/written.  Both LEN and *OFFS must be multiples of DEV's block
   size.  If an error occurs, the error code is returned, otherwise 0.  */
error_t dev_read(struct dev *dev,
		 vm_address_t *buf, vm_size_t *buf_len, vm_size_t amount,
		 vm_offset_t *offs);

/* Writes AMOUNT bytes from the buffer pointed to by BUF to the device DEV.
   *OFFS is incremented to reflect the amount read/written.  Both AMOUNT and
   *OFFS must be multiples of DEV's block size, and either BUF must be
   page-aligned, or dev_write_valid() must return true for these arguments.
   If an error occurs, the error code is returned, otherwise 0.  */
error_t dev_write(struct dev *dev,
		  vm_address_t buf, vm_size_t amount, vm_offset_t *offs);

/* Returns in MEMOBJ the port for a memory object backed by the storage on
   DEV.  Returns 0 or the error code if an error occurred.  */
error_t dev_get_memory_object(struct dev *dev, memory_object_t *memobj);

/* Try to stop all paging activity on DEV, returning true if we were
   successful.  If NOSYNC is true, then we won't write back any (kernel)
   cached pages to the device.  */
int dev_stop_paging (struct dev *dev, int nosync);

/* Try and write out any pending writes to DEV.  If WAIT is true, will wait
   for any paging activity to cease.  */
error_t dev_sync(struct dev *dev, int wait);

#ifdef MSG
char *brep(vm_address_t buf, vm_size_t len);
#endif

#endif /* !__DEV_H__ */