1 /*        $NetBSD: sunscpalvar.h,v 1.10 2023/01/23 22:16:44 andvar Exp $        */
2 
3 /*
4  * Copyright (c) 2001 Matthew Fredette
5  * Copyright (c) 1995 David Jones, Gordon W. Ross
6  * Copyright (c) 1994 Jarle Greipsland
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. The name of the authors may not be used to endorse or promote products
18  *    derived from this software without specific prior written permission.
19  * 4. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgement:
21  *      This product includes software developed by
22  *      David Jones and Gordon Ross
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 /*
37  * This file defines the interface between the machine-dependent
38  * module and the machine-independent sunscpal.c module.
39  */
40 
41 /*
42  * The sun2 and sparc use real bus_space.
43  */
44 #if defined(sun2) || defined(__sparc__)
45 # define SUNSCPAL_USE_BUS_SPACE
46 #endif
47 /*
48  * The sun2 and sparc use real bus_dma.
49  */
50 #if defined(sun2) || defined(__sparc__)
51 #define SUNSCPAL_USE_BUS_DMA
52 #endif
53 
54 /*
55  * Handy read/write macros
56  */
57 #ifdef SUNSCPAL_USE_BUS_SPACE
58 # include <sys/bus.h>
59 /* bus_space() variety */
60 #define SUNSCPAL_READ_1(sc, reg)        bus_space_read_1(sc->sunscpal_regt, \
61                                                             sc->sunscpal_regh, sc->reg)
62 #define SUNSCPAL_WRITE_1(sc, reg, val)  bus_space_write_1(sc->sunscpal_regt, \
63                                                             sc->sunscpal_regh, sc->reg, val)
64 #define SUNSCPAL_READ_2(sc, reg)        bus_space_read_2(sc->sunscpal_regt, \
65                                                             sc->sunscpal_regh, sc->reg)
66 #define SUNSCPAL_WRITE_2(sc, reg, val)  bus_space_write_2(sc->sunscpal_regt, \
67                                                             sc->sunscpal_regh, sc->reg, val)
68 #else
69 /* legacy memory-mapped variety */
70 # define SUNSCPAL_READ_1(sc, reg)       (*sc->reg)
71 # define SUNSCPAL_WRITE_1(sc, reg, val) do { *(sc->reg) = val; } while(0)
72 # define SUNSCPAL_READ_2 SUNSCPAL_READ_1
73 # define SUNSCPAL_WRITE_2 SUNSCPAL_WRITE_1
74 #endif
75 
76 #define SUNSCPAL_CLR_INTR(sc) do { SUNSCPAL_READ_2(sc, sunscpal_dma_count); SUNSCPAL_READ_2(sc, sunscpal_icr); } while(0)
77 #define   SUNSCPAL_BUSY(sc)   (SUNSCPAL_READ_2(sc, sunscpal_icr) & SUNSCPAL_ICR_BUSY)
78 
79 /* These are NOT artibtrary, but map to bits in sunscpal_icr */
80 #define SUNSCPAL_PHASE_DATA_IN          (SUNSCPAL_ICR_INPUT_OUTPUT)
81 #define SUNSCPAL_PHASE_DATA_OUT         (0)
82 #define SUNSCPAL_PHASE_COMMAND          (SUNSCPAL_ICR_COMMAND_DATA)
83 #define SUNSCPAL_PHASE_STATUS (SUNSCPAL_ICR_COMMAND_DATA | \
84                                          SUNSCPAL_ICR_INPUT_OUTPUT)
85 #define SUNSCPAL_PHASE_MSG_IN (SUNSCPAL_ICR_MESSAGE | \
86                                          SUNSCPAL_ICR_COMMAND_DATA | \
87                                          SUNSCPAL_ICR_INPUT_OUTPUT)
88 #define SUNSCPAL_PHASE_MSG_OUT          (SUNSCPAL_ICR_MESSAGE | \
89                                          SUNSCPAL_ICR_COMMAND_DATA)
90 #define SUNSCPAL_PHASE_UNSPEC1          (SUNSCPAL_ICR_MESSAGE | \
91                                          SUNSCPAL_ICR_INPUT_OUTPUT)
92 #define SUNSCPAL_PHASE_UNSPEC2          (SUNSCPAL_ICR_MESSAGE)
93 #define SUNSCPAL_BYTE_READ(sc, phase)   (((phase) & SUNSCPAL_ICR_COMMAND_DATA) ? \
94                                                    SUNSCPAL_READ_1(sc, sunscpal_cmd_stat) : \
95                                                    SUNSCPAL_READ_1(sc, sunscpal_data))
96 #define SUNSCPAL_BYTE_WRITE(sc, phase, b)         do { \
97                                                                       if ((phase) & SUNSCPAL_ICR_COMMAND_DATA) { \
98                                                                                 SUNSCPAL_WRITE_1(sc, sunscpal_cmd_stat, b); \
99                                                                       } else { \
100                                                                                 SUNSCPAL_WRITE_1(sc, sunscpal_data, b); \
101                                                                       } \
102                                                             } while(0)
103 /*
104  * A mask and a macro for getting the current bus phase.
105  */
106 #define SUNSCPAL_ICR_PHASE_MASK         (SUNSCPAL_ICR_MESSAGE | \
107                                          SUNSCPAL_ICR_COMMAND_DATA | \
108                                          SUNSCPAL_ICR_INPUT_OUTPUT)
109 #define SUNSCPAL_BUS_PHASE(icr)         ((icr) & SUNSCPAL_ICR_PHASE_MASK)
110 
111 /*
112  * This illegal phase is used to prevent the PAL from having
113  * a phase-match condition when we don't want one, such as
114  * when setting up the DMA engine or whatever...
115  */
116 #define SUNSCPAL_PHASE_INVALID          SUNSCPAL_PHASE_UNSPEC1
117 
118 /*
119  * Transfers larger than 65535 bytes need to be split-up.
120  * (The DMA count register is only 16 bits.)
121  * Make the size an integer multiple of the page size
122  * to avoid buf/cluster remap problems.  (paranoid?)
123  */
124 #define   SUNSCPAL_MAX_DMA_LEN 0xE000
125 
126 #ifdef SUNSCPAL_USE_BUS_DMA
127 /*
128  * This structure is used to keep track of mapped DMA requests.
129  */
130 struct sunscpal_dma_handle {
131           int                 dh_flags;
132 #define   SUNSCDH_BUSY        0x01                /* This DH is in use */
133           uint8_t * dh_mapaddr;         /* Original data pointer */
134           int                 dh_maplen;          /* Original data length */
135           bus_dmamap_t        dh_dmamap;
136 #define   dh_dvma dh_dmamap->dm_segs[0].ds_addr /* VA of buffer in DVMA space */
137 };
138 typedef struct sunscpal_dma_handle *sunscpal_dma_handle_t;
139 #else
140 typedef void *sunscpal_dma_handle_t;
141 #endif
142 
143 /* Per-request state.  This is required in order to support reselection. */
144 struct sunscpal_req {
145           struct              scsipi_xfer *sr_xs; /* Pointer to xfer struct, NULL=unused */
146           int                 sr_target, sr_lun;  /* For fast access */
147           sunscpal_dma_handle_t sr_dma_hand;      /* Current DMA handle */
148           uint8_t             *sr_dataptr;                  /* Saved data pointer */
149           int                 sr_datalen;
150           int                 sr_flags;           /* Internal error code */
151 #define   SR_IMMED                      1         /* Immediate command */
152 #define   SR_OVERDUE                              2         /* Timeout while not current */
153 #define   SR_ERROR                      4         /* Error occurred */
154           int                 sr_status;                    /* Status code from last cmd */
155 };
156 #define   SUNSCPAL_OPENINGS   16                  /* How many commands we can enqueue. */
157 
158 
159 struct sunscpal_softc {
160           device_t            sc_dev;
161           struct scsipi_adapter         sc_adapter;
162           struct scsipi_channel         sc_channel;
163 
164 #ifdef SUNSCPAL_USE_BUS_SPACE
165           /* Pointers to bus_space */
166           bus_space_tag_t     sunscpal_regt;
167           bus_space_handle_t  sunscpal_regh;
168 
169           /* Pointers to PAL registers.  */
170           bus_size_t          sunscpal_data;
171           bus_size_t          sunscpal_cmd_stat;
172           bus_size_t          sunscpal_icr;
173           bus_size_t          sunscpal_dma_addr_h;
174           bus_size_t          sunscpal_dma_addr_l;
175           bus_size_t          sunscpal_dma_count;
176           bus_size_t          sunscpal_intvec;
177 #else
178           /* Pointers to PAL registers.  See sunscpalreg.h */
179           volatile uint8_t    *sunscpal_data;
180           volatile uint8_t    *sunscpal_cmd_stat;
181           volatile uint16_t   *sunscpal_icr;
182           volatile uint16_t   *sunscpal_dma_addr_h;
183           volatile uint16_t   *sunscpal_dma_addr_l;
184           volatile uint16_t   *sunscpal_dma_count;
185           volatile uint8_t    *sunscpal_intvec;
186 #endif
187 
188           /* Pointers to DMA-related structures */
189 #ifdef    SUNSCPAL_USE_BUS_DMA
190           bus_dma_tag_t       sunscpal_dmat;
191 #endif
192           sunscpal_dma_handle_t         sc_dma_handles;
193 
194           /* Functions set from MD code */
195 #ifndef   SUNSCPAL_USE_BUS_DMA
196           void                (*sc_dma_alloc)(struct sunscpal_softc *);
197           void                (*sc_dma_free)(struct sunscpal_softc *);
198 
199           void                (*sc_dma_setup)(struct sunscpal_softc *);
200 #endif
201 
202           void                (*sc_intr_on)(struct sunscpal_softc *);
203           void                (*sc_intr_off)(struct sunscpal_softc *);
204 
205           int                 sc_flags; /* Misc. flags and capabilities */
206 #define   SUNSCPAL_DISABLE_DMA          1         /* Do not use DMA. */
207 
208           /* Set bits in this to disable parity for some target. */
209           int                 sc_parity_disable;
210 
211           int       sc_min_dma_len;     /* Smaller than this is done with PIO */
212 
213           /* Begin MI shared data */
214 
215           int                 sc_state;
216 #define   SUNSCPAL_IDLE                    0      /* Ready for new work. */
217 #define SUNSCPAL_WORKING      0x01      /* Some command is in progress. */
218 #define   SUNSCPAL_ABORTING   0x02      /* Bailing out */
219 #define SUNSCPAL_DOINGDMA     0x04      /* The FIFO data path is active! */
220 #define SUNSCPAL_DROP_MSGIN   0x10      /* Discard all msgs (parity err detected) */
221 
222           /* The request that has the bus now. */
223           struct              sunscpal_req *sc_current;
224 
225           /* Active data pointer for current SCSI command. */
226           uint8_t             *sc_dataptr;
227           int                 sc_datalen;
228           int                 sc_reqlen;
229 
230           /* Begin MI private data */
231 
232           /* The number of operations in progress on the bus */
233           volatile int        sc_ncmds;
234 
235           /* Ring buffer of pending/active requests */
236           struct              sunscpal_req sc_ring[SUNSCPAL_OPENINGS];
237           int                 sc_rr;              /* Round-robin scan pointer */
238 
239           /* Active requests, by target/LUN */
240           struct              sunscpal_req *sc_matrix[8][8];
241 
242           /* Message stuff */
243           int       sc_prevphase;
244 
245           u_int     sc_msgpriq;         /* Messages we want to send */
246           u_int     sc_msgoutq;         /* Messages sent during last MESSAGE OUT */
247           u_int     sc_msgout;          /* Message last transmitted */
248 #define SEND_DEV_RESET                  0x01
249 #define SEND_PARITY_ERROR     0x02
250 #define SEND_ABORT            0x04
251 #define SEND_REJECT           0x08
252 #define SEND_INIT_DET_ERR     0x10
253 #define SEND_IDENTIFY                   0x20
254 #define SEND_SDTR             0x40
255 #define   SEND_WDTR           0x80
256 #define SUNSCPAL_MAX_MSG_LEN 8
257           uint8_t   sc_omess[SUNSCPAL_MAX_MSG_LEN];
258           uint8_t   *sc_omp;            /* Outgoing message pointer */
259           uint8_t   sc_imess[SUNSCPAL_MAX_MSG_LEN];
260           uint8_t   *sc_imp;            /* Incoming message pointer */
261           int       sc_rev;                       /* Chip revision */
262 #define SUNSCPAL_VARIANT_501_1006       0
263 #define SUNSCPAL_VARIANT_501_1045       1
264 
265 };
266 
267 void      sunscpal_attach(struct sunscpal_softc *, int);
268 int       sunscpal_detach(struct sunscpal_softc *, int);
269 int       sunscpal_intr(void *);
270 void      sunscpal_scsipi_request(struct scsipi_channel *,
271                     scsipi_adapter_req_t, void *);
272 int       sunscpal_pio_in(struct sunscpal_softc *, int, int, uint8_t *);
273 int       sunscpal_pio_out(struct sunscpal_softc *, int, int, uint8_t *);
274 void      sunscpal_init(struct sunscpal_softc *);
275 
276 /* Options for no-parity, DMA, and interrupts. */
277 #define SUNSCPAL_OPT_NO_PARITY_CHK  0xff
278 #define SUNSCPAL_OPT_FORCE_POLLING 0x100
279 #define SUNSCPAL_OPT_DISABLE_DMA   0x200
280 
281 #ifdef    SUNSCPAL_DEBUG
282 struct sunscpal_softc *sunscpal_debug_sc;
283 void sunscpal_trace(char *msg, long val);
284 #define   SUNSCPAL_TRACE(msg, val) sunscpal_trace(msg, val)
285 #else     /* SUNSCPAL_DEBUG */
286 #define   SUNSCPAL_TRACE(msg, val)      /* nada */
287 #endif    /* SUNSCPAL_DEBUG */
288