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/dev/ct/bshw_machdep.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 /* $FreeBSD: releng/5.0/sys/dev/ct/bshw_machdep.c 92739 2002-03-20 02:08:01Z alfred $ */
    2 /*      $NecBSD: bshw_machdep.c,v 1.8.12.6 2001/06/29 06:28:05 honda Exp $      */
    3 /*      $NetBSD$        */
    4 
    5 /*
    6  * [NetBSD for NEC PC-98 series]
    7  *  Copyright (c) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
    8  *      NetBSD/pc98 porting staff. All rights reserved.
    9  * 
   10  *  Copyright (c) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
   11  *      Naofumi HONDA.  All rights reserved.
   12  *
   13  *  Redistribution and use in source and binary forms, with or without
   14  *  modification, are permitted provided that the following conditions
   15  *  are met:
   16  *  1. Redistributions of source code must retain the above copyright
   17  *     notice, this list of conditions and the following disclaimer.
   18  *  2. Redistributions in binary form must reproduce the above copyright
   19  *     notice, this list of conditions and the following disclaimer in the
   20  *     documentation and/or other materials provided with the distribution.
   21  *  3. The name of the author may not be used to endorse or promote products
   22  *     derived from this software without specific prior written permission.
   23  * 
   24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   26  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   27  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
   28  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   29  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
   30  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   32  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   33  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   34  * POSSIBILITY OF SUCH DAMAGE.
   35  */
   36 
   37 #include "opt_ddb.h"
   38 
   39 #include <sys/param.h>
   40 #include <sys/systm.h>
   41 #include <sys/kernel.h>
   42 #if defined(__FreeBSD__) && __FreeBSD_version > 500001
   43 #include <sys/bio.h>
   44 #endif  /* __ FreeBSD__ */
   45 #include <sys/buf.h>
   46 #include <sys/queue.h>
   47 #include <sys/malloc.h>
   48 #include <sys/errno.h>
   49 
   50 #include <vm/vm.h>
   51 
   52 #ifdef __NetBSD__
   53 #include <sys/device.h>
   54 
   55 #include <machine/bus.h>
   56 #include <machine/intr.h>
   57 
   58 #include <dev/scsipi/scsi_all.h>
   59 #include <dev/scsipi/scsipi_all.h>
   60 #include <dev/scsipi/scsiconf.h>
   61 #include <dev/scsipi/scsi_disk.h>
   62 
   63 #include <machine/dvcfg.h>
   64 #include <machine/physio_proc.h>
   65 
   66 #include <i386/Cbus/dev/scsi_low.h>
   67 
   68 #include <dev/ic/wd33c93reg.h>
   69 #include <i386/Cbus/dev/ct/ctvar.h>
   70 #include <i386/Cbus/dev/ct/ct_machdep.h>
   71 #include <i386/Cbus/dev/ct/bshwvar.h>
   72 #endif /* __NetBSD__ */
   73 
   74 #ifdef __FreeBSD__
   75 #include <machine/bus.h>
   76 #include <machine/clock.h>
   77 #include <machine/md_var.h>
   78 
   79 #include <machine/dvcfg.h>
   80 #include <machine/physio_proc.h>
   81 
   82 #include <cam/scsi/scsi_low.h>
   83 
   84 #include <dev/ic/wd33c93reg.h>
   85 #include <dev/ct/ctvar.h>
   86 #include <dev/ct/ct_machdep.h>
   87 #include <dev/ct/bshwvar.h>
   88 
   89 #include <vm/pmap.h>
   90 #endif /* __FreeBSD__ */
   91 
   92 #define BSHW_IO_CONTROL_FLAGS   0
   93 
   94 u_int bshw_io_control = BSHW_IO_CONTROL_FLAGS;
   95 int bshw_data_read_bytes = 4096;
   96 int bshw_data_write_bytes = 4096;
   97 
   98 /*********************************************************
   99  * OS dep part
  100  *********************************************************/
  101 #ifdef  __NetBSD__
  102 #define BSHW_PAGE_SIZE NBPG
  103 #endif  /* __NetBSD__ */
  104 
  105 #ifdef  __FreeBSD__
  106 #define BSHW_PAGE_SIZE PAGE_SIZE
  107 typedef unsigned long vaddr_t;
  108 #endif /* __FreeBSD__ */
  109 
  110 /*********************************************************
  111  * GENERIC MACHDEP FUNCTIONS
  112  *********************************************************/
  113 void
  114 bshw_synch_setup(ct, ti)
  115         struct ct_softc *ct;
  116         struct targ_info *ti;
  117 {
  118         struct ct_bus_access_handle *chp = &ct->sc_ch;
  119         struct ct_targ_info *cti = (void *) ti;
  120         struct bshw_softc *bs = ct->ct_hw;
  121         struct bshw *hw = bs->sc_hw;
  122 
  123         if (hw->hw_sregaddr == 0)
  124                 return;
  125 
  126         ct_cr_write_1(chp, hw->hw_sregaddr + ti->ti_id, cti->cti_syncreg);
  127         if (hw->hw_flags & BSHW_DOUBLE_DMACHAN)
  128         {
  129                 ct_cr_write_1(chp, hw->hw_sregaddr + ti->ti_id + 8, 
  130                               cti->cti_syncreg);
  131         }
  132 }
  133 
  134 void
  135 bshw_bus_reset(ct)
  136         struct ct_softc *ct;
  137 {
  138         struct scsi_low_softc *slp = &ct->sc_sclow;
  139         struct ct_bus_access_handle *chp = &ct->sc_ch;
  140         struct bshw_softc *bs = ct->ct_hw;
  141         struct bshw *hw = bs->sc_hw;
  142         bus_addr_t offs;
  143         u_int8_t regv;
  144         int i;
  145 
  146         /* open hardware busmaster mode */
  147         if (hw->hw_dma_init != NULL && ((*hw->hw_dma_init)(ct)) != 0)
  148         {
  149                 printf("%s: change mode using external DMA (%x)\n",
  150                     slp->sl_xname, (u_int)ct_cr_read_1(chp, 0x37));
  151         }
  152 
  153         /* clear hardware synch registers */
  154         offs = hw->hw_sregaddr;
  155         if (offs != 0)
  156         {
  157                 for (i = 0; i < 8; i ++, offs ++)
  158                 {
  159                         ct_cr_write_1(chp, offs, 0);
  160                         if ((hw->hw_flags & BSHW_DOUBLE_DMACHAN) != 0)
  161                                 ct_cr_write_1(chp, offs + 8, 0);
  162                 }
  163         }
  164 
  165         /* disable interrupt & assert reset */
  166         regv = ct_cr_read_1(chp, wd3s_mbank);
  167         regv |= MBR_RST;
  168         regv &= ~MBR_IEN;
  169         ct_cr_write_1(chp, wd3s_mbank, regv);
  170 
  171         SCSI_LOW_DELAY(500000);
  172 
  173         /* reset signal off */
  174         regv &= ~MBR_RST;
  175         ct_cr_write_1(chp, wd3s_mbank, regv);
  176 
  177         /* interrupt enable */
  178         regv |= MBR_IEN;
  179         ct_cr_write_1(chp, wd3s_mbank, regv);
  180 }
  181 
  182 /* probe */
  183 int
  184 bshw_read_settings(chp, bs)
  185         struct ct_bus_access_handle *chp;
  186         struct bshw_softc *bs;
  187 {
  188         static int irq_tbl[] = { 3, 5, 6, 9, 12, 13 };
  189 
  190         bs->sc_hostid = (ct_cr_read_1(chp, wd3s_auxc) & AUXCR_HIDM);
  191         bs->sc_irq = irq_tbl[(ct_cr_read_1(chp, wd3s_auxc) >> 3) & 7];
  192         bs->sc_drq = ct_cmdp_read_1(chp) & 3;
  193         return 0;
  194 }
  195 
  196 /*********************************************************
  197  * DMA PIO TRANSFER (SMIT)
  198  *********************************************************/
  199 #define LC_SMIT_TIMEOUT 2       /* 2 sec: timeout for a fifo status ready */
  200 #define LC_SMIT_OFFSET  0x1000
  201 #define LC_FSZ          DEV_BSIZE
  202 #define LC_SFSZ         0x0c
  203 #define LC_REST         (LC_FSZ - LC_SFSZ)
  204 
  205 #define BSHW_LC_FSET    0x36
  206 #define BSHW_LC_FCTRL   0x44
  207 #define FCTRL_EN        0x01
  208 #define FCTRL_WRITE     0x02
  209 
  210 #define SF_ABORT        0x08
  211 #define SF_RDY          0x10
  212 
  213 static __inline void bshw_lc_smit_start(struct ct_softc *, int, u_int);
  214 static __inline void bshw_lc_smit_stop(struct ct_softc *);
  215 static int bshw_lc_smit_fstat(struct ct_softc *, int, int);
  216 
  217 static __inline void
  218 bshw_lc_smit_stop(ct)
  219         struct ct_softc *ct;
  220 {
  221         struct ct_bus_access_handle *chp = &ct->sc_ch;
  222 
  223         ct_cr_write_1(chp, BSHW_LC_FCTRL, 0);
  224         ct_cmdp_write_1(chp, CMDP_DMER);
  225 }
  226 
  227 static __inline void
  228 bshw_lc_smit_start(ct, count, direction)
  229         struct ct_softc *ct;
  230         int count;
  231         u_int direction;
  232 {
  233         struct ct_bus_access_handle *chp = &ct->sc_ch;
  234         u_int8_t pval, val;
  235 
  236         val = ct_cr_read_1(chp, BSHW_LC_FSET);
  237         cthw_set_count(chp, count);
  238 
  239         pval = FCTRL_EN;
  240         if (direction == SCSI_LOW_WRITE)
  241                 pval |= (val & 0xe0) | FCTRL_WRITE;
  242         ct_cr_write_1(chp, BSHW_LC_FCTRL, pval);
  243         ct_cr_write_1(chp, wd3s_cmd, WD3S_TFR_INFO);
  244 }
  245 
  246 static int
  247 bshw_lc_smit_fstat(ct, wc, read)
  248         struct ct_softc *ct;
  249         int wc, read;
  250 {
  251         struct ct_bus_access_handle *chp = &ct->sc_ch;
  252         u_int8_t stat;
  253 
  254         while (wc -- > 0)
  255         {
  256                 chp->ch_bus_weight(chp);
  257                 stat = ct_cmdp_read_1(chp);
  258                 if (read == SCSI_LOW_READ)
  259                 {
  260                         if ((stat & SF_RDY) != 0)
  261                                 return 0;
  262                         if ((stat & SF_ABORT) != 0)
  263                                 return EIO;
  264                 }
  265                 else
  266                 {
  267                         if ((stat & SF_ABORT) != 0)
  268                                 return EIO;
  269                         if ((stat & SF_RDY) != 0)
  270                                 return 0;
  271                 }
  272         }
  273 
  274         printf("%s: SMIT fifo status timeout\n", ct->sc_sclow.sl_xname);
  275         return EIO;
  276 }
  277 
  278 void
  279 bshw_smit_xfer_stop(ct)
  280         struct ct_softc *ct;
  281 {
  282         struct scsi_low_softc *slp = &ct->sc_sclow;
  283         struct bshw_softc *bs = ct->ct_hw;
  284         struct targ_info *ti;
  285         struct sc_p *sp = &slp->sl_scp;
  286         u_int count;
  287 
  288         bshw_lc_smit_stop(ct);
  289 
  290         ti = slp->sl_Tnexus;
  291         if (ti == NULL)
  292                 return;
  293 
  294         if (ti->ti_phase == PH_DATA)
  295         {
  296                 count = cthw_get_count(&ct->sc_ch);
  297                 if (count < bs->sc_sdatalen)
  298                 {
  299                         if (sp->scp_direction == SCSI_LOW_READ &&
  300                             count != bs->sc_edatalen)
  301                                 goto bad;
  302 
  303                         count = bs->sc_sdatalen - count;
  304                         if (count > (u_int) sp->scp_datalen)
  305                                 goto bad;
  306 
  307                         sp->scp_data += count;
  308                         sp->scp_datalen -= count;
  309                 }
  310                 else if (count > bs->sc_sdatalen)
  311                 {
  312 bad:
  313                         printf("%s: smit_xfer_end: cnt error\n", slp->sl_xname);
  314                         slp->sl_error |= PDMAERR;
  315                 }
  316                 scsi_low_data_finish(slp);
  317         }
  318         else
  319         {
  320                 printf("%s: smit_xfer_end: phase miss\n", slp->sl_xname);
  321                 slp->sl_error |= PDMAERR;
  322         }
  323 }
  324 
  325 int
  326 bshw_smit_xfer_start(ct)
  327         struct ct_softc *ct;
  328 {
  329         struct scsi_low_softc *slp = &ct->sc_sclow;
  330         struct ct_bus_access_handle *chp = &ct->sc_ch;
  331         struct bshw_softc *bs = ct->ct_hw;
  332         struct sc_p *sp = &slp->sl_scp;
  333         struct targ_info *ti = slp->sl_Tnexus;
  334         struct ct_targ_info *cti = (void *) ti;
  335         u_int datalen, count, io_control;
  336         int wc;
  337         u_int8_t *data;
  338 
  339         io_control = bs->sc_io_control | bshw_io_control;
  340         if ((io_control & BSHW_SMIT_BLOCK) != 0)
  341                 return EINVAL;
  342 
  343         if ((slp->sl_scp.scp_datalen % DEV_BSIZE) != 0)
  344                 return EINVAL;
  345 
  346         datalen = sp->scp_datalen;
  347         if (slp->sl_scp.scp_direction == SCSI_LOW_READ)
  348         {
  349                 if ((io_control & BSHW_READ_INTERRUPT_DRIVEN) != 0 &&
  350                      datalen > bshw_data_read_bytes)
  351                         datalen = bshw_data_read_bytes;
  352         }
  353         else 
  354         {
  355                 if ((io_control & BSHW_WRITE_INTERRUPT_DRIVEN) != 0 &&
  356                     datalen > bshw_data_write_bytes)
  357                         datalen = bshw_data_write_bytes;
  358         }
  359 
  360         bs->sc_sdatalen = datalen;
  361         data = sp->scp_data;
  362         wc = LC_SMIT_TIMEOUT * 1024 * 1024;
  363 
  364         ct_cr_write_1(chp, wd3s_ctrl, ct->sc_creg | CR_DMA);
  365         bshw_lc_smit_start(ct, datalen, sp->scp_direction);
  366 
  367         if (sp->scp_direction == SCSI_LOW_READ)
  368         {
  369                 do
  370                 {
  371                         if (bshw_lc_smit_fstat(ct, wc, SCSI_LOW_READ))
  372                                 break;
  373 
  374                         count = (datalen > LC_FSZ ? LC_FSZ : datalen);
  375                         bus_space_read_region_4(chp->ch_memt, chp->ch_memh,
  376                                 LC_SMIT_OFFSET, (u_int32_t *) data, count >> 2);
  377                         data += count;
  378                         datalen -= count;
  379                 }
  380                 while (datalen > 0);
  381 
  382                 bs->sc_edatalen = datalen;
  383         }
  384         else
  385         {
  386                 do
  387                 {
  388                         if (bshw_lc_smit_fstat(ct, wc, SCSI_LOW_WRITE))
  389                                 break;
  390                         if (cti->cti_syncreg == 0)
  391                         {
  392                                 /* XXX:
  393                                  * If async transfer, reconfirm a scsi phase
  394                                  * again. Unless C bus might hang up.
  395                                  */
  396                                 if (bshw_lc_smit_fstat(ct, wc, SCSI_LOW_WRITE))
  397                                         break;
  398                         }
  399 
  400                         count = (datalen > LC_SFSZ ? LC_SFSZ : datalen);
  401                         bus_space_write_region_4(chp->ch_memt, chp->ch_memh,
  402                                 LC_SMIT_OFFSET, (u_int32_t *) data, count >> 2);
  403                         data += count;
  404                         datalen -= count;
  405 
  406                         if (bshw_lc_smit_fstat(ct, wc, SCSI_LOW_WRITE))
  407                                 break;
  408 
  409                         count = (datalen > LC_REST ? LC_REST : datalen);
  410                         bus_space_write_region_4(chp->ch_memt, chp->ch_memh,
  411                                                  LC_SMIT_OFFSET + LC_SFSZ, 
  412                                                  (u_int32_t *) data, count >> 2);
  413                         data += count;
  414                         datalen -= count;
  415                 }
  416                 while (datalen > 0);
  417         }
  418         return 0;
  419 }
  420 
  421 /*********************************************************
  422  * DMA TRANSFER (BS)
  423  *********************************************************/
  424 static __inline void bshw_dma_write_1 \
  425         (struct ct_bus_access_handle *, bus_addr_t, u_int8_t);
  426 static void bshw_dmastart(struct ct_softc *);
  427 static void bshw_dmadone(struct ct_softc *);
  428 
  429 int
  430 bshw_dma_xfer_start(ct)
  431         struct ct_softc *ct;
  432 {
  433         struct scsi_low_softc *slp = &ct->sc_sclow;
  434         struct sc_p *sp = &slp->sl_scp;
  435         struct ct_bus_access_handle *chp = &ct->sc_ch;
  436         struct bshw_softc *bs = ct->ct_hw;
  437         vaddr_t va, endva, phys, nphys;
  438         u_int io_control;
  439 
  440         io_control = bs->sc_io_control | bshw_io_control;
  441         if ((io_control & BSHW_DMA_BLOCK) != 0 && sp->scp_datalen < 256)
  442                 return EINVAL;
  443 
  444         ct_cr_write_1(chp, wd3s_ctrl, ct->sc_creg | CR_DMA);
  445         phys = vtophys((vaddr_t) sp->scp_data);
  446         if (phys >= bs->sc_minphys)
  447         {
  448                 /* setup segaddr */
  449                 bs->sc_segaddr = bs->sc_bounce_phys;
  450                 /* setup seglen */
  451                 bs->sc_seglen = sp->scp_datalen;
  452                 if (bs->sc_seglen > bs->sc_bounce_size)
  453                         bs->sc_seglen = bs->sc_bounce_size;
  454                 /* setup bufp */
  455                 bs->sc_bufp = bs->sc_bounce_addr;
  456                 if (sp->scp_direction == SCSI_LOW_WRITE)
  457                         bcopy(sp->scp_data, bs->sc_bufp, bs->sc_seglen);
  458         }
  459         else
  460         {
  461                 /* setup segaddr */
  462                 bs->sc_segaddr = (u_int8_t *) phys;
  463                 /* setup seglen */
  464                 endva = (vaddr_t) round_page((vaddr_t) sp->scp_data + sp->scp_datalen);
  465                 for (va = (vaddr_t) sp->scp_data; ; phys = nphys)
  466                 {
  467                         if ((va += BSHW_PAGE_SIZE) >= endva)
  468                         {
  469                                 bs->sc_seglen = sp->scp_datalen;
  470                                 break;
  471                         }
  472 
  473                         nphys = vtophys(va);
  474                         if (phys + BSHW_PAGE_SIZE != nphys || nphys >= bs->sc_minphys)
  475                         {
  476                                 bs->sc_seglen =
  477                                     (u_int8_t *) trunc_page(va) - sp->scp_data;
  478                                 break;
  479                         }
  480                 }
  481                 /* setup bufp */
  482                 bs->sc_bufp = NULL;
  483         }
  484 
  485         bshw_dmastart(ct);
  486         cthw_set_count(chp, bs->sc_seglen);
  487         ct_cr_write_1(chp, wd3s_cmd, WD3S_TFR_INFO);
  488         return 0;
  489 }
  490 
  491 void
  492 bshw_dma_xfer_stop(ct)
  493         struct ct_softc *ct;
  494 {
  495         struct scsi_low_softc *slp = &ct->sc_sclow;
  496         struct sc_p *sp = &slp->sl_scp;
  497         struct bshw_softc *bs = ct->ct_hw;
  498         struct targ_info *ti;
  499         u_int count, transbytes;
  500 
  501         bshw_dmadone(ct);
  502 
  503         ti = slp->sl_Tnexus;
  504         if (ti == NULL)
  505                 return;
  506 
  507         if (ti->ti_phase == PH_DATA)
  508         {
  509                 count = cthw_get_count(&ct->sc_ch);
  510                 if (count < (u_int) bs->sc_seglen)
  511                 {
  512                         transbytes = bs->sc_seglen - count;
  513                         if (bs->sc_bufp != NULL &&
  514                             sp->scp_direction == SCSI_LOW_READ)
  515                                 bcopy(bs->sc_bufp, sp->scp_data, transbytes);
  516 
  517                         sp->scp_data += transbytes;
  518                         sp->scp_datalen -= transbytes;
  519                 }
  520                 else if (count > (u_int) bs->sc_seglen)
  521                 {
  522                         printf("%s: port data %x != seglen %x\n",
  523                                 slp->sl_xname, count, bs->sc_seglen);
  524                         slp->sl_error |= PDMAERR;
  525                 }
  526 
  527                 scsi_low_data_finish(slp);
  528         }
  529         else
  530         {
  531                 printf("%s: extra DMA interrupt\n", slp->sl_xname);
  532                 slp->sl_error |= PDMAERR;
  533         }
  534 
  535         bs->sc_bufp = NULL;
  536 }
  537 
  538 /* common dma settings */
  539 #undef  DMA1_SMSK
  540 #define DMA1_SMSK       (0x15)
  541 #undef  DMA1_MODE
  542 #define DMA1_MODE       (0x17)
  543 #undef  DMA1_FFC
  544 #define DMA1_FFC        (0x19)
  545 #undef  DMA1_CHN
  546 #define DMA1_CHN(c)     (0x01 + ((c) << 2))
  547 
  548 #define DMA37SM_SET     0x04
  549 #define DMA37MD_WRITE   0x04
  550 #define DMA37MD_READ    0x08
  551 #define DMA37MD_SINGLE  0x40
  552 
  553 static bus_addr_t dmapageport[4] = { 0x27, 0x21, 0x23, 0x25 };
  554 
  555 static __inline void 
  556 bshw_dma_write_1(chp, port, val)
  557         struct ct_bus_access_handle *chp;
  558         bus_addr_t port;
  559         u_int8_t val;
  560 {
  561 
  562         CT_BUS_WEIGHT(chp);
  563         outb(port, val);
  564 }
  565 
  566 static void
  567 bshw_dmastart(ct)
  568         struct ct_softc *ct;
  569 {
  570         struct scsi_low_softc *slp = &ct->sc_sclow;
  571         struct bshw_softc *bs = ct->ct_hw;
  572         struct ct_bus_access_handle *chp = &ct->sc_ch;
  573         int chan = bs->sc_drq;
  574         bus_addr_t waport;
  575         u_int8_t regv, *phys = bs->sc_segaddr;
  576         u_int nbytes = bs->sc_seglen;
  577 
  578         /* flush cpu cache */
  579         (*bs->sc_dmasync_before) (ct);
  580 
  581         /*
  582          * Program one of DMA channels 0..3. These are
  583          * byte mode channels.
  584          */
  585         /* set dma channel mode, and reset address ff */
  586 
  587         if (slp->sl_scp.scp_direction == SCSI_LOW_READ)
  588                 regv = DMA37MD_WRITE | DMA37MD_SINGLE | chan;
  589         else
  590                 regv = DMA37MD_READ | DMA37MD_SINGLE | chan;
  591 
  592         bshw_dma_write_1(chp, DMA1_MODE, regv);
  593         bshw_dma_write_1(chp, DMA1_FFC, 0);
  594 
  595         /* send start address */
  596         waport = DMA1_CHN(chan);
  597         bshw_dma_write_1(chp, waport, (u_int) phys);
  598         bshw_dma_write_1(chp, waport, ((u_int) phys) >> 8);
  599         bshw_dma_write_1(chp, dmapageport[chan], ((u_int) phys) >> 16);
  600 
  601         /* send count */
  602         bshw_dma_write_1(chp, waport + 2, --nbytes);
  603         bshw_dma_write_1(chp, waport + 2, nbytes >> 8);
  604 
  605         /* vendor unique hook */
  606         if (bs->sc_hw->hw_dma_start)
  607                 (*bs->sc_hw->hw_dma_start)(ct);
  608 
  609         bshw_dma_write_1(chp, DMA1_SMSK, chan);
  610         ct_cmdp_write_1(chp, CMDP_DMES);
  611 }
  612 
  613 static void
  614 bshw_dmadone(ct)
  615         struct ct_softc *ct;
  616 {
  617         struct bshw_softc *bs = ct->ct_hw;
  618         struct ct_bus_access_handle *chp = &ct->sc_ch;
  619 
  620         bshw_dma_write_1(chp, DMA1_SMSK, (bs->sc_drq | DMA37SM_SET));
  621         ct_cmdp_write_1(chp, CMDP_DMER);
  622 
  623         /* vendor unique hook */
  624         if (bs->sc_hw->hw_dma_stop)
  625                 (*bs->sc_hw->hw_dma_stop) (ct);
  626 
  627         /* flush cpu cache */
  628         (*bs->sc_dmasync_after) (ct);
  629 }
  630 
  631 /**********************************************
  632  * VENDOR UNIQUE DMA FUNCS
  633  **********************************************/
  634 static int bshw_dma_init_sc98(struct ct_softc *);
  635 static void bshw_dma_start_sc98(struct ct_softc *);
  636 static void bshw_dma_stop_sc98(struct ct_softc *);
  637 static int bshw_dma_init_texa(struct ct_softc *);
  638 static void bshw_dma_start_elecom(struct ct_softc *);
  639 static void bshw_dma_stop_elecom(struct ct_softc *);
  640 
  641 static int
  642 bshw_dma_init_texa(ct)
  643         struct ct_softc *ct;
  644 {
  645         struct ct_bus_access_handle *chp = &ct->sc_ch;
  646         u_int8_t regval;
  647 
  648         if ((regval = ct_cr_read_1(chp, 0x37)) & 0x08)
  649                 return 0;
  650 
  651         ct_cr_write_1(chp, 0x37, regval | 0x08);
  652         regval = ct_cr_read_1(chp, 0x3f);
  653         ct_cr_write_1(chp, 0x3f, regval | 0x08);
  654         return 1;
  655 }
  656 
  657 static int
  658 bshw_dma_init_sc98(ct)
  659         struct ct_softc *ct;
  660 {
  661         struct ct_bus_access_handle *chp = &ct->sc_ch;
  662 
  663         if (ct_cr_read_1(chp, 0x37) & 0x08)
  664                 return 0;
  665 
  666         /* If your card is SC98 with bios ver 1.01 or 1.02 under no PCI */
  667         ct_cr_write_1(chp, 0x37, 0x1a);
  668         ct_cr_write_1(chp, 0x3f, 0x1a);
  669 #if     0
  670         /* only valid for IO */
  671         ct_cr_write_1(chp, 0x40, 0xf4);
  672         ct_cr_write_1(chp, 0x41, 0x9);
  673         ct_cr_write_1(chp, 0x43, 0xff);
  674         ct_cr_write_1(chp, 0x46, 0x4e);
  675 
  676         ct_cr_write_1(chp, 0x48, 0xf4);
  677         ct_cr_write_1(chp, 0x49, 0x9);
  678         ct_cr_write_1(chp, 0x4b, 0xff);
  679         ct_cr_write_1(chp, 0x4e, 0x4e);
  680 #endif
  681         return 1;
  682 }
  683 
  684 static void
  685 bshw_dma_start_sc98(ct)
  686         struct ct_softc *ct;
  687 {
  688         struct ct_bus_access_handle *chp = &ct->sc_ch;
  689 
  690         ct_cr_write_1(chp, 0x73, 0x32);
  691         ct_cr_write_1(chp, 0x74, 0x23);
  692 }
  693 
  694 static void
  695 bshw_dma_stop_sc98(ct)
  696         struct ct_softc *ct;
  697 {
  698         struct ct_bus_access_handle *chp = &ct->sc_ch;
  699 
  700         ct_cr_write_1(chp, 0x73, 0x43);
  701         ct_cr_write_1(chp, 0x74, 0x34);
  702 }
  703 
  704 static void
  705 bshw_dma_start_elecom(ct)
  706         struct ct_softc *ct;
  707 {
  708         struct ct_bus_access_handle *chp = &ct->sc_ch;
  709         u_int8_t tmp = ct_cr_read_1(chp, 0x4c);
  710 
  711         ct_cr_write_1(chp, 0x32, tmp & 0xdf);
  712 }
  713 
  714 static void
  715 bshw_dma_stop_elecom(ct)
  716         struct ct_softc *ct;
  717 {
  718         struct ct_bus_access_handle *chp = &ct->sc_ch;
  719         u_int8_t tmp = ct_cr_read_1(chp, 0x4c);
  720 
  721         ct_cr_write_1(chp, 0x32, tmp | 0x20);
  722 }
  723 
  724 static struct bshw bshw_generic = {
  725         BSHW_SYNC_RELOAD,
  726 
  727         0,
  728 
  729         NULL,
  730         NULL,
  731         NULL,
  732 };
  733 
  734 static struct bshw bshw_sc98 = {
  735         BSHW_DOUBLE_DMACHAN,
  736 
  737         0x60,
  738 
  739         bshw_dma_init_sc98,
  740         bshw_dma_start_sc98,
  741         bshw_dma_stop_sc98,
  742 };
  743 
  744 static struct bshw bshw_texa = {
  745         BSHW_DOUBLE_DMACHAN,
  746 
  747         0x60,
  748 
  749         bshw_dma_init_texa,
  750         NULL,
  751         NULL,
  752 };
  753 
  754 static struct bshw bshw_elecom = {
  755         0,
  756 
  757         0x38,
  758 
  759         NULL,
  760         bshw_dma_start_elecom,
  761         bshw_dma_stop_elecom,
  762 };
  763 
  764 static struct bshw bshw_lc_smit = {
  765         BSHW_SMFIFO | BSHW_DOUBLE_DMACHAN,
  766 
  767         0x60,
  768 
  769         NULL,
  770         NULL,
  771         NULL,
  772 };
  773 
  774 static struct bshw bshw_lha20X = {
  775         BSHW_DOUBLE_DMACHAN,
  776 
  777         0x60,
  778 
  779         NULL,
  780         NULL,
  781         NULL,
  782 };
  783 
  784 /* hw tabs */
  785 static dvcfg_hw_t bshw_hwsel_array[] = {
  786 /* 0x00 */      &bshw_generic,
  787 /* 0x01 */      &bshw_sc98,
  788 /* 0x02 */      &bshw_texa,
  789 /* 0x03 */      &bshw_elecom,
  790 /* 0x04 */      &bshw_lc_smit,
  791 /* 0x05 */      &bshw_lha20X,
  792 };
  793 
  794 struct dvcfg_hwsel bshw_hwsel = {
  795         DVCFG_HWSEL_SZ(bshw_hwsel_array),
  796         bshw_hwsel_array
  797 };

Cache object: 64b5fbaa3da8c51a2f640fd50b2827c0


[ 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.