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