Assignment 8, Solutions

Part of the homework for 22C:50, Spring 2003
by Douglas W. Jones
THE UNIVERSITY OF IOWA Department of Computer Science

Homework

Do problem 4 from the end of Chapter 11 (1 point each).

a) 7200 RPM is 120 revolutions per second, and we can transfer data at 555,000,000 bits per second. Therefore, there are 555,000,000/120 bits per revolution or 4,625,000 bits per revolution. Divide this by 8 to get 578,000 bytes per revolution. Since you can read exactly one track in one revolution, there must be 578 bytes per unformatted track.

b) If we take a 512-byte sector with a 3-byte epilogue and a 13-byte prologue, that means the actual sector size is 528 bytes. This suggests that there might be 1094 sectors per track. More likely, it's something close to 1024!

c) The advertised rotational latency time of 4.16 milliseconds suggests that it takes 8.32 milliseconds for one revolution. 1000 milliseconds (one second) divided by 8.32 gives us 120.2 revolutions per second. This is consistant with the advertised 120 revolutions per second (some decimal places were probably discarded from the 8.32 figure).

Do problem 6 from the end of Chapter 11 (1 point each).

            0 0 0 0 -- no error
            0 0 0 1 -- disk not mounted
          * 0 0 1 0 -- disk not up to speed  (ERRNOSPIN)
            0 0 1 1 -- no such cylinder
            0 1 0 0 -- no such surface
            0 1 0 1 -- no such sector
            0 1 1 0 -- byte count larger than sector size
          * 1 0 0 0 -- formatting error      (ERRFORMAT)
          * 1 0 0 1 -- parity error          (ERRPARITY)

The starred error conditions might go away spontaneously if we wait a bit and retry the read or write attempt. The motor might manage to get the disk up to the required speed, and the formatting or parity error might have been caused by a transient problem such as a grain of dust or a bit of static electricity. All the others are unlikely to be corrected by a quick retry.

	void diskread( char * buffer, int len, int cyl, int surf, int sect )
	{
	    int trycount;
	    int error;
	    for (;;) {
		/* first set up all the disk addressing registers */
		diskaddress( buffer, len, cyl, surf, sect );

		/* then issue the read command */
		outp( DISKCON, ON | READ );

		/* finally wait for the operation to complete */
		waitdiskdone();

		error = inp( DISKSTAT ) & ERRMSK;

		trycount ++;
		if (trycount > 3)    break;
		
		if (error == ERRNOSPIN) continue;
		if (error == ERRFORMAT) continue;
		if (error == ERRPARITY) continue;
		break;
	    }
	}

Do problem 11 from the end of Chapter 11 (1 point each).

The critical section involves enabling interrupts for the disk interrupt service routine. These interrupts might have been left disabled if the output queue was empty. If they were left disabled, the interrupt service routine cannot interrupt this critical section, so it is not a problem.

If, on the other hand, the output interrupts were already enabled, then one of the following lines in the interrupt service routine might get executed:

		outp( DISKCON, WRITE + ON + IE )
		outp( DISKCON, READ + ON + IE );
		outp( DISKCON, IDLE + ON );

The risk here is that the diskread routine gets the old contents of the disk control register, changes just one bit, the IE bit, and then writes it back. If a disk interrupt occurs at any time after diskread reads the DISKCON register and before it restores the DISKCON register, the result will be that the new command written by the disk interrupt service routine will be overwritten by the value diskread saves. This could turn a read into a write or a write into a read!

Do problem 13 from the end of Chapter 11 (1 point each).

In the order given:
(1,2) start
(2,5) moves out 1, skip 4 requires 1 extra rev
(4,10) moves out 2, skip 6 requires 1 extra rev
(5,14) moves out 1, skip 4 requires 1 extra rev
(1,6) moves in 4, finish 1 rev skip 8 requires 1 extra rev
(3,11) moves out 2, skip 6 requires 1 extra rev

So, we take 5 extra revolutions plus 1 and 10/16 revolutions, or 6 10/16; the fractional part comes from the last minus the first sector number, plus one, all modulo sectors per track.

The best order is something like:
(1,2) start
(1,6) moves 0
(2,5) moves out 1, finish 1 rev, skip 4 requires no extra rev
(3,11) moves out 1, skip 4 requires no extra rev
(4,10) moves out 1, finish 2 revs, skip 4 requires no extra rev
(5,14) moves out 1, skip 4 requires 1 extra rev

This takes 3 full revolutions plus 13/16.