]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/dev/isp/isp_sbus.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / sys / dev / isp / isp_sbus.c
1 /*-
2  * Copyright (c) 1997-2006 by Matthew Jacob
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice immediately at the beginning of the file, without modification,
10  *    this list of conditions, and the following disclaimer.
11  * 2. The name of the author may not be used to endorse or promote products
12  *    derived from this software without specific prior written permission.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
18  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 /*
27  * SBus specific probe and attach routines for Qlogic ISP SCSI adapters.
28  * FreeBSD Version.
29  */
30
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #if __FreeBSD_version >= 700000
37 #include <sys/linker.h>
38 #include <sys/firmware.h>
39 #endif
40 #include <sys/bus.h>
41 #include <sys/kernel.h>
42 #include <sys/module.h>
43 #include <sys/resource.h>
44
45 #include <dev/ofw/ofw_bus.h>
46
47 #include <machine/bus.h>
48 #include <machine/resource.h>
49 #include <sys/rman.h>
50 #include <sparc64/sbus/sbusvar.h>
51
52 #include <dev/isp/isp_freebsd.h>
53
54 static uint32_t
55 isp_sbus_rd_reg(ispsoftc_t *, int);
56 static void
57 isp_sbus_wr_reg(ispsoftc_t *, int, uint32_t);
58 static int
59 isp_sbus_rd_isr(ispsoftc_t *, uint32_t *, uint16_t *, uint16_t *);
60 static int isp_sbus_mbxdma(ispsoftc_t *);
61 static int
62 isp_sbus_dmasetup(ispsoftc_t *, XS_T *, ispreq_t *, uint32_t *, uint32_t);
63
64 static void isp_sbus_reset0(ispsoftc_t *);
65 static void isp_sbus_reset1(ispsoftc_t *);
66 static void isp_sbus_dumpregs(ispsoftc_t *, const char *);
67
68 static struct ispmdvec mdvec = {
69         isp_sbus_rd_isr,
70         isp_sbus_rd_reg,
71         isp_sbus_wr_reg,
72         isp_sbus_mbxdma,
73         isp_sbus_dmasetup,
74         isp_common_dmateardown,
75         isp_sbus_reset0,
76         isp_sbus_reset1,
77         isp_sbus_dumpregs,
78         NULL,
79         BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64
80 };
81
82 static int isp_sbus_probe (device_t);
83 static int isp_sbus_attach (device_t);
84
85
86 #define ISP_SBD(isp)    ((struct isp_sbussoftc *)isp)->sbus_dev
87 struct isp_sbussoftc {
88         ispsoftc_t                      sbus_isp;
89         device_t                        sbus_dev;
90         struct resource *               sbus_reg;
91         void *                          ih;
92         int16_t                         sbus_poff[_NREG_BLKS];
93         sdparam                         sbus_param;
94         struct ispmdvec                 sbus_mdvec;
95         struct resource *               sbus_ires;
96 };
97
98
99 static device_method_t isp_sbus_methods[] = {
100         /* Device interface */
101         DEVMETHOD(device_probe,         isp_sbus_probe),
102         DEVMETHOD(device_attach,        isp_sbus_attach),
103         { 0, 0 }
104 };
105
106 static driver_t isp_sbus_driver = {
107         "isp", isp_sbus_methods, sizeof (struct isp_sbussoftc)
108 };
109 static devclass_t isp_devclass;
110 DRIVER_MODULE(isp, sbus, isp_sbus_driver, isp_devclass, 0, 0);
111 #if __FreeBSD_version < 700000
112 extern ispfwfunc *isp_get_firmware_p;
113 #endif
114
115 static int
116 isp_sbus_probe(device_t dev)
117 {
118         int found = 0;
119         const char *name = ofw_bus_get_name(dev);
120         if (strcmp(name, "SUNW,isp") == 0 ||
121             strcmp(name, "QLGC,isp") == 0 ||
122             strcmp(name, "ptisp") == 0 ||
123             strcmp(name, "PTI,ptisp") == 0) {
124                 found++;
125         }
126         if (!found)
127                 return (ENXIO);
128         
129         if (isp_announced == 0 && bootverbose) {
130                 printf("Qlogic ISP Driver, FreeBSD Version %d.%d, "
131                     "Core Version %d.%d\n",
132                     ISP_PLATFORM_VERSION_MAJOR, ISP_PLATFORM_VERSION_MINOR,
133                     ISP_CORE_VERSION_MAJOR, ISP_CORE_VERSION_MINOR);
134                 isp_announced++;
135         }
136         return (0);
137 }
138
139 static int
140 isp_sbus_attach(device_t dev)
141 {
142         struct resource *regs;
143         int tval, iqd, isp_debug, role, rid, ispburst;
144         struct isp_sbussoftc *sbs;
145         ispsoftc_t *isp = NULL;
146         int locksetup = 0;
147         int ints_setup = 0;
148
149         /*
150          * Figure out if we're supposed to skip this one.
151          * If we are, we actually go to ISP_ROLE_NONE.
152          */
153
154         tval = 0;
155         if (resource_int_value(device_get_name(dev), device_get_unit(dev),
156             "disable", &tval) == 0 && tval) {
157                 device_printf(dev, "device is disabled\n");
158                 /* but return 0 so the !$)$)*!$*) unit isn't reused */
159                 return (0);
160         }
161         
162         role = 0;
163         if (resource_int_value(device_get_name(dev), device_get_unit(dev),
164             "role", &role) == 0 &&
165             ((role & ~(ISP_ROLE_INITIATOR|ISP_ROLE_TARGET)) == 0)) {
166                 device_printf(dev, "setting role to 0x%x\n", role);
167         } else {
168 #ifdef  ISP_TARGET_MODE
169                 role = ISP_ROLE_INITIATOR|ISP_ROLE_TARGET;
170 #else
171                 role = ISP_DEFAULT_ROLES;
172 #endif
173         }
174
175         sbs = malloc(sizeof (*sbs), M_DEVBUF, M_NOWAIT | M_ZERO);
176         if (sbs == NULL) {
177                 device_printf(dev, "cannot allocate softc\n");
178                 return (ENOMEM);
179         }
180
181         regs = NULL;
182         iqd = 0;
183         rid = 0;
184         regs = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
185         if (regs == 0) {
186                 device_printf(dev, "unable to map registers\n");
187                 goto bad;
188         }
189         sbs->sbus_dev = dev;
190         sbs->sbus_reg = regs;
191         sbs->sbus_mdvec = mdvec;
192
193         sbs->sbus_poff[BIU_BLOCK >> _BLK_REG_SHFT] = BIU_REGS_OFF;
194         sbs->sbus_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = SBUS_MBOX_REGS_OFF;
195         sbs->sbus_poff[SXP_BLOCK >> _BLK_REG_SHFT] = SBUS_SXP_REGS_OFF;
196         sbs->sbus_poff[RISC_BLOCK >> _BLK_REG_SHFT] = SBUS_RISC_REGS_OFF;
197         sbs->sbus_poff[DMA_BLOCK >> _BLK_REG_SHFT] = DMA_REGS_OFF;
198         isp = &sbs->sbus_isp;
199         isp->isp_bus_tag = rman_get_bustag(regs);
200         isp->isp_bus_handle = rman_get_bushandle(regs);
201         isp->isp_mdvec = &sbs->sbus_mdvec;
202         isp->isp_bustype = ISP_BT_SBUS;
203         isp->isp_type = ISP_HA_SCSI_UNKNOWN;
204         isp->isp_param = &sbs->sbus_param;
205         isp->isp_revision = 0;  /* XXX */
206         isp->isp_role = role;
207         isp->isp_dev = dev;
208
209         /*
210          * Get the clock frequency and convert it from HZ to MHz,
211          * rounding up. This defaults to 25MHz if there isn't a
212          * device specific one in the OFW device tree.
213          */
214         sbs->sbus_mdvec.dv_clock = (sbus_get_clockfreq(dev) + 500000)/1000000;
215
216         /*
217          * Now figure out what the proper burst sizes, etc., to use.
218          * Unfortunately, there is no ddi_dma_burstsizes here which
219          * walks up the tree finding the limiting burst size node (if
220          * any). We just use what's here for isp.
221          */
222         ispburst = sbus_get_burstsz(dev);
223         if (ispburst == 0) {
224                 ispburst = SBUS_BURST_32 - 1;
225         }
226         sbs->sbus_mdvec.dv_conf1 =  0;
227         if (ispburst & (1 << 5)) {
228                 sbs->sbus_mdvec.dv_conf1 = BIU_SBUS_CONF1_FIFO_32;
229         } else if (ispburst & (1 << 4)) {
230                 sbs->sbus_mdvec.dv_conf1 = BIU_SBUS_CONF1_FIFO_16;
231         } else if (ispburst & (1 << 3)) {
232                 sbs->sbus_mdvec.dv_conf1 =
233                     BIU_SBUS_CONF1_BURST8 | BIU_SBUS_CONF1_FIFO_8;
234         }
235         if (sbs->sbus_mdvec.dv_conf1) {
236                 sbs->sbus_mdvec.dv_conf1 |= BIU_BURST_ENABLE;
237         }
238
239         /*
240          * We don't trust NVRAM on SBus cards
241          */
242         isp->isp_confopts |= ISP_CFG_NONVRAM;
243
244         /*
245          * Mark things if we're a PTI SBus adapter.
246          */
247         if (strcmp("PTI,ptisp", ofw_bus_get_name(dev)) == 0 ||
248             strcmp("ptisp", ofw_bus_get_name(dev)) == 0) {
249                 SDPARAM(isp)->isp_ptisp = 1;
250         }
251
252
253 #if __FreeBSD_version >= 700000
254         isp->isp_osinfo.fw = firmware_get("isp_1000");
255         if (isp->isp_osinfo.fw) {
256                 union {
257                         const void *cp;
258                         uint16_t *sp;
259                 } stupid;
260                 stupid.cp = isp->isp_osinfo.fw->data;
261                 isp->isp_mdvec->dv_ispfw = stupid.sp;
262         }
263 #else
264         /*
265          * Try and find firmware for this device.
266          */
267         if (isp_get_firmware_p) {
268                 (*isp_get_firmware_p)(0, 0, 0x1000, &sbs->sbus_mdvec.dv_ispfw);
269         }
270 #endif
271
272         tval = 0;
273         if (resource_int_value(device_get_name(dev), device_get_unit(dev),
274             "fwload_disable", &tval) == 0 && tval != 0) {
275                 isp->isp_confopts |= ISP_CFG_NORELOAD;
276         }
277
278         isp->isp_osinfo.default_id = -1;
279         if (resource_int_value(device_get_name(dev), device_get_unit(dev),
280             "iid", &tval) == 0) {
281                 isp->isp_osinfo.default_id = tval;
282                 isp->isp_confopts |= ISP_CFG_OWNLOOPID;
283         }
284         if (isp->isp_osinfo.default_id == -1) {
285                 /*
286                  * XXX: should be a way to get properties w/o having
287                  * XXX: to call OF_xxx functions
288                  */
289                 isp->isp_osinfo.default_id = 7;
290         }
291
292         isp_debug = 0;
293         (void) resource_int_value(device_get_name(dev), device_get_unit(dev),
294             "debug", &isp_debug);
295
296         /* Make sure the lock is set up. */
297         mtx_init(&isp->isp_osinfo.lock, "isp", NULL, MTX_DEF);
298         locksetup++;
299
300         iqd = 0;
301         sbs->sbus_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &iqd,
302             RF_ACTIVE | RF_SHAREABLE);
303         if (sbs->sbus_ires == NULL) {
304                 device_printf(dev, "could not allocate interrupt\n");
305                 goto bad;
306         }
307
308         if (isp_setup_intr(dev, sbs->sbus_ires, ISP_IFLAGS, NULL,
309             isp_platform_intr, isp, &sbs->ih)) {
310                 device_printf(dev, "could not setup interrupt\n");
311                 goto bad;
312         }
313         ints_setup++;
314
315         /*
316          * Set up logging levels.
317          */
318         if (isp_debug) {
319                 isp->isp_dblev = isp_debug;
320         } else {
321                 isp->isp_dblev = ISP_LOGWARN|ISP_LOGERR;
322         }
323         if (bootverbose) {
324                 isp->isp_dblev |= ISP_LOGCONFIG|ISP_LOGINFO;
325         }
326
327         /*
328          * Make sure we're in reset state.
329          */
330         ISP_LOCK(isp);
331         isp_reset(isp);
332         if (isp->isp_state != ISP_RESETSTATE) {
333                 isp_uninit(isp);
334                 ISP_UNLOCK(isp);
335                 goto bad;
336         }
337         isp_init(isp);
338         if (isp->isp_role != ISP_ROLE_NONE && isp->isp_state != ISP_INITSTATE) {
339                 isp_uninit(isp);
340                 ISP_UNLOCK(isp);
341                 goto bad;
342         }
343         isp_attach(isp);
344         if (isp->isp_role != ISP_ROLE_NONE && isp->isp_state != ISP_RUNSTATE) {
345                 isp_uninit(isp);
346                 ISP_UNLOCK(isp);
347                 goto bad;
348         }
349         ISP_UNLOCK(isp);
350         return (0);
351
352 bad:
353
354         if (sbs && ints_setup) {
355                 (void) bus_teardown_intr(dev, sbs->sbus_ires, sbs->ih);
356         }
357
358         if (sbs && sbs->sbus_ires) {
359                 bus_release_resource(dev, SYS_RES_IRQ, iqd, sbs->sbus_ires);
360         }
361
362         if (locksetup && isp) {
363                 mtx_destroy(&isp->isp_osinfo.lock);
364         }
365
366         if (regs) {
367                 (void) bus_release_resource(dev, 0, 0, regs);
368         }
369
370         if (sbs) {
371                 if (sbs->sbus_isp.isp_param) {
372                         free(sbs->sbus_isp.isp_param, M_DEVBUF);
373                 }
374                 free(sbs, M_DEVBUF);
375         }
376         return (ENXIO);
377 }
378
379 #define IspVirt2Off(a, x)       \
380         (((struct isp_sbussoftc *)a)->sbus_poff[((x) & _BLK_REG_MASK) >> \
381         _BLK_REG_SHFT] + ((x) & 0xff))
382
383 #define BXR2(sbc, off)          \
384         bus_space_read_2(isp->isp_bus_tag, isp->isp_bus_handle, off)
385
386 static int
387 isp_sbus_rd_isr(ispsoftc_t *isp, uint32_t *isrp, uint16_t *semap, uint16_t *mbp)
388 {
389         uint16_t isr, sema;
390
391         isr = BXR2(sbc, IspVirt2Off(isp, BIU_ISR));
392         sema = BXR2(sbc, IspVirt2Off(isp, BIU_SEMA));
393         isp_prt(isp, ISP_LOGDEBUG3, "ISR 0x%x SEMA 0x%x", isr, sema);
394         isr &= INT_PENDING_MASK(isp);
395         sema &= BIU_SEMA_LOCK;
396         if (isr == 0 && sema == 0) {
397                 return (0);
398         }
399         *isrp = isr;
400         if ((*semap = sema) != 0) {
401                 *mbp = BXR2(sbc, IspVirt2Off(isp, OUTMAILBOX0));
402         }
403         return (1);
404 }
405
406 static uint32_t
407 isp_sbus_rd_reg(ispsoftc_t *isp, int regoff)
408 {
409         uint16_t rval;
410         struct isp_sbussoftc *sbs = (struct isp_sbussoftc *) isp;
411         int offset = sbs->sbus_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT];
412         offset += (regoff & 0xff);
413         rval = bus_space_read_2(isp->isp_bus_tag, isp->isp_bus_handle, offset);
414         isp_prt(isp, ISP_LOGDEBUG3,
415             "isp_sbus_rd_reg(off %x) = %x", regoff, rval);
416         return (rval);
417 }
418
419 static void
420 isp_sbus_wr_reg(ispsoftc_t *isp, int regoff, uint32_t val)
421 {
422         struct isp_sbussoftc *sbs = (struct isp_sbussoftc *) isp;
423         int offset = sbs->sbus_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT];
424         offset += (regoff & 0xff);
425         isp_prt(isp, ISP_LOGDEBUG3,
426             "isp_sbus_wr_reg(off %x) = %x", regoff, val);
427         bus_space_write_2(isp->isp_bus_tag, isp->isp_bus_handle, offset, val);
428         MEMORYBARRIER(isp, SYNC_REG, offset, 2);
429 }
430
431 struct imush {
432         ispsoftc_t *isp;
433         int error;
434 };
435
436 static void imc(void *, bus_dma_segment_t *, int, int);
437
438 static void
439 imc(void *arg, bus_dma_segment_t *segs, int nseg, int error)
440 {
441         struct imush *imushp = (struct imush *) arg;
442         if (error) {
443                 imushp->error = error;
444         } else {
445                 ispsoftc_t *isp =imushp->isp;
446                 bus_addr_t addr = segs->ds_addr;
447
448                 isp->isp_rquest_dma = addr;
449                 addr += ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp));
450                 isp->isp_result_dma = addr;
451         }
452 }
453
454 static int
455 isp_sbus_mbxdma(ispsoftc_t *isp)
456 {
457         caddr_t base;
458         uint32_t len;
459         int i, error, ns;
460         struct imush im;
461
462         /*
463          * Already been here? If so, leave...
464          */
465         if (isp->isp_rquest) {
466                 return (0);
467         }
468
469         ISP_UNLOCK(isp);
470
471         len = sizeof (struct isp_pcmd) * isp->isp_maxcmds;
472         isp->isp_osinfo.pcmd_pool = (struct isp_pcmd *)
473             malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
474         if (isp->isp_osinfo.pcmd_pool == NULL) {
475                 isp_prt(isp, ISP_LOGERR, "cannot alloc pcmd pool");
476                 ISP_LOCK(isp);
477                 return (1);
478         }
479
480         len = sizeof (XS_T **) * isp->isp_maxcmds;
481         isp->isp_xflist = (XS_T **) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
482         if (isp->isp_xflist == NULL) {
483                 isp_prt(isp, ISP_LOGERR, "cannot alloc xflist array");
484                 ISP_LOCK(isp);
485                 return (1);
486         }
487         len = sizeof (bus_dmamap_t) * isp->isp_maxcmds;
488
489         if (isp_dma_tag_create(BUS_DMA_ROOTARG(ISP_SBD(isp)), 1,
490             BUS_SPACE_MAXADDR_24BIT+1, BUS_SPACE_MAXADDR_32BIT,
491             BUS_SPACE_MAXADDR_32BIT, NULL, NULL, BUS_SPACE_MAXSIZE_32BIT,
492             ISP_NSEGS, BUS_SPACE_MAXADDR_24BIT, 0, &isp->isp_osinfo.dmat)) {
493                 isp_prt(isp, ISP_LOGERR, "could not create master dma tag");
494                 free(isp->isp_osinfo.pcmd_pool, M_DEVBUF);
495                 free(isp->isp_xflist, M_DEVBUF);
496                 ISP_LOCK(isp);
497                 return(1);
498         }
499
500         /*
501          * Allocate and map the request, result queues, plus FC scratch area.
502          */
503         len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp));
504         len += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp));
505
506         ns = (len / PAGE_SIZE) + 1;
507         if (isp_dma_tag_create(isp->isp_osinfo.dmat, QENTRY_LEN,
508             BUS_SPACE_MAXADDR_24BIT+1, BUS_SPACE_MAXADDR_32BIT,
509             BUS_SPACE_MAXADDR_32BIT, NULL, NULL, len, ns,
510             BUS_SPACE_MAXADDR_24BIT, 0, &isp->isp_cdmat)) {
511                 isp_prt(isp, ISP_LOGERR,
512                     "cannot create a dma tag for control spaces");
513                 free(isp->isp_osinfo.pcmd_pool, M_DEVBUF);
514                 free(isp->isp_xflist, M_DEVBUF);
515                 ISP_LOCK(isp);
516                 return (1);
517         }
518
519         if (bus_dmamem_alloc(isp->isp_cdmat, (void **)&base, BUS_DMA_NOWAIT,
520             &isp->isp_cdmap) != 0) {
521                 isp_prt(isp, ISP_LOGERR,
522                     "cannot allocate %d bytes of CCB memory", len);
523                 bus_dma_tag_destroy(isp->isp_cdmat);
524                 free(isp->isp_osinfo.pcmd_pool, M_DEVBUF);
525                 free(isp->isp_xflist, M_DEVBUF);
526                 ISP_LOCK(isp);
527                 return (1);
528         }
529
530         for (i = 0; i < isp->isp_maxcmds; i++) {
531                 struct isp_pcmd *pcmd = &isp->isp_osinfo.pcmd_pool[i];
532                 error = bus_dmamap_create(isp->isp_osinfo.dmat, 0, &pcmd->dmap);
533                 if (error) {
534                         isp_prt(isp, ISP_LOGERR,
535                             "error %d creating per-cmd DMA maps", error);
536                         while (--i >= 0) {
537                                 bus_dmamap_destroy(isp->isp_osinfo.dmat,
538                                     isp->isp_osinfo.pcmd_pool[i].dmap);
539                         }
540                         goto bad;
541                 }
542                 isp_callout_init(&pcmd->wdog);
543                 if (i == isp->isp_maxcmds-1) {
544                         pcmd->next = NULL;
545                 } else {
546                         pcmd->next = &isp->isp_osinfo.pcmd_pool[i+1];
547                 }
548         }
549         isp->isp_osinfo.pcmd_free = &isp->isp_osinfo.pcmd_pool[0];
550
551         im.isp = isp;
552         im.error = 0;
553         bus_dmamap_load(isp->isp_cdmat, isp->isp_cdmap, base, len, imc, &im, 0);
554         if (im.error) {
555                 isp_prt(isp, ISP_LOGERR,
556                     "error %d loading dma map for control areas", im.error);
557                 goto bad;
558         }
559
560         isp->isp_rquest = base;
561         base += ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp));
562         isp->isp_result = base;
563         ISP_LOCK(isp);
564         return (0);
565
566 bad:
567         bus_dmamem_free(isp->isp_cdmat, base, isp->isp_cdmap);
568         bus_dma_tag_destroy(isp->isp_cdmat);
569         free(isp->isp_xflist, M_DEVBUF);
570         free(isp->isp_osinfo.pcmd_pool, M_DEVBUF);
571         isp->isp_rquest = NULL;
572         ISP_LOCK(isp);
573         return (1);
574 }
575
576 typedef struct {
577         ispsoftc_t *isp;
578         void *cmd_token;
579         void *rq;
580         uint32_t *nxtip;
581         uint32_t optr;
582         int error;
583 } mush_t;
584
585 #define MUSHERR_NOQENTRIES      -2
586
587
588 static void dma2(void *, bus_dma_segment_t *, int, int);
589
590 static void
591 dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
592 {
593         mush_t *mp;
594         ispsoftc_t *isp;
595         struct ccb_scsiio *csio;
596         bus_dma_segment_t *eseg;
597         ispreq_t *rq;
598         int seglim, datalen;
599         uint16_t nxti;
600
601         mp = (mush_t *) arg;
602         if (error) {
603                 mp->error = error;
604                 return;
605         }
606
607         if (nseg < 1) {
608                 isp_prt(mp->isp, ISP_LOGERR, "bad segment count (%d)", nseg);
609                 mp->error = EFAULT;
610                 return;
611         }
612         csio = mp->cmd_token;
613         isp = mp->isp;
614         rq = mp->rq;
615         nxti = *mp->nxtip;
616
617         if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
618                 bus_dmamap_sync(isp->isp_osinfo.dmat,
619                     PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREREAD);
620         } else {
621                 bus_dmamap_sync(isp->isp_osinfo.dmat,
622                     PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREWRITE);
623         }
624
625         datalen = XS_XFRLEN(csio);
626
627         /*
628          * We're passed an initial partially filled in entry that
629          * has most fields filled in except for data transfer
630          * related values.
631          *
632          * Our job is to fill in the initial request queue entry and
633          * then to start allocating and filling in continuation entries
634          * until we've covered the entire transfer.
635          */
636
637         if (csio->cdb_len > 12) {
638                 seglim = 0;
639         } else {
640                 seglim = ISP_RQDSEG;
641         }
642         if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
643                 rq->req_flags |= REQFLAG_DATA_IN;
644         } else {
645                 rq->req_flags |= REQFLAG_DATA_OUT;
646         }
647
648         eseg = dm_segs + nseg;
649
650         while (datalen != 0 && rq->req_seg_count < seglim && dm_segs != eseg) {
651                 rq->req_dataseg[rq->req_seg_count].ds_base = dm_segs->ds_addr;
652                 rq->req_dataseg[rq->req_seg_count].ds_count = dm_segs->ds_len;
653                 datalen -= dm_segs->ds_len;
654                 rq->req_seg_count++;
655                 dm_segs++;
656         }
657
658         while (datalen > 0 && dm_segs != eseg) {
659                 uint16_t onxti;
660                 ispcontreq_t local, *crq = &local, *cqe;
661
662                 cqe = (ispcontreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, nxti);
663                 onxti = nxti;
664                 nxti = ISP_NXT_QENTRY(onxti, RQUEST_QUEUE_LEN(isp));
665                 if (nxti == mp->optr) {
666                         isp_prt(isp, ISP_LOGDEBUG0, "Request Queue Overflow++");
667                         mp->error = MUSHERR_NOQENTRIES;
668                         return;
669                 }
670                 rq->req_header.rqs_entry_count++;
671                 MEMZERO((void *)crq, sizeof (*crq));
672                 crq->req_header.rqs_entry_count = 1;
673                 crq->req_header.rqs_entry_type = RQSTYPE_DATASEG;
674
675                 seglim = 0;
676                 while (datalen > 0 && seglim < ISP_CDSEG && dm_segs != eseg) {
677                         crq->req_dataseg[seglim].ds_base =
678                             dm_segs->ds_addr;
679                         crq->req_dataseg[seglim].ds_count =
680                             dm_segs->ds_len;
681                         rq->req_seg_count++;
682                         dm_segs++;
683                         seglim++;
684                         datalen -= dm_segs->ds_len;
685                 }
686                 isp_put_cont_req(isp, crq, cqe);
687                 MEMORYBARRIER(isp, SYNC_REQUEST, onxti, QENTRY_LEN);
688         }
689         *mp->nxtip = nxti;
690 }
691
692 static int
693 isp_sbus_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, ispreq_t *rq,
694         uint32_t *nxtip, uint32_t optr)
695 {
696         ispreq_t *qep;
697         mush_t mush, *mp;
698         void (*eptr)(void *, bus_dma_segment_t *, int, int);
699
700         qep = (ispreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, isp->isp_reqidx);
701         eptr = dma2;
702
703
704         if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE ||
705             (csio->dxfer_len == 0)) {
706                 rq->req_seg_count = 1;
707                 goto mbxsync;
708         }
709
710         /*
711          * Do a virtual grapevine step to collect info for
712          * the callback dma allocation that we have to use...
713          */
714         mp = &mush;
715         mp->isp = isp;
716         mp->cmd_token = csio;
717         mp->rq = rq;
718         mp->nxtip = nxtip;
719         mp->optr = optr;
720         mp->error = 0;
721
722         if ((csio->ccb_h.flags & CAM_SCATTER_VALID) == 0) {
723                 if ((csio->ccb_h.flags & CAM_DATA_PHYS) == 0) {
724                         int error = bus_dmamap_load(isp->isp_osinfo.dmat,
725                             PISP_PCMD(csio)->dmap, csio->data_ptr,
726                             csio->dxfer_len, eptr, mp, 0);
727                         if (error == EINPROGRESS) {
728                                 bus_dmamap_unload(isp->isp_osinfo.dmat,
729                                     PISP_PCMD(csio)->dmap);
730                                 mp->error = EINVAL;
731                                 isp_prt(isp, ISP_LOGERR,
732                                     "deferred dma allocation not supported");
733                         } else if (error && mp->error == 0) {
734 #ifdef  DIAGNOSTIC
735                                 isp_prt(isp, ISP_LOGERR,
736                                     "error %d in dma mapping code", error);
737 #endif
738                                 mp->error = error;
739                         }
740                 } else {
741                         /* Pointer to physical buffer */
742                         struct bus_dma_segment seg;
743                         seg.ds_addr = (bus_addr_t)csio->data_ptr;
744                         seg.ds_len = csio->dxfer_len;
745                         (*eptr)(mp, &seg, 1, 0);
746                 }
747         } else {
748                 struct bus_dma_segment *segs;
749
750                 if ((csio->ccb_h.flags & CAM_DATA_PHYS) != 0) {
751                         isp_prt(isp, ISP_LOGERR,
752                             "Physical segment pointers unsupported");
753                         mp->error = EINVAL;
754                 } else if ((csio->ccb_h.flags & CAM_SG_LIST_PHYS) == 0) {
755                         isp_prt(isp, ISP_LOGERR,
756                             "Virtual segment addresses unsupported");
757                         mp->error = EINVAL;
758                 } else {
759                         /* Just use the segments provided */
760                         segs = (struct bus_dma_segment *) csio->data_ptr;
761                         (*eptr)(mp, segs, csio->sglist_cnt, 0);
762                 }
763         }
764         if (mp->error) {
765                 int retval = CMD_COMPLETE;
766                 if (mp->error == MUSHERR_NOQENTRIES) {
767                         retval = CMD_EAGAIN;
768                 } else if (mp->error == EFBIG) {
769                         XS_SETERR(csio, CAM_REQ_TOO_BIG);
770                 } else if (mp->error == EINVAL) {
771                         XS_SETERR(csio, CAM_REQ_INVALID);
772                 } else {
773                         XS_SETERR(csio, CAM_UNREC_HBA_ERROR);
774                 }
775                 return (retval);
776         }
777 mbxsync:
778         if (isp->isp_dblev & ISP_LOGDEBUG1) {
779                 isp_print_bytes(isp, "Request Queue Entry", QENTRY_LEN, rq);
780         }
781         switch (rq->req_header.rqs_entry_type) {
782         case RQSTYPE_REQUEST:
783                 isp_put_request(isp, rq, qep);
784                 break;
785         case RQSTYPE_CMDONLY:
786                 isp_put_extended_request(isp, (ispextreq_t *)rq,
787                     (ispextreq_t *)qep);
788                 break;
789         }
790         return (CMD_QUEUED);
791 }
792
793 static void
794 isp_sbus_reset0(ispsoftc_t *isp)
795 {
796         ISP_DISABLE_INTS(isp);
797 }
798
799 static void
800 isp_sbus_reset1(ispsoftc_t *isp)
801 {
802         ISP_ENABLE_INTS(isp);
803 }
804
805 static void
806 isp_sbus_dumpregs(ispsoftc_t *isp, const char *msg)
807 {
808         if (msg)
809                 printf("%s: %s\n", device_get_nameunit(isp->isp_dev), msg);
810         else
811                 printf("%s:\n", device_get_nameunit(isp->isp_dev));
812         printf("    biu_conf1=%x", ISP_READ(isp, BIU_CONF1));
813         printf(" biu_icr=%x biu_isr=%x biu_sema=%x ", ISP_READ(isp, BIU_ICR),
814             ISP_READ(isp, BIU_ISR), ISP_READ(isp, BIU_SEMA));
815         printf("risc_hccr=%x\n", ISP_READ(isp, HCCR));
816
817
818         ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE);
819         printf("    cdma_conf=%x cdma_sts=%x cdma_fifostat=%x\n",
820                 ISP_READ(isp, CDMA_CONF), ISP_READ(isp, CDMA_STATUS),
821                 ISP_READ(isp, CDMA_FIFO_STS));
822         printf("    ddma_conf=%x ddma_sts=%x ddma_fifostat=%x\n",
823                 ISP_READ(isp, DDMA_CONF), ISP_READ(isp, DDMA_STATUS),
824                 ISP_READ(isp, DDMA_FIFO_STS));
825         printf("    sxp_int=%x sxp_gross=%x sxp(scsi_ctrl)=%x\n",
826                 ISP_READ(isp, SXP_INTERRUPT),
827                 ISP_READ(isp, SXP_GROSS_ERR),
828                 ISP_READ(isp, SXP_PINS_CTRL));
829         ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE);
830         printf("    mbox regs: %x %x %x %x %x\n",
831             ISP_READ(isp, OUTMAILBOX0), ISP_READ(isp, OUTMAILBOX1),
832             ISP_READ(isp, OUTMAILBOX2), ISP_READ(isp, OUTMAILBOX3),
833             ISP_READ(isp, OUTMAILBOX4));
834 }