Sync CAM with FreeBSD using lockmgr locks instead of mutexes.
[dragonfly.git] / sys / dev / raid / ips / ips.c
blob0b0ea887c4a527d2de275a08ff88630b67ea60b2
1 /*-
2 * Written by: David Jeffery
3 * Copyright (c) 2002 Adaptec Inc.
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
27 * $FreeBSD: src/sys/dev/ips/ips.c,v 1.12 2004/05/30 04:01:29 scottl Exp $
28 * $DragonFly: src/sys/dev/raid/ips/ips.c,v 1.19 2006/12/22 23:26:23 swildner Exp $
31 #include <dev/raid/ips/ips.h>
32 #include <sys/stat.h>
33 #include <sys/time.h>
34 #include <sys/thread2.h>
35 #include <machine/clock.h>
37 static d_open_t ips_open;
38 static d_close_t ips_close;
39 static d_ioctl_t ips_ioctl;
41 MALLOC_DEFINE(M_IPSBUF, "ipsbuf", "IPS driver buffer");
43 static struct dev_ops ips_ops = {
44 { "ips", IPS_CDEV_MAJOR, D_DISK },
45 .d_open = ips_open,
46 .d_close = ips_close,
47 .d_ioctl = ips_ioctl,
50 static const char *ips_adapter_name[] = {
51 "N/A",
52 "ServeRAID (copperhead)",
53 "ServeRAID II (copperhead refresh)",
54 "ServeRAID onboard (copperhead)",
55 "ServeRAID onboard (copperhead)",
56 "ServeRAID 3H (clarinet)",
57 "ServeRAID 3L (clarinet lite)",
58 "ServeRAID 4H (trombone)",
59 "ServeRAID 4M (morpheus)",
60 "ServeRAID 4L (morpheus lite)",
61 "ServeRAID 4Mx (neo)",
62 "ServeRAID 4Lx (neo lite)",
63 "ServeRAID 5i II (sarasota)",
64 "ServeRAID 5i (sarasota)",
65 "ServeRAID 6M (marco)",
66 "ServeRAID 6i (sebring)"
70 static int
71 ips_open(struct dev_open_args *ap)
73 cdev_t dev = ap->a_head.a_dev;
74 ips_softc_t *sc = dev->si_drv1;
76 sc->state |= IPS_DEV_OPEN;
77 return 0;
80 static int
81 ips_close(struct dev_close_args *ap)
83 cdev_t dev = ap->a_head.a_dev;
84 ips_softc_t *sc = dev->si_drv1;
86 sc->state &= ~IPS_DEV_OPEN;
87 return 0;
90 static int
91 ips_ioctl(struct dev_ioctl_args *ap)
93 ips_softc_t *sc;
95 sc = ap->a_head.a_dev->si_drv1;
96 return ips_ioctl_request(sc, ap->a_cmd, ap->a_data, ap->a_fflag);
99 static void
100 ips_cmd_dmaload(void *cmdptr, bus_dma_segment_t *segments, int segnum,
101 int error)
103 ips_command_t *command = cmdptr;
105 PRINTF(10, "ips: in ips_cmd_dmaload\n");
106 if (!error)
107 command->command_phys_addr = segments[0].ds_addr;
111 /* is locking needed? what locking guarentees are there on removal? */
112 static int
113 ips_cmdqueue_free(ips_softc_t *sc)
115 int i, error = -1;
116 ips_command_t *command;
118 crit_enter();
119 if (sc->used_commands == 0) {
120 for (i = 0; i < sc->max_cmds; i++) {
121 command = &sc->commandarray[i];
122 if (command->command_phys_addr == 0)
123 continue;
124 bus_dmamap_unload(sc->command_dmatag,
125 command->command_dmamap);
126 bus_dmamem_free(sc->command_dmatag,
127 command->command_buffer,
128 command->command_dmamap);
129 if (command->data_dmamap != NULL)
130 bus_dmamap_destroy(command->data_dmatag,
131 command->data_dmamap);
133 error = 0;
134 sc->state |= IPS_OFFLINE;
136 sc->staticcmd = NULL;
137 kfree(sc->commandarray, M_IPSBUF);
138 crit_exit();
139 return error;
143 * Places all ips command structs on the free command queue.
144 * The first slot is used exclusively for static commands
145 * No locking as if someone else tries to access this during init,
146 * we have bigger problems
148 static int
149 ips_cmdqueue_init(ips_softc_t *sc)
151 int i;
152 ips_command_t *command;
154 sc->commandarray = kmalloc(sizeof(sc->commandarray[0]) * sc->max_cmds,
155 M_IPSBUF, M_INTWAIT | M_ZERO);
156 SLIST_INIT(&sc->free_cmd_list);
157 for (i = 0; i < sc->max_cmds; i++) {
158 command = &sc->commandarray[i];
159 command->id = i;
160 command->sc = sc;
161 if (bus_dmamem_alloc(sc->command_dmatag,
162 &command->command_buffer, BUS_DMA_NOWAIT,
163 &command->command_dmamap))
164 goto error;
165 bus_dmamap_load(sc->command_dmatag, command->command_dmamap,
166 command->command_buffer, IPS_COMMAND_LEN, ips_cmd_dmaload,
167 command, BUS_DMA_NOWAIT);
168 if (command->command_phys_addr == 0) {
169 bus_dmamem_free(sc->command_dmatag,
170 command->command_buffer, command->command_dmamap);
171 goto error;
174 if (i == 0)
175 sc->staticcmd = command;
176 else {
177 command->data_dmatag = sc->sg_dmatag;
178 if (bus_dmamap_create(command->data_dmatag, 0,
179 &command->data_dmamap))
180 goto error;
181 SLIST_INSERT_HEAD(&sc->free_cmd_list, command, next);
184 sc->state &= ~IPS_OFFLINE;
185 return 0;
186 error:
187 ips_cmdqueue_free(sc);
188 return ENOMEM;
192 * returns a free command struct if one is available.
193 * It also blanks out anything that may be a wild pointer/value.
194 * Also, command buffers are not freed. They are
195 * small so they are saved and kept dmamapped and loaded.
198 ips_get_free_cmd(ips_softc_t *sc, ips_command_t **cmd, unsigned long flags)
200 ips_command_t *command = NULL;
201 int error = 0;
203 crit_enter();
204 if (sc->state & IPS_OFFLINE) {
205 error = EIO;
206 goto bail;
208 if ((flags & IPS_STATIC_FLAG) != 0) {
209 if (sc->state & IPS_STATIC_BUSY) {
210 error = EAGAIN;
211 goto bail;
213 command = sc->staticcmd;
214 sc->state |= IPS_STATIC_BUSY;
215 } else {
216 command = SLIST_FIRST(&sc->free_cmd_list);
217 if (!command || (sc->state & IPS_TIMEOUT)) {
218 error = EBUSY;
219 goto bail;
221 SLIST_REMOVE_HEAD(&sc->free_cmd_list, next);
222 sc->used_commands++;
224 bail:
225 crit_exit();
226 if (error != 0)
227 return error;
229 bzero(&command->status, (char *)(command + 1) - (char *)(&command->status));
230 bzero(command->command_buffer, IPS_COMMAND_LEN);
231 *cmd = command;
232 return 0;
235 /* adds a command back to the free command queue */
236 void
237 ips_insert_free_cmd(ips_softc_t *sc, ips_command_t *command)
239 crit_enter();
240 if (command == sc->staticcmd)
241 sc->state &= ~IPS_STATIC_BUSY;
242 else {
243 SLIST_INSERT_HEAD(&sc->free_cmd_list, command, next);
244 sc->used_commands--;
246 crit_exit();
249 static const char *
250 ips_diskdev_statename(u_int8_t state)
252 static char statebuf[20];
254 switch(state) {
255 case IPS_LD_OFFLINE:
256 return("OFFLINE");
257 break;
258 case IPS_LD_OKAY:
259 return("OK");
260 break;
261 case IPS_LD_DEGRADED:
262 return("DEGRADED");
263 break;
264 case IPS_LD_FREE:
265 return("FREE");
266 break;
267 case IPS_LD_SYS:
268 return("SYS");
269 break;
270 case IPS_LD_CRS:
271 return("CRS");
272 break;
274 ksprintf(statebuf, "UNKNOWN(0x%02x)", state);
275 return (statebuf);
278 static int
279 ips_diskdev_init(ips_softc_t *sc)
281 int i;
283 for (i = 0; i < IPS_MAX_NUM_DRIVES; i++) {
284 if (sc->drives[i].state == IPS_LD_FREE)
285 continue;
286 device_printf(sc->dev,
287 "Logical Drive %d: RAID%d sectors: %u, state %s\n", i,
288 sc->drives[i].raid_lvl, sc->drives[i].sector_count,
289 ips_diskdev_statename(sc->drives[i].state));
290 if (sc->drives[i].state == IPS_LD_OKAY ||
291 sc->drives[i].state == IPS_LD_DEGRADED) {
292 sc->diskdev[i] = device_add_child(sc->dev, NULL, -1);
293 device_set_ivars(sc->diskdev[i], (void *)(uintptr_t)i);
296 if (bus_generic_attach(sc->dev))
297 device_printf(sc->dev, "Attaching bus failed\n");
298 return 0;
301 static int
302 ips_diskdev_free(ips_softc_t *sc)
304 int i;
305 int error = 0;
307 for (i = 0; i < IPS_MAX_NUM_DRIVES; i++) {
308 if (sc->diskdev[i] != NULL) {
309 error = device_delete_child(sc->dev, sc->diskdev[i]);
310 if (error)
311 return error;
314 bus_generic_detach(sc->dev);
315 return 0;
319 * ips_timeout is periodically called to make sure no commands sent
320 * to the card have become stuck. If it finds a stuck command, it
321 * sets a flag so the driver won't start any more commands and then
322 * is periodically called to see if all outstanding commands have
323 * either finished or timed out. Once timed out, an attempt to
324 * reinitialize the card is made. If that fails, the driver gives
325 * up and declares the card dead.
327 static void
328 ips_timeout(void *arg)
330 ips_command_t *command;
331 ips_softc_t *sc = arg;
332 int i, state = 0;
334 lockmgr(&sc->queue_lock, LK_EXCLUSIVE|LK_RETRY);
335 command = &sc->commandarray[0];
336 for (i = 0; i < sc->max_cmds; i++) {
337 if (!command[i].timeout)
338 continue;
339 command[i].timeout--;
340 if (command[i].timeout == 0) {
341 if (!(sc->state & IPS_TIMEOUT)) {
342 sc->state |= IPS_TIMEOUT;
343 device_printf(sc->dev, "WARNING: command timeout. Adapter is in toaster mode, resetting to known state\n");
345 command[i].status.value = IPS_ERROR_STATUS;
346 command[i].callback(&command[i]);
347 /* hmm, this should be enough cleanup */
348 } else
349 state = 1;
351 if (!state && (sc->state & IPS_TIMEOUT)) {
352 if (sc->ips_adapter_reinit(sc, 1)) {
353 device_printf(sc->dev, "AIEE! adapter reset failed, "
354 "giving up and going home! Have a nice day.\n");
355 sc->state |= IPS_OFFLINE;
356 sc->state &= ~IPS_TIMEOUT;
358 * Grr, I hate this solution. I run waiting commands
359 * one at a time and error them out just before they
360 * would go to the card. This sucks.
362 } else
363 sc->state &= ~IPS_TIMEOUT;
365 if (sc->state != IPS_OFFLINE)
366 callout_reset(&sc->timer, 10 * hz, ips_timeout, sc);
367 lockmgr(&sc->queue_lock, LK_RELEASE);
370 /* check card and initialize it */
372 ips_adapter_init(ips_softc_t *sc)
374 int i;
375 cdev_t dev;
377 DEVICE_PRINTF(1, sc->dev, "initializing\n");
378 if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag,
379 /* alignemnt */ 1,
380 /* boundary */ 0,
381 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT,
382 /* highaddr */ BUS_SPACE_MAXADDR,
383 /* filter */ NULL,
384 /* filterarg */ NULL,
385 /* maxsize */ IPS_COMMAND_LEN +
386 IPS_MAX_SG_LEN,
387 /* numsegs */ 1,
388 /* maxsegsize*/ IPS_COMMAND_LEN +
389 IPS_MAX_SG_LEN,
390 /* flags */ 0,
391 &sc->command_dmatag) != 0) {
392 device_printf(sc->dev, "can't alloc command dma tag\n");
393 goto error;
395 if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag,
396 /* alignemnt */ 1,
397 /* boundary */ 0,
398 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT,
399 /* highaddr */ BUS_SPACE_MAXADDR,
400 /* filter */ NULL,
401 /* filterarg */ NULL,
402 /* maxsize */ IPS_MAX_IOBUF_SIZE,
403 /* numsegs */ IPS_MAX_SG_ELEMENTS,
404 /* maxsegsize*/ IPS_MAX_IOBUF_SIZE,
405 /* flags */ 0,
406 &sc->sg_dmatag) != 0) {
407 device_printf(sc->dev, "can't alloc SG dma tag\n");
408 goto error;
411 * create one command buffer until we know how many commands this card
412 * can handle
414 sc->max_cmds = 1;
415 ips_cmdqueue_init(sc);
416 callout_init(&sc->timer);
417 if (sc->ips_adapter_reinit(sc, 0))
418 goto error;
419 /* initialize ffdc values */
420 microtime(&sc->ffdc_resettime);
421 sc->ffdc_resetcount = 1;
422 if ((i = ips_ffdc_reset(sc)) != 0) {
423 device_printf(sc->dev,
424 "failed to send ffdc reset to device (%d)\n", i);
425 goto error;
427 if ((i = ips_get_adapter_info(sc)) != 0) {
428 device_printf(sc->dev, "failed to get adapter configuration "
429 "data from device (%d)\n", i);
430 goto error;
432 /* no error check as failure doesn't matter */
433 ips_update_nvram(sc);
434 if (sc->adapter_type > 0 && sc->adapter_type <= IPS_ADAPTER_MAX_T) {
435 device_printf(sc->dev, "adapter type: %s\n",
436 ips_adapter_name[sc->adapter_type]);
438 if ((i = ips_get_drive_info(sc)) != 0) {
439 device_printf(sc->dev, "failed to get drive "
440 "configuration data from device (%d)\n", i);
441 goto error;
443 ips_cmdqueue_free(sc);
444 if (sc->adapter_info.max_concurrent_cmds)
445 sc->max_cmds = min(128, sc->adapter_info.max_concurrent_cmds);
446 else
447 sc->max_cmds = 32;
448 if (ips_cmdqueue_init(sc)) {
449 device_printf(sc->dev,
450 "failed to initialize command buffers\n");
451 goto error;
453 dev_ops_add(&ips_ops, -1, device_get_unit(sc->dev));
454 dev = make_dev(&ips_ops, device_get_unit(sc->dev),
455 UID_ROOT, GID_OPERATOR, S_IRUSR | S_IWUSR,
456 "ips%d", device_get_unit(sc->dev));
457 dev->si_drv1 = sc;
458 ips_diskdev_init(sc);
459 callout_reset(&sc->timer, 10 * hz, ips_timeout, sc);
460 return 0;
461 error:
462 ips_adapter_free(sc);
463 return ENXIO;
467 * see if we should reinitialize the card and wait for it to timeout
468 * or complete initialization
471 ips_morpheus_reinit(ips_softc_t *sc, int force)
473 u_int32_t tmp;
474 int i;
476 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
477 if (!force && (ips_read_4(sc, MORPHEUS_REG_OMR0) >= IPS_POST1_OK) &&
478 (ips_read_4(sc, MORPHEUS_REG_OMR1) != 0xdeadbeef) && !tmp) {
479 ips_write_4(sc, MORPHEUS_REG_OIMR, 0);
480 return 0;
482 ips_write_4(sc, MORPHEUS_REG_OIMR, 0xff);
483 ips_read_4(sc, MORPHEUS_REG_OIMR);
484 device_printf(sc->dev,
485 "resetting adapter, this may take up to 5 minutes\n");
486 ips_write_4(sc, MORPHEUS_REG_IDR, 0x80000000);
487 DELAY(5000000);
488 pci_read_config(sc->dev, 0, 4);
489 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
490 for (i = 0; i < 45 && !(tmp & MORPHEUS_BIT_POST1); i++) {
491 DELAY(1000000);
492 DEVICE_PRINTF(2, sc->dev, "post1: %d\n", i);
493 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
495 if (tmp & MORPHEUS_BIT_POST1)
496 ips_write_4(sc, MORPHEUS_REG_OISR, MORPHEUS_BIT_POST1);
498 if (i == 45 || ips_read_4(sc, MORPHEUS_REG_OMR0) < IPS_POST1_OK) {
499 device_printf(sc->dev,
500 "Adapter error during initialization.\n");
501 return 1;
503 for (i = 0; i < 240 && !(tmp & MORPHEUS_BIT_POST2); i++) {
504 DELAY(1000000);
505 DEVICE_PRINTF(2, sc->dev, "post2: %d\n", i);
506 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
508 if (tmp & MORPHEUS_BIT_POST2)
509 ips_write_4(sc, MORPHEUS_REG_OISR, MORPHEUS_BIT_POST2);
511 if (i == 240 || !ips_read_4(sc, MORPHEUS_REG_OMR1)) {
512 device_printf(sc->dev, "adapter failed config check\n");
513 return 1;
515 ips_write_4(sc, MORPHEUS_REG_OIMR, 0);
516 if (force && ips_clear_adapter(sc)) {
517 device_printf(sc->dev, "adapter clear failed\n");
518 return 1;
520 return 0;
523 /* clean up so we can unload the driver. */
525 ips_adapter_free(ips_softc_t *sc)
527 int error = 0;
529 if (sc->state & IPS_DEV_OPEN)
530 return EBUSY;
531 if ((error = ips_diskdev_free(sc)))
532 return error;
533 if (ips_cmdqueue_free(sc)) {
534 device_printf(sc->dev,
535 "trying to exit when command queue is not empty!\n");
536 return EBUSY;
538 DEVICE_PRINTF(1, sc->dev, "free\n");
539 crit_enter();
540 callout_stop(&sc->timer);
541 crit_exit();
542 if (sc->sg_dmatag)
543 bus_dma_tag_destroy(sc->sg_dmatag);
544 if (sc->command_dmatag)
545 bus_dma_tag_destroy(sc->command_dmatag);
546 dev_ops_remove(&ips_ops, -1, device_get_unit(sc->dev));
547 return 0;
550 static int
551 ips_morpheus_check_intr(void *void_sc)
553 ips_softc_t *sc = (ips_softc_t *)void_sc;
554 u_int32_t oisr, iisr;
555 ips_cmd_status_t status;
556 ips_command_t *command;
557 int cmdnumber;
558 int found = 0;
560 iisr =ips_read_4(sc, MORPHEUS_REG_IISR);
561 oisr =ips_read_4(sc, MORPHEUS_REG_OISR);
562 PRINTF(9, "interrupt registers in:%x out:%x\n", iisr, oisr);
563 if (!(oisr & MORPHEUS_BIT_CMD_IRQ)) {
564 DEVICE_PRINTF(2, sc->dev, "got a non-command irq\n");
565 return(0);
567 while ((status.value = ips_read_4(sc, MORPHEUS_REG_OQPR))
568 != 0xffffffff) {
569 cmdnumber = status.fields.command_id;
570 command = &sc->commandarray[cmdnumber];
571 command->status.value = status.value;
572 command->timeout = 0;
573 command->callback(command);
574 DEVICE_PRINTF(9, sc->dev, "got command %d\n", cmdnumber);
575 found = 1;
577 return(found);
580 void
581 ips_morpheus_intr(void *void_sc)
583 ips_softc_t *sc = void_sc;
585 lockmgr(&sc->queue_lock, LK_EXCLUSIVE|LK_RETRY);
586 ips_morpheus_check_intr(sc);
587 lockmgr(&sc->queue_lock, LK_RELEASE);
590 void
591 ips_issue_morpheus_cmd(ips_command_t *command)
593 crit_enter();
594 /* hmmm, is there a cleaner way to do this? */
595 if (command->sc->state & IPS_OFFLINE) {
596 crit_exit();
597 command->status.value = IPS_ERROR_STATUS;
598 command->callback(command);
599 return;
601 command->timeout = 10;
602 ips_write_4(command->sc, MORPHEUS_REG_IQPR, command->command_phys_addr);
603 crit_exit();
606 void
607 ips_morpheus_poll(ips_command_t *command)
609 uint32_t ts;
611 ts = time_second + command->timeout;
612 while (command->timeout != 0 &&
613 ips_morpheus_check_intr(command->sc) == 0 &&
614 (ts > time_second))
615 DELAY(1000);
618 static void
619 ips_copperhead_queue_callback(void *queueptr, bus_dma_segment_t *segments,
620 int segnum, int error)
622 ips_copper_queue_t *queue = queueptr;
624 if (error)
625 return;
626 queue->base_phys_addr = segments[0].ds_addr;
629 static int
630 ips_copperhead_queue_init(ips_softc_t *sc)
632 bus_dma_tag_t dmatag;
633 bus_dmamap_t dmamap;
634 int error;
636 if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag,
637 /* alignemnt */ 1,
638 /* boundary */ 0,
639 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT,
640 /* highaddr */ BUS_SPACE_MAXADDR,
641 /* filter */ NULL,
642 /* filterarg */ NULL,
643 /* maxsize */ sizeof(ips_copper_queue_t),
644 /* numsegs */ 1,
645 /* maxsegsize*/ sizeof(ips_copper_queue_t),
646 /* flags */ 0,
647 &dmatag) != 0) {
648 device_printf(sc->dev, "can't alloc dma tag for statue queue\n");
649 error = ENOMEM;
650 goto exit;
652 if (bus_dmamem_alloc(dmatag, (void *)&(sc->copper_queue),
653 BUS_DMA_NOWAIT, &dmamap)) {
654 error = ENOMEM;
655 goto exit;
657 bzero(sc->copper_queue, sizeof(ips_copper_queue_t));
658 sc->copper_queue->dmatag = dmatag;
659 sc->copper_queue->dmamap = dmamap;
660 sc->copper_queue->nextstatus = 1;
661 bus_dmamap_load(dmatag, dmamap, &(sc->copper_queue->status[0]),
662 IPS_MAX_CMD_NUM * 4, ips_copperhead_queue_callback,
663 sc->copper_queue, BUS_DMA_NOWAIT);
664 if (sc->copper_queue->base_phys_addr == 0) {
665 error = ENOMEM;
666 goto exit;
668 ips_write_4(sc, COPPER_REG_SQSR, sc->copper_queue->base_phys_addr);
669 ips_write_4(sc, COPPER_REG_SQER, sc->copper_queue->base_phys_addr +
670 IPS_MAX_CMD_NUM * 4);
671 ips_write_4(sc, COPPER_REG_SQHR, sc->copper_queue->base_phys_addr + 4);
672 ips_write_4(sc, COPPER_REG_SQTR, sc->copper_queue->base_phys_addr);
673 return 0;
674 exit:
675 bus_dmamem_free(dmatag, sc->copper_queue, dmamap);
676 bus_dma_tag_destroy(dmatag);
677 return error;
681 * see if we should reinitialize the card and wait for it to timeout or
682 * complete initialization FIXME
685 ips_copperhead_reinit(ips_softc_t *sc, int force)
687 u_int32_t postcode = 0, configstatus = 0;
688 int i, j;
690 ips_write_1(sc, COPPER_REG_SCPR, 0x80);
691 ips_write_1(sc, COPPER_REG_SCPR, 0);
692 device_printf(sc->dev,
693 "reinitializing adapter, this could take several minutes.\n");
694 for (j = 0; j < 2; j++) {
695 postcode <<= 8;
696 for (i = 0; i < 45; i++) {
697 if (ips_read_1(sc, COPPER_REG_HISR) & COPPER_GHI_BIT) {
698 postcode |= ips_read_1(sc, COPPER_REG_ISPR);
699 ips_write_1(sc, COPPER_REG_HISR,
700 COPPER_GHI_BIT);
701 break;
702 } else
703 DELAY(1000000);
705 if (i == 45)
706 return 1;
708 for (j = 0; j < 2; j++) {
709 configstatus <<= 8;
710 for (i = 0; i < 240; i++) {
711 if (ips_read_1(sc, COPPER_REG_HISR) & COPPER_GHI_BIT) {
712 configstatus |= ips_read_1(sc, COPPER_REG_ISPR);
713 ips_write_1(sc, COPPER_REG_HISR,
714 COPPER_GHI_BIT);
715 break;
716 } else
717 DELAY(1000000);
719 if (i == 240)
720 return 1;
722 for (i = 0; i < 240; i++) {
723 if (!(ips_read_1(sc, COPPER_REG_CBSP) & COPPER_OP_BIT))
724 break;
725 else
726 DELAY(1000000);
728 if (i == 240)
729 return 1;
730 ips_write_2(sc, COPPER_REG_CCCR, 0x1000 | COPPER_ILE_BIT);
731 ips_write_1(sc, COPPER_REG_SCPR, COPPER_EBM_BIT);
732 ips_copperhead_queue_init(sc);
733 ips_write_1(sc, COPPER_REG_HISR, COPPER_GHI_BIT);
734 i = ips_read_1(sc, COPPER_REG_SCPR);
735 ips_write_1(sc, COPPER_REG_HISR, COPPER_EI_BIT);
736 if (configstatus == 0) {
737 device_printf(sc->dev, "adapter initialization failed\n");
738 return 1;
740 if (force && ips_clear_adapter(sc)) {
741 device_printf(sc->dev, "adapter clear failed\n");
742 return 1;
744 return 0;
747 static u_int32_t
748 ips_copperhead_cmd_status(ips_softc_t *sc)
750 u_int32_t value;
751 int statnum;
753 statnum = sc->copper_queue->nextstatus++;
754 if (sc->copper_queue->nextstatus == IPS_MAX_CMD_NUM)
755 sc->copper_queue->nextstatus = 0;
756 crit_enter();
757 value = sc->copper_queue->status[statnum];
758 ips_write_4(sc, COPPER_REG_SQTR, sc->copper_queue->base_phys_addr +
759 4 * statnum);
760 crit_exit();
761 return value;
764 void
765 ips_copperhead_intr(void *void_sc)
767 ips_softc_t *sc = (ips_softc_t *)void_sc;
768 ips_cmd_status_t status;
769 int cmdnumber;
771 lockmgr(&sc->queue_lock, LK_EXCLUSIVE|LK_RETRY);
772 while (ips_read_1(sc, COPPER_REG_HISR) & COPPER_SCE_BIT) {
773 status.value = ips_copperhead_cmd_status(sc);
774 cmdnumber = status.fields.command_id;
775 sc->commandarray[cmdnumber].status.value = status.value;
776 sc->commandarray[cmdnumber].timeout = 0;
777 sc->commandarray[cmdnumber].callback(&(sc->commandarray[cmdnumber]));
778 PRINTF(9, "ips: got command %d\n", cmdnumber);
780 lockmgr(&sc->queue_lock, LK_RELEASE);
781 return;
784 void
785 ips_issue_copperhead_cmd(ips_command_t *command)
787 int i;
789 crit_enter();
790 /* hmmm, is there a cleaner way to do this? */
791 if (command->sc->state & IPS_OFFLINE) {
792 crit_exit();
793 command->status.value = IPS_ERROR_STATUS;
794 command->callback(command);
795 return;
797 command->timeout = 10;
798 for (i = 0; ips_read_4(command->sc, COPPER_REG_CCCR) & COPPER_SEM_BIT;
799 i++) {
800 if (i == 20) {
801 kprintf("sem bit still set, can't send a command\n");
802 crit_exit();
803 return;
805 DELAY(500); /* need to do a delay here */
807 ips_write_4(command->sc, COPPER_REG_CCSAR, command->command_phys_addr);
808 ips_write_2(command->sc, COPPER_REG_CCCR, COPPER_CMD_START);
809 crit_exit();
812 void
813 ips_copperhead_poll(ips_command_t *command)
815 kprintf("ips: cmd polling not implemented for copperhead devices\n");