sd.c revision 1.2 1 /*
2 * Written by Julian Elischer (julian (at) tfs.com)
3 * for TRW Financial Systems for use under the MACH(2.5) operating system.
4 *
5 * TRW Financial Systems, in accordance with their agreement with Carnegie
6 * Mellon University, makes this software available to CMU to distribute
7 * or use in any manner that they see fit as long as this message is kept with
8 * the software. For this reason TFS also grants any other persons or
9 * organisations permission to use or modify this software.
10 *
11 * TFS supplies this software to be publicly redistributed
12 * on the understanding that TFS is not responsible for the correct
13 * functioning of this software in any circumstances.
14 *
15 * PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
16 * -------------------- ----- ----------------------
17 * CURRENT PATCH LEVEL: 1 00098
18 * -------------------- ----- ----------------------
19 *
20 * 16 Feb 93 Julian Elischer ADDED for SCSI system
21 *
22 */
23
24 /*
25 * Ported to run under 386BSD by Julian Elischer (julian (at) tfs.com) Sept 1992
26 */
27
28 #define SPLSD splbio
29 #define ESUCCESS 0
30 #include <sd.h>
31 #include <sys/types.h>
32 #include <sys/param.h>
33 #include <sys/dkbad.h>
34 #include <sys/systm.h>
35 #include <sys/conf.h>
36 #include <sys/file.h>
37 #include <sys/stat.h>
38 #include <sys/ioctl.h>
39 #include <sys/buf.h>
40 #include <sys/uio.h>
41 #include <sys/malloc.h>
42 #include <sys/errno.h>
43 #include <sys/disklabel.h>
44 #include <scsi/scsi_all.h>
45 #include <scsi/scsi_disk.h>
46 #include <scsi/scsiconf.h>
47
48 long int sdstrats,sdqueues;
49
50
51 #ifdef DDB
52 int Debugger();
53 #else
54 #define Debugger()
55 #endif
56
57
58 #define PAGESIZ 4096
59 #define SECSIZE 512
60 #define PDLOCATION 29
61 #define BOOTRECORDSIGNATURE (0x55aa & 0x00ff)
62 #define SDOUTSTANDING 2
63 #define SDQSIZE 4
64 #define SD_RETRIES 4
65
66 #define MAKESDDEV(maj, unit, part) (makedev(maj,((unit<<3)+part)))
67 #define UNITSHIFT 3
68 #define PARTITION(z) (minor(z) & 0x07)
69 #define RAW_PART 3
70 #define UNIT(z) ( (minor(z) >> UNITSHIFT) )
71
72 #define WHOLE_DISK(unit) ( (unit << UNITSHIFT) + RAW_PART )
73
74 struct buf sd_buf_queue[NSD];
75 int sd_done();
76 int sdstrategy();
77
78 int sd_debug = 0;
79
80 struct scsi_xfer *sd_free_xfer[NSD];
81 int sd_xfer_block_wait[NSD];
82
83 struct sd_data
84 {
85 int flags;
86 #define SDVALID 0x02 /* PARAMS LOADED */
87 #define SDINIT 0x04 /* device has been init'd */
88 #define SDWAIT 0x08 /* device has someone waiting */
89 #define SDHAVELABEL 0x10 /* have read the label */
90 #define SDDOSPART 0x20 /* Have read the DOS partition table */
91 #define SDWRITEPROT 0x40 /* Device in readonly mode (S/W)*/
92 struct scsi_switch *sc_sw; /* address of scsi low level switch */
93 int ctlr; /* so they know which one we want */
94 int targ; /* our scsi target ID */
95 int lu; /* out scsi lu */
96 long int ad_info; /* info about the adapter */
97 int cmdscount; /* cmds allowed outstanding by board*/
98 int wlabel; /* label is writable */
99 struct disk_parms
100 {
101 u_char heads; /* Number of heads */
102 u_short cyls; /* Number of cylinders */
103 u_char sectors;/*dubious*/ /* Number of sectors/track */
104 u_short secsiz; /* Number of bytes/sector */
105 u_long disksize; /* total number sectors */
106 }params;
107 struct disklabel disklabel;
108 struct dos_partition dosparts[NDOSPART]; /* DOS view of disk */
109 int partflags[MAXPARTITIONS]; /* per partition flags */
110 #define SDOPEN 0x01
111 int openparts; /* one bit for each open partition */
112 unsigned int sd_start_of_unix; /* unix vs dos partitions */
113 }sd_data[NSD];
114
115
116 static int next_sd_unit = 0;
117 /***********************************************************************\
118 * The routine called by the low level scsi routine when it discovers *
119 * A device suitable for this driver *
120 \***********************************************************************/
121
122 int sdattach(ctlr,targ,lu,scsi_switch)
123 struct scsi_switch *scsi_switch;
124 {
125 int unit,i;
126 unsigned char *tbl;
127 struct sd_data *sd;
128 struct disk_parms *dp;
129 long int ad_info;
130 struct scsi_xfer *sd_scsi_xfer;
131
132 unit = next_sd_unit++;
133 sd = sd_data + unit;
134 dp = &(sd->params);
135 if(scsi_debug & PRINTROUTINES) printf("sdattach: ");
136 /*******************************************************\
137 * Check we have the resources for another drive *
138 \*******************************************************/
139 if( unit >= NSD)
140 {
141 printf("Too many scsi disks..(%d > %d) reconfigure kernel",(unit + 1),NSD);
142 return(0);
143 }
144 /*******************************************************\
145 * Store information needed to contact our base driver *
146 \*******************************************************/
147 sd->sc_sw = scsi_switch;
148 sd->ctlr = ctlr;
149 sd->targ = targ;
150 sd->lu = lu;
151 if(sd->sc_sw->adapter_info)
152 {
153 sd->ad_info = ( (*(sd->sc_sw->adapter_info))(ctlr));
154 sd->cmdscount = sd->ad_info & AD_INF_MAX_CMDS;
155 if(sd->cmdscount > SDOUTSTANDING)
156 {
157 sd->cmdscount = SDOUTSTANDING;
158 }
159 }
160 else
161 {
162 sd->ad_info = 1;
163 sd->cmdscount = 1;
164 }
165
166 i = sd->cmdscount;
167 sd_scsi_xfer = (struct scsi_xfer *)malloc(sizeof(struct scsi_xfer) * i
168 ,M_TEMP, M_NOWAIT);
169 while(i-- )
170 {
171 sd_scsi_xfer->next = sd_free_xfer[unit];
172 sd_free_xfer[unit] = sd_scsi_xfer;
173 sd_scsi_xfer++;
174 }
175 /*******************************************************\
176 * Use the subdriver to request information regarding *
177 * the drive. We cannot use interrupts yet, so the *
178 * request must specify this. *
179 \*******************************************************/
180 sd_get_parms(unit, SCSI_NOSLEEP | SCSI_NOMASK);
181 printf(" sd%d: %dMB, cyls %d, heads %d, secs %d, bytes/sec %d\n",
182 unit,
183 ( dp->cyls
184 * dp->heads
185 * dp->sectors
186 * dp->secsiz
187 )
188 / (1024 * 1024),
189 dp->cyls,
190 dp->heads,
191 dp->sectors,
192 dp->secsiz);
193 /*******************************************************\
194 * Set up the bufs for this device *
195 \*******************************************************/
196 sd->flags |= SDINIT;
197 return;
198
199 }
200
201
202
203 /*******************************************************\
204 * open the device. Make sure the partition info *
205 * is a up-to-date as can be. *
206 \*******************************************************/
207 sdopen(dev)
208 {
209 int errcode = 0;
210 int unit, part;
211 struct disk_parms disk_parms;
212 struct sd_data *sd ;
213
214 unit = UNIT(dev);
215 part = PARTITION(dev);
216 sd = sd_data + unit;
217 if(scsi_debug & (PRINTROUTINES | TRACEOPENS))
218 printf("sdopen: dev=0x%x (unit %d (of %d),partition %d)\n"
219 , dev, unit, NSD, part);
220 /*******************************************************\
221 * Check the unit is legal *
222 \*******************************************************/
223 if ( unit >= NSD )
224 {
225 return(ENXIO);
226 }
227 /*******************************************************\
228 * Make sure the disk has been initialised *
229 * At some point in the future, get the scsi driver *
230 * to look for a new device if we are not initted *
231 \*******************************************************/
232 if (! (sd->flags & SDINIT))
233 {
234 return(ENXIO);
235 }
236
237 /*******************************************************\
238 * If it's been invalidated, and not everybody has *
239 * closed it then forbid re-entry. *
240 \*******************************************************/
241 if ((! (sd->flags & SDVALID))
242 && ( sd->openparts))
243 return(ENXIO);
244 /*******************************************************\
245 * Check that it is still responding and ok. *
246 * "unit attention errors should occur here if the drive *
247 * has been restarted or the pack changed *
248 \*******************************************************/
249
250 if(scsi_debug & TRACEOPENS)
251 printf("device is ");
252 if (sd_test_unit_ready(unit,0))
253 {
254 if(scsi_debug & TRACEOPENS) printf("not reponding\n");
255 return(ENXIO);
256 }
257 if(scsi_debug & TRACEOPENS)
258 printf("ok\n");
259 /*******************************************************\
260 * In case it is a funny one, tell it to start *
261 * not needed for most hard drives (ignore failure) *
262 \*******************************************************/
263 sd_start_unit(unit,SCSI_ERR_OK|SCSI_SILENT);
264 if(scsi_debug & TRACEOPENS)
265 printf("started ");
266 /*******************************************************\
267 * Load the physical device parameters *
268 \*******************************************************/
269 sd_get_parms(unit, 0); /* sets SDVALID */
270 if (sd->params.secsiz != SECSIZE)
271 {
272 printf("sd%d: Can't deal with %d bytes logical blocks\n"
273 ,unit, sd->params.secsiz);
274 Debugger();
275 return(ENXIO);
276 }
277 if(scsi_debug & TRACEOPENS)
278 printf("Params loaded ");
279 /*******************************************************\
280 * Load the partition info if not already loaded *
281 \*******************************************************/
282 sd_prevent(unit,PR_PREVENT,SCSI_ERR_OK|SCSI_SILENT); /* who cares if it fails? */
283 if((errcode = sdgetdisklabel(unit)) && (part != RAW_PART))
284 {
285 sd_prevent(unit,PR_ALLOW,SCSI_ERR_OK|SCSI_SILENT); /* who cares if it fails? */
286 return(errcode);
287 }
288 if(scsi_debug & TRACEOPENS)
289 printf("Disklabel loaded ");
290 /*******************************************************\
291 * Check the partition is legal *
292 \*******************************************************/
293 if ( part >= MAXPARTITIONS ) {
294 sd_prevent(unit,PR_ALLOW,SCSI_ERR_OK|SCSI_SILENT); /* who cares if it fails? */
295 return(ENXIO);
296 }
297 if(scsi_debug & TRACEOPENS)
298 printf("ok");
299 /*******************************************************\
300 * Check that the partition exists *
301 \*******************************************************/
302 if (( sd->disklabel.d_partitions[part].p_size == 0 )
303 && (part != RAW_PART))
304 {
305 sd_prevent(unit,PR_ALLOW,SCSI_ERR_OK|SCSI_SILENT); /* who cares if it fails? */
306 return(ENXIO);
307 }
308 sd->partflags[part] |= SDOPEN;
309 sd->openparts |= (1 << part);
310 if(scsi_debug & TRACEOPENS)
311 printf("open %d %d\n",sdstrats,sdqueues);
312 return(0);
313 }
314
315 /*******************************************************\
316 * Get ownership of a scsi_xfer *
317 * If need be, sleep on it, until it comes free *
318 \*******************************************************/
319 struct scsi_xfer *sd_get_xs(unit,flags)
320 int flags;
321 int unit;
322 {
323 struct scsi_xfer *xs;
324 int s;
325
326 if(flags & (SCSI_NOSLEEP | SCSI_NOMASK))
327 {
328 if (xs = sd_free_xfer[unit])
329 {
330 sd_free_xfer[unit] = xs->next;
331 xs->flags = 0;
332 }
333 }
334 else
335 {
336 s = SPLSD();
337 while (!(xs = sd_free_xfer[unit]))
338 {
339 sd_xfer_block_wait[unit]++; /* someone waiting! */
340 sleep((caddr_t)&sd_free_xfer[unit], PRIBIO+1);
341 sd_xfer_block_wait[unit]--;
342 }
343 sd_free_xfer[unit] = xs->next;
344 splx(s);
345 xs->flags = 0;
346 }
347 return(xs);
348 }
349
350 /*******************************************************\
351 * Free a scsi_xfer, wake processes waiting for it *
352 \*******************************************************/
353 sd_free_xs(unit,xs,flags)
354 struct scsi_xfer *xs;
355 int unit;
356 int flags;
357 {
358 int s;
359
360 if(flags & SCSI_NOMASK)
361 {
362 if (sd_xfer_block_wait[unit])
363 {
364 printf("doing a wakeup from NOMASK mode\n");
365 wakeup((caddr_t)&sd_free_xfer[unit]);
366 }
367 xs->next = sd_free_xfer[unit];
368 sd_free_xfer[unit] = xs;
369 }
370 else
371 {
372 s = SPLSD();
373 if (sd_xfer_block_wait[unit])
374 wakeup((caddr_t)&sd_free_xfer[unit]);
375 xs->next = sd_free_xfer[unit];
376 sd_free_xfer[unit] = xs;
377 splx(s);
378 }
379 }
380
381 /*******************************************************\
382 * trim the size of the transfer if needed, *
383 * called by physio *
384 * basically the smaller of our max and the scsi driver's*
385 * minphys (note we have no max) *
386 \*******************************************************/
387 /* Trim buffer length if buffer-size is bigger than page size */
388 void sdminphys(bp)
389 struct buf *bp;
390 {
391 (*(sd_data[UNIT(bp->b_dev)].sc_sw->scsi_minphys))(bp);
392 }
393
394 /*******************************************************\
395 * Actually translate the requested transfer into *
396 * one the physical driver can understand *
397 * The transfer is described by a buf and will include *
398 * only one physical transfer. *
399 \*******************************************************/
400
401 int sdstrategy(bp)
402 struct buf *bp;
403 {
404 struct buf *dp;
405 unsigned int opri;
406 struct sd_data *sd ;
407 int unit;
408
409 sdstrats++;
410 unit = UNIT((bp->b_dev));
411 sd = sd_data + unit;
412 if(scsi_debug & PRINTROUTINES) printf("\nsdstrategy ");
413 if(scsi_debug & SHOWREQUESTS) printf("sd%d: %d bytes @ blk%d\n",
414 unit,bp->b_bcount,bp->b_blkno);
415 sdminphys(bp);
416 /*******************************************************\
417 * If the device has been made invalid, error out *
418 \*******************************************************/
419 if(!(sd->flags & SDVALID))
420 {
421 bp->b_error = EIO;
422 goto bad;
423 }
424 /*******************************************************\
425 * "soft" write protect check *
426 \*******************************************************/
427 if ((sd->flags & SDWRITEPROT) && (bp->b_flags & B_READ) == 0) {
428 bp->b_error = EROFS;
429 goto bad;
430 }
431 /*******************************************************\
432 * If it's a null transfer, return immediatly *
433 \*******************************************************/
434 if (bp->b_bcount == 0)
435 {
436 goto done;
437 }
438
439 /*******************************************************\
440 * Decide which unit and partition we are talking about *
441 * only raw is ok if no label *
442 \*******************************************************/
443 if(PARTITION(bp->b_dev) != RAW_PART)
444 {
445 if (!(sd->flags & SDHAVELABEL))
446 {
447 bp->b_error = EIO;
448 goto bad;
449 }
450
451 /*
452 * do bounds checking, adjust transfer. if error, process.
453 * if end of partition, just return
454 */
455 if (bounds_check_with_label(bp,&sd->disklabel,sd->wlabel) <= 0)
456 goto done;
457 /* otherwise, process transfer request */
458 }
459
460 opri = SPLSD();
461 dp = &sd_buf_queue[unit];
462
463 /*******************************************************\
464 * Place it in the queue of disk activities for this disk*
465 \*******************************************************/
466 disksort(dp, bp);
467
468 /*******************************************************\
469 * Tell the device to get going on the transfer if it's *
470 * not doing anything, otherwise just wait for completion*
471 \*******************************************************/
472 sdstart(unit);
473
474 splx(opri);
475 return;
476 bad:
477 bp->b_flags |= B_ERROR;
478 done:
479
480 /*******************************************************\
481 * Correctly set the buf to indicate a completed xfer *
482 \*******************************************************/
483 bp->b_resid = bp->b_bcount;
484 biodone(bp);
485 return;
486 }
487
488 /***************************************************************\
489 * sdstart looks to see if there is a buf waiting for the device *
490 * and that the device is not already busy. If both are true, *
491 * It deques the buf and creates a scsi command to perform the *
492 * transfer in the buf. The transfer request will call sd_done *
493 * on completion, which will in turn call this routine again *
494 * so that the next queued transfer is performed. *
495 * The bufs are queued by the strategy routine (sdstrategy) *
496 * *
497 * This routine is also called after other non-queued requests *
498 * have been made of the scsi driver, to ensure that the queue *
499 * continues to be drained. *
500 * *
501 * must be called at the correct (highish) spl level *
502 \***************************************************************/
503 /* sdstart() is called at SPLSD from sdstrategy and sd_done*/
504 sdstart(unit)
505 int unit;
506 {
507 int drivecount;
508 register struct buf *bp = 0;
509 register struct buf *dp;
510 struct scsi_xfer *xs;
511 struct scsi_rw_big cmd;
512 int blkno, nblk;
513 struct sd_data *sd = sd_data + unit;
514 struct partition *p ;
515
516 if(scsi_debug & PRINTROUTINES) printf("sdstart%d ",unit);
517 /*******************************************************\
518 * See if there is a buf to do and we are not already *
519 * doing one *
520 \*******************************************************/
521 if(!sd_free_xfer[unit])
522 {
523 return; /* none for us, unit already underway */
524 }
525
526 if(sd_xfer_block_wait[unit]) /* there is one, but a special waits */
527 {
528 return; /* give the special that's waiting a chance to run */
529 }
530
531
532 dp = &sd_buf_queue[unit];
533 if ((bp = dp->b_actf) != NULL) /* yes, an assign */
534 {
535 dp->b_actf = bp->av_forw;
536 }
537 else
538 {
539 return;
540 }
541
542 xs=sd_get_xs(unit,0); /* ok we can grab it */
543 xs->flags = INUSE; /* Now ours */
544 /*******************************************************\
545 * If the device has become invalid, abort all the *
546 * reads and writes until all files have been closed and *
547 * re-openned *
548 \*******************************************************/
549 if(!(sd->flags & SDVALID))
550 {
551 xs->error = XS_DRIVER_STUFFUP;
552 sd_done(unit,xs); /* clean up (calls sdstart) */
553 return ;
554 }
555 /*******************************************************\
556 * We have a buf, now we should move the data into *
557 * a scsi_xfer definition and try start it *
558 \*******************************************************/
559 /*******************************************************\
560 * First, translate the block to absolute *
561 \*******************************************************/
562 p = sd->disklabel.d_partitions + PARTITION(bp->b_dev);
563 blkno = bp->b_blkno + p->p_offset;
564 nblk = (bp->b_bcount + 511) >> 9;
565
566 /*******************************************************\
567 * Fill out the scsi command *
568 \*******************************************************/
569 bzero(&cmd, sizeof(cmd));
570 cmd.op_code = (bp->b_flags & B_READ)
571 ? READ_BIG : WRITE_BIG;
572 cmd.addr_3 = (blkno & 0xff000000) >> 24;
573 cmd.addr_2 = (blkno & 0xff0000) >> 16;
574 cmd.addr_1 = (blkno & 0xff00) >> 8;
575 cmd.addr_0 = blkno & 0xff;
576 cmd.length2 = (nblk & 0xff00) >> 8;
577 cmd.length1 = (nblk & 0xff);
578 /*******************************************************\
579 * Fill out the scsi_xfer structure *
580 * Note: we cannot sleep as we may be an interrupt *
581 \*******************************************************/
582 xs->flags |= SCSI_NOSLEEP;
583 xs->adapter = sd->ctlr;
584 xs->targ = sd->targ;
585 xs->lu = sd->lu;
586 xs->retries = SD_RETRIES;
587 xs->timeout = 10000;/* 10000 millisecs for a disk !*/
588 xs->cmd = (struct scsi_generic *)&cmd;
589 xs->cmdlen = sizeof(cmd);
590 xs->resid = bp->b_bcount;
591 xs->when_done = sd_done;
592 xs->done_arg = unit;
593 xs->done_arg2 = (int)xs;
594 xs->error = XS_NOERROR;
595 xs->bp = bp;
596 xs->data = (u_char *)bp->b_un.b_addr;
597 xs->datalen = bp->b_bcount;
598 /*******************************************************\
599 * Pass all this info to the scsi driver. *
600 \*******************************************************/
601
602
603
604 if ( (*(sd->sc_sw->scsi_cmd))(xs) != SUCCESSFULLY_QUEUED)
605 {
606 printf("sd%d: oops not queued",unit);
607 xs->error = XS_DRIVER_STUFFUP;
608 sd_done(unit,xs); /* clean up (calls sdstart) */
609 }
610 sdqueues++;
611 }
612
613 /*******************************************************\
614 * This routine is called by the scsi interrupt when *
615 * the transfer is complete.
616 \*******************************************************/
617 int sd_done(unit,xs)
618 int unit;
619 struct scsi_xfer *xs;
620 {
621 struct buf *bp;
622 int retval;
623 int retries = 0;
624
625 if(scsi_debug & PRINTROUTINES) printf("sd_done%d ",unit);
626 if (! (xs->flags & INUSE))
627 panic("scsi_xfer not in use!");
628 if(bp = xs->bp)
629 {
630 switch(xs->error)
631 {
632 case XS_NOERROR:
633 bp->b_error = 0;
634 bp->b_resid = 0;
635 break;
636
637 case XS_SENSE:
638 retval = (sd_interpret_sense(unit,xs));
639 if(retval)
640 {
641 bp->b_flags |= B_ERROR;
642 bp->b_error = retval;
643 }
644 break;
645
646 case XS_TIMEOUT:
647 printf("sd%d timeout\n",unit);
648
649 case XS_BUSY: /* should retry */ /* how? */
650 /************************************************/
651 /* SHOULD put buf back at head of queue */
652 /* and decrement retry count in (*xs) */
653 /* HOWEVER, this should work as a kludge */
654 /************************************************/
655 if(xs->retries--)
656 {
657 xs->error = XS_NOERROR;
658 xs->flags &= ~ITSDONE;
659 if ( (*(sd_data[unit].sc_sw->scsi_cmd))(xs)
660 == SUCCESSFULLY_QUEUED)
661 { /* don't wake the job, ok? */
662 return;
663 }
664 xs->flags |= ITSDONE;
665 } /* fall through */
666
667 case XS_DRIVER_STUFFUP:
668 bp->b_flags |= B_ERROR;
669 bp->b_error = EIO;
670 break;
671 default:
672 printf("sd%d: unknown error category from scsi driver\n"
673 ,unit);
674 }
675 biodone(bp);
676 sd_free_xs(unit,xs,0);
677 sdstart(unit); /* If there's anything waiting.. do it */
678 }
679 else /* special has finished */
680 {
681 wakeup(xs);
682 }
683 }
684 /*******************************************************\
685 * Perform special action on behalf of the user *
686 * Knows about the internals of this device *
687 \*******************************************************/
688 sdioctl(dev_t dev, int cmd, caddr_t addr, int flag)
689 {
690 /* struct sd_cmd_buf *args;*/
691 int error = 0;
692 unsigned int opri;
693 unsigned char unit, part;
694 register struct sd_data *sd;
695
696
697 /*******************************************************\
698 * Find the device that the user is talking about *
699 \*******************************************************/
700 unit = UNIT(dev);
701 part = PARTITION(dev);
702 sd = &sd_data[unit];
703 if(scsi_debug & PRINTROUTINES) printf("sdioctl%d ",unit);
704
705 /*******************************************************\
706 * If the device is not valid.. abandon ship *
707 \*******************************************************/
708 if (!(sd_data[unit].flags & SDVALID))
709 return(EIO);
710 switch(cmd)
711 {
712
713 case DIOCSBAD:
714 error = EINVAL;
715 break;
716
717 case DIOCGDINFO:
718 *(struct disklabel *)addr = sd->disklabel;
719 break;
720
721 case DIOCGPART:
722 ((struct partinfo *)addr)->disklab = &sd->disklabel;
723 ((struct partinfo *)addr)->part =
724 &sd->disklabel.d_partitions[PARTITION(dev)];
725 break;
726
727 case DIOCSDINFO:
728 if ((flag & FWRITE) == 0)
729 error = EBADF;
730 else
731 error = setdisklabel(&sd->disklabel,
732 (struct disklabel *)addr,
733 /*(sd->flags & DKFL_BSDLABEL) ? sd->openparts : */0,
734 sd->dosparts);
735 if (error == 0) {
736 sd->flags |= SDHAVELABEL;
737 }
738 break;
739
740 case DIOCWLABEL:
741 sd->flags &= ~SDWRITEPROT;
742 if ((flag & FWRITE) == 0)
743 error = EBADF;
744 else
745 sd->wlabel = *(int *)addr;
746 break;
747
748 case DIOCWDINFO:
749 sd->flags &= ~SDWRITEPROT;
750 if ((flag & FWRITE) == 0)
751 error = EBADF;
752 else
753 {
754 if ((error = setdisklabel(&sd->disklabel
755 , (struct disklabel *)addr
756 , /*(sd->flags & SDHAVELABEL) ? sd->openparts :*/ 0
757 , sd->dosparts)) == 0)
758 {
759 int wlab;
760
761 sd->flags |= SDHAVELABEL; /* ok write will succeed */
762
763 /* simulate opening partition 0 so write succeeds */
764 sd->openparts |= (1 << 0); /* XXX */
765 wlab = sd->wlabel;
766 sd->wlabel = 1;
767 error = writedisklabel(dev, sdstrategy,
768 &sd->disklabel, sd->dosparts);
769 sd->wlabel = wlab;
770 }
771 }
772 break;
773
774
775 default:
776 error = ENOTTY;
777 break;
778 }
779 return (error);
780 }
781
782
783 /*******************************************************\
784 * Load the label information on the named device *
785 \*******************************************************/
786 int sdgetdisklabel(unit)
787 unsigned char unit;
788 {
789 /*unsigned int n, m;*/
790 char *errstring;
791 struct dos_partition *dos_partition_p;
792 struct sd_data *sd = sd_data + unit;
793
794 /*******************************************************\
795 * If the inflo is already loaded, use it *
796 \*******************************************************/
797 if(sd->flags & SDHAVELABEL) return(ESUCCESS);
798
799 bzero(&sd->disklabel,sizeof(struct disklabel));
800 /*******************************************************\
801 * make partition 3 the whole disk in case of failure *
802 * then get pdinfo *
803 \*******************************************************/
804 sd->disklabel.d_partitions[0].p_offset = 0;
805 sd->disklabel.d_partitions[0].p_size = sd->params.disksize;
806 sd->disklabel.d_partitions[RAW_PART].p_offset = 0;
807 sd->disklabel.d_partitions[RAW_PART].p_size = sd->params.disksize;
808 sd->disklabel.d_npartitions = MAXPARTITIONS;
809 sd->disklabel.d_secsize = 512; /* as long as it's not 0 */
810 sd->disklabel.d_ntracks = sd->params.heads;
811 sd->disklabel.d_nsectors = sd->params.sectors;
812 sd->disklabel.d_ncylinders = sd->params.cyls;
813 sd->disklabel.d_secpercyl = sd->params.heads * sd->params.sectors;
814 if (sd->disklabel.d_secpercyl == 0)
815 {
816 sd->disklabel.d_secpercyl = 100;
817 /* as long as it's not 0 */
818 /* readdisklabel divides by it */
819 }
820
821 /*******************************************************\
822 * all the generic bisklabel extraction routine *
823 \*******************************************************/
824 if(errstring = readdisklabel(makedev(0 ,(unit<<UNITSHIFT )+3)
825 , sdstrategy
826 , &sd->disklabel
827 , sd->dosparts
828 , 0
829 , 0))
830 {
831 printf("sd%d: %s\n",unit, errstring);
832 return(ENXIO);
833 }
834 /*******************************************************\
835 * leave partition 2 "open" for raw I/O *
836 \*******************************************************/
837
838 sd->flags |= SDHAVELABEL; /* WE HAVE IT ALL NOW */
839 return(ESUCCESS);
840 }
841
842 /*******************************************************\
843 * Find out from the device what it's capacity is *
844 \*******************************************************/
845 sd_size(unit, flags)
846 {
847 struct scsi_read_cap_data rdcap;
848 struct scsi_read_capacity scsi_cmd;
849 int size;
850
851 /*******************************************************\
852 * make up a scsi command and ask the scsi driver to do *
853 * it for you. *
854 \*******************************************************/
855 bzero(&scsi_cmd, sizeof(scsi_cmd));
856 scsi_cmd.op_code = READ_CAPACITY;
857
858 /*******************************************************\
859 * If the command works, interpret the result as a 4 byte*
860 * number of blocks *
861 \*******************************************************/
862 if (sd_scsi_cmd(unit,
863 &scsi_cmd,
864 sizeof(scsi_cmd),
865 &rdcap,
866 sizeof(rdcap),
867 2000,
868 flags) != 0)
869 {
870 printf("could not get size of unit %d\n", unit);
871 return(0);
872 } else {
873 size = rdcap.addr_0 + 1 ;
874 size += rdcap.addr_1 << 8;
875 size += rdcap.addr_2 << 16;
876 size += rdcap.addr_3 << 24;
877 }
878 return(size);
879 }
880
881 /*******************************************************\
882 * Get scsi driver to send a "are you ready?" command *
883 \*******************************************************/
884 sd_test_unit_ready(unit,flags)
885 int unit,flags;
886 {
887 struct scsi_test_unit_ready scsi_cmd;
888
889 bzero(&scsi_cmd, sizeof(scsi_cmd));
890 scsi_cmd.op_code = TEST_UNIT_READY;
891
892 return (sd_scsi_cmd(unit,
893 &scsi_cmd,
894 sizeof(scsi_cmd),
895 0,
896 0,
897 100000,
898 flags));
899 }
900
901 /*******************************************************\
902 * Prevent or allow the user to remove the tape *
903 \*******************************************************/
904 sd_prevent(unit,type,flags)
905 int unit,type,flags;
906 {
907 struct scsi_prevent scsi_cmd;
908
909 bzero(&scsi_cmd, sizeof(scsi_cmd));
910 scsi_cmd.op_code = PREVENT_ALLOW;
911 scsi_cmd.prevent=type;
912 return (sd_scsi_cmd(unit,
913 &scsi_cmd,
914 sizeof(scsi_cmd),
915 0,
916 0,
917 5000,
918 flags) );
919 }
920 /*******************************************************\
921 * Get scsi driver to send a "start up" command *
922 \*******************************************************/
923 sd_start_unit(unit,flags)
924 int unit,flags;
925 {
926 struct scsi_start_stop scsi_cmd;
927
928 bzero(&scsi_cmd, sizeof(scsi_cmd));
929 scsi_cmd.op_code = START_STOP;
930 scsi_cmd.start = 1;
931
932 return (sd_scsi_cmd(unit,
933 &scsi_cmd,
934 sizeof(scsi_cmd),
935 0,
936 0,
937 2000,
938 flags));
939 }
940
941 /*******************************************************\
942 * Tell the device to map out a defective block *
943 \*******************************************************/
944 sd_reassign_blocks(unit,block)
945 {
946 struct scsi_reassign_blocks scsi_cmd;
947 struct scsi_reassign_blocks_data rbdata;
948
949
950 bzero(&scsi_cmd, sizeof(scsi_cmd));
951 bzero(&rbdata, sizeof(rbdata));
952 scsi_cmd.op_code = REASSIGN_BLOCKS;
953
954 rbdata.length_msb = 0;
955 rbdata.length_lsb = sizeof(rbdata.defect_descriptor[0]);
956 rbdata.defect_descriptor[0].dlbaddr_3 = ((block >> 24) & 0xff);
957 rbdata.defect_descriptor[0].dlbaddr_2 = ((block >> 16) & 0xff);
958 rbdata.defect_descriptor[0].dlbaddr_1 = ((block >> 8) & 0xff);
959 rbdata.defect_descriptor[0].dlbaddr_0 = ((block ) & 0xff);
960
961 return(sd_scsi_cmd(unit,
962 &scsi_cmd,
963 sizeof(scsi_cmd),
964 &rbdata,
965 sizeof(rbdata),
966 5000,
967 0));
968 }
969
970 #define b2tol(a) (((unsigned)(a##_1) << 8) + (unsigned)a##_0 )
971
972 /*******************************************************\
973 * Get the scsi driver to send a full inquiry to the *
974 * device and use the results to fill out the disk *
975 * parameter structure. *
976 \*******************************************************/
977
978 int sd_get_parms(unit, flags)
979 {
980 struct sd_data *sd = sd_data + unit;
981 struct disk_parms *disk_parms = &sd->params;
982 struct scsi_mode_sense scsi_cmd;
983 struct scsi_mode_sense_data
984 {
985 struct scsi_mode_header header;
986 struct blk_desc blk_desc;
987 union disk_pages pages;
988 }scsi_sense;
989 int sectors;
990
991 /*******************************************************\
992 * First check if we have it all loaded *
993 \*******************************************************/
994 if(sd->flags & SDVALID) return(0);
995 /*******************************************************\
996 * First do a mode sense page 3 *
997 \*******************************************************/
998 if (sd_debug)
999 {
1000 bzero(&scsi_cmd, sizeof(scsi_cmd));
1001 scsi_cmd.op_code = MODE_SENSE;
1002 scsi_cmd.page_code = 3;
1003 scsi_cmd.length = 0x24;
1004 /*******************************************************\
1005 * do the command, but we don't need the results *
1006 * just print them for our interest's sake *
1007 \*******************************************************/
1008 if (sd_scsi_cmd(unit,
1009 &scsi_cmd,
1010 sizeof(scsi_cmd),
1011 &scsi_sense,
1012 sizeof(scsi_sense),
1013 2000,
1014 flags) != 0)
1015 {
1016 printf("could not mode sense (3) for unit %d\n", unit);
1017 return(ENXIO);
1018 }
1019 printf("unit %d: %d trk/zone, %d alt_sec/zone, %d alt_trk/zone, %d alt_trk/lun\n",
1020 unit,
1021 b2tol(scsi_sense.pages.disk_format.trk_z),
1022 b2tol(scsi_sense.pages.disk_format.alt_sec),
1023 b2tol(scsi_sense.pages.disk_format.alt_trk_z),
1024 b2tol(scsi_sense.pages.disk_format.alt_trk_v));
1025 printf(" %d sec/trk, %d bytes/sec, %d interleave, %d %d bytes/log_blk\n",
1026 b2tol(scsi_sense.pages.disk_format.ph_sec_t),
1027 b2tol(scsi_sense.pages.disk_format.bytes_s),
1028 b2tol(scsi_sense.pages.disk_format.interleave),
1029 sd_size(unit, flags),
1030 _3btol(scsi_sense.blk_desc.blklen));
1031 }
1032
1033
1034 /*******************************************************\
1035 * do a "mode sense page 4" *
1036 \*******************************************************/
1037 bzero(&scsi_cmd, sizeof(scsi_cmd));
1038 scsi_cmd.op_code = MODE_SENSE;
1039 scsi_cmd.page_code = 4;
1040 scsi_cmd.length = 0x20;
1041 /*******************************************************\
1042 * If the command worked, use the results to fill out *
1043 * the parameter structure *
1044 \*******************************************************/
1045 if (sd_scsi_cmd(unit,
1046 &scsi_cmd,
1047 sizeof(scsi_cmd),
1048 &scsi_sense,
1049 sizeof(scsi_sense),
1050 2000,
1051 flags) != 0)
1052 {
1053 printf("could not mode sense (4) for unit %d\n", unit);
1054 printf(" using ficticious geometry\n");
1055 /* use adaptec standard ficticious geometry */
1056 sectors = sd_size(unit, flags);
1057 disk_parms->heads = 64;
1058 disk_parms->sectors = 32;
1059 disk_parms->cyls = sectors/(64 * 32);
1060 disk_parms->secsiz = SECSIZE;
1061 }
1062 else
1063 {
1064
1065 if (sd_debug)
1066 {
1067 printf(" %d cyls, %d heads, %d precomp, %d red_write, %d land_zone\n",
1068 _3btol(&scsi_sense.pages.rigid_geometry.ncyl_2),
1069 scsi_sense.pages.rigid_geometry.nheads,
1070 b2tol(scsi_sense.pages.rigid_geometry.st_cyl_wp),
1071 b2tol(scsi_sense.pages.rigid_geometry.st_cyl_rwc),
1072 b2tol(scsi_sense.pages.rigid_geometry.land_zone));
1073 }
1074
1075 /*******************************************************\
1076 * KLUDGE!!(for zone recorded disks) *
1077 * give a number of sectors so that sec * trks * cyls *
1078 * is <= disk_size *
1079 \*******************************************************/
1080 disk_parms->heads = scsi_sense.pages.rigid_geometry.nheads;
1081 disk_parms->cyls = _3btol(&scsi_sense.pages.rigid_geometry.ncyl_2);
1082 disk_parms->secsiz = _3btol(&scsi_sense.blk_desc.blklen);
1083
1084 sectors = sd_size(unit, flags);
1085 sectors /= disk_parms->cyls;
1086 sectors /= disk_parms->heads;
1087 disk_parms->sectors = sectors; /* dubious on SCSI*/
1088 }
1089
1090 sd->flags |= SDVALID;
1091 return(0);
1092 }
1093
1094 /*******************************************************\
1095 * close the device.. only called if we are the LAST *
1096 * occurence of an open device *
1097 \*******************************************************/
1098 sdclose(dev)
1099 dev_t dev;
1100 {
1101 unsigned char unit, part;
1102 unsigned int old_priority;
1103
1104 unit = UNIT(dev);
1105 part = PARTITION(dev);
1106 sd_data[unit].partflags[part] &= ~SDOPEN;
1107 sd_data[unit].openparts &= ~(1 << part);
1108 if(sd_data[unit].openparts == 0) /* if all partitions closed */
1109 {
1110 sd_prevent(unit,PR_ALLOW,SCSI_SILENT|SCSI_ERR_OK);
1111 }
1112 return(0);
1113 }
1114
1115 /*******************************************************\
1116 * ask the scsi driver to perform a command for us. *
1117 * Call it through the switch table, and tell it which *
1118 * sub-unit we want, and what target and lu we wish to *
1119 * talk to. Also tell it where to find the command *
1120 * how long int is. *
1121 * Also tell it where to read/write the data, and how *
1122 * long the data is supposed to be *
1123 \*******************************************************/
1124 int sd_scsi_cmd(unit,scsi_cmd,cmdlen,data_addr,datalen,timeout,flags)
1125
1126 int unit,flags;
1127 struct scsi_generic *scsi_cmd;
1128 int cmdlen;
1129 int timeout;
1130 u_char *data_addr;
1131 int datalen;
1132 {
1133 struct scsi_xfer *xs;
1134 int retval;
1135 int s;
1136 struct sd_data *sd = sd_data + unit;
1137
1138 if(scsi_debug & PRINTROUTINES) printf("\nsd_scsi_cmd%d ",unit);
1139 if(sd->sc_sw) /* If we have a scsi driver */
1140 {
1141 xs = sd_get_xs(unit,flags); /* should wait unless booting */
1142 if(!xs)
1143 {
1144 printf("sd_scsi_cmd%d: controller busy"
1145 " (this should never happen)\n",unit);
1146 return(EBUSY);
1147 }
1148 xs->flags |= INUSE;
1149 /*******************************************************\
1150 * Fill out the scsi_xfer structure *
1151 \*******************************************************/
1152 xs->flags |= flags;
1153 xs->adapter = sd->ctlr;
1154 xs->targ = sd->targ;
1155 xs->lu = sd->lu;
1156 xs->retries = SD_RETRIES;
1157 xs->timeout = timeout;
1158 xs->cmd = scsi_cmd;
1159 xs->cmdlen = cmdlen;
1160 xs->data = data_addr;
1161 xs->datalen = datalen;
1162 xs->resid = datalen;
1163 xs->when_done = (flags & SCSI_NOMASK)
1164 ?(int (*)())0
1165 :sd_done;
1166 xs->done_arg = unit;
1167 xs->done_arg2 = (int)xs;
1168 retry: xs->error = XS_NOERROR;
1169 xs->bp = 0;
1170 retval = (*(sd->sc_sw->scsi_cmd))(xs);
1171 switch(retval)
1172 {
1173 case SUCCESSFULLY_QUEUED:
1174 s = splbio();
1175 while(!(xs->flags & ITSDONE))
1176 sleep(xs,PRIBIO+1);
1177 splx(s);
1178
1179 case HAD_ERROR:
1180 /*printf("err = %d ",xs->error);*/
1181 switch(xs->error)
1182 {
1183 case XS_NOERROR:
1184 retval = ESUCCESS;
1185 break;
1186 case XS_SENSE:
1187 retval = (sd_interpret_sense(unit,xs));
1188 break;
1189 case XS_DRIVER_STUFFUP:
1190 retval = EIO;
1191 break;
1192 case XS_TIMEOUT:
1193 if(xs->retries-- )
1194 {
1195 xs->flags &= ~ITSDONE;
1196 goto retry;
1197 }
1198 retval = EIO;
1199 break;
1200 case XS_BUSY:
1201 if(xs->retries-- )
1202 {
1203 xs->flags &= ~ITSDONE;
1204 goto retry;
1205 }
1206 retval = EIO;
1207 break;
1208 default:
1209 retval = EIO;
1210 printf("sd%d: unknown error category from scsi driver\n"
1211 ,unit);
1212 }
1213 break;
1214 case COMPLETE:
1215 retval = ESUCCESS;
1216 break;
1217 case TRY_AGAIN_LATER:
1218 if(xs->retries-- )
1219 {
1220 xs->flags &= ~ITSDONE;
1221 goto retry;
1222 }
1223 retval = EIO;
1224 break;
1225 default:
1226 retval = EIO;
1227 }
1228 sd_free_xs(unit,xs,flags);
1229 sdstart(unit); /* check if anything is waiting fr the xs */
1230 }
1231 else
1232 {
1233 printf("sd%d: not set up\n",unit);
1234 return(EINVAL);
1235 }
1236 return(retval);
1237 }
1238 /***************************************************************\
1239 * Look at the returned sense and act on the error and detirmine *
1240 * The unix error number to pass back... (0 = report no error) *
1241 \***************************************************************/
1242
1243 int sd_interpret_sense(unit,xs)
1244 int unit;
1245 struct scsi_xfer *xs;
1246 {
1247 struct scsi_sense_data *sense;
1248 int key;
1249 int silent;
1250
1251 /***************************************************************\
1252 * If the flags say errs are ok, then always return ok. *
1253 \***************************************************************/
1254 if (xs->flags & SCSI_ERR_OK) return(ESUCCESS);
1255 silent = (xs->flags & SCSI_SILENT);
1256
1257 sense = &(xs->sense);
1258 switch(sense->error_class)
1259 {
1260 case 7:
1261 {
1262 key=sense->ext.extended.sense_key;
1263 switch(key)
1264 {
1265 case 0x0:
1266 return(ESUCCESS);
1267 case 0x1:
1268 if(!silent)
1269 {
1270 printf("sd%d: soft error(corrected) ", unit);
1271 if(sense->valid)
1272 {
1273 printf("block no. %d (decimal)",
1274 (sense->ext.extended.info[0] <<24),
1275 (sense->ext.extended.info[1] <<16),
1276 (sense->ext.extended.info[2] <<8),
1277 (sense->ext.extended.info[3] ));
1278 }
1279 printf("\n");
1280 }
1281 return(ESUCCESS);
1282 case 0x2:
1283 if(!silent)printf("sd%d: not ready\n ",
1284 unit);
1285 return(ENODEV);
1286 case 0x3:
1287 if(!silent)
1288 {
1289 printf("sd%d: medium error ", unit);
1290 if(sense->valid)
1291 {
1292 printf("block no. %d (decimal)",
1293 (sense->ext.extended.info[0] <<24),
1294 (sense->ext.extended.info[1] <<16),
1295 (sense->ext.extended.info[2] <<8),
1296 (sense->ext.extended.info[3] ));
1297 }
1298 printf("\n");
1299 }
1300 return(EIO);
1301 case 0x4:
1302 if(!silent)printf("sd%d: non-media hardware failure\n ",
1303 unit);
1304 return(EIO);
1305 case 0x5:
1306 if(!silent)printf("sd%d: illegal request\n ",
1307 unit);
1308 return(EINVAL);
1309 case 0x6:
1310 /***********************************************\
1311 * If we are not open, then this is not an error *
1312 * as we don't have state yet. Either way, make *
1313 * sure that we don't have any residual state *
1314 \***********************************************/
1315 if(!silent)printf("sd%d: Unit attention.\n ", unit);
1316 sd_data[unit].flags &= ~(SDVALID | SDHAVELABEL);
1317 if (sd_data[unit].openparts)
1318 {
1319 return(EIO);
1320 }
1321 return(ESUCCESS); /* not an error if nothing's open */
1322 case 0x7:
1323 if(!silent)
1324 {
1325 printf("sd%d: attempted protection violation ",
1326 unit);
1327 if(sense->valid)
1328 {
1329 printf("block no. %d (decimal)\n",
1330 (sense->ext.extended.info[0] <<24),
1331 (sense->ext.extended.info[1] <<16),
1332 (sense->ext.extended.info[2] <<8),
1333 (sense->ext.extended.info[3] ));
1334 }
1335 printf("\n");
1336 }
1337 return(EACCES);
1338 case 0x8:
1339 if(!silent)
1340 {
1341 printf("sd%d: block wrong state (worm)\n ",
1342 unit);
1343 if(sense->valid)
1344 {
1345 printf("block no. %d (decimal)\n",
1346 (sense->ext.extended.info[0] <<24),
1347 (sense->ext.extended.info[1] <<16),
1348 (sense->ext.extended.info[2] <<8),
1349 (sense->ext.extended.info[3] ));
1350 }
1351 printf("\n");
1352 }
1353 return(EIO);
1354 case 0x9:
1355 if(!silent)printf("sd%d: vendor unique\n",
1356 unit);
1357 return(EIO);
1358 case 0xa:
1359 if(!silent)printf("sd%d: copy aborted\n ",
1360 unit);
1361 return(EIO);
1362 case 0xb:
1363 if(!silent)printf("sd%d: command aborted\n ",
1364 unit);
1365 return(EIO);
1366 case 0xc:
1367 if(!silent)
1368 {
1369 printf("sd%d: search returned\n ",
1370 unit);
1371 if(sense->valid)
1372 {
1373 printf("block no. %d (decimal)\n",
1374 (sense->ext.extended.info[0] <<24),
1375 (sense->ext.extended.info[1] <<16),
1376 (sense->ext.extended.info[2] <<8),
1377 (sense->ext.extended.info[3] ));
1378 }
1379 printf("\n");
1380 }
1381 return(ESUCCESS);
1382 case 0xd:
1383 if(!silent)printf("sd%d: volume overflow\n ",
1384 unit);
1385 return(ENOSPC);
1386 case 0xe:
1387 if(!silent)
1388 {
1389 printf("sd%d: verify miscompare\n ",
1390 unit);
1391 if(sense->valid)
1392 {
1393 printf("block no. %d (decimal)\n",
1394 (sense->ext.extended.info[0] <<24),
1395 (sense->ext.extended.info[1] <<16),
1396 (sense->ext.extended.info[2] <<8),
1397 (sense->ext.extended.info[3] ));
1398 }
1399 printf("\n");
1400 }
1401 return(EIO);
1402 case 0xf:
1403 if(!silent)printf("sd%d: unknown error key\n ",
1404 unit);
1405 return(EIO);
1406 }
1407 break;
1408 }
1409 case 0:
1410 case 1:
1411 case 2:
1412 case 3:
1413 case 4:
1414 case 5:
1415 case 6:
1416 {
1417 if(!silent)printf("sd%d: error class %d code %d\n",
1418 unit,
1419 sense->error_class,
1420 sense->error_code);
1421 if(sense->valid)
1422 if(!silent)printf("block no. %d (decimal)\n",
1423 (sense->ext.unextended.blockhi <<16),
1424 + (sense->ext.unextended.blockmed <<8),
1425 + (sense->ext.unextended.blocklow ));
1426 }
1427 return(EIO);
1428 }
1429 }
1430
1431
1432
1433
1434 int
1435 sdsize(dev_t dev)
1436 {
1437 int unit = UNIT(dev), part = PARTITION(dev), val;
1438 struct sd_data *sd;
1439
1440 if (unit >= NSD)
1441 return(-1);
1442
1443 sd = &sd_data[unit];
1444 if((sd->flags & SDINIT) == 0) return(-1);
1445 if (sd == 0 || (sd->flags & SDHAVELABEL) == 0)
1446 val = sdopen (MAKESDDEV(major(dev), unit, RAW_PART), FREAD, S_IFBLK, 0);
1447 if ( val != 0 || sd->flags & SDWRITEPROT)
1448 return (-1);
1449
1450 return((int)sd->disklabel.d_partitions[part].p_size);
1451 }
1452
1453 sddump()
1454 {
1455 printf("sddump() -- not implemented\n");
1456 return(-1);
1457 }
1458
1459
1460
1461
1462
1463