xref: /dragonfly/sys/dev/raid/dpt/dpt_scsi.c (revision 030b0c8c4cf27c560ccec70410c8e21934ae677d)
1 /*
2  *       Copyright (c) 1997 by Simon Shapiro
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, this list of conditions, and the following disclaimer,
10  *    without modification, immediately at the beginning of the file.
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  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
21  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * $FreeBSD: src/sys/dev/dpt/dpt_scsi.c,v 1.28.2.3 2003/01/31 02:47:10 grog Exp $
30  */
31 
32 /*
33  * dpt_scsi.c: SCSI dependant code for the DPT driver
34  *
35  * credits:         Assisted by Mike Neuffer in the early low level DPT code
36  *                  Thanx to Mark Salyzyn of DPT for his assistance.
37  *                  Special thanx to Justin Gibbs for invaluable help in
38  *                  making this driver look and work like a FreeBSD component.
39  *                  Last but not least, many thanx to UCB and the FreeBSD
40  *                  team for creating and maintaining such a wonderful O/S.
41  *
42  * TODO:     * Add ISA probe code.
43  *             * Add driver-level RAID-0. This will allow interoperability with
44  *               NiceTry, M$-Doze, Win-Dog, Slowlaris, etc., in recognizing RAID
45  *               arrays that span controllers (Wow!).
46  */
47 
48 #define _DPT_C_
49 
50 #include "opt_dpt.h"
51 #include <sys/param.h>
52 #include <sys/systm.h>
53 #include <sys/eventhandler.h>
54 #include <sys/malloc.h>
55 #include <sys/kernel.h>
56 #include <sys/bus.h>
57 #include <sys/thread2.h>
58 
59 #include <machine/clock.h>
60 
61 #include <bus/cam/cam.h>
62 #include <bus/cam/cam_ccb.h>
63 #include <bus/cam/cam_sim.h>
64 #include <bus/cam/cam_xpt_sim.h>
65 #include <bus/cam/cam_debug.h>
66 #include <bus/cam/scsi/scsi_all.h>
67 #include <bus/cam/scsi/scsi_message.h>
68 
69 #include <vm/vm.h>
70 #include <vm/pmap.h>
71 
72 #include "dpt.h"
73 
74 /* dpt_isa.c and dpt_pci.c need this in a central place */
75 int dpt_controllers_present;
76 
77 u_long    dpt_unit; /* Next unit number to use */
78 
79 /* The linked list of softc structures */
80 struct dpt_softc_list dpt_softcs = TAILQ_HEAD_INITIALIZER(dpt_softcs);
81 
82 #define microtime_now dpt_time_now()
83 
84 #define dpt_inl(dpt, port)                                  \
85           bus_space_read_4((dpt)->tag, (dpt)->bsh, port)
86 #define dpt_inb(dpt, port)                                  \
87           bus_space_read_1((dpt)->tag, (dpt)->bsh, port)
88 #define dpt_outl(dpt, port, value)                          \
89           bus_space_write_4((dpt)->tag, (dpt)->bsh, port, value)
90 #define dpt_outb(dpt, port, value)                          \
91           bus_space_write_1((dpt)->tag, (dpt)->bsh, port, value)
92 
93 /*
94  * These will have to be setup by parameters passed at boot/load time. For
95  * perfromance reasons, we make them constants for the time being.
96  */
97 #define   dpt_min_segs        DPT_MAX_SEGS
98 #define   dpt_max_segs        DPT_MAX_SEGS
99 
100 /* Definitions for our use of the SIM private CCB area */
101 #define ccb_dccb_ptr spriv_ptr0
102 #define ccb_dpt_ptr spriv_ptr1
103 
104 /* ================= Private Inline Function declarations ===================*/
105 static __inline int           dpt_just_reset(dpt_softc_t * dpt);
106 static __inline int           dpt_raid_busy(dpt_softc_t * dpt);
107 static __inline int           dpt_pio_wait (u_int32_t, u_int, u_int, u_int);
108 static __inline int           dpt_wait(dpt_softc_t *dpt, u_int bits,
109                                                    u_int state);
110 static __inline struct dpt_ccb* dptgetccb(struct dpt_softc *dpt);
111 static __inline void                    dptfreeccb(struct dpt_softc *dpt,
112                                                      struct dpt_ccb *dccb);
113 static __inline bus_addr_t    dptccbvtop(struct dpt_softc *dpt,
114                                                      struct dpt_ccb *dccb);
115 
116 static __inline int           dpt_send_immediate(dpt_softc_t *dpt,
117                                                                eata_ccb_t *cmd_block,
118                                                                u_int32_t cmd_busaddr,
119                                                                u_int retries,
120                                                                u_int ifc, u_int code,
121                                                                u_int code2);
122 
123 /* ==================== Private Function declarations =======================*/
124 static void                   dptmapmem(void *arg, bus_dma_segment_t *segs,
125                                           int nseg, int error);
126 
127 static struct sg_map_node*
128                               dptallocsgmap(struct dpt_softc *dpt);
129 
130 static int                    dptallocccbs(dpt_softc_t *dpt);
131 
132 static int                    dpt_get_conf(dpt_softc_t *dpt, dpt_ccb_t *dccb,
133                                              u_int32_t dccb_busaddr, u_int size,
134                                              u_int page, u_int target, int extent);
135 static void                   dpt_detect_cache(dpt_softc_t *dpt, dpt_ccb_t *dccb,
136                                                    u_int32_t dccb_busaddr,
137                                                    u_int8_t *buff);
138 
139 static void                   dpt_poll(struct cam_sim *sim);
140 
141 static void                   dptexecuteccb(void *arg, bus_dma_segment_t *dm_segs,
142                                               int nseg, int error);
143 
144 static void                   dpt_action(struct cam_sim *sim, union ccb *ccb);
145 
146 static int                    dpt_send_eata_command(dpt_softc_t *dpt, eata_ccb_t *cmd,
147                                                         u_int32_t cmd_busaddr,
148                                                         u_int command, u_int retries,
149                                                         u_int ifc, u_int code,
150                                                         u_int code2);
151 static void                   dptprocesserror(dpt_softc_t *dpt, dpt_ccb_t *dccb,
152                                                   union ccb *ccb, u_int hba_stat,
153                                                   u_int scsi_stat, u_int32_t resid);
154 
155 static void                   dpttimeout(void *arg);
156 static void                   dptshutdown(void *arg, int howto);
157 
158 /* ================= Private Inline Function definitions ====================*/
159 static __inline int
dpt_just_reset(dpt_softc_t * dpt)160 dpt_just_reset(dpt_softc_t * dpt)
161 {
162           if ((dpt_inb(dpt, 2) == 'D')
163            && (dpt_inb(dpt, 3) == 'P')
164            && (dpt_inb(dpt, 4) == 'T')
165            && (dpt_inb(dpt, 5) == 'H'))
166                     return (1);
167           else
168                     return (0);
169 }
170 
171 static __inline int
dpt_raid_busy(dpt_softc_t * dpt)172 dpt_raid_busy(dpt_softc_t * dpt)
173 {
174           if ((dpt_inb(dpt, 0) == 'D')
175            && (dpt_inb(dpt, 1) == 'P')
176            && (dpt_inb(dpt, 2) == 'T'))
177                     return (1);
178           else
179                     return (0);
180 }
181 
182 static __inline int
dpt_pio_wait(u_int32_t base,u_int reg,u_int bits,u_int state)183 dpt_pio_wait (u_int32_t base, u_int reg, u_int bits, u_int state)
184 {
185           int   i;
186           u_int c;
187 
188           for (i = 0; i < 20000; i++) { /* wait 20ms for not busy */
189                     c = inb(base + reg) & bits;
190                     if (!(c == state))
191                               return (0);
192                     else
193                               DELAY(50);
194           }
195           return (-1);
196 }
197 
198 static __inline int
dpt_wait(dpt_softc_t * dpt,u_int bits,u_int state)199 dpt_wait(dpt_softc_t *dpt, u_int bits, u_int state)
200 {
201           int   i;
202           u_int c;
203 
204           for (i = 0; i < 20000; i++) { /* wait 20ms for not busy */
205                     c = dpt_inb(dpt, HA_RSTATUS) & bits;
206                     if (c == state)
207                               return (0);
208                     else
209                               DELAY(50);
210           }
211           return (-1);
212 }
213 
214 static __inline struct dpt_ccb*
dptgetccb(struct dpt_softc * dpt)215 dptgetccb(struct dpt_softc *dpt)
216 {
217           struct    dpt_ccb* dccb;
218 
219           crit_enter();
220           if ((dccb = SLIST_FIRST(&dpt->free_dccb_list)) != NULL) {
221                     SLIST_REMOVE_HEAD(&dpt->free_dccb_list, links);
222                     dpt->free_dccbs--;
223           } else if (dpt->total_dccbs < dpt->max_dccbs) {
224                     dptallocccbs(dpt);
225                     dccb = SLIST_FIRST(&dpt->free_dccb_list);
226                     if (dccb == NULL)
227                               kprintf("dpt%d: Can't malloc DCCB\n", dpt->unit);
228                     else {
229                               SLIST_REMOVE_HEAD(&dpt->free_dccb_list, links);
230                               dpt->free_dccbs--;
231                     }
232           }
233           crit_exit();
234 
235           return (dccb);
236 }
237 
238 static __inline void
dptfreeccb(struct dpt_softc * dpt,struct dpt_ccb * dccb)239 dptfreeccb(struct dpt_softc *dpt, struct dpt_ccb *dccb)
240 {
241           crit_enter();
242           if ((dccb->state & DCCB_ACTIVE) != 0)
243                     LIST_REMOVE(&dccb->ccb->ccb_h, sim_links.le);
244           if ((dccb->state & DCCB_RELEASE_SIMQ) != 0)
245                     dccb->ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
246           else if (dpt->resource_shortage != 0
247            && (dccb->ccb->ccb_h.status & CAM_RELEASE_SIMQ) == 0) {
248                     dccb->ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
249                     dpt->resource_shortage = FALSE;
250           }
251           dccb->state = DCCB_FREE;
252           SLIST_INSERT_HEAD(&dpt->free_dccb_list, dccb, links);
253           ++dpt->free_dccbs;
254           crit_exit();
255 }
256 
257 static __inline bus_addr_t
dptccbvtop(struct dpt_softc * dpt,struct dpt_ccb * dccb)258 dptccbvtop(struct dpt_softc *dpt, struct dpt_ccb *dccb)
259 {
260           return (dpt->dpt_ccb_busbase
261                 + (u_int32_t)((caddr_t)dccb - (caddr_t)dpt->dpt_dccbs));
262 }
263 
264 static __inline struct dpt_ccb *
dptccbptov(struct dpt_softc * dpt,bus_addr_t busaddr)265 dptccbptov(struct dpt_softc *dpt, bus_addr_t busaddr)
266 {
267           return (dpt->dpt_dccbs
268                +  ((struct dpt_ccb *)busaddr
269                  - (struct dpt_ccb *)dpt->dpt_ccb_busbase));
270 }
271 
272 /*
273  * Send a command for immediate execution by the DPT
274  * See above function for IMPORTANT notes.
275  */
276 static __inline int
dpt_send_immediate(dpt_softc_t * dpt,eata_ccb_t * cmd_block,u_int32_t cmd_busaddr,u_int retries,u_int ifc,u_int code,u_int code2)277 dpt_send_immediate(dpt_softc_t *dpt, eata_ccb_t *cmd_block,
278                        u_int32_t cmd_busaddr, u_int retries,
279                        u_int ifc, u_int code, u_int code2)
280 {
281           return (dpt_send_eata_command(dpt, cmd_block, cmd_busaddr,
282                                               EATA_CMD_IMMEDIATE, retries, ifc,
283                                               code, code2));
284 }
285 
286 
287 /* ===================== Private Function definitions =======================*/
288 static void
dptmapmem(void * arg,bus_dma_segment_t * segs,int nseg,int error)289 dptmapmem(void *arg, bus_dma_segment_t *segs, int nseg, int error)
290 {
291           bus_addr_t *busaddrp;
292 
293           busaddrp = (bus_addr_t *)arg;
294           *busaddrp = segs->ds_addr;
295 }
296 
297 static struct sg_map_node *
dptallocsgmap(struct dpt_softc * dpt)298 dptallocsgmap(struct dpt_softc *dpt)
299 {
300           struct sg_map_node *sg_map;
301 
302           sg_map = kmalloc(sizeof(*sg_map), M_DEVBUF, M_INTWAIT);
303 
304           /* Allocate S/G space for the next batch of CCBS */
305           if (bus_dmamem_alloc(dpt->sg_dmat, (void *)&sg_map->sg_vaddr,
306                                    BUS_DMA_NOWAIT, &sg_map->sg_dmamap) != 0) {
307                     kfree(sg_map, M_DEVBUF);
308                     return (NULL);
309           }
310 
311           (void)bus_dmamap_load(dpt->sg_dmat, sg_map->sg_dmamap, sg_map->sg_vaddr,
312                                     PAGE_SIZE, dptmapmem, &sg_map->sg_physaddr,
313                                     /*flags*/0);
314 
315           SLIST_INSERT_HEAD(&dpt->sg_maps, sg_map, links);
316 
317           return (sg_map);
318 }
319 
320 /*
321  * Allocate another chunk of CCB's. Return count of entries added.
322  * Assumed to be called at splcam().
323  */
324 static int
dptallocccbs(dpt_softc_t * dpt)325 dptallocccbs(dpt_softc_t *dpt)
326 {
327           struct dpt_ccb *next_ccb;
328           struct sg_map_node *sg_map;
329           bus_addr_t physaddr;
330           dpt_sg_t *segs;
331           int newcount;
332           int i;
333 
334           next_ccb = &dpt->dpt_dccbs[dpt->total_dccbs];
335 
336           if (next_ccb == dpt->dpt_dccbs) {
337                     /*
338                      * First time through.  Re-use the S/G
339                      * space we allocated for initialization
340                      * CCBS.
341                      */
342                     sg_map = SLIST_FIRST(&dpt->sg_maps);
343           } else {
344                     sg_map = dptallocsgmap(dpt);
345           }
346 
347           if (sg_map == NULL)
348                     return (0);
349 
350           segs = sg_map->sg_vaddr;
351           physaddr = sg_map->sg_physaddr;
352 
353           newcount = (PAGE_SIZE / (dpt->sgsize * sizeof(dpt_sg_t)));
354           for (i = 0; dpt->total_dccbs < dpt->max_dccbs && i < newcount; i++) {
355                     int error;
356 
357                     error = bus_dmamap_create(dpt->buffer_dmat, /*flags*/0,
358                                                     &next_ccb->dmamap);
359                     if (error != 0)
360                               break;
361                     next_ccb->sg_list = segs;
362                     next_ccb->sg_busaddr = htonl(physaddr);
363                     next_ccb->eata_ccb.cp_dataDMA = htonl(physaddr);
364                     next_ccb->eata_ccb.cp_statDMA = htonl(dpt->sp_physaddr);
365                     next_ccb->eata_ccb.cp_reqDMA =
366                         htonl(dptccbvtop(dpt, next_ccb)
367                               + offsetof(struct dpt_ccb, sense_data));
368                     next_ccb->eata_ccb.cp_busaddr = dpt->dpt_ccb_busend;
369                     next_ccb->state = DCCB_FREE;
370                     next_ccb->tag = dpt->total_dccbs;
371                     SLIST_INSERT_HEAD(&dpt->free_dccb_list, next_ccb, links);
372                     segs += dpt->sgsize;
373                     physaddr += (dpt->sgsize * sizeof(dpt_sg_t));
374                     dpt->dpt_ccb_busend += sizeof(*next_ccb);
375                     next_ccb++;
376                     dpt->total_dccbs++;
377           }
378           return (i);
379 }
380 
381 dpt_conf_t *
dpt_pio_get_conf(u_int32_t base)382 dpt_pio_get_conf (u_int32_t base)
383 {
384           static dpt_conf_t * conf;
385           u_int16_t *                   p;
386           int                           i;
387 
388           /*
389            * Allocate a dpt_conf_t
390            */
391           if (conf == NULL)
392                     conf = kmalloc(sizeof(dpt_conf_t), M_DEVBUF, M_INTWAIT);
393 
394           /*
395            * If we have one, clean it up.
396            */
397           bzero(conf, sizeof(dpt_conf_t));
398 
399           /*
400            * Reset the controller.
401            */
402           outb((base + HA_WCOMMAND), EATA_CMD_RESET);
403 
404           /*
405            * Wait for the controller to become ready.
406            * For some reason there can be -no- delays after calling reset
407            * before we wait on ready status.
408            */
409           if (dpt_pio_wait(base, HA_RSTATUS, HA_SBUSY, 0)) {
410                     kprintf("dpt: timeout waiting for controller to become ready\n");
411                     return (NULL);
412           }
413 
414           if (dpt_pio_wait(base, HA_RAUXSTAT, HA_ABUSY, 0)) {
415                     kprintf("dpt: timetout waiting for adapter ready.\n");
416                     return (NULL);
417           }
418 
419           /*
420            * Send the PIO_READ_CONFIG command.
421            */
422           outb((base + HA_WCOMMAND), EATA_CMD_PIO_READ_CONFIG);
423 
424           /*
425            * Read the data into the struct.
426            */
427           p = (u_int16_t *)conf;
428           for (i = 0; i < (sizeof(dpt_conf_t) / 2); i++) {
429 
430                     if (dpt_pio_wait(base, HA_RSTATUS, HA_SDRQ, 0)) {
431                               kprintf("dpt: timeout in data read.\n");
432                               return (NULL);
433                     }
434 
435                     (*p) = inw(base + HA_RDATA);
436                     p++;
437           }
438 
439           if (inb(base + HA_RSTATUS) & HA_SERROR) {
440                     kprintf("dpt: error reading configuration data.\n");
441                     return (NULL);
442           }
443 
444 #define BE_EATA_SIGNATURE     0x45415441
445 #define LE_EATA_SIGNATURE     0x41544145
446 
447           /*
448            * Test to see if we have a valid card.
449            */
450           if ((conf->signature == BE_EATA_SIGNATURE) ||
451               (conf->signature == LE_EATA_SIGNATURE)) {
452 
453                     while (inb(base + HA_RSTATUS) & HA_SDRQ) {
454                               inw(base + HA_RDATA);
455                     }
456 
457                     return (conf);
458           }
459           return (NULL);
460 }
461 
462 /*
463  * Read a configuration page into the supplied dpt_cont_t buffer.
464  */
465 static int
dpt_get_conf(dpt_softc_t * dpt,dpt_ccb_t * dccb,u_int32_t dccb_busaddr,u_int size,u_int page,u_int target,int extent)466 dpt_get_conf(dpt_softc_t *dpt, dpt_ccb_t *dccb, u_int32_t dccb_busaddr,
467                u_int size, u_int page, u_int target, int extent)
468 {
469           eata_ccb_t *cp;
470 
471           u_int8_t   status;
472 
473           int          ndx;
474           int          result;
475 
476           cp = &dccb->eata_ccb;
477           bzero((void *)(uintptr_t)(volatile void *)dpt->sp, sizeof(*dpt->sp));
478 
479           cp->Interpret = 1;
480           cp->DataIn = 1;
481           cp->Auto_Req_Sen = 1;
482           cp->reqlen = sizeof(struct scsi_sense_data);
483 
484           cp->cp_id = target;
485           cp->cp_LUN = 0;               /* In the EATA packet */
486           cp->cp_lun = 0;               /* In the SCSI command */
487 
488           cp->cp_scsi_cmd = INQUIRY;
489           cp->cp_len = size;
490 
491           cp->cp_extent = extent;
492 
493           cp->cp_page = page;
494           cp->cp_channel = 0; /* DNC, Interpret mode is set */
495           cp->cp_identify = 1;
496           cp->cp_datalen = htonl(size);
497 
498           crit_enter();
499 
500           /*
501            * This could be a simple for loop, but we suspected the compiler To
502            * have optimized it a bit too much. Wait for the controller to
503            * become ready
504            */
505           while (((status = dpt_inb(dpt, HA_RSTATUS)) != (HA_SREADY | HA_SSC)
506                && (status != (HA_SREADY | HA_SSC | HA_SERROR))
507                && (status != (HA_SDRDY | HA_SERROR | HA_SDRQ)))
508               || (dpt_wait(dpt, HA_SBUSY, 0))) {
509 
510                     /*
511                      * RAID Drives still Spinning up? (This should only occur if
512                      * the DPT controller is in a NON PC (PCI?) platform).
513                      */
514                     if (dpt_raid_busy(dpt)) {
515                               kprintf("dpt%d WARNING: Get_conf() RSUS failed.\n",
516                                      dpt->unit);
517                               crit_exit();
518                               return (0);
519                     }
520           }
521 
522           DptStat_Reset_BUSY(dpt->sp);
523 
524           /*
525            * XXXX We might want to do something more clever than aborting at
526            * this point, like resetting (rebooting) the controller and trying
527            * again.
528            */
529           if ((result = dpt_send_eata_command(dpt, cp, dccb_busaddr,
530                                                       EATA_CMD_DMA_SEND_CP,
531                                                       10000, 0, 0, 0)) != 0) {
532                     kprintf("dpt%d WARNING: Get_conf() failed (%d) to send "
533                            "EATA_CMD_DMA_READ_CONFIG\n",
534                            dpt->unit, result);
535                     crit_exit();
536                     return (0);
537           }
538           /* Wait for two seconds for a response.  This can be slow  */
539           for (ndx = 0;
540                (ndx < 20000)
541                && !((status = dpt_inb(dpt, HA_RAUXSTAT)) & HA_AIRQ);
542                ndx++) {
543                     DELAY(50);
544           }
545 
546           /* Grab the status and clear interrupts */
547           status = dpt_inb(dpt, HA_RSTATUS);
548 
549           crit_exit();
550 
551           /*
552            * Check the status carefully.  Return only if the
553            * command was successful.
554            */
555           if (((status & HA_SERROR) == 0)
556            && (dpt->sp->hba_stat == 0)
557            && (dpt->sp->scsi_stat == 0)
558            && (dpt->sp->residue_len == 0))
559                     return (0);
560 
561           if (dpt->sp->scsi_stat == SCSI_STATUS_CHECK_COND)
562                     return (0);
563 
564           return (1);
565 }
566 
567 /* Detect Cache parameters and size */
568 static void
dpt_detect_cache(dpt_softc_t * dpt,dpt_ccb_t * dccb,u_int32_t dccb_busaddr,u_int8_t * buff)569 dpt_detect_cache(dpt_softc_t *dpt, dpt_ccb_t *dccb, u_int32_t dccb_busaddr,
570                      u_int8_t *buff)
571 {
572           eata_ccb_t *cp;
573           u_int8_t   *param;
574           int           bytes;
575           int           result;
576           int           ndx;
577           u_int8_t    status;
578 
579           /*
580            * Default setting, for best perfromance..
581            * This is what virtually all cards default to..
582            */
583           dpt->cache_type = DPT_CACHE_WRITEBACK;
584           dpt->cache_size = 0;
585 
586           cp = &dccb->eata_ccb;
587           bzero((void *)(uintptr_t)(volatile void *)dpt->sp, sizeof(dpt->sp));
588           bzero(buff, 512);
589 
590           /* Setup the command structure */
591           cp->Interpret = 1;
592           cp->DataIn = 1;
593           cp->Auto_Req_Sen = 1;
594           cp->reqlen = sizeof(struct scsi_sense_data);
595 
596           cp->cp_id = 0;                /* who cares?  The HBA will interpret.. */
597           cp->cp_LUN = 0;               /* In the EATA packet */
598           cp->cp_lun = 0;               /* In the SCSI command */
599           cp->cp_channel = 0;
600 
601           cp->cp_scsi_cmd = EATA_CMD_DMA_SEND_CP;
602           cp->cp_len = 56;
603 
604           cp->cp_extent = 0;
605           cp->cp_page = 0;
606           cp->cp_identify = 1;
607           cp->cp_dispri = 1;
608 
609           /*
610            * Build the EATA Command Packet structure
611            * for a Log Sense Command.
612            */
613           cp->cp_cdb[0] = 0x4d;
614           cp->cp_cdb[1] = 0x0;
615           cp->cp_cdb[2] = 0x40 | 0x33;
616           cp->cp_cdb[7] = 1;
617 
618           cp->cp_datalen = htonl(512);
619 
620           crit_enter();
621           result = dpt_send_eata_command(dpt, cp, dccb_busaddr,
622                                                EATA_CMD_DMA_SEND_CP,
623                                                10000, 0, 0, 0);
624           if (result != 0) {
625                     kprintf("dpt%d WARNING: detect_cache() failed (%d) to send "
626                            "EATA_CMD_DMA_SEND_CP\n", dpt->unit, result);
627                     crit_exit();
628                     return;
629           }
630           /* Wait for two seconds for a response.  This can be slow... */
631           for (ndx = 0;
632                (ndx < 20000) &&
633                !((status = dpt_inb(dpt, HA_RAUXSTAT)) & HA_AIRQ);
634                ndx++) {
635                     DELAY(50);
636           }
637 
638           /* Grab the status and clear interrupts */
639           status = dpt_inb(dpt, HA_RSTATUS);
640           crit_exit();
641 
642           /*
643            * Sanity check
644            */
645           if (buff[0] != 0x33) {
646                     return;
647           }
648           bytes = DPT_HCP_LENGTH(buff);
649           param = DPT_HCP_FIRST(buff);
650 
651           if (DPT_HCP_CODE(param) != 1) {
652                     /*
653                      * DPT Log Page layout error
654                      */
655                     kprintf("dpt%d: NOTICE: Log Page (1) layout error\n",
656                            dpt->unit);
657                     return;
658           }
659           if (!(param[4] & 0x4)) {
660                     dpt->cache_type = DPT_NO_CACHE;
661                     return;
662           }
663           while (DPT_HCP_CODE(param) != 6) {
664                     param = DPT_HCP_NEXT(param);
665                     if ((param < buff)
666                      || (param >= &buff[bytes])) {
667                               return;
668                     }
669           }
670 
671           if (param[4] & 0x2) {
672                     /*
673                      * Cache disabled
674                      */
675                     dpt->cache_type = DPT_NO_CACHE;
676                     return;
677           }
678 
679           if (param[4] & 0x4) {
680                     dpt->cache_type = DPT_CACHE_WRITETHROUGH;
681           }
682 
683           /* XXX This isn't correct.  This log parameter only has two bytes.... */
684 #if 0
685           dpt->cache_size = param[5]
686                               | (param[6] << 8)
687                               | (param[7] << 16)
688                               | (param[8] << 24);
689 #endif
690 }
691 
692 static void
dpt_poll(struct cam_sim * sim)693 dpt_poll(struct cam_sim *sim)
694 {
695           dpt_intr(cam_sim_softc(sim));
696 }
697 
698 static void
dptexecuteccb(void * arg,bus_dma_segment_t * dm_segs,int nseg,int error)699 dptexecuteccb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
700 {
701           struct     dpt_ccb *dccb;
702           union      ccb *ccb;
703           struct     dpt_softc *dpt;
704 
705           dccb = (struct dpt_ccb *)arg;
706           ccb = dccb->ccb;
707           dpt = (struct dpt_softc *)ccb->ccb_h.ccb_dpt_ptr;
708 
709           if (error != 0) {
710                     if (error != EFBIG)
711                               kprintf("dpt%d: Unexpected error 0x%x returned from "
712                                      "bus_dmamap_load\n", dpt->unit, error);
713                     if (ccb->ccb_h.status == CAM_REQ_INPROG) {
714                               xpt_freeze_devq(ccb->ccb_h.path, /*count*/1);
715                               ccb->ccb_h.status = CAM_REQ_TOO_BIG|CAM_DEV_QFRZN;
716                     }
717                     dptfreeccb(dpt, dccb);
718                     xpt_done(ccb);
719                     return;
720           }
721 
722           if (nseg != 0) {
723                     dpt_sg_t *sg;
724                     bus_dma_segment_t *end_seg;
725                     bus_dmasync_op_t op;
726 
727                     end_seg = dm_segs + nseg;
728 
729                     /* Copy the segments into our SG list */
730                     sg = dccb->sg_list;
731                     while (dm_segs < end_seg) {
732                               sg->seg_len = htonl(dm_segs->ds_len);
733                               sg->seg_addr = htonl(dm_segs->ds_addr);
734                               sg++;
735                               dm_segs++;
736                     }
737 
738                     if (nseg > 1) {
739                               dccb->eata_ccb.scatter = 1;
740                               dccb->eata_ccb.cp_dataDMA = dccb->sg_busaddr;
741                               dccb->eata_ccb.cp_datalen =
742                                   htonl(nseg * sizeof(dpt_sg_t));
743                     } else {
744                               dccb->eata_ccb.cp_dataDMA = dccb->sg_list[0].seg_addr;
745                               dccb->eata_ccb.cp_datalen = dccb->sg_list[0].seg_len;
746                     }
747 
748                     if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
749                               op = BUS_DMASYNC_PREREAD;
750                     else
751                               op = BUS_DMASYNC_PREWRITE;
752 
753                     bus_dmamap_sync(dpt->buffer_dmat, dccb->dmamap, op);
754 
755           } else {
756                     dccb->eata_ccb.cp_dataDMA = 0;
757                     dccb->eata_ccb.cp_datalen = 0;
758           }
759 
760           crit_enter();
761 
762           /*
763            * Last time we need to check if this CCB needs to
764            * be aborted.
765            */
766           if (ccb->ccb_h.status != CAM_REQ_INPROG) {
767                     if (nseg != 0)
768                               bus_dmamap_unload(dpt->buffer_dmat, dccb->dmamap);
769                     dptfreeccb(dpt, dccb);
770                     xpt_done(ccb);
771                     crit_exit();
772                     return;
773           }
774 
775           dccb->state |= DCCB_ACTIVE;
776           ccb->ccb_h.status |= CAM_SIM_QUEUED;
777           LIST_INSERT_HEAD(&dpt->pending_ccb_list, &ccb->ccb_h, sim_links.le);
778           callout_reset(ccb->ccb_h.timeout_ch, (ccb->ccb_h.timeout * hz) / 1000,
779                           dpttimeout, dccb);
780           if (dpt_send_eata_command(dpt, &dccb->eata_ccb,
781                                           dccb->eata_ccb.cp_busaddr,
782                                           EATA_CMD_DMA_SEND_CP, 0, 0, 0, 0) != 0) {
783                     ccb->ccb_h.status = CAM_NO_HBA; /* HBA dead or just busy?? */
784                     if (nseg != 0)
785                               bus_dmamap_unload(dpt->buffer_dmat, dccb->dmamap);
786                     dptfreeccb(dpt, dccb);
787                     xpt_done(ccb);
788           }
789 
790           crit_exit();
791 }
792 
793 static void
dpt_action(struct cam_sim * sim,union ccb * ccb)794 dpt_action(struct cam_sim *sim, union ccb *ccb)
795 {
796           struct      dpt_softc *dpt;
797 
798           CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("dpt_action\n"));
799 
800           dpt = (struct dpt_softc *)cam_sim_softc(sim);
801 
802           if ((dpt->state & DPT_HA_SHUTDOWN_ACTIVE) != 0) {
803                     xpt_print_path(ccb->ccb_h.path);
804                     kprintf("controller is shutdown. Aborting CCB.\n");
805                     ccb->ccb_h.status = CAM_NO_HBA;
806                     xpt_done(ccb);
807                     return;
808           }
809 
810           switch (ccb->ccb_h.func_code) {
811           /* Common cases first */
812           case XPT_SCSI_IO:   /* Execute the requested I/O operation */
813           {
814                     struct    ccb_scsiio *csio;
815                     struct    ccb_hdr *ccbh;
816                     struct    dpt_ccb *dccb;
817                     struct    eata_ccb *eccb;
818 
819                     csio = &ccb->csio;
820                     ccbh = &ccb->ccb_h;
821                     /* Max CDB length is 12 bytes */
822                     if (csio->cdb_len > 12) {
823                               ccb->ccb_h.status = CAM_REQ_INVALID;
824                               xpt_done(ccb);
825                               return;
826                     }
827                     if ((dccb = dptgetccb(dpt)) == NULL) {
828                               crit_enter();
829                               dpt->resource_shortage = 1;
830                               crit_exit();
831                               xpt_freeze_simq(sim, /*count*/1);
832                               ccb->ccb_h.status = CAM_REQUEUE_REQ;
833                               xpt_done(ccb);
834                               return;
835                     }
836                     eccb = &dccb->eata_ccb;
837 
838                     /* Link dccb and ccb so we can find one from the other */
839                     dccb->ccb = ccb;
840                     ccb->ccb_h.ccb_dccb_ptr = dccb;
841                     ccb->ccb_h.ccb_dpt_ptr = dpt;
842 
843                     /*
844                      * Explicitly set all flags so that the compiler can
845                      * be smart about setting them.
846                      */
847                     eccb->SCSI_Reset = 0;
848                     eccb->HBA_Init = 0;
849                     eccb->Auto_Req_Sen = (ccb->ccb_h.flags & CAM_DIS_AUTOSENSE)
850                                            ? 0 : 1;
851                     eccb->scatter = 0;
852                     eccb->Quick = 0;
853                     eccb->Interpret =
854                         ccb->ccb_h.target_id == dpt->hostid[cam_sim_bus(sim)]
855                         ? 1 : 0;
856                     eccb->DataOut = (ccb->ccb_h.flags & CAM_DIR_OUT) ? 1 : 0;
857                     eccb->DataIn = (ccb->ccb_h.flags & CAM_DIR_IN) ? 1 : 0;
858                     eccb->reqlen = csio->sense_len;
859                     eccb->cp_id = ccb->ccb_h.target_id;
860                     eccb->cp_channel = cam_sim_bus(sim);
861                     eccb->cp_LUN = ccb->ccb_h.target_lun;
862                     eccb->cp_luntar = 0;
863                     eccb->cp_dispri = (ccb->ccb_h.flags & CAM_DIS_DISCONNECT)
864                                         ? 0 : 1;
865                     eccb->cp_identify = 1;
866 
867                     if ((ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) != 0
868                      && csio->tag_action != CAM_TAG_ACTION_NONE) {
869                               eccb->cp_msg[0] = csio->tag_action;
870                               eccb->cp_msg[1] = dccb->tag;
871                     } else {
872                               eccb->cp_msg[0] = 0;
873                               eccb->cp_msg[1] = 0;
874                     }
875                     eccb->cp_msg[2] = 0;
876 
877                     if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0) {
878                               if ((ccb->ccb_h.flags & CAM_CDB_PHYS) == 0) {
879                                         bcopy(csio->cdb_io.cdb_ptr,
880                                               eccb->cp_cdb, csio->cdb_len);
881                               } else {
882                                         /* I guess I could map it in... */
883                                         ccb->ccb_h.status = CAM_REQ_INVALID;
884                                         dptfreeccb(dpt, dccb);
885                                         xpt_done(ccb);
886                                         return;
887                               }
888                     } else {
889                               bcopy(csio->cdb_io.cdb_bytes,
890                                     eccb->cp_cdb, csio->cdb_len);
891                     }
892                     /*
893                      * If we have any data to send with this command,
894                      * map it into bus space.
895                      */
896                   /* Only use S/G if there is a transfer */
897                     if ((ccbh->flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
898                               if ((ccbh->flags & CAM_SCATTER_VALID) == 0) {
899                                         /*
900                                          * We've been given a pointer
901                                          * to a single buffer.
902                                          */
903                                         if ((ccbh->flags & CAM_DATA_PHYS) == 0) {
904                                                   int error;
905 
906                                                   crit_enter();
907                                                   error =
908                                                       bus_dmamap_load(dpt->buffer_dmat,
909                                                                           dccb->dmamap,
910                                                                           csio->data_ptr,
911                                                                           csio->dxfer_len,
912                                                                           dptexecuteccb,
913                                                                           dccb, /*flags*/0);
914                                                   if (error == EINPROGRESS) {
915                                                             /*
916                                                              * So as to maintain ordering,
917                                                              * freeze the controller queue
918                                                              * until our mapping is
919                                                              * returned.
920                                                              */
921                                                             xpt_freeze_simq(sim, 1);
922                                                             dccb->state |= CAM_RELEASE_SIMQ;
923                                                   }
924                                                   crit_exit();
925                                         } else {
926                                                   struct bus_dma_segment seg;
927 
928                                                   /* Pointer to physical buffer */
929                                                   seg.ds_addr =
930                                                       (bus_addr_t)csio->data_ptr;
931                                                   seg.ds_len = csio->dxfer_len;
932                                                   dptexecuteccb(dccb, &seg, 1, 0);
933                                         }
934                               } else {
935                                         struct bus_dma_segment *segs;
936 
937                                         if ((ccbh->flags & CAM_DATA_PHYS) != 0)
938                                                   panic("dpt_action - Physical "
939                                                         "segment pointers "
940                                                         "unsupported");
941 
942                                         if ((ccbh->flags&CAM_SG_LIST_PHYS)==0)
943                                                   panic("dpt_action - Virtual "
944                                                         "segment addresses "
945                                                         "unsupported");
946 
947                                         /* Just use the segments provided */
948                                         segs = (struct bus_dma_segment *)csio->data_ptr;
949                                         dptexecuteccb(dccb, segs, csio->sglist_cnt, 0);
950                               }
951                     } else {
952                               /*
953                                * XXX JGibbs.
954                                * Does it want them both on or both off?
955                                * CAM_DIR_NONE is both on, so this code can
956                                * be removed if this is also what the DPT
957                                * exptects.
958                                */
959                               eccb->DataOut = 0;
960                               eccb->DataIn = 0;
961                               dptexecuteccb(dccb, NULL, 0, 0);
962                     }
963                     break;
964           }
965           case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */
966           case XPT_ABORT:                         /* Abort the specified CCB */
967                     /* XXX Implement */
968                     ccb->ccb_h.status = CAM_REQ_INVALID;
969                     xpt_done(ccb);
970                     break;
971           case XPT_SET_TRAN_SETTINGS:
972           {
973                     ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
974                     xpt_done(ccb);
975                     break;
976           }
977           case XPT_GET_TRAN_SETTINGS:
978           /* Get default/user set transfer settings for the target */
979           {
980                     struct    ccb_trans_settings *cts = &ccb->cts;
981                     struct ccb_trans_settings_scsi *scsi =
982                         &cts->proto_specific.scsi;
983                     struct ccb_trans_settings_spi *spi =
984                         &cts->xport_specific.spi;
985 
986                     cts->protocol = PROTO_SCSI;
987                     cts->protocol_version = SCSI_REV_2;
988                     cts->transport = XPORT_SPI;
989                     cts->transport_version = 2;
990 
991                     if (cts->type == CTS_TYPE_USER_SETTINGS) {
992                               spi->flags = CTS_SPI_FLAGS_DISC_ENB;
993                               spi->bus_width = (dpt->max_id > 7)
994                                                ? MSG_EXT_WDTR_BUS_8_BIT
995                                                : MSG_EXT_WDTR_BUS_16_BIT;
996                               spi->sync_period = 25; /* 10MHz */
997                               if (spi->sync_period != 0)
998                                         spi->sync_offset = 15;
999                               scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
1000 
1001                               spi->valid = CTS_SPI_VALID_SYNC_RATE
1002                                         | CTS_SPI_VALID_SYNC_OFFSET
1003                                         | CTS_SPI_VALID_BUS_WIDTH
1004                                         | CTS_SPI_VALID_DISC;
1005                               scsi->valid = CTS_SCSI_VALID_TQ;
1006                               ccb->ccb_h.status = CAM_REQ_CMP;
1007                     } else {
1008                               ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
1009                     }
1010                     xpt_done(ccb);
1011                     break;
1012           }
1013           case XPT_CALC_GEOMETRY:
1014           {
1015                     struct      ccb_calc_geometry *ccg;
1016                     u_int32_t size_mb;
1017                     u_int32_t secs_per_cylinder;
1018                     int         extended;
1019 
1020                     /*
1021                      * XXX Use Adaptec translation until I find out how to
1022                      *     get this information from the card.
1023                      */
1024                     ccg = &ccb->ccg;
1025                     size_mb = ccg->volume_size
1026                               / ((1024L * 1024L) / ccg->block_size);
1027                     extended = 1;
1028 
1029                     if (size_mb > 1024 && extended) {
1030                               ccg->heads = 255;
1031                               ccg->secs_per_track = 63;
1032                     } else {
1033                               ccg->heads = 64;
1034                               ccg->secs_per_track = 32;
1035                     }
1036                     secs_per_cylinder = ccg->heads * ccg->secs_per_track;
1037                     ccg->cylinders = ccg->volume_size / secs_per_cylinder;
1038                     ccb->ccb_h.status = CAM_REQ_CMP;
1039                     xpt_done(ccb);
1040                     break;
1041           }
1042           case XPT_RESET_BUS:           /* Reset the specified SCSI bus */
1043           {
1044                     /* XXX Implement */
1045                     ccb->ccb_h.status = CAM_REQ_CMP;
1046                     xpt_done(ccb);
1047                     break;
1048           }
1049           case XPT_TERM_IO:             /* Terminate the I/O process */
1050                     /* XXX Implement */
1051                     ccb->ccb_h.status = CAM_REQ_INVALID;
1052                     xpt_done(ccb);
1053                     break;
1054           case XPT_PATH_INQ:            /* Path routing inquiry */
1055           {
1056                     struct ccb_pathinq *cpi = &ccb->cpi;
1057 
1058                     cpi->version_num = 1;
1059                     cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE;
1060                     if (dpt->max_id > 7)
1061                               cpi->hba_inquiry |= PI_WIDE_16;
1062                     cpi->target_sprt = 0;
1063                     cpi->hba_misc = 0;
1064                     cpi->hba_eng_cnt = 0;
1065                     cpi->max_target = dpt->max_id;
1066                     cpi->max_lun = dpt->max_lun;
1067                     cpi->initiator_id = dpt->hostid[cam_sim_bus(sim)];
1068                     cpi->bus_id = cam_sim_bus(sim);
1069                     cpi->base_transfer_speed = 3300;
1070                     strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
1071                     strncpy(cpi->hba_vid, "DPT", HBA_IDLEN);
1072                     strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
1073                     cpi->unit_number = cam_sim_unit(sim);
1074                 cpi->transport = XPORT_SPI;
1075                 cpi->transport_version = 2;
1076                 cpi->protocol = PROTO_SCSI;
1077                 cpi->protocol_version = SCSI_REV_2;
1078                     cpi->ccb_h.status = CAM_REQ_CMP;
1079                     xpt_done(ccb);
1080                     break;
1081           }
1082           default:
1083                     ccb->ccb_h.status = CAM_REQ_INVALID;
1084                     xpt_done(ccb);
1085                     break;
1086           }
1087 }
1088 
1089 /*
1090  * This routine will try to send an EATA command to the DPT HBA.
1091  * It will, by default, try 20,000 times, waiting 50us between tries.
1092  * It returns 0 on success and 1 on failure.
1093  * It is assumed to be called at splcam().
1094  */
1095 static int
dpt_send_eata_command(dpt_softc_t * dpt,eata_ccb_t * cmd_block,u_int32_t cmd_busaddr,u_int command,u_int retries,u_int ifc,u_int code,u_int code2)1096 dpt_send_eata_command(dpt_softc_t *dpt, eata_ccb_t *cmd_block,
1097                           u_int32_t cmd_busaddr, u_int command, u_int retries,
1098                           u_int ifc, u_int code, u_int code2)
1099 {
1100           u_int     loop;
1101 
1102           if (!retries)
1103                     retries = 20000;
1104 
1105           /*
1106            * I hate this polling nonsense. Wish there was a way to tell the DPT
1107            * to go get commands at its own pace,  or to interrupt when ready.
1108            * In the mean time we will measure how many itterations it really
1109            * takes.
1110            */
1111           for (loop = 0; loop < retries; loop++) {
1112                     if ((dpt_inb(dpt, HA_RAUXSTAT) & HA_ABUSY) == 0)
1113                               break;
1114                     else
1115                               DELAY(50);
1116           }
1117 
1118           if (loop < retries) {
1119 #ifdef DPT_MEASURE_PERFORMANCE
1120                     if (loop > dpt->performance.max_eata_tries)
1121                               dpt->performance.max_eata_tries = loop;
1122 
1123                     if (loop < dpt->performance.min_eata_tries)
1124                               dpt->performance.min_eata_tries = loop;
1125 #endif
1126           } else {
1127 #ifdef DPT_MEASURE_PERFORMANCE
1128                     ++dpt->performance.command_too_busy;
1129 #endif
1130                     return (1);
1131           }
1132 
1133           /* The controller is alive, advance the wedge timer */
1134 #ifdef DPT_RESET_HBA
1135           dpt->last_contact = microtime_now;
1136 #endif
1137 
1138           if (cmd_block == NULL)
1139                     cmd_busaddr = 0;
1140 #if (BYTE_ORDER == BIG_ENDIAN)
1141           else {
1142                     cmd_busaddr = ((cmd_busaddr >> 24) & 0xFF)
1143                                   | ((cmd_busaddr >> 16) & 0xFF)
1144                                   | ((cmd_busaddr >> 8) & 0xFF)
1145                                   | (cmd_busaddr & 0xFF);
1146           }
1147 #endif
1148           /* And now the address */
1149           dpt_outl(dpt, HA_WDMAADDR, cmd_busaddr);
1150 
1151           if (command == EATA_CMD_IMMEDIATE) {
1152                     if (cmd_block == NULL) {
1153                               dpt_outb(dpt, HA_WCODE2, code2);
1154                               dpt_outb(dpt, HA_WCODE, code);
1155                     }
1156                     dpt_outb(dpt, HA_WIFC, ifc);
1157           }
1158           dpt_outb(dpt, HA_WCOMMAND, command);
1159 
1160           return (0);
1161 }
1162 
1163 
1164 /* ==================== Exported Function definitions =======================*/
1165 dpt_softc_t *
dpt_alloc(device_t dev,bus_space_tag_t tag,bus_space_handle_t bsh)1166 dpt_alloc(device_t dev, bus_space_tag_t tag, bus_space_handle_t bsh)
1167 {
1168           dpt_softc_t         *dpt = device_get_softc(dev);
1169           int    i;
1170 
1171           bzero(dpt, sizeof(dpt_softc_t));
1172           dpt->tag = tag;
1173           dpt->bsh = bsh;
1174           dpt->unit = device_get_unit(dev);
1175           SLIST_INIT(&dpt->free_dccb_list);
1176           LIST_INIT(&dpt->pending_ccb_list);
1177           TAILQ_INSERT_TAIL(&dpt_softcs, dpt, links);
1178           for (i = 0; i < MAX_CHANNELS; i++)
1179                     dpt->resetlevel[i] = DPT_HA_OK;
1180 
1181 #ifdef DPT_MEASURE_PERFORMANCE
1182           dpt_reset_performance(dpt);
1183 #endif /* DPT_MEASURE_PERFORMANCE */
1184           return (dpt);
1185 }
1186 
1187 void
dpt_free(struct dpt_softc * dpt)1188 dpt_free(struct dpt_softc *dpt)
1189 {
1190           switch (dpt->init_level) {
1191           default:
1192           case 5:
1193                     bus_dmamap_unload(dpt->dccb_dmat, dpt->dccb_dmamap);
1194           case 4:
1195                     bus_dmamem_free(dpt->dccb_dmat, dpt->dpt_dccbs,
1196                                         dpt->dccb_dmamap);
1197                     bus_dmamap_destroy(dpt->dccb_dmat, dpt->dccb_dmamap);
1198           case 3:
1199                     bus_dma_tag_destroy(dpt->dccb_dmat);
1200           case 2:
1201                     bus_dma_tag_destroy(dpt->buffer_dmat);
1202           case 1:
1203           {
1204                     struct sg_map_node *sg_map;
1205 
1206                     while ((sg_map = SLIST_FIRST(&dpt->sg_maps)) != NULL) {
1207                               SLIST_REMOVE_HEAD(&dpt->sg_maps, links);
1208                               bus_dmamap_unload(dpt->sg_dmat,
1209                                                     sg_map->sg_dmamap);
1210                               bus_dmamem_free(dpt->sg_dmat, sg_map->sg_vaddr,
1211                                                   sg_map->sg_dmamap);
1212                               kfree(sg_map, M_DEVBUF);
1213                     }
1214                     bus_dma_tag_destroy(dpt->sg_dmat);
1215           }
1216           case 0:
1217                     break;
1218           }
1219           TAILQ_REMOVE(&dpt_softcs, dpt, links);
1220 }
1221 
1222 static u_int8_t string_sizes[] =
1223 {
1224           sizeof(((dpt_inq_t*)NULL)->vendor),
1225           sizeof(((dpt_inq_t*)NULL)->modelNum),
1226           sizeof(((dpt_inq_t*)NULL)->firmware),
1227           sizeof(((dpt_inq_t*)NULL)->protocol),
1228 };
1229 
1230 int
dpt_init(struct dpt_softc * dpt)1231 dpt_init(struct dpt_softc *dpt)
1232 {
1233           dpt_conf_t  conf;
1234           struct        sg_map_node *sg_map;
1235           dpt_ccb_t  *dccb;
1236           u_int8_t   *strp;
1237           int           index;
1238           int           i;
1239           int           retval;
1240 
1241           dpt->init_level = 0;
1242           SLIST_INIT(&dpt->sg_maps);
1243 
1244 #ifdef DPT_RESET_BOARD
1245           kprintf("dpt%d: resetting HBA\n", dpt->unit);
1246           dpt_outb(dpt, HA_WCOMMAND, EATA_CMD_RESET);
1247           DELAY(750000);
1248           /* XXX Shouldn't we poll a status register or something??? */
1249 #endif
1250           /* DMA tag for our S/G structures.  We allocate in page sized chunks */
1251           if (bus_dma_tag_create(dpt->parent_dmat, /*alignment*/1, /*boundary*/0,
1252                                      /*lowaddr*/BUS_SPACE_MAXADDR,
1253                                      /*highaddr*/BUS_SPACE_MAXADDR,
1254                                      PAGE_SIZE, /*nsegments*/1,
1255                                      /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
1256                                      /*flags*/0, &dpt->sg_dmat) != 0) {
1257                     goto error_exit;
1258         }
1259 
1260           dpt->init_level++;
1261 
1262           /*
1263            * We allocate our DPT ccbs as a contiguous array of bus dma'able
1264            * memory.  To get the allocation size, we need to know how many
1265            * ccbs the card supports.  This requires a ccb.  We solve this
1266            * chicken and egg problem by allocating some re-usable S/G space
1267            * up front, and treating it as our status packet, CCB, and target
1268            * memory space for these commands.
1269            */
1270           sg_map = dptallocsgmap(dpt);
1271           if (sg_map == NULL)
1272                     goto error_exit;
1273 
1274           dpt->sp = (volatile dpt_sp_t *)sg_map->sg_vaddr;
1275           dccb = (struct dpt_ccb *)(uintptr_t)(volatile void *)&dpt->sp[1];
1276           bzero(dccb, sizeof(*dccb));
1277           dpt->sp_physaddr = sg_map->sg_physaddr;
1278           dccb->eata_ccb.cp_dataDMA =
1279               htonl(sg_map->sg_physaddr + sizeof(dpt_sp_t) + sizeof(*dccb));
1280           dccb->eata_ccb.cp_busaddr = ~0;
1281           dccb->eata_ccb.cp_statDMA = htonl(dpt->sp_physaddr);
1282           dccb->eata_ccb.cp_reqDMA = htonl(dpt->sp_physaddr + sizeof(*dccb)
1283                                                + offsetof(struct dpt_ccb, sense_data));
1284 
1285           /* Okay.  Fetch our config */
1286           bzero(&dccb[1], sizeof(conf)); /* data area */
1287           retval = dpt_get_conf(dpt, dccb, sg_map->sg_physaddr + sizeof(dpt_sp_t),
1288                                     sizeof(conf), 0xc1, 7, 1);
1289 
1290           if (retval != 0) {
1291                     kprintf("dpt%d: Failed to get board configuration\n", dpt->unit);
1292                     return (retval);
1293           }
1294           bcopy(&dccb[1], &conf, sizeof(conf));
1295 
1296           bzero(&dccb[1], sizeof(dpt->board_data));
1297           retval = dpt_get_conf(dpt, dccb, sg_map->sg_physaddr + sizeof(dpt_sp_t),
1298                                     sizeof(dpt->board_data), 0, conf.scsi_id0, 0);
1299           if (retval != 0) {
1300                     kprintf("dpt%d: Failed to get inquiry information\n", dpt->unit);
1301                     return (retval);
1302           }
1303           bcopy(&dccb[1], &dpt->board_data, sizeof(dpt->board_data));
1304 
1305           dpt_detect_cache(dpt, dccb, sg_map->sg_physaddr + sizeof(dpt_sp_t),
1306                                (u_int8_t *)&dccb[1]);
1307 
1308           switch (ntohl(conf.splen)) {
1309           case DPT_EATA_REVA:
1310                     dpt->EATA_revision = 'a';
1311                     break;
1312           case DPT_EATA_REVB:
1313                     dpt->EATA_revision = 'b';
1314                     break;
1315           case DPT_EATA_REVC:
1316                     dpt->EATA_revision = 'c';
1317                     break;
1318           case DPT_EATA_REVZ:
1319                     dpt->EATA_revision = 'z';
1320                     break;
1321           default:
1322                     dpt->EATA_revision = '?';
1323           }
1324 
1325           dpt->max_id          = conf.MAX_ID;
1326           dpt->max_lun         = conf.MAX_LUN;
1327           dpt->irq   = conf.IRQ;
1328           dpt->dma_channel = (8 - conf.DMA_channel) & 7;
1329           dpt->channels        = conf.MAX_CHAN + 1;
1330           dpt->state          |= DPT_HA_OK;
1331           if (conf.SECOND)
1332                     dpt->primary = FALSE;
1333           else
1334                     dpt->primary = TRUE;
1335 
1336           dpt->more_support = conf.MORE_support;
1337 
1338           if (strncmp(dpt->board_data.firmware, "07G0", 4) >= 0)
1339                     dpt->immediate_support = 1;
1340           else
1341                     dpt->immediate_support = 0;
1342 
1343           dpt->broken_INQUIRY = FALSE;
1344 
1345           dpt->cplen = ntohl(conf.cplen);
1346           dpt->cppadlen = ntohs(conf.cppadlen);
1347           dpt->max_dccbs = ntohs(conf.queuesiz);
1348 
1349           if (dpt->max_dccbs > 256) {
1350                     kprintf("dpt%d: Max CCBs reduced from %d to "
1351                            "256 due to tag algorithm\n", dpt->unit, dpt->max_dccbs);
1352                     dpt->max_dccbs = 256;
1353           }
1354 
1355           dpt->hostid[0] = conf.scsi_id0;
1356           dpt->hostid[1] = conf.scsi_id1;
1357           dpt->hostid[2] = conf.scsi_id2;
1358 
1359           if (conf.SG_64K)
1360                     dpt->sgsize = 8192;
1361           else
1362                     dpt->sgsize = ntohs(conf.SGsiz);
1363 
1364           /* We can only get 64k buffers, so don't bother to waste space. */
1365           if (dpt->sgsize < 17 || dpt->sgsize > 32)
1366                     dpt->sgsize = 32;
1367 
1368           if (dpt->sgsize > dpt_max_segs)
1369                     dpt->sgsize = dpt_max_segs;
1370 
1371           /* DMA tag for mapping buffers into device visible space. */
1372           if (bus_dma_tag_create(dpt->parent_dmat, /*alignment*/1, /*boundary*/0,
1373                                      /*lowaddr*/BUS_SPACE_MAXADDR,
1374                                      /*highaddr*/BUS_SPACE_MAXADDR,
1375                                      /*maxsize*/MAXBSIZE, /*nsegments*/dpt->sgsize,
1376                                      /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
1377                                      /*flags*/BUS_DMA_ALLOCNOW,
1378                                      &dpt->buffer_dmat) != 0) {
1379                     kprintf("dpt: bus_dma_tag_create(...,dpt->buffer_dmat) failed\n");
1380                     goto error_exit;
1381           }
1382 
1383           dpt->init_level++;
1384 
1385           /* DMA tag for our ccb structures and interrupt status packet */
1386           if (bus_dma_tag_create(dpt->parent_dmat, /*alignment*/1, /*boundary*/0,
1387                                      /*lowaddr*/BUS_SPACE_MAXADDR,
1388                                      /*highaddr*/BUS_SPACE_MAXADDR,
1389                                      (dpt->max_dccbs * sizeof(struct dpt_ccb))
1390                                      + sizeof(dpt_sp_t),
1391                                      /*nsegments*/1,
1392                                      /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
1393                                      /*flags*/0, &dpt->dccb_dmat) != 0) {
1394                     kprintf("dpt: bus_dma_tag_create(...,dpt->dccb_dmat) failed\n");
1395                     goto error_exit;
1396         }
1397 
1398           dpt->init_level++;
1399 
1400           /* Allocation for our ccbs and interrupt status packet */
1401           if (bus_dmamem_alloc(dpt->dccb_dmat, (void *)&dpt->dpt_dccbs,
1402                                    BUS_DMA_NOWAIT, &dpt->dccb_dmamap) != 0) {
1403                     kprintf("dpt: bus_dmamem_alloc(dpt->dccb_dmat,...) failed\n");
1404                     goto error_exit;
1405           }
1406 
1407           dpt->init_level++;
1408 
1409           /* And permanently map them */
1410           bus_dmamap_load(dpt->dccb_dmat, dpt->dccb_dmamap,
1411                               dpt->dpt_dccbs,
1412                               (dpt->max_dccbs * sizeof(struct dpt_ccb))
1413                               + sizeof(dpt_sp_t),
1414                               dptmapmem, &dpt->dpt_ccb_busbase, /*flags*/0);
1415 
1416           /* Clear them out. */
1417           bzero(dpt->dpt_dccbs,
1418                 (dpt->max_dccbs * sizeof(struct dpt_ccb)) + sizeof(dpt_sp_t));
1419 
1420           dpt->dpt_ccb_busend = dpt->dpt_ccb_busbase;
1421 
1422           dpt->sp = (dpt_sp_t*)&dpt->dpt_dccbs[dpt->max_dccbs];
1423           dpt->sp_physaddr = dpt->dpt_ccb_busbase
1424                                + (dpt->max_dccbs * sizeof(dpt_ccb_t));
1425           dpt->init_level++;
1426 
1427           /* Allocate our first batch of ccbs */
1428           if (dptallocccbs(dpt) == 0) {
1429                     kprintf("dpt: dptallocccbs(dpt) == 0\n");
1430                     return (2);
1431           }
1432 
1433           /* Prepare for Target Mode */
1434           dpt->target_mode_enabled = 1;
1435 
1436           /* Nuke excess spaces from inquiry information */
1437           strp = dpt->board_data.vendor;
1438           for (i = 0; i < sizeof(string_sizes); i++) {
1439                     index = string_sizes[i] - 1;
1440                     while (index && (strp[index] == ' '))
1441                               strp[index--] = '\0';
1442                     strp += string_sizes[i];
1443           }
1444 
1445           kprintf("dpt%d: %.8s %.16s FW Rev. %.4s, ",
1446                  dpt->unit, dpt->board_data.vendor,
1447                  dpt->board_data.modelNum, dpt->board_data.firmware);
1448 
1449           kprintf("%d channel%s, ", dpt->channels, dpt->channels > 1 ? "s" : "");
1450 
1451           if (dpt->cache_type != DPT_NO_CACHE
1452            && dpt->cache_size != 0) {
1453                     kprintf("%s Cache, ",
1454                            dpt->cache_type == DPT_CACHE_WRITETHROUGH
1455                          ? "Write-Through" : "Write-Back");
1456           }
1457 
1458           kprintf("%d CCBs\n", dpt->max_dccbs);
1459           return (0);
1460 
1461 error_exit:
1462           return (1);
1463 }
1464 
1465 int
dpt_attach(dpt_softc_t * dpt)1466 dpt_attach(dpt_softc_t *dpt)
1467 {
1468           struct cam_devq *devq;
1469           int i;
1470 
1471           /*
1472            * Create the device queue for our SIM.
1473            */
1474           devq = cam_simq_alloc(dpt->max_dccbs);
1475           if (devq == NULL)
1476                     return (0);
1477 
1478           for (i = 0; i < dpt->channels; i++) {
1479                     /*
1480                      * Construct our SIM entry
1481                      */
1482                     dpt->sims[i] = cam_sim_alloc(dpt_action, dpt_poll, "dpt",
1483                                                        dpt, dpt->unit, &sim_mplock,
1484                                                        /*untagged*/2,
1485                                                        /*tagged*/dpt->max_dccbs, devq);
1486                     if (xpt_bus_register(dpt->sims[i], i) != CAM_SUCCESS) {
1487                               cam_sim_free(dpt->sims[i]);
1488                               break;
1489                     }
1490 
1491                     if (xpt_create_path(&dpt->paths[i], /*periph*/NULL,
1492                                             cam_sim_path(dpt->sims[i]),
1493                                             CAM_TARGET_WILDCARD,
1494                                             CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
1495                               xpt_bus_deregister(cam_sim_path(dpt->sims[i]));
1496                               cam_sim_free(dpt->sims[i]);
1497                               break;
1498                     }
1499 
1500           }
1501           cam_simq_release(devq);
1502           if (i > 0)
1503                     EVENTHANDLER_REGISTER(shutdown_post_sync, dptshutdown,
1504                                               dpt, SHUTDOWN_PRI_DRIVER);
1505           return (i);
1506 }
1507 
1508 
1509 /*
1510  * This is the interrupt handler for the DPT driver.
1511  */
1512 void
dpt_intr(void * arg)1513 dpt_intr(void *arg)
1514 {
1515           dpt_softc_t    *dpt;
1516           dpt_ccb_t      *dccb;
1517           union ccb      *ccb;
1518           u_int               status;
1519           u_int               aux_status;
1520           u_int               hba_stat;
1521           u_int               scsi_stat;
1522           u_int32_t residue_len;        /* Number of bytes not transferred */
1523 
1524           dpt = (dpt_softc_t *)arg;
1525 
1526           /* First order of business is to check if this interrupt is for us */
1527           while (((aux_status = dpt_inb(dpt, HA_RAUXSTAT)) & HA_AIRQ) != 0) {
1528 
1529                     /*
1530                      * What we want to do now, is to capture the status, all of it,
1531                      * move it where it belongs, wake up whoever sleeps waiting to
1532                      * process this result, and get out of here.
1533                      */
1534                     if (dpt->sp->ccb_busaddr < dpt->dpt_ccb_busbase
1535                      || dpt->sp->ccb_busaddr >= dpt->dpt_ccb_busend) {
1536                               kprintf("Encountered bogus status packet\n");
1537                               status = dpt_inb(dpt, HA_RSTATUS);
1538                               return;
1539                     }
1540 
1541                     dccb = dptccbptov(dpt, dpt->sp->ccb_busaddr);
1542 
1543                     dpt->sp->ccb_busaddr = ~0;
1544 
1545                     /* Ignore status packets with EOC not set */
1546                     if (dpt->sp->EOC == 0) {
1547                               kprintf("dpt%d ERROR: Request %d received with "
1548                                      "clear EOC.\n     Marking as LOST.\n",
1549                                      dpt->unit, dccb->transaction_id);
1550 
1551 #ifdef DPT_HANDLE_TIMEOUTS
1552                               dccb->state |= DPT_CCB_STATE_MARKED_LOST;
1553 #endif
1554                               /* This CLEARS the interrupt! */
1555                               status = dpt_inb(dpt, HA_RSTATUS);
1556                               continue;
1557                     }
1558                     dpt->sp->EOC = 0;
1559 
1560                     /*
1561                      * Double buffer the status information so the hardware can
1562                      * work on updating the status packet while we decifer the
1563                      * one we were just interrupted for.
1564                      * According to Mark Salyzyn, we only need few pieces of it.
1565                      */
1566                     hba_stat = dpt->sp->hba_stat;
1567                     scsi_stat = dpt->sp->scsi_stat;
1568                     residue_len = dpt->sp->residue_len;
1569 
1570                     /* Clear interrupts, check for error */
1571                     if ((status = dpt_inb(dpt, HA_RSTATUS)) & HA_SERROR) {
1572                               /*
1573                                * Error Condition. Check for magic cookie. Exit
1574                                * this test on earliest sign of non-reset condition
1575                                */
1576 
1577                               /* Check that this is not a board reset interrupt */
1578                               if (dpt_just_reset(dpt)) {
1579                                         kprintf("dpt%d: HBA rebooted.\n"
1580                                                "      All transactions should be "
1581                                                "resubmitted\n",
1582                                                dpt->unit);
1583 
1584                                         kprintf("dpt%d: >>---->>  This is incomplete, "
1585                                                "fix me....  <<----<<", dpt->unit);
1586                                         panic("DPT Rebooted");
1587 
1588                               }
1589                     }
1590                     /* Process CCB */
1591                     ccb = dccb->ccb;
1592                     callout_stop(ccb->ccb_h.timeout_ch);
1593                     if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
1594                               bus_dmasync_op_t op;
1595 
1596                               if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
1597                                         op = BUS_DMASYNC_POSTREAD;
1598                               else
1599                                         op = BUS_DMASYNC_POSTWRITE;
1600                               bus_dmamap_sync(dpt->buffer_dmat, dccb->dmamap, op);
1601                               bus_dmamap_unload(dpt->buffer_dmat, dccb->dmamap);
1602                     }
1603 
1604                     /* Common Case inline... */
1605                     if (hba_stat == HA_NO_ERROR) {
1606                               ccb->csio.scsi_status = scsi_stat;
1607                               ccb->ccb_h.status = 0;
1608                               switch (scsi_stat) {
1609                               case SCSI_STATUS_OK:
1610                                         ccb->ccb_h.status |= CAM_REQ_CMP;
1611                                         break;
1612                               case SCSI_STATUS_CHECK_COND:
1613                               case SCSI_STATUS_CMD_TERMINATED:
1614                                         bcopy(&dccb->sense_data, &ccb->csio.sense_data,
1615                                               ccb->csio.sense_len);
1616                                         ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
1617                                         /* FALLTHROUGH */
1618                               default:
1619                                         ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
1620                                         /* XXX Freeze DevQ */
1621                                         break;
1622                               }
1623                               ccb->csio.resid = residue_len;
1624                               dptfreeccb(dpt, dccb);
1625                               xpt_done(ccb);
1626                     } else {
1627                               dptprocesserror(dpt, dccb, ccb, hba_stat, scsi_stat,
1628                                                   residue_len);
1629                     }
1630           }
1631 }
1632 
1633 static void
dptprocesserror(dpt_softc_t * dpt,dpt_ccb_t * dccb,union ccb * ccb,u_int hba_stat,u_int scsi_stat,u_int32_t resid)1634 dptprocesserror(dpt_softc_t *dpt, dpt_ccb_t *dccb, union ccb *ccb,
1635                     u_int hba_stat, u_int scsi_stat, u_int32_t resid)
1636 {
1637           ccb->csio.resid = resid;
1638           switch (hba_stat) {
1639           case HA_ERR_SEL_TO:
1640                     ccb->ccb_h.status = CAM_SEL_TIMEOUT;
1641                     break;
1642           case HA_ERR_CMD_TO:
1643                     ccb->ccb_h.status = CAM_CMD_TIMEOUT;
1644                     break;
1645           case HA_SCSIBUS_RESET:
1646           case HA_HBA_POWER_UP:         /* Similar effect to a bus reset??? */
1647                     ccb->ccb_h.status = CAM_SCSI_BUS_RESET;
1648                     break;
1649           case HA_CP_ABORTED:
1650           case HA_CP_RESET:   /* XXX ??? */
1651           case HA_CP_ABORT_NA:          /* XXX ??? */
1652           case HA_CP_RESET_NA:          /* XXX ??? */
1653                     if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG)
1654                               ccb->ccb_h.status = CAM_REQ_ABORTED;
1655                     break;
1656           case HA_PCI_PARITY:
1657           case HA_PCI_MABORT:
1658           case HA_PCI_TABORT:
1659           case HA_PCI_STABORT:
1660           case HA_BUS_PARITY:
1661           case HA_PARITY_ERR:
1662           case HA_ECC_ERR:
1663                     ccb->ccb_h.status = CAM_UNCOR_PARITY;
1664                     break;
1665           case HA_UNX_MSGRJCT:
1666                     ccb->ccb_h.status = CAM_MSG_REJECT_REC;
1667                     break;
1668           case HA_UNX_BUSPHASE:
1669                     ccb->ccb_h.status = CAM_SEQUENCE_FAIL;
1670                     break;
1671           case HA_UNX_BUS_FREE:
1672                     ccb->ccb_h.status = CAM_UNEXP_BUSFREE;
1673                     break;
1674           case HA_SCSI_HUNG:
1675           case HA_RESET_STUCK:
1676                     /*
1677                      * Dead???  Can the controller get unstuck
1678                      * from these conditions
1679                      */
1680                     ccb->ccb_h.status = CAM_NO_HBA;
1681                     break;
1682           case HA_RSENSE_FAIL:
1683                     ccb->ccb_h.status = CAM_AUTOSENSE_FAIL;
1684                     break;
1685           default:
1686                     kprintf("dpt%d: Undocumented Error %x\n", dpt->unit, hba_stat);
1687                     kprintf("Please mail this message to shimon@simon-shapiro.org\n");
1688                     ccb->ccb_h.status = CAM_REQ_CMP_ERR;
1689                     break;
1690           }
1691           dptfreeccb(dpt, dccb);
1692           xpt_done(ccb);
1693 }
1694 
1695 static void
dpttimeout(void * arg)1696 dpttimeout(void *arg)
1697 {
1698           struct dpt_ccb       *dccb;
1699           union  ccb           *ccb;
1700           struct dpt_softc *dpt;
1701 
1702           dccb = (struct dpt_ccb *)arg;
1703           ccb = dccb->ccb;
1704           dpt = (struct dpt_softc *)ccb->ccb_h.ccb_dpt_ptr;
1705           xpt_print_path(ccb->ccb_h.path);
1706           kprintf("CCB %p - timed out\n", (void *)dccb);
1707 
1708           crit_enter();
1709 
1710           /*
1711            * Try to clear any pending jobs.  FreeBSD will loose interrupts,
1712            * leaving the controller suspended, and commands timed-out.
1713            * By calling the interrupt handler, any command thus stuck will be
1714            * completed.
1715            */
1716           dpt_intr(dpt);
1717 
1718           if ((dccb->state & DCCB_ACTIVE) == 0) {
1719                     xpt_print_path(ccb->ccb_h.path);
1720                     kprintf("CCB %p - timed out CCB already completed\n",
1721                            (void *)dccb);
1722                     crit_exit();
1723                     return;
1724           }
1725 
1726           /* Abort this particular command.  Leave all others running */
1727           dpt_send_immediate(dpt, &dccb->eata_ccb, dccb->eata_ccb.cp_busaddr,
1728                                  /*retries*/20000, EATA_SPECIFIC_ABORT, 0, 0);
1729           ccb->ccb_h.status = CAM_CMD_TIMEOUT;
1730           crit_exit();
1731 }
1732 
1733 /*
1734  * Shutdown the controller and ensure that the cache is completely flushed.
1735  * Called from the shutdown_final event after all disk access has completed.
1736  */
1737 static void
dptshutdown(void * arg,int howto)1738 dptshutdown(void *arg, int howto)
1739 {
1740           dpt_softc_t *dpt;
1741 
1742           dpt = (dpt_softc_t *)arg;
1743 
1744           kprintf("dpt%d: Shutting down (mode %x) HBA.      Please wait...\n",
1745                  dpt->unit, howto);
1746 
1747           /*
1748            * What we do for a shutdown, is give the DPT early power loss warning
1749            */
1750           dpt_send_immediate(dpt, NULL, 0, EATA_POWER_OFF_WARN, 0, 0, 0);
1751           DELAY(1000 * 1000 * 5);
1752           kprintf("dpt%d: Controller was warned of shutdown and is now "
1753                  "disabled\n", dpt->unit);
1754 }
1755 
1756 /*============================================================================*/
1757 
1758 #if 0
1759 #ifdef DPT_RESET_HBA
1760 
1761 /*
1762 **        Function name : dpt_reset_hba
1763 **
1764 **        Description : Reset the HBA and properly discard all pending work
1765 **        Input :       Softc
1766 **        Output :      Nothing
1767 */
1768 static void
1769 dpt_reset_hba(dpt_softc_t *dpt)
1770 {
1771           eata_ccb_t       *ccb;
1772           dpt_ccb_t         dccb, *dccbp;
1773           int               result;
1774           struct scsi_xfer *xs;
1775 
1776           /* Prepare a control block.  The SCSI command part is immaterial */
1777           dccb.xs = NULL;
1778           dccb.flags = 0;
1779           dccb.state = DPT_CCB_STATE_NEW;
1780           dccb.std_callback = NULL;
1781           dccb.wrbuff_callback = NULL;
1782 
1783           ccb = &dccb.eata_ccb;
1784           ccb->CP_OpCode = EATA_CMD_RESET;
1785           ccb->SCSI_Reset = 0;
1786           ccb->HBA_Init = 1;
1787           ccb->Auto_Req_Sen = 1;
1788           ccb->cp_id = 0; /* Should be ignored */
1789           ccb->DataIn = 1;
1790           ccb->DataOut = 0;
1791           ccb->Interpret = 1;
1792           ccb->reqlen = htonl(sizeof(struct scsi_sense_data));
1793           ccb->cp_statDMA = htonl(vtophys(&ccb->cp_statDMA));
1794           ccb->cp_reqDMA = htonl(vtophys(&ccb->cp_reqDMA));
1795           ccb->cp_viraddr = (u_int32_t) & ccb;
1796 
1797           ccb->cp_msg[0] = HA_IDENTIFY_MSG | HA_DISCO_RECO;
1798           ccb->cp_scsi_cmd = 0;  /* Should be ignored */
1799 
1800           /* Lock up the submitted queue.  We are very persistant here */
1801           crit_enter();
1802           while (dpt->queue_status & DPT_SUBMITTED_QUEUE_ACTIVE) {
1803                     DELAY(100);
1804           }
1805 
1806           dpt->queue_status |= DPT_SUBMITTED_QUEUE_ACTIVE;
1807           crit_exit();
1808 
1809           /* Send the RESET message */
1810           if ((result = dpt_send_eata_command(dpt, &dccb.eata_ccb,
1811                                                       EATA_CMD_RESET, 0, 0, 0, 0)) != 0) {
1812                     kprintf("dpt%d: Failed to send the RESET message.\n"
1813                            "      Trying cold boot (ouch!)\n", dpt->unit);
1814 
1815 
1816                     if ((result = dpt_send_eata_command(dpt, &dccb.eata_ccb,
1817                                                                 EATA_COLD_BOOT, 0, 0,
1818                                                                 0, 0)) != 0) {
1819                               panic("dpt%d:  Faild to cold boot the HBA",
1820                                     dpt->unit);
1821                     }
1822 #ifdef DPT_MEASURE_PERFORMANCE
1823                     dpt->performance.cold_boots++;
1824 #endif /* DPT_MEASURE_PERFORMANCE */
1825           }
1826 
1827 #ifdef DPT_MEASURE_PERFORMANCE
1828           dpt->performance.warm_starts++;
1829 #endif /* DPT_MEASURE_PERFORMANCE */
1830 
1831           kprintf("dpt%d:  Aborting pending requests.  O/S should re-submit\n",
1832                  dpt->unit);
1833 
1834           while ((dccbp = TAILQ_FIRST(&dpt->completed_ccbs)) != NULL) {
1835                     struct scsi_xfer *xs = dccbp->xs;
1836 
1837                     /* Not all transactions have xs structs */
1838                     if (xs != NULL) {
1839                               /* Tell the kernel proper this did not complete well */
1840                               xs->error |= XS_SELTIMEOUT;
1841                               xs->flags |= SCSI_ITSDONE;
1842                               scsi_done(xs);
1843                     }
1844 
1845                     dpt_Qremove_submitted(dpt, dccbp);
1846 
1847                     /* Remember, Callbacks are NOT in the standard queue */
1848                     if (dccbp->std_callback != NULL) {
1849                               (dccbp->std_callback)(dpt, dccbp->eata_ccb.cp_channel,
1850                                                          dccbp);
1851                     } else {
1852                               crit_enter();
1853                               dpt_Qpush_free(dpt, dccbp);
1854                               crit_exit();
1855                     }
1856           }
1857 
1858           kprintf("dpt%d: reset done aborting all pending commands\n", dpt->unit);
1859           dpt->queue_status &= ~DPT_SUBMITTED_QUEUE_ACTIVE;
1860 }
1861 
1862 #endif /* DPT_RESET_HBA */
1863 
1864 /*
1865  * Build a Command Block for target mode READ/WRITE BUFFER,
1866  * with the ``sync'' bit ON.
1867  *
1868  * Although the length and offset are 24 bit fields in the command, they cannot
1869  * exceed 8192 bytes, so we take them as short integers andcheck their range.
1870  * If they are sensless, we round them to zero offset, maximum length and
1871  * complain.
1872  */
1873 
1874 static void
1875 dpt_target_ccb(dpt_softc_t * dpt, int bus, u_int8_t target, u_int8_t lun,
1876                  dpt_ccb_t * ccb, int mode, u_int8_t command,
1877                  u_int16_t length, u_int16_t offset)
1878 {
1879           eata_ccb_t     *cp;
1880 
1881           if ((length + offset) > DPT_MAX_TARGET_MODE_BUFFER_SIZE) {
1882                     kprintf("dpt%d:  Length of %d, and offset of %d are wrong\n",
1883                            dpt->unit, length, offset);
1884                     length = DPT_MAX_TARGET_MODE_BUFFER_SIZE;
1885                     offset = 0;
1886           }
1887           ccb->xs = NULL;
1888           ccb->flags = 0;
1889           ccb->state = DPT_CCB_STATE_NEW;
1890           ccb->std_callback = (ccb_callback) dpt_target_done;
1891           ccb->wrbuff_callback = NULL;
1892 
1893           cp = &ccb->eata_ccb;
1894           cp->CP_OpCode = EATA_CMD_DMA_SEND_CP;
1895           cp->SCSI_Reset = 0;
1896           cp->HBA_Init = 0;
1897           cp->Auto_Req_Sen = 1;
1898           cp->cp_id = target;
1899           cp->DataIn = 1;
1900           cp->DataOut = 0;
1901           cp->Interpret = 0;
1902           cp->reqlen = htonl(sizeof(struct scsi_sense_data));
1903           cp->cp_statDMA = htonl(vtophys(&cp->cp_statDMA));
1904           cp->cp_reqDMA = htonl(vtophys(&cp->cp_reqDMA));
1905           cp->cp_viraddr = (u_int32_t) & ccb;
1906 
1907           cp->cp_msg[0] = HA_IDENTIFY_MSG | HA_DISCO_RECO;
1908 
1909           cp->cp_scsi_cmd = command;
1910           cp->cp_cdb[1] = (u_int8_t) (mode & SCSI_TM_MODE_MASK);
1911           cp->cp_lun = lun;   /* Order is important here! */
1912           cp->cp_cdb[2] = 0x00;         /* Buffer Id, only 1 :-( */
1913           cp->cp_cdb[3] = (length >> 16) & 0xFF;  /* Buffer offset MSB */
1914           cp->cp_cdb[4] = (length >> 8) & 0xFF;
1915           cp->cp_cdb[5] = length & 0xFF;
1916           cp->cp_cdb[6] = (length >> 16) & 0xFF;  /* Length MSB */
1917           cp->cp_cdb[7] = (length >> 8) & 0xFF;
1918           cp->cp_cdb[8] = length & 0xFF;          /* Length LSB */
1919           cp->cp_cdb[9] = 0;  /* No sync, no match bits */
1920 
1921           /*
1922            * This could be optimized to live in dpt_register_buffer.
1923            * We keep it here, just in case the kernel decides to reallocate pages
1924            */
1925           if (dpt_scatter_gather(dpt, ccb, DPT_RW_BUFFER_SIZE,
1926                                      dpt->rw_buffer[bus][target][lun])) {
1927                     kprintf("dpt%d: Failed to setup Scatter/Gather for "
1928                            "Target-Mode buffer\n", dpt->unit);
1929           }
1930 }
1931 
1932 /* Setup a target mode READ command */
1933 
1934 static void
1935 dpt_set_target(int redo, dpt_softc_t * dpt,
1936                  u_int8_t bus, u_int8_t target, u_int8_t lun, int mode,
1937                  u_int16_t length, u_int16_t offset, dpt_ccb_t * ccb)
1938 {
1939           if (dpt->target_mode_enabled) {
1940                     crit_enter();
1941 
1942                     if (!redo)
1943                               dpt_target_ccb(dpt, bus, target, lun, ccb, mode,
1944                                                SCSI_TM_READ_BUFFER, length, offset);
1945 
1946                     ccb->transaction_id = ++dpt->commands_processed;
1947 
1948 #ifdef DPT_MEASURE_PERFORMANCE
1949                     dpt->performance.command_count[ccb->eata_ccb.cp_scsi_cmd]++;
1950                     ccb->command_started = microtime_now;
1951 #endif
1952                     dpt_Qadd_waiting(dpt, ccb);
1953                     dpt_sched_queue(dpt);
1954 
1955                     crit_exit();
1956           } else {
1957                     kprintf("dpt%d:  Target Mode Request, but Target Mode is OFF\n",
1958                            dpt->unit);
1959           }
1960 }
1961 
1962 /*
1963  * Schedule a buffer to be sent to another target.
1964  * The work will be scheduled and the callback provided will be called when
1965  * the work is actually done.
1966  *
1967  * Please NOTE:  ``Anyone'' can send a buffer, but only registered clients
1968  * get notified of receipt of buffers.
1969  */
1970 
1971 int
1972 dpt_send_buffer(int unit, u_int8_t channel, u_int8_t target, u_int8_t lun,
1973                     u_int8_t mode, u_int16_t length, u_int16_t offset, void *data,
1974                     buff_wr_done callback)
1975 {
1976           dpt_softc_t    *dpt;
1977           dpt_ccb_t      *ccb = NULL;
1978 
1979           /* This is an external call.  Be a bit paranoid */
1980           for (dpt = TAILQ_FIRST(&dpt_softc_list);
1981                dpt != NULL;
1982                dpt = TAILQ_NEXT(dpt, links)) {
1983                     if (dpt->unit == unit)
1984                               goto valid_unit;
1985           }
1986 
1987           return (INVALID_UNIT);
1988 
1989 valid_unit:
1990 
1991           if (dpt->target_mode_enabled) {
1992                     if ((channel >= dpt->channels) || (target > dpt->max_id) ||
1993                         (lun > dpt->max_lun)) {
1994                               return (INVALID_SENDER);
1995                     }
1996                     if ((dpt->rw_buffer[channel][target][lun] == NULL) ||
1997                         (dpt->buffer_receiver[channel][target][lun] == NULL))
1998                               return (NOT_REGISTERED);
1999 
2000                     crit_enter();
2001                     /* Process the free list */
2002                     if ((TAILQ_EMPTY(&dpt->free_ccbs)) && dpt_alloc_freelist(dpt)) {
2003                               kprintf("dpt%d ERROR: Cannot allocate any more free CCB's.\n"
2004                                      "             Please try later\n",
2005                                      dpt->unit);
2006                               crit_exit();
2007                               return (NO_RESOURCES);
2008                     }
2009                     /* Now grab the newest CCB */
2010                     if ((ccb = dpt_Qpop_free(dpt)) == NULL) {
2011                               crit_exit();
2012                               panic("dpt%d: Got a NULL CCB from pop_free()", dpt->unit);
2013                     }
2014                     crit_exit();
2015 
2016                     bcopy(dpt->rw_buffer[channel][target][lun] + offset, data, length);
2017                     dpt_target_ccb(dpt, channel, target, lun, ccb, mode,
2018                                                      SCSI_TM_WRITE_BUFFER,
2019                                                      length, offset);
2020                     ccb->std_callback = (ccb_callback) callback; /* Potential trouble */
2021 
2022                     crit_enter();
2023                     ccb->transaction_id = ++dpt->commands_processed;
2024 
2025 #ifdef DPT_MEASURE_PERFORMANCE
2026                     dpt->performance.command_count[ccb->eata_ccb.cp_scsi_cmd]++;
2027                     ccb->command_started = microtime_now;
2028 #endif
2029                     dpt_Qadd_waiting(dpt, ccb);
2030                     dpt_sched_queue(dpt);
2031 
2032                     crit_exit();
2033                     return (0);
2034           }
2035           return (DRIVER_DOWN);
2036 }
2037 
2038 static void
2039 dpt_target_done(dpt_softc_t * dpt, int bus, dpt_ccb_t * ccb)
2040 {
2041           eata_ccb_t     *cp;
2042 
2043           cp = &ccb->eata_ccb;
2044 
2045           /*
2046            * Remove the CCB from the waiting queue.
2047            *  We do NOT put it back on the free, etc., queues as it is a special
2048            * ccb, owned by the dpt_softc of this unit.
2049            */
2050           crit_enter();
2051           dpt_Qremove_completed(dpt, ccb);
2052           crit_exit();
2053 
2054 #define br_channel           (ccb->eata_ccb.cp_channel)
2055 #define br_target            (ccb->eata_ccb.cp_id)
2056 #define br_lun               (ccb->eata_ccb.cp_LUN)
2057 #define br_index         [br_channel][br_target][br_lun]
2058 #define read_buffer_callback (dpt->buffer_receiver br_index )
2059 #define   read_buffer              (dpt->rw_buffer[br_channel][br_target][br_lun])
2060 #define cb(offset)           (ccb->eata_ccb.cp_cdb[offset])
2061 #define br_offset            ((cb(3) << 16) | (cb(4) << 8) | cb(5))
2062 #define br_length            ((cb(6) << 16) | (cb(7) << 8) | cb(8))
2063 
2064           /* Different reasons for being here, you know... */
2065           switch (ccb->eata_ccb.cp_scsi_cmd) {
2066           case SCSI_TM_READ_BUFFER:
2067                     if (read_buffer_callback != NULL) {
2068                               /* This is a buffer generated by a kernel process */
2069                               read_buffer_callback(dpt->unit, br_channel,
2070                                                        br_target, br_lun,
2071                                                        read_buffer,
2072                                                        br_offset, br_length);
2073                     } else {
2074                               /*
2075                                * This is a buffer waited for by a user (sleeping)
2076                                * command
2077                                */
2078                               wakeup(ccb);
2079                     }
2080 
2081                     /* We ALWAYS re-issue the same command; args are don't-care  */
2082                     dpt_set_target(1, 0, 0, 0, 0, 0, 0, 0, 0);
2083                     break;
2084 
2085           case SCSI_TM_WRITE_BUFFER:
2086                     (ccb->wrbuff_callback) (dpt->unit, br_channel, br_target,
2087                                                   br_offset, br_length,
2088                                                   br_lun, ccb->status_packet.hba_stat);
2089                     break;
2090           default:
2091                     kprintf("dpt%d:  %s is an unsupported command for target mode\n",
2092                            dpt->unit, scsi_cmd_name(ccb->eata_ccb.cp_scsi_cmd));
2093           }
2094           crit_enter();
2095           dpt->target_ccb[br_channel][br_target][br_lun] = NULL;
2096           dpt_Qpush_free(dpt, ccb);
2097           crit_exit();
2098 }
2099 
2100 
2101 /*
2102  * Use this function to register a client for a buffer read target operation.
2103  * The function you register will be called every time a buffer is received
2104  * by the target mode code.
2105  */
2106 dpt_rb_t
2107 dpt_register_buffer(int unit, u_int8_t channel, u_int8_t target, u_int8_t lun,
2108                         u_int8_t mode, u_int16_t length, u_int16_t offset,
2109                         dpt_rec_buff callback, dpt_rb_op_t op)
2110 {
2111           dpt_softc_t    *dpt;
2112           dpt_ccb_t      *ccb = NULL;
2113 
2114           for (dpt = TAILQ_FIRST(&dpt_softc_list);
2115                dpt != NULL;
2116                dpt = TAILQ_NEXT(dpt, links)) {
2117                     if (dpt->unit == unit)
2118                               goto valid_unit;
2119           }
2120 
2121           return (INVALID_UNIT);
2122 
2123 valid_unit:
2124 
2125           if (dpt->state & DPT_HA_SHUTDOWN_ACTIVE)
2126                     return (DRIVER_DOWN);
2127 
2128           if ((channel > (dpt->channels - 1)) || (target > (dpt->max_id - 1)) ||
2129               (lun > (dpt->max_lun - 1)))
2130                     return (INVALID_SENDER);
2131 
2132           if (dpt->buffer_receiver[channel][target][lun] == NULL) {
2133                     if (op == REGISTER_BUFFER) {
2134                               /* Assign the requested callback */
2135                               dpt->buffer_receiver[channel][target][lun] = callback;
2136                               /* Get a CCB */
2137                               crit_enter();
2138 
2139                               /* Process the free list */
2140                               if ((TAILQ_EMPTY(&dpt->free_ccbs)) && dpt_alloc_freelist(dpt)) {
2141                                         kprintf("dpt%d ERROR: Cannot allocate any more free CCB's.\n"
2142                                                "             Please try later\n",
2143                                                dpt->unit);
2144                                         crit_exit();
2145                                         return (NO_RESOURCES);
2146                               }
2147                               /* Now grab the newest CCB */
2148                               if ((ccb = dpt_Qpop_free(dpt)) == NULL) {
2149                                         crit_exit();
2150                                         panic("dpt%d: Got a NULL CCB from pop_free()",
2151                                               dpt->unit);
2152                               }
2153                               crit_exit();
2154 
2155                               /* Clean up the leftover of the previous tenant */
2156                               ccb->status = DPT_CCB_STATE_NEW;
2157                               dpt->target_ccb[channel][target][lun] = ccb;
2158 
2159                               dpt->rw_buffer[channel][target][lun] =
2160                                         kmalloc(DPT_RW_BUFFER_SIZE, M_DEVBUF, M_INTWAIT);
2161                               dpt_set_target(0, dpt, channel, target, lun, mode,
2162                                                length, offset, ccb);
2163                               return (SUCCESSFULLY_REGISTERED);
2164                     } else
2165                               return (NOT_REGISTERED);
2166           } else {
2167                     if (op == REGISTER_BUFFER) {
2168                               if (dpt->buffer_receiver[channel][target][lun] == callback)
2169                                         return (ALREADY_REGISTERED);
2170                               else
2171                                         return (REGISTERED_TO_ANOTHER);
2172                     } else {
2173                               if (dpt->buffer_receiver[channel][target][lun] == callback) {
2174                                         dpt->buffer_receiver[channel][target][lun] = NULL;
2175                                         crit_enter();
2176                                         dpt_Qpush_free(dpt, ccb);
2177                                         crit_exit();
2178                                         kfree(dpt->rw_buffer[channel][target][lun], M_DEVBUF);
2179                                         return (SUCCESSFULLY_REGISTERED);
2180                               } else
2181                                         return (INVALID_CALLBACK);
2182                     }
2183 
2184           }
2185 }
2186 
2187 /* Return the state of the blinking DPT LED's */
2188 u_int8_t
2189 dpt_blinking_led(dpt_softc_t * dpt)
2190 {
2191           int             ndx;
2192           u_int32_t       state;
2193           u_int32_t       previous;
2194           u_int8_t        result;
2195 
2196           crit_enter();
2197 
2198           result = 0;
2199 
2200           for (ndx = 0, state = 0, previous = 0;
2201                (ndx < 10) && (state != previous);
2202                ndx++) {
2203                     previous = state;
2204                     state = dpt_inl(dpt, 1);
2205           }
2206 
2207           if ((state == previous) && (state == DPT_BLINK_INDICATOR))
2208                     result = dpt_inb(dpt, 5);
2209 
2210           crit_exit();
2211           return (result);
2212 }
2213 
2214 /*
2215  * Execute a command which did not come from the kernel's SCSI layer.
2216  * The only way to map user commands to bus and target is to comply with the
2217  * standard DPT wire-down scheme:
2218  */
2219 int
2220 dpt_user_cmd(dpt_softc_t * dpt, eata_pt_t * user_cmd,
2221                caddr_t cmdarg, int minor_no)
2222 {
2223           dpt_ccb_t *ccb;
2224           void        *data;
2225           int          channel, target, lun;
2226           int          huh;
2227           int          result;
2228           int          submitted;
2229           size_t       contigsize = 0;
2230 
2231           data = NULL;
2232           channel = minor2hba(minor_no);
2233           target = minor2target(minor_no);
2234           lun = minor2lun(minor_no);
2235 
2236           if ((channel > (dpt->channels - 1))
2237            || (target > dpt->max_id)
2238            || (lun > dpt->max_lun))
2239                     return (ENXIO);
2240 
2241           if (target == dpt->sc_scsi_link[channel].adapter_targ) {
2242                     /* This one is for the controller itself */
2243                     if ((user_cmd->eataID[0] != 'E')
2244                      || (user_cmd->eataID[1] != 'A')
2245                      || (user_cmd->eataID[2] != 'T')
2246                      || (user_cmd->eataID[3] != 'A')) {
2247                               return (ENXIO);
2248                     }
2249           }
2250           /* Get a DPT CCB, so we can prepare a command */
2251           crit_enter();
2252 
2253           /* Process the free list */
2254           if ((TAILQ_EMPTY(&dpt->free_ccbs)) && dpt_alloc_freelist(dpt)) {
2255                     kprintf("dpt%d ERROR: Cannot allocate any more free CCB's.\n"
2256                            "             Please try later\n",
2257                            dpt->unit);
2258                     crit_exit();
2259                     return (EFAULT);
2260           }
2261           /* Now grab the newest CCB */
2262           if ((ccb = dpt_Qpop_free(dpt)) == NULL) {
2263                     crit_exit();
2264                     panic("dpt%d: Got a NULL CCB from pop_free()", dpt->unit);
2265           } else {
2266                     crit_exit();
2267                     /* Clean up the leftover of the previous tenant */
2268                     ccb->status = DPT_CCB_STATE_NEW;
2269           }
2270 
2271           bcopy((caddr_t) & user_cmd->command_packet, (caddr_t) & ccb->eata_ccb,
2272                 sizeof(eata_ccb_t));
2273 
2274           /* We do not want to do user specified scatter/gather.  Why?? */
2275           if (ccb->eata_ccb.scatter == 1)
2276                     return (EINVAL);
2277 
2278           ccb->eata_ccb.Auto_Req_Sen = 1;
2279           ccb->eata_ccb.reqlen = htonl(sizeof(struct scsi_sense_data));
2280           ccb->eata_ccb.cp_datalen = htonl(sizeof(ccb->eata_ccb.cp_datalen));
2281           ccb->eata_ccb.cp_dataDMA = htonl(vtophys(ccb->eata_ccb.cp_dataDMA));
2282           ccb->eata_ccb.cp_statDMA = htonl(vtophys(&ccb->eata_ccb.cp_statDMA));
2283           ccb->eata_ccb.cp_reqDMA = htonl(vtophys(&ccb->eata_ccb.cp_reqDMA));
2284           ccb->eata_ccb.cp_viraddr = (u_int32_t) & ccb;
2285 
2286           if (ccb->eata_ccb.DataIn || ccb->eata_ccb.DataOut) {
2287                     /* Data I/O is involved in this command.  Alocate buffer */
2288                     if (ccb->eata_ccb.cp_datalen > PAGE_SIZE) {
2289                               contigsize = ccb->eata_ccb.cp_datalen;
2290                               data = contigmalloc(ccb->eata_ccb.cp_datalen,
2291                                                       M_TEMP, M_WAITOK, 0, ~0,
2292                                                       ccb->eata_ccb.cp_datalen,
2293                                                       0x10000);
2294                     } else {
2295                               data = kmalloc(ccb->eata_ccb.cp_datalen, M_TEMP,
2296                                               M_WAITOK);
2297                     }
2298 
2299                     if (data == NULL) {
2300                               kprintf("dpt%d: Cannot allocate %d bytes "
2301                                      "for EATA command\n", dpt->unit,
2302                                      ccb->eata_ccb.cp_datalen);
2303                               return (EFAULT);
2304                     }
2305 #define usr_cmd_DMA (caddr_t)user_cmd->command_packet.cp_dataDMA
2306                     if (ccb->eata_ccb.DataIn == 1) {
2307                               if (copyin(usr_cmd_DMA,
2308                                            data, ccb->eata_ccb.cp_datalen) == -1)
2309                                         return (EFAULT);
2310                     }
2311           } else {
2312                     /* No data I/O involved here.  Make sure the DPT knows that */
2313                     ccb->eata_ccb.cp_datalen = 0;
2314                     data = NULL;
2315           }
2316 
2317           if (ccb->eata_ccb.FWNEST == 1)
2318                     ccb->eata_ccb.FWNEST = 0;
2319 
2320           if (ccb->eata_ccb.cp_datalen != 0) {
2321                     if (dpt_scatter_gather(dpt, ccb, ccb->eata_ccb.cp_datalen,
2322                                                data) != 0) {
2323                               if (data != NULL) {
2324                                         if (contigsize)
2325                                                   contigfree(data, contigsize, M_TEMP);
2326                                         else
2327                                                   kfree(data, M_TEMP);
2328                               }
2329                               return (EFAULT);
2330                     }
2331           }
2332           /**
2333            * We are required to quiet a SCSI bus.
2334            * since we do not queue comands on a bus basis,
2335            * we wait for ALL commands on a controller to complete.
2336            * In the mean time, sched_queue() will not schedule new commands.
2337            */
2338           if ((ccb->eata_ccb.cp_cdb[0] == MULTIFUNCTION_CMD)
2339               && (ccb->eata_ccb.cp_cdb[2] == BUS_QUIET)) {
2340                     /* We wait for ALL traffic for this HBa to subside */
2341                     crit_enter();
2342                     dpt->state |= DPT_HA_QUIET;
2343                     crit_exit();
2344 
2345                     while ((submitted = dpt->submitted_ccbs_count) != 0) {
2346                               huh = tsleep((void *) dpt, PCATCH, "dptqt", 100 * hz);
2347                               switch (huh) {
2348                               case 0:
2349                                         /* Wakeup call received */
2350                                         break;
2351                               case EWOULDBLOCK:
2352                                         /* Timer Expired */
2353                                         break;
2354                               default:
2355                                         /* anything else */
2356                                         break;
2357                               }
2358                     }
2359           }
2360           /* Resume normal operation */
2361           if ((ccb->eata_ccb.cp_cdb[0] == MULTIFUNCTION_CMD)
2362               && (ccb->eata_ccb.cp_cdb[2] == BUS_UNQUIET)) {
2363                     crit_enter();
2364                     dpt->state &= ~DPT_HA_QUIET;
2365                     crit_exit();
2366           }
2367           /**
2368            * Schedule the command and submit it.
2369            * We bypass dpt_sched_queue, as it will block on DPT_HA_QUIET
2370            */
2371           ccb->xs = NULL;
2372           ccb->flags = 0;
2373           ccb->eata_ccb.Auto_Req_Sen = 1;         /* We always want this feature */
2374 
2375           ccb->transaction_id = ++dpt->commands_processed;
2376           ccb->std_callback = (ccb_callback) dpt_user_cmd_done;
2377           ccb->result = (u_int32_t) & cmdarg;
2378           ccb->data = data;
2379 
2380 #ifdef DPT_MEASURE_PERFORMANCE
2381           ++dpt->performance.command_count[ccb->eata_ccb.cp_scsi_cmd];
2382           ccb->command_started = microtime_now;
2383 #endif
2384           crit_enter();
2385           dpt_Qadd_waiting(dpt, ccb);
2386           crit_exit();
2387 
2388           dpt_sched_queue(dpt);
2389 
2390           /* Wait for the command to complete */
2391           (void) tsleep((void *) ccb, PCATCH, "dptucw", 100 * hz);
2392 
2393           /* Free allocated memory */
2394           if (data != NULL) {
2395                     if (contigsize)
2396                               contigfree(data, contigsize, M_TEMP);
2397                     else
2398                               kfree(data, M_TEMP);
2399           }
2400 
2401           return (0);
2402 }
2403 
2404 static void
2405 dpt_user_cmd_done(dpt_softc_t * dpt, int bus, dpt_ccb_t * ccb)
2406 {
2407           u_int32_t       result;
2408           caddr_t         cmd_arg;
2409 
2410           crit_enter();
2411 
2412           /**
2413            * If Auto Request Sense is on, copyout the sense struct
2414            */
2415 #define usr_pckt_DMA          (caddr_t)(intptr_t)ntohl(ccb->eata_ccb.cp_reqDMA)
2416 #define usr_pckt_len          ntohl(ccb->eata_ccb.cp_datalen)
2417           if (ccb->eata_ccb.Auto_Req_Sen == 1) {
2418                     if (copyout((caddr_t) & ccb->sense_data, usr_pckt_DMA,
2419                                   sizeof(struct scsi_sense_data))) {
2420                               ccb->result = EFAULT;
2421                               dpt_Qpush_free(dpt, ccb);
2422                               crit_exit();
2423                               wakeup(ccb);
2424                               return;
2425                     }
2426           }
2427           /* If DataIn is on, copyout the data */
2428           if ((ccb->eata_ccb.DataIn == 1)
2429               && (ccb->status_packet.hba_stat == HA_NO_ERROR)) {
2430                     if (copyout(ccb->data, usr_pckt_DMA, usr_pckt_len)) {
2431                               dpt_Qpush_free(dpt, ccb);
2432                               ccb->result = EFAULT;
2433 
2434                               crit_exit();
2435                               wakeup(ccb);
2436                               return;
2437                     }
2438           }
2439           /* Copyout the status */
2440           result = ccb->status_packet.hba_stat;
2441           cmd_arg = (caddr_t) ccb->result;
2442 
2443           if (copyout((caddr_t) & result, cmd_arg, sizeof(result))) {
2444                     dpt_Qpush_free(dpt, ccb);
2445                     ccb->result = EFAULT;
2446                     crit_exit();
2447                     wakeup(ccb);
2448                     return;
2449           }
2450           /* Put the CCB back in the freelist */
2451           ccb->state |= DPT_CCB_STATE_COMPLETED;
2452           dpt_Qpush_free(dpt, ccb);
2453 
2454           /* Free allocated memory */
2455           crit_exit();
2456           return;
2457 }
2458 
2459 #ifdef DPT_HANDLE_TIMEOUTS
2460 /**
2461  * This function walks down the SUBMITTED queue.
2462  * Every request that is too old gets aborted and marked.
2463  * Since the DPT will complete (interrupt) immediately (what does that mean?),
2464  * We just walk the list, aborting old commands and marking them as such.
2465  * The dpt_complete function will get rid of the that were interrupted in the
2466  * normal manner.
2467  *
2468  * This function needs to run at splcam(), as it interacts with the submitted
2469  * queue, as well as the completed and free queues.  Just like dpt_intr() does.
2470  * To run it at any ISPL other than that of dpt_intr(), will mean that dpt_intr
2471  * willbe able to pre-empt it, grab a transaction in progress (towards
2472  * destruction) and operate on it.  The state of this transaction will be not
2473  * very clear.
2474  * The only other option, is to lock it only as long as necessary but have
2475  * dpt_intr() spin-wait on it. In a UP environment this makes no sense and in
2476  * a SMP environment, the advantage is dubvious for a function that runs once
2477  * every ten seconds for few microseconds and, on systems with healthy
2478  * hardware, does not do anything anyway.
2479  */
2480 
2481 static void
2482 dpt_handle_timeouts(dpt_softc_t * dpt)
2483 {
2484           dpt_ccb_t      *ccb;
2485 
2486           crit_enter();
2487 
2488           if (dpt->state & DPT_HA_TIMEOUTS_ACTIVE) {
2489                     kprintf("dpt%d WARNING: Timeout Handling Collision\n",
2490                            dpt->unit);
2491                     crit_exit();
2492                     return;
2493           }
2494           dpt->state |= DPT_HA_TIMEOUTS_ACTIVE;
2495 
2496           /* Loop through the entire submitted queue, looking for lost souls */
2497           for (ccb = TAILQ_FIRST(&dpt->submitted_ccbs);
2498                ccb != NULL;
2499                ccb = TAILQ_NEXT(ccb, links)) {
2500                     struct scsi_xfer *xs;
2501                     u_int32_t       age, max_age;
2502 
2503                     xs = ccb->xs;
2504                     age = dpt_time_delta(ccb->command_started, microtime_now);
2505 
2506 #define TenSec      10000000
2507 
2508                     if (xs == NULL) {   /* Local, non-kernel call */
2509                               max_age = TenSec;
2510                     } else {
2511                               max_age = (((xs->timeout * (dpt->submitted_ccbs_count
2512                                                                 + DPT_TIMEOUT_FACTOR))
2513                                             > TenSec)
2514                                          ? (xs->timeout * (dpt->submitted_ccbs_count
2515                                                                + DPT_TIMEOUT_FACTOR))
2516                                            : TenSec);
2517                     }
2518 
2519                     /*
2520                      * If a transaction is marked lost and is TWICE as old as we
2521                      * care, then, and only then do we destroy it!
2522                      */
2523                     if (ccb->state & DPT_CCB_STATE_MARKED_LOST) {
2524                               /* Remember who is next */
2525                               if (age > (max_age * 2)) {
2526                                         dpt_Qremove_submitted(dpt, ccb);
2527                                         ccb->state &= ~DPT_CCB_STATE_MARKED_LOST;
2528                                         ccb->state |= DPT_CCB_STATE_ABORTED;
2529 #define cmd_name scsi_cmd_name(ccb->eata_ccb.cp_scsi_cmd)
2530                                         if (ccb->retries++ > DPT_RETRIES) {
2531                                                   kprintf("dpt%d ERROR: Destroying stale "
2532                                                          "%d (%s)\n"
2533                                                          "            on "
2534                                                          "c%db%dt%du%d (%d/%d)\n",
2535                                                        dpt->unit, ccb->transaction_id,
2536                                                          cmd_name,
2537                                                          dpt->unit,
2538                                                          ccb->eata_ccb.cp_channel,
2539                                                          ccb->eata_ccb.cp_id,
2540                                                          ccb->eata_ccb.cp_LUN, age,
2541                                                          ccb->retries);
2542 #define send_ccb &ccb->eata_ccb
2543 #define ESA          EATA_SPECIFIC_ABORT
2544                                                   (void) dpt_send_immediate(dpt,
2545                                                                                   send_ccb,
2546                                                                                   ESA,
2547                                                                                   0, 0);
2548                                                   dpt_Qpush_free(dpt, ccb);
2549 
2550                                                   /* The SCSI layer should re-try */
2551                                                   xs->error |= XS_TIMEOUT;
2552                                                   xs->flags |= SCSI_ITSDONE;
2553                                                   scsi_done(xs);
2554                                         } else {
2555                                                   kprintf("dpt%d ERROR: Stale %d (%s) on "
2556                                                          "c%db%dt%du%d (%d)\n"
2557                                                        "              gets another "
2558                                                          "chance(%d/%d)\n",
2559                                                        dpt->unit, ccb->transaction_id,
2560                                                          cmd_name,
2561                                                          dpt->unit,
2562                                                          ccb->eata_ccb.cp_channel,
2563                                                          ccb->eata_ccb.cp_id,
2564                                                          ccb->eata_ccb.cp_LUN,
2565                                                       age, ccb->retries, DPT_RETRIES);
2566 
2567                                                   dpt_Qpush_waiting(dpt, ccb);
2568                                                   dpt_sched_queue(dpt);
2569                                         }
2570                               }
2571                     } else {
2572                               /*
2573                                * This is a transaction that is not to be destroyed
2574                                * (yet) But it is too old for our liking. We wait as
2575                                * long as the upper layer thinks. Not really, we
2576                                * multiply that by the number of commands in the
2577                                * submitted queue + 1.
2578                                */
2579                               if (!(ccb->state & DPT_CCB_STATE_MARKED_LOST) &&
2580                                   (age != ~0) && (age > max_age)) {
2581                                         kprintf("dpt%d ERROR: Marking %d (%s) on "
2582                                                "c%db%dt%du%d \n"
2583                                                "            as late after %dusec\n",
2584                                                dpt->unit, ccb->transaction_id,
2585                                                cmd_name,
2586                                                dpt->unit, ccb->eata_ccb.cp_channel,
2587                                                ccb->eata_ccb.cp_id,
2588                                                ccb->eata_ccb.cp_LUN, age);
2589                                         ccb->state |= DPT_CCB_STATE_MARKED_LOST;
2590                               }
2591                     }
2592           }
2593 
2594           dpt->state &= ~DPT_HA_TIMEOUTS_ACTIVE;
2595           crit_exit();
2596 }
2597 
2598 #endif                                  /* DPT_HANDLE_TIMEOUTS */
2599 
2600 #endif
2601