diff -Naur -X exclude-files ac_cur/arch/um/drivers/mconsole_kern.c ac/arch/um/drivers/mconsole_kern.c --- ac_cur/arch/um/drivers/mconsole_kern.c Sun Jul 15 21:26:31 2001 +++ ac/arch/um/drivers/mconsole_kern.c Sun Jul 15 22:03:32 2001 @@ -10,11 +10,13 @@ #include "linux/reboot.h" #include "linux/utsname.h" #include "linux/ctype.h" +#include "linux/interrupt.h" #include "asm/irq.h" #include "user_util.h" #include "kern_util.h" #include "kern.h" #include "mconsole.h" +#include "mconsole_kern.h" extern int create_listening_socket(void); extern int get_request(int fd, struct mconsole_request *req); @@ -33,16 +35,45 @@ return(unlink_socket()); } +LIST_HEAD(mc_requests); + +void mc_tasklet(unsigned long unused) +{ + struct mconsole_entry *req; + unsigned long flags; + int done; + + do { + save_flags(flags); + req = list_entry(mc_requests.next, struct mconsole_entry, + list); + list_del(&req->list); + done = list_empty(&mc_requests); + handle_request(&req->request); + kfree(req); + restore_flags(flags); + } while(!done); +} + +DECLARE_TASKLET(mconsole_tasklet, mc_tasklet, 0); + void mconsole_interrupt(int irq, void *dev_id, struct pt_regs *regs) { int fd; + struct mconsole_entry *new; struct mconsole_request req; fd = (int) dev_id; while (get_request(fd, &req)) { - handle_request(&req); + new = kmalloc(sizeof(req), GFP_ATOMIC); + if(new == NULL) + mconsole_reply(&req, "ERR Out of memory"); + else { + new->request = req; + list_add(&new->list, &mc_requests); + } } - + tasklet_schedule(&mconsole_tasklet); reactivate_fd(fd); } @@ -58,72 +89,72 @@ void mconsole_halt(struct mconsole_request *req) { - static struct tq_struct halt = { - routine: (void (*)(void *))machine_halt, - }; - mconsole_reply(req, "OK"); - schedule_task(&halt); + machine_halt(); } void mconsole_reboot(struct mconsole_request *req) { - static struct tq_struct reboot = { - routine: (void (*)(void *))machine_restart, - }; - mconsole_reply(req, "OK"); - schedule_task(&reboot); + machine_restart(NULL); } -static struct config_command configs[] = { - { "gdb=", config_gdb }, -}; +LIST_HEAD(mconsole_devices); + +void mconsole_register_dev(struct mc_device *new) +{ + list_add(&new->list, &mconsole_devices); +} + +static struct mc_device *mconsole_find_dev(char *name) +{ + struct list_head *ele; + struct mc_device *dev; + + list_for_each(ele, &mconsole_devices){ + dev = list_entry(ele, struct mc_device, list); + if(!strncmp(name, dev->name, strlen(dev->name))) + return(dev); + } + return(NULL); +} void mconsole_config(struct mconsole_request *req) { - struct config_command *c; + struct mc_device *dev; char *ptr = req->buf, *ok; - int i, err; + int err; ptr += strlen("config"); while(isspace(*ptr)) ptr++; - for(i=0;icommand, strlen(c->command))){ - err = c->handler(&ptr[strlen(c->command)]); - if(err) ok = "ERR"; - else ok = "OK"; - mconsole_reply(req, ok); - return; - } + dev = mconsole_find_dev(ptr); + if(dev == NULL){ + mconsole_reply(req, "ERR Bad configuration option"); + return; } - mconsole_reply(req, "ERR Bad configuration option"); + err = (*dev->config)(&ptr[strlen(dev->name)]); + if(err) ok = "ERR"; + else ok = "OK"; + mconsole_reply(req, ok); } -static struct remove_command removes[] = { - { "gdb", remove_gdb }, -}; - void mconsole_remove(struct mconsole_request *req) { - struct remove_command *r; + struct mc_device *dev; char *ptr = req->buf, *ok; - int i, err; + int err; ptr += strlen("remove"); while(isspace(*ptr)) ptr++; - for(i=0;icommand, strlen(r->command))){ - err = r->handler(); - if(err) ok = "ERR"; - else ok = "OK"; - mconsole_reply(req, ok); - return; - } + dev = mconsole_find_dev(ptr); + if(dev == NULL){ + mconsole_reply(req, "ERR Bad remove option"); + return; } - mconsole_reply(req, "ERR Bad remove option"); + err = (*dev->remove)(&ptr[strlen(dev->name)]); + if(err) ok = "ERR"; + else ok = "OK"; + mconsole_reply(req, ok); } int mconsole_init(void) diff -Naur -X exclude-files ac_cur/arch/um/drivers/ubd.c ac/arch/um/drivers/ubd.c --- ac_cur/arch/um/drivers/ubd.c Sun Jul 15 21:30:40 2001 +++ ac/arch/um/drivers/ubd.c Sun Jul 15 22:03:32 2001 @@ -13,12 +13,15 @@ #include "linux/devfs_fs_kernel.h" #include "linux/cdrom.h" #include "linux/proc_fs.h" +#include "linux/ctype.h" +#include "linux/capability.h" #include "asm/segment.h" #include "asm/uaccess.h" #include "asm/irq.h" #include "user_util.h" #include "kern_util.h" #include "kern.h" +#include "mconsole_kern.h" static int ubd_open(struct inode * inode, struct file * filp); static int ubd_release(struct inode * inode, struct file * file); @@ -76,7 +79,19 @@ #define OPEN_FLAGS O_RDWR #endif -struct { +#define DEFAULT_UBD { \ + file: NULL, \ + is_dir: 0, \ + count: 0, \ + fd: -1, \ + size: -1, \ + boot_openflags: OPEN_FLAGS, \ + openflags: OPEN_FLAGS, \ + real: NULL, \ + fake: NULL, \ +} + +struct ubd { char *file; int is_dir; int count; @@ -84,9 +99,22 @@ __u64 size; int boot_openflags; int openflags; -} ubd_dev[MAX_DEV] = { { "root_fs", 0, 0, -1, 0, OPEN_FLAGS, OPEN_FLAGS }, - [ 1 ... MAX_DEV - 1 ] = - { NULL, 0, 0, -1, -1, OPEN_FLAGS, OPEN_FLAGS } }; + devfs_handle_t real; + devfs_handle_t fake; +} ubd_dev[MAX_DEV] = { +{ + file: "root_fs", + is_dir: 0, + count: 0, + fd: -1, + size: 0, + boot_openflags: OPEN_FLAGS, + openflags: OPEN_FLAGS, + real: NULL, + fake: NULL, +}, +[ 1 ... MAX_DEV - 1 ] = DEFAULT_UBD +}; static struct hd_driveid ubd_id = { cyls: 0, @@ -148,11 +176,12 @@ __setup("fake_ide", fake_ide_setup); -static int ubd_setup(char *str) +static int ubd_setup_common(char *str, int *index_out, int copy_name) { int n; int sync, perm = O_RDWR; + if(index_out) *index_out = -1; n = *str++; if(n == '='){ char *end; @@ -181,6 +210,7 @@ printk("ubd_setup : index out of range\n"); return(1); } + if(index_out) *index_out = n; sync = ubd_dev[n].boot_openflags & O_SYNC; if (*str == 'r') { perm = O_RDONLY; @@ -194,11 +224,21 @@ printk("ubd_setup : Expected '='\n"); return(1); } - ubd_dev[n].file = str; + if(copy_name){ + ubd_dev[n].file = kmalloc(strlen(str) + 1, GFP_ATOMIC); + if(ubd_dev[n].file == NULL) return(0); + strcpy(ubd_dev[n].file, str); + } + else ubd_dev[n].file = str; ubd_dev[n].boot_openflags = perm | sync; return(1); } +static int ubd_setup(char *str) +{ + return(ubd_setup_common(str, NULL, 0)); +} + __setup("ubd", ubd_setup); static int fakehd(char *str) @@ -270,15 +310,80 @@ int sync = 0; +devfs_handle_t ubd_dir_handle; + +static int ubd_add(int n) +{ + char name[sizeof("nnnnnn\0")], dev_name[sizeof("ubd0x")]; + + if(ubd_dev[n].file == NULL) return(-1); + sprintf(name, "%d", n); + ubd_dev[n].real = devfs_register (ubd_dir_handle, name, + DEVFS_FL_DEFAULT, MAJOR_NR, n, + S_IFBLK | S_IRUSR | S_IWUSR | + S_IRGRP |S_IWGRP, + &ubd_blops, NULL); + if(fake_major != 0){ + ubd_dev[n].fake = devfs_register (ubd_dir_handle, name, + DEVFS_FL_DEFAULT, fake_major, + n, S_IFBLK | S_IRUSR | + S_IWUSR | S_IRGRP | S_IWGRP, + &ubd_blops, NULL); + } + if(!strcmp(ubd_gendisk.major_name, "ubd")){ + sprintf(dev_name, "%s%d", ubd_gendisk.major_name, n); + } + else sprintf(dev_name, "%s%c", ubd_gendisk.major_name, + n + 'a'); + make_ide_entries(dev_name); + return(0); +} + +static int ubd_config(char *str) +{ + int n, err; + + err = ubd_setup_common(str, &n, 1); + if(err != 1) return(-1); + if(n != -1) ubd_add(n); + return(0); +} + +static int ubd_remove(char *str) +{ + int n; + + if(!isdigit(*str)) return(-1); + n = *str - '0'; + if(ubd_dev[n].file == NULL) return(0); + if(ubd_dev[n].count > 0) return(-1); + if(ubd_dev[n].real != NULL) devfs_unregister(ubd_dev[n].real); + if(ubd_dev[n].fake != NULL) devfs_unregister(ubd_dev[n].fake); + ubd_dev[n] = ((struct ubd) DEFAULT_UBD); + return(0); +} + +static struct mc_device ubd_mc = { + name: "ubd", + config: ubd_config, + remove: ubd_remove, +}; + +int ubd_mc_init(void) +{ + mconsole_register_dev(&ubd_mc); + return(0); +} + +__initcall(ubd_mc_init); + int ubd_init(void) { unsigned long stack; int i, err; - char name[6], dev_name[sizeof("ubd0x")]; - devfs_handle_t devfs_handle; request_queue_t *q; - devfs_handle = devfs_mk_dir (NULL, "ubd", NULL); + ubd_dir_handle = devfs_mk_dir (NULL, "ubd", NULL); if (devfs_register_blkdev(MAJOR_NR, "ubd", &ubd_blops)) { printk("ubd: unable to get major %d\n", MAJOR_NR); return -1; @@ -304,28 +409,7 @@ fake_gendisk.next = gendisk_head; gendisk_head = &fake_gendisk; } - for(i=0;i