NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

kern/46599: atapi xfers through a sil 3112 controller of an odd number of bytes or less than 4 bytes causes system lockup



>Number:         46599
>Category:       kern
>Synopsis:       atapi xfers through a sil 3112 controller of an odd number of 
>bytes or less than 4 bytes causes system lockup
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Jun 14 19:40:00 +0000 2012
>Originator:     Onno van der Linden
>Release:        6.99.7
>Organization:
>Environment:
NetBSD sheep 6.99.7 NetBSD 6.99.7 (SHEEP) #3: Fri Jun  8 20:53:24 MEST 2012  
root@sheep:/usr/src/sys/arch/i386/compile/SHEEP i386
>Description:
Running one of the cdrtool commands with the -scanbus option causes a system
with a sil 3112 controller and an atapi device to lockup solidly after which a 
hard reset
is the only way out. 
>How-To-Repeat:
#include <sys/param.h>
#include <sys/scsiio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>

#include <dev/scsipi/scsi_spc.h>
#include <dev/scsipi/scsipiconf.h>

/* XXX hardcoded devicename attached to the sil 3112 ctrl */
const char      *dvname = "/dev/rcd0d";

void
scsi_command(int fd, const void *cmd, size_t cmdlen,
        void *data, size_t datalen, int timeout, int flags)
{
        scsireq_t req;

        memset(&req, 0, sizeof(req));        req.datalen = datalen;
        req.timeout = timeout;
        req.flags = flags;
        req.senselen = SENSEBUFLEN;

        if (ioctl(fd, SCIOCCOMMAND, &req) == -1)
                err(1, "SCIOCCOMMAND");

        if (req.retsts == SCCMD_OK)
                return;

        /* Some problem; report it and exit. */
        if (req.retsts == SCCMD_TIMEOUT)
                fprintf(stderr, "%s: SCSI command timed out\n", dvname);
        else if (req.retsts == SCCMD_BUSY)
                fprintf(stderr, "%s: device is busy\n", dvname);
        else if (req.retsts == SCCMD_SENSE)
                fprintf(stderr, "%s: device returned sense data\n", dvname);
        else
                fprintf(stderr, "%s: device had unknown status %x\n", dvname,
                    req.retsts);

        exit(1);
}
void
scsi_mode_sense10(int fd, u_int8_t pgcode, u_int8_t pctl, void *buf, size_t len)
{
        struct scsi_mode_sense_10 cmd;

        memset(&cmd, 0, sizeof(cmd));
        memset(buf, 0, len);

        cmd.opcode = SCSI_MODE_SENSE_10;
        cmd.page = pgcode | pctl;
        _lto2b(len, &cmd.length[0]);

        scsi_command(fd, &cmd, sizeof(cmd), buf, len, 60000,
                        SCCMD_READ|SCCMD_ESCAPE);
}


main(int argc, char *argv[])
{
        int     fd;        close(fd);


        char    buf[256];

        fd = open(dvname,O_RDWR,0);
/* 2,3 or any odd number will cause a lockup with satalink(4) */
        scsi_mode_sense10(fd, 0x2A, 0, buf, 2);
        close(fd);
}

>Fix:
Looks like the silicon image controller doesn't like small (< 4 bytes) or
transfers with an odd number of bytes at all even if the code in
atapi_wdc.c  uses PIO instead of DMA in such cases.

Force transfers of at least 4 bytes in even numbers.



Home | Main Index | Thread Index | Old Index