1/* $NetBSD: devopen.c,v 1.10 2010/10/14 06:39:52 kiyohara Exp $ */ 2 3/*- 4 * Copyright (c) 1993 John Brezak 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 27 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31#include <lib/libsa/stand.h> 32#include <lib/libkern/libkern.h> 33#include <sys/param.h> 34#include <sys/reboot.h> 35 36static int devparse(const char *, int *, int *, int *, int *, int *, char **); 37 38 39/* 40 * Parse a device spec. 41 * i.e. 42 * /dev/disk/floppy 43 * /dev/disk/ide/0/master/0_n 44 * /dev/disk/ide/0/slave/0_n 45 * /dev/disk/scsi/000/0_n 46 * /dev/disk/scsi/030/0_n 47 */ 48static int 49devparse(const char *fname, int *dev, int *ctlr, int *unit, int *lunit, 50 int *part, char **file) 51{ 52 int i; 53 char devdir[] = "/dev/disk/"; 54 char floppy[] = "floppy"; 55 char ide[] = "ide"; 56 char scsi[] = "scsi"; 57 char *p; 58 59 if (strncmp(fname, devdir, strlen(devdir)) != 0) 60 return EINVAL; 61 p = __UNCONST(fname) + strlen(devdir); 62 63 if (strncmp(p, floppy, strlen(floppy)) == 0) { 64 p += strlen(floppy); 65 for (i = 0; devsw[i].dv_name != NULL; i++) 66 if (strcmp(devsw[i].dv_name, "fd") == 0) { 67 *dev = i; 68 *ctlr = 0; 69 *unit = 1; 70 *lunit = 0; 71 break; 72 } 73 } else if (strncmp(p, ide, strlen(ide)) == 0) { 74 char master[] = "master"; 75 char slave[] = "slave"; 76 77 p += strlen(ide); 78 if (*p++ != '/' || 79 !isdigit(*p++) || 80 *p++ != '/') 81 return EINVAL; 82 *ctlr = *(p - 2) - '0'; 83 if (strncmp(p, master, strlen(master)) == 0) { 84 *unit = 0; 85 p += strlen(master); 86 } else if (strncmp(p, slave, strlen(slave)) == 0) { 87 *unit = 1; 88 p += strlen(slave); 89 } else 90 return EINVAL; 91 if (*p++ != '/' || 92 !isdigit(*p++) || 93 *p++ != '_' || 94 !isdigit(*p++)) 95 return EINVAL; 96 *lunit = *(p - 3) - '0'; 97 *part = *(p - 1) - '0'; 98 for (i = 0; devsw[i].dv_name != NULL; i++) 99 if (strcmp(devsw[i].dv_name, "wd") == 0) { 100 *dev = i; 101 break; 102 } 103 if (devsw[i].dv_name == NULL) 104 return EINVAL; 105 } else if (strncmp(p, scsi, strlen(scsi)) == 0) { 106 p += strlen(scsi); 107 if (*p++ != '/' || 108 !isdigit(*p++) || 109 !isdigit(*p++) || 110 !isdigit(*p++) || 111 *p++ != '/' || 112 !isdigit(*p++) || 113 *p++ != '_' || 114 !isdigit(*p++)) 115 return EINVAL; 116 *ctlr = *(p - 7) - '0'; 117 *unit = *(p - 6) - '0'; 118 *lunit = *(p - 5) - '0'; 119 *part = *(p - 1) - '0'; 120 for (i = 0; devsw[i].dv_name != NULL; i++) 121 if (strcmp(devsw[i].dv_name, "sd") == 0) { 122 *dev = i; 123 break; 124 } 125 if (devsw[i].dv_name == NULL) 126 return EINVAL; 127 } 128 129 if (*p++ != ':') 130 return EINVAL; 131 *file = p; 132 return 0; 133} 134 135int 136devopen(struct open_file *f, const char *fname, char **file) 137{ 138 int error; 139 int dev = 0, ctlr = 0, unit = 0, lunit = 0, part = 0; 140 struct devsw *dp = &devsw[0]; 141 extern struct devsw pseudo_devsw; 142 143 **file = '\0'; 144 error = devparse(fname, &dev, &ctlr, &unit, &lunit, &part, file); 145 if (error == 0) { 146 dp = &devsw[dev]; 147 if (!dp->dv_open) 148 return ENODEV; 149 } else { 150 if (strcmp(fname, "in") == 0) 151 /* special case: kernel in memory */ 152 dp = &pseudo_devsw; 153 else 154 return error; 155 } 156 157 f->f_dev = dp; 158 if ((error = (*dp->dv_open)(f, ctlr, unit, lunit, part)) == 0) 159 return 0; 160 161 printf("%s %s\n", fname, strerror(error)); 162 163 return error; 164} 165