From owner-freebsd-current Thu Aug 8 21:53:17 1996 Return-Path: owner-current Received: (from root@localhost) by freefall.freebsd.org (8.7.5/8.7.3) id VAA07028 for current-outgoing; Thu, 8 Aug 1996 21:53:17 -0700 (PDT) Received: from skynet.ctr.columbia.edu (skynet.ctr.columbia.edu [128.59.64.70]) by freefall.freebsd.org (8.7.5/8.7.3) with SMTP id VAA07021 for ; Thu, 8 Aug 1996 21:53:10 -0700 (PDT) Received: (from wpaul@localhost) by skynet.ctr.columbia.edu (8.6.12/8.6.9) id AAA21823 for current@freebsd.org; Fri, 9 Aug 1996 00:53:06 -0400 From: Bill Paul Message-Id: <199608090453.AAA21823@skynet.ctr.columbia.edu> Subject: wd.c/ATAPI patch -- testers wanted To: current@freebsd.org Date: Fri, 9 Aug 1996 00:53:05 -0400 (EDT) X-Mailer: ELM [version 2.4 PL24] Content-Type: text Sender: owner-current@freebsd.org X-Loop: FreeBSD.org Precedence: bulk Tonight I blew a few hours playing with the ATAPI support. The result was the small patch appended to this message, which seems to make the detection of ATAPI devices happen much more reliably. This patch is for 2.2-current. The machine I used for testing is a Gateway 2000 Pentium 200 Mhz with 64MB or RAM, 2.5GB Western Digital IDE disk drive, Toshiba 8x ATAPI/IDE CD-ROM drive, primary and secondary PCI-based on-board IDE controllers. (Default configuration is IDE hard disk as only disk on primary controller and CD-ROM as master on secondary controller.) The problems I had with this system were as follows: - The kernel fails to find the ATAPI CD-ROM drive when it's jumpered as the master device on the secondary controller. Windoze NT is able to handle this configuration with no trouble. - With the GENERIC configuration and the drive jumpered as the slave on the secondary controller, the kernel finds the drive but it also finds a phantom wd2. This hoses sysinstall when booting from the installation floppy (it attempts to open the phantom drive and wedges). In the first case, the problem is that wdprobe() decides that there is no wdc1 controller because the code near the end which checks the error status of the drives bails out incorrectly. The comments say that some controllers return 0x81 and then, when the DRV bit is set, they return 0x01 later. In my case, the check returns 0x81 both times. The comments also say that 0x81 means drive 0 okay and drive 1 failed. This is more or less correct (we have a master drive and no slave), but the code bails out unless it gets 0x01 again. My fix was to honor the second 0x81 as a valid response. This was a one line change. In the second case, the problem is in the wgetctlr(). It checks wd_status (among other things) in search of a WDSC_READY state. It turns out that with my hardware, the controller will bogusly return WDSC_READY on the empty master slot when the CD-ROM is jumpered as a slave. If you check wd_status a second time, a different value is returned. My fix was to read the wd_status location once and discard the value before reading it again as part of the actual test. I'm not really sure about this one but it seems to do the job. With these two small changes, I was able to get the CD-ROM detected reliably in a number of different hardware configurations: - master on secondary controller with another IDE disk as slave - slave as secondary controller with another IDE disk as master - master on secondary controller alone - slave on second controller alone - only drive on secondary controller (no jumper in either master or slave position) - slave on primary controller with another IDE disk as master - master on primary controller with another IDE disk as slave I couldn't really check the CD-ROM on the primary controller alone since then I wouldn't have a boot disk. I would also have liked to test the drive with a different controller, but I didn't have one handy that I could configure for the secondary address and IRQ. I'd like some people who have IDE/ATAPI CD-ROMs exhibiting similar problems to test this patch to see if it makes any difference. Since I need this to make my machines work right, I'll be committing this to -current eventually if nobody offers any objections. -Bill -- ============================================================================= -Bill Paul (212) 854-6020 | System Manager, Master of Unix-Fu Work: wpaul@ctr.columbia.edu | Center for Telecommunications Research Home: wpaul@skynet.ctr.columbia.edu | Columbia University, New York City ============================================================================= "If you're ever in trouble, go to the CTR. Ask for Bill. He will help you." ============================================================================= *** wd.c.old Sat Jul 27 15:01:10 1996 --- wd.c Thu Aug 8 23:01:00 1996 *************** *** 410,417 **** /* Get status for drive 1 */ du->dk_error = inb(du->dk_port + wd_error); /* printf("Error (drv 1) : %x\n", du->dk_error); */ ! ! if(du->dk_error != 0x01) goto nodevice; } else /* drive 0 fail */ goto nodevice; --- 410,421 ---- /* Get status for drive 1 */ du->dk_error = inb(du->dk_port + wd_error); /* printf("Error (drv 1) : %x\n", du->dk_error); */ ! /* ! * Sometimes (apparently mostly with ATAPI ! * drives involved) 0x81 really means 0x81 ! * (drive 0 OK, drive 1 failed). ! */ ! if(du->dk_error != 0x01 && du->dk_error != 0x81) goto nodevice; } else /* drive 0 fail */ goto nodevice; *************** *** 1520,1525 **** --- 1524,1533 ---- return (1); outb(du->dk_port + wd_sdh, WDSD_IBM | (du->dk_unit << 4)); DELAY(5000); /* usually unnecessary; drive select is fast */ + /* + * Do this twice: may get a false WDCS_READY the first time. + */ + inb(du->dk_port + wd_status); if ((inb(du->dk_port + wd_status) & (WDCS_BUSY | WDCS_READY)) != WDCS_READY || wdcommand(du, 0, 0, 0, 0, WDCC_RESTORE | WD_STEP) != 0