summaryrefslogtreecommitdiff
path: root/linux/dev/glue
diff options
context:
space:
mode:
Diffstat (limited to 'linux/dev/glue')
-rw-r--r--linux/dev/glue/block.c88
-rw-r--r--linux/dev/glue/glue.h44
-rw-r--r--linux/dev/glue/kmem.c18
-rw-r--r--linux/dev/glue/misc.c37
-rw-r--r--linux/dev/glue/net.c15
5 files changed, 132 insertions, 70 deletions
diff --git a/linux/dev/glue/block.c b/linux/dev/glue/block.c
index b920fb62..8c41f088 100644
--- a/linux/dev/glue/block.c
+++ b/linux/dev/glue/block.c
@@ -49,6 +49,8 @@
#include <mach/vm_param.h>
#include <mach/notify.h>
+#include <kern/kalloc.h>
+
#include <ipc/ipc_port.h>
#include <ipc/ipc_space.h>
@@ -61,6 +63,7 @@
#include <device/disk_status.h>
#include <device/device_reply.user.h>
#include <device/device_emul.h>
+#include <device/ds_routines.h>
/* TODO. This should be fixed to not be i386 specific. */
#include <i386at/disk.h>
@@ -78,9 +81,7 @@
#include <linux/hdreg.h>
#include <asm/io.h>
-extern int linux_auto_config;
-extern int linux_intr_pri;
-extern int linux_to_mach_error (int);
+#include <linux/dev/glue/glue.h>
/* This task queue is not used in Mach: just for fixing undefined symbols. */
DECLARE_TASK_QUEUE (tq_disk);
@@ -193,9 +194,6 @@ int read_ahead[MAX_BLKDEV] = {0, };
This is unused in Mach. It is here to make drivers compile. */
struct wait_queue *wait_for_request = NULL;
-/* Map for allocating device memory. */
-extern vm_map_t device_io_map;
-
/* Initialize block drivers. */
int
blk_dev_init ()
@@ -230,19 +228,17 @@ int
register_blkdev (unsigned major, const char *name,
struct file_operations *fops)
{
- int err = 0;
-
if (major == 0)
{
for (major = MAX_BLKDEV - 1; major > 0; major--)
if (blkdevs[major].fops == NULL)
goto out;
- return -LINUX_EBUSY;
+ return -EBUSY;
}
if (major >= MAX_BLKDEV)
- return -LINUX_EINVAL;
+ return -EINVAL;
if (blkdevs[major].fops && blkdevs[major].fops != fops)
- return -LINUX_EBUSY;
+ return -EBUSY;
out:
blkdevs[major].name = name;
@@ -260,12 +256,10 @@ out:
int
unregister_blkdev (unsigned major, const char *name)
{
- int err;
-
if (major >= MAX_BLKDEV)
- return -LINUX_EINVAL;
+ return -EINVAL;
if (! blkdevs[major].fops || strcmp (blkdevs[major].name, name))
- return -LINUX_EINVAL;
+ return -EINVAL;
blkdevs[major].fops = NULL;
if (blkdevs[major].labels)
{
@@ -280,8 +274,6 @@ unregister_blkdev (unsigned major, const char *name)
void
set_blocksize (kdev_t dev, int size)
{
- extern int *blksize_size[];
-
if (! blksize_size[MAJOR (dev)])
return;
@@ -315,7 +307,7 @@ alloc_buffer (int size)
d = current_thread ()->pcb->data;
assert (d);
queue_enter (&d->pages, m, vm_page_t, pageq);
- return (void *) m->phys_addr;
+ return (void *) phystokv(m->phys_addr);
}
return (void *) __get_free_pages (GFP_KERNEL, 0, ~0UL);
}
@@ -324,7 +316,6 @@ alloc_buffer (int size)
static void
free_buffer (void *p, int size)
{
- int i;
struct temp_data *d;
vm_page_t m;
@@ -336,7 +327,7 @@ free_buffer (void *p, int size)
assert (d);
queue_iterate (&d->pages, m, vm_page_t, pageq)
{
- if (m->phys_addr == (vm_offset_t) p)
+ if (phystokv(m->phys_addr) == (vm_offset_t) p)
{
queue_remove (&d->pages, m, vm_page_t, pageq);
VM_PAGE_FREE (m);
@@ -388,7 +379,6 @@ __brelse (struct buffer_head *bh)
struct buffer_head *
bread (kdev_t dev, int block, int size)
{
- int err;
struct buffer_head *bh;
bh = getblk (dev, block, size);
@@ -537,7 +527,7 @@ rdwr_partial (int rw, kdev_t dev, loff_t *off,
}
bh->b_data = alloc_buffer (bh->b_size);
if (! bh->b_data)
- return -LINUX_ENOMEM;
+ return -ENOMEM;
ll_rw_block (READ, 1, &bh);
wait_on_buffer (bh);
if (buffer_uptodate (bh))
@@ -556,7 +546,7 @@ rdwr_partial (int rw, kdev_t dev, loff_t *off,
wait_on_buffer (bh);
if (! buffer_uptodate (bh))
{
- err = -LINUX_EIO;
+ err = -EIO;
goto out;
}
}
@@ -565,7 +555,7 @@ rdwr_partial (int rw, kdev_t dev, loff_t *off,
*off += c;
}
else
- err = -LINUX_EIO;
+ err = -EIO;
out:
free_buffer (bh->b_data, bh->b_size);
return err;
@@ -610,15 +600,15 @@ rdwr_full (int rw, kdev_t dev, loff_t *off, char **buf, int *resid, int bshift)
if (cc > ((nbuf - nb) << bshift))
cc = (nbuf - nb) << bshift;
if (! test_bit (BH_Bounce, &bh->b_state))
- bh->b_data = (char *) pmap_extract (vm_map_pmap (device_io_map),
+ bh->b_data = (char *) phystokv(pmap_extract (vm_map_pmap (device_io_map),
(((vm_offset_t) *buf)
- + (nb << bshift)));
+ + (nb << bshift))));
else
{
bh->b_data = alloc_buffer (cc);
if (! bh->b_data)
{
- err = -LINUX_ENOMEM;
+ err = -ENOMEM;
break;
}
if (rw == WRITE)
@@ -642,7 +632,7 @@ rdwr_full (int rw, kdev_t dev, loff_t *off, char **buf, int *resid, int bshift)
&& rw == READ && test_bit (BH_Bounce, &bh->b_state))
memcpy (*buf + cc, bh->b_data, bh->b_size);
else if (! err && ! buffer_uptodate (bh))
- err = -LINUX_EIO;
+ err = -EIO;
if (test_bit (BH_Bounce, &bh->b_state))
free_buffer (bh->b_data, bh->b_size);
}
@@ -789,6 +779,7 @@ static struct block_data *open_list;
extern struct device_emulation_ops linux_block_emulation_ops;
static io_return_t device_close (void *);
+static io_return_t device_close_forced (void *, int);
/* Return a send right for block device BD. */
static ipc_port_t
@@ -922,7 +913,7 @@ static kern_return_t
init_partition (struct name_map *np, kdev_t *dev,
struct device_struct *ds, int slice, int *part)
{
- int err, i, j;
+ int i, j;
struct disklabel *lp;
struct gendisk *gd = ds->gd;
struct partition *p;
@@ -947,7 +938,7 @@ init_partition (struct name_map *np, kdev_t *dev,
if (gd->part[MINOR (d->inode.i_rdev)].nr_sects <= 0
|| gd->part[MINOR (d->inode.i_rdev)].start_sect < 0)
continue;
- linux_intr_pri = SPL5;
+ linux_intr_pri = SPL6;
d->file.f_flags = 0;
d->file.f_mode = O_RDONLY;
if (ds->fops->open && (*ds->fops->open) (&d->inode, &d->file))
@@ -1093,7 +1084,7 @@ device_open (ipc_port_t reply_port, mach_msg_type_name_t reply_port_type,
if (ds->fops->open)
{
td.inode.i_rdev = dev;
- linux_intr_pri = SPL5;
+ linux_intr_pri = SPL6;
err = (*ds->fops->open) (&td.inode, &td.file);
if (err)
{
@@ -1164,6 +1155,7 @@ out:
{
ipc_kobject_set (bd->port, IKO_NULL, IKOT_NONE);
ipc_port_dealloc_kernel (bd->port);
+ *devp = IP_NULL;
}
kfree ((vm_offset_t) bd, sizeof (struct block_data));
bd = NULL;
@@ -1174,18 +1166,16 @@ out:
bd->open_count = 1;
bd->next = open_list;
open_list = bd;
+ *devp = &bd -> device;
}
- if (IP_VALID (reply_port))
- ds_device_open_reply (reply_port, reply_port_type, err, dev_to_port (bd));
- else if (! err)
+ if (!IP_VALID (reply_port) && ! err)
device_close (bd);
-
- return MIG_NO_REPLY;
+ return err;
}
static io_return_t
-device_close (void *d)
+device_close_forced (void *d, int force)
{
struct block_data *bd = d, *bdp, **prev;
struct device_struct *ds = bd->ds;
@@ -1202,7 +1192,7 @@ device_close (void *d)
}
ds->busy = 1;
- if (--bd->open_count == 0)
+ if (force || --bd->open_count == 0)
{
/* Wait for pending I/O to complete. */
while (bd->iocount > 0)
@@ -1245,6 +1235,13 @@ device_close (void *d)
return D_SUCCESS;
}
+static io_return_t
+device_close (void *d)
+{
+ return device_close_forced (d, 0);
+}
+
+
#define MAX_COPY (VM_MAP_COPY_PAGE_LIST_MAX << PAGE_SHIFT)
/* Check block BN and size COUNT for I/O validity
@@ -1674,7 +1671,7 @@ device_get_status (void *d, dev_flavor_t flavor, dev_status_t status,
INIT_DATA();
if ((*bd->ds->fops->ioctl) (&td.inode, &td.file,
- HDIO_GETGEO, &hg))
+ HDIO_GETGEO, (unsigned long)&hg))
return D_INVALID_OPERATION;
dp->dp_type = DPT_WINI; /* XXX: It may be a floppy... */
@@ -1723,6 +1720,17 @@ device_set_status (void *d, dev_flavor_t flavor, dev_status_t status,
return D_INVALID_OPERATION;
}
+
+static void
+device_no_senders (mach_no_senders_notification_t *ns)
+{
+ device_t dev;
+
+ dev = dev_port_lookup((ipc_port_t) ns->not_header.msgh_remote_port);
+ assert(dev);
+ device_close_forced (dev->emul_data, 1);
+}
+
struct device_emulation_ops linux_block_emulation_ops =
{
NULL,
@@ -1738,7 +1746,7 @@ struct device_emulation_ops linux_block_emulation_ops =
device_get_status,
NULL,
NULL,
- NULL,
+ device_no_senders,
NULL,
NULL
};
diff --git a/linux/dev/glue/glue.h b/linux/dev/glue/glue.h
new file mode 100644
index 00000000..5d4f6d88
--- /dev/null
+++ b/linux/dev/glue/glue.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2011 Free Software Foundation
+ *
+ * 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 of the License, 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 the program ; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef LINUX_DEV_GLUE_GLUE_H
+#define LINUX_DEV_GLUE_GLUE_H
+
+#include <vm/vm_types.h>
+#include <mach/machine/vm_types.h>
+
+extern int linux_auto_config;
+extern int linux_intr_pri;
+
+extern void *alloc_contig_mem (unsigned, unsigned, unsigned, vm_page_t *);
+extern void free_contig_mem (vm_page_t);
+extern void init_IRQ (void);
+extern void restore_IRQ (void);
+extern void linux_kmem_init (void);
+extern void linux_net_emulation_init (void);
+extern void device_setup (void);
+extern void linux_timer_intr (void);
+extern void linux_bad_intr (int);
+extern void linux_sched_init (void);
+extern void pcmcia_init (void);
+extern void linux_soft_intr (void);
+extern int issig (void);
+extern int linux_to_mach_error (int);
+extern char *get_options(char *str, int *ints);
+
+#endif /* LINUX_DEV_GLUE_GLUE_H */
diff --git a/linux/dev/glue/kmem.c b/linux/dev/glue/kmem.c
index 8c21ce7d..28321711 100644
--- a/linux/dev/glue/kmem.c
+++ b/linux/dev/glue/kmem.c
@@ -29,6 +29,7 @@
#include <kern/assert.h>
#include <kern/kalloc.h>
+#include <kern/printf.h>
#include <vm/vm_page.h>
#include <vm/vm_kern.h>
@@ -40,14 +41,13 @@
#include <asm/system.h>
-extern void *alloc_contig_mem (unsigned, unsigned, unsigned, vm_page_t *);
-extern int printf (const char *, ...);
+#include <linux/dev/glue/glue.h>
/* Amount of memory to reserve for Linux memory allocator.
We reserve 64K chunks to stay within DMA limits.
Increase MEM_CHUNKS if the kernel is running out of memory. */
#define MEM_CHUNK_SIZE (64 * 1024)
-#define MEM_CHUNKS 7
+#define MEM_CHUNKS 32
#define MEM_DMA_LIMIT (16 * 1024 * 1024)
/* Mininum amount that linux_kmalloc will allocate. */
@@ -218,7 +218,7 @@ void *
linux_kmalloc (unsigned int size, int priority)
{
int order, coalesced = 0;
- unsigned flags;
+ unsigned long flags;
struct pagehdr *ph;
struct blkhdr *bh, *new_bh;
@@ -310,7 +310,7 @@ again:
void
linux_kfree (void *p)
{
- unsigned flags;
+ unsigned long flags;
struct blkhdr *bh;
struct pagehdr *ph;
@@ -385,7 +385,8 @@ unsigned long
__get_free_pages (int priority, unsigned long order, int dma)
{
int i, pages_collected = 0;
- unsigned flags, bits, off, j, len;
+ unsigned bits, off, j, len;
+ unsigned long flags;
assert ((PAGE_SIZE << order) <= MEM_CHUNK_SIZE);
@@ -444,7 +445,8 @@ void
free_pages (unsigned long addr, unsigned long order)
{
int i;
- unsigned flags, bits, len, j;
+ unsigned bits, len, j;
+ unsigned long flags;
assert ((addr & PAGE_MASK) == 0);
@@ -554,7 +556,7 @@ vfree (void *addr)
if (!p)
panic ("vmalloc_list_lookup failure");
- kmem_free (kernel_map, addr, p->size);
+ kmem_free (kernel_map, (vm_offset_t) addr, p->size);
vmalloc_list_remove (p);
}
diff --git a/linux/dev/glue/misc.c b/linux/dev/glue/misc.c
index d8ca3c24..77dc31dd 100644
--- a/linux/dev/glue/misc.c
+++ b/linux/dev/glue/misc.c
@@ -53,6 +53,7 @@
#include <sys/types.h>
#include <mach/vm_param.h>
#include <kern/thread.h>
+#include <kern/printf.h>
#include <vm/vm_map.h>
#include <vm/vm_page.h>
#include <device/device_types.h>
@@ -66,10 +67,7 @@
#include <linux/blk.h>
#include <linux/proc_fs.h>
#include <linux/kernel_stat.h>
-
-extern boolean_t vm_map_lookup_entry (register vm_map_t, register vm_offset_t,
- vm_map_entry_t *);
-extern int printf (const char *, ...);
+#include <linux/dev/glue/glue.h>
int (*dispatch_scsi_info_ptr) (int ino, char *buffer, char **start,
off_t offset, int length, int inout) = 0;
@@ -84,34 +82,34 @@ linux_to_mach_error (int err)
case 0:
return D_SUCCESS;
- case -LINUX_EPERM:
+ case -EPERM:
return D_INVALID_OPERATION;
- case -LINUX_EIO:
+ case -EIO:
return D_IO_ERROR;
- case -LINUX_ENXIO:
+ case -ENXIO:
return D_NO_SUCH_DEVICE;
- case -LINUX_EACCES:
+ case -EACCES:
return D_INVALID_OPERATION;
- case -LINUX_EFAULT:
+ case -EFAULT:
return D_INVALID_SIZE;
- case -LINUX_EBUSY:
+ case -EBUSY:
return D_ALREADY_OPEN;
- case -LINUX_EINVAL:
+ case -EINVAL:
return D_INVALID_SIZE;
- case -LINUX_EROFS:
+ case -EROFS:
return D_READ_ONLY;
- case -LINUX_EWOULDBLOCK:
+ case -EWOULDBLOCK:
return D_WOULD_BLOCK;
- case -LINUX_ENOMEM:
+ case -ENOMEM:
return D_NO_MEMORY;
default:
@@ -123,6 +121,8 @@ linux_to_mach_error (int err)
int
issig ()
{
+ if (!current_thread())
+ return 0;
return current_thread ()->wait_result != THREAD_AWAKENED;
}
@@ -148,7 +148,7 @@ verify_area (int rw, const void *p, unsigned long size)
|| (entry->protection & prot) != prot)
{
vm_map_unlock_read (current_map ());
- return -LINUX_EFAULT;
+ return -EFAULT;
}
if (entry->vme_end - entry->vme_start >= len)
break;
@@ -229,7 +229,12 @@ add_blkdev_randomness (int major)
void
do_gettimeofday (struct timeval *tv)
{
- host_get_time (1, tv);
+ /*
+ * XXX: The first argument should be mach_host_self (), but that's too
+ * expensive, and the host argument is not used by host_get_time (),
+ * only checked not to be HOST_NULL.
+ */
+ host_get_time ((host_t) 1, (time_value_t *) tv);
}
int
diff --git a/linux/dev/glue/net.c b/linux/dev/glue/net.c
index 095428d3..15732737 100644
--- a/linux/dev/glue/net.c
+++ b/linux/dev/glue/net.c
@@ -61,6 +61,7 @@
#include <sys/types.h>
#include <machine/spl.h>
+#include <machine/vm_param.h>
#include <mach/mach_types.h>
#include <mach/kern_return.h>
@@ -69,6 +70,9 @@
#include <mach/vm_param.h>
#include <mach/notify.h>
+#include <kern/kalloc.h>
+#include <kern/printf.h>
+
#include <ipc/ipc_port.h>
#include <ipc/ipc_space.h>
@@ -84,6 +88,7 @@
#include <device/net_io.h>
#include <device/device_reply.user.h>
#include <device/device_emul.h>
+#include <device/ds_routines.h>
#define MACH_INCLUDE
#include <linux/kernel.h>
@@ -97,7 +102,7 @@
#include <linux/etherdevice.h>
#include <linux/wireless.h>
-extern int linux_intr_pri;
+#include <linux/dev/glue/glue.h>
/* One of these is associated with each instance of a device. */
struct net_data
@@ -248,7 +253,6 @@ void
dev_kfree_skb (struct sk_buff *skb, int mode)
{
unsigned flags;
- extern void *io_done_list;
/* Queue sk_buff on done list if there is a
page list attached or we need to send a reply.
@@ -425,7 +429,6 @@ device_write (void *d, ipc_port_t reply_port,
{
unsigned char *p;
int i, amt, skblen, s;
- io_return_t err = 0;
vm_map_copy_t copy = (vm_map_copy_t) data;
struct net_data *nd = d;
struct linux_device *dev = nd->dev;
@@ -447,7 +450,7 @@ device_write (void *d, ipc_port_t reply_port,
assert (copy->cpy_npages == 1);
skb->copy = copy;
- skb->data = ((void *) copy->cpy_page_list[0]->phys_addr
+ skb->data = ((void *) phystokv(copy->cpy_page_list[0]->phys_addr)
+ (copy->offset & PAGE_MASK));
skb->len = count;
skb->head = skb->data;
@@ -461,7 +464,7 @@ device_write (void *d, ipc_port_t reply_port,
skb->end = skb->tail;
memcpy (skb->data,
- ((void *) copy->cpy_page_list[0]->phys_addr
+ ((void *) phystokv(copy->cpy_page_list[0]->phys_addr)
+ (copy->offset & PAGE_MASK)),
amt);
count -= amt;
@@ -471,7 +474,7 @@ device_write (void *d, ipc_port_t reply_port,
amt = PAGE_SIZE;
if (amt > count)
amt = count;
- memcpy (p, (void *) copy->cpy_page_list[i]->phys_addr, amt);
+ memcpy (p, (void *) phystokv(copy->cpy_page_list[i]->phys_addr), amt);
count -= amt;
p += amt;
}