1 /*        $NetBSD: bzsc.c,v 1.50 2019/01/08 19:41:09 jdolecek Exp $ */
2 
3 /*
4  * Copyright (c) 1997 Michael L. Hitch
5  * Copyright (c) 1995 Daniel Widenfalk
6  * Copyright (c) 1994 Christian E. Hopps
7  * Copyright (c) 1982, 1990 The Regents of the University of California.
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. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *        This product includes software developed by Daniel Widenfalk
21  *        and Michael L. Hitch.
22  * 4. Neither the name of the University nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  */
38 
39 #ifdef __m68k__
40 #include "opt_m68k_arch.h"
41 #endif
42 
43 #include <sys/cdefs.h>
44 __KERNEL_RCSID(0, "$NetBSD: bzsc.c,v 1.50 2019/01/08 19:41:09 jdolecek Exp $");
45 
46 /*
47  * Initial amiga Blizzard 1230-II driver by Daniel Widenfalk.  Conversion to
48  * 53c9x MI driver by Michael L. Hitch (mhitch@montana.edu).
49  */
50 
51 #include <sys/types.h>
52 #include <sys/param.h>
53 #include <sys/systm.h>
54 #include <sys/kernel.h>
55 #include <sys/errno.h>
56 #include <sys/ioctl.h>
57 #include <sys/device.h>
58 #include <sys/buf.h>
59 #include <sys/proc.h>
60 #include <sys/queue.h>
61 
62 #include <dev/scsipi/scsi_all.h>
63 #include <dev/scsipi/scsipi_all.h>
64 #include <dev/scsipi/scsiconf.h>
65 #include <dev/scsipi/scsi_message.h>
66 
67 #include <machine/cpu.h>
68 
69 #include <dev/ic/ncr53c9xreg.h>
70 #include <dev/ic/ncr53c9xvar.h>
71 
72 #include <amiga/amiga/isr.h>
73 #include <amiga/dev/bzscvar.h>
74 #include <amiga/dev/zbusvar.h>
75 
76 #ifdef __powerpc__
77 #define badaddr(a)      badaddr_read(a, 2, NULL)
78 #endif
79 
80 int       bzscmatch(device_t, cfdata_t, void *);
81 void      bzscattach(device_t, device_t, void *);
82 
83 /* Linkup to the rest of the kernel */
84 CFATTACH_DECL_NEW(bzsc, sizeof(struct bzsc_softc),
85     bzscmatch, bzscattach, NULL, NULL);
86 
87 /*
88  * Functions and the switch for the MI code.
89  */
90 uint8_t   bzsc_read_reg(struct ncr53c9x_softc *, int);
91 void      bzsc_write_reg(struct ncr53c9x_softc *, int, uint8_t);
92 int       bzsc_dma_isintr(struct ncr53c9x_softc *);
93 void      bzsc_dma_reset(struct ncr53c9x_softc *);
94 int       bzsc_dma_intr(struct ncr53c9x_softc *);
95 int       bzsc_dma_setup(struct ncr53c9x_softc *, uint8_t **,
96               size_t *, int, size_t *);
97 void      bzsc_dma_go(struct ncr53c9x_softc *);
98 void      bzsc_dma_stop(struct ncr53c9x_softc *);
99 int       bzsc_dma_isactive(struct ncr53c9x_softc *);
100 
101 struct ncr53c9x_glue bzsc_glue = {
102           bzsc_read_reg,
103           bzsc_write_reg,
104           bzsc_dma_isintr,
105           bzsc_dma_reset,
106           bzsc_dma_intr,
107           bzsc_dma_setup,
108           bzsc_dma_go,
109           bzsc_dma_stop,
110           bzsc_dma_isactive,
111           NULL,
112 };
113 
114 /* Maximum DMA transfer length to reduce impact on high-speed serial input */
115 u_long bzsc_max_dma = 1024;
116 extern int ser_open_speed;
117 
118 u_long bzsc_cnt_pio = 0;      /* number of PIO transfers */
119 u_long bzsc_cnt_dma = 0;      /* number of DMA transfers */
120 u_long bzsc_cnt_dma2 = 0;     /* number of DMA transfers broken up */
121 u_long bzsc_cnt_dma3 = 0;     /* number of pages combined */
122 
123 #ifdef DEBUG
124 struct {
125           uint8_t hardbits;
126           uint8_t status;
127           uint8_t xx;
128           uint8_t yy;
129 } bzsc_trace[128];
130 int bzsc_trace_ptr = 0;
131 int bzsc_trace_enable = 1;
132 void bzsc_dump(void);
133 #endif
134 
135 /*
136  * if we are a Phase5 Blizzard 1230 II
137  */
138 int
bzscmatch(device_t parent,cfdata_t cf,void * aux)139 bzscmatch(device_t parent, cfdata_t cf, void *aux)
140 {
141           struct zbus_args *zap;
142           volatile uint8_t *regs;
143 
144           zap = aux;
145           if (zap->manid != 0x2140 || zap->prodid != 11)
146                     return 0;                     /* It's not Blizzard 1230 */
147           if (!is_a1200())
148                     return 0;                     /* And not A1200 */
149           regs = &((volatile uint8_t *)zap->va)[0x10000];
150           if (badaddr((void *)__UNVOLATILE(regs)))
151                     return 0;
152           regs[NCR_CFG1 * 2] = 0;
153           regs[NCR_CFG1 * 2] = NCRCFG1_PARENB | 7;
154           delay(5);
155           if (regs[NCR_CFG1 * 2] != (NCRCFG1_PARENB | 7))
156                     return 0;
157           return 1;
158 }
159 
160 /*
161  * Attach this instance, and then all the sub-devices
162  */
163 void
bzscattach(device_t parent,device_t self,void * aux)164 bzscattach(device_t parent, device_t self, void *aux)
165 {
166           struct bzsc_softc *bsc = device_private(self);
167           struct ncr53c9x_softc *sc = &bsc->sc_ncr53c9x;
168           struct zbus_args  *zap;
169           extern u_long scsi_nosync;
170           extern int shift_nosync;
171           extern int ncr53c9x_debug;
172 
173           /*
174            * Set up the glue for MI code early; we use some of it here.
175            */
176           sc->sc_dev = self;
177           sc->sc_glue = &bzsc_glue;
178 
179           /*
180            * Save the regs
181            */
182           zap = aux;
183           bsc->sc_reg = &((volatile uint8_t *)zap->va)[0x10000];
184           bsc->sc_dmabase = &bsc->sc_reg[0x21];
185 
186           sc->sc_freq = 40;             /* Clocked at 40 MHz */
187 
188           aprint_normal(": address %p", bsc->sc_reg);
189 
190           sc->sc_id = 7;
191 
192           /*
193            * It is necessary to try to load the 2nd config register here,
194            * to find out what rev the FAS chip is, else the ncr53c9x_reset
195            * will not set up the defaults correctly.
196            */
197           sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB;
198           sc->sc_cfg2 = NCRCFG2_SCSI2 | NCRCFG2_FE;
199           sc->sc_cfg3 = 0x08 /*FCLK*/ | NCRESPCFG3_FSCSI | NCRESPCFG3_CDB;
200           sc->sc_rev = NCR_VARIANT_FAS216;
201 
202           /*
203            * This is the value used to start sync negotiations
204            * Note that the NCR register "SYNCTP" is programmed
205            * in "clocks per byte", and has a minimum value of 4.
206            * The SCSI period used in negotiation is one-fourth
207            * of the time (in nanoseconds) needed to transfer one byte.
208            * Since the chip's clock is given in MHz, we have the following
209            * formula: 4 * period = (1000 / freq) * 4
210            */
211           sc->sc_minsync = 1000 / sc->sc_freq;
212 
213           /*
214            * get flags from -I argument and set cf_flags.
215            * NOTE: low 8 bits are to disable disconnect, and the next
216            *       8 bits are to disable sync.
217            */
218           device_cfdata(self)->cf_flags |= (scsi_nosync >> shift_nosync)
219               & 0xffff;
220           shift_nosync += 16;
221 
222           /* Use next 16 bits of -I argument to set ncr53c9x_debug flags */
223           ncr53c9x_debug |= (scsi_nosync >> shift_nosync) & 0xffff;
224           shift_nosync += 16;
225 
226 #if 1
227           if (((scsi_nosync >> shift_nosync) & 0xff00) == 0xff00)
228                     sc->sc_minsync = 0;
229 #endif
230 
231           /* Really no limit, but since we want to fit into the TCR... */
232           sc->sc_maxxfer = 64 * 1024;
233 
234           /*
235            * Configure interrupts.
236            */
237           bsc->sc_isr.isr_intr = ncr53c9x_intr;
238           bsc->sc_isr.isr_arg  = sc;
239           bsc->sc_isr.isr_ipl  = 2;
240           add_isr(&bsc->sc_isr);
241 
242           /*
243            * Now try to attach all the sub-devices
244            */
245           sc->sc_adapter.adapt_request = ncr53c9x_scsipi_request;
246           sc->sc_adapter.adapt_minphys = minphys;
247           ncr53c9x_attach(sc);
248 }
249 
250 /*
251  * Glue functions.
252  */
253 
254 uint8_t
bzsc_read_reg(struct ncr53c9x_softc * sc,int reg)255 bzsc_read_reg(struct ncr53c9x_softc *sc, int reg)
256 {
257           struct bzsc_softc *bsc = (struct bzsc_softc *)sc;
258 
259           return bsc->sc_reg[reg * 2];
260 }
261 
262 void
bzsc_write_reg(struct ncr53c9x_softc * sc,int reg,uint8_t val)263 bzsc_write_reg(struct ncr53c9x_softc *sc, int reg, uint8_t val)
264 {
265           struct bzsc_softc *bsc = (struct bzsc_softc *)sc;
266           uint8_t v = val;
267 
268           bsc->sc_reg[reg * 2] = v;
269 #ifdef DEBUG
270 if (bzsc_trace_enable/* && sc->sc_nexus && sc->sc_nexus->xs->xs_control & XS_CTL_POLL*/ &&
271   reg == NCR_CMD/* && bsc->sc_active*/) {
272   bzsc_trace[(bzsc_trace_ptr - 1) & 127].yy = v;
273 /*  printf(" cmd %x", v);*/
274 }
275 #endif
276 }
277 
278 int
bzsc_dma_isintr(struct ncr53c9x_softc * sc)279 bzsc_dma_isintr(struct ncr53c9x_softc *sc)
280 {
281           struct bzsc_softc *bsc = (struct bzsc_softc *)sc;
282 
283           if ((bsc->sc_reg[NCR_STAT * 2] & NCRSTAT_INT) == 0)
284                     return 0;
285 
286 #ifdef DEBUG
287 if (/*sc->sc_nexus && sc->sc_nexus->xs->xs_control & XS_CTL_POLL &&*/ bzsc_trace_enable) {
288   bzsc_trace[bzsc_trace_ptr].status = bsc->sc_reg[NCR_STAT * 2];
289   bzsc_trace[bzsc_trace_ptr].xx = bsc->sc_reg[NCR_CMD * 2];
290   bzsc_trace[bzsc_trace_ptr].yy = bsc->sc_active;
291   bzsc_trace_ptr = (bzsc_trace_ptr + 1) & 127;
292 }
293 #endif
294           return 1;
295 }
296 
297 void
bzsc_dma_reset(struct ncr53c9x_softc * sc)298 bzsc_dma_reset(struct ncr53c9x_softc *sc)
299 {
300           struct bzsc_softc *bsc = (struct bzsc_softc *)sc;
301 
302           bsc->sc_active = 0;
303 }
304 
305 int
bzsc_dma_intr(struct ncr53c9x_softc * sc)306 bzsc_dma_intr(struct ncr53c9x_softc *sc)
307 {
308           struct bzsc_softc *bsc = (struct bzsc_softc *)sc;
309           int       cnt;
310 
311           NCR_DMA(("bzsc_dma_intr: cnt %d int %x stat %x fifo %d ",
312               bsc->sc_dmasize, sc->sc_espintr, sc->sc_espstat,
313               bsc->sc_reg[NCR_FFLAG * 2] & NCRFIFO_FF));
314           if (bsc->sc_active == 0) {
315                     printf("bzsc_intr--inactive DMA\n");
316                     return -1;
317           }
318 
319           /* update sc_dmaaddr and sc_pdmalen */
320           cnt = bsc->sc_reg[NCR_TCL * 2];
321           cnt += bsc->sc_reg[NCR_TCM * 2] << 8;
322           cnt += bsc->sc_reg[NCR_TCH * 2] << 16;
323           if (!bsc->sc_datain) {
324                     cnt += bsc->sc_reg[NCR_FFLAG * 2] & NCRFIFO_FF;
325                     bsc->sc_reg[NCR_CMD * 2] = NCRCMD_FLUSH;
326           }
327           cnt = bsc->sc_dmasize - cnt;  /* number of bytes transferred */
328           NCR_DMA(("DMA xferred %d\n", cnt));
329           if (bsc->sc_xfr_align) {
330                     memcpy(*bsc->sc_dmaaddr, bsc->sc_alignbuf, cnt);
331                     bsc->sc_xfr_align = 0;
332           }
333           *bsc->sc_dmaaddr += cnt;
334           *bsc->sc_pdmalen -= cnt;
335           bsc->sc_active = 0;
336           return 0;
337 }
338 
339 int
bzsc_dma_setup(struct ncr53c9x_softc * sc,uint8_t ** addr,size_t * len,int datain,size_t * dmasize)340 bzsc_dma_setup(struct ncr53c9x_softc *sc, uint8_t **addr, size_t *len,
341                int datain, size_t *dmasize)
342 {
343           struct bzsc_softc *bsc = (struct bzsc_softc *)sc;
344           paddr_t pa;
345           uint8_t *ptr;
346           size_t xfer;
347 
348           bsc->sc_dmaaddr = addr;
349           bsc->sc_pdmalen = len;
350           bsc->sc_datain = datain;
351           bsc->sc_dmasize = *dmasize;
352           /*
353            * DMA can be nasty for high-speed serial input, so limit the
354            * size of this DMA operation if the serial port is running at
355            * a high speed (higher than 19200 for now - should be adjusted
356            * based on CPU type and speed?).
357            * XXX - add serial speed check XXX
358            */
359           if (ser_open_speed > 19200 && bzsc_max_dma != 0 &&
360               bsc->sc_dmasize > bzsc_max_dma)
361                     bsc->sc_dmasize = bzsc_max_dma;
362           ptr = *addr;                            /* Kernel virtual address */
363           pa = kvtop(ptr);              /* Physical address of DMA */
364           xfer = uimin(bsc->sc_dmasize, PAGE_SIZE - (pa & (PAGE_SIZE - 1)));
365           bsc->sc_xfr_align = 0;
366           /*
367            * If output and unaligned, stuff odd byte into FIFO
368            */
369           if (datain == 0 && (int)ptr & 1) {
370                     NCR_DMA(("bzsc_dma_setup: align byte written to fifo\n"));
371                     pa++;
372                     xfer--;                       /* XXXX CHECK THIS !!!! XXXX */
373                     bsc->sc_reg[NCR_FIFO * 2] = *ptr++;
374           }
375           /*
376            * If unaligned address, read unaligned bytes into alignment buffer
377            */
378           else if ((int)ptr & 1) {
379                     pa = kvtop((void *)&bsc->sc_alignbuf);
380                     xfer = bsc->sc_dmasize = uimin(xfer, sizeof(bsc->sc_alignbuf));
381                     NCR_DMA(("bzsc_dma_setup: align read by %d bytes\n", xfer));
382                     bsc->sc_xfr_align = 1;
383           }
384 ++bzsc_cnt_dma;               /* number of DMA operations */
385 
386           while (xfer < bsc->sc_dmasize) {
387                     if ((pa + xfer) != kvtop(*addr + xfer))
388                               break;
389                     if ((bsc->sc_dmasize - xfer) < PAGE_SIZE)
390                               xfer = bsc->sc_dmasize;
391                     else
392                               xfer += PAGE_SIZE;
393 ++bzsc_cnt_dma3;
394           }
395 if (xfer != *len)
396   ++bzsc_cnt_dma2;
397 
398           bsc->sc_dmasize = xfer;
399           *dmasize = bsc->sc_dmasize;
400           bsc->sc_pa = pa;
401 #if defined(M68040) || defined(M68060)
402           if (mmutype == MMU_68040) {
403                     if (bsc->sc_xfr_align) {
404                               dma_cachectl(bsc->sc_alignbuf,
405                                   sizeof(bsc->sc_alignbuf));
406                     }
407                     else
408                               dma_cachectl(*bsc->sc_dmaaddr, bsc->sc_dmasize);
409           }
410 #endif
411 
412           pa >>= 1;
413           if (!bsc->sc_datain)
414                     pa |= 0x80000000;
415           bsc->sc_dmabase[0x10] = (uint8_t)(pa >> 24);
416           bsc->sc_dmabase[0] = (uint8_t)(pa >> 16);
417           bsc->sc_dmabase[0] = (uint8_t)(pa >> 8);
418           bsc->sc_dmabase[0] = (uint8_t)(pa);
419           bsc->sc_active = 1;
420           return 0;
421 }
422 
423 void
bzsc_dma_go(struct ncr53c9x_softc * sc)424 bzsc_dma_go(struct ncr53c9x_softc *sc)
425 {
426 }
427 
428 void
bzsc_dma_stop(struct ncr53c9x_softc * sc)429 bzsc_dma_stop(struct ncr53c9x_softc *sc)
430 {
431 }
432 
433 int
bzsc_dma_isactive(struct ncr53c9x_softc * sc)434 bzsc_dma_isactive(struct ncr53c9x_softc *sc)
435 {
436           struct bzsc_softc *bsc = (struct bzsc_softc *)sc;
437 
438           return bsc->sc_active;
439 }
440 
441 #ifdef DEBUG
442 void
bzsc_dump(void)443 bzsc_dump(void)
444 {
445           int i;
446 
447           i = bzsc_trace_ptr;
448           printf("bzsc_trace dump: ptr %x\n", bzsc_trace_ptr);
449           do {
450                     if (bzsc_trace[i].hardbits == 0) {
451                               i = (i + 1) & 127;
452                               continue;
453                     }
454                     printf("%02x%02x%02x%02x(", bzsc_trace[i].hardbits,
455                         bzsc_trace[i].status, bzsc_trace[i].xx, bzsc_trace[i].yy);
456                     if (bzsc_trace[i].status & NCRSTAT_INT)
457                               printf("NCRINT/");
458                     if (bzsc_trace[i].status & NCRSTAT_TC)
459                               printf("NCRTC/");
460                     switch(bzsc_trace[i].status & NCRSTAT_PHASE) {
461                     case 0:
462                               printf("dataout"); break;
463                     case 1:
464                               printf("datain"); break;
465                     case 2:
466                               printf("cmdout"); break;
467                     case 3:
468                               printf("status"); break;
469                     case 6:
470                               printf("msgout"); break;
471                     case 7:
472                               printf("msgin"); break;
473                     default:
474                               printf("phase%d?", bzsc_trace[i].status & NCRSTAT_PHASE);
475                     }
476                     printf(") ");
477                     i = (i + 1) & 127;
478           } while (i != bzsc_trace_ptr);
479           printf("\n");
480 }
481 #endif
482