1 /* $NetBSD: isp_sbus.c,v 1.78 2009/09/07 13:39:19 tsutsui Exp $ */
3 * SBus specific probe and attach routines for Qlogic ISP SCSI adapters.
5 * Copyright (C) 1997, 1998, 1999 National Aeronautics & Space Administration
8 * Additional Copyright (C) 2000-2007 by Matthew Jacob
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 #include <sys/cdefs.h>
36 __KERNEL_RCSID(0, "$NetBSD: isp_sbus.c,v 1.78 2009/09/07 13:39:19 tsutsui Exp $");
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/device.h>
41 #include <sys/kernel.h>
42 #include <sys/malloc.h>
43 #include <sys/queue.h>
44 #include <dev/ic/isp_netbsd.h>
46 #include <machine/autoconf.h>
47 #include <dev/sbus/sbusvar.h>
48 #include <sys/reboot.h>
50 static void isp_sbus_reset0(ispsoftc_t
*);
51 static void isp_sbus_reset1(ispsoftc_t
*);
52 static int isp_sbus_intr(void *);
54 isp_sbus_rd_isr(ispsoftc_t
*, uint32_t *, uint16_t *, uint16_t *);
55 static uint32_t isp_sbus_rd_reg(ispsoftc_t
*, int);
56 static void isp_sbus_wr_reg (ispsoftc_t
*, int, uint32_t);
57 static int isp_sbus_mbxdma(ispsoftc_t
*);
58 static int isp_sbus_dmasetup(ispsoftc_t
*, XS_T
*, void *);
59 static void isp_sbus_dmateardown(ispsoftc_t
*, XS_T
*, uint32_t);
61 #ifndef ISP_DISABLE_FW
62 #include <dev/microcode/isp/asm_sbus.h>
64 #define ISP_1000_RISC_CODE NULL
67 static const struct ispmdvec mdvec
= {
82 struct isp_sbussoftc
{
85 struct scsipi_channel sbus_chan
;
86 bus_space_tag_t sbus_bustag
;
87 bus_space_handle_t sbus_reg
;
90 struct ispmdvec sbus_mdvec
;
91 bus_dmamap_t
*sbus_dmamap
;
92 int16_t sbus_poff
[_NREG_BLKS
];
96 static int isp_match(device_t
, cfdata_t
, void *);
97 static void isp_sbus_attach(device_t
, device_t
, void *);
98 CFATTACH_DECL_NEW(isp_sbus
, sizeof (struct isp_sbussoftc
),
99 isp_match
, isp_sbus_attach
, NULL
, NULL
);
102 isp_match(device_t parent
, cfdata_t cf
, void *aux
)
105 struct sbus_attach_args
*sa
= aux
;
107 rv
= (strcmp(cf
->cf_name
, sa
->sa_name
) == 0 ||
108 strcmp("PTI,ptisp", sa
->sa_name
) == 0 ||
109 strcmp("ptisp", sa
->sa_name
) == 0 ||
110 strcmp("SUNW,isp", sa
->sa_name
) == 0 ||
111 strcmp("QLGC,isp", sa
->sa_name
) == 0);
118 isp_sbus_attach(device_t parent
, device_t self
, void *aux
)
120 int freq
, ispburst
, sbusburst
;
121 struct sbus_attach_args
*sa
= aux
;
122 struct isp_sbussoftc
*sbc
= device_private(self
);
123 struct sbus_softc
*sbsc
= device_private(parent
);
124 ispsoftc_t
*isp
= &sbc
->sbus_isp
;
126 isp
->isp_osinfo
.dev
= self
;
128 printf(" for %s\n", sa
->sa_name
);
130 isp
->isp_nchan
= isp
->isp_osinfo
.adapter
.adapt_nchannels
= 1;
132 sbc
->sbus_bustag
= sa
->sa_bustag
;
133 if (sa
->sa_nintr
!= 0)
134 sbc
->sbus_pri
= sa
->sa_pri
;
135 sbc
->sbus_mdvec
= mdvec
;
137 if (sa
->sa_npromvaddrs
) {
138 sbus_promaddr_to_handle(sa
->sa_bustag
,
139 sa
->sa_promvaddrs
[0], &sbc
->sbus_reg
);
141 if (sbus_bus_map(sa
->sa_bustag
, sa
->sa_slot
, sa
->sa_offset
,
142 sa
->sa_size
, 0, &sbc
->sbus_reg
) != 0) {
143 aprint_error_dev(self
, "cannot map registers\n");
147 sbc
->sbus_node
= sa
->sa_node
;
149 freq
= prom_getpropint(sa
->sa_node
, "clock-frequency", 0);
152 * Convert from HZ to MHz, rounding up.
154 freq
= (freq
+ 500000)/1000000;
156 sbc
->sbus_mdvec
.dv_clock
= freq
;
159 * Now figure out what the proper burst sizes, etc., to use.
160 * Unfortunately, there is no ddi_dma_burstsizes here which
161 * walks up the tree finding the limiting burst size node (if
164 sbusburst
= sbsc
->sc_burst
;
166 sbusburst
= SBUS_BURST_32
- 1;
167 ispburst
= prom_getpropint(sa
->sa_node
, "burst-sizes", -1);
168 if (ispburst
== -1) {
169 ispburst
= sbusburst
;
171 ispburst
&= sbusburst
;
172 ispburst
&= ~(1 << 7);
173 ispburst
&= ~(1 << 6);
174 sbc
->sbus_mdvec
.dv_conf1
= 0;
175 if (ispburst
& (1 << 5)) {
176 sbc
->sbus_mdvec
.dv_conf1
= BIU_SBUS_CONF1_FIFO_32
;
177 } else if (ispburst
& (1 << 4)) {
178 sbc
->sbus_mdvec
.dv_conf1
= BIU_SBUS_CONF1_FIFO_16
;
179 } else if (ispburst
& (1 << 3)) {
180 sbc
->sbus_mdvec
.dv_conf1
=
181 BIU_SBUS_CONF1_BURST8
| BIU_SBUS_CONF1_FIFO_8
;
183 if (sbc
->sbus_mdvec
.dv_conf1
) {
184 sbc
->sbus_mdvec
.dv_conf1
|= BIU_BURST_ENABLE
;
187 isp
->isp_mdvec
= &sbc
->sbus_mdvec
;
188 isp
->isp_bustype
= ISP_BT_SBUS
;
189 isp
->isp_type
= ISP_HA_SCSI_UNKNOWN
;
190 isp
->isp_param
= &sbc
->sbus_dev
;
191 isp
->isp_dmatag
= sa
->sa_dmatag
;
192 ISP_MEMZERO(isp
->isp_param
, sizeof (sdparam
));
193 isp
->isp_osinfo
.chan
= &sbc
->sbus_chan
;
195 sbc
->sbus_poff
[BIU_BLOCK
>> _BLK_REG_SHFT
] = BIU_REGS_OFF
;
196 sbc
->sbus_poff
[MBOX_BLOCK
>> _BLK_REG_SHFT
] = SBUS_MBOX_REGS_OFF
;
197 sbc
->sbus_poff
[SXP_BLOCK
>> _BLK_REG_SHFT
] = SBUS_SXP_REGS_OFF
;
198 sbc
->sbus_poff
[RISC_BLOCK
>> _BLK_REG_SHFT
] = SBUS_RISC_REGS_OFF
;
199 sbc
->sbus_poff
[DMA_BLOCK
>> _BLK_REG_SHFT
] = DMA_REGS_OFF
;
201 /* Establish interrupt channel */
202 bus_intr_establish(sbc
->sbus_bustag
, sbc
->sbus_pri
, IPL_BIO
,
206 * Set up logging levels.
208 #ifdef ISP_LOGDEFAULT
209 isp
->isp_dblev
= ISP_LOGDEFAULT
;
211 isp
->isp_dblev
= ISP_LOGWARN
|ISP_LOGERR
;
213 isp
->isp_dblev
|= ISP_LOGCONFIG
|ISP_LOGINFO
;
215 isp
->isp_dblev
|= ISP_LOGDEBUG1
|ISP_LOGDEBUG2
;
218 isp
->isp_dblev
|= ISP_LOGDEBUG0
;
222 isp
->isp_confopts
= device_cfdata(self
)->cf_flags
;
223 SDPARAM(isp
, 0)->role
= ISP_DEFAULT_ROLES
;
226 * There's no tool on sparc to set NVRAM for ISPs, so ignore it.
228 isp
->isp_confopts
|= ISP_CFG_NONVRAM
;
231 * Mark things if we're a PTI SBus adapter.
233 if (strcmp("PTI,ptisp", sa
->sa_name
) == 0 ||
234 strcmp("ptisp", sa
->sa_name
) == 0) {
235 SDPARAM(isp
, 0)->isp_ptisp
= 1;
239 if (isp
->isp_state
!= ISP_RESETSTATE
) {
243 ISP_ENABLE_INTS(isp
);
245 if (isp
->isp_state
!= ISP_INITSTATE
) {
260 isp_sbus_reset0(ispsoftc_t
*isp
)
262 ISP_DISABLE_INTS(isp
);
266 isp_sbus_reset1(ispsoftc_t
*isp
)
268 ISP_ENABLE_INTS(isp
);
272 isp_sbus_intr(void *arg
)
276 ispsoftc_t
*isp
= arg
;
278 if (ISP_READ_ISR(isp
, &isr
, &sema
, &mbox
) == 0) {
282 struct isp_sbussoftc
*sbc
= arg
;
283 sbc
->sbus_isp
.isp_osinfo
.onintstack
= 1;
284 isp_intr(isp
, isr
, sema
, mbox
);
285 sbc
->sbus_isp
.isp_osinfo
.onintstack
= 0;
290 #define IspVirt2Off(a, x) \
291 (((struct isp_sbussoftc *)a)->sbus_poff[((x) & _BLK_REG_MASK) >> \
292 _BLK_REG_SHFT] + ((x) & 0xff))
294 #define BXR2(sbc, off) \
295 bus_space_read_2(sbc->sbus_bustag, sbc->sbus_reg, off)
298 isp_sbus_rd_isr(ispsoftc_t
*isp
, uint32_t *isrp
,
299 uint16_t *semap
, uint16_t *mbp
)
301 struct isp_sbussoftc
*sbc
= (struct isp_sbussoftc
*) isp
;
305 isr
= BXR2(sbc
, IspVirt2Off(isp
, BIU_ISR
));
306 sema
= BXR2(sbc
, IspVirt2Off(isp
, BIU_SEMA
));
307 isp_prt(isp
, ISP_LOGDEBUG3
, "ISR 0x%x SEMA 0x%x", isr
, sema
);
308 isr
&= INT_PENDING_MASK(isp
);
309 sema
&= BIU_SEMA_LOCK
;
310 if (isr
== 0 && sema
== 0) {
314 if ((*semap
= sema
) != 0) {
315 *mbp
= BXR2(sbc
, IspVirt2Off(isp
, OUTMAILBOX0
));
321 isp_sbus_rd_reg(ispsoftc_t
*isp
, int regoff
)
323 struct isp_sbussoftc
*sbc
= (struct isp_sbussoftc
*) isp
;
324 int offset
= sbc
->sbus_poff
[(regoff
& _BLK_REG_MASK
) >> _BLK_REG_SHFT
];
325 offset
+= (regoff
& 0xff);
326 return (bus_space_read_2(sbc
->sbus_bustag
, sbc
->sbus_reg
, offset
));
330 isp_sbus_wr_reg(ispsoftc_t
*isp
, int regoff
, uint32_t val
)
332 struct isp_sbussoftc
*sbc
= (struct isp_sbussoftc
*) isp
;
333 int offset
= sbc
->sbus_poff
[(regoff
& _BLK_REG_MASK
) >> _BLK_REG_SHFT
];
334 offset
+= (regoff
& 0xff);
335 bus_space_write_2(sbc
->sbus_bustag
, sbc
->sbus_reg
, offset
, val
);
339 isp_sbus_mbxdma(ispsoftc_t
*isp
)
341 struct isp_sbussoftc
*sbc
= (struct isp_sbussoftc
*) isp
;
342 bus_dma_segment_t reqseg
, rspseg
;
343 int reqrs
, rsprs
, i
, progress
;
347 if (isp
->isp_rquest_dma
)
350 n
= isp
->isp_maxcmds
* sizeof (XS_T
*);
351 isp
->isp_xflist
= (XS_T
**) malloc(n
, M_DEVBUF
, M_WAITOK
);
352 if (isp
->isp_xflist
== NULL
) {
353 isp_prt(isp
, ISP_LOGERR
, "cannot alloc xflist array");
356 ISP_MEMZERO(isp
->isp_xflist
, n
);
357 n
= sizeof (bus_dmamap_t
) * isp
->isp_maxcmds
;
358 sbc
->sbus_dmamap
= (bus_dmamap_t
*) malloc(n
, M_DEVBUF
, M_WAITOK
);
359 if (sbc
->sbus_dmamap
== NULL
) {
360 free(isp
->isp_xflist
, M_DEVBUF
);
361 isp
->isp_xflist
= NULL
;
362 isp_prt(isp
, ISP_LOGERR
, "cannot alloc dmamap array");
365 for (i
= 0; i
< isp
->isp_maxcmds
; i
++) {
366 /* Allocate a DMA handle */
367 if (bus_dmamap_create(isp
->isp_dmatag
, MAXPHYS
, 1, MAXPHYS
,
368 1 << 24, BUS_DMA_NOWAIT
, &sbc
->sbus_dmamap
[i
]) != 0) {
369 isp_prt(isp
, ISP_LOGERR
, "cmd DMA maps create error");
373 if (i
< isp
->isp_maxcmds
) {
375 bus_dmamap_destroy(isp
->isp_dmatag
,
376 sbc
->sbus_dmamap
[i
]);
378 free(isp
->isp_xflist
, M_DEVBUF
);
379 free(sbc
->sbus_dmamap
, M_DEVBUF
);
380 isp
->isp_xflist
= NULL
;
381 sbc
->sbus_dmamap
= NULL
;
386 * Allocate and map the request and response queues
389 len
= ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp
));
390 if (bus_dmamem_alloc(isp
->isp_dmatag
, len
, 0, 0, &reqseg
, 1, &reqrs
,
395 if (bus_dmamem_map(isp
->isp_dmatag
, &reqseg
, reqrs
, len
,
396 (void *)&isp
->isp_rquest
, BUS_DMA_NOWAIT
|BUS_DMA_COHERENT
)) {
400 if (bus_dmamap_create(isp
->isp_dmatag
, len
, 1, len
, 1 << 24,
401 BUS_DMA_NOWAIT
, &isp
->isp_rqdmap
) != 0) {
405 if (bus_dmamap_load(isp
->isp_dmatag
, isp
->isp_rqdmap
,
406 isp
->isp_rquest
, len
, NULL
, BUS_DMA_NOWAIT
) != 0) {
410 isp
->isp_rquest_dma
= isp
->isp_rqdmap
->dm_segs
[0].ds_addr
;
412 len
= ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp
));
413 if (bus_dmamem_alloc(isp
->isp_dmatag
, len
, 0, 0, &rspseg
, 1, &rsprs
,
418 if (bus_dmamem_map(isp
->isp_dmatag
, &rspseg
, rsprs
, len
,
419 (void *)&isp
->isp_result
, BUS_DMA_NOWAIT
|BUS_DMA_COHERENT
)) {
423 if (bus_dmamap_create(isp
->isp_dmatag
, len
, 1, len
, 1 << 24,
424 BUS_DMA_NOWAIT
, &isp
->isp_rsdmap
) != 0) {
428 if (bus_dmamap_load(isp
->isp_dmatag
, isp
->isp_rsdmap
,
429 isp
->isp_result
, len
, NULL
, BUS_DMA_NOWAIT
) != 0) {
432 isp
->isp_result_dma
= isp
->isp_rsdmap
->dm_segs
[0].ds_addr
;
437 isp_prt(isp
, ISP_LOGERR
, "Mailbox DMA Setup Failure");
440 bus_dmamap_unload(isp
->isp_dmatag
, isp
->isp_rsdmap
);
443 bus_dmamap_destroy(isp
->isp_dmatag
, isp
->isp_rsdmap
);
446 bus_dmamem_unmap(isp
->isp_dmatag
,
447 isp
->isp_result
, ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp
)));
450 bus_dmamem_free(isp
->isp_dmatag
, &rspseg
, rsprs
);
454 bus_dmamap_unload(isp
->isp_dmatag
, isp
->isp_rqdmap
);
457 bus_dmamap_destroy(isp
->isp_dmatag
, isp
->isp_rqdmap
);
460 bus_dmamem_unmap(isp
->isp_dmatag
,
461 isp
->isp_rquest
, ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp
)));
464 bus_dmamem_free(isp
->isp_dmatag
, &reqseg
, reqrs
);
467 for (i
= 0; i
< isp
->isp_maxcmds
; i
++) {
468 bus_dmamap_destroy(isp
->isp_dmatag
, sbc
->sbus_dmamap
[i
]);
470 free(sbc
->sbus_dmamap
, M_DEVBUF
);
471 free(isp
->isp_xflist
, M_DEVBUF
);
472 isp
->isp_xflist
= NULL
;
473 sbc
->sbus_dmamap
= NULL
;
479 * We're guaranteed that rq->req_handle is a value from 1 to isp->isp_maxcmds.
483 isp_sbus_dmasetup(struct ispsoftc
*isp
, struct scsipi_xfer
*xs
, void *arg
)
485 struct isp_sbussoftc
*sbc
= (struct isp_sbussoftc
*)isp
;
488 bus_dma_segment_t
*dm_segs
;
492 dmap
= sbc
->sbus_dmamap
[isp_handle_index(rq
->req_handle
)];
493 if (xs
->datalen
== 0) {
501 if (xs
->xs_control
& XS_CTL_DATA_IN
) {
502 flg2
= BUS_DMASYNC_PREREAD
;
504 ddir
= ISP_FROM_DEVICE
;
506 flg2
= BUS_DMASYNC_PREWRITE
;
507 flag
= BUS_DMA_WRITE
;
508 ddir
= ISP_TO_DEVICE
;
510 error
= bus_dmamap_load(isp
->isp_dmatag
, dmap
, xs
->data
, xs
->datalen
,
511 NULL
, ((xs
->xs_control
& XS_CTL_NOSLEEP
) ? BUS_DMA_NOWAIT
: BUS_DMA_WAITOK
) | BUS_DMA_STREAMING
| flag
);
513 isp_prt(isp
, ISP_LOGWARN
, "unable to load DMA (%d)", error
);
514 XS_SETERR(xs
, HBA_BOTCH
);
515 if (error
== EAGAIN
|| error
== ENOMEM
) {
518 return (CMD_COMPLETE
);
521 dm_segs
= dmap
->dm_segs
;
522 nsegs
= dmap
->dm_nsegs
;
523 bus_dmamap_sync(isp
->isp_dmatag
, dmap
, 0, dmap
->dm_mapsize
, flg2
);
526 if (isp_send_cmd(isp
, rq
, dm_segs
, nsegs
, xs
->datalen
, ddir
) != CMD_QUEUED
) {
534 isp_sbus_dmateardown(ispsoftc_t
*isp
, XS_T
*xs
, uint32_t handle
)
536 struct isp_sbussoftc
*sbc
= (struct isp_sbussoftc
*) isp
;
539 dmap
= sbc
->sbus_dmamap
[isp_handle_index(handle
)];
541 if (dmap
->dm_nsegs
== 0) {
542 panic("%s: DMA map not already allocated",
543 device_xname(isp
->isp_osinfo
.dev
));
546 bus_dmamap_sync(isp
->isp_dmatag
, dmap
, 0,
547 xs
->datalen
, (xs
->xs_control
& XS_CTL_DATA_IN
)?
548 BUS_DMASYNC_POSTREAD
: BUS_DMASYNC_POSTWRITE
);
549 bus_dmamap_unload(isp
->isp_dmatag
, dmap
);