home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 4 / DATAFILE_PDCD4.iso / unix / riscbsd / sources / patches / netbsd / atapi_i386 / atapi_i386~ / diffs-current < prev    next >
Encoding:
Text File  |  1996-06-06  |  193.7 KB  |  7,081 lines

  1. diff --exclude compile -bcrNP src.orig/sys/arch/i386/conf/GENERIC src/sys/arch/i386/conf/GENERIC
  2. *** src.orig/sys/arch/i386/conf/GENERIC    Tue May 21 13:28:55 1996
  3. --- src/sys/arch/i386/conf/GENERIC    Thu Jun  6 16:59:30 1996
  4. ***************
  5. *** 158,165 ****
  6.   mcd0    at isa? port 0x300 irq 10    # Mitsumi CD-ROM drives
  7.   
  8.   wdc0    at isa? port 0x1f0 irq 14    # ST506, ESDI, and IDE controllers
  9. ! #wdc1    at isa? port 0x170 irq ?
  10.   wd*    at wdc? drive ?
  11.   
  12.   wt0    at isa? port 0x300 irq 5 drq 1    # Archive and Wangtek QIC tape drives
  13.   
  14. --- 158,167 ----
  15.   mcd0    at isa? port 0x300 irq 10    # Mitsumi CD-ROM drives
  16.   
  17.   wdc0    at isa? port 0x1f0 irq 14    # ST506, ESDI, and IDE controllers
  18. ! wdc1    at isa? port 0x170 irq 15
  19.   wd*    at wdc? drive ?
  20. + atapibus* at wdc?
  21. + acd* at atapibus? drive?
  22.   
  23.   wt0    at isa? port 0x300 irq 5 drq 1    # Archive and Wangtek QIC tape drives
  24.   
  25. diff --exclude compile -bcrNP src.orig/sys/arch/i386/conf/GENERICADP src/sys/arch/i386/conf/GENERICADP
  26. *** src.orig/sys/arch/i386/conf/GENERICADP    Tue May 21 13:28:55 1996
  27. --- src/sys/arch/i386/conf/GENERICADP    Thu Jun  6 16:59:36 1996
  28. ***************
  29. *** 144,151 ****
  30.   mcd0    at isa? port 0x300 irq 10    # Mitsumi CD-ROM drives
  31.   
  32.   wdc0    at isa? port 0x1f0 irq 14    # ST506, ESDI, and IDE controllers
  33. ! #wdc1    at isa? port 0x170 irq ?
  34.   wd*    at wdc? drive ?
  35.   
  36.   wt0    at isa? port 0x300 irq 5 drq 1    # Archive and Wangtek QIC tape drives
  37.   
  38. --- 144,153 ----
  39.   mcd0    at isa? port 0x300 irq 10    # Mitsumi CD-ROM drives
  40.   
  41.   wdc0    at isa? port 0x1f0 irq 14    # ST506, ESDI, and IDE controllers
  42. ! wdc1    at isa? port 0x170 irq 15
  43.   wd*    at wdc? drive ?
  44. + atapibus* at wdc?
  45. + acd* at atapibus? drive?
  46.   
  47.   wt0    at isa? port 0x300 irq 5 drq 1    # Archive and Wangtek QIC tape drives
  48.   
  49. diff --exclude compile -bcrNP src.orig/sys/arch/i386/conf/GENERICOTHER src/sys/arch/i386/conf/GENERICOTHER
  50. *** src.orig/sys/arch/i386/conf/GENERICOTHER    Tue May 21 13:28:55 1996
  51. --- src/sys/arch/i386/conf/GENERICOTHER    Thu Jun  6 16:59:44 1996
  52. ***************
  53. *** 149,156 ****
  54.   mcd0    at isa? port 0x300 irq 10    # Mitsumi CD-ROM drives
  55.   
  56.   wdc0    at isa? port 0x1f0 irq 14    # ST506, ESDI, and IDE controllers
  57. ! #wdc1    at isa? port 0x170 irq ?
  58.   wd*    at wdc? drive ?
  59.   
  60.   wt0    at isa? port 0x300 irq 5 drq 1    # Archive and Wangtek QIC tape drives
  61.   
  62. --- 149,158 ----
  63.   mcd0    at isa? port 0x300 irq 10    # Mitsumi CD-ROM drives
  64.   
  65.   wdc0    at isa? port 0x1f0 irq 14    # ST506, ESDI, and IDE controllers
  66. ! wdc1    at isa? port 0x170 irq 15
  67.   wd*    at wdc? drive ?
  68. + atapibus* at wdc?
  69. + acd* at atapibus? drive?
  70.   
  71.   wt0    at isa? port 0x300 irq 5 drq 1    # Archive and Wangtek QIC tape drives
  72.   
  73. diff --exclude compile -bcrNP src.orig/sys/arch/i386/conf/files.i386 src/sys/arch/i386/conf/files.i386
  74. *** src.orig/sys/arch/i386/conf/files.i386    Tue May  7 13:26:13 1996
  75. --- src/sys/arch/i386/conf/files.i386    Thu Jun  6 12:21:57 1996
  76. ***************
  77. *** 47,52 ****
  78. --- 47,57 ----
  79.   major    {rd = 17}
  80.   
  81.   #
  82. + # Machine-independent ATAPI drivers
  83. + #
  84. + include "../../../atapi/files.atapi"
  85. + #
  86.   # System bus types
  87.   #
  88.   
  89. diff --exclude compile -bcrNP src.orig/sys/arch/i386/i386/conf.c src/sys/arch/i386/i386/conf.c
  90. *** src.orig/sys/arch/i386/i386/conf.c    Sat May  4 13:47:01 1996
  91. --- src/sys/arch/i386/i386/conf.c    Thu Jun  6 12:24:31 1996
  92. ***************
  93. *** 56,61 ****
  94. --- 56,63 ----
  95.   bdev_decl(st);
  96.   #include "cd.h"
  97.   bdev_decl(cd);
  98. + #include "acd.h"
  99. + bdev_decl(acd);
  100.   #include "mcd.h"
  101.   bdev_decl(mcd);
  102.   #include "vnd.h"
  103. ***************
  104. *** 88,93 ****
  105. --- 90,96 ----
  106.       bdev_disk_init(NSCD,scd),    /* 15: Sony CD-ROM */
  107.       bdev_disk_init(NCCD,ccd),    /* 16: concatenated disk driver */
  108.       bdev_disk_init(NRD,rd),        /* 17: ram disk driver */
  109. +     bdev_disk_init(NACD,acd),   /* 18: ATAPI CD-ROM */
  110.   };
  111.   int    nblkdev = sizeof(bdevsw) / sizeof(bdevsw[0]);
  112.   
  113. ***************
  114. *** 145,150 ****
  115. --- 148,154 ----
  116.   #include "ss.h"
  117.   cdev_decl(ss);
  118.   cdev_decl(cd);
  119. + cdev_decl(acd);
  120.   #include "lpt.h"
  121.   cdev_decl(lpt);
  122.   #include "ch.h"
  123. ***************
  124. *** 202,208 ****
  125.       cdev_disk_init(NCCD,ccd),    /* 18: concatenated disk driver */
  126.       cdev_ss_init(NSS,ss),        /* 19: SCSI scanner */
  127.       cdev_notdef(),            /* 20 */
  128. !     cdev_notdef(),            /* 21 */
  129.       cdev_fd_init(1,filedesc),    /* 22: file descriptor pseudo-device */
  130.       cdev_bpftun_init(NBPFILTER,bpf),/* 23: Berkeley packet filter */
  131.       cdev_notdef(),            /* 24 */
  132. --- 206,212 ----
  133.       cdev_disk_init(NCCD,ccd),    /* 18: concatenated disk driver */
  134.       cdev_ss_init(NSS,ss),        /* 19: SCSI scanner */
  135.       cdev_notdef(),            /* 20 */
  136. !     cdev_disk_init(NACD,acd),   /* 21: ATAPI CD-ROM */
  137.       cdev_fd_init(1,filedesc),    /* 22: file descriptor pseudo-device */
  138.       cdev_bpftun_init(NBPFILTER,bpf),/* 23: Berkeley packet filter */
  139.       cdev_notdef(),            /* 24 */
  140. diff --exclude compile -bcrNP src.orig/sys/atapi/acd.c src/sys/atapi/acd.c
  141. *** src.orig/sys/atapi/acd.c    Thu Jan  1 01:00:00 1970
  142. --- src/sys/atapi/acd.c    Tue Apr 23 21:11:46 1996
  143. ***************
  144. *** 0 ****
  145. --- 1,1293 ----
  146. + /*
  147. +  * Copyright (c) 1996 Manuel Bouyer.  All rights reserved.
  148. +  *
  149. +  * Redistribution and use in source and binary forms, with or without
  150. +  * modification, are permitted provided that the following conditions
  151. +  * are met:
  152. +  * 1. Redistributions of source code must retain the above copyright
  153. +  *    notice, this list of conditions and the following disclaimer.
  154. +  * 2. Redistributions in binary form must reproduce the above copyright
  155. +  *    notice, this list of conditions and the following disclaimer in the
  156. +  *    documentation and/or other materials provided with the distribution.
  157. +  * 3. All advertising materials mentioning features or use of this software
  158. +  *    must display the following acknowledgement:
  159. +  *  This product includes software developed by Manuel Bouyer.
  160. +  * 4. The name of the author may not be used to endorse or promote products
  161. +  *    derived from this software without specific prior written permission.
  162. +  *
  163. +  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  164. +  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  165. +  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  166. +  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  167. +  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  168. +  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  169. +  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  170. +  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  171. +  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  172. +  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  173. +  */
  174. + #include <sys/types.h>
  175. + #include <sys/param.h>
  176. + #include <sys/systm.h>
  177. + #include <sys/kernel.h>
  178. + #include <sys/conf.h>
  179. + #include <sys/file.h>
  180. + #include <sys/stat.h>
  181. + #include <sys/ioctl.h>
  182. + #include <sys/buf.h>
  183. + #include <sys/uio.h>
  184. + #include <sys/malloc.h>
  185. + #include <sys/errno.h>
  186. + #include <sys/device.h>
  187. + #include <sys/disklabel.h>
  188. + #include <sys/disk.h>
  189. + #include <sys/cdio.h>
  190. + #include <sys/proc.h>  
  191. + #include <atapi/atapilink.h>
  192. + #include <atapi/atapi.h>
  193. + #define    CDUNIT(z)            DISKUNIT(z)
  194. + #define    CDPART(z)            DISKPART(z)
  195. + #define    MAKECDDEV(maj, unit, part)    MAKEDISKDEV(maj, unit, part)
  196. + struct acd_softc {
  197. +     struct device sc_dev;
  198. +     struct disk sc_dk;
  199. +     int flags;
  200. + #define    CDF_LOCKED    0x01
  201. + #define    CDF_WANTED    0x02
  202. + #define    CDF_WLABEL    0x04        /* label is writable */
  203. + #define    CDF_LABELLING    0x08        /* writing label */
  204. +     struct at_dev_link *ad_link;    /* contains our drive number, etc ... */
  205. +     struct cd_parms {
  206. +         int blksize;
  207. +         u_long disksize;    /* total number sectors */
  208. +     } params;
  209. +     struct buf buf_queue;
  210. + };
  211. + int acdmatch __P((struct device *, void *, void *));
  212. + void acdattach __P((struct device *, struct device *, void *));
  213. + struct cfattach acd_ca = {
  214. +     sizeof(struct acd_softc), acdmatch, acdattach
  215. + };
  216. + struct cfdriver acd_cd = {
  217. +     NULL, "acd", DV_DISK
  218. + };
  219. + void acdgetdisklabel __P((struct acd_softc *));
  220. + int acd_get_parms __P((struct acd_softc *, int));
  221. + void acdstrategy __P((struct buf *));
  222. + void acdstart __P((struct acd_softc *));
  223. + int acd_pause __P((struct acd_softc *, int));
  224. + void    acdminphys __P((struct buf*));
  225. + u_long acd_size __P((struct acd_softc*, int));
  226. + int acddone __P((struct atapi_command_packet *));
  227. + struct dkdriver acddkdriver = { acdstrategy };
  228. + int
  229. + acdmatch(parent, match, aux)
  230. +     struct device *parent;
  231. +     void *match, *aux;
  232. + {
  233. +     struct cfdata *cf = match;
  234. +     struct at_dev_link *sa = aux;
  235. + #ifdef ATAPI_DEBUG_PROBE
  236. +     printf("acdmatch: device %d\n",sa->id.config.device_type);
  237. + #endif
  238. +     if (sa->id.config.device_type == ATAPI_DEVICE_TYPE_CD) return 1;
  239. +     return 0;
  240. +     
  241. + }
  242. + /*
  243. +  * The routine called by the low level atapi routine when it discovers
  244. +  * A device suitable for this driver
  245. +  */
  246. + void
  247. + acdattach(parent, self, aux)
  248. +     struct device *parent, *self;
  249. +     void *aux;
  250. + {
  251. +     struct acd_softc *acd = (void *)self;
  252. +     struct at_dev_link *sa = aux;
  253. +     struct mode_sense cmd;
  254. +     struct cappage cap;
  255. +     sa->device_softc = acd;
  256. +     sa->start = acdstart;
  257. +     sa->done = acddone;
  258. +     sa->flags |= ADEV_REMOVABLE;
  259. +     sa->openings = 1;
  260. +     acd->ad_link = sa;
  261. +     /*
  262. +      * Initialize and attach the disk structure.
  263. +      */
  264. +     acd->sc_dk.dk_driver = &acddkdriver;
  265. +     acd->sc_dk.dk_name = acd->sc_dev.dv_xname;
  266. +     disk_attach(&acd->sc_dk);
  267. + #if !defined(i386) || defined(NEWCONFIG)
  268. +     dk_establish(&acd->sc_dk, &acd->sc_dev);   
  269. + #endif
  270. +     (void)atapi_test_unit_ready(sa, A_POLLED | A_SILENT); 
  271. +     delay(1000);
  272. +     (void)atapi_test_unit_ready(sa, A_POLLED | A_SILENT);
  273. +                                         /* To clear media change, etc ...*/
  274. +     bzero(&cmd, sizeof(cmd));
  275. +     cmd.operation_code = ATAPI_MODE_SENSE;
  276. +     cmd.page_code = CAP_PAGE;
  277. +     cmd.length[0] = sizeof (cap) >> 8;
  278. +     cmd.length[1] = sizeof (cap);
  279. +     if (atapi_exec_cmd(sa, &cmd , sizeof(cmd), &cap, sizeof(cap),
  280. +                                             B_READ, A_POLLED) != 0) {
  281. +         printf("atapi_exec_cmd failed\n");
  282. +         return;
  283. +     }
  284. +     switch (cap.medium_type) {
  285. +         case MDT_UNKNOWN:   printf ("medium type unknown");
  286. +                             break;
  287. +         case MDT_DATA_120:  printf ("120mm data disc ");
  288. +                             break;
  289. +         case MDT_AUDIO_120: printf ("120mm audio disc ");
  290. +                             break;
  291. +         case MDT_COMB_120:  printf ("120mm data/audio disc ");
  292. +                             break;
  293. +         case MDT_PHOTO_120: printf ("120mm photo disc ");
  294. +                             break;
  295. +         case MDT_DATA_80:   printf ("80mm data disc ");
  296. +                             break;
  297. +         case MDT_AUDIO_80:  printf ("80mm audio disc ");
  298. +                             break;
  299. +         case MDT_COMB_80:   printf ("80mm data/audio disc ");
  300. +                             break;
  301. +         case MDT_PHOTO_80:  printf ("80mm photo disc ");
  302. +                             break;
  303. +         case MDT_NO_DISC:   printf ("drive empty ");
  304. +                             break;
  305. +         case MDT_DOOR_OPEN: printf ("door open");
  306. +                             break;
  307. +         case MDT_FMT_ERROR: printf ("medium format error");
  308. +                             break;
  309. +         default:    printf ("unknown medium type=0x%x", cap.medium_type);
  310. +                     break;
  311. +     }
  312. +     printf("\n");
  313. + }
  314. + /*
  315. +  * Wait interruptibly for an exclusive lock.
  316. +  *
  317. +  * XXX
  318. +  * Several drivers do this; it should be abstracted and made MP-safe.
  319. +  */
  320. + int
  321. + acdlock(acd)
  322. +     struct acd_softc *acd;
  323. + {
  324. +     int error;
  325. +     while ((acd->flags & CDF_LOCKED) != 0) {
  326. +         acd->flags |= CDF_WANTED;
  327. +         if ((error = tsleep(acd, PRIBIO | PCATCH, "acdlck", 0)) != 0)
  328. +             return error;
  329. +     }
  330. +     acd->flags |= CDF_LOCKED;
  331. +     return 0;
  332. + }
  333. + /*
  334. +  * Unlock and wake up any waiters.
  335. +  */
  336. + void
  337. + acdunlock(acd)
  338. +     struct acd_softc *acd;
  339. + {
  340. +     acd->flags &= ~CDF_LOCKED;
  341. +     if ((acd->flags & CDF_WANTED) != 0) {
  342. +         acd->flags &= ~CDF_WANTED;
  343. +         wakeup(acd);
  344. +     }
  345. + }
  346. + /*
  347. +  * open the device. Make sure the partition info is a up-to-date as can be.
  348. +  */
  349. + int
  350. + acdopen(dev, flag, fmt)
  351. +     dev_t dev;
  352. +     int flag, fmt;
  353. + {
  354. +     struct acd_softc *acd;
  355. +     struct at_dev_link *ad_link;
  356. +     int unit, part;
  357. +     int error;
  358. + #ifdef ACD_DEBUG
  359. +     printf("acd: open\n");
  360. + #endif
  361. +     unit = CDUNIT(dev);
  362. +     if (unit >= acd_cd.cd_ndevs)
  363. +         return ENXIO;
  364. +     acd = acd_cd.cd_devs[unit];
  365. +     if (!acd)
  366. +         return ENXIO;
  367. +     ad_link = acd->ad_link;
  368. +     if ((error = atapi_test_unit_ready(ad_link,0)) != 0) {
  369. +         if (error != UNIT_ATTENTION) return EIO;
  370. +         if ((ad_link->flags & ADEV_OPEN) != 0 ) return EIO;
  371. +     }
  372. +     if (error = acdlock(acd))
  373. +         return error;
  374. +     if (acd->sc_dk.dk_openmask != 0) {
  375. +         /*
  376. +          * If any partition is open, but the disk has been invalidated,
  377. +          * disallow further opens.
  378. +          */
  379. +         if ((ad_link->flags & ADEV_MEDIA_LOADED) == 0) {
  380. +             error = EIO;
  381. +             goto bad3;
  382. +         }
  383. +     } else {
  384. +         ad_link->flags |= ADEV_OPEN;
  385. +         /* Lock the pack in. */
  386. +         if (error = atapi_prevent(ad_link, PR_PREVENT))
  387. +             goto bad;
  388. +         if ((ad_link->flags & ADEV_MEDIA_LOADED) == 0) {
  389. +             ad_link->flags |= ADEV_MEDIA_LOADED;
  390. +             /* Load the physical device parameters. */
  391. +             if (acd_get_parms(acd, 0) != 0) {
  392. +                 error = ENXIO;
  393. +                 goto bad2;
  394. +             }
  395. +             /* Fabricate a disk label. */
  396. +             acdgetdisklabel(acd);
  397. +         }
  398. +     }
  399. +     part = CDPART(dev);
  400. +     /* Check that the partition exists. */
  401. +     if (part != RAW_PART &&
  402. +         (part >= acd->sc_dk.dk_label->d_npartitions ||
  403. +          acd->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) {
  404. +         error = ENXIO;
  405. +         goto bad;
  406. +     }
  407. +     /* Insure only one open at a time. */
  408. +     switch (fmt) {
  409. +     case S_IFCHR:
  410. +         acd->sc_dk.dk_copenmask |= (1 << part);
  411. +         break;
  412. +     case S_IFBLK:
  413. +         acd->sc_dk.dk_bopenmask |= (1 << part);
  414. +         break;
  415. +     }
  416. +     acd->sc_dk.dk_openmask = acd->sc_dk.dk_copenmask | acd->sc_dk.dk_bopenmask;
  417. + #ifdef ACD_DEBUG
  418. +     printf("open complete\n");
  419. + #endif
  420. +     acdunlock(acd);
  421. +     return 0;
  422. + bad2:
  423. +     ad_link->flags &= ~ADEV_MEDIA_LOADED;
  424. + bad:
  425. +     if (acd->sc_dk.dk_openmask == 0) {
  426. +         atapi_prevent(ad_link, PR_ALLOW);
  427. +         ad_link->flags &= ~ADEV_OPEN;
  428. +     }
  429. + bad3:
  430. +     acdunlock(acd);
  431. +     return error;
  432. + }
  433. + /*
  434. +  * close the device.. only called if we are the LAST
  435. +  * occurence of an open device
  436. +  */
  437. + int
  438. + acdclose(dev, flag, fmt)
  439. +     dev_t dev;
  440. +     int flag, fmt;
  441. + {
  442. +     struct acd_softc *acd = acd_cd.cd_devs[CDUNIT(dev)];
  443. +     int part = CDPART(dev);
  444. +     int error;
  445. +     if (error = acdlock(acd))
  446. +         return error;
  447. +     switch (fmt) {
  448. +     case S_IFCHR:
  449. +         acd->sc_dk.dk_copenmask &= ~(1 << part);
  450. +         break;
  451. +     case S_IFBLK:
  452. +         acd->sc_dk.dk_bopenmask &= ~(1 << part);
  453. +         break;
  454. +     }
  455. +     acd->sc_dk.dk_openmask = acd->sc_dk.dk_copenmask | acd->sc_dk.dk_bopenmask;
  456. +     if (acd->sc_dk.dk_openmask == 0) {
  457. +         /* XXXX Must wait for I/O to complete! */
  458. +         atapi_prevent(acd->ad_link, PR_ALLOW);
  459. +         acd->ad_link->flags &= ~ADEV_OPEN;
  460. +     }
  461. +     acdunlock(acd);
  462. +     return 0;
  463. + }
  464. + /*
  465. +  * Actually translate the requested transfer into one the physical driver can
  466. +  * understand.  The transfer is described by a buf and will include only one
  467. +  * physical transfer.
  468. +  */
  469. + void
  470. + acdstrategy(bp)
  471. +     struct buf *bp;
  472. + {
  473. +     struct acd_softc *acd = acd_cd.cd_devs[CDUNIT(bp->b_dev)];
  474. +     int opri;
  475. + #ifdef ACD_DEBUG
  476. +     printf("acdstrategy\n");
  477. + #endif
  478. +     /*
  479. +      * The transfer must be a whole number of blocks.
  480. +      */
  481. +     if ((bp->b_bcount % acd->sc_dk.dk_label->d_secsize) != 0) {
  482. +         bp->b_error = EINVAL;
  483. +         goto bad;
  484. +     }
  485. +     if ((bp->b_flags & (B_READ|B_WRITE)) == B_WRITE) {
  486. +         bp->b_error = EROFS;
  487. +         goto bad;
  488. +     }
  489. +     /*
  490. +      * If the device has been made invalid, error out
  491. +      * maybe the media changed
  492. +      */
  493. +     if ((acd->ad_link->flags & ADEV_MEDIA_LOADED) == 0) {
  494. +         bp->b_error = EIO;
  495. +         goto bad;
  496. +     }
  497. +     /*
  498. +      * If it's a null transfer, return immediately
  499. +      */
  500. +     if (bp->b_bcount == 0)
  501. +         goto done;
  502. +     /*
  503. +      * Do bounds checking, adjust transfer. if error, process.
  504. +      * If end of partition, just return.
  505. +      */
  506. +     if (CDPART(bp->b_dev) != RAW_PART &&
  507. +         bounds_check_with_label(bp, acd->sc_dk.dk_label,
  508. +         (acd->flags & (CDF_WLABEL|CDF_LABELLING)) != 0) <= 0)
  509. +         goto done;
  510. +     opri = splbio();
  511. +     /*
  512. +      * Place it in the queue of disk activities for this disk
  513. +      */
  514. +     disksort(&acd->buf_queue, bp);
  515. +     /*
  516. +      * Tell the device to get going on the transfer if it's
  517. +      * not doing anything, otherwise just wait for completion
  518. +      */
  519. +     acdstart(acd);
  520. +     splx(opri);
  521. +     return;
  522. + bad:
  523. +     bp->b_flags |= B_ERROR;
  524. + done:
  525. +     /*
  526. +      * Correctly set the buf to indicate a completed xfer
  527. +      */
  528. +     bp->b_resid = bp->b_bcount;
  529. +     biodone(bp);
  530. + }
  531. + /*
  532. +  * acdstart looks to see if there is a buf waiting for the device
  533. +  * and that the device is not already busy. If both are true,
  534. +  * It deques the buf and creates a atapi command to perform the
  535. +  * transfer in the buf. The transfer request will call atapi_done
  536. +  * on completion, which will in turn call this routine again
  537. +  * so that the next queued transfer is performed.
  538. +  * The bufs are queued by the strategy routine (cdstrategy)
  539. +  *
  540. +  * This routine is also called after other non-queued requests
  541. +  * have been made of the atapi driver, to ensure that the queue
  542. +  * continues to be drained.
  543. +  *
  544. +  * must be called at the correct (highish) spl level
  545. +  * cdstart() is called at splbio from cdstrategy and atapi_done
  546. +  */
  547. + void
  548. + acdstart(acd)
  549. +     struct acd_softc *acd;
  550. + {
  551. +     struct at_dev_link *ad_link;
  552. +     struct buf *bp = 0;
  553. +     struct buf *dp;
  554. +     struct read cmd;
  555. +     u_int32_t blkno, nblks;
  556. +     struct partition *p;
  557. + #ifdef ACD_DEBUG
  558. +     printf("acd: acdstart\n");
  559. +     if (acd == NULL) {
  560. +         printf("acdstart: null acd\n");
  561. +         return;
  562. +     }
  563. + #endif
  564. +         
  565. +     ad_link = acd->ad_link;
  566. + #ifdef ACD_DEBUG
  567. +     if (ad_link == NULL) {
  568. +         printf("acdstart: null ad_link\n");
  569. +         return;
  570. +     }
  571. + #endif
  572. +     /*
  573. +      * Check if the device has room for another command
  574. +      */
  575. +     while (ad_link->openings >0 ) {
  576. +         /*
  577. +          * there is excess capacity, but a special waits
  578. +          * It'll need the adapter as soon as we clear out of the
  579. +          * way and let it run (user level wait).
  580. +          */
  581. +         if (ad_link->flags & ADEV_WAITING) {
  582. + #ifdef ATAPI_DEBUG
  583. +             printf("acdstart: waking up\n");
  584. + #endif
  585. +             ad_link->flags &= ~ADEV_WAITING;
  586. +             wakeup((caddr_t)ad_link);
  587. +             return;
  588. +         }
  589. +         
  590. +         /*
  591. +          * See if there is a buf with work for us to do..
  592. +          */
  593. +         dp = &acd->buf_queue;
  594. + #ifdef ACD_DEBUG
  595. +         if (dp == NULL) {
  596. +             printf("acdstart: null dp\n");
  597. +             return;
  598. +         }
  599. + #endif
  600. +         if ((bp = dp->b_actf) == NULL)    /* yes, an assign */
  601. +             return;
  602. + #ifdef ACD_DEBUG
  603. +         printf("acdstart: a buf\n");
  604. + #endif
  605. +         dp->b_actf = bp->b_actf;
  606. +         /*
  607. +          * If the device has become invalid, abort all the
  608. +          * reads and writes until all files have been closed and
  609. +          * re-opened
  610. +          */
  611. +         if ((ad_link->flags & ADEV_MEDIA_LOADED) == 0) {
  612. +             bp->b_error = EIO;
  613. +             bp->b_flags |= B_ERROR;
  614. +             biodone(bp);
  615. +             continue;
  616. +         }
  617. +         /*
  618. +          *
  619. +          * First, translate the block to absolute and put it in terms
  620. +          * of the logical blocksize of the device.
  621. +          */
  622. +         blkno =
  623. +             bp->b_blkno / (acd->sc_dk.dk_label->d_secsize / DEV_BSIZE);
  624. +         if (CDPART(bp->b_dev) != RAW_PART) {
  625. +             p = &acd->sc_dk.dk_label->d_partitions[CDPART(bp->b_dev)];
  626. +             blkno += p->p_offset;
  627. +         }
  628. +         nblks = howmany(bp->b_bcount, acd->sc_dk.dk_label->d_secsize);
  629. + #ifdef ACD_DEBUG
  630. +         printf("acdstart: blkno %d nblk %d\n",blkno, nblks);
  631. + #endif
  632. +         /*
  633. +          *  Fill out the atapi command
  634. +          */
  635. +         bzero(&cmd, sizeof(cmd));
  636. +         cmd.operation_code = ATAPI_READ;
  637. +         cmd.lba[0] = (blkno >> 24) & 0xff;
  638. +         cmd.lba[1] = (blkno >> 16) & 0xff;
  639. +         cmd.lba[2] = (blkno >> 8) & 0xff;
  640. +         cmd.lba[3] = blkno & 0xff;
  641. +         cmd.length[0] = (nblks >> 8) & 0xff;
  642. +         cmd.length[1] = nblks & 0xff;
  643. +         /* Instrumentation. */
  644. +         disk_busy(&acd->sc_dk);
  645. +         /*
  646. +          * Call the routine that chats with the adapter.
  647. +          * Note: we cannot sleep as we may be an interrupt
  648. +          */
  649. +          if (atapi_exec_io(ad_link, &cmd, sizeof(cmd), bp, A_NOSLEEP))
  650. +             printf("%s: not queued", acd->sc_dev.dv_xname);
  651. +     }
  652. + }
  653. + int
  654. + acdread(dev, uio)
  655. +     dev_t dev;
  656. +     struct uio *uio;
  657. + {
  658. +     return (physio(acdstrategy, NULL, dev, B_READ,
  659. +                acdminphys, uio));
  660. + }
  661. + int
  662. + acdwrite(dev, uio)
  663. +     dev_t dev;
  664. +     struct uio *uio;
  665. + {
  666. +     return (physio(acdstrategy, NULL, dev, B_WRITE,
  667. +                acdminphys, uio));
  668. + }
  669. + /*
  670. +  * Perform special action on behalf of the user.
  671. +  * Knows about the internals of this device
  672. +  */
  673. + int
  674. + acdioctl(dev, cmd, addr, flag, p)
  675. +     dev_t dev;
  676. +     u_long cmd;
  677. +     caddr_t addr;
  678. +     int flag;
  679. +     struct proc *p;
  680. + {
  681. +     struct acd_softc *acd = acd_cd.cd_devs[CDUNIT(dev)];
  682. +     int error;
  683. +     /*
  684. +      * If the device is not valid.. abandon ship
  685. +      */
  686. +     if ((acd->ad_link->flags & ADEV_MEDIA_LOADED) == 0)
  687. +         return EIO;
  688. +     switch (cmd) {
  689. +     case DIOCGDINFO:
  690. +         *(struct disklabel *)addr = *acd->sc_dk.dk_label;
  691. +         return 0;
  692. +     case DIOCGPART:
  693. +         ((struct partinfo *)addr)->disklab = acd->sc_dk.dk_label;
  694. +         ((struct partinfo *)addr)->part =
  695. +             &acd->sc_dk.dk_label->d_partitions[CDPART(dev)];
  696. +         return 0;
  697. +     case DIOCWDINFO:
  698. +     case DIOCSDINFO:
  699. +         if ((flag & FWRITE) == 0)
  700. +             return EBADF;
  701. +         if (error = acdlock(acd))
  702. +             return error;
  703. +         acd->flags |= CDF_LABELLING;
  704. +         error = setdisklabel(acd->sc_dk.dk_label,
  705. +             (struct disklabel *)addr, /*acd->sc_dk.dk_openmask : */0,
  706. +             acd->sc_dk.dk_cpulabel);
  707. +         if (error == 0) {
  708. +         }
  709. +         acd->flags &= ~CDF_LABELLING;
  710. +         acdunlock(acd);
  711. +         return error;
  712. +     case DIOCWLABEL:
  713. +         return EBADF;
  714. +     case CDIOCPLAYTRACKS:
  715. + #ifdef notyet
  716. +         {
  717. +         struct ioc_play_track *args = (struct ioc_play_track *)addr;
  718. +         struct acd_mode_data data;
  719. +         if (error = acd_get_mode(acd, &data, AUDIO_PAGE))
  720. +             return error;
  721. +         data.page.audio.flags &= ~CD_PA_SOTC;
  722. +         data.page.audio.flags |= CD_PA_IMMED;
  723. +         if (error = acd_set_mode(acd, &data))
  724. +             return error;
  725. +         return acd_play_tracks(acd, args->start_track, args->start_index,
  726. +             args->end_track, args->end_index);
  727. +     }
  728. + #else
  729. +     return ENOTTY;
  730. + #endif
  731. +     case CDIOCPLAYMSF:
  732. + #ifdef notyet
  733. +         {
  734. +         struct ioc_play_msf *args
  735. +         = (struct ioc_play_msf *)addr;
  736. +         struct cd_mode_data data;
  737. +         if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
  738. +             return error;
  739. +         data.page.audio.flags &= ~CD_PA_SOTC;
  740. +         data.page.audio.flags |= CD_PA_IMMED;
  741. +         if (error = cd_set_mode(cd, &data))
  742. +             return error;
  743. +         return cd_play_msf(cd, args->start_m, args->start_s,
  744. +             args->start_f, args->end_m, args->end_s, args->end_f);
  745. +     }
  746. + #else
  747. +     return ENOTTY; 
  748. + #endif
  749. +     case CDIOCPLAYBLOCKS:
  750. + #ifdef notyet
  751. +     {
  752. +         struct ioc_play_blocks *args
  753. +         = (struct ioc_play_blocks *)addr;
  754. +         struct cd_mode_data data;
  755. +         if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
  756. +             return error;
  757. +         data.page.audio.flags &= ~CD_PA_SOTC;
  758. +         data.page.audio.flags |= CD_PA_IMMED;
  759. +         if (error = cd_set_mode(cd, &data))
  760. +             return error;
  761. +         return cd_play(cd, args->blk, args->len);
  762. +     }
  763. + #else
  764. +     return ENOTTY; 
  765. + #endif
  766. +     case CDIOCREADSUBCHANNEL:
  767. + #ifdef notyet 
  768. +     {
  769. +         struct ioc_read_subchannel *args
  770. +         = (struct ioc_read_subchannel *)addr;
  771. +         struct cd_sub_channel_info data;
  772. +         int len = args->data_len;
  773. +         if (len > sizeof(data) ||
  774. +             len < sizeof(struct cd_sub_channel_header))
  775. +             return EINVAL;
  776. +         if (error = cd_read_subchannel(cd, args->address_format,
  777. +             args->data_format, args->track, &data, len))
  778. +             return error;
  779. +         len = min(len, ((data.header.data_len[0] << 8) +
  780. +             data.header.data_len[1] +
  781. +             sizeof(struct cd_sub_channel_header)));
  782. +         return copyout(&data, args->data, len);
  783. +     }
  784. + #else
  785. +     return ENOTTY; 
  786. + #endif
  787. +     case CDIOREADTOCHEADER:
  788. + #ifdef notyet
  789. +     {
  790. +         struct ioc_toc_header th;
  791. +         if (error = cd_read_toc(cd, 0, 0, &th, sizeof(th)))
  792. +             return error;
  793. +         th.len = ntohs(th.len);
  794. +         bcopy(&th, addr, sizeof(th));
  795. +         return 0;
  796. +     }
  797. + #else
  798. +     return ENOTTY; 
  799. + #endif
  800. +     case CDIOREADTOCENTRYS:
  801. + #ifdef notyet
  802. +     {
  803. +         struct cd_toc {
  804. +             struct ioc_toc_header header;
  805. +             struct cd_toc_entry entries[65];
  806. +         } data;
  807. +         struct ioc_read_toc_entry *te =
  808. +         (struct ioc_read_toc_entry *)addr;
  809. +         struct ioc_toc_header *th;
  810. +         int len = te->data_len;
  811. +         th = &data.header;
  812. +         if (len > sizeof(data.entries) ||
  813. +             len < sizeof(struct cd_toc_entry))
  814. +             return EINVAL;
  815. +         if (error = cd_read_toc(cd, te->address_format,
  816. +             te->starting_track, (struct cd_toc_entry *)&data,
  817. +             len + sizeof(struct ioc_toc_header)))
  818. +             return error;
  819. +         len = min(len, ntohs(th->len) - (sizeof(th->starting_track) +
  820. +             sizeof(th->ending_track)));
  821. +         return copyout(data.entries, te->data, len);
  822. +     }
  823. + #else
  824. +     return ENOTTY; 
  825. + #endif
  826. +     case CDIOCSETPATCH:
  827. + #ifdef notyet
  828. + {
  829. +         struct ioc_patch *arg = (struct ioc_patch *)addr;
  830. +         struct cd_mode_data data;
  831. +         if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
  832. +             return error;
  833. +         data.page.audio.port[LEFT_PORT].channels = arg->patch[0];
  834. +         data.page.audio.port[RIGHT_PORT].channels = arg->patch[1];
  835. +         data.page.audio.port[2].channels = arg->patch[2];
  836. +         data.page.audio.port[3].channels = arg->patch[3];
  837. +         return cd_set_mode(cd, &data);
  838. +     }
  839. + #else
  840. +     return ENOTTY; 
  841. + #endif
  842. +     case CDIOCGETVOL:
  843. + #ifdef notyet
  844. +     {
  845. +         struct ioc_vol *arg = (struct ioc_vol *)addr;
  846. +         struct cd_mode_data data;
  847. +         if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
  848. +             return error;
  849. +         arg->vol[LEFT_PORT] = data.page.audio.port[LEFT_PORT].volume;
  850. +         arg->vol[RIGHT_PORT] = data.page.audio.port[RIGHT_PORT].volume;
  851. +         arg->vol[2] = data.page.audio.port[2].volume;
  852. +         arg->vol[3] = data.page.audio.port[3].volume;
  853. +         return 0;
  854. +     }
  855. + #else
  856. +     return ENOTTY; 
  857. + #endif
  858. +     case CDIOCSETVOL:
  859. + #ifdef notyet
  860. + {
  861. +         struct ioc_vol *arg = (struct ioc_vol *)addr;
  862. +         struct cd_mode_data data;
  863. +         if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
  864. +             return error;
  865. +         data.page.audio.port[LEFT_PORT].channels = CHANNEL_0;
  866. +         data.page.audio.port[LEFT_PORT].volume = arg->vol[LEFT_PORT];
  867. +         data.page.audio.port[RIGHT_PORT].channels = CHANNEL_1;
  868. +         data.page.audio.port[RIGHT_PORT].volume = arg->vol[RIGHT_PORT];
  869. +         data.page.audio.port[2].volume = arg->vol[2];
  870. +         data.page.audio.port[3].volume = arg->vol[3];
  871. +         return cd_set_mode(cd, &data);
  872. +     }
  873. + #else
  874. +     return ENOTTY; 
  875. + #endif
  876. +     case CDIOCSETMONO:
  877. + #ifdef notyet
  878. +     {
  879. +         struct ioc_vol *arg = (struct ioc_vol *)addr;
  880. +         struct cd_mode_data data;
  881. +         if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
  882. +             return error;
  883. +         data.page.audio.port[LEFT_PORT].channels =
  884. +             LEFT_CHANNEL | RIGHT_CHANNEL | 4 | 8;
  885. +         data.page.audio.port[RIGHT_PORT].channels =
  886. +             LEFT_CHANNEL | RIGHT_CHANNEL;
  887. +         data.page.audio.port[2].channels = 0;
  888. +         data.page.audio.port[3].channels = 0;
  889. +         return cd_set_mode(cd, &data);
  890. +     }
  891. + #else
  892. +     return ENOTTY; 
  893. + #endif
  894. +     case CDIOCSETSTEREO:
  895. + #ifdef notyet
  896. +     {
  897. +         struct ioc_vol *arg = (struct ioc_vol *)addr;
  898. +         struct cd_mode_data data;
  899. +         if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
  900. +             return error;
  901. +         data.page.audio.port[LEFT_PORT].channels = LEFT_CHANNEL;
  902. +         data.page.audio.port[RIGHT_PORT].channels = RIGHT_CHANNEL;
  903. +         data.page.audio.port[2].channels = 0;
  904. +         data.page.audio.port[3].channels = 0;
  905. +         return cd_set_mode(cd, &data);
  906. +     }
  907. + #else
  908. +     return ENOTTY; 
  909. + #endif
  910. +     case CDIOCSETMUTE:
  911. + #ifdef notyet
  912. + {
  913. +         struct ioc_vol *arg = (struct ioc_vol *)addr;
  914. +         struct cd_mode_data data;
  915. +         if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
  916. +             return error;
  917. +         data.page.audio.port[LEFT_PORT].channels = 0;
  918. +         data.page.audio.port[RIGHT_PORT].channels = 0;
  919. +         data.page.audio.port[2].channels = 0;
  920. +         data.page.audio.port[3].channels = 0;
  921. +         return cd_set_mode(cd, &data);
  922. +     }
  923. + #else
  924. +     return ENOTTY; 
  925. + #endif
  926. +     case CDIOCSETLEFT:
  927. + #ifdef notyet
  928. + {
  929. +         struct ioc_vol *arg = (struct ioc_vol *)addr;
  930. +         struct cd_mode_data data;
  931. +         if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
  932. +             return error;
  933. +         data.page.audio.port[LEFT_PORT].channels = LEFT_CHANNEL;
  934. +         data.page.audio.port[RIGHT_PORT].channels = LEFT_CHANNEL;
  935. +         data.page.audio.port[2].channels = 0;
  936. +         data.page.audio.port[3].channels = 0;
  937. +         return cd_set_mode(cd, &data);
  938. +     }
  939. + #else
  940. +     return ENOTTY; 
  941. + #endif
  942. +     case CDIOCSETRIGHT:
  943. + #ifdef notyet
  944. + {
  945. +         struct ioc_vol *arg = (struct ioc_vol *)addr;
  946. +         struct cd_mode_data data;
  947. +         if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
  948. +             return error;
  949. +         data.page.audio.port[LEFT_PORT].channels = RIGHT_CHANNEL;
  950. +         data.page.audio.port[RIGHT_PORT].channels = RIGHT_CHANNEL;
  951. +         data.page.audio.port[2].channels = 0;
  952. +         data.page.audio.port[3].channels = 0;
  953. +         return cd_set_mode(cd, &data);
  954. +     }
  955. + #else
  956. +     return ENOTTY; 
  957. + #endif
  958. +     case CDIOCRESUME:
  959. +         return acd_pause(acd, 1);
  960. +     case CDIOCPAUSE:
  961. +         return acd_pause(acd, 0);
  962. +     case CDIOCSTART:
  963. +         return atapi_start_stop(acd->ad_link, SSS_START, 0);
  964. +     case CDIOCSTOP:
  965. +         return atapi_start_stop(acd->ad_link, SSS_STOP, 0);
  966. +     case CDIOCEJECT: /* FALLTHROUGH */
  967. +     case DIOCEJECT:
  968. +         return atapi_start_stop(acd->ad_link, SSS_STOP|SSS_LOEJ, 0);
  969. +     case CDIOCALLOW:
  970. +         return atapi_prevent(acd->ad_link, PR_ALLOW);
  971. +     case CDIOCPREVENT:
  972. +         return atapi_prevent(acd->ad_link, PR_PREVENT);
  973. +     case DIOCLOCK:
  974. +         return atapi_prevent(acd->ad_link,
  975. +             (*(int *)addr) ? PR_PREVENT : PR_ALLOW);
  976. +     case CDIOCRESET:
  977. +         return acd_reset(acd);
  978. +     default:
  979. +         return ENOTTY;
  980. +     }
  981. + #ifdef DIAGNOSTIC
  982. +     panic("cdioctl: impossible");
  983. + #endif
  984. + }
  985. + /*
  986. +  * Load the label information on the named device
  987. +  * Actually fabricate a disklabel
  988. +  *
  989. +  * EVENTUALLY take information about different
  990. +  * data tracks from the TOC and put it in the disklabel
  991. +  */
  992. + void
  993. + acdgetdisklabel(acd)
  994. +     struct acd_softc *acd;
  995. + {
  996. +     struct disklabel *lp = acd->sc_dk.dk_label;
  997. +     bzero(lp, sizeof(struct disklabel));
  998. +     bzero(acd->sc_dk.dk_cpulabel, sizeof(struct cpu_disklabel));
  999. + /*    lp->d_secsize = acd->params.blksize; /* XXX */
  1000. +     lp->d_secsize = 2048;
  1001. +     lp->d_ntracks = 1;
  1002. +     lp->d_nsectors = 100;
  1003. +     lp->d_ncylinders = (acd->params.disksize / 100) + 1;
  1004. +     lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
  1005. +     strncpy(lp->d_typename, "ATAPI CD-ROM", 16);
  1006. +     lp->d_type = DTYPE_SCSI; /* XXX */
  1007. +     strncpy(lp->d_packname, "fictitious", 16);
  1008. +     lp->d_secperunit = acd->params.disksize;
  1009. +     lp->d_rpm = 300;
  1010. +     lp->d_interleave = 1;
  1011. +     lp->d_flags = D_REMOVABLE;
  1012. +     lp->d_partitions[0].p_offset = 0;
  1013. +     lp->d_partitions[0].p_size =
  1014. +         lp->d_secperunit * (lp->d_secsize / DEV_BSIZE);
  1015. +     lp->d_partitions[0].p_fstype = FS_ISO9660;
  1016. +     lp->d_partitions[RAW_PART].p_offset = 0;
  1017. +     lp->d_partitions[RAW_PART].p_size =
  1018. +         lp->d_secperunit * (lp->d_secsize / DEV_BSIZE);
  1019. +     lp->d_partitions[RAW_PART].p_fstype = FS_ISO9660;
  1020. +     lp->d_npartitions = RAW_PART + 1;
  1021. +     lp->d_magic = DISKMAGIC;
  1022. +     lp->d_magic2 = DISKMAGIC;
  1023. +     lp->d_checksum = dkcksum(lp);
  1024. + }
  1025. + /*
  1026. +  * Find out from the device what it's capacity is
  1027. +  */
  1028. + u_long
  1029. + acd_size(cd, flags)
  1030. +     struct acd_softc *cd;
  1031. +     int flags;
  1032. + {
  1033. +     struct read_cd_capacity_data rdcap;
  1034. +     struct read_cd_capacity cmd;
  1035. +     u_long blksize;
  1036. +     u_long size;
  1037. +     /*
  1038. +      * make up a atapi command and ask the atapi driver to do
  1039. +      * it for you.
  1040. +      */
  1041. +     bzero(&cmd, sizeof(cmd));
  1042. +     cmd.operation_code = ATAPI_READ_CD_CAPACITY;
  1043. +     cmd.len = sizeof(rdcap);
  1044. +     /*
  1045. +      * If the command works, interpret the result as a 4 byte
  1046. +      * number of blocks and a blocksize
  1047. +      */
  1048. +     if (atapi_exec_cmd(cd->ad_link, &cmd , sizeof(cmd),
  1049. +         &rdcap, sizeof(rdcap), B_READ, 0) != 0) {
  1050. + #ifdef ATAPI_DEBUG
  1051. +         printf("ATAPI_READ_CD_CAPACITY failed\n");
  1052. + #endif
  1053. +         return 0;
  1054. +     }
  1055. +     blksize = ntohl(rdcap.blksize);
  1056. +     if (blksize < 512)
  1057. +         blksize = 2048;    /* some drives lie ! */
  1058. +     cd->params.blksize = blksize;
  1059. +     size = ntohl(size);
  1060. +     if (size < 100)
  1061. +         size = 400000;    /* ditto */
  1062. +     cd->params.disksize = size;
  1063. + #ifdef ATAPI_DEBUG
  1064. +     printf("acd_size: %ld %ld\n",blksize,size);
  1065. + #endif
  1066. +     return size;
  1067. + }
  1068. + #ifdef notyet
  1069. + /*
  1070. +  * Get the requested page into the buffer given
  1071. +  */
  1072. + int
  1073. + cd_get_mode(cd, data, page)
  1074. +     struct acd_softc *cd;
  1075. +     struct cd_mode_data *data;
  1076. +     int page;
  1077. + {
  1078. +     struct scsi_mode_sense scsi_cmd;
  1079. +     int error;
  1080. +     bzero(&scsi_cmd, sizeof(scsi_cmd));
  1081. +     bzero(data, sizeof(*data));
  1082. +     scsi_cmd.opcode = MODE_SENSE;
  1083. +     scsi_cmd.page = page;
  1084. +     scsi_cmd.length = sizeof(*data) & 0xff;
  1085. +     return scsi_scsi_cmd(cd->ad_link, (struct scsi_generic *)&scsi_cmd,
  1086. +         sizeof(scsi_cmd), (u_char *)data, sizeof(*data), CDRETRIES, 20000,
  1087. +         NULL, SCSI_DATA_IN);
  1088. + }
  1089. + /*
  1090. +  * Get the requested page into the buffer given
  1091. +  */
  1092. + int
  1093. + cd_set_mode(cd, data)
  1094. +     struct acd_softc *cd;
  1095. +     struct cd_mode_data *data;
  1096. + {
  1097. +     struct scsi_mode_select scsi_cmd;
  1098. +     bzero(&scsi_cmd, sizeof(scsi_cmd));
  1099. +     scsi_cmd.opcode = MODE_SELECT;
  1100. +     scsi_cmd.byte2 |= SMS_PF;
  1101. +     scsi_cmd.length = sizeof(*data) & 0xff;
  1102. +     data->header.data_length = 0;
  1103. +     return scsi_scsi_cmd(cd->ad_link, (struct scsi_generic *)&scsi_cmd,
  1104. +         sizeof(scsi_cmd), (u_char *)data, sizeof(*data), CDRETRIES, 20000,
  1105. +         NULL, SCSI_DATA_OUT);
  1106. + }
  1107. + /*
  1108. +  * Get scsi driver to send a "start playing" command
  1109. +  */
  1110. + int
  1111. + cd_play(cd, blkno, nblks)
  1112. +     struct acd_softc *cd;
  1113. +     int blkno, nblks;
  1114. + {
  1115. +     struct scsi_play scsi_cmd;
  1116. +     bzero(&scsi_cmd, sizeof(scsi_cmd));
  1117. +     scsi_cmd.opcode = PLAY;
  1118. +     scsi_cmd.blk_addr[0] = (blkno >> 24) & 0xff;
  1119. +     scsi_cmd.blk_addr[1] = (blkno >> 16) & 0xff;
  1120. +     scsi_cmd.blk_addr[2] = (blkno >> 8) & 0xff;
  1121. +     scsi_cmd.blk_addr[3] = blkno & 0xff;
  1122. +     scsi_cmd.xfer_len[0] = (nblks >> 8) & 0xff;
  1123. +     scsi_cmd.xfer_len[1] = nblks & 0xff;
  1124. +     return scsi_scsi_cmd(cd->ad_link, (struct scsi_generic *)&scsi_cmd,
  1125. +         sizeof(scsi_cmd), 0, 0, CDRETRIES, 200000, NULL, 0);
  1126. + }
  1127. + /*
  1128. +  * Get scsi driver to send a "start playing" command
  1129. +  */
  1130. + int
  1131. + cd_play_big(cd, blkno, nblks)
  1132. +     struct acd_softc *cd;
  1133. +     int blkno, nblks;
  1134. + {
  1135. +     struct scsi_play_big scsi_cmd;
  1136. +     bzero(&scsi_cmd, sizeof(scsi_cmd));
  1137. +     scsi_cmd.opcode = PLAY_BIG;
  1138. +     scsi_cmd.blk_addr[0] = (blkno >> 24) & 0xff;
  1139. +     scsi_cmd.blk_addr[1] = (blkno >> 16) & 0xff;
  1140. +     scsi_cmd.blk_addr[2] = (blkno >> 8) & 0xff;
  1141. +     scsi_cmd.blk_addr[3] = blkno & 0xff;
  1142. +     scsi_cmd.xfer_len[0] = (nblks >> 24) & 0xff;
  1143. +     scsi_cmd.xfer_len[1] = (nblks >> 16) & 0xff;
  1144. +     scsi_cmd.xfer_len[2] = (nblks >> 8) & 0xff;
  1145. +     scsi_cmd.xfer_len[3] = nblks & 0xff;
  1146. +     return scsi_scsi_cmd(cd->ad_link, (struct scsi_generic *)&scsi_cmd,
  1147. +         sizeof(scsi_cmd), 0, 0, CDRETRIES, 20000, NULL, 0);
  1148. + }
  1149. + /*
  1150. +  * Get scsi driver to send a "start playing" command
  1151. +  */
  1152. + int
  1153. + cd_play_tracks(cd, strack, sindex, etrack, eindex)
  1154. +     struct acd_softc *cd;
  1155. +     int strack, sindex, etrack, eindex;
  1156. + {
  1157. +     struct scsi_play_track scsi_cmd;
  1158. +     bzero(&scsi_cmd, sizeof(scsi_cmd));
  1159. +     scsi_cmd.opcode = PLAY_TRACK;
  1160. +     scsi_cmd.start_track = strack;
  1161. +     scsi_cmd.start_index = sindex;
  1162. +     scsi_cmd.end_track = etrack;
  1163. +     scsi_cmd.end_index = eindex;
  1164. +     return scsi_scsi_cmd(cd->ad_link, (struct scsi_generic *)&scsi_cmd,
  1165. +         sizeof(scsi_cmd), 0, 0, CDRETRIES, 20000, NULL, 0);
  1166. + }
  1167. + /*
  1168. +  * Get scsi driver to send a "play msf" command
  1169. +  */
  1170. + int
  1171. + cd_play_msf(cd, startm, starts, startf, endm, ends, endf)
  1172. +     struct acd_softc *cd;
  1173. +     int startm, starts, startf, endm, ends, endf;
  1174. + {
  1175. +     struct scsi_play_msf scsi_cmd;
  1176. +     bzero(&scsi_cmd, sizeof(scsi_cmd));
  1177. +     scsi_cmd.opcode = PLAY_MSF;
  1178. +     scsi_cmd.start_m = startm;
  1179. +     scsi_cmd.start_s = starts;
  1180. +     scsi_cmd.start_f = startf;
  1181. +     scsi_cmd.end_m = endm;
  1182. +     scsi_cmd.end_s = ends;
  1183. +     scsi_cmd.end_f = endf;
  1184. +     return scsi_scsi_cmd(cd->ad_link, (struct scsi_generic *)&scsi_cmd,
  1185. +         sizeof(scsi_cmd), 0, 0, CDRETRIES, 2000, NULL, 0);
  1186. + }
  1187. + #endif  /* notyet */
  1188. + /*
  1189. +  * Get atapi driver to send a "start up" command
  1190. +  */
  1191. + int
  1192. + acd_pause(acd, go)
  1193. +     struct acd_softc *acd;
  1194. +     int go;
  1195. + {
  1196. +     struct pause_resume cmd;
  1197. +     bzero(&cmd, sizeof(cmd));
  1198. +     cmd.operation_code = ATAPI_PAUSE_RESUME;
  1199. +     cmd.resume = go;
  1200. +     return atapi_exec_cmd(acd->ad_link, &cmd , sizeof(cmd), 0, 0, 0, 0);
  1201. + }
  1202. + /*
  1203. +  * Get atapi driver to send a "RESET" command
  1204. +  */
  1205. + int
  1206. + acd_reset(acd)
  1207. +     struct acd_softc *acd;
  1208. + {
  1209. + #ifdef notyet    
  1210. +     return atapi_soft_reset(acd->ad_link);
  1211. + #else
  1212. +      return 0;
  1213. + #endif
  1214. + }
  1215. + #ifdef notyet
  1216. + /*
  1217. +  * Read subchannel
  1218. +  */
  1219. + int
  1220. + cd_read_subchannel(cd, mode, format, track, data, len)
  1221. +     struct acd_softc *cd;
  1222. +     int mode, format, len;
  1223. +     struct cd_sub_channel_info *data;
  1224. + {
  1225. +     struct scsi_read_subchannel scsi_cmd;
  1226. +     bzero(&scsi_cmd, sizeof(scsi_cmd));
  1227. +     scsi_cmd.opcode = READ_SUBCHANNEL;
  1228. +     if (mode == CD_MSF_FORMAT)
  1229. +         scsi_cmd.byte2 |= CD_MSF;
  1230. +     scsi_cmd.byte3 = SRS_SUBQ;
  1231. +     scsi_cmd.subchan_format = format;
  1232. +     scsi_cmd.track = track;
  1233. +     scsi_cmd.data_len[0] = (len >> 8) & 0xff;
  1234. +     scsi_cmd.data_len[1] = len & 0xff;
  1235. +     return scsi_scsi_cmd(cd->ad_link, (struct scsi_generic *)&scsi_cmd,
  1236. +         sizeof(struct scsi_read_subchannel), (u_char *)data, len,
  1237. +         CDRETRIES, 5000, NULL, SCSI_DATA_IN);
  1238. + }
  1239. + /*
  1240. +  * Read table of contents
  1241. +  */
  1242. + int
  1243. + cd_read_toc(cd, mode, start, data, len)
  1244. +     struct acd_softc *cd;
  1245. +     int mode, start, len;
  1246. +     struct cd_toc_entry *data;
  1247. + {
  1248. +     struct scsi_read_toc scsi_cmd;
  1249. +     int ntoc;
  1250. +     bzero(&scsi_cmd, sizeof(scsi_cmd));
  1251. +     /*if (len!=sizeof(struct ioc_toc_header))
  1252. +      * ntoc=((len)-sizeof(struct ioc_toc_header))/sizeof(struct cd_toc_entry);
  1253. +      * else */
  1254. +     ntoc = len;
  1255. +     scsi_cmd.opcode = READ_TOC;
  1256. +     if (mode == CD_MSF_FORMAT)
  1257. +         scsi_cmd.byte2 |= CD_MSF;
  1258. +     scsi_cmd.from_track = start;
  1259. +     scsi_cmd.data_len[0] = (ntoc >> 8) & 0xff;
  1260. +     scsi_cmd.data_len[1] = ntoc & 0xff;
  1261. +     return scsi_scsi_cmd(cd->ad_link, (struct scsi_generic *)&scsi_cmd,
  1262. +         sizeof(struct scsi_read_toc), (u_char *)data, len, CDRETRIES,
  1263. +         5000, NULL, SCSI_DATA_IN);
  1264. + }
  1265. + #endif /* notyet */
  1266. + /*
  1267. +  * Get the atapi driver to send a full inquiry to the device and use the
  1268. +  * results to fill out the disk parameter structure.
  1269. +  */
  1270. + int
  1271. + acd_get_parms(acd, flags)
  1272. +     struct acd_softc *acd;
  1273. +     int flags;
  1274. + {
  1275. +     /*
  1276. +      * give a number of sectors so that sec * trks * cyls
  1277. +      * is <= disk_size
  1278. +      */
  1279. +     if (acd_size(acd, flags) == 0)
  1280. +         return ENXIO;
  1281. +     return 0;
  1282. + }
  1283. + int
  1284. + acdsize(dev)
  1285. +     dev_t dev;
  1286. + {
  1287. +     /* CD-ROMs are read-only. */
  1288. +     return -1;
  1289. + }
  1290. + void acdminphys(bp)
  1291. + struct buf *bp;
  1292. + {
  1293. +     minphys(bp);
  1294. + }
  1295. + int
  1296. + acddump(dev, blkno, va, size)
  1297. +     dev_t dev;
  1298. +     daddr_t blkno;
  1299. +     caddr_t va;
  1300. +     size_t size;
  1301. + {
  1302. +     /* Not implemented. */
  1303. +     return ENXIO;
  1304. + }
  1305. + int
  1306. + acddone(acp)
  1307. + struct atapi_command_packet *acp;
  1308. + {
  1309. +     struct at_dev_link *ad_link = acp->ad_link;
  1310. +     struct acd_softc *acd = ad_link->device_softc;
  1311. +     if (acp->bp != NULL)
  1312. +         disk_unbusy(&acd->sc_dk, (acp->bp->b_bcount - acp->bp->b_resid));
  1313. +     return (0);     
  1314. + }   
  1315. diff --exclude compile -bcrNP src.orig/sys/atapi/atapi.h src/sys/atapi/atapi.h
  1316. *** src.orig/sys/atapi/atapi.h    Thu Jan  1 01:00:00 1970
  1317. --- src/sys/atapi/atapi.h    Thu Jan 11 22:03:56 1996
  1318. ***************
  1319. *** 0 ****
  1320. --- 1,244 ----
  1321. + /*
  1322. +  * Copyright (c) 1996 Manuel Bouyer.  All rights reserved.
  1323. +  *
  1324. +  * Redistribution and use in source and binary forms, with or without
  1325. +  * modification, are permitted provided that the following conditions
  1326. +  * are met:
  1327. +  * 1. Redistributions of source code must retain the above copyright
  1328. +  *    notice, this list of conditions and the following disclaimer.
  1329. +  * 2. Redistributions in binary form must reproduce the above copyright
  1330. +  *    notice, this list of conditions and the following disclaimer in the
  1331. +  *    documentation and/or other materials provided with the distribution.
  1332. +  * 3. All advertising materials mentioning features or use of this software
  1333. +  *    must display the following acknowledgement:
  1334. +  *  This product includes software developed by Manuel Bouyer.
  1335. +  * 4. The name of the author may not be used to endorse or promote products
  1336. +  *    derived from this software without specific prior written permission.
  1337. +  *
  1338. +  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  1339. +  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  1340. +  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  1341. +  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  1342. +  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  1343. +  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  1344. +  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  1345. +  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  1346. +  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  1347. +  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  1348. +  */
  1349. + /* Definition of atapi commands and associated data structures */
  1350. + /* 
  1351. +    TEST UNIT READY (mandatory)
  1352. +  */
  1353. + #define ATAPI_TEST_UNIT_READY           0x00
  1354. + struct test_unit_ready {
  1355. +     u_char  operation_code;
  1356. +     u_char  reserved1[15];
  1357. + };
  1358. + /* 
  1359. +    START/STOP UNIT (mandatory)
  1360. +    */ 
  1361. +  
  1362. + #define ATAPI_START_STOP_UNIT           0x1b
  1363. +  
  1364. + struct start_stop_unit {
  1365. +     u_char  operation_code;
  1366. +     u_char  immed       :1;
  1367. +     u_char  reserved1   :7;
  1368. +     u_char  reserved2[2]; 
  1369. +     u_char  how;
  1370. + #define SSS_STOP        0x00 
  1371. + #define SSS_START       0x01
  1372. + #define SSS_LOEJ        0x02
  1373. +     u_char  reserved4[11];
  1374. + };
  1375. + /* 
  1376. +    PREVENT/ALLOW MEDIUM REMOVAL (mandatory)
  1377. +    */ 
  1378. +  
  1379. + #define ATAPI_PREVENT_ALLOW_MEDIUM_REMOVAL  0x1e
  1380. +  
  1381. + struct prevent_allow_medium_removal {
  1382. +     u_char  operation_code;
  1383. +     u_char  reserved1[3];
  1384. +     u_char  prevent     :1;
  1385. + #define PR_PREVENT 0x01
  1386. + #define PR_ALLOW   0x00
  1387. +     u_char  reserved2   :7;
  1388. +     u_char  reserved3[11];
  1389. + };
  1390. + /* 
  1391. +    READ CD CAPACITY (mandatory)
  1392. +  */
  1393. +        
  1394. + #define ATAPI_READ_CD_CAPACITY          0x25
  1395. +     
  1396. + struct read_cd_capacity {
  1397. +     u_char  operation_code;
  1398. +     u_char  reserved1[7];
  1399. +     u_char len;
  1400. +     u_char reserved2[7];
  1401. + };
  1402. + /* 
  1403. +  * Volume size info.
  1404. +  */
  1405. + struct read_cd_capacity_data {
  1406. +     u_long size;         /* Volume size in blocks */
  1407. +     u_long blksize;         /* Block size in bytes */
  1408. + };
  1409. + /*
  1410. +    READ (10) (mandatory)
  1411. +  */  
  1412. +     
  1413. + #define ATAPI_READ              0x28  
  1414. + struct read {    
  1415. +     u_char  operation_code;
  1416. +     u_char  reserved1;  
  1417. +     u_char  lba[4];       
  1418. +     u_char  reserved2;            
  1419. +     u_char  length[2];                    
  1420. +     u_char  reserved3[7];                         
  1421. + }; 
  1422. + /* 
  1423. +    PAUSE/RESUME (optional) 
  1424. +  */ 
  1425. +  
  1426. + #define ATAPI_PAUSE_RESUME      0x4b
  1427. +  
  1428. + struct pause_resume {
  1429. +     u_char  operation_code;
  1430. +     u_char  reserved1[7];
  1431. +     u_char  resume      :1;
  1432. +     u_char  reserved2   :7;
  1433. +     u_char  reserved3[7];
  1434. + };
  1435. + /*
  1436. +    MODE SENSE (mandatory)
  1437. +    */
  1438. + #define ATAPI_MODE_SENSE        0x5a
  1439. + struct mode_sense {
  1440. +     u_char  operation_code;
  1441. +     u_char  reserved1;
  1442. +     u_char  page_code   :6;
  1443. +     u_char  page_control    :2;  /* page control */
  1444. +     u_char  reserved2[4];
  1445. +     u_char  length[2];
  1446. +     u_char  reserved3[7];
  1447. + };
  1448. + struct cappage {
  1449. +     /* Mode data header */
  1450. +     u_short data_length;
  1451. +     u_char  medium_type;
  1452. + #define MDT_UNKNOWN     0x00        
  1453. + #define MDT_DATA_120    0x01
  1454. + #define MDT_AUDIO_120   0x02
  1455. + #define MDT_COMB_120    0x03    
  1456. + #define MDT_PHOTO_120   0x04    
  1457. + #define MDT_DATA_80     0x05
  1458. + #define MDT_AUDIO_80    0x06
  1459. + #define MDT_COMB_80     0x07 
  1460. + #define MDT_PHOTO_80    0x08
  1461. + #define MDT_NO_DISC     0x70
  1462. + #define MDT_DOOR_OPEN   0x71
  1463. + #define MDT_FMT_ERROR   0x72
  1464. +     u_char  reserved1[5];
  1465. +     /* Capabilities page */
  1466. +     u_char  page_code;
  1467. + #define CAP_PAGE        0x2a
  1468. +     u_char  param_len;
  1469. +     u_char  reserved2[2];
  1470. +     u_char  audio_play : 1;         /* audio play supported */
  1471. +     u_char  composite : 1;          /* composite audio/video supported */
  1472. +     u_char  dport1 : 1;             /* digital audio on port 1 */
  1473. +     u_char  dport2 : 1;             /* digital audio on port 2 */
  1474. +     u_char  mode2_form1 : 1;        /* mode 2 form 1 (XA) read */
  1475. +     u_char  mode2_form2 : 1;        /* mode 2 form 2 format */
  1476. +     u_char  multisession : 1;       /* multi-session photo-CD */
  1477. +     u_char  : 1;
  1478. +     u_char  cd_da : 1;              /* audio-CD read supported */
  1479. +     u_char  cd_da_stream : 1;       /* CD-DA streaming */
  1480. +     u_char  rw : 1;                 /* combined R-W subchannels */
  1481. +     u_char  rw_corr : 1;            /* R-W subchannel data corrected */
  1482. +     u_char  c2 : 1;                 /* C2 error pointers supported */
  1483. +     u_char  isrc : 1;               /* can return the ISRC info */
  1484. +     u_char  upc : 1;                /* can return the catalog number UPC */
  1485. +     u_char  : 1;
  1486. +     u_char  lock : 1;               /* could be locked */
  1487. +     u_char  locked : 1;             /* current lock state */
  1488. +     u_char  prevent : 1;            /* prevent jumper installed */
  1489. +     u_char  eject : 1;              /* can eject */
  1490. +     u_char  : 1;
  1491. +     u_char  mech : 3;               /* loading mechanism type */
  1492. + #define MECH_CADDY      0
  1493. + #define MECH_TRAY       1
  1494. + #define MECH_POPUP      2
  1495. + #define MECH_CHANGER    4
  1496. + #define MECH_CARTRIDGE  5
  1497. +     u_char  sep_vol : 1;            /* independent volume of channels */
  1498. +     u_char  sep_mute : 1;           /* independent mute of channels */
  1499. +     u_char  : 6;
  1500. +     u_short max_speed;              /* max raw data rate in bytes/1000 */
  1501. +     u_short max_vol_levels;         /* number of discrete volume levels */
  1502. +     u_short buf_size;               /* internal buffer size in bytes/1024 */
  1503. +     u_short cur_speed;              /* current data rate in bytes/1000  */
  1504. +     /* Digital drive output format description (optional?) */
  1505. +     u_char  reserved3;
  1506. +     u_char  bckf : 1;               /* data valid on failing edge of BCK */
  1507. +     u_char  rch : 1;                /* high LRCK indicates left channel */
  1508. +     u_char  lsbf : 1;               /* set if LSB first */
  1509. +     u_char  dlen: 2;
  1510. + #define DLEN_32         0               /* 32 BCKs */
  1511. + #define DLEN_16         1               /* 16 BCKs */
  1512. + #define DLEN_24         2               /* 24 BCKs */
  1513. + #define DLEN_24_I2S     3               /* 24 BCKs (I2S) */
  1514. +     u_char  : 3;
  1515. +     u_char  reserved4[2];
  1516. + };
  1517. + /* ATAPI error codes */
  1518. + #define ATAPI_SK_NO_SENSE       0x0
  1519. + #define ATAPI_SK_REC_ERROR      0x1  /* recovered error */
  1520. + #define ATAPI_SK_NOT_READY      0x2
  1521. + #define ATAPI_SK_MEDIUM_ERROR       0x3
  1522. + #define ATAPI_SK_HARDWARE_ERROR     0x4
  1523. + #define ATAPI_SK_ILLEGAL_REQUEST    0x5
  1524. + #define ATAPI_SK_UNIT_ATTENTION     0x6
  1525. + #define ATAPI_SK_DATA_PROTECT       0x7
  1526. +                          /* 0x8 reserved */
  1527. +                          /* 0x9-0xa reserved */
  1528. + #define ATAPI_SK_ABORTED_COMMAND    0xb
  1529. +                         /* 0xc-0xd not referenced */
  1530. + #define ATAPI_SK_MISCOMPARE     0xe
  1531. +                         /* 0xf reserved */
  1532. + #define ATAPI_MCR           0x08 /* media change requested */
  1533. + #define ATAPI_ABRT          0x04 /* aborted command */
  1534. + #define ATAPI_EOM           0x02 /* end of media */
  1535. + #define ATAPI_ILI           0x01 /* illegal length indication */
  1536. + int atapi_exec_cmd __P((struct at_dev_link *, void*, int, void*, int, long, int));
  1537. + int atapi_exec_io __P((struct at_dev_link *, void *, int, struct buf *, int));
  1538. + int atapi_test_unit_ready __P((struct at_dev_link  *, int));
  1539. + int atapi_start_stop __P((struct at_dev_link  *, int, int));
  1540. + int atapi_prevent __P((struct at_dev_link  *, int));
  1541. diff --exclude compile -bcrNP src.orig/sys/atapi/atapiconf.c src/sys/atapi/atapiconf.c
  1542. *** src.orig/sys/atapi/atapiconf.c    Thu Jan  1 01:00:00 1970
  1543. --- src/sys/atapi/atapiconf.c    Fri Apr 19 16:17:56 1996
  1544. ***************
  1545. *** 0 ****
  1546. --- 1,588 ----
  1547. + /*
  1548. +  * Copyright (c) 1996 Manuel Bouyer.  All rights reserved.
  1549. +  *
  1550. +  * Redistribution and use in source and binary forms, with or without
  1551. +  * modification, are permitted provided that the following conditions
  1552. +  * are met:
  1553. +  * 1. Redistributions of source code must retain the above copyright
  1554. +  *    notice, this list of conditions and the following disclaimer.
  1555. +  * 2. Redistributions in binary form must reproduce the above copyright
  1556. +  *    notice, this list of conditions and the following disclaimer in the
  1557. +  *    documentation and/or other materials provided with the distribution.
  1558. +  * 3. All advertising materials mentioning features or use of this software
  1559. +  *    must display the following acknowledgement:
  1560. +  *  This product includes software developed by Manuel Bouyer.
  1561. +  * 4. The name of the author may not be used to endorse or promote products
  1562. +  *    derived from this software without specific prior written permission.
  1563. +  *
  1564. +  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  1565. +  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  1566. +  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  1567. +  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  1568. +  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  1569. +  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  1570. +  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  1571. +  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  1572. +  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  1573. +  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  1574. +  */
  1575. + #include <sys/types.h>
  1576. + #include <sys/param.h>
  1577. + #include <sys/systm.h>
  1578. + #include <sys/malloc.h>
  1579. + #include <sys/device.h>
  1580. + #include <sys/buf.h>
  1581. + #include <sys/proc.h>  
  1582. + #include <atapi/atapilink.h>
  1583. + #include <atapi/atapi.h>
  1584. + #define SILENT_PRINTF(flags,string) if (!(flags & A_SILENT)) printf string
  1585. + struct atapibus_softc {
  1586. +     struct device sc_dev;
  1587. +     struct bus_link *b_link;
  1588. +     struct atapi_devices *ad_link[2];
  1589. + };
  1590. + LIST_HEAD(pkt_free_list, atapi_command_packet) pkt_free_list;
  1591. + void bswap __P((char*, int));
  1592. + void btrim __P((char*, int));
  1593. + int atapi_error __P((struct atapi_command_packet*));
  1594. + void atapi_sense __P((struct atapi_command_packet*, u_char, u_char));
  1595. + void at_print_addr __P((struct at_dev_link*, u_char));
  1596. + int atapibusmatch __P((struct device *, void *, void *));
  1597. + void atapibusattach __P((struct device *, struct device *, void *));
  1598. + struct cfattach atapibus_ca = {
  1599. +     sizeof(struct atapibus_softc), atapibusmatch, atapibusattach,
  1600. + };
  1601. + struct cfdriver atapibus_cd = {
  1602. +     NULL, "atapibus", DV_DULL
  1603. + };
  1604. + int
  1605. + atapibusmatch(parent, match, aux)
  1606. +         struct device *parent;
  1607. +         void *match, *aux;
  1608. + {
  1609. +     struct cfdata *cf = match;
  1610. +     struct bus_link *ab_link = aux;
  1611. +     if (ab_link == NULL ) return 0;
  1612. +     if (ab_link-> type != BUS) return 0;
  1613. +     return 1;
  1614. + }
  1615. + int
  1616. + atapiprint(aux, bus)
  1617. +     void *aux;
  1618. +     char *bus;
  1619. + {
  1620. +     struct at_dev_link *ad_link = aux;
  1621. +  
  1622. +      if (!bus)
  1623. +          printf(" drive %d: ", ad_link->drive); 
  1624. +      return QUIET; 
  1625. + }
  1626. + void atapibusattach(parent, self, aux)
  1627. +         struct device *parent, *self;
  1628. +         void *aux;
  1629. + {
  1630. +     struct atapibus_softc *ab = (struct atapibus_softc *)self;
  1631. +     struct bus_link *ab_link_proto = aux;
  1632. +     int drive;
  1633. +     struct atapi_identify ids;
  1634. +     struct atapi_identify *id = &ids;
  1635. +     struct at_dev_link *ad_link;
  1636. +     ab_link_proto->atapibus_softc = (caddr_t)ab;
  1637. +     ab->b_link = ab_link_proto;
  1638. +     printf("\n");
  1639. +     for (drive = 0; drive < 2 ; drive++) {
  1640. +         if (wdc_atapi_get_params(ab_link_proto, drive, id)) {
  1641. +             /*
  1642. +              * Shuffle string byte order.
  1643. +              * Mitsumi and NEC drives don't need this.
  1644. +              */
  1645. +             if (! ((id->model[0] == 'N' && id->model[1] == 'E') ||
  1646. +                 (id->model[0] == 'F' && id->model[1] == 'X')))
  1647. +                 bswap(id->model, sizeof(id->model));
  1648. +             bswap (id->serial_number, sizeof(id->serial_number));
  1649. +             bswap (id->firmware_revision, sizeof(id->firmware_revision));
  1650. +             /* Clean up the model name, serial and revision numbers. */
  1651. +             btrim (id->model, sizeof(id->model));
  1652. +             btrim (id->serial_number, sizeof(id->serial_number));
  1653. +             btrim (id->firmware_revision, sizeof(id->firmware_revision));
  1654. +             printf("atapibus%d drive%d: <%s, %s, %s> ",
  1655. +                 ab->sc_dev.dv_unit, drive, id->model, id->serial_number, id->firmware_revision);
  1656. +             switch (id->config.device_type) {
  1657. +             case ATAPI_DEVICE_TYPE_DAD: printf("direct, ");
  1658. +                                        break;
  1659. +             case ATAPI_DEVICE_TYPE_CD: printf("cdrom, ");
  1660. +                                        break;
  1661. +             case ATAPI_DEVICE_TYPE_OMD: printf(" optical, ");
  1662. +                                        break;
  1663. +             default: printf(" unknown type %d, ",id->config.device_type);
  1664. +             }
  1665. +             printf("%s.\n", id->config.removable?"removable":"fixed");
  1666. + #ifdef ATAPI_DEBUG_PROBE
  1667. +             printf("cmdsz %d drqtype %d\n",id->config.packet_size, id->config.drq_type);
  1668. + #endif
  1669. +             
  1670. +             ad_link = malloc(sizeof(*ad_link), M_DEVBUF, M_NOWAIT);
  1671. +             if (ad_link == NULL) {
  1672. +                 printf("Warning: cannot allocate memory for device\n");
  1673. +                 continue;
  1674. +             }
  1675. +             ad_link->drive = drive;
  1676. +             if (id->config.packet_size) ad_link->flags |= ACAP_LEN;
  1677. +             ad_link->flags |= id->config.drq_type << 8;
  1678. +             bcopy(id, &ad_link->id, sizeof(*id));
  1679. +             ad_link->bus=ab_link_proto;
  1680. +             if (config_found(self,ad_link,atapiprint) == NULL) {
  1681. +                 printf("atapibus:config not found\n");
  1682. +                 free(ad_link,M_DEVBUF);
  1683. +             }
  1684. +         }
  1685. +     }
  1686. + }
  1687. + void
  1688. + bswap (buf, len)
  1689. + char *buf;
  1690. + int len;
  1691. + {       
  1692. +     u_short *p = (u_short*) (buf + len);
  1693. +     while (--p >= (u_short*) buf)
  1694. +             *p = ntohs (*p);
  1695. + }   
  1696. + void
  1697. + btrim (buf, len)
  1698. + char *buf;
  1699. + int len;
  1700. + {
  1701. +     char *p; 
  1702. +      
  1703. +      /* Remove the trailing spaces. */
  1704. +      for (p=buf; p<buf+len; ++p)
  1705. +          if (! *p)
  1706. +              *p = ' ';
  1707. +          for (p=buf+len-1; p>=buf && *p==' '; --p)
  1708. +              *p = 0;
  1709. + }
  1710. + int atapi_exec_cmd(ad_link, cmd, cmd_size, databuf, datalen, rw, flags)
  1711. + struct at_dev_link *ad_link;
  1712. + void *cmd;
  1713. + int cmd_size;
  1714. + void *databuf;
  1715. + int datalen;
  1716. + long rw;
  1717. + int flags;
  1718. + {
  1719. +     struct atapi_command_packet *pkt;
  1720. +     struct bus_link *b_link = ad_link->bus;
  1721. +     int status, s;
  1722. +     pkt = atapi_get_pkt(ad_link, flags);
  1723. +     if (!pkt) return -1;
  1724. +     bcopy(cmd, &pkt->cmd_store, cmd_size);
  1725. +     pkt->command = &pkt->cmd_store;
  1726. +     pkt->command_size = (ad_link->flags & ACAP_LEN)?16:12;
  1727. +     pkt->databuf = databuf;
  1728. +     pkt->data_size = datalen;
  1729. +     pkt->flags = rw|(flags & 0xff)| (ad_link->flags & 0x0300);
  1730. +     pkt->drive = ad_link->drive;
  1731. +     wdc_atapi_send_command_packet(b_link, pkt);
  1732. +     if ((flags & (A_POLLED|A_NOSLEEP)) == 0 ) {
  1733. + #ifdef ATAPI_DEBUG_CMD
  1734. +         printf("atapi_exec_cmd: sleeping\n");
  1735. + #endif
  1736. +         s=splbio();
  1737. +         while ((pkt->status & ITSDONE) == 0)
  1738. +             tsleep(pkt,PRIBIO+1,"atapicmd",0);
  1739. +         splx(s);
  1740. + #ifdef ATAPI_DEBUG_CMD
  1741. +         printf("atapi_exec_cmd: done sleeping\n");
  1742. + #endif
  1743. +         status = pkt->status & STATUS_MASK;
  1744. +         atapi_free_pkt(pkt);
  1745. +     } else {
  1746. +         if ((flags & A_POLLED) != 0) {
  1747. +             if ((pkt->status & ERROR) && (pkt->error)) {
  1748. +                 atapi_error(pkt);
  1749. +                 SILENT_PRINTF(flags,("\n"));
  1750. +             }
  1751. +         }
  1752. +         status = pkt->status & STATUS_MASK;
  1753. +         if ((flags & A_POLLED) != 0)
  1754. +             atapi_free_pkt(pkt);
  1755. +     }
  1756. +     return status;
  1757. + }
  1758. + int atapi_exec_io(ad_link, cmd, cmd_size, bp, flags)
  1759. + struct at_dev_link *ad_link;
  1760. + void *cmd;
  1761. + int cmd_size;
  1762. + struct buf *bp;
  1763. + int flags;
  1764. + {
  1765. +     struct atapi_command_packet *pkt;
  1766. +     struct bus_link *b_link = ad_link->bus;
  1767. +     pkt = atapi_get_pkt(ad_link, flags);
  1768. +     if (pkt == NULL) {
  1769. +         printf("atapi_exec_io: no pkt\n");
  1770. +         return ERROR;
  1771. +     }
  1772. +     bcopy(cmd, &pkt->cmd_store, cmd_size);
  1773. +     pkt->command = &pkt->cmd_store;
  1774. +     pkt->command_size = (ad_link->flags & ACAP_LEN)?16:12;
  1775. +     pkt->bp = bp;
  1776. +     pkt->databuf = bp->b_data;
  1777. +     pkt->data_size = bp->b_bcount;
  1778. +     pkt->flags = bp->b_flags & (B_READ|B_WRITE)|(flags & 0xff)|
  1779. +             (ad_link->flags & 0x0300);
  1780. +     pkt->drive = ad_link->drive;
  1781. +     wdc_atapi_send_command_packet(b_link, pkt);
  1782. +     return (pkt->status & STATUS_MASK);
  1783. + }
  1784. + void atapi_done(acp)
  1785. + struct atapi_command_packet *acp;
  1786. + {
  1787. +     struct at_dev_link *ad_link=acp->ad_link;
  1788. +     struct buf *bp = acp->bp;
  1789. +     int error = 0;
  1790. + #ifdef ATAPI_DEBUG_CMD
  1791. +     printf("atapi_done\n");
  1792. + #endif
  1793. +     if ((acp->status & ERROR) && (acp->error)) {
  1794. +         atapi_error(acp);
  1795. +         if (acp->status & RETRY) {
  1796. +             if (acp->retries <ATAPI_NRETRIES) {
  1797. +                 acp->retries++;
  1798. +                 acp->status = 0;
  1799. +                 acp->error = 0;
  1800. +                 SILENT_PRINTF(acp->flags & 0xff,(", retry #%d\n",acp->retries));
  1801. +                 wdc_atapi_send_command_packet(ad_link->bus, acp);
  1802. +                 return;
  1803. +             } else acp->status = ERROR;
  1804. +         }
  1805. +         SILENT_PRINTF(acp->flags & 0xff,("\n"));
  1806. +     }
  1807. +     acp->status |= ITSDONE;
  1808. +     if (ad_link->done) {
  1809. + #ifdef ATAPI_DEBUG_CMD
  1810. +         printf("calling private done\n");
  1811. + #endif
  1812. +         error = (*ad_link->done) (acp);
  1813. +         if (error == EJUSTRETURN) return;
  1814. +     }
  1815. +     if (acp->bp == NULL) {
  1816. + #ifdef ATAPI_DEBUG_CMD
  1817. +         printf("atapidone: wakeup acp\n");
  1818. + #endif
  1819. +         wakeup(acp);
  1820. +         return;
  1821. +     }
  1822. + #ifdef ATAPI_DEBUG_CMD
  1823. +     printf("atapi_done: status %d\n", acp->status);
  1824. + #endif
  1825. +     switch (acp->status&0x0f) {
  1826. +     case MEDIA_CHANGE:
  1827. +         if (ad_link->flags & ADEV_REMOVABLE) {
  1828. +             ad_link->flags &= ~ADEV_MEDIA_LOADED;
  1829. +         }
  1830. +         error=EIO;
  1831. +         break;
  1832. +     case NO_ERROR:
  1833. +         error=0;
  1834. +         break;
  1835. +     case ERROR:
  1836. +     case END_OF_MEDIA:
  1837. +     default:
  1838. +         error=EIO;
  1839. +         break;
  1840. +     }
  1841. +     switch (acp->status&0xf0) {
  1842. +     case NOT_READY:
  1843. +     case UNIT_ATTENTION:
  1844. +         if (ad_link->flags & ADEV_REMOVABLE) {  
  1845. +             ad_link->flags &= ~ADEV_MEDIA_LOADED;
  1846. +         }   
  1847. +         error=EIO;
  1848. +         break;
  1849. +     default:
  1850. +     }
  1851. +     if (error) {
  1852. +         bp->b_error = error;;
  1853. +         bp->b_flags |= B_ERROR;
  1854. +         bp->b_resid = bp->b_bcount;
  1855. +     } else {
  1856. +         bp->b_error = 0;
  1857. +         bp->b_resid = acp->data_size;
  1858. +     }
  1859. +     biodone(bp);
  1860. +     atapi_free_pkt(acp);
  1861. + }
  1862. + struct atapi_command_packet *
  1863. + atapi_get_pkt(ad_link, flags)
  1864. + struct at_dev_link *ad_link;
  1865. + int flags;
  1866. + {
  1867. +     struct atapi_command_packet *pkt;
  1868. +     int s;
  1869. +     s = splbio();
  1870. +     while (ad_link->openings <= 0) {
  1871. +         if (flags & A_NOSLEEP) {
  1872. +             splx(s);
  1873. +             return 0;
  1874. +         }
  1875. + #ifdef ATAPI_DEBUG_CMD
  1876. +         printf("atapi_get_pkt: sleeping\n");
  1877. + #endif
  1878. +         ad_link->flags |= ADEV_WAITING;
  1879. +         (void) tsleep(ad_link, PRIBIO, "getpkt", 0);
  1880. +     }
  1881. +     ad_link->openings--;
  1882. +     if ((pkt = pkt_free_list.lh_first) != 0) {
  1883. +         LIST_REMOVE(pkt, free_list);
  1884. +         splx(s);
  1885. +     } else {
  1886. +         splx(s);
  1887. +         pkt = malloc(sizeof(struct atapi_command_packet), M_DEVBUF,
  1888. +             ((flags & A_NOSLEEP) != 0 ? M_NOWAIT : M_WAITOK));
  1889. +         if (!pkt) {
  1890. +             printf("atapi_get_pkt: cannot allocate pkt\n");
  1891. +             ad_link->openings++;
  1892. +             return 0;
  1893. +         }
  1894. +     }
  1895. +     bzero(pkt, sizeof(struct atapi_command_packet));
  1896. +     pkt->ad_link = ad_link;
  1897. +     return pkt;
  1898. + }
  1899. + void
  1900. + atapi_free_pkt(pkt)
  1901. + struct atapi_command_packet *pkt;
  1902. + {
  1903. +     struct at_dev_link *ad_link = pkt->ad_link;
  1904. +     int s;
  1905. +     s = splbio();
  1906. +     LIST_INSERT_HEAD(&pkt_free_list, pkt, free_list);
  1907. +     ad_link->openings++;
  1908. +     if ((ad_link->flags & ADEV_WAITING) != 0) {
  1909. +         ad_link->flags &= ~ADEV_WAITING;
  1910. +         wakeup(ad_link);
  1911. +     } else {
  1912. +         if (ad_link->start) {
  1913. + #ifdef ATAPI_DEBUG_CMD
  1914. +             printf("atapi_free_pkt: calling private start\n");
  1915. + #endif
  1916. +             (*(ad_link->start)) ((void*)ad_link->device_softc);
  1917. +         }
  1918. +     }
  1919. +     splx(s);
  1920. + }
  1921. + int
  1922. + atapi_test_unit_ready(ad_link, flags)
  1923. + struct at_dev_link  *ad_link;
  1924. + int flags;
  1925. + {    
  1926. +     int ret;
  1927. +     struct test_unit_ready cmd;
  1928. + #ifdef ATAPI_DEBUG_FCTN
  1929. +     printf("atapi_test_unit_ready: ");
  1930. + #endif
  1931. +     bzero(&cmd, sizeof(cmd));
  1932. +     cmd.operation_code = ATAPI_TEST_UNIT_READY;
  1933. +     ret = atapi_exec_cmd(ad_link, &cmd, sizeof(cmd), 0,0,0,flags);
  1934. + #ifdef ATAPI_DEBUG_FCTN
  1935. +     printf("atapi_test_unit_ready: ret %d\n", ret);
  1936. + #endif
  1937. +     return ret;
  1938. + }
  1939. + int
  1940. + atapi_start_stop(ad_link, how, flags)
  1941. + struct at_dev_link  *ad_link;
  1942. + int how;
  1943. + int flags;
  1944. + {
  1945. +     struct start_stop_unit cmd;
  1946. +     int ret;
  1947. +         
  1948. + #ifdef ATAPI_DEBUG_FCTN
  1949. +     printf("atapi_start_stop: ");
  1950. + #endif
  1951. +     bzero(&cmd, sizeof(cmd));
  1952. +     cmd.operation_code = ATAPI_START_STOP_UNIT;
  1953. +     cmd.how = how;
  1954. +     ret = atapi_exec_cmd(ad_link, &cmd, sizeof(cmd), 0,0,0,flags);
  1955. + #ifdef ATAPI_DEBUG_FCTN
  1956. +     printf("ret %d\n", ret);
  1957. + #endif
  1958. +     return ret;
  1959. + }
  1960. + int
  1961. + atapi_prevent(ad_link, how)
  1962. + struct at_dev_link  *ad_link;
  1963. + int how;
  1964. + {
  1965. +     struct prevent_allow_medium_removal cmd;
  1966. +     int ret;
  1967. + #ifdef ATAPI_DEBUG_FCTN
  1968. +     printf("atapi_prevent: ");
  1969. + #endif
  1970. +     bzero(&cmd, sizeof(cmd));
  1971. +     cmd.operation_code = ATAPI_PREVENT_ALLOW_MEDIUM_REMOVAL;
  1972. +     cmd.prevent = how;
  1973. +     ret = atapi_exec_cmd(ad_link, &cmd, sizeof(cmd), 0,0,0,0);
  1974. + #ifdef ATAPI_DEBUG_FCTN
  1975. +     printf("ret %d\n", ret);
  1976. + #endif
  1977. +     return ret;
  1978. + }
  1979. + int 
  1980. + atapi_error(acp)
  1981. + struct atapi_command_packet* acp;
  1982. + {
  1983. +     int flags, error, ret = -1;
  1984. +     struct at_dev_link *ad_link = acp->ad_link;
  1985. +     flags = acp->flags & 0xff;
  1986. +     error = acp->error;
  1987. +     at_print_addr(ad_link, acp->flags & 0xff);
  1988. +     if (error & ATAPI_MCR) {
  1989. +         SILENT_PRINTF(flags,("media change requested"));
  1990. +         acp->status = MEDIA_CHANGE;
  1991. +     }
  1992. +     if (error & ATAPI_ABRT) {      
  1993. +         SILENT_PRINTF(flags,("command aborted"));
  1994. +         acp->status = ERROR; 
  1995. +     }
  1996. +     if (error & ATAPI_EOM) {
  1997. +         SILENT_PRINTF(flags,("end of media"));
  1998. +         acp->status = END_OF_MEDIA;
  1999. +     }
  2000. +     if (error & ATAPI_ILI) {
  2001. +         SILENT_PRINTF(flags,("illegal length indication"));
  2002. +         acp->status = ERROR;
  2003. +     }
  2004. +     if ((error & 0x0f) == 0) {
  2005. +         ret=0;
  2006. +     }
  2007. +     atapi_sense (acp, error >> 4, flags);
  2008. +     if (!(flags & A_SILENT) && (acp->status != NO_ERROR)) {
  2009. +         int i;
  2010. +         printf(", command:");
  2011. +         for (i=0; i< acp->command_size; i++)
  2012. +             printf(" %2x", ((u_char*)acp->command)[i]);
  2013. +     }
  2014. +     return ret;
  2015. + }
  2016. + void
  2017. + atapi_sense(acp, sense_key, flags)
  2018. + struct atapi_command_packet *acp;
  2019. + u_char sense_key;
  2020. + u_char flags;
  2021. + {
  2022. +     struct at_dev_link *ad_link = acp->ad_link;
  2023. +     switch (sense_key)
  2024. +     {
  2025. +     case ATAPI_SK_NO_SENSE:
  2026. +     break;
  2027. +     case ATAPI_SK_REC_ERROR:
  2028. +     SILENT_PRINTF(flags,("recovered error"));
  2029. +     acp->status = 0;
  2030. +     break;
  2031. +     case ATAPI_SK_NOT_READY:
  2032. +     SILENT_PRINTF(flags,("not ready"));
  2033. +     acp->status = NOT_READY;
  2034. +     break;
  2035. +     case ATAPI_SK_MEDIUM_ERROR:
  2036. +     SILENT_PRINTF(flags,("medium error"));
  2037. +     acp->status = ERROR;
  2038. +     break;
  2039. +     case ATAPI_SK_HARDWARE_ERROR:
  2040. +     SILENT_PRINTF(flags,("hardware error"));
  2041. +     acp->status = ERROR;
  2042. +     break;
  2043. +     case ATAPI_SK_ILLEGAL_REQUEST:
  2044. +     SILENT_PRINTF(flags,("illegal request"));
  2045. +     acp->status = ERROR;
  2046. +     break;
  2047. +     case ATAPI_SK_UNIT_ATTENTION:
  2048. +     SILENT_PRINTF(flags,("unit attention"));
  2049. +     acp->status = UNIT_ATTENTION;
  2050. +     if (ad_link->flags & ADEV_REMOVABLE) {  
  2051. +         ad_link->flags &= ~ADEV_MEDIA_LOADED;
  2052. +     }   
  2053. +     break;
  2054. +     case ATAPI_SK_DATA_PROTECT:
  2055. +     SILENT_PRINTF(flags,("data protect"));
  2056. +     acp->status = ERROR;
  2057. +     break;
  2058. +     case ATAPI_SK_ABORTED_COMMAND:
  2059. +     SILENT_PRINTF(flags,("aborted command"));
  2060. +     acp->status = RETRY;
  2061. +     break;
  2062. +     case ATAPI_SK_MISCOMPARE:
  2063. +     SILENT_PRINTF(flags,("miscompare"));
  2064. +     acp->status = ERROR;
  2065. +     break;
  2066. +     default:
  2067. +     SILENT_PRINTF(flags,("unexpected sense key %02x", sense_key));
  2068. +     acp->status = ERROR;
  2069. +     break;
  2070. +     }
  2071. + }
  2072. + void
  2073. + at_print_addr(ad_link, flags)
  2074. +     struct at_dev_link *ad_link; 
  2075. +     u_char flags;
  2076. + {
  2077. +     if (flags & A_SILENT) return;
  2078. +     printf("%s(%s:%d): ",
  2079. +         ad_link->device_softc ?
  2080. +         ((struct device *)ad_link->device_softc)->dv_xname : "probe",
  2081. +         ((struct device *)ad_link->bus->wdc_softc)->dv_xname,
  2082. +         ad_link->drive);
  2083. + }       
  2084. diff --exclude compile -bcrNP src.orig/sys/atapi/atapilink.h src/sys/atapi/atapilink.h
  2085. *** src.orig/sys/atapi/atapilink.h    Thu Jan  1 01:00:00 1970
  2086. --- src/sys/atapi/atapilink.h    Tue Mar  5 21:45:44 1996
  2087. ***************
  2088. *** 0 ****
  2089. --- 1,186 ----
  2090. + /*
  2091. +  * Copyright (c) 1996 Manuel Bouyer.  All rights reserved.
  2092. +  *
  2093. +  * Redistribution and use in source and binary forms, with or without
  2094. +  * modification, are permitted provided that the following conditions
  2095. +  * are met:
  2096. +  * 1. Redistributions of source code must retain the above copyright
  2097. +  *    notice, this list of conditions and the following disclaimer.
  2098. +  * 2. Redistributions in binary form must reproduce the above copyright
  2099. +  *    notice, this list of conditions and the following disclaimer in the
  2100. +  *    documentation and/or other materials provided with the distribution.
  2101. +  * 3. All advertising materials mentioning features or use of this software
  2102. +  *    must display the following acknowledgement:
  2103. +  *  This product includes software developed by Manuel Bouyer.
  2104. +  * 4. The name of the author may not be used to endorse or promote products
  2105. +  *    derived from this software without specific prior written permission.
  2106. +  *
  2107. +  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  2108. +  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  2109. +  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  2110. +  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  2111. +  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  2112. +  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  2113. +  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  2114. +  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  2115. +  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  2116. +  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  2117. +  */
  2118. + #undef ATAPI_DEBUG
  2119. + #undef ATAPI_DEBUG_PROBE
  2120. + struct bus_link {
  2121. +     u_int8_t type;  
  2122. + #define DRIVE 0
  2123. + #define BUS 1
  2124. +     caddr_t wdc_softc;
  2125. +     caddr_t atapibus_softc;
  2126. +     struct wdc_link *ctlr_link;
  2127. +     u_int8_t ctrl;
  2128. + };
  2129. + struct atapi_identify {
  2130. +     struct config_s {
  2131. +     u_int8_t  packet_size :2;
  2132. + #define ATAPI_PACKET_SIZE_12        0x0
  2133. + #define ATAPI_PACKET_SIZE_16        0x1
  2134. +                          /* 1xb reserved */
  2135. +     u_int8_t  reserved1   :3;
  2136. +     u_int8_t  drq_type    :2;
  2137. + #define ATAPI_MICROPROCESSOR_DRQ    0x0
  2138. + #define ATAPI_INTERRUPT_DRQ     0x1
  2139. + #define ATAPI_ACCELERATED_DRQ       0x2
  2140. +                          /* 0x3 reserved */
  2141. +     u_int8_t  removable   :1;
  2142. +     u_int8_t  device_type :5;
  2143. + #define ATAPI_DEVICE_TYPE_DAD       0x0  /* direct access device, eg magnetic di
  2144. + sk */
  2145. +                          /* 0x1-0x4 reserved */
  2146. + #define ATAPI_DEVICE_TYPE_CD        0x5
  2147. +                          /* 0x6 reserved */
  2148. + #define ATAPI_DEVICE_TYPE_OMD       0x7  /* optical memory device */
  2149. +                          /* 0x8-0x1e reserved */
  2150. + #define ATAPI_DEVICE_TYPE_UNKNOWN   0x1f
  2151. +     u_int8_t  reserved2   :1;
  2152. +     u_int8_t  protocol_type   :2;
  2153. +                          /* 0x0, 0x1 are ATA */
  2154. + #define ATAPI_GC_PROTO_TYPE_ATAPI   0x2
  2155. + #define ATAPI_GC_PROTO_TYPE_RESERVED    0x3
  2156. +     } config;                /* general configuration */
  2157. +     u_int16_t cylinders;
  2158. +     u_int16_t reserved1;
  2159. +     u_int16_t heads;
  2160. +     u_int16_t unf_bytes_per_track;
  2161. +     u_int16_t unf_bytes_per_sector;
  2162. +     u_int16_t sectors_per_track;
  2163. +     u_int16_t reserved2[3];
  2164. +     char    serial_number[20];
  2165. +     u_int16_t buffer_type;
  2166. +     u_int16_t buffer_size;
  2167. +     u_int16_t ECC_bytes_available;
  2168. +     char    firmware_revision[8];
  2169. +     char    model[40];
  2170. +     u_int16_t sector_count;
  2171. +     u_int16_t double_word;             /* ==0 for CD-ROMs */
  2172. +     struct capabilities_s {
  2173. +       u_int8_t    vendor;
  2174. +       u_int8_t    dma     :1;      /* DMA supported */
  2175. +       u_int8_t    lba     :1;      /* LBA supported */
  2176. +       u_int8_t    iordy_disable   :1;      /* IORDY can be disabled */
  2177. +       u_int8_t    iordy       :1;      /* IORDY supported */
  2178. +       u_int8_t    reserved1   :4;
  2179. +     } capabilities;
  2180. +     u_int16_t reserved3;
  2181. +     u_int16_t PIO_cycle_timing;
  2182. +     u_int16_t DMA_cycle_timing;
  2183. +     u_int16_t validity;            /* of words 54-58, 64-70 in this table */
  2184. + #define ATAPI_VALID_FIRST       0x0  /* == 1 => words 54-58 are valid */
  2185. + #define ATAPI_VALID_SECOND      0x1  /* == 1 => words 64-70 are valid */
  2186. +     u_int16_t current_chs[3];          /* cylinder/head/sector */
  2187. +     u_int16_t current_capacity[2];
  2188. +     u_int16_t reserved4;
  2189. +     u_int16_t user_addressable_sectors[2];
  2190. +     u_int16_t singleword_DMA_mode;
  2191. + #define ATAPI_SW_DMA_MODE_AVAIL     0x00ff /* bit 0 set => Mode 0 is supported */
  2192. + #define ATAPI_SW_DMA_MODE_ACTIVE    0xff00 /* which mode is active */
  2193. +     u_int16_t multiword_DMA_mode;
  2194. + #define ATAPI_MW_DMA_MODE_AVAIL     0x00ff /* bit 0 set => Mode 0 is supported */
  2195. + #define ATAPI_MW_DMA_MODE_ACTIVE    0xff00 /* which mode is active */
  2196. +     u_int16_t enhanced_PIO_mode;
  2197. + #define ATAPI_ENHANCED_PIO_AVAIL    0x0001 /* bit 0 set => PIO Mode 3 is support
  2198. + ed */
  2199. +     u_int16_t blind_PIO_minimum_cycles;
  2200. +     u_int16_t mw_dma_tct;          /* multi-word DMA transfer cycle time */
  2201. +     u_int16_t min_PIO_tct_no_flow_control;
  2202. +     u_int16_t min_PIO_tct_with_flow_control;
  2203. +     u_int16_t reserved5[2];
  2204. +     u_int16_t reserved6[57];
  2205. +     u_int16_t vendor[32];          /* vendor unique */
  2206. +     u_int16_t reserved7[96];
  2207. + };
  2208. + struct at_dev_link {
  2209. +     void *device_softc;
  2210. +     u_int8_t drive;
  2211. +     u_int8_t openings;
  2212. +     struct atapi_identify id;  
  2213. +     struct bus_link *bus;
  2214. +     u_int16_t flags;
  2215. + #define ADEV_REMOVABLE      0x001    /* media is removable */
  2216. + #define ADEV_MEDIA_LOADED   0x002    /* device figures are still valid */  
  2217. + #define ADEV_WAITING        0x004    /* a process is waiting for this */
  2218. + #define ADEV_OPEN           0x008    /* at least 1 open session */
  2219. + #define ACAP_DRQ_MPROC        0x000   /* microprocessor DRQ */
  2220. + #define ACAP_DRQ_INTR        0x100    /* interrupt DRQ */
  2221. + #define ACAP_DRQ_ACCEL        0x200    /* accelerated DRQ */
  2222. + #define ACAP_LEN             0x400   /* 16 bit commands */
  2223. +     void (*start)();
  2224. +     int (*done)();
  2225. + };
  2226. + struct atapi_command_packet {
  2227. +     void *ad_link;
  2228. +     void *command;
  2229. +     char cmd_store[16];
  2230. +     int command_size;
  2231. +     struct buf* bp; 
  2232. +     void *databuf;
  2233. +     int data_size;
  2234. +     long flags;   /* handle B_READ/B_WRITE mask 0x00f00000 */
  2235. +                   /* controller flags maks 0x0000000f */
  2236. +                   /* ATAPI flags mask 0x000000f0 */
  2237. +                   /* Capabilities flags 0x00000f00 */
  2238. +     u_int8_t drive;
  2239. +     u_int16_t status;
  2240. + #define STATUS_MASK 0xff
  2241. + #define NO_ERROR 0x00
  2242. + #define ERROR 0x01
  2243. + #define MEDIA_CHANGE 0x02
  2244. + #define END_OF_MEDIA 0x03
  2245. + #define NOT_READY 0x10
  2246. + #define UNIT_ATTENTION 0x20
  2247. + #define RETRY 0x40
  2248. + #define ITSDONE 0x100
  2249. +     u_int8_t error;
  2250. +     u_int8_t retries;
  2251. + #define ATAPI_NRETRIES 5
  2252. +     LIST_ENTRY(atapi_command_packet) free_list;
  2253. + };
  2254. + int wdc_atapi_get_params  __P((struct bus_link *,u_int8_t, struct atapi_identify *)); 
  2255. + void wdc_atapi_send_command_packet __P((struct bus_link*, struct atapi_command_packet*));
  2256. + #define A_POLLED 0x10
  2257. + #define A_NOSLEEP 0x20
  2258. + #define A_SILENT 0x40
  2259. + void atapi_done __P((struct atapi_command_packet *));
  2260. + struct atapi_command_packet *atapi_get_pkt __P((struct at_dev_link *, int));
  2261. + void atapi_free_pkt __P((struct atapi_command_packet *));
  2262. diff --exclude compile -bcrNP src.orig/sys/atapi/files.atapi src/sys/atapi/files.atapi
  2263. *** src.orig/sys/atapi/files.atapi    Thu Jan  1 01:00:00 1970
  2264. --- src/sys/atapi/files.atapi    Fri Apr 19 16:17:58 1996
  2265. ***************
  2266. *** 0 ****
  2267. --- 1,14 ----
  2268. + #
  2269. + # Config.new file and device description for machine-independent ATAPI code.
  2270. + # Included by ports that need it.  Ports that usee it must provide
  2271. + # their own "major" declarations for the appropriate devices.
  2272. + define    atapi {}
  2273. + file    atapi/atapiconf.c            atapi
  2274. + device    atapibus {drive = -1}
  2275. + attach atapibus at atapi
  2276. + device  acd: disk
  2277. + attach  acd at atapibus
  2278. + file    atapi/acd.c           acd needs-flag
  2279. diff --exclude compile -bcrNP src.orig/sys/dev/isa/files.isa src/sys/dev/isa/files.isa
  2280. *** src.orig/sys/dev/isa/files.isa    Thu May 16 20:16:36 1996
  2281. --- src/sys/dev/isa/files.isa    Thu Jun  6 12:31:55 1996
  2282. ***************
  2283. *** 109,119 ****
  2284.   file    dev/isa/scd.c            scd needs-flag
  2285.   
  2286.   # ISA "wd" (ESDI/IDE/etc.) controllers
  2287. ! device    wdc {drive = -1}
  2288.   attach    wdc at isa
  2289. ! device    wd: disk, isadma
  2290. ! attach    wd at wdc
  2291. ! file    dev/isa/wd.c            wdc needs-flag
  2292.   
  2293.   # Wangtek- and Archive-compatible tape controller boards
  2294.   device    wt: tape, isadma
  2295. --- 109,121 ----
  2296.   file    dev/isa/scd.c            scd needs-flag
  2297.   
  2298.   # ISA "wd" (ESDI/IDE/etc.) controllers
  2299. ! define ata {drive=-1}
  2300. ! device  wdc: atapi, isadma, ata 
  2301.   attach  wdc at isa
  2302. ! device  wd: disk
  2303. ! attach  wd at ata
  2304. ! file    dev/isa/wdc.c           wdc needs-flag
  2305. ! file    dev/isa/wd.c            wd needs-flag
  2306.    
  2307.   # Wangtek- and Archive-compatible tape controller boards
  2308.   device    wt: tape, isadma
  2309. diff --exclude compile -bcrNP src.orig/sys/dev/isa/wd.c src/sys/dev/isa/wd.c
  2310. *** src.orig/sys/dev/isa/wd.c    Mon May 13 13:36:27 1996
  2311. --- src/sys/dev/isa/wd.c    Thu Jun  6 17:48:42 1996
  2312. ***************
  2313. *** 1,1775 ****
  2314. - /*    $NetBSD: wd.c,v 1.150 1996/05/12 23:54:03 mycroft Exp $    */
  2315. - /*
  2316. -  * Copyright (c) 1994, 1995 Charles M. Hannum.  All rights reserved.
  2317. -  *
  2318. -  * DMA and multi-sector PIO handling are derived from code contributed by
  2319. -  * Onno van der Linden.
  2320. -  *
  2321. -  * Redistribution and use in source and binary forms, with or without
  2322. -  * modification, are permitted provided that the following conditions
  2323. -  * are met:
  2324. -  * 1. Redistributions of source code must retain the above copyright
  2325. -  *    notice, this list of conditions and the following disclaimer.
  2326. -  * 2. Redistributions in binary form must reproduce the above copyright
  2327. -  *    notice, this list of conditions and the following disclaimer in the
  2328. -  *    documentation and/or other materials provided with the distribution.
  2329. -  * 3. All advertising materials mentioning features or use of this software
  2330. -  *    must display the following acknowledgement:
  2331. -  *    This product includes software developed by Charles M. Hannum.
  2332. -  * 4. The name of the author may not be used to endorse or promote products
  2333. -  *    derived from this software without specific prior written permission.
  2334. -  *
  2335. -  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  2336. -  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  2337. -  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  2338. -  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  2339. -  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  2340. -  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  2341. -  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  2342. -  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  2343. -  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  2344. -  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  2345. -  */
  2346. - #include <sys/param.h>
  2347. - #include <sys/systm.h>
  2348. - #include <sys/kernel.h>
  2349. - #include <sys/conf.h>
  2350. - #include <sys/file.h>
  2351. - #include <sys/stat.h>
  2352. - #include <sys/ioctl.h>
  2353. - #include <sys/buf.h>
  2354. - #include <sys/uio.h>
  2355. - #include <sys/malloc.h>
  2356. - #include <sys/device.h>
  2357. - #include <sys/disklabel.h>
  2358. - #include <sys/disk.h>
  2359. - #include <sys/syslog.h>
  2360. - #include <sys/proc.h>
  2361. - #include <vm/vm.h>
  2362. - #include <machine/cpu.h>
  2363. - #include <machine/intr.h>
  2364. - #include <machine/pio.h>
  2365. - #include <dev/isa/isavar.h>
  2366. - #include <dev/isa/isadmavar.h>
  2367. - #include <dev/isa/wdreg.h>
  2368. - #define    WAITTIME    (4 * hz)    /* time to wait for a completion */
  2369. - #define    RECOVERYTIME    (hz / 2)    /* time to recover from an error */
  2370. - #define WDCDELAY    100
  2371. - #define WDCNDELAY    100000        /* delay = 100us; so 10s for a controller state change */
  2372. - #if 0
  2373. - /* If you enable this, it will report any delays more than 100us * N long. */
  2374. - #define WDCNDELAY_DEBUG    10
  2375. - #endif
  2376. - #define    WDIORETRIES    5        /* number of retries before giving up */
  2377. - #define    WDUNIT(dev)            DISKUNIT(dev)
  2378. - #define    WDPART(dev)            DISKPART(dev)
  2379. - #define    MAKEWDDEV(maj, unit, part)    MAKEDISKDEV(maj, unit, part)
  2380. - #define    WDLABELDEV(dev)    (MAKEWDDEV(major(dev), WDUNIT(dev), RAW_PART))
  2381. - struct wd_softc {
  2382. -     struct device sc_dev;
  2383. -     struct disk sc_dk;
  2384. -     /* Information about the current transfer: */
  2385. -     daddr_t sc_blkno;    /* starting block number */
  2386. -     int sc_bcount;        /* byte count left */
  2387. -     int sc_skip;        /* bytes already transferred */
  2388. -     int sc_nblks;        /* number of blocks currently transferring */
  2389. -     int sc_nbytes;        /* number of bytes currently transferring */
  2390. -     /* Long-term state: */
  2391. -     int sc_drive;            /* physical unit number */
  2392. -     int sc_state;            /* control state */
  2393. - #define    RECAL        0        /* recalibrate */
  2394. - #define    RECAL_WAIT    1        /* done recalibrating */
  2395. - #define    GEOMETRY    2        /* upload geometry */
  2396. - #define    GEOMETRY_WAIT    3        /* done uploading geometry */
  2397. - #define    MULTIMODE    4        /* set multiple mode */
  2398. - #define    MULTIMODE_WAIT    5        /* done setting multiple mode */
  2399. - #define    OPEN        6        /* done with open */
  2400. -     int sc_mode;            /* transfer mode */
  2401. - #define    WDM_PIOSINGLE    0        /* single-sector PIO */
  2402. - #define    WDM_PIOMULTI    1        /* multi-sector PIO */
  2403. - #define    WDM_DMA        2        /* DMA */
  2404. -     int sc_multiple;        /* multiple for WDM_PIOMULTI */
  2405. -     int sc_flags;            /* drive characteistics found */
  2406. - #define    WDF_LOCKED    0x01
  2407. - #define    WDF_WANTED    0x02
  2408. - #define    WDF_WLABEL    0x04        /* label is writable */
  2409. - #define    WDF_LABELLING    0x08        /* writing label */
  2410. - /* XXX Nothing resets this yet, but disk change sensing will when ATAPI is
  2411. -    implemented. */
  2412. - #define    WDF_LOADED    0x10        /* parameters loaded */
  2413. - #define    WDF_32BIT    0x20        /* can do 32-bit transfer */
  2414. -     struct wdparams sc_params;    /* ESDI/ATA drive parameters */
  2415. -     daddr_t    sc_badsect[127];    /* 126 plus trailing -1 marker */
  2416. -     TAILQ_ENTRY(wd_softc) sc_drivechain;
  2417. -     struct buf sc_q;
  2418. - };
  2419. - struct wdc_softc {
  2420. -     struct device sc_dev;
  2421. -     void *sc_ih;
  2422. -     int sc_iobase;            /* I/O port base */
  2423. -     int sc_drq;            /* DMA channel */
  2424. -     TAILQ_HEAD(drivehead, wd_softc) sc_drives;
  2425. -     int sc_flags;
  2426. - #define    WDCF_ACTIVE    0x01        /* controller is active */
  2427. - #define    WDCF_SINGLE    0x02        /* sector at a time mode */
  2428. - #define    WDCF_ERROR    0x04        /* processing a disk error */
  2429. - #define    WDCF_WANTED    0x08        /* XXX locking for wd_get_parms() */
  2430. -     int sc_errors;            /* errors during current transfer */
  2431. -     u_char sc_status;        /* copy of status register */
  2432. -     u_char sc_error;        /* copy of error register */
  2433. - };
  2434. - int    wdcprobe     __P((struct device *, void *, void *));
  2435. - void    wdcattach     __P((struct device *, struct device *, void *));
  2436. - int    wdcintr        __P((void *));
  2437. - struct cfattach wdc_ca = {
  2438. -     sizeof(struct wdc_softc), wdcprobe, wdcattach
  2439. - };
  2440. - struct cfdriver wdc_cd = {
  2441. -     NULL, "wdc", DV_DULL
  2442. - };
  2443. - int wdprobe __P((struct device *, void *, void *));
  2444. - void wdattach __P((struct device *, struct device *, void *));
  2445. - int wdprint __P((void *, char *));
  2446. - struct cfattach wd_ca = {
  2447. -     sizeof(struct wd_softc), wdprobe, wdattach
  2448. - };
  2449. - struct cfdriver wd_cd = {
  2450. -     NULL, "wd", DV_DISK
  2451. - };
  2452. - void    wdgetdisklabel    __P((struct wd_softc *));
  2453. - int    wd_get_parms    __P((struct wd_softc *));
  2454. - void    wdstrategy    __P((struct buf *));
  2455. - void    wdstart        __P((struct wd_softc *));
  2456. - struct dkdriver wddkdriver = { wdstrategy };
  2457. - /* XXX: these should go elsewhere */
  2458. - cdev_decl(wd);
  2459. - bdev_decl(wd);
  2460. - void    wdfinish    __P((struct wd_softc *, struct buf *));
  2461. - int     dcintr        __P((void *));
  2462. - void    wdcstart    __P((struct wdc_softc *));
  2463. - int    wdcommand    __P((struct wd_softc *, int, int, int, int, int));
  2464. - int    wdcommandshort    __P((struct wdc_softc *, int, int));
  2465. - int    wdcontrol    __P((struct wd_softc *));
  2466. - int    wdsetctlr    __P((struct wd_softc *));
  2467. - static void bad144intern __P((struct wd_softc *));
  2468. - int    wdcreset    __P((struct wdc_softc *));
  2469. - void    wdcrestart    __P((void *arg));
  2470. - void    wdcunwedge    __P((struct wdc_softc *));
  2471. - void    wdctimeout    __P((void *arg));
  2472. - void    wderror        __P((void *, struct buf *, char *));
  2473. - int    wdcwait        __P((struct wdc_softc *, int));
  2474. - int    wdlock        __P((struct wd_softc *));
  2475. - void    wdunlock    __P((struct wd_softc *));
  2476. - /* ST506 spec says that if READY or SEEKCMPLT go off, then the read or write
  2477. -    command is aborted. */
  2478. - #define    wait_for_drq(d)        wdcwait(d, WDCS_DRDY | WDCS_DSC | WDCS_DRQ)
  2479. - #define    wait_for_ready(d)    wdcwait(d, WDCS_DRDY | WDCS_DSC)
  2480. - #define    wait_for_unbusy(d)    wdcwait(d, 0)
  2481. - int
  2482. - wdcprobe(parent, match, aux)
  2483. -     struct device *parent;
  2484. -     void *match, *aux;
  2485. - {
  2486. -     struct wdc_softc *wdc = match;
  2487. -     struct isa_attach_args *ia = aux;
  2488. -     int iobase;
  2489. -     wdc->sc_iobase = iobase = ia->ia_iobase;
  2490. -     /* Check if we have registers that work. */
  2491. -     outb(iobase+wd_error, 0x5a);    /* Error register not writable, */
  2492. -     outb(iobase+wd_cyl_lo, 0xa5);    /* but all of cyllo are. */
  2493. -     if (inb(iobase+wd_error) == 0x5a || inb(iobase+wd_cyl_lo) != 0xa5)
  2494. -         return 0;
  2495. -     if (wdcreset(wdc) != 0) {
  2496. -         delay(500000);
  2497. -         if (wdcreset(wdc) != 0)
  2498. -             return 0;
  2499. -     }
  2500. -     /* Select drive 0. */
  2501. -     outb(iobase+wd_sdh, WDSD_IBM | 0);
  2502. -     /* Wait for controller to become ready. */
  2503. -     if (wait_for_unbusy(wdc) < 0)
  2504. -         return 0;
  2505. -     
  2506. -     /* Start drive diagnostics. */
  2507. -     outb(iobase+wd_command, WDCC_DIAGNOSE);
  2508. -     /* Wait for command to complete. */
  2509. -     if (wait_for_unbusy(wdc) < 0)
  2510. -         return 0;
  2511. -     ia->ia_iosize = 8;
  2512. -     ia->ia_msize = 0;
  2513. -     return 1;
  2514. - }
  2515. - struct wdc_attach_args {
  2516. -     int wa_drive;
  2517. - };
  2518. - int
  2519. - wdprint(aux, wdc)
  2520. -     void *aux;
  2521. -     char *wdc;
  2522. - {
  2523. -     struct wdc_attach_args *wa = aux;
  2524. -     if (!wdc)
  2525. -         printf(" drive %d", wa->wa_drive);
  2526. -     return QUIET;
  2527. - }
  2528. - void
  2529. - wdcattach(parent, self, aux)
  2530. -     struct device *parent, *self;
  2531. -     void *aux;
  2532. - {
  2533. -     struct wdc_softc *wdc = (void *)self;
  2534. -     struct isa_attach_args *ia = aux;
  2535. -     struct wdc_attach_args wa;
  2536. -     TAILQ_INIT(&wdc->sc_drives);
  2537. -     wdc->sc_drq = ia->ia_drq;
  2538. -     printf("\n");
  2539. -     wdc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
  2540. -         IPL_BIO, wdcintr, wdc);
  2541. -     for (wa.wa_drive = 0; wa.wa_drive < 2; wa.wa_drive++)
  2542. -         (void)config_found(self, (void *)&wa, wdprint);
  2543. - }
  2544. - int
  2545. - wdprobe(parent, match, aux)
  2546. -     struct device *parent;
  2547. -     void *match, *aux;
  2548. - {
  2549. -     struct wdc_softc *wdc = (void *)parent;
  2550. -     struct cfdata *cf = match;
  2551. -     struct wdc_attach_args *wa = aux;
  2552. -     int drive = wa->wa_drive;
  2553. -     if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != drive)
  2554. -         return 0;
  2555. -     
  2556. -     if (wdcommandshort(wdc, drive, WDCC_RECAL) != 0 ||
  2557. -         wait_for_ready(wdc) != 0)
  2558. -         return 0;
  2559. -     return 1;
  2560. - }
  2561. - void
  2562. - wdattach(parent, self, aux)
  2563. -     struct device *parent, *self;
  2564. -     void *aux;
  2565. - {
  2566. -     struct wd_softc *wd = (void *)self;
  2567. -     struct wdc_softc *wdc = (void *)parent;
  2568. -     struct wdc_attach_args *wa = aux;
  2569. -     int i, blank;
  2570. -     char buf[41], c, *p, *q;
  2571. -     wd->sc_drive = wa->wa_drive;
  2572. -     /*
  2573. -      * Initialize and attach the disk structure.
  2574. -      */
  2575. -     wd->sc_dk.dk_driver = &wddkdriver;
  2576. -     wd->sc_dk.dk_name = wd->sc_dev.dv_xname;
  2577. -     disk_attach(&wd->sc_dk);
  2578. -     wd_get_parms(wd);
  2579. -     for (blank = 0, p = wd->sc_params.wdp_model, q = buf, i = 0;
  2580. -          i < sizeof(wd->sc_params.wdp_model); i++) {
  2581. -         c = *p++;
  2582. -         if (c == '\0')
  2583. -             break;
  2584. -         if (c != ' ') {
  2585. -             if (blank) {
  2586. -                 *q++ = ' ';
  2587. -                 blank = 0;
  2588. -             }
  2589. -             *q++ = c;
  2590. -         } else
  2591. -             blank = 1;
  2592. -     }
  2593. -     *q++ = '\0';
  2594. -     printf(": %dMB, %d cyl, %d head, %d sec, %d bytes/sec <%s>\n",
  2595. -         wd->sc_params.wdp_cylinders *
  2596. -         (wd->sc_params.wdp_heads * wd->sc_params.wdp_sectors) /
  2597. -         (1048576 / DEV_BSIZE),
  2598. -         wd->sc_params.wdp_cylinders,
  2599. -         wd->sc_params.wdp_heads,
  2600. -         wd->sc_params.wdp_sectors,
  2601. -         DEV_BSIZE,
  2602. -         buf);
  2603. -     if ((wd->sc_params.wdp_capabilities & WD_CAP_DMA) != 0 &&
  2604. -         wdc->sc_drq != DRQUNK) {
  2605. -         wd->sc_mode = WDM_DMA;
  2606. -     } else if (wd->sc_params.wdp_maxmulti > 1) {
  2607. -         wd->sc_mode = WDM_PIOMULTI;
  2608. -         wd->sc_multiple = min(wd->sc_params.wdp_maxmulti, 16);
  2609. -     } else {
  2610. -         wd->sc_mode = WDM_PIOSINGLE;
  2611. -         wd->sc_multiple = 1;
  2612. -     }
  2613. -     printf("%s: using", wd->sc_dev.dv_xname);
  2614. -     if (wd->sc_mode == WDM_DMA)
  2615. -         printf(" dma transfers,");
  2616. -     else
  2617. -         printf(" %d-sector %d-bit pio transfers,",
  2618. -             wd->sc_multiple, (wd->sc_flags & WDF_32BIT) == 0 ? 16 : 32);
  2619. -     if ((wd->sc_params.wdp_capabilities & WD_CAP_LBA) != 0)
  2620. -         printf(" lba addressing\n");
  2621. -     else
  2622. -         printf(" chs addressing\n");
  2623. - }
  2624. - /*
  2625. -  * Read/write routine for a buffer.  Validates the arguments and schedules the
  2626. -  * transfer.  Does not wait for the transfer to complete.
  2627. -  */
  2628. - void
  2629. - wdstrategy(bp)
  2630. -     struct buf *bp;
  2631. - {
  2632. -     struct wd_softc *wd = wd_cd.cd_devs[WDUNIT(bp->b_dev)];
  2633. -     int s;
  2634. -     
  2635. -     /* Valid request?  */
  2636. -     if (bp->b_blkno < 0 ||
  2637. -         (bp->b_bcount % wd->sc_dk.dk_label->d_secsize) != 0 ||
  2638. -         (bp->b_bcount / wd->sc_dk.dk_label->d_secsize) >= (1 << NBBY)) {
  2639. -         bp->b_error = EINVAL;
  2640. -         goto bad;
  2641. -     }
  2642. -     
  2643. -     /* If device invalidated (e.g. media change, door open), error. */
  2644. -     if ((wd->sc_flags & WDF_LOADED) == 0) {
  2645. -         bp->b_error = EIO;
  2646. -         goto bad;
  2647. -     }
  2648. -     /* If it's a null transfer, return immediately. */
  2649. -     if (bp->b_bcount == 0)
  2650. -         goto done;
  2651. -     /*
  2652. -      * Do bounds checking, adjust transfer. if error, process.
  2653. -      * If end of partition, just return.
  2654. -      */
  2655. -     if (WDPART(bp->b_dev) != RAW_PART &&
  2656. -         bounds_check_with_label(bp, wd->sc_dk.dk_label,
  2657. -         (wd->sc_flags & (WDF_WLABEL|WDF_LABELLING)) != 0) <= 0)
  2658. -         goto done;
  2659. -     
  2660. -     /* Queue transfer on drive, activate drive and controller if idle. */
  2661. -     s = splbio();
  2662. -     disksort(&wd->sc_q, bp);
  2663. -     if (!wd->sc_q.b_active)
  2664. -         wdstart(wd);
  2665. - #if 0
  2666. -     else {
  2667. -         struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent;
  2668. -         if ((wdc->sc_flags & (WDCF_ACTIVE|WDCF_ERROR)) == 0) {
  2669. -             printf("wdstrategy: controller inactive\n");
  2670. -             wdcstart(wdc);
  2671. -         }
  2672. -     }
  2673. - #endif
  2674. -     splx(s);
  2675. -     return;
  2676. -     
  2677. - bad:
  2678. -     bp->b_flags |= B_ERROR;
  2679. - done:
  2680. -     /* Toss transfer; we're done early. */
  2681. -     bp->b_resid = bp->b_bcount;
  2682. -     biodone(bp);
  2683. - }
  2684. - /*
  2685. -  * Queue a drive for I/O.
  2686. -  */
  2687. - void
  2688. - wdstart(wd)
  2689. -     struct wd_softc *wd;
  2690. - {
  2691. -     struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent;
  2692. -     int active = wdc->sc_drives.tqh_first != 0;
  2693. -     /* Link onto controller queue. */
  2694. -     wd->sc_q.b_active = 1;
  2695. -     TAILQ_INSERT_TAIL(&wdc->sc_drives, wd, sc_drivechain);
  2696. -     disk_busy(&wd->sc_dk);
  2697. -     
  2698. -     /* If controller not already active, start it. */
  2699. -     if (!active)
  2700. -         wdcstart(wdc);
  2701. - }
  2702. - /*
  2703. -  * Finish an I/O operation.  Clean up the drive and controller state, set the
  2704. -  * residual count, and inform the upper layers that the operation is complete.
  2705. -  */
  2706. - void
  2707. - wdfinish(wd, bp)
  2708. -     struct wd_softc *wd;
  2709. -     struct buf *bp;
  2710. - {
  2711. -     struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent;
  2712. -     wdc->sc_flags &= ~(WDCF_SINGLE | WDCF_ERROR);
  2713. -     wdc->sc_errors = 0;
  2714. -     /*
  2715. -      * Move this drive to the end of the queue to give others a `fair'
  2716. -      * chance.
  2717. -      */
  2718. -     if (wd->sc_drivechain.tqe_next) {
  2719. -         TAILQ_REMOVE(&wdc->sc_drives, wd, sc_drivechain);
  2720. -         if (bp->b_actf) {
  2721. -             TAILQ_INSERT_TAIL(&wdc->sc_drives, wd, sc_drivechain);
  2722. -         } else
  2723. -             wd->sc_q.b_active = 0;
  2724. -     }
  2725. -     bp->b_resid = wd->sc_bcount;
  2726. -     wd->sc_skip = 0;
  2727. -     wd->sc_q.b_actf = bp->b_actf;
  2728. -     disk_unbusy(&wd->sc_dk, (bp->b_bcount - bp->b_resid));
  2729. -     if (!wd->sc_q.b_actf) {
  2730. -         TAILQ_REMOVE(&wdc->sc_drives, wd, sc_drivechain);
  2731. -         wd->sc_q.b_active = 0;
  2732. -     } else
  2733. -         disk_busy(&wd->sc_dk);
  2734. -     biodone(bp);
  2735. - }
  2736. - int
  2737. - wdread(dev, uio, flags)
  2738. -     dev_t dev;
  2739. -     struct uio *uio;
  2740. -     int flags;
  2741. - {
  2742. -     return (physio(wdstrategy, NULL, dev, B_READ, minphys, uio));
  2743. - }
  2744. - int
  2745. - wdwrite(dev, uio, flags)
  2746. -     dev_t dev;
  2747. -     struct uio *uio;
  2748. -     int flags;
  2749. - {
  2750. -     return (physio(wdstrategy, NULL, dev, B_WRITE, minphys, uio));
  2751. - }
  2752. - /*
  2753. -  * Start I/O on a controller.  This does the calculation, and starts a read or
  2754. -  * write operation.  Called to from wdstart() to start a transfer, from
  2755. -  * wdcintr() to continue a multi-sector transfer or start the next transfer, or
  2756. -  * wdcrestart() after recovering from an error.
  2757. -  */
  2758. - void
  2759. - wdcstart(wdc)
  2760. -     struct wdc_softc *wdc;
  2761. - {
  2762. -     struct wd_softc *wd;
  2763. -     struct buf *bp;
  2764. -     struct disklabel *lp;
  2765. -     int nblks;
  2766. - #ifdef DIAGNOSTIC
  2767. -     if ((wdc->sc_flags & WDCF_ACTIVE) != 0)
  2768. -         panic("wdcstart: controller still active");
  2769. - #endif
  2770. -     /*
  2771. -      * XXX
  2772. -      * This is a kluge.  See comments in wd_get_parms().
  2773. -      */
  2774. -     if ((wdc->sc_flags & WDCF_WANTED) != 0) {
  2775. -         wdc->sc_flags &= ~WDCF_WANTED;
  2776. -         wakeup(wdc);
  2777. -         return;
  2778. -     }
  2779. - loop:
  2780. -     /* Is there a drive for the controller to do a transfer with? */
  2781. -     wd = wdc->sc_drives.tqh_first;
  2782. -     if (wd == NULL)
  2783. -         return;
  2784. -     
  2785. -     /* Is there a transfer to this drive?  If not, deactivate drive. */
  2786. -     bp = wd->sc_q.b_actf;
  2787. -     
  2788. -     if (wdc->sc_errors >= WDIORETRIES) {
  2789. -         wderror(wd, bp, "hard error");
  2790. -         bp->b_error = EIO;
  2791. -         bp->b_flags |= B_ERROR;
  2792. -         wdfinish(wd, bp);
  2793. -         goto loop;
  2794. -     }
  2795. -     /* Do control operations specially. */
  2796. -     if (wd->sc_state < OPEN) {
  2797. -         /*
  2798. -          * Actually, we want to be careful not to mess with the control
  2799. -          * state if the device is currently busy, but we can assume
  2800. -          * that we never get to this point if that's the case.
  2801. -          */
  2802. -         if (wdcontrol(wd) == 0) {
  2803. -             /* The drive is busy.  Wait. */
  2804. -             return;
  2805. -         }
  2806. -     }
  2807. -     /*
  2808. -      * WDCF_ERROR is set by wdcunwedge() and wdcintr() when an error is
  2809. -      * encountered.  If we are in multi-sector mode, then we switch to
  2810. -      * single-sector mode and retry the operation from the start.
  2811. -      */
  2812. -     if (wdc->sc_flags & WDCF_ERROR) {
  2813. -         wdc->sc_flags &= ~WDCF_ERROR;
  2814. -         if ((wdc->sc_flags & WDCF_SINGLE) == 0) {
  2815. -             wdc->sc_flags |= WDCF_SINGLE;
  2816. -             wd->sc_skip = 0;
  2817. -         }
  2818. -     }
  2819. -     lp = wd->sc_dk.dk_label;
  2820. -     /* When starting a transfer... */
  2821. -     if (wd->sc_skip == 0) {
  2822. -         int part = WDPART(bp->b_dev);
  2823. -         daddr_t blkno;
  2824. - #ifdef WDDEBUG
  2825. -         printf("\n%s: wdcstart %s %d@%d; map ", wd->sc_dev.dv_xname,
  2826. -             (bp->b_flags & B_READ) ? "read" : "write", bp->b_bcount,
  2827. -             bp->b_blkno);
  2828. - #endif
  2829. -         wd->sc_bcount = bp->b_bcount;
  2830. -         blkno = bp->b_blkno;
  2831. -         if (part != RAW_PART)
  2832. -             blkno += lp->d_partitions[part].p_offset;
  2833. -         wd->sc_blkno = blkno / (lp->d_secsize / DEV_BSIZE);
  2834. -     } else {
  2835. - #ifdef WDDEBUG
  2836. -         printf(" %d)%x", wd->sc_skip, inb(wd->sc_iobase+wd_altsts));
  2837. - #endif
  2838. -     }
  2839. -     /* When starting a multi-sector transfer, or doing single-sector
  2840. -         transfers... */
  2841. -     if (wd->sc_skip == 0 || (wdc->sc_flags & WDCF_SINGLE) != 0 ||
  2842. -         wd->sc_mode == WDM_DMA) {
  2843. -         daddr_t blkno = wd->sc_blkno;
  2844. -         long cylin, head, sector;
  2845. -         int command;
  2846. -         if ((wdc->sc_flags & WDCF_SINGLE) != 0)
  2847. -             nblks = 1;
  2848. -         else if (wd->sc_mode != WDM_DMA)
  2849. -             nblks = wd->sc_bcount / lp->d_secsize;
  2850. -         else
  2851. -             nblks = min(wd->sc_bcount / lp->d_secsize, 8);
  2852. -         /* Check for bad sectors and adjust transfer, if necessary. */
  2853. -         if ((lp->d_flags & D_BADSECT) != 0
  2854. - #ifdef B_FORMAT
  2855. -             && (bp->b_flags & B_FORMAT) == 0
  2856. - #endif
  2857. -             ) {
  2858. -             long blkdiff;
  2859. -             int i;
  2860. -             for (i = 0; (blkdiff = wd->sc_badsect[i]) != -1; i++) {
  2861. -                 blkdiff -= blkno;
  2862. -                 if (blkdiff < 0)
  2863. -                     continue;
  2864. -                 if (blkdiff == 0) {
  2865. -                     /* Replace current block of transfer. */
  2866. -                     blkno =
  2867. -                         lp->d_secperunit - lp->d_nsectors - i - 1;
  2868. -                 }
  2869. -                 if (blkdiff < nblks) {
  2870. -                     /* Bad block inside transfer. */
  2871. -                     wdc->sc_flags |= WDCF_SINGLE;
  2872. -                     nblks = 1;
  2873. -                 }
  2874. -                 break;
  2875. -             }
  2876. -             /* Tranfer is okay now. */
  2877. -         }
  2878. -         if ((wd->sc_params.wdp_capabilities & WD_CAP_LBA) != 0) {
  2879. -             sector = (blkno >> 0) & 0xff;
  2880. -             cylin = (blkno >> 8) & 0xffff;
  2881. -             head = (blkno >> 24) & 0xf;
  2882. -             head |= WDSD_LBA;
  2883. -         } else {
  2884. -             sector = blkno % lp->d_nsectors;
  2885. -             sector++;    /* Sectors begin with 1, not 0. */
  2886. -             blkno /= lp->d_nsectors;
  2887. -             head = blkno % lp->d_ntracks;
  2888. -             blkno /= lp->d_ntracks;
  2889. -             cylin = blkno;
  2890. -             head |= WDSD_CHS;
  2891. -         }
  2892. -         if (wd->sc_mode == WDM_PIOSINGLE ||
  2893. -             (wdc->sc_flags & WDCF_SINGLE) != 0)
  2894. -             wd->sc_nblks = 1;
  2895. -         else if (wd->sc_mode == WDM_PIOMULTI)
  2896. -             wd->sc_nblks = min(nblks, wd->sc_multiple);
  2897. -         else
  2898. -             wd->sc_nblks = nblks;
  2899. -         wd->sc_nbytes = wd->sc_nblks * lp->d_secsize;
  2900. -     
  2901. - #ifdef B_FORMAT
  2902. -         if (bp->b_flags & B_FORMAT) {
  2903. -             sector = lp->d_gap3;
  2904. -             nblks = lp->d_nsectors;
  2905. -             command = WDCC_FORMAT;
  2906. -         } else
  2907. - #endif
  2908. -         switch (wd->sc_mode) {
  2909. -         case WDM_DMA:
  2910. -             command = (bp->b_flags & B_READ) ?
  2911. -                 WDCC_READDMA : WDCC_WRITEDMA;
  2912. -             /* Start the DMA channel and bounce the buffer if
  2913. -                necessary. */
  2914. -             isa_dmastart(
  2915. -                 bp->b_flags & B_READ ? DMAMODE_READ : DMAMODE_WRITE,
  2916. -                 bp->b_data + wd->sc_skip,
  2917. -                 wd->sc_nbytes, wdc->sc_drq);
  2918. -             break;
  2919. -         case WDM_PIOMULTI:
  2920. -             command = (bp->b_flags & B_READ) ?
  2921. -                 WDCC_READMULTI : WDCC_WRITEMULTI;
  2922. -             break;
  2923. -         case WDM_PIOSINGLE:
  2924. -             command = (bp->b_flags & B_READ) ?
  2925. -                 WDCC_READ : WDCC_WRITE;
  2926. -             break;
  2927. -         default:
  2928. - #ifdef DIAGNOSTIC
  2929. -             panic("bad wd mode");
  2930. - #endif
  2931. -             return;
  2932. -         }
  2933. -     
  2934. -         /* Initiate command! */
  2935. -         if (wdcommand(wd, command, cylin, head, sector, nblks) != 0) {
  2936. -             wderror(wd, NULL,
  2937. -                 "wdcstart: timeout waiting for unbusy");
  2938. -             wdcunwedge(wdc);
  2939. -             return;
  2940. -         }
  2941. - #ifdef WDDEBUG
  2942. -         printf("sector %d cylin %d head %d addr %x sts %x\n", sector,
  2943. -             cylin, head, bp->b_data, inb(wd->sc_iobase+wd_altsts));
  2944. - #endif
  2945. -     } else if (wd->sc_nblks > 1) {
  2946. -         /* The number of blocks in the last stretch may be smaller. */
  2947. -         nblks = wd->sc_bcount / lp->d_secsize;
  2948. -         if (wd->sc_nblks > nblks) {
  2949. -             wd->sc_nblks = nblks;
  2950. -             wd->sc_nbytes = wd->sc_bcount;
  2951. -         }
  2952. -     }
  2953. -     /* If this was a write and not using DMA, push the data. */
  2954. -     if (wd->sc_mode != WDM_DMA &&
  2955. -         (bp->b_flags & (B_READ|B_WRITE)) == B_WRITE) {
  2956. -         if (wait_for_drq(wdc) < 0) {
  2957. -             wderror(wd, NULL, "wdcstart: timeout waiting for drq");
  2958. -             wdcunwedge(wdc);
  2959. -             return;
  2960. -         }
  2961. -         /* Push out data. */
  2962. -         if ((wd->sc_flags & WDF_32BIT) == 0)
  2963. -             outsw(wdc->sc_iobase+wd_data, bp->b_data + wd->sc_skip,
  2964. -                 wd->sc_nbytes >> 1);
  2965. -         else
  2966. -             outsl(wdc->sc_iobase+wd_data, bp->b_data + wd->sc_skip,
  2967. -                 wd->sc_nbytes >> 2);
  2968. -     }
  2969. -     wdc->sc_flags |= WDCF_ACTIVE;
  2970. -     timeout(wdctimeout, wdc, WAITTIME);
  2971. - }
  2972. - /*
  2973. -  * Interrupt routine for the controller.  Acknowledge the interrupt, check for
  2974. -  * errors on the current operation, mark it done if necessary, and start the
  2975. -  * next request.  Also check for a partially done transfer, and continue with
  2976. -  * the next chunk if so.
  2977. -  */
  2978. - int
  2979. - wdcintr(arg)
  2980. -     void *arg;
  2981. - {
  2982. -     struct wdc_softc *wdc = arg;
  2983. -     struct wd_softc *wd;
  2984. -     struct buf *bp;
  2985. -     if ((wdc->sc_flags & WDCF_ACTIVE) == 0) {
  2986. -         /* Clear the pending interrupt and abort. */
  2987. -         (void) inb(wdc->sc_iobase+wd_status);
  2988. -         return 0;
  2989. -     }
  2990. -     wdc->sc_flags &= ~WDCF_ACTIVE;
  2991. -     untimeout(wdctimeout, wdc);
  2992. -     wd = wdc->sc_drives.tqh_first;
  2993. -     bp = wd->sc_q.b_actf;
  2994. - #ifdef WDDEBUG
  2995. -     printf("I%d ", ctrlr);
  2996. - #endif
  2997. -     if (wait_for_unbusy(wdc) < 0) {
  2998. -         wderror(wd, NULL, "wdcintr: timeout waiting for unbusy");
  2999. -         wdc->sc_status |= WDCS_ERR;    /* XXX */
  3000. -     }
  3001. -     
  3002. -     /* Is it not a transfer, but a control operation? */
  3003. -     if (wd->sc_state < OPEN) {
  3004. -         if (wdcontrol(wd) == 0) {
  3005. -             /* The drive is busy.  Wait. */
  3006. -             return 1;
  3007. -         }
  3008. -         wdcstart(wdc);
  3009. -         return 1;
  3010. -     }
  3011. -     /* Turn off the DMA channel and unbounce the buffer. */
  3012. -     if (wd->sc_mode == WDM_DMA)
  3013. -         isa_dmadone(bp->b_flags & B_READ ? DMAMODE_READ : DMAMODE_WRITE,
  3014. -             bp->b_data + wd->sc_skip, wd->sc_nbytes, wdc->sc_drq);
  3015. -     /* Have we an error? */
  3016. -     if (wdc->sc_status & WDCS_ERR) {
  3017. - #ifdef WDDEBUG
  3018. -         wderror(wd, NULL, "wdcintr");
  3019. - #endif
  3020. -         if ((wdc->sc_flags & WDCF_SINGLE) == 0) {
  3021. -             wdc->sc_flags |= WDCF_ERROR;
  3022. -             goto restart;
  3023. -         }
  3024. - #ifdef B_FORMAT
  3025. -         if (bp->b_flags & B_FORMAT)
  3026. -             goto bad;
  3027. - #endif
  3028. -     
  3029. -         if (++wdc->sc_errors < WDIORETRIES)
  3030. -             goto restart;
  3031. -         wderror(wd, bp, "hard error");
  3032. - #ifdef B_FORMAT
  3033. -     bad:
  3034. - #endif
  3035. -         bp->b_error = EIO;
  3036. -         bp->b_flags |= B_ERROR;
  3037. -         goto done;
  3038. -     }
  3039. -     /* If this was a read and not using DMA, fetch the data. */
  3040. -     if (wd->sc_mode != WDM_DMA &&
  3041. -         (bp->b_flags & (B_READ|B_WRITE)) == B_READ) {
  3042. -         if ((wdc->sc_status & (WDCS_DRDY | WDCS_DSC | WDCS_DRQ))
  3043. -             != (WDCS_DRDY | WDCS_DSC | WDCS_DRQ)) {
  3044. -             wderror(wd, NULL, "wdcintr: read intr before drq");
  3045. -             wdcunwedge(wdc);
  3046. -             return 1;
  3047. -         }
  3048. -         /* Pull in data. */
  3049. -         if ((wd->sc_flags & WDF_32BIT) == 0)
  3050. -             insw(wdc->sc_iobase+wd_data, bp->b_data + wd->sc_skip, 
  3051. -                 wd->sc_nbytes >> 1);
  3052. -         else
  3053. -             insl(wdc->sc_iobase+wd_data, bp->b_data + wd->sc_skip, 
  3054. -                 wd->sc_nbytes >> 2);
  3055. -     }
  3056. -     
  3057. -     /* If we encountered any abnormalities, flag it as a soft error. */
  3058. -     if (wdc->sc_errors > 0 ||
  3059. -         (wdc->sc_status & WDCS_CORR) != 0) {
  3060. -         wderror(wd, bp, "soft error (corrected)");
  3061. -         wdc->sc_errors = 0;
  3062. -     }
  3063. -     
  3064. -     /* Adjust pointers for the next block, if any. */
  3065. -     wd->sc_blkno += wd->sc_nblks;
  3066. -     wd->sc_skip += wd->sc_nbytes;
  3067. -     wd->sc_bcount -= wd->sc_nbytes;
  3068. -     /* See if this transfer is complete. */
  3069. -     if (wd->sc_bcount > 0)
  3070. -         goto restart;
  3071. - done:
  3072. -     /* Done with this transfer, with or without error. */
  3073. -     wdfinish(wd, bp);
  3074. - restart:
  3075. -     /* Start the next operation, if any. */
  3076. -     wdcstart(wdc);
  3077. -     return 1;
  3078. - }
  3079. - /*
  3080. -  * Wait interruptibly for an exclusive lock.
  3081. -  *
  3082. -  * XXX
  3083. -  * Several drivers do this; it should be abstracted and made MP-safe.
  3084. -  */
  3085. - int
  3086. - wdlock(wd)
  3087. -     struct wd_softc *wd;
  3088. - {
  3089. -     int error;
  3090. -     while ((wd->sc_flags & WDF_LOCKED) != 0) {
  3091. -         wd->sc_flags |= WDF_WANTED;
  3092. -         if ((error = tsleep(wd, PRIBIO | PCATCH, "wdlck", 0)) != 0)
  3093. -             return error;
  3094. -     }
  3095. -     wd->sc_flags |= WDF_LOCKED;
  3096. -     return 0;
  3097. - }
  3098. - /*
  3099. -  * Unlock and wake up any waiters.
  3100. -  */
  3101. - void
  3102. - wdunlock(wd)
  3103. -     struct wd_softc *wd;
  3104. - {
  3105. -     wd->sc_flags &= ~WDF_LOCKED;
  3106. -     if ((wd->sc_flags & WDF_WANTED) != 0) {
  3107. -         wd->sc_flags &= ~WDF_WANTED;
  3108. -         wakeup(wd);
  3109. -     }
  3110. - }
  3111. - int
  3112. - wdopen(dev, flag, fmt, p)
  3113. -     dev_t dev;
  3114. -     int flag, fmt;
  3115. -     struct proc *p;
  3116. - {
  3117. -     struct wd_softc *wd;
  3118. -     int unit, part;
  3119. -     int error;
  3120. -     
  3121. -     unit = WDUNIT(dev);
  3122. -     if (unit >= wd_cd.cd_ndevs)
  3123. -         return ENXIO;
  3124. -     wd = wd_cd.cd_devs[unit];
  3125. -     if (wd == 0)
  3126. -         return ENXIO;
  3127. -     
  3128. -     if ((error = wdlock(wd)) != 0)
  3129. -         return error;
  3130. -     if (wd->sc_dk.dk_openmask != 0) {
  3131. -         /*
  3132. -          * If any partition is open, but the disk has been invalidated,
  3133. -          * disallow further opens.
  3134. -          */
  3135. -         if ((wd->sc_flags & WDF_LOADED) == 0) {
  3136. -             error = EIO;
  3137. -             goto bad3;
  3138. -         }
  3139. -     } else {
  3140. -         if ((wd->sc_flags & WDF_LOADED) == 0) {
  3141. -             wd->sc_flags |= WDF_LOADED;
  3142. -             /* Load the physical device parameters. */
  3143. -             if (wd_get_parms(wd) != 0) {
  3144. -                 error = ENXIO;
  3145. -                 goto bad2;
  3146. -             }
  3147. -             /* Load the partition info if not already loaded. */
  3148. -             wdgetdisklabel(wd);
  3149. -         }
  3150. -     }
  3151. -     part = WDPART(dev);
  3152. -     /* Check that the partition exists. */
  3153. -     if (part != RAW_PART &&
  3154. -         (part >= wd->sc_dk.dk_label->d_npartitions ||
  3155. -          wd->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) {
  3156. -         error = ENXIO;
  3157. -         goto bad;
  3158. -     }
  3159. -     
  3160. -     /* Insure only one open at a time. */
  3161. -     switch (fmt) {
  3162. -     case S_IFCHR:
  3163. -         wd->sc_dk.dk_copenmask |= (1 << part);
  3164. -         break;
  3165. -     case S_IFBLK:
  3166. -         wd->sc_dk.dk_bopenmask |= (1 << part);
  3167. -         break;
  3168. -     }
  3169. -     wd->sc_dk.dk_openmask = wd->sc_dk.dk_copenmask | wd->sc_dk.dk_bopenmask;
  3170. -     wdunlock(wd);
  3171. -     return 0;
  3172. - bad2:
  3173. -     wd->sc_flags &= ~WDF_LOADED;
  3174. - bad:
  3175. -     if (wd->sc_dk.dk_openmask == 0) {
  3176. -     }
  3177. - bad3:
  3178. -     wdunlock(wd);
  3179. -     return error;
  3180. - }
  3181. - int
  3182. - wdclose(dev, flag, fmt, p)
  3183. -     dev_t dev;
  3184. -     int flag, fmt;
  3185. -     struct proc *p;
  3186. - {
  3187. -     struct wd_softc *wd = wd_cd.cd_devs[WDUNIT(dev)];
  3188. -     int part = WDPART(dev);
  3189. -     int error;
  3190. -     
  3191. -     if ((error = wdlock(wd)) != 0)
  3192. -         return error;
  3193. -     switch (fmt) {
  3194. -     case S_IFCHR:
  3195. -         wd->sc_dk.dk_copenmask &= ~(1 << part);
  3196. -         break;
  3197. -     case S_IFBLK:
  3198. -         wd->sc_dk.dk_bopenmask &= ~(1 << part);
  3199. -         break;
  3200. -     }
  3201. -     wd->sc_dk.dk_openmask = wd->sc_dk.dk_copenmask | wd->sc_dk.dk_bopenmask;
  3202. -     if (wd->sc_dk.dk_openmask == 0) {
  3203. -         /* XXXX Must wait for I/O to complete! */
  3204. -     }
  3205. -     wdunlock(wd);
  3206. -     return 0;
  3207. - }
  3208. - /*
  3209. -  * Fabricate a default disk label, and try to read the correct one.
  3210. -  */
  3211. - void
  3212. - wdgetdisklabel(wd)
  3213. -     struct wd_softc *wd;
  3214. - {
  3215. -     struct disklabel *lp = wd->sc_dk.dk_label;
  3216. -     char *errstring;
  3217. -     bzero(lp, sizeof(struct disklabel));
  3218. -     bzero(wd->sc_dk.dk_cpulabel, sizeof(struct cpu_disklabel));
  3219. -     lp->d_secsize = DEV_BSIZE;
  3220. -     lp->d_ntracks = wd->sc_params.wdp_heads;
  3221. -     lp->d_nsectors = wd->sc_params.wdp_sectors;
  3222. -     lp->d_ncylinders = wd->sc_params.wdp_cylinders;
  3223. -     lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
  3224. - #if 0
  3225. -     strncpy(lp->d_typename, "ST506 disk", 16);
  3226. -     lp->d_type = DTYPE_ST506;
  3227. - #endif
  3228. -     strncpy(lp->d_packname, wd->sc_params.wdp_model, 16);
  3229. -     lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders;
  3230. -     lp->d_rpm = 3600;
  3231. -     lp->d_interleave = 1;
  3232. -     lp->d_flags = 0;
  3233. -     lp->d_partitions[RAW_PART].p_offset = 0;
  3234. -     lp->d_partitions[RAW_PART].p_size =
  3235. -         lp->d_secperunit * (lp->d_secsize / DEV_BSIZE);
  3236. -     lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED;
  3237. -     lp->d_npartitions = RAW_PART + 1;
  3238. -     lp->d_magic = DISKMAGIC;
  3239. -     lp->d_magic2 = DISKMAGIC;
  3240. -     lp->d_checksum = dkcksum(lp);
  3241. -     wd->sc_badsect[0] = -1;
  3242. -     if (wd->sc_state > RECAL)
  3243. -         wd->sc_state = RECAL;
  3244. -     errstring = readdisklabel(MAKEWDDEV(0, wd->sc_dev.dv_unit, RAW_PART),
  3245. -         wdstrategy, lp, wd->sc_dk.dk_cpulabel);
  3246. -     if (errstring) {
  3247. -         /*
  3248. -          * This probably happened because the drive's default
  3249. -          * geometry doesn't match the DOS geometry.  We
  3250. -          * assume the DOS geometry is now in the label and try
  3251. -          * again.  XXX This is a kluge.
  3252. -          */
  3253. -         if (wd->sc_state > GEOMETRY)
  3254. -             wd->sc_state = GEOMETRY;
  3255. -         errstring = readdisklabel(MAKEWDDEV(0, wd->sc_dev.dv_unit, RAW_PART),
  3256. -             wdstrategy, lp, wd->sc_dk.dk_cpulabel);
  3257. -     }
  3258. -     if (errstring) {
  3259. -         printf("%s: %s\n", wd->sc_dev.dv_xname, errstring);
  3260. -         return;
  3261. -     }
  3262. -     if (wd->sc_state > GEOMETRY)
  3263. -         wd->sc_state = GEOMETRY;
  3264. -     if ((lp->d_flags & D_BADSECT) != 0)
  3265. -         bad144intern(wd);
  3266. - }
  3267. - /*
  3268. -  * Implement operations needed before read/write.
  3269. -  * Returns 0 if operation still in progress, 1 if completed.
  3270. -  */
  3271. - int
  3272. - wdcontrol(wd)
  3273. -     struct wd_softc *wd;
  3274. - {
  3275. -     struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent;
  3276. -     
  3277. -     switch (wd->sc_state) {
  3278. -     case RECAL:            /* Set SDH, step rate, do recal. */
  3279. -         if (wdcommandshort(wdc, wd->sc_drive, WDCC_RECAL) != 0) {
  3280. -             wderror(wd, NULL, "wdcontrol: recal failed (1)");
  3281. -             goto bad;
  3282. -         }
  3283. -         wd->sc_state = RECAL_WAIT;
  3284. -         break;
  3285. -     case RECAL_WAIT:
  3286. -         if (wdc->sc_status & WDCS_ERR) {
  3287. -             wderror(wd, NULL, "wdcontrol: recal failed (2)");
  3288. -             goto bad;
  3289. -         }
  3290. -         /* fall through */
  3291. -     case GEOMETRY:
  3292. -         if ((wd->sc_params.wdp_capabilities & WD_CAP_LBA) != 0)
  3293. -             goto multimode;
  3294. -         if (wdsetctlr(wd) != 0) {
  3295. -             /* Already printed a message. */
  3296. -             goto bad;
  3297. -         }
  3298. -         wd->sc_state = GEOMETRY_WAIT;
  3299. -         break;
  3300. -     case GEOMETRY_WAIT:
  3301. -         if (wdc->sc_status & WDCS_ERR) {
  3302. -             wderror(wd, NULL, "wdcontrol: geometry failed");
  3303. -             goto bad;
  3304. -         }
  3305. -         /* fall through */
  3306. -     case MULTIMODE:
  3307. -     multimode:
  3308. -         if (wd->sc_mode != WDM_PIOMULTI)
  3309. -             goto open;
  3310. -         outb(wdc->sc_iobase+wd_seccnt, wd->sc_multiple);
  3311. -         if (wdcommandshort(wdc, wd->sc_drive, WDCC_SETMULTI) != 0) {
  3312. -             wderror(wd, NULL, "wdcontrol: setmulti failed (1)");
  3313. -             goto bad;
  3314. -         }
  3315. -         wd->sc_state = MULTIMODE_WAIT;
  3316. -         break;
  3317. -     case MULTIMODE_WAIT:
  3318. -         if (wdc->sc_status & WDCS_ERR) {
  3319. -             wderror(wd, NULL, "wdcontrol: setmulti failed (2)");
  3320. -             goto bad;
  3321. -         }
  3322. -         /* fall through */
  3323. -     case OPEN:
  3324. -     open:
  3325. -         wdc->sc_errors = 0;
  3326. -         wd->sc_state = OPEN;
  3327. -         /*
  3328. -          * The rest of the initialization can be done by normal means.
  3329. -          */
  3330. -         return 1;
  3331. -     bad:
  3332. -         wdcunwedge(wdc);
  3333. -         return 0;
  3334. -     }
  3335. -     wdc->sc_flags |= WDCF_ACTIVE;
  3336. -     timeout(wdctimeout, wdc, WAITTIME);
  3337. -     return 0;
  3338. - }
  3339. - /*
  3340. -  * Wait for the drive to become ready and send a command.
  3341. -  * Return -1 if busy for too long or 0 otherwise.
  3342. -  * Assumes interrupts are blocked.
  3343. -  */
  3344. - int
  3345. - wdcommand(wd, command, cylin, head, sector, count)
  3346. -     struct wd_softc *wd;
  3347. -     int command;
  3348. -     int cylin, head, sector, count;
  3349. - {
  3350. -     struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent;
  3351. -     int iobase = wdc->sc_iobase;
  3352. -     int stat;
  3353. -     
  3354. -     /* Select drive, head, and addressing mode. */
  3355. -     outb(iobase+wd_sdh, WDSD_IBM | (wd->sc_drive << 4) | head);
  3356. -     /* Wait for it to become ready to accept a command. */
  3357. -     if (command == WDCC_IDP)
  3358. -         stat = wait_for_unbusy(wdc);
  3359. -     else
  3360. -         stat = wdcwait(wdc, WDCS_DRDY);
  3361. -     if (stat < 0)
  3362. -         return -1;
  3363. -     
  3364. -     /* Load parameters. */
  3365. -     if (wd->sc_dk.dk_label->d_type == DTYPE_ST506)
  3366. -         outb(iobase+wd_precomp, wd->sc_dk.dk_label->d_precompcyl / 4);
  3367. -     else
  3368. -         outb(iobase+wd_features, 0);
  3369. -     outb(iobase+wd_cyl_lo, cylin);
  3370. -     outb(iobase+wd_cyl_hi, cylin >> 8);
  3371. -     outb(iobase+wd_sector, sector);
  3372. -     outb(iobase+wd_seccnt, count);
  3373. -     /* Send command. */
  3374. -     outb(iobase+wd_command, command);
  3375. -     return 0;
  3376. - }
  3377. - /*
  3378. -  * Simplified version of wdcommand().
  3379. -  */
  3380. - int
  3381. - wdcommandshort(wdc, drive, command)
  3382. -     struct wdc_softc *wdc;
  3383. -     int drive;
  3384. -     int command;
  3385. - {
  3386. -     int iobase = wdc->sc_iobase;
  3387. -     /* Select drive. */
  3388. -     outb(iobase+wd_sdh, WDSD_IBM | (drive << 4));
  3389. -     if (wdcwait(wdc, WDCS_DRDY) < 0)
  3390. -         return -1;
  3391. -     outb(iobase+wd_command, command);
  3392. -     return 0;
  3393. - }
  3394. - /*
  3395. -  * Tell the drive what geometry to use.
  3396. -  */
  3397. - int
  3398. - wdsetctlr(wd)
  3399. -     struct wd_softc *wd;
  3400. - {
  3401. - #ifdef WDDEBUG
  3402. -     printf("wd(%d,%d) C%dH%dS%d\n", wd->sc_dev.dv_unit, wd->sc_drive,
  3403. -         wd->sc_dk.dk_label->d_ncylinders, wd->sc_dk.dk_label->d_ntracks,
  3404. -         wd->sc_dk.dk_label->d_nsectors);
  3405. - #endif
  3406. -     
  3407. -     if (wdcommand(wd, WDCC_IDP, wd->sc_dk.dk_label->d_ncylinders,
  3408. -         wd->sc_dk.dk_label->d_ntracks - 1, 0,
  3409. -         wd->sc_dk.dk_label->d_nsectors) != 0) {
  3410. -         wderror(wd, NULL, "wdsetctlr: geometry upload failed");
  3411. -         return -1;
  3412. -     }
  3413. -     return 0;
  3414. - }
  3415. - /*
  3416. -  * Get the drive parameters, if ESDI or ATA, or create fake ones for ST506.
  3417. -  */
  3418. - int
  3419. - wd_get_parms(wd)
  3420. -     struct wd_softc *wd;
  3421. - {
  3422. -     struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent;
  3423. -     int i;
  3424. -     char tb[DEV_BSIZE];
  3425. -     int s, error;
  3426. -     /*
  3427. -      * XXX
  3428. -      * The locking done here, and the length of time this may keep the rest
  3429. -      * of the system suspended, is a kluge.  This should be rewritten to
  3430. -      * set up a transfer and queue it through wdstart(), but it's called
  3431. -      * infrequently enough that this isn't a pressing matter.
  3432. -      */
  3433. -     s = splbio();
  3434. -     while ((wdc->sc_flags & WDCF_ACTIVE) != 0) {
  3435. -         wdc->sc_flags |= WDCF_WANTED;
  3436. -         if ((error = tsleep(wdc, PRIBIO | PCATCH, "wdprm", 0)) != 0) {
  3437. -             splx(s);
  3438. -             return error;
  3439. -         }
  3440. -     }
  3441. -     if (wdcommandshort(wdc, wd->sc_drive, WDCC_IDENTIFY) != 0 ||
  3442. -         wait_for_drq(wdc) != 0) {
  3443. -         /*
  3444. -          * We `know' there's a drive here; just assume it's old.
  3445. -          * This geometry is only used to read the MBR and print a
  3446. -          * (false) attach message.
  3447. -          */
  3448. -         strncpy(wd->sc_dk.dk_label->d_typename, "ST506",
  3449. -             sizeof wd->sc_dk.dk_label->d_typename);
  3450. -         wd->sc_dk.dk_label->d_type = DTYPE_ST506;
  3451. -         strncpy(wd->sc_params.wdp_model, "unknown",
  3452. -             sizeof wd->sc_params.wdp_model);
  3453. -         wd->sc_params.wdp_config = WD_CFG_FIXED;
  3454. -         wd->sc_params.wdp_cylinders = 1024;
  3455. -         wd->sc_params.wdp_heads = 8;
  3456. -         wd->sc_params.wdp_sectors = 17;
  3457. -         wd->sc_params.wdp_maxmulti = 0;
  3458. -         wd->sc_params.wdp_usedmovsd = 0;
  3459. -         wd->sc_params.wdp_capabilities = 0;
  3460. -     } else {
  3461. -         strncpy(wd->sc_dk.dk_label->d_typename, "ESDI/IDE",
  3462. -             sizeof wd->sc_dk.dk_label->d_typename);
  3463. -         wd->sc_dk.dk_label->d_type = DTYPE_ESDI;
  3464. -         /* Read in parameter block. */
  3465. -         insw(wdc->sc_iobase+wd_data, tb, sizeof(tb) / sizeof(short));
  3466. -         bcopy(tb, &wd->sc_params, sizeof(struct wdparams));
  3467. -         /* Shuffle string byte order. */
  3468. -         for (i = 0; i < sizeof(wd->sc_params.wdp_model); i += 2) {
  3469. -             u_short *p;
  3470. -             p = (u_short *)(wd->sc_params.wdp_model + i);
  3471. -             *p = ntohs(*p);
  3472. -         }
  3473. -     }
  3474. -     /* Clear any leftover interrupt. */
  3475. -     (void) inb(wdc->sc_iobase+wd_status);
  3476. -     /* Restart the queue. */
  3477. -     wdcstart(wdc);
  3478. -     splx(s);
  3479. -     return 0;
  3480. - }
  3481. - int
  3482. - wdioctl(dev, cmd, addr, flag, p)
  3483. -     dev_t dev;
  3484. -     u_long cmd;
  3485. -     caddr_t addr;
  3486. -     int flag;
  3487. -     struct proc *p;
  3488. - {
  3489. -     struct wd_softc *wd = wd_cd.cd_devs[WDUNIT(dev)];
  3490. -     int error;
  3491. -     
  3492. -     if ((wd->sc_flags & WDF_LOADED) == 0)
  3493. -         return EIO;
  3494. -     switch (cmd) {
  3495. -     case DIOCSBAD:
  3496. -         if ((flag & FWRITE) == 0)
  3497. -             return EBADF;
  3498. -         wd->sc_dk.dk_cpulabel->bad = *(struct dkbad *)addr;
  3499. -         wd->sc_dk.dk_label->d_flags |= D_BADSECT;
  3500. -         bad144intern(wd);
  3501. -         return 0;
  3502. -     case DIOCGDINFO:
  3503. -         *(struct disklabel *)addr = *(wd->sc_dk.dk_label);
  3504. -         return 0;
  3505. -     
  3506. -     case DIOCGPART:
  3507. -         ((struct partinfo *)addr)->disklab = wd->sc_dk.dk_label;
  3508. -         ((struct partinfo *)addr)->part =
  3509. -             &wd->sc_dk.dk_label->d_partitions[WDPART(dev)];
  3510. -         return 0;
  3511. -     
  3512. -     case DIOCWDINFO:
  3513. -     case DIOCSDINFO:
  3514. -         if ((flag & FWRITE) == 0)
  3515. -             return EBADF;
  3516. -         if ((error = wdlock(wd)) != 0)
  3517. -             return error;
  3518. -         wd->sc_flags |= WDF_LABELLING;
  3519. -         error = setdisklabel(wd->sc_dk.dk_label,
  3520. -             (struct disklabel *)addr, /*wd->sc_dk.dk_openmask : */0,
  3521. -             wd->sc_dk.dk_cpulabel);
  3522. -         if (error == 0) {
  3523. -             if (wd->sc_state > GEOMETRY)
  3524. -                 wd->sc_state = GEOMETRY;
  3525. -             if (cmd == DIOCWDINFO)
  3526. -                 error = writedisklabel(WDLABELDEV(dev),
  3527. -                     wdstrategy, wd->sc_dk.dk_label,
  3528. -                     wd->sc_dk.dk_cpulabel);
  3529. -         }
  3530. -         wd->sc_flags &= ~WDF_LABELLING;
  3531. -         wdunlock(wd);
  3532. -         return error;
  3533. -     
  3534. -     case DIOCWLABEL:
  3535. -         if ((flag & FWRITE) == 0)
  3536. -             return EBADF;
  3537. -         if (*(int *)addr)
  3538. -             wd->sc_flags |= WDF_WLABEL;
  3539. -         else
  3540. -             wd->sc_flags &= ~WDF_WLABEL;
  3541. -         return 0;
  3542. -     
  3543. - #ifdef notyet
  3544. -     case DIOCWFORMAT:
  3545. -         if ((flag & FWRITE) == 0)
  3546. -             return EBADF;
  3547. -     {
  3548. -         register struct format_op *fop;
  3549. -         struct iovec aiov;
  3550. -         struct uio auio;
  3551. -         
  3552. -         fop = (struct format_op *)addr;
  3553. -         aiov.iov_base = fop->df_buf;
  3554. -         aiov.iov_len = fop->df_count;
  3555. -         auio.uio_iov = &aiov;
  3556. -         auio.uio_iovcnt = 1;
  3557. -         auio.uio_resid = fop->df_count;
  3558. -         auio.uio_segflg = 0;
  3559. -         auio.uio_offset =
  3560. -             fop->df_startblk * wd->sc_dk.dk_label->d_secsize;
  3561. -         auio.uio_procp = p;
  3562. -         error = physio(wdformat, NULL, dev, B_WRITE, minphys,
  3563. -             &auio);
  3564. -         fop->df_count -= auio.uio_resid;
  3565. -         fop->df_reg[0] = wdc->sc_status;
  3566. -         fop->df_reg[1] = wdc->sc_error;
  3567. -         return error;
  3568. -     }
  3569. - #endif
  3570. -     default:
  3571. -         return ENOTTY;
  3572. -     }
  3573. - #ifdef DIAGNOSTIC
  3574. -     panic("wdioctl: impossible");
  3575. - #endif
  3576. - }
  3577. - #ifdef B_FORMAT
  3578. - int
  3579. - wdformat(struct buf *bp)
  3580. - {
  3581. -     bp->b_flags |= B_FORMAT;
  3582. -     return wdstrategy(bp);
  3583. - }
  3584. - #endif
  3585. - int
  3586. - wdsize(dev)
  3587. -     dev_t dev;
  3588. - {
  3589. -     struct wd_softc *wd;
  3590. -     int part;
  3591. -     int size;
  3592. -     
  3593. -     if (wdopen(dev, 0, S_IFBLK, NULL) != 0)
  3594. -         return -1;
  3595. -     wd = wd_cd.cd_devs[WDUNIT(dev)];
  3596. -     part = WDPART(dev);
  3597. -     if (wd->sc_dk.dk_label->d_partitions[part].p_fstype != FS_SWAP)
  3598. -         size = -1;
  3599. -     else
  3600. -         size = wd->sc_dk.dk_label->d_partitions[part].p_size;
  3601. -     if (wdclose(dev, 0, S_IFBLK, NULL) != 0)
  3602. -         return -1;
  3603. -     return size;
  3604. - }
  3605. - #ifndef __BDEVSW_DUMP_OLD_TYPE
  3606. - /* #define WD_DUMP_NOT_TRUSTED if you just want to watch */
  3607. - static int wddoingadump;
  3608. - static int wddumprecalibrated;
  3609. - /*
  3610. -  * Dump core after a system crash.
  3611. -  */
  3612. - int
  3613. - wddump(dev, blkno, va, size)
  3614. -         dev_t dev;
  3615. -         daddr_t blkno;
  3616. -         caddr_t va;
  3617. -         size_t size;
  3618. - {
  3619. -     struct wd_softc *wd;    /* disk unit to do the I/O */
  3620. -     struct wdc_softc *wdc;    /* disk controller to do the I/O */
  3621. -     struct disklabel *lp;    /* disk's disklabel */
  3622. -     int    unit, part;
  3623. -     int    nblks;        /* total number of sectors left to write */
  3624. -     /* Check if recursive dump; if so, punt. */
  3625. -     if (wddoingadump)
  3626. -         return EFAULT;
  3627. -     wddoingadump = 1;
  3628. -     unit = WDUNIT(dev);
  3629. -     if (unit >= wd_cd.cd_ndevs)
  3630. -         return ENXIO;
  3631. -     wd = wd_cd.cd_devs[unit];
  3632. -     if (wd == 0)
  3633. -         return ENXIO;
  3634. -     part = WDPART(dev);
  3635. -     /* Make sure it was initialized. */
  3636. -     if (wd->sc_state < OPEN)
  3637. -         return ENXIO;
  3638. -     wdc = (void *)wd->sc_dev.dv_parent;
  3639. -         /* Convert to disk sectors.  Request must be a multiple of size. */
  3640. -     lp = wd->sc_dk.dk_label;
  3641. -     if ((size % lp->d_secsize) != 0)
  3642. -         return EFAULT;
  3643. -     nblks = size / lp->d_secsize;
  3644. -     blkno = blkno / (lp->d_secsize / DEV_BSIZE);
  3645. -     /* Check transfer bounds against partition size. */
  3646. -     if ((blkno < 0) || ((blkno + nblks) > lp->d_partitions[part].p_size))
  3647. -         return EINVAL;  
  3648. -     /* Offset block number to start of partition. */
  3649. -     blkno += lp->d_partitions[part].p_offset;
  3650. -     /* Recalibrate, if first dump transfer. */
  3651. -     if (wddumprecalibrated == 0) {
  3652. -         wddumprecalibrated = 1;
  3653. -         if (wdcommandshort(wdc, wd->sc_drive, WDCC_RECAL) != 0 ||
  3654. -             wait_for_ready(wdc) != 0 || wdsetctlr(wd) != 0 ||
  3655. -             wait_for_ready(wdc) != 0) {
  3656. -             wderror(wd, NULL, "wddump: recal failed");
  3657. -             return EIO;
  3658. -         }
  3659. -     }
  3660. -    
  3661. -     while (nblks > 0) {
  3662. -         daddr_t xlt_blkno = blkno;
  3663. -         long cylin, head, sector;
  3664. -         if ((lp->d_flags & D_BADSECT) != 0) {
  3665. -             long blkdiff;
  3666. -             int i;
  3667. -             for (i = 0; (blkdiff = wd->sc_badsect[i]) != -1; i++) {
  3668. -                 blkdiff -= xlt_blkno;
  3669. -                 if (blkdiff < 0)
  3670. -                     continue;
  3671. -                 if (blkdiff == 0) {
  3672. -                     /* Replace current block of transfer. */
  3673. -                     xlt_blkno = lp->d_secperunit -
  3674. -                         lp->d_nsectors - i - 1;
  3675. -                 }
  3676. -                 break;
  3677. -             }
  3678. -             /* Tranfer is okay now. */
  3679. -         }
  3680. -         if ((wd->sc_params.wdp_capabilities & WD_CAP_LBA) != 0) {
  3681. -             sector = (xlt_blkno >> 0) & 0xff;
  3682. -             cylin = (xlt_blkno >> 8) & 0xffff;
  3683. -             head = (xlt_blkno >> 24) & 0xf;
  3684. -             head |= WDSD_LBA;
  3685. -         } else {
  3686. -             sector = xlt_blkno % lp->d_nsectors;
  3687. -             sector++;    /* Sectors begin with 1, not 0. */
  3688. -             xlt_blkno /= lp->d_nsectors;
  3689. -             head = xlt_blkno % lp->d_ntracks;
  3690. -             xlt_blkno /= lp->d_ntracks;
  3691. -             cylin = xlt_blkno;
  3692. -             head |= WDSD_CHS;
  3693. -         }
  3694. - #ifndef WD_DUMP_NOT_TRUSTED
  3695. -         if (wdcommand(wd, WDCC_WRITE, cylin, head, sector, 1) != 0 ||
  3696. -             wait_for_drq(wdc) != 0) {
  3697. -             wderror(wd, NULL, "wddump: write failed");
  3698. -             return EIO;
  3699. -         }
  3700. -     
  3701. -         outsw(wdc->sc_iobase+wd_data, va, lp->d_secsize >> 1);
  3702. -     
  3703. -         /* Check data request (should be done). */
  3704. -         if (wait_for_ready(wdc) != 0) {
  3705. -             wderror(wd, NULL, "wddump: timeout waiting for ready");
  3706. -             return EIO;
  3707. -         }
  3708. - #else    /* WD_DUMP_NOT_TRUSTED */
  3709. -         /* Let's just talk about this first... */
  3710. -         printf("wd%d: dump addr 0x%x, cylin %d, head %d, sector %d\n",
  3711. -             unit, va, cylin, head, sector);
  3712. -         delay(500 * 1000);    /* half a second */
  3713. - #endif
  3714. -         /* update block count */
  3715. -         nblks -= 1;
  3716. -         blkno += 1;
  3717. -         va += lp->d_secsize;
  3718. -     }
  3719. -     wddoingadump = 0;
  3720. -     return 0;
  3721. - }
  3722. - #else /* __BDEVSW_DUMP_NEW_TYPE */
  3723. - int
  3724. - wddump(dev, blkno, va, size)
  3725. -         dev_t dev;
  3726. -         daddr_t blkno;
  3727. -         caddr_t va;
  3728. -         size_t size;
  3729. - {
  3730. -     /* Not implemented. */
  3731. -     return ENXIO;
  3732. - }
  3733. - #endif /* __BDEVSW_DUMP_NEW_TYPE */
  3734. - /*
  3735. -  * Internalize the bad sector table.
  3736. -  */
  3737. - void
  3738. - bad144intern(wd)
  3739. -     struct wd_softc *wd;
  3740. - {
  3741. -     struct dkbad *bt = &wd->sc_dk.dk_cpulabel->bad;
  3742. -     struct disklabel *lp = wd->sc_dk.dk_label;
  3743. -     int i = 0;
  3744. -     for (; i < 126; i++) {
  3745. -         if (bt->bt_bad[i].bt_cyl == 0xffff)
  3746. -             break;
  3747. -         wd->sc_badsect[i] =
  3748. -             bt->bt_bad[i].bt_cyl * lp->d_secpercyl +
  3749. -             (bt->bt_bad[i].bt_trksec >> 8) * lp->d_nsectors +
  3750. -             (bt->bt_bad[i].bt_trksec & 0xff);
  3751. -     }
  3752. -     for (; i < 127; i++)
  3753. -         wd->sc_badsect[i] = -1;
  3754. - }
  3755. - int
  3756. - wdcreset(wdc)
  3757. -     struct wdc_softc *wdc;
  3758. - {
  3759. -     int iobase = wdc->sc_iobase;
  3760. -     /* Reset the device. */
  3761. -     outb(iobase+wd_ctlr, WDCTL_RST | WDCTL_IDS);
  3762. -     delay(1000);
  3763. -     outb(iobase+wd_ctlr, WDCTL_IDS);
  3764. -     delay(1000);
  3765. -     (void) inb(iobase+wd_error);
  3766. -     outb(iobase+wd_ctlr, WDCTL_4BIT);
  3767. -     if (wait_for_unbusy(wdc) < 0) {
  3768. -         printf("%s: reset failed\n", wdc->sc_dev.dv_xname);
  3769. -         return 1;
  3770. -     }
  3771. -     return 0;
  3772. - }
  3773. - void
  3774. - wdcrestart(arg)
  3775. -     void *arg;
  3776. - {
  3777. -     struct wdc_softc *wdc = arg;
  3778. -     int s;
  3779. -     s = splbio();
  3780. -     wdcstart(wdc);
  3781. -     splx(s);
  3782. - }
  3783. - /*
  3784. -  * Unwedge the controller after an unexpected error.  We do this by resetting
  3785. -  * it, marking all drives for recalibration, and stalling the queue for a short
  3786. -  * period to give the reset time to finish.
  3787. -  * NOTE: We use a timeout here, so this routine must not be called during
  3788. -  * autoconfig or dump.
  3789. -  */
  3790. - void
  3791. - wdcunwedge(wdc)
  3792. -     struct wdc_softc *wdc;
  3793. - {
  3794. -     int unit;
  3795. -     untimeout(wdctimeout, wdc);
  3796. -     (void) wdcreset(wdc);
  3797. -     /* Schedule recalibrate for all drives on this controller. */
  3798. -     for (unit = 0; unit < wd_cd.cd_ndevs; unit++) {
  3799. -         struct wd_softc *wd = wd_cd.cd_devs[unit];
  3800. -         if (!wd || (void *)wd->sc_dev.dv_parent != wdc)
  3801. -             continue;
  3802. -         if (wd->sc_state > RECAL)
  3803. -             wd->sc_state = RECAL;
  3804. -     }
  3805. -     wdc->sc_flags |= WDCF_ERROR;
  3806. -     ++wdc->sc_errors;
  3807. -     /* Wake up in a little bit and restart the operation. */
  3808. -     timeout(wdcrestart, wdc, RECOVERYTIME);
  3809. - }
  3810. - int
  3811. - wdcwait(wdc, mask)
  3812. -     struct wdc_softc *wdc;
  3813. -     int mask;
  3814. - {
  3815. -     int iobase = wdc->sc_iobase;
  3816. -     int timeout = 0;
  3817. -     u_char status;
  3818. - #ifdef WDCNDELAY_DEBUG
  3819. -     extern int cold;
  3820. - #endif
  3821. -     for (;;) {
  3822. -         wdc->sc_status = status = inb(iobase+wd_status);
  3823. -         if ((status & WDCS_BSY) == 0 && (status & mask) == mask)
  3824. -             break;
  3825. -         if (++timeout > WDCNDELAY)
  3826. -             return -1;
  3827. -         delay(WDCDELAY);
  3828. -     }
  3829. -     if (status & WDCS_ERR) {
  3830. -         wdc->sc_error = inb(iobase+wd_error);
  3831. -         return WDCS_ERR;
  3832. -     }
  3833. - #ifdef WDCNDELAY_DEBUG
  3834. -     /* After autoconfig, there should be no long delays. */
  3835. -     if (!cold && timeout > WDCNDELAY_DEBUG)
  3836. -         printf("%s: warning: busy-wait took %dus\n",
  3837. -             wdc->sc_dev.dv_xname, WDCDELAY * timeout);
  3838. - #endif
  3839. -     return 0;
  3840. - }
  3841. - void
  3842. - wdctimeout(arg)
  3843. -     void *arg;
  3844. - {
  3845. -     struct wdc_softc *wdc = (struct wdc_softc *)arg;
  3846. -     int s;
  3847. -     s = splbio();
  3848. -     if ((wdc->sc_flags & WDCF_ACTIVE) != 0) {
  3849. -         struct wd_softc *wd = wdc->sc_drives.tqh_first;
  3850. -         struct buf *bp = wd->sc_q.b_actf;
  3851. -         wdc->sc_flags &= ~WDCF_ACTIVE;
  3852. -         wderror(wdc, NULL, "lost interrupt");
  3853. -         printf("%s: lost interrupt: %sing %d@%s:%d\n",
  3854. -             wdc->sc_dev.dv_xname,
  3855. -             (bp->b_flags & B_READ) ? "read" : "writ",
  3856. -             wd->sc_nblks, wd->sc_dev.dv_xname, wd->sc_blkno);
  3857. -         wdcunwedge(wdc);
  3858. -     } else
  3859. -         wderror(wdc, NULL, "missing untimeout");
  3860. -     splx(s);
  3861. - }
  3862. - void
  3863. - wderror(dev, bp, msg)
  3864. -     void *dev;
  3865. -     struct buf *bp;
  3866. -     char *msg;
  3867. - {
  3868. -     struct wd_softc *wd = dev;
  3869. -     struct wdc_softc *wdc = dev;
  3870. -     if (bp) {
  3871. -         diskerr(bp, "wd", msg, LOG_PRINTF, wd->sc_skip / DEV_BSIZE,
  3872. -             wd->sc_dk.dk_label);
  3873. -         printf("\n");
  3874. -     } else
  3875. -         printf("%s: %s: status %b error %b\n", wdc->sc_dev.dv_xname,
  3876. -             msg, wdc->sc_status, WDCS_BITS, wdc->sc_error, WDERR_BITS);
  3877. - }
  3878. --- 0 ----
  3879. diff --exclude compile -bcrNP src.orig/sys/dev/isa/wd.c src/sys/dev/isa/wd.c
  3880. *** src.orig/sys/dev/isa/wd.c    Thu Jan  1 01:00:00 1970
  3881. --- src/sys/dev/isa/wd.c    Thu Jun  6 12:21:06 1996
  3882. ***************
  3883. *** 0 ****
  3884. --- 1,852 ----
  3885. + /*    $NetBSD: wd.c,v 1.142 1995/08/05 23:50:23 mycroft Exp $    */
  3886. + /*
  3887. +  * Copyright (c) 1994, 1995 Charles M. Hannum.  All rights reserved.
  3888. +  *
  3889. +  * DMA and multi-sector PIO handling are derived from code contributed by
  3890. +  * Onno van der Linden.
  3891. +  *
  3892. +  * Redistribution and use in source and binary forms, with or without
  3893. +  * modification, are permitted provided that the following conditions
  3894. +  * are met:
  3895. +  * 1. Redistributions of source code must retain the above copyright
  3896. +  *    notice, this list of conditions and the following disclaimer.
  3897. +  * 2. Redistributions in binary form must reproduce the above copyright
  3898. +  *    notice, this list of conditions and the following disclaimer in the
  3899. +  *    documentation and/or other materials provided with the distribution.
  3900. +  * 3. All advertising materials mentioning features or use of this software
  3901. +  *    must display the following acknowledgement:
  3902. +  *    This product includes software developed by Charles M. Hannum.
  3903. +  * 4. The name of the author may not be used to endorse or promote products
  3904. +  *    derived from this software without specific prior written permission.
  3905. +  *
  3906. +  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  3907. +  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  3908. +  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  3909. +  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  3910. +  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  3911. +  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  3912. +  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  3913. +  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  3914. +  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  3915. +  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  3916. +  */
  3917. + #include <sys/param.h>
  3918. + #include <sys/systm.h>
  3919. + #include <sys/kernel.h>
  3920. + #include <sys/conf.h>
  3921. + #include <sys/file.h>
  3922. + #include <sys/stat.h>
  3923. + #include <sys/ioctl.h>
  3924. + #include <sys/buf.h>
  3925. + #include <sys/uio.h>
  3926. + #include <sys/malloc.h>
  3927. + #include <sys/device.h>
  3928. + #include <sys/disklabel.h>
  3929. + #include <sys/disk.h>
  3930. + #include <sys/syslog.h>
  3931. + #include <sys/proc.h>
  3932. + #include <vm/vm.h>
  3933. + #include <machine/cpu.h>
  3934. + #include <machine/pio.h>
  3935. + #include <dev/isa/isavar.h>
  3936. + #include <dev/isa/wdreg.h>
  3937. + #include <dev/isa/wdlink.h>
  3938. + #define    WAITTIME    (4 * hz)    /* time to wait for a completion */
  3939. + #define    WDIORETRIES    5        /* number of retries before giving up */
  3940. + #define    WDUNIT(dev)            DISKUNIT(dev)
  3941. + #define    WDPART(dev)            DISKPART(dev)
  3942. + #define    MAKEWDDEV(maj, unit, part)    MAKEDISKDEV(maj, unit, part)
  3943. + #define    WDLABELDEV(dev)    (MAKEWDDEV(major(dev), WDUNIT(dev), RAW_PART))
  3944. + struct wd_softc {
  3945. +     struct device sc_dev;
  3946. +     struct disk sc_dk;
  3947. +     struct wd_link *d_link;
  3948. +     struct buf sc_q;
  3949. + };
  3950. + int wdprobe __P((struct device *, void *, void *));
  3951. + void wdattach __P((struct device *, struct device *, void *));
  3952. + struct cfdriver wd_cd = {
  3953. +     NULL, "wd", DV_DISK
  3954. + };
  3955. + struct cfattach wd_ca = {
  3956. +     sizeof(struct wd_softc), wdprobe, wdattach
  3957. + };
  3958. + void wdgetdisklabel __P((struct wd_softc *));
  3959. + void wdstrategy __P((struct buf *));
  3960. + void wdstart __P((struct wd_softc *));
  3961. + struct dkdriver wddkdriver = { wdstrategy };
  3962. + int wdlock __P((struct wd_link *));
  3963. + void wdunlock __P((struct wd_link *));
  3964. + int wdsetctlr __P((struct wd_link *));
  3965. + static void bad144intern __P((struct wd_softc *));
  3966. + int
  3967. + wdprobe(parent, match, aux)
  3968. +     struct device *parent;
  3969. +     void *match, *aux;
  3970. + {
  3971. +     caddr_t *wdc = (void *)parent;
  3972. +     struct cfdata *cf = match;
  3973. +     struct wd_link *d_link = aux;
  3974. +     int drive;
  3975. +     
  3976. +     if (d_link == NULL ) return 0;
  3977. +     if (d_link-> type != DRIVE) return 0;
  3978. +     drive = d_link->sc_drive;
  3979. +     if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != drive)
  3980. +         return 0;
  3981. +     return 1;
  3982. + }
  3983. + void
  3984. + wdattach(parent, self, aux)
  3985. +     struct device *parent, *self;
  3986. +     void *aux;
  3987. + {
  3988. +     struct wd_softc *wd = (void *)self;
  3989. +     struct caddr_t *wdc = (void *)parent;
  3990. +     struct wd_link *d_link= aux;
  3991. +     int i, blank;
  3992. +     char buf[41], c, *p, *q;
  3993. +     wd->d_link = d_link;
  3994. +     d_link->openings = 1;
  3995. +     d_link->wd_softc = (caddr_t)wd;
  3996. +     /*
  3997. +      * Initialize and attach the disk structure.
  3998. +      */
  3999. +     wd->sc_dk.dk_driver = &wddkdriver;
  4000. +     wd->sc_dk.dk_name = wd->sc_dev.dv_xname;
  4001. +     disk_attach(&wd->sc_dk);
  4002. +     d_link->sc_lp = wd->sc_dk.dk_label;
  4003. +     wdc_get_parms(d_link);
  4004. +     for (blank = 0, p = d_link->sc_params.wdp_model, q = buf, i = 0;
  4005. +          i < sizeof(d_link->sc_params.wdp_model); i++) {
  4006. +         c = *p++;
  4007. +         if (c == '\0')
  4008. +             break;
  4009. +         if (c != ' ') {
  4010. +             if (blank) {
  4011. +                 *q++ = ' ';
  4012. +                 blank = 0;
  4013. +             }
  4014. +             *q++ = c;
  4015. +         } else
  4016. +             blank = 1;
  4017. +     }
  4018. +     *q++ = '\0';
  4019. +     printf(": %dMB, %d cyl, %d head, %d sec, %d bytes/sec <%s>\n",
  4020. +         d_link->sc_params.wdp_cylinders *
  4021. +         (d_link->sc_params.wdp_heads * d_link->sc_params.wdp_sectors) /
  4022. +         (1048576 / DEV_BSIZE),
  4023. +         d_link->sc_params.wdp_cylinders,
  4024. +         d_link->sc_params.wdp_heads,
  4025. +         d_link->sc_params.wdp_sectors,
  4026. +         DEV_BSIZE,
  4027. +         buf);
  4028. +     if ((d_link->sc_params.wdp_capabilities & WD_CAP_DMA) != 0 &&
  4029. +         d_link->sc_mode == WDM_DMA) {
  4030. +         d_link->sc_mode = WDM_DMA;
  4031. +     } else if (d_link->sc_params.wdp_maxmulti > 1) {
  4032. +         d_link->sc_mode = WDM_PIOMULTI;
  4033. +         d_link->sc_multiple = min(d_link->sc_params.wdp_maxmulti, 16);
  4034. +     } else {
  4035. +         d_link->sc_mode = WDM_PIOSINGLE;
  4036. +         d_link->sc_multiple = 1;
  4037. +     }
  4038. +     printf("%s: using", wd->sc_dev.dv_xname);
  4039. +     if (d_link->sc_mode == WDM_DMA)
  4040. +         printf(" dma transfers,");
  4041. +     else
  4042. +         printf(" %d-sector %d-bit pio transfers,",
  4043. +             d_link->sc_multiple, (d_link->sc_flags & WDF_32BIT) == 0 ? 16 : 32);
  4044. +     if ((d_link->sc_params.wdp_capabilities & WD_CAP_LBA) != 0)
  4045. +         printf(" lba addressing\n");
  4046. +     else
  4047. +         printf(" chs addressing\n");
  4048. + }
  4049. + /*
  4050. +  * Read/write routine for a buffer.  Validates the arguments and schedules the
  4051. +  * transfer.  Does not wait for the transfer to complete.
  4052. +  */
  4053. + void
  4054. + wdstrategy(bp)
  4055. +     struct buf *bp;
  4056. + {
  4057. +     struct wd_softc *wd = wd_cd.cd_devs[WDUNIT(bp->b_dev)];
  4058. +     struct wd_link *d_link= wd->d_link;
  4059. +     int s;
  4060. +     
  4061. +     /* Valid request?  */
  4062. +     if (bp->b_blkno < 0 ||
  4063. +         (bp->b_bcount % wd->sc_dk.dk_label->d_secsize) != 0 ||
  4064. +         (bp->b_bcount / wd->sc_dk.dk_label->d_secsize) >= (1 << NBBY)) {
  4065. +         bp->b_error = EINVAL;
  4066. +         goto bad;
  4067. +     }
  4068. +     
  4069. +     /* If device invalidated (e.g. media change, door open), error. */
  4070. +     if ((d_link->sc_flags & WDF_LOADED) == 0) {
  4071. +         bp->b_error = EIO;
  4072. +         goto bad;
  4073. +     }
  4074. +     /* If it's a null transfer, return immediately. */
  4075. +     if (bp->b_bcount == 0)
  4076. +         goto done;
  4077. +     /*
  4078. +      * Do bounds checking, adjust transfer. if error, process.
  4079. +      * If end of partition, just return.
  4080. +      */
  4081. +     if (WDPART(bp->b_dev) != RAW_PART &&
  4082. +         bounds_check_with_label(bp, wd->sc_dk.dk_label,
  4083. +         (d_link->sc_flags & (WDF_WLABEL|WDF_LABELLING)) != 0) <= 0)
  4084. +         goto done;
  4085. +     
  4086. +     /* Queue transfer on drive, activate drive and controller if idle. */
  4087. +     s = splbio();
  4088. +     disksort(&wd->sc_q, bp);
  4089. +     wdstart(wd);
  4090. +     splx(s);
  4091. +     return;
  4092. +     
  4093. + bad:
  4094. +     bp->b_flags |= B_ERROR;
  4095. + done:
  4096. +     /* Toss transfer; we're done early. */
  4097. +     bp->b_resid = bp->b_bcount;
  4098. +     biodone(bp);
  4099. + }
  4100. + /*
  4101. +  * Queue a drive for I/O.
  4102. +  */
  4103. + void
  4104. + wdstart(wd)
  4105. +     struct wd_softc *wd;
  4106. + {
  4107. +     struct buf *dp, *bp=0;
  4108. +     struct wd_link *d_link = wd->d_link;
  4109. +     struct wdc_link *ctlr_link = d_link->ctlr_link;
  4110. +     struct wdc_xfer *xfer;
  4111. +     int blkno, nblks;
  4112. +     u_long p_offset; 
  4113. +     while (d_link->openings > 0) {
  4114. +         /* Is there a buf for us ? */
  4115. +         dp = &wd->sc_q;
  4116. +         if ((bp = dp->b_actf) == NULL)  /* yes, an assign */
  4117. +                      return;
  4118. +         dp->b_actf = bp->b_actf;
  4119. +         
  4120. +         /* 
  4121. +          * Make the command. First lock the device
  4122. +          */
  4123. +         d_link->openings--;
  4124. +         if (WDPART(bp->b_dev) != RAW_PART)
  4125. +             p_offset=wd->sc_dk.dk_label->d_partitions[WDPART(bp->b_dev)].p_offset;
  4126. +         else p_offset=0;
  4127. +         xfer = wdc_get_xfer(ctlr_link,0);
  4128. +         if (xfer == NULL) panic("wdc_xfer");
  4129. +         xfer->d_link = d_link;
  4130. +         xfer->c_bp = bp;
  4131. +         xfer->c_p_offset = p_offset;
  4132. +         xfer->databuf = bp->b_data;
  4133. +         xfer->c_bcount = bp->b_bcount;
  4134. +         xfer->c_flags |= bp->b_flags & (B_READ|B_WRITE);
  4135. +         xfer->c_blkno = bp->b_blkno;
  4136. +         /* Instrumentation. */
  4137. +         disk_busy(&wd->sc_dk);
  4138. +         wdc_exec_xfer(wd->d_link,xfer);
  4139. +     }
  4140. + }
  4141. + int
  4142. + wdread(dev, uio, flags)
  4143. +     dev_t dev;
  4144. +     struct uio *uio;
  4145. +     int flags;
  4146. + {
  4147. + #ifdef WDDEBUG
  4148. +     printf("wdread\n");
  4149. + #endif
  4150. +     return (physio(wdstrategy, NULL, dev, B_READ, minphys, uio));
  4151. + }
  4152. + int
  4153. + wdwrite(dev, uio, flags)
  4154. +     dev_t dev;
  4155. +     struct uio *uio;
  4156. +     int flags;
  4157. + {
  4158. + #ifdef WDDEBUG
  4159. +     printf("wdwrite\n");
  4160. + #endif
  4161. +     return (physio(wdstrategy, NULL, dev, B_WRITE, minphys, uio));
  4162. + }
  4163. + /*
  4164. +  * Wait interruptibly for an exclusive lock.
  4165. +  *
  4166. +  * XXX
  4167. +  * Several drivers do this; it should be abstracted and made MP-safe.
  4168. +  */
  4169. + int
  4170. + wdlock(d_link)
  4171. +     struct wd_link *d_link;
  4172. + {
  4173. +     int error;
  4174. +     int s;
  4175. + #ifdef WDDEBUG
  4176. +     printf("wdlock\n");
  4177. + #endif
  4178. +     s=splbio();
  4179. +     while ((d_link->sc_flags & WDF_LOCKED) != 0) {
  4180. +         d_link->sc_flags |= WDF_WANTED;
  4181. +         if ((error = tsleep(d_link, PRIBIO | PCATCH, "wdlck", 0)) != 0) {
  4182. +             splx(s);
  4183. +             return error;
  4184. +         }
  4185. +     }
  4186. +     d_link->sc_flags |= WDF_LOCKED;
  4187. +     splx(s);
  4188. +     return 0;
  4189. + }
  4190. + /*
  4191. +  * Unlock and wake up any waiters.
  4192. +  */
  4193. + void
  4194. + wdunlock(d_link)
  4195. +     struct wd_link *d_link;
  4196. + {
  4197. + #ifdef WDDEBUG
  4198. +     printf("wdunlock\n");
  4199. + #endif
  4200. +     d_link->sc_flags &= ~WDF_LOCKED;
  4201. +     if ((d_link->sc_flags & WDF_WANTED) != 0) {
  4202. +         d_link->sc_flags &= ~WDF_WANTED;
  4203. +         wakeup(d_link);
  4204. +     }
  4205. + }
  4206. + int
  4207. + wdopen(dev, flag, fmt, p)
  4208. +     dev_t dev;
  4209. +     int flag, fmt;
  4210. +     struct proc *p;
  4211. + {
  4212. +     struct wd_softc *wd;
  4213. +     struct wd_link *d_link;
  4214. +     int unit, part;
  4215. +     int error;
  4216. + #ifdef WDDEBUG
  4217. +     printf("wdopen\n");
  4218. + #endif
  4219. +     
  4220. +     unit = WDUNIT(dev);
  4221. +     if (unit >= wd_cd.cd_ndevs)
  4222. +         return ENXIO;
  4223. +     wd = wd_cd.cd_devs[unit];
  4224. +     if (wd == 0)
  4225. +         return ENXIO;
  4226. +     
  4227. +     d_link = wd->d_link;
  4228. +     if ((error = wdlock(d_link)) != 0)
  4229. +         return error;
  4230. +     if (wd->sc_dk.dk_openmask != 0) {
  4231. +         /*
  4232. +          * If any partition is open, but the disk has been invalidated,
  4233. +          * disallow further opens.
  4234. +          */
  4235. +         if ((d_link->sc_flags & WDF_LOADED) == 0) {
  4236. +             error = EIO;
  4237. +             goto bad3;
  4238. +         }
  4239. +     } else {
  4240. +         if ((d_link->sc_flags & WDF_LOADED) == 0) {
  4241. +             d_link->sc_flags |= WDF_LOADED;
  4242. +             /* Load the physical device parameters. */
  4243. +             if (wdc_get_parms(d_link) != 0) {
  4244. +                 error = ENXIO;
  4245. +                 goto bad2;
  4246. +             }
  4247. +             /* Load the partition info if not already loaded. */
  4248. +             wdgetdisklabel(wd);
  4249. +         }
  4250. +     }
  4251. +     part = WDPART(dev);
  4252. +     /* Check that the partition exists. */
  4253. +     if (part != RAW_PART &&
  4254. +         (part >= wd->sc_dk.dk_label->d_npartitions ||
  4255. +          wd->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) {
  4256. +         error = ENXIO;
  4257. +         goto bad;
  4258. +     }
  4259. +     
  4260. +     /* Insure only one open at a time. */
  4261. +     switch (fmt) {
  4262. +     case S_IFCHR:
  4263. +         wd->sc_dk.dk_copenmask |= (1 << part);
  4264. +         break;
  4265. +     case S_IFBLK:
  4266. +         wd->sc_dk.dk_bopenmask |= (1 << part);
  4267. +         break;
  4268. +     }
  4269. +     wd->sc_dk.dk_openmask = wd->sc_dk.dk_copenmask | wd->sc_dk.dk_bopenmask;
  4270. +     wdunlock(d_link);
  4271. +     return 0;
  4272. + bad2:
  4273. +     d_link->sc_flags &= ~WDF_LOADED;
  4274. + bad:
  4275. +     if (wd->sc_dk.dk_openmask == 0) {
  4276. +     }
  4277. + bad3:
  4278. +     wdunlock(d_link);
  4279. +     return error;
  4280. + }
  4281. + int
  4282. + wdclose(dev, flag, fmt, p)
  4283. +     dev_t dev;
  4284. +     int flag, fmt;
  4285. +     struct proc *p;
  4286. + {
  4287. +     struct wd_softc *wd = wd_cd.cd_devs[WDUNIT(dev)];
  4288. +     int part = WDPART(dev);
  4289. +     int error;
  4290. +     
  4291. +     if ((error = wdlock(wd->d_link)) != 0)
  4292. +         return error;
  4293. +     switch (fmt) {
  4294. +     case S_IFCHR:
  4295. +         wd->sc_dk.dk_copenmask &= ~(1 << part);
  4296. +         break;
  4297. +     case S_IFBLK:
  4298. +         wd->sc_dk.dk_bopenmask &= ~(1 << part);
  4299. +         break;
  4300. +     }
  4301. +     wd->sc_dk.dk_openmask = wd->sc_dk.dk_copenmask | wd->sc_dk.dk_bopenmask;
  4302. +     if (wd->sc_dk.dk_openmask == 0) {
  4303. +         /* XXXX Must wait for I/O to complete! */
  4304. +     }
  4305. +     wdunlock(wd->d_link);
  4306. +     return 0;
  4307. + }
  4308. + /*
  4309. +  * Fabricate a default disk label, and try to read the correct one.
  4310. +  */
  4311. + void
  4312. + wdgetdisklabel(wd)
  4313. +     struct wd_softc *wd;
  4314. + {
  4315. +     struct disklabel *lp = wd->sc_dk.dk_label;
  4316. +     struct wd_link *d_link = wd->d_link;
  4317. +     char *errstring;
  4318. + #ifdef WDDEBUG
  4319. +     printf("wdgetdisklabel\n");
  4320. + #endif
  4321. +     bzero(lp, sizeof(struct disklabel));
  4322. +     bzero(wd->sc_dk.dk_cpulabel, sizeof(struct cpu_disklabel));
  4323. +     lp->d_secsize = DEV_BSIZE;
  4324. +     lp->d_ntracks = d_link->sc_params.wdp_heads;
  4325. +     lp->d_nsectors = d_link->sc_params.wdp_sectors;
  4326. +     lp->d_ncylinders = d_link->sc_params.wdp_cylinders;
  4327. +     lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
  4328. + #if 0
  4329. +     strncpy(lp->d_typename, "ST506 disk", 16);
  4330. +     lp->d_type = DTYPE_ST506;
  4331. + #endif
  4332. +     strncpy(lp->d_packname, d_link->sc_params.wdp_model, 16);
  4333. +     lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders;
  4334. +     lp->d_rpm = 3600;
  4335. +     lp->d_interleave = 1;
  4336. +     lp->d_flags = 0;
  4337. +     lp->d_partitions[RAW_PART].p_offset = 0;
  4338. +     lp->d_partitions[RAW_PART].p_size =
  4339. +         lp->d_secperunit * (lp->d_secsize / DEV_BSIZE);
  4340. +     lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED;
  4341. +     lp->d_npartitions = RAW_PART + 1;
  4342. +     lp->d_magic = DISKMAGIC;
  4343. +     lp->d_magic2 = DISKMAGIC;
  4344. +     lp->d_checksum = dkcksum(lp);
  4345. +     d_link->sc_badsect[0] = -1;
  4346. +     if (d_link->sc_state > RECAL)
  4347. +         d_link->sc_state = RECAL;
  4348. +     errstring = readdisklabel(MAKEWDDEV(0, wd->sc_dev.dv_unit, RAW_PART),
  4349. +         wdstrategy, lp, wd->sc_dk.dk_cpulabel);
  4350. +     if (errstring) {
  4351. +         /*
  4352. +          * This probably happened because the drive's default
  4353. +          * geometry doesn't match the DOS geometry.  We
  4354. +          * assume the DOS geometry is now in the label and try
  4355. +          * again.  XXX This is a kluge.
  4356. +          */
  4357. +         if (d_link->sc_state > GEOMETRY)
  4358. +             d_link->sc_state = GEOMETRY;
  4359. +         errstring = readdisklabel(MAKEWDDEV(0, wd->sc_dev.dv_unit, RAW_PART),
  4360. +             wdstrategy, lp, wd->sc_dk.dk_cpulabel);
  4361. +     }
  4362. +     if (errstring) {
  4363. +         printf("%s: %s\n", wd->sc_dev.dv_xname, errstring);
  4364. +         return;
  4365. +     }
  4366. +     if (d_link->sc_state > GEOMETRY)
  4367. +         d_link->sc_state = GEOMETRY;
  4368. +     if ((lp->d_flags & D_BADSECT) != 0)
  4369. +         bad144intern(wd);
  4370. + }
  4371. + /*
  4372. +  * Tell the drive what geometry to use.
  4373. +  */
  4374. + int
  4375. + wdsetctlr(d_link)
  4376. +     struct wd_link *d_link;
  4377. + {
  4378. +     struct wd_softc *wd=(struct wd_softc *)d_link->wd_softc;
  4379. + #ifdef WDDEBUG
  4380. +     printf("wd(%d,%d) C%dH%dS%d\n", wd->sc_dev.dv_unit, d_link->sc_drive,
  4381. +         wd->sc_dk.dk_label->d_ncylinders, wd->sc_dk.dk_label->d_ntracks,
  4382. +         wd->sc_dk.dk_label->d_nsectors);
  4383. + #endif
  4384. +     
  4385. +     if (wdccommand(d_link, WDCC_IDP, d_link->sc_drive, wd->sc_dk.dk_label->d_ncylinders,
  4386. +         wd->sc_dk.dk_label->d_ntracks - 1, 0, wd->sc_dk.dk_label->d_nsectors)
  4387. +         != 0) {
  4388. +         wderror(d_link, NULL, "wdsetctlr: geometry upload failed");
  4389. +         return -1;
  4390. +     }
  4391. +     return 0;
  4392. + }
  4393. + int
  4394. + wdioctl(dev, xfer, addr, flag, p)
  4395. +     dev_t dev;
  4396. +     u_long xfer;
  4397. +     caddr_t addr;
  4398. +     int flag;
  4399. +     struct proc *p;
  4400. + {
  4401. +     struct wd_softc *wd = wd_cd.cd_devs[WDUNIT(dev)];
  4402. +     struct wd_link *d_link = wd->d_link;
  4403. +     int error;
  4404. + #ifdef WDDEBUG
  4405. +     printf("wdioctl\n");
  4406. + #endif
  4407. +     if ((d_link->sc_flags & WDF_LOADED) == 0)
  4408. +         return EIO;
  4409. +     switch (xfer) {
  4410. +     case DIOCSBAD:
  4411. +         if ((flag & FWRITE) == 0)
  4412. +             return EBADF;
  4413. +         wd->sc_dk.dk_cpulabel->bad = *(struct dkbad *)addr;
  4414. +         wd->sc_dk.dk_label->d_flags |= D_BADSECT;
  4415. +         bad144intern(wd);
  4416. +         return 0;
  4417. +     case DIOCGDINFO:
  4418. +         *(struct disklabel *)addr = *(wd->sc_dk.dk_label);
  4419. +         return 0;
  4420. +     
  4421. +     case DIOCGPART:
  4422. +         ((struct partinfo *)addr)->disklab = wd->sc_dk.dk_label;
  4423. +         ((struct partinfo *)addr)->part =
  4424. +             &wd->sc_dk.dk_label->d_partitions[WDPART(dev)];
  4425. +         return 0;
  4426. +     
  4427. +     case DIOCWDINFO:
  4428. +     case DIOCSDINFO:
  4429. +         if ((flag & FWRITE) == 0)
  4430. +             return EBADF;
  4431. +         if ((error = wdlock(wd->d_link)) != 0)
  4432. +             return error;
  4433. +         d_link->sc_flags |= WDF_LABELLING;
  4434. +         error = setdisklabel(wd->sc_dk.dk_label,
  4435. +             (struct disklabel *)addr, /*wd->sc_dk.dk_openmask : */0,
  4436. +             wd->sc_dk.dk_cpulabel);
  4437. +         if (error == 0) {
  4438. +             if (d_link->sc_state > GEOMETRY)
  4439. +                 d_link->sc_state = GEOMETRY;
  4440. +             if (xfer == DIOCWDINFO)
  4441. +                 error = writedisklabel(WDLABELDEV(dev),
  4442. +                     wdstrategy, wd->sc_dk.dk_label,
  4443. +                     wd->sc_dk.dk_cpulabel);
  4444. +         }
  4445. +         d_link->sc_flags &= ~WDF_LABELLING;
  4446. +         wdunlock(d_link);
  4447. +         return error;
  4448. +     
  4449. +     case DIOCWLABEL:
  4450. +         if ((flag & FWRITE) == 0)
  4451. +             return EBADF;
  4452. +         if (*(int *)addr)
  4453. +             d_link->sc_flags |= WDF_WLABEL;
  4454. +         else
  4455. +             d_link->sc_flags &= ~WDF_WLABEL;
  4456. +         return 0;
  4457. +     
  4458. + #ifdef notyet
  4459. +     case DIOCWFORMAT:
  4460. +         if ((flag & FWRITE) == 0)
  4461. +             return EBADF;
  4462. +     {
  4463. +         register struct format_op *fop;
  4464. +         struct iovec aiov;
  4465. +         struct uio auio;
  4466. +         
  4467. +         fop = (struct format_op *)addr;
  4468. +         aiov.iov_base = fop->df_buf;
  4469. +         aiov.iov_len = fop->df_count;
  4470. +         auio.uio_iov = &aiov;
  4471. +         auio.uio_iovcnt = 1;
  4472. +         auio.uio_resid = fop->df_count;
  4473. +         auio.uio_segflg = 0;
  4474. +         auio.uio_offset =
  4475. +             fop->df_startblk * wd->sc_dk.dk_label->d_secsize;
  4476. +         auio.uio_procp = p;
  4477. +         error = physio(wdformat, NULL, dev, B_WRITE, minphys,
  4478. +             &auio);
  4479. +         fop->df_count -= auio.uio_resid;
  4480. +         fop->df_reg[0] = wdc->sc_status;
  4481. +         fop->df_reg[1] = wdc->sc_error;
  4482. +         return error;
  4483. +     }
  4484. + #endif
  4485. +     
  4486. +     default:
  4487. +         return ENOTTY;
  4488. +     }
  4489. + #ifdef DIAGNOSTIC
  4490. +     panic("wdioctl: impossible");
  4491. + #endif
  4492. + }
  4493. + #ifdef B_FORMAT
  4494. + int
  4495. + wdformat(struct buf *bp)
  4496. + {
  4497. +     bp->b_flags |= B_FORMAT;
  4498. +     return wdstrategy(bp);
  4499. + }
  4500. + #endif
  4501. + int
  4502. + wdsize(dev)
  4503. +     dev_t dev;
  4504. + {
  4505. +     struct wd_softc *wd;
  4506. +     int part;
  4507. +     int size;
  4508. + #ifdef WDDEBUG
  4509. +     printf("wdsize\n");
  4510. + #endif
  4511. +     if (wdopen(dev, 0, S_IFBLK, NULL) != 0)
  4512. +         return -1;
  4513. +     wd = wd_cd.cd_devs[WDUNIT(dev)];
  4514. +     part = WDPART(dev);
  4515. +     if (wd->sc_dk.dk_label->d_partitions[part].p_fstype != FS_SWAP)
  4516. +         size = -1;
  4517. +     else
  4518. +         size = wd->sc_dk.dk_label->d_partitions[part].p_size;
  4519. +     if (wdclose(dev, 0, S_IFBLK, NULL) != 0)
  4520. +         return -1;
  4521. +     return size;
  4522. + }
  4523. + #ifndef __BDEVSW_DUMP_OLD_TYPE
  4524. + static int wddoingadump;
  4525. + static int wddumprecalibrated;
  4526. + /*
  4527. +  * Dump core after a system crash.
  4528. +  */
  4529. + int
  4530. + wddump(dev, blkno, va, size)
  4531. +         dev_t dev;
  4532. +         daddr_t blkno;
  4533. +         caddr_t va;
  4534. +         size_t size;
  4535. + {
  4536. +     struct wd_softc *wd;    /* disk unit to do the I/O */
  4537. +     struct wd_link *d_link; /* link struct for this disk */
  4538. +     struct disklabel *lp;    /* disk's disklabel */
  4539. +     int    unit, part;
  4540. +     int    nblks;        /* total number of sectors left to write */
  4541. +     int err;
  4542. +     /* Check if recursive dump; if so, punt. */
  4543. +     if (wddoingadump)
  4544. +         return EFAULT;
  4545. +     wddoingadump = 1;
  4546. +     unit = WDUNIT(dev);
  4547. +     if (unit >= wd_cd.cd_ndevs)
  4548. +         return ENXIO;
  4549. +     wd = wd_cd.cd_devs[unit];
  4550. +     d_link = wd->d_link;
  4551. +     if (wd == 0)
  4552. +         return ENXIO;
  4553. +     part = WDPART(dev);
  4554. +     /* Make sure it was initialized. */
  4555. +     if (d_link->sc_state < OPEN)
  4556. +         return ENXIO;
  4557. +         /* Convert to disk sectors.  Request must be a multiple of size. */
  4558. +     lp = wd->sc_dk.dk_label;
  4559. +     if ((size % lp->d_secsize) != 0)
  4560. +         return EFAULT;
  4561. +     nblks = size / lp->d_secsize;
  4562. +     blkno = blkno / (lp->d_secsize / DEV_BSIZE);
  4563. +     /* Check transfer bounds against partition size. */
  4564. +     if ((blkno < 0) || ((blkno + nblks) > lp->d_partitions[part].p_size))
  4565. +         return EINVAL;  
  4566. +     /* Offset block number to start of partition. */
  4567. +     blkno += lp->d_partitions[part].p_offset;
  4568. +     err =  wdcdump(d_link, blkno, nblks, va);
  4569. +     if (err == 0) {
  4570. +         wddoingadump = 0;
  4571. +     }
  4572. +     return err;
  4573. + }
  4574. + #else /* __BDEVSW_DUMP_NEW_TYPE */
  4575. + int
  4576. + wddump(dev, blkno, va, size)
  4577. +         dev_t dev;
  4578. +         daddr_t blkno;
  4579. +         caddr_t va;
  4580. +         size_t size;
  4581. + {
  4582. +     /* Not implemented. */
  4583. +     return ENXIO;
  4584. + }
  4585. + #endif /* __BDEVSW_DUMP_NEW_TYPE */
  4586. + /*
  4587. +  * Internalize the bad sector table.
  4588. +  */
  4589. + void
  4590. + bad144intern(wd)
  4591. +     struct wd_softc *wd;
  4592. + {
  4593. +     struct dkbad *bt = &wd->sc_dk.dk_cpulabel->bad;
  4594. +     struct disklabel *lp = wd->sc_dk.dk_label;
  4595. +     struct wd_link *d_link = wd->d_link;
  4596. +     int i = 0;
  4597. + #ifdef WDDEBUG
  4598. +     printf("bad144intern\n");
  4599. + #endif
  4600. +     for (; i < 126; i++) {
  4601. +         if (bt->bt_bad[i].bt_cyl == 0xffff)
  4602. +             break;
  4603. +         d_link->sc_badsect[i] =
  4604. +             bt->bt_bad[i].bt_cyl * lp->d_secpercyl +
  4605. +             (bt->bt_bad[i].bt_trksec >> 8) * lp->d_nsectors +
  4606. +             (bt->bt_bad[i].bt_trksec & 0xff);
  4607. +     }
  4608. +     for (; i < 127; i++)
  4609. +         d_link->sc_badsect[i] = -1;
  4610. + }
  4611. + void
  4612. + wderror(d_link, bp, msg)
  4613. +     struct wd_link *d_link;
  4614. +     struct buf *bp;
  4615. +     char *msg;
  4616. + {
  4617. +     struct wd_softc *wd = (struct wd_softc *)d_link->wd_softc;
  4618. +     if (bp) {
  4619. +         diskerr(bp, "wd", msg, LOG_PRINTF, bp->b_bcount ,
  4620. +             wd->sc_dk.dk_label);
  4621. +         printf("\n");
  4622. +     } else
  4623. +         printf("%s: %s\n", wd->sc_dev.dv_xname,
  4624. +             msg);
  4625. + }
  4626. + void
  4627. + wddone(d_link, bp)
  4628. + struct wd_link *d_link;
  4629. + struct buf *bp;
  4630. + {
  4631. +     struct wd_softc *wd = (void*)d_link->wd_softc;
  4632. +     disk_unbusy(&wd->sc_dk, (bp->b_bcount - bp->b_resid));
  4633. + }
  4634. diff --exclude compile -bcrNP src.orig/sys/dev/isa/wdc.c src/sys/dev/isa/wdc.c
  4635. *** src.orig/sys/dev/isa/wdc.c    Thu Jan  1 01:00:00 1970
  4636. --- src/sys/dev/isa/wdc.c    Thu Jun  6 12:21:06 1996
  4637. ***************
  4638. *** 0 ****
  4639. --- 1,1733 ----
  4640. + /*    $NetBSD: wd.c,v 1.142 1995/08/05 23:50:23 mycroft Exp $    */
  4641. + /*
  4642. +  * Copyright (c) 1994, 1995 Charles M. Hannum.  All rights reserved.
  4643. +  *
  4644. +  * DMA and multi-sector PIO handling are derived from code contributed by
  4645. +  * Onno van der Linden.
  4646. +  *
  4647. +  * Atapi support added by Manuel Bouyer.
  4648. +  *
  4649. +  * Redistribution and use in source and binary forms, with or without
  4650. +  * modification, are permitted provided that the following conditions
  4651. +  * are met:
  4652. +  * 1. Redistributions of source code must retain the above copyright
  4653. +  *    notice, this list of conditions and the following disclaimer.
  4654. +  * 2. Redistributions in binary form must reproduce the above copyright
  4655. +  *    notice, this list of conditions and the following disclaimer in the
  4656. +  *    documentation and/or other materials provided with the distribution.
  4657. +  * 3. All advertising materials mentioning features or use of this software
  4658. +  *    must display the following acknowledgement:
  4659. +  *    This product includes software developed by Charles M. Hannum.
  4660. +  * 4. The name of the author may not be used to endorse or promote products
  4661. +  *    derived from this software without specific prior written permission.
  4662. +  *
  4663. +  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  4664. +  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  4665. +  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  4666. +  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  4667. +  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  4668. +  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  4669. +  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  4670. +  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  4671. +  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  4672. +  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  4673. +  */
  4674. + #undef ATAPI_DEBUG_WDC
  4675. + #include <sys/param.h>
  4676. + #include <sys/systm.h>
  4677. + #include <sys/kernel.h>
  4678. + #include <sys/conf.h>
  4679. + #include <sys/file.h>
  4680. + #include <sys/stat.h>
  4681. + #include <sys/ioctl.h>
  4682. + #include <sys/buf.h>
  4683. + #include <sys/uio.h>
  4684. + #include <sys/malloc.h>
  4685. + #include <sys/device.h>
  4686. + #include <sys/disklabel.h>
  4687. + #include <sys/disk.h>
  4688. + #include <sys/syslog.h>
  4689. + #include <sys/proc.h>
  4690. + #include <vm/vm.h>
  4691. + #include <machine/cpu.h>
  4692. + #include <machine/intr.h>
  4693. + #include <machine/pio.h>
  4694. + #include <dev/isa/isavar.h>
  4695. + #include <dev/isa/isadmavar.h>
  4696. + #include <dev/isa/wdreg.h>
  4697. + #include <dev/isa/wdlink.h>
  4698. + #include <atapi/atapilink.h>
  4699. + #define    WAITTIME    (10 * hz)    /* time to wait for a completion */
  4700. +     /* this is a lot for hard drives, but not for cdroms */
  4701. + #define RECOVERYTIME hz/2
  4702. + #define WDCDELAY    100
  4703. + #define WDCNDELAY    100000        /* delay = 100us; so 10s for a controller state change */
  4704. + #if 0
  4705. + /* If you enable this, it will report any delays more than 100us * N long. */
  4706. + #define WDCNDELAY_DEBUG    50
  4707. + #endif
  4708. + #define    WDIORETRIES    5        /* number of retries before giving up */
  4709. + #define    WDPART(dev)            DISKPART(dev)
  4710. + LIST_HEAD(xfer_free_list, wdc_xfer) xfer_free_list;
  4711. + struct wdc_softc {
  4712. +     struct device sc_dev;
  4713. +     void *sc_ih;
  4714. +     struct wd_link *d_link[2];
  4715. +     struct bus_link *ab_link;
  4716. +     struct wdc_link ctlr_link;
  4717. +     int sc_iobase;            /* I/O port base */
  4718. +     int sc_drq;            /* DMA channel */
  4719. +     TAILQ_HEAD(xferhead, wdc_xfer) sc_xfer;
  4720. +     int sc_flags;
  4721. + #define    WDCF_ACTIVE        0x01    /* controller is active */
  4722. + #define    WDCF_SINGLE        0x02    /* sector at a time mode */
  4723. + #define    WDCF_ERROR        0x04    /* processing a disk error */
  4724. + #define    WDCF_WANTED        0x08    /* XXX locking for wd_get_parms() */
  4725. + #define    WDCF_IRQ_WAIT        0x10    /* controller is waiting for irq */
  4726. + #define    WDCF_ONESLAVE        0x20    /* ctrl. has one ATAPI slave attached */
  4727. +     int sc_errors;            /* errors during current transfer */
  4728. +     u_char sc_status;        /* copy of status register */
  4729. +     u_char sc_error;        /* copy of error register */
  4730. + };
  4731. + int wdcprobe __P((struct device *, void *, void *));
  4732. + void wdcattach __P((struct device *, struct device *, void *));
  4733. + struct cfattach wdc_ca = {
  4734. +     sizeof(struct wdc_softc), wdcprobe, wdcattach
  4735. + };
  4736. + struct cfdriver wdc_cd = {
  4737. +       NULL, "wdc", DV_DULL
  4738. + };
  4739. + int wdcintr __P((void *));
  4740. + int wdc_ata_intr __P((struct wdc_softc *,struct wdc_xfer *));
  4741. + void wdcstart __P((struct wdc_softc *));
  4742. + void wdc_ata_start __P((struct wdc_softc *,struct wdc_xfer *));
  4743. + void wdc_atapi_start __P((struct wdc_softc *,struct wdc_xfer *));
  4744. + int wdcreset __P((struct wdc_softc *));
  4745. + void wdcrestart __P((void *arg));
  4746. + void wdcunwedge __P((struct wdc_softc *));
  4747. + void wdctimeout __P((void *arg));
  4748. + int wdcwait __P((struct wdc_softc *, int));
  4749. + int wdccontrol __P((struct wd_link *));
  4750. + void wdc_ata_done __P((struct wdc_softc *, struct wdc_xfer *));
  4751. + void wdc_free_xfer __P((struct wdc_xfer *));
  4752. + void wdcerror __P((struct wdc_softc*, char *));
  4753. + int wdccommandshort __P((struct wdc_softc *, int, int));
  4754. + void wdcbit_bucket __P(( struct wdc_softc *, int));
  4755. + int wdc_atapi_intr __P((struct wdc_softc *, struct wdc_xfer *));
  4756. + void wdc_atapi_done __P((struct wdc_softc *, struct wdc_xfer *));
  4757. + /* ST506 spec says that if READY or SEEKCMPLT go off, then the read or write
  4758. +    command is aborted. */
  4759. + #define    wait_for_drq(d)        wdcwait(d, WDCS_DRDY | WDCS_DSC | WDCS_DRQ)
  4760. + #define    wait_for_unbusy(d)      wdcwait(d, 0)
  4761. + #define    wait_for_ready(d)       wdcwait(d, WDCS_DRDY | WDCS_DSC)
  4762. + #define    atapi_ready(d)       wdcwait(d, WDCS_DRQ)
  4763. + #ifdef ATAPI_DEBUG
  4764. + static int wdc_nxfer;
  4765. + #endif
  4766. + int
  4767. + wdcprobe(parent, match, aux)
  4768. +     struct device *parent;
  4769. +     void *match, *aux;
  4770. + {
  4771. +     struct wdc_softc *wdc = match;
  4772. +     struct isa_attach_args *ia = aux;
  4773. +     int iobase;
  4774. +     wdc->sc_iobase = iobase = ia->ia_iobase;
  4775. +     /* Check if we have registers that work. */
  4776. +     outb(iobase+wd_error, 0x5a);    /* Error register not writable, */
  4777. +     outb(iobase+wd_cyl_lo, 0xa5);    /* but all of cyllo are. */
  4778. +     if (inb(iobase+wd_error) == 0x5a || inb(iobase+wd_cyl_lo) != 0xa5) {
  4779. +         /*
  4780. +          * Test for a controller with no IDE master, just one
  4781. +          * ATAPI device. Select drive 1, and try again.
  4782. +          */
  4783. +         outb(iobase+wd_sdh, WDSD_IBM | 0x10);
  4784. +         outb(iobase+wd_error, 0x5a);
  4785. +         outb(iobase+wd_cyl_lo, 0xa5);
  4786. +         if (inb(iobase+wd_error) == 0x5a || inb(iobase+wd_cyl_lo)
  4787. +             != 0xa5)
  4788. +             return 0;
  4789. +         wdc->sc_flags |= WDCF_ONESLAVE;
  4790. +     }
  4791. +     if (wdcreset(wdc) != 0) {
  4792. +         delay(500000);
  4793. +         if (wdcreset(wdc) != 0)
  4794. +             return 0;
  4795. +     }
  4796. +     /* Select drive 0 or ATAPI slave device */
  4797. +     if (wdc->sc_flags & WDCF_ONESLAVE)
  4798. +         outb(iobase+wd_sdh, WDSD_IBM | 0x10);
  4799. +     else
  4800. +         outb(iobase+wd_sdh, WDSD_IBM);
  4801. +     /* Wait for controller to become ready. */
  4802. +     if (wait_for_unbusy(wdc) < 0)
  4803. +         return 0;
  4804. +     
  4805. +     /* Start drive diagnostics. */
  4806. +     outb(iobase+wd_command, WDCC_DIAGNOSE);
  4807. +     /* Wait for command to complete. */
  4808. +     if (wait_for_unbusy(wdc) < 0)
  4809. +         return 0;
  4810. +     ia->ia_iosize = 8;
  4811. +     ia->ia_msize = 0;
  4812. +     return 1;
  4813. + }
  4814. + int
  4815. + wdprint(aux, wdc)
  4816. +     void *aux;
  4817. +     char *wdc;
  4818. + {
  4819. +     struct wd_link *d_link = aux;
  4820. +     if (!wdc)
  4821. +         printf(" drive %d", d_link->sc_drive);
  4822. +     return QUIET;
  4823. + }
  4824. + void
  4825. + wdcattach(parent, self, aux)
  4826. +     struct device *parent, *self;
  4827. +     void *aux;
  4828. + {
  4829. +     struct wdc_softc *wdc = (void *)self;
  4830. +     struct isa_attach_args *ia = aux;
  4831. +     int drive;
  4832. +     TAILQ_INIT(&wdc->sc_xfer);
  4833. +     wdc->sc_drq = ia->ia_drq;
  4834. +     printf("\n");
  4835. +     wdc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
  4836. +         IPL_BIO, wdcintr, wdc);
  4837. +     wdc->ctlr_link.flags = 0;
  4838. + #ifdef ATAPI_DEBUG
  4839. +     wdc_nxfer = 0;
  4840. + #endif
  4841. +     for (drive = 0; drive < 2; drive++) {
  4842. +         wdc->sc_flags |= WDCF_ACTIVE; /* controller active while autoconf */
  4843. +         if (wdccommandshort(wdc, drive, WDCC_RECAL) != 0 ||
  4844. +                     wait_for_ready(wdc) != 0) {
  4845. +             wdc->d_link[drive]=NULL;
  4846. +             wdc->sc_flags &= ~WDCF_ACTIVE;
  4847. +         }
  4848. +         else {
  4849. +             wdc->sc_flags &= ~WDCF_ACTIVE;
  4850. +             wdc->d_link[drive]=malloc(sizeof(struct wd_link), M_DEVBUF, M_NOWAIT);
  4851. +             bzero(wdc->d_link[drive],sizeof(struct wd_link));
  4852. +             wdc->d_link[drive]->type = DRIVE;
  4853. +             wdc->d_link[drive]->wdc_softc =(caddr_t) wdc;
  4854. +             wdc->d_link[drive]->ctlr_link = &(wdc->ctlr_link);
  4855. +             wdc->d_link[drive]->sc_drive = drive;
  4856. +             if (wdc->sc_drq != DRQUNK) 
  4857. +                 wdc->d_link[drive]->sc_mode = WDM_DMA;
  4858. +             else wdc->d_link[drive]->sc_mode = 0;
  4859. +             (void)config_found(self, (void *)wdc->d_link[drive], wdprint);
  4860. +         }
  4861. +     }
  4862. +     wdc->ab_link = malloc(sizeof(struct bus_link), M_DEVBUF, M_NOWAIT);
  4863. +     bzero(wdc->ab_link,sizeof(struct bus_link));
  4864. +     wdc->ab_link->type = BUS;
  4865. +     wdc->ab_link->wdc_softc = (caddr_t) wdc;
  4866. +     wdc->ab_link->ctlr_link = &(wdc->ctlr_link);
  4867. +     wdc->ab_link->ctrl = self->dv_unit;
  4868. +     (void)config_found(self, (void *)wdc->ab_link, NULL);
  4869. + }
  4870. + /*
  4871. +  * Start I/O on a controller.  This does the calculation, and starts a read or
  4872. +  * write operation.  Called to from wdstart() to start a transfer, from
  4873. +  * wdcintr() to continue a multi-sector transfer or start the next transfer, or
  4874. +  * wdcrestart() after recovering from an error.
  4875. +  */
  4876. + void
  4877. + wdcstart(wdc)
  4878. +     struct wdc_softc *wdc;
  4879. + {
  4880. +     struct wdc_xfer *xfer;
  4881. +     if ((wdc->sc_flags & WDCF_ACTIVE) != 0 ) {
  4882. + #ifdef WDDEBUG
  4883. +         printf("wdcstart: already active\n");
  4884. + #endif
  4885. +         return; /* controller aleady active */
  4886. +     }
  4887. + #ifdef DIAGNOSTIC
  4888. +     if ((wdc->sc_flags & WDCF_IRQ_WAIT) != 0)
  4889. +         panic("wdcstart: controller waiting for irq\n");
  4890. + #endif
  4891. +     /*
  4892. +      * XXX
  4893. +      * This is a kluge.  See comments in wd_get_parms().
  4894. +      */
  4895. +     if ((wdc->sc_flags & WDCF_WANTED) != 0) {
  4896. + #ifdef ATAPI_DEBUG_WDC
  4897. +         printf("WDCF_WANTED\n");
  4898. + #endif
  4899. +         wdc->sc_flags &= ~WDCF_WANTED;
  4900. +         wakeup(wdc);
  4901. +         return;
  4902. +     }
  4903. +     /* is there a xfer ? */
  4904. +     xfer = wdc->sc_xfer.tqh_first;
  4905. +     if (xfer == NULL) {
  4906. + #ifdef ATAPI_DEBUG2
  4907. +         printf("wdcstart: null xfer\n");
  4908. + #endif
  4909. +         return;
  4910. +     }
  4911. +     wdc->sc_flags |= WDCF_ACTIVE;
  4912. +     if (xfer->c_flags & C_ATAPI) {
  4913. + #ifdef ATAPI_DEBUG_WDC
  4914. +         printf("wdcstart: atapi\n");
  4915. + #endif
  4916. +         wdc_atapi_start(wdc,xfer);
  4917. +     } else {
  4918. +         wdc_ata_start(wdc,xfer);
  4919. +     }
  4920. + }
  4921. + void wdc_ata_start(wdc, xfer)
  4922. +     struct wdc_softc *wdc;
  4923. +     struct wdc_xfer *xfer;
  4924. + {
  4925. +     struct wd_link *d_link;
  4926. +     struct buf *bp = xfer->c_bp;
  4927. +     int nblks;
  4928. +     d_link=xfer->d_link;
  4929. + loop:
  4930. +     
  4931. +     if (wdc->sc_errors >= WDIORETRIES) {
  4932. +         wderror(d_link, bp, "hard error");
  4933. +         xfer->c_flags |= C_ERROR;
  4934. +         wdc_ata_done(wdc, xfer);
  4935. +         return;
  4936. +     }
  4937. +     /* Do control operations specially. */
  4938. +     if (d_link->sc_state < OPEN) {
  4939. +         /*
  4940. +          * Actually, we want to be careful not to mess with the control
  4941. +          * state if the device is currently busy, but we can assume
  4942. +          * that we never get to this point if that's the case.
  4943. +          */
  4944. +         if (wdccontrol(d_link) == 0) {
  4945. +             /* The drive is busy.  Wait. */
  4946. +             return;
  4947. +         }
  4948. +     }
  4949. +     /*
  4950. +      * WDCF_ERROR is set by wdcunwedge() and wdcintr() when an error is
  4951. +      * encountered.  If we are in multi-sector mode, then we switch to
  4952. +      * single-sector mode and retry the operation from the start.
  4953. +      */
  4954. +     if (wdc->sc_flags & WDCF_ERROR) {
  4955. +         wdc->sc_flags &= ~WDCF_ERROR;
  4956. +         if ((wdc->sc_flags & WDCF_SINGLE) == 0) {
  4957. +             wdc->sc_flags |= WDCF_SINGLE;
  4958. +             xfer->c_skip = 0;
  4959. +         }
  4960. +     }
  4961. +     /* When starting a transfer... */
  4962. +     if (xfer->c_skip == 0) {
  4963. +         daddr_t blkno;
  4964. + #ifdef WDDEBUG
  4965. +         printf("\n%s: wdc_ata_start %s %d@%d; map ", wdc->sc_dev.dv_xname,
  4966. +             (xfer->c_flags & B_READ) ? "read" : "write", xfer->c_bcount,
  4967. +             xfer->c_blkno);
  4968. + #endif
  4969. +         blkno = xfer->c_blkno+xfer->c_p_offset;
  4970. +         xfer->c_blkno = blkno / (d_link->sc_lp->d_secsize / DEV_BSIZE);
  4971. +     } else {
  4972. + #ifdef WDDEBUG
  4973. +         printf(" %d)%x", xfer->c_skip, inb(wdc->sc_iobase+wd_altsts));
  4974. + #endif
  4975. +     }
  4976. +     /* When starting a multi-sector transfer, or doing single-sector
  4977. +         transfers... */
  4978. +     if (xfer->c_skip == 0 || (wdc->sc_flags & WDCF_SINGLE) != 0 ||
  4979. +         d_link->sc_mode == WDM_DMA) {
  4980. +         daddr_t blkno = xfer->c_blkno;
  4981. +         long cylin, head, sector;
  4982. +         int command;
  4983. +         if ((wdc->sc_flags & WDCF_SINGLE) != 0)
  4984. +             nblks = 1;
  4985. +         else if (d_link->sc_mode != WDM_DMA)
  4986. +             nblks = xfer->c_bcount / d_link->sc_lp->d_secsize;
  4987. +         else
  4988. +             nblks = min(xfer->c_bcount / d_link->sc_lp->d_secsize, 8);
  4989. +         /* Check for bad sectors and adjust transfer, if necessary. */
  4990. +         if ((d_link->sc_lp->d_flags & D_BADSECT) != 0
  4991. + #ifdef B_FORMAT
  4992. +             && (bp->b_flags & B_FORMAT) == 0
  4993. + #endif
  4994. +             ) {
  4995. +             long blkdiff;
  4996. +             int i;
  4997. +             for (i = 0; (blkdiff = d_link->sc_badsect[i]) != -1; i++) {
  4998. +                 blkdiff -= blkno;
  4999. +                 if (blkdiff < 0)
  5000. +                     continue;
  5001. +                 if (blkdiff == 0) {
  5002. +                     /* Replace current block of transfer. */
  5003. +                     blkno =
  5004. +                         d_link->sc_lp->d_secperunit -
  5005. +                         d_link->sc_lp->d_nsectors - i - 1;
  5006. +                 }
  5007. +                 if (blkdiff < nblks) {
  5008. +                     /* Bad block inside transfer. */
  5009. +                     wdc->sc_flags |= WDCF_SINGLE;
  5010. +                     nblks = 1;
  5011. +                 }
  5012. +                 break;
  5013. +             }
  5014. +             /* Tranfer is okay now. */
  5015. +         }
  5016. +         if ((d_link->sc_params.wdp_capabilities & WD_CAP_LBA) != 0) {
  5017. +             sector = (blkno >> 0) & 0xff;
  5018. +             cylin = (blkno >> 8) & 0xffff;
  5019. +             head = (blkno >> 24) & 0xf;
  5020. +             head |= WDSD_LBA;
  5021. +         } else {
  5022. +             sector = blkno % d_link->sc_lp->d_nsectors;
  5023. +             sector++;    /* Sectors begin with 1, not 0. */
  5024. +             blkno /= d_link->sc_lp->d_nsectors;
  5025. +             head = blkno % d_link->sc_lp->d_ntracks;
  5026. +             blkno /= d_link->sc_lp->d_ntracks;
  5027. +             cylin = blkno;
  5028. +             head |= WDSD_CHS;
  5029. +         }
  5030. +         if (d_link->sc_mode == WDM_PIOSINGLE ||
  5031. +             (wdc->sc_flags & WDCF_SINGLE) != 0)
  5032. +             xfer->c_nblks = 1;
  5033. +         else if (d_link->sc_mode == WDM_PIOMULTI)
  5034. +             xfer->c_nblks = min(nblks, d_link->sc_multiple);
  5035. +         else
  5036. +             xfer->c_nblks = nblks;
  5037. +         xfer->c_nbytes = xfer->c_nblks * d_link->sc_lp->d_secsize;
  5038. +     
  5039. + #ifdef B_FORMAT
  5040. +         if (bp->b_flags & B_FORMAT) {
  5041. +             sector = d_link->sc_lp->d_gap3;
  5042. +             nblks = d_link->sc_lp->d_nsectors;
  5043. +             command = WDCC_FORMAT;
  5044. +         } else
  5045. + #endif
  5046. +         switch (d_link->sc_mode) {
  5047. +         case WDM_DMA:
  5048. +             command = (xfer->c_flags & B_READ) ?
  5049. +                 WDCC_READDMA : WDCC_WRITEDMA;
  5050. +             /* Start the DMA channel and bounce the buffer if
  5051. +                necessary. */
  5052. +             isa_dmastart(xfer->c_flags & B_READ ? DMAMODE_READ : DMAMODE_WRITE,
  5053. +                 xfer->databuf + xfer->c_skip,
  5054. +                 xfer->c_nbytes, wdc->sc_drq);
  5055. +             break;
  5056. +         case WDM_PIOMULTI:
  5057. +             command = (xfer->c_flags & B_READ) ?
  5058. +                 WDCC_READMULTI : WDCC_WRITEMULTI;
  5059. +             break;
  5060. +         case WDM_PIOSINGLE:
  5061. +             command = (xfer->c_flags & B_READ) ?
  5062. +                 WDCC_READ : WDCC_WRITE;
  5063. +             break;
  5064. +                 default:
  5065. + #ifdef DIAGNOSTIC
  5066. +                         panic("bad wd mode");
  5067. + #endif
  5068. +                         return;
  5069. +         }
  5070. +     
  5071. +         /* Initiate command! */
  5072. +         if (wdccommand(d_link, command, d_link->sc_drive, cylin, head, sector, nblks) != 0) {
  5073. +             wderror(d_link, NULL,
  5074. +                 "wdc_ata_start: timeout waiting for unbusy");
  5075. +             wdcunwedge(wdc);
  5076. +             return;
  5077. +         }
  5078. + #ifdef WDDEBUG
  5079. +         printf("sector %d cylin %d head %d addr %x sts %x\n", sector,
  5080. +             cylin, head, xfer->databuf, inb(wdc->sc_iobase+wd_altsts));
  5081. + #endif
  5082. +     } else if (xfer->c_nblks > 1) {
  5083. +         /* The number of blocks in the last stretch may be smaller. */
  5084. +         nblks = xfer->c_bcount / d_link->sc_lp->d_secsize;
  5085. +         if (xfer->c_nblks > nblks) {
  5086. +             xfer->c_nblks = nblks;
  5087. +             xfer->c_nbytes = xfer->c_bcount;
  5088. +         }
  5089. +     }
  5090. +     /* If this was a write and not using DMA, push the data. */
  5091. +     if (d_link->sc_mode != WDM_DMA &&
  5092. +         (xfer->c_flags & (B_READ|B_WRITE)) == B_WRITE) {
  5093. +         if (wait_for_drq(wdc) < 0) {
  5094. +             wderror(d_link, NULL, "wdc_ata_start: timeout waiting for drq");
  5095. +             wdcunwedge(wdc);
  5096. +             return;
  5097. +         }
  5098. +         /* Push out data. */
  5099. +         if ((d_link->sc_flags & WDF_32BIT) == 0)
  5100. +             outsw(wdc->sc_iobase+wd_data, xfer->databuf + xfer->c_skip,
  5101. +                 xfer->c_nbytes >> 1);
  5102. +         else
  5103. +             outsl(wdc->sc_iobase+wd_data, xfer->databuf + xfer->c_skip,
  5104. +                 xfer->c_nbytes >> 2);
  5105. +     }
  5106. +     wdc->sc_flags |= WDCF_IRQ_WAIT;
  5107. + #ifdef WDDEBUG
  5108. +     printf("wdc_ata_start: timeout ");
  5109. + #endif
  5110. +     timeout(wdctimeout, wdc, WAITTIME);
  5111. + #ifdef WDDEBUG
  5112. +     printf("done\n");
  5113. + #endif
  5114. + }
  5115. + void
  5116. + wdc_atapi_start (wdc, xfer)
  5117. + struct wdc_softc *wdc;
  5118. + struct wdc_xfer *xfer;
  5119. + {
  5120. +     struct atapi_command_packet *acp = xfer->atapi_cmd;
  5121. + #ifdef ATAPI_DEBUG_WDC
  5122. +     printf("wdc_atapi_start, acp flags %lx\n",acp->flags);
  5123. + #endif
  5124. +     if (wdc->sc_errors >= WDIORETRIES) {
  5125. +         acp->status |= ERROR;
  5126. +         acp->error = inb (wdc->sc_iobase + wd_error);
  5127. +         wdc_atapi_done(wdc, xfer);
  5128. +         return;
  5129. +     }
  5130. +     if (wait_for_unbusy (wdc) != 0)
  5131. +         if (!(wdc->sc_status & WDCS_ERR)) {
  5132. +             printf ("wdc_atapi_start: not ready, st = %02x\n",wdc->sc_status);
  5133. +             acp->status = ERROR;
  5134. +             return;
  5135. +         }
  5136. +     if (wdccommand ((struct wd_link*)xfer->d_link, ATAPI_PACKET_COMMAND,
  5137. +         acp->drive, acp->data_size, 0, 0, 0) != 0) {
  5138. +         printf("wdc_atapi_start: can't send atapi paket command\n");
  5139. +         acp->status = ERROR;
  5140. +         wdc->sc_flags |= WDCF_IRQ_WAIT;
  5141. +         return;
  5142. +     }
  5143. +     if ((acp->flags & 0x0300) != ACAP_DRQ_INTR) {
  5144. +         int i, phase;
  5145. +         for (i=20000; i>0; --i) {
  5146. +             phase = (inb(wdc->sc_iobase + wd_ireason) & (WDCI_CMD | WDCI_IN)) |
  5147. +                 (inb(wdc->sc_iobase + wd_status) & WDCS_DRQ);
  5148. +             if (phase == PHASE_CMDOUT)
  5149. +                 break;
  5150. +             delay(10);
  5151. +         }
  5152. +         if (phase != PHASE_CMDOUT ) {
  5153. +             printf("wdc_atapi_start: timout waiting PHASE_CMDOUT");
  5154. +             acp->status = ERROR;
  5155. +             wdc_atapi_done(wdc, xfer);
  5156. +             return;
  5157. +         }
  5158. +         outsw (wdc->sc_iobase + wd_data, acp->command,
  5159. +             acp->command_size/ sizeof (short));
  5160. +     }
  5161. +     wdc->sc_flags |= WDCF_IRQ_WAIT;
  5162. +      
  5163. + #ifdef ATAPI_DEBUG2
  5164. +     printf("wdc_atapi_start: timeout\n");
  5165. + #endif
  5166. +     timeout(wdctimeout, wdc, WAITTIME);
  5167. +     return;
  5168. + }
  5169. + /*
  5170. +  * Interrupt routine for the controller.  Acknowledge the interrupt, check for
  5171. +  * errors on the current operation, mark it done if necessary, and start the
  5172. +  * next request.  Also check for a partially done transfer, and continue with
  5173. +  * the next chunk if so.
  5174. +  */
  5175. + int
  5176. + wdcintr(arg)
  5177. +     void *arg;
  5178. + {
  5179. +     struct wdc_softc *wdc = arg;
  5180. +     struct wdc_xfer *xfer;
  5181. +     if ((wdc->sc_flags & WDCF_IRQ_WAIT) == 0) {
  5182. +         /* Clear the pending interrupt and abort. */
  5183. +         u_char s = inb(wdc->sc_iobase+wd_status);
  5184. +         u_char e = inb(wdc->sc_iobase+wd_error);
  5185. +         u_char i = inb(wdc->sc_iobase+wd_seccnt);
  5186. + #ifdef ATAPI_DEBUG_WDC
  5187. +         printf ("wdcintr: inactive controller, punting st=%02x er=%02x irr=%02x\n", s, e, i);
  5188. + #endif /* ATAPI_DEBUG */
  5189. +        if (s & WDCS_DRQ) {
  5190. +             int len = inb (wdc->sc_iobase + wd_cyl_lo) +
  5191. +             256 * inb (wdc->sc_iobase + wd_cyl_hi);
  5192. + #ifdef ATAPI_DEBUG_WDC
  5193. +             printf ("wdcintr: clearing up %d bytes\n", len);
  5194. + #endif /* ATAPI_DEBUG */
  5195. +             wdcbit_bucket (wdc, len);
  5196. +         }
  5197. +         return 0;
  5198. +     }
  5199. + #ifdef WDDEBUG
  5200. +     printf("wdcintr\n");
  5201. + #endif
  5202. +     wdc->sc_flags &= ~WDCF_IRQ_WAIT;
  5203. +     xfer = wdc->sc_xfer.tqh_first;
  5204. +     if (xfer->c_flags & C_ATAPI) {
  5205. +         (void) wdc_atapi_intr(wdc,xfer);
  5206. +         return 0;
  5207. +     } else {
  5208. +         return wdc_ata_intr(wdc,xfer);
  5209. +     }
  5210. + }
  5211. + int
  5212. + wdc_ata_intr(wdc,xfer)
  5213. +     struct wdc_softc *wdc;
  5214. +     struct wdc_xfer *xfer;
  5215. + {
  5216. +     struct wd_link *d_link;
  5217. +     d_link = xfer->d_link;
  5218. +     if (wait_for_unbusy(wdc) < 0) {
  5219. +         wdcerror(wdc, "wdcintr: timeout waiting for unbusy");
  5220. +         wdc->sc_status |= WDCS_ERR;    /* XXX */
  5221. +     }
  5222. +     untimeout(wdctimeout, wdc);
  5223. +     /* Is it not a transfer, but a control operation? */
  5224. +     if (d_link->sc_state < OPEN) {
  5225. +         if (wdccontrol(d_link) == 0) {
  5226. +             /* The drive is busy.  Wait. */
  5227. +             return 1;
  5228. +         }
  5229. + #ifdef WDDEBUG
  5230. +         printf("wdc_ata_start from wdc_ata_intr(open) flags %d\n",
  5231. +             dc->sc_flags);
  5232. + #endif
  5233. +         wdc_ata_start(wdc,xfer);
  5234. +         return 1;
  5235. +     }
  5236. +     /* Turn off the DMA channel and unbounce the buffer. */
  5237. +     if (d_link->sc_mode == WDM_DMA)
  5238. +         isa_dmadone(xfer->c_flags & B_READ ? DMAMODE_READ : DMAMODE_WRITE,
  5239. +             xfer->databuf + xfer->c_skip, xfer->c_nbytes, wdc->sc_drq);
  5240. +     /* Have we an error? */
  5241. +     if (wdc->sc_status & WDCS_ERR) {
  5242. + #ifdef WDDEBUG
  5243. +         wderror(d_link, NULL, "wdc_ata_start");
  5244. + #endif
  5245. +         if ((wdc->sc_flags & WDCF_SINGLE) == 0) {
  5246. +             wdc->sc_flags |= WDCF_ERROR;
  5247. +             goto restart;
  5248. +         }
  5249. + #ifdef B_FORMAT
  5250. +         if (bp->b_flags & B_FORMAT)
  5251. +             goto bad;
  5252. + #endif
  5253. +     
  5254. +         if (++wdc->sc_errors < WDIORETRIES)
  5255. +             goto restart;
  5256. +         wderror(d_link, xfer->c_bp, "hard error");
  5257. + #ifdef B_FORMAT
  5258. +     bad:
  5259. + #endif
  5260. +         xfer->c_flags |= C_ERROR;
  5261. +         goto done;
  5262. +     }
  5263. +     /* If this was a read and not using DMA, fetch the data. */
  5264. +     if (d_link->sc_mode != WDM_DMA &&
  5265. +         (xfer->c_flags & (B_READ|B_WRITE)) == B_READ) {
  5266. +         if ((wdc->sc_status & (WDCS_DRDY | WDCS_DSC | WDCS_DRQ))
  5267. +             != (WDCS_DRDY | WDCS_DSC | WDCS_DRQ)) {
  5268. +             wderror(d_link, NULL, "wdcintr: read intr before drq");
  5269. +             wdcunwedge(wdc);
  5270. +             return 1;
  5271. +         }
  5272. +         /* Pull in data. */
  5273. +         if ((d_link->sc_flags & WDF_32BIT) == 0)
  5274. +             insw(wdc->sc_iobase+wd_data, xfer->databuf + xfer->c_skip, 
  5275. +                 xfer->c_nbytes >> 1);
  5276. +         else
  5277. +             insl(wdc->sc_iobase+wd_data, xfer->databuf + xfer->c_skip, 
  5278. +                 xfer->c_nbytes >> 2);
  5279. +     }
  5280. +     
  5281. +     /* If we encountered any abnormalities, flag it as a soft error. */
  5282. +     if (wdc->sc_errors > 0 ||
  5283. +         (wdc->sc_status & WDCS_CORR) != 0) {
  5284. +         wderror(d_link, xfer->c_bp, "soft error (corrected)");
  5285. +         wdc->sc_errors = 0;
  5286. +     }
  5287. +     
  5288. +     /* Adjust pointers for the next block, if any. */
  5289. +     xfer->c_blkno += xfer->c_nblks;
  5290. +     xfer->c_skip += xfer->c_nbytes;
  5291. +     xfer->c_bcount -= xfer->c_nbytes;
  5292. +     /* See if this transfer is complete. */
  5293. +     if (xfer->c_bcount > 0)
  5294. +         goto restart;
  5295. + done:
  5296. +     /* Done with this transfer, with or without error. */
  5297. +     wdc_ata_done(wdc, xfer);
  5298. +     return 0;
  5299. + restart:
  5300. +     /* Start the next operation */
  5301. + #ifdef WDDEBUG
  5302. +     printf("wdc_ata_start from wdcintr flags %d\n",wdc->sc_flags);
  5303. + #endif
  5304. +     wdc_ata_start(wdc, xfer);
  5305. +     return 1;
  5306. + }
  5307. + int
  5308. + wdcreset(wdc)
  5309. +     struct wdc_softc *wdc;
  5310. + {
  5311. +     int iobase = wdc->sc_iobase;
  5312. +     /* Reset the device. */
  5313. +     outb(iobase+wd_ctlr, WDCTL_RST | WDCTL_IDS);
  5314. +     delay(1000);
  5315. +     outb(iobase+wd_ctlr, WDCTL_IDS);
  5316. +     delay(1000);
  5317. +     (void) inb(iobase+wd_error);
  5318. +     outb(iobase+wd_ctlr, WDCTL_4BIT);
  5319. +     if (wait_for_unbusy(wdc) < 0) {
  5320. +         printf("%s: reset failed\n", wdc->sc_dev.dv_xname);
  5321. +         return 1;
  5322. +     }
  5323. +     return 0;
  5324. + }
  5325. + void
  5326. + wdcrestart(arg)
  5327. +     void *arg;
  5328. + {
  5329. +     struct wdc_softc *wdc = arg;
  5330. +     int s;
  5331. +     s = splbio();
  5332. +     wdcstart(wdc);
  5333. +     splx(s);
  5334. + }
  5335. + /*
  5336. +  * Unwedge the controller after an unexpected error.  We do this by resetting
  5337. +  * it, marking all drives for recalibration, and stalling the queue for a short
  5338. +  * period to give the reset time to finish.
  5339. +  * NOTE: We use a timeout here, so this routine must not be called during
  5340. +  * autoconfig or dump.
  5341. +  */
  5342. + void
  5343. + wdcunwedge(wdc)
  5344. +     struct wdc_softc *wdc;
  5345. + {
  5346. +     int unit;
  5347. + #ifdef ATAPI_DEBUG
  5348. +     printf("wdcunwedge\n");
  5349. + #endif
  5350. +     untimeout(wdctimeout, wdc);
  5351. +     wdc->sc_flags &= ~WDCF_IRQ_WAIT;
  5352. +     (void) wdcreset(wdc);
  5353. +     /* Schedule recalibrate for all drives on this controller. */
  5354. +     for (unit = 0; unit < 2; unit++) {
  5355. +         if (!wdc->d_link[unit]) continue;
  5356. +         if (wdc->d_link[unit]->sc_state > RECAL)
  5357. +             wdc->d_link[unit]->sc_state = RECAL;
  5358. +     }
  5359. +     wdc->sc_flags |= WDCF_ERROR;
  5360. +     ++wdc->sc_errors;
  5361. +     /* Wake up in a little bit and restart the operation. */
  5362. + #ifdef WDDEBUG
  5363. +     printf("wdcrestart from wdcunwedge\n");
  5364. + #endif
  5365. +     wdc->sc_flags &= ~WDCF_ACTIVE;
  5366. +     timeout(wdcrestart, wdc, RECOVERYTIME);
  5367. + }
  5368. + int
  5369. + wdcwait(wdc, mask)
  5370. +     struct wdc_softc *wdc;
  5371. +     int mask;
  5372. + {
  5373. +     int iobase = wdc->sc_iobase;
  5374. +     int timeout = 0;
  5375. +     u_char status;
  5376. + #ifdef WDCNDELAY_DEBUG
  5377. +     extern int cold;
  5378. + #endif
  5379. + #ifdef WDDEBUG
  5380. +     printf("wdcwait\n");
  5381. + #endif
  5382. +         
  5383. +     for (;;) {
  5384. +         wdc->sc_status = status = inb(iobase+wd_status);
  5385. +         /*
  5386. +          * XXX
  5387. +          * If a single slave ATAPI device is attached, it may
  5388. +          * have released the bus. Select it and try again.
  5389. +          */
  5390. +         if (status == 0xff && wdc->sc_flags & WDCF_ONESLAVE) {
  5391. +             outb(iobase+wd_sdh, WDSD_IBM | 0x10);
  5392. +             wdc->sc_status = status = inb(iobase+wd_status);
  5393. +         }
  5394. +         if ((status & WDCS_BSY) == 0 && (status & mask) == mask)
  5395. +             break;
  5396. +         if (++timeout > WDCNDELAY) {
  5397. + #ifdef ATAPI_DEBUG2
  5398. +             printf("wdcwait: timeout, status %x\n", status);
  5399. + #endif
  5400. +             return -1;
  5401. +         }
  5402. +         delay(WDCDELAY);
  5403. +     }
  5404. +     if (status & WDCS_ERR) {
  5405. +         wdc->sc_error = inb(iobase+wd_error);
  5406. +         return WDCS_ERR;
  5407. +     }
  5408. + #ifdef WDCNDELAY_DEBUG
  5409. +     /* After autoconfig, there should be no long delays. */
  5410. +     if (!cold && timeout > WDCNDELAY_DEBUG) {
  5411. +         struct wdc_xfer *xfer = wdc->sc_xfer.tqh_first;
  5412. +         if (xfer == NULL)
  5413. +             printf("%s: warning: busy-wait took %dus\n",
  5414. +                 wdc->sc_dev.dv_xname, WDCDELAY * timeout);
  5415. +         else 
  5416. +             printf("%s(%s): warning: busy-wait took %dus\n",
  5417. +                 wdc->sc_dev.dv_xname,
  5418. +                 ((struct device*)xfer->d_link->wd_softc)->dv_xname,
  5419. +                 WDCDELAY * timeout);
  5420. +     }
  5421. + #endif
  5422. +     return 0;
  5423. + }
  5424. + void
  5425. + wdctimeout(arg)
  5426. +     void *arg;
  5427. + {
  5428. +     struct wdc_softc *wdc = (struct wdc_softc *)arg;
  5429. +     int s;
  5430. + #ifdef WDDEBUG
  5431. +     printf("wdctimeout\n");
  5432. + #endif
  5433. +     s = splbio();
  5434. +     if ((wdc->sc_flags & WDCF_IRQ_WAIT) != 0) {
  5435. +         wdc->sc_flags &= ~WDCF_IRQ_WAIT;
  5436. +         wdcerror(wdc, "lost interrupt");
  5437. +         wdcunwedge(wdc);
  5438. +     } else
  5439. +         wdcerror(wdc, "missing untimeout");
  5440. +     splx(s);
  5441. + }
  5442. + /*
  5443. +  * Wait for the drive to become ready and send a command.
  5444. +  * Return -1 if busy for too long or 0 otherwise.
  5445. +  * Assumes interrupts are blocked.
  5446. +  */
  5447. + int
  5448. + wdccommand(d_link, command, drive, cylin, head, sector, count)
  5449. +         struct wd_link *d_link;
  5450. +         int command;
  5451. +         int drive, cylin, head, sector, count;
  5452. + {
  5453. +         struct wdc_softc *wdc = (void*)d_link->wdc_softc;
  5454. +         int iobase = wdc->sc_iobase;
  5455. +         int stat;
  5456. + #ifdef WDDEBUG
  5457. +     printf("wdccommand drive %d\n",drive);
  5458. + #endif
  5459. + #if defined(DIAGNOSTIC) && defined(WDCDEBUG)
  5460. +     if ((wdc->sc_flags & WDCF_ACTIVE) == 0 )
  5461. +         printf("wdccommand: controler not active (drive %d)\n", drive);
  5462. + #endif
  5463. +         /* Select drive, head, and addressing mode. */
  5464. +         outb(iobase+wd_sdh, WDSD_IBM | (drive << 4) | head);
  5465. +         /* Wait for it to become ready to accept a command. */
  5466. +         if (command == WDCC_IDP || d_link->type == BUS)
  5467. +                 stat = wait_for_unbusy(wdc);
  5468. +         else
  5469. +                 stat = wdcwait(wdc, WDCS_DRDY);
  5470. +         if (stat < 0) {
  5471. + #ifdef ATAPI_DEBUG
  5472. +                 printf("wdcommand:xfer failed (wait_for_unbusy) status %d\n",stat);
  5473. + #endif
  5474. +                 return -1;
  5475. +          }
  5476. +         /* Load parameters. */
  5477. +         if (d_link->type == DRIVE && d_link->sc_lp->d_type == DTYPE_ST506)
  5478. +                 outb(iobase+wd_precomp, d_link->sc_lp->d_precompcyl / 4);
  5479. +         else
  5480. +                 outb(iobase+wd_features, 0);
  5481. +         outb(iobase+wd_cyl_lo, cylin);
  5482. +         outb(iobase+wd_cyl_hi, cylin >> 8);
  5483. +         outb(iobase+wd_sector, sector);
  5484. +         outb(iobase+wd_seccnt, count);
  5485. +         /* Send command. */
  5486. +         outb(iobase+wd_command, command);
  5487. +         return 0;
  5488. + }
  5489. + /*
  5490. +  * Simplified version of wdccommand().
  5491. +  */
  5492. + int
  5493. + wdccommandshort(wdc, drive, command)
  5494. +         struct wdc_softc *wdc;
  5495. +         int drive;
  5496. +         int command;
  5497. + {
  5498. +         int iobase = wdc->sc_iobase;
  5499. + #ifdef WDDEBUG
  5500. +     printf("wdccommandshort\n");
  5501. + #endif
  5502. + #if defined(DIAGNOSTIC) && defined(WDCDEBUG)
  5503. +     if ((wdc->sc_flags & WDCF_ACTIVE) == 0 )
  5504. +         printf("wdccommandshort: controler not active (drive %d)\n", drive);
  5505. + #endif
  5506. +         /* Select drive. */
  5507. +         outb(iobase+wd_sdh, WDSD_IBM | (drive << 4));
  5508. +         if (wdcwait(wdc, WDCS_DRDY) < 0)
  5509. +                 return -1;
  5510. +         outb(iobase+wd_command, command);
  5511. +         return 0;
  5512. + }
  5513. + #ifndef __BDEVSW_DUMP_OLD_TYPE
  5514. + /* #define WD_DUMP_NOT_TRUSTED /* if you just want to watch */
  5515. + static int wddumprecalibrated;
  5516. + int
  5517. + wdcdump(d_link, blkno, nblks, va)
  5518. + struct wd_link *d_link;
  5519. + daddr_t blkno;
  5520. + int nblks;
  5521. + caddr_t va;
  5522. + {
  5523. +     struct wdc_softc *wdc = (void*)d_link->wdc_softc;
  5524. +     struct disklabel *lp = d_link->sc_lp;
  5525. +     /* Recalibrate, if first dump transfer. */
  5526. +     wdc->sc_flags  |= WDCF_ACTIVE;
  5527. +     if (wddumprecalibrated == 0) {
  5528. +         if (wdccommandshort(wdc, d_link->sc_drive, WDCC_RECAL) != 0 ||
  5529. +         wait_for_ready(wdc) != 0 ||
  5530. +         wdsetctlr(d_link) != 0 || wait_for_ready(wdc) != 0) {
  5531. +                 wdcerror(wdc, "wdcdump: recal failed");
  5532. +              return EIO;
  5533. +         }
  5534. +     }
  5535. +     while (nblks > 0) {
  5536. +         daddr_t xlt_blkno = blkno;
  5537. +         long cylin, head, sector;
  5538. +     
  5539. +         if ((lp->d_flags & D_BADSECT) != 0) {
  5540. +             long blkdiff;
  5541. +             int i;
  5542. +             for (i = 0; (blkdiff = d_link->sc_badsect[i]) != -1; i++) {
  5543. +                 blkdiff -= xlt_blkno;
  5544. +                 if (blkdiff < 0)
  5545. +                     continue;
  5546. +                 if (blkdiff == 0) {
  5547. +                     /* Replace current block of transfer. */
  5548. +                     xlt_blkno = lp->d_secperunit -
  5549. +                         lp->d_nsectors - i - 1;
  5550. +                 }
  5551. +                 break;
  5552. +             }
  5553. +             /* Tranfer is okay now. */
  5554. +         }
  5555. +      
  5556. +         if ((d_link->sc_params.wdp_capabilities & WD_CAP_LBA) != 0) {
  5557. +             sector = (xlt_blkno >> 0) & 0xff;
  5558. +             cylin = (xlt_blkno >> 8) & 0xffff;
  5559. +             head = (xlt_blkno >> 24) & 0xf;
  5560. +             head |= WDSD_LBA;
  5561. +         } else {
  5562. +             sector = xlt_blkno % lp->d_nsectors;
  5563. +             sector++;   /* Sectors begin with 1, not 0. */
  5564. +             xlt_blkno /= lp->d_nsectors;
  5565. +             head = xlt_blkno % lp->d_ntracks;
  5566. +             xlt_blkno /= lp->d_ntracks;
  5567. +             cylin = xlt_blkno;
  5568. +             head |= WDSD_CHS;
  5569. +         }
  5570. + #ifndef WD_DUMP_NOT_TRUSTED
  5571. +         if (wdccommand(d_link, WDCC_WRITE, d_link->sc_drive, cylin, head, sector, 1) != 0 ||
  5572. +             wait_for_drq(wdc) != 0) {
  5573. +             wdcerror(wdc, "wddump: write failed");
  5574. +             return EIO;
  5575. +         }
  5576. +    
  5577. +         outsw(wdc->sc_iobase+wd_data, va, lp->d_secsize >> 1);
  5578. +    
  5579. +         /* Check data request (should be done). */
  5580. +         if (wait_for_ready(wdc) != 0) {
  5581. +             wdcerror(wdc, "wddump: timeout waiting for ready");
  5582. +             return EIO;
  5583. +         }
  5584. + #else   /* WD_DUMP_NOT_TRUSTED */
  5585. +         /* Let's just talk about this first... */
  5586. +         printf("wd%d: dump addr 0x%x, cylin %d, head %d, sector %d\n",
  5587. +             d_link->sc_drive, va, cylin, head, sector);
  5588. +         delay(500 * 1000);  /* half a second */
  5589. + #endif
  5590. +         /* update block count */
  5591. +         nblks -= 1;
  5592. +         blkno += 1;
  5593. +         va += lp->d_secsize;
  5594. +     }
  5595. +     wdc->sc_flags  &= ~WDCF_ACTIVE;
  5596. +     return 0;
  5597. + }
  5598. + #endif
  5599. + void wdc_ata_done(wdc, xfer)
  5600. + struct wdc_softc *wdc;
  5601. + struct wdc_xfer *xfer;
  5602. + {
  5603. +     int s;
  5604. +     struct buf *bp = xfer->c_bp;
  5605. +     struct wd_link *d_link = xfer->d_link;
  5606. + #ifdef WDDEBUG
  5607. +     printf("wdc_ata_done\n");
  5608. + #endif
  5609. +     /* remove this command from xfer queue */
  5610. +     s = splbio();
  5611. +     TAILQ_REMOVE(&wdc->sc_xfer, xfer, c_xferchain);
  5612. +     wdc->sc_flags &= ~(WDCF_SINGLE | WDCF_ERROR | WDCF_ACTIVE);
  5613. +     wdc->sc_errors = 0;
  5614. +     if (bp) {
  5615. +         if (xfer->c_flags & C_ERROR) {
  5616. +             bp->b_flags |= B_ERROR;
  5617. +             bp->b_error = EIO;
  5618. +         }
  5619. +         bp->b_resid = xfer->c_bcount;
  5620. +         wddone(d_link, bp);
  5621. +         biodone(bp);
  5622. +     } else {
  5623. +         wakeup(xfer->databuf);
  5624. +     }
  5625. +     xfer->c_skip = 0;
  5626. +     wdc_free_xfer(xfer);
  5627. +     d_link->openings++;
  5628. +     wdstart((void*)d_link->wd_softc);
  5629. + #ifdef WDDEBUG
  5630. +     printf("wdcstart from wdc_ata_done, flags %d\n",wdc->sc_flags);
  5631. + #endif
  5632. +     wdcstart(wdc);
  5633. +     splx(s);
  5634. + }
  5635. + void wdc_exec_xfer(d_link, xfer)
  5636. + struct wd_link *d_link;
  5637. + struct wdc_xfer *xfer;
  5638. + {
  5639. +    struct wdc_softc *wdc=(struct wdc_softc *)d_link->wdc_softc;
  5640. +    int s;
  5641. +   
  5642. + #ifdef WDDEBUG
  5643. +     printf("wdc_exec_xfer\n");
  5644. + #endif
  5645. +     s = splbio();
  5646. +    /* insert at the end of command list */
  5647. +    TAILQ_INSERT_TAIL(&wdc->sc_xfer,xfer , c_xferchain)
  5648. + #ifdef WDDEBUG
  5649. +     printf("wdcstart from wdc_exec_xfer, flags %d\n",wdc->sc_flags);
  5650. + #endif
  5651. +     wdcstart(wdc);
  5652. +     splx(s);
  5653. + }   
  5654. + struct wdc_xfer *
  5655. + wdc_get_xfer(c_link,flags)
  5656. + struct wdc_link *c_link;
  5657. + int flags;
  5658. + {
  5659. +     struct wdc_xfer *xfer;
  5660. +     int s;
  5661. +     s = splbio();
  5662. +     if (xfer = xfer_free_list.lh_first) {
  5663. +         LIST_REMOVE(xfer, free_list);
  5664. +         splx(s);
  5665. + #ifdef DIAGNOSTIC
  5666. +         if ((xfer->c_flags & C_INUSE) != 0) panic("xfer already in use\n");
  5667. + #endif
  5668. +     } else {
  5669. +         splx(s);
  5670. + #ifdef ATAPI_DEBUG
  5671. +         printf("wdc:making xfer %d\n",wdc_nxfer);
  5672. + #endif
  5673. +         xfer = malloc(sizeof(*xfer), M_DEVBUF,
  5674. +         ((flags & IDE_NOSLEEP) != 0 ? M_NOWAIT : M_WAITOK));
  5675. +         if (!xfer) {
  5676. +             return 0;
  5677. +         }
  5678. + #ifdef DIAGNOSTIC
  5679. +         xfer->c_flags &= ~C_INUSE;
  5680. + #endif
  5681. + #ifdef ATAPI_DEBUG
  5682. +         wdc_nxfer++;
  5683. + #endif
  5684. +     }
  5685. + #ifdef DIAGNOSTIC
  5686. +     if ((xfer->c_flags & C_INUSE) != 0) panic("xfer already in use\n");
  5687. + #endif
  5688. +     bzero(xfer,sizeof(struct wdc_xfer));
  5689. +     xfer->c_flags = C_INUSE;
  5690. +     xfer->c_link = c_link;
  5691. +     return xfer;
  5692. + }
  5693. + void
  5694. + wdc_free_xfer(xfer)
  5695. +     struct wdc_xfer *xfer;
  5696. + {
  5697. +     int s;
  5698. +     s = splbio();
  5699. +     xfer->c_flags &= ~C_INUSE;
  5700. +     LIST_INSERT_HEAD(&xfer_free_list, xfer, free_list);
  5701. +     splx(s);
  5702. + }
  5703. + /*
  5704. +  * Implement operations needed before read/write.
  5705. +  * Returns 0 if operation still in progress, 1 if completed.
  5706. +  */
  5707. + int
  5708. + wdccontrol(d_link)
  5709. +     struct wd_link *d_link;
  5710. + {
  5711. +     struct wdc_softc *wdc = (void *)d_link->wdc_softc;
  5712. + #ifdef WDDEBUG
  5713. +     printf("wdccontrol\n");
  5714. + #endif
  5715. +     switch (d_link->sc_state) {
  5716. +     case RECAL:         /* Set SDH, step rate, do recal. */
  5717. +         if (wdccommandshort(wdc, d_link->sc_drive, WDCC_RECAL) != 0) {
  5718. +             wderror(d_link, NULL, "wdccontrol: recal failed (1)");
  5719. +             goto bad;
  5720. +         }
  5721. +         d_link->sc_state = RECAL_WAIT;
  5722. +         break;
  5723. +     case RECAL_WAIT:
  5724. +         if (wdc->sc_status & WDCS_ERR) {
  5725. +             wderror(d_link, NULL, "wdccontrol: recal failed (2)");
  5726. +             goto bad;
  5727. +         }
  5728. +         /* fall through */
  5729. +     case GEOMETRY:
  5730. +         if ((d_link->sc_params.wdp_capabilities & WD_CAP_LBA) != 0)
  5731. +             goto multimode;
  5732. +         if (wdsetctlr(d_link) != 0) {
  5733. +             /* Already printed a message. */
  5734. +             goto bad;
  5735. +         }
  5736. +         d_link->sc_state = GEOMETRY_WAIT;
  5737. +         break;
  5738. +     case GEOMETRY_WAIT:
  5739. +         if (wdc->sc_status & WDCS_ERR) {
  5740. +             wderror(d_link, NULL, "wdccontrol: geometry failed");
  5741. +             goto bad;
  5742. +         }
  5743. +         /* fall through */
  5744. +     case MULTIMODE:
  5745. +     multimode:
  5746. +         if (d_link->sc_mode != WDM_PIOMULTI)
  5747. +             goto open;
  5748. +         outb(wdc->sc_iobase+wd_seccnt, d_link->sc_multiple);
  5749. +         if (wdccommandshort(wdc, d_link->sc_drive, WDCC_SETMULTI) != 0) {
  5750. +             wderror(d_link, NULL, "wdccontrol: setmulti failed (1)");
  5751. +             goto bad;
  5752. +         }
  5753. +         d_link->sc_state = MULTIMODE_WAIT;
  5754. +         break;
  5755. +     case MULTIMODE_WAIT:
  5756. +         if (wdc->sc_status & WDCS_ERR) {
  5757. +             wderror(d_link, NULL, "wdccontrol: setmulti failed (2)");
  5758. +             goto bad;
  5759. +         }
  5760. +         /* fall through */
  5761. +     case OPEN:
  5762. +     open:
  5763. +         wdc->sc_errors = 0;
  5764. +         d_link->sc_state = OPEN;
  5765. +         /*
  5766. +          * The rest of the initialization can be done by normal means.
  5767. +          */
  5768. +         return 1;
  5769. +     bad:
  5770. +         wdcunwedge(wdc);
  5771. +         return 0;
  5772. +     }
  5773. +     wdc->sc_flags |= WDCF_IRQ_WAIT;
  5774. +     timeout(wdctimeout, wdc, WAITTIME);
  5775. +     return 0;
  5776. + }
  5777. + /*
  5778. +  * Get the drive parameters, if ESDI or ATA, or create fake ones for ST506.
  5779. +  */
  5780. + int
  5781. + wdc_get_parms(d_link)
  5782. +     struct wd_link *d_link;
  5783. + {
  5784. +     struct wdc_softc *wdc = (struct wdc_softc *)d_link->wdc_softc;
  5785. +     int i;
  5786. +     char tb[DEV_BSIZE];
  5787. +     int s, error;
  5788. +     /*
  5789. +      * XXX
  5790. +      * The locking done here, and the length of time this may keep the rest
  5791. +      * of the system suspended, is a kluge.  This should be rewritten to
  5792. +      * set up a transfer and queue it through wdstart(), but it's called
  5793. +      * infrequently enough that this isn't a pressing matter.
  5794. +      */
  5795. +     s = splbio();
  5796. +     while ((wdc->sc_flags & WDCF_ACTIVE) != 0) {
  5797. +         wdc->sc_flags |= WDCF_WANTED;
  5798. +         if ((error = tsleep(wdc, PRIBIO | PCATCH, "wdprm", 0)) != 0) {
  5799. +             splx(s);
  5800. +             return error;
  5801. +         }
  5802. +     }
  5803. +     wdc->sc_flags |= WDCF_ACTIVE;
  5804. +     if (wdccommandshort(wdc, d_link->sc_drive, WDCC_IDENTIFY) != 0 ||
  5805. +         wait_for_drq(wdc) != 0) {
  5806. +         /*
  5807. +          * We `know' there's a drive here; just assume it's old.
  5808. +          * This geometry is only used to read the MBR and print a
  5809. +          * (false) attach message.
  5810. +          */
  5811. +         strncpy(d_link->sc_lp->d_typename, "ST506",
  5812. +             sizeof d_link->sc_lp->d_typename);
  5813. +         d_link->sc_lp->d_type = DTYPE_ST506;
  5814. +         strncpy(d_link->sc_params.wdp_model, "unknown",
  5815. +             sizeof d_link->sc_params.wdp_model);
  5816. +         d_link->sc_params.wdp_config = WD_CFG_FIXED;
  5817. +         d_link->sc_params.wdp_cylinders = 1024;
  5818. +         d_link->sc_params.wdp_heads = 8;
  5819. +         d_link->sc_params.wdp_sectors = 17;
  5820. +         d_link->sc_params.wdp_maxmulti = 0;
  5821. +         d_link->sc_params.wdp_usedmovsd = 0;
  5822. +         d_link->sc_params.wdp_capabilities = 0;
  5823. +     } else {
  5824. +         strncpy(d_link->sc_lp->d_typename, "ESDI/IDE",
  5825. +             sizeof d_link->sc_lp->d_typename);
  5826. +         d_link->sc_lp->d_type = DTYPE_ESDI;
  5827. +         /* Read in parameter block. */
  5828. +         insw(wdc->sc_iobase+wd_data, tb, sizeof(tb) / sizeof(short));
  5829. +         bcopy(tb, &d_link->sc_params, sizeof(struct wdparams));
  5830. +         /* Shuffle string byte order. */
  5831. +         for (i = 0; i < sizeof(d_link->sc_params.wdp_model); i += 2) {
  5832. +             u_short *p;
  5833. +             p = (u_short *)(d_link->sc_params.wdp_model + i);
  5834. +             *p = ntohs(*p);
  5835. +         }
  5836. +     }
  5837. +     /* Clear any leftover interrupt. */
  5838. +     (void) inb(wdc->sc_iobase+wd_status);
  5839. +     /* Restart the queue. */
  5840. + #ifdef WDDEBUG
  5841. +     printf("wdcstart from wdc_get_parms flags %d\n",wdc->sc_flags);
  5842. + #endif
  5843. +     wdc->sc_flags &= ~WDCF_ACTIVE;
  5844. +     wdcstart(wdc);
  5845. +     splx(s);
  5846. +     return 0;
  5847. + }
  5848. + void
  5849. + wdcerror(wdc, msg) 
  5850. +     struct wdc_softc *wdc;
  5851. +     char *msg;
  5852. + {
  5853. +     struct wdc_xfer *xfer = wdc->sc_xfer.tqh_first;
  5854. +     if (xfer == NULL)
  5855. +         printf("%s: %s\n", wdc->sc_dev.dv_xname, msg);
  5856. +     else
  5857. +         printf("%s(%s): %s\n", wdc->sc_dev.dv_xname, 
  5858. +             ((struct device*)xfer->d_link->wd_softc)->dv_xname, msg);
  5859. +  }
  5860. + int wdc_atapi_get_params(ab_link, drive, id)
  5861. + struct bus_link *ab_link;
  5862. + u_int8_t drive;
  5863. + struct atapi_identify *id;
  5864. + {
  5865. +     struct wdc_softc *wdc = (void*)ab_link->wdc_softc;
  5866. +     int status, len, excess = 0;
  5867. +     int s, error;
  5868. +     if (wdc->d_link[drive] != 0) {
  5869. + #ifdef ATAPI_DEBUG_PROBE
  5870. +         printf("wdc_atapi_get_params: WD drive %d\n", drive);
  5871. + #endif
  5872. +         return 0;
  5873. +     }
  5874. +     /* If there is only one ATAPI slave ion the bus,don't probe
  5875. +        drive 0 (master) */
  5876. +     if (wdc->sc_flags & WDCF_ONESLAVE && drive != 1)
  5877. +         return 0;
  5878. + #ifdef ATAPI_DEBUG_PROBE
  5879. +     printf("wdc_atapi_get_params: probing drive %d\n", drive);
  5880. + #endif
  5881. +     /*
  5882. +      * XXX
  5883. +      * The locking done here, and the length of time this may keep the rest
  5884. +      * of the system suspended, is a kluge.  This should be rewritten to
  5885. +      * set up a transfer and queue it through wdstart(), but it's called
  5886. +      * infrequently enough that this isn't a pressing matter.
  5887. +      */
  5888. +     s = splbio();
  5889. +     while ((wdc->sc_flags & WDCF_ACTIVE) != 0) {
  5890. +         wdc->sc_flags |= WDCF_WANTED;
  5891. +         if ((error = tsleep(wdc, PRIBIO | PCATCH, "atprm", 0)) != 0) {
  5892. +             splx(s);
  5893. +             return error;
  5894. +         }
  5895. +     }
  5896. +     wdc->sc_flags |= WDCF_ACTIVE;
  5897. +     error = 1;
  5898. +     (void)wdcreset(wdc);
  5899. +     if ((status = wdccommand((struct wd_link*)ab_link, ATAPI_SOFT_RESET, drive,
  5900. +         0, 0, 0, 0)) != 0) {
  5901. + #ifdef ATAPI_DEBUG
  5902. +         printf("wdc_atapi_get_params: ATAPI_SOFT_RESET failed for drive %d: status %d error %d\n", drive, status, wdc->sc_error);
  5903. + #endif
  5904. +         error = 0;
  5905. +         goto end;
  5906. +     } 
  5907. +     if ((status = wait_for_unbusy(wdc)) != 0 ) {
  5908. + #ifdef ATAPI_DEBUG
  5909. +         printf("wdc_atapi_get_params: wait_for_unbusy failed for drive %d: status %d error %d\n", drive, status, wdc->sc_error);
  5910. + #endif
  5911. +         error = 0;
  5912. +         goto end;
  5913. +     }
  5914. +     if (wdccommand((struct wd_link*)ab_link, ATAPI_IDENTIFY_DEVICE, drive, sizeof(struct atapi_identify), 0,
  5915. +     0, 0) != 0 || atapi_ready(wdc) != 0) {
  5916. + #ifdef ATAPI_DEBUG_PROBE
  5917. +         printf("ATAPI_IDENTIFY_DEVICE failed for drive %d\n",drive);
  5918. + #endif
  5919. +         error = 0;
  5920. +         goto end;
  5921. +     }
  5922. +     len = inb(wdc->sc_iobase + wd_cyl_lo) +
  5923. +         256 * inb(wdc->sc_iobase + wd_cyl_hi);
  5924. +     if (len != sizeof(struct atapi_identify)) {
  5925. +         printf("Warning drive %d returned %d/%d of indentify device data\n",
  5926. +             drive, len, sizeof(struct atapi_identify));
  5927. +         excess = len - sizeof(struct atapi_identify);
  5928. +         if (excess < 0) excess = 0;
  5929. +     }
  5930. +     insw(wdc->sc_iobase + wd_data, id,
  5931. +         sizeof(struct atapi_identify)/sizeof(short));
  5932. +     wdcbit_bucket(wdc, excess);
  5933. + end: /* Restart the queue. */
  5934. + #ifdef WDDEBUG
  5935. +     printf("wdcstart from wdc_atapi_get_parms flags %d\n",wdc->sc_flags);
  5936. + #endif
  5937. +     wdc->sc_flags &= ~WDCF_ACTIVE;
  5938. +     wdcstart(wdc);
  5939. +     splx(s);
  5940. +     return error;
  5941. + }
  5942. +     
  5943. + void wdc_atapi_send_command_packet(ab_link, acp)
  5944. + struct bus_link *ab_link;
  5945. + struct atapi_command_packet *acp;
  5946. + {
  5947. +     struct wdc_softc *wdc = (void*)ab_link->wdc_softc;
  5948. +     struct wdc_xfer *xfer;
  5949. +     int s;
  5950. +     u_int8_t flags = acp->flags & 0xff;
  5951. +     
  5952. +     if (flags & A_POLLED) {   /* Must use the queue and wdc_atapi_start */
  5953. +         struct wdc_xfer xfer_s;
  5954. +         int i;
  5955. + #ifdef ATAPI_DEBUG_WDC
  5956. +         printf("wdc_atapi_send_cmd: flags %ld drive %d cmdlen %d datalen %d",
  5957. +         acp->flags, acp->drive, acp->command_size, acp->data_size);
  5958. + #endif
  5959. +         xfer = &xfer_s;
  5960. +         bzero(xfer, sizeof(xfer_s));
  5961. +         xfer->c_flags = C_INUSE|C_ATAPI|acp->flags;
  5962. +         xfer->d_link = (struct wd_link*) ab_link;
  5963. +         xfer->c_link = ab_link->ctlr_link;
  5964. +         xfer->c_bp = acp->bp;
  5965. +         xfer->atapi_cmd = acp;
  5966. +         xfer->c_blkno = 0;
  5967. +         xfer->databuf = acp->databuf;
  5968. +         xfer->c_bcount = acp->data_size;
  5969. +         if (wait_for_unbusy (wdc) != 0) 
  5970. +             if (!(wdc->sc_status & WDCS_ERR)) {
  5971. +                 printf ("wdc_atapi_send_command: not ready, st = %02x\n",wdc->sc_status);
  5972. +                 acp->status = ERROR;
  5973. +                 return;
  5974. +             }
  5975. +         if (wdccommand ((struct wd_link*)ab_link, ATAPI_PACKET_COMMAND,
  5976. +     acp->drive, acp->data_size, 0, 0, 0) != 0) {
  5977. +             printf("can't send atapi paket command\n");
  5978. +             acp->status = ERROR;
  5979. +             return;
  5980. +         }
  5981. +         /* Wait for cmd i/o phase. */
  5982. +         for (i=20000; i>0; --i) {
  5983. +             int phase;
  5984. +             phase = (inb(wdc->sc_iobase + wd_ireason) & (WDCI_CMD | WDCI_IN)) |
  5985. +                 (inb(wdc->sc_iobase + wd_status) & WDCS_DRQ);
  5986. +             if (phase == PHASE_CMDOUT)
  5987. +                 break;
  5988. +             delay(10);
  5989. +         }
  5990. + #ifdef ATAPI_DEBUG_WDC
  5991. +         printf("Wait for cmd i/o phase: i= %d\n", i);
  5992. + #endif
  5993. +         outsw (wdc->sc_iobase + wd_data, acp->command,
  5994. +             acp->command_size/ sizeof (short));
  5995. +         /* Wait for data i/o phase. */
  5996. +         for (i=20000; i>0; --i) {
  5997. +             int phase;
  5998. +             phase = (inb(wdc->sc_iobase + wd_ireason) & (WDCI_CMD | WDCI_IN)) |
  5999. +                 (inb(wdc->sc_iobase + wd_status) & WDCS_DRQ);
  6000. +             if (phase != PHASE_CMDOUT) {
  6001. +                 break;
  6002. +             }
  6003. +             delay(10);
  6004. +         }
  6005. + #ifdef ATAPI_DEBUG_WDC
  6006. +         printf("Wait for data i/o phase: i= %d\n", i);
  6007. + #endif
  6008. +         while (wdc_atapi_intr(wdc, xfer)) {
  6009. +             for (i=2000; i>0; --i)
  6010. +                 if (! (inb (wdc->sc_iobase + wd_status) & WDCS_DRQ))
  6011. +                     break;
  6012. + #ifdef ATAPI_DEBUG_WDC
  6013. +             printf("wdc_atapi_intr: i=%d\n", i);
  6014. + #endif
  6015. +         }
  6016. +         wdc->sc_flags &= ~(WDCF_IRQ_WAIT | WDCF_SINGLE | WDCF_ERROR);
  6017. +         wdc->sc_errors = 0;
  6018. +         xfer->c_skip = 0;
  6019. +         return;
  6020. +     } else {   /* POLLED */
  6021. +         xfer = wdc_get_xfer(ab_link->ctlr_link, flags&A_NOSLEEP?IDE_NOSLEEP:0);
  6022. +         if (xfer == NULL) {
  6023. +             acp->status = ERROR;
  6024. +             return;
  6025. +         }
  6026. +         xfer->c_flags |= C_ATAPI|acp->flags;
  6027. +         xfer->d_link = (struct wd_link*) ab_link;
  6028. +         xfer->c_link = ab_link->ctlr_link;
  6029. +         xfer->c_bp = acp->bp;
  6030. +         xfer->atapi_cmd = acp;
  6031. +         xfer->c_blkno = 0;
  6032. +         xfer->databuf = acp->databuf;
  6033. +         xfer->c_bcount = acp->data_size;
  6034. +         wdc_exec_xfer((struct wd_link*)ab_link,xfer);
  6035. +         return;
  6036. +     }
  6037. + }
  6038. +         
  6039. + /* 
  6040. +    the bit bucket
  6041. +    */
  6042. + void wdcbit_bucket (wdc, size)
  6043. +     struct wdc_softc *wdc; 
  6044. +     int size;
  6045. + {
  6046. +     int iobase = wdc->sc_iobase; 
  6047. +     int i;
  6048. +  
  6049. +     for (i = 0 ; i < size / 2 ; i++) {
  6050. +     short null; 
  6051. +     (void) insw (iobase + wd_data, &null, 1);
  6052. +     } 
  6053. +  
  6054. +     if (size % 2)
  6055. +     (void) inb (iobase + wd_data);
  6056. + }
  6057. + int wdc_atapi_intr(wdc, xfer)
  6058. + struct wdc_softc *wdc;
  6059. + struct wdc_xfer *xfer;
  6060. + {
  6061. +     int len, phase, i;
  6062. +     int err, st, ire;
  6063. +     struct atapi_command_packet *acp = xfer->atapi_cmd;
  6064. +     if (wait_for_unbusy(wdc)<0) {
  6065. +         printf("wdc_atapi_intr: controller busy\n");
  6066. +         acp->status = ERROR;
  6067. +         acp->error = inb (wdc->sc_iobase + wd_error);
  6068. +         return 0;
  6069. +     }
  6070. + #ifdef ATAPI_DEBUG2
  6071. +      printf("wdc_atapi_intr: %s\n", wdc->sc_dev.dv_xname);
  6072. + #endif
  6073. +     len = inb (wdc->sc_iobase + wd_cyl_lo) +
  6074. +     256 * inb (wdc->sc_iobase + wd_cyl_hi);
  6075. +     st = inb(wdc->sc_iobase + wd_status);
  6076. +     err = inb(wdc->sc_iobase + wd_error);
  6077. +     ire = inb(wdc->sc_iobase + wd_ireason);
  6078. +     
  6079. +     phase = (ire & (WDCI_CMD | WDCI_IN)) | (st & WDCS_DRQ);
  6080. + #ifdef ATAPI_DEBUG_WDC
  6081. +     printf("wdc_atapi_intr: len %d st %d err %d ire %d :", len, st, err, ire);
  6082. + #endif
  6083. +     switch (phase) {
  6084. +     case PHASE_CMDOUT:
  6085. +         /* send packet command */
  6086. + #ifdef ATAPI_DEBUG_WDC
  6087. +         printf("PHASE_CMDOUT\n");
  6088. + #endif
  6089. + #ifdef ATAPI_DEBUG_WDC
  6090. +         {
  6091. +         int i;
  6092. +         char *c = (char*)acp->command;   
  6093. +         printf("wdc_atapi_intr: cmd ");
  6094. +         for(i=0;i<acp->command_size;i++) printf("%x ",c[i]);
  6095. +         printf("\n");
  6096. +         }
  6097. + #endif
  6098. +         wdc->sc_flags |= WDCF_IRQ_WAIT;
  6099. +         outsw (wdc->sc_iobase + wd_data, acp->command,
  6100. +             acp->command_size/ sizeof (short));
  6101. +         return 1;
  6102. +     case PHASE_DATAOUT:
  6103. +         /* write data */
  6104. + #ifdef ATAPI_DEBUG_WDC
  6105. +         printf("PHASE_DATAOUT\n");
  6106. + #endif
  6107. +         if ((acp->flags & (B_READ|B_WRITE)) != B_WRITE) {
  6108. +             printf("wdc_atapi_intr: bad data phase\n");
  6109. +             acp->status = ERROR;
  6110. +             return 1;
  6111. +         }
  6112. +         wdc->sc_flags |= WDCF_IRQ_WAIT;
  6113. +         if (xfer->c_bcount < len) {
  6114. +             printf("wdc_atapi_intr: warning: write only %d of %d requested bytes\n",
  6115. +             xfer->c_bcount, len);
  6116. +             outsw (wdc->sc_iobase + wd_data, xfer->databuf+xfer->c_skip,
  6117. +                         xfer->c_bcount/sizeof (short));
  6118. +             for(i = xfer->c_bcount; i<len; i+=sizeof(short))
  6119. +                 outw(wdc->sc_iobase + wd_data, 0);
  6120. +             xfer->c_bcount = 0;
  6121. +             return 1;
  6122. +         } else {
  6123. +             outsw (wdc->sc_iobase + wd_data, xfer->databuf+xfer->c_skip,
  6124. +                     len/sizeof (short));
  6125. +             xfer->c_skip += len;
  6126. +             xfer->c_bcount -= len;
  6127. +             return 1;
  6128. +         }
  6129. +     
  6130. +         case PHASE_DATAIN:
  6131. +             /* Read data */
  6132. + #ifdef ATAPI_DEBUG_WDC
  6133. +         printf("PHASE_DATAIN\n");
  6134. + #endif
  6135. +         if ((acp->flags & (B_READ|B_WRITE)) != B_READ) {
  6136. +             printf("wdc_atapi_intr: bad data phase\n");
  6137. +             acp->status = ERROR;
  6138. +             return 1;
  6139. +         }
  6140. +         wdc->sc_flags |= WDCF_IRQ_WAIT;
  6141. +         if (xfer->c_bcount < len) {
  6142. +             printf("wdc_atapi_intr: warning: reading only %d of %d bytes\n",
  6143. +                 xfer->c_bcount, len);
  6144. +             insw(wdc->sc_iobase + wd_data, xfer->databuf+xfer->c_skip,
  6145. +                 xfer->c_bcount/sizeof(short));
  6146. +             wdcbit_bucket(wdc, len - xfer->c_bcount);
  6147. +             xfer->c_bcount = 0;
  6148. +             return 1;
  6149. +         } else {
  6150. +             insw(wdc->sc_iobase + wd_data, xfer->databuf+xfer->c_skip,
  6151. +                 len/sizeof(short));
  6152. +             xfer->c_skip += len;
  6153. +             xfer->c_bcount -=len;
  6154. +             return 1;
  6155. +         }
  6156. +         case PHASE_ABORTED:
  6157. +         case PHASE_COMPLETED:
  6158. + #ifdef ATAPI_DEBUG_WDC
  6159. +         printf("PHASE_COMPLETED\n");
  6160. + #endif
  6161. +         if (st & WDCS_ERR)  {
  6162. +             acp->error = inb (wdc->sc_iobase + wd_error);
  6163. +             acp->status = ERROR;
  6164. +         }
  6165. + #ifdef ATAPI_DEBUG_WDC
  6166. +         if (xfer->c_bcount != 0) {
  6167. +             printf("wdc_atapi_intr warning: bcount value is %d after io\n",
  6168. +                 xfer->c_bcount );
  6169. +         }
  6170. + #endif
  6171. +         break;
  6172. +         default: 
  6173. +             printf("wdc_atapi_intr: unknown phase %d\n", phase);
  6174. +             acp->status = ERROR;
  6175. +     }
  6176. +     wdc_atapi_done(wdc, xfer);
  6177. +     return(0);
  6178. + }
  6179. + void
  6180. + wdc_atapi_done(wdc, xfer)
  6181. + struct wdc_softc *wdc;
  6182. + struct wdc_xfer *xfer;
  6183. + {
  6184. +     struct atapi_command_packet *acp = xfer->atapi_cmd;
  6185. +     int s;
  6186. +     acp->data_size = xfer->c_bcount;
  6187. +     s = splbio();
  6188. +     /* remove this command from xfer queue */
  6189. +     wdc->sc_errors = 0;
  6190. +     xfer->c_skip = 0;
  6191. +     if ((xfer->c_flags & A_POLLED) == 0) {
  6192. +         untimeout(wdctimeout, wdc);
  6193. +         TAILQ_REMOVE(&wdc->sc_xfer, xfer, c_xferchain);
  6194. +         wdc->sc_flags &= ~(WDCF_SINGLE | WDCF_ERROR | WDCF_ACTIVE);
  6195. +         wdc_free_xfer(xfer);
  6196. + #ifdef ATAPI_DEBU
  6197. +         printf("wdc_atapi_done: atapi_done\n");
  6198. + #endif
  6199. +         atapi_done(acp);
  6200. + #ifdef WDDEBUG
  6201. +            printf("wdcstart from wdc_atapi_intr, flags %d\n",wdc->sc_flags);
  6202. + #endif
  6203. +         wdcstart(wdc);
  6204. +     } else {
  6205. +         wdc->sc_flags &= ~(WDCF_SINGLE | WDCF_ERROR | WDCF_ACTIVE);
  6206. +     }
  6207. +     splx(s);
  6208. + }
  6209. diff --exclude compile -bcrNP src.orig/sys/dev/isa/wdlink.h src/sys/dev/isa/wdlink.h
  6210. *** src.orig/sys/dev/isa/wdlink.h    Thu Jan  1 01:00:00 1970
  6211. --- src/sys/dev/isa/wdlink.h    Thu Jun  6 12:21:06 1996
  6212. ***************
  6213. *** 0 ****
  6214. --- 1,112 ----
  6215. + /*
  6216. +  * Copyright (c) 1994, 1995 Charles M. Hannum.  All rights reserved.
  6217. +  *
  6218. +  * DMA and multi-sector PIO handling are derived from code contributed by
  6219. +  * Onno van der Linden.
  6220. +  *
  6221. +  * Atapi support added by Manuel Bouyer.
  6222. +  *
  6223. +  * Redistribution and use in source and binary forms, with or without
  6224. +  * modification, are permitted provided that the following conditions
  6225. +  * are met:
  6226. +  * 1. Redistributions of source code must retain the above copyright
  6227. +  *    notice, this list of conditions and the following disclaimer.
  6228. +  * 2. Redistributions in binary form must reproduce the above copyright
  6229. +  *    notice, this list of conditions and the following disclaimer in the
  6230. +  *    documentation and/or other materials provided with the distribution.
  6231. +  * 3. All advertising materials mentioning features or use of this software
  6232. +  *    must display the following acknowledgement:
  6233. +  *  This product includes software developed by Charles M. Hannum.
  6234. +  * 4. The name of the author may not be used to endorse or promote products
  6235. +  *    derived from this software without specific prior written permission.
  6236. +  *
  6237. +  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  6238. +  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  6239. +  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  6240. +  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  6241. +  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  6242. +  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  6243. +  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  6244. +  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  6245. +  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  6246. +  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  6247. +  */
  6248. + #undef WDDEBUG
  6249. + /* #undef DIAGNOSTIC */
  6250. + struct wdc_link {
  6251. +     int flags;
  6252. +     int openings;
  6253. + };
  6254. + struct wd_link {
  6255. +     u_char type;  
  6256. + #define DRIVE 0
  6257. + #define BUS 1
  6258. +     caddr_t wdc_softc;
  6259. +     caddr_t wd_softc;
  6260. +     struct wdc_link *ctlr_link;
  6261. +     struct wdparams sc_params;
  6262. +     /* Long-term state: */
  6263. +     u_int8_t openings;
  6264. +     int sc_drive;                   /* physical unit number */
  6265. +     int sc_state;                   /* control state */
  6266. + #define RECAL           0               /* recalibrate */
  6267. + #define RECAL_WAIT      1               /* done recalibrating */
  6268. + #define GEOMETRY        2               /* upload geometry */
  6269. + #define GEOMETRY_WAIT   3               /* done uploading geometry */
  6270. + #define MULTIMODE       4               /* set multiple mode */
  6271. + #define MULTIMODE_WAIT  5               /* done setting multiple mode */
  6272. + #define OPEN            6               /* done with open */
  6273. +     int sc_mode;                    /* transfer mode */
  6274. + #define WDM_PIOSINGLE   0               /* single-sector PIO */
  6275. + #define WDM_PIOMULTI    1               /* multi-sector PIO */
  6276. + #define WDM_DMA         2               /* DMA */
  6277. +     int sc_multiple;                /* multiple for WDM_PIOMULTI */
  6278. +     int sc_flags;                   /* drive characteistics found */
  6279. + #define WDF_LOCKED      0x01
  6280. + #define WDF_WANTED      0x02
  6281. + #define WDF_WLABEL      0x04            /* label is writable */
  6282. + #define WDF_LABELLING   0x08            /* writing label */
  6283. + /* XXX Nothing resets this yet, but disk change sensing will when ATAPI is
  6284. +    implemented. */
  6285. + #define WDF_LOADED      0x10            /* parameters loaded */
  6286. + #define WDF_32BIT       0x20            /* can do 32-bit transfer */
  6287. + #define WDF_WAIT         0x40            /* waiting for resourses */
  6288. +     daddr_t sc_badsect[127];        /* 126 plus trailing -1 marker */
  6289. +     struct disklabel * sc_lp;    /* label info for this disk */
  6290. + };
  6291. + struct wdc_xfer {
  6292. +     struct wdc_link *c_link;   /* controller structure info */
  6293. +     struct wd_link *d_link;   /* drive/bus structure info */
  6294. +     volatile long c_flags; /* handle also B_READ and B_WRITE */
  6295. + #define C_INUSE 0x01
  6296. + #define C_ATAPI 0x02
  6297. + #define C_ERROR 0x04
  6298. +     /* Information about the current transfer  */
  6299. +     struct buf *c_bp;
  6300. +     void *atapi_cmd;
  6301. +     void* databuf;
  6302. +     daddr_t c_blkno;       /* starting block number */
  6303. +     int c_bcount;          /* byte count left */
  6304. +     int c_skip;            /* bytes already transferred */
  6305. +     int c_nblks;           /* number of blocks currently transferring */
  6306. +     int c_nbytes;          /* number of bytes currently transferring */
  6307. +     u_long c_p_offset;  /* offset of the partition */
  6308. +     TAILQ_ENTRY(wdc_xfer) c_xferchain;
  6309. +     LIST_ENTRY(wdc_xfer) free_list;
  6310. + };
  6311. + void wdc_exec_xfer __P((struct wd_link *, struct wdc_xfer *));
  6312. + struct wdc_xfer * wdc_get_xfer __P((struct wdc_link *, int));
  6313. + int wdc_get_parms __P((struct wd_link *));
  6314. + void wderror __P((struct wd_link* , struct buf *, char *));
  6315. + void wddone __P((struct wd_link*, struct buf*));
  6316. + int wdccommand __P((struct wd_link *, int, int, int, int, int, int));
  6317. + int wdcdumpprecalibrated __P((struct wd_link *));
  6318. + #define IDE_NOSLEEP 0x01
  6319. diff --exclude compile -bcrNP src.orig/sys/dev/isa/wdreg.h src/sys/dev/isa/wdreg.h
  6320. *** src.orig/sys/dev/isa/wdreg.h    Sat Oct 14 03:39:23 1995
  6321. --- src/sys/dev/isa/wdreg.h    Thu Jun  6 12:27:04 1996
  6322. ***************
  6323. *** 46,51 ****
  6324. --- 46,52 ----
  6325.   #define    wd_precomp    0x001    /* write precompensation (W) */
  6326.   #define    wd_features    0x001    /* features (W) */
  6327.   #define    wd_seccnt    0x002    /* sector count (R/W) */
  6328. + #define wd_ireason  0x002   /* interrupt reason (R/W) (for atapi) */
  6329.   #define    wd_sector    0x003    /* first sector number (R/W) */
  6330.   #define    wd_cyl_lo    0x004    /* cylinder address, low byte (R/W) */
  6331.   #define    wd_cyl_hi    0x005    /* cylinder address, high byte (R/W) */
  6332. ***************
  6333. *** 118,123 ****
  6334. --- 119,146 ----
  6335.   #define    WDSD_CHS    0x00    /* cylinder/head/sector addressing */
  6336.   #define    WDSD_LBA    0x40    /* logical block addressing */
  6337.   
  6338. + /* Commands for ATAPI devices */
  6339. + #define ATAPI_CHECK_POWER_MODE      0xe5
  6340. + #define ATAPI_EXEC_DRIVE_DIAGS      0x90
  6341. + #define ATAPI_IDLE_IMMEDIATE        0xe1
  6342. + #define ATAPI_NOP           0x00
  6343. + #define ATAPI_PACKET_COMMAND        0xa0
  6344. + #define ATAPI_IDENTIFY_DEVICE       0xa1
  6345. + #define ATAPI_SOFT_RESET        0x08
  6346. + #define ATAPI_SET_FEATURES      0xef
  6347. + #define ATAPI_SLEEP         0xe6
  6348. + #define ATAPI_STANDBY_IMMEDIATE     0xe0
  6349. + /* ireason */
  6350. + #define WDCI_CMD         0x01    /* command(1) or data(0) */
  6351. + #define WDCI_IN          0x02    /* transfer to(1) or from(0) the host */
  6352. + #define WDCI_RELEASE     0x04    /* bus released until completion */
  6353. + #define PHASE_CMDOUT    (WDCS_DRQ | WDCI_CMD)
  6354. + #define PHASE_DATAIN    (WDCS_DRQ | WDCI_IN)
  6355. + #define PHASE_DATAOUT   WDCS_DRQ
  6356. + #define PHASE_COMPLETED (WDCI_IN | WDCI_CMD)
  6357. + #define PHASE_ABORTED   0
  6358.   
  6359.   #ifdef _KERNEL
  6360.   /*
  6361. diff --exclude compile -bcrNP src.orig/usr.bin/eject/eject.c src/usr.bin/eject/eject.c
  6362. *** src.orig/usr.bin/eject/eject.c    Thu Feb  1 13:27:47 1996
  6363. --- src/usr.bin/eject/eject.c    Thu Jun  6 16:54:06 1996
  6364. ***************
  6365. *** 88,93 ****
  6366. --- 88,96 ----
  6367.       { "mcd", "/dev/mcd0", 'a', DISK },
  6368.       { "mcd0", "/dev/mcd0", 'a', DISK },
  6369.       { "mcd1", "/dev/mcd1", 'a', DISK },
  6370. +     { "acd", "/dev/acd0", 'a', DISK },
  6371. +     { "acd0", "/dev/acd0", 'a', DISK },
  6372. +     { "acd1", "/dev/acd1", 'a', DISK },
  6373.       { "tape", "/dev/rst0", '\0', TAPE },
  6374.       { "tape0", "/dev/rst0", '\0', TAPE },
  6375.       { "tape1", "/dev/rst1", '\0', TAPE },
  6376.