]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - sys/dev/siis/siis.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / sys / dev / siis / siis.c
1 /*-
2  * Copyright (c) 2009 Alexander Motin <mav@FreeBSD.org>
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  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 #include <sys/param.h>
31 #include <sys/module.h>
32 #include <sys/systm.h>
33 #include <sys/kernel.h>
34 #include <sys/ata.h>
35 #include <sys/bus.h>
36 #include <sys/endian.h>
37 #include <sys/malloc.h>
38 #include <sys/lock.h>
39 #include <sys/mutex.h>
40 #include <sys/sema.h>
41 #include <sys/taskqueue.h>
42 #include <vm/uma.h>
43 #include <machine/stdarg.h>
44 #include <machine/resource.h>
45 #include <machine/bus.h>
46 #include <sys/rman.h>
47 #include <dev/pci/pcivar.h>
48 #include <dev/pci/pcireg.h>
49 #include "siis.h"
50
51 #include <cam/cam.h>
52 #include <cam/cam_ccb.h>
53 #include <cam/cam_sim.h>
54 #include <cam/cam_xpt_sim.h>
55 #include <cam/cam_debug.h>
56
57 /* local prototypes */
58 static int siis_setup_interrupt(device_t dev);
59 static void siis_intr(void *data);
60 static int siis_suspend(device_t dev);
61 static int siis_resume(device_t dev);
62 static int siis_ch_init(device_t dev);
63 static int siis_ch_deinit(device_t dev);
64 static int siis_ch_suspend(device_t dev);
65 static int siis_ch_resume(device_t dev);
66 static void siis_ch_intr_locked(void *data);
67 static void siis_ch_intr(void *data);
68 static void siis_begin_transaction(device_t dev, union ccb *ccb);
69 static void siis_dmasetprd(void *arg, bus_dma_segment_t *segs, int nsegs, int error);
70 static void siis_execute_transaction(struct siis_slot *slot);
71 static void siis_timeout(struct siis_slot *slot);
72 static void siis_end_transaction(struct siis_slot *slot, enum siis_err_type et);
73 static int siis_setup_fis(device_t dev, struct siis_cmd *ctp, union ccb *ccb, int tag);
74 static void siis_dmainit(device_t dev);
75 static void siis_dmasetupc_cb(void *xsc, bus_dma_segment_t *segs, int nsegs, int error);
76 static void siis_dmafini(device_t dev);
77 static void siis_slotsalloc(device_t dev);
78 static void siis_slotsfree(device_t dev);
79 static void siis_reset(device_t dev);
80 static void siis_portinit(device_t dev);
81 static int siis_wait_ready(device_t dev, int t);
82
83 static int siis_sata_connect(struct siis_channel *ch);
84
85 static void siis_issue_read_log(device_t dev);
86 static void siis_process_read_log(device_t dev, union ccb *ccb);
87
88 static void siisaction(struct cam_sim *sim, union ccb *ccb);
89 static void siispoll(struct cam_sim *sim);
90
91 MALLOC_DEFINE(M_SIIS, "SIIS driver", "SIIS driver data buffers");
92
93 static struct {
94         uint32_t        id;
95         const char      *name;
96         int             ports;
97         int             quirks;
98 #define SIIS_Q_SNTF     1
99 #define SIIS_Q_NOMSI    2
100 } siis_ids[] = {
101         {0x31241095,    "SiI3124",      4,      0},
102         {0x31248086,    "SiI3124",      4,      0},
103         {0x31321095,    "SiI3132",      2,      SIIS_Q_SNTF|SIIS_Q_NOMSI},
104         {0x02421095,    "SiI3132",      2,      SIIS_Q_SNTF|SIIS_Q_NOMSI},
105         {0x02441095,    "SiI3132",      2,      SIIS_Q_SNTF|SIIS_Q_NOMSI},
106         {0x31311095,    "SiI3131",      1,      SIIS_Q_SNTF|SIIS_Q_NOMSI},
107         {0x35311095,    "SiI3531",      1,      SIIS_Q_SNTF|SIIS_Q_NOMSI},
108         {0,             NULL,           0,      0}
109 };
110
111 static int
112 siis_probe(device_t dev)
113 {
114         char buf[64];
115         int i;
116         uint32_t devid = pci_get_devid(dev);
117
118         for (i = 0; siis_ids[i].id != 0; i++) {
119                 if (siis_ids[i].id == devid) {
120                         snprintf(buf, sizeof(buf), "%s SATA controller",
121                             siis_ids[i].name);
122                         device_set_desc_copy(dev, buf);
123                         return (BUS_PROBE_VENDOR);
124                 }
125         }
126         return (ENXIO);
127 }
128
129 static int
130 siis_attach(device_t dev)
131 {
132         struct siis_controller *ctlr = device_get_softc(dev);
133         uint32_t devid = pci_get_devid(dev);
134         device_t child;
135         int     error, i, unit;
136
137         ctlr->dev = dev;
138         for (i = 0; siis_ids[i].id != 0; i++) {
139                 if (siis_ids[i].id == devid)
140                         break;
141         }
142         ctlr->quirks = siis_ids[i].quirks;
143         /* Global memory */
144         ctlr->r_grid = PCIR_BAR(0);
145         if (!(ctlr->r_gmem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
146             &ctlr->r_grid, RF_ACTIVE)))
147                 return (ENXIO);
148         ctlr->gctl = ATA_INL(ctlr->r_gmem, SIIS_GCTL);
149         /* Channels memory */
150         ctlr->r_rid = PCIR_BAR(2);
151         if (!(ctlr->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
152             &ctlr->r_rid, RF_ACTIVE)))
153                 return (ENXIO);
154         /* Setup our own memory management for channels. */
155         ctlr->sc_iomem.rm_start = rman_get_start(ctlr->r_mem);
156         ctlr->sc_iomem.rm_end = rman_get_end(ctlr->r_mem);
157         ctlr->sc_iomem.rm_type = RMAN_ARRAY;
158         ctlr->sc_iomem.rm_descr = "I/O memory addresses";
159         if ((error = rman_init(&ctlr->sc_iomem)) != 0) {
160                 bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem);
161                 bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_grid, ctlr->r_gmem);
162                 return (error);
163         }
164         if ((error = rman_manage_region(&ctlr->sc_iomem,
165             rman_get_start(ctlr->r_mem), rman_get_end(ctlr->r_mem))) != 0) {
166                 bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem);
167                 bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_grid, ctlr->r_gmem);
168                 rman_fini(&ctlr->sc_iomem);
169                 return (error);
170         }
171         pci_enable_busmaster(dev);
172         /* Reset controller */
173         siis_resume(dev);
174         /* Number of HW channels */
175         ctlr->channels = siis_ids[i].ports;
176         /* Setup interrupts. */
177         if (siis_setup_interrupt(dev)) {
178                 bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem);
179                 bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_grid, ctlr->r_gmem);
180                 rman_fini(&ctlr->sc_iomem);
181                 return ENXIO;
182         }
183         /* Attach all channels on this controller */
184         for (unit = 0; unit < ctlr->channels; unit++) {
185                 child = device_add_child(dev, "siisch", -1);
186                 if (child == NULL)
187                         device_printf(dev, "failed to add channel device\n");
188                 else
189                         device_set_ivars(child, (void *)(intptr_t)unit);
190         }
191         bus_generic_attach(dev);
192         return 0;
193 }
194
195 static int
196 siis_detach(device_t dev)
197 {
198         struct siis_controller *ctlr = device_get_softc(dev);
199         device_t *children;
200         int nchildren, i;
201
202         /* Detach & delete all children */
203         if (!device_get_children(dev, &children, &nchildren)) {
204                 for (i = 0; i < nchildren; i++)
205                         device_delete_child(dev, children[i]);
206                 free(children, M_TEMP);
207         }
208         /* Free interrupts. */
209         if (ctlr->irq.r_irq) {
210                 bus_teardown_intr(dev, ctlr->irq.r_irq,
211                     ctlr->irq.handle);
212                 bus_release_resource(dev, SYS_RES_IRQ,
213                     ctlr->irq.r_irq_rid, ctlr->irq.r_irq);
214         }
215         pci_release_msi(dev);
216         /* Free memory. */
217         rman_fini(&ctlr->sc_iomem);
218         bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem);
219         bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_grid, ctlr->r_gmem);
220         return (0);
221 }
222
223 static int
224 siis_suspend(device_t dev)
225 {
226         struct siis_controller *ctlr = device_get_softc(dev);
227
228         bus_generic_suspend(dev);
229         /* Put controller into reset state. */
230         ctlr->gctl |= SIIS_GCTL_GRESET;
231         ATA_OUTL(ctlr->r_gmem, SIIS_GCTL, ctlr->gctl);
232         return 0;
233 }
234
235 static int
236 siis_resume(device_t dev)
237 {
238         struct siis_controller *ctlr = device_get_softc(dev);
239
240         /* Set PCIe max read request size to at least 1024 bytes */
241         if (pci_get_max_read_req(dev) < 1024)
242                 pci_set_max_read_req(dev, 1024);
243         /* Put controller into reset state. */
244         ctlr->gctl |= SIIS_GCTL_GRESET;
245         ATA_OUTL(ctlr->r_gmem, SIIS_GCTL, ctlr->gctl);
246         DELAY(10000);
247         /* Get controller out of reset state and enable port interrupts. */
248         ctlr->gctl &= ~(SIIS_GCTL_GRESET | SIIS_GCTL_I2C_IE);
249         ctlr->gctl |= 0x0000000f;
250         ATA_OUTL(ctlr->r_gmem, SIIS_GCTL, ctlr->gctl);
251         return (bus_generic_resume(dev));
252 }
253
254 static int
255 siis_setup_interrupt(device_t dev)
256 {
257         struct siis_controller *ctlr = device_get_softc(dev);
258         int msi = ctlr->quirks & SIIS_Q_NOMSI ? 0 : 1;
259
260         /* Process hints. */
261         resource_int_value(device_get_name(dev),
262             device_get_unit(dev), "msi", &msi);
263         if (msi < 0)
264                 msi = 0;
265         else if (msi > 0)
266                 msi = min(1, pci_msi_count(dev));
267         /* Allocate MSI if needed/present. */
268         if (msi && pci_alloc_msi(dev, &msi) != 0)
269                 msi = 0;
270         /* Allocate all IRQs. */
271         ctlr->irq.r_irq_rid = msi ? 1 : 0;
272         if (!(ctlr->irq.r_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
273             &ctlr->irq.r_irq_rid, RF_SHAREABLE | RF_ACTIVE))) {
274                 device_printf(dev, "unable to map interrupt\n");
275                 return ENXIO;
276         }
277         if ((bus_setup_intr(dev, ctlr->irq.r_irq, ATA_INTR_FLAGS, NULL,
278             siis_intr, ctlr, &ctlr->irq.handle))) {
279                 /* SOS XXX release r_irq */
280                 device_printf(dev, "unable to setup interrupt\n");
281                 return ENXIO;
282         }
283         return (0);
284 }
285
286 /*
287  * Common case interrupt handler.
288  */
289 static void
290 siis_intr(void *data)
291 {
292         struct siis_controller *ctlr = (struct siis_controller *)data;
293         u_int32_t is;
294         void *arg;
295         int unit;
296
297         is = ATA_INL(ctlr->r_gmem, SIIS_IS);
298         for (unit = 0; unit < ctlr->channels; unit++) {
299                 if ((is & SIIS_IS_PORT(unit)) != 0 &&
300                     (arg = ctlr->interrupt[unit].argument)) {
301                         ctlr->interrupt[unit].function(arg);
302                 }
303         }
304         /* Acknowledge interrupt, if MSI enabled. */
305         if (ctlr->irq.r_irq_rid) {
306                 ATA_OUTL(ctlr->r_gmem, SIIS_GCTL,
307                     ctlr->gctl | SIIS_GCTL_MSIACK);
308         }
309 }
310
311 static struct resource *
312 siis_alloc_resource(device_t dev, device_t child, int type, int *rid,
313                        u_long start, u_long end, u_long count, u_int flags)
314 {
315         struct siis_controller *ctlr = device_get_softc(dev);
316         int unit = ((struct siis_channel *)device_get_softc(child))->unit;
317         struct resource *res = NULL;
318         int offset = unit << 13;
319         long st;
320
321         switch (type) {
322         case SYS_RES_MEMORY:
323                 st = rman_get_start(ctlr->r_mem);
324                 res = rman_reserve_resource(&ctlr->sc_iomem, st + offset,
325                     st + offset + 0x2000, 0x2000, RF_ACTIVE, child);
326                 if (res) {
327                         bus_space_handle_t bsh;
328                         bus_space_tag_t bst;
329                         bsh = rman_get_bushandle(ctlr->r_mem);
330                         bst = rman_get_bustag(ctlr->r_mem);
331                         bus_space_subregion(bst, bsh, offset, 0x2000, &bsh);
332                         rman_set_bushandle(res, bsh);
333                         rman_set_bustag(res, bst);
334                 }
335                 break;
336         case SYS_RES_IRQ:
337                 if (*rid == ATA_IRQ_RID)
338                         res = ctlr->irq.r_irq;
339                 break;
340         }
341         return (res);
342 }
343
344 static int
345 siis_release_resource(device_t dev, device_t child, int type, int rid,
346                          struct resource *r)
347 {
348
349         switch (type) {
350         case SYS_RES_MEMORY:
351                 rman_release_resource(r);
352                 return (0);
353         case SYS_RES_IRQ:
354                 if (rid != ATA_IRQ_RID)
355                         return ENOENT;
356                 return (0);
357         }
358         return (EINVAL);
359 }
360
361 static int
362 siis_setup_intr(device_t dev, device_t child, struct resource *irq, 
363                    int flags, driver_filter_t *filter, driver_intr_t *function, 
364                    void *argument, void **cookiep)
365 {
366         struct siis_controller *ctlr = device_get_softc(dev);
367         int unit = (intptr_t)device_get_ivars(child);
368
369         if (filter != NULL) {
370                 printf("siis.c: we cannot use a filter here\n");
371                 return (EINVAL);
372         }
373         ctlr->interrupt[unit].function = function;
374         ctlr->interrupt[unit].argument = argument;
375         return (0);
376 }
377
378 static int
379 siis_teardown_intr(device_t dev, device_t child, struct resource *irq,
380                       void *cookie)
381 {
382         struct siis_controller *ctlr = device_get_softc(dev);
383         int unit = (intptr_t)device_get_ivars(child);
384
385         ctlr->interrupt[unit].function = NULL;
386         ctlr->interrupt[unit].argument = NULL;
387         return (0);
388 }
389
390 static int
391 siis_print_child(device_t dev, device_t child)
392 {
393         int retval;
394
395         retval = bus_print_child_header(dev, child);
396         retval += printf(" at channel %d",
397             (int)(intptr_t)device_get_ivars(child));
398         retval += bus_print_child_footer(dev, child);
399
400         return (retval);
401 }
402
403 static int
404 siis_child_location_str(device_t dev, device_t child, char *buf,
405     size_t buflen)
406 {
407
408         snprintf(buf, buflen, "channel=%d",
409             (int)(intptr_t)device_get_ivars(child));
410         return (0);
411 }
412
413 devclass_t siis_devclass;
414 static device_method_t siis_methods[] = {
415         DEVMETHOD(device_probe,     siis_probe),
416         DEVMETHOD(device_attach,    siis_attach),
417         DEVMETHOD(device_detach,    siis_detach),
418         DEVMETHOD(device_suspend,   siis_suspend),
419         DEVMETHOD(device_resume,    siis_resume),
420         DEVMETHOD(bus_print_child,  siis_print_child),
421         DEVMETHOD(bus_alloc_resource,       siis_alloc_resource),
422         DEVMETHOD(bus_release_resource,     siis_release_resource),
423         DEVMETHOD(bus_setup_intr,   siis_setup_intr),
424         DEVMETHOD(bus_teardown_intr,siis_teardown_intr),
425         DEVMETHOD(bus_child_location_str, siis_child_location_str),
426         { 0, 0 }
427 };
428 static driver_t siis_driver = {
429         "siis",
430         siis_methods,
431         sizeof(struct siis_controller)
432 };
433 DRIVER_MODULE(siis, pci, siis_driver, siis_devclass, 0, 0);
434 MODULE_VERSION(siis, 1);
435 MODULE_DEPEND(siis, cam, 1, 1, 1);
436
437 static int
438 siis_ch_probe(device_t dev)
439 {
440
441         device_set_desc_copy(dev, "SIIS channel");
442         return (0);
443 }
444
445 static int
446 siis_ch_attach(device_t dev)
447 {
448         struct siis_controller *ctlr = device_get_softc(device_get_parent(dev));
449         struct siis_channel *ch = device_get_softc(dev);
450         struct cam_devq *devq;
451         int rid, error, i, sata_rev = 0;
452
453         ch->dev = dev;
454         ch->unit = (intptr_t)device_get_ivars(dev);
455         ch->quirks = ctlr->quirks;
456         resource_int_value(device_get_name(dev),
457             device_get_unit(dev), "pm_level", &ch->pm_level);
458         resource_int_value(device_get_name(dev),
459             device_get_unit(dev), "sata_rev", &sata_rev);
460         for (i = 0; i < 16; i++) {
461                 ch->user[i].revision = sata_rev;
462                 ch->user[i].mode = 0;
463                 ch->user[i].bytecount = 8192;
464                 ch->user[i].tags = SIIS_MAX_SLOTS;
465                 ch->curr[i] = ch->user[i];
466                 if (ch->pm_level)
467                         ch->user[i].caps = CTS_SATA_CAPS_H_PMREQ;
468         }
469         mtx_init(&ch->mtx, "SIIS channel lock", NULL, MTX_DEF);
470         rid = ch->unit;
471         if (!(ch->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
472             &rid, RF_ACTIVE)))
473                 return (ENXIO);
474         siis_dmainit(dev);
475         siis_slotsalloc(dev);
476         siis_ch_init(dev);
477         mtx_lock(&ch->mtx);
478         rid = ATA_IRQ_RID;
479         if (!(ch->r_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
480             &rid, RF_SHAREABLE | RF_ACTIVE))) {
481                 bus_release_resource(dev, SYS_RES_MEMORY, ch->unit, ch->r_mem);
482                 device_printf(dev, "Unable to map interrupt\n");
483                 return (ENXIO);
484         }
485         if ((bus_setup_intr(dev, ch->r_irq, ATA_INTR_FLAGS, NULL,
486             siis_ch_intr_locked, dev, &ch->ih))) {
487                 device_printf(dev, "Unable to setup interrupt\n");
488                 error = ENXIO;
489                 goto err1;
490         }
491         /* Create the device queue for our SIM. */
492         devq = cam_simq_alloc(SIIS_MAX_SLOTS);
493         if (devq == NULL) {
494                 device_printf(dev, "Unable to allocate simq\n");
495                 error = ENOMEM;
496                 goto err1;
497         }
498         /* Construct SIM entry */
499         ch->sim = cam_sim_alloc(siisaction, siispoll, "siisch", ch,
500             device_get_unit(dev), &ch->mtx, 2, SIIS_MAX_SLOTS, devq);
501         if (ch->sim == NULL) {
502                 device_printf(dev, "unable to allocate sim\n");
503                 error = ENOMEM;
504                 goto err2;
505         }
506         if (xpt_bus_register(ch->sim, dev, 0) != CAM_SUCCESS) {
507                 device_printf(dev, "unable to register xpt bus\n");
508                 error = ENXIO;
509                 goto err2;
510         }
511         if (xpt_create_path(&ch->path, /*periph*/NULL, cam_sim_path(ch->sim),
512             CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
513                 device_printf(dev, "unable to create path\n");
514                 error = ENXIO;
515                 goto err3;
516         }
517         mtx_unlock(&ch->mtx);
518         return (0);
519
520 err3:
521         xpt_bus_deregister(cam_sim_path(ch->sim));
522 err2:
523         cam_sim_free(ch->sim, /*free_devq*/TRUE);
524 err1:
525         bus_release_resource(dev, SYS_RES_IRQ, ATA_IRQ_RID, ch->r_irq);
526         bus_release_resource(dev, SYS_RES_MEMORY, ch->unit, ch->r_mem);
527         mtx_unlock(&ch->mtx);
528         return (error);
529 }
530
531 static int
532 siis_ch_detach(device_t dev)
533 {
534         struct siis_channel *ch = device_get_softc(dev);
535
536         mtx_lock(&ch->mtx);
537         xpt_async(AC_LOST_DEVICE, ch->path, NULL);
538         xpt_free_path(ch->path);
539         xpt_bus_deregister(cam_sim_path(ch->sim));
540         cam_sim_free(ch->sim, /*free_devq*/TRUE);
541         mtx_unlock(&ch->mtx);
542
543         bus_teardown_intr(dev, ch->r_irq, ch->ih);
544         bus_release_resource(dev, SYS_RES_IRQ, ATA_IRQ_RID, ch->r_irq);
545
546         siis_ch_deinit(dev);
547         siis_slotsfree(dev);
548         siis_dmafini(dev);
549
550         bus_release_resource(dev, SYS_RES_MEMORY, ch->unit, ch->r_mem);
551         mtx_destroy(&ch->mtx);
552         return (0);
553 }
554
555 static int
556 siis_ch_init(device_t dev)
557 {
558         struct siis_channel *ch = device_get_softc(dev);
559
560         /* Get port out of reset state. */
561         ATA_OUTL(ch->r_mem, SIIS_P_CTLCLR, SIIS_P_CTL_PORT_RESET);
562         ATA_OUTL(ch->r_mem, SIIS_P_CTLCLR, SIIS_P_CTL_32BIT);
563         if (ch->pm_present)
564                 ATA_OUTL(ch->r_mem, SIIS_P_CTLSET, SIIS_P_CTL_PME);
565         else
566                 ATA_OUTL(ch->r_mem, SIIS_P_CTLCLR, SIIS_P_CTL_PME);
567         /* Enable port interrupts */
568         ATA_OUTL(ch->r_mem, SIIS_P_IESET, SIIS_P_IX_ENABLED);
569         return (0);
570 }
571
572 static int
573 siis_ch_deinit(device_t dev)
574 {
575         struct siis_channel *ch = device_get_softc(dev);
576
577         /* Put port into reset state. */
578         ATA_OUTL(ch->r_mem, SIIS_P_CTLSET, SIIS_P_CTL_PORT_RESET);
579         return (0);
580 }
581
582 static int
583 siis_ch_suspend(device_t dev)
584 {
585         struct siis_channel *ch = device_get_softc(dev);
586
587         mtx_lock(&ch->mtx);
588         xpt_freeze_simq(ch->sim, 1);
589         while (ch->oslots)
590                 msleep(ch, &ch->mtx, PRIBIO, "siissusp", hz/100);
591         siis_ch_deinit(dev);
592         mtx_unlock(&ch->mtx);
593         return (0);
594 }
595
596 static int
597 siis_ch_resume(device_t dev)
598 {
599         struct siis_channel *ch = device_get_softc(dev);
600
601         mtx_lock(&ch->mtx);
602         siis_ch_init(dev);
603         siis_reset(dev);
604         xpt_release_simq(ch->sim, TRUE);
605         mtx_unlock(&ch->mtx);
606         return (0);
607 }
608
609 devclass_t siisch_devclass;
610 static device_method_t siisch_methods[] = {
611         DEVMETHOD(device_probe,     siis_ch_probe),
612         DEVMETHOD(device_attach,    siis_ch_attach),
613         DEVMETHOD(device_detach,    siis_ch_detach),
614         DEVMETHOD(device_suspend,   siis_ch_suspend),
615         DEVMETHOD(device_resume,    siis_ch_resume),
616         { 0, 0 }
617 };
618 static driver_t siisch_driver = {
619         "siisch",
620         siisch_methods,
621         sizeof(struct siis_channel)
622 };
623 DRIVER_MODULE(siisch, siis, siisch_driver, siis_devclass, 0, 0);
624
625 struct siis_dc_cb_args {
626         bus_addr_t maddr;
627         int error;
628 };
629
630 static void
631 siis_dmainit(device_t dev)
632 {
633         struct siis_channel *ch = device_get_softc(dev);
634         struct siis_dc_cb_args dcba;
635
636         /* Command area. */
637         if (bus_dma_tag_create(bus_get_dma_tag(dev), 1024, 0,
638             BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
639             NULL, NULL, SIIS_WORK_SIZE, 1, SIIS_WORK_SIZE,
640             0, NULL, NULL, &ch->dma.work_tag))
641                 goto error;
642         if (bus_dmamem_alloc(ch->dma.work_tag, (void **)&ch->dma.work, 0,
643             &ch->dma.work_map))
644                 goto error;
645         if (bus_dmamap_load(ch->dma.work_tag, ch->dma.work_map, ch->dma.work,
646             SIIS_WORK_SIZE, siis_dmasetupc_cb, &dcba, 0) || dcba.error) {
647                 bus_dmamem_free(ch->dma.work_tag, ch->dma.work, ch->dma.work_map);
648                 goto error;
649         }
650         ch->dma.work_bus = dcba.maddr;
651         /* Data area. */
652         if (bus_dma_tag_create(bus_get_dma_tag(dev), 1, 0,
653             BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
654             NULL, NULL,
655             SIIS_SG_ENTRIES * PAGE_SIZE * SIIS_MAX_SLOTS,
656             SIIS_SG_ENTRIES, 0xFFFFFFFF,
657             0, busdma_lock_mutex, &ch->mtx, &ch->dma.data_tag)) {
658                 goto error;
659         }
660         return;
661
662 error:
663         device_printf(dev, "WARNING - DMA initialization failed\n");
664         siis_dmafini(dev);
665 }
666
667 static void
668 siis_dmasetupc_cb(void *xsc, bus_dma_segment_t *segs, int nsegs, int error)
669 {
670         struct siis_dc_cb_args *dcba = (struct siis_dc_cb_args *)xsc;
671
672         if (!(dcba->error = error))
673                 dcba->maddr = segs[0].ds_addr;
674 }
675
676 static void
677 siis_dmafini(device_t dev)
678 {
679         struct siis_channel *ch = device_get_softc(dev);
680
681         if (ch->dma.data_tag) {
682                 bus_dma_tag_destroy(ch->dma.data_tag);
683                 ch->dma.data_tag = NULL;
684         }
685         if (ch->dma.work_bus) {
686                 bus_dmamap_unload(ch->dma.work_tag, ch->dma.work_map);
687                 bus_dmamem_free(ch->dma.work_tag, ch->dma.work, ch->dma.work_map);
688                 ch->dma.work_bus = 0;
689                 ch->dma.work_map = NULL;
690                 ch->dma.work = NULL;
691         }
692         if (ch->dma.work_tag) {
693                 bus_dma_tag_destroy(ch->dma.work_tag);
694                 ch->dma.work_tag = NULL;
695         }
696 }
697
698 static void
699 siis_slotsalloc(device_t dev)
700 {
701         struct siis_channel *ch = device_get_softc(dev);
702         int i;
703
704         /* Alloc and setup command/dma slots */
705         bzero(ch->slot, sizeof(ch->slot));
706         for (i = 0; i < SIIS_MAX_SLOTS; i++) {
707                 struct siis_slot *slot = &ch->slot[i];
708
709                 slot->dev = dev;
710                 slot->slot = i;
711                 slot->state = SIIS_SLOT_EMPTY;
712                 slot->ccb = NULL;
713                 callout_init_mtx(&slot->timeout, &ch->mtx, 0);
714
715                 if (bus_dmamap_create(ch->dma.data_tag, 0, &slot->dma.data_map))
716                         device_printf(ch->dev, "FAILURE - create data_map\n");
717         }
718 }
719
720 static void
721 siis_slotsfree(device_t dev)
722 {
723         struct siis_channel *ch = device_get_softc(dev);
724         int i;
725
726         /* Free all dma slots */
727         for (i = 0; i < SIIS_MAX_SLOTS; i++) {
728                 struct siis_slot *slot = &ch->slot[i];
729
730                 callout_drain(&slot->timeout);
731                 if (slot->dma.data_map) {
732                         bus_dmamap_destroy(ch->dma.data_tag, slot->dma.data_map);
733                         slot->dma.data_map = NULL;
734                 }
735         }
736 }
737
738 static void
739 siis_notify_events(device_t dev)
740 {
741         struct siis_channel *ch = device_get_softc(dev);
742         struct cam_path *dpath;
743         u_int32_t status;
744         int i;
745
746         if (ch->quirks & SIIS_Q_SNTF) {
747                 status = ATA_INL(ch->r_mem, SIIS_P_SNTF);
748                 ATA_OUTL(ch->r_mem, SIIS_P_SNTF, status);
749         } else {
750                 /*
751                  * Without SNTF we have no idea which device sent notification.
752                  * If PMP is connected, assume it, else - device.
753                  */
754                 status = (ch->pm_present) ? 0x8000 : 0x0001;
755         }
756         if (bootverbose)
757                 device_printf(dev, "SNTF 0x%04x\n", status);
758         for (i = 0; i < 16; i++) {
759                 if ((status & (1 << i)) == 0)
760                         continue;
761                 if (xpt_create_path(&dpath, NULL,
762                     xpt_path_path_id(ch->path), i, 0) == CAM_REQ_CMP) {
763                         xpt_async(AC_SCSI_AEN, dpath, NULL);
764                         xpt_free_path(dpath);
765                 }
766         }
767
768 }
769
770 static void
771 siis_phy_check_events(device_t dev)
772 {
773         struct siis_channel *ch = device_get_softc(dev);
774
775         /* If we have a connection event, deal with it */
776         if (ch->pm_level == 0) {
777                 u_int32_t status = ATA_INL(ch->r_mem, SIIS_P_SSTS);
778                 union ccb *ccb;
779
780                 if (bootverbose) {
781                         if (((status & ATA_SS_DET_MASK) == ATA_SS_DET_PHY_ONLINE) &&
782                             ((status & ATA_SS_SPD_MASK) != ATA_SS_SPD_NO_SPEED) &&
783                             ((status & ATA_SS_IPM_MASK) == ATA_SS_IPM_ACTIVE)) {
784                                 device_printf(dev, "CONNECT requested\n");
785                         } else
786                                 device_printf(dev, "DISCONNECT requested\n");
787                 }
788                 siis_reset(dev);
789                 if ((ccb = xpt_alloc_ccb_nowait()) == NULL)
790                         return;
791                 if (xpt_create_path(&ccb->ccb_h.path, NULL,
792                     cam_sim_path(ch->sim),
793                     CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
794                         xpt_free_ccb(ccb);
795                         return;
796                 }
797                 xpt_rescan(ccb);
798         }
799 }
800
801 static void
802 siis_ch_intr_locked(void *data)
803 {
804         device_t dev = (device_t)data;
805         struct siis_channel *ch = device_get_softc(dev);
806
807         mtx_lock(&ch->mtx);
808         siis_ch_intr(data);
809         mtx_unlock(&ch->mtx);
810 }
811
812 static void
813 siis_ch_intr(void *data)
814 {
815         device_t dev = (device_t)data;
816         struct siis_channel *ch = device_get_softc(dev);
817         uint32_t istatus, sstatus, ctx, estatus, ok, err = 0;
818         enum siis_err_type et;
819         int i, ccs, port, tslots;
820
821         mtx_assert(&ch->mtx, MA_OWNED);
822         /* Read command statuses. */
823         sstatus = ATA_INL(ch->r_mem, SIIS_P_SS);
824         ok = ch->rslots & ~sstatus;
825         /* Complete all successfull commands. */
826         for (i = 0; i < SIIS_MAX_SLOTS; i++) {
827                 if ((ok >> i) & 1)
828                         siis_end_transaction(&ch->slot[i], SIIS_ERR_NONE);
829         }
830         /* Do we have any other events? */
831         if ((sstatus & SIIS_P_SS_ATTN) == 0)
832                 return;
833         /* Read and clear interrupt statuses. */
834         istatus = ATA_INL(ch->r_mem, SIIS_P_IS) &
835             (0xFFFF & ~SIIS_P_IX_COMMCOMP);
836         ATA_OUTL(ch->r_mem, SIIS_P_IS, istatus);
837         /* Process PHY events */
838         if (istatus & SIIS_P_IX_PHYRDYCHG)
839                 siis_phy_check_events(dev);
840         /* Process NOTIFY events */
841         if (istatus & SIIS_P_IX_SDBN)
842                 siis_notify_events(dev);
843         /* Process command errors */
844         if (istatus & SIIS_P_IX_COMMERR) {
845                 estatus = ATA_INL(ch->r_mem, SIIS_P_CMDERR);
846                 ctx = ATA_INL(ch->r_mem, SIIS_P_CTX);
847                 ccs = (ctx & SIIS_P_CTX_SLOT) >> SIIS_P_CTX_SLOT_SHIFT;
848                 port = (ctx & SIIS_P_CTX_PMP) >> SIIS_P_CTX_PMP_SHIFT;
849                 err = ch->rslots & sstatus;
850 //device_printf(dev, "%s ERROR ss %08x is %08x rs %08x es %d act %d port %d serr %08x\n",
851 //    __func__, sstatus, istatus, ch->rslots, estatus, ccs, port,
852 //    ATA_INL(ch->r_mem, SIIS_P_SERR));
853
854                 if (!ch->readlog && !ch->recovery) {
855                         xpt_freeze_simq(ch->sim, ch->numrslots);
856                         ch->recovery = 1;
857                 }
858                 if (ch->frozen) {
859                         union ccb *fccb = ch->frozen;
860                         ch->frozen = NULL;
861                         fccb->ccb_h.status &= ~CAM_STATUS_MASK;
862                         fccb->ccb_h.status |= CAM_REQUEUE_REQ | CAM_RELEASE_SIMQ;
863                         if (!(fccb->ccb_h.status & CAM_DEV_QFRZN)) {
864                                 xpt_freeze_devq(fccb->ccb_h.path, 1);
865                                 fccb->ccb_h.status |= CAM_DEV_QFRZN;
866                         }
867                         xpt_done(fccb);
868                 }
869                 if (estatus == SIIS_P_CMDERR_DEV ||
870                     estatus == SIIS_P_CMDERR_SDB ||
871                     estatus == SIIS_P_CMDERR_DATAFIS) {
872                         tslots = ch->numtslots[port];
873                         for (i = 0; i < SIIS_MAX_SLOTS; i++) {
874                                 /* XXX: requests in loading state. */
875                                 if (((ch->rslots >> i) & 1) == 0)
876                                         continue;
877                                 if (ch->slot[i].ccb->ccb_h.target_id != port)
878                                         continue;
879                                 if (tslots == 0) {
880                                         /* Untagged operation. */
881                                         if (i == ccs)
882                                                 et = SIIS_ERR_TFE;
883                                         else
884                                                 et = SIIS_ERR_INNOCENT;
885                                 } else {
886                                         /* Tagged operation. */
887                                         et = SIIS_ERR_NCQ;
888                                 }
889                                 siis_end_transaction(&ch->slot[i], et);
890                         }
891                         /*
892                          * We can't reinit port if there are some other
893                          * commands active, use resume to complete them.
894                          */
895                         if (ch->rslots != 0)
896                                 ATA_OUTL(ch->r_mem, SIIS_P_CTLSET, SIIS_P_CTL_RESUME);
897                 } else {
898                         if (estatus == SIIS_P_CMDERR_SENDFIS ||
899                             estatus == SIIS_P_CMDERR_INCSTATE ||
900                             estatus == SIIS_P_CMDERR_PPE ||
901                             estatus == SIIS_P_CMDERR_SERVICE) {
902                                 et = SIIS_ERR_SATA;
903                         } else
904                                 et = SIIS_ERR_INVALID;
905                         for (i = 0; i < SIIS_MAX_SLOTS; i++) {
906                                 /* XXX: requests in loading state. */
907                                 if (((ch->rslots >> i) & 1) == 0)
908                                         continue;
909                                 siis_end_transaction(&ch->slot[i], et);
910                         }
911                 }
912         }
913 }
914
915 /* Must be called with channel locked. */
916 static int
917 siis_check_collision(device_t dev, union ccb *ccb)
918 {
919         struct siis_channel *ch = device_get_softc(dev);
920
921         mtx_assert(&ch->mtx, MA_OWNED);
922         if ((ccb->ccb_h.func_code == XPT_ATA_IO) &&
923             (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA)) {
924                 /* Tagged command while we have no supported tag free. */
925                 if (((~ch->oslots) & (0x7fffffff >> (31 -
926                     ch->curr[ccb->ccb_h.target_id].tags))) == 0)
927                         return (1);
928         }
929         if ((ccb->ccb_h.func_code == XPT_ATA_IO) &&
930             (ccb->ataio.cmd.flags & (CAM_ATAIO_CONTROL | CAM_ATAIO_NEEDRESULT))) {
931                 /* Atomic command while anything active. */
932                 if (ch->numrslots != 0)
933                         return (1);
934         }
935        /* We have some atomic command running. */
936        if (ch->aslots != 0)
937                return (1);
938         return (0);
939 }
940
941 /* Must be called with channel locked. */
942 static void
943 siis_begin_transaction(device_t dev, union ccb *ccb)
944 {
945         struct siis_channel *ch = device_get_softc(dev);
946         struct siis_slot *slot;
947         int tag, tags;
948
949         mtx_assert(&ch->mtx, MA_OWNED);
950         /* Choose empty slot. */
951         tags = SIIS_MAX_SLOTS;
952         if ((ccb->ccb_h.func_code == XPT_ATA_IO) &&
953             (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA))
954                 tags = ch->curr[ccb->ccb_h.target_id].tags;
955         tag = fls((~ch->oslots) & (0x7fffffff >> (31 - tags))) - 1;
956         /* Occupy chosen slot. */
957         slot = &ch->slot[tag];
958         slot->ccb = ccb;
959         /* Update channel stats. */
960         ch->oslots |= (1 << slot->slot);
961         ch->numrslots++;
962         if ((ccb->ccb_h.func_code == XPT_ATA_IO) &&
963             (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA)) {
964                 ch->numtslots[ccb->ccb_h.target_id]++;
965         }
966         if ((ccb->ccb_h.func_code == XPT_ATA_IO) &&
967             (ccb->ataio.cmd.flags & (CAM_ATAIO_CONTROL | CAM_ATAIO_NEEDRESULT)))
968                 ch->aslots |= (1 << slot->slot);
969         slot->dma.nsegs = 0;
970         /* If request moves data, setup and load SG list */
971         if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
972                 void *buf;
973                 bus_size_t size;
974
975                 slot->state = SIIS_SLOT_LOADING;
976                 if (ccb->ccb_h.func_code == XPT_ATA_IO) {
977                         buf = ccb->ataio.data_ptr;
978                         size = ccb->ataio.dxfer_len;
979                 } else {
980                         buf = ccb->csio.data_ptr;
981                         size = ccb->csio.dxfer_len;
982                 }
983                 bus_dmamap_load(ch->dma.data_tag, slot->dma.data_map,
984                     buf, size, siis_dmasetprd, slot, 0);
985         } else
986                 siis_execute_transaction(slot);
987 }
988
989 /* Locked by busdma engine. */
990 static void
991 siis_dmasetprd(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
992 {    
993         struct siis_slot *slot = arg;
994         struct siis_channel *ch = device_get_softc(slot->dev);
995         struct siis_cmd *ctp;
996         struct siis_dma_prd *prd;
997         int i;
998
999         mtx_assert(&ch->mtx, MA_OWNED);
1000         if (error) {
1001                 device_printf(slot->dev, "DMA load error\n");
1002                 if (!ch->readlog)
1003                         xpt_freeze_simq(ch->sim, 1);
1004                 siis_end_transaction(slot, SIIS_ERR_INVALID);
1005                 return;
1006         }
1007         KASSERT(nsegs <= SIIS_SG_ENTRIES, ("too many DMA segment entries\n"));
1008         /* Get a piece of the workspace for this request */
1009         ctp = (struct siis_cmd *)
1010                 (ch->dma.work + SIIS_CT_OFFSET + (SIIS_CT_SIZE * slot->slot));
1011         /* Fill S/G table */
1012         if (slot->ccb->ccb_h.func_code == XPT_ATA_IO) 
1013                 prd = &ctp->u.ata.prd[0];
1014         else
1015                 prd = &ctp->u.atapi.prd[0];
1016         for (i = 0; i < nsegs; i++) {
1017                 prd[i].dba = htole64(segs[i].ds_addr);
1018                 prd[i].dbc = htole32(segs[i].ds_len);
1019                 prd[i].control = 0;
1020         }
1021         prd[nsegs - 1].control = htole32(SIIS_PRD_TRM);
1022         slot->dma.nsegs = nsegs;
1023         bus_dmamap_sync(ch->dma.data_tag, slot->dma.data_map,
1024             ((slot->ccb->ccb_h.flags & CAM_DIR_IN) ?
1025             BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE));
1026         siis_execute_transaction(slot);
1027 }
1028
1029 /* Must be called with channel locked. */
1030 static void
1031 siis_execute_transaction(struct siis_slot *slot)
1032 {
1033         device_t dev = slot->dev;
1034         struct siis_channel *ch = device_get_softc(dev);
1035         struct siis_cmd *ctp;
1036         union ccb *ccb = slot->ccb;
1037         u_int64_t prb_bus;
1038
1039         mtx_assert(&ch->mtx, MA_OWNED);
1040         /* Get a piece of the workspace for this request */
1041         ctp = (struct siis_cmd *)
1042                 (ch->dma.work + SIIS_CT_OFFSET + (SIIS_CT_SIZE * slot->slot));
1043         ctp->control = 0;
1044         ctp->protocol_override = 0;
1045         ctp->transfer_count = 0;
1046         /* Special handling for Soft Reset command. */
1047         if (ccb->ccb_h.func_code == XPT_ATA_IO) {
1048                 if (ccb->ataio.cmd.flags & CAM_ATAIO_CONTROL) {
1049                         ctp->control |= htole16(SIIS_PRB_SOFT_RESET);
1050                 } else {
1051                         ctp->control |= htole16(SIIS_PRB_PROTOCOL_OVERRIDE);
1052                         if (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA) {
1053                                 ctp->protocol_override |=
1054                                     htole16(SIIS_PRB_PROTO_NCQ);
1055                         }
1056                         if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
1057                                 ctp->protocol_override |=
1058                                     htole16(SIIS_PRB_PROTO_READ);
1059                         } else
1060                         if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) {
1061                                 ctp->protocol_override |=
1062                                     htole16(SIIS_PRB_PROTO_WRITE);
1063                         }
1064                 }
1065         } else if (ccb->ccb_h.func_code == XPT_SCSI_IO) {
1066                 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
1067                         ctp->control |= htole16(SIIS_PRB_PACKET_READ);
1068                 else
1069                 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
1070                         ctp->control |= htole16(SIIS_PRB_PACKET_WRITE);
1071         }
1072         /* Special handling for Soft Reset command. */
1073         if ((ccb->ccb_h.func_code == XPT_ATA_IO) &&
1074             (ccb->ataio.cmd.flags & CAM_ATAIO_CONTROL) &&
1075             (ccb->ataio.cmd.control & ATA_A_RESET)) {
1076                 /* Kick controller into sane state */
1077                 siis_portinit(dev);
1078         }
1079         /* Setup the FIS for this request */
1080         if (!siis_setup_fis(dev, ctp, ccb, slot->slot)) {
1081                 device_printf(ch->dev, "Setting up SATA FIS failed\n");
1082                 if (!ch->readlog)
1083                         xpt_freeze_simq(ch->sim, 1);
1084                 siis_end_transaction(slot, SIIS_ERR_INVALID);
1085                 return;
1086         }
1087         bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map,
1088             BUS_DMASYNC_PREWRITE);
1089         /* Issue command to the controller. */
1090         slot->state = SIIS_SLOT_RUNNING;
1091         ch->rslots |= (1 << slot->slot);
1092         prb_bus = ch->dma.work_bus +
1093               SIIS_CT_OFFSET + (SIIS_CT_SIZE * slot->slot);
1094         ATA_OUTL(ch->r_mem, SIIS_P_CACTL(slot->slot), prb_bus);
1095         ATA_OUTL(ch->r_mem, SIIS_P_CACTH(slot->slot), prb_bus >> 32);
1096         /* Start command execution timeout */
1097         callout_reset(&slot->timeout, (int)ccb->ccb_h.timeout * hz / 1000,
1098             (timeout_t*)siis_timeout, slot);
1099         return;
1100 }
1101
1102 /* Must be called with channel locked. */
1103 static void
1104 siis_process_timeout(device_t dev)
1105 {
1106         struct siis_channel *ch = device_get_softc(dev);
1107         int i;
1108
1109         mtx_assert(&ch->mtx, MA_OWNED);
1110         if (!ch->readlog && !ch->recovery) {
1111                 xpt_freeze_simq(ch->sim, ch->numrslots);
1112                 ch->recovery = 1;
1113         }
1114         /* Handle the rest of commands. */
1115         for (i = 0; i < SIIS_MAX_SLOTS; i++) {
1116                 /* Do we have a running request on slot? */
1117                 if (ch->slot[i].state < SIIS_SLOT_RUNNING)
1118                         continue;
1119                 siis_end_transaction(&ch->slot[i], SIIS_ERR_TIMEOUT);
1120         }
1121 }
1122
1123 /* Must be called with channel locked. */
1124 static void
1125 siis_rearm_timeout(device_t dev)
1126 {
1127         struct siis_channel *ch = device_get_softc(dev);
1128         int i;
1129
1130         mtx_assert(&ch->mtx, MA_OWNED);
1131         for (i = 0; i < SIIS_MAX_SLOTS; i++) {
1132                 struct siis_slot *slot = &ch->slot[i];
1133
1134                 /* Do we have a running request on slot? */
1135                 if (slot->state < SIIS_SLOT_RUNNING)
1136                         continue;
1137                 if ((ch->toslots & (1 << i)) == 0)
1138                         continue;
1139                 callout_reset(&slot->timeout,
1140                     (int)slot->ccb->ccb_h.timeout * hz / 1000,
1141                     (timeout_t*)siis_timeout, slot);
1142         }
1143 }
1144
1145 /* Locked by callout mechanism. */
1146 static void
1147 siis_timeout(struct siis_slot *slot)
1148 {
1149         device_t dev = slot->dev;
1150         struct siis_channel *ch = device_get_softc(dev);
1151
1152         mtx_assert(&ch->mtx, MA_OWNED);
1153         /* Check for stale timeout. */
1154         if (slot->state < SIIS_SLOT_RUNNING)
1155                 return;
1156         device_printf(dev, "Timeout on slot %d\n", slot->slot);
1157         device_printf(dev, "%s is %08x ss %08x rs %08x es %08x sts %08x serr %08x\n",
1158             __func__, ATA_INL(ch->r_mem, SIIS_P_IS),
1159             ATA_INL(ch->r_mem, SIIS_P_SS), ch->rslots,
1160             ATA_INL(ch->r_mem, SIIS_P_CMDERR), ATA_INL(ch->r_mem, SIIS_P_STS),
1161             ATA_INL(ch->r_mem, SIIS_P_SERR));
1162
1163         if (ch->toslots == 0)
1164                 xpt_freeze_simq(ch->sim, 1);
1165         ch->toslots |= (1 << slot->slot);
1166         if ((ch->rslots & ~ch->toslots) == 0)
1167                 siis_process_timeout(dev);
1168         else
1169                 device_printf(dev, " ... waiting for slots %08x\n",
1170                     ch->rslots & ~ch->toslots);
1171 }
1172
1173 /* Must be called with channel locked. */
1174 static void
1175 siis_end_transaction(struct siis_slot *slot, enum siis_err_type et)
1176 {
1177         device_t dev = slot->dev;
1178         struct siis_channel *ch = device_get_softc(dev);
1179         union ccb *ccb = slot->ccb;
1180
1181         mtx_assert(&ch->mtx, MA_OWNED);
1182         bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map,
1183             BUS_DMASYNC_POSTWRITE);
1184         /* Read result registers to the result struct
1185          * May be incorrect if several commands finished same time,
1186          * so read only when sure or have to.
1187          */
1188         if (ccb->ccb_h.func_code == XPT_ATA_IO) {
1189                 struct ata_res *res = &ccb->ataio.res;
1190                 if ((et == SIIS_ERR_TFE) ||
1191                     (ccb->ataio.cmd.flags & CAM_ATAIO_NEEDRESULT)) {
1192                         int offs = SIIS_P_LRAM_SLOT(slot->slot) + 8;
1193
1194                         res->status = ATA_INB(ch->r_mem, offs + 2);
1195                         res->error = ATA_INB(ch->r_mem, offs + 3);
1196                         res->lba_low = ATA_INB(ch->r_mem, offs + 4);
1197                         res->lba_mid = ATA_INB(ch->r_mem, offs + 5);
1198                         res->lba_high = ATA_INB(ch->r_mem, offs + 6);
1199                         res->device = ATA_INB(ch->r_mem, offs + 7);
1200                         res->lba_low_exp = ATA_INB(ch->r_mem, offs + 8);
1201                         res->lba_mid_exp = ATA_INB(ch->r_mem, offs + 9);
1202                         res->lba_high_exp = ATA_INB(ch->r_mem, offs + 10);
1203                         res->sector_count = ATA_INB(ch->r_mem, offs + 12);
1204                         res->sector_count_exp = ATA_INB(ch->r_mem, offs + 13);
1205                 } else
1206                         bzero(res, sizeof(*res));
1207         }
1208         if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
1209                 bus_dmamap_sync(ch->dma.data_tag, slot->dma.data_map,
1210                     (ccb->ccb_h.flags & CAM_DIR_IN) ?
1211                     BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
1212                 bus_dmamap_unload(ch->dma.data_tag, slot->dma.data_map);
1213         }
1214         /* Set proper result status. */
1215         if (et != SIIS_ERR_NONE || ch->recovery) {
1216                 ch->eslots |= (1 << slot->slot);
1217                 ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
1218         }
1219         /* In case of error, freeze device for proper recovery. */
1220         if (et != SIIS_ERR_NONE &&
1221             !(ccb->ccb_h.status & CAM_DEV_QFRZN)) {
1222                 xpt_freeze_devq(ccb->ccb_h.path, 1);
1223                 ccb->ccb_h.status |= CAM_DEV_QFRZN;
1224         }
1225         ccb->ccb_h.status &= ~CAM_STATUS_MASK;
1226         switch (et) {
1227         case SIIS_ERR_NONE:
1228                 ccb->ccb_h.status |= CAM_REQ_CMP;
1229                 if (ccb->ccb_h.func_code == XPT_SCSI_IO)
1230                         ccb->csio.scsi_status = SCSI_STATUS_OK;
1231                 break;
1232         case SIIS_ERR_INVALID:
1233                 ch->fatalerr = 1;
1234                 ccb->ccb_h.status |= CAM_REQ_INVALID;
1235                 break;
1236         case SIIS_ERR_INNOCENT:
1237                 ccb->ccb_h.status |= CAM_REQUEUE_REQ;
1238                 break;
1239         case SIIS_ERR_TFE:
1240         case SIIS_ERR_NCQ:
1241                 if (ccb->ccb_h.func_code == XPT_SCSI_IO) {
1242                         ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
1243                         ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
1244                 } else {
1245                         ccb->ccb_h.status |= CAM_ATA_STATUS_ERROR;
1246                 }
1247                 break;
1248         case SIIS_ERR_SATA:
1249                 ch->fatalerr = 1;
1250                 ccb->ccb_h.status |= CAM_UNCOR_PARITY;
1251                 break;
1252         case SIIS_ERR_TIMEOUT:
1253                 ch->fatalerr = 1;
1254                 ccb->ccb_h.status |= CAM_CMD_TIMEOUT;
1255                 break;
1256         default:
1257                 ccb->ccb_h.status |= CAM_REQ_CMP_ERR;
1258         }
1259         /* Free slot. */
1260         ch->oslots &= ~(1 << slot->slot);
1261         ch->rslots &= ~(1 << slot->slot);
1262         ch->aslots &= ~(1 << slot->slot);
1263         if (et != SIIS_ERR_TIMEOUT) {
1264                 if (ch->toslots == (1 << slot->slot))
1265                         xpt_release_simq(ch->sim, TRUE);
1266                 ch->toslots &= ~(1 << slot->slot);
1267         }
1268         slot->state = SIIS_SLOT_EMPTY;
1269         slot->ccb = NULL;
1270         /* Update channel stats. */
1271         ch->numrslots--;
1272         if ((ccb->ccb_h.func_code == XPT_ATA_IO) &&
1273             (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA)) {
1274                 ch->numtslots[ccb->ccb_h.target_id]--;
1275         }
1276         /* If it was our READ LOG command - process it. */
1277         if (ch->readlog) {
1278                 siis_process_read_log(dev, ccb);
1279         /* If it was NCQ command error, put result on hold. */
1280         } else if (et == SIIS_ERR_NCQ) {
1281                 ch->hold[slot->slot] = ccb;
1282                 ch->numhslots++;
1283         } else
1284                 xpt_done(ccb);
1285         /* Unfreeze frozen command. */
1286         if (ch->frozen && !siis_check_collision(dev, ch->frozen)) {
1287                 union ccb *fccb = ch->frozen;
1288                 ch->frozen = NULL;
1289                 siis_begin_transaction(dev, fccb);
1290                 xpt_release_simq(ch->sim, TRUE);
1291         }
1292         /* If we have no other active commands, ... */
1293         if (ch->rslots == 0) {
1294                 /* if there were timeouts or fatal error - reset port. */
1295                 if (ch->toslots != 0 || ch->fatalerr) {
1296                         siis_reset(dev);
1297                 } else {
1298                         /* if we have slots in error, we can reinit port. */
1299                         if (ch->eslots != 0)
1300                                 siis_portinit(dev);
1301                         /* if there commands on hold, we can do READ LOG. */
1302                         if (!ch->readlog && ch->numhslots)
1303                                 siis_issue_read_log(dev);
1304                 }
1305         /* If all the reset of commands are in timeout - abort them. */
1306         } else if ((ch->rslots & ~ch->toslots) == 0 &&
1307             et != SIIS_ERR_TIMEOUT)
1308                 siis_rearm_timeout(dev);
1309 }
1310
1311 static void
1312 siis_issue_read_log(device_t dev)
1313 {
1314         struct siis_channel *ch = device_get_softc(dev);
1315         union ccb *ccb;
1316         struct ccb_ataio *ataio;
1317         int i;
1318
1319         /* Find some holden command. */
1320         for (i = 0; i < SIIS_MAX_SLOTS; i++) {
1321                 if (ch->hold[i])
1322                         break;
1323         }
1324         if (i == SIIS_MAX_SLOTS)
1325                 return;
1326         ch->readlog = 1;
1327         ccb = xpt_alloc_ccb_nowait();
1328         if (ccb == NULL) {
1329                 device_printf(dev, "Unable allocate READ LOG command");
1330                 return; /* XXX */
1331         }
1332         ccb->ccb_h = ch->hold[i]->ccb_h;        /* Reuse old header. */
1333         ccb->ccb_h.func_code = XPT_ATA_IO;
1334         ccb->ccb_h.flags = CAM_DIR_IN;
1335         ccb->ccb_h.timeout = 1000;      /* 1s should be enough. */
1336         ataio = &ccb->ataio;
1337         ataio->data_ptr = malloc(512, M_SIIS, M_NOWAIT);
1338         if (ataio->data_ptr == NULL) {
1339                 device_printf(dev, "Unable allocate memory for READ LOG command");
1340                 return; /* XXX */
1341         }
1342         ataio->dxfer_len = 512;
1343         bzero(&ataio->cmd, sizeof(ataio->cmd));
1344         ataio->cmd.flags = CAM_ATAIO_48BIT;
1345         ataio->cmd.command = 0x2F;      /* READ LOG EXT */
1346         ataio->cmd.sector_count = 1;
1347         ataio->cmd.sector_count_exp = 0;
1348         ataio->cmd.lba_low = 0x10;
1349         ataio->cmd.lba_mid = 0;
1350         ataio->cmd.lba_mid_exp = 0;
1351         siis_begin_transaction(dev, ccb);
1352 }
1353
1354 static void
1355 siis_process_read_log(device_t dev, union ccb *ccb)
1356 {
1357         struct siis_channel *ch = device_get_softc(dev);
1358         uint8_t *data;
1359         struct ata_res *res;
1360         int i;
1361
1362         ch->readlog = 0;
1363         data = ccb->ataio.data_ptr;
1364         if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP &&
1365             (data[0] & 0x80) == 0) {
1366                 for (i = 0; i < SIIS_MAX_SLOTS; i++) {
1367                         if (!ch->hold[i])
1368                                 continue;
1369                         if (ch->hold[i]->ccb_h.target_id != ccb->ccb_h.target_id)
1370                                 continue;
1371                         if ((data[0] & 0x1F) == i) {
1372                                 res = &ch->hold[i]->ataio.res;
1373                                 res->status = data[2];
1374                                 res->error = data[3];
1375                                 res->lba_low = data[4];
1376                                 res->lba_mid = data[5];
1377                                 res->lba_high = data[6];
1378                                 res->device = data[7];
1379                                 res->lba_low_exp = data[8];
1380                                 res->lba_mid_exp = data[9];
1381                                 res->lba_high_exp = data[10];
1382                                 res->sector_count = data[12];
1383                                 res->sector_count_exp = data[13];
1384                         } else {
1385                                 ch->hold[i]->ccb_h.status &= ~CAM_STATUS_MASK;
1386                                 ch->hold[i]->ccb_h.status |= CAM_REQUEUE_REQ;
1387                         }
1388                         xpt_done(ch->hold[i]);
1389                         ch->hold[i] = NULL;
1390                         ch->numhslots--;
1391                 }
1392         } else {
1393                 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
1394                         device_printf(dev, "Error while READ LOG EXT\n");
1395                 else if ((data[0] & 0x80) == 0) {
1396                         device_printf(dev, "Non-queued command error in READ LOG EXT\n");
1397                 }
1398                 for (i = 0; i < SIIS_MAX_SLOTS; i++) {
1399                         if (!ch->hold[i])
1400                                 continue;
1401                         if (ch->hold[i]->ccb_h.target_id != ccb->ccb_h.target_id)
1402                                 continue;
1403                         xpt_done(ch->hold[i]);
1404                         ch->hold[i] = NULL;
1405                         ch->numhslots--;
1406                 }
1407         }
1408         free(ccb->ataio.data_ptr, M_SIIS);
1409         xpt_free_ccb(ccb);
1410 }
1411
1412 static void
1413 siis_portinit(device_t dev)
1414 {
1415         struct siis_channel *ch = device_get_softc(dev);
1416         int i;
1417
1418         ch->eslots = 0;
1419         ch->recovery = 0;
1420         ATA_OUTL(ch->r_mem, SIIS_P_CTLCLR, SIIS_P_CTL_RESUME);
1421         for (i = 0; i < 16; i++) {
1422                 ATA_OUTL(ch->r_mem, SIIS_P_PMPSTS(i), 0),
1423                 ATA_OUTL(ch->r_mem, SIIS_P_PMPQACT(i), 0);
1424         }
1425         ATA_OUTL(ch->r_mem, SIIS_P_CTLSET, SIIS_P_CTL_PORT_INIT);
1426         siis_wait_ready(dev, 1000);
1427 }
1428
1429 static int
1430 siis_devreset(device_t dev)
1431 {
1432         struct siis_channel *ch = device_get_softc(dev);
1433         int timeout = 0;
1434         uint32_t val;
1435
1436         ATA_OUTL(ch->r_mem, SIIS_P_CTLSET, SIIS_P_CTL_DEV_RESET);
1437         while (((val = ATA_INL(ch->r_mem, SIIS_P_STS)) &
1438             SIIS_P_CTL_DEV_RESET) != 0) {
1439                 DELAY(1000);
1440                 if (timeout++ > 100) {
1441                         device_printf(dev, "device reset stuck (timeout %dms) "
1442                             "status = %08x\n", timeout, val);
1443                         return (EBUSY);
1444                 }
1445         }
1446         return (0);
1447 }
1448
1449 static int
1450 siis_wait_ready(device_t dev, int t)
1451 {
1452         struct siis_channel *ch = device_get_softc(dev);
1453         int timeout = 0;
1454         uint32_t val;
1455
1456         while (((val = ATA_INL(ch->r_mem, SIIS_P_STS)) &
1457             SIIS_P_CTL_READY) == 0) {
1458                 DELAY(1000);
1459                 if (timeout++ > t) {
1460                         device_printf(dev, "port is not ready (timeout %dms) "
1461                             "status = %08x\n", t, val);
1462                         return (EBUSY);
1463                 }
1464         }
1465         return (0);
1466 }
1467
1468 static void
1469 siis_reset(device_t dev)
1470 {
1471         struct siis_channel *ch = device_get_softc(dev);
1472         int i, retry = 0, sata_rev;
1473         uint32_t val;
1474
1475         xpt_freeze_simq(ch->sim, 1);
1476         if (bootverbose)
1477                 device_printf(dev, "SIIS reset...\n");
1478         if (!ch->readlog && !ch->recovery)
1479                 xpt_freeze_simq(ch->sim, ch->numrslots);
1480         /* Requeue frozen command. */
1481         if (ch->frozen) {
1482                 union ccb *fccb = ch->frozen;
1483                 ch->frozen = NULL;
1484                 fccb->ccb_h.status &= ~CAM_STATUS_MASK;
1485                 fccb->ccb_h.status |= CAM_REQUEUE_REQ | CAM_RELEASE_SIMQ;
1486                 if (!(fccb->ccb_h.status & CAM_DEV_QFRZN)) {
1487                         xpt_freeze_devq(fccb->ccb_h.path, 1);
1488                         fccb->ccb_h.status |= CAM_DEV_QFRZN;
1489                 }
1490                 xpt_done(fccb);
1491         }
1492         /* Requeue all running commands. */
1493         for (i = 0; i < SIIS_MAX_SLOTS; i++) {
1494                 /* Do we have a running request on slot? */
1495                 if (ch->slot[i].state < SIIS_SLOT_RUNNING)
1496                         continue;
1497                 /* XXX; Commands in loading state. */
1498                 siis_end_transaction(&ch->slot[i], SIIS_ERR_INNOCENT);
1499         }
1500         /* Finish all holden commands as-is. */
1501         for (i = 0; i < SIIS_MAX_SLOTS; i++) {
1502                 if (!ch->hold[i])
1503                         continue;
1504                 xpt_done(ch->hold[i]);
1505                 ch->hold[i] = NULL;
1506                 ch->numhslots--;
1507         }
1508         if (ch->toslots != 0)
1509                 xpt_release_simq(ch->sim, TRUE);
1510         ch->eslots = 0;
1511         ch->recovery = 0;
1512         ch->toslots = 0;
1513         ch->fatalerr = 0;
1514         /* Disable port interrupts */
1515         ATA_OUTL(ch->r_mem, SIIS_P_IECLR, 0x0000FFFF);
1516         /* Set speed limit. */
1517         sata_rev = ch->user[ch->pm_present ? 15 : 0].revision;
1518         if (sata_rev == 1)
1519                 val = ATA_SC_SPD_SPEED_GEN1;
1520         else if (sata_rev == 2)
1521                 val = ATA_SC_SPD_SPEED_GEN2;
1522         else if (sata_rev == 3)
1523                 val = ATA_SC_SPD_SPEED_GEN3;
1524         else
1525                 val = 0;
1526         ATA_OUTL(ch->r_mem, SIIS_P_SCTL,
1527             ATA_SC_DET_IDLE | val | ((ch->pm_level > 0) ? 0 :
1528             (ATA_SC_IPM_DIS_PARTIAL | ATA_SC_IPM_DIS_SLUMBER)));
1529 retry:
1530         siis_devreset(dev);
1531         /* Reset and reconnect PHY, */
1532         if (!siis_sata_connect(ch)) {
1533                 ch->devices = 0;
1534                 /* Enable port interrupts */
1535                 ATA_OUTL(ch->r_mem, SIIS_P_IESET, SIIS_P_IX_ENABLED);
1536                 if (bootverbose)
1537                         device_printf(dev,
1538                             "SIIS reset done: phy reset found no device\n");
1539                 /* Tell the XPT about the event */
1540                 xpt_async(AC_BUS_RESET, ch->path, NULL);
1541                 xpt_release_simq(ch->sim, TRUE);
1542                 return;
1543         }
1544         /* Wait for clearing busy status. */
1545         if (siis_wait_ready(dev, 10000)) {
1546                 device_printf(dev, "device ready timeout\n");
1547                 if (!retry) {
1548                         device_printf(dev, "trying full port reset ...\n");
1549                         /* Get port to the reset state. */
1550                         ATA_OUTL(ch->r_mem, SIIS_P_CTLSET, SIIS_P_CTL_PORT_RESET);
1551                         DELAY(10000);
1552                         /* Get port out of reset state. */
1553                         ATA_OUTL(ch->r_mem, SIIS_P_CTLCLR, SIIS_P_CTL_PORT_RESET);
1554                         ATA_OUTL(ch->r_mem, SIIS_P_CTLCLR, SIIS_P_CTL_32BIT);
1555                         if (ch->pm_present)
1556                                 ATA_OUTL(ch->r_mem, SIIS_P_CTLSET, SIIS_P_CTL_PME);
1557                         else
1558                                 ATA_OUTL(ch->r_mem, SIIS_P_CTLCLR, SIIS_P_CTL_PME);
1559                         siis_wait_ready(dev, 5000);
1560                         retry = 1;
1561                         goto retry;
1562                 }
1563         }
1564         ch->devices = 1;
1565         /* Enable port interrupts */
1566         ATA_OUTL(ch->r_mem, SIIS_P_IS, 0xFFFFFFFF);
1567         ATA_OUTL(ch->r_mem, SIIS_P_IESET, SIIS_P_IX_ENABLED);
1568         if (bootverbose)
1569                 device_printf(dev, "SIIS reset done: devices=%08x\n", ch->devices);
1570         /* Tell the XPT about the event */
1571         xpt_async(AC_BUS_RESET, ch->path, NULL);
1572         xpt_release_simq(ch->sim, TRUE);
1573 }
1574
1575 static int
1576 siis_setup_fis(device_t dev, struct siis_cmd *ctp, union ccb *ccb, int tag)
1577 {
1578         struct siis_channel *ch = device_get_softc(dev);
1579         u_int8_t *fis = &ctp->fis[0];
1580
1581         bzero(fis, 24);
1582         fis[0] = 0x27;                  /* host to device */
1583         fis[1] = (ccb->ccb_h.target_id & 0x0f);
1584         if (ccb->ccb_h.func_code == XPT_SCSI_IO) {
1585                 fis[1] |= 0x80;
1586                 fis[2] = ATA_PACKET_CMD;
1587                 if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE &&
1588                     ch->curr[ccb->ccb_h.target_id].mode >= ATA_DMA)
1589                         fis[3] = ATA_F_DMA;
1590                 else {
1591                         fis[5] = ccb->csio.dxfer_len;
1592                         fis[6] = ccb->csio.dxfer_len >> 8;
1593                 }
1594                 fis[7] = ATA_D_LBA;
1595                 fis[15] = ATA_A_4BIT;
1596                 bzero(ctp->u.atapi.ccb, 16);
1597                 bcopy((ccb->ccb_h.flags & CAM_CDB_POINTER) ?
1598                     ccb->csio.cdb_io.cdb_ptr : ccb->csio.cdb_io.cdb_bytes,
1599                     ctp->u.atapi.ccb, ccb->csio.cdb_len);
1600         } else if ((ccb->ataio.cmd.flags & CAM_ATAIO_CONTROL) == 0) {
1601                 fis[1] |= 0x80;
1602                 fis[2] = ccb->ataio.cmd.command;
1603                 fis[3] = ccb->ataio.cmd.features;
1604                 fis[4] = ccb->ataio.cmd.lba_low;
1605                 fis[5] = ccb->ataio.cmd.lba_mid;
1606                 fis[6] = ccb->ataio.cmd.lba_high;
1607                 fis[7] = ccb->ataio.cmd.device;
1608                 fis[8] = ccb->ataio.cmd.lba_low_exp;
1609                 fis[9] = ccb->ataio.cmd.lba_mid_exp;
1610                 fis[10] = ccb->ataio.cmd.lba_high_exp;
1611                 fis[11] = ccb->ataio.cmd.features_exp;
1612                 if (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA) {
1613                         fis[12] = tag << 3;
1614                         fis[13] = 0;
1615                 } else {
1616                         fis[12] = ccb->ataio.cmd.sector_count;
1617                         fis[13] = ccb->ataio.cmd.sector_count_exp;
1618                 }
1619                 fis[15] = ATA_A_4BIT;
1620         } else {
1621                 /* Soft reset. */
1622         }
1623         return (20);
1624 }
1625
1626 static int
1627 siis_sata_connect(struct siis_channel *ch)
1628 {
1629         u_int32_t status;
1630         int timeout;
1631
1632         /* Wait up to 100ms for "connect well" */
1633         for (timeout = 0; timeout < 100 ; timeout++) {
1634                 status = ATA_INL(ch->r_mem, SIIS_P_SSTS);
1635                 if (((status & ATA_SS_DET_MASK) == ATA_SS_DET_PHY_ONLINE) &&
1636                     ((status & ATA_SS_SPD_MASK) != ATA_SS_SPD_NO_SPEED) &&
1637                     ((status & ATA_SS_IPM_MASK) == ATA_SS_IPM_ACTIVE))
1638                         break;
1639                 DELAY(1000);
1640         }
1641         if (timeout >= 100) {
1642                 if (bootverbose) {
1643                         device_printf(ch->dev, "SATA connect timeout status=%08x\n",
1644                             status);
1645                 }
1646                 return (0);
1647         }
1648         if (bootverbose) {
1649                 device_printf(ch->dev, "SATA connect time=%dms status=%08x\n",
1650                     timeout, status);
1651         }
1652         /* Clear SATA error register */
1653         ATA_OUTL(ch->r_mem, SIIS_P_SERR, 0xffffffff);
1654         return (1);
1655 }
1656
1657 static int
1658 siis_check_ids(device_t dev, union ccb *ccb)
1659 {
1660
1661         if (ccb->ccb_h.target_id > 15) {
1662                 ccb->ccb_h.status = CAM_TID_INVALID;
1663                 xpt_done(ccb);
1664                 return (-1);
1665         }
1666         if (ccb->ccb_h.target_lun != 0) {
1667                 ccb->ccb_h.status = CAM_LUN_INVALID;
1668                 xpt_done(ccb);
1669                 return (-1);
1670         }
1671         return (0);
1672 }
1673
1674 static void
1675 siisaction(struct cam_sim *sim, union ccb *ccb)
1676 {
1677         device_t dev;
1678         struct siis_channel *ch;
1679
1680         CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("siisaction func_code=%x\n",
1681             ccb->ccb_h.func_code));
1682
1683         ch = (struct siis_channel *)cam_sim_softc(sim);
1684         dev = ch->dev;
1685         mtx_assert(&ch->mtx, MA_OWNED);
1686         switch (ccb->ccb_h.func_code) {
1687         /* Common cases first */
1688         case XPT_ATA_IO:        /* Execute the requested I/O operation */
1689         case XPT_SCSI_IO:
1690                 if (siis_check_ids(dev, ccb))
1691                         return;
1692                 if (ch->devices == 0 ||
1693                     (ch->pm_present == 0 &&
1694                      ccb->ccb_h.target_id > 0 && ccb->ccb_h.target_id < 15)) {
1695                         ccb->ccb_h.status = CAM_SEL_TIMEOUT;
1696                         break;
1697                 }
1698                 /* Check for command collision. */
1699                 if (siis_check_collision(dev, ccb)) {
1700                         /* Freeze command. */
1701                         ch->frozen = ccb;
1702                         /* We have only one frozen slot, so freeze simq also. */
1703                         xpt_freeze_simq(ch->sim, 1);
1704                         return;
1705                 }
1706                 siis_begin_transaction(dev, ccb);
1707                 return;
1708         case XPT_EN_LUN:                /* Enable LUN as a target */
1709         case XPT_TARGET_IO:             /* Execute target I/O request */
1710         case XPT_ACCEPT_TARGET_IO:      /* Accept Host Target Mode CDB */
1711         case XPT_CONT_TARGET_IO:        /* Continue Host Target I/O Connection*/
1712         case XPT_ABORT:                 /* Abort the specified CCB */
1713                 /* XXX Implement */
1714                 ccb->ccb_h.status = CAM_REQ_INVALID;
1715                 break;
1716         case XPT_SET_TRAN_SETTINGS:
1717         {
1718                 struct  ccb_trans_settings *cts = &ccb->cts;
1719                 struct  siis_device *d; 
1720
1721                 if (siis_check_ids(dev, ccb))
1722                         return;
1723                 if (cts->type == CTS_TYPE_CURRENT_SETTINGS)
1724                         d = &ch->curr[ccb->ccb_h.target_id];
1725                 else
1726                         d = &ch->user[ccb->ccb_h.target_id];
1727                 if (cts->xport_specific.sata.valid & CTS_SATA_VALID_REVISION)
1728                         d->revision = cts->xport_specific.sata.revision;
1729                 if (cts->xport_specific.sata.valid & CTS_SATA_VALID_MODE)
1730                         d->mode = cts->xport_specific.sata.mode;
1731                 if (cts->xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT)
1732                         d->bytecount = min(8192, cts->xport_specific.sata.bytecount);
1733                 if (cts->xport_specific.sata.valid & CTS_SATA_VALID_TAGS)
1734                         d->tags = min(SIIS_MAX_SLOTS, cts->xport_specific.sata.tags);
1735                 if (cts->xport_specific.sata.valid & CTS_SATA_VALID_PM) {
1736                         ch->pm_present = cts->xport_specific.sata.pm_present;
1737                         if (ch->pm_present)
1738                                 ATA_OUTL(ch->r_mem, SIIS_P_CTLSET, SIIS_P_CTL_PME);
1739                         else
1740                                 ATA_OUTL(ch->r_mem, SIIS_P_CTLCLR, SIIS_P_CTL_PME);
1741                 }
1742                 if (cts->xport_specific.sata.valid & CTS_SATA_VALID_TAGS)
1743                         d->atapi = cts->xport_specific.sata.atapi;
1744                 if (cts->xport_specific.sata.valid & CTS_SATA_VALID_CAPS)
1745                         d->caps = cts->xport_specific.sata.caps;
1746                 ccb->ccb_h.status = CAM_REQ_CMP;
1747                 break;
1748         }
1749         case XPT_GET_TRAN_SETTINGS:
1750         /* Get default/user set transfer settings for the target */
1751         {
1752                 struct  ccb_trans_settings *cts = &ccb->cts;
1753                 struct  siis_device *d;
1754                 uint32_t status;
1755
1756                 if (siis_check_ids(dev, ccb))
1757                         return;
1758                 if (cts->type == CTS_TYPE_CURRENT_SETTINGS)
1759                         d = &ch->curr[ccb->ccb_h.target_id];
1760                 else
1761                         d = &ch->user[ccb->ccb_h.target_id];
1762                 cts->protocol = PROTO_ATA;
1763                 cts->protocol_version = PROTO_VERSION_UNSPECIFIED;
1764                 cts->transport = XPORT_SATA;
1765                 cts->transport_version = XPORT_VERSION_UNSPECIFIED;
1766                 cts->proto_specific.valid = 0;
1767                 cts->xport_specific.sata.valid = 0;
1768                 if (cts->type == CTS_TYPE_CURRENT_SETTINGS &&
1769                     (ccb->ccb_h.target_id == 15 ||
1770                     (ccb->ccb_h.target_id == 0 && !ch->pm_present))) {
1771                         status = ATA_INL(ch->r_mem, SIIS_P_SSTS) & ATA_SS_SPD_MASK;
1772                         if (status & 0x0f0) {
1773                                 cts->xport_specific.sata.revision =
1774                                     (status & 0x0f0) >> 4;
1775                                 cts->xport_specific.sata.valid |=
1776                                     CTS_SATA_VALID_REVISION;
1777                         }
1778                         cts->xport_specific.sata.caps = d->caps & CTS_SATA_CAPS_D;
1779                         if (ch->pm_level)
1780                                 cts->xport_specific.sata.caps |= CTS_SATA_CAPS_H_PMREQ;
1781                         cts->xport_specific.sata.caps &=
1782                             ch->user[ccb->ccb_h.target_id].caps;
1783                         cts->xport_specific.sata.valid |= CTS_SATA_VALID_CAPS;
1784                 } else {
1785                         cts->xport_specific.sata.revision = d->revision;
1786                         cts->xport_specific.sata.valid |= CTS_SATA_VALID_REVISION;
1787                         cts->xport_specific.sata.caps = d->caps;
1788                         cts->xport_specific.sata.valid |= CTS_SATA_VALID_CAPS;
1789                 }
1790                 cts->xport_specific.sata.mode = d->mode;
1791                 cts->xport_specific.sata.valid |= CTS_SATA_VALID_MODE;
1792                 cts->xport_specific.sata.bytecount = d->bytecount;
1793                 cts->xport_specific.sata.valid |= CTS_SATA_VALID_BYTECOUNT;
1794                 cts->xport_specific.sata.pm_present = ch->pm_present;
1795                 cts->xport_specific.sata.valid |= CTS_SATA_VALID_PM;
1796                 cts->xport_specific.sata.tags = d->tags;
1797                 cts->xport_specific.sata.valid |= CTS_SATA_VALID_TAGS;
1798                 cts->xport_specific.sata.atapi = d->atapi;
1799                 cts->xport_specific.sata.valid |= CTS_SATA_VALID_ATAPI;
1800                 ccb->ccb_h.status = CAM_REQ_CMP;
1801                 break;
1802         }
1803         case XPT_RESET_BUS:             /* Reset the specified SCSI bus */
1804         case XPT_RESET_DEV:     /* Bus Device Reset the specified SCSI device */
1805                 siis_reset(dev);
1806                 ccb->ccb_h.status = CAM_REQ_CMP;
1807                 break;
1808         case XPT_TERM_IO:               /* Terminate the I/O process */
1809                 /* XXX Implement */
1810                 ccb->ccb_h.status = CAM_REQ_INVALID;
1811                 break;
1812         case XPT_PATH_INQ:              /* Path routing inquiry */
1813         {
1814                 struct ccb_pathinq *cpi = &ccb->cpi;
1815
1816                 cpi->version_num = 1; /* XXX??? */
1817                 cpi->hba_inquiry = PI_SDTR_ABLE | PI_TAG_ABLE;
1818                 cpi->hba_inquiry |= PI_SATAPM;
1819                 cpi->target_sprt = 0;
1820                 cpi->hba_misc = PIM_SEQSCAN;
1821                 cpi->hba_eng_cnt = 0;
1822                 cpi->max_target = 15;
1823                 cpi->max_lun = 0;
1824                 cpi->initiator_id = 0;
1825                 cpi->bus_id = cam_sim_bus(sim);
1826                 cpi->base_transfer_speed = 150000;
1827                 strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
1828                 strncpy(cpi->hba_vid, "SIIS", HBA_IDLEN);
1829                 strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
1830                 cpi->unit_number = cam_sim_unit(sim);
1831                 cpi->transport = XPORT_SATA;
1832                 cpi->transport_version = XPORT_VERSION_UNSPECIFIED;
1833                 cpi->protocol = PROTO_ATA;
1834                 cpi->protocol_version = PROTO_VERSION_UNSPECIFIED;
1835                 cpi->ccb_h.status = CAM_REQ_CMP;
1836                 cpi->maxio = MAXPHYS;
1837                 break;
1838         }
1839         default:
1840                 ccb->ccb_h.status = CAM_REQ_INVALID;
1841                 break;
1842         }
1843         xpt_done(ccb);
1844 }
1845
1846 static void
1847 siispoll(struct cam_sim *sim)
1848 {
1849         struct siis_channel *ch = (struct siis_channel *)cam_sim_softc(sim);
1850
1851         siis_ch_intr(ch->dev);
1852 }