home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / hp300 / stand / scsi.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-07  |  10.7 KB  |  460 lines

  1. /*
  2.  * Copyright (c) 1988 University of Utah.
  3.  * Copyright (c) 1990 The Regents of the University of California.
  4.  * All rights reserved.
  5.  *
  6.  * This code is derived from software contributed to Berkeley by
  7.  * Van Jacobson of Lawrence Berkeley Laboratory and the Systems
  8.  * Programming Group of the University of Utah Computer Science Department.
  9.  *
  10.  * Redistribution and use in source and binary forms, with or without
  11.  * modification, are permitted provided that the following conditions
  12.  * are met:
  13.  * 1. Redistributions of source code must retain the above copyright
  14.  *    notice, this list of conditions and the following disclaimer.
  15.  * 2. Redistributions in binary form must reproduce the above copyright
  16.  *    notice, this list of conditions and the following disclaimer in the
  17.  *    documentation and/or other materials provided with the distribution.
  18.  * 3. All advertising materials mentioning features or use of this software
  19.  *    must display the following acknowledgement:
  20.  *    This product includes software developed by the University of
  21.  *    California, Berkeley and its contributors.
  22.  * 4. Neither the name of the University nor the names of its contributors
  23.  *    may be used to endorse or promote products derived from this software
  24.  *    without specific prior written permission.
  25.  *
  26.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  27.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  28.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  29.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  30.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  31.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  32.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  33.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  34.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  35.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  36.  * SUCH DAMAGE.
  37.  *
  38.  * from: Utah $Hdr: scsi.c 1.3 90/01/27$
  39.  *
  40.  *    @(#)scsi.c    7.4 (Berkeley) 5/7/91
  41.  */
  42.  
  43. /*
  44.  * SCSI bus driver for standalone programs.
  45.  */
  46.  
  47. #include <sys/param.h>
  48. #include <sys/reboot.h>
  49. #include "../dev/device.h"
  50. #include "../dev/scsireg.h"
  51. #include "scsivar.h"
  52.  
  53. #include "saio.h"
  54. #include "samachdep.h"
  55.  
  56. struct    scsi_softc scsi_softc[NSCSI];
  57.  
  58. #define    scsiunit(x)    ((x) >> 3)
  59. #define    scsislave(x)    ((x) & 7)
  60.  
  61. void scsireset();
  62. int scsi_cmd_wait = 500;
  63. int scsi_data_wait = 300000;
  64.  
  65. scsiinit()
  66. {
  67.     extern struct hp_hw sc_table[];
  68.     register struct hp_hw *hw;
  69.     register struct scsi_softc *hs;
  70.     register int i, addr;
  71.     static int first = 1;
  72.     
  73.     i = 0;
  74.     for (hw = sc_table; i < NSCSI && hw < &sc_table[MAXCTLRS]; hw++) {
  75.         if (!HW_ISSCSI(hw))
  76.             continue;
  77.         hs = &scsi_softc[i];
  78.         hs->sc_addr = hw->hw_kva;
  79.         scsireset(i);
  80.         if (howto & RB_ASKNAME)
  81.             printf("scsi%d at sc%d\n", i, hw->hw_sc);
  82.         /*
  83.          * Adjust devtype on first call.  This routine assumes that
  84.          * adaptor is in the high byte of devtype.
  85.          */
  86.         if (first && ((devtype >> 24) & 0xff) == hw->hw_sc) {
  87.             devtype = (devtype & 0x00ffffff) | (i << 24);
  88.             first = 0;
  89.         }
  90.         hs->sc_alive = 1;
  91.         i++;
  92.     }
  93. }
  94.  
  95. scsialive(unit)
  96.     register int unit;
  97. {
  98.     unit = scsiunit(unit);
  99.     if (unit >= NSCSI || scsi_softc[unit].sc_alive == 0)
  100.         return (0);
  101.     return (1);
  102. }
  103.  
  104. void
  105. scsireset(unit)
  106.     register int unit;
  107. {
  108.     volatile register struct scsidevice *hd;
  109.     register struct scsi_softc *hs;
  110.     u_int i;
  111.  
  112.     unit = scsiunit(unit);
  113.     hs = &scsi_softc[unit];
  114.     hd = (struct scsidevice *)hs->sc_addr;
  115.     hd->scsi_id = 0xFF;
  116.     DELAY(100);
  117.     /*
  118.      * Disable interrupts then reset the FUJI chip.
  119.      */
  120.     hd->scsi_csr  = 0;
  121.     hd->scsi_sctl = SCTL_DISABLE | SCTL_CTRLRST;
  122.     hd->scsi_scmd = 0;
  123.     hd->scsi_tmod = 0;
  124.     hd->scsi_pctl = 0;
  125.     hd->scsi_temp = 0;
  126.     hd->scsi_tch  = 0;
  127.     hd->scsi_tcm  = 0;
  128.     hd->scsi_tcl  = 0;
  129.     hd->scsi_ints = 0;
  130.  
  131.     /*
  132.      * Configure the FUJI chip with its SCSI address, all
  133.      * interrupts enabled & appropriate parity.
  134.      */
  135.     i = (~hd->scsi_hconf) & 0x7;
  136.     hs->sc_scsi_addr = 1 << i;
  137.     hd->scsi_bdid = i;
  138.     if (hd->scsi_hconf & HCONF_PARITY)
  139.         hd->scsi_sctl = SCTL_DISABLE | SCTL_ABRT_ENAB |
  140.                 SCTL_SEL_ENAB | SCTL_RESEL_ENAB |
  141.                 SCTL_INTR_ENAB | SCTL_PARITY_ENAB;
  142.     else
  143.         hd->scsi_sctl = SCTL_DISABLE | SCTL_ABRT_ENAB |
  144.                 SCTL_SEL_ENAB | SCTL_RESEL_ENAB |
  145.                 SCTL_INTR_ENAB;
  146.     hd->scsi_sctl &=~ SCTL_DISABLE;
  147. }
  148.  
  149.  
  150. int
  151. scsiabort(hs, hd)
  152.     register struct scsi_softc *hs;
  153.     volatile register struct scsidevice *hd;
  154. {
  155.     printf("scsi error: scsiabort\n");
  156.     return (0);
  157. }
  158.  
  159. static int
  160. issue_select(hd, target, our_addr)
  161.     volatile register struct scsidevice *hd;
  162.     u_char target, our_addr;
  163. {
  164.     if (hd->scsi_ssts & (SSTS_INITIATOR|SSTS_TARGET|SSTS_BUSY))
  165.         return (1);
  166.  
  167.     if (hd->scsi_ints & INTS_DISCON)
  168.         hd->scsi_ints = INTS_DISCON;
  169.  
  170.     hd->scsi_pctl = 0;
  171.     hd->scsi_temp = (1 << target) | our_addr;
  172.     /* select timeout is hardcoded to 2ms */
  173.     hd->scsi_tch = 0;
  174.     hd->scsi_tcm = 32;
  175.     hd->scsi_tcl = 4;
  176.  
  177.     hd->scsi_scmd = SCMD_SELECT;
  178.     return (0);
  179. }
  180.  
  181. static int
  182. wait_for_select(hd)
  183.     volatile register struct scsidevice *hd;
  184. {
  185.     u_char ints;
  186.  
  187.     while ((ints = hd->scsi_ints) == 0)
  188.         DELAY(1);
  189.     hd->scsi_ints = ints;
  190.     return (!(hd->scsi_ssts & SSTS_INITIATOR));
  191. }
  192.  
  193. static int
  194. ixfer_start(hd, len, phase, wait)
  195.     volatile register struct scsidevice *hd;
  196.     int len;
  197.     u_char phase;
  198.     register int wait;
  199. {
  200.  
  201.     hd->scsi_tch = len >> 16;
  202.     hd->scsi_tcm = len >> 8;
  203.     hd->scsi_tcl = len;
  204.     hd->scsi_pctl = phase;
  205.     hd->scsi_tmod = 0; /*XXX*/
  206.     hd->scsi_scmd = SCMD_XFR | SCMD_PROG_XFR;
  207.  
  208.     /* wait for xfer to start or svc_req interrupt */
  209.     while ((hd->scsi_ssts & SSTS_BUSY) == 0) {
  210.         if (hd->scsi_ints || --wait < 0)
  211.             return (0);
  212.         DELAY(1);
  213.     }
  214.     return (1);
  215. }
  216.  
  217. static int
  218. ixfer_out(hd, len, buf)
  219.     volatile register struct scsidevice *hd;
  220.     int len;
  221.     register u_char *buf;
  222. {
  223.     register int wait = scsi_data_wait;
  224.  
  225.     for (; len > 0; --len) {
  226.         while (hd->scsi_ssts & SSTS_DREG_FULL) {
  227.             if (hd->scsi_ints || --wait < 0)
  228.                 return (len);
  229.             DELAY(1);
  230.         }
  231.         hd->scsi_dreg = *buf++;
  232.     }
  233.     return (0);
  234. }
  235.  
  236. static int
  237. ixfer_in(hd, len, buf)
  238.     volatile register struct scsidevice *hd;
  239.     int len;
  240.     register u_char *buf;
  241. {
  242.     register int wait = scsi_data_wait;
  243.  
  244.     for (; len > 0; --len) {
  245.         while (hd->scsi_ssts & SSTS_DREG_EMPTY) {
  246.             if (hd->scsi_ints || --wait < 0) {
  247.                 while (! (hd->scsi_ssts & SSTS_DREG_EMPTY)) {
  248.                     *buf++ = hd->scsi_dreg;
  249.                     --len;
  250.                 }
  251.                 return (len);
  252.             }
  253.             DELAY(1);
  254.         }
  255.         *buf++ = hd->scsi_dreg;
  256.     }
  257.     return (len);
  258. }
  259.  
  260. static int
  261. scsiicmd(hs, target, cbuf, clen, buf, len, xferphase)
  262.     struct scsi_softc *hs;
  263.     int target;
  264.     u_char *cbuf;
  265.     int clen;
  266.     u_char *buf;
  267.     int len;
  268.     u_char xferphase;
  269. {
  270.     volatile register struct scsidevice *hd =
  271.                 (struct scsidevice *)hs->sc_addr;
  272.     int i;
  273.     u_char phase, ints;
  274.     register int wait;
  275.  
  276.     /* select the SCSI bus (it's an error if bus isn't free) */
  277.     if (issue_select(hd, target, hs->sc_scsi_addr))
  278.         return (0);
  279.     if (wait_for_select(hd))
  280.         return (0);
  281.     /*
  282.      * Wait for a phase change (or error) then let the device
  283.      * sequence us through the various SCSI phases.
  284.      */
  285.     phase = CMD_PHASE;
  286.     while (1) {
  287.         wait = scsi_cmd_wait;
  288.         switch (phase) {
  289.  
  290.         case CMD_PHASE:
  291.             if (ixfer_start(hd, clen, phase, wait))
  292.                 if (ixfer_out(hd, clen, cbuf))
  293.                     goto abort;
  294.             phase = xferphase;
  295.             break;
  296.  
  297.         case DATA_IN_PHASE:
  298.             if (len <= 0)
  299.                 goto abort;
  300.             wait = scsi_data_wait;
  301.             if (ixfer_start(hd, len, phase, wait) ||
  302.                 !(hd->scsi_ssts & SSTS_DREG_EMPTY))
  303.                 ixfer_in(hd, len, buf);
  304.             phase = STATUS_PHASE;
  305.             break;
  306.  
  307.         case DATA_OUT_PHASE:
  308.             if (len <= 0)
  309.                 goto abort;
  310.             wait = scsi_data_wait;
  311.             if (ixfer_start(hd, len, phase, wait))
  312.                 if (ixfer_out(hd, len, buf))
  313.                     goto abort;
  314.             phase = STATUS_PHASE;
  315.             break;
  316.  
  317.         case STATUS_PHASE:
  318.             wait = scsi_data_wait;
  319.             if (ixfer_start(hd, sizeof(hs->sc_stat), phase, wait) ||
  320.                 !(hd->scsi_ssts & SSTS_DREG_EMPTY))
  321.                 ixfer_in(hd, sizeof(hs->sc_stat), &hs->sc_stat);
  322.             phase = MESG_IN_PHASE;
  323.             break;
  324.  
  325.         case MESG_IN_PHASE:
  326.             if (ixfer_start(hd, sizeof(hs->sc_msg), phase, wait) ||
  327.                 !(hd->scsi_ssts & SSTS_DREG_EMPTY)) {
  328.                 ixfer_in(hd, sizeof(hs->sc_msg), &hs->sc_msg);
  329.                 hd->scsi_scmd = SCMD_RST_ACK;
  330.             }
  331.             phase = BUS_FREE_PHASE;
  332.             break;
  333.  
  334.         case BUS_FREE_PHASE:
  335.             return (1);
  336.  
  337.         default:
  338.             printf("unexpected scsi phase %d\n", phase);
  339.             goto abort;
  340.         }
  341.         /* wait for last command to complete */
  342.         while ((ints = hd->scsi_ints) == 0) {
  343.             if (--wait < 0)
  344.                 goto abort;
  345.             DELAY(1);
  346.         }
  347.         hd->scsi_ints = ints;
  348.         if (ints & INTS_SRV_REQ)
  349.             phase = hd->scsi_psns & PHASE;
  350.         else if (ints & INTS_DISCON)
  351.             return (1);
  352.         else if ((ints & INTS_CMD_DONE) == 0) {
  353.             goto abort;
  354.         }
  355.     }
  356. abort:
  357.     scsiabort(hs, hd);
  358.     return (0);
  359. }
  360.  
  361. int
  362. scsi_test_unit_rdy(unit)
  363. {
  364.     int ctlr = scsiunit(unit);
  365.     int slave = scsislave(unit);
  366.     register struct scsi_softc *hs = &scsi_softc[ctlr];
  367.     static struct scsi_cdb6 cdb = { CMD_TEST_UNIT_READY };
  368.  
  369.     if (scsiicmd(hs, slave, &cdb, sizeof(cdb), (u_char *)0, 0,
  370.              STATUS_PHASE) == 0)
  371.         return (0);
  372.         
  373.     return (hs->sc_stat == 0);
  374. }
  375.  
  376. int
  377. scsi_request_sense(unit, buf, len)
  378.     int unit;
  379.     u_char *buf;
  380.     unsigned len;
  381. {
  382.     int ctlr = scsiunit(unit);
  383.     int slave = scsislave(unit);
  384.     register struct scsi_softc *hs = &scsi_softc[ctlr];
  385.     static struct scsi_cdb6 cdb = { CMD_REQUEST_SENSE };
  386.  
  387.     cdb.len = len;
  388.     return (scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, DATA_IN_PHASE));
  389. }
  390.  
  391. int
  392. scsi_read_capacity(unit, buf, len)
  393.     int unit;
  394.     u_char *buf;
  395.     unsigned len;
  396. {
  397.     int ctlr = scsiunit(unit);
  398.     int slave = scsislave(unit);
  399.     register struct scsi_softc *hs = &scsi_softc[ctlr];
  400.     static struct scsi_cdb10 cdb = { CMD_READ_CAPACITY };
  401.  
  402.     return (scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, DATA_IN_PHASE));
  403. }
  404.  
  405. int
  406. scsi_tt_read(unit, buf, len, blk, nblk)
  407.     int unit;
  408.     u_char *buf;
  409.     u_int len;
  410.     daddr_t blk;
  411.     u_int nblk;
  412. {
  413.     int ctlr = scsiunit(unit);
  414.     int slave = scsislave(unit);
  415.     register struct scsi_softc *hs = &scsi_softc[ctlr];
  416.     struct scsi_cdb10 cdb;
  417.     int stat;
  418.  
  419.     bzero(&cdb, sizeof(cdb));
  420.     cdb.cmd = CMD_READ_EXT;
  421.     cdb.lbah = blk >> 24;
  422.     cdb.lbahm = blk >> 16;
  423.     cdb.lbalm = blk >> 8;
  424.     cdb.lbal = blk;
  425.     cdb.lenh = nblk >> (8 + DEV_BSHIFT);
  426.     cdb.lenl = nblk >> DEV_BSHIFT;
  427.     stat = scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, DATA_IN_PHASE);
  428.     if (stat == 0)
  429.         return (1);
  430.     return (hs->sc_stat);
  431. }
  432.  
  433. int
  434. scsi_tt_write(unit, buf, len, blk, nblk)
  435.     int unit;
  436.     u_char *buf;
  437.     u_int len;
  438.     daddr_t blk;
  439.     u_int nblk;
  440. {
  441.     int ctlr = scsiunit(unit);
  442.     int slave = scsislave(unit);
  443.     register struct scsi_softc *hs = &scsi_softc[ctlr];
  444.     struct scsi_cdb10 cdb;
  445.     int stat;
  446.  
  447.     bzero(&cdb, sizeof(cdb));
  448.     cdb.cmd = CMD_WRITE_EXT;
  449.     cdb.lbah = blk >> 24;
  450.     cdb.lbahm = blk >> 16;
  451.     cdb.lbalm = blk >> 8;
  452.     cdb.lbal = blk;
  453.     cdb.lenh = nblk >> (8 + DEV_BSHIFT);
  454.     cdb.lenl = nblk >> DEV_BSHIFT;
  455.     stat = scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, DATA_OUT_PHASE);
  456.     if (stat == 0)
  457.         return (1);
  458.     return (hs->sc_stat);
  459. }
  460.