home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-06-14 | 147.5 KB | 5,446 lines |
- diff -c -r -N --exclude exp --exclude compile sys/arch/arm32.orig/arm32/autoconf.c sys/arch/arm32/arm32/autoconf.c
- *** sys/arch/arm32.orig/arm32/autoconf.c Wed Jun 12 20:37:59 1996
- --- sys/arch/arm32/arm32/autoconf.c Thu Jun 13 02:56:50 1996
- ***************
- *** 59,64 ****
- --- 59,65 ----
- #include "rd.h"
- #include "sd.h"
- #include "cd.h"
- + #include "acd.h"
- #include "podulebus.h"
-
- extern dev_t rootdev;
- ***************
- *** 92,97 ****
- --- 93,101 ----
- #endif
- #if NSD > 0
- { "sd", 0x18 },
- + #endif
- + #if NCD > 0
- + { "acd", 0x14 },
- #endif
- #if NCD > 0
- { "cd", 0x1a },
- diff -c -r -N --exclude exp --exclude compile sys/arch/arm32.orig/arm32/autoconf.c.orig sys/arch/arm32/arm32/autoconf.c.orig
- *** sys/arch/arm32.orig/arm32/autoconf.c.orig Thu Jan 1 01:00:00 1970
- --- sys/arch/arm32/arm32/autoconf.c.orig Wed Jun 12 20:37:59 1996
- ***************
- *** 0 ****
- --- 1,295 ----
- + /* $NetBSD: autoconf.c,v 1.7 1996/06/12 19:42:23 mark Exp $ */
- +
- + /*
- + * Copyright (c) 1994,1995 Mark Brinicombe.
- + * Copyright (c) 1994 Brini.
- + * All rights reserved.
- + *
- + * Redistribution and use in source and binary forms, with or without
- + * modification, are permitted provided that the following conditions
- + * are met:
- + * 1. Redistributions of source code must retain the above copyright
- + * notice, this list of conditions and the following disclaimer.
- + * 2. Redistributions in binary form must reproduce the above copyright
- + * notice, this list of conditions and the following disclaimer in the
- + * documentation and/or other materials provided with the distribution.
- + * 3. All advertising materials mentioning features or use of this software
- + * must display the following acknowledgement:
- + * This product includes software developed by Mark Brinicombe for
- + * the NetBSD project.
- + * 4. The name of the company nor the name of the author may be used to
- + * endorse or promote products derived from this software without specific
- + * prior written permission.
- + *
- + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- + * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- + * SUCH DAMAGE.
- + *
- + * RiscBSD kernel project
- + *
- + * autoconf.c
- + *
- + * Autoconfiguration functions
- + *
- + * Created : 08/10/94
- + */
- +
- + #include <sys/param.h>
- + #include <sys/systm.h>
- + #include <sys/reboot.h>
- + #include <sys/disklabel.h>
- + #include <sys/device.h>
- + #include <sys/conf.h>
- + #include <sys/kernel.h>
- + #include <sys/malloc.h>
- +
- + #include <machine/irqhandler.h>
- + #include <machine/bootconfig.h>
- +
- + #include "wdc.h"
- + #include "fdc.h"
- + #include "rd.h"
- + #include "sd.h"
- + #include "cd.h"
- + #include "podulebus.h"
- +
- + extern dev_t rootdev;
- + extern dev_t swapdev;
- + extern dev_t dumpdev;
- + extern dev_t argdev;
- +
- + extern struct swdevt swdevt[];
- +
- + extern char *boot_args;
- + extern int pmap_debug_level;
- +
- + char * strstr __P((char */*s1*/, char */*s2*/));
- + long strtoul __P((const char *, char **, int));
- + void dumpconf __P(());
- +
- + /* Table major numbers for the device names, NULL terminated */
- +
- + struct {
- + char *name;
- + dev_t dev;
- + } rootdevices[] = {
- + #if NWDC > 0
- + { "wd", 0x10 },
- + #endif
- + #if NFDC > 0
- + { "fd", 0x11 },
- + #endif
- + #if NRD > 0
- + { "rd", 0x12 },
- + #endif
- + #if NSD > 0
- + { "sd", 0x18 },
- + #endif
- + #if NCD > 0
- + { "cd", 0x1a },
- + #endif
- + { NULL, 0x00 },
- + };
- +
- + /* Decode a device name to a major and minor number */
- +
- + dev_t
- + get_device(name)
- + char *name;
- + {
- + int loop;
- + int unit;
- + int part;
- +
- + if (strncmp(name, "/dev/", 5) == 0)
- + name += 5;
- +
- + for (loop = 0; rootdevices[loop].name; ++loop) {
- + if (strncmp(name, rootdevices[loop].name,
- + strlen(rootdevices[loop].name)) == 0) {
- + name += strlen(rootdevices[loop].name);
- +
- + if (name[0] >= '0' && name[0] <= '9')
- + unit = name[0] - '0';
- + else if (name[0] == 0 || name[0] == ' ')
- + unit = 0;
- + else
- + unit = -1;
- + if (name[1] >= 'a' && name[1] <= 'z')
- + part = name[1] - 'a';
- + else if (name[1] == 0 || name[1] == ' ')
- + part = 0;
- + else
- + part = -1;
- +
- + if (unit < 0 || unit > 9)
- + return(NODEV);
- + if (part < 0 || part > MAXPARTITIONS)
- + return(NODEV);
- + return(makedev(rootdevices[loop].dev,
- + unit * MAXPARTITIONS + part));
- + }
- + }
- + return(NODEV);
- + }
- +
- +
- + /* Set the rootdev variable from the root specifier in the boot args */
- +
- + void
- + set_root_device()
- + {
- + char *ptr;
- +
- + if (boot_args) {
- + ptr = strstr(boot_args, "root=");
- + if (ptr) {
- + ptr += 5;
- + rootdev = get_device(ptr);
- +
- + #ifdef DEBUG
- + if (pmap_debug_level >= 0)
- + printf("rootdev = %08x\n", rootdev);
- + #endif
- + }
- + }
- +
- + if (rootdev == NODEV)
- + panic("No root device specified in boot config\n");
- + }
- +
- +
- + /* Set the swap devices from the swap specifiers in the boot ars */
- +
- + void
- + set_swap_device()
- + {
- + char *ptr;
- + int nswap = 0;
- +
- + if (boot_args) {
- + ptr = boot_args;
- + do {
- + ptr = strstr(ptr, "swap=");
- + if (ptr) {
- + ptr += 5;
- + swdevt[nswap].sw_dev = get_device(ptr);
- +
- + /*
- + * Remember the first swap device
- + */
- +
- + if (nswap == 0)
- + swapdev = get_device(ptr);
- + ++nswap;
- + }
- + } while (ptr);
- + }
- + }
- +
- +
- + /*
- + * Configure swap space and related parameters.
- + */
- +
- + void
- + swapconf()
- + {
- + register struct swdevt *swp;
- + register int nblks;
- + int swapsize = -1;
- + int maj;
- + int s; /* The spl stuff was here for debugging reaons */
- +
- + /*
- + * Loop round all the defined swap device configuring them.
- + */
- +
- + for (swp = swdevt; swp->sw_dev != NODEV; swp++) {
- + maj = major(swp->sw_dev);
- + if (maj > nblkdev)
- + break;
- + if (bdevsw[maj].d_psize) {
- + s = spltty();
- + printf("swap dev %04x ", swp->sw_dev);
- + (void)splx(s);
- + if (swapsize == -1)
- + nblks = (*bdevsw[maj].d_psize)(swp->sw_dev);
- + else
- + nblks = swapsize;
- + s = spltty();
- + if (nblks == -1)
- + printf("-> device not configured for swap\n");
- + else
- + printf("-> %d bytes\n", nblks*DEV_BSIZE);
- + (void)splx(s);
- + if (nblks != -1 &&
- + (swp->sw_nblks == 0 || swp->sw_nblks > nblks))
- + swp->sw_nblks = nblks;
- + swp->sw_nblks = ctod(dtoc(swp->sw_nblks));
- + }
- + }
- + }
- +
- +
- + /* Set up the root and swap device numbers, configure the swap space and dump space */
- +
- + void
- + set_boot_devs()
- + {
- + set_root_device();
- + set_swap_device();
- +
- + if (swapdev == NODEV && minor(rootdev) < (MAXPARTITIONS - 2))
- + swapdev = makedev(major(rootdev), minor(rootdev) + 1);
- +
- + dumpdev = swapdev;
- + argdev = swapdev;
- + swdevt[0].sw_dev = swapdev;
- +
- + swapconf();
- + dumpconf();
- + }
- +
- +
- + /*
- + * void configure()
- + *
- + * Configure all the root devices
- + * The root devices are expected to configure their own children
- + */
- +
- + void
- + configure()
- + {
- +
- + /*
- + * Configure all the roots.
- + * We have to have a mainbus
- + */
- +
- + config_rootfound("mainbus", NULL);
- + #if NPODULEBUS > 0
- + config_rootfound("podulebus", NULL);
- + #endif
- +
- + /* Debugging information */
- +
- + printf("ipl_bio=%08x ipl_net=%08x ipl_tty=%08x ipl_clock=%08x ipl_imp=%08x ipl_none=%08x\n",
- + irqmasks[IPL_BIO], irqmasks[IPL_NET], irqmasks[IPL_TTY],
- + irqmasks[IPL_CLOCK], irqmasks[IPL_IMP], irqmasks[IPL_NONE]);
- +
- + /* Time to start taking interrupts so lets open the flood gates .... */
- +
- + (void)spl0();
- + }
- +
- + /* End of autoconf.c */
- diff -c -r -N --exclude exp --exclude compile sys/arch/arm32.orig/arm32/conf.c sys/arch/arm32/arm32/conf.c
- *** sys/arch/arm32.orig/arm32/conf.c Mon Jun 3 22:33:15 1996
- --- sys/arch/arm32/arm32/conf.c Thu Jun 13 02:56:51 1996
- ***************
- *** 77,82 ****
- --- 77,84 ----
- bdev_decl(vnd);
- #include "ccd.h"
- bdev_decl(ccd);
- + #include "acd.h"
- + bdev_decl(acd);
-
- /* Block devices */
-
- ***************
- *** 101,107 ****
- bdev_disk_init(NFDC, fd), /* 17: floppy diskette */
- bdev_disk_init(NRD, rd), /* 18: ramdisk */
- bdev_disk_init(NVND,vnd), /* 19: vnode disk driver */
- ! bdev_lkm_dummy(), /* 20: */
- bdev_disk_init(NCCD,ccd), /* 21: concatenated disk driver */
- bdev_lkm_dummy(), /* 22: */
- bdev_lkm_dummy(), /* 23: */
- --- 103,109 ----
- bdev_disk_init(NFDC, fd), /* 17: floppy diskette */
- bdev_disk_init(NRD, rd), /* 18: ramdisk */
- bdev_disk_init(NVND,vnd), /* 19: vnode disk driver */
- ! bdev_disk_init(NACD,acd), /* 20: ATAPI CD-ROM */
- bdev_disk_init(NCCD,ccd), /* 21: concatenated disk driver */
- bdev_lkm_dummy(), /* 22: */
- bdev_lkm_dummy(), /* 23: */
- ***************
- *** 244,249 ****
- --- 246,252 ----
- cdev_decl(tun);
- cdev_decl(vnd);
- cdev_decl(ccd);
- + cdev_decl(acd);
- #include "quadmouse.h"
- cdev_decl(quadmouse);
- #include "pms.h"
- ***************
- *** 284,290 ****
- cdev_disk_init(NFDC, fd), /* 17: floppy diskette */
- cdev_disk_init(NRD, rd), /* 18: ram disk driver */
- cdev_disk_init(NVND,vnd), /* 19: vnode disk driver */
- ! cdev_lkm_dummy(), /* 20: */
- cdev_disk_init(NCCD,ccd), /* 21: concatenated disk driver */
- cdev_lkm_dummy(), /* 22: */
- cdev_lkm_dummy(), /* 23: */
- --- 287,293 ----
- cdev_disk_init(NFDC, fd), /* 17: floppy diskette */
- cdev_disk_init(NRD, rd), /* 18: ram disk driver */
- cdev_disk_init(NVND,vnd), /* 19: vnode disk driver */
- ! cdev_disk_init(NACD,acd), /* 20: ATAPI CD-ROM */
- cdev_disk_init(NCCD,ccd), /* 21: concatenated disk driver */
- cdev_lkm_dummy(), /* 22: */
- cdev_lkm_dummy(), /* 23: */
- ***************
- *** 359,365 ****
- /* 17 */ 17,
- /* 18 */ 18,
- /* 19 */ 19,
- ! /* 20 */ NODEV,
- /* 21 */ 21,
- /* 22 */ NODEV,
- /* 23 */ NODEV,
- --- 362,368 ----
- /* 17 */ 17,
- /* 18 */ 18,
- /* 19 */ 19,
- ! /* 20 */ 20,
- /* 21 */ 21,
- /* 22 */ NODEV,
- /* 23 */ NODEV,
- diff -c -r -N --exclude exp --exclude compile sys/arch/arm32.orig/arm32/conf.c.orig sys/arch/arm32/arm32/conf.c.orig
- *** sys/arch/arm32.orig/arm32/conf.c.orig Thu Jan 1 01:00:00 1970
- --- sys/arch/arm32/arm32/conf.c.orig Mon Jun 3 22:33:15 1996
- ***************
- *** 0 ****
- --- 1,430 ----
- + /* $NetBSD: conf.c,v 1.8 1996/06/03 21:36:14 mark Exp $ */
- +
- + /*
- + * Copyright (c) 1994 Mark Brinicombe.
- + * Copyright (c) 1994 Brini.
- + * All rights reserved.
- + *
- + * Redistribution and use in source and binary forms, with or without
- + * modification, are permitted provided that the following conditions
- + * are met:
- + * 1. Redistributions of source code must retain the above copyright
- + * notice, this list of conditions and the following disclaimer.
- + * 2. Redistributions in binary form must reproduce the above copyright
- + * notice, this list of conditions and the following disclaimer in the
- + * documentation and/or other materials provided with the distribution.
- + * 3. All advertising materials mentioning features or use of this software
- + * must display the following acknowledgement:
- + * This product includes software developed by Mark Brinicombe.
- + * 4. The name of the company nor the name of the author may be used to
- + * endorse or promote products derived from this software without specific
- + * prior written permission.
- + *
- + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- + * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- + * SUCH DAMAGE.
- + *
- + * RiscBSD kernel project
- + *
- + * conf.c
- + *
- + * Character and Block Device configuration
- + * Console configuration
- + *
- + * Defines the structures cdevsw and constab
- + *
- + * Created : 17/09/94
- + */
- +
- + #include <sys/param.h>
- + #include <sys/systm.h>
- + #include <sys/buf.h>
- + #include <sys/ioctl.h>
- + #include <sys/tty.h>
- + #include <sys/conf.h>
- + #include <sys/vnode.h>
- +
- + int ttselect __P((dev_t, int, struct proc *));
- +
- + #ifndef LKM
- + #define lkmenodev enodev
- + #else
- + int lkmenodev();
- + #endif
- +
- + #include "wdc.h"
- + bdev_decl(wd);
- + bdev_decl(sw);
- + #include "fdc.h"
- + bdev_decl(fd);
- + #include "rd.h"
- + bdev_decl(rd);
- + #include "sd.h"
- + bdev_decl(sd);
- + #include "st.h"
- + bdev_decl(st);
- + #include "cd.h"
- + bdev_decl(cd);
- + #include "vnd.h"
- + bdev_decl(vnd);
- + #include "ccd.h"
- + bdev_decl(ccd);
- +
- + /* Block devices */
- +
- + struct bdevsw bdevsw[] = {
- + bdev_lkm_dummy(), /* 0: */
- + bdev_swap_init(1, sw), /* 1: swap pseudo-device */
- + bdev_lkm_dummy(), /* 2: */
- + bdev_lkm_dummy(), /* 3: */
- + bdev_lkm_dummy(), /* 4: */
- + bdev_lkm_dummy(), /* 5: */
- + bdev_lkm_dummy(), /* 6: */
- + bdev_lkm_dummy(), /* 7: */
- + bdev_lkm_dummy(), /* 8: */
- + bdev_lkm_dummy(), /* 9: */
- + bdev_lkm_dummy(), /* 10: */
- + bdev_lkm_dummy(), /* 11: */
- + bdev_lkm_dummy(), /* 12: */
- + bdev_lkm_dummy(), /* 13: */
- + bdev_lkm_dummy(), /* 14: */
- + bdev_lkm_dummy(), /* 15: */
- + bdev_disk_init(NWDC, wd), /* 16: Internal IDE disk */
- + bdev_disk_init(NFDC, fd), /* 17: floppy diskette */
- + bdev_disk_init(NRD, rd), /* 18: ramdisk */
- + bdev_disk_init(NVND,vnd), /* 19: vnode disk driver */
- + bdev_lkm_dummy(), /* 20: */
- + bdev_disk_init(NCCD,ccd), /* 21: concatenated disk driver */
- + bdev_lkm_dummy(), /* 22: */
- + bdev_lkm_dummy(), /* 23: */
- + bdev_disk_init(NSD,sd), /* 24: SCSI disk */
- + bdev_tape_init(NST,st), /* 25: SCSI tape */
- + bdev_disk_init(NCD,cd), /* 26: SCSI cdrom */
- + bdev_lkm_dummy(), /* 27: */
- + bdev_lkm_dummy(), /* 28: */
- + bdev_lkm_dummy(), /* 29: */
- + bdev_lkm_dummy(), /* 30: */
- + bdev_lkm_dummy(), /* 31: */
- + bdev_lkm_dummy(), /* 32: */
- + bdev_lkm_dummy(), /* 33: */
- + bdev_lkm_dummy(), /* 34: */
- + bdev_lkm_dummy(), /* 35: */
- + bdev_lkm_dummy(), /* 36: */
- + bdev_lkm_dummy(), /* 37: */
- + bdev_lkm_dummy(), /* 38: */
- + bdev_lkm_dummy(), /* 39: */
- + bdev_lkm_dummy(), /* 40: */
- + bdev_lkm_dummy(), /* 41: */
- + bdev_lkm_dummy(), /* 42: */
- + bdev_lkm_dummy(), /* 43: */
- + };
- +
- + int nblkdev = sizeof(bdevsw) / sizeof(bdevsw[0]);
- +
- +
- + /* Character device declarations */
- +
- + /* open, close, read, write, ioctl, tty, mmap */
- + #define cdev_physcon_init(c,n) { \
- + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \
- + dev_init(c,n,write), dev_init(c,n,ioctl), dev_init(c,n,stop), \
- + dev_init(c,n,tty), ttselect, dev_init(c,n,mmap), 0 }
- +
- + /* open, close, write, ioctl */
- + #define cdev_lpt_init(c,n) { \
- + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \
- + dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) enodev, \
- + 0, seltrue, (dev_type_mmap((*))) enodev, 0 }
- +
- + /* open, close, write, ioctl */
- + #define cdev_beep_init(c,n) { \
- + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \
- + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \
- + (dev_type_stop((*))) enodev, \
- + 0, seltrue, (dev_type_mmap((*))) enodev, 0 }
- +
- + /* open, close, write, ioctl */
- + #define cdev_kbd_init(c,n) { \
- + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \
- + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \
- + (dev_type_stop((*))) enodev, \
- + 0, dev_init(c,n,select), (dev_type_mmap((*))) enodev, 0 }
- +
- + /* open, close, write, ioctl */
- + #define cdev_cpu_init(c,n) { \
- + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \
- + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \
- + (dev_type_stop((*))) enodev, \
- + 0, seltrue, (dev_type_mmap((*))) enodev, 0 }
- +
- + /* open, close, write, ioctl */
- + #define cdev_vidcvid_init(c,n) { \
- + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \
- + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \
- + (dev_type_stop((*))) enodev, \
- + 0, seltrue, dev_init(c,n,mmap), 0 }
- +
- + /* open, close, write, ioctl */
- + #define cdev_uk_init(c,n) { \
- + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \
- + dev_init(c,n,write), dev_init(c,n,ioctl), \
- + (dev_type_stop((*))) enodev, \
- + 0, seltrue, (dev_type_mmap((*))) enodev, 0 }
- +
- + /* open, close, read, ioctl */
- + #define cdev_ss_init(c,n) { \
- + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \
- + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \
- + (dev_type_stop((*))) enodev, 0, seltrue, \
- + (dev_type_mmap((*))) enodev }
- +
- + /* open, close, write, ioctl */
- + #define cdev_iic_init(c,n) { \
- + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \
- + dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) enodev, \
- + 0, seltrue, (dev_type_mmap((*))) enodev, 0 }
- +
- + /* open, close, write, ioctl */
- + #define cdev_rtc_init(c,n) { \
- + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \
- + dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) enodev, \
- + 0, seltrue, (dev_type_mmap((*))) enodev, 0 }
- +
- + cdev_decl(cn);
- + cdev_decl(ctty);
- + #include "vt.h"
- + cdev_decl(physcon);
- + cdev_decl(vidcvideo);
- + #define mmread mmrw
- + #define mmwrite mmrw
- + cdev_decl(mm);
- + cdev_decl(wd);
- + cdev_decl(sw);
- + #include "pty.h"
- + #define ptstty ptytty
- + #define ptsioctl ptyioctl
- + cdev_decl(pts);
- + #define ptctty ptytty
- + #define ptcioctl ptyioctl
- + cdev_decl(ptc);
- + cdev_decl(log);
- + #include "com.h"
- + cdev_decl(com);
- + #include "lpt.h"
- + cdev_decl(lpt);
- + cdev_decl(fd);
- + dev_decl(filedesc,open);
- + cdev_decl(rd);
- + #include "bpfilter.h"
- + cdev_decl(bpf);
- + cdev_decl(sd);
- + cdev_decl(st);
- + cdev_decl(cd);
- + #include "ch.h"
- + cdev_decl(ch);
- + #include "uk.h"
- + cdev_decl(uk);
- + #include "ss.h"
- + cdev_decl(ss);
- + #ifdef LKM
- + #define NLKM 1
- + #else
- + #define NLKM 0
- + #endif
- + cdev_decl(lkm);
- + #include "tun.h"
- + cdev_decl(tun);
- + cdev_decl(vnd);
- + cdev_decl(ccd);
- + #include "quadmouse.h"
- + cdev_decl(quadmouse);
- + #include "pms.h"
- + cdev_decl(pms);
- + #include "beep.h"
- + cdev_decl(beep);
- + #include "kbd.h"
- + cdev_decl(kbd);
- + #include "audio.h"
- + cdev_decl(audio);
- + #include "cpu.h"
- + cdev_decl(cpu);
- + #include "iic.h"
- + cdev_decl(iic);
- + #include "rtc.h"
- + cdev_decl(rtc);
- +
- + /* Character devices */
- +
- + struct cdevsw cdevsw[] = {
- + cdev_mm_init(1, mm), /* 0: /dev/{null,mem,kmem,...} */
- + cdev_swap_init(1, sw), /* 1: /dev/drum (swap pseudo-device) */
- + cdev_cn_init(1, cn), /* 2: virtual console */
- + cdev_ctty_init(1,ctty), /* 3: controlling terminal */
- + cdev_physcon_init(NVT, physcon), /* 4: RPC console */
- + cdev_log_init(1,log), /* 5: /dev/klog */
- + cdev_ptc_init(NPTY,ptc), /* 6: pseudo-tty master */
- + cdev_tty_init(NPTY,pts), /* 7: pseudo-tty slave */
- + cdev_lpt_init(NLPT,lpt), /* 8: parallel printer */
- + cdev_mouse_init(NQUADMOUSE,quadmouse), /* 9: quadmouse driver */
- + cdev_beep_init(NBEEP,beep), /* 10: simple beep device */
- + cdev_kbd_init(NKBD,kbd), /* 11: kbd device */
- + cdev_tty_init(NCOM,com), /* 12: serial port */
- + cdev_lkm_dummy(), /* 13: */
- + cdev_lkm_dummy(), /* 14: */
- + cdev_lkm_dummy(), /* 15: */
- + cdev_disk_init(NWDC, wd), /* 16: ST506/ESDI/IDE disk */
- + cdev_disk_init(NFDC, fd), /* 17: floppy diskette */
- + cdev_disk_init(NRD, rd), /* 18: ram disk driver */
- + cdev_disk_init(NVND,vnd), /* 19: vnode disk driver */
- + cdev_lkm_dummy(), /* 20: */
- + cdev_disk_init(NCCD,ccd), /* 21: concatenated disk driver */
- + cdev_lkm_dummy(), /* 22: */
- + cdev_lkm_dummy(), /* 23: */
- + cdev_disk_init(NSD,sd), /* 24: SCSI disk */
- + cdev_tape_init(NST,st), /* 25: SCSI tape */
- + cdev_disk_init(NCD,cd), /* 26: SCSI CD-ROM */
- + cdev_ch_init(NCH,ch), /* 27: SCSI autochanger */
- + cdev_ch_init(NUK,uk), /* 28: SCSI unknown */
- + cdev_ss_init(NSS,ss), /* 29: SCSI scanner */
- + cdev_lkm_dummy(), /* 30: */
- + cdev_lkm_dummy(), /* 31: */
- + cdev_bpftun_init(NBPFILTER,bpf),/* 32: Berkeley packet filter */
- + cdev_bpftun_init(NTUN,tun), /* 33: network tunnel */
- + cdev_fd_init(1,filedesc), /* 34: file descriptor pseudo-device */
- + cdev_lkm_init(NLKM,lkm), /* 35: loadable module driver */
- + cdev_audio_init(NAUDIO,audio), /* 36: generic audio I/O */
- + cdev_vidcvid_init(1,vidcvideo), /* 37: vidcvideo device */
- + cdev_cpu_init(NCPU,cpu), /* 38: cpu device */
- + cdev_lkm_dummy(), /* 39: */
- + cdev_mouse_init(NPMS,pms), /* 40: PS2 mouse driver */
- + cdev_lkm_dummy(), /* 41: */
- + cdev_iic_init(NIIC, iic), /* 42: IIC bus driver */
- + cdev_rtc_init(NRTC, rtc), /* 43: RTC driver */
- + };
- +
- + int nchrdev = sizeof(cdevsw) / sizeof(cdevsw[0]);
- +
- + int mem_no = 0; /* major device number of memory special file */
- +
- +
- + /*
- + * Returns true if dev is /dev/mem or /dev/kmem.
- + */
- + int
- + iskmemdev(dev)
- + dev_t dev;
- + {
- + return (major(dev) == mem_no && minor(dev) < 2);
- + }
- +
- + /*
- + * Returns true if dev is /dev/zero.
- + */
- + int
- + iszerodev(dev)
- + dev_t dev;
- + {
- + return (major(dev) == mem_no && minor(dev) == 3);
- + }
- +
- +
- + static int chrtoblktbl[] = {
- + /* XXXX This needs to be dynamic for LKMs. */
- + /*VCHR*/ /*VBLK*/
- + /* 0 */ NODEV,
- + /* 1 */ 1,
- + /* 2 */ NODEV,
- + /* 3 */ NODEV,
- + /* 4 */ NODEV,
- + /* 5 */ NODEV,
- + /* 6 */ NODEV,
- + /* 7 */ NODEV,
- + /* 8 */ NODEV,
- + /* 9 */ NODEV,
- + /* 10 */ NODEV,
- + /* 11 */ NODEV,
- + /* 12 */ NODEV,
- + /* 13 */ NODEV,
- + /* 14 */ NODEV,
- + /* 15 */ NODEV,
- + /* 16 */ 16,
- + /* 17 */ 17,
- + /* 18 */ 18,
- + /* 19 */ 19,
- + /* 20 */ NODEV,
- + /* 21 */ 21,
- + /* 22 */ NODEV,
- + /* 23 */ NODEV,
- + /* 24 */ 24,
- + /* 25 */ 25,
- + /* 26 */ 26,
- + /* 27 */ NODEV,
- + /* 28 */ NODEV,
- + /* 29 */ NODEV,
- + /* 30 */ NODEV,
- + /* 31 */ NODEV,
- + /* 32 */ NODEV,
- + /* 33 */ NODEV,
- + /* 34 */ NODEV,
- + /* 35 */ NODEV,
- + /* 36 */ NODEV,
- + /* 37 */ NODEV,
- + /* 38 */ NODEV,
- + /* 39 */ NODEV,
- + /* 40 */ NODEV,
- + /* 41 */ NODEV,
- + /* 42 */ NODEV,
- + /* 43 */ NODEV,
- + };
- +
- + /*
- + * Convert a character device number to a block device number.
- + */
- +
- + dev_t
- + chrtoblk(dev)
- + dev_t dev;
- + {
- + int blkmaj;
- +
- + if (major(dev) >= nchrdev)
- + return (NODEV);
- +
- + blkmaj = chrtoblktbl[major(dev)];
- + if (blkmaj == NODEV)
- + return (NODEV);
- + return (makedev(blkmaj, minor(dev)));
- + }
- +
- + /*
- + * This entire table could be autoconfig()ed but that would mean that
- + * the kernel's idea of the console would be out of sync with that of
- + * the standalone boot. I think it best that they both use the same
- + * known algorithm unless we see a pressing need otherwise.
- + */
- +
- + #include <dev/cons.h>
- +
- + cons_decl(rpcconsole);
- + cons_decl(com);
- +
- + struct consdev constab[] = {
- + #if (NVT + NRPC > 0)
- + cons_init(rpcconsole),
- + #endif
- +
- + /*#if (NCOM > 0)
- + cons_init(com),
- + #endif*/
- + { 0 },
- + };
- +
- + /* End of conf.c */
- diff -c -r -N --exclude exp --exclude compile sys/arch/arm32.orig/conf/VOYAGER sys/arch/arm32/conf/VOYAGER
- *** sys/arch/arm32.orig/conf/VOYAGER Thu Jun 13 02:08:19 1996
- --- sys/arch/arm32/conf/VOYAGER Thu Jun 13 02:56:51 1996
- ***************
- *** 124,129 ****
- --- 124,132 ----
- wdc0 at mainbus? base 0x002107c0 irq 9
- wd* at wdc? drive ?
-
- + atapibus* at wdc?
- + acd* at atapibus? drive?
- +
- # Floppy disk controller
- fdc0 at mainbus? base 0x00210fc0 irq 12 dack 0x00002000
- fd0 at fdc? drive ?
- diff -c -r -N --exclude exp --exclude compile sys/arch/arm32.orig/conf/VOYAGER.orig sys/arch/arm32/conf/VOYAGER.orig
- *** sys/arch/arm32.orig/conf/VOYAGER.orig Thu Jan 1 01:00:00 1970
- --- sys/arch/arm32/conf/VOYAGER.orig Thu Jun 13 02:08:19 1996
- ***************
- *** 0 ****
- --- 1,201 ----
- + #
- + # VOYAGER -- Mark's master development machine
- + #
- +
- + include "std.arm32"
- +
- + # estimated number of users
- +
- + maxusers 32
- +
- + # Standard system options
- +
- + options TIMEZONE=0 # time zone to adjust RTC time by
- + options DST=0 # daylight savings time used by RTC
- + options SWAPPAGER # paging; REQUIRED
- + options VNODEPAGER # mmap() of files
- + options DEVPAGER # mmap() of devices
- +
- + # CPU options
- +
- + options CPU_ARM6
- + options CPU_LATE_ABORT # ARM7XX compatibility
- +
- + # FPA options
- +
- + #options FPE # Single precision FPE
- + options ARMFPE # ARM Ltd FPE
- +
- + # File system options
- +
- + options FFS # UFS
- + #options QUOTA # UFS quotas
- + #options LFS # log-structured file system
- + options MFS # memory file system
- +
- + options CD9660 # ISO 9660 + Rock Ridge file system
- + options MSDOSFS # MS-DOS file system
- + options FDESC # /dev/fd
- + options FIFO # FIFOs; RECOMMENDED
- + options KERNFS # /kern
- + options NULLFS # loopback file system
- + #options PORTAL # portal filesystem (still experimental)
- + options PROCFS # /proc
- + options UMAPFS # NULLFS + uid and gid remapping
- + options UNION # union file system
- +
- + # Networking options
- +
- + options NFSCLIENT
- + options NFSSERVER
- + options GATEWAY # packet forwarding
- + options INET # IP + ICMP + TCP + UDP
- + #options NS # XNS
- + #options ISO,TPIP # OSI
- + #options EON # OSI tunneling over IP
- + #options CCITT,LLC,HDLC # X.25
- +
- + # Compatibility options
- +
- + options COMPAT_43
- + options COMPAT_10
- + options COMPAT_09
- + options TCP_COMPAT_42 # TCP bug compatibility with 4.2BSD
- +
- + # Shared memory options
- +
- + options SYSVMSG # System V-like message queues
- + options SYSVSEM # System V-like semaphores
- + options SYSVSHM # System V-like memory sharing
- + options SHMMAXPGS=1024 # 1024 pages is the default
- +
- + # Device options
- +
- + options RAMDISK_HOOKS # boottime setup of ramdisk
- + options RAMDISK_SIZE=0 # Size in KBytes
- + options PLIP # Build plip device into lpt driver
- +
- + # Development options
- +
- + #options ARM700BUGTRACK # track the ARM700 swi bug
- + options HYDRA # Experimental hydra support
- + options MPSUPPORT # Experimental MP support
- + options DIAGNOSTIC # internally consistency checks
- + options KTRACE # system call tracing, a la ktrace(1)
- + options IRQSTATS # IRQ statistics
- + options POSTMORTEM # perform postmortem on panic
- + #options ROTTEN_INNARDS # show the gory bit of the postmortem
- + options KSHELL # kernel developemnt shell (debug)
- + options LKM # loadable kernel modules
- + #options DEBUGTERM # create a debug console
- + #options KGDB # remote kernel debugging
- + options DDB # in-kernel debugger
- + #makeoptions DEBUG="-g" # compile full symbol table
- +
- + config netbsd swap generic
- + options GENERIC
- +
- + # The main bus device
- + mainbus0 at root
- +
- + # The boot cpu
- + cpu0 at mainbus?
- +
- + # The hydra multiprocessor device
- + hydrabus0 at mainbus?
- +
- + #hcpu0 at hydrabus?
- + #hcpu1 at hydrabus? slot 0
- + #hcpu2 at hydrabus?
- + #hcpu3 at hydrabus?
- +
- + # The vidc
- + vidcvideo0 at mainbus?
- +
- + # generic VT console device
- + vt0 at mainbus?
- + vt1 at mainbus?
- + vt2 at mainbus?
- + vt3 at mainbus?
- + vt4 at mainbus?
- + vt5 at mainbus?
- +
- + # IDE disk controller
- + wdc0 at mainbus? base 0x002107c0 irq 9
- + wd* at wdc? drive ?
- +
- + # Floppy disk controller
- + fdc0 at mainbus? base 0x00210fc0 irq 12 dack 0x00002000
- + fd0 at fdc? drive ?
- +
- + # kbd via IOMD
- + kbd0 at mainbus? base 0x00000000
- +
- + # quadrature mouse
- + quadmouse0 at mainbus? base 0x00000000 irq 6 # TMR1
- + #quadmouse0 at mainbus? base 0x00000000 irq 3 # VSYNC
- +
- + # PS2 mouse
- + pms0 at mainbus? base 0x00000000
- +
- + # Serial ports
- + com0 at mainbus? base 0x00210fe0 irq 10
- + #com1 at mainbus? base 0x00210be0
- +
- + # Parallel ports
- + lpt0 at mainbus? base 0x002109e0 irq 0
- +
- + # Crude sound device
- + beep0 at mainbus? base 0x00000000
- +
- + # IIC bus device
- + iic0 at mainbus?
- +
- + # RTC device
- + rtc0 at iic? addr 0xa0
- +
- + # Podule bus device
- + podulebus0 at root
- +
- + asc0 at podulebus? # Acorn SCSI card
- + scsibus* at asc?
- +
- + csc0 at podulebus? # Cumana SCSI II card
- + scsibus* at csc?
- +
- + ptsc0 at podulebus? # Power-Tec SCSI II card
- + scsibus* at ptsc?
- +
- + oak0 at podulebus? # Oak SCSI I card
- + scsibus* at oak?
- +
- + sd* at scsibus? target ? lun ? # SCSI disk drives
- + st* at scsibus? target ? lun ? # SCSI tape drives
- + cd* at scsibus? target ? lun ? # SCSI CD-ROM drives
- + ch* at scsibus? target ? lun ? # SCSI auto-changers
- + uk* at scsibus? target ? lun ? # SCSI unknown device
- + ss* at scsibus? target ? lun ? # SCSI scanner
- +
- + #kie* at podulebus? slot ? offset ?
- +
- + ea0 at podulebus? # Ether3 podules
- + eb0 at podulebus? # EtherB network slot cards
- + eh0 at podulebus? # EtherH network slot cards
- + ie0 at podulebus? # Ether1 podules
- +
- + pseudo-device loop 1 # network loopback
- + pseudo-device bpfilter 8 # packet filter
- + pseudo-device sl 2 # CSLIP
- + pseudo-device ppp 2 # PPP
- + pseudo-device tun 2 # network tunneling over tty
- +
- + pseudo-device pty 32 # pseudo-terminals
- + pseudo-device tb 1 # tablet line discipline
- + pseudo-device vnd 4 # paging to files
- + pseudo-device ccd 2 # concatenated disk devices
- +
- + pseudo-device rd 1 # Ramdisk device
- +
- + makeoptions MONITOR="Taxan875+LR"
- + #makeoptions MONITOR="AKF60"
- + makeoptions MODES="1024,768,60 1024,768,70 800,600,60 640,480,60 1280,1024 1152,900"
- diff -c -r -N --exclude exp --exclude compile sys/arch/arm32.orig/conf/files.arm32 sys/arch/arm32/conf/files.arm32
- *** sys/arch/arm32.orig/conf/files.arm32 Thu Jun 13 02:17:41 1996
- --- sys/arch/arm32/conf/files.arm32 Thu Jun 13 02:56:55 1996
- ***************
- *** 39,50 ****
- file arch/arm32/arm32/kgdb_glue.c kgdb needs-flag
- file arch/arm32/arm32/kgdb_step.c kgdb
-
- # Standard NetBSD wd driver
- ! device wdc {drive = -1}
- attach wdc at mainbus
- device wd: disk
- ! attach wd at wdc
- file arch/arm32/mainbus/wd.c wdc needs-flag
- major {wd = 16}
-
- # Standard NetBSD fd driver
- --- 39,57 ----
- file arch/arm32/arm32/kgdb_glue.c kgdb needs-flag
- file arch/arm32/arm32/kgdb_step.c kgdb
-
- + #
- + # Machine-independent ATAPI drivers
- + #
- + include "../../../atapi/files.atapi"
- +
- # Standard NetBSD wd driver
- ! define ata {drive=-1}
- ! device wdc: atapi, ata
- attach wdc at mainbus
- device wd: disk
- ! attach wd at ata
- file arch/arm32/mainbus/wd.c wdc needs-flag
- + file arch/arm32/mainbus/wdc.c wdc needs-flag
- major {wd = 16}
-
- # Standard NetBSD fd driver
- diff -c -r -N --exclude exp --exclude compile sys/arch/arm32.orig/conf/files.arm32.orig sys/arch/arm32/conf/files.arm32.orig
- *** sys/arch/arm32.orig/conf/files.arm32.orig Thu Jan 1 01:00:00 1970
- --- sys/arch/arm32/conf/files.arm32.orig Thu Jun 13 02:17:41 1996
- ***************
- *** 0 ****
- --- 1,276 ----
- + #
- + # First try for arm-specific configuration info
- + #
- +
- + maxpartitions 8
- + maxusers 2 8 64
- +
- + device mainbus { [base = -1], [dack = -1], [irq = -1] }
- + attach mainbus at root
- + file arch/arm32/mainbus/mainbus.c mainbus
- +
- + device cpu
- + attach cpu at mainbus
- + file arch/arm32/mainbus/cpu.c cpu needs-flag
- + major {cpu = 38}
- +
- + device hydrabus { [slot = -1] }
- + attach hydrabus at mainbus
- + file arch/arm32/mainbus/exp/hydrabus.c hydrabus needs-flag
- +
- + device hcpu
- + attach hcpu at hydrabus
- + file arch/arm32/mainbus/exp/hcpu.c hcpu needs-count
- +
- + file arch/arm32/mainbus/exp/hydraboot.S hydrabus | hcpu
- + file arch/arm32/mainbus/exp/hydra.c hydrabus | hcpu
- +
- + #
- + # Machine-independent KGDB support
- + #
- + #include "../../../kgdb/files.kgdb"
- + define kgdb
- + device kgdbslip: kgdb
- + device kgdbppp: kgdb
- +
- + #device kie
- + #attach kie at podule
- + #file arch/arm32/podulebus/kgdb_ie.c kie
- + file arch/arm32/arm32/kgdb_glue.c kgdb needs-flag
- + file arch/arm32/arm32/kgdb_step.c kgdb
- +
- + # Standard NetBSD wd driver
- + device wdc {drive = -1}
- + attach wdc at mainbus
- + device wd: disk
- + attach wd at wdc
- + file arch/arm32/mainbus/wd.c wdc needs-flag
- + major {wd = 16}
- +
- + # Standard NetBSD fd driver
- + device fdc {drive = -1}
- + attach fdc at mainbus
- + device fd: disk
- + attach fd at fdc
- + file arch/arm32/mainbus/fd.c fdc needs-flag
- + major {fd = 17}
- +
- + # RAM disk driver
- + pseudo-device rd
- + file dev/ramdisk.c rd needs-count
- + file arch/arm32/dev/rd_hooks.c rd | ramdisk_hooks
- + major {rd = 18}
- +
- + # Standard parallal driver
- + device lpt: tty, ether, ifnet
- + attach lpt at mainbus
- + file arch/arm32/mainbus/lpt.c lpt needs-flag
- + major {lpt = 8}
- +
- + # Standard serial driver
- + define kgdbcom {[ disable = 0], [ address = 0x12345678 ], [ speed = 9600 ]}
- + device com: tty, kgdbcom
- + attach com at mainbus
- + file arch/arm32/mainbus/com.c com | kgdb_cslp | kgdb_cppp needs-flag
- + major {com = 12}
- +
- + attach kgdbslip at kgdbcom with kgdb_cslp
- + attach kgdbppp at kgdbcom with kgdb_cppp
- +
- + # Mouse devices
- + device quadmouse: tty
- + attach quadmouse at mainbus
- + file arch/arm32/mainbus/qmouse.c quadmouse needs-flag
- + major {quadmouse = 9}
- +
- + device pms: tty
- + attach pms at mainbus
- + file arch/arm32/mainbus/pms.c pms needs-flag
- + major {pms = 40}
- +
- + # Audio devices
- + device beep
- + attach beep at mainbus
- + file arch/arm32/mainbus/beep.c beep needs-flag
- + major {beep = 10}
- +
- + device audio: audio
- + attach audio at mainbus
- + file arch/arm32/mainbus/vidcaudio.c vidcaudio needs-flag
- + major {audio = 36}
- +
- + # Standard keyboard driver
- + device kbd
- + attach kbd at mainbus
- + file arch/arm32/mainbus/kbd.c kbd needs-flag
- + major {kbd = 11}
- +
- + # Podule bus device
- + device podulebus { [slot = -1] }
- + attach podulebus at root
- + file arch/arm32/podulebus/podulebus.c podulebus needs-flag
- +
- + # Ethernet devices
- + device ea: ether, ifnet
- + attach ea at podulebus
- + file arch/arm32/podulebus/if_ea.c ea
- +
- + device eb: ether, ifnet
- + attach eb at podulebus
- + file arch/arm32/podulebus/if_eb.c eb
- +
- + device eh: ether, ifnet
- + attach eh at podulebus
- + file arch/arm32/podulebus/if_eh.c eh
- +
- + device ie: ether, ifnet
- + attach ie at podulebus
- + file arch/arm32/podulebus/if_ie.c ie
- +
- + device es: ether, ifnet
- + attach es at mainbus
- + file arch/arm32/mainbus/if_es.c es
- +
- + # IIC/RTC files
- + device iic { addr = -1 }
- + attach iic at mainbus
- + file arch/arm32/mainbus/iic_asm.S iic
- + file arch/arm32/mainbus/iic.c iic needs-flag
- +
- + device rtc
- + attach rtc at iic
- + file arch/arm32/mainbus/rtc.c rtc needs-count
- +
- + #
- + # Machine-independent SCSI drivers
- + #
- +
- + include "../../../scsi/files.scsi"
- + major {sd = 24}
- + major {st = 25}
- + major {cd = 26}
- + major {ch = 27}
- + major {uk = 28}
- + major {ss = 29}
- +
- + # Generic sbic (WD3393) driver
- + define sbic
- + file arch/arm32/podulebus/sbic.c sbic
- +
- + # Acorn SCSI I specific layer for sbic
- + device asc: scsi, sbic
- + attach asc at podulebus
- + file arch/arm32/podulebus/asc.c asc needs-flag
- +
- + # Generic fas216 + esp216 driver
- + define sfas
- + file arch/arm32/podulebus/sfas.c sfas
- +
- + # Cumana specific layer for sfas
- + device csc: scsi, sfas
- + attach csc at podulebus
- + file arch/arm32/podulebus/exp/csc.c csc
- +
- + device ptsc: scsi, sfas
- + attach ptsc at podulebus
- + file arch/arm32/podulebus/ptsc.c ptsc
- +
- + # Generic NCR driver
- + define ncr
- + file arch/arm32/podulebus/ncr5380sbc.c ncr
- +
- + # Oak specific layer for ncr
- + device oak: scsi, ncr
- + attach oak at podulebus
- + file arch/arm32/podulebus/oak.c oak
- +
- + device vidcvideo
- + attach vidcvideo at mainbus
- + major {vidcvideo = 37}
- + device vt: tty
- + attach vt at mainbus
- + file arch/arm32/dev/console/console.c vt needs-count
- + file arch/arm32/dev/console/vidcconsole.c vt needs-count
- + file arch/arm32/dev/console/vidc_mc.S vt needs-count
- + file arch/arm32/dev/console/vidc.c vt needs-count
- + file arch/arm32/dev/console/vt220.c vt needs-count
- + file arch/arm32/dev/console/debugconsole.c vt needs-count
- + file arch/arm32/dev/console/dumb.c vt needs-count
- +
- + file arch/arm32/arm32/autoconf.c
- + file arch/arm32/arm32/blockio.S
- + file arch/arm32/arm32/clock.c
- + file arch/arm32/arm32/conf.c
- + file arch/arm32/arm32/cpuswitch.S
- + file arch/arm32/arm32/disksubr.c disk
- + file arch/arm32/arm32/stubs.c
- + file arch/arm32/arm32/exception.S
- + file arch/arm32/arm32/syscall.c
- + file arch/arm32/arm32/ast.c
- + file arch/arm32/arm32/fault.c
- + file arch/arm32/arm32/undefined.c
- + file arch/arm32/arm32/mem.c
- + file arch/arm32/arm32/scratch.S
- + file arch/arm32/arm32/process_machdep.c
- + file arch/arm32/arm32/machdep.c
- + file arch/arm32/arm32/sys_machdep.c
- + file arch/arm32/arm32/vm_machdep.c
- + file arch/arm32/arm32/pmap.c
- + file arch/arm32/arm32/fusu.c
- +
- + file netinet/in_cksum.c inet
- + file netns/ns_cksum.c ns
- +
- + # IRQ/FIQ files
- + file arch/arm32/arm32/spl.S
- + file arch/arm32/arm32/irq.S
- + file arch/arm32/arm32/irqhandler.c
- + file arch/arm32/arm32/fiq.S
- +
- + # library functions
- + file arch/arm32/arm32/strstr.c
- + file arch/arm32/arm32/strtoul.c
- + file arch/arm32/arm32/memset.S
- + file arch/arm32/arm32/bcopy_page.S
- + file arch/arm32/arm32/bcopy.S
- + file arch/arm32/arm32/bcopyinout.S
- + file arch/arm32/arm32/copystr.S
- + file arch/arm32/arm32/coproc15.S
- + file arch/arm32/arm32/setcpsr.S
- + file arch/arm32/arm32/setstack.S
- +
- + # files related to the shell
- + file arch/arm32/kshell/shell_input.c kshell
- + file arch/arm32/kshell/shell_shell.c kshell
- + file arch/arm32/kshell/shell_disassem.c kshell
- + file arch/arm32/kshell/strchr.c kshell
- + file arch/arm32/kshell/dumphex.c kshell
- +
- + # files related to debugging
- + file arch/arm32/arm32/debug.c
- + file arch/arm32/arm32/disassem.c
- + file arch/arm32/arm32/postmortem.c
- +
- + file dev/cons.c
- + file dev/cninit.c
- +
- + # Signal precision FPE
- + file arch/arm32/fpe-sp/fpe.c fpe
- + file arch/arm32/fpe-sp/fpeadd.S fpe
- + file arch/arm32/fpe-sp/fpesub.S fpe
- + file arch/arm32/fpe-sp/fpemul.S fpe
- + file arch/arm32/fpe-sp/fpediv.S fpe
- + file arch/arm32/fpe-sp/fpefix.S fpe
- + file arch/arm32/fpe-sp/fpecmf.S fpe
- + file arch/arm32/fpe-sp/fpetoe.S fpe
- +
- + # ARM FPE
- + file arch/arm32/fpe-arm/armfpe_glue.S armfpe
- + file arch/arm32/fpe-arm/armfpe_init.c armfpe
- + file arch/arm32/fpe-arm/armfpe.s armfpe
- +
- + # DDB
- + file arch/arm32/arm32/db_disasm.c ddb
- + file arch/arm32/arm32/db_interface.c ddb
- + file arch/arm32/arm32/db_trace.c ddb
- + file arch/arm32/arm32/db_machdep.c ddb
- diff -c -r -N --exclude exp --exclude compile sys/arch/arm32.orig/mainbus/wd.c sys/arch/arm32/mainbus/wd.c
- *** sys/arch/arm32.orig/mainbus/wd.c Wed Jun 12 22:41:10 1996
- --- sys/arch/arm32/mainbus/wd.c Thu Jun 13 03:11:10 1996
- ***************
- *** 57,76 ****
- #include <machine/io.h>
- #include <machine/katelib.h>
-
- - #include <arm32/mainbus/wdreg.h>
- #include <arm32/mainbus/mainbus.h>
- !
- ! extern int wdresethack;
- !
- #define WAITTIME (4 * hz) /* time to wait for a completion */
- - #define RECOVERYTIME (hz / 2) /* time to recover from an error */
- -
- - #define WDCDELAY 100
- - #define WDCNDELAY 100000 /* delay = 100us; so 10s for a controller state change */
- - #if 0
- - /* If you enable this, it will report any delays more than 100us * N long. */
- - #define WDCNDELAY_DEBUG 10
- - #endif
-
- #define WDIORETRIES 5 /* number of retries before giving up */
-
- --- 57,67 ----
- #include <machine/io.h>
- #include <machine/katelib.h>
-
- #include <arm32/mainbus/mainbus.h>
- ! #include <arm32/mainbus/wdreg.h>
- ! #include <arm32/mainbus/wdlink.h>
- !
- #define WAITTIME (4 * hz) /* time to wait for a completion */
-
- #define WDIORETRIES 5 /* number of retries before giving up */
-
- ***************
- *** 83,303 ****
- struct wd_softc {
- struct device sc_dev;
- struct disk sc_dk;
- !
- ! /* Information about the current transfer: */
- ! daddr_t sc_blkno; /* starting block number */
- ! int sc_bcount; /* byte count left */
- ! int sc_skip; /* bytes already transferred */
- ! int sc_nblks; /* number of blocks currently transferring */
- ! int sc_nbytes; /* number of bytes currently transferring */
- !
- ! /* Long-term state: */
- ! int sc_drive; /* physical unit number */
- ! int sc_state; /* control state */
- ! #define RECAL 0 /* recalibrate */
- ! #define RECAL_WAIT 1 /* done recalibrating */
- ! #define GEOMETRY 2 /* upload geometry */
- ! #define GEOMETRY_WAIT 3 /* done uploading geometry */
- ! #define MULTIMODE 4 /* set multiple mode */
- ! #define MULTIMODE_WAIT 5 /* done setting multiple mode */
- ! #define OPEN 6 /* done with open */
- ! int sc_mode; /* transfer mode */
- ! #define WDM_PIOSINGLE 0 /* single-sector PIO */
- ! #define WDM_PIOMULTI 1 /* multi-sector PIO */
- ! #define WDM_DMA 2 /* DMA */
- ! int sc_multiple; /* multiple for WDM_PIOMULTI */
- ! int sc_flags; /* drive characteistics found */
- ! #define WDF_LOCKED 0x01
- ! #define WDF_WANTED 0x02
- ! #define WDF_WLABEL 0x04 /* label is writable */
- ! #define WDF_LABELLING 0x08 /* writing label */
- ! /* XXX Nothing resets this yet, but disk change sensing will when ATAPI is
- ! implemented. */
- ! #define WDF_LOADED 0x10 /* parameters loaded */
- ! #define WDF_32BIT 0x20 /* can do 32-bit transfer */
- !
- ! struct wdparams sc_params; /* ESDI/ATA drive parameters */
- ! daddr_t sc_badsect[127]; /* 126 plus trailing -1 marker */
- !
- ! TAILQ_ENTRY(wd_softc) sc_drivechain;
- struct buf sc_q;
- };
-
- ! struct wdc_softc {
- ! struct device sc_dev;
- ! irqhandler_t sc_ih;
- !
- ! int sc_iobase; /* I/O port base */
- ! int sc_drq; /* DMA channel */
- !
- ! TAILQ_HEAD(drivehead, wd_softc) sc_drives;
- ! int sc_flags;
- ! #define WDCF_ACTIVE 0x01 /* controller is active */
- ! #define WDCF_SINGLE 0x02 /* sector at a time mode */
- ! #define WDCF_ERROR 0x04 /* processing a disk error */
- ! #define WDCF_WANTED 0x08 /* XXX locking for wd_get_parms() */
- ! int sc_errors; /* errors during current transfer */
- ! u_char sc_status; /* copy of status register */
- ! u_char sc_error; /* copy of error register */
- ! };
- !
- ! int wdcprobe __P((struct device *, void *, void *));
- ! void wdcattach __P((struct device *, struct device *, void *));
- ! int wdcintr __P((void *));
- !
- ! struct cfattach wdc_ca = {
- ! sizeof(struct wdc_softc), wdcprobe, wdcattach
- ! };
-
- ! struct cfdriver wdc_cd = {
- ! NULL, "wdc", DV_DULL
- };
-
- - int wdprobe __P((struct device *, void *, void *));
- - void wdattach __P((struct device *, struct device *, void *));
- - int wdprint __P((void *, char *));
- -
- struct cfattach wd_ca = {
- sizeof(struct wd_softc), wdprobe, wdattach
- };
-
- - struct cfdriver wd_cd = {
- - NULL, "wd", DV_DISK
- - };
-
- ! void wdgetdisklabel __P((struct wd_softc *));
- ! int wd_get_parms __P((struct wd_softc *));
- ! void wdstrategy __P((struct buf *));
- ! void wdstart __P((struct wd_softc *));
-
- struct dkdriver wddkdriver = { wdstrategy };
-
- ! /* XXX: these should go elsewhere */
- ! cdev_decl(wd);
- ! bdev_decl(wd);
- !
- ! void wdfinish __P((struct wd_softc *, struct buf *));
- ! int dcintr __P((void *));
- ! void wdcstart __P((struct wdc_softc *));
- ! int wdcommand __P((struct wd_softc *, int, int, int, int, int));
- ! int wdcommandshort __P((struct wdc_softc *, int, int));
- ! int wdcontrol __P((struct wd_softc *));
- ! int wdsetctlr __P((struct wd_softc *));
- ! static void bad144intern __P((struct wd_softc *));
- ! int wdcreset __P((struct wdc_softc *));
- ! void wdcrestart __P((void *arg));
- ! void wdcunwedge __P((struct wdc_softc *));
- ! void wdctimeout __P((void *arg));
- ! void wderror __P((void *, struct buf *, char *));
- ! int wdcwait __P((struct wdc_softc *, int));
- ! int wdlock __P((struct wd_softc *));
- ! void wdunlock __P((struct wd_softc *));
- !
- ! /* ST506 spec says that if READY or SEEKCMPLT go off, then the read or write
- ! command is aborted. */
- ! #define wait_for_drq(d) wdcwait(d, WDCS_DRDY | WDCS_DSC | WDCS_DRQ)
- ! #define wait_for_ready(d) wdcwait(d, WDCS_DRDY | WDCS_DSC)
- ! #define wait_for_unbusy(d) wdcwait(d, 0)
- !
- ! int
- ! wdcprobe(parent, match, aux)
- ! struct device *parent;
- ! void *match, *aux;
- ! {
- ! struct wdc_softc *wdc = match;
- ! struct mainbus_attach_args *mb = aux;
- ! int iobase;
- !
- ! wdc->sc_iobase = iobase = mb->mb_iobase;
- !
- ! /* Check if we have registers that work. */
- ! outb(iobase+wd_error, 0x5a); /* Error register not writable, */
- ! outb(iobase+wd_cyl_lo, 0xa5); /* but all of cyllo are. */
- ! if (inb(iobase+wd_error) == 0x5a || inb(iobase+wd_cyl_lo) != 0xa5)
- ! return 0;
- !
- ! if (wdcreset(wdc) != 0) {
- ! delay(500000);
- ! if (wdcreset(wdc) != 0)
- ! return 0;
- ! }
- !
- ! /* Select drive 0. */
- ! outb(iobase+wd_sdh, WDSD_IBM | 0);
- !
- ! /* Wait for controller to become ready. */
- ! if (wait_for_unbusy(wdc) < 0)
- ! return 0;
- !
- ! /* Start drive diagnostics. */
- ! outb(iobase+wd_command, WDCC_DIAGNOSE);
- !
- ! /* Wait for command to complete. */
- ! if (wait_for_unbusy(wdc) < 0)
- ! return 0;
- !
- ! mb->mb_iosize = 32;
- ! return 1;
- ! }
- !
- ! struct wdc_attach_args {
- ! int wa_drive;
- ! };
-
- ! int
- ! wdprint(aux, wdc)
- ! void *aux;
- ! char *wdc;
- ! {
- ! struct wdc_attach_args *wa = aux;
- !
- ! if (!wdc)
- ! printf(" drive %d", wa->wa_drive);
- ! return QUIET;
- ! }
- !
- ! void
- ! wdcattach(parent, self, aux)
- ! struct device *parent, *self;
- ! void *aux;
- ! {
- ! struct wdc_softc *wdc = (void *)self;
- ! struct mainbus_attach_args *mb = aux;
- ! struct wdc_attach_args wa;
- !
- ! TAILQ_INIT(&wdc->sc_drives);
- ! wdc->sc_drq = mb->mb_drq;
- !
- ! printf("\n");
- !
- ! wdc->sc_ih.ih_func = wdcintr;
- ! wdc->sc_ih.ih_arg = wdc;
- ! wdc->sc_ih.ih_level = IPL_BIO;
- ! wdc->sc_ih.ih_name = "wdc";
- ! if (irq_claim(mb->mb_irq, &wdc->sc_ih))
- ! panic("Cannot claim IRQ %d for wdc%d\n", mb->mb_irq, parent->dv_unit);
- !
- ! for (wa.wa_drive = 0; wa.wa_drive < 2; wa.wa_drive++)
- ! (void)config_found(self, (void *)&wa, wdprint);
- ! }
-
- int
- wdprobe(parent, match, aux)
- struct device *parent;
- void *match, *aux;
- {
- ! struct wdc_softc *wdc = (void *)parent;
- struct cfdata *cf = match;
- ! struct wdc_attach_args *wa = aux;
- ! int drive = wa->wa_drive;
- !
- ! if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != drive)
- ! return 0;
-
- ! if (wdcommandshort(wdc, drive, WDCC_RECAL) != 0 ||
- ! wait_for_ready(wdc) != 0)
- return 0;
- -
- return 1;
- }
-
- --- 74,123 ----
- struct wd_softc {
- struct device sc_dev;
- struct disk sc_dk;
- ! struct wd_link *d_link;
- struct buf sc_q;
- };
-
- ! int wdprobe __P((struct device *, void *, void *));
- ! void wdattach __P((struct device *, struct device *, void *));
-
- ! struct cfdriver wd_cd = {
- ! NULL, "wd", DV_DISK
- };
-
- struct cfattach wd_ca = {
- sizeof(struct wd_softc), wdprobe, wdattach
- };
-
-
- ! void wdgetdisklabel __P((struct wd_softc *));
- ! void wdstrategy __P((struct buf *));
- ! void wdstart __P((struct wd_softc *));
-
- struct dkdriver wddkdriver = { wdstrategy };
-
- ! int wdlock __P((struct wd_link *));
- ! void wdunlock __P((struct wd_link *));
-
- ! int wdsetctlr __P((struct wd_link *));
- ! static void bad144intern __P((struct wd_softc *));
- ! int wdcdump __P((struct wd_link *, daddr_t blkno, int nblks, caddr_t va));
-
- int
- wdprobe(parent, match, aux)
- struct device *parent;
- void *match, *aux;
- {
- ! /* caddr_t *wdc = (void *)parent;*/
- struct cfdata *cf = match;
- ! struct wd_link *d_link = aux;
- ! int drive;
-
- ! if (d_link == NULL ) return 0;
- ! if (d_link-> type != DRIVE) return 0;
- ! drive = d_link->sc_drive;
- ! if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != drive)
- return 0;
- return 1;
- }
-
- ***************
- *** 307,329 ****
- void *aux;
- {
- struct wd_softc *wd = (void *)self;
- ! struct wdc_softc *wdc = (void *)parent;
- ! struct wdc_attach_args *wa = aux;
- int i, blank;
- char buf[41], c, *p, *q;
-
- ! wd->sc_drive = wa->wa_drive;
-
- ! /*
- ! * Initialize and attach the disk structure.
- */
- wd->sc_dk.dk_driver = &wddkdriver;
- wd->sc_dk.dk_name = wd->sc_dev.dv_xname;
- disk_attach(&wd->sc_dk);
-
- ! wd_get_parms(wd);
- ! for (blank = 0, p = wd->sc_params.wdp_model, q = buf, i = 0;
- ! i < sizeof(wd->sc_params.wdp_model); i++) {
- c = *p++;
- if (c == '\0')
- break;
- --- 127,153 ----
- void *aux;
- {
- struct wd_softc *wd = (void *)self;
- ! /* struct caddr_t *wdc = (void *)parent;*/
- ! struct wd_link *d_link= aux;
- int i, blank;
- char buf[41], c, *p, *q;
-
- ! wd->d_link = d_link;
- ! d_link->openings = 1;
- ! d_link->wd_softc = (caddr_t)wd;
-
- ! /*
- ! * Initialize and attach the disk structure.
- */
- wd->sc_dk.dk_driver = &wddkdriver;
- wd->sc_dk.dk_name = wd->sc_dev.dv_xname;
- disk_attach(&wd->sc_dk);
-
- ! d_link->sc_lp = wd->sc_dk.dk_label;
- !
- ! wdc_get_parms(d_link);
- ! for (blank = 0, p = d_link->sc_params.wdp_model, q = buf, i = 0;
- ! i < sizeof(d_link->sc_params.wdp_model); i++) {
- c = *p++;
- if (c == '\0')
- break;
- ***************
- *** 339,371 ****
- *q++ = '\0';
-
- printf(": %dMB, %d cyl, %d head, %d sec, %d bytes/sec <%s>\n",
- ! wd->sc_params.wdp_cylinders *
- ! (wd->sc_params.wdp_heads * wd->sc_params.wdp_sectors) /
- (1048576 / DEV_BSIZE),
- ! wd->sc_params.wdp_cylinders,
- ! wd->sc_params.wdp_heads,
- ! wd->sc_params.wdp_sectors,
- DEV_BSIZE,
- buf);
-
- ! if ((wd->sc_params.wdp_capabilities & WD_CAP_DMA) != 0 &&
- ! wdc->sc_drq != DRQUNK) {
- ! wd->sc_mode = WDM_DMA;
- ! } else if (wd->sc_params.wdp_maxmulti > 1) {
- ! wd->sc_mode = WDM_PIOMULTI;
- ! wd->sc_multiple = min(wd->sc_params.wdp_maxmulti, 16);
- } else {
- ! wd->sc_mode = WDM_PIOSINGLE;
- ! wd->sc_multiple = 1;
- }
-
- printf("%s: using", wd->sc_dev.dv_xname);
- ! if (wd->sc_mode == WDM_DMA)
- printf(" dma transfers,");
- else
- printf(" %d-sector %d-bit pio transfers,",
- ! wd->sc_multiple, (wd->sc_flags & WDF_32BIT) == 0 ? 16 : 32);
- ! if ((wd->sc_params.wdp_capabilities & WD_CAP_LBA) != 0)
- printf(" lba addressing\n");
- else
- printf(" chs addressing\n");
- --- 163,195 ----
- *q++ = '\0';
-
- printf(": %dMB, %d cyl, %d head, %d sec, %d bytes/sec <%s>\n",
- ! d_link->sc_params.wdp_cylinders *
- ! (d_link->sc_params.wdp_heads * d_link->sc_params.wdp_sectors) /
- (1048576 / DEV_BSIZE),
- ! d_link->sc_params.wdp_cylinders,
- ! d_link->sc_params.wdp_heads,
- ! d_link->sc_params.wdp_sectors,
- DEV_BSIZE,
- buf);
-
- ! if ((d_link->sc_params.wdp_capabilities & WD_CAP_DMA) != 0 &&
- ! d_link->sc_mode == WDM_DMA) {
- ! d_link->sc_mode = WDM_DMA;
- ! } else if (d_link->sc_params.wdp_maxmulti > 1) {
- ! d_link->sc_mode = WDM_PIOMULTI;
- ! d_link->sc_multiple = min(d_link->sc_params.wdp_maxmulti, 16);
- } else {
- ! d_link->sc_mode = WDM_PIOSINGLE;
- ! d_link->sc_multiple = 1;
- }
-
- printf("%s: using", wd->sc_dev.dv_xname);
- ! if (d_link->sc_mode == WDM_DMA)
- printf(" dma transfers,");
- else
- printf(" %d-sector %d-bit pio transfers,",
- ! d_link->sc_multiple, (d_link->sc_flags & WDF_32BIT) == 0 ? 16 : 32);
- ! if ((d_link->sc_params.wdp_capabilities & WD_CAP_LBA) != 0)
- printf(" lba addressing\n");
- else
- printf(" chs addressing\n");
- ***************
- *** 380,385 ****
- --- 204,210 ----
- struct buf *bp;
- {
- struct wd_softc *wd = wd_cd.cd_devs[WDUNIT(bp->b_dev)];
- + struct wd_link *d_link= wd->d_link;
- int s;
-
- /* Valid request? */
- ***************
- *** 391,397 ****
- }
-
- /* If device invalidated (e.g. media change, door open), error. */
- ! if ((wd->sc_flags & WDF_LOADED) == 0) {
- bp->b_error = EIO;
- goto bad;
- }
- --- 216,222 ----
- }
-
- /* If device invalidated (e.g. media change, door open), error. */
- ! if ((d_link->sc_flags & WDF_LOADED) == 0) {
- bp->b_error = EIO;
- goto bad;
- }
- ***************
- *** 406,428 ****
- */
- if (WDPART(bp->b_dev) != RAW_PART &&
- bounds_check_with_label(bp, wd->sc_dk.dk_label,
- ! (wd->sc_flags & (WDF_WLABEL|WDF_LABELLING)) != 0) <= 0)
- goto done;
-
- /* Queue transfer on drive, activate drive and controller if idle. */
- s = splbio();
- disksort(&wd->sc_q, bp);
- ! if (!wd->sc_q.b_active)
- ! wdstart(wd);
- ! #if 0
- ! else {
- ! struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent;
- ! if ((wdc->sc_flags & (WDCF_ACTIVE|WDCF_ERROR)) == 0) {
- ! printf("wdstrategy: controller inactive\n");
- ! wdcstart(wdc);
- ! }
- ! }
- ! #endif
- splx(s);
- return;
-
- --- 231,243 ----
- */
- if (WDPART(bp->b_dev) != RAW_PART &&
- bounds_check_with_label(bp, wd->sc_dk.dk_label,
- ! (d_link->sc_flags & (WDF_WLABEL|WDF_LABELLING)) != 0) <= 0)
- goto done;
-
- /* Queue transfer on drive, activate drive and controller if idle. */
- s = splbio();
- disksort(&wd->sc_q, bp);
- ! wdstart(wd);
- splx(s);
- return;
-
- ***************
- *** 441,497 ****
- wdstart(wd)
- struct wd_softc *wd;
- {
- ! struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent;
- ! int active = wdc->sc_drives.tqh_first != 0;
- !
- ! /* Link onto controller queue. */
- ! wd->sc_q.b_active = 1;
- ! TAILQ_INSERT_TAIL(&wdc->sc_drives, wd, sc_drivechain);
- !
- ! disk_busy(&wd->sc_dk);
- !
- ! /* If controller not already active, start it. */
- ! if (!active)
- ! wdcstart(wdc);
- ! }
- !
- ! /*
- ! * Finish an I/O operation. Clean up the drive and controller state, set the
- ! * residual count, and inform the upper layers that the operation is complete.
- ! */
- ! void
- ! wdfinish(wd, bp)
- ! struct wd_softc *wd;
- ! struct buf *bp;
- ! {
- ! struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent;
- !
- ! wdc->sc_flags &= ~(WDCF_SINGLE | WDCF_ERROR);
- ! wdc->sc_errors = 0;
- ! /*
- ! * Move this drive to the end of the queue to give others a `fair'
- ! * chance.
- ! */
- ! if (wd->sc_drivechain.tqe_next) {
- ! TAILQ_REMOVE(&wdc->sc_drives, wd, sc_drivechain);
- ! if (bp->b_actf) {
- ! TAILQ_INSERT_TAIL(&wdc->sc_drives, wd, sc_drivechain);
- ! } else
- ! wd->sc_q.b_active = 0;
- ! }
- ! bp->b_resid = wd->sc_bcount;
- ! wd->sc_skip = 0;
- ! wd->sc_q.b_actf = bp->b_actf;
- !
- ! disk_unbusy(&wd->sc_dk, (bp->b_bcount - bp->b_resid));
-
- ! if (!wd->sc_q.b_actf) {
- ! TAILQ_REMOVE(&wdc->sc_drives, wd, sc_drivechain);
- ! wd->sc_q.b_active = 0;
- ! } else
- disk_busy(&wd->sc_dk);
- !
- ! biodone(bp);
- }
-
- int
- --- 256,297 ----
- wdstart(wd)
- struct wd_softc *wd;
- {
- ! struct buf *dp, *bp=0;
- ! struct wd_link *d_link = wd->d_link;
- ! struct wdc_link *ctlr_link = d_link->ctlr_link;
- ! struct wdc_xfer *xfer;
- ! /* int blkno, nblks;*/
- ! u_long p_offset;
- !
- ! while (d_link->openings > 0) {
- !
- ! /* Is there a buf for us ? */
- ! dp = &wd->sc_q;
- ! if ((bp = dp->b_actf) == NULL) /* yes, an assign */
- ! return;
- ! dp->b_actf = bp->b_actf;
- !
- ! /*
- ! * Make the command. First lock the device
- ! */
- ! d_link->openings--;
- ! if (WDPART(bp->b_dev) != RAW_PART)
- ! p_offset=wd->sc_dk.dk_label->d_partitions[WDPART(bp->b_dev)].p_offset;
- ! else p_offset=0;
- ! xfer = wdc_get_xfer(ctlr_link,0);
- ! if (xfer == NULL) panic("wdc_xfer");
- ! xfer->d_link = d_link;
- ! xfer->c_bp = bp;
- ! xfer->c_p_offset = p_offset;
- ! xfer->databuf = bp->b_data;
- ! xfer->c_bcount = bp->b_bcount;
- ! xfer->c_flags |= bp->b_flags & (B_READ|B_WRITE);
- ! xfer->c_blkno = bp->b_blkno;
-
- ! /* Instrumentation. */
- disk_busy(&wd->sc_dk);
- ! wdc_exec_xfer(wd->d_link,xfer);
- ! }
- }
-
- int
- ***************
- *** 500,506 ****
- struct uio *uio;
- int flags;
- {
- !
- return (physio(wdstrategy, NULL, dev, B_READ, minphys, uio));
- }
-
- --- 300,308 ----
- struct uio *uio;
- int flags;
- {
- ! #ifdef WDDEBUG
- ! printf("wdread\n");
- ! #endif
- return (physio(wdstrategy, NULL, dev, B_READ, minphys, uio));
- }
-
- ***************
- *** 510,884 ****
- struct uio *uio;
- int flags;
- {
- -
- - return (physio(wdstrategy, NULL, dev, B_WRITE, minphys, uio));
- - }
- -
- - /*
- - * Start I/O on a controller. This does the calculation, and starts a read or
- - * write operation. Called to from wdstart() to start a transfer, from
- - * wdcintr() to continue a multi-sector transfer or start the next transfer, or
- - * wdcrestart() after recovering from an error.
- - */
- - void
- - wdcstart(wdc)
- - struct wdc_softc *wdc;
- - {
- - struct wd_softc *wd;
- - struct buf *bp;
- - struct disklabel *lp;
- - int nblks;
- -
- - #ifdef DIAGNOSTIC
- - if ((wdc->sc_flags & WDCF_ACTIVE) != 0)
- - panic("wdcstart: controller still active");
- - #endif
- -
- - /*
- - * XXX
- - * This is a kluge. See comments in wd_get_parms().
- - */
- - if ((wdc->sc_flags & WDCF_WANTED) != 0) {
- - wdc->sc_flags &= ~WDCF_WANTED;
- - wakeup(wdc);
- - return;
- - }
- -
- - loop:
- - /* Is there a drive for the controller to do a transfer with? */
- - wd = wdc->sc_drives.tqh_first;
- - if (wd == NULL)
- - return;
- -
- - /* Is there a transfer to this drive? If not, deactivate drive. */
- - bp = wd->sc_q.b_actf;
- -
- - if (wdc->sc_errors >= WDIORETRIES) {
- - wderror(wd, bp, "hard error");
- - bp->b_error = EIO;
- - bp->b_flags |= B_ERROR;
- - wdfinish(wd, bp);
- - goto loop;
- - }
- -
- - /* Do control operations specially. */
- - if (wd->sc_state < OPEN) {
- - /*
- - * Actually, we want to be careful not to mess with the control
- - * state if the device is currently busy, but we can assume
- - * that we never get to this point if that's the case.
- - */
- - if (wdcontrol(wd) == 0) {
- - /* The drive is busy. Wait. */
- - return;
- - }
- - }
- -
- - /*
- - * WDCF_ERROR is set by wdcunwedge() and wdcintr() when an error is
- - * encountered. If we are in multi-sector mode, then we switch to
- - * single-sector mode and retry the operation from the start.
- - */
- - if (wdc->sc_flags & WDCF_ERROR) {
- - wdc->sc_flags &= ~WDCF_ERROR;
- - if ((wdc->sc_flags & WDCF_SINGLE) == 0) {
- - wdc->sc_flags |= WDCF_SINGLE;
- - wd->sc_skip = 0;
- - }
- - }
- -
- - lp = wd->sc_dk.dk_label;
- -
- - /* When starting a transfer... */
- - if (wd->sc_skip == 0) {
- - int part = WDPART(bp->b_dev);
- - daddr_t blkno;
- -
- - #ifdef WDDEBUG
- - printf("\n%s: wdcstart %s %d@%d; map ", wd->sc_dev.dv_xname,
- - (bp->b_flags & B_READ) ? "read" : "write", bp->b_bcount,
- - bp->b_blkno);
- - #endif
- - wd->sc_bcount = bp->b_bcount;
- - blkno = bp->b_blkno;
- - if (part != RAW_PART)
- - blkno += lp->d_partitions[part].p_offset;
- - wd->sc_blkno = blkno / (lp->d_secsize / DEV_BSIZE);
- - } else {
- - #ifdef WDDEBUG
- - printf(" %d)%x", wd->sc_skip, inb(wd->sc_iobase+wd_altsts));
- - #endif
- - }
- -
- - /* When starting a multi-sector transfer, or doing single-sector
- - transfers... */
- - if (wd->sc_skip == 0 || (wdc->sc_flags & WDCF_SINGLE) != 0 ||
- - wd->sc_mode == WDM_DMA) {
- - daddr_t blkno = wd->sc_blkno;
- - long cylin, head, sector;
- - int command;
- -
- - if ((wdc->sc_flags & WDCF_SINGLE) != 0)
- - nblks = 1;
- - else if (wd->sc_mode != WDM_DMA)
- - nblks = wd->sc_bcount / lp->d_secsize;
- - else
- - nblks = min(wd->sc_bcount / lp->d_secsize, 8);
- -
- - /* Check for bad sectors and adjust transfer, if necessary. */
- - if ((lp->d_flags & D_BADSECT) != 0
- - #ifdef B_FORMAT
- - && (bp->b_flags & B_FORMAT) == 0
- - #endif
- - ) {
- - long blkdiff;
- - int i;
- -
- - for (i = 0; (blkdiff = wd->sc_badsect[i]) != -1; i++) {
- - blkdiff -= blkno;
- - if (blkdiff < 0)
- - continue;
- - if (blkdiff == 0) {
- - /* Replace current block of transfer. */
- - blkno =
- - lp->d_secperunit - lp->d_nsectors - i - 1;
- - }
- - if (blkdiff < nblks) {
- - /* Bad block inside transfer. */
- - wdc->sc_flags |= WDCF_SINGLE;
- - nblks = 1;
- - }
- - break;
- - }
- - /* Tranfer is okay now. */
- - }
- -
- - if ((wd->sc_params.wdp_capabilities & WD_CAP_LBA) != 0) {
- - sector = (blkno >> 0) & 0xff;
- - cylin = (blkno >> 8) & 0xffff;
- - head = (blkno >> 24) & 0xf;
- - head |= WDSD_LBA;
- - } else {
- - sector = blkno % lp->d_nsectors;
- - sector++; /* Sectors begin with 1, not 0. */
- - blkno /= lp->d_nsectors;
- - head = blkno % lp->d_ntracks;
- - blkno /= lp->d_ntracks;
- - cylin = blkno;
- - head |= WDSD_CHS;
- - }
- -
- - if (wd->sc_mode == WDM_PIOSINGLE ||
- - (wdc->sc_flags & WDCF_SINGLE) != 0)
- - wd->sc_nblks = 1;
- - else if (wd->sc_mode == WDM_PIOMULTI)
- - wd->sc_nblks = min(nblks, wd->sc_multiple);
- - else
- - wd->sc_nblks = nblks;
- - wd->sc_nbytes = wd->sc_nblks * lp->d_secsize;
- -
- - #ifdef B_FORMAT
- - if (bp->b_flags & B_FORMAT) {
- - sector = lp->d_gap3;
- - nblks = lp->d_nsectors;
- - command = WDCC_FORMAT;
- - } else
- - #endif
- - switch (wd->sc_mode) {
- - case WDM_DMA:
- - #if 0
- - command = (bp->b_flags & B_READ) ?
- - WDCC_READDMA : WDCC_WRITEDMA;
- - /* Start the DMA channel and bounce the buffer if
- - necessary. */
- - isa_dmastart(
- - bp->b_flags & B_READ ? DMAMODE_READ : DMAMODE_WRITE,
- - bp->b_data + wd->sc_skip,
- - wd->sc_nbytes, wdc->sc_drq);
- - #endif
- - panic("wd cannot do DMA yet\n");
- - break;
- - case WDM_PIOMULTI:
- - command = (bp->b_flags & B_READ) ?
- - WDCC_READMULTI : WDCC_WRITEMULTI;
- - break;
- - case WDM_PIOSINGLE:
- - command = (bp->b_flags & B_READ) ?
- - WDCC_READ : WDCC_WRITE;
- - break;
- - default:
- - #ifdef DIAGNOSTIC
- - panic("bad wd mode");
- - #endif
- - return;
- - }
- -
- - /* Initiate command! */
- - if (wdcommand(wd, command, cylin, head, sector, nblks) != 0) {
- - wderror(wd, NULL,
- - "wdcstart: timeout waiting for unbusy");
- - wdcunwedge(wdc);
- - return;
- - }
- -
- #ifdef WDDEBUG
- ! printf("sector %d cylin %d head %d addr %x sts %x\n", sector,
- ! cylin, head, bp->b_data, 0/*inb(wd->sc_iobase+wd_altsts*/));
- ! #endif
- ! } else if (wd->sc_nblks > 1) {
- ! /* The number of blocks in the last stretch may be smaller. */
- ! nblks = wd->sc_bcount / lp->d_secsize;
- ! if (wd->sc_nblks > nblks) {
- ! wd->sc_nblks = nblks;
- ! wd->sc_nbytes = wd->sc_bcount;
- ! }
- ! }
- !
- ! /* If this was a write and not using DMA, push the data. */
- ! if (wd->sc_mode != WDM_DMA &&
- ! (bp->b_flags & (B_READ|B_WRITE)) == B_WRITE) {
- ! if (wait_for_drq(wdc) < 0) {
- ! wderror(wd, NULL, "wdcstart: timeout waiting for drq");
- ! wdcunwedge(wdc);
- ! return;
- ! }
- !
- ! /* Push out data. */
- ! if ((wd->sc_flags & WDF_32BIT) == 0)
- ! outsw(wdc->sc_iobase+wd_data, bp->b_data + wd->sc_skip,
- ! wd->sc_nbytes >> 1);
- ! else
- ! outsl(wdc->sc_iobase+wd_data, bp->b_data + wd->sc_skip,
- ! wd->sc_nbytes >> 2);
- ! }
- !
- ! wdc->sc_flags |= WDCF_ACTIVE;
- ! timeout(wdctimeout, wdc, WAITTIME);
- ! }
- !
- ! /*
- ! * Interrupt routine for the controller. Acknowledge the interrupt, check for
- ! * errors on the current operation, mark it done if necessary, and start the
- ! * next request. Also check for a partially done transfer, and continue with
- ! * the next chunk if so.
- ! */
- ! int
- ! wdcintr(arg)
- ! void *arg;
- ! {
- ! struct wdc_softc *wdc = arg;
- ! struct wd_softc *wd;
- ! struct buf *bp;
- !
- ! if ((wdc->sc_flags & WDCF_ACTIVE) == 0) {
- ! /* Clear the pending interrupt and abort. */
- ! (void) inb(wdc->sc_iobase+wd_status);
- ! return 0;
- ! }
- !
- ! wdc->sc_flags &= ~WDCF_ACTIVE;
- ! untimeout(wdctimeout, wdc);
- !
- ! wd = wdc->sc_drives.tqh_first;
- ! bp = wd->sc_q.b_actf;
- !
- ! #ifdef WDDEBUG
- ! printf("I%d ", ctrlr);
- ! #endif
- !
- ! if (wait_for_unbusy(wdc) < 0) {
- ! wderror(wd, NULL, "wdcintr: timeout waiting for unbusy");
- ! wdc->sc_status |= WDCS_ERR; /* XXX */
- ! }
- !
- ! /* Is it not a transfer, but a control operation? */
- ! if (wd->sc_state < OPEN) {
- ! if (wdcontrol(wd) == 0) {
- ! /* The drive is busy. Wait. */
- ! return 1;
- ! }
- ! wdcstart(wdc);
- ! return 1;
- ! }
- !
- ! /* Turn off the DMA channel and unbounce the buffer. */
- ! if (wd->sc_mode == WDM_DMA)
- ! panic("wd cannot do DMA\n");
- ! #if 0
- ! isa_dmadone(bp->b_flags & B_READ ? DMAMODE_READ : DMAMODE_WRITE,
- ! bp->b_data + wd->sc_skip, wd->sc_nbytes, wdc->sc_drq);
- ! #endif
- ! /* Have we an error? */
- ! if (wdc->sc_status & WDCS_ERR) {
- ! #ifdef WDDEBUG
- ! wderror(wd, NULL, "wdcintr");
- ! #endif
- ! if ((wdc->sc_flags & WDCF_SINGLE) == 0) {
- ! wdc->sc_flags |= WDCF_ERROR;
- ! goto restart;
- ! }
- !
- ! #ifdef B_FORMAT
- ! if (bp->b_flags & B_FORMAT)
- ! goto bad;
- ! #endif
- !
- ! if (++wdc->sc_errors < WDIORETRIES)
- ! goto restart;
- ! wderror(wd, bp, "hard error");
- !
- ! #ifdef B_FORMAT
- ! bad:
- #endif
- - bp->b_error = EIO;
- - bp->b_flags |= B_ERROR;
- - goto done;
- - }
- -
- - /* If this was a read and not using DMA, fetch the data. */
- - if (wd->sc_mode != WDM_DMA &&
- - (bp->b_flags & (B_READ|B_WRITE)) == B_READ) {
- - if ((wdc->sc_status & (WDCS_DRDY | WDCS_DSC | WDCS_DRQ))
- - != (WDCS_DRDY | WDCS_DSC | WDCS_DRQ)) {
- - wderror(wd, NULL, "wdcintr: read intr before drq");
- - wdcunwedge(wdc);
- - return 1;
- - }
- -
- - /* Pull in data. */
- - if ((wd->sc_flags & WDF_32BIT) == 0)
- - insw(wdc->sc_iobase+wd_data, bp->b_data + wd->sc_skip,
- - wd->sc_nbytes >> 1);
- - else
- - insl(wdc->sc_iobase+wd_data, bp->b_data + wd->sc_skip,
- - wd->sc_nbytes >> 2);
- - }
- -
- - /* If we encountered any abnormalities, flag it as a soft error. */
- - if (wdc->sc_errors > 0 ||
- - (wdc->sc_status & WDCS_CORR) != 0) {
- - wderror(wd, bp, "soft error (corrected)");
- - wdc->sc_errors = 0;
- - }
- -
- - /* Adjust pointers for the next block, if any. */
- - wd->sc_blkno += wd->sc_nblks;
- - wd->sc_skip += wd->sc_nbytes;
- - wd->sc_bcount -= wd->sc_nbytes;
- -
- - /* See if this transfer is complete. */
- - if (wd->sc_bcount > 0)
- - goto restart;
- -
- - done:
- - /* Done with this transfer, with or without error. */
- - wdfinish(wd, bp);
- -
- - restart:
- - /* Start the next operation, if any. */
- - wdcstart(wdc);
-
- ! return 1;
- }
-
- /*
- --- 312,322 ----
- struct uio *uio;
- int flags;
- {
- #ifdef WDDEBUG
- ! printf("wdwrite\n");
- #endif
-
- ! return (physio(wdstrategy, NULL, dev, B_WRITE, minphys, uio));
- }
-
- /*
- ***************
- *** 888,904 ****
- * Several drivers do this; it should be abstracted and made MP-safe.
- */
- int
- ! wdlock(wd)
- ! struct wd_softc *wd;
- {
- int error;
-
- ! while ((wd->sc_flags & WDF_LOCKED) != 0) {
- ! wd->sc_flags |= WDF_WANTED;
- ! if ((error = tsleep(wd, PRIBIO | PCATCH, "wdlck", 0)) != 0)
- return error;
- }
- ! wd->sc_flags |= WDF_LOCKED;
- return 0;
- }
-
- --- 326,351 ----
- * Several drivers do this; it should be abstracted and made MP-safe.
- */
- int
- ! wdlock(d_link)
- ! struct wd_link *d_link;
- {
- int error;
- + int s;
-
- ! #ifdef WDDEBUG
- ! printf("wdlock\n");
- ! #endif
- ! s=splbio();
- !
- ! while ((d_link->sc_flags & WDF_LOCKED) != 0) {
- ! d_link->sc_flags |= WDF_WANTED;
- ! if ((error = tsleep(d_link, PRIBIO | PCATCH, "wdlck", 0)) != 0) {
- ! splx(s);
- return error;
- + }
- }
- ! d_link->sc_flags |= WDF_LOCKED;
- ! splx(s);
- return 0;
- }
-
- ***************
- *** 906,919 ****
- * Unlock and wake up any waiters.
- */
- void
- ! wdunlock(wd)
- ! struct wd_softc *wd;
- {
-
- ! wd->sc_flags &= ~WDF_LOCKED;
- ! if ((wd->sc_flags & WDF_WANTED) != 0) {
- ! wd->sc_flags &= ~WDF_WANTED;
- ! wakeup(wd);
- }
- }
-
- --- 353,369 ----
- * Unlock and wake up any waiters.
- */
- void
- ! wdunlock(d_link)
- ! struct wd_link *d_link;
- {
- + #ifdef WDDEBUG
- + printf("wdunlock\n");
- + #endif
-
- ! d_link->sc_flags &= ~WDF_LOCKED;
- ! if ((d_link->sc_flags & WDF_WANTED) != 0) {
- ! d_link->sc_flags &= ~WDF_WANTED;
- ! wakeup(d_link);
- }
- }
-
- ***************
- *** 924,931 ****
- --- 374,387 ----
- struct proc *p;
- {
- struct wd_softc *wd;
- + struct wd_link *d_link;
- int unit, part;
- int error;
- +
- + #ifdef WDDEBUG
- + printf("wdopen\n");
- + #endif
- +
-
- unit = WDUNIT(dev);
- if (unit >= wd_cd.cd_ndevs)
- ***************
- *** 934,957 ****
- if (wd == 0)
- return ENXIO;
-
- ! if ((error = wdlock(wd)) != 0)
- return error;
- -
- if (wd->sc_dk.dk_openmask != 0) {
- /*
- * If any partition is open, but the disk has been invalidated,
- * disallow further opens.
- */
- ! if ((wd->sc_flags & WDF_LOADED) == 0) {
- error = EIO;
- goto bad3;
- }
- } else {
- ! if ((wd->sc_flags & WDF_LOADED) == 0) {
- ! wd->sc_flags |= WDF_LOADED;
-
- /* Load the physical device parameters. */
- ! if (wd_get_parms(wd) != 0) {
- error = ENXIO;
- goto bad2;
- }
- --- 390,413 ----
- if (wd == 0)
- return ENXIO;
-
- ! d_link = wd->d_link;
- ! if ((error = wdlock(d_link)) != 0)
- return error;
- if (wd->sc_dk.dk_openmask != 0) {
- /*
- * If any partition is open, but the disk has been invalidated,
- * disallow further opens.
- */
- ! if ((d_link->sc_flags & WDF_LOADED) == 0) {
- error = EIO;
- goto bad3;
- }
- } else {
- ! if ((d_link->sc_flags & WDF_LOADED) == 0) {
- ! d_link->sc_flags |= WDF_LOADED;
-
- /* Load the physical device parameters. */
- ! if (wdc_get_parms(d_link) != 0) {
- error = ENXIO;
- goto bad2;
- }
- ***************
- *** 982,999 ****
- }
- wd->sc_dk.dk_openmask = wd->sc_dk.dk_copenmask | wd->sc_dk.dk_bopenmask;
-
- ! wdunlock(wd);
- return 0;
-
- bad2:
- ! wd->sc_flags &= ~WDF_LOADED;
-
- bad:
- if (wd->sc_dk.dk_openmask == 0) {
- }
-
- bad3:
- ! wdunlock(wd);
- return error;
- }
-
- --- 438,455 ----
- }
- wd->sc_dk.dk_openmask = wd->sc_dk.dk_copenmask | wd->sc_dk.dk_bopenmask;
-
- ! wdunlock(d_link);
- return 0;
-
- bad2:
- ! d_link->sc_flags &= ~WDF_LOADED;
-
- bad:
- if (wd->sc_dk.dk_openmask == 0) {
- }
-
- bad3:
- ! wdunlock(d_link);
- return error;
- }
-
- ***************
- *** 1007,1013 ****
- int part = WDPART(dev);
- int error;
-
- ! if ((error = wdlock(wd)) != 0)
- return error;
-
- switch (fmt) {
- --- 463,469 ----
- int part = WDPART(dev);
- int error;
-
- ! if ((error = wdlock(wd->d_link)) != 0)
- return error;
-
- switch (fmt) {
- ***************
- *** 1024,1030 ****
- /* XXXX Must wait for I/O to complete! */
- }
-
- ! wdunlock(wd);
- return 0;
- }
-
- --- 480,486 ----
- /* XXXX Must wait for I/O to complete! */
- }
-
- ! wdunlock(wd->d_link);
- return 0;
- }
-
- ***************
- *** 1036,1057 ****
- struct wd_softc *wd;
- {
- struct disklabel *lp = wd->sc_dk.dk_label;
- char *errstring;
-
- bzero(lp, sizeof(struct disklabel));
- bzero(wd->sc_dk.dk_cpulabel, sizeof(struct cpu_disklabel));
-
- lp->d_secsize = DEV_BSIZE;
- ! lp->d_ntracks = wd->sc_params.wdp_heads;
- ! lp->d_nsectors = wd->sc_params.wdp_sectors;
- ! lp->d_ncylinders = wd->sc_params.wdp_cylinders;
- lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
-
- #if 0
- strncpy(lp->d_typename, "ST506 disk", 16);
- lp->d_type = DTYPE_ST506;
- #endif
- ! strncpy(lp->d_packname, wd->sc_params.wdp_model, 16);
- lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders;
- lp->d_rpm = 3600;
- lp->d_interleave = 1;
- --- 492,518 ----
- struct wd_softc *wd;
- {
- struct disklabel *lp = wd->sc_dk.dk_label;
- + struct wd_link *d_link = wd->d_link;
- char *errstring;
-
- + #ifdef WDDEBUG
- + printf("wdgetdisklabel\n");
- + #endif
- +
- bzero(lp, sizeof(struct disklabel));
- bzero(wd->sc_dk.dk_cpulabel, sizeof(struct cpu_disklabel));
-
- lp->d_secsize = DEV_BSIZE;
- ! lp->d_ntracks = d_link->sc_params.wdp_heads;
- ! lp->d_nsectors = d_link->sc_params.wdp_sectors;
- ! lp->d_ncylinders = d_link->sc_params.wdp_cylinders;
- lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
-
- #if 0
- strncpy(lp->d_typename, "ST506 disk", 16);
- lp->d_type = DTYPE_ST506;
- #endif
- ! strncpy(lp->d_packname, d_link->sc_params.wdp_model, 16);
- lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders;
- lp->d_rpm = 3600;
- lp->d_interleave = 1;
- ***************
- *** 1067,1076 ****
- lp->d_magic2 = DISKMAGIC;
- lp->d_checksum = dkcksum(lp);
-
- ! wd->sc_badsect[0] = -1;
-
- ! if (wd->sc_state > RECAL)
- ! wd->sc_state = RECAL;
- errstring = readdisklabel(MAKEWDDEV(0, wd->sc_dev.dv_unit, RAW_PART),
- wdstrategy, lp, wd->sc_dk.dk_cpulabel);
- if (errstring) {
- --- 528,537 ----
- lp->d_magic2 = DISKMAGIC;
- lp->d_checksum = dkcksum(lp);
-
- ! d_link->sc_badsect[0] = -1;
-
- ! if (d_link->sc_state > RECAL)
- ! d_link->sc_state = RECAL;
- errstring = readdisklabel(MAKEWDDEV(0, wd->sc_dev.dv_unit, RAW_PART),
- wdstrategy, lp, wd->sc_dk.dk_cpulabel);
- if (errstring) {
- ***************
- *** 1080,1087 ****
- * assume the DOS geometry is now in the label and try
- * again. XXX This is a kluge.
- */
- ! if (wd->sc_state > GEOMETRY)
- ! wd->sc_state = GEOMETRY;
- errstring = readdisklabel(MAKEWDDEV(0, wd->sc_dev.dv_unit, RAW_PART),
- wdstrategy, lp, wd->sc_dk.dk_cpulabel);
- }
- --- 541,548 ----
- * assume the DOS geometry is now in the label and try
- * again. XXX This is a kluge.
- */
- ! if (d_link->sc_state > GEOMETRY)
- ! d_link->sc_state = GEOMETRY;
- errstring = readdisklabel(MAKEWDDEV(0, wd->sc_dev.dv_unit, RAW_PART),
- wdstrategy, lp, wd->sc_dk.dk_cpulabel);
- }
- ***************
- *** 1090,1359 ****
- return;
- }
-
- ! if (wd->sc_state > GEOMETRY)
- ! wd->sc_state = GEOMETRY;
- if ((lp->d_flags & D_BADSECT) != 0)
- bad144intern(wd);
- }
-
- - /*
- - * Implement operations needed before read/write.
- - * Returns 0 if operation still in progress, 1 if completed.
- - */
- - int
- - wdcontrol(wd)
- - struct wd_softc *wd;
- - {
- - struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent;
- -
- - switch (wd->sc_state) {
- - case RECAL: /* Set SDH, step rate, do recal. */
- - if (wdcommandshort(wdc, wd->sc_drive, WDCC_RECAL) != 0) {
- - wderror(wd, NULL, "wdcontrol: recal failed (1)");
- - goto bad;
- - }
- - wd->sc_state = RECAL_WAIT;
- - break;
- -
- - case RECAL_WAIT:
- - if (wdc->sc_status & WDCS_ERR) {
- - wderror(wd, NULL, "wdcontrol: recal failed (2)");
- - goto bad;
- - }
- - /* fall through */
- - case GEOMETRY:
- - if ((wd->sc_params.wdp_capabilities & WD_CAP_LBA) != 0)
- - goto multimode;
- - if (wdsetctlr(wd) != 0) {
- - /* Already printed a message. */
- - goto bad;
- - }
- - wd->sc_state = GEOMETRY_WAIT;
- - break;
- -
- - case GEOMETRY_WAIT:
- - if (wdc->sc_status & WDCS_ERR) {
- - wderror(wd, NULL, "wdcontrol: geometry failed");
- - goto bad;
- - }
- - /* fall through */
- - case MULTIMODE:
- - multimode:
- - if (wd->sc_mode != WDM_PIOMULTI)
- - goto open;
- - outb(wdc->sc_iobase+wd_seccnt, wd->sc_multiple);
- - if (wdcommandshort(wdc, wd->sc_drive, WDCC_SETMULTI) != 0) {
- - wderror(wd, NULL, "wdcontrol: setmulti failed (1)");
- - goto bad;
- - }
- - wd->sc_state = MULTIMODE_WAIT;
- - break;
- -
- - case MULTIMODE_WAIT:
- - if (wdc->sc_status & WDCS_ERR) {
- - wderror(wd, NULL, "wdcontrol: setmulti failed (2)");
- - goto bad;
- - }
- - /* fall through */
- - case OPEN:
- - open:
- - wdc->sc_errors = 0;
- - wd->sc_state = OPEN;
- - /*
- - * The rest of the initialization can be done by normal means.
- - */
- - return 1;
- -
- - bad:
- - wdcunwedge(wdc);
- - return 0;
- - }
- -
- - wdc->sc_flags |= WDCF_ACTIVE;
- - timeout(wdctimeout, wdc, WAITTIME);
- - return 0;
- - }
- -
- - /*
- - * Wait for the drive to become ready and send a command.
- - * Return -1 if busy for too long or 0 otherwise.
- - * Assumes interrupts are blocked.
- - */
- - int
- - wdcommand(wd, command, cylin, head, sector, count)
- - struct wd_softc *wd;
- - int command;
- - int cylin, head, sector, count;
- - {
- - struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent;
- - int iobase = wdc->sc_iobase;
- - int stat;
- -
- - /* Select drive, head, and addressing mode. */
- - outb(iobase+wd_sdh, WDSD_IBM | (wd->sc_drive << 4) | head);
- -
- - /* Wait for it to become ready to accept a command. */
- - if (command == WDCC_IDP)
- - stat = wait_for_unbusy(wdc);
- - else
- - stat = wdcwait(wdc, WDCS_DRDY);
- - if (stat < 0)
- - return -1;
- -
- - /* Load parameters. */
- - if (wd->sc_dk.dk_label->d_type == DTYPE_ST506)
- - outb(iobase+wd_precomp, wd->sc_dk.dk_label->d_precompcyl / 4);
- - else
- - outb(iobase+wd_features, 0);
- - outb(iobase+wd_cyl_lo, cylin);
- - outb(iobase+wd_cyl_hi, cylin >> 8);
- - outb(iobase+wd_sector, sector);
- - outb(iobase+wd_seccnt, count);
- -
- - /* Send command. */
- - outb(iobase+wd_command, command);
- -
- - return 0;
- - }
- -
- - /*
- - * Simplified version of wdcommand().
- - */
- - int
- - wdcommandshort(wdc, drive, command)
- - struct wdc_softc *wdc;
- - int drive;
- - int command;
- - {
- - int iobase = wdc->sc_iobase;
- -
- - /* Select drive. */
- - outb(iobase+wd_sdh, WDSD_IBM | (drive << 4));
- -
- - if (wdcwait(wdc, WDCS_DRDY) < 0)
- - return -1;
- -
- - outb(iobase+wd_command, command);
- -
- - return 0;
- - }
-
- /*
- * Tell the drive what geometry to use.
- */
- int
- ! wdsetctlr(wd)
- ! struct wd_softc *wd;
- {
-
- #ifdef WDDEBUG
- ! printf("wd(%d,%d) C%dH%dS%d\n", wd->sc_dev.dv_unit, wd->sc_drive,
- wd->sc_dk.dk_label->d_ncylinders, wd->sc_dk.dk_label->d_ntracks,
- wd->sc_dk.dk_label->d_nsectors);
- #endif
-
- ! if (wdcommand(wd, WDCC_IDP, wd->sc_dk.dk_label->d_ncylinders,
- ! wd->sc_dk.dk_label->d_ntracks - 1, 0,
- ! wd->sc_dk.dk_label->d_nsectors) != 0) {
- ! wderror(wd, NULL, "wdsetctlr: geometry upload failed");
- return -1;
- }
-
- return 0;
- }
-
- - /*
- - * Get the drive parameters, if ESDI or ATA, or create fake ones for ST506.
- - */
- int
- ! wd_get_parms(wd)
- ! struct wd_softc *wd;
- ! {
- ! struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent;
- ! int i;
- ! char tb[DEV_BSIZE];
- ! int s, error;
- !
- ! /*
- ! * XXX
- ! * The locking done here, and the length of time this may keep the rest
- ! * of the system suspended, is a kluge. This should be rewritten to
- ! * set up a transfer and queue it through wdstart(), but it's called
- ! * infrequently enough that this isn't a pressing matter.
- ! */
- !
- ! s = splbio();
- !
- ! while ((wdc->sc_flags & WDCF_ACTIVE) != 0) {
- ! wdc->sc_flags |= WDCF_WANTED;
- ! if ((error = tsleep(wdc, PRIBIO | PCATCH, "wdprm", 0)) != 0) {
- ! splx(s);
- ! return error;
- ! }
- ! }
- !
- ! if (wdcommandshort(wdc, wd->sc_drive, WDCC_IDENTIFY) != 0 ||
- ! wait_for_drq(wdc) != 0) {
- ! /*
- ! * We `know' there's a drive here; just assume it's old.
- ! * This geometry is only used to read the MBR and print a
- ! * (false) attach message.
- ! */
- ! strncpy(wd->sc_dk.dk_label->d_typename, "ST506",
- ! sizeof wd->sc_dk.dk_label->d_typename);
- ! wd->sc_dk.dk_label->d_type = DTYPE_ST506;
- !
- ! strncpy(wd->sc_params.wdp_model, "unknown",
- ! sizeof wd->sc_params.wdp_model);
- ! wd->sc_params.wdp_config = WD_CFG_FIXED;
- ! wd->sc_params.wdp_cylinders = 1024;
- ! wd->sc_params.wdp_heads = 8;
- ! wd->sc_params.wdp_sectors = 17;
- ! wd->sc_params.wdp_maxmulti = 0;
- ! wd->sc_params.wdp_usedmovsd = 0;
- ! wd->sc_params.wdp_capabilities = 0;
- ! } else {
- ! strncpy(wd->sc_dk.dk_label->d_typename, "ESDI/IDE",
- ! sizeof wd->sc_dk.dk_label->d_typename);
- ! wd->sc_dk.dk_label->d_type = DTYPE_ESDI;
- !
- ! /* Read in parameter block. */
- ! insw(wdc->sc_iobase+wd_data, tb, sizeof(tb) / sizeof(short));
- ! bcopy(tb, &wd->sc_params, sizeof(struct wdparams));
- !
- ! /* Shuffle string byte order. */
- ! for (i = 0; i < sizeof(wd->sc_params.wdp_model); i += 2) {
- ! u_short *p;
- ! p = (u_short *)(wd->sc_params.wdp_model + i);
- ! *p = ntohs(*p);
- ! }
- ! }
- !
- ! /* Clear any leftover interrupt. */
- ! (void) inb(wdc->sc_iobase+wd_status);
- !
- ! /* Restart the queue. */
- ! wdcstart(wdc);
- !
- ! splx(s);
- ! return 0;
- ! }
- !
- ! int
- ! wdioctl(dev, cmd, addr, flag, p)
- dev_t dev;
- ! u_long cmd;
- caddr_t addr;
- int flag;
- struct proc *p;
- {
- struct wd_softc *wd = wd_cd.cd_devs[WDUNIT(dev)];
- int error;
- !
- ! if ((wd->sc_flags & WDF_LOADED) == 0)
- return EIO;
-
- ! switch (cmd) {
- case DIOCSBAD:
- if ((flag & FWRITE) == 0)
- return EBADF;
- --- 551,607 ----
- return;
- }
-
- ! if (d_link->sc_state > GEOMETRY)
- ! d_link->sc_state = GEOMETRY;
- if ((lp->d_flags & D_BADSECT) != 0)
- bad144intern(wd);
- }
-
-
- /*
- * Tell the drive what geometry to use.
- */
- int
- ! wdsetctlr(d_link)
- ! struct wd_link *d_link;
- {
- + struct wd_softc *wd=(struct wd_softc *)d_link->wd_softc;
-
- #ifdef WDDEBUG
- ! printf("wd(%d,%d) C%dH%dS%d\n", wd->sc_dev.dv_unit, d_link->sc_drive,
- wd->sc_dk.dk_label->d_ncylinders, wd->sc_dk.dk_label->d_ntracks,
- wd->sc_dk.dk_label->d_nsectors);
- #endif
-
- ! if (wdccommand(d_link, WDCC_IDP, d_link->sc_drive, wd->sc_dk.dk_label->d_ncylinders,
- ! wd->sc_dk.dk_label->d_ntracks - 1, 0, wd->sc_dk.dk_label->d_nsectors)
- ! != 0) {
- ! wderror(d_link, NULL, "wdsetctlr: geometry upload failed");
- return -1;
- }
-
- return 0;
- }
-
- int
- ! wdioctl(dev, xfer, addr, flag, p)
- dev_t dev;
- ! u_long xfer;
- caddr_t addr;
- int flag;
- struct proc *p;
- {
- struct wd_softc *wd = wd_cd.cd_devs[WDUNIT(dev)];
- + struct wd_link *d_link = wd->d_link;
- int error;
- ! #ifdef WDDEBUG
- ! printf("wdioctl\n");
- ! #endif
- !
- ! if ((d_link->sc_flags & WDF_LOADED) == 0)
- return EIO;
-
- ! switch (xfer) {
- case DIOCSBAD:
- if ((flag & FWRITE) == 0)
- return EBADF;
- ***************
- *** 1377,1409 ****
- if ((flag & FWRITE) == 0)
- return EBADF;
-
- ! if ((error = wdlock(wd)) != 0)
- return error;
- ! wd->sc_flags |= WDF_LABELLING;
-
- error = setdisklabel(wd->sc_dk.dk_label,
- (struct disklabel *)addr, /*wd->sc_dk.dk_openmask : */0,
- wd->sc_dk.dk_cpulabel);
- if (error == 0) {
- ! if (wd->sc_state > GEOMETRY)
- ! wd->sc_state = GEOMETRY;
- ! if (cmd == DIOCWDINFO)
- error = writedisklabel(WDLABELDEV(dev),
- wdstrategy, wd->sc_dk.dk_label,
- wd->sc_dk.dk_cpulabel);
- }
-
- ! wd->sc_flags &= ~WDF_LABELLING;
- ! wdunlock(wd);
- return error;
-
- case DIOCWLABEL:
- if ((flag & FWRITE) == 0)
- return EBADF;
- if (*(int *)addr)
- ! wd->sc_flags |= WDF_WLABEL;
- else
- ! wd->sc_flags &= ~WDF_WLABEL;
- return 0;
-
- #ifdef notyet
- --- 625,657 ----
- if ((flag & FWRITE) == 0)
- return EBADF;
-
- ! if ((error = wdlock(wd->d_link)) != 0)
- return error;
- ! d_link->sc_flags |= WDF_LABELLING;
-
- error = setdisklabel(wd->sc_dk.dk_label,
- (struct disklabel *)addr, /*wd->sc_dk.dk_openmask : */0,
- wd->sc_dk.dk_cpulabel);
- if (error == 0) {
- ! if (d_link->sc_state > GEOMETRY)
- ! d_link->sc_state = GEOMETRY;
- ! if (xfer == DIOCWDINFO)
- error = writedisklabel(WDLABELDEV(dev),
- wdstrategy, wd->sc_dk.dk_label,
- wd->sc_dk.dk_cpulabel);
- }
-
- ! d_link->sc_flags &= ~WDF_LABELLING;
- ! wdunlock(d_link);
- return error;
-
- case DIOCWLABEL:
- if ((flag & FWRITE) == 0)
- return EBADF;
- if (*(int *)addr)
- ! d_link->sc_flags |= WDF_WLABEL;
- else
- ! d_link->sc_flags &= ~WDF_WLABEL;
- return 0;
-
- #ifdef notyet
- ***************
- *** 1433,1439 ****
- return error;
- }
- #endif
- !
- default:
- return ENOTTY;
- }
- --- 681,687 ----
- return error;
- }
- #endif
- !
- default:
- return ENOTTY;
- }
- ***************
- *** 1460,1466 ****
- struct wd_softc *wd;
- int part;
- int size;
- !
- if (wdopen(dev, 0, S_IFBLK, NULL) != 0)
- return -1;
- wd = wd_cd.cd_devs[WDUNIT(dev)];
- --- 708,717 ----
- struct wd_softc *wd;
- int part;
- int size;
- ! #ifdef WDDEBUG
- ! printf("wdsize\n");
- ! #endif
- !
- if (wdopen(dev, 0, S_IFBLK, NULL) != 0)
- return -1;
- wd = wd_cd.cd_devs[WDUNIT(dev)];
- ***************
- *** 1476,1484 ****
-
-
- #ifndef __BDEVSW_DUMP_OLD_TYPE
- - /* #define WD_DUMP_NOT_TRUSTED if you just want to watch */
- static int wddoingadump;
- ! static int wddumprecalibrated;
-
- /*
- * Dump core after a system crash.
- --- 727,734 ----
-
-
- #ifndef __BDEVSW_DUMP_OLD_TYPE
- static int wddoingadump;
- ! /*static int wddumprecalibrated;*/
-
- /*
- * Dump core after a system crash.
- ***************
- *** 1491,1500 ****
- size_t size;
- {
- struct wd_softc *wd; /* disk unit to do the I/O */
- ! struct wdc_softc *wdc; /* disk controller to do the I/O */
- struct disklabel *lp; /* disk's disklabel */
- int unit, part;
- int nblks; /* total number of sectors left to write */
-
- /* Check if recursive dump; if so, punt. */
- if (wddoingadump)
- --- 741,751 ----
- size_t size;
- {
- struct wd_softc *wd; /* disk unit to do the I/O */
- ! struct wd_link *d_link; /* link struct for this disk */
- struct disklabel *lp; /* disk's disklabel */
- int unit, part;
- int nblks; /* total number of sectors left to write */
- + int err;
-
- /* Check if recursive dump; if so, punt. */
- if (wddoingadump)
- ***************
- *** 1505,1521 ****
- if (unit >= wd_cd.cd_ndevs)
- return ENXIO;
- wd = wd_cd.cd_devs[unit];
- if (wd == 0)
- return ENXIO;
-
- part = WDPART(dev);
-
- /* Make sure it was initialized. */
- ! if (wd->sc_state < OPEN)
- return ENXIO;
-
- - wdc = (void *)wd->sc_dev.dv_parent;
- -
- /* Convert to disk sectors. Request must be a multiple of size. */
- lp = wd->sc_dk.dk_label;
- if ((size % lp->d_secsize) != 0)
- --- 756,771 ----
- if (unit >= wd_cd.cd_ndevs)
- return ENXIO;
- wd = wd_cd.cd_devs[unit];
- + d_link = wd->d_link;
- if (wd == 0)
- return ENXIO;
-
- part = WDPART(dev);
-
- /* Make sure it was initialized. */
- ! if (d_link->sc_state < OPEN)
- return ENXIO;
-
- /* Convert to disk sectors. Request must be a multiple of size. */
- lp = wd->sc_dk.dk_label;
- if ((size % lp->d_secsize) != 0)
- ***************
- *** 1530,1614 ****
- /* Offset block number to start of partition. */
- blkno += lp->d_partitions[part].p_offset;
-
- ! /* Recalibrate, if first dump transfer. */
- ! if (wddumprecalibrated == 0) {
- ! wddumprecalibrated = 1;
- ! if (wdcommandshort(wdc, wd->sc_drive, WDCC_RECAL) != 0 ||
- ! wait_for_ready(wdc) != 0 || wdsetctlr(wd) != 0 ||
- ! wait_for_ready(wdc) != 0) {
- ! wderror(wd, NULL, "wddump: recal failed");
- ! return EIO;
- ! }
- }
- !
- ! while (nblks > 0) {
- ! daddr_t xlt_blkno = blkno;
- ! long cylin, head, sector;
- !
- ! if ((lp->d_flags & D_BADSECT) != 0) {
- ! long blkdiff;
- ! int i;
- !
- ! for (i = 0; (blkdiff = wd->sc_badsect[i]) != -1; i++) {
- ! blkdiff -= xlt_blkno;
- ! if (blkdiff < 0)
- ! continue;
- ! if (blkdiff == 0) {
- ! /* Replace current block of transfer. */
- ! xlt_blkno = lp->d_secperunit -
- ! lp->d_nsectors - i - 1;
- ! }
- ! break;
- ! }
- ! /* Tranfer is okay now. */
- ! }
- !
- ! if ((wd->sc_params.wdp_capabilities & WD_CAP_LBA) != 0) {
- ! sector = (xlt_blkno >> 0) & 0xff;
- ! cylin = (xlt_blkno >> 8) & 0xffff;
- ! head = (xlt_blkno >> 24) & 0xf;
- ! head |= WDSD_LBA;
- ! } else {
- ! sector = xlt_blkno % lp->d_nsectors;
- ! sector++; /* Sectors begin with 1, not 0. */
- ! xlt_blkno /= lp->d_nsectors;
- ! head = xlt_blkno % lp->d_ntracks;
- ! xlt_blkno /= lp->d_ntracks;
- ! cylin = xlt_blkno;
- ! head |= WDSD_CHS;
- ! }
- !
- ! #ifndef WD_DUMP_NOT_TRUSTED
- ! if (wdcommand(wd, WDCC_WRITE, cylin, head, sector, 1) != 0 ||
- ! wait_for_drq(wdc) != 0) {
- ! wderror(wd, NULL, "wddump: write failed");
- ! return EIO;
- ! }
- !
- ! outsw(wdc->sc_iobase+wd_data, va, lp->d_secsize >> 1);
- !
- ! /* Check data request (should be done). */
- ! if (wait_for_ready(wdc) != 0) {
- ! wderror(wd, NULL, "wddump: timeout waiting for ready");
- ! return EIO;
- ! }
- ! #else /* WD_DUMP_NOT_TRUSTED */
- ! /* Let's just talk about this first... */
- ! printf("wd%d: dump addr 0x%x, cylin %d, head %d, sector %d\n",
- ! unit, va, cylin, head, sector);
- ! delay(500 * 1000); /* half a second */
- ! #endif
- !
- ! /* update block count */
- ! nblks -= 1;
- ! blkno += 1;
- ! va += lp->d_secsize;
- ! }
- !
- ! wddoingadump = 0;
- ! return 0;
- }
- #else /* __BDEVSW_DUMP_NEW_TYPE */
- int
- wddump(dev, blkno, va, size)
- dev_t dev;
- --- 780,794 ----
- /* Offset block number to start of partition. */
- blkno += lp->d_partitions[part].p_offset;
-
- ! err = wdcdump(d_link, blkno, nblks, va);
- ! if (err == 0) {
- ! wddoingadump = 0;
- }
- ! return err;
- }
- #else /* __BDEVSW_DUMP_NEW_TYPE */
- +
- +
- int
- wddump(dev, blkno, va, size)
- dev_t dev;
- ***************
- *** 1631,1789 ****
- {
- struct dkbad *bt = &wd->sc_dk.dk_cpulabel->bad;
- struct disklabel *lp = wd->sc_dk.dk_label;
- int i = 0;
-
- for (; i < 126; i++) {
- if (bt->bt_bad[i].bt_cyl == 0xffff)
- break;
- ! wd->sc_badsect[i] =
- bt->bt_bad[i].bt_cyl * lp->d_secpercyl +
- (bt->bt_bad[i].bt_trksec >> 8) * lp->d_nsectors +
- (bt->bt_bad[i].bt_trksec & 0xff);
- }
- for (; i < 127; i++)
- ! wd->sc_badsect[i] = -1;
- ! }
- !
- ! int
- ! wdcreset(wdc)
- ! struct wdc_softc *wdc;
- ! {
- ! int iobase = wdc->sc_iobase;
- !
- ! /* Reset the device. */
- ! if (wdresethack) {
- ! outb(iobase+wd_ctlr, WDCTL_RST | WDCTL_IDS);
- ! delay(1000);
- ! outb(iobase+wd_ctlr, WDCTL_IDS);
- ! delay(1000);
- ! (void) inb(iobase+wd_error);
- ! outb(iobase+wd_ctlr, WDCTL_4BIT);
- ! }
- !
- ! if (wait_for_unbusy(wdc) < 0) {
- ! printf("%s: reset failed\n", wdc->sc_dev.dv_xname);
- ! return 1;
- ! }
- !
- ! return 0;
- ! }
- !
- ! void
- ! wdcrestart(arg)
- ! void *arg;
- ! {
- ! struct wdc_softc *wdc = arg;
- ! int s;
- !
- ! s = splbio();
- ! wdcstart(wdc);
- ! splx(s);
- }
-
- - /*
- - * Unwedge the controller after an unexpected error. We do this by resetting
- - * it, marking all drives for recalibration, and stalling the queue for a short
- - * period to give the reset time to finish.
- - * NOTE: We use a timeout here, so this routine must not be called during
- - * autoconfig or dump.
- - */
- void
- ! wdcunwedge(wdc)
- ! struct wdc_softc *wdc;
- ! {
- ! int unit;
- !
- ! untimeout(wdctimeout, wdc);
- ! (void) wdcreset(wdc);
- !
- ! /* Schedule recalibrate for all drives on this controller. */
- ! for (unit = 0; unit < wd_cd.cd_ndevs; unit++) {
- ! struct wd_softc *wd = wd_cd.cd_devs[unit];
- ! if (!wd || (void *)wd->sc_dev.dv_parent != wdc)
- ! continue;
- ! if (wd->sc_state > RECAL)
- ! wd->sc_state = RECAL;
- ! }
- !
- ! wdc->sc_flags |= WDCF_ERROR;
- ! ++wdc->sc_errors;
- !
- ! /* Wake up in a little bit and restart the operation. */
- ! timeout(wdcrestart, wdc, RECOVERYTIME);
- ! }
- !
- ! int
- ! wdcwait(wdc, mask)
- ! struct wdc_softc *wdc;
- ! int mask;
- ! {
- ! int iobase = wdc->sc_iobase;
- ! int timeout = 0;
- ! u_char status;
- ! #ifdef WDCNDELAY_DEBUG
- ! extern int cold;
- ! #endif
- !
- ! for (;;) {
- ! wdc->sc_status = status = inb(iobase+wd_status);
- ! if ((status & WDCS_BSY) == 0 && (status & mask) == mask)
- ! break;
- ! if (++timeout > WDCNDELAY)
- ! return -1;
- ! delay(WDCDELAY);
- ! }
- ! if (status & WDCS_ERR) {
- ! wdc->sc_error = inb(iobase+wd_error);
- ! return WDCS_ERR;
- ! }
- ! #ifdef WDCNDELAY_DEBUG
- ! /* After autoconfig, there should be no long delays. */
- ! if (!cold && timeout > WDCNDELAY_DEBUG)
- ! printf("%s: warning: busy-wait took %dus\n",
- ! wdc->sc_dev.dv_xname, WDCDELAY * timeout);
- ! #endif
- ! return 0;
- ! }
- !
- ! void
- ! wdctimeout(arg)
- ! void *arg;
- ! {
- ! struct wdc_softc *wdc = (struct wdc_softc *)arg;
- ! int s;
- !
- ! s = splbio();
- ! if ((wdc->sc_flags & WDCF_ACTIVE) != 0) {
- ! struct wd_softc *wd = wdc->sc_drives.tqh_first;
- ! struct buf *bp = wd->sc_q.b_actf;
- !
- ! wdc->sc_flags &= ~WDCF_ACTIVE;
- ! wderror(wdc, NULL, "lost interrupt");
- ! printf("%s: lost interrupt: %sing %d@%s:%d (%d)\n",
- ! wdc->sc_dev.dv_xname,
- ! (bp->b_flags & B_READ) ? "read" : "writ",
- ! wd->sc_nblks, wd->sc_dev.dv_xname, wd->sc_blkno, wd->sc_state);
- ! wdcunwedge(wdc);
- ! } else
- ! wderror(wdc, NULL, "missing untimeout");
- ! splx(s);
- ! }
- !
- ! void
- ! wderror(dev, bp, msg)
- ! void *dev;
- struct buf *bp;
- char *msg;
- {
- ! struct wd_softc *wd = dev;
- ! struct wdc_softc *wdc = dev;
-
- if (bp) {
- ! diskerr(bp, "wd", msg, LOG_PRINTF, wd->sc_skip / DEV_BSIZE,
- wd->sc_dk.dk_label);
- printf("\n");
- } else
- ! printf("%s: %s: status %b error %b\n", wdc->sc_dev.dv_xname,
- ! msg, wdc->sc_status, WDCS_BITS, wdc->sc_error, WDERR_BITS);
- }
- --- 811,857 ----
- {
- struct dkbad *bt = &wd->sc_dk.dk_cpulabel->bad;
- struct disklabel *lp = wd->sc_dk.dk_label;
- + struct wd_link *d_link = wd->d_link;
- int i = 0;
-
- + #ifdef WDDEBUG
- + printf("bad144intern\n");
- + #endif
- +
- for (; i < 126; i++) {
- if (bt->bt_bad[i].bt_cyl == 0xffff)
- break;
- ! d_link->sc_badsect[i] =
- bt->bt_bad[i].bt_cyl * lp->d_secpercyl +
- (bt->bt_bad[i].bt_trksec >> 8) * lp->d_nsectors +
- (bt->bt_bad[i].bt_trksec & 0xff);
- }
- for (; i < 127; i++)
- ! d_link->sc_badsect[i] = -1;
- }
-
- void
- ! wderror(d_link, bp, msg)
- ! struct wd_link *d_link;
- struct buf *bp;
- char *msg;
- {
- ! struct wd_softc *wd = (struct wd_softc *)d_link->wd_softc;
-
- if (bp) {
- ! diskerr(bp, "wd", msg, LOG_PRINTF, bp->b_bcount ,
- wd->sc_dk.dk_label);
- printf("\n");
- } else
- ! printf("%s: %s\n", wd->sc_dev.dv_xname,
- ! msg);
- ! }
- !
- ! void
- ! wddone(d_link, bp)
- ! struct wd_link *d_link;
- ! struct buf *bp;
- ! {
- ! struct wd_softc *wd = (void*)d_link->wd_softc;
- ! disk_unbusy(&wd->sc_dk, (bp->b_bcount - bp->b_resid));
- }
- diff -c -r -N --exclude exp --exclude compile sys/arch/arm32.orig/mainbus/wdc.c sys/arch/arm32/mainbus/wdc.c
- *** sys/arch/arm32.orig/mainbus/wdc.c Thu Jan 1 01:00:00 1970
- --- sys/arch/arm32/mainbus/wdc.c Thu Jun 13 02:57:04 1996
- ***************
- *** 0 ****
- --- 1,1747 ----
- + /* $NetBSD$ */
- +
- + /*
- + * Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved.
- + *
- + * DMA and multi-sector PIO handling are derived from code contributed by
- + * Onno van der Linden.
- + *
- + * Atapi support added by Manuel Bouyer.
- + *
- + * Redistribution and use in source and binary forms, with or without
- + * modification, are permitted provided that the following conditions
- + * are met:
- + * 1. Redistributions of source code must retain the above copyright
- + * notice, this list of conditions and the following disclaimer.
- + * 2. Redistributions in binary form must reproduce the above copyright
- + * notice, this list of conditions and the following disclaimer in the
- + * documentation and/or other materials provided with the distribution.
- + * 3. All advertising materials mentioning features or use of this software
- + * must display the following acknowledgement:
- + * This product includes software developed by Charles M. Hannum.
- + * 4. The name of the author may not be used to endorse or promote products
- + * derived from this software without specific prior written permission.
- + *
- + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- + */
- +
- + #undef ATAPI_DEBUG_WDC
- +
- + #include <sys/param.h>
- + #include <sys/systm.h>
- + #include <sys/kernel.h>
- + #include <sys/conf.h>
- + #include <sys/file.h>
- + #include <sys/stat.h>
- + #include <sys/ioctl.h>
- + #include <sys/buf.h>
- + #include <sys/uio.h>
- + #include <sys/malloc.h>
- + #include <sys/device.h>
- + #include <sys/disklabel.h>
- + #include <sys/disk.h>
- + #include <sys/syslog.h>
- + #include <sys/proc.h>
- +
- + #include <vm/vm.h>
- +
- + #include <machine/cpu.h>
- + #include <machine/irqhandler.h>
- + #include <machine/io.h>
- + #include <machine/katelib.h>
- +
- + #include <arm32/mainbus/mainbus.h>
- + #include <arm32/mainbus/wdreg.h>
- + #include <arm32/mainbus/wdlink.h>
- + #include <atapi/atapilink.h>
- +
- + extern int wdresethack;
- +
- + #define WAITTIME (10 * hz) /* time to wait for a completion */
- + /* this is a lot for hard drives, but not for cdroms */
- + #define RECOVERYTIME hz/2
- + #define WDCDELAY 100
- + #define WDCNDELAY 100000 /* delay = 100us; so 10s for a controller state change */
- + #if 0
- + /* If you enable this, it will report any delays more than 100us * N long. */
- + #define WDCNDELAY_DEBUG 50
- + #endif
- +
- + #define WDIORETRIES 5 /* number of retries before giving up */
- +
- + #define WDPART(dev) DISKPART(dev)
- +
- + LIST_HEAD(xfer_free_list, wdc_xfer) xfer_free_list;
- +
- + struct wdc_softc {
- + struct device sc_dev;
- + irqhandler_t sc_ih;
- + struct wd_link *d_link[2];
- + struct bus_link *ab_link;
- + struct wdc_link ctlr_link;
- + int sc_iobase; /* I/O port base */
- + int sc_drq; /* DMA channel */
- +
- + TAILQ_HEAD(xferhead, wdc_xfer) sc_xfer;
- + int sc_flags;
- + #define WDCF_ACTIVE 0x01 /* controller is active */
- + #define WDCF_SINGLE 0x02 /* sector at a time mode */
- + #define WDCF_ERROR 0x04 /* processing a disk error */
- + #define WDCF_WANTED 0x08 /* XXX locking for wd_get_parms() */
- + #define WDCF_IRQ_WAIT 0x10 /* controller is waiting for irq */
- + #define WDCF_ONESLAVE 0x20 /* ctrl. has one ATAPI slave attached */
- + int sc_errors; /* errors during current transfer */
- + u_char sc_status; /* copy of status register */
- + u_char sc_error; /* copy of error register */
- + };
- +
- + int wdcprobe __P((struct device *, void *, void *));
- + void wdcattach __P((struct device *, struct device *, void *));
- +
- + struct cfattach wdc_ca = {
- + sizeof(struct wdc_softc), wdcprobe, wdcattach
- + };
- +
- + struct cfdriver wdc_cd = {
- + NULL, "wdc", DV_DULL
- + };
- +
- +
- + int wdcintr __P((void *));
- + int wdc_ata_intr __P((struct wdc_softc *,struct wdc_xfer *));
- + void wdcstart __P((struct wdc_softc *));
- + void wdc_ata_start __P((struct wdc_softc *,struct wdc_xfer *));
- + void wdc_atapi_start __P((struct wdc_softc *,struct wdc_xfer *));
- + int wdcreset __P((struct wdc_softc *));
- + void wdcrestart __P((void *arg));
- + void wdcunwedge __P((struct wdc_softc *));
- + void wdctimeout __P((void *arg));
- + int wdcwait __P((struct wdc_softc *, int));
- + int wdccontrol __P((struct wd_link *));
- + void wdc_ata_done __P((struct wdc_softc *, struct wdc_xfer *));
- + void wdc_free_xfer __P((struct wdc_xfer *));
- + void wdcerror __P((struct wdc_softc*, char *));
- + int wdccommandshort __P((struct wdc_softc *, int, int));
- + void wdcbit_bucket __P(( struct wdc_softc *, int));
- + int wdc_atapi_intr __P((struct wdc_softc *, struct wdc_xfer *));
- + void wdc_atapi_done __P((struct wdc_softc *, struct wdc_xfer *));
- +
- + /* ST506 spec says that if READY or SEEKCMPLT go off, then the read or write
- + command is aborted. */
- + #define wait_for_drq(d) wdcwait(d, WDCS_DRDY | WDCS_DSC | WDCS_DRQ)
- + #define wait_for_unbusy(d) wdcwait(d, 0)
- + #define wait_for_ready(d) wdcwait(d, WDCS_DRDY | WDCS_DSC)
- + #define atapi_ready(d) wdcwait(d, WDCS_DRQ)
- +
- + #ifdef ATAPI_DEBUG
- + static int wdc_nxfer;
- + #endif
- +
- + int
- + wdcprobe(parent, match, aux)
- + struct device *parent;
- + void *match, *aux;
- + {
- + struct wdc_softc *wdc = match;
- + struct mainbus_attach_args *mb = aux;
- + int iobase;
- +
- + wdc->sc_iobase = iobase = mb->mb_iobase;
- +
- + /* Check if we have registers that work. */
- + outb(iobase+wd_error, 0x5a); /* Error register not writable, */
- + outb(iobase+wd_cyl_lo, 0xa5); /* but all of cyllo are. */
- + if (inb(iobase+wd_error) == 0x5a || inb(iobase+wd_cyl_lo) != 0xa5) {
- + /*
- + * Test for a controller with no IDE master, just one
- + * ATAPI device. Select drive 1, and try again.
- + */
- + outb(iobase+wd_sdh, WDSD_IBM | 0x10);
- + outb(iobase+wd_error, 0x5a);
- + outb(iobase+wd_cyl_lo, 0xa5);
- + if (inb(iobase+wd_error) == 0x5a || inb(iobase+wd_cyl_lo)
- + != 0xa5)
- + return 0;
- + wdc->sc_flags |= WDCF_ONESLAVE;
- + }
- +
- + if (wdcreset(wdc) != 0) {
- + delay(500000);
- + if (wdcreset(wdc) != 0)
- + return 0;
- + }
- +
- + /* Select drive 0 or ATAPI slave device */
- + if (wdc->sc_flags & WDCF_ONESLAVE)
- + outb(iobase+wd_sdh, WDSD_IBM | 0x10);
- + else
- + outb(iobase+wd_sdh, WDSD_IBM);
- +
- + /* Wait for controller to become ready. */
- + if (wait_for_unbusy(wdc) < 0)
- + return 0;
- +
- + /* Start drive diagnostics. */
- + outb(iobase+wd_command, WDCC_DIAGNOSE);
- +
- + /* Wait for command to complete. */
- + if (wait_for_unbusy(wdc) < 0)
- + return 0;
- +
- + mb->mb_iosize = 32;
- + return 1;
- + }
- +
- + int
- + wdprint(aux, wdc)
- + void *aux;
- + char *wdc;
- + {
- + struct wd_link *d_link = aux;
- +
- + if (!wdc)
- + printf(" drive %d", d_link->sc_drive);
- + return QUIET;
- + }
- +
- + void
- + wdcattach(parent, self, aux)
- + struct device *parent, *self;
- + void *aux;
- + {
- + struct wdc_softc *wdc = (void *)self;
- + struct mainbus_attach_args *mb = aux;
- + int drive;
- +
- + TAILQ_INIT(&wdc->sc_xfer);
- + wdc->sc_drq = mb->mb_drq;
- +
- + printf("\n");
- +
- + wdc->sc_ih.ih_func = wdcintr;
- + wdc->sc_ih.ih_arg = wdc;
- + wdc->sc_ih.ih_level = IPL_BIO;
- + wdc->sc_ih.ih_name = "wdc";
- +
- + if (irq_claim(mb->mb_irq, &wdc->sc_ih))
- + panic("Cannot claim IRQ %d for wdc%d\n", mb->mb_irq, parent->dv_unit);
- +
- + wdc->ctlr_link.flags = 0;
- + #ifdef ATAPI_DEBUG
- + wdc_nxfer = 0;
- + #endif
- +
- + for (drive = 0; drive < 2; drive++) {
- + wdc->sc_flags |= WDCF_ACTIVE; /* controller active while autoconf */
- + if (wdccommandshort(wdc, drive, WDCC_RECAL) != 0 ||
- + wait_for_ready(wdc) != 0) {
- + wdc->d_link[drive]=NULL;
- + wdc->sc_flags &= ~WDCF_ACTIVE;
- + }
- + else {
- + wdc->sc_flags &= ~WDCF_ACTIVE;
- + wdc->d_link[drive]=malloc(sizeof(struct wd_link), M_DEVBUF, M_NOWAIT);
- + bzero(wdc->d_link[drive],sizeof(struct wd_link));
- + wdc->d_link[drive]->type = DRIVE;
- + wdc->d_link[drive]->wdc_softc =(caddr_t) wdc;
- + wdc->d_link[drive]->ctlr_link = &(wdc->ctlr_link);
- + wdc->d_link[drive]->sc_drive = drive;
- + if (wdc->sc_drq != DRQUNK)
- + wdc->d_link[drive]->sc_mode = WDM_DMA;
- + else wdc->d_link[drive]->sc_mode = 0;
- +
- + (void)config_found(self, (void *)wdc->d_link[drive], wdprint);
- + }
- + }
- +
- + wdc->ab_link = malloc(sizeof(struct bus_link), M_DEVBUF, M_NOWAIT);
- + bzero(wdc->ab_link,sizeof(struct bus_link));
- + wdc->ab_link->type = BUS;
- + wdc->ab_link->wdc_softc = (caddr_t) wdc;
- + wdc->ab_link->ctlr_link = &(wdc->ctlr_link);
- + wdc->ab_link->ctrl = self->dv_unit;
- + (void)config_found(self, (void *)wdc->ab_link, NULL);
- + }
- +
- + /*
- + * Start I/O on a controller. This does the calculation, and starts a read or
- + * write operation. Called to from wdstart() to start a transfer, from
- + * wdcintr() to continue a multi-sector transfer or start the next transfer, or
- + * wdcrestart() after recovering from an error.
- + */
- + void
- + wdcstart(wdc)
- + struct wdc_softc *wdc;
- + {
- + struct wdc_xfer *xfer;
- +
- +
- + if ((wdc->sc_flags & WDCF_ACTIVE) != 0 ) {
- + #ifdef WDDEBUG
- + printf("wdcstart: already active\n");
- + #endif
- + return; /* controller aleady active */
- + }
- + #ifdef DIAGNOSTIC
- + if ((wdc->sc_flags & WDCF_IRQ_WAIT) != 0)
- + panic("wdcstart: controller waiting for irq\n");
- + #endif
- + /*
- + * XXX
- + * This is a kluge. See comments in wd_get_parms().
- + */
- + if ((wdc->sc_flags & WDCF_WANTED) != 0) {
- + #ifdef ATAPI_DEBUG_WDC
- + printf("WDCF_WANTED\n");
- + #endif
- + wdc->sc_flags &= ~WDCF_WANTED;
- + wakeup(wdc);
- + return;
- + }
- + /* is there a xfer ? */
- + xfer = wdc->sc_xfer.tqh_first;
- + if (xfer == NULL) {
- + #ifdef ATAPI_DEBUG2
- + printf("wdcstart: null xfer\n");
- + #endif
- + return;
- + }
- + wdc->sc_flags |= WDCF_ACTIVE;
- + if (xfer->c_flags & C_ATAPI) {
- + #ifdef ATAPI_DEBUG_WDC
- + printf("wdcstart: atapi\n");
- + #endif
- + wdc_atapi_start(wdc,xfer);
- + } else {
- + wdc_ata_start(wdc,xfer);
- + }
- + }
- +
- +
- + void wdc_ata_start(wdc, xfer)
- + struct wdc_softc *wdc;
- + struct wdc_xfer *xfer;
- + {
- + struct wd_link *d_link;
- + struct buf *bp = xfer->c_bp;
- + int nblks;
- +
- + d_link=xfer->d_link;
- +
- + /*loop:*/
- +
- + if (wdc->sc_errors >= WDIORETRIES) {
- + wderror(d_link, bp, "hard error");
- + xfer->c_flags |= C_ERROR;
- + wdc_ata_done(wdc, xfer);
- + return;
- + }
- +
- + /* Do control operations specially. */
- + if (d_link->sc_state < OPEN) {
- + /*
- + * Actually, we want to be careful not to mess with the control
- + * state if the device is currently busy, but we can assume
- + * that we never get to this point if that's the case.
- + */
- + if (wdccontrol(d_link) == 0) {
- + /* The drive is busy. Wait. */
- + return;
- + }
- + }
- +
- + /*
- + * WDCF_ERROR is set by wdcunwedge() and wdcintr() when an error is
- + * encountered. If we are in multi-sector mode, then we switch to
- + * single-sector mode and retry the operation from the start.
- + */
- + if (wdc->sc_flags & WDCF_ERROR) {
- + wdc->sc_flags &= ~WDCF_ERROR;
- + if ((wdc->sc_flags & WDCF_SINGLE) == 0) {
- + wdc->sc_flags |= WDCF_SINGLE;
- + xfer->c_skip = 0;
- + }
- + }
- +
- +
- + /* When starting a transfer... */
- + if (xfer->c_skip == 0) {
- + daddr_t blkno;
- +
- + #ifdef WDDEBUG
- + printf("\n%s: wdc_ata_start %s %d@%d; map ", wdc->sc_dev.dv_xname,
- + (xfer->c_flags & B_READ) ? "read" : "write", xfer->c_bcount,
- + xfer->c_blkno);
- + #endif
- + blkno = xfer->c_blkno+xfer->c_p_offset;
- + xfer->c_blkno = blkno / (d_link->sc_lp->d_secsize / DEV_BSIZE);
- + } else {
- + #ifdef WDDEBUG
- + printf(" %d)%x", xfer->c_skip, inb(wdc->sc_iobase+wd_altsts));
- + #endif
- + }
- +
- + /* When starting a multi-sector transfer, or doing single-sector
- + transfers... */
- + if (xfer->c_skip == 0 || (wdc->sc_flags & WDCF_SINGLE) != 0 ||
- + d_link->sc_mode == WDM_DMA) {
- + daddr_t blkno = xfer->c_blkno;
- + long cylin, head, sector;
- + int command;
- +
- + if ((wdc->sc_flags & WDCF_SINGLE) != 0)
- + nblks = 1;
- + else if (d_link->sc_mode != WDM_DMA)
- + nblks = xfer->c_bcount / d_link->sc_lp->d_secsize;
- + else
- + nblks = min(xfer->c_bcount / d_link->sc_lp->d_secsize, 8);
- +
- + /* Check for bad sectors and adjust transfer, if necessary. */
- + if ((d_link->sc_lp->d_flags & D_BADSECT) != 0
- + #ifdef B_FORMAT
- + && (bp->b_flags & B_FORMAT) == 0
- + #endif
- + ) {
- + long blkdiff;
- + int i;
- +
- + for (i = 0; (blkdiff = d_link->sc_badsect[i]) != -1; i++) {
- + blkdiff -= blkno;
- + if (blkdiff < 0)
- + continue;
- + if (blkdiff == 0) {
- + /* Replace current block of transfer. */
- + blkno =
- + d_link->sc_lp->d_secperunit -
- + d_link->sc_lp->d_nsectors - i - 1;
- + }
- + if (blkdiff < nblks) {
- + /* Bad block inside transfer. */
- + wdc->sc_flags |= WDCF_SINGLE;
- + nblks = 1;
- + }
- + break;
- + }
- + /* Tranfer is okay now. */
- + }
- +
- + if ((d_link->sc_params.wdp_capabilities & WD_CAP_LBA) != 0) {
- + sector = (blkno >> 0) & 0xff;
- + cylin = (blkno >> 8) & 0xffff;
- + head = (blkno >> 24) & 0xf;
- + head |= WDSD_LBA;
- + } else {
- + sector = blkno % d_link->sc_lp->d_nsectors;
- + sector++; /* Sectors begin with 1, not 0. */
- + blkno /= d_link->sc_lp->d_nsectors;
- + head = blkno % d_link->sc_lp->d_ntracks;
- + blkno /= d_link->sc_lp->d_ntracks;
- + cylin = blkno;
- + head |= WDSD_CHS;
- + }
- +
- + if (d_link->sc_mode == WDM_PIOSINGLE ||
- + (wdc->sc_flags & WDCF_SINGLE) != 0)
- + xfer->c_nblks = 1;
- + else if (d_link->sc_mode == WDM_PIOMULTI)
- + xfer->c_nblks = min(nblks, d_link->sc_multiple);
- + else
- + xfer->c_nblks = nblks;
- + xfer->c_nbytes = xfer->c_nblks * d_link->sc_lp->d_secsize;
- +
- + #ifdef B_FORMAT
- + if (bp->b_flags & B_FORMAT) {
- + sector = d_link->sc_lp->d_gap3;
- + nblks = d_link->sc_lp->d_nsectors;
- + command = WDCC_FORMAT;
- + } else
- + #endif
- + switch (d_link->sc_mode) {
- + case WDM_DMA:
- + panic("wdc: Cannot do DMA\n");
- + #if 0
- + command = (xfer->c_flags & B_READ) ?
- + WDCC_READDMA : WDCC_WRITEDMA;
- + /* Start the DMA channel and bounce the buffer if
- + necessary. */
- + isa_dmastart(xfer->c_flags & B_READ ? DMAMODE_READ : DMAMODE_WRITE,
- + xfer->databuf + xfer->c_skip,
- + xfer->c_nbytes, wdc->sc_drq);
- + break;
- + #endif
- + case WDM_PIOMULTI:
- + command = (xfer->c_flags & B_READ) ?
- + WDCC_READMULTI : WDCC_WRITEMULTI;
- + break;
- + case WDM_PIOSINGLE:
- + command = (xfer->c_flags & B_READ) ?
- + WDCC_READ : WDCC_WRITE;
- + break;
- + default:
- + #ifdef DIAGNOSTIC
- + panic("bad wd mode");
- + #endif
- + return;
- + }
- +
- + /* Initiate command! */
- + if (wdccommand(d_link, command, d_link->sc_drive, cylin, head, sector, nblks) != 0) {
- + wderror(d_link, NULL,
- + "wdc_ata_start: timeout waiting for unbusy");
- + wdcunwedge(wdc);
- + return;
- + }
- +
- + #ifdef WDDEBUG
- + printf("sector %d cylin %d head %d addr %x sts %x\n", sector,
- + cylin, head, xfer->databuf, 0/*inb(wdc->sc_iobase+wd_altsts)*/);
- + #endif
- + } else if (xfer->c_nblks > 1) {
- + /* The number of blocks in the last stretch may be smaller. */
- + nblks = xfer->c_bcount / d_link->sc_lp->d_secsize;
- + if (xfer->c_nblks > nblks) {
- + xfer->c_nblks = nblks;
- + xfer->c_nbytes = xfer->c_bcount;
- + }
- + }
- +
- + /* If this was a write and not using DMA, push the data. */
- + if (d_link->sc_mode != WDM_DMA &&
- + (xfer->c_flags & (B_READ|B_WRITE)) == B_WRITE) {
- + if (wait_for_drq(wdc) < 0) {
- + wderror(d_link, NULL, "wdc_ata_start: timeout waiting for drq");
- + wdcunwedge(wdc);
- + return;
- + }
- +
- + /* Push out data. */
- + if ((d_link->sc_flags & WDF_32BIT) == 0)
- + outsw(wdc->sc_iobase+wd_data, xfer->databuf + xfer->c_skip,
- + xfer->c_nbytes >> 1);
- + else
- + outsl(wdc->sc_iobase+wd_data, xfer->databuf + xfer->c_skip,
- + xfer->c_nbytes >> 2);
- + }
- +
- + wdc->sc_flags |= WDCF_IRQ_WAIT;
- + #ifdef WDDEBUG
- + printf("wdc_ata_start: timeout ");
- + #endif
- + timeout(wdctimeout, wdc, WAITTIME);
- + #ifdef WDDEBUG
- + printf("done\n");
- + #endif
- + }
- +
- + void
- + wdc_atapi_start (wdc, xfer)
- + struct wdc_softc *wdc;
- + struct wdc_xfer *xfer;
- + {
- + struct atapi_command_packet *acp = xfer->atapi_cmd;
- + #ifdef ATAPI_DEBUG_WDC
- + printf("wdc_atapi_start, acp flags %lx\n",acp->flags);
- + #endif
- + if (wdc->sc_errors >= WDIORETRIES) {
- + acp->status |= ERROR;
- + acp->error = inb (wdc->sc_iobase + wd_error);
- + wdc_atapi_done(wdc, xfer);
- + return;
- + }
- + if (wait_for_unbusy (wdc) != 0)
- + if (!(wdc->sc_status & WDCS_ERR)) {
- + printf ("wdc_atapi_start: not ready, st = %02x\n",wdc->sc_status);
- + acp->status = ERROR;
- + return;
- + }
- +
- + if (wdccommand ((struct wd_link*)xfer->d_link, ATAPI_PACKET_COMMAND,
- + acp->drive, acp->data_size, 0, 0, 0) != 0) {
- + printf("wdc_atapi_start: can't send atapi paket command\n");
- + acp->status = ERROR;
- + wdc->sc_flags |= WDCF_IRQ_WAIT;
- + return;
- + }
- + if ((acp->flags & 0x0300) != ACAP_DRQ_INTR) {
- + int i, phase;
- + for (i=20000; i>0; --i) {
- + phase = (inb(wdc->sc_iobase + wd_ireason) & (WDCI_CMD | WDCI_IN)) |
- + (inb(wdc->sc_iobase + wd_status) & WDCS_DRQ);
- + if (phase == PHASE_CMDOUT)
- + break;
- + delay(10);
- + }
- + if (phase != PHASE_CMDOUT ) {
- + printf("wdc_atapi_start: timout waiting PHASE_CMDOUT");
- + acp->status = ERROR;
- + wdc_atapi_done(wdc, xfer);
- + return;
- + }
- + outsw (wdc->sc_iobase + wd_data, acp->command,
- + acp->command_size/ sizeof (short));
- + }
- + wdc->sc_flags |= WDCF_IRQ_WAIT;
- +
- +
- + #ifdef ATAPI_DEBUG2
- + printf("wdc_atapi_start: timeout\n");
- + #endif
- + timeout(wdctimeout, wdc, WAITTIME);
- + return;
- + }
- +
- +
- + /*
- + * Interrupt routine for the controller. Acknowledge the interrupt, check for
- + * errors on the current operation, mark it done if necessary, and start the
- + * next request. Also check for a partially done transfer, and continue with
- + * the next chunk if so.
- + */
- + int
- + wdcintr(arg)
- + void *arg;
- + {
- + struct wdc_softc *wdc = arg;
- + struct wdc_xfer *xfer;
- +
- + if ((wdc->sc_flags & WDCF_IRQ_WAIT) == 0) {
- + /* Clear the pending interrupt and abort. */
- + u_char s = inb(wdc->sc_iobase+wd_status);
- + u_char e = inb(wdc->sc_iobase+wd_error);
- + u_char i = inb(wdc->sc_iobase+wd_seccnt);
- + #ifdef ATAPI_DEBUG_WDC
- + printf ("wdcintr: inactive controller, punting st=%02x er=%02x irr=%02x\n", s, e, i);
- + #endif /* ATAPI_DEBUG */
- + if (s & WDCS_DRQ) {
- + int len = inb (wdc->sc_iobase + wd_cyl_lo) +
- + 256 * inb (wdc->sc_iobase + wd_cyl_hi);
- + #ifdef ATAPI_DEBUG_WDC
- + printf ("wdcintr: clearing up %d bytes\n", len);
- + #endif /* ATAPI_DEBUG */
- + wdcbit_bucket (wdc, len);
- + }
- + return 0;
- + }
- +
- + #ifdef WDDEBUG
- + printf("wdcintr\n");
- + #endif
- + wdc->sc_flags &= ~WDCF_IRQ_WAIT;
- + xfer = wdc->sc_xfer.tqh_first;
- + if (xfer->c_flags & C_ATAPI) {
- + (void) wdc_atapi_intr(wdc,xfer);
- + return 0;
- + } else {
- + return wdc_ata_intr(wdc,xfer);
- + }
- + }
- +
- +
- + int
- + wdc_ata_intr(wdc,xfer)
- + struct wdc_softc *wdc;
- + struct wdc_xfer *xfer;
- + {
- + struct wd_link *d_link;
- +
- + d_link = xfer->d_link;
- +
- + if (wait_for_unbusy(wdc) < 0) {
- + wdcerror(wdc, "wdcintr: timeout waiting for unbusy");
- + wdc->sc_status |= WDCS_ERR; /* XXX */
- + }
- +
- + untimeout(wdctimeout, wdc);
- +
- + /* Is it not a transfer, but a control operation? */
- + if (d_link->sc_state < OPEN) {
- + if (wdccontrol(d_link) == 0) {
- + /* The drive is busy. Wait. */
- + return 1;
- + }
- + #ifdef WDDEBUG
- + printf("wdc_ata_start from wdc_ata_intr(open) flags %d\n",
- + dc->sc_flags);
- + #endif
- + wdc_ata_start(wdc,xfer);
- + return 1;
- + }
- +
- + /* Turn off the DMA channel and unbounce the buffer. */
- + if (d_link->sc_mode == WDM_DMA)
- + panic("wdc: Cannot do DMA\n");
- + #if 0
- + isa_dmadone(xfer->c_flags & B_READ ? DMAMODE_READ : DMAMODE_WRITE,
- + xfer->databuf + xfer->c_skip, xfer->c_nbytes, wdc->sc_drq);
- + #endif
- +
- + /* Have we an error? */
- + if (wdc->sc_status & WDCS_ERR) {
- + #ifdef WDDEBUG
- + wderror(d_link, NULL, "wdc_ata_start");
- + #endif
- + if ((wdc->sc_flags & WDCF_SINGLE) == 0) {
- + wdc->sc_flags |= WDCF_ERROR;
- + goto restart;
- + }
- +
- + #ifdef B_FORMAT
- + if (bp->b_flags & B_FORMAT)
- + goto bad;
- + #endif
- +
- + if (++wdc->sc_errors < WDIORETRIES)
- + goto restart;
- +
- + wderror(d_link, xfer->c_bp, "hard error");
- + #ifdef B_FORMAT
- + bad:
- + #endif
- + xfer->c_flags |= C_ERROR;
- + goto done;
- + }
- +
- + /* If this was a read and not using DMA, fetch the data. */
- + if (d_link->sc_mode != WDM_DMA &&
- + (xfer->c_flags & (B_READ|B_WRITE)) == B_READ) {
- + if ((wdc->sc_status & (WDCS_DRDY | WDCS_DSC | WDCS_DRQ))
- + != (WDCS_DRDY | WDCS_DSC | WDCS_DRQ)) {
- + wderror(d_link, NULL, "wdcintr: read intr before drq");
- + wdcunwedge(wdc);
- + return 1;
- + }
- +
- + /* Pull in data. */
- + if ((d_link->sc_flags & WDF_32BIT) == 0)
- + insw(wdc->sc_iobase+wd_data, xfer->databuf + xfer->c_skip,
- + xfer->c_nbytes >> 1);
- + else
- + insl(wdc->sc_iobase+wd_data, xfer->databuf + xfer->c_skip,
- + xfer->c_nbytes >> 2);
- + }
- +
- + /* If we encountered any abnormalities, flag it as a soft error. */
- + if (wdc->sc_errors > 0 ||
- + (wdc->sc_status & WDCS_CORR) != 0) {
- + wderror(d_link, xfer->c_bp, "soft error (corrected)");
- + wdc->sc_errors = 0;
- + }
- +
- + /* Adjust pointers for the next block, if any. */
- + xfer->c_blkno += xfer->c_nblks;
- + xfer->c_skip += xfer->c_nbytes;
- + xfer->c_bcount -= xfer->c_nbytes;
- +
- + /* See if this transfer is complete. */
- + if (xfer->c_bcount > 0)
- + goto restart;
- +
- + done:
- + /* Done with this transfer, with or without error. */
- + wdc_ata_done(wdc, xfer);
- + return 0;
- +
- + restart:
- + /* Start the next operation */
- + #ifdef WDDEBUG
- + printf("wdc_ata_start from wdcintr flags %d\n",wdc->sc_flags);
- + #endif
- + wdc_ata_start(wdc, xfer);
- +
- + return 1;
- + }
- +
- + int
- + wdcreset(wdc)
- + struct wdc_softc *wdc;
- + {
- + int iobase = wdc->sc_iobase;
- +
- + /* Reset the device. */
- + if (wdresethack) {
- + outb(iobase+wd_ctlr, WDCTL_RST | WDCTL_IDS);
- + delay(1000);
- + outb(iobase+wd_ctlr, WDCTL_IDS);
- + delay(1000);
- + (void) inb(iobase+wd_error);
- + outb(iobase+wd_ctlr, WDCTL_4BIT);
- + }
- +
- + if (wait_for_unbusy(wdc) < 0) {
- + printf("%s: reset failed\n", wdc->sc_dev.dv_xname);
- + return 1;
- + }
- +
- + return 0;
- + }
- +
- + void
- + wdcrestart(arg)
- + void *arg;
- + {
- + struct wdc_softc *wdc = arg;
- + int s;
- +
- + s = splbio();
- + wdcstart(wdc);
- + splx(s);
- + }
- +
- + /*
- + * Unwedge the controller after an unexpected error. We do this by resetting
- + * it, marking all drives for recalibration, and stalling the queue for a short
- + * period to give the reset time to finish.
- + * NOTE: We use a timeout here, so this routine must not be called during
- + * autoconfig or dump.
- + */
- + void
- + wdcunwedge(wdc)
- + struct wdc_softc *wdc;
- + {
- + int unit;
- + #ifdef ATAPI_DEBUG
- + printf("wdcunwedge\n");
- + #endif
- + untimeout(wdctimeout, wdc);
- + wdc->sc_flags &= ~WDCF_IRQ_WAIT;
- + (void) wdcreset(wdc);
- +
- + /* Schedule recalibrate for all drives on this controller. */
- + for (unit = 0; unit < 2; unit++) {
- + if (!wdc->d_link[unit]) continue;
- + if (wdc->d_link[unit]->sc_state > RECAL)
- + wdc->d_link[unit]->sc_state = RECAL;
- + }
- +
- + wdc->sc_flags |= WDCF_ERROR;
- + ++wdc->sc_errors;
- +
- + /* Wake up in a little bit and restart the operation. */
- + #ifdef WDDEBUG
- + printf("wdcrestart from wdcunwedge\n");
- + #endif
- + wdc->sc_flags &= ~WDCF_ACTIVE;
- + timeout(wdcrestart, wdc, RECOVERYTIME);
- + }
- +
- + int
- + wdcwait(wdc, mask)
- + struct wdc_softc *wdc;
- + int mask;
- + {
- + int iobase = wdc->sc_iobase;
- + int timeout = 0;
- + u_char status;
- + #ifdef WDCNDELAY_DEBUG
- + extern int cold;
- + #endif
- + #ifdef WDDEBUG
- + printf("wdcwait\n");
- + #endif
- +
- + for (;;) {
- + wdc->sc_status = status = inb(iobase+wd_status);
- + /*
- + * XXX
- + * If a single slave ATAPI device is attached, it may
- + * have released the bus. Select it and try again.
- + */
- + if (status == 0xff && wdc->sc_flags & WDCF_ONESLAVE) {
- + outb(iobase+wd_sdh, WDSD_IBM | 0x10);
- + wdc->sc_status = status = inb(iobase+wd_status);
- + }
- + if ((status & WDCS_BSY) == 0 && (status & mask) == mask)
- + break;
- + if (++timeout > WDCNDELAY) {
- + #ifdef ATAPI_DEBUG2
- + printf("wdcwait: timeout, status %x\n", status);
- + #endif
- + return -1;
- + }
- + delay(WDCDELAY);
- + }
- + if (status & WDCS_ERR) {
- + wdc->sc_error = inb(iobase+wd_error);
- + return WDCS_ERR;
- + }
- + #ifdef WDCNDELAY_DEBUG
- + /* After autoconfig, there should be no long delays. */
- + if (!cold && timeout > WDCNDELAY_DEBUG) {
- + struct wdc_xfer *xfer = wdc->sc_xfer.tqh_first;
- + if (xfer == NULL)
- + printf("%s: warning: busy-wait took %dus\n",
- + wdc->sc_dev.dv_xname, WDCDELAY * timeout);
- + else
- + printf("%s(%s): warning: busy-wait took %dus\n",
- + wdc->sc_dev.dv_xname,
- + ((struct device*)xfer->d_link->wd_softc)->dv_xname,
- + WDCDELAY * timeout);
- + }
- + #endif
- + return 0;
- + }
- +
- + void
- + wdctimeout(arg)
- + void *arg;
- + {
- + struct wdc_softc *wdc = (struct wdc_softc *)arg;
- + int s;
- + #ifdef WDDEBUG
- + printf("wdctimeout\n");
- + #endif
- +
- + s = splbio();
- + if ((wdc->sc_flags & WDCF_IRQ_WAIT) != 0) {
- + wdc->sc_flags &= ~WDCF_IRQ_WAIT;
- + wdcerror(wdc, "lost interrupt");
- + wdcunwedge(wdc);
- + } else
- + wdcerror(wdc, "missing untimeout");
- + splx(s);
- + }
- +
- + /*
- + * Wait for the drive to become ready and send a command.
- + * Return -1 if busy for too long or 0 otherwise.
- + * Assumes interrupts are blocked.
- + */
- + int
- + wdccommand(d_link, command, drive, cylin, head, sector, count)
- + struct wd_link *d_link;
- + int command;
- + int drive, cylin, head, sector, count;
- + {
- + struct wdc_softc *wdc = (void*)d_link->wdc_softc;
- + int iobase = wdc->sc_iobase;
- + int stat;
- + #ifdef WDDEBUG
- + printf("wdccommand drive %d\n",drive);
- + #endif
- + #if defined(DIAGNOSTIC) && defined(WDCDEBUG)
- + if ((wdc->sc_flags & WDCF_ACTIVE) == 0 )
- + printf("wdccommand: controler not active (drive %d)\n", drive);
- + #endif
- +
- + /* Select drive, head, and addressing mode. */
- + outb(iobase+wd_sdh, WDSD_IBM | (drive << 4) | head);
- +
- + /* Wait for it to become ready to accept a command. */
- + if (command == WDCC_IDP || d_link->type == BUS)
- + stat = wait_for_unbusy(wdc);
- + else
- + stat = wdcwait(wdc, WDCS_DRDY);
- + if (stat < 0) {
- + #ifdef ATAPI_DEBUG
- + printf("wdcommand:xfer failed (wait_for_unbusy) status %d\n",stat);
- + #endif
- + return -1;
- + }
- +
- + /* Load parameters. */
- + if (d_link->type == DRIVE && d_link->sc_lp->d_type == DTYPE_ST506)
- + outb(iobase+wd_precomp, d_link->sc_lp->d_precompcyl / 4);
- + else
- + outb(iobase+wd_features, 0);
- + outb(iobase+wd_cyl_lo, cylin);
- + outb(iobase+wd_cyl_hi, cylin >> 8);
- + outb(iobase+wd_sector, sector);
- + outb(iobase+wd_seccnt, count);
- +
- + /* Send command. */
- + outb(iobase+wd_command, command);
- +
- + return 0;
- + }
- +
- + /*
- + * Simplified version of wdccommand().
- + */
- + int
- + wdccommandshort(wdc, drive, command)
- + struct wdc_softc *wdc;
- + int drive;
- + int command;
- + {
- + int iobase = wdc->sc_iobase;
- + #ifdef WDDEBUG
- + printf("wdccommandshort\n");
- + #endif
- + #if defined(DIAGNOSTIC) && defined(WDCDEBUG)
- + if ((wdc->sc_flags & WDCF_ACTIVE) == 0 )
- + printf("wdccommandshort: controler not active (drive %d)\n", drive);
- + #endif
- +
- + /* Select drive. */
- + outb(iobase+wd_sdh, WDSD_IBM | (drive << 4));
- +
- + if (wdcwait(wdc, WDCS_DRDY) < 0)
- + return -1;
- +
- + outb(iobase+wd_command, command);
- +
- + return 0;
- + }
- +
- + #ifndef __BDEVSW_DUMP_OLD_TYPE
- + /* #define WD_DUMP_NOT_TRUSTED*/ /* if you just want to watch */
- + static int wddumprecalibrated;
- +
- + int
- + wdcdump(d_link, blkno, nblks, va)
- + struct wd_link *d_link;
- + daddr_t blkno;
- + int nblks;
- + caddr_t va;
- + {
- + struct wdc_softc *wdc = (void*)d_link->wdc_softc;
- + struct disklabel *lp = d_link->sc_lp;
- + /* Recalibrate, if first dump transfer. */
- + wdc->sc_flags |= WDCF_ACTIVE;
- + if (wddumprecalibrated == 0) {
- + if (wdccommandshort(wdc, d_link->sc_drive, WDCC_RECAL) != 0 ||
- + wait_for_ready(wdc) != 0 ||
- + wdsetctlr(d_link) != 0 || wait_for_ready(wdc) != 0) {
- + wdcerror(wdc, "wdcdump: recal failed");
- + return EIO;
- + }
- + }
- + while (nblks > 0) {
- + daddr_t xlt_blkno = blkno;
- + long cylin, head, sector;
- +
- + if ((lp->d_flags & D_BADSECT) != 0) {
- + long blkdiff;
- + int i;
- +
- + for (i = 0; (blkdiff = d_link->sc_badsect[i]) != -1; i++) {
- + blkdiff -= xlt_blkno;
- + if (blkdiff < 0)
- + continue;
- + if (blkdiff == 0) {
- + /* Replace current block of transfer. */
- + xlt_blkno = lp->d_secperunit -
- + lp->d_nsectors - i - 1;
- + }
- + break;
- + }
- + /* Tranfer is okay now. */
- + }
- +
- + if ((d_link->sc_params.wdp_capabilities & WD_CAP_LBA) != 0) {
- + sector = (xlt_blkno >> 0) & 0xff;
- + cylin = (xlt_blkno >> 8) & 0xffff;
- + head = (xlt_blkno >> 24) & 0xf;
- + head |= WDSD_LBA;
- + } else {
- + sector = xlt_blkno % lp->d_nsectors;
- + sector++; /* Sectors begin with 1, not 0. */
- + xlt_blkno /= lp->d_nsectors;
- + head = xlt_blkno % lp->d_ntracks;
- + xlt_blkno /= lp->d_ntracks;
- + cylin = xlt_blkno;
- + head |= WDSD_CHS;
- + }
- + #ifndef WD_DUMP_NOT_TRUSTED
- +
- + if (wdccommand(d_link, WDCC_WRITE, d_link->sc_drive, cylin, head, sector, 1) != 0 ||
- + wait_for_drq(wdc) != 0) {
- + wdcerror(wdc, "wddump: write failed");
- + return EIO;
- + }
- +
- + outsw(wdc->sc_iobase+wd_data, va, lp->d_secsize >> 1);
- +
- + /* Check data request (should be done). */
- + if (wait_for_ready(wdc) != 0) {
- + wdcerror(wdc, "wddump: timeout waiting for ready");
- + return EIO;
- + }
- + #else /* WD_DUMP_NOT_TRUSTED */
- + /* Let's just talk about this first... */
- + printf("wd%d: dump addr 0x%x, cylin %d, head %d, sector %d\n",
- + d_link->sc_drive, va, cylin, head, sector);
- + delay(500 * 1000); /* half a second */
- + #endif
- + /* update block count */
- + nblks -= 1;
- + blkno += 1;
- + va += lp->d_secsize;
- + }
- + wdc->sc_flags &= ~WDCF_ACTIVE;
- + return 0;
- + }
- + #endif
- +
- + void wdc_ata_done(wdc, xfer)
- + struct wdc_softc *wdc;
- + struct wdc_xfer *xfer;
- + {
- + int s;
- + struct buf *bp = xfer->c_bp;
- + struct wd_link *d_link = xfer->d_link;
- + #ifdef WDDEBUG
- + printf("wdc_ata_done\n");
- + #endif
- + /* remove this command from xfer queue */
- + s = splbio();
- + TAILQ_REMOVE(&wdc->sc_xfer, xfer, c_xferchain);
- + wdc->sc_flags &= ~(WDCF_SINGLE | WDCF_ERROR | WDCF_ACTIVE);
- + wdc->sc_errors = 0;
- + if (bp) {
- + if (xfer->c_flags & C_ERROR) {
- + bp->b_flags |= B_ERROR;
- + bp->b_error = EIO;
- + }
- + bp->b_resid = xfer->c_bcount;
- + wddone(d_link, bp);
- + biodone(bp);
- + } else {
- + wakeup(xfer->databuf);
- + }
- + xfer->c_skip = 0;
- + wdc_free_xfer(xfer);
- + d_link->openings++;
- + wdstart((void*)d_link->wd_softc);
- + #ifdef WDDEBUG
- + printf("wdcstart from wdc_ata_done, flags %d\n",wdc->sc_flags);
- + #endif
- + wdcstart(wdc);
- + splx(s);
- + }
- +
- + void wdc_exec_xfer(d_link, xfer)
- + struct wd_link *d_link;
- + struct wdc_xfer *xfer;
- + {
- + struct wdc_softc *wdc=(struct wdc_softc *)d_link->wdc_softc;
- + int s;
- +
- + #ifdef WDDEBUG
- + printf("wdc_exec_xfer\n");
- + #endif
- + s = splbio();
- + /* insert at the end of command list */
- + TAILQ_INSERT_TAIL(&wdc->sc_xfer,xfer , c_xferchain)
- + #ifdef WDDEBUG
- + printf("wdcstart from wdc_exec_xfer, flags %d\n",wdc->sc_flags);
- + #endif
- + wdcstart(wdc);
- + splx(s);
- + }
- +
- + struct wdc_xfer *
- + wdc_get_xfer(c_link,flags)
- + struct wdc_link *c_link;
- + int flags;
- + {
- + struct wdc_xfer *xfer;
- + int s;
- +
- + s = splbio();
- + if (xfer = xfer_free_list.lh_first) {
- + LIST_REMOVE(xfer, free_list);
- + splx(s);
- + #ifdef DIAGNOSTIC
- + if ((xfer->c_flags & C_INUSE) != 0) panic("xfer already in use\n");
- + #endif
- + } else {
- + splx(s);
- + #ifdef ATAPI_DEBUG
- + printf("wdc:making xfer %d\n",wdc_nxfer);
- + #endif
- + xfer = malloc(sizeof(*xfer), M_DEVBUF,
- + ((flags & IDE_NOSLEEP) != 0 ? M_NOWAIT : M_WAITOK));
- + if (!xfer) {
- + return 0;
- + }
- + #ifdef DIAGNOSTIC
- + xfer->c_flags &= ~C_INUSE;
- + #endif
- + #ifdef ATAPI_DEBUG
- + wdc_nxfer++;
- + #endif
- + }
- + #ifdef DIAGNOSTIC
- + if ((xfer->c_flags & C_INUSE) != 0) panic("xfer already in use\n");
- + #endif
- + bzero(xfer,sizeof(struct wdc_xfer));
- + xfer->c_flags = C_INUSE;
- + xfer->c_link = c_link;
- + return xfer;
- + }
- +
- + void
- + wdc_free_xfer(xfer)
- + struct wdc_xfer *xfer;
- + {
- + int s;
- +
- + s = splbio();
- + xfer->c_flags &= ~C_INUSE;
- + LIST_INSERT_HEAD(&xfer_free_list, xfer, free_list);
- + splx(s);
- + }
- +
- + /*
- + * Implement operations needed before read/write.
- + * Returns 0 if operation still in progress, 1 if completed.
- + */
- + int
- + wdccontrol(d_link)
- + struct wd_link *d_link;
- + {
- + struct wdc_softc *wdc = (void *)d_link->wdc_softc;
- + #ifdef WDDEBUG
- + printf("wdccontrol\n");
- + #endif
- +
- + switch (d_link->sc_state) {
- + case RECAL: /* Set SDH, step rate, do recal. */
- + if (wdccommandshort(wdc, d_link->sc_drive, WDCC_RECAL) != 0) {
- + wderror(d_link, NULL, "wdccontrol: recal failed (1)");
- + goto bad;
- + }
- + d_link->sc_state = RECAL_WAIT;
- + break;
- +
- +
- + case RECAL_WAIT:
- + if (wdc->sc_status & WDCS_ERR) {
- + wderror(d_link, NULL, "wdccontrol: recal failed (2)");
- + goto bad;
- + }
- + /* fall through */
- + case GEOMETRY:
- + if ((d_link->sc_params.wdp_capabilities & WD_CAP_LBA) != 0)
- + goto multimode;
- + if (wdsetctlr(d_link) != 0) {
- + /* Already printed a message. */
- + goto bad;
- + }
- + d_link->sc_state = GEOMETRY_WAIT;
- + break;
- +
- + case GEOMETRY_WAIT:
- + if (wdc->sc_status & WDCS_ERR) {
- + wderror(d_link, NULL, "wdccontrol: geometry failed");
- + goto bad;
- + }
- + /* fall through */
- + case MULTIMODE:
- + multimode:
- + if (d_link->sc_mode != WDM_PIOMULTI)
- + goto open;
- + outb(wdc->sc_iobase+wd_seccnt, d_link->sc_multiple);
- + if (wdccommandshort(wdc, d_link->sc_drive, WDCC_SETMULTI) != 0) {
- + wderror(d_link, NULL, "wdccontrol: setmulti failed (1)");
- + goto bad;
- + }
- + d_link->sc_state = MULTIMODE_WAIT;
- + break;
- +
- + case MULTIMODE_WAIT:
- + if (wdc->sc_status & WDCS_ERR) {
- + wderror(d_link, NULL, "wdccontrol: setmulti failed (2)");
- + goto bad;
- + }
- + /* fall through */
- + case OPEN:
- + open:
- + wdc->sc_errors = 0;
- + d_link->sc_state = OPEN;
- + /*
- + * The rest of the initialization can be done by normal means.
- + */
- + return 1;
- +
- + bad:
- + wdcunwedge(wdc);
- + return 0;
- + }
- +
- + wdc->sc_flags |= WDCF_IRQ_WAIT;
- + timeout(wdctimeout, wdc, WAITTIME);
- + return 0;
- + }
- +
- + /*
- + * Get the drive parameters, if ESDI or ATA, or create fake ones for ST506.
- + */
- + int
- + wdc_get_parms(d_link)
- + struct wd_link *d_link;
- + {
- + struct wdc_softc *wdc = (struct wdc_softc *)d_link->wdc_softc;
- + int i;
- + char tb[DEV_BSIZE];
- + int s, error;
- +
- + /*
- + * XXX
- + * The locking done here, and the length of time this may keep the rest
- + * of the system suspended, is a kluge. This should be rewritten to
- + * set up a transfer and queue it through wdstart(), but it's called
- + * infrequently enough that this isn't a pressing matter.
- + */
- +
- + s = splbio();
- +
- + while ((wdc->sc_flags & WDCF_ACTIVE) != 0) {
- + wdc->sc_flags |= WDCF_WANTED;
- + if ((error = tsleep(wdc, PRIBIO | PCATCH, "wdprm", 0)) != 0) {
- + splx(s);
- + return error;
- + }
- + }
- +
- + wdc->sc_flags |= WDCF_ACTIVE;
- +
- + if (wdccommandshort(wdc, d_link->sc_drive, WDCC_IDENTIFY) != 0 ||
- + wait_for_drq(wdc) != 0) {
- + /*
- + * We `know' there's a drive here; just assume it's old.
- + * This geometry is only used to read the MBR and print a
- + * (false) attach message.
- + */
- + strncpy(d_link->sc_lp->d_typename, "ST506",
- + sizeof d_link->sc_lp->d_typename);
- + d_link->sc_lp->d_type = DTYPE_ST506;
- +
- + strncpy(d_link->sc_params.wdp_model, "unknown",
- + sizeof d_link->sc_params.wdp_model);
- + d_link->sc_params.wdp_config = WD_CFG_FIXED;
- + d_link->sc_params.wdp_cylinders = 1024;
- + d_link->sc_params.wdp_heads = 8;
- + d_link->sc_params.wdp_sectors = 17;
- + d_link->sc_params.wdp_maxmulti = 0;
- + d_link->sc_params.wdp_usedmovsd = 0;
- + d_link->sc_params.wdp_capabilities = 0;
- + } else {
- + strncpy(d_link->sc_lp->d_typename, "ESDI/IDE",
- + sizeof d_link->sc_lp->d_typename);
- + d_link->sc_lp->d_type = DTYPE_ESDI;
- +
- + /* Read in parameter block. */
- + insw(wdc->sc_iobase+wd_data, tb, sizeof(tb) / sizeof(short));
- + bcopy(tb, &d_link->sc_params, sizeof(struct wdparams));
- +
- + /* Shuffle string byte order. */
- + for (i = 0; i < sizeof(d_link->sc_params.wdp_model); i += 2) {
- + u_short *p;
- + p = (u_short *)(d_link->sc_params.wdp_model + i);
- + *p = ntohs(*p);
- + }
- + }
- +
- + /* Clear any leftover interrupt. */
- + (void) inb(wdc->sc_iobase+wd_status);
- +
- + /* Restart the queue. */
- + #ifdef WDDEBUG
- + printf("wdcstart from wdc_get_parms flags %d\n",wdc->sc_flags);
- + #endif
- + wdc->sc_flags &= ~WDCF_ACTIVE;
- + wdcstart(wdc);
- +
- + splx(s);
- + return 0;
- + }
- + void
- + wdcerror(wdc, msg)
- + struct wdc_softc *wdc;
- + char *msg;
- + {
- + struct wdc_xfer *xfer = wdc->sc_xfer.tqh_first;
- + if (xfer == NULL)
- + printf("%s: %s\n", wdc->sc_dev.dv_xname, msg);
- + else
- + printf("%s(%s): %s\n", wdc->sc_dev.dv_xname,
- + ((struct device*)xfer->d_link->wd_softc)->dv_xname, msg);
- + }
- +
- + int wdc_atapi_get_params(ab_link, drive, id)
- + struct bus_link *ab_link;
- + u_int8_t drive;
- + struct atapi_identify *id;
- + {
- + struct wdc_softc *wdc = (void*)ab_link->wdc_softc;
- + int status, len, excess = 0;
- + int s, error;
- +
- + if (wdc->d_link[drive] != 0) {
- + #ifdef ATAPI_DEBUG_PROBE
- + printf("wdc_atapi_get_params: WD drive %d\n", drive);
- + #endif
- + return 0;
- + }
- +
- + /* If there is only one ATAPI slave ion the bus,don't probe
- + drive 0 (master) */
- +
- + if (wdc->sc_flags & WDCF_ONESLAVE && drive != 1)
- + return 0;
- +
- + #ifdef ATAPI_DEBUG_PROBE
- + printf("wdc_atapi_get_params: probing drive %d\n", drive);
- + #endif
- +
- + /*
- + * XXX
- + * The locking done here, and the length of time this may keep the rest
- + * of the system suspended, is a kluge. This should be rewritten to
- + * set up a transfer and queue it through wdstart(), but it's called
- + * infrequently enough that this isn't a pressing matter.
- + */
- +
- + s = splbio();
- +
- + while ((wdc->sc_flags & WDCF_ACTIVE) != 0) {
- + wdc->sc_flags |= WDCF_WANTED;
- + if ((error = tsleep(wdc, PRIBIO | PCATCH, "atprm", 0)) != 0) {
- + splx(s);
- + return error;
- + }
- + }
- +
- + wdc->sc_flags |= WDCF_ACTIVE;
- + error = 1;
- + (void)wdcreset(wdc);
- + if ((status = wdccommand((struct wd_link*)ab_link, ATAPI_SOFT_RESET, drive,
- + 0, 0, 0, 0)) != 0) {
- + #ifdef ATAPI_DEBUG
- + printf("wdc_atapi_get_params: ATAPI_SOFT_RESET failed for drive %d: status %d error %d\n", drive, status, wdc->sc_error);
- + #endif
- + error = 0;
- + goto end;
- + }
- + if ((status = wait_for_unbusy(wdc)) != 0 ) {
- + #ifdef ATAPI_DEBUG
- + printf("wdc_atapi_get_params: wait_for_unbusy failed for drive %d: status %d error %d\n", drive, status, wdc->sc_error);
- + #endif
- + error = 0;
- + goto end;
- + }
- +
- + if (wdccommand((struct wd_link*)ab_link, ATAPI_IDENTIFY_DEVICE, drive, sizeof(struct atapi_identify), 0,
- + 0, 0) != 0 || atapi_ready(wdc) != 0) {
- + #ifdef ATAPI_DEBUG_PROBE
- + printf("ATAPI_IDENTIFY_DEVICE failed for drive %d\n",drive);
- + #endif
- + error = 0;
- + goto end;
- + }
- + len = inb(wdc->sc_iobase + wd_cyl_lo) +
- + 256 * inb(wdc->sc_iobase + wd_cyl_hi);
- + if (len != sizeof(struct atapi_identify)) {
- + printf("Warning drive %d returned %d/%d of indentify device data\n",
- + drive, len, sizeof(struct atapi_identify));
- + excess = len - sizeof(struct atapi_identify);
- + if (excess < 0) excess = 0;
- + }
- + insw(wdc->sc_iobase + wd_data, id,
- + sizeof(struct atapi_identify)/sizeof(short));
- + wdcbit_bucket(wdc, excess);
- +
- + end: /* Restart the queue. */
- + #ifdef WDDEBUG
- + printf("wdcstart from wdc_atapi_get_parms flags %d\n",wdc->sc_flags);
- + #endif
- + wdc->sc_flags &= ~WDCF_ACTIVE;
- + wdcstart(wdc);
- + splx(s);
- + return error;
- + }
- +
- +
- + void wdc_atapi_send_command_packet(ab_link, acp)
- + struct bus_link *ab_link;
- + struct atapi_command_packet *acp;
- + {
- + struct wdc_softc *wdc = (void*)ab_link->wdc_softc;
- + struct wdc_xfer *xfer;
- + int s;
- + u_int8_t flags = acp->flags & 0xff;
- +
- + if (flags & A_POLLED) { /* Must use the queue and wdc_atapi_start */
- + struct wdc_xfer xfer_s;
- + int i;
- + #ifdef ATAPI_DEBUG_WDC
- + printf("wdc_atapi_send_cmd: flags %ld drive %d cmdlen %d datalen %d",
- + acp->flags, acp->drive, acp->command_size, acp->data_size);
- + #endif
- + xfer = &xfer_s;
- + bzero(xfer, sizeof(xfer_s));
- + xfer->c_flags = C_INUSE|C_ATAPI|acp->flags;
- + xfer->d_link = (struct wd_link*) ab_link;
- + xfer->c_link = ab_link->ctlr_link;
- + xfer->c_bp = acp->bp;
- + xfer->atapi_cmd = acp;
- + xfer->c_blkno = 0;
- + xfer->databuf = acp->databuf;
- + xfer->c_bcount = acp->data_size;
- + if (wait_for_unbusy (wdc) != 0)
- + if (!(wdc->sc_status & WDCS_ERR)) {
- + printf ("wdc_atapi_send_command: not ready, st = %02x\n",wdc->sc_status);
- + acp->status = ERROR;
- + return;
- + }
- +
- + if (wdccommand ((struct wd_link*)ab_link, ATAPI_PACKET_COMMAND,
- + acp->drive, acp->data_size, 0, 0, 0) != 0) {
- + printf("can't send atapi paket command\n");
- + acp->status = ERROR;
- + return;
- + }
- + /* Wait for cmd i/o phase. */
- + for (i=20000; i>0; --i) {
- + int phase;
- + phase = (inb(wdc->sc_iobase + wd_ireason) & (WDCI_CMD | WDCI_IN)) |
- + (inb(wdc->sc_iobase + wd_status) & WDCS_DRQ);
- + if (phase == PHASE_CMDOUT)
- + break;
- + delay(10);
- + }
- + #ifdef ATAPI_DEBUG_WDC
- + printf("Wait for cmd i/o phase: i= %d\n", i);
- + #endif
- +
- + outsw (wdc->sc_iobase + wd_data, acp->command,
- + acp->command_size/ sizeof (short));
- + /* Wait for data i/o phase. */
- +
- + for (i=20000; i>0; --i) {
- + int phase;
- + phase = (inb(wdc->sc_iobase + wd_ireason) & (WDCI_CMD | WDCI_IN)) |
- + (inb(wdc->sc_iobase + wd_status) & WDCS_DRQ);
- + if (phase != PHASE_CMDOUT) {
- + break;
- + }
- + delay(10);
- + }
- +
- + #ifdef ATAPI_DEBUG_WDC
- + printf("Wait for data i/o phase: i= %d\n", i);
- + #endif
- + while (wdc_atapi_intr(wdc, xfer)) {
- + for (i=2000; i>0; --i)
- + if (! (inb (wdc->sc_iobase + wd_status) & WDCS_DRQ))
- + break;
- + #ifdef ATAPI_DEBUG_WDC
- + printf("wdc_atapi_intr: i=%d\n", i);
- + #endif
- + }
- + wdc->sc_flags &= ~(WDCF_IRQ_WAIT | WDCF_SINGLE | WDCF_ERROR);
- + wdc->sc_errors = 0;
- + xfer->c_skip = 0;
- + return;
- + } else { /* POLLED */
- + xfer = wdc_get_xfer(ab_link->ctlr_link, flags&A_NOSLEEP?IDE_NOSLEEP:0);
- + if (xfer == NULL) {
- + acp->status = ERROR;
- + return;
- + }
- + xfer->c_flags |= C_ATAPI|acp->flags;
- + xfer->d_link = (struct wd_link*) ab_link;
- + xfer->c_link = ab_link->ctlr_link;
- + xfer->c_bp = acp->bp;
- + xfer->atapi_cmd = acp;
- + xfer->c_blkno = 0;
- + xfer->databuf = acp->databuf;
- + xfer->c_bcount = acp->data_size;
- + wdc_exec_xfer((struct wd_link*)ab_link,xfer);
- + return;
- + }
- + }
- +
- +
- + /*
- + the bit bucket
- + */
- + void wdcbit_bucket (wdc, size)
- + struct wdc_softc *wdc;
- + int size;
- + {
- + int iobase = wdc->sc_iobase;
- + int i;
- +
- + for (i = 0 ; i < size / 2 ; i++) {
- + short null;
- + (void) insw (iobase + wd_data, &null, 1);
- + }
- +
- + if (size % 2)
- + (void) inb (iobase + wd_data);
- +
- + }
- +
- + int wdc_atapi_intr(wdc, xfer)
- + struct wdc_softc *wdc;
- + struct wdc_xfer *xfer;
- + {
- + int len, phase, i;
- + int err, st, ire;
- + struct atapi_command_packet *acp = xfer->atapi_cmd;
- + if (wait_for_unbusy(wdc)<0) {
- + printf("wdc_atapi_intr: controller busy\n");
- + acp->status = ERROR;
- + acp->error = inb (wdc->sc_iobase + wd_error);
- + return 0;
- + }
- + #ifdef ATAPI_DEBUG2
- + printf("wdc_atapi_intr: %s\n", wdc->sc_dev.dv_xname);
- + #endif
- +
- + len = inb (wdc->sc_iobase + wd_cyl_lo) +
- + 256 * inb (wdc->sc_iobase + wd_cyl_hi);
- +
- + st = inb(wdc->sc_iobase + wd_status);
- + err = inb(wdc->sc_iobase + wd_error);
- + ire = inb(wdc->sc_iobase + wd_ireason);
- +
- + phase = (ire & (WDCI_CMD | WDCI_IN)) | (st & WDCS_DRQ);
- + #ifdef ATAPI_DEBUG_WDC
- + printf("wdc_atapi_intr: len %d st %d err %d ire %d :", len, st, err, ire);
- + #endif
- + switch (phase) {
- +
- + case PHASE_CMDOUT:
- + /* send packet command */
- + #ifdef ATAPI_DEBUG_WDC
- + printf("PHASE_CMDOUT\n");
- + #endif
- +
- + #ifdef ATAPI_DEBUG_WDC
- + {
- + int i;
- + char *c = (char*)acp->command;
- + printf("wdc_atapi_intr: cmd ");
- + for(i=0;i<acp->command_size;i++) printf("%x ",c[i]);
- + printf("\n");
- + }
- + #endif
- +
- + wdc->sc_flags |= WDCF_IRQ_WAIT;
- + outsw (wdc->sc_iobase + wd_data, acp->command,
- + acp->command_size/ sizeof (short));
- + return 1;
- +
- + case PHASE_DATAOUT:
- + /* write data */
- + #ifdef ATAPI_DEBUG_WDC
- + printf("PHASE_DATAOUT\n");
- + #endif
- + if ((acp->flags & (B_READ|B_WRITE)) != B_WRITE) {
- + printf("wdc_atapi_intr: bad data phase\n");
- + acp->status = ERROR;
- + return 1;
- + }
- + wdc->sc_flags |= WDCF_IRQ_WAIT;
- + if (xfer->c_bcount < len) {
- + printf("wdc_atapi_intr: warning: write only %d of %d requested bytes\n",
- + xfer->c_bcount, len);
- + outsw (wdc->sc_iobase + wd_data, xfer->databuf+xfer->c_skip,
- + xfer->c_bcount/sizeof (short));
- + for(i = xfer->c_bcount; i<len; i+=sizeof(short))
- + outw(wdc->sc_iobase + wd_data, 0);
- + xfer->c_bcount = 0;
- + return 1;
- + } else {
- + outsw (wdc->sc_iobase + wd_data, xfer->databuf+xfer->c_skip,
- + len/sizeof (short));
- + xfer->c_skip += len;
- + xfer->c_bcount -= len;
- + return 1;
- + }
- +
- + case PHASE_DATAIN:
- + /* Read data */
- + #ifdef ATAPI_DEBUG_WDC
- + printf("PHASE_DATAIN\n");
- + #endif
- + if ((acp->flags & (B_READ|B_WRITE)) != B_READ) {
- + printf("wdc_atapi_intr: bad data phase\n");
- + acp->status = ERROR;
- + return 1;
- + }
- + wdc->sc_flags |= WDCF_IRQ_WAIT;
- + if (xfer->c_bcount < len) {
- + printf("wdc_atapi_intr: warning: reading only %d of %d bytes\n",
- + xfer->c_bcount, len);
- + insw(wdc->sc_iobase + wd_data, xfer->databuf+xfer->c_skip,
- + xfer->c_bcount/sizeof(short));
- + wdcbit_bucket(wdc, len - xfer->c_bcount);
- + xfer->c_bcount = 0;
- + return 1;
- + } else {
- + insw(wdc->sc_iobase + wd_data, xfer->databuf+xfer->c_skip,
- + len/sizeof(short));
- + xfer->c_skip += len;
- + xfer->c_bcount -=len;
- + return 1;
- + }
- + case PHASE_ABORTED:
- + case PHASE_COMPLETED:
- + #ifdef ATAPI_DEBUG_WDC
- + printf("PHASE_COMPLETED\n");
- + #endif
- + if (st & WDCS_ERR) {
- + acp->error = inb (wdc->sc_iobase + wd_error);
- + acp->status = ERROR;
- + }
- + #ifdef ATAPI_DEBUG_WDC
- + if (xfer->c_bcount != 0) {
- + printf("wdc_atapi_intr warning: bcount value is %d after io\n",
- + xfer->c_bcount );
- + }
- + #endif
- + break;
- + default:
- + printf("wdc_atapi_intr: unknown phase %d\n", phase);
- + acp->status = ERROR;
- + }
- + wdc_atapi_done(wdc, xfer);
- + return(0);
- + }
- +
- +
- + void
- + wdc_atapi_done(wdc, xfer)
- + struct wdc_softc *wdc;
- + struct wdc_xfer *xfer;
- + {
- + struct atapi_command_packet *acp = xfer->atapi_cmd;
- + int s;
- +
- + acp->data_size = xfer->c_bcount;
- + s = splbio();
- + /* remove this command from xfer queue */
- + wdc->sc_errors = 0;
- + xfer->c_skip = 0;
- + if ((xfer->c_flags & A_POLLED) == 0) {
- + untimeout(wdctimeout, wdc);
- + TAILQ_REMOVE(&wdc->sc_xfer, xfer, c_xferchain);
- + wdc->sc_flags &= ~(WDCF_SINGLE | WDCF_ERROR | WDCF_ACTIVE);
- + wdc_free_xfer(xfer);
- + #ifdef ATAPI_DEBU
- + printf("wdc_atapi_done: atapi_done\n");
- + #endif
- + atapi_done(acp);
- + #ifdef WDDEBUG
- + printf("wdcstart from wdc_atapi_intr, flags %d\n",wdc->sc_flags);
- + #endif
- + wdcstart(wdc);
- + } else {
- + wdc->sc_flags &= ~(WDCF_SINGLE | WDCF_ERROR | WDCF_ACTIVE);
- + }
- + splx(s);
- + }
- diff -c -r -N --exclude exp --exclude compile sys/arch/arm32.orig/mainbus/wdlink.h sys/arch/arm32/mainbus/wdlink.h
- *** sys/arch/arm32.orig/mainbus/wdlink.h Thu Jan 1 01:00:00 1970
- --- sys/arch/arm32/mainbus/wdlink.h Thu Jun 13 02:57:04 1996
- ***************
- *** 0 ****
- --- 1,112 ----
- + /*
- + * Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved.
- + *
- + * DMA and multi-sector PIO handling are derived from code contributed by
- + * Onno van der Linden.
- + *
- + * Atapi support added by Manuel Bouyer.
- + *
- + * Redistribution and use in source and binary forms, with or without
- + * modification, are permitted provided that the following conditions
- + * are met:
- + * 1. Redistributions of source code must retain the above copyright
- + * notice, this list of conditions and the following disclaimer.
- + * 2. Redistributions in binary form must reproduce the above copyright
- + * notice, this list of conditions and the following disclaimer in the
- + * documentation and/or other materials provided with the distribution.
- + * 3. All advertising materials mentioning features or use of this software
- + * must display the following acknowledgement:
- + * This product includes software developed by Charles M. Hannum.
- + * 4. The name of the author may not be used to endorse or promote products
- + * derived from this software without specific prior written permission.
- + *
- + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- + */
- +
- +
- + #undef WDDEBUG
- + /* #undef DIAGNOSTIC */
- +
- + struct wdc_link {
- + int flags;
- + int openings;
- + };
- +
- + struct wd_link {
- + u_char type;
- + #define DRIVE 0
- + #define BUS 1
- + caddr_t wdc_softc;
- + caddr_t wd_softc;
- + struct wdc_link *ctlr_link;
- + struct wdparams sc_params;
- + /* Long-term state: */
- + u_int8_t openings;
- + int sc_drive; /* physical unit number */
- + int sc_state; /* control state */
- + #define RECAL 0 /* recalibrate */
- + #define RECAL_WAIT 1 /* done recalibrating */
- + #define GEOMETRY 2 /* upload geometry */
- + #define GEOMETRY_WAIT 3 /* done uploading geometry */
- + #define MULTIMODE 4 /* set multiple mode */
- + #define MULTIMODE_WAIT 5 /* done setting multiple mode */
- + #define OPEN 6 /* done with open */
- + int sc_mode; /* transfer mode */
- + #define WDM_PIOSINGLE 0 /* single-sector PIO */
- + #define WDM_PIOMULTI 1 /* multi-sector PIO */
- + #define WDM_DMA 2 /* DMA */
- + int sc_multiple; /* multiple for WDM_PIOMULTI */
- + int sc_flags; /* drive characteistics found */
- + #define WDF_LOCKED 0x01
- + #define WDF_WANTED 0x02
- + #define WDF_WLABEL 0x04 /* label is writable */
- + #define WDF_LABELLING 0x08 /* writing label */
- + /* XXX Nothing resets this yet, but disk change sensing will when ATAPI is
- + implemented. */
- + #define WDF_LOADED 0x10 /* parameters loaded */
- + #define WDF_32BIT 0x20 /* can do 32-bit transfer */
- + #define WDF_WAIT 0x40 /* waiting for resourses */
- + daddr_t sc_badsect[127]; /* 126 plus trailing -1 marker */
- + struct disklabel * sc_lp; /* label info for this disk */
- + };
- +
- + struct wdc_xfer {
- + struct wdc_link *c_link; /* controller structure info */
- + struct wd_link *d_link; /* drive/bus structure info */
- + volatile long c_flags; /* handle also B_READ and B_WRITE */
- + #define C_INUSE 0x01
- + #define C_ATAPI 0x02
- + #define C_ERROR 0x04
- + /* Information about the current transfer */
- + struct buf *c_bp;
- + void *atapi_cmd;
- + void* databuf;
- + daddr_t c_blkno; /* starting block number */
- + int c_bcount; /* byte count left */
- + int c_skip; /* bytes already transferred */
- + int c_nblks; /* number of blocks currently transferring */
- + int c_nbytes; /* number of bytes currently transferring */
- + u_long c_p_offset; /* offset of the partition */
- + TAILQ_ENTRY(wdc_xfer) c_xferchain;
- + LIST_ENTRY(wdc_xfer) free_list;
- + };
- +
- +
- + void wdc_exec_xfer __P((struct wd_link *, struct wdc_xfer *));
- + struct wdc_xfer * wdc_get_xfer __P((struct wdc_link *, int));
- + int wdc_get_parms __P((struct wd_link *));
- + void wderror __P((struct wd_link* , struct buf *, char *));
- + void wddone __P((struct wd_link*, struct buf*));
- + int wdccommand __P((struct wd_link *, int, int, int, int, int, int));
- + int wdcdumpprecalibrated __P((struct wd_link *));
- +
- + #define IDE_NOSLEEP 0x01
- diff -c -r -N --exclude exp --exclude compile sys/arch/arm32.orig/mainbus/wdreg.h sys/arch/arm32/mainbus/wdreg.h
- *** sys/arch/arm32.orig/mainbus/wdreg.h Sun May 12 22:34:06 1996
- --- sys/arch/arm32/mainbus/wdreg.h Thu Jun 13 02:57:04 1996
- ***************
- *** 47,52 ****
- --- 47,53 ----
- #define wd_precomp 0x004 /* write precompensation (W) */
- #define wd_features 0x004 /* features (W) */
- #define wd_seccnt 0x008 /* sector count (R/W) */
- + #define wd_ireason 0x008 /* interrupt reason (R/W) (for atapi) */
- #define wd_sector 0x00c /* first sector number (R/W) */
- #define wd_cyl_lo 0x010 /* cylinder address, low byte (R/W) */
- #define wd_cyl_hi 0x014 /* cylinder address, high byte (R/W) */
- ***************
- *** 119,124 ****
- --- 120,147 ----
- #define WDSD_CHS 0x00 /* cylinder/head/sector addressing */
- #define WDSD_LBA 0x40 /* logical block addressing */
-
- + /* Commands for ATAPI devices */
- + #define ATAPI_CHECK_POWER_MODE 0xe5
- + #define ATAPI_EXEC_DRIVE_DIAGS 0x90
- + #define ATAPI_IDLE_IMMEDIATE 0xe1
- + #define ATAPI_NOP 0x00
- + #define ATAPI_PACKET_COMMAND 0xa0
- + #define ATAPI_IDENTIFY_DEVICE 0xa1
- + #define ATAPI_SOFT_RESET 0x08
- + #define ATAPI_SET_FEATURES 0xef
- + #define ATAPI_SLEEP 0xe6
- + #define ATAPI_STANDBY_IMMEDIATE 0xe0
- +
- + /* ireason */
- + #define WDCI_CMD 0x01 /* command(1) or data(0) */
- + #define WDCI_IN 0x02 /* transfer to(1) or from(0) the host */
- + #define WDCI_RELEASE 0x04 /* bus released until completion */
- +
- + #define PHASE_CMDOUT (WDCS_DRQ | WDCI_CMD)
- + #define PHASE_DATAIN (WDCS_DRQ | WDCI_IN)
- + #define PHASE_DATAOUT WDCS_DRQ
- + #define PHASE_COMPLETED (WDCI_IN | WDCI_CMD)
- + #define PHASE_ABORTED 0
-
- #ifdef _KERNEL
- /*
-