1 /*
2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Sony Corp. and Kazumasa Utashiro of Software Research Associates, Inc.
7 *
8 * %sccs.include.redist.c%
9 *
10 * from: $Hdr: sd.c,v 4.300 91/06/27 20:42:56 root Rel41 $ SONY
11 *
12 * @(#)sd.c 8.2 (Berkeley) 09/23/93
13 */
14 #define dkblock(bp) bp->b_blkno
15
16 /*
17 * Copyright (c) 1987-1991 by SONY Corporation.
18 */
19
20 #include "sd.h"
21 #if NSD > 0
22
23 #include <sys/param.h>
24 #include <sys/buf.h>
25 #include <sys/proc.h>
26 #include <sys/user.h>
27 #include <sys/dkstat.h>
28 #include <sys/uio.h>
29 #include <sys/kernel.h>
30 #include <sys/reboot.h>
31 #include <sys/ioctl.h>
32 #include <sys/systm.h>
33 #include <sys/mtio.h>
34 #include <sys/stat.h>
35 #include <sys/disklabel.h>
36 #include <vm/vm.h>
37 #include <sys/syslog.h>
38
39 #include <ufs/ffs/fs.h>
40
41 # include <machine/cpu.h>
42
43 #ifdef IPC_MRX
44 # include "../iop/iopvar.h"
45 # include "../ipc/newsipc.h"
46 #endif
47
48 #ifdef CPU_SINGLE
49 # include <news3400/hbdev/hbvar.h>
50 # include <news3400/iodev/ioptohb.h>
51 #endif
52
53 #include <news3400/iodev/scsireg.h>
54 #include <news3400/iodev/scu.h>
55 #include <news3400/iodev/dkio.h>
56 #include <news3400/iodev/sdreg.h>
57
58 #define sce_sdecode sce_hdecode
59
60 #define dev2unit(x) ((minor(x) & ~0x80) >> 3)
61 #define dev2part(x) (minor(x) & 0x7)
62
63 /* /sys/sys/file.h */
64 #define FREAD 00001 /* descriptor read/receive'able */
65 #define FWRITE 00002 /* descriptor write/send'able */
66
67 #define PART_A 0
68 #define PART_B 1
69 #define PART_C 2
70 #define PART_D 3
71 #define PART_E 4
72 #define PART_F 5
73 #define PART_G 6
74 #define PART_H 7
75
76 #define MAXPROBERETRY 100
77 #define NRETRY 10
78 #define MAXHRDERR 100
79 #define MAXRETRYCNT 16
80
81 #define SDBSIZE1K (DEV_BSIZE * 2)
82 #define MAXSDPHYS ((NSCMAP - 1) * NBPG)
83
84 #define D100MSEC 100000
85
86 #if OD_STOPTIME < 1
87 # define OD_STOPTIME 5
88 #endif /* OD_STOPTIME < 1 */
89
90 #define FORMAT_MODE_CORRUPTED 0x31
91 #define ONLY_ONE 1
92
93 /************** PARTITIONS *************************************/
94
95 #define PART_UNUSED (0)
96 #define PART_SPEC (-1)
97 #define PART_CALCF (-2)
98 #define PART_CALCG (-3)
99
100 struct defpart {
101 int range_min;
102 int range_max;
103 int partsize[PNUM];
104 };
105
106 struct defpart defpart_std[] = {
107 {
108 0, /* range_min */
109 20, /* range_max */
110
111 PART_SPEC, /* A: */
112 PART_UNUSED, /* B: */
113 PART_SPEC, /* C: */
114 PART_UNUSED, /* D: */
115 PART_UNUSED, /* E: */
116 PART_UNUSED, /* F: */
117 PART_UNUSED, /* G: */
118 PART_UNUSED, /* H: */
119 },
120 {
121 20, /* range_min */
122 61, /* range_max */
123
124 15884, /* A: */
125 10032, /* B: */
126 PART_SPEC, /* C: */
127 15884, /* D: */
128 PART_UNUSED, /* E: */
129 PART_CALCF, /* F: */
130 PART_CALCG, /* G: */
131 PART_UNUSED, /* H: */
132 },
133 {
134 61, /* range_min */
135 206, /* range_max */
136
137 15884, /* A: */
138 33440, /* B: */
139 PART_SPEC, /* C: */
140 15884, /* D: */
141 55936, /* E: */
142 PART_CALCF, /* F: */
143 PART_CALCG, /* G: */
144 PART_UNUSED, /* H: */
145 },
146 {
147 206, /* range_min */
148 356, /* range_max */
149
150 15884, /* A: */
151 33440, /* B: */
152 PART_SPEC, /* C: */
153 15884, /* D: */
154 55936, /* E: */
155 PART_CALCF, /* F: */
156 PART_CALCG, /* G: */
157 291346, /* H: */
158 },
159 {
160 356, /* range_min */
161 99999999, /* range_max */
162
163 15884, /* A: */
164 66880, /* B: */
165 PART_SPEC, /* C: */
166 15884, /* D: */
167 307200, /* E: */
168 PART_CALCF, /* F: */
169 PART_CALCG, /* G: */
170 291346, /* H: */
171 },
172 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
173 };
174
175 /************* ADDITIONAL SENSE ERROR CODES *************************/
176
177 struct msg_list {
178 int ml_code; /* message code */
179 int ml_msglvl; /* message level */
180 char *ml_msgstr; /* message string */
181 };
182
183 #define sdskeylist skeylist
184
185 struct msg_list ecodelist_mo[] = {
186 { 0x80, 0, NULL },
187 { 0x81, 0, NULL },
188 { 0x82, 0, NULL },
189 { 0x83, 0, NULL },
190
191 { -1, 0, NULL }
192 };
193
194 /************** Ref. sd_var.c ********************************/
195
196 extern struct iop/**/_ctlr *sdminfo[];
197 extern struct iop/**/_device *sddinfo[];
198 extern struct iop/**/_device *sdip[][MAXSLAVE];
199
200 extern struct buf rsdbuf[]; /* buffer for raw I/O */
201 extern struct buf csdbuf[]; /* buffer for controll */
202 extern struct buf sdutab[]; /* per drive buffers */
203
204 extern struct sdc_softc sdc_softc[];
205 extern struct sdd_softc sdd_softc[];
206 extern u_char sd_b_openf[][PNUM];
207 extern u_char sd_c_openf[][PNUM];
208
209 extern struct scsi kernscsi[];
210 extern struct sdst sdstdrv[];
211 extern struct disklabel sdlabel[];
212 extern struct size sdsizedrv[][PNUM];
213
214 extern u_char sdc_rsense[][RSEN_CNT];
215
216 extern struct sync_param sd_sync_param[];
217
218 extern int nsd;
219 extern int nsdc;
220
221 /************** Ref. sddefs.c *********************************/
222
223 extern struct sddevinfo sddevinfo[];
224
225 /**************************************************************/
226
227 extern struct msg_list skeylist[];
228 extern struct msg_list ecodelist[];
229
230 extern int boothowto;
231 extern int rsense_msg_disp; /* RSENSE-message display flag */
232 extern int mo_disp_format; /* MO format mode display flag */
233
234 int sd_ignore_error;
235
236 static int re_init_done;
237
238 static u_char sdwork[2340]; /* buffer for error recovery */
239 static u_char sdtmp[DEV_BSIZE]; /* buffer for temporary */
240 #ifdef mips
241 volatile static int sdtmp_stat = 0; /* status of sdtmp */
242 #else
243 static int sdtmp_stat = 0; /* status of sdtmp */
244 #endif
245
246 char pname[] = "abcdefgh";
247
248 struct scsi *get_scsi();
249 struct sc_map *get_sc_map();
250 struct sc_inq *get_sc_inq();
251
252 int sdprobe(), sdslave(), sdattach(), sddgo(), sdintr();
253 int sdwstart, sdwatch(), sdstop(); /* Have started guardian */
254 void sdexec();
255
256 static sd_check(), sd_tstdrv(), sd_other_pages(), sd_err_rcv(), sd_synctr_on();
257 static disklabel2sdst(), sdst2disklabel(), sd_scu_exec();
258
259 #ifdef CPU_SINGLE
260 struct hb_driver sdcdriver =
261 {sdprobe, sdslave, sdattach, sddgo, sdintr, "sd", sddinfo, "sdc", sdminfo};
262 #else
263 struct iop_driver sdcdriver =
264 {sdprobe, sdslave, sdattach, sddgo, "sd", sddinfo, "sdc", sdminfo};
265 #endif
266
267 /*ARGSUSED*/
268 sdprobe(im)
269 struct iop/**/_ctlr *im;
270 {
271 static int sdd_init = 0;
272 register struct sc_inq *sci;
273 register int ctlr;
274 register int fw;
275 int i;
276
277 if (sdd_init == 0) {
278 sdd_init++;
279 for (i = 0; i < nsd; i++)
280 sdd_softc[i].sdd_start = -2;
281 }
282
283 sci = get_sc_inq(im->im_intr);
284 ctlr = im->im_ctlr;
285 /*
286 * Check device type
287 * 0x00: Direct access device.
288 * 0x01: Sequential access device.
289 * 0x04: Write-once read-multiple device.
290 * 0x05: Read-only Direct-access device.
291 * 0x7f: Specified device is nonexistent.
292 */
293 fw = sdc_softc[ctlr].sdc_firmware & ~SDCFW_DEVMASK;
294
295 switch (sci->sci_devtype) {
296
297 case 0x00:
298 /*
299 * Assumed that the device is HD.
300 * Later, distinguish MO from HD.
301 */
302 sdc_softc[ctlr].sdc_firmware = fw | SDCFW_HD;
303 break;
304
305 default:
306 /*
307 * device type mis-match
308 */
309 return (0);
310 }
311
312 /*
313 * Set interrupt handler routine
314 */
315 if (set_inthandler(im, sdintr) == 0)
316 return (0);
317
318 return (1);
319 }
320
321
322 /*ARGSUSED*/
sdslave(ii,reg,intr)323 sdslave(ii, reg, intr)
324 register struct iop/**/_device *ii;
325 caddr_t reg;
326 int intr;
327 {
328 register struct scsi *sc;
329
330 sc = get_scsi(intr);
331 sdip[ii->ii_ctlr][ii->ii_slave] = ii;
332 ii->ii_intr = intr;
333
334 /*
335 * check what the device is.
336 */
337 if ((ii->ii_type = sd_check(ii, sc)) < 0)
338 goto bad_slave;
339
340 /*
341 * set up ERROR RECOVERY PARAMETERS
342 */
343 if (sd_err_rcv(ii, sc) < 0)
344 goto bad_slave;
345
346 /*
347 * set up OTHER PARAMETERS
348 */
349 if (sd_other_pages(ii, sc) < 0)
350 goto bad_slave;
351
352 /*
353 * set up Synchronous Transfer
354 */
355 sd_synctr_on(ii, sc);
356
357 return (1);
358
359 bad_slave:
360 /*
361 * no such slave
362 */
363 ii->ii_intr = -1;
364 return (0);
365 }
366
identity_check(sci,capacity,unit)367 identity_check(sci, capacity, unit)
368 register struct sc_inq *sci;
369 int capacity;
370 int unit;
371 {
372 register struct sddevinfo *sdi;
373 register u_char *id_name;
374 register int index;
375 register int i;
376 int id_pass;
377
378 id_name = sci->sci_vendid;
379 while (*id_name == ' ')
380 id_name++;
381
382 index = UNKNOWN_DISK;
383 id_pass = 0;
384 for (sdi = sddevinfo; sdi->id_len >= 0; sdi++) {
385 /*
386 * check vendor & product ID
387 */
388 if (strncmp(id_name, sdi->id_name, sdi->id_len) != 0)
389 continue;
390 id_pass = sdi - sddevinfo;
391
392 /*
393 * check revision
394 */
395 if (strncmp(sdi->revs, sci->sci_revision, 4) == 0)
396 index = id_pass;
397 else {
398 for (i = 0; i < 4; i++) {
399 if (*(sdi->revs + i) == '?')
400 continue;
401 if (*(sdi->revs + i) != sci->sci_revision[i])
402 break;
403 }
404 if (i < 4)
405 continue;
406 }
407
408 /*
409 * check capacity
410 */
411 if (capacity == -1)
412 break;
413 if (sdi->capacity == -1) {
414 printf("sd%d: capacity=0x%x(%d)\n",
415 unit, capacity, capacity);
416 break;
417 }
418 if (capacity == sdi->capacity)
419 break;
420 }
421 if (index == 0)
422 index = id_pass;
423
424 return (index);
425 }
426
search_index(type)427 search_index(type)
428 register int type;
429 {
430 register struct sddevinfo *sdi;
431 register int i;
432 int index;
433
434 index = UNKNOWN_DISK;
435 i = 0;
436 for (sdi = sddevinfo; sdi->id_len > 0; sdi++) {
437 if (sdi->type == type) {
438 index = i;
439 break;
440 }
441 i++;
442 }
443 return (index);
444 }
445
446 static
sd_check(ii,sc)447 sd_check(ii, sc)
448 register struct iop/**/_device *ii;
449 register struct scsi *sc;
450 {
451 register struct sc_inq *sci;
452 register struct sc_rcap *scr;
453 register int intr;
454 register int slave;
455 register int unit;
456 struct sdc_softc *sdc;
457 struct sdd_softc *sdd;
458 struct sc_extnd *sce;
459 int retrycnt;
460 int index;
461 int media_in;
462
463 intr = ii->ii_intr;
464 slave = ii->ii_slave;
465 unit = ii->ii_unit;
466 sdc = &sdc_softc[ii->ii_ctlr];
467 sdd = &sdd_softc[unit];
468 scr = (struct sc_rcap *)sc->sc_param;
469 sce = (struct sc_extnd *)&sdc_rsense[ii->ii_ctlr][0];
470
471 /*
472 * check if the logical unit is ready.
473 * (by TEST UNIT READY command)
474 */
475 media_in = sd_tstdrv(ii, sc);
476 if (media_in < 0)
477 return (-3);
478
479 /*
480 * Get controller and drive information.
481 * (by INQUIRY command)
482 */
483 retrycnt = 0;
484 sci = get_sc_inq(intr);
485 loop_inq:
486 if (retrycnt++ > MAXPROBERETRY)
487 return (-1);
488
489 scop_inquiry(intr, sc, slave, SCSI_INTDIS, sizeof(struct sc_inq), sci);
490 sc->sc_tstatus &= TGSTMASK;
491
492 if (sc->sc_istatus != INST_EP || sc->sc_tstatus != TGST_GOOD) {
493
494 bzero((caddr_t)sce, RSEN_CNT);
495 scop_rsense(intr, sc, slave, SCSI_INTDIS, RSEN_CNT,
496 (caddr_t)sce);
497 sc->sc_tstatus &= TGSTMASK;
498 if (sc->sc_istatus != INST_EP || sc->sc_tstatus != TGST_GOOD)
499 return (-1);
500 if (sce->sce_extend != 0x70)
501 goto loop_inq;
502
503 switch (sce->sce_sdecode) {
504
505 case 0x04: /* Drive Not Ready */
506 case 0x28: /* Medium Changed */
507 case 0x29: /* Power On or Reset or Bus Device Reset */
508 case 0x2a: /* Mode Select Parameter Changed */
509 break;
510
511 default:
512 return (-1);
513 }
514 DELAY(D100MSEC); /* wait 100 ms. */
515 goto loop_inq;
516 }
517
518 index = identity_check(sci, -1, unit);
519
520 switch (sddevinfo[index].type) {
521
522 case SMO_S501:
523 case SMO_S501_ISO:
524 case SMO_S501_ISO2:
525 sdc->sdc_firmware =
526 SDCFW_MO | (sdc->sdc_firmware & ~SDCFW_DEVMASK);
527 break;
528
529 defaults:
530 break;
531 }
532
533 if (sci->sci_qual & 0x80) {
534 /*
535 * removable medium device
536 */
537 sdc->sdc_firmware |= SDCFW_RMB;
538 if ((media_in == 0) || ((sdc->sdc_firmware & SDCFW_MO) == 0))
539 return (index);
540 }
541
542 /****************/
543 /* HD & MO only */
544 /****************/
545 /*
546 * Get drive capacity
547 * (by READ CAPACITY command)
548 */
549 retrycnt = 0;
550 loop_rcap:
551 if (retrycnt++ > MAXPROBERETRY)
552 return (-4);
553
554 scop_rcap(intr, sc, slave, SCSI_INTDIS, 8, (caddr_t)0);
555 sc->sc_tstatus &= TGSTMASK;
556 if (sc->sc_istatus != INST_EP)
557 return (-5);
558 if (sc->sc_tstatus == TGST_CC) {
559 bzero((caddr_t)sce, RSEN_CNT);
560 scop_rsense(intr, sc, slave, SCSI_INTDIS, RSEN_CNT,
561 (caddr_t)sce);
562 sc->sc_tstatus &= TGSTMASK;
563 if (sc->sc_istatus != INST_EP || sc->sc_tstatus != TGST_GOOD)
564 return (-6);
565 if (sderrordisp((caddr_t)sce, ii) == FORMAT_MODE_CORRUPTED) {
566 scr->scr_nblock = 0;
567 scr->scr_blocklen = DEV_BSIZE;
568 sdd->sdd_flags |= SDDF_NONFMT;
569 } else {
570 DELAY(D100MSEC); /* wait 100 ms. */
571 goto loop_rcap;
572 }
573 }
574 else if (sc->sc_tstatus != TGST_GOOD) {
575 DELAY(D100MSEC); /* wait 100 ms. */
576 goto loop_rcap;
577 }
578
579 sdd->sdd_nsect = scr->scr_nblock + 1;
580 sdd->sdd_sectsize = scr->scr_blocklen;
581
582 index = identity_check(sci, scr->scr_nblock +1, unit);
583
584 return (index);
585 }
586
587 static
sd_tstdrv(ii,sc)588 sd_tstdrv(ii, sc)
589 register struct iop/**/_device *ii;
590 register struct scsi *sc;
591 {
592 register struct sc_extnd *sce;
593 register int intr;
594 register int slave;
595 register int retrycnt;
596 struct sdc_softc *sdc;
597 struct sdd_softc *sdd;
598
599 sdc = &sdc_softc[ii->ii_ctlr];
600 sdd = &sdd_softc[ii->ii_unit];
601
602 intr = ii->ii_intr;
603 slave = ii->ii_slave;
604 sce = (struct sc_extnd *)&sdc_rsense[ii->ii_ctlr][0];
605 retrycnt = 0;
606 loop_tst:
607 if (retrycnt++ > MAXPROBERETRY)
608 return (-1);
609
610 scop_tst(intr, sc, slave, SCSI_INTDIS);
611 sc->sc_tstatus &= TGSTMASK;
612 if (sc->sc_istatus != INST_EP) {
613 DELAY(D100MSEC); /* wait 100 ms. */
614 goto loop_tst;
615 }
616
617 switch (sc->sc_tstatus) {
618
619 case TGST_CC:
620 /* Get error code */
621 bzero((caddr_t)sce, RSEN_CNT);
622 scop_rsense(intr, sc, slave, SCSI_INTDIS, RSEN_CNT,
623 (caddr_t)sce);
624 sc->sc_tstatus &= TGSTMASK;
625 if (sc->sc_istatus != INST_EP || sc->sc_tstatus != TGST_GOOD) {
626 DELAY(D100MSEC); /* wait 100 ms. */
627 goto loop_tst;
628 }
629
630 if (sce->sce_extend != 0x70)
631 goto loop_tst;
632
633 switch (sce->sce_skey) {
634
635 case 0x0: /* No Sense */
636 case 0x4: /* Hardware error */
637 case 0x6: /* Unit attention */
638 goto loop_tst;
639
640 case 0x2: /* Not ready */
641 switch (sce->sce_sdecode) {
642
643 case 0x04: /* Not ready */
644 /*
645 * Drive not ready... so start..
646 */
647 scop_stst(intr, sc, slave, SCSI_INTDIS, SDSS_START);
648 DELAY(D100MSEC * 10); /* wait 1 sec. */
649 goto loop_tst;
650
651 case 0x0a: /* No Disk *//*MO*/
652 default:
653 DELAY(D100MSEC);
654 goto loop_tst;
655 }
656 break;
657
658 case 0x03:
659 if (sce->sce_sdecode == FORMAT_MODE_CORRUPTED)
660 return (1); /* ignore error */
661 /* fall through */
662
663 default:
664 return (-2);
665 }
666 break;
667
668 case TGST_BUSY:
669 goto loop_tst;
670
671 case TGST_GOOD:
672 break;
673
674 default:
675 return (-3);
676 }
677
678 return (1);
679 }
680
681 static
sd_other_pages(ii,sc)682 sd_other_pages(ii, sc)
683 register struct iop/**/_device *ii;
684 register struct scsi *sc;
685 {
686 register struct sddevinfo *sdi;
687 char **p;
688 char *page;
689 int length;
690 int retrycnt;
691 int len;
692
693 sdi = &sddevinfo[ii->ii_type];
694 if ((p = sdi->other_pages) == NULL)
695 return (0);
696
697 /*
698 * set other parameters
699 */
700 while (page = *p++) {
701 retrycnt = 0;
702 loop_other_pages:
703 bzero((caddr_t)sdtmp, 4);
704 length = *(page + 1) + 2;
705 bcopy(page, &sdtmp[4], length);
706 if (retrycnt++ > MAXPROBERETRY)
707 return (-1);
708
709 scop_mselect(ii->ii_intr, sc, ii->ii_slave, SCSI_INTDIS,
710 (SDM_PF<<24) + length +4, (caddr_t)sdtmp);
711 sc->sc_tstatus &= TGSTMASK;
712 if ((sc->sc_istatus != INST_EP)
713 || (sc->sc_tstatus != TGST_GOOD)) {
714 struct sc_extnd *sce;
715
716 sce = (struct sc_extnd *)&sdc_rsense[ii->ii_ctlr][0];
717 scop_rsense(ii->ii_intr, sc, ii->ii_slave, SCSI_INTDIS,
718 RSEN_CNT, (caddr_t)sce);
719 switch (sce->sce_skey) {
720
721 case 0x00:
722 case 0x02:
723 case 0x04:
724 case 0x06:
725 DELAY(D100MSEC); /* 100 ms. */
726 goto loop_other_pages;
727
728 default:
729 return (-1);
730 }
731 }
732 }
733
734 if (sdi->firm_flags & FIRM_CACHE_ON)
735 sdc_softc[ii->ii_ctlr].sdc_firmware |= SDCFW_CACHE;
736 else
737 sdc_softc[ii->ii_ctlr].sdc_firmware &= ~SDCFW_CACHE;
738
739 return (1);
740 }
741
742 static
sd_err_rcv(ii,sc)743 sd_err_rcv(ii, sc)
744 register struct iop/**/_device *ii;
745 register struct scsi *sc;
746 {
747 register struct sdc_softc *sdc;
748 register int intr;
749 register int slave;
750 register int len;
751 struct sc_extnd *sce;
752 struct sdd_softc *sdd;
753 struct sddevinfo *sdi;
754 int retrycnt;
755 char *erp_page;
756
757 intr = ii->ii_intr;
758 slave = ii->ii_slave;
759 sdc = &sdc_softc[ii->ii_ctlr];
760 sdd = &sdd_softc[ii->ii_unit];
761 sdi = &sddevinfo[ii->ii_type];
762 sce = (struct sc_extnd *)&sdc_rsense[ii->ii_ctlr][0];
763
764 /*
765 * set Default DISK sector size
766 */
767 if (sdd->sdd_sectsize == 0)
768 sdd->sdd_sectsize = DEV_BSIZE;
769
770
771 if (sdi->ERP_page == NULL) {
772 /*
773 * use default error recovery parameters
774 */
775 sdc->sdc_firmware |= SDCFW_DEFMODE;
776 return (0);
777 }
778
779 if (sdi->firm_flags & FIRM_AWRE)
780 sdc->sdc_firmware |= SDCFW_AWRE;
781 if (sdi->firm_flags & FIRM_ARRE)
782 sdc->sdc_firmware |= SDCFW_ARRE;
783 /*
784 * set ERROR RECOVERY PARAMETERS
785 */
786 loop_err_rcv:
787 bzero((caddr_t)sdtmp, 4);
788 erp_page = sdi->ERP_page;
789 len = *(erp_page + 1) + 2;
790 bcopy(erp_page, &sdtmp[4], len);
791
792 scop_mselect(intr, sc, slave, SCSI_INTDIS,
793 (SDM_PF<<24) + len +4, (caddr_t)sdtmp);
794 sc->sc_tstatus &= TGSTMASK;
795 if (sc->sc_istatus != INST_EP || sc->sc_tstatus != TGST_GOOD) {
796 if (sc->sc_tstatus == TGST_CC) {
797 bzero((caddr_t)sce, RSEN_CNT);
798 scop_rsense(intr, sc, slave, SCSI_INTDIS, RSEN_CNT,
799 (caddr_t)sce);
800 if (sce->sce_sdecode == 0x2a) {
801 /* mode select parameter changed */
802 goto ercv_done;
803 } else if (sce->sce_skey == 0x6) {
804 /* unit attention */
805 goto loop_err_rcv;
806 }
807 }
808 /*
809 * use default ERROR RECOVERY mode
810 */
811 sdc->sdc_firmware |= SDCFW_DEFMODE;
812 sdc->sdc_firmware &= ~(SDCFW_AWRE|SDCFW_ARRE);
813 }
814
815 ercv_done:
816
817 return (1);
818 }
819
820 static
sd_synctr_on(ii,sc)821 sd_synctr_on(ii, sc)
822 register struct iop/**/_device *ii;
823 register struct scsi *sc;
824 {
825 register struct sddevinfo *sdi;
826 register struct sync_param *syncp;
827
828 sdi = &sddevinfo[ii->ii_type];
829
830 if (sdi->firm_flags & FIRM_SYNCTR) {
831 scinit(sc, ii->ii_slave, DEV_BSIZE);
832 sc->sc_opcode = SCOP_TST;
833 sc->sc_message = MSG_EXTND; /* extended message */
834 sc->sc_param[0] = MSG_EXTND;
835 sc->sc_param[1] = 0x03;
836 sc->sc_param[2] = 0x01; /* synchronous transfer */
837 sc->sc_param[3] = sdi->tr_period; /* transfer period */
838 sc->sc_param[4] = sdi->tr_offset; /* REQ offset */
839
840 if (sdc_softc[ii->ii_ctlr].sdc_firmware & SDCFW_CACHE)
841 sc->sc_tstatus |= TS_CONTR_ON; /* contiguous TR ON */
842 else
843 sc->sc_tstatus |= TS_CONTR_OFF; /* contiguous TR OFF */
844
845 #ifdef news1800
846 if (scsi_berr_bug() != 0) {
847 sc->sc_tstatus &= ~TS_CONTR_ON;
848 sc->sc_tstatus |= TS_CONTR_OFF;
849 }
850 #endif
851
852 if (sc->sc_tstatus & TS_CONTR_OFF)
853 sdc_softc[ii->ii_ctlr].sdc_firmware &= ~SDCFW_CONTR;
854 else
855 sdc_softc[ii->ii_ctlr].sdc_firmware |= SDCFW_CONTR;
856
857 sc_go(ii->ii_intr, sc, SCSI_INTDIS);
858
859 syncp = &sd_sync_param[ii->ii_unit];
860 syncp->tr_period = sc->sc_param[3];
861 syncp->tr_offset = sc->sc_param[4];
862 if (sc->sc_param[4])
863 sdd_softc[ii->ii_unit].sdd_flags |= SDDF_SYNCTR;
864 }
865 }
866
867
sdattach(ii)868 sdattach(ii)
869 register struct iop/**/_device *ii;
870 {
871 register int unit;
872 register int i;
873 struct sdc_softc *sdc;
874 struct sdd_softc *sdd;
875 int dummy;
876
877 sdc = &sdc_softc[ii->ii_ctlr];
878 sdc->sdc_timeo = 60; /* timeout 60 sec */
879
880 unit = ii->ii_unit;
881 sdd = &sdd_softc[unit];
882 sdd->sdd_stoptime = OD_STOPTIME; /* REMOVABLE MEDIA */
883 sdd->sdd_start = -2;
884
885 sdmaptype(ii);
886
887 if (sdwstart == 0) {
888 sdwstart++;
889 timeout(sdwatch, (caddr_t)0, hz);
890 timeout(sdstop, (caddr_t)0, hz);
891 }
892
893 /*
894 * initialize open flag
895 */
896 for (i = 0; i < PNUM; i++) {
897 sd_b_openf[unit][i] = 0;
898 sd_c_openf[unit][i] = 0;
899 }
900
901 if (re_init_done > 0)
902 return;
903
904 if (sdc->sdc_firmware & SDCFW_HD) {
905 /*
906 * If device is Hard Disk,
907 * then get partition information.
908 */
909 sdrpartinfo(ii);
910 dummy = DEV_BSIZE * sdstdrv[unit].rps * sdstdrv[unit].nsect;
911 } else
912 dummy = DEV_BSIZE * 40 * 31;
913
914 if (ii->ii_dk >= 0 && dummy)
915 dk_wpms[ii->ii_dk] = dummy / (2 * 1000000);
916 }
917
sdmaptype(ii)918 sdmaptype(ii)
919 register struct iop/**/_device *ii;
920 {
921 printf("sd%d: %s\n", ii->ii_unit, sddevinfo[ii->ii_type].call_name);
922 }
923
924 int sd_b_major = -1;
925
sd_b_open(dev,flag)926 sd_b_open(dev, flag)
927 dev_t dev;
928 int flag;
929 {
930 sd_b_major = major(dev);
931 return (_sdopen(dev, flag, S_IFBLK));
932 }
933
934 int sd_c_major = -1;
935
sd_c_open(dev,flag)936 sd_c_open(dev, flag)
937 dev_t dev;
938 int flag;
939 {
940 sd_c_major = major(dev);
941 return (_sdopen(dev, flag, S_IFCHR));
942 }
943
_sdopen(dev,flag,fmt)944 _sdopen(dev, flag, fmt)
945 register dev_t dev;
946 int flag;
947 int fmt;
948 {
949 register struct iop/**/_device *ii;
950 register struct sdd_softc *sdd;
951 register struct sdc_softc *sdc;
952 register struct sddevinfo *sdi;
953 register int unit;
954 register int i;
955 u_char *sdopfp;
956 u_char old_sdopf;
957 int media_changed;
958 int s;
959 int stat;
960 struct scsi uscsi;
961
962 unit = dev2unit(dev);
963 if (unit >= nsd || (ii = sddinfo[unit]) == 0 || ii->ii_alive == 0)
964 return (ENXIO);
965
966 sdd = &sdd_softc[unit];
967 sdc = &sdc_softc[ii->ii_ctlr];
968 sdi = &sddevinfo[ii->ii_type];
969
970 if (sdd->sdd_flags & SDDF_XUSE)
971 return (EBUSY);
972
973 /*
974 * LOCK while sdstop() running.
975 */
976 s = splclock();
977 while (sdc->sdc_state & SDCS_SCUNLOCK) {
978 sdc->sdc_state |= SDCS_OPEN_WAIT;
979 sleep((caddr_t)sdc, PRIBIO);
980 }
981 splx(s);
982
983 /*
984 * LOCK sdtmp buffer
985 */
986 s = splclock();
987 while (sdtmp_stat & B_BUSY) {
988 sdtmp_stat |= B_WANTED;
989 sleep((caddr_t)sdtmp, PRIBIO);
990 }
991 sdtmp_stat |= B_BUSY;
992 splx(s);
993 sdd->sdd_flags |= SDDF_GETTMP;
994
995 if ((fmt & S_IFMT) == S_IFBLK)
996 sdopfp = &sd_b_openf[unit][dev2part(dev)];
997 else
998 sdopfp = &sd_c_openf[unit][dev2part(dev)];
999 old_sdopf = *sdopfp;
1000 if (old_sdopf <= 1)
1001 *sdopfp += 1; /* 1: 1st open (ONLY_ONE) */
1002 /* 2: already opened */
1003 stat = 0;
1004 media_changed = 0;
1005
1006 /*
1007 * From here on until pre_open_done is only for removable devices
1008 */
1009 if ((sdc->sdc_firmware & SDCFW_RMB) == 0)
1010 goto pre_open_done;
1011
1012 if ((minor(dev) & 0x80) || (dev == rootdev))
1013 sdd->sdd_stoptime = 0x7fffffff; /*XXX*/
1014
1015 /*
1016 * Start Unit
1017 */
1018 s = splclock(); /* inhibit clock interrupt */
1019 i = sdd->sdd_start;
1020 sdd->sdd_start = sdd->sdd_stoptime;
1021 splx(s);
1022 if (i <= 0) {
1023 scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize);
1024 uscsi.sc_opcode = SCOP_STST;
1025 uscsi.sc_count = SDSS_START;
1026
1027 if (sdcmd(dev, &uscsi)) {
1028 sdd->sdd_start = i;
1029 if ((flag & FWRITE) == 0)
1030 goto sdopen_setup;
1031 stat = EIO;
1032 goto pre_open_done;
1033 }
1034 }
1035
1036 /*
1037 * prevent medium removal
1038 */
1039 scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize);
1040 uscsi.sc_opcode = SCOP_MEDRMV;
1041 uscsi.sc_count = SDRMV_PREV;
1042 if (sdcmd(dev, &uscsi)) {
1043 stat = EIO;
1044 goto pre_open_done;
1045 }
1046 sdd->sdd_flags |= SDDF_INHRMV;
1047
1048 sdopen_setup:
1049 if ((sdd->sdd_flags & SDDF_SAMEDSK) == SDDF_DSKCHGD) {
1050 sdd->sdd_flags |= SDDF_SAMEDSK;
1051 media_changed = 1;
1052
1053 /*
1054 * From here on until mo_check_done is only for MO device
1055 */
1056 if ((sdc->sdc_firmware & SDCFW_MO) == 0)
1057 goto mo_check_done;
1058
1059 /*
1060 * Mode Sense
1061 */
1062 bzero(sdtmp, 36);
1063 scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize);
1064 uscsi.sc_cpoint = sdtmp;
1065 uscsi.sc_ctrnscnt = 36;
1066 uscsi.sc_opcode = SCOP_MSENSE;
1067 uscsi.sc_lad = (SDM_PF << 16)|((SDM_PC_CUR|SDM_PCODE_ALL) << 8);
1068 uscsi.sc_count = 36;
1069
1070 if (sdcmd(dev, &uscsi) == 0) {
1071 /*
1072 * check Write Protect mode
1073 */
1074 if (sdtmp[2] & 0x80)
1075 sdd->sdd_flags |= SDDF_WPROTECT;
1076 else
1077 sdd->sdd_flags &= ~SDDF_WPROTECT;
1078 /*
1079 * check Format Mode
1080 */
1081 if (sdtmp[26] == 2) {
1082 ii->ii_type = search_index(SMO_S501);
1083 if (mo_disp_format)
1084 printf("sd%d: format mode 2 (original format)\n", unit);
1085 } else if (sdtmp[26] == 3) {
1086 int spare;
1087
1088 spare = *(short *)&sdtmp[32];
1089 if (spare == 2048)
1090 ii->ii_type =
1091 search_index(SMO_S501_ISO2);
1092 else
1093 ii->ii_type =
1094 search_index(SMO_S501_ISO);
1095 if (mo_disp_format)
1096 printf("sd%d: format mode 3 (ISO format) spare=%d\n", unit, spare);
1097 } else {
1098 sdd->sdd_flags |= SDDF_NONFMT;
1099 if (mo_disp_format)
1100 printf("sd%d: Non format\n", unit);
1101 }
1102 sdi = &sddevinfo[ii->ii_type];
1103 }
1104
1105 /*
1106 * Mode Select
1107 * Error Recovery Parameters set
1108 */
1109 i = *(sdi->ERP_page +1) + 2; /* page length */
1110 bzero(sdtmp, i + 4);
1111 bcopy(sdi->ERP_page, (caddr_t)&sdtmp[4], i);
1112 scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize);
1113 uscsi.sc_cpoint = sdtmp;
1114 uscsi.sc_ctrnscnt = i + 4;
1115 uscsi.sc_opcode = SCOP_MSELECT;
1116 uscsi.sc_lad = (SDM_PF << 16);
1117 uscsi.sc_count = i + 4;
1118
1119 (void) sdcmd(dev, &uscsi);
1120
1121 /*
1122 * Read Grown Defect list
1123 */
1124 scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize);
1125 uscsi.sc_cpoint = sdtmp;
1126 uscsi.sc_ctrnscnt = 4;
1127 uscsi.sc_opcode = SCOP_RDL;
1128 uscsi.sc_cdb.un_type1.t1_ladhi = (SDDL_GLIST|SDDL_PHYSFMT) << 8;
1129 uscsi.sc_cdb.un_type1.t1_p3 = 4;
1130
1131 (void) sdcmd(dev, &uscsi);
1132 i = *(short *)&sdtmp[2] / 8;
1133 if (i > (1024*9/10))
1134 printf("sd%d: WARNING: DEFECT SPARE LOCATION < 10%\n",
1135 unit);
1136 mo_check_done:
1137 /*
1138 * Read Capacity
1139 */
1140 bzero((caddr_t)sdtmp, 8);
1141 scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize);
1142 uscsi.sc_cpoint = sdtmp;
1143 uscsi.sc_ctrnscnt = 8;
1144 uscsi.sc_opcode = SCOP_RCAP;
1145
1146 (void) sdcmd(dev, &uscsi);
1147 sdd->sdd_nsect = *(int *)&sdtmp[0] + 1;
1148 sdd->sdd_sectsize = *(int *)&sdtmp[4];
1149
1150 if ((sdd->sdd_sectsize != DEV_BSIZE)
1151 && (sdd->sdd_sectsize != SDBSIZE1K))
1152 sdd->sdd_sectsize = DEV_BSIZE;
1153 }
1154
1155 if ((sdd->sdd_flags & SDDF_WPROTECT) && (flag & FWRITE))
1156 stat = EROFS;
1157
1158 pre_open_done:
1159
1160 if (stat == 0) {
1161 if ((isalone(unit) == ONLY_ONE) || media_changed) {
1162 /*
1163 * read partition information from sector zero.
1164 */
1165 sdrpartinfo(ii);
1166 if (ii->ii_dk >= 0) {
1167 dk_wpms[ii->ii_dk] =
1168 sdd->sdd_sectsize * sdstdrv[unit].rps
1169 * sdstdrv[unit].nsect / (2 * 1000000);
1170 }
1171 }
1172 } else {
1173 /*
1174 * open error
1175 */
1176 *sdopfp = old_sdopf;
1177 if ((sdd->sdd_flags & SDDF_INHRMV) && (isalone(unit) == 0)) {
1178 sdd->sdd_flags &= ~SDDF_INHRMV;
1179 scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize);
1180 uscsi.sc_opcode = SCOP_MEDRMV;
1181 uscsi.sc_count = SDRMV_ALLOW;
1182 (void) sdcmd(dev, &uscsi);
1183 }
1184 }
1185
1186 /*
1187 * UNLOCK open
1188 */
1189 s = splclock();
1190 sdd->sdd_flags &= ~SDDF_GETTMP;
1191 if (sdtmp_stat & B_WANTED)
1192 wakeup((caddr_t)sdtmp);
1193 sdtmp_stat &= ~(B_BUSY|B_WANTED);
1194 splx(s);
1195 return (stat);
1196 }
1197
1198 int sd_access_check_on; /* Common flags for sd_access_check() */
1199
sd_access_check(bp)1200 sd_access_check(bp)
1201 register struct buf *bp;
1202 {
1203 register struct iop/**/_device *ii;
1204 register struct sdd_softc *sdd;
1205 int unit;
1206 int check_part;
1207 int limit;
1208 int over;
1209 register struct size *sizes;
1210 register int lba; /* logical block address */
1211 register int sz;
1212 register int i;
1213
1214 check_part = 0;
1215 unit = dev2unit(bp->b_dev);
1216 ii = sddinfo[unit];
1217 sdd = &sdd_softc[unit];
1218 sizes = sdstdrv[unit].sizes;
1219
1220 lba = sizes[dev2part(bp->b_dev)].sd_blkoff + dkblock(bp);
1221 sz = howmany(bp->b_bcount, sdd->sdd_sectsize);
1222
1223 /*
1224 * When block device is used,
1225 * inhibit raw device write operation.
1226 */
1227 if ((major(bp->b_dev) == sd_c_major) /* RAW I/O */
1228 && ((bp->b_flags & B_READ) == 0) /* WRITE */
1229 && ((ii->ii_flags & SD_F_ENW) == 0) /* INHIBIT */
1230 && ((sd_access_check_on & SD_F_ENW) == 0)) {
1231
1232 for (i = 0; i < PNUM; i++) {
1233 if (sd_b_openf[unit][i] == 0)
1234 continue;
1235 /*
1236 * |----|========|---|======|-------|
1237 * 1 |---+++--------------------------| CUT OFF
1238 * 2 |---++++++++++++-----------------| CUT OFF
1239 * 3 |---++++++++++++++++-------------| CUT OFF
1240 * 4 |---++++++++++++++++++++++++-----| CUT OFF
1241 * 5 |-------+++----------------------| ERROR
1242 * 6 |------------+++-----------------| ERROR
1243 * 7 |------------+++++++-------------| ERROR
1244 * 8 |------------+++++++++++++++-----| ERROR
1245 */
1246 if ((lba < (sizes[i].sd_blkoff + sizes[i].sd_nblocks))
1247 && ((lba + sz) > sizes[i].sd_blkoff))
1248 check_part |= (1 << i);
1249 }
1250 }
1251
1252 if (check_part) {
1253 limit = 0x7fffffff; /* XXX */
1254 for (i = 0; i < PNUM; i++) {
1255 if ((check_part & (1 << i)) == 0)
1256 continue;
1257
1258 if (lba >= sizes[i].sd_blkoff) {
1259 bp->b_flags |= B_ERROR;
1260 bp->b_error = EIO;
1261 bp->b_resid = bp->b_bcount;
1262
1263 printf("sd%d%c: RAW DEVICE WRITE PROTECTED: ",
1264 unit, pname[dev2part(bp->b_dev)]);
1265 printf("sn = 0x%x(%d), off = 0x%x(%d)\n",
1266 dkblock(bp)*DEV_BSIZE/sdd->sdd_sectsize,
1267 dkblock(bp)*DEV_BSIZE/sdd->sdd_sectsize,
1268 sizes[dev2part(bp->b_dev)].sd_blkoff,
1269 sizes[dev2part(bp->b_dev)].sd_blkoff);
1270
1271 return (-1);
1272 }
1273
1274 if (sizes[i].sd_blkoff < limit)
1275 limit = sizes[i].sd_blkoff;
1276 }
1277 } else {
1278 limit = sizes[dev2part(bp->b_dev)].sd_blkoff
1279 + sizes[dev2part(bp->b_dev)].sd_nblocks;
1280 }
1281
1282 if ((over = (lba + sz) - limit) > 0) {
1283 /*
1284 * Logical Block Address is outside the valid area.
1285 */
1286 if (((ii->ii_flags & SD_F_EOLBA) != 0)
1287 || ((sd_access_check_on & SD_F_EOLBA) != 0)) {
1288 /*
1289 * error if outside LBA
1290 */
1291 return(-1);
1292 }
1293 bp->b_resid = bp->b_bcount - (sz - over) * sdd->sdd_sectsize;
1294 if (bp->b_resid >= bp->b_bcount) {
1295 bp->b_resid = bp->b_bcount;
1296 return(-1);
1297 }
1298 }
1299
1300 return (0);
1301 }
1302
sd_b_close(dev,flag)1303 sd_b_close(dev, flag)
1304 dev_t dev;
1305 int flag;
1306 {
1307 return (_sdclose(dev, flag, S_IFBLK));
1308 }
1309
sd_c_close(dev,flag)1310 sd_c_close(dev, flag)
1311 dev_t dev;
1312 int flag;
1313 {
1314 return (_sdclose(dev, flag, S_IFCHR));
1315 }
1316
_sdclose(dev,flag,fmt)1317 _sdclose(dev, flag, fmt)
1318 register dev_t dev;
1319 int flag;
1320 int fmt;
1321 {
1322 register struct iop/**/_device *ii;
1323 register struct sdd_softc *sdd;
1324 register int unit;
1325 struct sdc_softc *sdc;
1326 struct scsi uscsi;
1327 struct sc_extnd *sce;
1328
1329 unit = dev2unit(dev);
1330 if (unit >= nsd || (ii = sddinfo[unit]) == 0 || ii->ii_alive == 0)
1331 return (ENXIO);
1332
1333 sdd = &sdd_softc[unit];
1334 sdc = &sdc_softc[ii->ii_ctlr];
1335 sce = (struct sc_extnd *)&sdc_rsense[ii->ii_ctlr][0];
1336
1337 /*
1338 * still remain jobs
1339 * sleep about 10ms -> 1sec
1340 */
1341 while (ii->ii_mi->im_tab.b_actf != NULL)
1342 sleep((caddr_t)&lbolt, PRIBIO);
1343
1344 if ((fmt & S_IFMT) == S_IFBLK)
1345 sd_b_openf[unit][dev2part(dev)] = 0;
1346 else
1347 sd_c_openf[unit][dev2part(dev)] = 0;
1348 sdd->sdd_flags &= ~SDDF_XUSE;
1349
1350 if ((sdc->sdc_firmware & SDCFW_RMB) && (isalone(unit) == 0)) {
1351 sdd->sdd_flags &= ~SDDF_INHRMV;
1352 scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize);
1353 uscsi.sc_opcode = SCOP_MEDRMV;
1354 uscsi.sc_count = SDRMV_ALLOW;
1355 (void) sdcmd(dev, &uscsi);
1356 }
1357 return (0);
1358 }
1359
sdcmd(dev,usc)1360 sdcmd(dev, usc)
1361 dev_t dev;
1362 struct scsi *usc;
1363 {
1364 register struct buf *bp;
1365 register struct scsi *ksc;
1366 register u_char *point;
1367 register int unit;
1368 int error;
1369 int s;
1370 int cnt;
1371
1372 if (usc == 0)
1373 return (ENXIO);
1374
1375 error = 0;
1376 unit = dev2unit(dev);
1377 bp = &csdbuf[unit];
1378
1379 /*
1380 * LOCK csdbuf
1381 */
1382 s = splclock();
1383 while (bp->b_flags & B_BUSY) {
1384 bp->b_flags |= B_WANTED;
1385 sleep((caddr_t)bp, PRIBIO);
1386 }
1387 bzero((caddr_t)bp, sizeof(struct buf));
1388 bp->b_flags = B_BUSY|B_READ;
1389 splx(s);
1390
1391 ksc = &kernscsi[unit];
1392 bcopy((caddr_t)usc, (caddr_t)ksc, sizeof(struct scsi));
1393 /*
1394 * setup command buffer
1395 */
1396 bp->b_dev = dev;
1397 bp->b_proc = curproc;
1398 cnt = ksc->sc_ctrnscnt;
1399 bp->b_bcount = cnt;
1400
1401 point = ksc->sc_cpoint;
1402 bp->b_un.b_addr = (caddr_t)point;
1403 if (cnt > 0) {
1404 if (point == NULL) {
1405 ksc->sc_cpoint = point = get_scsi(unit)->sc_param;
1406 if (cnt > 20) {
1407 error = EFAULT;
1408 goto done;
1409 }
1410 }
1411 if (point < (u_char *)KERNBASE) {
1412 if (useracc(point, cnt, B_WRITE) == NULL) {
1413 error = EFAULT;
1414 goto done;
1415 }
1416 curproc->p_flag |= P_PHYSIO;
1417 vslock(point, cnt);
1418 bp->b_flags |= B_PHYS;
1419 }
1420 #ifndef mips
1421 else {
1422 if (kernacc(point, cnt, B_WRITE) == NULL) {
1423 error = EFAULT;
1424 goto done;
1425 }
1426 }
1427 #endif
1428 ksc->sc_tstatus = TS_MAPPED_PIO; /* XXX */
1429 }
1430
1431 /*
1432 * call strategy entry, and wait command done.
1433 */
1434 sdstrategy(bp);
1435 iowait(bp);
1436
1437 if ((cnt > 0) && (point < (u_char *)KERNBASE)) {
1438 vsunlock(point, cnt, B_READ);
1439 curproc->p_flag &= ~P_PHYSIO;
1440 }
1441 if ((bp->b_flags & B_ERROR) == 0)
1442 error = 0;
1443 else {
1444 if (bp->b_error)
1445 error = bp->b_error;
1446 else
1447 error = EIO;
1448 }
1449 bcopy((caddr_t)ksc, (caddr_t)usc, sizeof(struct scsi));
1450
1451 done:
1452 /*
1453 * UNLOCK csdbuf
1454 */
1455 s = splclock();
1456 if (bp->b_flags & B_WANTED)
1457 wakeup((caddr_t)bp);
1458 bp->b_flags = 0;
1459 splx(s);
1460 return (error);
1461 }
1462
1463 /*
1464 * read partition information from sector zero.
1465 */
sdrpartinfo(ii)1466 sdrpartinfo(ii)
1467 register struct iop/**/_device *ii;
1468 {
1469 register struct disklabel *dlp;
1470 register struct sdst *hsp;
1471 register struct sdst *st;
1472 register int unit;
1473 register int i;
1474 struct firstsector *fsp;
1475 struct sdc_softc *sdc;
1476 struct sdd_softc *sdd;
1477 struct sddevinfo *sdi;
1478 struct scsi uscsi;
1479 int s;
1480
1481 sdi = &sddevinfo[ii->ii_type];
1482 unit = ii->ii_unit;
1483
1484 sdd = &sdd_softc[unit];
1485 sdc = &sdc_softc[ii->ii_ctlr];
1486
1487 if ((sdd->sdd_flags & (SDDF_NONFMT|SDDF_FMTDONE)) == 0) {
1488 register struct sc_rcap *scr = (struct sc_rcap *)sdtmp;
1489
1490 sdd->sdd_flags |= SDDF_FMTDONE;
1491
1492 bzero((caddr_t)sdtmp, 8);
1493 scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize);
1494 uscsi.sc_cpoint = (u_char *)scr;
1495 uscsi.sc_ctrnscnt = 8;
1496 uscsi.sc_opcode = SCOP_RCAP;
1497 (void) sdcmd(unit << 3, &uscsi);
1498
1499 sdd->sdd_nsect = scr->scr_nblock + 1;
1500 sdd->sdd_sectsize = scr->scr_blocklen;
1501 if (sdd->sdd_sectsize == 0)
1502 sdd->sdd_sectsize = SDBSIZE1K;
1503 }
1504
1505 bzero(sdtmp, DEV_BSIZE);
1506
1507 if ((sdd->sdd_flags & SDDF_NONFMT) == 0) {
1508 scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize);
1509 uscsi.sc_cpoint = sdtmp;
1510 uscsi.sc_ctrnscnt = DEV_BSIZE;
1511 uscsi.sc_opcode = SCOP_READ;
1512 uscsi.sc_lad = 0;
1513 uscsi.sc_count = 1;
1514
1515 (void) sdcmd(unit << 3, &uscsi);
1516 sdd->sdd_flags &= ~SDDF_SKIPCHECK;
1517 }
1518
1519 fsp = (struct firstsector *)sdtmp;
1520 dlp = (struct disklabel *)(sdtmp + LABELOFFSET);
1521
1522 s = splclock();
1523 hsp = &sdstdrv[unit];
1524 bzero((caddr_t)hsp, sizeof (struct sdst));
1525 bzero(&sdlabel[unit], sizeof (struct disklabel));
1526
1527 if ((dlp->d_magic == DISKMAGIC)
1528 && ((ii->ii_flags & SD_F_IGNLABEL) == 0)) {
1529 sdlabel[unit] = *dlp;
1530 disklabel2sdst(unit, dlp, hsp);
1531 } else {
1532 if ((ii->ii_type == UNKNOWN_DISK)
1533 || (sdi->sdstp->sizes == calc_disk_sizes)) {
1534 /*
1535 * If device is UNKNOWN PARTITION SIZE,
1536 * calculate default partition from capacity.
1537 */
1538 st = sdi->sdstp;
1539 hsp->nsect = st->nsect; /* # sectors/track */
1540 hsp->ntrak = st->ntrak; /* # tracks/cylinder */
1541 hsp->nspc = st->nspc; /* # sectors/cylinder */
1542 hsp->ncyl = st->ncyl; /* # cylinders */
1543 hsp->rps = st->rps; /* # revolutions/sec */
1544 hsp->sizes = sdsizedrv[unit]; /* partition table */
1545
1546 sd_calcpart(ii, hsp->sizes,
1547 sdd->sdd_nsect, sdd->sdd_sectsize);
1548 sdst2disklabel(unit, hsp, &sdlabel[unit]);
1549 } else {
1550 /*
1551 * If device is support disk,
1552 * copy default partition from size table.
1553 */
1554 st = sdi->sdstp;
1555
1556 hsp->nsect = st->nsect; /* # sectors/track */
1557 hsp->ntrak = st->ntrak; /* # tracks/cylinder */
1558 hsp->nspc = st->nspc; /* # sectors/cylinder */
1559 hsp->ncyl = st->ncyl; /* # cylinders */
1560 hsp->rps = st->rps; /* # revolutions / second */
1561 hsp->sizes = sdsizedrv[unit]; /* partition table */
1562
1563 for (i = 0; i < PNUM; i++) {
1564 hsp->sizes[i].sd_nblocks = st->sizes[i].sd_nblocks;
1565 hsp->sizes[i].sd_blkoff = st->sizes[i].sd_blkoff;
1566 }
1567 sdst2disklabel(unit, hsp, &sdlabel[unit]);
1568 }
1569 }
1570
1571 /* BEGIN XXX*/
1572 if (hsp->rps == 0) {
1573 /*
1574 * If device is support disk,
1575 * copy default partition from size table.
1576 */
1577 st = sdi->sdstp;
1578
1579 hsp->nsect = st->nsect; /* # sectors/track */
1580 hsp->ntrak = st->ntrak; /* # tracks/cylinder */
1581 hsp->nspc = st->nspc; /* # sectors/cylinder */
1582 hsp->ncyl = st->ncyl; /* # cylinders */
1583 hsp->rps = st->rps; /* # revolutions / second */
1584 sdst2disklabel(unit, hsp, &sdlabel[unit]);
1585 }
1586 /* END XXX*/
1587 (void)splx(s);
1588 }
1589
1590 static char Warn_Part[] = "sd%d: PARTITION TABLE CHANGED\n";
1591 static char Pr_Part_Fmt[] = "sd%d%c: nblk=%d, off=%d\n";
1592
1593 #define stsz(N) st->sizes[(N)].sd_nblocks
1594 #define stof(N) st->sizes[(N)].sd_blkoff
1595 #define dlsz(N) dlp->d_partitions[(N)].p_size
1596 #define dlof(N) dlp->d_partitions[(N)].p_offset
1597 #define disz(N) dip->di_part[(N)].dp_nblocks
1598 #define diof(N) dip->di_part[(N)].dp_blkoff
1599
1600 #ifndef BBSIZE
1601 #define BBSIZE 8192
1602 #endif
1603
1604 static
check_sdst(unit,st)1605 check_sdst(unit, st)
1606 int unit;
1607 struct sdst *st;
1608 {
1609 if (st->nsect == 0) {
1610 st->nsect = 1;
1611 printf("sd%d: nsect SHOULD BE != 0, 1 assumed\n", unit);
1612 }
1613
1614 if (st->rps == 0) {
1615 st->rps = 60;
1616 printf("sd%d: rps SHOULD BE != 0, 60 assumed\n", unit);
1617 }
1618 }
1619
1620 static
disklabel2sdst(unit,dlp,st)1621 disklabel2sdst(unit, dlp, st)
1622 int unit;
1623 register struct disklabel *dlp;
1624 register struct sdst *st;
1625 {
1626 register int i;
1627 int msg_header_printed;
1628
1629 msg_header_printed = 0;
1630
1631 st->nsect = dlp->d_nsectors; /* # sectors/track */
1632 st->ntrak = dlp->d_ntracks; /* # tracks/cylinder */
1633 st->nspc = dlp->d_secpercyl; /* # sectors/cylinder */
1634 st->ncyl = dlp->d_ncylinders; /* # cylinders */
1635 st->rps = dlp->d_rpm / 60; /* # revolutions / second */
1636 st->sizes = sdsizedrv[unit]; /* partition table */
1637
1638 check_sdst(unit, st);
1639
1640 for (i = 0; i < PNUM; i++) {
1641 if (msg_header_printed == 0) {
1642 if (((stsz(i) != 0) || (stof(i) != 0))
1643 && ((stsz(i) != dlsz(i)) || (stof(i) != dlof(i)))) {
1644 msg_header_printed = 1;
1645 }
1646 }
1647 }
1648
1649 for (i = 0; i < PNUM; i++) {
1650 stsz(i) = dlsz(i);
1651 stof(i) = dlof(i);
1652 }
1653
1654 if (msg_header_printed) {
1655 printf(Warn_Part, unit);
1656 for (i = 0; i < PNUM; i++)
1657 printf(Pr_Part_Fmt, unit, pname[i], stsz(i), stof(i));
1658 }
1659 }
1660
1661 static
sdst2disklabel(unit,st,dlp)1662 sdst2disklabel(unit, st, dlp)
1663 int unit; /*XXX*/
1664 register struct sdst *st;
1665 register struct disklabel *dlp;
1666 {
1667 register int i;
1668
1669 dlp->d_type = DTYPE_SCSI; /* drive type */
1670 dlp->d_secsize = sdd_softc[unit].sdd_sectsize; /* # of bytes per sector */
1671 dlp->d_nsectors = st->nsect; /* # sectors/track */
1672 dlp->d_ntracks = st->ntrak; /* # tracks/cylinder */
1673 dlp->d_ncylinders = st->ncyl; /* # cylinders */
1674 dlp->d_secpercyl = st->nspc; /* # sectors/cylinder */
1675 dlp->d_rpm = st->rps * 60; /* # revolutions / minute */
1676 dlp->d_bbsize = BBSIZE; /*XXX*/ /* size of boot area at sn0, bytes */
1677 dlp->d_sbsize = SBSIZE; /*XXX*/ /* max size of fs superblock, bytes */
1678
1679 for (i = 0; i < PNUM; i++) {
1680 dlsz(i) = stsz(i);
1681 dlof(i) = stof(i);
1682 }
1683 }
1684
1685 #undef stsz
1686 #undef stof
1687 #undef dlsz
1688 #undef dlof
1689 #undef disz
1690 #undef diof
1691
sd_calcpart(ii,disk_sizes,nsect,sectsize)1692 sd_calcpart(ii, disk_sizes, nsect, sectsize)
1693 register struct iop/**/_device *ii;
1694 register struct size disk_sizes[];
1695 int nsect;
1696 int sectsize;
1697 {
1698 register struct defpart *dp;
1699 register int size_mb;
1700 register int i;
1701 int psize;
1702
1703 size_mb = nsect * sectsize / (1024 * 1024);
1704
1705 for (dp = defpart_std; dp->range_max; dp++)
1706 if ((dp->range_min <= size_mb) && (size_mb < dp->range_max))
1707 break;
1708
1709 /* PASS1 */
1710 for (i = 0; i < PNUM; i++) {
1711 psize = dp->partsize[i];
1712
1713 switch (psize) {
1714
1715 case PART_UNUSED:
1716 disk_sizes[i].sd_nblocks = 0;
1717 break;
1718
1719 case PART_SPEC:
1720 disk_sizes[i].sd_nblocks = nsect * sectsize / DEV_BSIZE;
1721 break;
1722
1723 case PART_CALCF:
1724 case PART_CALCG:
1725 break;
1726
1727 default:
1728 disk_sizes[i].sd_nblocks = psize;
1729 break;
1730 }
1731 }
1732
1733 /* PASS2 */
1734 for (i = 0; i < PNUM; i++) {
1735 psize = dp->partsize[i];
1736
1737 switch (psize) {
1738
1739 case PART_UNUSED:
1740 case PART_SPEC:
1741 break;
1742
1743 case PART_CALCF:
1744 disk_sizes[i].sd_nblocks =
1745 disk_sizes[PART_C].sd_nblocks -
1746 (disk_sizes[PART_A].sd_nblocks +
1747 disk_sizes[PART_B].sd_nblocks +
1748 disk_sizes[PART_D].sd_nblocks +
1749 disk_sizes[PART_E].sd_nblocks +
1750 disk_sizes[PART_H].sd_nblocks);
1751 break;
1752
1753 case PART_CALCG:
1754 disk_sizes[i].sd_nblocks =
1755 disk_sizes[PART_C].sd_nblocks -
1756 (disk_sizes[PART_A].sd_nblocks +
1757 disk_sizes[PART_B].sd_nblocks +
1758 disk_sizes[PART_H].sd_nblocks);
1759 break;
1760
1761 default:
1762 break;
1763 }
1764 }
1765
1766 /* OFFSET */
1767 disk_sizes[PART_A].sd_blkoff = 0;
1768 disk_sizes[PART_B].sd_blkoff = disk_sizes[PART_A].sd_nblocks;
1769 disk_sizes[PART_C].sd_blkoff = 0;
1770 disk_sizes[PART_D].sd_blkoff = disk_sizes[PART_A].sd_nblocks
1771 + disk_sizes[PART_B].sd_nblocks
1772 + disk_sizes[PART_H].sd_nblocks;
1773 disk_sizes[PART_E].sd_blkoff = disk_sizes[PART_D].sd_blkoff
1774 + disk_sizes[PART_D].sd_nblocks;
1775 disk_sizes[PART_F].sd_blkoff = disk_sizes[PART_E].sd_blkoff
1776 + disk_sizes[PART_E].sd_nblocks;
1777 disk_sizes[PART_G].sd_blkoff = disk_sizes[PART_D].sd_blkoff;
1778
1779 if (disk_sizes[PART_H].sd_nblocks == 0)
1780 disk_sizes[PART_H].sd_blkoff = 0;
1781 else {
1782 disk_sizes[PART_H].sd_blkoff =
1783 disk_sizes[PART_A].sd_nblocks +
1784 disk_sizes[PART_B].sd_nblocks;
1785 }
1786
1787 for (i = 0; i < PNUM; i++)
1788 if (disk_sizes[i].sd_nblocks == 0)
1789 disk_sizes[i].sd_blkoff = 0;
1790 }
1791
1792 int sd_str_pr = 0;
1793
sdstrategy(bp)1794 sdstrategy(bp)
1795 register struct buf *bp;
1796 {
1797 register struct iop/**/_device *ii;
1798 register struct sdst *st;
1799 register struct buf *dp;
1800 register int unit;
1801 register int ssize;
1802 struct sdd_softc *sdd;
1803 struct sdc_softc *sdc;
1804 long bn;
1805 int xunit;
1806 int s;
1807
1808 xunit = dev2part(bp->b_dev);
1809 unit = dev2unit(bp->b_dev);
1810 if (unit >= nsd || (ii = sddinfo[unit]) == 0 || ii->ii_alive == 0)
1811 goto bad;
1812
1813 if (bp != &csdbuf[unit]) {
1814 /*
1815 * READ / WRITE command
1816 */
1817 sdd = &sdd_softc[unit];
1818 if (sdd->sdd_flags & SDDF_NONFMT)
1819 goto bad;
1820 sdc = &sdc_softc[ii->ii_ctlr];
1821 ssize = sdd->sdd_sectsize;
1822 if ((ssize != DEV_BSIZE)
1823 && ((((dkblock(bp) * DEV_BSIZE) % ssize) != 0)
1824 || (((bp->b_flags & B_READ) == 0) &&
1825 ((bp->b_bcount % ssize) != 0)))) {
1826 goto bad;
1827 }
1828
1829 st = &sdstdrv[unit];
1830 bn = dkblock(bp);
1831 bp->b_resid = 0;
1832 if ((bn < 0) || (bn >= st->sizes[xunit].sd_nblocks))
1833 goto bad2;
1834 if (sd_access_check(bp) < 0)
1835 goto bad2;
1836
1837 #ifdef notdef /* KU: XXX */
1838 bp->b_cylin = (bn + st->sizes[xunit].sd_blkoff) / st->nspc;
1839 } else {
1840 bp->b_cylin = 0;
1841 #endif
1842 }
1843
1844 s = splsc();
1845 dp = &sdutab[ii->ii_unit];
1846 disksort(dp, bp);
1847 if (dp->b_active == 0) {
1848 sdustart(ii);
1849 bp = &ii->ii_mi->im_tab;
1850 if (bp->b_actf && bp->b_active == 0)
1851 sdstart(ii->ii_mi);
1852 }
1853 splx(s);
1854 return;
1855
1856 bad:
1857 bp->b_flags |= B_ERROR;
1858 goto done;
1859 bad2:
1860 bp->b_resid = bp->b_bcount;
1861 done:
1862 iodone(bp);
1863 }
1864
1865 /*
1866 * Unit start routine.
1867 */
sdustart(ii)1868 sdustart(ii)
1869 register struct iop/**/_device *ii;
1870 {
1871 register struct iop/**/_ctlr *im;
1872 register struct buf *dp;
1873
1874 if (ii == NULL)
1875 return;
1876 im = ii->ii_mi;
1877 dk_busy &= ~(1 << ii->ii_dk);
1878 dp = &sdutab[ii->ii_unit];
1879 if (dp->b_actf == NULL)
1880 return;
1881 /*
1882 * If the controller is active, just remember
1883 * that this device would like to be positioned ...
1884 * if we tried to position now we would confuse the SD.
1885 */
1886 if (im->im_tab.b_active) {
1887 sdc_softc[im->im_ctlr].sdc_softas |= (1 << ii->ii_slave);
1888 return;
1889 }
1890 /*
1891 * If we have already positioned this drive,
1892 * then just put it on the ready queue.
1893 */
1894 if (dp->b_active == 0)
1895 dp->b_active = 1;
1896 /*
1897 * Device is ready to go
1898 * put it on the ready queue for the controller
1899 * (unless its already there.)
1900 */
1901 if (dp->b_active != 2) {
1902 im->im_tab.b_actf = dp;
1903 dp->b_active = 2;
1904 }
1905 }
1906
1907 /*
1908 * Start up a transfer on a drive.
1909 */
sdstart(im)1910 sdstart(im)
1911 register struct iop/**/_ctlr *im;
1912 {
1913 register struct buf *bp;
1914 register struct buf *dp;
1915 register struct sdc_softc *sdc;
1916
1917 loop:
1918 /*
1919 * Pull a request off the controller queue.
1920 */
1921 if ((dp = im->im_tab.b_actf) == NULL)
1922 return;
1923 if ((bp = dp->b_actf) == NULL)
1924 return;
1925 /*
1926 * Mark controller busy, and
1927 * determine destination of this request.
1928 */
1929 im->im_tab.b_active++;
1930
1931 sdexec(bp);
1932 }
1933
1934 void
sdexec(bp)1935 sdexec(bp)
1936 register struct buf *bp;
1937 {
1938 register struct iop/**/_device *ii;
1939 register struct buf_stat *bs;
1940 register struct scsi *sc;
1941 register int ssize;
1942 register int unit;
1943 register int intr;
1944 register int bn;
1945 struct sdc_softc *sdc;
1946 struct sdd_softc *sdd;
1947 struct sdst *st;
1948 int sz;
1949 int over;
1950 struct sc_map *map;
1951
1952 unit = dev2unit(bp->b_dev);
1953 ii = sddinfo[unit];
1954 intr = ii->ii_intr;
1955 sdd = &sdd_softc[unit];
1956 sdc = &sdc_softc[ii->ii_ctlr];
1957
1958 sc = get_scsi(intr);
1959
1960 if (bp == &csdbuf[unit]) { /* do sdcmd() */
1961 bcopy((caddr_t)&kernscsi[unit],
1962 (caddr_t)sc, sizeof(struct scsi));
1963 if (bp->b_un.b_addr == NULL) {
1964 map = 0;
1965 } else {
1966 map = get_sc_map(intr);
1967 sc->sc_map = (struct sc_map *)ipc_phys(map);
1968 }
1969 } else { /* R/W */
1970 ssize = sdd->sdd_sectsize;
1971
1972 st = &sdstdrv[unit];
1973 bn = dkblock(bp);
1974 if (sdd->sdd_lastblk / st->nspc != bn / st->nspc)
1975 dk_seek[ii->ii_dk]++;
1976
1977 st = &sdstdrv[unit];
1978 bn = dkblock(bp);
1979
1980 /*
1981 * Setup for the transfer, and get in the IOP queue.
1982 */
1983 scinit(sc, ii->ii_slave, ssize);
1984 sc->sc_ctrnscnt = bp->b_bcount - bp->b_resid;
1985 map = get_sc_map(intr);
1986 sc->sc_map = (struct sc_map *)ipc_phys(map);
1987
1988 /* cdb */
1989 sc->sc_cdb.un_type1.t1_opcode =
1990 (bp->b_flags & B_READ) ? SCOP_EREAD :
1991 (ii->ii_flags & SD_F_WRTVRFY) ? SCOP_WRTVRFY :
1992 SCOP_EWRITE;
1993 #ifdef mips
1994 {
1995 int v;
1996
1997 v = (bn + st->sizes[dev2part(bp->b_dev)].sd_blkoff)
1998 * DEV_BSIZE / sdd->sdd_sectsize;
1999 sc->sc_ladhi = v >> 16;
2000 sc->sc_ladlo = v;
2001
2002 v = (sc->sc_ctrnscnt + ssize - 1) / ssize;
2003 sc->sc_cdb.un_type1.t1_p2 = v >> 8;
2004 sc->sc_cdb.un_type1.t1_p3 = v;
2005 }
2006 #else
2007 *(u_int *)(&sc->sc_cdb.un_type1.t1_ladhi) =
2008 (bn + st->sizes[dev2part(bp->b_dev)].sd_blkoff)
2009 * DEV_BSIZE / sdd->sdd_sectsize;
2010 *(u_short *)(&sc->sc_cdb.un_type1.t1_p2) =
2011 (sc->sc_ctrnscnt + ssize -1) / ssize;
2012 #endif
2013 if ((sdd->sdd_flags & SDDF_ERASEOFF)
2014 && ((bp->b_flags & B_READ) == 0)) {
2015 sc->sc_ctrl = 0x40;
2016 }
2017 }
2018
2019 sdc->sdc_firmware |= SDCFW_BUSY;
2020 iop/**/go(ii, map);
2021 }
2022
2023 /*
2024 * Now all ready to go.
2025 */
sddgo(im)2026 sddgo(im)
2027 register struct iop/**/_ctlr *im;
2028 {
2029 register int intr;
2030
2031 im->im_tab.b_active = 2;
2032 intr = im->im_intr;
2033
2034 sc_go(intr, get_scsi(intr), SCSI_INTEN);
2035 }
2036
2037 /*
2038 * copyin(), copyout() can't use in the interrupt routine.
2039 * because user process is changed.
2040 */
2041 /*
2042 * Handle a disk interrupt.
2043 * d: controller number
2044 */
sdintr(d)2045 sdintr(d)
2046 int d;
2047 {
2048 register struct iop/**/_ctlr *im;
2049 register struct sdc_softc *sdc;
2050 register struct sdd_softc *sdd;
2051 register struct scsi *sc;
2052 register int intr;
2053 register int unit;
2054 register int slave;
2055 register int as;
2056 struct iop/**/_device *ii;
2057 struct sddevinfo *sdi;
2058 struct sc_extnd *sce;
2059 struct sdst *st;
2060 struct buf *bp;
2061 struct buf *dp;
2062 char *erp_page;
2063 int code;
2064 int len;
2065 int tstatus;
2066 int delay_start();
2067 int delay_medrmv();
2068 int wait_re_init_done();
2069
2070 im = sdminfo[d];
2071 sdc = &sdc_softc[im->im_ctlr];
2072 intr = im->im_intr;
2073 as = sdc->sdc_softas;
2074
2075 sdc->sdc_wticks = 0;
2076 sc = get_scsi(intr);
2077 /*
2078 * If SDCS_IOCTL bit is set, then don't check error.
2079 */
2080 if (sdc->sdc_state & SDCS_IOCTL) {
2081 sdc->sdc_state &= ~SDCS_IOCTL;
2082 sdd = &sdd_softc[(sdip[d][sc->sc_identify & IDT_DRMASK])->ii_unit];
2083
2084 if (sdc->sdc_state & SDCS_SCUNLOCK) {
2085 int s;
2086
2087 sdc->sdc_state &= ~SDCS_SCUNLOCK;
2088 s = splclock();
2089 if (sdc->sdc_state & SDCS_OPEN_WAIT) {
2090 sdc->sdc_state &= ~SDCS_OPEN_WAIT;
2091 wakeup((caddr_t)sdc);
2092 }
2093 splx(s);
2094 /*
2095 * UNLOCK SCSI access
2096 */
2097 sdc->sdc_firmware &= ~SDCFW_BUSY;
2098 }
2099 return;
2100 }
2101
2102 im->im_tab.b_active = 1;
2103 /*
2104 * Get device and block structures, and a pointer
2105 * to the iop_device for the drive.
2106 */
2107 dp = im->im_tab.b_actf;
2108 bp = dp->b_actf;
2109 unit = dev2unit(bp->b_dev);
2110
2111 ii = sddinfo[unit];
2112 slave = ii->ii_slave;
2113 st = &sdstdrv[unit];
2114 dk_busy &= ~(1 << ii->ii_dk);
2115 sdd = &sdd_softc[unit];
2116 sdi = &sddevinfo[ii->ii_type];
2117 sce = (struct sc_extnd *)&sdc_rsense[ii->ii_ctlr][0];
2118
2119 /*
2120 * Check error on the drive.
2121 */
2122 tstatus = sc->sc_tstatus & TGSTMASK;
2123 if (sc->sc_istatus != INST_EP) {
2124 /*
2125 * initiator status is bad.
2126 * check & retry !!
2127 */
2128 if ((sc->sc_istatus&(INST_EP|INST_PRE)) == (INST_EP|INST_PRE)) {
2129 /* detect parity error or abnormal terminate */
2130 if ((sc->sc_istatus & INST_LB) == 0)
2131 printf("sd%d: SCSI bus parity error\n", unit);
2132 sdc->sdc_countcc--;
2133 goto sdintr_exec;
2134 }
2135 if ((sc->sc_istatus & INST_EP) == 0) {
2136 if (sc->sc_istatus & (INST_WAIT | INST_IP | INST_WR)) {
2137 if (++sdc->sdc_retrycnt < NRETRY) {
2138 im->im_tab.b_active = 2;
2139 /*
2140 * Konomama return sitemo,
2141 * lost interrupt ni narudake deha
2142 * naidarou ka ?
2143 * Isso error ni sitahou ga
2144 * ii nodeha naidarou ka ?
2145 */
2146 return;
2147 }
2148 }
2149 printf("SCSI%d: abnormal termination\n", intr);
2150 printf("ISTAT = 0x%x, TSTAT = 0x%x\n",
2151 sc->sc_istatus, sc->sc_tstatus);
2152 if (++sdc->sdc_nhrderr >= MAXHRDERR) {
2153 printf("SCSI%d: too many hard errors\n", intr);
2154 sdc->sdc_nhrderr = 0;
2155 goto sdintr_error;
2156 }
2157 screset(intr);
2158 goto sdintr_exec;
2159 }
2160 if ((sc->sc_istatus & (INST_TO|INST_HE)) != 0) {
2161 if (sc->sc_istatus & INST_HE) {
2162 /*
2163 * SCSI bus reset is occured.
2164 * to be continue --> hdreset()
2165 */
2166 re_init_done = 0;
2167 timeout(wait_re_init_done, bp, 10*hz);
2168 return;
2169 }
2170 if (++sdc->sdc_nhrderr >= MAXHRDERR) {
2171 printf("SCSI%d: too many hard errors (ISTAT=0x%x)\n",
2172 intr, sc->sc_istatus);
2173 sdc->sdc_nhrderr = 0;
2174 goto sdintr_error;
2175 }
2176 if (++sdc->sdc_retrycnt >= NRETRY) {
2177 printf("SCSI%d: too many initiator errors (ISTAT=0x%x)\n",
2178 intr, sc->sc_istatus);
2179 goto sdintr_error;
2180 }
2181 DELAY(D100MSEC * 10);
2182 goto sdintr_exec;
2183 }
2184 }
2185
2186 if (sdd->sdd_flags & SDDF_SKIPCHECK)
2187 goto sdintr_done;
2188
2189 check_target_status:
2190 /*
2191 * check target status
2192 */
2193 switch (sdc->sdc_state) {
2194
2195 /********************************/
2196 /* */
2197 /* NORMAL OPERATION */
2198 /* */
2199 /********************************/
2200 case SDCS_NORMAL:
2201 switch (tstatus) {
2202
2203 case TGST_GOOD:
2204 break;
2205
2206 case TGST_CC:
2207 sdc->sdc_state |= SDCS_RSENSE;
2208 sdintr_rsense:
2209 im->im_tab.b_active = 2;
2210 bzero((caddr_t)sce, RSEN_CNT);
2211 scop_rsense(intr, sc, slave,
2212 SCSI_INTEN, RSEN_CNT, (caddr_t)sce);
2213 return;
2214
2215 case TGST_BUSY:
2216 if (++sdc->sdc_retrycnt > MAXRETRYCNT) {
2217 goto sdintr_error;
2218 }
2219 timeout(sdexec, (caddr_t)bp, hz);
2220 return;
2221
2222 default:
2223 printf("sd%d: bad target status 0x%x\n",
2224 unit, sc->sc_tstatus);
2225 goto sdintr_error;
2226 }
2227 break;
2228
2229 /****************************************/
2230 /* */
2231 /* REQUEST SENSE analysis */
2232 /* */
2233 /****************************************/
2234 case SDCS_RSENSE:
2235 case SDCS_PREVRMB|SDCS_RSENSE:
2236 case SDCS_ECC|SDCS_RASREAD|SDCS_RSENSE:
2237 case SDCS_ECC|SDCS_RASWRITE|SDCS_RSENSE:
2238 case SDCS_ECCOFF|SDCS_RSENSE:
2239 case SDCS_ECCOFF|SDCS_RASBLK|SDCS_RSENSE:
2240 case SDCS_ECCOFF|SDCS_RASBLK|SDCS_LOSTDATA|SDCS_RSENSE:
2241 case SDCS_ECC|SDCS_RASBLK|SDCS_RSENSE:
2242 case SDCS_ECC|SDCS_RASBLK|SDCS_LOSTDATA|SDCS_RSENSE:
2243 if (tstatus != TGST_GOOD) {
2244 printf("sd%d: bad target status 0x%x\n",
2245 unit, sc->sc_tstatus);
2246 goto sdintr_error;
2247 }
2248 /*
2249 * error message print out
2250 */
2251 code = sderrordisp(sce, ii);
2252
2253
2254 if ((sdc->sdc_state == (SDCS_ECC|SDCS_RASBLK|SDCS_RSENSE)) ||
2255 (sdc->sdc_state == (SDCS_ECC|SDCS_RASBLK|SDCS_LOSTDATA|SDCS_RSENSE))) {
2256 printf("sd%d: cannot reassign block %d\n",
2257 unit, sdd->sdd_badsect);
2258 goto sdintr_error;
2259 }
2260 if (sdc->sdc_state == (SDCS_PREVRMB|SDCS_RSENSE)) {
2261 if (sce->sce_skey == 0x2) {
2262 /*
2263 * Not ready
2264 */
2265 sdc->sdc_state = SDCS_PREVRMB;
2266 timeout(delay_medrmv, (caddr_t)ii, hz);
2267 return;
2268 }
2269 }
2270
2271 /* */
2272 /* RSENSE error handler */
2273 /* */
2274 switch (code) {
2275
2276 /********************************/
2277 /* continue */
2278 /********************************/
2279 /* NO SENSE */
2280 case 0x00: /* No Additional Sense Information */
2281 /* RECOVERED ERROR */
2282 case 0x38: /* Recovered with Auto-Reallocation */
2283 sdc->sdc_state &= ~SDCS_RSENSE;
2284 goto check_target_status;
2285
2286 /********************************/
2287 /* continue or error */
2288 /********************************/
2289 /* ILLEGAL REQUEST */
2290
2291 case 0x21: /* illegal Logical Block Address */
2292 if (&st->sizes[dev2part(bp->b_dev)] == NULL)
2293 goto sdintr_error;
2294 if (bp->b_bcount > 0) {
2295 bp->b_resid = bp->b_bcount
2296 - (sdd->sdd_badsect * sdd->sdd_sectsize
2297 - (st->sizes[dev2part(bp->b_dev)].sd_blkoff
2298 + dkblock(bp)) * DEV_BSIZE);
2299 }
2300 if (bp->b_resid >= bp->b_bcount || bp->b_resid <= 0) {
2301 /*
2302 * all I/O failure
2303 */
2304 bp->b_resid = bp->b_bcount;
2305 goto sdintr_error;
2306 }
2307 /* Ignore error */
2308 break;
2309
2310 /* MEDIUM ERROR */
2311 case 0x31: /* Medium Format Corrupted */
2312 sdd->sdd_flags |= SDDF_NONFMT;
2313 /* Ignore error */
2314 break;
2315
2316 /********************************/
2317 /* more retry */
2318 /********************************/
2319 /* MEDIUM or RECOVERED ERROR */
2320 case 0x10: /* ID CRC Error */
2321 case 0x12: /* No Address Mark found in ID field */
2322 case 0x13: /* No Address Mark found in Data field */
2323 case 0x14: /* No recode found */
2324 /* H/W or MEDIUM or RECOVERED ERROR */
2325 case 0x15: /* Seek Positioning Error */
2326 if (sd_ignore_error) {
2327 sdc->sdc_state = SDCS_NORMAL;
2328 goto check_target_status;
2329 }
2330 /* fall through */
2331
2332 /* H/W ERROR */
2333 case 0x01: /* No Index/Address Mark Found signal */
2334 case 0x02: /* No Seek Complete */
2335 case 0x06: /* No Track Zero found */
2336 /* H/W ERROR or RECOVERED ERROR */
2337 case 0x03: /* Write Fault */
2338 case 0x08: /* Logical Unit Communication Failure */
2339 case 0x09: /* Track Following Error */
2340 case 0x0b: /* Load/Unload Failure */
2341 case 0x0c: /* Spindle Failure */
2342 case 0x0d: /* Focus Failure */
2343 case 0x0e: /* Tracking Failure */
2344 case 0x0f: /* Drive Initialization Failure */
2345 sdc->sdc_state = SDCS_ECC|SDCS_ECC_HOLD|SDCS_REZERO;
2346
2347 scinit(sc, slave, sdd->sdd_sectsize);
2348 /* sc_cdb */
2349 sc->sc_opcode = SCOP_REZERO;
2350
2351 sddgo(im);
2352 return;
2353
2354 /********************************/
2355 /* re-allocate & retry */
2356 /********************************/
2357 /* MEDIUM or RECOVERED ERROR */
2358 case 0x11: /* Unrecovered Read Error */
2359 if (sdc->sdc_state & SDCS_RASREAD) {
2360 sdintr_lostdata:
2361 sdc->sdc_state =
2362 SDCS_ECC|SDCS_RASBLK|SDCS_LOSTDATA;
2363 im->im_tab.b_active = 2;
2364 scop_rasblk(intr, sc, slave,
2365 SCSI_INTEN, sdd->sdd_badsect);
2366 sdd->sdd_flags &= ~SDDF_VBADSECT;
2367 return;
2368 }
2369 /* fall through */
2370
2371 /* RECOVERED ERROR */
2372 case 0x17: /* Recovered read data with retries */
2373 case 0x18: /* Recovered read data with ECC */
2374 /*
2375 * set ECC ON & more retry
2376 */
2377 if (sdc->sdc_firmware & SDCFW_DEFMODE)
2378 goto sdintr_ecc;
2379
2380 if (sdc->sdc_state & SDCS_RASREAD)
2381 goto sdintr_rasblk;
2382
2383 sdc->sdc_state = SDCS_ECC;
2384 goto sdintr_msel_set;
2385
2386 /********************************/
2387 /* unit start & retry */
2388 /********************************/
2389 /* NOT READY */
2390 case 0x04: /* Drive Not Ready */
2391 if (sdc->sdc_state & SDCS_ECC)
2392 sdc->sdc_state = SDCS_ECCOFF|SDCS_RETRY;
2393 else
2394 sdc->sdc_state = SDCS_RETRY;
2395 goto sdintr_stst;
2396
2397 /********************************/
2398 /* retry */
2399 /********************************/
2400 /* UNIT ATTENTION */
2401 case 0x28: /* Medium Changed */
2402 sdd->sdd_flags &= ~(SDDF_NONFMT
2403 |SDDF_SAMEDSK
2404 |SDDF_REQ_EJECT
2405 |SDDF_XUSE
2406 |SDDF_INHRMV
2407 |SDDF_ERASEOFF);
2408 /* fall through */
2409
2410 case 0x29: /* Power On or Reset or Bus Device Reset */
2411 if (sdc->sdc_firmware & SDCFW_RMB) {
2412 /***************************/
2413 /* medium removable device */
2414 /***************************/
2415 sdc->sdc_state = SDCS_PREVRMB;
2416 im->im_tab.b_active = 2;
2417 scop_medrmv(intr, sc, slave,
2418 SCSI_INTEN, SDRMV_PREV);
2419 return;
2420 }
2421
2422 case 0x2a: /* Mode Select Parameter Changed */
2423 case 0x47: /* SCSI interface bus parity error */
2424 if (sdc->sdc_state & SDCS_ECC) {
2425 sdc->sdc_state = SDCS_RETRY;
2426 goto sdintr_msel_reset;
2427 }
2428 sdc->sdc_state = SDCS_NORMAL;
2429 goto sdintr_exec;
2430
2431 /********************************/
2432 /* set error flag */
2433 /********************************/
2434 case 0x40: /* RAM failure */
2435 case 0x41: /* Data Path diagnostic failure */
2436 case 0x42: /* Power On diagnostic failure */
2437
2438 case 0xb2: /* Caddy load/eject failed */
2439 case 0xb4: /* Focus servo failure */
2440 case 0xb5: /* Spindle servo failure */
2441 case 0xb6: /* Caddy load mechanism failed */
2442 goto sdintr_error;
2443
2444 /*MO*/ case 0x80: /* Limit Laser Life */
2445 /*MO*/ case 0x81: /* Focus Coil Over-current Failure */
2446 /*MO*/ case 0x82: /* Tracking Coil Over-current Failure */
2447 /*MO*/ case 0x83: /* Temperature Alarm */
2448 /*CD*/ /* case 0x80: */ /* Prevent bit is set */
2449 /*CD*/ /* case 0x81: */ /* Logical unit is reserved */
2450 /*CD*/ /* case 0x82: */ /* End of usr area encountered */
2451 /*CD*/ /* case 0x83: */ /* Overlapped commands attempted */
2452 goto sdintr_error;
2453
2454 default:
2455 /*
2456 * error detect, but what shall we do ?
2457 */
2458 /* case 0x05: */ /* Drive Not Selected */
2459 /* case 0x07: */ /* Multiple Drives Selected */
2460 /* case 0x0a: */ /* No disk */
2461 /* case 0x1a: */ /* Parameter overrun */
2462 /* case 0x1b: */ /* Synchronous transfer error */
2463 /* case 0x1d: */ /* Compare error */
2464 /* case 0x22: */ /* Illegal function for device type */
2465 /* case 0x23: */ /* Illegal function for Medium type */
2466 /* case 0x25: */ /* Illegal LUN */
2467 /* case 0x27: */ /* Write Protected */
2468 /* case 0x2b: */ /* Firmware has been downloaded */
2469 /* case 0x39: */ /* Automatic Reallocation Failure */
2470 /* case 0x43: */ /* Message Reject Error */
2471 /* case 0x45: */ /* Selection/Reselection failure */
2472 /* case 0x48: */ /* Initiator detected error */
2473 /* case 0x49: */ /* Inappropriate/illegal message */
2474 /* case 0x60: */ /* COPY: STATUS error */
2475 /* case 0x85: */ /* Audio address not valid */
2476 /* case 0xb0: */ /* Caddy not inserted in drive */
2477 /* case 0xb1: */ /* Unable to recover TOC */
2478 /* case 0xb3: */ /* CIRC unrecovered data error(L-EC off) */
2479 /* case 0xc3: */ /* COPY: Illegale CDB length */
2480 /* case 0xc5: */ /* COPY: Catastrophic error */
2481 /* case 0xc6: */ /* COPY: Illegal phase change */
2482 /* case 0xfc: */ /* COPY: MODE SENSE failed */
2483
2484 /*
2485 * medium error
2486 */
2487 /* case 0x19: */ /* Defect list error */
2488 /* case 0x1c: */ /* Primary Defect List not found */
2489 /* case 0x30: */ /* Incompatible Cartridge */
2490 /* case 0x32: */ /* No Spare Defect Location Available */
2491 /* case 0x3a: */ /* Defect List Update Failure */
2492 /* case 0x3d: */ /* Defect List Not Available */
2493 goto sdintr_error;
2494 }
2495 /*
2496 * No error detected or ignored.
2497 */
2498 break;
2499
2500 /************************************************/
2501 /* */
2502 /* PREVENT MEDIUM REMOVABLE COMMAND */
2503 /* */
2504 /************************************************/
2505 case SDCS_PREVRMB:
2506 if (tstatus == TGST_CC) {
2507 sdc->sdc_state = SDCS_PREVRMB|SDCS_RSENSE;
2508 goto sdintr_rsense;
2509 }
2510 sdd->sdd_flags |= SDDF_INHRMV;
2511 if (sdc->sdc_state & SDCS_ECC) {
2512 sdc->sdc_state = SDCS_RETRY;
2513 goto sdintr_msel_reset;
2514 }
2515 sdc->sdc_state = SDCS_NORMAL;
2516 goto sdintr_exec;
2517 break;
2518
2519 /****************************************/
2520 /* */
2521 /* REZERO done & RETRY COMMAND */
2522 /* */
2523 /****************************************/
2524 case SDCS_ECC|SDCS_ECC_HOLD|SDCS_REZERO:
2525 if (sdc->sdc_firmware & SDCFW_DEFMODE) {
2526 sdc->sdc_state = SDCS_ECC|SDCS_ECC_HOLD|SDCS_RETRY;
2527 goto sdintr_stst;
2528 }
2529
2530 sdc->sdc_state = SDCS_ECC|SDCS_ECC_HOLD;
2531 goto sdintr_msel_set;
2532
2533 /********************************/
2534 /* */
2535 /* RETRY COMMAND */
2536 /* */
2537 /********************************/
2538 case SDCS_RETRY:
2539 sdc->sdc_state = SDCS_NORMAL;
2540 goto sdintr_exec;
2541
2542 /************************************************/
2543 /* */
2544 /* ERROR CORRECTION ON MODE SELECT result */
2545 /* */
2546 /************************************************/
2547 case SDCS_ECC:
2548 if (tstatus != TGST_GOOD) {
2549 printf("sd%d: bad target status 0x%x\n",
2550 unit, sc->sc_tstatus);
2551 goto sdintr_error;
2552 }
2553 sdintr_ecc:
2554 if (bp->b_flags & B_READ) {
2555 sdc->sdc_state = SDCS_ECC|SDCS_RASREAD;
2556 im->im_tab.b_active = 2;
2557 scop_rdwr(intr, sc, slave, SCSI_INTEN,
2558 B_READ, sdwork,
2559 sdd->sdd_badsect, sdd->sdd_sectsize);
2560 return;
2561 }
2562 goto sdintr_rasblk;
2563
2564 /************************************************/
2565 /* */
2566 /* READ DATA from BAD BLOCK result */
2567 /* */
2568 /************************************************/
2569 case SDCS_ECC|SDCS_RASREAD:
2570 if (tstatus == TGST_CC) {
2571 sdc->sdc_state = SDCS_ECC|SDCS_RASREAD|SDCS_RSENSE;
2572 goto sdintr_rsense;
2573 } else if (tstatus != TGST_GOOD) {
2574 printf("sd%d: bad target status 0x%x\n",
2575 unit, sc->sc_tstatus);
2576 printf("sd%d: cannot read block\n", unit);
2577 goto sdintr_error;
2578 }
2579 sdintr_rasblk:
2580 if (sdd->sdd_flags & SDDF_WPROTECT)
2581 goto sdintr_error;
2582 sdc->sdc_state = SDCS_ECC|SDCS_RASBLK;
2583 im->im_tab.b_active = 2;
2584 scop_rasblk(intr, sc, slave, SCSI_INTEN, sdd->sdd_badsect);
2585 sdd->sdd_flags &= ~SDDF_VBADSECT;
2586 return;
2587
2588 /****************************************/
2589 /* */
2590 /* REASSIGN BLOCK result */
2591 /* */
2592 /****************************************/
2593 case SDCS_ECC|SDCS_RASBLK:
2594 if (tstatus == TGST_CC) {
2595 sdc->sdc_state = SDCS_ECC|SDCS_RASBLK|SDCS_RSENSE;
2596 goto sdintr_rsense;
2597 } else if (tstatus != TGST_GOOD) {
2598 printf("sd%d: bad target status 0x%x\n",
2599 unit, sc->sc_tstatus);
2600 goto sdintr_error;
2601 }
2602 printf("sd%d: block %d is reassigned\n",
2603 unit, sdd->sdd_badsect);
2604 if (bp->b_flags & B_READ) {
2605 sdintr_raswrite:
2606 sdc->sdc_state = SDCS_ECC|SDCS_RASWRITE;
2607 im->im_tab.b_active = 2;
2608 scop_rdwr(intr, sc, slave, SCSI_INTEN,
2609 B_WRITE, sdwork,
2610 sdd->sdd_badsect, sdd->sdd_sectsize);
2611 return;
2612 }
2613 sdc->sdc_state = SDCS_RETRY;
2614 goto sdintr_msel_reset;
2615
2616 /************************************************/
2617 /* */
2618 /* WRITE DATA to REASSIGNED BLOCK result */
2619 /* */
2620 /************************************************/
2621 case SDCS_ECC|SDCS_RASWRITE:
2622 if (tstatus == TGST_CC) {
2623 sdc->sdc_state = SDCS_ECC|SDCS_RASWRITE|SDCS_RSENSE;
2624 goto sdintr_rsense;
2625 } else if (tstatus != TGST_GOOD) {
2626 printf("sd%d: bad target status 0x%x\n",
2627 unit, sc->sc_tstatus);
2628 goto sdintr_error;
2629 }
2630 sdc->sdc_state = SDCS_RETRY;
2631 goto sdintr_msel_reset;
2632
2633 /****************************************/
2634 /* */
2635 /* reset ECC & RETRY TIMES */
2636 /* */
2637 /****************************************/
2638 case SDCS_ECCOFF|SDCS_RETRY:
2639 sdc->sdc_state = SDCS_RETRY;
2640 goto sdintr_msel_reset;
2641
2642 /********************************************************/
2643 /* */
2644 /* READ DATA from BAD BLOCK result in faliure */
2645 /* */
2646 /********************************************************/
2647 case SDCS_ECC|SDCS_RASBLK|SDCS_LOSTDATA:
2648 if (tstatus == TGST_CC) {
2649 sdc->sdc_state =
2650 SDCS_ECC|SDCS_RASBLK|SDCS_LOSTDATA|SDCS_RSENSE;
2651 goto sdintr_rsense;
2652 } else if (tstatus != TGST_GOOD) {
2653 printf("sd%d: rasblk: bad target status 0x%x\n",
2654 unit, sc->sc_tstatus);
2655 goto sdintr_error;
2656 }
2657 bzero(sdwork, sdd->sdd_sectsize);
2658 scop_rdwr(intr, sc, slave, SCSI_INTDIS,
2659 B_WRITE, sdwork, sdd->sdd_badsect, sdd->sdd_sectsize);
2660 printf("sd%d: block %d is reassigned (lost data)\n",
2661 unit, sdd->sdd_badsect);
2662 goto sdintr_error;
2663
2664 /****************************************/
2665 /* */
2666 /* issue START UNIT command */
2667 /* */
2668 /****************************************/
2669 case SDCS_ECC|SDCS_ECC_HOLD:
2670 /*
2671 * Drive not ready... so start..
2672 */
2673 sdc->sdc_state = SDCS_ECC|SDCS_ECC_HOLD|SDCS_RETRY;
2674 sdintr_stst:
2675 timeout(delay_start, (caddr_t)ii, hz);
2676 return;
2677
2678 /****************************************/
2679 /* */
2680 /* RETRY with ECC & more RETRYS */
2681 /* */
2682 /****************************************/
2683 case SDCS_ECC|SDCS_ECC_HOLD|SDCS_RETRY:
2684 sdc->sdc_state = SDCS_ECCOFF;
2685 sdintr_exec:
2686 if (sdc->sdc_countcc++ > MAXRETRYCNT)
2687 goto sdintr_error;
2688 sdexec(bp);
2689 return;
2690
2691 /****************************************/
2692 /* */
2693 /* reset ECC & RETRY TIMES */
2694 /* */
2695 /****************************************/
2696 case SDCS_ECCOFF:
2697 if (tstatus == TGST_CC) {
2698 sdc->sdc_state = SDCS_ECCOFF|SDCS_RSENSE;
2699 goto sdintr_rsense;
2700 } else if (tstatus != TGST_GOOD) {
2701 printf("sd%d: bad target status 0x%x\n",
2702 unit, sc->sc_tstatus);
2703 goto sdintr_error;
2704 }
2705 sdc->sdc_state = SDCS_NORMAL;
2706 goto sdintr_msel_reset;
2707
2708 sdintr_msel_set:
2709 /*
2710 * set more ERROR RECOVERY PARAMETERS
2711 */
2712 if ((erp_page = sdi->max_ERP_page) == NULL)
2713 goto check_target_status;
2714 bzero((caddr_t)sc->sc_param, 4);
2715 len = *(erp_page + 1) + 2;
2716 bcopy(erp_page, &sc->sc_param[4], len);
2717
2718 im->im_tab.b_active = 2;
2719 scop_mselect(intr, sc, slave, SCSI_INTEN,
2720 (SDM_PF<<24) + len +4, (caddr_t)0);
2721 return;
2722
2723 sdintr_msel_reset:
2724 if (sdc->sdc_firmware & SDCFW_DEFMODE)
2725 goto sdintr_exec;
2726
2727 /*
2728 * set normal ERROR RECOVERY PARAMETERS
2729 */
2730 erp_page = sdi->ERP_page;
2731 bzero((caddr_t)sc->sc_param, 4);
2732 len = *(erp_page + 1) + 2;
2733 bcopy(erp_page, &sc->sc_param[4], len);
2734
2735 im->im_tab.b_active = 2;
2736 scop_mselect(intr, sc, slave, SCSI_INTEN,
2737 (SDM_PF<<24) + len +4, (caddr_t)0);
2738 return;
2739
2740 sdintr_error:
2741 bp->b_flags |= B_ERROR;
2742 if (sdc->sdc_state & SDCS_ECC) {
2743 sdc->sdc_state = SDCS_NORMAL;
2744 goto sdintr_msel_reset;
2745 }
2746 break;
2747
2748 /*
2749 * UNKNOWN STATUS
2750 */
2751 default:
2752 printf("sd%d: unknown status (0x%x)\n", unit, sdc->sdc_state);
2753 goto sdintr_error;
2754 }
2755
2756 sdintr_done:
2757
2758 if (bp->b_flags & B_ERROR) {
2759 printf("%s%d%c: hard error sn%d ", "sd",
2760 minor(bp->b_dev) >> 3, 'a'+(minor(bp->b_dev)&07), bp->b_blkno);
2761 printf("\n");
2762 }
2763 sdd->sdd_lastblk = dkblock(bp) + btodb(bp->b_bcount - bp->b_resid);
2764 sdc->sdc_countcc = 0;
2765 sdc->sdc_retrycnt = 0;
2766 sdd->sdd_flags &= ~SDDF_VBADSECT;
2767
2768 if (im->im_tab.b_active) {
2769 im->im_tab.b_active = 0;
2770 im->im_tab.b_errcnt = 0;
2771 im->im_tab.b_actf = 0;
2772 dp->b_active = 0;
2773 dp->b_errcnt = 0;
2774 dp->b_actf = bp->b_actf;
2775 if (bp == &csdbuf[unit]) {
2776 register struct scsi *ksc = &kernscsi[unit];
2777 /* copy result */
2778 bcopy((caddr_t)sc, (caddr_t)ksc, sizeof(struct scsi));
2779 }
2780
2781 iodone(bp);
2782
2783 /*
2784 * If this unit has more work to do,
2785 * then start it up right away.
2786 */
2787 if (dp->b_actf)
2788 sdustart(ii);
2789 }
2790 as &= ~(1 << slave);
2791
2792 sdc->sdc_state = SDCS_NORMAL;
2793
2794 /*
2795 * UNLOCK SCSI access
2796 */
2797 sdc->sdc_firmware &= ~SDCFW_BUSY;
2798
2799 start:
2800 /*
2801 * Process other units which need attention.
2802 * For each unit which needs attention, call
2803 * the unit start routine to place the slave
2804 * on the controller device queue.
2805 */
2806 sdc->sdc_softas = 0;
2807 while (unit = ffs(as)) {
2808 unit--;
2809 as &= ~(1 << unit);
2810 sdustart(sdip[im->im_ctlr][unit]);
2811 }
2812 /*
2813 * If the controller is not transferring,
2814 * but there are devices ready to transfer,
2815 * start the controller.
2816 */
2817 if (im->im_tab.b_actf && im->im_tab.b_active == 0)
2818 (void) sdstart(im);
2819 }
2820
wait_re_init_done(bp)2821 wait_re_init_done(bp)
2822 register struct buf *bp;
2823 {
2824 if (re_init_done >= 2)
2825 sdexec(bp);
2826 else
2827 timeout(wait_re_init_done, bp, 10*hz);
2828 }
2829
2830 delay_start(ii)
2831 struct iop/**/_device *ii;
2832 {
2833 ii->ii_mi->im_tab.b_active = 2;
2834 scop_stst(ii->ii_intr, get_scsi(ii->ii_intr), ii->ii_slave,
2835 SCSI_INTEN, SDSS_START);
2836 }
2837
2838 delay_medrmv(ii)
2839 struct iop/**/_device *ii;
2840 {
2841 ii->ii_mi->im_tab.b_active = 2;
2842 scop_medrmv(ii->ii_intr, get_scsi(ii->ii_intr), ii->ii_slave,
2843 SCSI_INTEN, SDRMV_PREV);
2844 }
2845
sderrordisp(rsen_data,ii)2846 sderrordisp(rsen_data, ii)
2847 u_char *rsen_data;
2848 struct iop/**/_device *ii;
2849 {
2850 register struct sc_extnd *sce;
2851 register struct sdc_softc *sdc;
2852 register struct sdd_softc *sdd;
2853 register int unit;
2854 register int code;
2855 struct sc_nextnd *scn;
2856 struct msg_list *ml;
2857
2858 unit = ii->ii_unit;
2859 sdc = &sdc_softc[ii->ii_ctlr];
2860 sdd = &sdd_softc[unit];
2861
2862 sce = (struct sc_extnd *)rsen_data;
2863
2864 if (sce->sce_extend == 0x70) {
2865 /*
2866 * Extended Sense data
2867 */
2868 code = sce->sce_sdecode;
2869
2870 if (code & 0x80)
2871 ml = ecodelist_mo;
2872 else
2873 ml = ecodelist;
2874
2875 if (sce->sce_advalid) {
2876 if ((sdd->sdd_flags & SDDF_VBADSECT) == 0) {
2877 #ifdef mips
2878 sdd->sdd_badsect = (sce->sce_infob1 << 24) +
2879 (sce->sce_infob2 << 16) +
2880 (sce->sce_infob3 << 8) +
2881 (sce->sce_infob4);
2882 #else
2883 sdd->sdd_badsect = *((int *)&sce->sce_infob1);
2884 #endif
2885 sdd->sdd_flags |= SDDF_VBADSECT;
2886 }
2887 }
2888
2889 if (!rsense_msg_disp && !isdispmsg(code, ml, sdc->sdc_countcc))
2890 return (code);
2891
2892 if (sce->sce_advalid) {
2893 int sn;
2894 #ifdef mips
2895 sn = (sce->sce_infob1 << 24) +
2896 (sce->sce_infob2 << 16) +
2897 (sce->sce_infob3 << 8) +
2898 (sce->sce_infob4);
2899 #else
2900 sn = *((int *)&sce->sce_infob1);
2901 #endif
2902 if (sce->sce_addlen >= 5) {
2903 printf("sd%d(sn %d): skey=0x%x, code=0x%x\n",
2904 unit, sn, sce->sce_skey, code);
2905 } else {
2906 printf("sd%d(sn %d): skey=0x%x\n",
2907 unit, sn, sce->sce_skey);
2908 }
2909 } else {
2910 if (sce->sce_addlen >= 5)
2911 printf("sd%d: skey=0x%x, code=0x%x\n",
2912 unit, sce->sce_skey, code);
2913 else
2914 printf("sd%d: skey=0x%x\n",
2915 unit, sce->sce_skey);
2916 }
2917 if (sce->sce_addlen >= 6)
2918 printf("sd%d: ASCQ=0x%x\n", unit, sce->sce_ascq);
2919 {
2920 u_char *p;
2921 int len;
2922
2923 len = 8 + sce->sce_addlen;
2924 if (len > RSEN_CNT)
2925 len = RSEN_CNT;
2926 p = (u_char *)sce;
2927 printf("sd%d: ", unit);
2928 while (len--)
2929 printf("%x ", *p++);
2930 printf("\n");
2931 }
2932 } else {
2933 /*
2934 * Non-extended Sense data
2935 */
2936 scn = (struct sc_nextnd *)rsen_data;
2937
2938 code = scn->scn_ecode;
2939 ml = ecodelist;
2940 if (sce->sce_advalid) {
2941 if ((sdd->sdd_flags & SDDF_VBADSECT) == 0) {
2942 sdd->sdd_badsect = scn->scn_secno;
2943 sdd->sdd_flags |= SDDF_VBADSECT;
2944 }
2945 }
2946 if (rsense_msg_disp || isdispmsg(code, ml, sdc->sdc_countcc)) {
2947 if (sce->sce_advalid)
2948 printf("sd%d(sn %d): code=0x%x\n",
2949 unit, scn->scn_secno, code);
2950 else
2951 printf("sd%d: code=0x%x\n", unit, code);
2952 }
2953 }
2954 return (code);
2955 }
2956
2957 void
sdminphys(bp)2958 sdminphys(bp)
2959 struct buf *bp;
2960 {
2961 if (bp->b_bcount > MAXSDPHYS)
2962 bp->b_bcount = MAXSDPHYS;
2963 }
2964
2965
2966 #define sdphysio physio
2967
sdread(dev,uio,flag)2968 sdread(dev, uio, flag)
2969 register dev_t dev;
2970 struct uio *uio;
2971 int flag;
2972 {
2973 register struct iop/**/_device *ii;
2974 register int unit;
2975
2976 unit = dev2unit(dev);
2977 if (unit >= nsd || (ii = sddinfo[unit]) == 0)
2978 return (ENXIO);
2979
2980 return (sdphysio(sdstrategy, &rsdbuf[unit], dev, B_READ, sdminphys, uio));
2981 }
2982
sdwrite(dev,uio,flag)2983 sdwrite(dev, uio, flag)
2984 register dev_t dev;
2985 struct uio *uio;
2986 int flag;
2987 {
2988 register struct iop/**/_device *ii;
2989 register int unit;
2990
2991 unit = dev2unit(dev);
2992 if (unit >= nsd || (ii = sddinfo[unit]) == 0)
2993 return (ENXIO);
2994
2995 return (sdphysio(sdstrategy, &rsdbuf[unit], dev, B_WRITE, sdminphys, uio));
2996 }
2997
2998 #define MAXBL 256
2999
3000 struct Partinfo {
3001 /*00*/ daddr_t dp_nblocks; /* partition size (sector #) */
3002 /*04*/ daddr_t dp_blkoff; /* partition start block */
3003 /*08*/
3004 };
3005
3006 struct dkst {
3007 /*00*/ int dks_ncyl; /* # cylinders / drive */
3008 /*04*/ int dks_ntrak; /* # tracks / cylinder */
3009 /*08*/ int dks_nsect; /* # sectors / track */
3010 /*0c*/ int dks_rps; /* # revolutions / second */
3011 /*10*/
3012 };
3013
3014 /*ARGSUSED*/
sdioctl(dev,cmd,data,flag)3015 sdioctl(dev, cmd, data, flag)
3016 dev_t dev;
3017 int cmd;
3018 caddr_t data;
3019 int flag;
3020 {
3021 register struct iop/**/_device *ii;
3022 register struct sc_ureq *scu;
3023 register struct sdst *st;
3024 register struct scsi *sc;
3025 register int unit;
3026 register int ctlr;
3027 register int slave;
3028 struct sdc_softc *sdc;
3029 struct sdd_softc *sdd;
3030 struct Partinfo *pi;
3031 struct dkst *di;
3032 struct buf *bp;
3033 struct sddevinfo *sdi;
3034 struct sdst *stp;
3035 struct scsi uscsi;
3036 int error;
3037 int i;
3038 int s;
3039 int tstatus;
3040 char *p;
3041 int blkno, count;
3042
3043 unit = dev2unit(dev);
3044 if (unit >= nsd || (ii = sddinfo[unit]) == 0 || ii->ii_alive == 0)
3045 return (ENXIO);
3046
3047 slave = ii->ii_slave;
3048 ctlr = ii->ii_ctlr;
3049 sdc = &sdc_softc[ctlr];
3050 sdd = &sdd_softc[unit];
3051 sc = &uscsi;
3052
3053 error = 0;
3054 switch (cmd) {
3055
3056 case DIOCWLABEL:
3057 if (*(int *)data & SD_F_ENW)
3058 ii->ii_flags |= SD_F_ENW;
3059 else
3060 ii->ii_flags &= ~SD_F_ENW;
3061 break;
3062
3063 case DIOCGDINFO:
3064 *(struct disklabel *)data = sdlabel[unit];
3065 break;
3066
3067 case DIOCSDINFO:
3068 sdlabel[unit] = *(struct disklabel *)data;
3069 disklabel2sdst(unit, &sdlabel[unit], &sdstdrv[unit]);
3070 break;
3071
3072 case DIOCWDINFO:
3073 case DKIOCRGEOM:
3074 switch (cmd) {
3075 case DKIOCRGEOM:
3076 st = &sdstdrv[unit];
3077 sdi = &sddevinfo[ii->ii_type];
3078 stp = sdi->sdstp;
3079
3080 st->ncyl = stp->ncyl; /* # cylinders / drive */
3081 st->ntrak = stp->ntrak; /* # tracks / cylinder */
3082 st->nsect = stp->nsect; /* # sectors / track */
3083 st->rps = stp->rps; /* # revolutions / second */
3084
3085 sdst2disklabel(unit, st, &sdlabel[unit]);
3086
3087 if (*(int *)data == RGEOM_SDINFO)
3088 goto done;
3089
3090 break;
3091
3092 case DIOCWDINFO:
3093 sdlabel[unit] = *(struct disklabel *)data;
3094
3095 break;
3096 }
3097
3098 /*
3099 * Common code for DIOCWDINFO and DKIOCRGEOM
3100 */
3101
3102 /**** READ sector 0 ****/
3103 /*
3104 * LOCK sdtmp buffer
3105 */
3106 s = splclock();
3107 while (sdtmp_stat & B_BUSY) {
3108 sdtmp_stat |= B_WANTED;
3109 sleep((caddr_t)sdtmp, PRIBIO);
3110 }
3111 sdtmp_stat |= B_BUSY;
3112 splx(s);
3113
3114 bzero(sdtmp, DEV_BSIZE);
3115
3116 if ((sdd->sdd_flags & SDDF_NONFMT) == 0) {
3117 scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize);
3118 uscsi.sc_cpoint = sdtmp;
3119 uscsi.sc_ctrnscnt = DEV_BSIZE;
3120 uscsi.sc_opcode = SCOP_READ;
3121 uscsi.sc_lad = 0;
3122 uscsi.sc_count = 1;
3123 error = sdcmd(dev, &uscsi);
3124 } else {
3125 error = EIO;
3126 }
3127
3128 if (error) {
3129 /*
3130 * UNLOCK sdtmp buffer
3131 */
3132 s = splclock();
3133 if (sdtmp_stat & B_WANTED)
3134 wakeup((caddr_t)sdtmp);
3135 sdtmp_stat &= ~(B_BUSY|B_WANTED);
3136 splx(s);
3137
3138 break;
3139 }
3140
3141 *(struct disklabel *)(sdtmp + LABELOFFSET) = sdlabel[unit];
3142
3143 /**** WRITE sector 0 ****/
3144
3145 if (error == 0) {
3146 if ((sdd->sdd_flags & SDDF_NONFMT) == 0) {
3147 scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize);
3148 uscsi.sc_cpoint = sdtmp;
3149 uscsi.sc_ctrnscnt = DEV_BSIZE;
3150 uscsi.sc_opcode = SCOP_WRITE;
3151
3152 uscsi.sc_lad = 0;
3153 uscsi.sc_count = 1;
3154
3155 error = sdcmd(dev, &uscsi);
3156 } else
3157 error = EIO;
3158 }
3159
3160 /*
3161 * UNLOCK sdtmp buffer
3162 */
3163 s = splclock();
3164 if (sdtmp_stat & B_WANTED)
3165 wakeup((caddr_t)sdtmp);
3166 sdtmp_stat &= ~(B_BUSY|B_WANTED);
3167 splx(s);
3168
3169 disklabel2sdst(unit, &sdlabel[unit], &sdstdrv[unit]);
3170
3171 break;
3172
3173 case DKIOCGGEOM:
3174 st = &sdstdrv[unit];
3175 di = (struct dkst *)data;
3176
3177 di->dks_ncyl = st->ncyl; /* # cylinders / drive */
3178 di->dks_ntrak = st->ntrak; /* # tracks / cylinder */
3179 di->dks_nsect = st->nsect; /* # sectors / track */
3180 di->dks_rps = st->rps; /* # revolutions / second */
3181
3182 break;
3183
3184 case DKIOCSGEOM:
3185 st = &sdstdrv[unit];
3186 di = (struct dkst *)data;
3187
3188 st->ncyl = di->dks_ncyl; /* # cylinders / drive */
3189 st->ntrak = di->dks_ntrak; /* # tracks / cylinder */
3190 st->nsect = di->dks_nsect; /* # sectors / track */
3191 st->rps = di->dks_rps; /* # revolutions / second */
3192
3193 sdst2disklabel(unit, st, &sdlabel[unit]);
3194 break;
3195
3196 case DKIOCGPART:
3197 case DKIOCSPART:
3198 /*
3199 * partition information
3200 */
3201 st = &sdstdrv[unit];
3202 pi = (struct Partinfo *)data;
3203
3204 if (cmd == DKIOCGPART) {
3205 pi->dp_nblocks = st->sizes[dev2part(dev)].sd_nblocks;
3206 pi->dp_blkoff = st->sizes[dev2part(dev)].sd_blkoff;
3207 } else {
3208 st->sizes[dev2part(dev)].sd_nblocks = pi->dp_nblocks;
3209 st->sizes[dev2part(dev)].sd_blkoff = pi->dp_blkoff;
3210
3211 sdst2disklabel(unit, st, &sdlabel[unit]);
3212 }
3213 break;
3214
3215 case DKIOCGUNIT:
3216 *(int *)data = slave;
3217 break;
3218
3219 case DKIOCGCHAN:
3220 *(int *)data = ii->ii_intr;
3221 break;
3222
3223 case DKIOCSEEK:
3224 scinit(sc, slave, sdd->sdd_sectsize);
3225 sc->sc_opcode = SCOP_SEEK;
3226 sc->sc_lad = *(int *)data;
3227
3228 (void) sdcmd(dev, sc);
3229 tstatus = sc->sc_tstatus & TGSTMASK;
3230 if ((sc->sc_istatus != INST_EP) || (tstatus != TGST_GOOD))
3231 error = ESPIPE;
3232 break;
3233
3234 case DKIOCRSEC0:
3235 case DKIOCRBOOT1:
3236 case DKIOCRBOOT:
3237 if (sdd->sdd_flags & SDDF_NONFMT) {
3238 error = EIO;
3239 break;
3240 }
3241 switch (cmd) {
3242
3243 case DKIOCRSEC0:
3244 blkno = 0;
3245 count = 1;
3246 break;
3247
3248 case DKIOCRBOOT1:
3249 blkno = 1;
3250 count = 15;
3251 break;
3252
3253 default:
3254 blkno = 0;
3255 count = 16;
3256 }
3257 p = (char *)*(int *)data;
3258 for (i = 0; !error && i < count; i++) {
3259 s = splclock();
3260 while (sdtmp_stat & B_BUSY) {
3261 sdtmp_stat |= B_WANTED;
3262 sleep((caddr_t)sdtmp, PRIBIO);
3263 }
3264 sdtmp_stat |= B_BUSY;
3265 splx(s);
3266 scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize);
3267 uscsi.sc_cpoint = sdtmp;
3268 uscsi.sc_ctrnscnt = DEV_BSIZE;
3269 uscsi.sc_opcode = SCOP_READ;
3270 uscsi.sc_lad = blkno;
3271 uscsi.sc_count = 1;
3272 if (error = sdcmd(dev, &uscsi))
3273 goto dkior_done;
3274 if (error = copyout(sdtmp, p, DEV_BSIZE))
3275 goto dkior_done;
3276 blkno++;
3277 p += DEV_BSIZE;
3278
3279 dkior_done:
3280 s = splclock();
3281 if (sdtmp_stat & B_WANTED)
3282 wakeup((caddr_t)sdtmp);
3283 sdtmp_stat &= ~(B_BUSY|B_WANTED);
3284 splx(s);
3285 }
3286 break;
3287
3288 case DKIOCWSEC0:
3289 case DKIOCWBOOT1:
3290 case DKIOCWBOOT:
3291 if (sdd->sdd_flags & SDDF_NONFMT) {
3292 error = EIO;
3293 break;
3294 }
3295 switch (cmd) {
3296
3297 case DKIOCWSEC0:
3298 blkno = 0;
3299 count = 1;
3300 break;
3301
3302 case DKIOCWBOOT1:
3303 blkno = 1;
3304 count = 15;
3305 break;
3306
3307 default:
3308 blkno = 0;
3309 count = 16;
3310 }
3311 p = (char *)*(int *)data;
3312 for (i = 0; !error && i < count; i++) {
3313 s = splclock();
3314 while (sdtmp_stat & B_BUSY) {
3315 sdtmp_stat |= B_WANTED;
3316 sleep(sdtmp, PRIBIO);
3317 }
3318 sdtmp_stat |= B_BUSY;
3319 splx(s);
3320 if (error = copyin(p, sdtmp, DEV_BSIZE))
3321 goto dkiow_done;
3322 scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize);
3323 uscsi.sc_cpoint = sdtmp;
3324 uscsi.sc_ctrnscnt = DEV_BSIZE;
3325 uscsi.sc_opcode = SCOP_WRITE;
3326 uscsi.sc_lad = blkno;
3327 uscsi.sc_count = 1;
3328 if (error = sdcmd(dev, &uscsi))
3329 goto dkiow_done;
3330 blkno++;
3331 p += DEV_BSIZE;
3332
3333 dkiow_done:
3334 s = splclock();
3335 if (sdtmp_stat & B_WANTED)
3336 wakeup(sdtmp);
3337 sdtmp_stat &= ~(B_BUSY|B_WANTED);
3338 splx(s);
3339 }
3340 break;
3341
3342 case SDIOC_PRVRMV:
3343 case SDIOC_ALWRMV:
3344 /*
3345 * prevent/allow medium removal
3346 */
3347 scinit(sc, ii->ii_slave, sdd->sdd_sectsize);
3348 sc->sc_opcode = SCOP_MEDRMV;
3349 sc->sc_count = (cmd==SDIOC_PRVRMV)? SDRMV_PREV : SDRMV_ALLOW;
3350 if (cmd == SDIOC_PRVRMV)
3351 sdd->sdd_flags |= SDDF_INHRMV;
3352 else
3353 sdd->sdd_flags &= ~SDDF_INHRMV;
3354
3355 error = sdcmd(dev, sc);
3356 break;
3357
3358 case SDIOC_SXUSE:
3359 if (isalone(unit) != ONLY_ONE)
3360 return (EBUSY);
3361 sdd->sdd_flags |= SDDF_XUSE;
3362 break;
3363
3364 case SDIOC_RXUSE:
3365 sdd->sdd_flags &= ~SDDF_XUSE;
3366 break;
3367
3368 case SDIOC_ERSON:
3369 sdd->sdd_flags &= ~SDDF_ERASEOFF;
3370 break;
3371
3372 case SDIOC_ERSOFF:
3373 if ((sdd->sdd_flags & SDDF_XUSE) != 0)
3374 return (EBUSY);
3375 sdd->sdd_flags |= SDDF_ERASEOFF;
3376 sdd->sdd_flags &= ~SDDF_NONFMT;
3377 break;
3378
3379 case SDIOC_FORMAT:
3380 /*
3381 * format unit
3382 */
3383 if ((flag & FWRITE) == 0)
3384 return (EINVAL);
3385 if (isalone(unit) != ONLY_ONE)
3386 return (EBUSY);
3387 sdd->sdd_flags |= SDDF_XUSE;
3388 sdd->sdd_flags &= ~(SDDF_NONFMT|SDDF_FMTDONE|SDDF_SAMEDSK);
3389 scinit(sc, ii->ii_slave, sdd->sdd_sectsize);
3390 sc->sc_ctrnscnt = 4;
3391 sc->sc_opcode = SCOP_FMT;
3392
3393 sc->sc_lad = ((sddevinfo[ii->ii_type].fmt_opts & FMT_DLFMT)
3394 | SDF_FMTDAT) << 16;
3395
3396 switch (sddevinfo[ii->ii_type].type) {
3397
3398 case SMO_S501:
3399 case SMO_S501_ISO:
3400 case SMO_S501_ISO2:
3401 sc->sc_lad |= ((SDF_MKCDA|SDF_MKPLST) << 8);
3402 break;
3403
3404 default:
3405 break;
3406 }
3407
3408 {
3409 struct fmt_data *fdata = (struct fmt_data *)data;
3410
3411 error = copyin((caddr_t)fdata->dlh, sc->sc_param, 4);
3412 if (error != 0) {
3413 sdd->sdd_flags &= ~SDDF_XUSE;
3414 break;
3415 }
3416 if (fdata->noglist)
3417 sc->sc_lad |= (SDF_CMPLST<<16);
3418 }
3419
3420 if (sdd->sdd_flags & SDDF_ERASEOFF)
3421 sc->sc_ctrl = 0x40;
3422
3423 error = sdcmd(dev, sc);
3424 sdd->sdd_flags &= ~SDDF_XUSE;
3425 break;
3426
3427 case SDIOC_FORMAT2:
3428 /*
3429 * format unit
3430 */
3431 if ((flag & FWRITE) == 0)
3432 return (EINVAL);
3433 if (isalone(unit) != ONLY_ONE)
3434 return (EBUSY);
3435 sdd->sdd_flags |= SDDF_XUSE;
3436 sdd->sdd_flags &= ~(SDDF_NONFMT|SDDF_FMTDONE|SDDF_SAMEDSK);
3437
3438 scu = (struct sc_ureq *)data;
3439 error = sd_scu_exec(dev, scu, sc);
3440 sdd->sdd_flags &= ~SDDF_XUSE;
3441 break;
3442
3443 case SDIOC_GSTOPT:
3444 case SDIOC_SSTOPT:
3445 /*
3446 * get/set stop-unit timer
3447 */
3448 if (cmd == SDIOC_GSTOPT)
3449 *(int *)data = sdd->sdd_stoptime;
3450 else {
3451 if (*(int *)data == 0)
3452 return (EINVAL);
3453 sdd->sdd_stoptime = *(int *)data;
3454 }
3455 break;
3456
3457 case SDIOC_SEJECT:
3458 /*
3459 * set auto eject flag
3460 */
3461 sdd->sdd_flags |= SDDF_REQ_EJECT;
3462 break;
3463
3464 case SDIOC_GFLAGS:
3465 /*
3466 * get ii->ii_flags
3467 */
3468 *(int *)data = ii->ii_flags;
3469 break;
3470
3471 case SDIOC_SFLAGS:
3472 /*
3473 * set ii->ii_flags
3474 */
3475 ii->ii_flags = *(int *)data;
3476 break;
3477
3478 case SDIOC_RASBLK:
3479 /*
3480 * reassign block
3481 */
3482 {
3483 struct sc_rab *sca = (struct sc_rab *)sc->sc_param;
3484
3485 scinit(sc, ii->ii_slave, sdd->sdd_sectsize);
3486 sc->sc_opcode = SCOP_RASBLK;
3487 sc->sc_ctrnscnt = 8;
3488
3489 sca->sca_dllen = 4;
3490 sca->sca_dlad[0] = *(int *)data;
3491
3492 error = sdcmd(dev, sc);
3493 }
3494 break;
3495
3496 case SDIOC_GNICKNAME:
3497 {
3498 int len;
3499
3500 len = strlen(sddevinfo[ii->ii_type].call_name);
3501
3502 if (len > IOCPARM_MASK)
3503 len = IOCPARM_MASK;
3504
3505 error = copyout(
3506 (caddr_t) sddevinfo[ii->ii_type].call_name,
3507 (caddr_t) *(int *)data,
3508 len);
3509 }
3510 break;
3511
3512 case SDIOC_GTYPINDEX:
3513 *(int *)data = (int)ii->ii_type;
3514 break;
3515
3516 #ifdef SDIOC_SSYNCPARAM
3517 case SDIOC_SSYNCPARAM:
3518 {
3519 struct sync_param *syncp;
3520
3521 syncp = (struct sync_param *)data;
3522 scinit(sc, ii->ii_slave, sdd->sdd_sectsize);
3523 sc->sc_opcode = SCOP_TST;
3524 sc->sc_message = MSG_EXTND; /* extended message */
3525 sc->sc_param[0] = MSG_EXTND;
3526 sc->sc_param[1] = 0x03;
3527 sc->sc_param[2] = 0x01; /* synchronous transfer */
3528 sc->sc_param[3] = syncp->tr_period; /* transfer period */
3529 sc->sc_param[4] = syncp->tr_offset; /* REQ offset */
3530
3531 (void) sdcmd(dev, sc);
3532
3533 syncp = &sd_sync_param[unit];
3534 syncp->tr_period = sc->sc_param[3];
3535 syncp->tr_offset = sc->sc_param[4];
3536
3537 if (syncp->tr_offset)
3538 sdd->sdd_flags |= SDDF_SYNCTR;
3539 else
3540 sdd->sdd_flags &= ~SDDF_SYNCTR;
3541 }
3542 break;
3543
3544 case SDIOC_GSYNCPARAM:
3545 {
3546 struct sync_param *syncp = (struct sync_param *)data;
3547
3548 syncp->tr_period = sd_sync_param[unit].tr_period;
3549 syncp->tr_offset = sd_sync_param[unit].tr_offset;
3550 }
3551 break;
3552 #endif /* SDIOC_SSYNCPARAM */
3553
3554 case MTIOCTOP:
3555 {
3556 register struct mtop *mtop = (struct mtop *)data;
3557 register int lba;
3558 int rest;
3559 int blength;
3560
3561 switch (mtop->mt_op) {
3562
3563 case MTOFFL:
3564 /*
3565 * set auto eject flag
3566 */
3567 sdd->sdd_flags |= SDDF_REQ_EJECT;
3568 break;
3569
3570 #ifdef MTERASE
3571 case MTERASE:
3572 if (isalone(unit) != ONLY_ONE)
3573 return (EBUSY);
3574 sdd->sdd_flags |= SDDF_XUSE;
3575 st = &sdstdrv[unit];
3576 /*
3577 * MO disk erase
3578 * block 0 to end (C partition)
3579 */
3580 lba = 0;
3581 rest = sdd->sdd_nsect; /* C part size */
3582 while (rest > 0) {
3583 blength = (rest > MAXBL)? MAXBL : rest;
3584 scinit(sc, ii->ii_slave,
3585 sdd->sdd_sectsize);
3586 sc->sc_opcode = SCOP_MOERASE;
3587 sc->sc_lad = lba;
3588 sc->sc_count = (blength % MAXBL);
3589
3590 (void) sdcmd(dev, sc);
3591 lba += blength;
3592 rest -= blength;
3593 }
3594 sdd->sdd_flags &= ~SDDF_XUSE;
3595 break;
3596 #endif /* MTERASE */
3597
3598 default:
3599 return (EINVAL);
3600 }
3601 }
3602 break;
3603
3604 case SCSIIOCCMD:
3605 scu = (struct sc_ureq *)data;
3606 if ((scu->scu_count > 0) && scu->scu_addr) {
3607 if (useracc(scu->scu_addr, scu->scu_count, B_WRITE)
3608 == NULL) {
3609 error = EFAULT;
3610 break;
3611 }
3612 }
3613 error = sd_scu_exec(dev, scu, sc);
3614 break;
3615
3616
3617 case SDIOC_INQUIRY:
3618 /*
3619 * LOCK sdtmp buffer
3620 */
3621 s = splclock();
3622 while (sdtmp_stat & B_BUSY) {
3623 sdtmp_stat |= B_WANTED;
3624 sleep((caddr_t)sdtmp, PRIBIO);
3625 }
3626 sdtmp_stat |= B_BUSY;
3627 splx(s);
3628
3629 bzero((caddr_t)sdtmp, sizeof(struct sc_inq));
3630 scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize);
3631 uscsi.sc_cpoint = sdtmp;
3632 uscsi.sc_ctrnscnt = sizeof(struct sc_inq);
3633 uscsi.sc_opcode = SCOP_INQUIRY;
3634 uscsi.sc_count = sizeof(struct sc_inq);
3635
3636 if ((error = sdcmd(dev, &uscsi)) == 0)
3637 bcopy((caddr_t)sdtmp, data, sizeof(struct sc_inq));
3638 /*
3639 * UNLOCK open
3640 */
3641 s = splclock();
3642 if (sdtmp_stat & B_WANTED)
3643 wakeup((caddr_t)sdtmp);
3644 sdtmp_stat &= ~(B_BUSY|B_WANTED);
3645 splx(s);
3646 break;
3647
3648
3649 case SCSIIOCGTIMEO:
3650 *(int *)data = sdc->sdc_timeo;
3651 break;
3652
3653 case SCSIIOCSTIMEO:
3654 if (*(int *)data == 0)
3655 return (EINVAL);
3656 sdc->sdc_timeo = *(int *)data;
3657 sdc->sdc_wticks = 0;
3658 break;
3659
3660 default:
3661 error = EINVAL;
3662 break;
3663 }
3664
3665 done:
3666 return (error);
3667 }
3668
3669 static
sd_scu_exec(dev,scu,sc)3670 sd_scu_exec(dev, scu, sc)
3671 dev_t dev;
3672 register struct sc_ureq *scu;
3673 register struct scsi *sc;
3674 {
3675 struct sdd_softc *sdd;
3676 int error;
3677
3678 sdd = &sdd_softc[dev2unit(dev)];
3679
3680 if (((scu->scu_identify & MSG_IDENT) == 0)
3681 || (scu->scu_identify & ~(MSG_IDENT|IDT_DISCON|IDT_DRMASK))
3682 || (scu->scu_addr && (scu->scu_bytesec == 0))) {
3683 return (EINVAL);
3684 }
3685
3686 bzero((caddr_t)sc, sizeof(struct scsi));
3687 sc->sc_tstatus = scu->scu_tstatus;
3688 sc->sc_identify = scu->scu_identify;
3689 sc->sc_message = scu->scu_message;
3690 sc->sc_bytesec = scu->scu_bytesec;
3691 sc->sc_cpoint = scu->scu_addr;
3692 sc->sc_ctrnscnt = scu->scu_count;
3693 bcopy((caddr_t)scu->scu_cdb, &sc->sc_cdb, sizeof(sc->sc_cdb));
3694
3695 bcopy((caddr_t)scu->scu_param, (caddr_t)sc->sc_param,
3696 sizeof(sc->sc_param));
3697
3698 sdd->sdd_flags |= SDDF_SKIPCHECK;
3699 error = sdcmd(dev, sc);
3700 sdd->sdd_flags &= ~SDDF_SKIPCHECK;
3701
3702 scu->scu_istatus = sc->sc_istatus;
3703 scu->scu_tstatus = sc->sc_tstatus;
3704 scu->scu_message = sc->sc_message;
3705 bcopy((caddr_t)sc->sc_param, (caddr_t)scu->scu_param,
3706 sizeof(sc->sc_param));
3707 return (error);
3708 }
3709
3710 /*ARGSUSED*/
sddump(dev)3711 sddump(dev)
3712 dev_t dev;
3713 {
3714 return (ENXIO);
3715 }
3716
sdsize(dev)3717 sdsize(dev)
3718 register dev_t dev;
3719 {
3720 register struct iop/**/_device *ii;
3721 register struct sdd_softc *sdd;
3722 register struct sdst *st;
3723 register int unit;
3724 int i;
3725
3726 unit = dev2unit(dev);
3727 if (unit >= nsd || (ii = sddinfo[unit]) == 0 || ii->ii_alive == 0)
3728 return (-1);
3729
3730 sdd = &sdd_softc[unit];
3731 switch (sdc_softc[ii->ii_ctlr].sdc_firmware & SDCFW_DEVMASK) {
3732
3733 case SDCFW_HD: /* Hard Disk */
3734 st = &sdstdrv[unit];
3735 break;
3736
3737 case SDCFW_MO: /* MO only */
3738 if ((sdd->sdd_flags & SDDF_SAMEDSK) == SDDF_DSKCHGD) {
3739 /*
3740 * read partition information,
3741 * and set up sdstdrv[unit]
3742 */
3743 if (sd_b_open(dev, FREAD|FWRITE) != 0) {
3744 /*
3745 * block device open error
3746 */
3747 return (-1);
3748 } else {
3749 /*
3750 * use disk partition information
3751 */
3752 st = &sdstdrv[unit];
3753 if (isalone(unit) == ONLY_ONE)
3754 sd_b_close(dev, 0);
3755 }
3756 } else if (sdd->sdd_flags & SDDF_NONFMT) {
3757 /*
3758 * medium is not initialized.
3759 */
3760 return (-1);
3761 } else {
3762 st = &sdstdrv[unit];
3763 }
3764 break;
3765
3766 default:
3767 /* case SDCFW_CD: */
3768 return (-1);
3769
3770 }
3771
3772 if (st->sizes == NULL)
3773 return (-1); /* XXX */
3774 else
3775 return (st->sizes[dev2part(dev)].sd_nblocks); /* XXX */
3776 }
3777
3778 /*
3779 * Reset driver.
3780 * Cancel software state of all pending transfers,
3781 * and restart all units and the controller.
3782 */
sdreset()3783 sdreset()
3784 {
3785 register struct iop/**/_ctlr *im;
3786 register struct iop/**/_device *ii;
3787 register struct sdc_softc *sdc;
3788 register struct sdd_softc *sdd;
3789 register int i;
3790 register int unit;
3791
3792 re_init_done = 1;
3793 for (i = 0; i < nsdc; i++) {
3794 im = sdminfo[i];
3795 if (im == 0)
3796 continue;
3797 if (im->im_alive == 0)
3798 continue;
3799 printf(" sdc%d: ", i);
3800 sdc = &sdc_softc[i];
3801 sdc->sdc_wticks = 0;
3802
3803 /* scop_init() is already called by screset() */
3804
3805 sdtmp_stat &= ~B_BUSY;
3806
3807 for (unit = 0; unit < nsd; unit++) {
3808 ii = sddinfo[unit];
3809 if (ii == 0)
3810 continue;
3811 if (ii->ii_alive == 0)
3812 continue;
3813 if (ii->ii_mi != im)
3814 continue;
3815
3816 csdbuf[unit].b_flags &= ~B_BUSY;
3817
3818 sdd = &sdd_softc[unit];
3819 sdd->sdd_flags = 0;
3820
3821 /*
3822 * UNLOCK SCSI access
3823 */
3824 sdc->sdc_firmware &= ~SDCFW_BUSY;
3825
3826 if (sdslave(ii, ii->ii_addr, im->im_intr) == 0) {
3827 printf("sd%d: not ready\n", ii->ii_slave);
3828 continue;
3829 }
3830 sdattach(ii);
3831 }
3832 }
3833 re_init_done = 2;
3834 }
3835
3836 int sd_long_timeout = 24 * 60 * 60; /* 24 hours */
3837
3838 #define max(a, b) (((a)>(b))?(a):(b))
3839
3840 /*
3841 * Wake up every second and if interrupt is pending
3842 * but nothing has happened increment a counter.
3843 * If nothing happens for sdc_timeo seconds, reset the IOP
3844 * and begin anew.
3845 */
sdwatch()3846 sdwatch()
3847 {
3848 register struct iop/**/_ctlr *im;
3849 register struct sdc_softc *sdc;
3850 register int i;
3851 register int unit;
3852 int timeo;
3853
3854 extern int Scsi_Disconnect;
3855
3856 timeout(sdwatch, (caddr_t)0, hz);
3857 for (i = 0; i < nsdc; i++) {
3858 im = sdminfo[i];
3859 if (im == 0)
3860 continue;
3861 if (im->im_alive == 0)
3862 continue;
3863 sdc = &sdc_softc[i];
3864
3865 if (im->im_tab.b_active)
3866 goto active;
3867
3868 for (unit = 0; unit < nsd; unit++)
3869 if (sdutab[unit].b_active && sddinfo[unit]->ii_mi == im)
3870 goto active;
3871
3872 sdc->sdc_wticks = 0;
3873 continue;
3874 active:
3875 if (Scsi_Disconnect)
3876 timeo = sdc->sdc_timeo;
3877 else
3878 timeo = max(sdc->sdc_timeo, sd_long_timeout);
3879
3880 if (sdc->sdc_wticks++ >= timeo) {
3881 register struct scsi *sc;
3882
3883 sc = get_scsi(im->im_intr);
3884 sdc->sdc_wticks = 0;
3885 printf("sdc%d: lost interrupt\n", i);
3886
3887 screset(im->im_intr);
3888 }
3889 }
3890 }
3891
3892 /*
3893 * sdstop() is timer interrupt routine.
3894 * So, can't use sleep().
3895 */
sdstop()3896 sdstop()
3897 {
3898 register struct iop/**/_ctlr *im;
3899 register struct iop/**/_device *ii;
3900 register struct sdc_softc *sdc;
3901 register struct sdd_softc *sdd;
3902 register int unit;
3903 register int intr;
3904 register int i;
3905 struct scsi *sc;
3906 int eject_sw;
3907
3908 timeout(sdstop, (caddr_t)0, hz);
3909
3910 for (i = 0; i < nsdc; i++) {
3911 im = sdminfo[i];
3912 if (im == 0)
3913 continue;
3914 if (im->im_alive == 0)
3915 continue;
3916 for (unit = 0; unit < nsd; unit++) {
3917 if ((ii = sddinfo[unit]) == 0)
3918 continue;
3919 if (ii->ii_mi != im)
3920 continue;
3921 sdc = &sdc_softc[ii->ii_ctlr];
3922 if ((sdc->sdc_firmware & SDCFW_RMB) == 0)
3923 continue;
3924 intr = ii->ii_intr;
3925 if (isalone(unit))
3926 continue;
3927 /**********************/
3928 /* MO & CD-ROM */
3929 /**********************/
3930 /*
3931 * there is no process which open the unit.
3932 */
3933 sdd = &sdd_softc[unit];
3934 sc = get_scsi(intr);
3935 if (sdd->sdd_start > 0)
3936 sdd->sdd_start--;
3937 else if (sdd->sdd_start == 0) {
3938 /*
3939 * Now stop the unit.
3940 * check SCSI access
3941 */
3942 if (sdc->sdc_firmware & SDCFW_BUSY)
3943 continue;
3944 sdc->sdc_firmware |= SDCFW_BUSY;
3945 sdc->sdc_state |= SDCS_IOCTL|SDCS_SCUNLOCK;
3946
3947 eject_sw = (sdd->sdd_flags & SDDF_REQ_EJECT) ?
3948 SDSS_EJECT : SDSS_STOP;
3949 scop_stst(intr, sc, ii->ii_slave,
3950 SCSI_INTEN, eject_sw);
3951 sdd->sdd_start = -2;
3952 }
3953 }
3954 }
3955 }
3956
isalone(unit)3957 isalone(unit)
3958 register int unit;
3959 {
3960 register int i, n;
3961
3962 n = 0;
3963 for (i = 0; i < PNUM; i++)
3964 n += (sd_b_openf[unit][i] + sd_c_openf[unit][i]);
3965 return (n);
3966 }
3967
3968 /************************************************
3969 * Convert Hex and RS code table definition *
3970 ************************************************/
3971
3972 #define X8_L 0x001d
3973 #define X8_H 0x1d00
3974
3975
3976 #define hextors(data) hxtable[(int)((data) & 0xff)]
3977 #define XORMASK(code) xortable[(unsigned int)(code)]
3978
3979 int hxtable[256] = {
3980 0x00, 0x00, 0x01, 0x19, 0x02, 0x32, 0x1a, 0xc6,
3981 0x03, 0xdf, 0x33, 0xee, 0x1b, 0x68, 0xc7, 0x4b,
3982 0x04, 0x64, 0xe0, 0x0e, 0x34, 0x8d, 0xef, 0x81,
3983 0x1c, 0xc1, 0x69, 0xf8, 0xc8, 0x08, 0x4c, 0x71,
3984 0x05, 0x8a, 0x65, 0x2f, 0xe1, 0x24, 0x0f, 0x21,
3985 0x35, 0x93, 0x8e, 0xda, 0xf0, 0x12, 0x82, 0x45,
3986 0x1d, 0xb5, 0xc2, 0x7d, 0x6a, 0x27, 0xf9, 0xb9,
3987 0xc9, 0x9a, 0x09, 0x78, 0x4d, 0xe4, 0x72, 0xa6,
3988 0x06, 0xbf, 0x8b, 0x62, 0x66, 0xdd, 0x30, 0xfd,
3989 0xe2, 0x98, 0x25, 0xb3, 0x10, 0x91, 0x22, 0x88,
3990 0x36, 0xd0, 0x94, 0xce, 0x8f, 0x96, 0xdb, 0xbd,
3991 0xf1, 0xd2, 0x13, 0x5c, 0x83, 0x38, 0x46, 0x40,
3992 0x1e, 0x42, 0xb6, 0xa3, 0xc3, 0x48, 0x7e, 0x6e,
3993 0x6b, 0x3a, 0x28, 0x54, 0xfa, 0x85, 0xba, 0x3d,
3994 0xca, 0x5e, 0x9b, 0x9f, 0x0a, 0x15, 0x79, 0x2b,
3995 0x4e, 0xd4, 0xe5, 0xac, 0x73, 0xf3, 0xa7, 0x57,
3996 0x07, 0x70, 0xc0, 0xf7, 0x8c, 0x80, 0x63, 0x0d,
3997 0x67, 0x4a, 0xde, 0xed, 0x31, 0xc5, 0xfe, 0x18,
3998 0xe3, 0xa5, 0x99, 0x77, 0x26, 0xb8, 0xb4, 0x7c,
3999 0x11, 0x44, 0x92, 0xd9, 0x23, 0x20, 0x89, 0x2e,
4000 0x37, 0x3f, 0xd1, 0x5b, 0x95, 0xbc, 0xcf, 0xcd,
4001 0x90, 0x87, 0x97, 0xb2, 0xdc, 0xfc, 0xbe, 0x61,
4002 0xf2, 0x56, 0xd3, 0xab, 0x14, 0x2a, 0x5d, 0x9e,
4003 0x84, 0x3c, 0x39, 0x53, 0x47, 0x6d, 0x41, 0xa2,
4004 0x1f, 0x2d, 0x43, 0xd8, 0xb7, 0x7b, 0xa4, 0x76,
4005 0xc4, 0x17, 0x49, 0xec, 0x7f, 0x0c, 0x6f, 0xf6,
4006 0x6c, 0xa1, 0x3b, 0x52, 0x29, 0x9d, 0x55, 0xaa,
4007 0xfb, 0x60, 0x86, 0xb1, 0xbb, 0xcc, 0x3e, 0x5a,
4008 0xcb, 0x59, 0x5f, 0xb0, 0x9c, 0xa9, 0xa0, 0x51,
4009 0x0b, 0xf5, 0x16, 0xeb, 0x7a, 0x75, 0x2c, 0xd7,
4010 0x4f, 0xae, 0xd5, 0xe9, 0xe6, 0xe7, 0xad, 0xe8,
4011 0x74, 0xd6, 0xf4, 0xea, 0xa8, 0x50, 0x58, 0xaf,
4012 };
4013
4014 int xortable[256] = {
4015 0x00000000, 0x90910101, 0x91210201, 0x01b00300,
4016 0x92410401, 0x02d00500, 0x03600600, 0x93f10701,
4017 0x94810801, 0x04100900, 0x05a00a00, 0x95310b01,
4018 0x06c00c00, 0x96510d01, 0x97e10e01, 0x07700f00,
4019 0x99011001, 0x09901100, 0x08201200, 0x98b11301,
4020 0x0b401400, 0x9bd11501, 0x9a611601, 0x0af01700,
4021 0x0d801800, 0x9d111901, 0x9ca11a01, 0x0c301b00,
4022 0x9fc11c01, 0x0f501d00, 0x0ee01e00, 0x9e711f01,
4023 0x82012001, 0x12902100, 0x13202200, 0x83b12301,
4024 0x10402400, 0x80d12501, 0x81612601, 0x11f02700,
4025 0x16802800, 0x86112901, 0x87a12a01, 0x17302b00,
4026 0x84c12c01, 0x14502d00, 0x15e02e00, 0x85712f01,
4027 0x1b003000, 0x8b913101, 0x8a213201, 0x1ab03300,
4028 0x89413401, 0x19d03500, 0x18603600, 0x88f13701,
4029 0x8f813801, 0x1f103900, 0x1ea03a00, 0x8e313b01,
4030 0x1dc03c00, 0x8d513d01, 0x8ce13e01, 0x1c703f00,
4031 0xb4014001, 0x24904100, 0x25204200, 0xb5b14301,
4032 0x26404400, 0xb6d14501, 0xb7614601, 0x27f04700,
4033 0x20804800, 0xb0114901, 0xb1a14a01, 0x21304b00,
4034 0xb2c14c01, 0x22504d00, 0x23e04e00, 0xb3714f01,
4035 0x2d005000, 0xbd915101, 0xbc215201, 0x2cb05300,
4036 0xbf415401, 0x2fd05500, 0x2e605600, 0xbef15701,
4037 0xb9815801, 0x29105900, 0x28a05a00, 0xb8315b01,
4038 0x2bc05c00, 0xbb515d01, 0xbae15e01, 0x2a705f00,
4039 0x36006000, 0xa6916101, 0xa7216201, 0x37b06300,
4040 0xa4416401, 0x34d06500, 0x35606600, 0xa5f16701,
4041 0xa2816801, 0x32106900, 0x33a06a00, 0xa3316b01,
4042 0x30c06c00, 0xa0516d01, 0xa1e16e01, 0x31706f00,
4043 0xaf017001, 0x3f907100, 0x3e207200, 0xaeb17301,
4044 0x3d407400, 0xadd17501, 0xac617601, 0x3cf07700,
4045 0x3b807800, 0xab117901, 0xaaa17a01, 0x3a307b00,
4046 0xa9c17c01, 0x39507d00, 0x38e07e00, 0xa8717f01,
4047 0xd8018001, 0x48908100, 0x49208200, 0xd9b18301,
4048 0x4a408400, 0xdad18501, 0xdb618601, 0x4bf08700,
4049 0x4c808800, 0xdc118901, 0xdda18a01, 0x4d308b00,
4050 0xdec18c01, 0x4e508d00, 0x4fe08e00, 0xdf718f01,
4051 0x41009000, 0xd1919101, 0xd0219201, 0x40b09300,
4052 0xd3419401, 0x43d09500, 0x42609600, 0xd2f19701,
4053 0xd5819801, 0x45109900, 0x44a09a00, 0xd4319b01,
4054 0x47c09c00, 0xd7519d01, 0xd6e19e01, 0x46709f00,
4055 0x5a00a000, 0xca91a101, 0xcb21a201, 0x5bb0a300,
4056 0xc841a401, 0x58d0a500, 0x5960a600, 0xc9f1a701,
4057 0xce81a801, 0x5e10a900, 0x5fa0aa00, 0xcf31ab01,
4058 0x5cc0ac00, 0xcc51ad01, 0xcde1ae01, 0x5d70af00,
4059 0xc301b001, 0x5390b100, 0x5220b200, 0xc2b1b301,
4060 0x5140b400, 0xc1d1b501, 0xc061b601, 0x50f0b700,
4061 0x5780b800, 0xc711b901, 0xc6a1ba01, 0x5630bb00,
4062 0xc5c1bc01, 0x5550bd00, 0x54e0be00, 0xc471bf01,
4063 0x6c00c000, 0xfc91c101, 0xfd21c201, 0x6db0c300,
4064 0xfe41c401, 0x6ed0c500, 0x6f60c600, 0xfff1c701,
4065 0xf881c801, 0x6810c900, 0x69a0ca00, 0xf931cb01,
4066 0x6ac0cc00, 0xfa51cd01, 0xfbe1ce01, 0x6b70cf00,
4067 0xf501d001, 0x6590d100, 0x6420d200, 0xf4b1d301,
4068 0x6740d400, 0xf7d1d501, 0xf661d601, 0x66f0d700,
4069 0x6180d800, 0xf111d901, 0xf0a1da01, 0x6030db00,
4070 0xf3c1dc01, 0x6350dd00, 0x62e0de00, 0xf271df01,
4071 0xee01e001, 0x7e90e100, 0x7f20e200, 0xefb1e301,
4072 0x7c40e400, 0xecd1e501, 0xed61e601, 0x7df0e700,
4073 0x7a80e800, 0xea11e901, 0xeba1ea01, 0x7b30eb00,
4074 0xe8c1ec01, 0x7850ed00, 0x79e0ee00, 0xe971ef01,
4075 0x7700f000, 0xe791f101, 0xe621f201, 0x76b0f300,
4076 0xe541f401, 0x75d0f500, 0x7460f600, 0xe4f1f701,
4077 0xe381f801, 0x7310f900, 0x72a0fa00, 0xe231fb01,
4078 0x71c0fc00, 0xe151fd01, 0xe0e1fe01, 0x7070ff00
4079 };
4080
4081 /********************************************************
4082 * EDC (Error Detection Code) check *
4083 * (using CRC code) *
4084 * MODE 1 : Sync + Header + User data + edc *
4085 * MODE 2 : Sub header + User data + edc *
4086 ********************************************************/
4087
4088 #define SYNC_EDC 0x908eff4e /* sector sync EDC value */
4089 #define HEADER 4 /* header length 4 bytes */
4090 #define SUB_H 8 /* Subheader length 8 bytes */
4091 #define USER_DATA 2048 /* User data length 2048 bytes */
4092 #define EDC_LEN 4 /* EDC code length 4 bytes */
4093
cal_edc1(db,mode)4094 cal_edc1(db, mode)
4095 register unsigned char *db;
4096 int mode;
4097 {
4098 register int j;
4099 register unsigned int work;
4100
4101 j = USER_DATA + EDC_LEN;
4102 if (mode == 2) {
4103 j += SUB_H;
4104 work = 0;
4105 } else {
4106 j += HEADER;
4107 work = SYNC_EDC;
4108 }
4109 while (--j >= 0)
4110 work = ((work >> 8) | (*db++ << 24)) ^ XORMASK(work & 0xff);
4111
4112 return (work);
4113 }
4114
4115
4116 /************************************************/
4117 /* error detection & correction */
4118 /* if form 1 */
4119 /* header area should be zero */
4120 /************************************************/
4121
4122 /*
4123 * error detection & correction P-direction
4124 */
p_dir(dbuf)4125 p_dir(dbuf)
4126 register unsigned short *dbuf;
4127 {
4128 unsigned short s0, s1, d;
4129 register int col, row;
4130 register int x;
4131 unsigned char s0l, s0h, s1l, s1h;
4132
4133 /*
4134 * calculate syndrome S0 S1
4135 */
4136 for (col = 0; col < 43; col++) {
4137 s0 = s1 = 0;
4138
4139 for (row = 0; row < 26; row++) {
4140 d = dbuf[43 * row + col];
4141 s0 ^= d;
4142 s1 = rsshift(s1) ^ d;
4143 }
4144
4145 s0h = s0 & 0x00ff;
4146 s1h = s1 & 0x00ff;
4147 s0l = (s0 >> 8) & 0x00ff;
4148 s1l = (s1 >> 8) & 0x00ff;
4149 /*
4150 * calculate error position & correction
4151 */
4152 if (s0l != 0) {
4153 if((x = hextors(s1l) - hextors(s0l)) < 0)
4154 x += 255;
4155 if ((x >= 0) && (x < 26)) {
4156 x = 25 - x;
4157 /*
4158 * correction
4159 */
4160 dbuf[43 * x + col] ^= (s0 & 0xff00);
4161 }
4162 }
4163
4164 /*
4165 * calculate error position & correction
4166 */
4167 if (s0h != 0) {
4168 if((x = hextors(s1h) - hextors(s0h)) < 0)
4169 x += 255;
4170 if ((x >= 0) && (x < 26)) {
4171 x = 25 - x;
4172 /*
4173 * correction
4174 */
4175 dbuf[43 * x + col] ^= (s0 & 0x00ff);
4176 }
4177 }
4178 }
4179 }
4180
4181 /*
4182 * error detection & correction Q-direction
4183 */
q_dir(dbuf)4184 q_dir(dbuf)
4185 register unsigned short *dbuf;
4186 {
4187 unsigned short s0, s1, d;
4188 register int col, row;
4189 register int x;
4190 unsigned char s0l, s0h, s1l, s1h;
4191
4192 /*
4193 * calculate syndrome S0 S1
4194 */
4195 for (row = 0; row < 26; row++) {
4196 s0 = s1 = 0;
4197
4198 for (col = 0; col < 45; col++) {
4199 if (col < 43)
4200 d = dbuf[(44 * col + 43 * row) % 1118];
4201 else if (col == 43)
4202 d = dbuf[43 * 26 + row];
4203 else
4204 d = dbuf[44 * 26 + row];
4205 s0 ^= d;
4206 s1 = rsshift(s1) ^ d;
4207 }
4208
4209 s0h = s0 & 0x00ff;
4210 s1h = s1 & 0x00ff;
4211 s0l = (s0 >> 8) & 0x00ff;
4212 s1l = (s1 >> 8) & 0x00ff;
4213 /*
4214 * calculate error position & correction
4215 */
4216 if (s0l != 0) {
4217 if((x = hextors(s1l) - hextors(s0l)) < 0)
4218 x += 255;
4219 if (x >= 0 && x < 45) {
4220 x = 44 - x;
4221 /*
4222 * correction
4223 */
4224 if (x < 43)
4225 dbuf[(44 * x + 43 * row) % 1118]
4226 ^= s0 & 0xff00;
4227 else if (x == 43)
4228 dbuf[43 * 26 + row] ^= s0 & 0xff00;
4229 else
4230 dbuf[44 * 26 + row] ^= s0 & 0xff00;
4231 }
4232 }
4233
4234 /*
4235 * calculate error position & correction
4236 */
4237 if (s0h != 0) {
4238 if((x = hextors(s1h) - hextors(s0h)) < 0)
4239 x += 255;
4240 if ((x >= 0) && (x < 45)) {
4241 x = 44 - x;
4242 /*
4243 * correction
4244 */
4245 if (x < 43)
4246 dbuf[(44 * x + 43 * row) % 1118]
4247 ^= s0 & 0x00ff;
4248 else if ( x == 43)
4249 dbuf[43 * 26 + row] ^= s0 & 0x00ff;
4250 else
4251 dbuf[44 * 26 + row] ^= s0 & 0x00ff;
4252 }
4253 }
4254 }
4255 }
4256
4257 /*
4258 * shift high & low byte at the same time
4259 */
rsshift(d)4260 rsshift(d)
4261 unsigned short d;
4262 {
4263 register int x;
4264 register int dmy; /* This way is faster */
4265
4266 dmy = (int)d;
4267 x = (dmy << 1) & 0xfefe; /* clear LSB of high & low byte */
4268 if ((dmy & 0x0080) != 0)
4269 x ^= X8_L;
4270 if ((dmy & 0x8000) != 0)
4271 x ^= X8_H;
4272 return(x);
4273 }
4274 #endif /* NSD > 0 */
4275