1 /* $NetBSD: dklist.c,v 1.3 2001/09/29 17:04:10 jdolecek Exp $ */ 2 3 /*- 4 * Copyright (c) 2001 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Andrew Doran. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* 40 * Copyright (c) 1996 John M. Vinopal 41 * All rights reserved. 42 * 43 * Redistribution and use in source and binary forms, with or without 44 * modification, are permitted provided that the following conditions 45 * are met: 46 * 1. Redistributions of source code must retain the above copyright 47 * notice, this list of conditions and the following disclaimer. 48 * 2. Redistributions in binary form must reproduce the above copyright 49 * notice, this list of conditions and the following disclaimer in the 50 * documentation and/or other materials provided with the distribution. 51 * 3. All advertising materials mentioning features or use of this software 52 * must display the following acknowledgement: 53 * This product includes software developed for the NetBSD Project 54 * by John M. Vinopal. 55 * 4. The name of the author may not be used to endorse or promote products 56 * derived from this software without specific prior written permission. 57 * 58 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 59 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 60 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 61 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 62 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 63 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 64 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 65 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 66 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 67 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 68 * SUCH DAMAGE. 69 */ 70 71 #ifndef lint 72 #include <sys/cdefs.h> 73 __RCSID("$NetBSD: dklist.c,v 1.3 2001/09/29 17:04:10 jdolecek Exp $"); 74 #endif /* not lint */ 75 76 #include <sys/types.h> 77 #include <sys/disk.h> 78 #include <sys/ioctl.h> 79 80 #include <dev/ic/mlxreg.h> 81 #include <dev/ic/mlxio.h> 82 83 #include <err.h> 84 #include <fcntl.h> 85 #include <kvm.h> 86 #include <limits.h> 87 #include <nlist.h> 88 #include <stdio.h> 89 #include <stdlib.h> 90 #include <string.h> 91 #include <ctype.h> 92 #include <unistd.h> 93 94 #include "extern.h" 95 96 static SIMPLEQ_HEAD(, mlx_disk) mlx_disks; 97 98 static struct nlist namelist[] = { 99 #define X_DISK_COUNT 0 100 { "_disk_count" }, /* number of disks */ 101 #define X_DISKLIST 1 102 { "_disklist" }, /* TAILQ of disks */ 103 { NULL }, 104 }; 105 106 #define KVM_ERROR(_string) { \ 107 warnx("%s", (_string)); \ 108 errx(1, "%s", kvm_geterr(kd)); \ 109 } 110 111 /* 112 * Dereference the namelist pointer `v' and fill in the local copy 113 * 'p' which is of size 's'. 114 */ 115 #define deref_nl(kd, v, p, s) \ 116 deref_kptr(kd, (void *)namelist[(v)].n_value, (p), (s)); 117 118 static void deref_kptr(kvm_t *, void *, void *, size_t); 119 120 void 121 mlx_disk_init(void) 122 { 123 124 SIMPLEQ_INIT(&mlx_disks); 125 } 126 127 int 128 mlx_disk_empty(void) 129 { 130 131 return (SIMPLEQ_FIRST(&mlx_disks) == NULL); 132 } 133 134 void 135 mlx_disk_iterate(void (*func)(struct mlx_disk *)) 136 { 137 struct mlx_disk *md; 138 139 SIMPLEQ_FOREACH(md, &mlx_disks, chain) 140 (*func)(md); 141 } 142 143 static int 144 mlx_disk_add0(const char *name) 145 { 146 struct mlx_disk *md; 147 int unit; 148 149 if (name[0] != 'l' || name[1] != 'd' || !isdigit(name[2])) 150 return (-1); 151 152 SIMPLEQ_FOREACH(md, &mlx_disks, chain) 153 if (strcmp(md->name, name) == 0) 154 return (0); 155 156 unit = atoi(name + 2); 157 if (ioctl(mlxfd, MLX_GET_SYSDRIVE, &unit) < 0) 158 return (-1); 159 160 if ((md = malloc(sizeof(*md))) == NULL) 161 err(EXIT_FAILURE, "mlx_disk_add()"); 162 163 strlcpy(md->name, name, sizeof(md->name)); 164 md->hwunit = unit; 165 SIMPLEQ_INSERT_TAIL(&mlx_disks, md, chain); 166 return (0); 167 } 168 169 void 170 mlx_disk_add(const char *name) 171 { 172 173 if (mlx_disk_add0(name) != 0) 174 errx(EXIT_FAILURE, "%s is not attached to %s", name, mlxname); 175 } 176 177 void 178 mlx_disk_add_all(void) 179 { 180 struct disklist_head disk_head; 181 struct disk cur_disk, *dk; 182 char errbuf[_POSIX2_LINE_MAX]; 183 char buf[12]; 184 int i, ndrives; 185 kvm_t *kd; 186 187 /* Open the kernel. */ 188 if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf)) == NULL) 189 errx(1, "kvm_openfiles: %s", errbuf); 190 191 /* Obtain the namelist symbols from the kernel. */ 192 if (kvm_nlist(kd, namelist)) 193 KVM_ERROR("kvm_nlist failed to read symbols."); 194 195 /* Get the number of attached drives. */ 196 deref_nl(kd, X_DISK_COUNT, &ndrives, sizeof(ndrives)); 197 198 if (ndrives < 0) 199 errx(EXIT_FAILURE, "invalid _disk_count %d.", ndrives); 200 if (ndrives == 0) 201 errx(EXIT_FAILURE, "no drives attached."); 202 203 /* Get a pointer to the first disk. */ 204 deref_nl(kd, X_DISKLIST, &disk_head, sizeof(disk_head)); 205 dk = TAILQ_FIRST(&disk_head); 206 207 /* Try to add each disk to the list. */ 208 for (i = 0; i < ndrives; i++) { 209 deref_kptr(kd, dk, &cur_disk, sizeof(cur_disk)); 210 deref_kptr(kd, cur_disk.dk_name, buf, sizeof(buf)); 211 mlx_disk_add0(buf); 212 dk = TAILQ_NEXT(&cur_disk, dk_link); 213 } 214 215 kvm_close(kd); 216 } 217 218 /* 219 * Dereference the kernel pointer `kptr' and fill in the local copy pointed 220 * to by `ptr'. The storage space must be pre-allocated, and the size of 221 * the copy passed in `len'. 222 */ 223 static void 224 deref_kptr(kvm_t *kd, void *kptr, void *ptr, size_t len) 225 { 226 char buf[128]; 227 228 if (kvm_read(kd, (u_long)kptr, (char *)ptr, len) != len) { 229 memset(buf, 0, sizeof(buf)); 230 snprintf(buf, sizeof buf, "can't dereference kptr 0x%lx", 231 (u_long)kptr); 232 KVM_ERROR(buf); 233 } 234 } 235