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-1.1 next >
Encoding:
Text File  |  1996-03-05  |  172.9 KB  |  6,353 lines

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