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

Cache object: f5e9e61e34b516f0963f515c667f6f07


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