Subject: pool_get failing to allocate a scsipi xs struct
To: None <tech-kern@netbsd.org>
From: David Forbes <david@flossy.u-net.com>
List: tech-kern
Date: 07/15/1999 20:44:33
Summary:

I've got a driver for my parallel-port Iomega ZIP drive mainly working. It
probes & attaches, detects the drive, etc. fine, passing SCSI commands to
and from the drive as it goes.  However, when I attempt to mount a disk or
attempt anything useful, it fails, because the pool_get() call appears
to fail.  I think it due to a problem with how I communicate with the
scsibus layer...

In detail:

I've finally got around to porting FreeBSD's ppbus stuff.  Most of it
appears to work (I haven't rigorously tested the PLIP stuff).  However,
when it came to getting my ZIP drive to work, I first had to learn about
the NetBSD scsi stuff.  (Hence everything I know comes from reading
comments in /sys/dev/scsipi/* and a couple of random drivers that I've
looked at.) 

Unfortunately, because of the way the parallel port is shared within
ppbus, all scsi commands must be polled, because control of the parallel
port is relinquished after each command.  (Therefore there is no way for
an interrupt to be delivered when the command is complete.)

So, the vpo_scsi_cmd() function, does the following:

	1.  call vpoio_do_scsi()  /* executes the command on the ppbus */
	2.  set xs->error based on return code
	3.  does sense if required
	4.  xs->flags |= ITSDONE;	 
	5.  scsipi_done(xs);
	6.  return COMPLETE;

This appears to work fine until the first read command, (which
incidentally is the first to be called NOSLEEP and not POLL).  The above
is based on what I think needs to be done...please shout if I've missed
something or I'm not supposed to call scsipi_done(xs); here.

Anyway, mount hangs on the first read command.   dmesg says:

vpoio_scsi_cmd 8 flags 811      sd0(:6:0): scsipi_done
sd0(:6:0): command: 0x8,0x0,0x0,0x6,0x1,0x0-[512 bytes]
------------------------------
000: 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 
016: 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 
032: 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 
048: 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 
------------------------------
sd0(:6:0): sc_err1,err = 0x0 
sd0(:6:0): scsipi_free_xs
sd0(:6:0): calling private start()
sd0(:6:0): sdstart sd0(:6:0): scsipi_free_xs
sd0(:6:0): calling private start()
sd0(:6:0): sdstart sd0(:6:0): sdstrategy sd0(:6:0): 512 bytes @ blk 0
sd0(:6:0): sdstart sd0(:6:0): scsipi_get_xs
get_xs sc_link->openings 4
sd0(:6:0): calling pool_get
sd0(:6:0): cannot allocate scsipi xs
sd0(:6:0): returning
sd0: not queued, error 12

The first thing that I notice here is that sc_link->openings was 3 before
all previous commands and it's 4 here.  (The informational is printed
before anything is done in scsipi_get_xs().)  error 12 is ENOMEM and
results from pool_get() having returned NULL.  Trouble is that I'm fairly
sure this code works well, because I have heard of people using scsi disks
with NetBSD ;-)

Therefore, there must be something wrong with the way I'm talking to the
scsibus/sd stuff.  The only other things that I can think of that might be
relevant is what happens in the attach routine:

        /* Let's do the NetBSD SCSI stuff...*/
        vpo->adapter.scsipi_cmd = vpoio_scsi_cmd;       
        vpo->adapter.scsipi_minphys = minphys;  


        vpo->link.flags= (SDEV_REMOVABLE | SDEV_DBX);
        vpo->link.quirks = (SDEV_NOSYNC |
                                SDEV_NOWIDE |
                                SDEV_NOTAG |
                                SDEV_NOSYNCCACHE );     
        vpo->link.scsipi_scsi.channel = SCSI_CHANNEL_ONLY_ONE;
        vpo->link.adapter_softc = vpo;  /* Check this... */
        vpo->link.scsipi_scsi.adapter_target = 7; /* Don't know...*/
        vpo->link.adapter = &vpo->adapter;
        vpo->link.device = &vpo_dev;  /* ????? */
        vpo->link.openings = 3;  /* or 1? */
        vpo->link.scsipi_scsi.max_target = 7;
        vpo->link.scsipi_scsi.max_lun = 0;
        vpo->link.type = BUS_SCSI;


        /* Let's rock... */
        config_found(self, &vpo->link, scsiprint);

        return;

I think openings ought to be 1, but I set it higher when I had the
allocation problem.

Any SCSI gurus out there know what I'm doing wrong?

Thanks,

David.

PS - For a moment I thought removing scsipi_done(xs) might work (given the
fact that sc_link->openings had been incremented higher than it's initial
value), but it doesn't.  In fact, it doesn't get as far:

vpoio_scsi_cmd 8 flags 811      sd0(:6:0): scsipi_free_xs
sd0(:6:0): calling private start()
sd0(:6:0): sdstart