Subject: [Q] Raw interface to disk driver (long)
To: tech-kern <tech-kern@NetBSD.ORG>
From: Hauke Fath <hauke@Espresso.Rhein-Neckar.DE>
List: tech-kern
Date: 01/22/1997 21:30:48
Hi kern-techies,

after some busy months I am finally returning to my baby, the mac68k floppy
driver. Unfortunately, the problem that brought me to a grinding halt last
October has patiently awaited my return...

The driver lkm is currently capable of reading and decoding sectors from an
800K Apple GCR encoded disk. The IWM floppy controller is not capable of
doing DMA or interrupting the CPU, so it has to be polled. I cannot write
to floppy yet, so there is no file system to mount and I try to read a tar
archive written by the MacOS "suntar" off the raw disk.

Now I understand that raw io for disks is done through physio() (in
kern_physio.c) like

int
fdread(	dev_t		dev,
	struct uio	*uio,
	int		flags)
{
	return( physio( fdstrategy, NULL, dev, B_READ, minphys, uio) );
}

where the NULL parameter for a buffer address tells physio() to temporarily
allocate a swap buffer for io.

What I see is this:

# tar -tf /dev/rfd0a
iwm: Open drive 0.
 Get softc.
 Get format info.
 Set diskInfo flags.
 Seek track 00 says 0.
iwm: fdGetDiskLabel() for disk 0.
 now calling readdisklabel()...
iwm: fdstrategy()...
     Allocated buffer size (b_bufsize): 0x01000
     Base address of buffer (b_un.b_addr): 0x00x6ea9000
     Bytes to be transferred (b_bcount): 0x0200
     Remaining I/O (b_resid): 0x00
 This job has b_blkno 0 and b_bcount 512; sorted for cylinder # 0.
 Remap block 0 to track 0 side 0 sector 0.
 I read side 0 track 0 sector 0.
 fdStart().err = 0.
 fdStart() job finished.
iwm: fdstrategy() done. We have 0 bytes left, err = 0;
     b_flags are 0x0100210.
iwm: no disk label--NetBSD or Macintosh.

-- fine so far. The first disk access reads the first block on disk into a
buffer of size b_bufsize, searches it for a valid disklabel and fails,
because there is none. It falls back to a default geometry. But then...

iwm: fdopen() says 0.
iwm: fdstrategy()...
     Allocated buffer size (b_bufsize): 0x00
     Base address of buffer (b_un.b_addr): 0x00x7eb9000
     Bytes to be transferred (b_bcount): 0x02800
     Remaining I/O (b_resid): 0x00
 This job has b_blkno 0 and b_bcount 10240; sorted for cylinder # 0.
 Remap block 0 to track 0 side 0 sector 0.
 I read side 0 track 0 sector 0.

[...]

 Remap block 19 to track 0 side 1 sector 7.
 I read side 1 track 0 sector 7.
 fdStart().err = 0.
 fdStart() job finished.
iwm: fdstrategy() done. We have 0 bytes left, err = 0;
     b_flags are 0x01c0210.
 Raw read: physio() says 129.
tar: read error on /dev/rfd0a :iwm: Closing driver. Unknown error: 129
#

Here, b_bufsize is 0 "as it shouldn't", and the kernel dies a miserable
death because of a corrupted buffer cache. After having lost /etc and
/usr/libexec, I have turned to bringing the machine down to single-user and
mount all disks read-only before testing.

I am pretty sure I am missing something terribly simple here. I have read
that character device drivers have to go some lengths to copy stuff from
kernel to user address spaces, but I am under the impression that physio()
takes care of this for disk drivers.

Can anyone help here?


	hauke

---
"It's never straight up and down"     (DEVO)