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

Cache object: 1d2ad358c8dece31f13a5c6ffd11287f


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