xref: /dragonfly/sys/dev/raid/twe/twe_freebsd.c (revision 984263bc)
1 /*-
2  * Copyright (c) 2000 Michael Smith
3  * Copyright (c) 2000 BSDi
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  * $FreeBSD: src/sys/dev/twe/twe_freebsd.c,v 1.2.2.5 2002/03/07 09:57:02 msmith Exp $
28  */
29 
30 /*
31  * FreeBSD-specific code.
32  */
33 
34 #include <sys/param.h>
35 #include <sys/cons.h>
36 #include <machine/bus.h>
37 #include <machine/clock.h>
38 #include <machine/md_var.h>
39 #include <vm/vm.h>
40 #include <vm/pmap.h>
41 #include <dev/twe/twe_compat.h>
42 #include <dev/twe/twereg.h>
43 #include <dev/twe/tweio.h>
44 #include <dev/twe/twevar.h>
45 #include <dev/twe/twe_tables.h>
46 
47 #include <sys/devicestat.h>
48 
49 static devclass_t	twe_devclass;
50 
51 #ifdef TWE_DEBUG
52 static u_int32_t	twed_bio_in;
53 #define TWED_BIO_IN	twed_bio_in++
54 static u_int32_t	twed_bio_out;
55 #define TWED_BIO_OUT	twed_bio_out++
56 #else
57 #define TWED_BIO_IN
58 #define TWED_BIO_OUT
59 #endif
60 
61 /********************************************************************************
62  ********************************************************************************
63                                                          Control device interface
64  ********************************************************************************
65  ********************************************************************************/
66 
67 static	d_open_t		twe_open;
68 static	d_close_t		twe_close;
69 static	d_ioctl_t		twe_ioctl_wrapper;
70 
71 #define TWE_CDEV_MAJOR  146
72 
73 static struct cdevsw twe_cdevsw = {
74     twe_open,
75     twe_close,
76     noread,
77     nowrite,
78     twe_ioctl_wrapper,
79     nopoll,
80     nommap,
81     nostrategy,
82     "twe",
83     TWE_CDEV_MAJOR,
84     nodump,
85     nopsize,
86     0
87 };
88 
89 /********************************************************************************
90  * Accept an open operation on the control device.
91  */
92 static int
93 twe_open(dev_t dev, int flags, int fmt, d_thread_t *td)
94 {
95     int			unit = minor(dev);
96     struct twe_softc	*sc = devclass_get_softc(twe_devclass, unit);
97 
98     sc->twe_state |= TWE_STATE_OPEN;
99     return(0);
100 }
101 
102 /********************************************************************************
103  * Accept the last close on the control device.
104  */
105 static int
106 twe_close(dev_t dev, int flags, int fmt, d_thread_t *td)
107 {
108     int			unit = minor(dev);
109     struct twe_softc	*sc = devclass_get_softc(twe_devclass, unit);
110 
111     sc->twe_state &= ~TWE_STATE_OPEN;
112     return (0);
113 }
114 
115 /********************************************************************************
116  * Handle controller-specific control operations.
117  */
118 static int
119 twe_ioctl_wrapper(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, d_thread_t *td)
120 {
121     struct twe_softc		*sc = (struct twe_softc *)dev->si_drv1;
122 
123     return(twe_ioctl(sc, cmd, addr));
124 }
125 
126 /********************************************************************************
127  ********************************************************************************
128                                                              PCI device interface
129  ********************************************************************************
130  ********************************************************************************/
131 
132 static int	twe_probe(device_t dev);
133 static int	twe_attach(device_t dev);
134 static void	twe_free(struct twe_softc *sc);
135 static int	twe_detach(device_t dev);
136 static int	twe_shutdown(device_t dev);
137 static int	twe_suspend(device_t dev);
138 static int	twe_resume(device_t dev);
139 static void	twe_pci_intr(void *arg);
140 static void	twe_intrhook(void *arg);
141 
142 static device_method_t twe_methods[] = {
143     /* Device interface */
144     DEVMETHOD(device_probe,	twe_probe),
145     DEVMETHOD(device_attach,	twe_attach),
146     DEVMETHOD(device_detach,	twe_detach),
147     DEVMETHOD(device_shutdown,	twe_shutdown),
148     DEVMETHOD(device_suspend,	twe_suspend),
149     DEVMETHOD(device_resume,	twe_resume),
150 
151     DEVMETHOD(bus_print_child,	bus_generic_print_child),
152     DEVMETHOD(bus_driver_added,	bus_generic_driver_added),
153     { 0, 0 }
154 };
155 
156 static driver_t twe_pci_driver = {
157 	"twe",
158 	twe_methods,
159 	sizeof(struct twe_softc)
160 };
161 
162 #ifdef TWE_OVERRIDE
163 DRIVER_MODULE(Xtwe, pci, twe_pci_driver, twe_devclass, 0, 0);
164 #else
165 DRIVER_MODULE(twe, pci, twe_pci_driver, twe_devclass, 0, 0);
166 #endif
167 
168 /********************************************************************************
169  * Match a 3ware Escalade ATA RAID controller.
170  */
171 static int
172 twe_probe(device_t dev)
173 {
174 
175     debug_called(4);
176 
177     if ((pci_get_vendor(dev) == TWE_VENDOR_ID) &&
178 	((pci_get_device(dev) == TWE_DEVICE_ID) ||
179 	 (pci_get_device(dev) == TWE_DEVICE_ID_ASIC))) {
180 	device_set_desc(dev, TWE_DEVICE_NAME);
181 #ifdef TWE_OVERRIDE
182 	return(0);
183 #else
184 	return(-10);
185 #endif
186     }
187     return(ENXIO);
188 }
189 
190 /********************************************************************************
191  * Allocate resources, initialise the controller.
192  */
193 static int
194 twe_attach(device_t dev)
195 {
196     struct twe_softc	*sc;
197     int			rid, error;
198     u_int32_t		command;
199 
200     debug_called(4);
201 
202     /*
203      * Initialise the softc structure.
204      */
205     sc = device_get_softc(dev);
206     sc->twe_dev = dev;
207 
208     /*
209      * Make sure we are going to be able to talk to this board.
210      */
211     command = pci_read_config(dev, PCIR_COMMAND, 2);
212     if ((command & PCIM_CMD_PORTEN) == 0) {
213 	twe_printf(sc, "register window not available\n");
214 	return(ENXIO);
215     }
216     /*
217      * Force the busmaster enable bit on, in case the BIOS forgot.
218      */
219     command |= PCIM_CMD_BUSMASTEREN;
220     pci_write_config(dev, PCIR_COMMAND, command, 2);
221 
222     /*
223      * Allocate the PCI register window.
224      */
225     rid = TWE_IO_CONFIG_REG;
226     if ((sc->twe_io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE)) == NULL) {
227 	twe_printf(sc, "can't allocate register window\n");
228 	twe_free(sc);
229 	return(ENXIO);
230     }
231     sc->twe_btag = rman_get_bustag(sc->twe_io);
232     sc->twe_bhandle = rman_get_bushandle(sc->twe_io);
233 
234     /*
235      * Allocate the parent bus DMA tag appropriate for PCI.
236      */
237     if (bus_dma_tag_create(NULL, 				/* parent */
238 			   1, 0, 				/* alignment, boundary */
239 			   BUS_SPACE_MAXADDR_32BIT, 		/* lowaddr */
240 			   BUS_SPACE_MAXADDR, 			/* highaddr */
241 			   NULL, NULL, 				/* filter, filterarg */
242 			   MAXBSIZE, TWE_MAX_SGL_LENGTH,	/* maxsize, nsegments */
243 			   BUS_SPACE_MAXSIZE_32BIT,		/* maxsegsize */
244 			   BUS_DMA_ALLOCNOW,			/* flags */
245 			   &sc->twe_parent_dmat)) {
246 	twe_printf(sc, "can't allocate parent DMA tag\n");
247 	twe_free(sc);
248 	return(ENOMEM);
249     }
250 
251     /*
252      * Allocate and connect our interrupt.
253      */
254     rid = 0;
255     if ((sc->twe_irq = bus_alloc_resource(sc->twe_dev, SYS_RES_IRQ, &rid, 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE)) == NULL) {
256 	twe_printf(sc, "can't allocate interrupt\n");
257 	twe_free(sc);
258 	return(ENXIO);
259     }
260     if (bus_setup_intr(sc->twe_dev, sc->twe_irq, INTR_TYPE_BIO | INTR_ENTROPY,  twe_pci_intr, sc, &sc->twe_intr)) {
261 	twe_printf(sc, "can't set up interrupt\n");
262 	twe_free(sc);
263 	return(ENXIO);
264     }
265 
266     /*
267      * Create DMA tag for mapping objects into controller-addressable space.
268      */
269     if (bus_dma_tag_create(sc->twe_parent_dmat, 	/* parent */
270 			   1, 0, 			/* alignment, boundary */
271 			   BUS_SPACE_MAXADDR,		/* lowaddr */
272 			   BUS_SPACE_MAXADDR, 		/* highaddr */
273 			   NULL, NULL, 			/* filter, filterarg */
274 			   MAXBSIZE, TWE_MAX_SGL_LENGTH,/* maxsize, nsegments */
275 			   BUS_SPACE_MAXSIZE_32BIT,	/* maxsegsize */
276 			   0,				/* flags */
277 			   &sc->twe_buffer_dmat)) {
278 	twe_printf(sc, "can't allocate data buffer DMA tag\n");
279 	twe_free(sc);
280 	return(ENOMEM);
281     }
282 
283     /*
284      * Initialise the controller and driver core.
285      */
286     if ((error = twe_setup(sc)))
287 	return(error);
288 
289     /*
290      * Print some information about the controller and configuration.
291      */
292     twe_describe_controller(sc);
293 
294     /*
295      * Create the control device.
296      */
297     sc->twe_dev_t = make_dev(&twe_cdevsw, device_get_unit(sc->twe_dev), UID_ROOT, GID_OPERATOR,
298 			     S_IRUSR | S_IWUSR, "twe%d", device_get_unit(sc->twe_dev));
299     sc->twe_dev_t->si_drv1 = sc;
300     /*
301      * Schedule ourselves to bring the controller up once interrupts are available.
302      * This isn't strictly necessary, since we disable interrupts while probing the
303      * controller, but it is more in keeping with common practice for other disk
304      * devices.
305      */
306     sc->twe_ich.ich_func = twe_intrhook;
307     sc->twe_ich.ich_arg = sc;
308     if (config_intrhook_establish(&sc->twe_ich) != 0) {
309 	twe_printf(sc, "can't establish configuration hook\n");
310 	twe_free(sc);
311 	return(ENXIO);
312     }
313 
314     return(0);
315 }
316 
317 /********************************************************************************
318  * Free all of the resources associated with (sc).
319  *
320  * Should not be called if the controller is active.
321  */
322 static void
323 twe_free(struct twe_softc *sc)
324 {
325     struct twe_request	*tr;
326 
327     debug_called(4);
328 
329     /* throw away any command buffers */
330     while ((tr = twe_dequeue_free(sc)) != NULL)
331 	twe_free_request(tr);
332 
333     /* destroy the data-transfer DMA tag */
334     if (sc->twe_buffer_dmat)
335 	bus_dma_tag_destroy(sc->twe_buffer_dmat);
336 
337     /* disconnect the interrupt handler */
338     if (sc->twe_intr)
339 	bus_teardown_intr(sc->twe_dev, sc->twe_irq, sc->twe_intr);
340     if (sc->twe_irq != NULL)
341 	bus_release_resource(sc->twe_dev, SYS_RES_IRQ, 0, sc->twe_irq);
342 
343     /* destroy the parent DMA tag */
344     if (sc->twe_parent_dmat)
345 	bus_dma_tag_destroy(sc->twe_parent_dmat);
346 
347     /* release the register window mapping */
348     if (sc->twe_io != NULL)
349 	bus_release_resource(sc->twe_dev, SYS_RES_IOPORT, TWE_IO_CONFIG_REG, sc->twe_io);
350 
351     /* destroy control device */
352     if (sc->twe_dev_t != (dev_t)NULL)
353 	destroy_dev(sc->twe_dev_t);
354 }
355 
356 /********************************************************************************
357  * Disconnect from the controller completely, in preparation for unload.
358  */
359 static int
360 twe_detach(device_t dev)
361 {
362     struct twe_softc	*sc = device_get_softc(dev);
363     int			s, error;
364 
365     debug_called(4);
366 
367     error = EBUSY;
368     s = splbio();
369     if (sc->twe_state & TWE_STATE_OPEN)
370 	goto out;
371 
372     /*
373      * Shut the controller down.
374      */
375     if ((error = twe_shutdown(dev)))
376 	goto out;
377 
378     twe_free(sc);
379 
380     error = 0;
381  out:
382     splx(s);
383     return(error);
384 }
385 
386 /********************************************************************************
387  * Bring the controller down to a dormant state and detach all child devices.
388  *
389  * Note that we can assume that the bioq on the controller is empty, as we won't
390  * allow shutdown if any device is open.
391  */
392 static int
393 twe_shutdown(device_t dev)
394 {
395     struct twe_softc	*sc = device_get_softc(dev);
396     int			i, s, error;
397 
398     debug_called(4);
399 
400     s = splbio();
401     error = 0;
402 
403     /*
404      * Delete all our child devices.
405      */
406     for (i = 0; i < TWE_MAX_UNITS; i++) {
407 	if (sc->twe_drive[i].td_disk != 0) {
408 	    if ((error = device_delete_child(sc->twe_dev, sc->twe_drive[i].td_disk)) != 0)
409 		goto out;
410 	    sc->twe_drive[i].td_disk = 0;
411 	}
412     }
413 
414     /*
415      * Bring the controller down.
416      */
417     twe_deinit(sc);
418 
419  out:
420     splx(s);
421     return(error);
422 }
423 
424 /********************************************************************************
425  * Bring the controller to a quiescent state, ready for system suspend.
426  */
427 static int
428 twe_suspend(device_t dev)
429 {
430     struct twe_softc	*sc = device_get_softc(dev);
431     int			s;
432 
433     debug_called(4);
434 
435     s = splbio();
436     sc->twe_state |= TWE_STATE_SUSPEND;
437 
438     twe_disable_interrupts(sc);
439     splx(s);
440 
441     return(0);
442 }
443 
444 /********************************************************************************
445  * Bring the controller back to a state ready for operation.
446  */
447 static int
448 twe_resume(device_t dev)
449 {
450     struct twe_softc	*sc = device_get_softc(dev);
451 
452     debug_called(4);
453 
454     sc->twe_state &= ~TWE_STATE_SUSPEND;
455     twe_enable_interrupts(sc);
456 
457     return(0);
458 }
459 
460 /*******************************************************************************
461  * Take an interrupt, or be poked by other code to look for interrupt-worthy
462  * status.
463  */
464 static void
465 twe_pci_intr(void *arg)
466 {
467     twe_intr((struct twe_softc *)arg);
468 }
469 
470 /********************************************************************************
471  * Delayed-startup hook
472  */
473 static void
474 twe_intrhook(void *arg)
475 {
476     struct twe_softc		*sc = (struct twe_softc *)arg;
477 
478     /* pull ourselves off the intrhook chain */
479     config_intrhook_disestablish(&sc->twe_ich);
480 
481     /* call core startup routine */
482     twe_init(sc);
483 }
484 
485 /********************************************************************************
486  * Given a detected drive, attach it to the bio interface.
487  *
488  * This is called from twe_init.
489  */
490 void
491 twe_attach_drive(struct twe_softc *sc, struct twe_drive *dr)
492 {
493     char	buf[80];
494     int		error;
495 
496     dr->td_disk =  device_add_child(sc->twe_dev, NULL, -1);
497     if (dr->td_disk == NULL) {
498 	twe_printf(sc, "device_add_child failed\n");
499 	return;
500     }
501     device_set_ivars(dr->td_disk, dr);
502 
503     /*
504      * XXX It would make sense to test the online/initialising bits, but they seem to be
505      * always set...
506      */
507     sprintf(buf, "%s, %s", twe_describe_code(twe_table_unittype, dr->td_type),
508 	    twe_describe_code(twe_table_unitstate, dr->td_state & TWE_PARAM_UNITSTATUS_MASK));
509     device_set_desc_copy(dr->td_disk, buf);
510 
511     if ((error = bus_generic_attach(sc->twe_dev)) != 0)
512 	twe_printf(sc, "bus_generic_attach returned %d\n", error);
513 }
514 
515 /********************************************************************************
516  * Clear a PCI parity error.
517  */
518 void
519 twe_clear_pci_parity_error(struct twe_softc *sc)
520 {
521     TWE_CONTROL(sc, TWE_CONTROL_CLEAR_PARITY_ERROR);
522     pci_write_config(sc->twe_dev, PCIR_STATUS, TWE_PCI_CLEAR_PARITY_ERROR, 2);
523 }
524 
525 /********************************************************************************
526  * Clear a PCI abort.
527  */
528 void
529 twe_clear_pci_abort(struct twe_softc *sc)
530 {
531     TWE_CONTROL(sc, TWE_CONTROL_CLEAR_PCI_ABORT);
532     pci_write_config(sc->twe_dev, PCIR_STATUS, TWE_PCI_CLEAR_PCI_ABORT, 2);
533 }
534 
535 /********************************************************************************
536  ********************************************************************************
537                                                                       Disk device
538  ********************************************************************************
539  ********************************************************************************/
540 
541 /*
542  * Disk device softc
543  */
544 struct twed_softc
545 {
546     device_t		twed_dev;
547     dev_t		twed_dev_t;
548     struct twe_softc	*twed_controller;	/* parent device softc */
549     struct twe_drive	*twed_drive;		/* drive data in parent softc */
550     struct disk		twed_disk;		/* generic disk handle */
551     struct devstat	twed_stats;		/* accounting */
552     struct disklabel	twed_label;		/* synthetic label */
553     int			twed_flags;
554 #define TWED_OPEN	(1<<0)			/* drive is open (can't shut down) */
555 };
556 
557 /*
558  * Disk device bus interface
559  */
560 static int twed_probe(device_t dev);
561 static int twed_attach(device_t dev);
562 static int twed_detach(device_t dev);
563 
564 static device_method_t twed_methods[] = {
565     DEVMETHOD(device_probe,	twed_probe),
566     DEVMETHOD(device_attach,	twed_attach),
567     DEVMETHOD(device_detach,	twed_detach),
568     { 0, 0 }
569 };
570 
571 static driver_t twed_driver = {
572     "twed",
573     twed_methods,
574     sizeof(struct twed_softc)
575 };
576 
577 static devclass_t	twed_devclass;
578 #ifdef TWE_OVERRIDE
579 DRIVER_MODULE(Xtwed, Xtwe, twed_driver, twed_devclass, 0, 0);
580 #else
581 DRIVER_MODULE(twed, twe, twed_driver, twed_devclass, 0, 0);
582 #endif
583 
584 /*
585  * Disk device control interface.
586  */
587 static	d_open_t	twed_open;
588 static	d_close_t	twed_close;
589 static	d_strategy_t	twed_strategy;
590 static	d_dump_t	twed_dump;
591 
592 #define TWED_CDEV_MAJOR	147
593 
594 static struct cdevsw twed_cdevsw = {
595     twed_open,
596     twed_close,
597     physread,
598     physwrite,
599     noioctl,
600     nopoll,
601     nommap,
602     twed_strategy,
603     "twed",
604     TWED_CDEV_MAJOR,
605     twed_dump,
606     nopsize,
607     D_DISK
608 };
609 
610 static struct cdevsw	tweddisk_cdevsw;
611 #ifdef FREEBSD_4
612 static int		disks_registered = 0;
613 #endif
614 
615 /********************************************************************************
616  * Handle open from generic layer.
617  *
618  * Note that this is typically only called by the diskslice code, and not
619  * for opens on subdevices (eg. slices, partitions).
620  */
621 static int
622 twed_open(dev_t dev, int flags, int fmt, d_thread_t *td)
623 {
624     struct twed_softc	*sc = (struct twed_softc *)dev->si_drv1;
625     struct disklabel	*label;
626 
627     debug_called(4);
628 
629     if (sc == NULL)
630 	return (ENXIO);
631 
632     /* check that the controller is up and running */
633     if (sc->twed_controller->twe_state & TWE_STATE_SHUTDOWN)
634 	return(ENXIO);
635 
636     /* build synthetic label */
637     label = &sc->twed_disk.d_label;
638     bzero(label, sizeof(*label));
639     label->d_type = DTYPE_ESDI;
640     label->d_secsize    = TWE_BLOCK_SIZE;
641     label->d_nsectors   = sc->twed_drive->td_sectors;
642     label->d_ntracks    = sc->twed_drive->td_heads;
643     label->d_ncylinders = sc->twed_drive->td_cylinders;
644     label->d_secpercyl  = sc->twed_drive->td_sectors * sc->twed_drive->td_heads;
645     label->d_secperunit = sc->twed_drive->td_size;
646 
647     sc->twed_flags |= TWED_OPEN;
648     return (0);
649 }
650 
651 /********************************************************************************
652  * Handle last close of the disk device.
653  */
654 static int
655 twed_close(dev_t dev, int flags, int fmt, d_thread_t *td)
656 {
657     struct twed_softc	*sc = (struct twed_softc *)dev->si_drv1;
658 
659     debug_called(4);
660 
661     if (sc == NULL)
662 	return (ENXIO);
663 
664     sc->twed_flags &= ~TWED_OPEN;
665     return (0);
666 }
667 
668 /********************************************************************************
669  * Handle an I/O request.
670  */
671 static void
672 twed_strategy(twe_bio *bp)
673 {
674     struct twed_softc	*sc = (struct twed_softc *)TWE_BIO_SOFTC(bp);
675 
676     debug_called(4);
677 
678     TWED_BIO_IN;
679 
680     /* bogus disk? */
681     if (sc == NULL) {
682 	TWE_BIO_SET_ERROR(bp, EINVAL);
683 	printf("twe: bio for invalid disk!\n");
684 	TWE_BIO_DONE(bp);
685 	TWED_BIO_OUT;
686 	return;
687     }
688 
689     /* perform accounting */
690     TWE_BIO_STATS_START(bp);
691 
692     /* queue the bio on the controller */
693     twe_enqueue_bio(sc->twed_controller, bp);
694 
695     /* poke the controller to start I/O */
696     twe_startio(sc->twed_controller);
697     return;
698 }
699 
700 /********************************************************************************
701  * System crashdump support
702  */
703 int
704 twed_dump(dev_t dev)
705 {
706     struct twed_softc	*twed_sc = (struct twed_softc *)dev->si_drv1;
707     struct twe_softc	*twe_sc  = (struct twe_softc *)twed_sc->twed_controller;
708     u_int		count, blkno, secsize;
709     vm_offset_t		addr = 0;
710     long		blkcnt;
711     int			dumppages = MAXDUMPPGS;
712     int			error;
713     int			i;
714 
715     if ((error = disk_dumpcheck(dev, &count, &blkno, &secsize)))
716         return(error);
717 
718     if (!twed_sc || !twe_sc)
719 	return(ENXIO);
720 
721     blkcnt = howmany(PAGE_SIZE, secsize);
722 
723     while (count > 0) {
724 	caddr_t va = NULL;
725 
726 	if ((count / blkcnt) < dumppages)
727 	    dumppages = count / blkcnt;
728 
729 	for (i = 0; i < dumppages; ++i) {
730 	    vm_offset_t a = addr + (i * PAGE_SIZE);
731 	    if (is_physical_memory(a))
732 		va = pmap_kenter_temporary(trunc_page(a), i);
733 	    else
734 		va = pmap_kenter_temporary(trunc_page(0), i);
735 	}
736 
737 	if ((error = twe_dump_blocks(twe_sc, twed_sc->twed_drive->td_unit, blkno, va,
738 				     (PAGE_SIZE * dumppages) / TWE_BLOCK_SIZE)) != 0)
739 	    return(error);
740 
741 
742 	if (dumpstatus(addr, (off_t)count * DEV_BSIZE) < 0)
743 	    return(EINTR);
744 
745 	blkno += blkcnt * dumppages;
746 	count -= blkcnt * dumppages;
747 	addr += PAGE_SIZE * dumppages;
748     }
749     return(0);
750 }
751 
752 /********************************************************************************
753  * Handle completion of an I/O request.
754  */
755 void
756 twed_intr(twe_bio *bp)
757 {
758     debug_called(4);
759 
760     /* if no error, transfer completed */
761     if (!TWE_BIO_HAS_ERROR(bp))
762 	TWE_BIO_RESID(bp) = 0;
763 
764     TWE_BIO_STATS_END(bp);
765     TWE_BIO_DONE(bp);
766     TWED_BIO_OUT;
767 }
768 
769 /********************************************************************************
770  * Default probe stub.
771  */
772 static int
773 twed_probe(device_t dev)
774 {
775     return (0);
776 }
777 
778 /********************************************************************************
779  * Attach a unit to the controller.
780  */
781 static int
782 twed_attach(device_t dev)
783 {
784     struct twed_softc	*sc;
785     device_t		parent;
786     dev_t		dsk;
787 
788     debug_called(4);
789 
790     /* initialise our softc */
791     sc = device_get_softc(dev);
792     parent = device_get_parent(dev);
793     sc->twed_controller = (struct twe_softc *)device_get_softc(parent);
794     sc->twed_drive = device_get_ivars(dev);
795     sc->twed_dev = dev;
796 
797     /* report the drive */
798     twed_printf(sc, "%uMB (%u sectors)\n",
799 		sc->twed_drive->td_size / ((1024 * 1024) / TWE_BLOCK_SIZE),
800 		sc->twed_drive->td_size);
801 
802     devstat_add_entry(&sc->twed_stats, "twed", device_get_unit(dev), TWE_BLOCK_SIZE,
803 		      DEVSTAT_NO_ORDERED_TAGS,
804 		      DEVSTAT_TYPE_STORARRAY | DEVSTAT_TYPE_IF_OTHER,
805 		      DEVSTAT_PRIORITY_ARRAY);
806 
807     /* attach a generic disk device to ourselves */
808     dsk = disk_create(device_get_unit(dev), &sc->twed_disk, 0, &twed_cdevsw, &tweddisk_cdevsw);
809     dsk->si_drv1 = sc;
810     dsk->si_drv2 = &sc->twed_drive->td_unit;
811     sc->twed_dev_t = dsk;
812 #ifdef FREEBSD_4
813     disks_registered++;
814 #endif
815 
816     /* set the maximum I/O size to the theoretical maximum allowed by the S/G list size */
817     dsk->si_iosize_max = (TWE_MAX_SGL_LENGTH - 1) * PAGE_SIZE;
818 
819     return (0);
820 }
821 
822 /********************************************************************************
823  * Disconnect ourselves from the system.
824  */
825 static int
826 twed_detach(device_t dev)
827 {
828     struct twed_softc *sc = (struct twed_softc *)device_get_softc(dev);
829 
830     debug_called(4);
831 
832     if (sc->twed_flags & TWED_OPEN)
833 	return(EBUSY);
834 
835     devstat_remove_entry(&sc->twed_stats);
836 #ifdef FREEBSD_4
837     if (--disks_registered == 0)
838 	cdevsw_remove(&tweddisk_cdevsw);
839 #else
840     disk_destroy(sc->twed_dev_t);
841 #endif
842 
843     return(0);
844 }
845 
846 /********************************************************************************
847  ********************************************************************************
848                                                                              Misc
849  ********************************************************************************
850  ********************************************************************************/
851 
852 static void	twe_setup_data_dmamap(void *arg, bus_dma_segment_t *segs, int nsegments, int error);
853 static void	twe_setup_request_dmamap(void *arg, bus_dma_segment_t *segs, int nsegments, int error);
854 
855 /********************************************************************************
856  * Allocate a command buffer
857  */
858 MALLOC_DEFINE(TWE_MALLOC_CLASS, "twe commands", "twe commands");
859 
860 struct twe_request *
861 twe_allocate_request(struct twe_softc *sc)
862 {
863     struct twe_request	*tr;
864 
865     if ((tr = malloc(sizeof(struct twe_request), TWE_MALLOC_CLASS, M_NOWAIT)) == NULL)
866 	return(NULL);
867     bzero(tr, sizeof(*tr));
868     tr->tr_sc = sc;
869     if (bus_dmamap_create(sc->twe_buffer_dmat, 0, &tr->tr_cmdmap)) {
870 	twe_free_request(tr);
871 	return(NULL);
872     }
873     if (bus_dmamap_create(sc->twe_buffer_dmat, 0, &tr->tr_dmamap)) {
874 	bus_dmamap_destroy(sc->twe_buffer_dmat, tr->tr_cmdmap);
875 	twe_free_request(tr);
876 	return(NULL);
877     }
878     return(tr);
879 }
880 
881 /********************************************************************************
882  * Permanently discard a command buffer.
883  */
884 void
885 twe_free_request(struct twe_request *tr)
886 {
887     struct twe_softc	*sc = tr->tr_sc;
888 
889     debug_called(4);
890 
891     bus_dmamap_destroy(sc->twe_buffer_dmat, tr->tr_cmdmap);
892     bus_dmamap_destroy(sc->twe_buffer_dmat, tr->tr_dmamap);
893     free(tr, TWE_MALLOC_CLASS);
894 }
895 
896 /********************************************************************************
897  * Map/unmap (tr)'s command and data in the controller's addressable space.
898  *
899  * These routines ensure that the data which the controller is going to try to
900  * access is actually visible to the controller, in a machine-independant
901  * fashion.  Due to a hardware limitation, I/O buffers must be 512-byte aligned
902  * and we take care of that here as well.
903  */
904 static void
905 twe_setup_data_dmamap(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
906 {
907     struct twe_request	*tr = (struct twe_request *)arg;
908     TWE_Command		*cmd = &tr->tr_command;
909     int			i;
910 
911     debug_called(4);
912 
913     /* save base of first segment in command (applicable if there only one segment) */
914     tr->tr_dataphys = segs[0].ds_addr;
915 
916     /* correct command size for s/g list size */
917     tr->tr_command.generic.size += 2 * nsegments;
918 
919     /*
920      * Due to the fact that parameter and I/O commands have the scatter/gather list in
921      * different places, we need to determine which sort of command this actually is
922      * before we can populate it correctly.
923      */
924     switch(cmd->generic.opcode) {
925     case TWE_OP_GET_PARAM:
926     case TWE_OP_SET_PARAM:
927 	cmd->generic.sgl_offset = 2;
928 	for (i = 0; i < nsegments; i++) {
929 	    cmd->param.sgl[i].address = segs[i].ds_addr;
930 	    cmd->param.sgl[i].length = segs[i].ds_len;
931 	}
932 	for (; i < TWE_MAX_SGL_LENGTH; i++) {		/* XXX necessary? */
933 	    cmd->param.sgl[i].address = 0;
934 	    cmd->param.sgl[i].length = 0;
935 	}
936 	break;
937     case TWE_OP_READ:
938     case TWE_OP_WRITE:
939 	cmd->generic.sgl_offset = 3;
940 	for (i = 0; i < nsegments; i++) {
941 	    cmd->io.sgl[i].address = segs[i].ds_addr;
942 	    cmd->io.sgl[i].length = segs[i].ds_len;
943 	}
944 	for (; i < TWE_MAX_SGL_LENGTH; i++) {		/* XXX necessary? */
945 	    cmd->io.sgl[i].address = 0;
946 	    cmd->io.sgl[i].length = 0;
947 	}
948 	break;
949     default:
950 	/* no s/g list, nothing to do */
951     }
952 }
953 
954 static void
955 twe_setup_request_dmamap(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
956 {
957     struct twe_request	*tr = (struct twe_request *)arg;
958 
959     debug_called(4);
960 
961     /* command can't cross a page boundary */
962     tr->tr_cmdphys = segs[0].ds_addr;
963 }
964 
965 void
966 twe_map_request(struct twe_request *tr)
967 {
968     struct twe_softc	*sc = tr->tr_sc;
969 
970     debug_called(4);
971 
972 
973     /*
974      * Map the command into bus space.
975      */
976     bus_dmamap_load(sc->twe_buffer_dmat, tr->tr_cmdmap, &tr->tr_command, sizeof(tr->tr_command),
977 		    twe_setup_request_dmamap, tr, 0);
978     bus_dmamap_sync(sc->twe_buffer_dmat, tr->tr_cmdmap, BUS_DMASYNC_PREWRITE);
979 
980     /*
981      * If the command involves data, map that too.
982      */
983     if (tr->tr_data != NULL) {
984 
985 	/*
986 	 * Data must be 64-byte aligned; allocate a fixup buffer if it's not.
987 	 */
988 	if (((vm_offset_t)tr->tr_data % TWE_ALIGNMENT) != 0) {
989 	    tr->tr_realdata = tr->tr_data;				/* save pointer to 'real' data */
990 	    tr->tr_flags |= TWE_CMD_ALIGNBUF;
991 	    tr->tr_data = malloc(tr->tr_length, TWE_MALLOC_CLASS, M_NOWAIT);	/* XXX check result here */
992 	}
993 
994 	/*
995 	 * Map the data buffer into bus space and build the s/g list.
996 	 */
997 	bus_dmamap_load(sc->twe_buffer_dmat, tr->tr_dmamap, tr->tr_data, tr->tr_length,
998 			twe_setup_data_dmamap, tr, 0);
999 	if (tr->tr_flags & TWE_CMD_DATAIN)
1000 	    bus_dmamap_sync(sc->twe_buffer_dmat, tr->tr_dmamap, BUS_DMASYNC_PREREAD);
1001 	if (tr->tr_flags & TWE_CMD_DATAOUT) {
1002 	    /* if we're using an alignment buffer, and we're writing data, copy the real data out */
1003 	    if (tr->tr_flags & TWE_CMD_ALIGNBUF)
1004 		bcopy(tr->tr_realdata, tr->tr_data, tr->tr_length);
1005 	    bus_dmamap_sync(sc->twe_buffer_dmat, tr->tr_dmamap, BUS_DMASYNC_PREWRITE);
1006 	}
1007     }
1008 }
1009 
1010 void
1011 twe_unmap_request(struct twe_request *tr)
1012 {
1013     struct twe_softc	*sc = tr->tr_sc;
1014 
1015     debug_called(4);
1016 
1017     /*
1018      * Unmap the command from bus space.
1019      */
1020     bus_dmamap_sync(sc->twe_buffer_dmat, tr->tr_cmdmap, BUS_DMASYNC_POSTWRITE);
1021     bus_dmamap_unload(sc->twe_buffer_dmat, tr->tr_cmdmap);
1022 
1023     /*
1024      * If the command involved data, unmap that too.
1025      */
1026     if (tr->tr_data != NULL) {
1027 
1028 	if (tr->tr_flags & TWE_CMD_DATAIN) {
1029 	    bus_dmamap_sync(sc->twe_buffer_dmat, tr->tr_dmamap, BUS_DMASYNC_POSTREAD);
1030 	    /* if we're using an alignment buffer, and we're reading data, copy the real data in */
1031 	    if (tr->tr_flags & TWE_CMD_ALIGNBUF)
1032 		bcopy(tr->tr_data, tr->tr_realdata, tr->tr_length);
1033 	}
1034 	if (tr->tr_flags & TWE_CMD_DATAOUT)
1035 	    bus_dmamap_sync(sc->twe_buffer_dmat, tr->tr_dmamap, BUS_DMASYNC_POSTWRITE);
1036 
1037 	bus_dmamap_unload(sc->twe_buffer_dmat, tr->tr_dmamap);
1038     }
1039 
1040     /* free alignment buffer if it was used */
1041     if (tr->tr_flags & TWE_CMD_ALIGNBUF) {
1042 	free(tr->tr_data, TWE_MALLOC_CLASS);
1043 	tr->tr_data = tr->tr_realdata;		/* restore 'real' data pointer */
1044     }
1045 }
1046 
1047 #ifdef TWE_DEBUG
1048 /********************************************************************************
1049  * Print current controller status, call from DDB.
1050  */
1051 void
1052 twe_report(void)
1053 {
1054     struct twe_softc	*sc;
1055     int			i, s;
1056 
1057     s = splbio();
1058     for (i = 0; (sc = devclass_get_softc(twe_devclass, i)) != NULL; i++)
1059 	twe_print_controller(sc);
1060     printf("twed: total bio count in %u  out %u\n", twed_bio_in, twed_bio_out);
1061     splx(s);
1062 }
1063 #endif
1064