The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/i386/isa/bs/bshw.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NecBSD: bshw.c,v 1.1 1997/07/18 09:19:03 kmatsuda Exp $        */
    2 /*
    3  * [NetBSD for NEC PC98 series]
    4  *  Copyright (c) 1994, 1995, 1996 NetBSD/pc98 porting staff.
    5  *  All rights reserved.
    6  * 
    7  *  Redistribution and use in source and binary forms, with or without
    8  *  modification, are permitted provided that the following conditions
    9  *  are met:
   10  *  1. Redistributions of source code must retain the above copyright
   11  *     notice, this list of conditions and the following disclaimer.
   12  *  2. Redistributions in binary form must reproduce the above copyright
   13  *     notice, this list of conditions and the following disclaimer in the
   14  *     documentation and/or other materials provided with the distribution.
   15  *  3. The name of the author may not be used to endorse or promote products
   16  *     derived from this software without specific prior written permission.
   17  * 
   18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   21  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
   22  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
   24  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   26  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   27  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   28  * POSSIBILITY OF SUCH DAMAGE.
   29  */
   30 /*
   31  * Copyright (c) 1994, 1995, 1996 Naofumi HONDA.  All rights reserved.
   32  *
   33  * $FreeBSD: releng/5.0/sys/i386/isa/bs/bshw.c 92765 2002-03-20 07:51:46Z alfred $
   34  */
   35 
   36 #ifdef  __NetBSD__
   37 #include <dev/isa/isadmareg.h>
   38 #include <i386/Cbus/dev/bs/bsif.h>
   39 #include <i386/Cbus/dev/bs/bshw.lst>
   40 #endif
   41 #ifdef  __FreeBSD__
   42 #include "opt_pc98.h"
   43 #include <dev/ic/i8237.h>
   44 #include <i386/isa/bs/bsif.h>
   45 #include <i386/isa/bs/bshw.lst>
   46 #include <sys/cons.h>
   47 #endif
   48 
   49 static struct bs_softc *gbsc;
   50 
   51 /**************************************************
   52  * DECLARATION
   53  **************************************************/
   54 static void bshw_force_bsmode(struct bs_softc *);
   55 
   56 /**************************************************
   57  * STATIC VAL
   58  **************************************************/
   59 static int irq_tbl[] = { 3, 5, 6, 9, 12, 13 };
   60 
   61 /**************************************************
   62  * SCSI CMD BRANCH
   63  **************************************************/
   64 #define RS      (BSSAT | BSSMIT | BSLINK | BSREAD)
   65 #define WS      (BSSAT | BSSMIT | BSLINK)
   66 #define EOK     (BSERROROK)
   67 
   68 u_int8_t bshw_cmd[256] = {
   69 /*   0  1   2   3   4   5   6   7   8   9   A   B   C   E   D   F */
   70 /**/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,RS ,0  ,WS ,0  ,0  ,0  ,0  ,0  ,
   71 /*1*/0  ,0  ,EOK,0  ,0  ,0  ,0  ,0  ,0  ,0  ,EOK,0  ,0  ,0  ,0  ,0  ,
   72 /*2*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,RS ,0  ,WS ,0  ,0  ,0  ,0  ,0  ,
   73 /*3*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
   74 /*4*/0  ,0  ,EOK,EOK,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
   75 /*5*/0  ,0  ,0  ,0  ,EOK,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
   76 /*6*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
   77 /*7*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
   78 /*8*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
   79 /*9*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
   80 /*A*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
   81 /*B*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
   82 /*C*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
   83 /*D*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
   84 /*E*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
   85 /*F*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
   86 };
   87 
   88 #undef  RS
   89 #undef  WS
   90 #undef  EOK
   91 
   92 /**********************************************
   93  * init
   94  **********************************************/
   95 static void
   96 bshw_force_bsmode(bsc)
   97         struct bs_softc *bsc;
   98 {
   99 
  100         if (bsc->sc_flags & BSBSMODE)
  101                 return;
  102         bsc->sc_flags |= BSBSMODE;
  103 
  104         /*
  105          * If you have memory over 16M, some stupid boards always force to
  106          * use the io polling mode. Check such a case and change mode into
  107          * bus master DMA. However this depends heavily on the board's
  108          * specifications!
  109          */
  110 
  111         if (bsc->sc_hw->dma_init && ((*bsc->sc_hw->dma_init)(bsc)))
  112                 printf("%s change mode using external DMA (%x)\n",
  113                     bsc->sc_dvname, (u_int)read_wd33c93(bsc, 0x37));
  114 }
  115 
  116 #define RESET_DEFAULT   2000
  117 
  118 int
  119 bshw_chip_reset(bsc)
  120         struct bs_softc *bsc;
  121 {
  122         int ct;
  123         u_int8_t aux;
  124 
  125         bshw_lock(bsc);
  126 
  127         bshw_abort_cmd(bsc);
  128         delay(10000);
  129 
  130         bshw_get_auxstat(bsc);
  131         bshw_get_busstat(bsc);
  132 
  133         write_wd33c93(bsc, wd3s_oid, IDR_EHP | bsc->sc_cspeed | bsc->sc_hostid);
  134         write_wd33c93(bsc, wd3s_cmd, WD3S_RESET);
  135 
  136         for (ct = RESET_DEFAULT; ct > 0; ct--)
  137         {
  138                 aux = bshw_get_auxstat(bsc);
  139                 if (aux != 0xff && (aux & STR_INT))
  140                 {
  141                         if (bshw_get_busstat(bsc) == 0)
  142                                 break;
  143 
  144                         write_wd33c93(bsc, wd3s_cmd, WD3S_RESET);
  145                 }
  146                 delay(1);
  147         }
  148 
  149         if (ct == 0)
  150         {
  151                 bshw_unlock(bsc);
  152                 return ENXIO;
  153         }
  154 
  155         bshw_force_bsmode(bsc);
  156 
  157         write_wd33c93(bsc, wd3s_tout, BSHW_SEL_TIMEOUT);
  158         write_wd33c93(bsc, wd3s_sid, SIDR_RESEL);
  159         bsc->sc_flags |= BSDMATRANSFER;
  160         write_wd33c93(bsc, wd3s_ctrl, CR_DEFAULT);
  161         write_wd33c93(bsc, wd3s_synch, 0);
  162 
  163         bshw_get_auxstat(bsc);
  164         bsc->sc_busstat = bshw_get_busstat(bsc);
  165         bshw_unlock(bsc);
  166 
  167         return 0;
  168 }
  169 
  170 /* scsi bus hard reset */
  171 #define TWIDDLEWAIT     10000
  172 static int tw_pos;
  173 static char tw_chars[] = "|/-\\";
  174 
  175 /* this is some jokes */
  176 static void
  177 twiddle_wait(void)
  178 {
  179 
  180         cnputc('\b');
  181         cnputc(tw_chars[tw_pos++]);
  182         tw_pos %= (sizeof(tw_chars) - 1);
  183         delay(TWIDDLEWAIT);
  184 }
  185 
  186 static void bshw_set_vsp(struct bs_softc *, u_int, u_int8_t);
  187 
  188 static void
  189 bshw_set_vsp(bsc, chan, spva)
  190         struct bs_softc *bsc;
  191         u_int chan;
  192         u_int8_t spva;
  193 {
  194         struct bshw *hw = bsc->sc_hw;
  195 
  196         if (hw->sregaddr == 0)
  197                 return;
  198 
  199         write_wd33c93(bsc, hw->sregaddr + chan, spva);
  200         if (hw->hw_flags & BSHW_DOUBLE_DMACHAN)
  201                 write_wd33c93(bsc, hw->sregaddr + chan + 8, spva);
  202 }
  203 
  204 void
  205 bshw_bus_reset(bsc)
  206         struct bs_softc *bsc;
  207 {
  208         struct targ_info *ti;
  209         int i, lpc;
  210 
  211         if (bsc->sc_RSTdelay == 0)
  212                 bsc->sc_RSTdelay = 6 * 1000 * 1000;
  213         else
  214         {
  215                 /* XXX:
  216                  * second time reset will be requested by hardware failuer.
  217                  */
  218                 bsc->sc_RSTdelay = 12 * 1000 * 1000;
  219         }
  220 
  221         bshw_lock(bsc);
  222         write_wd33c93(bsc, wd3s_mbank, (bsc->sc_membank | MBR_RST) & ~MBR_IEN);
  223         delay(500000);
  224         write_wd33c93(bsc, wd3s_mbank, (bsc->sc_membank) & ~MBR_IEN);
  225         bshw_unlock(bsc);
  226 
  227         for (lpc = 0; lpc < 2; lpc ++)
  228         {
  229                 cnputc(' ');
  230                 for (i = 0; i <= bsc->sc_RSTdelay / TWIDDLEWAIT; i++)
  231                         twiddle_wait();
  232                 cnputc('\b');
  233 
  234                 (void) read_wd33c93(bsc, wd3s_auxc);
  235 
  236                 delay(10000);
  237 
  238                 if ((read_wd33c93(bsc, wd3s_auxc) & AUXCR_RRST) == 0)
  239                         break;
  240 
  241                 printf("\nreset state still continue, wait ...");
  242         }
  243 
  244         for (i = 0; i < NTARGETS; i++)
  245         {
  246                 if ((ti = bsc->sc_ti[i]) != NULL)
  247                 {
  248                         ti->ti_sync = 0;
  249                         bshw_set_vsp(bsc, i, 0);
  250                 }
  251         }
  252 }
  253 
  254 /* probe */
  255 int
  256 bshw_board_probe(bsc, drq, irq)
  257         struct bs_softc *bsc;
  258         u_int *drq;
  259         u_int *irq;
  260 {
  261 
  262         gbsc = bsc;
  263 #ifdef  SHOW_PORT
  264         bshw_print_port(bsc);
  265 #endif  /* SHOW_PORT */
  266 
  267         bsc->sc_hostid = (read_wd33c93(bsc, wd3s_auxc) & AUXCR_HIDM);
  268 
  269         if ((*irq) == IRQUNK)
  270                 *irq = irq_tbl[(read_wd33c93(bsc, wd3s_auxc) >> 3) & 7];
  271 
  272         if ((*drq) == DRQUNK)
  273                 *drq = BUS_IOR(cmd_port) & 3;
  274 
  275         bsc->sc_dmachan = *drq;
  276         bsc->sc_irq = (*irq);
  277 
  278         bsc->sc_membank = read_wd33c93(bsc, wd3s_mbank);
  279         bsc->sc_membank &= ~MBR_RST;
  280         bsc->sc_membank |= MBR_IEN;
  281 
  282         bsc->sc_cspeed = (read_wd33c93(bsc, wd3s_oid) & (~IDR_IDM));
  283         switch (BSC_CHIP_CLOCK(bsc->sc_cfgflags))
  284         {
  285         case 0:
  286                 break;
  287 
  288         case 1:
  289                 bsc->sc_cspeed &= ~(IDR_FS_12_15 | IDR_FS_16_20);
  290                 break;
  291 
  292         case 2:
  293                 bsc->sc_cspeed &= ~(IDR_FS_12_15 | IDR_FS_16_20);
  294                 bsc->sc_cspeed |= IDR_FS_12_15;
  295                 break;
  296 
  297         case 3:
  298                 bsc->sc_cspeed &= ~(IDR_FS_12_15 | IDR_FS_16_20);
  299                 bsc->sc_cspeed |= IDR_FS_16_20;
  300                 break;
  301         }
  302 
  303         /* XXX: host id fixed(7) */
  304         bsc->sc_hostid = 7;
  305 
  306         if (bshw_chip_reset(bsc))
  307                 return ENXIO;
  308 
  309         return 0;
  310 }
  311 
  312 /*
  313  * XXX:
  314  * Assume the board clock rate must be 20Mhz (always satisfied, maybe)!
  315  * Only 10M/s 6.6M/s 5.0M/s 3.3M/s for synchronus transfer speed set.
  316  */
  317 #define ILLEGAL_SYNCH
  318 #ifdef  ILLEGAL_SYNCH
  319 /*  A  10    6.6   5.0   4.0   3.3   2.8   2.5   2.0  M/s */
  320 /*  X  100   150   200   250   300   350   400   500  ns  */
  321 static u_int bshw_scsi_period[] =
  322    {0, 25,   37,   50,   62,   75,   87,   100,  125};
  323 static u_int8_t bshw_chip_pval[] =
  324    {0, 0xa0, 0xb0, 0x20, 0xd0, 0x30, 0xf0, 0x40, 0x50};
  325 #else   /* !ILLEGAL_SYNCH */
  326 /*  A  10    6.6   5.0   3.3   2.5 M/s */
  327 /*  X  100   150   200   300   400 ns  */
  328 static u_int bshw_scsi_period[] =
  329    {0, 25,   37,   50,   75,   100};
  330 static u_int8_t bshw_chip_pval[] =
  331    {0, 0xa0, 0xb0, 0x20, 0x30, 0x40};
  332 #endif  /* !ILLEGAL_SYNCH */
  333 
  334 void
  335 bshw_adj_syncdata(sdp)
  336         struct syncdata *sdp;
  337 {
  338         int i;
  339 
  340         if (sdp->offset == 0 || sdp->period < 25 || sdp->period > 100)
  341                 sdp->offset = sdp->period = 0;
  342         else
  343         {
  344                 for (i = 0; sdp->period > bshw_scsi_period[i] + 2; i ++)
  345                         ;
  346                 sdp->period = bshw_scsi_period[i];
  347         }
  348 }
  349 
  350 void
  351 bshw_set_synchronous(bsc, ti)
  352         struct bs_softc *bsc;
  353         struct targ_info *ti;
  354 {
  355         struct syncdata sd;
  356         int i;
  357 
  358         sd = ti->ti_syncnow;
  359         bshw_adj_syncdata(&sd);
  360         for (i = 0; sd.period != bshw_scsi_period[i]; i++)
  361                 ;
  362 
  363         ti->ti_sync = ((sd.offset & 0x0f) | bshw_chip_pval[i]);
  364         bshw_set_vsp(bsc, ti->ti_id, ti->ti_sync);
  365 
  366         if (bsc->sc_nexus == ti)
  367                 bshw_set_sync_reg(bsc, ti->ti_sync);
  368 }
  369 
  370 /* ctrl reg */
  371 void
  372 bshw_setup_ctrl_reg(bsc, flags)
  373         struct bs_softc *bsc;
  374         u_int flags;
  375 {
  376         u_int8_t regval;
  377 
  378         regval = (flags & BS_SCSI_NOPARITY) ? CR_DEFAULT : CR_DEFAULT_HP;
  379         if (bsc->sc_flags & BSDMATRANSFER)
  380                 regval |= CR_DMA;
  381         write_wd33c93(bsc, wd3s_ctrl, regval);
  382 }
  383 
  384 /* sat command */
  385 void
  386 bshw_issue_satcmd(bsc, cb, link)
  387         struct bs_softc *bsc;
  388         struct bsccb *cb;
  389         int link;
  390 {
  391         int i;
  392 
  393         BUS_IOW(addr_port, wd3s_cdb);
  394         for (i = 0; i < cb->cmdlen - 1; i++)
  395                 BUS_IOW(ctrl_port, cb->cmd[i]);
  396         BUS_IOW(ctrl_port, cb->cmd[i] | (link ? 1 : 0));
  397 }
  398 
  399 /* lock */
  400 void
  401 bshw_lock(bsc)
  402         struct bs_softc *bsc;
  403 {
  404 
  405         bsc->sc_hwlock++;
  406         write_wd33c93(bsc, wd3s_mbank, bsc->sc_membank & (~MBR_IEN));
  407 }
  408 
  409 void
  410 bshw_unlock(bsc)
  411         struct bs_softc *bsc;
  412 {
  413 
  414         if ((--bsc->sc_hwlock) <= 0)
  415                 write_wd33c93(bsc, wd3s_mbank, bsc->sc_membank);
  416 }
  417 
  418 /**********************************************
  419  * DMA OPERATIONS
  420  **********************************************/
  421 #ifdef  __NetBSD__
  422 #include <i386/Cbus/dev/bs/bshw_dma.c>
  423 #include <i386/Cbus/dev/bs/bshw_pdma.c>
  424 #endif
  425 #ifdef  __FreeBSD__
  426 #include <i386/isa/bs/bshw_dma.c>
  427 #include <i386/isa/bs/bshw_pdma.c>
  428 #endif
  429 
  430 /**********************************************
  431  * DEBUG
  432  **********************************************/
  433 /* misc */
  434 void
  435 bshw_print_port(bsc)
  436         struct bs_softc * bsc;
  437 {
  438         int i, j;
  439         int port = 0x0;
  440 
  441         if (bsc == NULL)
  442                 bsc = gbsc;
  443 
  444         printf("\n");
  445         for (j = 0; j <= 0x70; j += 0x10)
  446         {
  447                 printf("port %x: ", port);
  448                 for (i = 0; i < 0x10; i++)
  449                         printf("%x ", (u_int) read_wd33c93(bsc, port++));
  450                 printf("\n");
  451         }
  452 }

Cache object: 03adf88aca79c9767074c1e85a17e7b2


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.