1 /* @(#)maptodisk.c 1.33 21/07/22 Copyright 1991-2021 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static UConst char sccsid[] =
5 "@(#)maptodisk.c 1.33 21/07/22 Copyright 1991-2021 J. Schilling";
6 #endif
7 /*
8 * Routines to map SCSI targets to logical disk names
9 *
10 * Copyright (c) 1991-2021 J. Schilling
11 */
12 /*
13 * The contents of this file are subject to the terms of the
14 * Common Development and Distribution License, Version 1.0 only
15 * (the "License"). You may not use this file except in compliance
16 * with the License.
17 *
18 * See the file CDDL.Schily.txt in this distribution for details.
19 * A copy of the CDDL is also available via the Internet at
20 * http://www.opensource.org/licenses/cddl1.txt
21 *
22 * When distributing Covered Code, include this CDDL HEADER in each
23 * file and include the License file CDDL.Schily.txt from this distribution.
24 */
25
26 /*
27 * Wenn unterschiedliche SCSI Kontroller zugelassen werden sollen,
28 * dann mu� im scg Treiber der DKIOGCONF ioctl eingebaut sein.
29 *
30 * XXX #ifdef HAVE_DKIO ist vorerst nur ein Hack
31 *
32 */
33 #include <schily/stdio.h>
34 #include <schily/unistd.h>
35 #include <schily/standard.h>
36 #include <schily/string.h>
37 #include <schily/fcntl.h>
38 #include <schily/errno.h>
39 #include <schily/stat.h>
40 #include <schily/ioctl.h>
41 #include "dsklabel.h"
42 #include <schily/dirent.h>
43 #include <schily/utypes.h>
44 #include <schily/schily.h>
45 #include <schily/libport.h>
46 #include <schily/ctype.h>
47 #ifndef SVR4
48 #ifdef sun
49 #include <sun3/cpu.h> /* Tempor�r f�r alte Maschinen */
50 #endif
51 #endif
52 #include "fmt.h"
53 #include "map.h"
54
55 #define TARGET(slave) ((slave >> 3) & 07)
56 #define LUN(slave) (slave & 07)
57
58 #define MAX_SCG 8
59
60 typedef struct scsi_devices {
61 char lun[8];
62 }scdev;
63
64 #define NDISKNAMES 64
65
66 LOCAL scdev diskmap[8][8];
67 LOCAL char *disknames[NDISKNAMES];
68 LOCAL char *diskdevnames[NDISKNAMES];
69 LOCAL scgdrv scgmap[MAX_SCG];
70 #ifdef HAVE_DKIO
71 LOCAL int scgmap_known = FALSE;
72 #endif
73 LOCAL BOOL diskmap_init = FALSE;
74 LOCAL BOOL scgmap_init = FALSE;
75
76 LOCAL void init_diskmap __PR((void));
77 LOCAL void diskmap_null __PR((void));
78 LOCAL void scgmap_null __PR((void));
79 #ifdef HAVE_DKIO
80 LOCAL BOOL have_diskname __PR((char *));
81 #endif
82 #ifdef HAVE_DKIO
83 #ifdef SVR4
84 LOCAL BOOL is_svr4_disk __PR((char *));
85 #else
86 LOCAL BOOL is_4x_disk __PR((char *));
87 #endif
88 #endif
89 #ifdef HAVE_DKIO
90 #ifdef SVR4
91 LOCAL void make_svr4_dname __PR((char *, char *));
92 #else
93 LOCAL void make_dname __PR((char *, char *));
94 #endif
95 #endif
96 #ifdef HAVE_DKIO
97 LOCAL BOOL make_disknames __PR((char *, char *, char *));
98 LOCAL int opendisk __PR((char *));
99 #endif
100 LOCAL void map_alldisks __PR((void));
101 #ifdef HAVE_DKIO
102 LOCAL BOOL map_disk __PR((int, int, char *, char *));
103 LOCAL int scg_mapbus __PR((struct dk_conf *));
104 #endif /* HAVE_DKIO */
105 LOCAL void map_scg __PR((void));
106
107 extern int nomap;
108 extern int debug;
109
110 EXPORT int
maptodisk(scsibus,target,lun)111 maptodisk(scsibus, target, lun)
112 int scsibus;
113 int target;
114 int lun;
115 {
116 if (nomap)
117 return (-1);
118
119 if (!diskmap_init)
120 init_diskmap();
121
122 if (scsibus < 0 || target < 0 || lun < 0 ||
123 scsibus >= MAX_SCG || target >= 8 || lun >= 8)
124 return (-1);
125
126 if (debug)
127 printf("maptodisk(%d, %d, %d) = %d\n",
128 scsibus, target, lun,
129 diskmap[scsibus][target].lun[lun]);
130 return (diskmap[scsibus][target].lun[lun]);
131 }
132
133 EXPORT scgdrv *
scg_getdrv(scsibus)134 scg_getdrv(scsibus)
135 int scsibus;
136 {
137 return (&scgmap[scsibus]);
138 }
139
140 EXPORT char *
diskname(diskno)141 diskname(diskno)
142 int diskno;
143 {
144 return (disknames[diskno]);
145 }
146
147 EXPORT char *
diskdevname(diskno)148 diskdevname(diskno)
149 int diskno;
150 {
151 return (diskdevnames[diskno]);
152 }
153
154 EXPORT int
print_disknames(scsibus,target,lun)155 print_disknames(scsibus, target, lun)
156 int scsibus;
157 int target;
158 int lun;
159 {
160 int printed = 0;
161 int dnum;
162 int i;
163 int ccnt = 0;
164
165 if (nomap)
166 return (0);
167
168 if (lun >= 0) {
169 dnum = maptodisk(scsibus, target, lun);
170 if (dnum >= 0)
171 ccnt += printf("%s", disknames[dnum]);
172 return (ccnt);
173 }
174 for (i = 0; i < 8; i++) {
175 dnum = maptodisk(scsibus, target, i);
176 if (dnum >= 0) {
177 ccnt += printf("%s%s", printed?",":"", disknames[dnum]);
178 printed++;
179 }
180 }
181 return (ccnt);
182 }
183
184 #ifdef needed
185 /*
186 * No more needed. Now part of libscg.
187 */
188 EXPORT int
scg_initiator_id(scsibus)189 scg_initiator_id(scsibus)
190 int scsibus;
191 {
192 short id;
193
194 if (!scgmap_init)
195 map_scg();
196 if ((id = scgmap[scsibus].scg_slave) != -1)
197 id = TARGET(id);
198 return (id);
199 }
200 #endif
201
202 LOCAL void
init_diskmap()203 init_diskmap()
204 {
205 if (!scgmap_init)
206 map_scg();
207 map_alldisks();
208 }
209
210 LOCAL void
diskmap_null()211 diskmap_null()
212 {
213 register int i;
214 register int j;
215 register int k;
216 register scdev *sp;
217
218 for (i = 8; --i >= 0; ) {
219 for (j = 8; --j >= 0; ) {
220 sp = &diskmap[i][j];
221 for (k = 8; --k >= 0; ) {
222 sp->lun[k] = -1;
223 }
224 }
225 }
226 }
227
228 LOCAL void
scgmap_null()229 scgmap_null()
230 {
231 register int i;
232
233 for (i = MAX_SCG; --i >= 0; ) {
234 scgmap[i].scg_cname[0] = 0;
235 scgmap[i].scg_caddr = 0;
236 scgmap[i].scg_cunit = -1;
237 scgmap[i].scg_slave = -1;
238 }
239 }
240
241 #ifdef HAVE_DKIO
242 LOCAL BOOL
have_diskname(name)243 have_diskname(name)
244 char *name;
245 {
246 int i;
247
248 for (i = 0; i < NDISKNAMES; i++) {
249 if (disknames[i] && streql(disknames[i], name))
250 return (TRUE);
251 }
252 return (FALSE);
253 }
254 #endif
255
256 #define check_if(s, c) if (*s++ != c) return (FALSE);
257 #define skip_digits(s) while (isdigit(*s)) s++;
258
259 #ifdef SVR4
260
261 #ifdef HAVE_DKIO
262 LOCAL BOOL
is_svr4_disk(s)263 is_svr4_disk(s)
264 char *s;
265 {
266 Uchar *s1 = (Uchar *)s;
267 char *s2;
268
269 if ((s2 = strrchr((char *)s1, '/')) != NULL)
270 s1 = (Uchar *)++s2;
271 check_if(s1, 'c');
272 skip_digits(s1);
273 if (*s1 == 't') {
274 s1++;
275 skip_digits(s1);
276 }
277 check_if(s1, 'd');
278 skip_digits(s1);
279 check_if(s1, 's');
280 skip_digits(s1);
281 return (*s1 == '\0');
282 }
283
284 LOCAL void
make_svr4_dname(to,from)285 make_svr4_dname(to, from)
286 char *to;
287 char *from;
288 {
289 char *p;
290
291 if ((p = strchr(from, 'c')) != NULL) {
292 strcpy(to, p);
293 if ((p = strrchr(to, 's')) != NULL)
294 *p = '\0';
295 } else {
296 *to = '\0';
297 }
298 }
299
300 LOCAL BOOL
make_disknames(name,dname,cdname)301 make_disknames(name, dname, cdname)
302 char *name;
303 char *dname;
304 char *cdname;
305 {
306 if (is_svr4_disk(name)) {
307 make_svr4_dname(cdname, name);
308 if (have_diskname(cdname)) {
309 return (FALSE);
310 }
311 sprintf(dname, "/dev/rdsk/%s", name);
312 } else {
313 sprintf(dname, "/dev/rdsk/%s", name);
314 strcpy(cdname, name);
315 }
316 return (TRUE);
317 }
318 #endif
319
320 #else /* !SVR4 */
321
322 #ifdef HAVE_DKIO
323 LOCAL BOOL
is_4x_disk(s)324 is_4x_disk(s)
325 char *s;
326 {
327 Uchar *s1 = (Uchar *)s;
328 char *s2;
329
330 if ((s2 = strrchr((char *)s1, '/')) != NULL)
331 s1 = (Uchar *)++s2;
332 if (!strstr((char *)s1, "rsd"))
333 return (FALSE);
334 s1 += 3;
335 skip_digits(s1);
336 if (!strchr("abcdefgh", *s1))
337 return (FALSE);
338 return (*++s1 == '\0');
339 }
340
341 LOCAL void
make_dname(to,from)342 make_dname(to, from)
343 char *to;
344 char *from;
345 {
346 char *p;
347
348 if ((p = strchr(from, 'r')) != NULL) {
349 p++;
350 strcpy(to, p);
351 to[strlen(to)-1] = '\0';
352 } else {
353 *to = '\0';
354 }
355 }
356 #endif
357
358 #ifdef HAVE_DKIO
359 LOCAL BOOL
make_disknames(name,dname,cdname)360 make_disknames(name, dname, cdname)
361 char *name;
362 char *dname;
363 char *cdname;
364 {
365 if (!is_4x_disk(name))
366 return (FALSE);
367
368 make_dname(cdname, name);
369 if (have_diskname(cdname)) {
370 return (FALSE);
371 }
372 sprintf(dname, "/dev/%s", name);
373 return (TRUE);
374 }
375 #endif
376 #endif
377
378 #ifdef SVR4
379 #define is_disk(n) is_svr4_disk(n)
380 #else
381 #define is_disk(n) is_4x_disk(n)
382 #endif
383
384 #ifdef HAVE_DKIO
385 LOCAL int
opendisk(dname)386 opendisk(dname)
387 char *dname;
388 {
389 struct stat sb;
390 register int c = -1;
391 register int nlen = 0;
392 int f;
393
394 f = -1;
395 /*
396 * we always try to open 'c' partition (slice 2) first
397 * XXX This only works on sun's with NDKMAP <= 10 and
398 * XXX slice 2 beeing the whole disk!
399 */
400 if (is_disk(dname)) {
401 nlen = strlen(dname);
402 c = dname[nlen-1];
403 dname[nlen-1] = PARTOFF+2;
404 }
405 if (stat(dname, &sb) < 0 ||
406 ((f = open(dname, O_RDONLY|O_NDELAY)) < 0 &&
407 geterrno() == ENOENT)) {
408 /*
409 * It did'nt work try to open the original dname
410 */
411 if (c >= 0) {
412 dname[nlen-1] = c;
413 if (stat(dname, &sb) < 0)
414 return (f);
415 f = open(dname, O_RDONLY|O_NDELAY);
416 }
417 }
418 return (f);
419 }
420 #endif
421
422 LOCAL void
map_alldisks()423 map_alldisks()
424 {
425 #ifdef HAVE_DKIO
426 char dname[64];
427 char cdname[64];
428 register int i;
429 int f;
430 DIR *d;
431 struct dirent *dp;
432 #endif /* HAVE_DKIO */
433
434 diskmap_null();
435 diskmap_init = TRUE;
436
437 #ifdef HAVE_DKIO
438 #ifdef SVR4
439 d = opendir("/dev/rdsk/");
440 if (d == 0) {
441 errmsg("Cannot open '/dev/rdsk'\n");
442 return;
443 }
444 #else
445 d = opendir("/dev/");
446 if (d == 0) {
447 errmsg("Cannot open '/dev'\n");
448 return;
449 }
450 #endif
451
452 i = -1;
453 while ((dp = readdir(d)) != 0) {
454 if (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' ||
455 (dp->d_name[1] == '.' && dp->d_name[2] == '\0')))
456 continue;
457
458 if (!make_disknames(dp->d_name, dname, cdname))
459 continue;
460
461 if (++i >= NDISKNAMES) {
462 errmsgno(EX_BAD,
463 "WARNING: Too many disks. Cannot map %s\n",
464 cdname);
465 break;
466 }
467 f = opendisk(dname);
468 if (f < 0) {
469 if (geterrno() == ENXIO) {
470 /*
471 * The device node exists!
472 * Store the name to avoid looking up all other
473 * partitions.
474 */
475 disknames[i] = permstring(cdname);
476 diskdevnames[i] = permstring(dname);
477 } else {
478 --i;
479 }
480 continue;
481 }
482 if (!map_disk(f, i, dname, cdname))
483 --i;
484 close(f);
485 }
486 closedir(d);
487 #endif /* HAVE_DKIO */
488 }
489
490 #ifdef HAVE_DKIO
491 LOCAL BOOL
map_disk(f,dnum,dname,cdname)492 map_disk(f, dnum, dname, cdname)
493 int f;
494 int dnum;
495 char *dname;
496 char *cdname;
497 {
498 struct dk_conf conf;
499 int scg_bus;
500
501 if (ioctl(f, DKIOCGCONF, &conf) < 0) {
502 errmsg("DKIOGCONF on disk '%s'\n", dname);
503 return (FALSE);
504 }
505 scg_bus = scg_mapbus(&conf);
506 if (scg_bus == -1) {
507 errmsgno(-1, "No scg driver for disk '%s' on %s%d\n",
508 dname, conf.dkc_cname, conf.dkc_cnum);
509 return (FALSE);
510 }
511 if (diskmap[scg_bus][TARGET(conf.dkc_slave)].
512 lun[LUN(conf.dkc_slave)] != -1)
513 errmsgno(EX_BAD, "Double diskmap entry: '%s'\n", dname);
514
515 diskmap[scg_bus][TARGET(conf.dkc_slave)].
516 lun[LUN(conf.dkc_slave)] = dnum;
517 if (disknames[dnum]) {
518 errmsgno(EX_BAD, "Double diskname entry: '%s'\n", cdname);
519 } else {
520 disknames[dnum] = permstring(cdname);
521 diskdevnames[dnum] = permstring(dname);
522 }
523 return (TRUE);
524 }
525
526 LOCAL int
scg_mapbus(conf)527 scg_mapbus(conf)
528 struct dk_conf *conf;
529 {
530 register int i;
531
532 /*
533 * Stimmt dann, wenn nur ein Typ SCSI Kontroller vorhanden ist.
534 */
535 if (!scgmap_known)
536 return (conf->dkc_cnum);
537
538 for (i = 0; i < MAX_SCG; i++) {
539 if (conf->dkc_cnum == scgmap[i].scg_cunit &&
540 conf->dkc_addr == scgmap[i].scg_caddr &&
541 streql(conf->dkc_cname, scgmap[i].scg_cname))
542 return (i);
543 }
544 return (-1);
545 }
546 #endif /* HAVE_DKIO */
547
548 LOCAL void
map_scg()549 map_scg()
550 {
551 #ifdef HAVE_DKIO
552 struct dk_conf conf;
553 char dname[64];
554 register int i;
555 int f;
556 #ifndef SVR4
557 int cpu_type = gethostid() >> 24;
558 #endif
559 #endif /* HAVE_DKIO */
560
561
562 scgmap_null();
563 scgmap_init = TRUE;
564 #ifdef HAVE_DKIO
565 for (i = 0; i < MAX_SCG; i++) {
566 sprintf(dname, "/dev/scg%d", i);
567 if ((f = open(dname, O_RDONLY)) < 0)
568 continue;
569
570 if (ioctl(f, DKIOCGCONF, &conf) < 0) {
571 #ifndef SVR4
572 #ifdef sun
573 if (cpu_type != CPU_SUN3_50 &&
574 cpu_type != CPU_SUN3_60)
575 #endif
576 #endif
577 errmsg("DKIOGCONF not supported by '%s'.\n\
578 \nUpgrade Kernel for proper logical disk mapping.\n\n", dname);
579 return;
580 }
581 scgmap_known = TRUE;
582 strcpy(scgmap[i].scg_cname, conf.dkc_cname);
583 scgmap[i].scg_caddr = conf.dkc_addr;
584 scgmap[i].scg_cunit = conf.dkc_cnum;
585 scgmap[i].scg_slave = conf.dkc_slave;
586 close(f);
587
588 printf("scg%d at %s%d initiator id %d\n",
589 i,
590 conf.dkc_cname, conf.dkc_cnum,
591 conf.dkc_slave == -1 ? -1 : conf.dkc_slave/8);
592 }
593 #endif /* HAVE_DKIO */
594 }
595