Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / sys / dev / disk / i386 / bs / bshw_pdma.c
1 /* $FreeBSD: src/sys/i386/isa/bs/bshw_pdma.c,v 1.6.6.1 2000/10/21 07:44:26 nyan Exp $ */
2 /* $DragonFly: src/sys/dev/disk/i386/bs/Attic/bshw_pdma.c,v 1.2 2003/06/17 04:28:37 dillon Exp $ */
3 /*      $NecBSD: bshw_pdma.c,v 1.4 1997/10/31 17:43:39 honda Exp $      */
4 /*      $NetBSD$        */
5 /*
6  * [NetBSD for NEC PC98 series]
7  *  Copyright (c) 1994, 1995, 1996 NetBSD/pc98 porting staff.
8  *  All rights reserved.
9  * 
10  *  Redistribution and use in source and binary forms, with or without
11  *  modification, are permitted provided that the following conditions
12  *  are met:
13  *  1. Redistributions of source code must retain the above copyright
14  *     notice, this list of conditions and the following disclaimer.
15  *  2. Redistributions in binary form must reproduce the above copyright
16  *     notice, this list of conditions and the following disclaimer in the
17  *     documentation and/or other materials provided with the distribution.
18  *  3. The name of the author may not be used to endorse or promote products
19  *     derived from this software without specific prior written permission.
20  * 
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
25  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  */
33 /*
34  * Copyright (c) 1994, 1995, 1996 Naofumi HONDA.  All rights reserved.
35  */
36
37 #define LC_SMIT_TIMEOUT 2       /* 2 sec: timeout for a fifo status ready */
38
39 static BS_INLINE void bshw_lc_smit_start __P((struct bs_softc *, int, u_int));
40 static int bshw_lc_smit_fstat __P((struct bs_softc *, int, int));
41 static void bshw_lc_smit_stop __P((struct bs_softc *));
42
43 /*********************************************************
44  * SM FIFO (GENERIC)
45  *********************************************************/
46 void
47 bshw_smitabort(bsc)
48         struct bs_softc *bsc;
49 {
50         if (bsc->sc_hw->hw_flags & BSHW_SMFIFO)
51                 bshw_lc_smit_stop(bsc);
52
53         bshw_set_count(bsc, 0);
54         bsc->sc_flags &= ~BSSMITSTART;
55 }
56
57 void
58 bs_smit_xfer_end(ti)
59         struct targ_info *ti;
60 {
61         struct bs_softc *bsc = ti->ti_bsc;
62         struct sc_p *sp = &bsc->sc_p;
63         u_int count;
64         u_char *s;
65
66         bshw_lc_smit_stop(bsc);
67         bsc->sc_flags &= ~BSSMITSTART;
68
69         if (ti->ti_phase == DATAPHASE)
70         {
71                 count = bshw_get_count(bsc);
72                 if (count < (u_int) sp->datalen)
73                 {
74                         sp->data += (sp->datalen - count);
75                         sp->datalen = count;
76                         /* XXX:
77                          * strict double checks!
78                          * target   => wd33c93c transfer counts
79                          * wd33c93c => memory   transfer counts
80                          */
81                         if ((bsc->sc_dmadir & BSHW_READ) &&
82                              count != bsc->sm_tdatalen)
83                         {
84                                 s = "read count miss";
85                                 goto bad;
86                         }
87                         return;
88                 }
89                 else if (count == (u_int) sp->datalen)
90                 {
91                         return;
92                 }
93
94                 s = "strange count";
95         }
96         else
97                 s = "extra smit interrupt";
98
99 bad:
100         bs_printf(ti, "smit_xfer_end", s);
101         ti->ti_error |= BSDMAABNORMAL;
102 }
103
104 /*********************************************************
105  * LOGITEC's SMIT TRANSFER
106  *********************************************************/
107
108 #define BSHW_LC_FSET    0x36
109 #define BSHW_LC_FCTRL   0x44
110 #define FCTRL_EN        0x01
111 #define FCTRL_WRITE     0x02
112
113 #define SF_ABORT        0x08
114 #define SF_RDY          0x10
115
116 #define LC_FSZ          DEV_BSIZE
117 #define LC_SFSZ         0x0c
118 #define LC_REST         (LC_FSZ - LC_SFSZ)
119
120 static void
121 bshw_lc_smit_stop(bsc)
122         struct bs_softc *bsc;
123 {
124
125         write_wd33c93(bsc, BSHW_LC_FCTRL, 0);
126         BUS_IOW(cmd_port, CMDP_DMER);
127 }
128
129 static BS_INLINE void
130 bshw_lc_smit_start(bsc, count, direction)
131         struct bs_softc *bsc;
132         int count;
133         u_int direction;
134 {
135         u_int8_t pval, val = read_wd33c93(bsc, BSHW_LC_FSET);
136
137         bsc->sc_flags |= BSSMITSTART;
138         bshw_set_count(bsc, count);
139
140         pval = FCTRL_EN;
141         if ((direction & BSHW_READ) == 0)
142                 pval |= (val & 0xe0) | FCTRL_WRITE;
143         write_wd33c93(bsc, BSHW_LC_FCTRL, pval);
144         bshw_start_xfer(bsc);
145 }
146
147 static int
148 bshw_lc_smit_fstat(bsc, wc, read)
149         struct bs_softc *bsc;
150         int wc, read;
151 {
152         u_int8_t stat;
153
154 #define ALWAYS_ABORT
155 #ifdef  ALWAYS_ABORT
156         if (read == BSHW_READ)
157         {
158                 while (wc -- > 0)
159                 {
160                         BUS_IO_WEIGHT;
161                         stat = BUS_IOR(cmd_port);
162                         if (stat & SF_RDY)
163                                 return 0;
164                         if (stat & SF_ABORT)
165                                 return EIO;
166                 }
167         }
168         else
169         {
170 #endif  /* ALWAYS_ABORT */
171                 while (wc -- > 0)
172                 {
173                         BUS_IO_WEIGHT;
174                         stat = BUS_IOR(cmd_port);
175                         if (stat & SF_ABORT)
176                                 return EIO;
177                         if (stat & SF_RDY)
178                                 return 0;
179                 }
180 #ifdef  ALWAYS_ABORT
181         }
182 #endif  /* ALWAYS_ABORT */
183
184         bs_poll_timeout(bsc, "bshw_lc_smit");
185         return EIO;
186 }
187
188 void
189 bs_lc_smit_xfer(ti, direction)
190         struct targ_info *ti;
191         u_int direction;
192 {
193         struct bs_softc *bsc = ti->ti_bsc;
194         struct sc_p *sp = &bsc->sc_p;
195         int datalen, count, wc = LC_SMIT_TIMEOUT * 1024 * 1024;
196         u_int8_t *data;
197
198         sp->bufp = NULL;
199         sp->seglen = 0;
200         data = sp->data;
201         datalen = sp->datalen;
202
203         bsc->sc_dmadir = direction;
204         bshw_set_dma_trans(bsc, ti->ti_cfgflags);
205         bshw_lc_smit_start(bsc, sp->datalen, direction);
206
207         if (direction & BSHW_READ)
208         {
209                 do
210                 {
211                         if (bshw_lc_smit_fstat(bsc, wc, BSHW_READ))
212                                 break;
213
214                         count = (datalen > LC_FSZ ? LC_FSZ : datalen);
215 #ifdef  __FreeBSD__
216                         memcopy((u_int8_t *)ti->sm_offset, data, count);
217 #else   /* NetBSD */
218                         bus_space_read_region_4(bsc->sc_memt, bsc->sc_memh,
219                                 ti->sm_offset, (u_int32_t *) data, count >> 2);
220 #endif  /* NetBSD */
221                         data += count;
222                         datalen -= count;
223                 }
224                 while (datalen > 0);
225
226                 bsc->sm_tdatalen = datalen;
227         }
228         else
229         {
230                 do
231                 {
232                         if (bshw_lc_smit_fstat(bsc, wc, BSHW_WRITE))
233                                 break;
234
235                         count = (datalen > LC_SFSZ ? LC_SFSZ : datalen);
236 #ifdef  __FreeBSD__
237                         memcopy(data, (u_int8_t *)ti->sm_offset, count);
238 #else   /* NetBSD */
239                         bus_space_write_region_4(bsc->sc_memt, bsc->sc_memh,
240                                 ti->sm_offset, (u_int32_t *) data, count >> 2);
241 #endif  /* NetBSD */
242                         data += count;
243                         datalen -= count;
244
245                         if (bshw_lc_smit_fstat(bsc, wc, BSHW_WRITE))
246                                 break;
247
248                         count = (datalen > LC_REST ? LC_REST : datalen);
249 #ifdef  __FreeBSD__
250                         memcopy(data, (u_int8_t *)(ti->sm_offset + LC_SFSZ), count);
251 #else   /* NetBSD */
252                         bus_space_write_region_4(bsc->sc_memt, bsc->sc_memh,
253                                                  ti->sm_offset + LC_SFSZ, 
254                                                  (u_int32_t *) data, count >> 2);
255 #endif  /* NetBSD */
256                         data += count;
257                         datalen -= count;
258                 }
259                 while (datalen > 0);
260         }
261 }