Subject: kern/2535: sys/scsi/sd.c doesn't know about floppy devices
To: None <gnats-bugs@NetBSD.ORG>
From: None <leo@marco.de>
List: netbsd-bugs
Date: 06/10/1996 13:26:00
>Number:         2535
>Category:       kern
>Synopsis:       sys/scsi/sd.c doesn't know about floppy devices
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Jun 10 07:35:06 1996
>Last-Modified:
>Originator:     Matthias Pfaller
>Organization:
leo@dachau.marco.de			in real life: Matthias Pfaller
marco GmbH, 85221 Dachau, Germany	tel: +49 8131 516142
>Release:        960607
>Environment:
	
System: NetBSD klondike 1.2_ALPHA NetBSD 1.2_ALPHA (KLONDIKE) #4: Sat Jun 8 20:06:39 MET DST 1996 leo@klondike:/usr/src/sys/arch/pc532/compile/KLONDIKE pc532


>Description:
	sys/scsi/sd.c doesn't know how to deal with scsi floppy disk drives
	(like the TEAC FC-1). For floppy drives mode page 5 and not
	mode page 4 has to be asked for geometry information.

	In order to avoid unwanted error messages during kernel startup,
	I had to teach scsi_interpret_sense to honor SCSI_SILENT for
	illegal requests.

	One thing left open by this patch is the scsi_start problem.
	scsi_start should not get called for floppy drives.

>How-To-Repeat:
	Connect a TEAC FC-1 to your machine and you'll get a bunch of
	error messages when booting.
>Fix:
--- scsi_base.c.ORIG	Sat May  4 13:52:21 1996
+++ scsi_base.c	Wed May 29 19:47:13 1996
@@ -683,6 +683,8 @@
 		case 0x5:	/* ILLEGAL REQUEST */
 			if ((xs->flags & SCSI_IGNORE_ILLEGAL_REQUEST) != 0)
 				return 0;
+			if ((xs->flags & SCSI_SILENT) != 0)
+				return EIO;
 			error = EINVAL;
 			break;
 		case 0x6:	/* UNIT ATTENTION */
--- scsi_disk.h.ORIG	Tue Mar 19 13:30:26 1996
+++ scsi_disk.h	Wed May 29 19:47:15 1996
@@ -174,6 +174,43 @@
 		u_int8_t reserved2;
 		u_int8_t reserved3;
     	} rigid_geometry;
+	struct page_flex_geometry {
+	   u_char pg_code;		/* page code (should be 5) */
+	   u_char pg_length;		/* page length (should be 0x1e) */
+	   u_char xfr_rate1;
+	   u_char xfr_rate0;
+	   u_char nheads;		/* number of heads */
+	   u_char ph_sec_t;		/* physical sectors per track */
+	   u_char bytes_s_1;		/* bytes per sector (MSB) */
+	   u_char bytes_s_0;		/* bytes per sector (LSB) */
+	   u_char ncyl_1;		/* number of cylinders (MSB) */
+	   u_char ncyl_0;		/* number of cylinders (LSB) */
+	   u_char st_cyl_wp_1;		/* starting cyl., write precomp (MSB) */
+	   u_char st_cyl_wp_0;		/* starting cyl., write precomp (LSB) */
+	   u_char st_cyl_rwc_1; 	/* starting cyl., red. write cur (MSB) */
+	   u_char st_cyl_rwc_0; 	/* starting cyl., red. write cur (LSB) */
+	   u_char driv_step_1;		/* drive step rate (MSB) */
+	   u_char driv_step_0;		/* drive step rate (LSB) */
+	   u_char driv_step_w;		/* drive step pulse width */
+	   u_char head_settle_1;	/* head settle delay (MSB) */
+	   u_char head_settle_0;	/* head settle delay (LSB) */
+	   u_char motor_on;		/* motor on delay */
+	   u_char motor_off;		/* motor off delay */
+	   u_char flags;		/* various flags */
+#define MO	0x20			/* motor on (pin 16)? */
+#define SSN	0x40			/* start at sector 1  */
+#define TRDY	0x20			/* RDY (pin 34) valid */
+	   u_char step_p_cyl;		/* step pulses per cylinder */
+	   u_char write_pre;		/* write precompensation */
+	   u_char head_load;		/* head load delay */
+	   u_char head_unload;		/* head unload delay */
+	   u_char pin_34_2;		/* pin 34 (6) and pin 2 (7/11) definition */
+	   u_char pin_4_1;		/* pin 4 (8/9) and pin 1 (13) definition */
+	   u_char reserved1;
+	   u_char reserved2;
+	   u_char reserved3;
+	   u_char reserved4;
+	} flex_geometry;
 };
 
 #endif /* _SCSI_SCSI_DISK_H */
--- sd.c.ORIG	Tue May 14 13:57:46 1996
+++ sd.c	Sun Jun  9 18:28:28 1996
@@ -852,8 +861,39 @@
 	 */
 	if (scsi_scsi_cmd(sd->sc_link, (struct scsi_generic *)&scsi_cmd,
 	    sizeof(scsi_cmd), (u_char *)&scsi_sense, sizeof(scsi_sense),
-	    SDRETRIES, 6000, NULL, flags | SCSI_DATA_IN) != 0) {
-		printf("%s: could not mode sense (4)", sd->sc_dev.dv_xname);
+	    SDRETRIES, 6000, NULL, flags | SCSI_DATA_IN | SCSI_SILENT) != 0) {
+		bzero(&scsi_cmd, sizeof(scsi_cmd));
+		/*
+		 * do a "mode sense page 5"
+		 */
+		scsi_cmd.opcode = MODE_SENSE;
+		scsi_cmd.page = 5;
+		scsi_cmd.length = 0x20;
+		if (scsi_scsi_cmd(sd->sc_link, (struct scsi_generic *)&scsi_cmd,
+		    sizeof(scsi_cmd), (u_char *)&scsi_sense, sizeof(scsi_sense),
+		    SDRETRIES, 6000, NULL,
+		    flags | SCSI_DATA_IN | SCSI_SILENT) == 0) {
+			dp->heads = scsi_sense.pages.flex_geometry.nheads;
+			dp->cyls =
+			    scsi_sense.pages.flex_geometry.ncyl_1 * 256 +
+			    scsi_sense.pages.flex_geometry.ncyl_0;
+			dp->blksize = _3btol(scsi_sense.blk_desc.blklen);
+			dp->sectors = scsi_sense.pages.flex_geometry.ph_sec_t;
+			dp->disksize = dp->heads * dp->cyls * dp->sectors;
+			if (dp->heads == 0 || dp->cyls == 0
+			    || dp->sectors == 0) {
+				printf("%s: mode sense (5) returned nonsense",
+				    sd->sc_dev.dv_xname);
+				goto fake_it;
+			}
+
+			if (dp->blksize == 0)
+				dp->blksize = 512;
+
+			return 0;
+		}
+
+		printf("%s: could not mode sense (4/5)", sd->sc_dev.dv_xname);
 	fake_it:
 		printf("; using fictitious geometry\n");
 		/*
>Audit-Trail:
>Unformatted: