home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / f / ftp-102.zip / ftape-1.02 / driver / fdtape.c < prev    next >
C/C++ Source or Header  |  1992-10-24  |  59KB  |  2,459 lines

  1. /* Floppy Tape driver.
  2.    Copyright (C) 1992 David L. Brown, Jr.
  3.  
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2, or (at your option)
  7. any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. GNU General Public License for more details.
  13.  
  14. You should have received a copy of the GNU General Public License
  15. along with this program; see the file COPYING.  If not, write to
  16. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  17.  
  18. /*
  19.  * fdtape.c,v 1.24 1992/10/24 19:28:26 dbrown Exp
  20.  *
  21.  * fdtape.c,v
  22.  * Revision 1.24  1992/10/24  19:28:26  dbrown
  23.  * Fixed up the buffering code to work without allocs.
  24.  *
  25.  * Revision 1.23  1992/10/13  01:44:31  dbrown
  26.  * Added FSF copyright.
  27.  *
  28.  * Revision 1.22  1992/10/12  05:12:59  dbrown
  29.  * Added ioctl to set drive data rate.
  30.  *
  31.  * Fixed more write bugs.
  32.  *
  33.  * Revision 1.21  1992/10/11  18:31:31  dbrown
  34.  * Made interrupt handler static.
  35.  *
  36.  * Revision 1.20  1992/10/11  02:23:40  dbrown
  37.  * Fixed more write bugs.
  38.  *
  39.  * Revision 1.19  1992/10/10  23:18:10  dbrown
  40.  * Fixed bug in _do_write_cease causing it to ignore many error conditions.
  41.  *
  42.  * Revision 1.18  1992/10/10  22:38:06  dbrown
  43.  * Added locking mechnisms to prevent other operations during read and
  44.  * write and to stop the read or write when closing.
  45.  *
  46.  * Revision 1.17  1992/10/10  07:02:32  dbrown
  47.  * Fixed initial write acting like and error.
  48.  *
  49.  * Revision 1.16  1992/10/10  06:15:13  dbrown
  50.  * Force to COLORADO or MOUNTAIN drive type.
  51.  *
  52.  * Some fixes to write.
  53.  *
  54.  * Revision 1.15  1992/10/10  03:19:26  dbrown
  55.  * Added write error handling so that errors and their location can be
  56.  * passed back to the user.
  57.  *
  58.  * Revision 1.14  1992/10/09  05:53:31  dbrown
  59.  * Read is reliable.  Write is flaky and can't handle errors.
  60.  *
  61.  * Revision 1.13  1992/10/09  02:18:24  dbrown
  62.  * Attempted to fix stopping of tape problem.  This is very difficult to
  63.  * test because it occurs so rarely.
  64.  *
  65.  * Revision 1.12  1992/10/09  01:29:13  dbrown
  66.  * Write now streams and works somewhat robustly.  One little possible
  67.  * crashing position left.
  68.  *
  69.  * Revision 1.11  1992/10/09  00:36:03  dbrown
  70.  * Initial writing of full write.  Untested.
  71.  *
  72.  * Revision 1.10  1992/10/08  23:45:16  dbrown
  73.  * Read now does a copyout instead of using mapped buffers.  Before, read
  74.  * didn't have any control of when the user would actually get the data
  75.  * out of the buffer.  If the user delayed, then that data could be
  76.  * overwritten with the read from tape.
  77.  *
  78.  * Revision 1.9  1992/10/08  23:29:15  dbrown
  79.  * Performs streaming reliable reads.
  80.  *
  81.  * Revision 1.8  1992/10/08  22:26:36  dbrown
  82.  * Tried fixing read code, but didn't.
  83.  *
  84.  * Revision 1.7  1992/10/08  04:52:29  dbrown
  85.  * First attempt to add streaming read.  Doesn't really work and panics
  86.  * periodically.
  87.  *
  88.  * Revision 1.6  1992/10/06  19:56:31  dbrown
  89.  * Removed unused code.
  90.  *
  91.  * Revision 1.5  1992/10/05  04:34:40  dbrown
  92.  * Remove some commented out code.
  93.  *
  94.  * Revision 1.4  1992/10/04  23:10:08  dbrown
  95.  * Added facilities for performing seek test.
  96.  *
  97.  * Revision 1.3  1992/10/04  21:45:54  dbrown
  98.  * Now supports non-streaming, single sector reads.
  99.  *
  100.  * Revision 1.2  1992/10/03  23:56:16  dbrown
  101.  * Moved enough of the old driver into the new to get drive status, and
  102.  * seek the tape and the tape head.
  103.  *
  104.  * Revision 1.1  1992/10/03  20:55:09  dbrown
  105.  * Moved from old fdtape driver.
  106.  *
  107.  * Revision 4.1  92/06/07  17:58:07  dbrown
  108.  * Moved to a dynamically linked driver.
  109.  */
  110.  
  111. #ifdef LOADABLE
  112. # define NFDTAPE 1
  113. #else
  114. # include <fdtape.h>
  115. #endif
  116.  
  117. #if NFDTAPE > 0
  118.  
  119. #include <errno.h>
  120. #include <sys/types.h>
  121. #include <i386/ipl.h>
  122. #include <sys/ioctl.h>
  123.  
  124. #include <i386/pio.h>
  125.  
  126. #include "ftape-regs.h"
  127. #include "fdtape-io.h"
  128.  
  129. #include "kernel-interface.h"
  130.  
  131. #if 0
  132. #include <errno.h>
  133. #include <sys/user.h>
  134.  
  135. #include <sys/proc.h>
  136. #include <i386/ipl.h>
  137. #include <i386/pio.h>
  138. #include <i386at/atbus.h>
  139.  
  140. #include <vm/vm_kern.h>
  141. #include <mach/vm_param.h>
  142.  
  143. #include <sys/ioctl.h>
  144. #include "fdtape-io.h"
  145.  
  146. #include "ftape-regs.h"
  147.  
  148. #ifdef LOADABLE
  149. # include <sys/conf.h>
  150. # include <i386at/vd_data.h>
  151. #endif
  152. #endif
  153.  
  154. /* End debugging. */
  155.  
  156. #define STATIC static
  157.  
  158. #ifdef LOADABLE
  159. # define LSTATIC static
  160. #else
  161. # define LSTATIC /**/
  162. #endif
  163.  
  164. #define FDPIC 6            /* Should grab it, figure this out later. */
  165.  
  166. static int (*oldvect)();
  167. static int oldunit;
  168.  
  169. /* Although there may be multiple units, the unit number is only to
  170.    select which drive unit the drive is attached to.  Although two
  171.    tape drives could be conceivably be connected, this driver will not
  172.    support their simultaneous use. */
  173.  
  174. static int busy_flag = 0;
  175. static int tape_unit = 0;
  176.  
  177. /* Forward functions. */
  178.  
  179. static void reset_controller (), disable_controller ();
  180. /*static void fdt_sleep (int time);*/
  181. #define fdt_sleep(x) _th_sleep(x)
  182. /*static int interrupt_wait (int unit, int time);*/
  183. #define interrupt_wait(unit, time) _th_interrupt_wait(time)
  184. /*static void fdt_waker (void *arg);*/
  185. static int controller_wait ();
  186. static int issue_command (char *out_data, int out_count,
  187.               char *in_data, int in_count);
  188. static int specify (int hut, int srt, int hlt, int nd);
  189. static int sense_drive_status (int unit, int *st3);
  190. static int sense_interrupt_status (int *st0, int *pcn);
  191. static int recalibrate (int unit);
  192. static int tape_command (int unit, int command);
  193. static int report_status_operation (int unit, int *status,
  194.                     int command, int result_length);
  195. static int report_drive_status (int unit, int *status);
  196. static int report_error (int unit, int *status);
  197. static int report_configuration (int unit, int *status);
  198. static int report_rom_version (int unit, int *status);
  199. static int report_vendor_id (int unit, int *status);
  200. static int read_id (int unit, struct _fdt_id *location);
  201. /*static int read_data (int unit, int segment, void *addr);*/
  202. static int _wait_for_ready ();
  203. static void read_init ();
  204. static void write_init ();
  205.  
  206. /* Device (unit) structure. */
  207.  
  208. struct fdtape_unit_data {
  209. #if 0
  210.   int *wakeup;            /* What to wakeup on interrupt. */
  211.   int expect_stray_interrupt;    /* Expect stray interrupts. */
  212. #endif
  213.   int pcn;            /* Present cylinder number. */
  214.   int drive_type;        /* What kind of drive was detected. */
  215.   int track;            /* Last track we think the drive is on. */
  216. };
  217.  
  218. extern int expect_stray_interrupt;
  219.  
  220. static struct fdtape_unit_data unit_data[NFDTAPE];
  221.  
  222. /* Tape length of current tape.  Just tackily set here by the user
  223.    program to allow shorter length tapes to be used. */
  224.  
  225. static int segments_per_track = 150;
  226. static long error_results[2];    /* Error results from reads. */
  227. static int buffered_segment[2];    /* Segment that is in the numbered
  228.                    buffer.  -1 indicates that the
  229.                    buffer has nothing. */
  230. static int segment_being_read;    /* What segment is being read in. */
  231. static int segment_count;    /* How many more do we expect to read. */
  232. static int read_into;        /* Which buffer to read into. */
  233. static int last_actual_segments[2];
  234. #define CURRENT_BUFFER read_into
  235. #define PREVIOUS_BUFFER (read_into ^ 1)
  236. #define INCREMENT_BUFFER (read_into ^= 1)
  237.  
  238. /* Transfer operations. */
  239. static void
  240. _open_thread (void *arg)
  241. {
  242.   int result = 0;
  243.   int value;
  244.   int status;
  245.   int unit = (int) arg;
  246.  
  247.   reset_controller (unit, /*motor*/ 0);
  248.  
  249.   if (recalibrate (unit) != 0)
  250.     {
  251.       result = EIO;
  252.       goto error;
  253.     }
  254.  
  255.   value = report_drive_status (unit, &status);
  256.  
  257. #ifdef COLORADO
  258.   /* Try colorado. */
  259.   value = tape_command (unit, QIC_COLORADO_ENABLE1);
  260.   fdt_sleep (MILLISECOND);
  261.   value = tape_command (unit, QIC_COLORADO_ENABLE2);
  262.   fdt_sleep (MILLISECOND);
  263.   value = report_drive_status (unit, &status);
  264.   if (value == 0)
  265.     {
  266.       unit_data[unit].drive_type = DRIVE_IS_COLORADO;
  267.     }
  268.   else
  269.     {
  270.       result = ENODEV;
  271.       goto error;
  272.     }
  273. #elif MOUNTAIN
  274.   /* Try mountain. */
  275.   value = tape_command (unit, QIC_MOUNTAIN_ENABLE1);
  276.   fdt_sleep (MILLISECOND);
  277.   value = tape_command (unit, QIC_MOUNTAIN_ENABLE2);
  278.   fdt_sleep (MILLISECOND);
  279.   value = report_drive_status (unit, &status);
  280.   if (value == 0)
  281.     {
  282.       unit_data[unit].drive_type = DRIVE_IS_MOUNTAIN;
  283.     }
  284.   else
  285.     {
  286.       result = ENODEV;
  287.       goto error;
  288.     }
  289. #else
  290.   if (value == 0)
  291.     {
  292.       unit_data[unit].drive_type = DRIVE_IS_UNKNOWN;
  293.     }
  294.   else
  295.     {
  296.       /* Drive doesn't respond.  Try and wake it up using the known
  297.      methods of drive wakeup. */
  298.       
  299.       /* Try colorado. */
  300.       value = tape_command (unit, QIC_COLORADO_ENABLE1);
  301.       fdt_sleep (MILLISECOND);
  302.       value = tape_command (unit, QIC_COLORADO_ENABLE2);
  303.       fdt_sleep (MILLISECOND);
  304.       value = report_drive_status (unit, &status);
  305.       if (value == 0)
  306.     {
  307.       unit_data[unit].drive_type = DRIVE_IS_COLORADO;
  308.     }
  309.       else
  310.     {
  311.       /* Try mountain. */
  312.       value = tape_command (unit, QIC_MOUNTAIN_ENABLE1);
  313.       fdt_sleep (MILLISECOND);
  314.       value = tape_command (unit, QIC_MOUNTAIN_ENABLE2);
  315.       fdt_sleep (MILLISECOND);
  316.       value = report_drive_status (unit, &status);
  317.       if (value == 0)
  318.         {
  319.           unit_data[unit].drive_type = DRIVE_IS_MOUNTAIN;
  320.         }
  321.       else
  322.         {
  323.           result = ENODEV;
  324.           goto error;
  325.         }
  326.     }
  327.     }
  328. #endif
  329.  
  330.   /* Now we have valid status from the drive. */
  331.  
  332. #if 0
  333.   printf ("Drive status = 0x%x, type = %d\n", status,
  334.       unit_data[unit].drive_type);
  335. #endif
  336.   
  337.   result = ESUCCESS;
  338.  
  339.   buffered_segment[0] = -1;
  340.   buffered_segment[1] = -1;
  341.   segment_being_read = -1;
  342.   segment_count = 0;
  343.   read_into = 0;
  344.   read_init ();            /* Above should move into read_init. */
  345.   write_init ();
  346.  
  347.  error:
  348.   _th_done (result);
  349. }
  350.  
  351. static void
  352. _close_thread (void *arg)
  353. {
  354.   int result;
  355.   int unit = (int) arg;
  356.  
  357.   result = ESUCCESS;
  358.   
  359.   switch (unit_data[unit].drive_type)
  360.     {
  361.     case DRIVE_IS_COLORADO:
  362.       tape_command (unit, QIC_COLORADO_DISABLE);
  363.       break;
  364.     case DRIVE_IS_MOUNTAIN:
  365.       tape_command (unit, QIC_MOUNTAIN_DISABLE);
  366.       break;
  367.     default:
  368.       break;
  369.     }
  370.  
  371.   _th_done (result);
  372. }
  373.  
  374. static void
  375. _get_status_thread (int *status)
  376. {
  377.   int result;
  378.   result = ((report_drive_status (tape_unit, status) == 0)
  379.         ? ESUCCESS : EIO);
  380.   _th_done (result);
  381. }
  382.  
  383. static void
  384. _report_error_thread (struct fdt_error *error)
  385. {
  386.   int code;
  387.   int value;
  388.   int result;
  389.   
  390.   value = report_error (tape_unit, &code);
  391.   if (value == 0)
  392.     {
  393.       error->error = code & 0xff;
  394.       error->command = (code & 0xff00) >> 8;
  395.       result = ESUCCESS;
  396.     }
  397.   else
  398.     result = EIO;
  399.  
  400.   _th_done (result);
  401. }
  402.  
  403. static void
  404. _report_configuration_thread (int *config)
  405. {
  406.   int result;
  407.   result = ((report_configuration (tape_unit, config) == 0)
  408.         ? ESUCCESS : EIO);
  409.   _th_done (result);
  410. }
  411.  
  412. static void
  413. _report_rom_version_thread (int *version)
  414. {
  415.   int result;
  416.   result = ((report_rom_version (tape_unit, version) == 0)
  417.         ? ESUCCESS : EIO);
  418.   _th_done (result);
  419. }
  420.  
  421. static void
  422. _report_vendor_id_thread (int *id)
  423. {
  424.   int result;
  425.   result = ((report_rom_version (tape_unit, id) == 0)
  426.         ? ESUCCESS : EIO);
  427.   _th_done (result);
  428. }
  429.  
  430. /* Perform the specified tape operation and wait up to time_limit
  431.    seconds for the operation to complete.  The resultant status will
  432.    be placed into *status.  Returns ESUCCESS for success, or EIO for
  433.    an error. */
  434.  
  435. static int
  436. operate_and_wait (int command, int time_limit, int *status)
  437. {
  438.   int count;
  439.   int result;
  440.  
  441.   /* Assume the user process will wait for drive ready.  Should
  442.      actually do that here. */
  443.  
  444.   tape_command (tape_unit, command);
  445.  
  446.   /* Now poll the drive every 1/4 second and wait for the drive to
  447.      become ready. */
  448.  
  449.   result = report_drive_status (tape_unit, status);
  450.   if (result != 0)
  451.     return EIO;
  452.   count = time_limit * 4;    /* Wait up to 85 seconds for
  453.                    operation. */
  454.   while (count-- > 0
  455.      && (*status & QIC_STATUS_READY) == 0)
  456.     {
  457.       fdt_sleep (HZ / 4);    /* Sleep for 1/4 second and try again. */
  458.       result = report_drive_status (tape_unit, status);
  459.       if (result != 0)
  460.     return EIO;
  461.     }
  462.   fdt_sleep (HZ / 4);
  463.   result = report_drive_status (tape_unit, status);
  464.   if (result != 0)
  465.     return EIO;
  466.  
  467.   return ESUCCESS;
  468. }
  469.  
  470. /* Seek to the end of the tape, and wait. */
  471.  
  472. static void
  473. _seek_to_end_thread (void *arg)
  474. {
  475.   int result, status;
  476.  
  477.   result = _wait_for_ready ();
  478.   if (result != 0)
  479.     goto error;
  480.  
  481.   result = operate_and_wait (QIC_PHYSICAL_FORWARD, 85, &status);
  482.   if (result == ESUCCESS)
  483.     {
  484.       /* Now make sure the drive thinks we're at the end of the tape. */
  485.       if ((status & QIC_STATUS_AT_EOT) == 0)
  486.     result = EIO;
  487.     }
  488.  
  489.  error:
  490.   _th_done (result);
  491. }
  492.  
  493. /* Seek to the beginning of the tape. */
  494.  
  495. static void
  496. _seek_to_beginning_thread (void *arg)
  497. {
  498.   int result, status;
  499.  
  500.   result = _wait_for_ready ();
  501.   if (result != 0)
  502.     goto error;
  503.  
  504.   result = operate_and_wait (QIC_PHYSICAL_REVERSE, 85, &status);
  505.   if (result == ESUCCESS)
  506.     {
  507.       /* Now make sure the drive thinks we're at the start of the tape. */
  508.  
  509.       if ((status & QIC_STATUS_AT_BOT) == 0)
  510.     result = EIO;
  511.     }
  512.  
  513.  error:
  514.   _th_done (result);
  515. }
  516.  
  517. /* Perform the specified seek.  The absolute value of the argument is
  518.    one more than the number of segments to issue to the qic command.
  519.    If the argument is negative, the seek is done in the reverse
  520.    logical direction, otherwise it is done in the forward logical
  521.    direction. */
  522.  
  523. static void
  524. _seek_thread (int *amount)
  525. {
  526.   int dir, count;
  527.   int status;
  528.   int result = ESUCCESS;
  529.  
  530.   count = *amount;
  531.  
  532.   if (count > 0)
  533.     {
  534.       dir = QIC_SKIP_FORWARD;
  535.       count = count - 1;
  536.     }
  537.   else
  538.     {
  539.       dir = QIC_SKIP_REVERSE;
  540.       count = -1 - count;
  541.     }
  542.  
  543.   result = _wait_for_ready ();
  544.   if (result != 0)
  545.     goto error;
  546.  
  547.   /* Issue this tape command first. */
  548.   result = tape_command (tape_unit, dir);
  549.   if (result == ESUCCESS)
  550.     {
  551.       /* Issue the low nibble of the command. */
  552.  
  553.       result = tape_command (tape_unit, (count & 0x0f) + 2);
  554.       if (result == ESUCCESS)
  555.     {
  556.       /* Issue the high nibble and wait for the command to complete. */
  557.  
  558.       result = operate_and_wait (((count & 0xf0) >> 4) + 2,
  559.                      85, &status);
  560.     }
  561.     }
  562.  
  563.  error:
  564.   _th_done (result);
  565. }
  566.  
  567. /* Seek the head to the specified track. */
  568.  
  569. static void
  570. _seek_to_track_thread (int *track)
  571. {
  572.   int count;
  573.   int status;
  574.   int result;
  575.  
  576.   count = *track;
  577.   unit_data[tape_unit].track = *track;
  578.  
  579.   if (count < 0 || count > 27)
  580.     {
  581.       result = EINVAL;
  582.       goto error;
  583.     }
  584.  
  585.   result = _wait_for_ready ();
  586.   if (result != 0)
  587.     goto error;
  588.  
  589.   /* Issue this tape command first. */
  590.   result = tape_command (tape_unit, QIC_SEEK_HEAD_TO_TRACK);
  591.   if (result == ESUCCESS)
  592.     {
  593.       /* Issue the track and wait for the command to complete. */
  594.       result = operate_and_wait (count + 2, 85, &status);
  595.     }
  596.  
  597.  error:
  598.   _th_done (result);
  599. }
  600.  
  601. /* Reading from tape. */
  602.  
  603. /* Current error map. */
  604. unsigned long error_masks[150];
  605.  
  606. /* Wait for the drive to be ready. */
  607.  
  608. static int
  609. _wait_for_ready ()
  610. {
  611.   int count = 200;        /* 20 seconds. */
  612.   int result, status;
  613.  
  614.   result = report_drive_status (tape_unit, &status);
  615.   if (result != 0)
  616.     return EIO;
  617.  
  618.   while (count > 0
  619.      && (status & QIC_STATUS_READY) == 0)
  620.     {
  621.       fdt_sleep (HZ / 10);
  622.       result = report_drive_status (tape_unit, &status);
  623.       if (result != 0)
  624.     return EIO;
  625.     }
  626.  
  627.   return 0;
  628. }
  629.  
  630. /* Start the tape moving and wait for the segment before the given
  631.    segment to pass by.  Returns 0 if the tape is spinning and ready to
  632.    read the proper segment.  If an error is returned, actual_segment
  633.    will be set to the segment that just passed by, or a value < 0 if
  634.    the location cannot be determined (such as end of a track). */
  635.  
  636. static int
  637. _start_tape (int segment, int *actual_segment,
  638.          int *first_segment    /* Temporary! */
  639.          )
  640. {
  641.   int retries = 10 * 32;    /* Read up to 10 segments ahead. */
  642.   int result;
  643.   int trash;
  644.  
  645.   if (first_segment == 0)
  646.     first_segment = &trash;
  647.  
  648.   *first_segment = -1;
  649.  
  650.   /* Wait for the drive to be ready. */
  651.  
  652.   result = _wait_for_ready ();
  653.   if (result != 0)
  654.     return result;
  655.  
  656.   if (tape_command (tape_unit, QIC_LOGICAL_FORWARD) != 0)
  657.     return EIO;
  658.  
  659.   /* Wait for ID of previous segment to go by unless we are at the
  660.      beginning of the tape. */
  661.  
  662.   if ((segment % segments_per_track) != 0)
  663.     {
  664.       struct _fdt_id location;
  665.       do
  666.     {
  667.       result = read_id (tape_unit, &location);
  668.       if (result != 0)
  669.         {
  670.           *actual_segment = -2;
  671.           fdt_sleep (HZ/10); /* A read id error usually means the
  672.                     tape has run off of the end, wait
  673.                     here to avoid trouble. */
  674.           _wait_for_ready (); /* Even wait for it to become ready.
  675.                      This even causes a lot of problems
  676.                      if the drive isn't given a chance
  677.                      to calm down. */
  678.           goto error;
  679.         }
  680.       *actual_segment = (600 * location.head
  681.                  + 4 * location.cylinder
  682.                  + (location.sector - 1) / 32);
  683.       if (*first_segment < 0)
  684.         *first_segment = *actual_segment;
  685.       if (*actual_segment >= segment ||
  686.           segment - *actual_segment > 9)
  687.         goto error;
  688.     } while (*actual_segment != segment - 1
  689.          && retries-- > 0);
  690.     }
  691.   if (retries <= 0)
  692.     return EIO;
  693.  
  694.   return ESUCCESS;
  695.  error:
  696.   return EIO;
  697. }
  698.  
  699. /* Read one segment.  The tape is assumed to be spinning and the
  700.    proper segment should pass next under the head.  The bits in
  701.    error_mask that are set will not have their sectors read.
  702.    actual_segment will be set as per _start_tape, with -1 being a
  703.    successful read, and -3 being a real read error. */
  704.  
  705. static int
  706. _read_segment (int segment,
  707.            unsigned long error_mask,
  708.            char *buffer,
  709.            int *actual_segment,
  710.            unsigned long *error_bits)
  711. {
  712.   char out[9], in[7];
  713.   unsigned long error_runner;
  714.   int address;
  715.   int result;
  716.   int head, cylinder, sector;
  717.   int offset, remaining;
  718.   int data_offset;
  719.   int count;
  720.   int s;
  721.   int return_value = EIO;
  722.  
  723.   *error_bits = 0;
  724.  
  725.   /* Clear out actual segment. */
  726.   *actual_segment = -1;
  727.  
  728.   head = segment / 600;
  729.   cylinder = (segment % 600) / 4;
  730.   sector = (segment % 4) * 32 + 1;
  731.  
  732.   offset = 0;
  733.   data_offset = 0;
  734.   remaining = 32;
  735.   error_runner = error_mask;
  736.   while (remaining > 0)
  737.     {
  738.       if (error_runner & 1)
  739.     {
  740.       error_runner >>= 1;
  741.       offset++;
  742.       remaining--;
  743.       continue;
  744.     }
  745. #if 0
  746.       for (count = 0; (count < remaining
  747.                && (error_runner & 1) == 0); count++)
  748.     error_runner >>= 1;
  749. #else
  750.       count = 1;
  751.       error_runner >>= 1;
  752. #endif
  753.  
  754.       /* Program the DMA controller to read. */
  755.       address = kvtophys (buffer + data_offset * 1024);
  756.       s = splhigh ();
  757.       outb (DMA_COMMAND, 0);
  758.       outb (DMA_MASK_BIT, 2 | 4);
  759.       outb (DMA_CLEAR_FLIP_FLOP, DMA_MODE_READ);
  760.       outb (DMA_MODE, DMA_MODE_READ);
  761.       outb (DMA_ADDRESS, address & 0xff);
  762.       outb (DMA_ADDRESS, (address & 0xff00) >> 8);
  763.       outb (DMA_PAGE, (address & 0xff0000) >> 16);
  764.       outb (DMA_COUNT, (1024 * count - 1) & 0xff);
  765.       outb (DMA_COUNT, ((1024 * count - 1) & 0xff00) >> 8);
  766.       outb (DMA_MASK_BIT, 2);
  767.       splx (s);
  768.  
  769.       /* Issue FDC command to start reading. */
  770.       out[0] = FDC_READ_DATA;
  771.       out[1] = tape_unit;
  772.       out[2] = cylinder;
  773.       out[3] = head;
  774.       out[4] = sector + offset;
  775.       out[5] = 3;        /* Sector size of 1K. */
  776.       out[6] = sector + offset + count - 1; /* Read appropriate number
  777.                            of sectors. */
  778.       out[7] = 116;        /* Gap length.  From the suggested
  779.                    value for 1K MFM sectors 500K data
  780.                    rate.  The value 116 I made up myself. */
  781.       out[8] = 0xff;        /* No limit to transfer size. */
  782.       result = issue_command (out, 9, 0, 0);
  783.       if (result != 0)
  784.     {
  785.       printf ("fdtape: read issue error\n");
  786.       goto error;
  787.     }
  788.       result = interrupt_wait (tape_unit, READ_TIMEOUT);
  789.       if (result != 0)
  790.     {
  791.       printf ("fdtape: read timeout\n");
  792.       goto error;
  793.     }
  794.  
  795.       result = issue_command (0, 0, in, 7);
  796.       if (result != 0)
  797.     {
  798.       printf ("fdtape: read result error\n");
  799.       return result;
  800.     }
  801.  
  802.       if ((in[0] & ST0_CODE_MASK) != ST0_NORMAL)
  803.     {
  804.       /* Figure out the type of error. */
  805.  
  806.       if (in[1] & ST1_DATA_ERROR)
  807.         {
  808.           /* Rewind the tape. */
  809.           tape_command (tape_unit, QIC_PAUSE);
  810.           printf ("fdtape: crc error in sector %d or segment %d (%d)\n",
  811.               (in[5] - 1) % 32 + 1, segment, in[5]);
  812.  
  813.           /* Make sure the floppy disk controller is sane and
  814.          reporting a sector of a reasonable range. */
  815.  
  816.           if (in[5] < sector + offset
  817.           || in[5] >= sector + offset + count)
  818.         {
  819.           printf ("fdtape: crc error in unrealted data\n");
  820.           goto error;
  821.         }
  822.  
  823.           /* Run backward into the error. */
  824.  
  825.           while (sector + offset + count - 1 > in[5])
  826.         count--;
  827.  
  828.           /* Set the error bit. */
  829.  
  830.           *error_bits |= 1 << (offset + count - 1);
  831.  
  832.           /* Restart the tape. */
  833.           result = _start_tape (segment, actual_segment,
  834.                     0);
  835.           if (result == ESUCCESS)
  836.         *actual_segment = -1;
  837.           else
  838.         return_value = result;
  839.  
  840.           printf ("fdtape: start=%d,count=%d,bits=0x%x, do=%d\n",
  841.               sector + offset, count, *error_bits, data_offset);
  842.         }
  843.       else
  844.         {
  845.           printf ("fdtape: error st0 = 0x%x, st1 = 0x%x, st2 = 0x%x\n",
  846.               in[0], in[1], in[2]);
  847.           printf ("fdtape: read_segment, error cyl=%d, head=%d, sec=%d, ss=%d\n",
  848.               in[3], in[4], in[5], in[6]);
  849.           *actual_segment = -3;    /* Some kind of read error. */
  850.           goto error;
  851.         }
  852.     }
  853.  
  854.       offset += count;
  855.       data_offset += count;
  856.       remaining -= count;
  857.     }
  858.  
  859.   return_value = ESUCCESS;
  860.  
  861.  error:
  862.  
  863.   return return_value;
  864. }
  865.  
  866. /* Buffering and reading the data. */
  867.  
  868. /* The read routines exist in one of these states:
  869.  
  870.    XXX This isn't correct.
  871.  
  872.      Name        Buffers            User process.
  873.             Thread
  874.    ------------------------------------------------------------
  875.    - idle        empty            Nothing
  876.             Not running
  877.    - request        cur:read        Waiting
  878.             Reading->cur
  879.    - read_next        cur:read, prev:used    Nothing
  880.             Reading->cur
  881.    - got        cur:read, prev:data    Waiting
  882.             Reading->cur.
  883.    - idle_buffer    cur:data prev:data    Nothing
  884.             Not running.
  885.    - idle_one_buffer    prev:data, cur:empty    Nothing
  886.             Not running
  887.  
  888.    State transition conditions:
  889.  
  890.    idle: if user request -> request
  891.    request: if finish read then
  892.               if more to read -> read_next
  893.            else -> idle_one_buffer
  894.    read_next: if user gets buffer -> got
  895.              if finish read -> idle_buffer
  896.    got: if finish read then
  897.            if more to read -> read_next
  898.        else -> idle
  899.    idle_buffer: if user gets buffer then
  900.            if more to read -> request
  901.            else -> idle_one_buffer
  902.    idle_one_buffer: if user gets buffer -> idle
  903. */
  904.  
  905. enum read_states {
  906.   READ_IDLE, READ_REQUEST, READ_NEXT, READ_GOT, READ_BUFFER,
  907.   READ_WAIT, READ_STOPPING, READ_STOPPING_WAIT
  908. };
  909. static int read_state = READ_IDLE;
  910. static char *read_state_names[] = {
  911.   "Idle", "Request", "Next", "Got", "Buffer", "Wait",
  912.   "Stopping", "Stopping Wait"
  913. };
  914.  
  915. static void
  916. read_init ()
  917. {
  918.   read_state = READ_IDLE;
  919. }
  920.  
  921. /* Transitions within thread.  These are indexed by
  922.    2*read_state + (count>0). */
  923.  
  924. struct read_thread_transitions {
  925.   enum read_states    next;    /* Next state. */
  926.   int            wake;    /* Wake up the user process. */
  927.   int            done;    /* Done reading? */
  928. };
  929. static struct read_thread_transitions _read_thread_transitions[8*2] =
  930. {
  931.   /*        next,    wake,    continue. */
  932.   /* i0 */ -1,        -1,    -1,
  933.        -1,        -1,    -1,
  934.   /* q0 */ READ_IDLE,    1,    1,
  935.        READ_NEXT,    1,    0,
  936.   /* n0 */ READ_BUFFER,    1,    1,
  937.        READ_WAIT,    0,    1,
  938.   /* g0 */ READ_IDLE,    1,    1,
  939.        READ_NEXT,    1,    0,
  940.   /* b0 */ -1,        -1,    -1,
  941.        -1,        -1,    -1,
  942.   /* w0 */ -1,        -1,    -1,
  943.        -1,        -1,    -1,
  944.   /* s0 */ -1,        -1,    -1,
  945.        -1,        -1,    -1,
  946.   /* S0 */ -1,        -1,    -1,
  947.        -1,        -1,    -1,
  948. };
  949.  
  950. static void
  951. _read_thread (void *nothing)
  952. {
  953.   int old_state;
  954.   int result = 0;
  955.   int done = 0;
  956.   int wake_them = 0;
  957.   int index;
  958.  
  959. #if 0
  960.   printf ("_read_thread starts, state = %s (%d)\n",
  961.       read_state_names[read_state], segment_count);
  962. #endif
  963.  
  964.   result = _start_tape (segment_being_read,
  965.             &last_actual_segments[CURRENT_BUFFER],
  966.             0);
  967.  
  968.   if (result != 0)
  969.     {
  970.       read_state = READ_IDLE;
  971.       INCREMENT_BUFFER;
  972.       segment_count == 0;
  973.     }
  974.   else
  975.     {
  976.       while (!done)
  977.     {
  978.       result = _read_segment (segment_being_read,
  979.                   error_masks[segment_being_read
  980.                           % segments_per_track],
  981.                   (tape_buffer
  982.                    + 32768 * CURRENT_BUFFER),
  983.                   &last_actual_segments[CURRENT_BUFFER],
  984.                   &error_results[CURRENT_BUFFER]);
  985.       INCREMENT_BUFFER;
  986.       segment_being_read++;
  987.       segment_count--;
  988.       old_state = read_state;
  989.       if (result != 0)
  990.         {
  991.           read_state = READ_IDLE;
  992.           segment_count == 0;
  993.           done = 1;
  994.         }
  995.       else
  996.         {
  997.           index = 2 * old_state + (segment_count > 0);
  998.           if (_read_thread_transitions[index].next == -1)
  999.         {
  1000.           printf ("ftape error: invalid read thread state %d\n",
  1001.               index);
  1002.           read_state = READ_IDLE;
  1003.           _th_done (0);
  1004.         }
  1005.           read_state = _read_thread_transitions[index].next;
  1006.           wake_them = _read_thread_transitions[index].wake;
  1007.           done = _read_thread_transitions[index].done;
  1008.         }
  1009.       if (!done && wake_them)
  1010. #if 0
  1011.         printf ("_read_thread wakes, not done, state = %s (%d)\n",
  1012.             read_state_names[read_state], segment_count),
  1013. #endif
  1014.         _th_wakeup (0);    /* Process needs to be awoken. */
  1015.     }
  1016.     }
  1017.  
  1018.   old_state = read_state;
  1019.   read_state = READ_STOPPING;
  1020.   /* Stop tape appropriately */
  1021.   /* Can't wait for ready, because if the tape is moving, the drive
  1022.      won't be ready.  The stop seems to fail if we're at the beginning
  1023.      of the tape. */
  1024.   /*_wait_for_ready ();*/
  1025.   if (old_state == READ_IDLE)
  1026.     tape_command (tape_unit, QIC_STOP_TAPE);
  1027.   else
  1028.     tape_command (tape_unit, QIC_PAUSE);
  1029. #if 0
  1030.   if (read_state == READ_STOPPING_WAIT)
  1031.     _th_wakeup (0);
  1032. #endif                /* The done wakes us up. */
  1033.  
  1034.   read_state = old_state;
  1035.  
  1036. #if 0
  1037.   printf ("_read_thread finishes, state = %s (%d)\n",
  1038.       read_state_names[read_state], segment_count);
  1039. #endif
  1040.  
  1041.   _th_done (0);
  1042. }
  1043.  
  1044. struct read_transitions {
  1045.   enum read_states    next;    /* Next state. */
  1046.   int            start;    /* Start thread? */
  1047.   int            block;    /* Block for thread? */
  1048. };
  1049.  
  1050. /* These are indexed by read_state. */
  1051.  
  1052. struct read_transitions read_transitions[8] = {
  1053.   /* i */ READ_REQUEST,    1, 1,
  1054.   /* q */ -1,        -1, -1,
  1055.   /* n */ READ_GOT,    0, 1,
  1056.   /* g */ -1,        -1, -1,
  1057.   /* b */ READ_IDLE,    0, 0,
  1058.   /* w */ READ_NEXT,    1, 0,
  1059.   /* s */ -1,        -1, -1,
  1060.   /* S */ -1,        -1, -1,
  1061. };
  1062.  
  1063. static int
  1064. _do_read (struct tape_read *tr)
  1065. {
  1066.   int s;
  1067.   int buf;
  1068.   int old_state;
  1069.   int result = 0;
  1070.   int dont_really_wait = 0;
  1071.  
  1072.   /*printf ("Read is in state %s\n", read_state_names[read_state]);*/
  1073.   s = splhigh ();
  1074.  
  1075.   if (read_state == READ_STOPPING)
  1076.     {
  1077.       read_state == READ_STOPPING_WAIT;
  1078.       _th_wait ();
  1079.       dont_really_wait = 1;
  1080.     }
  1081.  
  1082.   old_state = read_state;
  1083.   if (read_transitions[old_state].next == -1)
  1084.     {
  1085.       printf ("ftape error: Read in invalid state %s\n",
  1086.           read_state_names[read_state]);
  1087.       goto abnormal;
  1088.     }
  1089.   else 
  1090.     {
  1091.       if (old_state == READ_IDLE)
  1092.     {
  1093.       segment_being_read = tr->segment;
  1094.       segment_count = tr->count;
  1095.     }
  1096.       read_state = read_transitions[old_state].next;
  1097.       switch (read_transitions[old_state].start * 2
  1098.           + read_transitions[old_state].block)
  1099.     {
  1100.     case 0:
  1101.       break;
  1102.     case 1:
  1103.       if (!dont_really_wait)
  1104.         _th_wait ();
  1105.       break;
  1106.     case 2:
  1107.       _th_async_begin (_read_thread, 0);
  1108.       break;
  1109.     case 3:
  1110.       _th_begin (_read_thread, 0);
  1111.       break;
  1112.     }
  1113.       tr->actual_segment = last_actual_segments[PREVIOUS_BUFFER];
  1114.       result = copyout (&tape_buffer[PREVIOUS_BUFFER * 32768],
  1115.             tr->buffer, 32768);
  1116.       tr->error_bits = error_results[PREVIOUS_BUFFER];
  1117.     }
  1118.     
  1119.   /*printf ("Read finished in state %s\n", read_state_names[read_state]);*/
  1120.  
  1121.  abnormal:
  1122.   splx (s);
  1123.   return result;
  1124. }
  1125.  
  1126. struct read_stop_trans {
  1127.   int count;            /* What to set segment count to. */
  1128.   int block;            /* Should we block? */
  1129. };
  1130. struct read_stop_trans _read_stop_trans[9] = {
  1131.   /* i */ 0, 0,
  1132.   /* q */ 1, 1,
  1133.   /* n */ 1, 1,
  1134.   /* g */ 0, 0,
  1135.   /* b */ 0, 0,
  1136.   /* w */ 0, 0,
  1137.   /* s */ 0, 0,
  1138.   /* S */ 0, 0,
  1139. };
  1140. static int
  1141. _do_read_stop ()
  1142. {
  1143.   int s;
  1144.  
  1145.   s = splhigh ();
  1146.  
  1147.   if (read_state == READ_STOPPING)
  1148.     {
  1149.       read_state == READ_STOPPING_WAIT;
  1150.       _th_wait ();
  1151.     }
  1152.   else
  1153.     {
  1154.       segment_count = _read_stop_trans[read_state].count;
  1155.       if (_read_stop_trans[read_state].block)
  1156.     _th_wait ();
  1157.     }
  1158.  
  1159.   read_state = READ_IDLE;
  1160.  
  1161.   splx (s);
  1162.  
  1163.   return 0;
  1164. }
  1165.  
  1166. static void
  1167. _read_id_thread (struct _fdt_find_me *fm)
  1168. {
  1169.   int result = 0;
  1170.   struct _fdt_id location;
  1171.   long error_bits;
  1172.  
  1173.   result = _start_tape (fm->segment, &fm->actual_segment,
  1174.             &fm->first_segment);
  1175.  
  1176. #if 0
  1177.   if (result == 0)
  1178.     {
  1179.       result = read_id (tape_unit, &location);
  1180.     }
  1181. #endif
  1182.  
  1183. #if 0
  1184.   if (result == 0)
  1185.     result = _read_segment (fm->segment,
  1186.                 0,    /* No error mask for test. */
  1187.                 tape_buffer, /* First tape buffer. */
  1188.                 &fm->actual_segment,
  1189.                 &error_bits);
  1190. #endif
  1191.  
  1192.   /* Don't return the error result, or the data won't be passed back.
  1193.      Instead, put the error code in the argument structure. */
  1194.  
  1195.   fm->result = result;
  1196.  
  1197.   tape_command (tape_unit, QIC_STOP_TAPE);
  1198.   tape_command (tape_unit, QIC_STOP_TAPE);
  1199.   _th_done (0);
  1200. }
  1201.  
  1202. /* Writing to tape. */
  1203.  
  1204. static int write_actual_segment = -1;
  1205. static int write_error_location = -1;
  1206.  
  1207. /* Write one segment.  The tape is assumed to be spinning and the
  1208.    proper segment should pass next under the head. */
  1209.  
  1210. static int
  1211. _write_segment (int segment,
  1212.         unsigned long error_mask,
  1213.         char *buffer)
  1214. {
  1215.   char out[9], in[7];
  1216.   unsigned long error_runner;
  1217.   int address;
  1218.   int result;
  1219.   int head, cylinder, sector;
  1220.   int offset, remaining;
  1221.   int data_offset;
  1222.   int count;
  1223.   int s;
  1224.   int return_value = EIO;
  1225.  
  1226.   /* Clear out actual segment. */
  1227.   write_actual_segment = -1;
  1228.  
  1229.   head = segment / 600;
  1230.   cylinder = (segment % 600) / 4;
  1231.   sector = (segment % 4) * 32 + 1;
  1232.  
  1233.   offset = 0;
  1234.   data_offset = 0;
  1235.   remaining = 32;
  1236.   error_runner = error_mask;
  1237.   while (remaining > 0)
  1238.     {
  1239.       if (error_runner & 1)
  1240.     {
  1241.       error_runner >>= 1;
  1242.       offset++;
  1243.       remaining--;
  1244.       continue;
  1245.     }
  1246. #if 0
  1247.       /* This is for larger chunks. */
  1248.       for (count = 0; (count < remaining
  1249.                && (error_runner & 1) == 0); count++)
  1250.     error_runner >>= 1;
  1251. #else
  1252.       count = 1;
  1253.       error_runner >>= 1;
  1254. #endif
  1255.  
  1256.       /* Program the DMA controller to write. */
  1257.       address = kvtophys (buffer + data_offset * 1024);
  1258.       s = splhigh ();
  1259.       outb (DMA_COMMAND, 0);
  1260.       outb (DMA_MASK_BIT, 2 | 4);
  1261.       outb (DMA_CLEAR_FLIP_FLOP, DMA_MODE_WRITE);
  1262.       outb (DMA_MODE, DMA_MODE_WRITE);
  1263.       outb (DMA_ADDRESS, address & 0xff);
  1264.       outb (DMA_ADDRESS, (address & 0xff00) >> 8);
  1265.       outb (DMA_PAGE, (address & 0xff0000) >> 16);
  1266.       outb (DMA_COUNT, (1024 * count - 1) & 0xff);
  1267.       outb (DMA_COUNT, ((1024 * count - 1) & 0xff00) >> 8);
  1268.       outb (DMA_MASK_BIT, 2);
  1269.       splx (s);
  1270.  
  1271.       /* Issue FDC command to start reading. */
  1272.       out[0] = FDC_WRITE_DATA;
  1273.       out[1] = tape_unit;
  1274.       out[2] = cylinder;
  1275.       out[3] = head;
  1276.       out[4] = sector + offset;
  1277.       out[5] = 3;        /* Sector size of 1K. */
  1278.       out[6] = sector + offset + count - 1; /* Read appropriate number
  1279.                            of sectors. */
  1280.       out[7] = 1;        /* Gap length.  From the suggested
  1281.                    value for 1K MFM sectors 500K data
  1282.                    rate.  The value 116 I made up myself.
  1283.                    I don't know what this is for.
  1284.                    Since write has more problems than
  1285.                    read, I'll set it to 1 and see if
  1286.                    that helps.  Does this affect the
  1287.                    data written? */
  1288.       out[8] = 0xff;        /* No limit to transfer size. */
  1289.       result = issue_command (out, 9, 0, 0);
  1290.       if (result != 0)
  1291.     {
  1292.       printf ("fdtape: write issue error\n");
  1293.       goto error;
  1294.     }
  1295.       result = interrupt_wait (tape_unit, WRITE_TIMEOUT);
  1296.       if (result != 0)
  1297.     {
  1298.       printf ("fdtape: write timeout\n");
  1299.       goto error;
  1300.     }
  1301.  
  1302.       result = issue_command (0, 0, in, 7);
  1303.       if (result != 0)
  1304.     {
  1305.       printf ("fdtape: write result error\n");
  1306.       return result;
  1307.     }
  1308.  
  1309.       if ((in[0] & ST0_CODE_MASK) != ST0_NORMAL)
  1310.     {
  1311.       printf ("fdtape: write error st0 = 0x%x, st1 = 0x%x, st2 = 0x%x\n",
  1312.           in[0], in[1], in[2]);
  1313.       printf ("fdtape: write_segment, error cyl=%d, head=%d, sec=%d, ss=%d\n",
  1314.           in[3], in[4], in[5], in[6]);
  1315.       write_actual_segment = -3;    /* Some kind of write error. */
  1316.       goto error;
  1317.     }
  1318.  
  1319.       offset += count;
  1320.       data_offset += count;
  1321.       remaining -= count;
  1322.     }
  1323.  
  1324.   return_value = ESUCCESS;
  1325.  
  1326.  error:
  1327.   return return_value;
  1328. }
  1329.  
  1330. /* Writing exists in one of seven states, i, q, qq, s, pp, w, and ww (for
  1331.    lack of better names). */
  1332.  
  1333. enum write_states { WRITE_i, WRITE_q, WRITE_qq, WRITE_s, WRITE_pp,
  1334.               WRITE_w, WRITE_ww,
  1335.               WRITE_stopping, WRITE_stopping_wait,
  1336.               WRITE_error,
  1337.             };
  1338. enum write_states write_state = WRITE_i;
  1339.  
  1340. /* Transitions for write thread. */
  1341.  
  1342. struct write_thread_transitions {
  1343.   enum write_states    next;    /* Next state. */
  1344.   int            wake;    /* Wake up user process? */
  1345.   int            done;    /* Done writing? */
  1346. };
  1347. static struct write_thread_transitions _write_thread_transitions[10] = {
  1348.   /* i  */ -1,        -1, -1,
  1349.   /* q  */ WRITE_s,    1, 1,
  1350.   /* qq */ WRITE_q,    0, 0,
  1351.   /* s  */ -1,        -1, -1,
  1352.   /* pp */ WRITE_qq,    1, 0,
  1353.   /* w  */ WRITE_i,    1, 1,
  1354.   /* ww */ WRITE_w,    0, 0,
  1355.   /* st */ -1,        -1, -1,
  1356.   /* ST */ -1,        -1, -1,
  1357.   /* ER */ -1,        -1, -1,
  1358. };
  1359. static char *write_state_names[10] = {
  1360.   "i", "q", "Q", "s", "P", "w", "W", "st", "ST", "Error"
  1361. };
  1362.  
  1363. static void
  1364. write_init ()
  1365. {
  1366.   write_state = WRITE_i;
  1367.   write_actual_segment = -1;
  1368. }
  1369.  
  1370. static void
  1371. _write_thread (void *nothing)
  1372. {
  1373.   int old_state;
  1374.   int result = 0;
  1375.   int done = 0;
  1376.   int wake_them = 0;
  1377.   int buffer;
  1378.   int segment;
  1379.  
  1380. #if 0
  1381.   printf ("_write_thread starts, state = %s (%d)\n",
  1382.       write_state_names[write_state], segment_count);
  1383. #endif
  1384.  
  1385.   buffer = PREVIOUS_BUFFER;
  1386.   result = _start_tape (segment_being_read,
  1387.             &write_actual_segment,
  1388.             0);
  1389.  
  1390.   if (result != 0)
  1391.     {
  1392.       write_state = WRITE_error;
  1393.       write_error_location = segment_being_read;
  1394.       INCREMENT_BUFFER;
  1395.     }
  1396.   else
  1397.     {
  1398.       while (!done)
  1399.     {
  1400.       result = _write_segment (segment_being_read,
  1401.                    error_masks[segment_being_read
  1402.                           % segments_per_track],
  1403.                    (tape_buffer
  1404.                     + 32768 * buffer));
  1405.       segment_being_read++;
  1406.       old_state = write_state;
  1407.       if (result != 0)
  1408.         {
  1409.           write_state = WRITE_error;
  1410.           write_error_location = segment_being_read - 1;
  1411.           done = 1;
  1412.         }
  1413.       else
  1414.         {
  1415.           if (_write_thread_transitions[old_state].next == -1)
  1416.         {
  1417.           printf ("ftape error: invalid write thread state %d\n",
  1418.               old_state);
  1419.           write_state = WRITE_error;
  1420.           _th_done (0);
  1421.         }
  1422.           write_state = _write_thread_transitions[old_state].next;
  1423.           wake_them = _write_thread_transitions[old_state].wake;
  1424.           done = _write_thread_transitions[old_state].done;
  1425.         }
  1426.       if (!done && wake_them)
  1427. #if 0
  1428.         printf ("_write_thread wakes, not done, state = %s (%d)\n",
  1429.             write_state_names[write_state], segment_count),
  1430. #endif
  1431.         _th_wakeup (0);    /* Process needs to be awoken. */
  1432.  
  1433.       buffer = PREVIOUS_BUFFER;
  1434.     }
  1435.     }
  1436.  
  1437.   old_state = write_state;
  1438.   /* Stop tape appropriately */
  1439.   /* Can't wait for ready, because if the tape is moving, the drive
  1440.      won't be ready.  The stop seems to fail if we're at the beginning
  1441.      of the tape. */
  1442.   /*_wait_for_ready ();*/
  1443.   if (old_state == WRITE_w)
  1444.     tape_command (tape_unit, QIC_STOP_TAPE);
  1445.   else
  1446.     tape_command (tape_unit, QIC_PAUSE);
  1447. #if 0
  1448.   if (read_state == READ_STOPPING_WAIT)
  1449.     _th_wakeup (0);
  1450. #endif                /* The done wakes us up. */
  1451.  
  1452.   write_state = old_state;
  1453.  
  1454. #if 0
  1455.   printf ("_write_thread finishes, state = %s (%d)\n",
  1456.       write_state_names[write_state], segment_count);
  1457. #endif
  1458.  
  1459.   _th_done (0);
  1460. }
  1461.  
  1462. struct write_transitions {
  1463.   enum write_states    next;    /* Next state. */
  1464.   int            start;    /* Start thread? */
  1465.   int            block;    /* Block? */
  1466.   int            cease_next; /* Next thread for cease. */
  1467.   int            cease_block; /* Block on cease? */
  1468. };
  1469. static struct write_transitions write_transitions[10] = {
  1470.   /*       Next         start Blk  cNext   cBlock */
  1471.   /* i  */ WRITE_q,    1, 0, WRITE_i,    0,
  1472.   /* q  */ WRITE_qq,    0, 0, WRITE_w,    1,
  1473.   /* qq */ WRITE_pp,    0, 1, WRITE_ww,    1,
  1474.   /* s  */ WRITE_q,    1, 0, WRITE_i,    0,
  1475.   /* pp */ -1,           -1, -1, -1,     -1,
  1476.   /* w  */ -1,           -1, -1, -1,     -1,
  1477.   /* ww */ -1,           -1, -1, -1,     -1,
  1478.   /* st */ -1,           -1, -1, -1,     -1,
  1479.   /* ST */ -1,           -1, -1, -1,     -1,
  1480.   /* ER */ -1,           -1, -1, WRITE_i, 0,
  1481. };
  1482.  
  1483. static int
  1484. _do_write (struct tape_write *tw)
  1485. {
  1486.   int s;
  1487.   int buf;
  1488.   int old_state;
  1489.   int result = 0;
  1490.   int dont_really_wait = 0;
  1491.  
  1492.   /*printf ("Write is in state %s\n", write_state_names[write_state]);*/
  1493.   s = splhigh ();
  1494.  
  1495.   if (write_state == WRITE_stopping)
  1496.     {
  1497.       write_state == WRITE_stopping_wait;
  1498.       _th_wait ();
  1499.       dont_really_wait = 1;
  1500.     }
  1501.  
  1502.   old_state = write_state;
  1503.  
  1504.   if (old_state == WRITE_error)
  1505.     {
  1506.     real_bad:
  1507.       tw->actual_segment = write_actual_segment;
  1508.       if (tw->actual_segment == -1)
  1509.     tw->actual_segment = -4;
  1510.       tw->error_location = write_error_location;
  1511.       goto abnormal;
  1512.     }
  1513.  
  1514.   if (write_transitions[old_state].next == -1)
  1515.     {
  1516.       printf ("ftape error: Write in invalid state %s\n",
  1517.           write_state_names[write_state]);
  1518.       goto abnormal;
  1519.     }
  1520.   else 
  1521.     {
  1522.       write_state = write_transitions[old_state].next;
  1523.       if (write_transitions[old_state].block
  1524.       && !dont_really_wait)
  1525.     _th_wait ();
  1526.       if (write_state == WRITE_error)
  1527.     goto real_bad;        /* Yuck. */
  1528.       if (old_state == WRITE_i)
  1529.     segment_being_read = tw->segment;
  1530.       result = copyin (tw->buffer,
  1531.             &tape_buffer[CURRENT_BUFFER * 32768],
  1532.             32768);
  1533.       INCREMENT_BUFFER;
  1534.       if (write_transitions[old_state].start)
  1535.     _th_async_begin (_write_thread, 0);
  1536.       tw->actual_segment = -1;
  1537.       tw->error_location = -1;
  1538.     }
  1539.     
  1540.   /*printf ("Write finished in state %s\n", write_state_names[write_state]);*/
  1541.  
  1542.  abnormal:
  1543.   splx (s);
  1544.   return result;
  1545. }
  1546.  
  1547. static int
  1548. _do_write_cease (struct write_cease *tc)
  1549. {
  1550.   int s;
  1551.   int result = 0;
  1552.   int block;
  1553.   int dont_really_wait = 0;
  1554.   int was_error = 0;
  1555.  
  1556.   /*printf ("Cease is in state %s\n", write_state_names[write_state]);*/
  1557.   s = splhigh ();
  1558.  
  1559.   was_error |= write_state == WRITE_error;
  1560.   if (write_state == WRITE_stopping)
  1561.     {
  1562.       write_state == WRITE_stopping_wait;
  1563.       _th_wait ();
  1564.       dont_really_wait = 1;
  1565.     }
  1566.  
  1567.   was_error |= write_state == WRITE_error;
  1568.   if (write_transitions[write_state].cease_next == -1)
  1569.     {
  1570.       printf ("ftape: write cease, impossible state %s\n",
  1571.           write_state_names[write_state]);
  1572.       goto abnormal;
  1573.     }
  1574.  
  1575.   block = write_transitions[write_state].cease_block;
  1576.   write_state = write_transitions[write_state].cease_next;
  1577.   if (block & !dont_really_wait)
  1578.     _th_wait ();
  1579.  
  1580.   /* Yes, check again. */
  1581.   if (write_state == WRITE_stopping)
  1582.     {
  1583.       write_state == WRITE_stopping_wait;
  1584.       _th_wait ();
  1585.       dont_really_wait = 1;
  1586.     }
  1587.  
  1588.   was_error |= write_state == WRITE_error;
  1589.   if (was_error)
  1590.     {
  1591.       write_state = WRITE_i;
  1592.       tc->actual_segment = write_actual_segment;
  1593.       write_actual_segment = -1;
  1594.       tc->error_location = write_error_location;
  1595.     }
  1596.   else
  1597.     {
  1598.       tc->actual_segment = -1;
  1599.       tc->error_location = -1;
  1600.     }
  1601.  
  1602.  abnormal:
  1603.   splx (s);
  1604.   return (result);
  1605. }
  1606.  
  1607. /* Set data rate. */
  1608.  
  1609. static int
  1610. _set_data_rate_thread (int *rate)
  1611. {
  1612.   int vfo;
  1613.   int qic_rate;
  1614.   int result;
  1615.   int status;
  1616.  
  1617.   switch (*rate)
  1618.     {
  1619.     case FDT_RATE_250:
  1620.       vfo = 0x02;
  1621.       qic_rate = 0;
  1622.       break;
  1623.     case FDT_RATE_500:
  1624.       vfo = 0x00;
  1625.       qic_rate = 2;
  1626.       break;
  1627.     default:
  1628.       result = EINVAL;
  1629.       goto error;
  1630.     }
  1631.  
  1632.   result = _wait_for_ready ();
  1633.   if (result != 0)
  1634.     goto error;
  1635.  
  1636.   result = tape_command (tape_unit, QIC_SELECT_RATE);
  1637.   if (result == ESUCCESS)
  1638.     {
  1639.       result = operate_and_wait (qic_rate + 2, 1, &status);
  1640.     }
  1641.  
  1642.   if (result == ESUCCESS)
  1643.     {
  1644.       outb (FDC_VFO_REGISTER, vfo);
  1645.     }
  1646.  
  1647.  error:
  1648.   _th_done (result);
  1649. }
  1650.  
  1651. _fdtape_attach ()
  1652. {
  1653.   busy_flag = 0;
  1654.   tape_unit = -1;
  1655.   printf ("fdtape: Present.\n");
  1656. }
  1657.  
  1658. static int
  1659. fdtape_intr (unit)
  1660.      int unit;
  1661. {
  1662.   unit &= 3;
  1663.   _th_got_interrupt ();
  1664.  
  1665. #if 0
  1666.   if (unit_data[unit].wakeup != 0)
  1667.     {
  1668.       *unit_data[unit].wakeup = WAKEN_BY_INTERRUPT;
  1669.       wakeup (unit_data[unit].wakeup);
  1670.     }
  1671.   else if (unit_data[unit].expect_stray_interrupt)
  1672.     ;
  1673.   else
  1674.     {
  1675.       printf ("fdtape: stray interrupt.\n");
  1676.     }
  1677. #endif
  1678. }
  1679.  
  1680. /* Open */
  1681.  
  1682. int
  1683. _fdtape_open (unit, flags)
  1684.      int unit;
  1685.      int flags;
  1686. {
  1687.   int result;
  1688.   int s;
  1689.  
  1690.   if (busy_flag)
  1691.     return (EBUSY);
  1692.   tape_unit = unit;
  1693.  
  1694.   /* Wedge in interrupt. */
  1695.   s = sploff ();
  1696.   oldvect = ivect[FDPIC];
  1697.   oldunit = iunit[FDPIC];
  1698.   ivect[FDPIC] = fdtape_intr;
  1699.   iunit[FDPIC] = unit;
  1700.   splon (s);
  1701.  
  1702.   result = _th_begin (_open_thread, (void *) unit);
  1703.   if (result == ESUCCESS)
  1704.     {
  1705.       busy_flag = 1;
  1706.     }
  1707.   else
  1708.     {
  1709.       s = sploff ();
  1710.       ivect[FDPIC] = oldvect;
  1711.       iunit[FDPIC] = oldunit;
  1712.       splon (s);
  1713.     }
  1714.   return result;
  1715. }
  1716.  
  1717. int
  1718. _fdtape_close (unit, flags)
  1719.      int unit;
  1720.      int flags;
  1721. {
  1722.   int s;
  1723.   int result;
  1724.   struct write_cease tc;
  1725.  
  1726.   unit &= 0x03;
  1727.  
  1728.   /* Make sure thing is shut down. */
  1729.  
  1730.   if (read_state != READ_IDLE)
  1731.     _do_read_stop ();
  1732.   if (read_state != READ_IDLE)
  1733.     printf ("ftape: warning: close can't stop read\n");
  1734.   if (write_state != WRITE_i)
  1735.     _do_write_cease (&tc);
  1736.   if (read_state != WRITE_i)
  1737.     printf ("ftape: warning: close can't stop write\n");
  1738.  
  1739.   result = _th_begin (_close_thread, (void *) unit);
  1740.  
  1741.   s = sploff ();
  1742.   ivect[FDPIC] = oldvect;
  1743.   iunit[FDPIC] = oldunit;
  1744.   splon (s);
  1745.  
  1746.   disable_controller (unit);
  1747.   busy_flag = 0;
  1748.   return (ESUCCESS);
  1749. }
  1750.  
  1751. int
  1752. _fdtape_ioctl (int unit, unsigned command, void *arg, int mode)
  1753. {
  1754.   int result = EINVAL;
  1755.  
  1756.   /* Don't do anything if reading or writing. */
  1757.   if ((read_state != READ_IDLE
  1758.        && command != FDT_READ && command != FDT_READ_STOP)
  1759.       || (write_state != WRITE_i
  1760.       && command != FDT_WRITE && command != FDT_CEASE_WRITING))
  1761.     {
  1762.       result = EBUSY;
  1763.       goto abnormal;
  1764.     }
  1765.   switch (command)
  1766.     {
  1767.     case FDT_REPORT_STATUS:
  1768.       result = _th_begin (_get_status_thread, arg);
  1769.       break;
  1770.     case FDT_REPORT_ERROR_CODE:
  1771.       result = _th_begin (_report_error_thread, arg);
  1772.       break;
  1773.     case FDT_REPORT_CONFIGURATION:
  1774.       result = _th_begin (_report_configuration_thread, arg);
  1775.       break;
  1776.     case FDT_REPORT_ROM_VERSION:
  1777.       result = _th_begin (_report_rom_version_thread, arg);
  1778.       break;
  1779.     case FDT_REPORT_VENDOR_ID:
  1780.       result = _th_begin (_report_vendor_id_thread, arg);
  1781.       break;
  1782.     case FDT_SEEK_TO_END:
  1783.       result = _th_begin (_seek_to_end_thread, arg);
  1784.       break;
  1785.     case FDT_SEEK_TO_BEGINNING:
  1786.       result = _th_begin (_seek_to_beginning_thread, arg);
  1787.       break;
  1788.     case FDT_SEEK_FORWARD:
  1789.     case FDT_SEEK_REVERSE:
  1790.       {
  1791.     int value = *((int *) arg);
  1792.     if (value < 0 || value > 255)
  1793.       return EINVAL;
  1794.     value++;
  1795.     if (command == FDT_SEEK_REVERSE)
  1796.       value = -value;
  1797.     result = _th_begin (_seek_thread, &value);
  1798.       }
  1799.       break;
  1800.     case FDT_SEEK_TO_TRACK:
  1801.       result = _th_begin (_seek_to_track_thread, arg);
  1802.       break;
  1803.     case FDT_FIND_ME:
  1804.       result = _th_begin (_read_id_thread, arg);
  1805.       break;
  1806.     case FDT_SUBMIT_ERROR_MAP:
  1807.       {
  1808.     struct error_map *map = arg;
  1809.     /* Zero out error map. */
  1810.     bzero (error_masks, segments_per_track * sizeof (unsigned long));
  1811.     result = copyin (map->error_masks,
  1812.              error_masks,
  1813.              map->count * sizeof (unsigned long));
  1814.       }
  1815.       break;
  1816.     case FDT_SET_TRACK_LENGTH:
  1817.       {
  1818.     int value = *((int *) arg);
  1819.     if (value != 150 && value != 100)
  1820.       result = EINVAL;
  1821.     else
  1822.       {
  1823.         segments_per_track = value;
  1824.         result = ESUCCESS;
  1825.       }
  1826.       }
  1827.       break;
  1828.     case FDT_READ:
  1829.       result = _do_read ((struct tape_read *) arg);
  1830.       break;
  1831.     case FDT_READ_STOP:
  1832.       result = _do_read_stop ();
  1833.       break;
  1834.     case FDT_WRITE:
  1835.       result = _do_write ((struct tape_write *) arg);
  1836.       break;
  1837.     case FDT_CEASE_WRITING:
  1838.       result = _do_write_cease ((struct write_cease *) arg);
  1839.       break;
  1840.     case FDT_SET_DATA_RATE:
  1841.       result = _th_begin (_set_data_rate_thread, (int*) arg);
  1842.       break;
  1843.     default:
  1844.       result = EINVAL;
  1845.       break;
  1846.     }
  1847.  abnormal:
  1848.   return result;
  1849. }
  1850. #if 0
  1851.  
  1852. LSTATIC int
  1853. fdtape_read (int dev, struct uio *uiop)
  1854. {
  1855. #if 0
  1856.   int cylinder, segment;
  1857.   int unit = minor (dev);
  1858.  
  1859.   if ((uiop->uio_offset & 32767) != 0)
  1860.     return EINVAL;
  1861.   if (uiop->uio_resid != 32768)
  1862.     return EINVAL;
  1863.   if (uiop->uio_iovcnt != 1)
  1864.     return EINVAL;
  1865.  
  1866.   segment = uiop->uio_offset / 32768;
  1867.  
  1868.   uiop->uio_resid -= 32768;
  1869.   return (read_data (unit, segment, uiop->uio_iov[0].iov_base));
  1870. #else
  1871.   return EINVAL;
  1872. #endif
  1873. }
  1874. #endif
  1875.  
  1876. /* Floppy disk controller communication. */
  1877.  
  1878. static int old_vfo;
  1879.  
  1880. /* Reset the floppy disk controller.  Leaves the FDTAPE unit selected. */
  1881.  
  1882. static void
  1883. reset_controller (int unit, int motor)
  1884. {
  1885.   int data;
  1886.  
  1887.   /*unit_data[unit].*/expect_stray_interrupt = 1;
  1888.  
  1889.   /* Assert the reset line.  Leave the proper unit selected. */
  1890.   data = unit;
  1891.   outb (FDC_CONTROL_REGISTER, data);
  1892.   fdt_sleep (MILLISECOND);
  1893.  
  1894.   /* Now lower the reset line. */
  1895.   data |= FDC_RESET;
  1896.   outb (FDC_CONTROL_REGISTER, data);
  1897.   fdt_sleep (MILLISECOND);
  1898.  
  1899.   /* Enable dma mode. */
  1900.   data |= FDC_DMA_REQUEST;
  1901.   if (motor)
  1902.     data |= FDC_MOTOR_0 << unit;
  1903.   outb (FDC_CONTROL_REGISTER, data);
  1904.   fdt_sleep (MILLISECOND);
  1905.  
  1906.   /* Select clock for fdc.  May need to be changed to select data
  1907.      rate. */
  1908.   old_vfo = inb (FDC_VFO_REGISTER);
  1909.   outb (FDC_VFO_REGISTER, 0x00);
  1910.  
  1911.   /*unit_data[unit].*/expect_stray_interrupt = 0;
  1912. }
  1913.  
  1914. /* When we're done, put the fdc into reset mode so that the regular
  1915.    floppy disk driver will figure out that something is wrong and
  1916.    initialize the controller the way it wants. */
  1917.  
  1918. static void
  1919. disable_controller (int unit)
  1920. {
  1921.   outb (FDC_VFO_REGISTER, old_vfo);
  1922.   outb (FDC_CONTROL_REGISTER, unit);
  1923. }
  1924.  
  1925. /* Floppy disk controller commands. */
  1926.  
  1927. /* Wait for the controller to be ready to send or receive data.  This
  1928.    returns 0 if the FDC is ready to receive, 1 if the FDC has data to
  1929.    send, or -1 if the FDC does not respond. */
  1930.  
  1931. static int
  1932. controller_wait ()
  1933. {
  1934.   int count, data;
  1935.  
  1936.   count = FDC_STATUS_RETRIES;
  1937.   while (count--)
  1938.     {
  1939.       data = inb (FDC_STATUS_REGISTER);
  1940.       if (data & FDC_STATUS_REQUEST_FOR_MASTER)
  1941.     return ((data & FDC_STATUS_DATA_OUT) ? 1 : 0);
  1942.     }
  1943.   return -1;
  1944. }
  1945.  
  1946. /* Issue one floppy disk command.  out_count bytes of data from
  1947.    out_data are sent to the FDC and in_count bytes are read in.  If
  1948.    in_count is zero, then in_data may be null.  Returns 0 if the
  1949.    operation was successful, or -1 if a timeout occured. */
  1950.  
  1951. static int
  1952. issue_command (char *out_data, int out_count,
  1953.            char *in_data, int in_count)
  1954. {
  1955.   while (out_count--)
  1956.     {
  1957.       if (controller_wait () != 0)
  1958.     goto error;
  1959.       outb (FDC_DATA_REGISTER, *out_data);
  1960.       out_data++;
  1961.     }
  1962.   while (in_count--)
  1963.     {
  1964.       if (controller_wait () != 1)
  1965.     goto error;
  1966.       *in_data = inb (FDC_DATA_REGISTER);
  1967.       in_data++;
  1968.     }
  1969.   return 0;
  1970.  error:
  1971.   return -1;
  1972. }
  1973.  
  1974. /* Specific fdc commands.  Refer to ftape-regs.h for more detail on
  1975.    these commands. */
  1976.  
  1977. /* Specify timing parameters.  Accepts hut (head unload time), srt
  1978.    (seek rate time), hlt (head load time), and (nd) non-dma.  Returns
  1979.    0 if no error, -1 on error. */
  1980.  
  1981. static int
  1982. specify (int hut, int srt, int hlt, int nd)
  1983. {
  1984.   char cmd[3];
  1985.  
  1986.   cmd[0] = FDC_SPECIFY;
  1987.   cmd[1] = (srt << 4) | hut;
  1988.   cmd[2] = (hlt << 1) | nd;
  1989.  
  1990.   return (issue_command (cmd, 3, 0, 0));
  1991. }
  1992.  
  1993. /* Sense drive status.  Given a unit, set the drive status.  Returns 0
  1994.    for no error. */
  1995.  
  1996. static int
  1997. sense_drive_status (int unit, int *st3)
  1998. {
  1999.   int result;
  2000.   char out[2], in[1];
  2001.  
  2002.   out[0] = FDC_SENSE_DRIVE_STATUS;
  2003.   out[1] = unit;
  2004.   result = issue_command (out, 2, in, 1);
  2005.   if (result)
  2006.     return result;
  2007.   else
  2008.     {
  2009.       *st3 = in[0] & 0xff;
  2010.       return 0;
  2011.     }
  2012. }
  2013.  
  2014. /* Return the interrupt status.  Returns 0 for success. */
  2015.  
  2016. static int
  2017. sense_interrupt_status (int *st0, int *pcn)
  2018. {
  2019.   int result;
  2020.   char out[1];
  2021.   char in[2];
  2022.  
  2023.   out[0] = FDC_SENSE_INTERRUPT_STATUS;
  2024.   result = issue_command (out, 1, in, 2);
  2025.   if (result)
  2026.     return result;
  2027.   else
  2028.     {
  2029.       *st0 = in[0] & 0xff;
  2030.       *pcn = in[1] & 0xff;
  2031.       return 0;
  2032.     }
  2033. }
  2034.  
  2035. /* Recalibrate and wait until recalibration completed.  (Returns 0 for
  2036.    success). */
  2037.  
  2038. static int
  2039. recalibrate (int unit)
  2040. {
  2041.   int result;
  2042.   char out[2];
  2043.   int st0, pcn;
  2044.   int count;
  2045.  
  2046.   result = specify_recalibrate ();
  2047.   if (result != 0)
  2048.     {
  2049.       printf ("fdtape: recalibrate,specify timed out.\n");
  2050.       return result;
  2051.     }
  2052.  
  2053.   out[0] = FDC_RECALIBRATE;
  2054.   out[1] = unit;
  2055.   result = issue_command (out, 2, 0, 0);
  2056.   if (result != 0)
  2057.     {
  2058.       printf ("fdtape: recalibrate, recalibrate timed out.\n");
  2059.       return result;
  2060.     }
  2061.  
  2062.   for (count = RECALIBRATE_RESULT_RETRIES; count >= 0; count--)
  2063.     {
  2064.       result = interrupt_wait (unit, RECALIBRATE_TIMEOUT);
  2065.       if (result != 0)
  2066.     {
  2067.       printf ("fdtape: recalibrate, interrupt(inner) timeout\n");
  2068.       return result;
  2069.     }
  2070.       result = sense_interrupt_status (&st0, &pcn);
  2071.       if (result != 0)
  2072.     {
  2073.       printf ("fdtape: recalibrate, sis timeout\n");
  2074.       return result;
  2075.     }
  2076.       if (st0 & ST0_SEEK_END)
  2077.     break;
  2078.     }
  2079.   if (count < 0)
  2080.     {
  2081.       printf ("fdtape: recalibrate, seek interrupt timeout\n");
  2082.       return -1;
  2083.     }
  2084.  
  2085. #if 0
  2086.   result = interrupt_wait (unit, RECALIBRATE_TIMEOUT);
  2087.   if (result != 0)
  2088.     {
  2089.       printf ("fdtape: recalibrate, interrupt timed out.\n");
  2090.       return result;
  2091.     }
  2092.  
  2093.   result = sense_interrupt_status (&st0, &pcn);
  2094.   if (result != 0)
  2095.     {
  2096.       printf ("fdtape: recalibrate, sis timed out.\n");
  2097.       return result;
  2098.     }
  2099. #endif
  2100.  
  2101.   unit_data[unit].pcn = pcn;
  2102.  
  2103.   result = specify_normal ();
  2104.   if (result != 0)
  2105.     {
  2106.       printf ("fdtape: recalibrate, specify(2) timed out.\n");
  2107.       return result;
  2108.     }
  2109.  
  2110.   /* We don't really care if the tape drive responded or not (it
  2111.      really shouldn't respond. */
  2112.  
  2113.   return 0;
  2114. }
  2115.  
  2116. /* Issue a tape command.  Seeks command tracks from the current track. */
  2117.  
  2118. static int
  2119. tape_command (int unit, int command)
  2120. {
  2121.   int result;
  2122.   char out[3];
  2123.   int st0, pcn;
  2124.   int destination;
  2125.   int count;
  2126.  
  2127.   /* printf ("fdtape: tape_command (%d) %d\n", unit, command); */
  2128.  
  2129.   fdt_sleep (MILLISECOND);
  2130.  
  2131.   /* Figure out where to seek to.  Seek toward zero if possible to
  2132.      keep these as small integers. */
  2133.  
  2134.   if (unit_data[unit].pcn >= command)
  2135.     destination = unit_data[unit].pcn - command;
  2136.   else
  2137.     destination = unit_data[unit].pcn + command;
  2138.   unit_data[unit].pcn = destination;
  2139.  
  2140.   out[0] = FDC_SEEK;
  2141.   out[1] = unit;
  2142.   out[2] = destination;
  2143.   result = issue_command (out, 3, 0, 0);
  2144.   if (result != 0)
  2145.     {
  2146.       printf ("fdtape: tape_command, seek command error (%d)\n",
  2147.           command);
  2148.       {
  2149.     int real_old_vfo = old_vfo;
  2150.     int res;
  2151.     /* Try hitting the fdc over the head. */
  2152.     reset_controller (tape_unit, 0);
  2153.     res = specify_normal ();
  2154.     printf ("fdtape: seek command error FDC reset didn't even work\n");
  2155.     old_vfo = real_old_vfo;
  2156.       }
  2157.       return result;
  2158.     }
  2159.  
  2160.   for (count = SEEK_RESULT_RETRIES; count >= 0; count--)
  2161.     {
  2162.       result = interrupt_wait (unit, SEEK_TIMEOUT);
  2163.       if (result != 0)
  2164.     {
  2165.       printf ("fdtape: tape_command, seek(inner) timeout\n");
  2166.       return result;
  2167.     }
  2168.       result = sense_interrupt_status (&st0, &pcn);
  2169.       if (result != 0)
  2170.     {
  2171.       printf ("fdtape: seek, sis timeout\n");
  2172.       return result;
  2173.     }
  2174.       if (st0 & ST0_SEEK_END)
  2175.     break;
  2176.     }
  2177.   if (count < 0)
  2178.     {
  2179.       printf ("fdtape: tape_command, seek interrupt timeout\n");
  2180.       return -1;
  2181.     }
  2182.  
  2183.   /* Verify that we seek to the proper track. */
  2184.   if (pcn != destination)
  2185.     {
  2186.       unit_data[unit].pcn = pcn;
  2187.       printf ("fdtape: tape_command, seek to incorrect track.\n");
  2188.       return -1;
  2189.     }
  2190.  
  2191.   return 0;
  2192. }
  2193.  
  2194. /* Query the drive about its status.  The command is sent and
  2195.    result_length bits of status are returned (2 extra bits are read
  2196.    for start and stop). */
  2197.  
  2198. static int
  2199. report_status_operation (int unit, int *status,
  2200.              int command, int result_length)
  2201. {
  2202.   int i, st3;
  2203.   int result;
  2204.  
  2205.   tape_command (unit, QIC_REPORT_NEXT_BIT);
  2206.   tape_command (unit, QIC_REPORT_NEXT_BIT);
  2207.   tape_command (unit, QIC_REPORT_NEXT_BIT);
  2208.   tape_command (unit, QIC_REPORT_NEXT_BIT);
  2209.  
  2210.   result = tape_command (unit, command);
  2211.   if (result != 0)
  2212.     {
  2213.       printf ("fdtape: report_drive_status: tape_command timeout\n");
  2214.       return result;
  2215.     }
  2216.  
  2217.   fdt_sleep (MILLISECOND);
  2218.  
  2219.   result = sense_drive_status (unit, &st3);
  2220.   if (result != 0)
  2221.     {
  2222.       printf ("fdtape: report_drive_status: sds timeout\n");
  2223.       return result;
  2224.     }
  2225.  
  2226.   if (!(st3 & ST3_TRACK_0))
  2227.     {
  2228. #if 0
  2229.       printf ("fdtape: report_drive_status: drive doesn't respond\n");
  2230. #endif
  2231.       return -1;
  2232.     }
  2233.  
  2234.   *status = 0;
  2235.   for (i = 0; i < result_length + 1; i++)
  2236.     {
  2237.       result = tape_command (unit, QIC_REPORT_NEXT_BIT);
  2238.       if (result != 0)
  2239.     {
  2240.       printf ("fdtape: report_drive_status: report next bit timeout\n");
  2241.       return result;
  2242.     }
  2243.       fdt_sleep (MILLISECOND);
  2244.       result = sense_drive_status (unit, &st3);
  2245.       if (result != 0)
  2246.     {
  2247.       printf ("fdtape; report_drive_status: sds(2) timeout\n");
  2248.       return result;
  2249.     }
  2250.  
  2251.       *status >>= 1;
  2252.       if (i < result_length)
  2253.     *status |= ((st3 & ST3_TRACK_0) != 0) << result_length;
  2254.       else if (!(st3 & ST3_TRACK_0))
  2255.     {
  2256.       printf ("fdtape: report_status, stop bit not present.\n");
  2257.       return -1;
  2258.     }
  2259.     }
  2260.   tape_command (unit, QIC_REPORT_NEXT_BIT);
  2261.  
  2262.   return 0;
  2263. }
  2264.  
  2265. /* Status and error handling. */
  2266.  
  2267. /* List of error codes, and their fatalness. */
  2268.  
  2269. struct _fdtape_error {
  2270.   char *message;        /* Text describing the error. */
  2271.   int fatal;            /* Non-zero if the error is fatal. */
  2272. };
  2273.  
  2274. /* These error messages were taken from the Quarter-Inch Cartridge
  2275.    Drive Standards, Inc. document titled ``Common Command Set
  2276.    Interface Specification for Flexible Disk Controller Based
  2277.    Minicartridge Tape Drives,'' document QIC-117 Revision B, 6 Dec 89.
  2278.    For more information, contact,
  2279.       Quarter-Inch Cartridge Drive Standards, Inc.
  2280.       311 East Carrillo Street
  2281.       Santa Barbara, California 93101
  2282.       Telephone (805) 963-3853
  2283.       Fax       (805) 962-1541 */
  2284.  
  2285. static struct _fdtape_error fdtape_errors[] = {
  2286.   /* 0*/ { "No error", 0, },
  2287.   /* 1*/ { "Command Received while Drive Not Ready", 0, },
  2288.   /* 2*/ { "Cartridge Not Present or Removed", 1, },
  2289.   /* 3*/ { "Motor Speed Error", 1, },
  2290.   /* 4*/ { "Motor Speed fault", 1, },
  2291.   /* 5*/ { "Cartridge Write Protected", 1, },
  2292.   /* 6*/ { "Undefined or Reserved Command Code", 1, },
  2293.   /* 7*/ { "Illegal Track address specified for Seek", 1, },
  2294.   /* 8*/ { "Illegal Command in Report Subcontext", 0, },
  2295.   /* 9*/ { "Illegal Entry into a Diagnostic Mode", 1, },
  2296.   /*10*/ { "Broken Tape Detected", 1, },
  2297.   /*11*/ { "Warning--Read Gain Setting Error", 1, },
  2298.   /*12*/ { "Command Received while Error Status Pending", 1, },
  2299.   /*13*/ { "Command Received while New Cartridge Pending", 1, },
  2300.   /*14*/ { "Command Illegal or Undefined in Primary Mode", 1, },
  2301.   /*15*/ { "Command Illegal or Undefined in Format Mode", 1, },
  2302.   /*16*/ { "Command Illegal or Undefined in Verify Mode", 1, },
  2303.   /*17*/ { "Logical Forward not a Logical BOT in Format Mode", 1, },
  2304.   /*18*/ { "Logical EOT before all Segments generated", 1, },
  2305.   /*19*/ { "Command Illegal when Cartridge Not Referenced", 1, },
  2306.   /*20*/ { "Self-Diagnostic Failed", 1, },
  2307.   /*21*/ { "Warning EEPROM Not Initialized, defaults set", 1, },
  2308.   /*22*/ { "EEPROM Corrupted or Hardware Failure", 1, },
  2309.   /*23*/ { "Motion Time-out error", 1, },
  2310.   /*24*/ { "Datat Segment Too Long--Logical Forward or Pause", 1, },
  2311.   /*25*/ { "Transmit Overrun", 1, },
  2312.   /*26*/ { "Power On Reset Occurred", 0, },
  2313.   /*27*/ { "Software Reset Occurred", 0, },
  2314.   /*28*/ { "Diagnostic Mode 1 Error", 1, },
  2315.   /*29*/ { "Diagnostic Mode 2 Error", 1, },
  2316.   /*30*/ { "Command Received During Non-Interruptable Process", 1, },
  2317.   /*31*/ { "Rate Selection error", 1, },
  2318.   /*32*/ { "Illegal command while in high speed mode", 1, },
  2319.   /*33*/ { "Illegal seek segment value", 1, },
  2320. };
  2321. #define MAXIMUM_ERROR 33
  2322.  
  2323. /* Report the current drive status. */
  2324.  
  2325. static int
  2326. report_drive_status (int unit, int *status)
  2327. {
  2328.   int result, count;
  2329.   int command;
  2330.   int error;
  2331.  
  2332.   for (count = 3; count >= 0; count--)
  2333.     {
  2334.       result = report_status_operation (unit, status,
  2335.                     QIC_REPORT_DRIVE_STATUS,
  2336.                     8);
  2337.       if (result == 0)
  2338.     break;
  2339.     }
  2340.  
  2341.   /* If there is an error pending and new cartridge present. */
  2342.  
  2343.   if ((*status & QIC_STATUS_READY) != 0
  2344.       && (*status & QIC_STATUS_ERROR) != 0
  2345.       && (*status & QIC_STATUS_NEW_CARTRIDGE) == 0)
  2346.     {
  2347.       result = report_error (unit, &error);
  2348.       if (result == 0)
  2349.     {
  2350.       command = error >> 8;
  2351.       error &= 0xff;
  2352.       if (error < 0 || error > MAXIMUM_ERROR)
  2353.         printf ("fdtape: tape error out of range (%d).\n",
  2354.             error);
  2355.       else
  2356.         {
  2357.           printf ("fdtape: error %d(%d): \"%s\"\n",
  2358.               error, command, fdtape_errors[error].message);
  2359.           if (fdtape_errors[error].fatal)
  2360.         result = EIO;
  2361.         }
  2362.     }
  2363.  
  2364.       /* Get the new drive status. */
  2365.       if (result == 0)
  2366.     result = report_status_operation (unit, status,
  2367.                       QIC_REPORT_DRIVE_STATUS,
  2368.                       8);
  2369.     }
  2370.  
  2371.   return result;
  2372. }
  2373.  
  2374. static int
  2375. report_error (int unit, int *error)
  2376. {
  2377.   return (report_status_operation (unit, error,
  2378.                    QIC_REPORT_ERROR_CODE,
  2379.                    16));
  2380. }
  2381.  
  2382. static int
  2383. report_configuration (int unit, int *configuration)
  2384. {
  2385.   return (report_status_operation (unit, configuration,
  2386.                    QIC_REPORT_DRIVE_CONFIGURATION,
  2387.                    8));
  2388. }
  2389.  
  2390. static int
  2391. report_rom_version (int unit, int *version)
  2392. {
  2393.   return (report_status_operation (unit, version,
  2394.                    QIC_REPORT_ROM_VERSION,
  2395.                    8));
  2396. }
  2397.  
  2398. static int
  2399. report_vendor_id (int unit, int *id)
  2400. {
  2401.   return (report_status_operation (unit, id,
  2402.                    QIC_REPORT_VENDOR_ID,
  2403.                    16));
  2404. }
  2405.  
  2406. /* Begin a read. */
  2407.  
  2408. static int
  2409. read_id (int unit, struct _fdt_id *location)
  2410. {
  2411.   int result;
  2412.   char out[2];
  2413.   char in[7];
  2414.  
  2415.   out[0] = FDC_READ_ID;
  2416.   out[1] = unit;
  2417.   result = issue_command (out, 2, 0, 0);
  2418.   if (result != 0)
  2419.     {
  2420.       printf ("fdtape: read_id, error issuing command\n");
  2421.       return result;
  2422.     }
  2423.  
  2424.   result = interrupt_wait (unit, READ_TIMEOUT);
  2425.   if (result != 0)
  2426.     {
  2427.       printf ("fdtape: read_id, timeout\n");
  2428.       return result;
  2429.     }
  2430.  
  2431.   result = issue_command (0, 0, in, 7);
  2432.   if (result != 0)
  2433.     {
  2434.       printf ("fdtape: read_id, result phase error\n");
  2435.       return result;
  2436.     }
  2437. #if 0
  2438.   printf ("fdtape: read_id: 0:0x%x, 1:0x%x, 2:0x%x, 3:0x%x, 4:0x%x, 5:0x%x, 6:0x%x\n",
  2439.       in[0], in[1], in[2], in[3], in[4], in[5], in[6]);
  2440. #endif
  2441.  
  2442.   /* Check return for normal. */
  2443.   if ((in[0] & ST0_CODE_MASK) == ST0_NORMAL)
  2444.     {
  2445.       location->cylinder = in[3] & 0xff;
  2446.       location->head = in[4] & 0xff;
  2447.       location->sector = in[5] & 0xff;
  2448.     }
  2449.   else
  2450.     {
  2451.       printf ("fdtape: read_id, error st0=0x%x, st1=0x%x, st2=0x%x\n",
  2452.           in[0] & 0xff, in[1] & 0xff, in[2] & 0xff);
  2453.       return -1;
  2454.     }
  2455.  
  2456.   return 0;
  2457. }
  2458. #endif NFDTAPE > 0
  2459.