diff options
Diffstat (limited to 'linux/dev/glue')
-rw-r--r-- | linux/dev/glue/block.c | 88 | ||||
-rw-r--r-- | linux/dev/glue/glue.h | 44 | ||||
-rw-r--r-- | linux/dev/glue/kmem.c | 18 | ||||
-rw-r--r-- | linux/dev/glue/misc.c | 37 | ||||
-rw-r--r-- | linux/dev/glue/net.c | 15 |
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; } |